From a495cd581c268b96ad9034c4569293de1f9e3156 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:43:54 -0400 Subject: [PATCH 01/81] Assert that `_Path_Separator` is 7-bit ASCII There are several places where this is assumed to be true, most visibly in `is_path_separator`, as it takes a `byte` argument. Note that the data type of `_Path_Separator` is a rune, which allows any Unicode value. --- core/os/os2/path.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/os/os2/path.odin b/core/os/os2/path.odin index 9231307f5..7d177a85d 100644 --- a/core/os/os2/path.odin +++ b/core/os/os2/path.odin @@ -8,6 +8,8 @@ Path_Separator :: _Path_Separator // OS-Specific Path_Separator_String :: _Path_Separator_String // OS-Specific Path_List_Separator :: _Path_List_Separator // OS-Specific +#assert(_Path_Separator <= rune(0x7F), "The system-specific path separator rune is expected to be within the 7-bit ASCII character set.") + @(require_results) is_path_separator :: proc(c: byte) -> bool { return _is_path_separator(c) From d1d86234aa82eeab898a926e20c47cb0f5935c7e Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:48:39 -0400 Subject: [PATCH 02/81] Add missing documentation to `os2/path` --- core/os/os2/path.odin | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/core/os/os2/path.odin b/core/os/os2/path.odin index 7d177a85d..3dedc2961 100644 --- a/core/os/os2/path.odin +++ b/core/os/os2/path.odin @@ -10,6 +10,10 @@ Path_List_Separator :: _Path_List_Separator // OS-Specific #assert(_Path_Separator <= rune(0x7F), "The system-specific path separator rune is expected to be within the 7-bit ASCII character set.") +/* +Return true if `c` is a character used to separate paths into directory and +file hierarchies on the current system. +*/ @(require_results) is_path_separator :: proc(c: byte) -> bool { return _is_path_separator(c) @@ -17,22 +21,42 @@ is_path_separator :: proc(c: byte) -> bool { mkdir :: make_directory +/* +Make a new directory. + +If `path` is relative, it will be relative to the process's current working directory. +*/ make_directory :: proc(name: string, perm: int = 0o755) -> Error { return _mkdir(name, perm) } mkdir_all :: make_directory_all +/* +Make a new directory, creating new intervening directories when needed. + +If `path` is relative, it will be relative to the process's current working directory. +*/ make_directory_all :: proc(path: string, perm: int = 0o755) -> Error { return _mkdir_all(path, perm) } +/* +Delete `path` and all files and directories inside of `path` if it is a directory. + +If `path` is relative, it will be relative to the process's current working directory. +*/ remove_all :: proc(path: string) -> Error { return _remove_all(path) } getwd :: get_working_directory +/* +Get the working directory of the current process. + +*Allocates Using Provided Allocator* +*/ @(require_results) get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { return _get_working_directory(allocator) @@ -40,14 +64,29 @@ get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err setwd :: set_working_directory +/* +Change the working directory of the current process. + +*Allocates Using Provided Allocator* +*/ set_working_directory :: proc(dir: string) -> (err: Error) { return _set_working_directory(dir) } +/* +Get the path for the currently running executable. + +*Allocates Using Provided Allocator* +*/ get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { return _get_executable_path(allocator) } +/* +Get the directory for the currently running executable. + +*Allocates Using Provided Allocator* +*/ get_executable_directory :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { path = _get_executable_path(allocator) or_return path, _ = filepath.split(path) From abe0c308371456b603c828ba09e2394a6d9171f2 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 20 Mar 2025 17:39:16 -0400 Subject: [PATCH 03/81] Add new path API for `os2` --- core/os/os2/path.odin | 369 ++++++++++++++++++++++++++++++++++ core/os/os2/path_posixfs.odin | 78 +++++++ core/os/os2/path_windows.odin | 96 ++++++++- core/os/os2/stat_windows.odin | 18 -- 4 files changed, 541 insertions(+), 20 deletions(-) create mode 100644 core/os/os2/path_posixfs.odin diff --git a/core/os/os2/path.odin b/core/os/os2/path.odin index 3dedc2961..fb2008f37 100644 --- a/core/os/os2/path.odin +++ b/core/os/os2/path.odin @@ -1,8 +1,10 @@ package os2 +import "base:intrinsics" import "base:runtime" import "core:path/filepath" +import "core:strings" Path_Separator :: _Path_Separator // OS-Specific Path_Separator_String :: _Path_Separator_String // OS-Specific @@ -92,3 +94,370 @@ get_executable_directory :: proc(allocator: runtime.Allocator) -> (path: string, path, _ = filepath.split(path) return } + +/* +Compare two paths for exactness without normalization. + +This procedure takes into account case-sensitivity on differing systems. +*/ +@(require_results) +are_paths_identical :: proc(a, b: string) -> (identical: bool) { + return _are_paths_identical(a, b) +} + +/* +Normalize a path. + +*Allocates Using Provided Allocator* + +This will remove duplicate separators and unneeded references to the current or +parent directory. +*/ +@(require_results) +clean_path :: proc(path: string, allocator: runtime.Allocator) -> (cleaned: string, err: Error) { + if path == "" || path == "." { + return strings.clone(".", allocator) + } + + TEMP_ALLOCATOR_GUARD() + + // The extra byte is to simplify appending path elements by letting the + // loop to end each with a separator. We'll trim the last one when we're done. + buffer := make([]u8, len(path) + 1, temp_allocator()) or_return + + // This is the only point where Windows and POSIX differ, as Windows has + // alphabet-based volumes for root paths. + rooted, start := _clean_path_handle_start(path, buffer) + + head, buffer_i := start, start + for i, j := start, start; i <= len(path); i += 1 { + if i == len(path) || _is_path_separator(path[i]) { + elem := path[j:i] + j = i + 1 + + switch elem { + case "", ".": + // Skip duplicate path separators and current directory references. + case "..": + if !rooted && buffer_i == head { + // Only allow accessing further parent directories when the path is relative. + buffer[buffer_i] = '.' + buffer[buffer_i+1] = '.' + buffer[buffer_i+2] = _Path_Separator + buffer_i += 3 + head = buffer_i + } else { + // Roll back to the last separator or the head of the buffer. + back_to := head + // `buffer_i` will be equal to 1 + the last set byte, so + // skipping two bytes avoids the final separator we just + // added. + for k := buffer_i-2; k >= head; k -= 1 { + if _is_path_separator(buffer[k]) { + back_to = k + 1 + break + } + } + buffer_i = back_to + } + case: + // Copy the path element verbatim and add a separator. + intrinsics.mem_copy_non_overlapping(raw_data(buffer[buffer_i:]), raw_data(elem), len(elem)) + buffer_i += len(elem) + buffer[buffer_i] = _Path_Separator + buffer_i += 1 + } + } + } + + // Trim the final separator. + // NOTE: No need to check if the last byte is a separator, as we always add it. + if buffer_i > start { + buffer_i -= 1 + } + + if buffer_i == 0 { + return strings.clone(".", allocator) + } + + compact := make([]u8, buffer_i, allocator) or_return + intrinsics.mem_copy_non_overlapping(raw_data(compact), raw_data(buffer), buffer_i) + return string(compact), nil +} + +/* +Return true if `path` is an absolute path as opposed to a relative one. +*/ +@(require_results) +is_absolute_path :: proc(path: string) -> bool { + return _is_absolute_path(path) +} + +/* +Get the absolute path to `path` with respect to the process's current directory. + +*Allocates Using Provided Allocator* +*/ +@(require_results) +get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { + return _get_absolute_path(path, allocator) +} + +/* +Get the relative path needed to change directories from `base` to `target`. + +*Allocates Using Provided Allocator* + +The result is such that `join_path(base, get_relative_path(base, target))` is equivalent to `target`. + +NOTE: This procedure expects both `base` and `target` to be normalized first, +which can be done by calling `clean_path` on them if needed. + +This procedure will return an `Invalid_Path` error if `base` begins with a +reference to the parent directory (`".."`). Use `get_working_directory` with +`join_path` to construct absolute paths for both arguments instead. +*/ +@(require_results) +get_relative_path :: proc(base, target: string, allocator: runtime.Allocator) -> (path: string, err: Error) { + if _are_paths_identical(base, target) { + return strings.clone(".", allocator) + } + if base == "." { + return strings.clone(target, allocator) + } + + // This is the first point where Windows and POSIX differ, as Windows has + // alphabet-based volumes for root paths. + if !_get_relative_path_handle_start(base, target) { + return "", .Invalid_Path + } + if strings.has_prefix(base, "..") && (len(base) == 2 || _is_path_separator(base[2])) { + // We could do the work for the user of getting absolute paths for both + // arguments, but that could make something costly (repeatedly + // normalizing paths) convenient, when it would be better for the user + // to store already-finalized paths and operate on those instead. + return "", .Invalid_Path + } + + // This is the other point where Windows and POSIX differ, as Windows is + // case-insensitive. + common := _get_common_path_len(base, target) + + // Get the result of splitting `base` and `target` on _Path_Separator, + // comparing them up to their most common elements, then count how many + // unshared parts are in the split `base`. + seps := 0 + size := 0 + if len(base)-common > 0 { + seps = 1 + size = 2 + } + // This range skips separators on the ends of the string. + for i in common+1.. 0 { + // Account for leading separators on the target after cutting the common part. + // (i.e. base == `/home`, target == `/home/a`) + if _is_path_separator(trailing[0]) { + trailing = trailing[1:] + } + size += len(trailing) + if seps > 0 { + size += 1 + } + } + if trailing == "." { + trailing = "" + size -= 2 + } + + // Build the string. + buf := make([]u8, size, allocator) or_return + n := 0 + if seps > 0 { + buf[0] = '.' + buf[1] = '.' + n = 2 + } + for _ in 1.. 0 { + if seps > 0 { + buf[n] = _Path_Separator + n += 1 + } + runtime.mem_copy_non_overlapping(raw_data(buf[n:]), raw_data(trailing), len(trailing)) + } + + path = string(buf) + + return +} + +/* +Split a path into a directory hierarchy and a filename. + +For example, `split_path("/home/foo/bar.tar.gz")` will return `"/home/foo"` and `"bar.tar.gz"`. +*/ +@(require_results) +split_path :: proc(path: string) -> (dir, filename: string) { + return _split_path(path) +} + +/* +Join all `elems` with the system's path separator and normalize the result. + +*Allocates Using Provided Allocator* + +For example, `join_path({"/home", "foo", "bar.txt"})` will result in `"/home/foo/bar.txt"`. +*/ +@(require_results) +join_path :: proc(elems: []string, allocator: runtime.Allocator) -> (joined: string, err: Error) { + for e, i in elems { + if e != "" { + TEMP_ALLOCATOR_GUARD() + p := strings.join(elems[i:], Path_Separator_String, temp_allocator()) or_return + return clean_path(p, allocator) + } + } + return "", nil +} + +/* +Split a filename from its extension. + +This procedure splits on the last separator. + +If the filename begins with a separator, such as `".readme.txt"`, the separator +will be included in the filename, resulting in `".readme"` and `"txt"`. + +For example, `split_filename("foo.tar.gz")` will return `"foo.tar"` and `"gz"`. +*/ +@(require_results) +split_filename :: proc(filename: string) -> (base, ext: string) { + i := strings.last_index_byte(filename, '.') + if i <= 0 { + return filename, "" + } + return filename[:i], filename[i+1:] +} + +/* +Split a filename from its extension. + +This procedure splits on the first separator. + +If the filename begins with a separator, such as `".readme.txt.gz"`, the separator +will be included in the filename, resulting in `".readme"` and `"txt.gz"`. + +For example, `split_filename_all("foo.tar.gz")` will return `"foo"` and `"tar.gz"`. +*/ +@(require_results) +split_filename_all :: proc(filename: string) -> (base, ext: string) { + i := strings.index_byte(filename, '.') + if i == 0 { + j := strings.index_byte(filename[1:], '.') + if j != -1 { + j += 1 + } + i = j + } + if i == -1 { + return filename, "" + } + return filename[:i], filename[i+1:] +} + +/* +Join `base` and `ext` with the system's filename extension separator. + +*Allocates Using Provided Allocator* + +For example, `join_filename("foo", "tar.gz")` will result in `"foo.tar.gz"`. +*/ +@(require_results) +join_filename :: proc(base: string, ext: string, allocator: runtime.Allocator) -> (joined: string, err: Error) { + len_base := len(base) + if len_base == 0 { + return strings.clone(ext, allocator) + } else if len(ext) == 0 { + return strings.clone(base, allocator) + } + + buf := make([]u8, len_base + 1 + len(ext), allocator) or_return + intrinsics.mem_copy_non_overlapping(raw_data(buf), raw_data(base), len_base) + buf[len_base] = '.' + intrinsics.mem_copy_non_overlapping(raw_data(buf[1+len_base:]), raw_data(ext), len(ext)) + + return string(buf), nil +} + +/* +Split a string that is separated by a system-specific separator, typically used +for environment variables specifying multiple directories. + +*Allocates Using Provided Allocator* + +For example, there is the "PATH" environment variable on POSIX systems which +this procedure can split into separate entries. +*/ +@(require_results) +split_path_list :: proc(path: string, allocator: runtime.Allocator) -> (list: []string, err: Error) { + if path == "" { + return nil, nil + } + + start: int + quote: bool + + start, quote = 0, false + count := 0 + + for i := 0; i < len(path); i += 1 { + c := path[i] + switch { + case c == '"': + quote = !quote + case c == Path_List_Separator && !quote: + count += 1 + } + } + + start, quote = 0, false + list = make([]string, count + 1, allocator) or_return + index := 0 + for i := 0; i < len(path); i += 1 { + c := path[i] + switch { + case c == '"': + quote = !quote + case c == Path_List_Separator && !quote: + list[index] = path[start:i] + index += 1 + start = i + 1 + } + } + assert(index == count) + list[index] = path[start:] + + for s0, i in list { + s, new := strings.replace_all(s0, `"`, ``, allocator) + if !new { + s = strings.clone(s, allocator) or_return + } + list[i] = s + } + + return list, nil +} diff --git a/core/os/os2/path_posixfs.odin b/core/os/os2/path_posixfs.odin new file mode 100644 index 000000000..8f9d43d63 --- /dev/null +++ b/core/os/os2/path_posixfs.odin @@ -0,0 +1,78 @@ +#+private +#+build linux, darwin, netbsd, freebsd, openbsd, wasi +package os2 + +// This implementation is for all systems that have POSIX-compliant filesystem paths. + +import "base:runtime" +import "core:strings" +import "core:sys/posix" + +_are_paths_identical :: proc(a, b: string) -> (identical: bool) { + return a == b +} + +_clean_path_handle_start :: proc(path: string, buffer: []u8) -> (rooted: bool, start: int) { + // Preserve rooted paths. + if _is_path_separator(path[0]) { + rooted = true + buffer[0] = _Path_Separator + start = 1 + } + return +} + +_is_absolute_path :: proc(path: string) -> bool { + return len(path) > 0 && _is_path_separator(path[0]) +} + +_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { + rel := path + if rel == "" { + rel = "." + } + TEMP_ALLOCATOR_GUARD() + rel_cstr := strings.clone_to_cstring(rel, temp_allocator()) + path_ptr := posix.realpath(rel_cstr, nil) + if path_ptr == nil { + return "", Platform_Error(posix.errno()) + } + defer posix.free(path_ptr) + + path_str := strings.clone(string(path_ptr), allocator) + return path_str, nil +} + +_get_relative_path_handle_start :: proc(base, target: string) -> bool { + base_rooted := len(base) > 0 && _is_path_separator(base[0]) + target_rooted := len(target) > 0 && _is_path_separator(target[0]) + return base_rooted == target_rooted +} + +_get_common_path_len :: proc(base, target: string) -> int { + i := 0 + end := min(len(base), len(target)) + for j in 0..=end { + if j == end || _is_path_separator(base[j]) { + if base[i:j] == target[i:j] { + i = j + } else { + break + } + } + } + return i +} + +_split_path :: proc(path: string) -> (dir, file: string) { + i := len(path) - 1 + for i >= 0 && !_is_path_separator(path[i]) { + i -= 1 + } + if i == 0 { + return path[:i+1], path[i+1:] + } else if i > 0 { + return path[:i], path[i+1:] + } + return "", path +} diff --git a/core/os/os2/path_windows.odin b/core/os/os2/path_windows.odin index 041a4d1e3..c8264cc2d 100644 --- a/core/os/os2/path_windows.odin +++ b/core/os/os2/path_windows.odin @@ -1,8 +1,10 @@ #+private package os2 -import win32 "core:sys/windows" +import "base:intrinsics" import "base:runtime" +import "core:strings" +import win32 "core:sys/windows" _Path_Separator :: '\\' _Path_Separator_String :: "\\" @@ -217,7 +219,7 @@ _fix_long_path_internal :: proc(path: string) -> string { return path } - if !_is_abs(path) { // relative path + if !_is_absolute_path(path) { // relative path return path } @@ -257,3 +259,93 @@ _fix_long_path_internal :: proc(path: string) -> string { return string(path_buf[:w]) } + +_are_paths_identical :: strings.equal_fold + +_clean_path_handle_start :: proc(path: string, buffer: []u8) -> (rooted: bool, start: int) { + // Preserve rooted paths. + start = _volume_name_len(path) + if start > 0 { + rooted = true + if len(path) > start && _is_path_separator(path[start]) { + // Take `C:` to `C:\`. + start += 1 + } + intrinsics.mem_copy_non_overlapping(raw_data(buffer), raw_data(path), start) + } + return +} + +_is_absolute_path :: proc(path: string) -> bool { + if _is_reserved_name(path) { + return true + } + l := _volume_name_len(path) + if l == 0 { + return false + } + + path := path + path = path[l:] + if path == "" { + return false + } + return _is_path_separator(path[0]) +} + +_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) { + rel := path + if rel == "" { + rel = "." + } + TEMP_ALLOCATOR_GUARD() + rel_utf16 := win32.utf8_to_utf16(rel, temp_allocator()) + n := win32.GetFullPathNameW(raw_data(rel_utf16), 0, nil, nil) + if n == 0 { + return "", Platform_Error(win32.GetLastError()) + } + + buf := make([]u16, n, temp_allocator()) or_return + n = win32.GetFullPathNameW(raw_data(rel_utf16), u32(n), raw_data(buf), nil) + if n == 0 { + return "", Platform_Error(win32.GetLastError()) + } + + return win32.utf16_to_utf8(buf, allocator) +} + +_get_relative_path_handle_start :: proc(base, target: string) -> bool { + base_root := base[:_volume_name_len(base)] + target_root := target[:_volume_name_len(target)] + return strings.equal_fold(base_root, target_root) +} + +_get_common_path_len :: proc(base, target: string) -> int { + i := 0 + end := min(len(base), len(target)) + for j in 0..=end { + if j == end || _is_path_separator(base[j]) { + if strings.equal_fold(base[i:j], target[i:j]) { + i = j + } else { + break + } + } + } + return i +} + +_split_path :: proc(path: string) -> (dir, file: string) { + vol_len := _volume_name_len(path) + + i := len(path) - 1 + for i >= vol_len && !_is_path_separator(path[i]) { + i -= 1 + } + if i == vol_len { + return path[:i+1], path[i+1:] + } else if i > vol_len { + return path[:i], path[i+1:] + } + return "", path +} diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin index 31f5d9e88..14744c90f 100644 --- a/core/os/os2/stat_windows.odin +++ b/core/os/os2/stat_windows.odin @@ -351,21 +351,3 @@ _volume_name_len :: proc(path: string) -> int { } return 0 } - -_is_abs :: proc(path: string) -> bool { - if _is_reserved_name(path) { - return true - } - l := _volume_name_len(path) - if l == 0 { - return false - } - - path := path - path = path[l:] - if path == "" { - return false - } - return is_path_separator(path[0]) -} - From 4e7f54c565408358a69998a0ed30cbf025514586 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 20 Mar 2025 18:24:12 -0400 Subject: [PATCH 04/81] Decouple usage of `filepath` from `os2` --- core/os/os2/path.odin | 3 +-- core/os/os2/path_posix.odin | 5 ++--- core/os/os2/path_wasi.odin | 5 ++--- core/os/os2/process_linux.odin | 5 ++--- core/os/os2/process_posix.odin | 3 +-- core/os/os2/stat.odin | 3 +-- core/os/os2/stat_linux.odin | 3 +-- core/os/os2/stat_posix.odin | 5 ++--- core/os/os2/stat_wasi.odin | 3 +-- tests/core/os/os2/dir.odin | 34 ++++++++++++++++++++++------------ tests/core/os/os2/file.odin | 6 ++++-- tests/core/os/os2/path.odin | 6 +++--- 12 files changed, 42 insertions(+), 39 deletions(-) diff --git a/core/os/os2/path.odin b/core/os/os2/path.odin index fb2008f37..24d1f35bd 100644 --- a/core/os/os2/path.odin +++ b/core/os/os2/path.odin @@ -3,7 +3,6 @@ package os2 import "base:intrinsics" import "base:runtime" -import "core:path/filepath" import "core:strings" Path_Separator :: _Path_Separator // OS-Specific @@ -91,7 +90,7 @@ Get the directory for the currently running executable. */ get_executable_directory :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { path = _get_executable_path(allocator) or_return - path, _ = filepath.split(path) + path, _ = split_path(path) return } diff --git a/core/os/os2/path_posix.odin b/core/os/os2/path_posix.odin index e6b95c0d4..39bd0a188 100644 --- a/core/os/os2/path_posix.odin +++ b/core/os/os2/path_posix.odin @@ -3,7 +3,6 @@ package os2 import "base:runtime" -import "core:path/filepath" import "core:sys/posix" @@ -35,11 +34,11 @@ _mkdir_all :: proc(path: string, perm: int) -> Error { return .Exist } - clean_path := filepath.clean(path, temp_allocator()) + clean_path := clean_path(path, temp_allocator()) or_return return internal_mkdir_all(clean_path, perm) internal_mkdir_all :: proc(path: string, perm: int) -> Error { - dir, file := filepath.split(path) + dir, file := split_path(path) if file != path && dir != "/" { if len(dir) > 1 && dir[len(dir) - 1] == '/' { dir = dir[:len(dir) - 1] diff --git a/core/os/os2/path_wasi.odin b/core/os/os2/path_wasi.odin index 1c4fafa17..7aee8fcc0 100644 --- a/core/os/os2/path_wasi.odin +++ b/core/os/os2/path_wasi.odin @@ -3,7 +3,6 @@ package os2 import "base:runtime" -import "core:path/filepath" import "core:sync" import "core:sys/wasm/wasi" @@ -35,11 +34,11 @@ _mkdir_all :: proc(path: string, perm: int) -> Error { return .Exist } - clean_path := filepath.clean(path, temp_allocator()) + clean_path := clean_path(path, temp_allocator()) return internal_mkdir_all(clean_path) internal_mkdir_all :: proc(path: string) -> Error { - dir, file := filepath.split(path) + dir, file := split_path(path) if file != path && dir != "/" { if len(dir) > 1 && dir[len(dir) - 1] == '/' { dir = dir[:len(dir) - 1] diff --git a/core/os/os2/process_linux.odin b/core/os/os2/process_linux.odin index 632bde6ba..6d654008b 100644 --- a/core/os/os2/process_linux.odin +++ b/core/os/os2/process_linux.odin @@ -10,7 +10,6 @@ import "core:slice" import "core:strings" import "core:strconv" import "core:sys/linux" -import "core:path/filepath" PIDFD_UNASSIGNED :: ~uintptr(0) @@ -205,7 +204,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator info.executable_path = strings.clone(cmdline[:terminator], allocator) or_return info.fields += {.Executable_Path} } else if cwd_err == nil { - info.executable_path = filepath.join({ cwd, cmdline[:terminator] }, allocator) or_return + info.executable_path = join_path({ cwd, cmdline[:terminator] }, allocator) or_return info.fields += {.Executable_Path} } else { break cmdline_if @@ -407,7 +406,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { executable_name := desc.command[0] if strings.index_byte(executable_name, '/') < 0 { path_env := get_env("PATH", temp_allocator()) - path_dirs := filepath.split_list(path_env, temp_allocator()) or_return + path_dirs := split_path_list(path_env, temp_allocator()) or_return exe_builder := strings.builder_make(temp_allocator()) or_return diff --git a/core/os/os2/process_posix.odin b/core/os/os2/process_posix.odin index 3fa429cbe..cd451781f 100644 --- a/core/os/os2/process_posix.odin +++ b/core/os/os2/process_posix.odin @@ -6,7 +6,6 @@ import "base:runtime" import "core:time" import "core:strings" -import "core:path/filepath" import kq "core:sys/kqueue" import "core:sys/posix" @@ -62,7 +61,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) { exe_name := desc.command[0] if strings.index_byte(exe_name, '/') < 0 { path_env := get_env("PATH", temp_allocator()) - path_dirs := filepath.split_list(path_env, temp_allocator()) + path_dirs := split_path_list(path_env, temp_allocator()) or_return found: bool for dir in path_dirs { diff --git a/core/os/os2/stat.odin b/core/os/os2/stat.odin index d0a5a659d..7d76902eb 100644 --- a/core/os/os2/stat.odin +++ b/core/os/os2/stat.odin @@ -1,7 +1,6 @@ package os2 import "base:runtime" -import "core:path/filepath" import "core:strings" import "core:time" @@ -25,7 +24,7 @@ File_Info :: struct { file_info_clone :: proc(fi: File_Info, allocator: runtime.Allocator) -> (cloned: File_Info, err: runtime.Allocator_Error) { cloned = fi cloned.fullpath = strings.clone(fi.fullpath, allocator) or_return - cloned.name = filepath.base(cloned.fullpath) + _, cloned.name = split_path(cloned.fullpath) return } diff --git a/core/os/os2/stat_linux.odin b/core/os/os2/stat_linux.odin index 0433c1a61..7bff08f29 100644 --- a/core/os/os2/stat_linux.odin +++ b/core/os/os2/stat_linux.odin @@ -4,7 +4,6 @@ package os2 import "core:time" import "base:runtime" import "core:sys/linux" -import "core:path/filepath" _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { impl := (^File_Impl)(f.impl) @@ -42,7 +41,7 @@ _fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fi: File creation_time = time.Time{i64(s.ctime.time_sec) * i64(time.Second) + i64(s.ctime.time_nsec)}, // regular stat does not provide this } fi.creation_time = fi.modification_time - fi.name = filepath.base(fi.fullpath) + _, fi.name = split_path(fi.fullpath) return } diff --git a/core/os/os2/stat_posix.odin b/core/os/os2/stat_posix.odin index 88029c1f5..260dc7b52 100644 --- a/core/os/os2/stat_posix.odin +++ b/core/os/os2/stat_posix.odin @@ -4,13 +4,12 @@ package os2 import "base:runtime" -import "core:path/filepath" import "core:sys/posix" import "core:time" internal_stat :: proc(stat: posix.stat_t, fullpath: string) -> (fi: File_Info) { fi.fullpath = fullpath - fi.name = filepath.base(fi.fullpath) + _, fi.name = split_path(fi.fullpath) fi.inode = u128(stat.st_ino) fi.size = i64(stat.st_size) @@ -104,7 +103,7 @@ _lstat :: proc(name: string, allocator: runtime.Allocator) -> (fi: File_Info, er // NOTE: This might not be correct when given "/symlink/foo.txt", // you would want that to resolve "/symlink", but not resolve "foo.txt". - fullpath := filepath.clean(name, temp_allocator()) + fullpath := clean_path(name, temp_allocator()) or_return assert(len(fullpath) > 0) switch { case fullpath[0] == '/': diff --git a/core/os/os2/stat_wasi.odin b/core/os/os2/stat_wasi.odin index 2992c6267..bf18d8273 100644 --- a/core/os/os2/stat_wasi.odin +++ b/core/os/os2/stat_wasi.odin @@ -3,13 +3,12 @@ package os2 import "base:runtime" -import "core:path/filepath" import "core:sys/wasm/wasi" import "core:time" internal_stat :: proc(stat: wasi.filestat_t, fullpath: string) -> (fi: File_Info) { fi.fullpath = fullpath - fi.name = filepath.base(fi.fullpath) + _, fi.name = split_path(fi.fullpath) fi.inode = u128(stat.ino) fi.size = i64(stat.size) diff --git a/tests/core/os/os2/dir.odin b/tests/core/os/os2/dir.odin index 7077e9ae2..8ef333219 100644 --- a/tests/core/os/os2/dir.odin +++ b/tests/core/os/os2/dir.odin @@ -2,27 +2,27 @@ package tests_core_os_os2 import os "core:os/os2" import "core:log" -import "core:path/filepath" import "core:slice" import "core:testing" import "core:strings" @(test) test_read_dir :: proc(t: ^testing.T) { - path := filepath.join({#directory, "../dir"}) + path, err_join := os.join_path({#directory, "../dir"}, context.allocator) defer delete(path) - fis, err := os.read_all_directory_by_path(path, context.allocator) + fis, err_read := os.read_all_directory_by_path(path, context.allocator) defer os.file_info_slice_delete(fis, context.allocator) slice.sort_by_key(fis, proc(fi: os.File_Info) -> string { return fi.name }) - if err == .Unsupported { + if err_read == .Unsupported { log.warn("os2 directory functionality is unsupported, skipping test") return } - testing.expect_value(t, err, nil) + testing.expect_value(t, err_join, nil) + testing.expect_value(t, err_read, nil) testing.expect_value(t, len(fis), 2) testing.expect_value(t, fis[0].name, "b.txt") @@ -34,8 +34,9 @@ test_read_dir :: proc(t: ^testing.T) { @(test) test_walker :: proc(t: ^testing.T) { - path := filepath.join({#directory, "../dir"}) + path, err := os.join_path({#directory, "../dir"}, context.allocator) defer delete(path) + testing.expect_value(t, err, nil) w := os.walker_create(path) defer os.walker_destroy(&w) @@ -45,11 +46,12 @@ test_walker :: proc(t: ^testing.T) { @(test) test_walker_file :: proc(t: ^testing.T) { - path := filepath.join({#directory, "../dir"}) + path, err_join := os.join_path({#directory, "../dir"}, context.allocator) defer delete(path) + testing.expect_value(t, err_join, nil) - f, err := os.open(path) - testing.expect_value(t, err, nil) + f, err_open := os.open(path) + testing.expect_value(t, err_open, nil) defer os.close(f) w := os.walker_create(f) @@ -64,10 +66,18 @@ test_walker_internal :: proc(t: ^testing.T, w: ^os.Walker) { path: string, } + joined_1, err_joined_1 := os.join_path({"dir", "b.txt"}, context.allocator) + joined_2, err_joined_2 := os.join_path({"dir", "sub"}, context.allocator) + joined_3, err_joined_3 := os.join_path({"dir", "sub", ".gitkeep"}, context.allocator) + + testing.expect_value(t, err_joined_1, nil) + testing.expect_value(t, err_joined_2, nil) + testing.expect_value(t, err_joined_3, nil) + expected := [?]Seen{ - {.Regular, filepath.join({"dir", "b.txt"})}, - {.Directory, filepath.join({"dir", "sub"})}, - {.Regular, filepath.join({"dir", "sub", ".gitkeep"})}, + {.Regular, joined_1}, + {.Directory, joined_2}, + {.Regular, joined_3}, } seen: [dynamic]Seen diff --git a/tests/core/os/os2/file.odin b/tests/core/os/os2/file.odin index c4df74f4a..0152a2008 100644 --- a/tests/core/os/os2/file.odin +++ b/tests/core/os/os2/file.odin @@ -2,11 +2,13 @@ package tests_core_os_os2 import os "core:os/os2" import "core:testing" -import "core:path/filepath" @(test) test_clone :: proc(t: ^testing.T) { - f, err := os.open(filepath.join({#directory, "file.odin"}, context.temp_allocator)) + joined, err := os.join_path({#directory, "file.odin"}, context.temp_allocator) + testing.expect_value(t, err, nil) + f: ^os.File + f, err = os.open(joined) testing.expect_value(t, err, nil) testing.expect(t, f != nil) diff --git a/tests/core/os/os2/path.odin b/tests/core/os/os2/path.odin index b91f43368..63a5572d8 100644 --- a/tests/core/os/os2/path.odin +++ b/tests/core/os/os2/path.odin @@ -2,7 +2,6 @@ package tests_core_os_os2 import os "core:os/os2" import "core:log" -import "core:path/filepath" import "core:testing" import "core:strings" @@ -17,6 +16,7 @@ test_executable :: proc(t: ^testing.T) { testing.expect_value(t, err, nil) testing.expect(t, len(path) > 0) - testing.expect(t, filepath.is_abs(path)) - testing.expectf(t, strings.contains(path, filepath.base(os.args[0])), "expected the executable path to contain the base of os.args[0] which is %q", filepath.base(os.args[0])) + testing.expect(t, os.is_absolute_path(path)) + _, filename := os.split_path(os.args[0]) + testing.expectf(t, strings.contains(path, filename), "expected the executable path to contain the base of os.args[0] which is %q", filename) } From 3525e71739343abd3a37bf59e9c184c699556bc7 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 20 Mar 2025 18:25:33 -0400 Subject: [PATCH 05/81] Add tests for new `os2` path API --- tests/core/os/os2/path.odin | 344 ++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) diff --git a/tests/core/os/os2/path.odin b/tests/core/os/os2/path.odin index 63a5572d8..2cf1f1f1c 100644 --- a/tests/core/os/os2/path.odin +++ b/tests/core/os/os2/path.odin @@ -20,3 +20,347 @@ test_executable :: proc(t: ^testing.T) { _, filename := os.split_path(os.args[0]) testing.expectf(t, strings.contains(path, filename), "expected the executable path to contain the base of os.args[0] which is %q", filename) } + +posix_to_dos_path :: proc(path: string) -> string { + if len(path) == 0 { + return path + } + path := path + path, _ = strings.replace_all(path, `/`, `\`, context.temp_allocator) + if path[0] == '\\' { + path = strings.concatenate({"C:", path}, context.temp_allocator) + } + return path +} + +@(test) +test_clean_path :: proc(t: ^testing.T) { + Test_Case :: struct{ + path: string, + expected: string, + } + + test_cases := [?]Test_Case { + {`../../foo/../../`, `../../..`}, + {`../../foo/..`, `../..`}, + {`../../foo`, `../../foo`}, + {`../..`, `../..`}, + {`.././foo`, `../foo`}, + {`..`, `..`}, + {`.`, `.`}, + {`.foo`, `.foo`}, + {`/../../foo/../../`, `/`}, + {`/../`, `/`}, + {`/..`, `/`}, + {`/`, `/`}, + {`//home/foo/bar/../../`, `/home`}, + {`/a/../..`, `/`}, + {`/a/../`, `/`}, + {`/a/あ`, `/a/あ`}, + {`/a/あ/..`, `/a`}, + {`/あ/a/..`, `/あ`}, + {`/あ/a/../あ`, `/あ/あ`}, + {`/home/../`, `/`}, + {`/home/..`, `/`}, + {`/home/foo/../../usr`, `/usr`}, + {`/home/foo/../..`, `/`}, + {`/home/foo/../`, `/home`}, + {``, `.`}, + {`a/..`, `.`}, + {`a`, `a`}, + {`abc//.//../foo`, `foo`}, + {`foo`, `foo`}, + {`home/foo/bar/../../`, `home`}, + } + + when ODIN_OS == .Windows { + for &tc in test_cases { + tc.path = posix_to_dos_path(tc.path) + tc.expected = posix_to_dos_path(tc.expected) + } + } + + for tc in test_cases { + joined, err := os.clean_path(tc.path, context.temp_allocator) + testing.expectf(t, joined == tc.expected && err == nil, "expected clean_path(%q) -> %q; got: %q, %v", tc.path, tc.expected, joined, err) + } +} + +@(test) +test_is_absolute_path :: proc(t: ^testing.T) { + when ODIN_OS == .Windows { + testing.expect(t, os.is_absolute_path(`C:\Windows`)) + } else { + testing.expect(t, os.is_absolute_path("/home")) + } + testing.expect(t, !os.is_absolute_path("home")) +} + +@(test) +test_get_relative_path :: proc(t: ^testing.T) { + Test_Case :: struct { + base, target: string, + expected: string, + } + + Fail_Case :: struct { + base, target: string, + } + + test_cases := [?]Test_Case { + {"", "foo", "foo"}, + {".", "foo", "foo"}, + {"/", "/", "."}, + {"/", "/home/alice/bert", "home/alice/bert"}, + {"/a", "/b", "../b"}, + {"/あ", "/あ/a", "a"}, + {"/a", "/a/あ", "あ"}, + {"/あ", "/い", "../い"}, + {"/a", "/usr", "../usr"}, + {"/home", "/", ".."}, + {"/home", "/home/alice/bert", "alice/bert"}, + {"/home/foo", "/", "../.."}, + {"/home/foo", "/home", ".."}, + {"/home/foo", "/home/alice/bert", "../alice/bert"}, + {"/home/foo", "/home/foo", "."}, + {"/home/foo", "/home/foo/bar", "bar"}, + {"/home/foo/bar", "/home", "../.."}, + {"/home/foo/bar", "/home/alice/bert", "../../alice/bert"}, + {"/home/foo/bar/bert", "/home/alice/bert", "../../../alice/bert"}, + {"/www", "/mount", "../mount"}, + {"foo", ".", ".."}, + {"foo", "bar", "../bar"}, + {"foo", "bar", "../bar"}, + {"foo", "../bar", "../../bar"}, + {"foo", "foo", "."}, + {"foo", "foo/bar", "bar"}, + {"home/foo/bar", "home/alice/bert", "../../alice/bert"}, + } + + fail_cases := [?]Fail_Case { + {"", "/home"}, + {"/home", ""}, + {"..", ""}, + } + + when ODIN_OS == .Windows { + for &tc in test_cases { + tc.base = posix_to_dos_path(tc.base) + tc.target = posix_to_dos_path(tc.target) + // Make one part all capitals to test case-insensitivity. + tc.target = strings.to_upper(tc.target, context.temp_allocator) + tc.expected = posix_to_dos_path(tc.expected) + } + for &tc in fail_cases { + tc.base = posix_to_dos_path(tc.base) + tc.target = posix_to_dos_path(tc.target) + } + } + + for tc in test_cases { + result, err := os.get_relative_path(tc.base, tc.target, context.temp_allocator) + joined, err2 := os.join_path({tc.base, result}, context.temp_allocator) + + when ODIN_OS == .Windows { + passed := strings.equal_fold(result, tc.expected) && err == nil + join_guaranteed := strings.equal_fold(joined, tc.target) && err2 == nil + } else { + passed := result == tc.expected && err == nil + join_guaranteed := joined == tc.target && err2 == nil + } + testing.expectf(t, passed, "expected get_relative_path(%q, %q) -> %q; got %q, %v", tc.base, tc.target, tc.expected, result, err) + testing.expectf(t, join_guaranteed, "join_path({{%q, %q}}) guarantee of get_relative_path(%q, %q) failed; got %q, %v instead", tc.base, result, tc.base, tc.target, joined, err2) + } + + for tc in fail_cases { + result, err := os.get_relative_path(tc.base, tc.target, context.temp_allocator) + testing.expectf(t, result == "" && err != nil, "expected get_relative_path(%q, %q) to fail, got %q, %v", tc.base, tc.target, result, err) + } +} + +@(test) +test_split_path :: proc(t: ^testing.T) { + Test_Case :: struct { + path: string, + dir, filename: string, + } + + test_cases := [?]Test_Case { + { "", "", "" }, + { "/", "/", "" }, + { "/a", "/", "a" }, + { "readme.txt", "", "readme.txt" }, + { "/readme.txt", "/", "readme.txt" }, + { "/var/readme.txt", "/var", "readme.txt" }, + { "/home/foo/bar.tar.gz", "/home/foo", "bar.tar.gz" }, + } + + when ODIN_OS == .Windows { + for &tc in test_cases { + tc.path = posix_to_dos_path(tc.path) + tc.dir = posix_to_dos_path(tc.dir) + tc.filename = posix_to_dos_path(tc.filename) + } + } + + for tc in test_cases { + dir, filename := os.split_path(tc.path) + testing.expectf(t, dir == tc.dir && filename == tc.filename, "expected split_path(%q) -> %q, %q; got: %q, %q", tc.path, tc.dir, tc.filename, dir, filename) + } +} + +@(test) +test_join_path :: proc(t: ^testing.T) { + Test_Case :: struct { + elems: []string, + expected: string, + } + + test_cases := [?]Test_Case { + { {"" }, "" }, + { {"/" }, "/" }, + { {"home" }, "home" }, + { {"home", "" }, "home" }, + { {"/home", "" }, "/home" }, + { {"", "home" }, "home" }, + { {"", "/home" }, "/home" }, + { {"", "/home", "", "foo" }, "/home/foo" }, + { {"", "home", "", "", "foo", "" }, "home/foo" }, + } + + when ODIN_OS == .Windows { + for &tc in test_cases { + for &elem in tc.elems { + elem = posix_to_dos_path(elem) + } + tc.expected = posix_to_dos_path(tc.expected) + } + } + + for tc in test_cases { + result, err := os.join_path(tc.elems, context.temp_allocator) + testing.expectf(t, result == tc.expected && err == nil, "expected join_path(%v) -> %q; got: %q, %v", tc.elems, tc.expected, result, err) + } +} + +@(test) +test_split_filename :: proc(t: ^testing.T) { + Test_Case :: struct { + filename: string, + base, ext: string, + } + + test_cases := [?]Test_Case { + {"", "", ""}, + {"a", "a", ""}, + {".", ".", ""}, + {".a", ".a", ""}, + {".foo", ".foo", ""}, + {".foo.txt", ".foo", "txt"}, + {"a.b", "a", "b"}, + {"foo", "foo", ""}, + {"readme.txt", "readme", "txt"}, + {"pkg.tar.gz", "pkg.tar", "gz"}, + // Assert API ignores directory hierarchies: + {"dir/FILE.TXT", "dir/FILE", "TXT"}, + } + + for tc in test_cases { + base, ext := os.split_filename(tc.filename) + testing.expectf(t, base == tc.base && ext == tc.ext, "expected split_filename(%q) -> %q, %q; got: %q, %q", tc.filename, tc.base, tc.ext, base, ext) + } +} + +@(test) +test_split_filename_all :: proc(t: ^testing.T) { + Test_Case :: struct { + filename: string, + base, ext: string, + } + + test_cases := [?]Test_Case { + {"", "", ""}, + {"a", "a", ""}, + {".", ".", ""}, + {".a", ".a", ""}, + {".foo", ".foo", ""}, + {".foo.txt", ".foo", "txt"}, + {"a.b", "a", "b"}, + {"foo", "foo", ""}, + {"readme.txt", "readme", "txt"}, + {"pkg.tar.gz", "pkg", "tar.gz"}, + // Assert API ignores directory hierarchies: + {"dir/FILE.TXT", "dir/FILE", "TXT"}, + } + + for tc in test_cases { + base, ext := os.split_filename_all(tc.filename) + testing.expectf(t, base == tc.base && ext == tc.ext, "expected split_filename_all(%q) -> %q, %q; got: %q, %q", tc.filename, tc.base, tc.ext, base, ext) + } +} + +@(test) +test_join_filename :: proc(t: ^testing.T) { + Test_Case :: struct { + base, ext: string, + expected: string, + } + + test_cases := [?]Test_Case { + {"", "", ""}, + {"", "foo", "foo"}, + {"foo", "", "foo"}, + {"readme", "txt", "readme.txt"}, + {"pkg.tar", "gz", "pkg.tar.gz"}, + {"pkg", "tar.gz", "pkg.tar.gz"}, + // Assert API ignores directory hierarchies: + {"dir/FILE", "TXT", "dir/FILE.TXT"}, + } + + for tc in test_cases { + result, err := os.join_filename(tc.base, tc.ext, context.temp_allocator) + testing.expectf(t, result == tc.expected && err == nil, "expected join_filename(%q, %q) -> %q; got: %q, %v", tc.base, tc.ext, tc.expected, result, err) + } +} + +@(test) +test_split_path_list :: proc(t: ^testing.T) { + Test_Case :: struct { + path_list: string, + expected: []string, + } + + when ODIN_OS != .Windows { + test_cases := [?]Test_Case { + {``, {}}, + {`/bin:`, {`/bin`, ``}}, + {`/usr/local/bin`, {`/usr/local/bin`}}, + {`/usr/local/bin:/usr/bin`, {`/usr/local/bin`, `/usr/bin`}}, + {`"/extra bin":/bin`, {`/extra bin`, `/bin`}}, + {`"/extra:bin":/bin`, {`/extra:bin`, `/bin`}}, + } + } else { + test_cases := [?]Test_Case { + {``, {}}, + {`C:\bin;`, {`C:\bin`, ``}}, + {`C:\usr\local\bin`, {`C:\usr\local\bin`}}, + {`C:\usr\local\bin;C:\usr\bin`, {`C:\usr\local\bin`, `C:\usr\bin`}}, + {`"C:\extra bin";C:\bin`, {`C:\extra bin`, `C:\bin`}}, + {`"C:\extra;bin";C:\bin`, {`C:\extra;bin`, `C:\bin`}}, + } + } + + for tc in test_cases { + result, err := os.split_path_list(tc.path_list, context.temp_allocator) + if testing.expectf(t, len(result) == len(tc.expected), "expected split_path_list(%q) -> %v; got %v, %v", tc.path_list, tc.expected, result, err) { + ok := true + for entry, i in result { + if entry != tc.expected[i] { + ok = false + break + } + } + testing.expectf(t, ok, "expected split_path_list(%q) -> %v; got %v, %v", tc.path_list, tc.expected, result, err) + } + } +} From 6a6980fda827b0f94a9d72daf64d905b38d268c1 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 20 Mar 2025 18:32:25 -0400 Subject: [PATCH 06/81] Remove `if ODIN_OS == .Windows` in file that can only be built on Windows --- core/os/os2/stat_windows.odin | 52 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin index 14744c90f..7d8dd3843 100644 --- a/core/os/os2/stat_windows.odin +++ b/core/os/os2/stat_windows.odin @@ -315,38 +315,36 @@ _is_UNC :: proc(path: string) -> bool { } _volume_name_len :: proc(path: string) -> int { - if ODIN_OS == .Windows { - if len(path) < 2 { - return 0 - } - c := path[0] - if path[1] == ':' { - switch c { - case 'a'..='z', 'A'..='Z': - return 2 - } + if len(path) < 2 { + return 0 + } + c := path[0] + if path[1] == ':' { + switch c { + case 'a'..='z', 'A'..='Z': + return 2 } + } - // URL: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx - if l := len(path); l >= 5 && _is_path_separator(path[0]) && _is_path_separator(path[1]) && - !_is_path_separator(path[2]) && path[2] != '.' { - for n := 3; n < l-1; n += 1 { - if _is_path_separator(path[n]) { - n += 1 - if !_is_path_separator(path[n]) { - if path[n] == '.' { - break - } + // URL: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx + if l := len(path); l >= 5 && _is_path_separator(path[0]) && _is_path_separator(path[1]) && + !_is_path_separator(path[2]) && path[2] != '.' { + for n := 3; n < l-1; n += 1 { + if _is_path_separator(path[n]) { + n += 1 + if !_is_path_separator(path[n]) { + if path[n] == '.' { + break } - for ; n < l; n += 1 { - if _is_path_separator(path[n]) { - break - } - } - return n } - break + for ; n < l; n += 1 { + if _is_path_separator(path[n]) { + break + } + } + return n } + break } } return 0 From cfa3e9796894f3269ef1451f19d711c80f95c956 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:40:17 -0400 Subject: [PATCH 07/81] Make `os2` Linux `_is_path_separator` compare against `_Path_Separator` --- core/os/os2/path_linux.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/os/os2/path_linux.odin b/core/os/os2/path_linux.odin index e3e7f8a7c..410b4cb28 100644 --- a/core/os/os2/path_linux.odin +++ b/core/os/os2/path_linux.odin @@ -14,7 +14,7 @@ _Path_List_Separator :: ':' _OPENDIR_FLAGS : linux.Open_Flags : {.NONBLOCK, .DIRECTORY, .LARGEFILE, .CLOEXEC} _is_path_separator :: proc(c: byte) -> bool { - return c == '/' + return c == _Path_Separator } _mkdir :: proc(path: string, perm: int) -> Error { From 649376fcfe330090b8c6020e29b0600ca7dd9a3b Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Fri, 21 Mar 2025 18:33:42 -0400 Subject: [PATCH 08/81] Add `require_results` to getters in `os2` path API --- core/os/os2/path.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/os/os2/path.odin b/core/os/os2/path.odin index 24d1f35bd..e62ee11bc 100644 --- a/core/os/os2/path.odin +++ b/core/os/os2/path.odin @@ -79,6 +79,7 @@ Get the path for the currently running executable. *Allocates Using Provided Allocator* */ +@(require_results) get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { return _get_executable_path(allocator) } @@ -88,6 +89,7 @@ Get the directory for the currently running executable. *Allocates Using Provided Allocator* */ +@(require_results) get_executable_directory :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { path = _get_executable_path(allocator) or_return path, _ = split_path(path) From 2af691f58741eae8fa4ada329bdf65729f9a50fe Mon Sep 17 00:00:00 2001 From: Wison Ye Date: Sun, 23 Mar 2025 13:22:19 +1300 Subject: [PATCH 09/81] Fixed: Freebsd syscall 'getpeername' is missing. --- core/sys/freebsd/syscalls.odin | 42 ++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/core/sys/freebsd/syscalls.odin b/core/sys/freebsd/syscalls.odin index 83b51138a..3c96e0b52 100644 --- a/core/sys/freebsd/syscalls.odin +++ b/core/sys/freebsd/syscalls.odin @@ -21,6 +21,7 @@ SYS_close : uintptr : 6 SYS_getpid : uintptr : 20 SYS_recvfrom : uintptr : 29 SYS_accept : uintptr : 30 +SYS_getpeername: uintptr : 31 SYS_getsockname: uintptr : 32 SYS_fcntl : uintptr : 92 SYS_fsync : uintptr : 95 @@ -202,24 +203,37 @@ accept_nil :: proc "contextless" (s: Fd) -> (Fd, Errno) { accept :: proc { accept_T, accept_nil } +getsockname_or_peername :: proc "contextless" (s: Fd, sockaddr: ^$T, is_peer: bool) -> Errno { + // sockaddr must contain a valid pointer, or this will segfault because + // we're telling the syscall that there's memory available to write to. + addrlen: socklen_t = size_of(T) + + result, ok := intrinsics.syscall_bsd( + is_peer ? SYS_getpeername : SYS_getsockname, + cast(uintptr)s, + cast(uintptr)sockaddr, + cast(uintptr)&addrlen + ) + + if !ok { + return cast(Errno)result + } + + return nil +} + +// Get name of connected peer +// +// The getpeername() system call appeared in 4.2BSD. +getpeername :: proc "contextless" (s: Fd, sockaddr: ^$T) -> Errno { + return getsockname_or_peername(s, sockaddr, true) +} + // Get socket name. // // The getsockname() system call appeared in 4.2BSD. getsockname :: proc "contextless" (s: Fd, sockaddr: ^$T) -> Errno { - // sockaddr must contain a valid pointer, or this will segfault because - // we're telling the syscall that there's memory available to write to. - addrlen: socklen_t = size_of(T) - - result, ok := intrinsics.syscall_bsd(SYS_getsockname, - cast(uintptr)s, - cast(uintptr)sockaddr, - cast(uintptr)&addrlen) - - if !ok { - return cast(Errno)result - } - - return nil + return getsockname_or_peername(s, sockaddr, false) } // Synchronize changes to a file. From 61acb1552918c773d771725a8a7179a41d6c4924 Mon Sep 17 00:00:00 2001 From: Wison Ye Date: Sun, 23 Mar 2025 13:32:11 +1300 Subject: [PATCH 10/81] #4959, fixed the broken CI build. --- core/sys/freebsd/syscalls.odin | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/sys/freebsd/syscalls.odin b/core/sys/freebsd/syscalls.odin index 3c96e0b52..405d1e47c 100644 --- a/core/sys/freebsd/syscalls.odin +++ b/core/sys/freebsd/syscalls.odin @@ -212,8 +212,7 @@ getsockname_or_peername :: proc "contextless" (s: Fd, sockaddr: ^$T, is_peer: bo is_peer ? SYS_getpeername : SYS_getsockname, cast(uintptr)s, cast(uintptr)sockaddr, - cast(uintptr)&addrlen - ) + cast(uintptr)&addrlen) if !ok { return cast(Errno)result From 0113907527a25a054d518fbe781d7de9602cc76b Mon Sep 17 00:00:00 2001 From: James Liljenquist Date: Sat, 22 Mar 2025 21:01:15 -0600 Subject: [PATCH 11/81] Bug fixes for wgpu.js --- vendor/wgpu/wgpu.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/vendor/wgpu/wgpu.js b/vendor/wgpu/wgpu.js index 055f7abab..7866c7131 100644 --- a/vendor/wgpu/wgpu.js +++ b/vendor/wgpu/wgpu.js @@ -2588,7 +2588,12 @@ class WebGPUInterface { } dynamicOffsetCount = this.unwrapBigInt(dynamicOffsetCount); - const dynamicOffsets = this.array(dynamicOffsetCount, dynamicOffsetsPtr, this.mem.loadU32, 4); + const dynamicOffsets = this.array( + dynamicOffsetCount, + dynamicOffsetsPtr, + (ptr) => this.mem.loadU32(ptr), + 4 + ); renderBundleEncoder.setBindGroup(groupIndex, group, dynamicOffsets); }, @@ -2780,7 +2785,12 @@ class WebGPUInterface { } dynamicOffsetCount = this.unwrapBigInt(dynamicOffsetCount); - const dynamicOffsets = this.array(dynamicOffsetCount, dynamicOffsetsPtr, this.mem.loadU32, 4); + const dynamicOffsets = this.array( + dynamicOffsetCount, + dynamicOffsetsPtr, + (ptr) => this.mem.loadU32(ptr), + 4 + ); renderPassEncoder.setBindGroup(groupIndex, group, dynamicOffsets); }, @@ -3087,7 +3097,7 @@ class WebGPUInterface { * @param {number} surfaceCapabilitiesPtr */ wgpuSurfaceCapabilitiesFreeMembers: (surfaceCapabilitiesPtr) => { - const off = this.struct(capabilitiesPtr); + const off = this.struct(surfaceCapabilitiesPtr); off(4); // nextInChain off(8); // usages off(this.mem.intSize); // formatCount From 4c28f6d170da9f7fe29ace5e40933fba9c2f946e Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Fri, 11 Oct 2024 02:10:02 +0900 Subject: [PATCH 12/81] core/crypto/_aes/hw_intel: Fix comment (NFC) --- core/crypto/_aes/hw_intel/ghash.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/crypto/_aes/hw_intel/ghash.odin b/core/crypto/_aes/hw_intel/ghash.odin index 4320dd59b..ed89d2956 100644 --- a/core/crypto/_aes/hw_intel/ghash.odin +++ b/core/crypto/_aes/hw_intel/ghash.odin @@ -52,7 +52,7 @@ GHASH_STRIDE_BYTES_HW :: GHASH_STRIDE_HW * _aes.GHASH_BLOCK_SIZE // that it is right-shifted by 1 bit. The left-shift is relatively // inexpensive, and it can be mutualised. // -// Since SSE2 opcodes do not have facilities for shitfting full 128-bit +// Since SSE2 opcodes do not have facilities for shifting full 128-bit // values with bit precision, we have to break down values into 64-bit // chunks. We number chunks from 0 to 3 in left to right order. From e4e76f27f6549560017c89bdf129fdcca6d9afa0 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Tue, 27 Aug 2024 20:54:50 +0900 Subject: [PATCH 13/81] core/crypto: Use `panic_contextless` instead of `intrinsics.trap` --- core/crypto/_aes/ct64/ct64.odin | 4 +--- core/crypto/_aes/ct64/ct64_enc.odin | 4 +--- core/crypto/_aes/ct64/ct64_keysched.odin | 3 +-- core/crypto/_aes/ct64/ghash.odin | 3 +-- core/crypto/_aes/ct64/helpers.odin | 13 ++++++------- core/crypto/_aes/hw_intel/ghash.odin | 2 +- core/crypto/_chacha20/chacha20.odin | 3 +-- .../_chacha20/simd256/chacha20_simd256_stub.odin | 2 +- core/crypto/_edwards25519/edwards25519.odin | 5 ++--- core/crypto/_edwards25519/edwards25519_scalar.odin | 5 ++--- core/crypto/_fiat/field_poly1305/field.odin | 3 +-- core/crypto/_fiat/field_scalar25519/field.odin | 5 ++--- core/crypto/aead/aead.odin | 2 +- 13 files changed, 21 insertions(+), 33 deletions(-) diff --git a/core/crypto/_aes/ct64/ct64.odin b/core/crypto/_aes/ct64/ct64.odin index f198cab81..b2d5b72bc 100644 --- a/core/crypto/_aes/ct64/ct64.odin +++ b/core/crypto/_aes/ct64/ct64.odin @@ -22,8 +22,6 @@ package aes_ct64 -import "base:intrinsics" - // Bitsliced AES for 64-bit general purpose (integer) registers. Each // invocation will process up to 4 blocks at a time. This implementation // is derived from the BearSSL ct64 code, and distributed under a 1-clause @@ -214,7 +212,7 @@ orthogonalize :: proc "contextless" (q: ^[8]u64) { @(require_results) interleave_in :: proc "contextless" (w: []u32) -> (q0, q1: u64) #no_bounds_check { if len(w) < 4 { - intrinsics.trap() + panic_contextless("aes/ct64: invalid input size") } x0, x1, x2, x3 := u64(w[0]), u64(w[1]), u64(w[2]), u64(w[3]) x0 |= (x0 << 16) diff --git a/core/crypto/_aes/ct64/ct64_enc.odin b/core/crypto/_aes/ct64/ct64_enc.odin index 36d4aebc8..e099b3eaf 100644 --- a/core/crypto/_aes/ct64/ct64_enc.odin +++ b/core/crypto/_aes/ct64/ct64_enc.odin @@ -22,11 +22,9 @@ package aes_ct64 -import "base:intrinsics" - add_round_key :: proc "contextless" (q: ^[8]u64, sk: []u64) #no_bounds_check { if len(sk) < 8 { - intrinsics.trap() + panic_contextless("aes/ct64: invalid round key size") } q[0] ~= sk[0] diff --git a/core/crypto/_aes/ct64/ct64_keysched.odin b/core/crypto/_aes/ct64/ct64_keysched.odin index 060a2c03e..0cb01aa08 100644 --- a/core/crypto/_aes/ct64/ct64_keysched.odin +++ b/core/crypto/_aes/ct64/ct64_keysched.odin @@ -22,7 +22,6 @@ package aes_ct64 -import "base:intrinsics" import "core:crypto/_aes" import "core:encoding/endian" import "core:mem" @@ -126,7 +125,7 @@ skey_expand :: proc "contextless" (skey, comp_skey: []u64, num_rounds: int) { orthogonalize_roundkey :: proc "contextless" (qq: []u64, key: []byte) { if len(qq) < 8 || len(key) != 16 { - intrinsics.trap() + panic_contextless("aes/ct64: invalid round key size") } skey: [4]u32 = --- diff --git a/core/crypto/_aes/ct64/ghash.odin b/core/crypto/_aes/ct64/ghash.odin index a522a481a..fe6e364fc 100644 --- a/core/crypto/_aes/ct64/ghash.odin +++ b/core/crypto/_aes/ct64/ghash.odin @@ -22,7 +22,6 @@ package aes_ct64 -import "base:intrinsics" import "core:crypto/_aes" import "core:encoding/endian" @@ -65,7 +64,7 @@ rev64 :: proc "contextless" (x: u64) -> u64 { // of GCM. ghash :: proc "contextless" (dst, key, data: []byte) { if len(dst) != _aes.GHASH_BLOCK_SIZE || len(key) != _aes.GHASH_BLOCK_SIZE { - intrinsics.trap() + panic_contextless("aes/ghash: invalid dst or key size") } buf := data diff --git a/core/crypto/_aes/ct64/helpers.odin b/core/crypto/_aes/ct64/helpers.odin index 169271f6d..0ca9c3f4e 100644 --- a/core/crypto/_aes/ct64/helpers.odin +++ b/core/crypto/_aes/ct64/helpers.odin @@ -1,12 +1,11 @@ package aes_ct64 -import "base:intrinsics" import "core:crypto/_aes" import "core:encoding/endian" load_blockx1 :: proc "contextless" (q: ^[8]u64, src: []byte) { if len(src) != _aes.BLOCK_SIZE { - intrinsics.trap() + panic_contextless("aes/ct64: invalid block size") } w: [4]u32 = --- @@ -20,7 +19,7 @@ load_blockx1 :: proc "contextless" (q: ^[8]u64, src: []byte) { store_blockx1 :: proc "contextless" (dst: []byte, q: ^[8]u64) { if len(dst) != _aes.BLOCK_SIZE { - intrinsics.trap() + panic_contextless("aes/ct64: invalid block size") } orthogonalize(q) @@ -33,13 +32,13 @@ store_blockx1 :: proc "contextless" (dst: []byte, q: ^[8]u64) { load_blocks :: proc "contextless" (q: ^[8]u64, src: [][]byte) { if n := len(src); n > STRIDE || n == 0 { - intrinsics.trap() + panic_contextless("aes/ct64: invalid block(s) size") } w: [4]u32 = --- for s, i in src { if len(s) != _aes.BLOCK_SIZE { - intrinsics.trap() + panic_contextless("aes/ct64: invalid block size") } w[0] = endian.unchecked_get_u32le(s[0:]) @@ -53,7 +52,7 @@ load_blocks :: proc "contextless" (q: ^[8]u64, src: [][]byte) { store_blocks :: proc "contextless" (dst: [][]byte, q: ^[8]u64) { if n := len(dst); n > STRIDE || n == 0 { - intrinsics.trap() + panic_contextless("aes/ct64: invalid block(s) size") } orthogonalize(q) @@ -63,7 +62,7 @@ store_blocks :: proc "contextless" (dst: [][]byte, q: ^[8]u64) { break } if len(d) != _aes.BLOCK_SIZE { - intrinsics.trap() + panic_contextless("aes/ct64: invalid block size") } w0, w1, w2, w3 := interleave_out(q[i], q[i + 4]) diff --git a/core/crypto/_aes/hw_intel/ghash.odin b/core/crypto/_aes/hw_intel/ghash.odin index ed89d2956..5f51b614b 100644 --- a/core/crypto/_aes/hw_intel/ghash.odin +++ b/core/crypto/_aes/hw_intel/ghash.odin @@ -155,7 +155,7 @@ square_f128 :: #force_inline proc "contextless" (kw: x86.__m128i) -> (x86.__m128 @(enable_target_feature = "sse2,ssse3,pclmul") ghash :: proc "contextless" (dst, key, data: []byte) #no_bounds_check { if len(dst) != _aes.GHASH_BLOCK_SIZE || len(key) != _aes.GHASH_BLOCK_SIZE { - intrinsics.trap() + panic_contextless("aes/ghash: invalid dst or key size") } // Note: BearSSL opts to copy the remainder into a zero-filled diff --git a/core/crypto/_chacha20/chacha20.odin b/core/crypto/_chacha20/chacha20.odin index a907209de..c7812f7ab 100644 --- a/core/crypto/_chacha20/chacha20.odin +++ b/core/crypto/_chacha20/chacha20.odin @@ -1,6 +1,5 @@ package _chacha20 -import "base:intrinsics" import "core:encoding/endian" import "core:math/bits" import "core:mem" @@ -47,7 +46,7 @@ Context :: struct { // HChaCha call can be suitably accelerated. init :: proc "contextless" (ctx: ^Context, key, iv: []byte, is_xchacha: bool) { if len(key) != KEY_SIZE || len(iv) != IV_SIZE { - intrinsics.trap() + panic_contextless("chacha20: invalid key or IV size") } k, n := key, iv diff --git a/core/crypto/_chacha20/simd256/chacha20_simd256_stub.odin b/core/crypto/_chacha20/simd256/chacha20_simd256_stub.odin index ce673b42b..287ddd885 100644 --- a/core/crypto/_chacha20/simd256/chacha20_simd256_stub.odin +++ b/core/crypto/_chacha20/simd256/chacha20_simd256_stub.odin @@ -13,5 +13,5 @@ stream_blocks :: proc(ctx: ^_chacha20.Context, dst, src: []byte, nr_blocks: int) } hchacha20 :: proc "contextless" (dst, key, iv: []byte) { - intrinsics.trap() + panic_contextless("crypto/chacha20: simd256 implementation unsupported") } \ No newline at end of file diff --git a/core/crypto/_edwards25519/edwards25519.odin b/core/crypto/_edwards25519/edwards25519.odin index 6495f7a3a..a091afad9 100644 --- a/core/crypto/_edwards25519/edwards25519.odin +++ b/core/crypto/_edwards25519/edwards25519.odin @@ -11,7 +11,6 @@ See: - https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html */ -import "base:intrinsics" import "core:crypto" import field "core:crypto/_fiat/field_curve25519" import "core:mem" @@ -108,7 +107,7 @@ ge_set :: proc "contextless" (ge, a: ^Group_Element) { @(require_results) ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool { if len(b) != 32 { - intrinsics.trap() + panic_contextless("edwards25519: invalid group element size") } b_ := (^[32]byte)(raw_data(b)) @@ -167,7 +166,7 @@ ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool { ge_bytes :: proc "contextless" (ge: ^Group_Element, dst: []byte) { if len(dst) != 32 { - intrinsics.trap() + panic_contextless("edwards25519: invalid group element size") } dst_ := (^[32]byte)(raw_data(dst)) diff --git a/core/crypto/_edwards25519/edwards25519_scalar.odin b/core/crypto/_edwards25519/edwards25519_scalar.odin index e21fa3755..a820ef948 100644 --- a/core/crypto/_edwards25519/edwards25519_scalar.odin +++ b/core/crypto/_edwards25519/edwards25519_scalar.odin @@ -1,6 +1,5 @@ package _edwards25519 -import "base:intrinsics" import field "core:crypto/_fiat/field_scalar25519" import "core:mem" @@ -26,7 +25,7 @@ sc_set_u64 :: proc "contextless" (sc: ^Scalar, i: u64) { @(require_results) sc_set_bytes :: proc "contextless" (sc: ^Scalar, b: []byte) -> bool { if len(b) != 32 { - intrinsics.trap() + panic_contextless("edwards25519: invalid scalar size") } b_ := (^[32]byte)(raw_data(b)) return field.fe_from_bytes(sc, b_) @@ -34,7 +33,7 @@ sc_set_bytes :: proc "contextless" (sc: ^Scalar, b: []byte) -> bool { sc_set_bytes_rfc8032 :: proc "contextless" (sc: ^Scalar, b: []byte) { if len(b) != 32 { - intrinsics.trap() + panic_contextless("edwards25519: invalid scalar size") } b_ := (^[32]byte)(raw_data(b)) field.fe_from_bytes_rfc8032(sc, b_) diff --git a/core/crypto/_fiat/field_poly1305/field.odin b/core/crypto/_fiat/field_poly1305/field.odin index b12046858..c888f1e8b 100644 --- a/core/crypto/_fiat/field_poly1305/field.odin +++ b/core/crypto/_fiat/field_poly1305/field.odin @@ -1,6 +1,5 @@ package field_poly1305 -import "base:intrinsics" import "core:encoding/endian" import "core:mem" @@ -30,7 +29,7 @@ fe_from_bytes :: #force_inline proc "contextless" ( // neater. if len(arg1) != 16 { - intrinsics.trap() + panic_contextless("poly1305: invalid field element size") } // While it may be unwise to do deserialization here on our diff --git a/core/crypto/_fiat/field_scalar25519/field.odin b/core/crypto/_fiat/field_scalar25519/field.odin index 9b40661b7..ddaf5d0c7 100644 --- a/core/crypto/_fiat/field_scalar25519/field.odin +++ b/core/crypto/_fiat/field_scalar25519/field.odin @@ -1,6 +1,5 @@ package field_scalar25519 -import "base:intrinsics" import "core:encoding/endian" import "core:math/bits" import "core:mem" @@ -96,7 +95,7 @@ fe_from_bytes_wide :: proc "contextless" ( _fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element, arg1: []byte) { // INVARIANT: len(arg1) < 32. if len(arg1) >= 32 { - intrinsics.trap() + panic_contextless("edwards25519: oversized short scalar") } tmp: [32]byte copy(tmp[:], arg1) @@ -107,7 +106,7 @@ _fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Eleme fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { if len(out1) != 32 { - intrinsics.trap() + panic_contextless("edwards25519: oversized scalar output buffer") } tmp: Non_Montgomery_Domain_Field_Element diff --git a/core/crypto/aead/aead.odin b/core/crypto/aead/aead.odin index 9b7d810e4..c8f324929 100644 --- a/core/crypto/aead/aead.odin +++ b/core/crypto/aead/aead.odin @@ -16,7 +16,7 @@ seal_oneshot :: proc(algo: Algorithm, dst, tag, key, iv, aad, plaintext: []byte, // returning true iff the authentication was successful. If authentication // fails, the destination buffer will be zeroed. // -// dst and plaintext MUST alias exactly or not at all. +// dst and ciphertext MUST alias exactly or not at all. @(require_results) open_oneshot :: proc(algo: Algorithm, dst, key, iv, aad, ciphertext, tag: []byte, impl: Implementation = nil) -> bool { ctx: Context From 6e8710fce43fb6890ca751d7a48d5cc15c93f1c1 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Wed, 28 Aug 2024 04:11:55 +0900 Subject: [PATCH 14/81] core/crypto/chacha20: Misc Simd128 improvements - Detect the RISC-V `v` profile - Don't bother trying to process 4 blocks at a time if emulated --- .../_chacha20/simd128/chacha20_simd128.odin | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/core/crypto/_chacha20/simd128/chacha20_simd128.odin b/core/crypto/_chacha20/simd128/chacha20_simd128.odin index fe0d0d518..cf78541d1 100644 --- a/core/crypto/_chacha20/simd128/chacha20_simd128.odin +++ b/core/crypto/_chacha20/simd128/chacha20_simd128.odin @@ -29,11 +29,24 @@ when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 { // explicitly using simd.u8x16 shuffles. @(private = "file") TARGET_SIMD_FEATURES :: "sse2,ssse3" +} else when ODIN_ARCH == .riscv64 { + @(private = "file") + TARGET_SIMD_FEATURES :: "v" } else { @(private = "file") TARGET_SIMD_FEATURES :: "" } +// Some targets lack runtime feature detection, and will flat out refuse +// to load binaries that have unknown instructions. This is distinct from +// `simd.IS_EMULATED` as actually good designs support runtime feature +// detection and that constant establishes a baseline. +// +// See: +// - https://github.com/WebAssembly/design/issues/1161 +@(private = "file") +TARGET_IS_DESIGNED_BY_IDIOTS :: (ODIN_ARCH == .wasm64p32 || ODIN_ARCH == .wasm32) && !intrinsics.has_target_feature("simd128") + @(private = "file") _ROT_7L: simd.u32x4 : {7, 7, 7, 7} @(private = "file") @@ -205,11 +218,13 @@ _store_simd128 :: #force_inline proc "contextless" ( // is_performant returns true iff the target and current host both support // "enough" 128-bit SIMD to make this implementation performant. is_performant :: proc "contextless" () -> bool { - when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 || ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 || ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 || ODIN_ARCH == .riscv64 { when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 { req_features :: info.CPU_Features{.asimd} } else when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { req_features :: info.CPU_Features{.sse2, .ssse3} + } else when ODIN_ARCH == .riscv64 { + req_features :: info.CPU_Features{.V} } features, ok := info.cpu_features.? @@ -245,8 +260,17 @@ stream_blocks :: proc(ctx: ^_chacha20.Context, dst, src: []byte, nr_blocks: int) // 8 blocks at a time. // - // Note: This is only worth it on Aarch64. - when ODIN_ARCH == .arm64 { + // Note: + // This uses a ton of registers so it is only worth it on targets + // that have something like 32 128-bit registers. This is currently + // all ARMv8 targets, and RISC-V Zvl128b (`V` application profile) + // targets. + // + // While our current definition of `.arm32` is 32-bit ARMv8, this + // may change in the future (ARMv7 is still relevant), and things + // like Cortex-A8/A9 does "pretend" 128-bit SIMD 64-bits at a time + // thus needs bemchmarking. + when ODIN_ARCH == .arm64 || ODIN_ARCH == .riscv64 { for ; n >= 8; n = n - 8 { v0, v1, v2, v3 := s0, s1, s2, s3 @@ -354,9 +378,11 @@ stream_blocks :: proc(ctx: ^_chacha20.Context, dst, src: []byte, nr_blocks: int) // 4 blocks at a time. // - // Note: The i386 target lacks the required number of registers - // for this to be performant, so it is skipped. - when ODIN_ARCH != .i386 { + // Note: This is skipped on several targets for various reasons. + // - i386 lacks the required number of registers + // - Generating code when runtime "hardware" SIMD support is impossible + // to detect is pointless, since this will be emulated using GP regs. + when ODIN_ARCH != .i386 && !TARGET_IS_DESIGNED_BY_IDIOTS { for ; n >= 4; n = n - 4 { v0, v1, v2, v3 := s0, s1, s2, s3 From 50d40c2a268af654487cb16ca1abbdbd3154d796 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Thu, 29 Aug 2024 17:51:55 +0900 Subject: [PATCH 15/81] core/crypto/chacha20poly1305: Add missing assertions --- core/crypto/chacha20poly1305/chacha20poly1305.odin | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/crypto/chacha20poly1305/chacha20poly1305.odin b/core/crypto/chacha20poly1305/chacha20poly1305.odin index 3de2532dd..bb80f560b 100644 --- a/core/crypto/chacha20poly1305/chacha20poly1305.odin +++ b/core/crypto/chacha20poly1305/chacha20poly1305.odin @@ -96,6 +96,8 @@ init_xchacha :: proc(ctx: ^Context, key: []byte, impl := chacha20.DEFAULT_IMPLEM // // dst and plaintext MUST alias exactly or not at all. seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { + assert(ctx._is_initialized) + ciphertext := dst _validate_common_slice_sizes(tag, iv, aad, plaintext, ctx._is_xchacha) if len(ciphertext) != len(plaintext) { @@ -151,6 +153,8 @@ seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { // dst and plaintext MUST alias exactly or not at all. @(require_results) open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { + assert(ctx._is_initialized) + plaintext := dst _validate_common_slice_sizes(tag, iv, aad, ciphertext, ctx._is_xchacha) if len(ciphertext) != len(plaintext) { From bb395aeb41873632c35846f2077eea01a69ce1c1 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Sat, 31 Aug 2024 04:22:32 +0900 Subject: [PATCH 16/81] core/crypto: Add `rodata` annotations (NFC) --- core/crypto/_aes/aes.odin | 1 + core/crypto/_blake2/blake2.odin | 4 ++-- core/crypto/_edwards25519/edwards25519.odin | 8 +++++--- core/crypto/_edwards25519/edwards25519_scalar.odin | 2 +- core/crypto/_fiat/field_curve25519/field51.odin | 3 +++ core/crypto/_fiat/field_scalar25519/field.odin | 4 ++-- core/crypto/_sha3/sha3.odin | 6 +++--- core/crypto/_sha3/sp800_185.odin | 2 +- core/crypto/chacha20poly1305/chacha20poly1305.odin | 2 +- core/crypto/kmac/kmac.odin | 2 +- core/crypto/ristretto255/ristretto255.odin | 10 +++++----- core/crypto/sha2/sha2.odin | 4 ++-- core/crypto/sm3/sm3.odin | 2 +- core/crypto/x25519/x25519.odin | 2 +- 14 files changed, 29 insertions(+), 23 deletions(-) diff --git a/core/crypto/_aes/aes.odin b/core/crypto/_aes/aes.odin index 4f52485d2..f458a12fb 100644 --- a/core/crypto/_aes/aes.odin +++ b/core/crypto/_aes/aes.odin @@ -25,4 +25,5 @@ GHASH_BLOCK_SIZE :: 16 GHASH_TAG_SIZE :: 16 // RCON is the AES keyschedule round constants. +@(rodata) RCON := [10]byte{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36} diff --git a/core/crypto/_blake2/blake2.odin b/core/crypto/_blake2/blake2.odin index 2ad74843b..a012b7e70 100644 --- a/core/crypto/_blake2/blake2.odin +++ b/core/crypto/_blake2/blake2.odin @@ -68,13 +68,13 @@ Blake2_Tree :: struct { is_last_node: bool, } -@(private) +@(private, rodata) BLAKE2S_IV := [8]u32 { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, } -@(private) +@(private, rodata) BLAKE2B_IV := [8]u64 { 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, diff --git a/core/crypto/_edwards25519/edwards25519.odin b/core/crypto/_edwards25519/edwards25519.odin index a091afad9..0234ba05a 100644 --- a/core/crypto/_edwards25519/edwards25519.odin +++ b/core/crypto/_edwards25519/edwards25519.odin @@ -31,6 +31,7 @@ import "core:mem" // - The group element decoding routine takes the opinionated stance of // rejecting non-canonical encodings. +@(rodata) FE_D := field.Tight_Field_Element { 929955233495203, 466365720129213, @@ -38,7 +39,7 @@ FE_D := field.Tight_Field_Element { 2033849074728123, 1442794654840575, } -@(private) +@(private, rodata) FE_A := field.Tight_Field_Element { 2251799813685228, 2251799813685247, @@ -46,7 +47,7 @@ FE_A := field.Tight_Field_Element { 2251799813685247, 2251799813685247, } -@(private) +@(private, rodata) FE_D2 := field.Tight_Field_Element { 1859910466990425, 932731440258426, @@ -54,7 +55,7 @@ FE_D2 := field.Tight_Field_Element { 1815898335770999, 633789495995903, } -@(private) +@(private, rodata) GE_BASEPOINT := Group_Element { field.Tight_Field_Element { 1738742601995546, @@ -79,6 +80,7 @@ GE_BASEPOINT := Group_Element { 1821297809914039, }, } +@(rodata) GE_IDENTITY := Group_Element { field.Tight_Field_Element{0, 0, 0, 0, 0}, field.Tight_Field_Element{1, 0, 0, 0, 0}, diff --git a/core/crypto/_edwards25519/edwards25519_scalar.odin b/core/crypto/_edwards25519/edwards25519_scalar.odin index a820ef948..f650b27d3 100644 --- a/core/crypto/_edwards25519/edwards25519_scalar.odin +++ b/core/crypto/_edwards25519/edwards25519_scalar.odin @@ -7,7 +7,7 @@ Scalar :: field.Montgomery_Domain_Field_Element // WARNING: This is non-canonical and only to be used when checking if // a group element is on the prime-order subgroup. -@(private) +@(private, rodata) SC_ELL := field.Non_Montgomery_Domain_Field_Element { field.ELL[0], field.ELL[1], diff --git a/core/crypto/_fiat/field_curve25519/field51.odin b/core/crypto/_fiat/field_curve25519/field51.odin index d039bd411..6716fa158 100644 --- a/core/crypto/_fiat/field_curve25519/field51.odin +++ b/core/crypto/_fiat/field_curve25519/field51.odin @@ -42,9 +42,12 @@ import "core:math/bits" Loose_Field_Element :: distinct [5]u64 Tight_Field_Element :: distinct [5]u64 +@(rodata) FE_ZERO := Tight_Field_Element{0, 0, 0, 0, 0} +@(rodata) FE_ONE := Tight_Field_Element{1, 0, 0, 0, 0} +@(rodata) FE_SQRT_M1 := Tight_Field_Element { 1718705420411056, 234908883556509, diff --git a/core/crypto/_fiat/field_scalar25519/field.odin b/core/crypto/_fiat/field_scalar25519/field.odin index ddaf5d0c7..430891641 100644 --- a/core/crypto/_fiat/field_scalar25519/field.odin +++ b/core/crypto/_fiat/field_scalar25519/field.odin @@ -4,14 +4,14 @@ import "core:encoding/endian" import "core:math/bits" import "core:mem" -@(private) +@(private, rodata) _TWO_168 := Montgomery_Domain_Field_Element { 0x5b8ab432eac74798, 0x38afddd6de59d5d7, 0xa2c131b399411b7c, 0x6329a7ed9ce5a30, } -@(private) +@(private, rodata) _TWO_336 := Montgomery_Domain_Field_Element { 0xbd3d108e2b35ecc5, 0x5c3a3718bdf9c90b, diff --git a/core/crypto/_sha3/sha3.odin b/core/crypto/_sha3/sha3.odin index 2db76fce0..98e15b29d 100644 --- a/core/crypto/_sha3/sha3.odin +++ b/core/crypto/_sha3/sha3.odin @@ -44,7 +44,7 @@ Context :: struct { is_finalized: bool, // For SHAKE (unlimited squeeze is allowed) } -@(private) +@(private, rodata) keccakf_rndc := [?]u64 { 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, @@ -56,13 +56,13 @@ keccakf_rndc := [?]u64 { 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, } -@(private) +@(private, rodata) keccakf_rotc := [?]int { 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, } -@(private) +@(private, rodata) keccakf_piln := [?]i32 { 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, diff --git a/core/crypto/_sha3/sp800_185.odin b/core/crypto/_sha3/sp800_185.odin index a96f78cc1..a08cb1d11 100644 --- a/core/crypto/_sha3/sp800_185.odin +++ b/core/crypto/_sha3/sp800_185.odin @@ -52,7 +52,7 @@ rate_cshake :: #force_inline proc(sec_strength: int) -> int { // // Thus we support 0 <= x < 2^128. -@(private) +@(private, rodata) _PAD: [RATE_128]byte // Biggest possible value of w per spec. bytepad :: proc(ctx: ^Context, x_strings: [][]byte, w: int) { diff --git a/core/crypto/chacha20poly1305/chacha20poly1305.odin b/core/crypto/chacha20poly1305/chacha20poly1305.odin index bb80f560b..3ef2a5586 100644 --- a/core/crypto/chacha20poly1305/chacha20poly1305.odin +++ b/core/crypto/chacha20poly1305/chacha20poly1305.odin @@ -51,7 +51,7 @@ _validate_common_slice_sizes :: proc (tag, iv, aad, text: []byte, is_xchacha: bo } } -@(private) +@(private, rodata) _PAD: [16]byte @(private) diff --git a/core/crypto/kmac/kmac.odin b/core/crypto/kmac/kmac.odin index e8bf42946..298cbf428 100644 --- a/core/crypto/kmac/kmac.odin +++ b/core/crypto/kmac/kmac.odin @@ -112,5 +112,5 @@ _init_kmac :: proc(ctx: ^Context, key, s: []byte, sec_strength: int) { _sha3.bytepad(ctx_, [][]byte{key}, _sha3.rate_cshake(sec_strength)) } -@(private) +@(private, rodata) N_KMAC := []byte{'K', 'M', 'A', 'C'} diff --git a/core/crypto/ristretto255/ristretto255.odin b/core/crypto/ristretto255/ristretto255.odin index 7b0944e33..c4d3f2615 100644 --- a/core/crypto/ristretto255/ristretto255.odin +++ b/core/crypto/ristretto255/ristretto255.odin @@ -16,7 +16,7 @@ ELEMENT_SIZE :: 32 // group element. WIDE_ELEMENT_SIZE :: 64 -@(private) +@(private, rodata) FE_NEG_ONE := field.Tight_Field_Element { 2251799813685228, 2251799813685247, @@ -24,7 +24,7 @@ FE_NEG_ONE := field.Tight_Field_Element { 2251799813685247, 2251799813685247, } -@(private) +@(private, rodata) FE_INVSQRT_A_MINUS_D := field.Tight_Field_Element { 278908739862762, 821645201101625, @@ -32,7 +32,7 @@ FE_INVSQRT_A_MINUS_D := field.Tight_Field_Element { 1777959178193151, 2118520810568447, } -@(private) +@(private, rodata) FE_ONE_MINUS_D_SQ := field.Tight_Field_Element { 1136626929484150, 1998550399581263, @@ -40,7 +40,7 @@ FE_ONE_MINUS_D_SQ := field.Tight_Field_Element { 118527312129759, 45110755273534, } -@(private) +@(private, rodata) FE_D_MINUS_ONE_SQUARED := field.Tight_Field_Element { 1507062230895904, 1572317787530805, @@ -48,7 +48,7 @@ FE_D_MINUS_ONE_SQUARED := field.Tight_Field_Element { 317374165784489, 1572899562415810, } -@(private) +@(private, rodata) FE_SQRT_AD_MINUS_ONE := field.Tight_Field_Element { 2241493124984347, 425987919032274, diff --git a/core/crypto/sha2/sha2.odin b/core/crypto/sha2/sha2.odin index 4230851ab..1c1ce11b6 100644 --- a/core/crypto/sha2/sha2.odin +++ b/core/crypto/sha2/sha2.odin @@ -270,7 +270,7 @@ reset :: proc(ctx: ^$T) { SHA2 implementation */ -@(private) +@(private, rodata) sha256_k := [64]u32 { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, @@ -290,7 +290,7 @@ sha256_k := [64]u32 { 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, } -@(private) +@(private, rodata) sha512_k := [80]u64 { 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, diff --git a/core/crypto/sm3/sm3.odin b/core/crypto/sm3/sm3.odin index f910d735b..06a5ef2db 100644 --- a/core/crypto/sm3/sm3.odin +++ b/core/crypto/sm3/sm3.odin @@ -136,7 +136,7 @@ reset :: proc(ctx: ^Context) { SM3 implementation */ -@(private) +@(private, rodata) IV := [8]u32 { 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e, diff --git a/core/crypto/x25519/x25519.odin b/core/crypto/x25519/x25519.odin index 412a767b8..fcb7015f3 100644 --- a/core/crypto/x25519/x25519.odin +++ b/core/crypto/x25519/x25519.odin @@ -15,7 +15,7 @@ SCALAR_SIZE :: 32 // POINT_SIZE is the size of a X25519 point (public key/shared secret) in bytes. POINT_SIZE :: 32 -@(private) +@(private, rodata) _BASE_POINT: [32]byte = {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} @(private) From 9fdcc4e39a4cfd160b36cbd144f77e4502f133f9 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Tue, 20 Aug 2024 12:03:04 +0900 Subject: [PATCH 17/81] core/crypto/x448: Initial import --- core/crypto/_fiat/field_curve448/field.odin | 235 ++++ core/crypto/_fiat/field_curve448/field51.odin | 1060 +++++++++++++++++ core/crypto/x448/x448.odin | 161 +++ examples/all/all_main.odin | 2 + tests/benchmark/crypto/benchmark_crypto.odin | 21 + ...519.odin => test_core_crypto_edwards.odin} | 63 + 6 files changed, 1542 insertions(+) create mode 100644 core/crypto/_fiat/field_curve448/field.odin create mode 100644 core/crypto/_fiat/field_curve448/field51.odin create mode 100644 core/crypto/x448/x448.odin rename tests/core/crypto/{test_core_crypto_ecc25519.odin => test_core_crypto_edwards.odin} (91%) diff --git a/core/crypto/_fiat/field_curve448/field.odin b/core/crypto/_fiat/field_curve448/field.odin new file mode 100644 index 000000000..540d88f28 --- /dev/null +++ b/core/crypto/_fiat/field_curve448/field.odin @@ -0,0 +1,235 @@ +package field_curve448 + +import "core:mem" + +fe_relax_cast :: #force_inline proc "contextless" ( + arg1: ^Tight_Field_Element, +) -> ^Loose_Field_Element { + return (^Loose_Field_Element)(arg1) +} + +fe_tighten_cast :: #force_inline proc "contextless" ( + arg1: ^Loose_Field_Element, +) -> ^Tight_Field_Element { + return (^Tight_Field_Element)(arg1) +} + +fe_clear :: proc "contextless" ( + arg1: $T, +) where T == ^Tight_Field_Element || T == ^Loose_Field_Element { + mem.zero_explicit(arg1, size_of(arg1^)) +} + +fe_clear_vec :: proc "contextless" ( + arg1: $T, +) where T == []^Tight_Field_Element || T == []^Loose_Field_Element { + for fe in arg1 { + fe_clear(fe) + } +} + +fe_carry_mul_small :: proc "contextless" ( + out1: ^Tight_Field_Element, + arg1: ^Loose_Field_Element, + arg2: u64, +) { + arg2_ := Loose_Field_Element{arg2, 0, 0, 0, 0, 0, 0, 0} + fe_carry_mul(out1, arg1, &arg2_) +} + +fe_carry_pow2k :: proc "contextless" ( + out1: ^Tight_Field_Element, + arg1: ^Loose_Field_Element, + arg2: uint, +) { + // Special case: `arg1^(2 * 0) = 1`, though this should never happen. + if arg2 == 0 { + fe_one(out1) + return + } + + fe_carry_square(out1, arg1) + for _ in 1 ..< arg2 { + fe_carry_square(out1, fe_relax_cast(out1)) + } +} + +fe_carry_inv :: proc "contextless" ( + out1: ^Tight_Field_Element, + arg1: ^Loose_Field_Element, +) { + // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // x12 = _111111 << 6 + _111111 + // x24 = x12 << 12 + x12 + // i34 = x24 << 6 + // x30 = _111111 + i34 + // x48 = i34 << 18 + x24 + // x96 = x48 << 48 + x48 + // x192 = x96 << 96 + x96 + // x222 = x192 << 30 + x30 + // x223 = 2*x222 + 1 + // return (x223 << 223 + x222) << 2 + 1 + // + // Operations: 447 squares 13 multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + t0, t1, t2: Tight_Field_Element = ---, ---, --- + + // Step 1: t0 = x^0x2 + fe_carry_square(&t0, arg1) + + // Step 2: t0 = x^0x3 + fe_carry_mul(&t0, arg1, fe_relax_cast(&t0)) + + // t0.Sqr(t0) + fe_carry_square(&t0, fe_relax_cast(&t0)) + + // Step 4: t0 = x^0x7 + fe_carry_mul(&t0, arg1, fe_relax_cast(&t0)) + + // Step 7: t1 = x^0x38 + fe_carry_pow2k(&t1, fe_relax_cast(&t0), 3) + + // Step 8: t0 = x^0x3f + fe_carry_mul(&t0, fe_relax_cast(&t0), fe_relax_cast(&t1)) + + // Step 14: t1 = x^0xfc0 + fe_carry_pow2k(&t1, fe_relax_cast(&t0), 6) + + // Step 15: t1 = x^0xfff + fe_carry_mul(&t1, fe_relax_cast(&t0), fe_relax_cast(&t1)) + + // Step 27: t2 = x^0xfff000 + fe_carry_pow2k(&t2, fe_relax_cast(&t1), 12) + + // Step 28: t1 = x^0xffffff + fe_carry_mul(&t1, fe_relax_cast(&t1), fe_relax_cast(&t2)) + + // Step 34: t2 = x^0x3fffffc0 + fe_carry_pow2k(&t2, fe_relax_cast(&t1), 6) + + // Step 35: t0 = x^0x3fffffff + fe_carry_mul(&t0, fe_relax_cast(&t0), fe_relax_cast(&t2)) + + // Step 53: t2 = x^0xffffff000000 + fe_carry_pow2k(&t2, fe_relax_cast(&t2), 18) + + // Step 54: t1 = x^0xffffffffffff + fe_carry_mul(&t1, fe_relax_cast(&t1), fe_relax_cast(&t2)) + + // Step 102: t2 = x^0xffffffffffff000000000000 + fe_carry_pow2k(&t2, fe_relax_cast(&t1), 48) + + // Step 103: t1 = x^0xffffffffffffffffffffffff + fe_carry_mul(&t1, fe_relax_cast(&t1), fe_relax_cast(&t2)) + + // Step 199: t2 = x^0xffffffffffffffffffffffff000000000000000000000000 + fe_carry_pow2k(&t2, fe_relax_cast(&t1), 96) + + // Step 200: t1 = x^0xffffffffffffffffffffffffffffffffffffffffffffffff + fe_carry_mul(&t1, fe_relax_cast(&t1), fe_relax_cast(&t2)) + + // Step 230: t1 = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffc0000000 + fe_carry_pow2k(&t1, fe_relax_cast(&t1), 30) + + // Step 231: t0 = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff + fe_carry_mul(&t0, fe_relax_cast(&t0), fe_relax_cast(&t1)) + + // Step 232: t1 = x^0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffe + fe_carry_square(&t1, fe_relax_cast(&t0)) + + // Step 233: t1 = x^0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffff + fe_carry_mul(&t1, arg1, fe_relax_cast(&t1)) + + // Step 456: t1 = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000 + fe_carry_pow2k(&t1, fe_relax_cast(&t1), 223) + + // Step 457: t0 = x^0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff + fe_carry_mul(&t0, fe_relax_cast(&t0), fe_relax_cast(&t1)) + + // Step 459: t0 = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffc + fe_carry_pow2k(&t0, fe_relax_cast(&t0), 2) + + // Step 460: z = x^0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffd + fe_carry_mul(out1, arg1, fe_relax_cast(&t0)) + + fe_clear_vec([]^Tight_Field_Element{&t0, &t1, &t2}) +} + +fe_zero :: proc "contextless" (out1: ^Tight_Field_Element) { + out1[0] = 0 + out1[1] = 0 + out1[2] = 0 + out1[3] = 0 + out1[4] = 0 + out1[5] = 0 + out1[6] = 0 + out1[7] = 0 +} + +fe_one :: proc "contextless" (out1: ^Tight_Field_Element) { + out1[0] = 1 + out1[1] = 0 + out1[2] = 0 + out1[3] = 0 + out1[4] = 0 + out1[5] = 0 + out1[6] = 0 + out1[7] = 0 +} + +fe_set :: proc "contextless" (out1, arg1: ^Tight_Field_Element) { + x1 := arg1[0] + x2 := arg1[1] + x3 := arg1[2] + x4 := arg1[3] + x5 := arg1[4] + x6 := arg1[5] + x7 := arg1[6] + x8 := arg1[7] + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 +} + +@(optimization_mode = "none") +fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: int) { + mask := (u64(arg1) * 0xffffffffffffffff) + x := (out1[0] ~ out2[0]) & mask + x1, y1 := out1[0] ~ x, out2[0] ~ x + x = (out1[1] ~ out2[1]) & mask + x2, y2 := out1[1] ~ x, out2[1] ~ x + x = (out1[2] ~ out2[2]) & mask + x3, y3 := out1[2] ~ x, out2[2] ~ x + x = (out1[3] ~ out2[3]) & mask + x4, y4 := out1[3] ~ x, out2[3] ~ x + x = (out1[4] ~ out2[4]) & mask + x5, y5 := out1[4] ~ x, out2[4] ~ x + x = (out1[5] ~ out2[5]) & mask + x6, y6 := out1[5] ~ x, out2[5] ~ x + x = (out1[6] ~ out2[6]) & mask + x7, y7 := out1[6] ~ x, out2[6] ~ x + x = (out1[7] ~ out2[7]) & mask + x8, y8 := out1[7] ~ x, out2[7] ~ x + out1[0], out2[0] = x1, y1 + out1[1], out2[1] = x2, y2 + out1[2], out2[2] = x3, y3 + out1[3], out2[3] = x4, y4 + out1[4], out2[4] = x5, y5 + out1[5], out2[5] = x6, y6 + out1[6], out2[6] = x7, y7 + out1[7], out2[7] = x8, y8 +} \ No newline at end of file diff --git a/core/crypto/_fiat/field_curve448/field51.odin b/core/crypto/_fiat/field_curve448/field51.odin new file mode 100644 index 000000000..d8e49e04d --- /dev/null +++ b/core/crypto/_fiat/field_curve448/field51.odin @@ -0,0 +1,1060 @@ +// The BSD 1-Clause License (BSD-1-Clause) +// +// Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, +// Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package field_curve448 + +// The file provides arithmetic on the field Z/(2^448 - 2^224 - 1) using +// unsaturated 64-bit integer arithmetic. It is derived primarily +// from the machine generated Golang output from the fiat-crypto project. +// +// While the base implementation is provably correct, this implementation +// makes no such claims as the port and optimizations were done by hand. +// +// TODO: +// * When fiat-crypto supports it, using a saturated 64-bit limbs +// instead of 56-bit limbs will be faster, though the gains are +// minimal unless adcx/adox/mulx are used. + +import fiat "core:crypto/_fiat" +import "core:math/bits" + +Loose_Field_Element :: distinct [8]u64 +Tight_Field_Element :: distinct [8]u64 + +@(rodata) +FE_ZERO := Tight_Field_Element{0, 0, 0, 0, 0, 0, 0, 0} +@(rodata) +FE_ONE := Tight_Field_Element{1, 0, 0, 0, 0, 0, 0, 0} + +_addcarryx_u56 :: #force_inline proc "contextless" ( + arg1: fiat.u1, + arg2, arg3: u64, +) -> ( + out1: u64, + out2: fiat.u1, +) { + x1 := ((u64(arg1) + arg2) + arg3) + x2 := (x1 & 0xffffffffffffff) + x3 := fiat.u1((x1 >> 56)) + out1 = x2 + out2 = x3 + return +} + +_subborrowx_u56 :: #force_inline proc "contextless" ( + arg1: fiat.u1, + arg2, arg3: u64, +) -> ( + out1: u64, + out2: fiat.u1, +) { + x1 := ((i64(arg2) - i64(arg1)) - i64(arg3)) + x2 := fiat.u1((x1 >> 56)) + x3 := (u64(x1) & 0xffffffffffffff) + out1 = x3 + out2 = (0x0 - fiat.u1(x2)) + return +} + +fe_carry_mul :: proc "contextless" (out1: ^Tight_Field_Element, arg1, arg2: ^Loose_Field_Element) { + x2, x1 := bits.mul_u64(arg1[7], arg2[7]) + x4, x3 := bits.mul_u64(arg1[7], arg2[6]) + x6, x5 := bits.mul_u64(arg1[7], arg2[5]) + x8, x7 := bits.mul_u64(arg1[6], arg2[7]) + x10, x9 := bits.mul_u64(arg1[6], arg2[6]) + x12, x11 := bits.mul_u64(arg1[5], arg2[7]) + x14, x13 := bits.mul_u64(arg1[7], arg2[7]) + x16, x15 := bits.mul_u64(arg1[7], arg2[6]) + x18, x17 := bits.mul_u64(arg1[7], arg2[5]) + x20, x19 := bits.mul_u64(arg1[6], arg2[7]) + x22, x21 := bits.mul_u64(arg1[6], arg2[6]) + x24, x23 := bits.mul_u64(arg1[5], arg2[7]) + x26, x25 := bits.mul_u64(arg1[7], arg2[7]) + x28, x27 := bits.mul_u64(arg1[7], arg2[6]) + x30, x29 := bits.mul_u64(arg1[7], arg2[5]) + x32, x31 := bits.mul_u64(arg1[7], arg2[4]) + x34, x33 := bits.mul_u64(arg1[7], arg2[3]) + x36, x35 := bits.mul_u64(arg1[7], arg2[2]) + x38, x37 := bits.mul_u64(arg1[7], arg2[1]) + x40, x39 := bits.mul_u64(arg1[6], arg2[7]) + x42, x41 := bits.mul_u64(arg1[6], arg2[6]) + x44, x43 := bits.mul_u64(arg1[6], arg2[5]) + x46, x45 := bits.mul_u64(arg1[6], arg2[4]) + x48, x47 := bits.mul_u64(arg1[6], arg2[3]) + x50, x49 := bits.mul_u64(arg1[6], arg2[2]) + x52, x51 := bits.mul_u64(arg1[5], arg2[7]) + x54, x53 := bits.mul_u64(arg1[5], arg2[6]) + x56, x55 := bits.mul_u64(arg1[5], arg2[5]) + x58, x57 := bits.mul_u64(arg1[5], arg2[4]) + x60, x59 := bits.mul_u64(arg1[5], arg2[3]) + x62, x61 := bits.mul_u64(arg1[4], arg2[7]) + x64, x63 := bits.mul_u64(arg1[4], arg2[6]) + x66, x65 := bits.mul_u64(arg1[4], arg2[5]) + x68, x67 := bits.mul_u64(arg1[4], arg2[4]) + x70, x69 := bits.mul_u64(arg1[3], arg2[7]) + x72, x71 := bits.mul_u64(arg1[3], arg2[6]) + x74, x73 := bits.mul_u64(arg1[3], arg2[5]) + x76, x75 := bits.mul_u64(arg1[2], arg2[7]) + x78, x77 := bits.mul_u64(arg1[2], arg2[6]) + x80, x79 := bits.mul_u64(arg1[1], arg2[7]) + x82, x81 := bits.mul_u64(arg1[7], arg2[4]) + x84, x83 := bits.mul_u64(arg1[7], arg2[3]) + x86, x85 := bits.mul_u64(arg1[7], arg2[2]) + x88, x87 := bits.mul_u64(arg1[7], arg2[1]) + x90, x89 := bits.mul_u64(arg1[6], arg2[5]) + x92, x91 := bits.mul_u64(arg1[6], arg2[4]) + x94, x93 := bits.mul_u64(arg1[6], arg2[3]) + x96, x95 := bits.mul_u64(arg1[6], arg2[2]) + x98, x97 := bits.mul_u64(arg1[5], arg2[6]) + x100, x99 := bits.mul_u64(arg1[5], arg2[5]) + x102, x101 := bits.mul_u64(arg1[5], arg2[4]) + x104, x103 := bits.mul_u64(arg1[5], arg2[3]) + x106, x105 := bits.mul_u64(arg1[4], arg2[7]) + x108, x107 := bits.mul_u64(arg1[4], arg2[6]) + x110, x109 := bits.mul_u64(arg1[4], arg2[5]) + x112, x111 := bits.mul_u64(arg1[4], arg2[4]) + x114, x113 := bits.mul_u64(arg1[3], arg2[7]) + x116, x115 := bits.mul_u64(arg1[3], arg2[6]) + x118, x117 := bits.mul_u64(arg1[3], arg2[5]) + x120, x119 := bits.mul_u64(arg1[2], arg2[7]) + x122, x121 := bits.mul_u64(arg1[2], arg2[6]) + x124, x123 := bits.mul_u64(arg1[1], arg2[7]) + x126, x125 := bits.mul_u64(arg1[7], arg2[0]) + x128, x127 := bits.mul_u64(arg1[6], arg2[1]) + x130, x129 := bits.mul_u64(arg1[6], arg2[0]) + x132, x131 := bits.mul_u64(arg1[5], arg2[2]) + x134, x133 := bits.mul_u64(arg1[5], arg2[1]) + x136, x135 := bits.mul_u64(arg1[5], arg2[0]) + x138, x137 := bits.mul_u64(arg1[4], arg2[3]) + x140, x139 := bits.mul_u64(arg1[4], arg2[2]) + x142, x141 := bits.mul_u64(arg1[4], arg2[1]) + x144, x143 := bits.mul_u64(arg1[4], arg2[0]) + x146, x145 := bits.mul_u64(arg1[3], arg2[4]) + x148, x147 := bits.mul_u64(arg1[3], arg2[3]) + x150, x149 := bits.mul_u64(arg1[3], arg2[2]) + x152, x151 := bits.mul_u64(arg1[3], arg2[1]) + x154, x153 := bits.mul_u64(arg1[3], arg2[0]) + x156, x155 := bits.mul_u64(arg1[2], arg2[5]) + x158, x157 := bits.mul_u64(arg1[2], arg2[4]) + x160, x159 := bits.mul_u64(arg1[2], arg2[3]) + x162, x161 := bits.mul_u64(arg1[2], arg2[2]) + x164, x163 := bits.mul_u64(arg1[2], arg2[1]) + x166, x165 := bits.mul_u64(arg1[2], arg2[0]) + x168, x167 := bits.mul_u64(arg1[1], arg2[6]) + x170, x169 := bits.mul_u64(arg1[1], arg2[5]) + x172, x171 := bits.mul_u64(arg1[1], arg2[4]) + x174, x173 := bits.mul_u64(arg1[1], arg2[3]) + x176, x175 := bits.mul_u64(arg1[1], arg2[2]) + x178, x177 := bits.mul_u64(arg1[1], arg2[1]) + x180, x179 := bits.mul_u64(arg1[1], arg2[0]) + x182, x181 := bits.mul_u64(arg1[0], arg2[7]) + x184, x183 := bits.mul_u64(arg1[0], arg2[6]) + x186, x185 := bits.mul_u64(arg1[0], arg2[5]) + x188, x187 := bits.mul_u64(arg1[0], arg2[4]) + x190, x189 := bits.mul_u64(arg1[0], arg2[3]) + x192, x191 := bits.mul_u64(arg1[0], arg2[2]) + x194, x193 := bits.mul_u64(arg1[0], arg2[1]) + x196, x195 := bits.mul_u64(arg1[0], arg2[0]) + x197, x198 := bits.add_u64(x43, x31, u64(0x0)) + x199, _ := bits.add_u64(x44, x32, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x53, x197, u64(0x0)) + x203, _ := bits.add_u64(x54, x199, u64(fiat.u1(x202))) + x205, x206 := bits.add_u64(x61, x201, u64(0x0)) + x207, _ := bits.add_u64(x62, x203, u64(fiat.u1(x206))) + x209, x210 := bits.add_u64(x153, x205, u64(0x0)) + x211, _ := bits.add_u64(x154, x207, u64(fiat.u1(x210))) + x213, x214 := bits.add_u64(x163, x209, u64(0x0)) + x215, _ := bits.add_u64(x164, x211, u64(fiat.u1(x214))) + x217, x218 := bits.add_u64(x175, x213, u64(0x0)) + x219, _ := bits.add_u64(x176, x215, u64(fiat.u1(x218))) + x221, x222 := bits.add_u64(x189, x217, u64(0x0)) + x223, _ := bits.add_u64(x190, x219, u64(fiat.u1(x222))) + x225 := ((x221 >> 56) | ((x223 << 8) & 0xffffffffffffffff)) + x226 := (x221 & 0xffffffffffffff) + x227, x228 := bits.add_u64(x89, x81, u64(0x0)) + x229, _ := bits.add_u64(x90, x82, u64(fiat.u1(x228))) + x231, x232 := bits.add_u64(x97, x227, u64(0x0)) + x233, _ := bits.add_u64(x98, x229, u64(fiat.u1(x232))) + x235, x236 := bits.add_u64(x105, x231, u64(0x0)) + x237, _ := bits.add_u64(x106, x233, u64(fiat.u1(x236))) + x239, x240 := bits.add_u64(x125, x235, u64(0x0)) + x241, _ := bits.add_u64(x126, x237, u64(fiat.u1(x240))) + x243, x244 := bits.add_u64(x127, x239, u64(0x0)) + x245, _ := bits.add_u64(x128, x241, u64(fiat.u1(x244))) + x247, x248 := bits.add_u64(x131, x243, u64(0x0)) + x249, _ := bits.add_u64(x132, x245, u64(fiat.u1(x248))) + x251, x252 := bits.add_u64(x137, x247, u64(0x0)) + x253, _ := bits.add_u64(x138, x249, u64(fiat.u1(x252))) + x255, x256 := bits.add_u64(x145, x251, u64(0x0)) + x257, _ := bits.add_u64(x146, x253, u64(fiat.u1(x256))) + x259, x260 := bits.add_u64(x155, x255, u64(0x0)) + x261, _ := bits.add_u64(x156, x257, u64(fiat.u1(x260))) + x263, x264 := bits.add_u64(x167, x259, u64(0x0)) + x265, _ := bits.add_u64(x168, x261, u64(fiat.u1(x264))) + x267, x268 := bits.add_u64(x181, x263, u64(0x0)) + x269, _ := bits.add_u64(x182, x265, u64(fiat.u1(x268))) + x271, x272 := bits.add_u64(x25, x13, u64(0x0)) + x273, _ := bits.add_u64(x26, x14, u64(fiat.u1(x272))) + x275, x276 := bits.add_u64(x83, x271, u64(0x0)) + x277, _ := bits.add_u64(x84, x273, u64(fiat.u1(x276))) + x279, x280 := bits.add_u64(x91, x275, u64(0x0)) + x281, _ := bits.add_u64(x92, x277, u64(fiat.u1(x280))) + x283, x284 := bits.add_u64(x99, x279, u64(0x0)) + x285, _ := bits.add_u64(x100, x281, u64(fiat.u1(x284))) + x287, x288 := bits.add_u64(x107, x283, u64(0x0)) + x289, _ := bits.add_u64(x108, x285, u64(fiat.u1(x288))) + x291, x292 := bits.add_u64(x113, x287, u64(0x0)) + x293, _ := bits.add_u64(x114, x289, u64(fiat.u1(x292))) + x295, x296 := bits.add_u64(x129, x291, u64(0x0)) + x297, _ := bits.add_u64(x130, x293, u64(fiat.u1(x296))) + x299, x300 := bits.add_u64(x133, x295, u64(0x0)) + x301, _ := bits.add_u64(x134, x297, u64(fiat.u1(x300))) + x303, x304 := bits.add_u64(x139, x299, u64(0x0)) + x305, _ := bits.add_u64(x140, x301, u64(fiat.u1(x304))) + x307, x308 := bits.add_u64(x147, x303, u64(0x0)) + x309, _ := bits.add_u64(x148, x305, u64(fiat.u1(x308))) + x311, x312 := bits.add_u64(x157, x307, u64(0x0)) + x313, _ := bits.add_u64(x158, x309, u64(fiat.u1(x312))) + x315, x316 := bits.add_u64(x169, x311, u64(0x0)) + x317, _ := bits.add_u64(x170, x313, u64(fiat.u1(x316))) + x319, x320 := bits.add_u64(x183, x315, u64(0x0)) + x321, _ := bits.add_u64(x184, x317, u64(fiat.u1(x320))) + x323, x324 := bits.add_u64(x19, x15, u64(0x0)) + x325, _ := bits.add_u64(x20, x16, u64(fiat.u1(x324))) + x327, x328 := bits.add_u64(x27, x323, u64(0x0)) + x329, _ := bits.add_u64(x28, x325, u64(fiat.u1(x328))) + x331, x332 := bits.add_u64(x39, x327, u64(0x0)) + x333, _ := bits.add_u64(x40, x329, u64(fiat.u1(x332))) + x335, x336 := bits.add_u64(x85, x331, u64(0x0)) + x337, _ := bits.add_u64(x86, x333, u64(fiat.u1(x336))) + x339, x340 := bits.add_u64(x93, x335, u64(0x0)) + x341, _ := bits.add_u64(x94, x337, u64(fiat.u1(x340))) + x343, x344 := bits.add_u64(x101, x339, u64(0x0)) + x345, _ := bits.add_u64(x102, x341, u64(fiat.u1(x344))) + x347, x348 := bits.add_u64(x109, x343, u64(0x0)) + x349, _ := bits.add_u64(x110, x345, u64(fiat.u1(x348))) + x351, x352 := bits.add_u64(x115, x347, u64(0x0)) + x353, _ := bits.add_u64(x116, x349, u64(fiat.u1(x352))) + x355, x356 := bits.add_u64(x119, x351, u64(0x0)) + x357, _ := bits.add_u64(x120, x353, u64(fiat.u1(x356))) + x359, x360 := bits.add_u64(x135, x355, u64(0x0)) + x361, _ := bits.add_u64(x136, x357, u64(fiat.u1(x360))) + x363, x364 := bits.add_u64(x141, x359, u64(0x0)) + x365, _ := bits.add_u64(x142, x361, u64(fiat.u1(x364))) + x367, x368 := bits.add_u64(x149, x363, u64(0x0)) + x369, _ := bits.add_u64(x150, x365, u64(fiat.u1(x368))) + x371, x372 := bits.add_u64(x159, x367, u64(0x0)) + x373, _ := bits.add_u64(x160, x369, u64(fiat.u1(x372))) + x375, x376 := bits.add_u64(x171, x371, u64(0x0)) + x377, _ := bits.add_u64(x172, x373, u64(fiat.u1(x376))) + x379, x380 := bits.add_u64(x185, x375, u64(0x0)) + x381, _ := bits.add_u64(x186, x377, u64(fiat.u1(x380))) + x383, x384 := bits.add_u64(x21, x17, u64(0x0)) + x385, _ := bits.add_u64(x22, x18, u64(fiat.u1(x384))) + x387, x388 := bits.add_u64(x23, x383, u64(0x0)) + x389, _ := bits.add_u64(x24, x385, u64(fiat.u1(x388))) + x391, x392 := bits.add_u64(x29, x387, u64(0x0)) + x393, _ := bits.add_u64(x30, x389, u64(fiat.u1(x392))) + x395, x396 := bits.add_u64(x41, x391, u64(0x0)) + x397, _ := bits.add_u64(x42, x393, u64(fiat.u1(x396))) + x399, x400 := bits.add_u64(x51, x395, u64(0x0)) + x401, _ := bits.add_u64(x52, x397, u64(fiat.u1(x400))) + x403, x404 := bits.add_u64(x87, x399, u64(0x0)) + x405, _ := bits.add_u64(x88, x401, u64(fiat.u1(x404))) + x407, x408 := bits.add_u64(x95, x403, u64(0x0)) + x409, _ := bits.add_u64(x96, x405, u64(fiat.u1(x408))) + x411, x412 := bits.add_u64(x103, x407, u64(0x0)) + x413, _ := bits.add_u64(x104, x409, u64(fiat.u1(x412))) + x415, x416 := bits.add_u64(x111, x411, u64(0x0)) + x417, _ := bits.add_u64(x112, x413, u64(fiat.u1(x416))) + x419, x420 := bits.add_u64(x117, x415, u64(0x0)) + x421, _ := bits.add_u64(x118, x417, u64(fiat.u1(x420))) + x423, x424 := bits.add_u64(x121, x419, u64(0x0)) + x425, _ := bits.add_u64(x122, x421, u64(fiat.u1(x424))) + x427, x428 := bits.add_u64(x123, x423, u64(0x0)) + x429, _ := bits.add_u64(x124, x425, u64(fiat.u1(x428))) + x431, x432 := bits.add_u64(x143, x427, u64(0x0)) + x433, _ := bits.add_u64(x144, x429, u64(fiat.u1(x432))) + x435, x436 := bits.add_u64(x151, x431, u64(0x0)) + x437, _ := bits.add_u64(x152, x433, u64(fiat.u1(x436))) + x439, x440 := bits.add_u64(x161, x435, u64(0x0)) + x441, _ := bits.add_u64(x162, x437, u64(fiat.u1(x440))) + x443, x444 := bits.add_u64(x173, x439, u64(0x0)) + x445, _ := bits.add_u64(x174, x441, u64(fiat.u1(x444))) + x447, x448 := bits.add_u64(x187, x443, u64(0x0)) + x449, _ := bits.add_u64(x188, x445, u64(fiat.u1(x448))) + x451, x452 := bits.add_u64(x33, x1, u64(0x0)) + x453, _ := bits.add_u64(x34, x2, u64(fiat.u1(x452))) + x455, x456 := bits.add_u64(x45, x451, u64(0x0)) + x457, _ := bits.add_u64(x46, x453, u64(fiat.u1(x456))) + x459, x460 := bits.add_u64(x55, x455, u64(0x0)) + x461, _ := bits.add_u64(x56, x457, u64(fiat.u1(x460))) + x463, x464 := bits.add_u64(x63, x459, u64(0x0)) + x465, _ := bits.add_u64(x64, x461, u64(fiat.u1(x464))) + x467, x468 := bits.add_u64(x69, x463, u64(0x0)) + x469, _ := bits.add_u64(x70, x465, u64(fiat.u1(x468))) + x471, x472 := bits.add_u64(x165, x467, u64(0x0)) + x473, _ := bits.add_u64(x166, x469, u64(fiat.u1(x472))) + x475, x476 := bits.add_u64(x177, x471, u64(0x0)) + x477, _ := bits.add_u64(x178, x473, u64(fiat.u1(x476))) + x479, x480 := bits.add_u64(x191, x475, u64(0x0)) + x481, _ := bits.add_u64(x192, x477, u64(fiat.u1(x480))) + x483, x484 := bits.add_u64(x7, x3, u64(0x0)) + x485, _ := bits.add_u64(x8, x4, u64(fiat.u1(x484))) + x487, x488 := bits.add_u64(x35, x483, u64(0x0)) + x489, _ := bits.add_u64(x36, x485, u64(fiat.u1(x488))) + x491, x492 := bits.add_u64(x47, x487, u64(0x0)) + x493, _ := bits.add_u64(x48, x489, u64(fiat.u1(x492))) + x495, x496 := bits.add_u64(x57, x491, u64(0x0)) + x497, _ := bits.add_u64(x58, x493, u64(fiat.u1(x496))) + x499, x500 := bits.add_u64(x65, x495, u64(0x0)) + x501, _ := bits.add_u64(x66, x497, u64(fiat.u1(x500))) + x503, x504 := bits.add_u64(x71, x499, u64(0x0)) + x505, _ := bits.add_u64(x72, x501, u64(fiat.u1(x504))) + x507, x508 := bits.add_u64(x75, x503, u64(0x0)) + x509, _ := bits.add_u64(x76, x505, u64(fiat.u1(x508))) + x511, x512 := bits.add_u64(x179, x507, u64(0x0)) + x513, _ := bits.add_u64(x180, x509, u64(fiat.u1(x512))) + x515, x516 := bits.add_u64(x193, x511, u64(0x0)) + x517, _ := bits.add_u64(x194, x513, u64(fiat.u1(x516))) + x519, x520 := bits.add_u64(x9, x5, u64(0x0)) + x521, _ := bits.add_u64(x10, x6, u64(fiat.u1(x520))) + x523, x524 := bits.add_u64(x11, x519, u64(0x0)) + x525, _ := bits.add_u64(x12, x521, u64(fiat.u1(x524))) + x527, x528 := bits.add_u64(x37, x523, u64(0x0)) + x529, _ := bits.add_u64(x38, x525, u64(fiat.u1(x528))) + x531, x532 := bits.add_u64(x49, x527, u64(0x0)) + x533, _ := bits.add_u64(x50, x529, u64(fiat.u1(x532))) + x535, x536 := bits.add_u64(x59, x531, u64(0x0)) + x537, _ := bits.add_u64(x60, x533, u64(fiat.u1(x536))) + x539, x540 := bits.add_u64(x67, x535, u64(0x0)) + x541, _ := bits.add_u64(x68, x537, u64(fiat.u1(x540))) + x543, x544 := bits.add_u64(x73, x539, u64(0x0)) + x545, _ := bits.add_u64(x74, x541, u64(fiat.u1(x544))) + x547, x548 := bits.add_u64(x77, x543, u64(0x0)) + x549, _ := bits.add_u64(x78, x545, u64(fiat.u1(x548))) + x551, x552 := bits.add_u64(x79, x547, u64(0x0)) + x553, _ := bits.add_u64(x80, x549, u64(fiat.u1(x552))) + x555, x556 := bits.add_u64(x195, x551, u64(0x0)) + x557, _ := bits.add_u64(x196, x553, u64(fiat.u1(x556))) + x559, x560 := bits.add_u64(x225, x447, u64(0x0)) + x561 := (u64(fiat.u1(x560)) + x449) + x562 := ((x267 >> 56) | ((x269 << 8) & 0xffffffffffffffff)) + x563 := (x267 & 0xffffffffffffff) + x564, x565 := bits.add_u64(x559, x562, u64(0x0)) + x566 := (u64(fiat.u1(x565)) + x561) + x567 := ((x564 >> 56) | ((x566 << 8) & 0xffffffffffffffff)) + x568 := (x564 & 0xffffffffffffff) + x569, x570 := bits.add_u64(x555, x562, u64(0x0)) + x571 := (u64(fiat.u1(x570)) + x557) + x572, x573 := bits.add_u64(x567, x379, u64(0x0)) + x574 := (u64(fiat.u1(x573)) + x381) + x575 := ((x569 >> 56) | ((x571 << 8) & 0xffffffffffffffff)) + x576 := (x569 & 0xffffffffffffff) + x577, x578 := bits.add_u64(x575, x515, u64(0x0)) + x579 := (u64(fiat.u1(x578)) + x517) + x580 := ((x572 >> 56) | ((x574 << 8) & 0xffffffffffffffff)) + x581 := (x572 & 0xffffffffffffff) + x582, x583 := bits.add_u64(x580, x319, u64(0x0)) + x584 := (u64(fiat.u1(x583)) + x321) + x585 := ((x577 >> 56) | ((x579 << 8) & 0xffffffffffffffff)) + x586 := (x577 & 0xffffffffffffff) + x587, x588 := bits.add_u64(x585, x479, u64(0x0)) + x589 := (u64(fiat.u1(x588)) + x481) + x590 := ((x582 >> 56) | ((x584 << 8) & 0xffffffffffffffff)) + x591 := (x582 & 0xffffffffffffff) + x592 := (x590 + x563) + x593 := ((x587 >> 56) | ((x589 << 8) & 0xffffffffffffffff)) + x594 := (x587 & 0xffffffffffffff) + x595 := (x593 + x226) + x596 := (x592 >> 56) + x597 := (x592 & 0xffffffffffffff) + x598 := (x595 >> 56) + x599 := (x595 & 0xffffffffffffff) + x600 := (x568 + x596) + x601 := (x576 + x596) + x602 := (x598 + x600) + x603 := fiat.u1((x602 >> 56)) + x604 := (x602 & 0xffffffffffffff) + x605 := (u64(x603) + x581) + x606 := fiat.u1((x601 >> 56)) + x607 := (x601 & 0xffffffffffffff) + x608 := (u64(x606) + x586) + out1[0] = x607 + out1[1] = x608 + out1[2] = x594 + out1[3] = x599 + out1[4] = x604 + out1[5] = x605 + out1[6] = x591 + out1[7] = x597 +} + +fe_carry_square :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) { + x1 := arg1[7] + x2 := arg1[7] + x3 := (x1 * 0x2) + x4 := (x2 * 0x2) + x5 := (arg1[7] * 0x2) + x6 := arg1[6] + x7 := arg1[6] + x8 := (x6 * 0x2) + x9 := (x7 * 0x2) + x10 := (arg1[6] * 0x2) + x11 := arg1[5] + x12 := arg1[5] + x13 := (x11 * 0x2) + x14 := (x12 * 0x2) + x15 := (arg1[5] * 0x2) + x16 := arg1[4] + x17 := arg1[4] + x18 := (arg1[4] * 0x2) + x19 := (arg1[3] * 0x2) + x20 := (arg1[2] * 0x2) + x21 := (arg1[1] * 0x2) + x23, x22 := bits.mul_u64(arg1[7], x1) + x25, x24 := bits.mul_u64(arg1[6], x3) + x27, x26 := bits.mul_u64(arg1[6], x6) + x29, x28 := bits.mul_u64(arg1[5], x3) + x31, x30 := bits.mul_u64(arg1[7], x1) + x33, x32 := bits.mul_u64(arg1[6], x3) + x35, x34 := bits.mul_u64(arg1[6], x6) + x37, x36 := bits.mul_u64(arg1[5], x3) + x39, x38 := bits.mul_u64(arg1[7], x2) + x41, x40 := bits.mul_u64(arg1[6], x4) + x43, x42 := bits.mul_u64(arg1[6], x7) + x45, x44 := bits.mul_u64(arg1[5], x4) + x47, x46 := bits.mul_u64(arg1[5], x9) + x49, x48 := bits.mul_u64(arg1[5], x8) + x51, x50 := bits.mul_u64(arg1[5], x12) + x53, x52 := bits.mul_u64(arg1[5], x11) + x55, x54 := bits.mul_u64(arg1[4], x4) + x57, x56 := bits.mul_u64(arg1[4], x3) + x59, x58 := bits.mul_u64(arg1[4], x9) + x61, x60 := bits.mul_u64(arg1[4], x8) + x63, x62 := bits.mul_u64(arg1[4], x14) + x65, x64 := bits.mul_u64(arg1[4], x13) + x67, x66 := bits.mul_u64(arg1[4], x17) + x69, x68 := bits.mul_u64(arg1[4], x16) + x71, x70 := bits.mul_u64(arg1[3], x4) + x73, x72 := bits.mul_u64(arg1[3], x3) + x75, x74 := bits.mul_u64(arg1[3], x9) + x77, x76 := bits.mul_u64(arg1[3], x8) + x79, x78 := bits.mul_u64(arg1[3], x14) + x81, x80 := bits.mul_u64(arg1[3], x13) + x83, x82 := bits.mul_u64(arg1[3], x18) + x85, x84 := bits.mul_u64(arg1[3], arg1[3]) + x87, x86 := bits.mul_u64(arg1[2], x4) + x89, x88 := bits.mul_u64(arg1[2], x3) + x91, x90 := bits.mul_u64(arg1[2], x9) + x93, x92 := bits.mul_u64(arg1[2], x8) + x95, x94 := bits.mul_u64(arg1[2], x15) + x97, x96 := bits.mul_u64(arg1[2], x18) + x99, x98 := bits.mul_u64(arg1[2], x19) + x101, x100 := bits.mul_u64(arg1[2], arg1[2]) + x103, x102 := bits.mul_u64(arg1[1], x4) + x105, x104 := bits.mul_u64(arg1[1], x3) + x107, x106 := bits.mul_u64(arg1[1], x10) + x109, x108 := bits.mul_u64(arg1[1], x15) + x111, x110 := bits.mul_u64(arg1[1], x18) + x113, x112 := bits.mul_u64(arg1[1], x19) + x115, x114 := bits.mul_u64(arg1[1], x20) + x117, x116 := bits.mul_u64(arg1[1], arg1[1]) + x119, x118 := bits.mul_u64(arg1[0], x5) + x121, x120 := bits.mul_u64(arg1[0], x10) + x123, x122 := bits.mul_u64(arg1[0], x15) + x125, x124 := bits.mul_u64(arg1[0], x18) + x127, x126 := bits.mul_u64(arg1[0], x19) + x129, x128 := bits.mul_u64(arg1[0], x20) + x131, x130 := bits.mul_u64(arg1[0], x21) + x133, x132 := bits.mul_u64(arg1[0], arg1[0]) + x134, x135 := bits.add_u64(x54, x46, u64(0x0)) + x136, _ := bits.add_u64(x55, x47, u64(fiat.u1(x135))) + x138, x139 := bits.add_u64(x114, x134, u64(0x0)) + x140, _ := bits.add_u64(x115, x136, u64(fiat.u1(x139))) + x142, x143 := bits.add_u64(x126, x138, u64(0x0)) + x144, _ := bits.add_u64(x127, x140, u64(fiat.u1(x143))) + x146 := ((x142 >> 56) | ((x144 << 8) & 0xffffffffffffffff)) + x147 := (x142 & 0xffffffffffffff) + x148, x149 := bits.add_u64(x56, x48, u64(0x0)) + x150, _ := bits.add_u64(x57, x49, u64(fiat.u1(x149))) + x152, x153 := bits.add_u64(x82, x148, u64(0x0)) + x154, _ := bits.add_u64(x83, x150, u64(fiat.u1(x153))) + x156, x157 := bits.add_u64(x94, x152, u64(0x0)) + x158, _ := bits.add_u64(x95, x154, u64(fiat.u1(x157))) + x160, x161 := bits.add_u64(x106, x156, u64(0x0)) + x162, _ := bits.add_u64(x107, x158, u64(fiat.u1(x161))) + x164, x165 := bits.add_u64(x118, x160, u64(0x0)) + x166, _ := bits.add_u64(x119, x162, u64(fiat.u1(x165))) + x168, x169 := bits.add_u64(x38, x30, u64(0x0)) + x170, _ := bits.add_u64(x39, x31, u64(fiat.u1(x169))) + x172, x173 := bits.add_u64(x52, x168, u64(0x0)) + x174, _ := bits.add_u64(x53, x170, u64(fiat.u1(x173))) + x176, x177 := bits.add_u64(x60, x172, u64(0x0)) + x178, _ := bits.add_u64(x61, x174, u64(fiat.u1(x177))) + x180, x181 := bits.add_u64(x72, x176, u64(0x0)) + x182, _ := bits.add_u64(x73, x178, u64(fiat.u1(x181))) + x184, x185 := bits.add_u64(x84, x180, u64(0x0)) + x186, _ := bits.add_u64(x85, x182, u64(fiat.u1(x185))) + x188, x189 := bits.add_u64(x96, x184, u64(0x0)) + x190, _ := bits.add_u64(x97, x186, u64(fiat.u1(x189))) + x192, x193 := bits.add_u64(x108, x188, u64(0x0)) + x194, _ := bits.add_u64(x109, x190, u64(fiat.u1(x193))) + x196, x197 := bits.add_u64(x120, x192, u64(0x0)) + x198, _ := bits.add_u64(x121, x194, u64(fiat.u1(x197))) + x200, x201 := bits.add_u64(x40, x32, u64(0x0)) + x202, _ := bits.add_u64(x41, x33, u64(fiat.u1(x201))) + x204, x205 := bits.add_u64(x64, x200, u64(0x0)) + x206, _ := bits.add_u64(x65, x202, u64(fiat.u1(x205))) + x208, x209 := bits.add_u64(x76, x204, u64(0x0)) + x210, _ := bits.add_u64(x77, x206, u64(fiat.u1(x209))) + x212, x213 := bits.add_u64(x88, x208, u64(0x0)) + x214, _ := bits.add_u64(x89, x210, u64(fiat.u1(x213))) + x216, x217 := bits.add_u64(x98, x212, u64(0x0)) + x218, _ := bits.add_u64(x99, x214, u64(fiat.u1(x217))) + x220, x221 := bits.add_u64(x110, x216, u64(0x0)) + x222, _ := bits.add_u64(x111, x218, u64(fiat.u1(x221))) + x224, x225 := bits.add_u64(x122, x220, u64(0x0)) + x226, _ := bits.add_u64(x123, x222, u64(fiat.u1(x225))) + x228, x229 := bits.add_u64(x36, x34, u64(0x0)) + x230, _ := bits.add_u64(x37, x35, u64(fiat.u1(x229))) + x232, x233 := bits.add_u64(x42, x228, u64(0x0)) + x234, _ := bits.add_u64(x43, x230, u64(fiat.u1(x233))) + x236, x237 := bits.add_u64(x44, x232, u64(0x0)) + x238, _ := bits.add_u64(x45, x234, u64(fiat.u1(x237))) + x240, x241 := bits.add_u64(x68, x236, u64(0x0)) + x242, _ := bits.add_u64(x69, x238, u64(fiat.u1(x241))) + x244, x245 := bits.add_u64(x80, x240, u64(0x0)) + x246, _ := bits.add_u64(x81, x242, u64(fiat.u1(x245))) + x248, x249 := bits.add_u64(x92, x244, u64(0x0)) + x250, _ := bits.add_u64(x93, x246, u64(fiat.u1(x249))) + x252, x253 := bits.add_u64(x100, x248, u64(0x0)) + x254, _ := bits.add_u64(x101, x250, u64(fiat.u1(x253))) + x256, x257 := bits.add_u64(x104, x252, u64(0x0)) + x258, _ := bits.add_u64(x105, x254, u64(fiat.u1(x257))) + x260, x261 := bits.add_u64(x112, x256, u64(0x0)) + x262, _ := bits.add_u64(x113, x258, u64(fiat.u1(x261))) + x264, x265 := bits.add_u64(x124, x260, u64(0x0)) + x266, _ := bits.add_u64(x125, x262, u64(fiat.u1(x265))) + x268, x269 := bits.add_u64(x50, x22, u64(0x0)) + x270, _ := bits.add_u64(x51, x23, u64(fiat.u1(x269))) + x272, x273 := bits.add_u64(x58, x268, u64(0x0)) + x274, _ := bits.add_u64(x59, x270, u64(fiat.u1(x273))) + x276, x277 := bits.add_u64(x70, x272, u64(0x0)) + x278, _ := bits.add_u64(x71, x274, u64(fiat.u1(x277))) + x280, x281 := bits.add_u64(x116, x276, u64(0x0)) + x282, _ := bits.add_u64(x117, x278, u64(fiat.u1(x281))) + x284, x285 := bits.add_u64(x128, x280, u64(0x0)) + x286, _ := bits.add_u64(x129, x282, u64(fiat.u1(x285))) + x288, x289 := bits.add_u64(x62, x24, u64(0x0)) + x290, _ := bits.add_u64(x63, x25, u64(fiat.u1(x289))) + x292, x293 := bits.add_u64(x74, x288, u64(0x0)) + x294, _ := bits.add_u64(x75, x290, u64(fiat.u1(x293))) + x296, x297 := bits.add_u64(x86, x292, u64(0x0)) + x298, _ := bits.add_u64(x87, x294, u64(fiat.u1(x297))) + x300, x301 := bits.add_u64(x130, x296, u64(0x0)) + x302, _ := bits.add_u64(x131, x298, u64(fiat.u1(x301))) + x304, x305 := bits.add_u64(x28, x26, u64(0x0)) + x306, _ := bits.add_u64(x29, x27, u64(fiat.u1(x305))) + x308, x309 := bits.add_u64(x66, x304, u64(0x0)) + x310, _ := bits.add_u64(x67, x306, u64(fiat.u1(x309))) + x312, x313 := bits.add_u64(x78, x308, u64(0x0)) + x314, _ := bits.add_u64(x79, x310, u64(fiat.u1(x313))) + x316, x317 := bits.add_u64(x90, x312, u64(0x0)) + x318, _ := bits.add_u64(x91, x314, u64(fiat.u1(x317))) + x320, x321 := bits.add_u64(x102, x316, u64(0x0)) + x322, _ := bits.add_u64(x103, x318, u64(fiat.u1(x321))) + x324, x325 := bits.add_u64(x132, x320, u64(0x0)) + x326, _ := bits.add_u64(x133, x322, u64(fiat.u1(x325))) + x328, x329 := bits.add_u64(x146, x264, u64(0x0)) + x330 := (u64(fiat.u1(x329)) + x266) + x331 := ((x164 >> 56) | ((x166 << 8) & 0xffffffffffffffff)) + x332 := (x164 & 0xffffffffffffff) + x333, x334 := bits.add_u64(x328, x331, u64(0x0)) + x335 := (u64(fiat.u1(x334)) + x330) + x336 := ((x333 >> 56) | ((x335 << 8) & 0xffffffffffffffff)) + x337 := (x333 & 0xffffffffffffff) + x338, x339 := bits.add_u64(x324, x331, u64(0x0)) + x340 := (u64(fiat.u1(x339)) + x326) + x341, x342 := bits.add_u64(x336, x224, u64(0x0)) + x343 := (u64(fiat.u1(x342)) + x226) + x344 := ((x338 >> 56) | ((x340 << 8) & 0xffffffffffffffff)) + x345 := (x338 & 0xffffffffffffff) + x346, x347 := bits.add_u64(x344, x300, u64(0x0)) + x348 := (u64(fiat.u1(x347)) + x302) + x349 := ((x341 >> 56) | ((x343 << 8) & 0xffffffffffffffff)) + x350 := (x341 & 0xffffffffffffff) + x351, x352 := bits.add_u64(x349, x196, u64(0x0)) + x353 := (u64(fiat.u1(x352)) + x198) + x354 := ((x346 >> 56) | ((x348 << 8) & 0xffffffffffffffff)) + x355 := (x346 & 0xffffffffffffff) + x356, x357 := bits.add_u64(x354, x284, u64(0x0)) + x358 := (u64(fiat.u1(x357)) + x286) + x359 := ((x351 >> 56) | ((x353 << 8) & 0xffffffffffffffff)) + x360 := (x351 & 0xffffffffffffff) + x361 := (x359 + x332) + x362 := ((x356 >> 56) | ((x358 << 8) & 0xffffffffffffffff)) + x363 := (x356 & 0xffffffffffffff) + x364 := (x362 + x147) + x365 := (x361 >> 56) + x366 := (x361 & 0xffffffffffffff) + x367 := (x364 >> 56) + x368 := (x364 & 0xffffffffffffff) + x369 := (x337 + x365) + x370 := (x345 + x365) + x371 := (x367 + x369) + x372 := fiat.u1((x371 >> 56)) + x373 := (x371 & 0xffffffffffffff) + x374 := (u64(x372) + x350) + x375 := fiat.u1((x370 >> 56)) + x376 := (x370 & 0xffffffffffffff) + x377 := (u64(x375) + x355) + out1[0] = x376 + out1[1] = x377 + out1[2] = x363 + out1[3] = x368 + out1[4] = x373 + out1[5] = x374 + out1[6] = x360 + out1[7] = x366 +} + +fe_carry :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^Loose_Field_Element) { + x1 := arg1[3] + x2 := arg1[7] + x3 := (x2 >> 56) + x4 := (((x1 >> 56) + arg1[4]) + x3) + x5 := (arg1[0] + x3) + x6 := ((x4 >> 56) + arg1[5]) + x7 := ((x5 >> 56) + arg1[1]) + x8 := ((x6 >> 56) + arg1[6]) + x9 := ((x7 >> 56) + arg1[2]) + x10 := ((x8 >> 56) + (x2 & 0xffffffffffffff)) + x11 := ((x9 >> 56) + (x1 & 0xffffffffffffff)) + x12 := fiat.u1((x10 >> 56)) + x13 := ((x5 & 0xffffffffffffff) + u64(x12)) + x14 := (u64(fiat.u1((x11 >> 56))) + ((x4 & 0xffffffffffffff) + u64(x12))) + x15 := (x13 & 0xffffffffffffff) + x16 := (u64(fiat.u1((x13 >> 56))) + (x7 & 0xffffffffffffff)) + x17 := (x9 & 0xffffffffffffff) + x18 := (x11 & 0xffffffffffffff) + x19 := (x14 & 0xffffffffffffff) + x20 := (u64(fiat.u1((x14 >> 56))) + (x6 & 0xffffffffffffff)) + x21 := (x8 & 0xffffffffffffff) + x22 := (x10 & 0xffffffffffffff) + out1[0] = x15 + out1[1] = x16 + out1[2] = x17 + out1[3] = x18 + out1[4] = x19 + out1[5] = x20 + out1[6] = x21 + out1[7] = x22 +} + +fe_add :: proc "contextless" (out1: ^Loose_Field_Element, arg1, arg2: ^Tight_Field_Element) { + x1 := (arg1[0] + arg2[0]) + x2 := (arg1[1] + arg2[1]) + x3 := (arg1[2] + arg2[2]) + x4 := (arg1[3] + arg2[3]) + x5 := (arg1[4] + arg2[4]) + x6 := (arg1[5] + arg2[5]) + x7 := (arg1[6] + arg2[6]) + x8 := (arg1[7] + arg2[7]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 +} + +fe_sub :: proc "contextless" (out1: ^Loose_Field_Element, arg1, arg2: ^Tight_Field_Element) { + x1 := ((0x1fffffffffffffe + arg1[0]) - arg2[0]) + x2 := ((0x1fffffffffffffe + arg1[1]) - arg2[1]) + x3 := ((0x1fffffffffffffe + arg1[2]) - arg2[2]) + x4 := ((0x1fffffffffffffe + arg1[3]) - arg2[3]) + x5 := ((0x1fffffffffffffc + arg1[4]) - arg2[4]) + x6 := ((0x1fffffffffffffe + arg1[5]) - arg2[5]) + x7 := ((0x1fffffffffffffe + arg1[6]) - arg2[6]) + x8 := ((0x1fffffffffffffe + arg1[7]) - arg2[7]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 +} + +fe_opp :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_Element) { + x1 := (0x1fffffffffffffe - arg1[0]) + x2 := (0x1fffffffffffffe - arg1[1]) + x3 := (0x1fffffffffffffe - arg1[2]) + x4 := (0x1fffffffffffffe - arg1[3]) + x5 := (0x1fffffffffffffc - arg1[4]) + x6 := (0x1fffffffffffffe - arg1[5]) + x7 := (0x1fffffffffffffe - arg1[6]) + x8 := (0x1fffffffffffffe - arg1[7]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 +} + +@(optimization_mode = "none") +fe_cond_assign :: #force_no_inline proc "contextless" ( + out1, arg1: ^Tight_Field_Element, + arg2: int, +) { + x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0]) + x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1]) + x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2]) + x4 := fiat.cmovznz_u64(fiat.u1(arg2), out1[3], arg1[3]) + x5 := fiat.cmovznz_u64(fiat.u1(arg2), out1[4], arg1[4]) + x6 := fiat.cmovznz_u64(fiat.u1(arg2), out1[5], arg1[5]) + x7 := fiat.cmovznz_u64(fiat.u1(arg2), out1[6], arg1[6]) + x8 := fiat.cmovznz_u64(fiat.u1(arg2), out1[7], arg1[7]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 +} + +fe_to_bytes :: proc "contextless" (out1: ^[56]byte, arg1: ^Tight_Field_Element) { + x1, x2 := _subborrowx_u56(0x0, arg1[0], 0xffffffffffffff) + x3, x4 := _subborrowx_u56(x2, arg1[1], 0xffffffffffffff) + x5, x6 := _subborrowx_u56(x4, arg1[2], 0xffffffffffffff) + x7, x8 := _subborrowx_u56(x6, arg1[3], 0xffffffffffffff) + x9, x10 := _subborrowx_u56(x8, arg1[4], 0xfffffffffffffe) + x11, x12 := _subborrowx_u56(x10, arg1[5], 0xffffffffffffff) + x13, x14 := _subborrowx_u56(x12, arg1[6], 0xffffffffffffff) + x15, x16 := _subborrowx_u56(x14, arg1[7], 0xffffffffffffff) + x17 := fiat.cmovznz_u64(x16, u64(0x0), 0xffffffffffffffff) + x18, x19 := _addcarryx_u56(0x0, x1, (x17 & 0xffffffffffffff)) + x20, x21 := _addcarryx_u56(x19, x3, (x17 & 0xffffffffffffff)) + x22, x23 := _addcarryx_u56(x21, x5, (x17 & 0xffffffffffffff)) + x24, x25 := _addcarryx_u56(x23, x7, (x17 & 0xffffffffffffff)) + x26, x27 := _addcarryx_u56(x25, x9, (x17 & 0xfffffffffffffe)) + x28, x29 := _addcarryx_u56(x27, x11, (x17 & 0xffffffffffffff)) + x30, x31 := _addcarryx_u56(x29, x13, (x17 & 0xffffffffffffff)) + x32, _ := _addcarryx_u56(x31, x15, (x17 & 0xffffffffffffff)) + x34 := (u8(x18) & 0xff) + x35 := (x18 >> 8) + x36 := (u8(x35) & 0xff) + x37 := (x35 >> 8) + x38 := (u8(x37) & 0xff) + x39 := (x37 >> 8) + x40 := (u8(x39) & 0xff) + x41 := (x39 >> 8) + x42 := (u8(x41) & 0xff) + x43 := (x41 >> 8) + x44 := (u8(x43) & 0xff) + x45 := u8((x43 >> 8)) + x46 := (u8(x20) & 0xff) + x47 := (x20 >> 8) + x48 := (u8(x47) & 0xff) + x49 := (x47 >> 8) + x50 := (u8(x49) & 0xff) + x51 := (x49 >> 8) + x52 := (u8(x51) & 0xff) + x53 := (x51 >> 8) + x54 := (u8(x53) & 0xff) + x55 := (x53 >> 8) + x56 := (u8(x55) & 0xff) + x57 := u8((x55 >> 8)) + x58 := (u8(x22) & 0xff) + x59 := (x22 >> 8) + x60 := (u8(x59) & 0xff) + x61 := (x59 >> 8) + x62 := (u8(x61) & 0xff) + x63 := (x61 >> 8) + x64 := (u8(x63) & 0xff) + x65 := (x63 >> 8) + x66 := (u8(x65) & 0xff) + x67 := (x65 >> 8) + x68 := (u8(x67) & 0xff) + x69 := u8((x67 >> 8)) + x70 := (u8(x24) & 0xff) + x71 := (x24 >> 8) + x72 := (u8(x71) & 0xff) + x73 := (x71 >> 8) + x74 := (u8(x73) & 0xff) + x75 := (x73 >> 8) + x76 := (u8(x75) & 0xff) + x77 := (x75 >> 8) + x78 := (u8(x77) & 0xff) + x79 := (x77 >> 8) + x80 := (u8(x79) & 0xff) + x81 := u8((x79 >> 8)) + x82 := (u8(x26) & 0xff) + x83 := (x26 >> 8) + x84 := (u8(x83) & 0xff) + x85 := (x83 >> 8) + x86 := (u8(x85) & 0xff) + x87 := (x85 >> 8) + x88 := (u8(x87) & 0xff) + x89 := (x87 >> 8) + x90 := (u8(x89) & 0xff) + x91 := (x89 >> 8) + x92 := (u8(x91) & 0xff) + x93 := u8((x91 >> 8)) + x94 := (u8(x28) & 0xff) + x95 := (x28 >> 8) + x96 := (u8(x95) & 0xff) + x97 := (x95 >> 8) + x98 := (u8(x97) & 0xff) + x99 := (x97 >> 8) + x100 := (u8(x99) & 0xff) + x101 := (x99 >> 8) + x102 := (u8(x101) & 0xff) + x103 := (x101 >> 8) + x104 := (u8(x103) & 0xff) + x105 := u8((x103 >> 8)) + x106 := (u8(x30) & 0xff) + x107 := (x30 >> 8) + x108 := (u8(x107) & 0xff) + x109 := (x107 >> 8) + x110 := (u8(x109) & 0xff) + x111 := (x109 >> 8) + x112 := (u8(x111) & 0xff) + x113 := (x111 >> 8) + x114 := (u8(x113) & 0xff) + x115 := (x113 >> 8) + x116 := (u8(x115) & 0xff) + x117 := u8((x115 >> 8)) + x118 := (u8(x32) & 0xff) + x119 := (x32 >> 8) + x120 := (u8(x119) & 0xff) + x121 := (x119 >> 8) + x122 := (u8(x121) & 0xff) + x123 := (x121 >> 8) + x124 := (u8(x123) & 0xff) + x125 := (x123 >> 8) + x126 := (u8(x125) & 0xff) + x127 := (x125 >> 8) + x128 := (u8(x127) & 0xff) + x129 := u8((x127 >> 8)) + out1[0] = x34 + out1[1] = x36 + out1[2] = x38 + out1[3] = x40 + out1[4] = x42 + out1[5] = x44 + out1[6] = x45 + out1[7] = x46 + out1[8] = x48 + out1[9] = x50 + out1[10] = x52 + out1[11] = x54 + out1[12] = x56 + out1[13] = x57 + out1[14] = x58 + out1[15] = x60 + out1[16] = x62 + out1[17] = x64 + out1[18] = x66 + out1[19] = x68 + out1[20] = x69 + out1[21] = x70 + out1[22] = x72 + out1[23] = x74 + out1[24] = x76 + out1[25] = x78 + out1[26] = x80 + out1[27] = x81 + out1[28] = x82 + out1[29] = x84 + out1[30] = x86 + out1[31] = x88 + out1[32] = x90 + out1[33] = x92 + out1[34] = x93 + out1[35] = x94 + out1[36] = x96 + out1[37] = x98 + out1[38] = x100 + out1[39] = x102 + out1[40] = x104 + out1[41] = x105 + out1[42] = x106 + out1[43] = x108 + out1[44] = x110 + out1[45] = x112 + out1[46] = x114 + out1[47] = x116 + out1[48] = x117 + out1[49] = x118 + out1[50] = x120 + out1[51] = x122 + out1[52] = x124 + out1[53] = x126 + out1[54] = x128 + out1[55] = x129 +} + +fe_from_bytes :: proc "contextless" (out1: ^Tight_Field_Element, arg1: ^[56]byte) { + x1 := (u64(arg1[55]) << 48) + x2 := (u64(arg1[54]) << 40) + x3 := (u64(arg1[53]) << 32) + x4 := (u64(arg1[52]) << 24) + x5 := (u64(arg1[51]) << 16) + x6 := (u64(arg1[50]) << 8) + x7 := arg1[49] + x8 := (u64(arg1[48]) << 48) + x9 := (u64(arg1[47]) << 40) + x10 := (u64(arg1[46]) << 32) + x11 := (u64(arg1[45]) << 24) + x12 := (u64(arg1[44]) << 16) + x13 := (u64(arg1[43]) << 8) + x14 := arg1[42] + x15 := (u64(arg1[41]) << 48) + x16 := (u64(arg1[40]) << 40) + x17 := (u64(arg1[39]) << 32) + x18 := (u64(arg1[38]) << 24) + x19 := (u64(arg1[37]) << 16) + x20 := (u64(arg1[36]) << 8) + x21 := arg1[35] + x22 := (u64(arg1[34]) << 48) + x23 := (u64(arg1[33]) << 40) + x24 := (u64(arg1[32]) << 32) + x25 := (u64(arg1[31]) << 24) + x26 := (u64(arg1[30]) << 16) + x27 := (u64(arg1[29]) << 8) + x28 := arg1[28] + x29 := (u64(arg1[27]) << 48) + x30 := (u64(arg1[26]) << 40) + x31 := (u64(arg1[25]) << 32) + x32 := (u64(arg1[24]) << 24) + x33 := (u64(arg1[23]) << 16) + x34 := (u64(arg1[22]) << 8) + x35 := arg1[21] + x36 := (u64(arg1[20]) << 48) + x37 := (u64(arg1[19]) << 40) + x38 := (u64(arg1[18]) << 32) + x39 := (u64(arg1[17]) << 24) + x40 := (u64(arg1[16]) << 16) + x41 := (u64(arg1[15]) << 8) + x42 := arg1[14] + x43 := (u64(arg1[13]) << 48) + x44 := (u64(arg1[12]) << 40) + x45 := (u64(arg1[11]) << 32) + x46 := (u64(arg1[10]) << 24) + x47 := (u64(arg1[9]) << 16) + x48 := (u64(arg1[8]) << 8) + x49 := arg1[7] + x50 := (u64(arg1[6]) << 48) + x51 := (u64(arg1[5]) << 40) + x52 := (u64(arg1[4]) << 32) + x53 := (u64(arg1[3]) << 24) + x54 := (u64(arg1[2]) << 16) + x55 := (u64(arg1[1]) << 8) + x56 := arg1[0] + x57 := (x55 + u64(x56)) + x58 := (x54 + x57) + x59 := (x53 + x58) + x60 := (x52 + x59) + x61 := (x51 + x60) + x62 := (x50 + x61) + x63 := (x48 + u64(x49)) + x64 := (x47 + x63) + x65 := (x46 + x64) + x66 := (x45 + x65) + x67 := (x44 + x66) + x68 := (x43 + x67) + x69 := (x41 + u64(x42)) + x70 := (x40 + x69) + x71 := (x39 + x70) + x72 := (x38 + x71) + x73 := (x37 + x72) + x74 := (x36 + x73) + x75 := (x34 + u64(x35)) + x76 := (x33 + x75) + x77 := (x32 + x76) + x78 := (x31 + x77) + x79 := (x30 + x78) + x80 := (x29 + x79) + x81 := (x27 + u64(x28)) + x82 := (x26 + x81) + x83 := (x25 + x82) + x84 := (x24 + x83) + x85 := (x23 + x84) + x86 := (x22 + x85) + x87 := (x20 + u64(x21)) + x88 := (x19 + x87) + x89 := (x18 + x88) + x90 := (x17 + x89) + x91 := (x16 + x90) + x92 := (x15 + x91) + x93 := (x13 + u64(x14)) + x94 := (x12 + x93) + x95 := (x11 + x94) + x96 := (x10 + x95) + x97 := (x9 + x96) + x98 := (x8 + x97) + x99 := (x6 + u64(x7)) + x100 := (x5 + x99) + x101 := (x4 + x100) + x102 := (x3 + x101) + x103 := (x2 + x102) + x104 := (x1 + x103) + out1[0] = x62 + out1[1] = x68 + out1[2] = x74 + out1[3] = x80 + out1[4] = x86 + out1[5] = x92 + out1[6] = x98 + out1[7] = x104 +} + +fe_relax :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_Element) { + x1 := arg1[0] + x2 := arg1[1] + x3 := arg1[2] + x4 := arg1[3] + x5 := arg1[4] + x6 := arg1[5] + x7 := arg1[6] + x8 := arg1[7] + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 +} diff --git a/core/crypto/x448/x448.odin b/core/crypto/x448/x448.odin new file mode 100644 index 000000000..d3aad6ac5 --- /dev/null +++ b/core/crypto/x448/x448.odin @@ -0,0 +1,161 @@ +/* +package x448 implements the X448 (aka curve448) Elliptic-Curve +Diffie-Hellman key exchange protocol. + +See: +- [[ https://www.rfc-editor.org/rfc/rfc7748 ]] +*/ +package x448 + +import field "core:crypto/_fiat/field_curve448" +import "core:mem" + +// SCALAR_SIZE is the size of a X448 scalar (private key) in bytes. +SCALAR_SIZE :: 56 +// POINT_SIZE is the size of a X448 point (public key/shared secret) in bytes. +POINT_SIZE :: 56 + +@(private, rodata) +_BASE_POINT: [56]byte = { + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +} + +@(private) +_scalar_bit :: #force_inline proc "contextless" (s: ^[56]byte, i: int) -> u8 { + if i < 0 { + return 0 + } + return (s[i >> 3] >> uint(i & 7)) & 1 +} + +@(private) +_scalarmult :: proc "contextless" (out, scalar, point: ^[56]byte) { + // Montgomery pseudo-multiplication, using the RFC 7748 formula. + t1, t2: field.Loose_Field_Element = ---, --- + + // x_1 = u + // x_2 = 1 + // z_2 = 0 + // x_3 = u + // z_3 = 1 + x1: field.Tight_Field_Element = --- + field.fe_from_bytes(&x1, point) + + x2, x3, z2, z3: field.Tight_Field_Element = ---, ---, ---, --- + field.fe_one(&x2) + field.fe_zero(&z2) + field.fe_set(&x3, &x1) + field.fe_one(&z3) + + // swap = 0 + swap: int + + // For t = bits-1 down to 0:a + for t := 448 - 1; t >= 0; t -= 1 { + // k_t = (k >> t) & 1 + k_t := int(_scalar_bit(scalar, t)) + // swap ^= k_t + swap ~= k_t + // Conditional swap; see text below. + // (x_2, x_3) = cswap(swap, x_2, x_3) + field.fe_cond_swap(&x2, &x3, swap) + // (z_2, z_3) = cswap(swap, z_2, z_3) + field.fe_cond_swap(&z2, &z3, swap) + // swap = k_t + swap = k_t + + // Note: This deliberately omits reductions after add/sub operations + // if the result is only ever used as the input to a mul/square since + // the implementations of those can deal with non-reduced inputs. + // + // fe_tighten_cast is only used to store a fully reduced + // output in a Loose_Field_Element, or to provide such a + // Loose_Field_Element as a Tight_Field_Element argument. + + // A = x_2 + z_2 + field.fe_add(&t1, &x2, &z2) + // B = x_2 - z_2 + field.fe_sub(&t2, &x2, &z2) + // D = x_3 - z_3 + field.fe_sub(field.fe_relax_cast(&z2), &x3, &z3) // (z2 unreduced) + // DA = D * A + field.fe_carry_mul(&x2, field.fe_relax_cast(&z2), &t1) + // C = x_3 + z_3 + field.fe_add(field.fe_relax_cast(&z3), &x3, &z3) // (z3 unreduced) + // CB = C * B + field.fe_carry_mul(&x3, &t2, field.fe_relax_cast(&z3)) + // z_3 = x_1 * (DA - CB)^2 + field.fe_sub(field.fe_relax_cast(&z3), &x2, &x3) // (z3 unreduced) + field.fe_carry_square(&z3, field.fe_relax_cast(&z3)) + field.fe_carry_mul(&z3, field.fe_relax_cast(&x1), field.fe_relax_cast(&z3)) + // x_3 = (DA + CB)^2 + field.fe_add(field.fe_relax_cast(&z2), &x2, &x3) // (z2 unreduced) + field.fe_carry_square(&x3, field.fe_relax_cast(&z2)) + + // AA = A^2 + field.fe_carry_square(&z2, &t1) + // BB = B^2 + field.fe_carry_square(field.fe_tighten_cast(&t1), &t2) // (t1 reduced) + // x_2 = AA * BB + field.fe_carry_mul(&x2, field.fe_relax_cast(&z2), &t1) + // E = AA - BB + field.fe_sub(&t2, &z2, field.fe_tighten_cast(&t1)) // (t1 (input) is reduced) + // z_2 = E * (AA + a24 * E) + field.fe_carry_mul_small(field.fe_tighten_cast(&t1), &t2, 39081) // (t1 reduced) + field.fe_add(&t1, &z2, field.fe_tighten_cast(&t1)) // (t1 (input) is reduced) + field.fe_carry_mul(&z2, &t2, &t1) + } + + // Conditional swap; see text below. + // (x_2, x_3) = cswap(swap, x_2, x_3) + field.fe_cond_swap(&x2, &x3, swap) + // (z_2, z_3) = cswap(swap, z_2, z_3) + field.fe_cond_swap(&z2, &z3, swap) + + // Return x_2 * (z_2^(p - 2)) + field.fe_carry_inv(&z2, field.fe_relax_cast(&z2)) + field.fe_carry_mul(&x2, field.fe_relax_cast(&x2), field.fe_relax_cast(&z2)) + field.fe_to_bytes(out, &x2) + + field.fe_clear_vec([]^field.Tight_Field_Element{&x1, &x2, &x3, &z2, &z3}) + field.fe_clear_vec([]^field.Loose_Field_Element{&t1, &t2}) +} + +// scalarmult "multiplies" the provided scalar and point, and writes the +// resulting point to dst. +scalarmult :: proc(dst, scalar, point: []byte) { + if len(scalar) != SCALAR_SIZE { + panic("crypto/x448: invalid scalar size") + } + if len(point) != POINT_SIZE { + panic("crypto/x448: invalid point size") + } + if len(dst) != POINT_SIZE { + panic("crypto/x448: invalid destination point size") + } + + // "clamp" the scalar + e: [56]byte = --- + copy_slice(e[:], scalar) + e[0] &= 252 + e[55] |= 128 + + p: [56]byte = --- + copy_slice(p[:], point) + + d: [56]byte = --- + _scalarmult(&d, &e, &p) + copy_slice(dst, d[:]) + + mem.zero_explicit(&e, size_of(e)) + mem.zero_explicit(&d, size_of(d)) +} + +// scalarmult_basepoint "multiplies" the provided scalar with the X448 +// base point and writes the resulting point to dst. +scalarmult_basepoint :: proc(dst, scalar: []byte) { + scalarmult(dst, scalar, _BASE_POINT[:]) +} diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index 4a8a198d3..e95dcb67d 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -48,6 +48,7 @@ import shake "core:crypto/shake" import sm3 "core:crypto/sm3" import tuplehash "core:crypto/tuplehash" import x25519 "core:crypto/x25519" +import x448 "core:crypto/x448" import pe "core:debug/pe" import trace "core:debug/trace" @@ -190,6 +191,7 @@ _ :: shake _ :: sm3 _ :: tuplehash _ :: x25519 +_ :: x448 _ :: pe _ :: trace _ :: dynlib diff --git a/tests/benchmark/crypto/benchmark_crypto.odin b/tests/benchmark/crypto/benchmark_crypto.odin index b139ea669..72e6d0932 100644 --- a/tests/benchmark/crypto/benchmark_crypto.odin +++ b/tests/benchmark/crypto/benchmark_crypto.odin @@ -14,6 +14,7 @@ import "core:crypto/chacha20poly1305" import "core:crypto/ed25519" import "core:crypto/poly1305" import "core:crypto/x25519" +import "core:crypto/x448" // Cryptographic primitive benchmarks. @@ -237,6 +238,26 @@ benchmark_crypto :: proc(t: ^testing.T) { time.duration_microseconds(elapsed) / iters, ) } + { + point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" + + point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator) + scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator) + out: [x448.POINT_SIZE]byte = --- + + iters :: 10000 + start := time.now() + for i := 0; i < iters; i = i + 1 { + x448.scalarmult(out[:], scalar[:], point[:]) + } + elapsed := time.since(start) + + fmt.sbprintfln(&str, + "x448.scalarmult: ~%f us/op", + time.duration_microseconds(elapsed) / iters, + ) + } } @(private) diff --git a/tests/core/crypto/test_core_crypto_ecc25519.odin b/tests/core/crypto/test_core_crypto_edwards.odin similarity index 91% rename from tests/core/crypto/test_core_crypto_ecc25519.odin rename to tests/core/crypto/test_core_crypto_edwards.odin index fec4fa38e..61933c00f 100644 --- a/tests/core/crypto/test_core_crypto_ecc25519.odin +++ b/tests/core/crypto/test_core_crypto_edwards.odin @@ -7,6 +7,7 @@ import field "core:crypto/_fiat/field_curve25519" import "core:crypto/ed25519" import "core:crypto/ristretto255" import "core:crypto/x25519" +import "core:crypto/x448" @(test) test_sqrt_ratio_m1 :: proc(t: ^testing.T) { @@ -684,6 +685,68 @@ test_x25519 :: proc(t: ^testing.T) { } } +@(test) +test_x448 :: proc(t: ^testing.T) { + // Local copy of this so that the base point doesn't need to be exported. + _BASE_POINT: [56]byte = { + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + } + + test_vectors := []struct { + scalar: string, + point: string, + product: string, + } { + // Test vectors from RFC 7748 + { + "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", + "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", + "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f", + }, + { + "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", + "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", + "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d", + }, + } + for v, _ in test_vectors { + scalar, _ := hex.decode(transmute([]byte)(v.scalar), context.temp_allocator) + point, _ := hex.decode(transmute([]byte)(v.point), context.temp_allocator) + + derived_point: [x448.POINT_SIZE]byte + x448.scalarmult(derived_point[:], scalar[:], point[:]) + derived_point_str := string(hex.encode(derived_point[:], context.temp_allocator)) + + testing.expectf( + t, + derived_point_str == v.product, + "Expected %s for %s * %s, but got %s instead", + v.product, + v.scalar, + v.point, + derived_point_str, + ) + + // Abuse the test vectors to sanity-check the scalar-basepoint multiply. + p1, p2: [x448.POINT_SIZE]byte + x448.scalarmult_basepoint(p1[:], scalar[:]) + x448.scalarmult(p2[:], scalar[:], _BASE_POINT[:]) + p1_str := string(hex.encode(p1[:], context.temp_allocator)) + p2_str := string(hex.encode(p2[:], context.temp_allocator)) + testing.expectf( + t, + p1_str == p2_str, + "Expected %s for %s * basepoint, but got %s instead", + p2_str, + v.scalar, + p1_str, + ) + } +} + @(private) ge_str :: proc(ge: ^ristretto255.Group_Element) -> string { b: [ristretto255.ELEMENT_SIZE]byte From c2786a6dd5b1645011efa1243945cd34eb51338f Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Sat, 31 Aug 2024 04:10:22 +0900 Subject: [PATCH 18/81] core/crypto/aegis: Initial import --- core/crypto/_aes/ct64/ct64.odin | 7 +- core/crypto/_aes/ct64/ct64_keysched.odin | 56 +-- core/crypto/_aes/ct64/helpers.odin | 55 ++- core/crypto/aead/low_level.odin | 47 +- core/crypto/aegis/aegis.odin | 213 +++++++++ core/crypto/aegis/aegis_impl_ct64.odin | 452 +++++++++++++++++++ core/crypto/aegis/aegis_impl_hw_gen.odin | 44 ++ core/crypto/aegis/aegis_impl_hw_intel.odin | 389 ++++++++++++++++ examples/all/all_main.odin | 2 + tests/benchmark/crypto/benchmark_crypto.odin | 58 +++ tests/core/crypto/test_core_crypto_aead.odin | 204 +++++++++ 11 files changed, 1441 insertions(+), 86 deletions(-) create mode 100644 core/crypto/aegis/aegis.odin create mode 100644 core/crypto/aegis/aegis_impl_ct64.odin create mode 100644 core/crypto/aegis/aegis_impl_hw_gen.odin create mode 100644 core/crypto/aegis/aegis_impl_hw_intel.odin diff --git a/core/crypto/_aes/ct64/ct64.odin b/core/crypto/_aes/ct64/ct64.odin index b2d5b72bc..af2b42c1e 100644 --- a/core/crypto/_aes/ct64/ct64.odin +++ b/core/crypto/_aes/ct64/ct64.odin @@ -210,11 +210,8 @@ orthogonalize :: proc "contextless" (q: ^[8]u64) { } @(require_results) -interleave_in :: proc "contextless" (w: []u32) -> (q0, q1: u64) #no_bounds_check { - if len(w) < 4 { - panic_contextless("aes/ct64: invalid input size") - } - x0, x1, x2, x3 := u64(w[0]), u64(w[1]), u64(w[2]), u64(w[3]) +interleave_in :: proc "contextless" (w0, w1, w2, w3: u32) -> (q0, q1: u64) #no_bounds_check { + x0, x1, x2, x3 := u64(w0), u64(w1), u64(w2), u64(w3) x0 |= (x0 << 16) x1 |= (x1 << 16) x2 |= (x2 << 16) diff --git a/core/crypto/_aes/ct64/ct64_keysched.odin b/core/crypto/_aes/ct64/ct64_keysched.odin index 0cb01aa08..591bf53e6 100644 --- a/core/crypto/_aes/ct64/ct64_keysched.odin +++ b/core/crypto/_aes/ct64/ct64_keysched.odin @@ -77,7 +77,7 @@ keysched :: proc(comp_skey: []u64, key: []byte) -> int { q: [8]u64 = --- for i, j := 0, 0; i < nkf; i, j = i + 4, j + 2 { - q[0], q[4] = interleave_in(skey[i:]) + q[0], q[4] = interleave_in(skey[i], skey[i+1], skey[i+2], skey[i+3]) q[1] = q[0] q[2] = q[0] q[3] = q[0] @@ -122,57 +122,3 @@ skey_expand :: proc "contextless" (skey, comp_skey: []u64, num_rounds: int) { skey[v + 3] = (x3 << 4) - x3 } } - -orthogonalize_roundkey :: proc "contextless" (qq: []u64, key: []byte) { - if len(qq) < 8 || len(key) != 16 { - panic_contextless("aes/ct64: invalid round key size") - } - - skey: [4]u32 = --- - skey[0] = endian.unchecked_get_u32le(key[0:]) - skey[1] = endian.unchecked_get_u32le(key[4:]) - skey[2] = endian.unchecked_get_u32le(key[8:]) - skey[3] = endian.unchecked_get_u32le(key[12:]) - - q: [8]u64 = --- - q[0], q[4] = interleave_in(skey[:]) - q[1] = q[0] - q[2] = q[0] - q[3] = q[0] - q[5] = q[4] - q[6] = q[4] - q[7] = q[4] - orthogonalize(&q) - - comp_skey: [2]u64 = --- - comp_skey[0] = - (q[0] & 0x1111111111111111) | - (q[1] & 0x2222222222222222) | - (q[2] & 0x4444444444444444) | - (q[3] & 0x8888888888888888) - comp_skey[1] = - (q[4] & 0x1111111111111111) | - (q[5] & 0x2222222222222222) | - (q[6] & 0x4444444444444444) | - (q[7] & 0x8888888888888888) - - for x, u in comp_skey { - x0 := x - x1, x2, x3 := x0, x0, x0 - x0 &= 0x1111111111111111 - x1 &= 0x2222222222222222 - x2 &= 0x4444444444444444 - x3 &= 0x8888888888888888 - x1 >>= 1 - x2 >>= 2 - x3 >>= 3 - qq[u * 4 + 0] = (x0 << 4) - x0 - qq[u * 4 + 1] = (x1 << 4) - x1 - qq[u * 4 + 2] = (x2 << 4) - x2 - qq[u * 4 + 3] = (x3 << 4) - x3 - } - - mem.zero_explicit(&skey, size_of(skey)) - mem.zero_explicit(&q, size_of(q)) - mem.zero_explicit(&comp_skey, size_of(comp_skey)) -} diff --git a/core/crypto/_aes/ct64/helpers.odin b/core/crypto/_aes/ct64/helpers.odin index 0ca9c3f4e..b26817cb3 100644 --- a/core/crypto/_aes/ct64/helpers.odin +++ b/core/crypto/_aes/ct64/helpers.odin @@ -3,17 +3,39 @@ package aes_ct64 import "core:crypto/_aes" import "core:encoding/endian" +@(require_results) +load_interleaved :: proc "contextless" (src: []byte) -> (u64, u64) { + w0 := endian.unchecked_get_u32le(src[0:]) + w1 := endian.unchecked_get_u32le(src[4:]) + w2 := endian.unchecked_get_u32le(src[8:]) + w3 := endian.unchecked_get_u32le(src[12:]) + return interleave_in(w0, w1, w2, w3) +} + +store_interleaved :: proc "contextless" (dst: []byte, a0, a1: u64) { + w0, w1, w2, w3 := interleave_out(a0, a1) + endian.unchecked_put_u32le(dst[0:], w0) + endian.unchecked_put_u32le(dst[4:], w1) + endian.unchecked_put_u32le(dst[8:], w2) + endian.unchecked_put_u32le(dst[12:], w3) +} + +@(require_results) +xor_interleaved :: #force_inline proc "contextless" (a0, a1, b0, b1: u64) -> (u64, u64) { + return a0 ~ b0, a1 ~ b1 +} + +@(require_results) +and_interleaved :: #force_inline proc "contextless" (a0, a1, b0, b1: u64) -> (u64, u64) { + return a0 & b0, a1 & b1 +} + load_blockx1 :: proc "contextless" (q: ^[8]u64, src: []byte) { if len(src) != _aes.BLOCK_SIZE { panic_contextless("aes/ct64: invalid block size") } - w: [4]u32 = --- - w[0] = endian.unchecked_get_u32le(src[0:]) - w[1] = endian.unchecked_get_u32le(src[4:]) - w[2] = endian.unchecked_get_u32le(src[8:]) - w[3] = endian.unchecked_get_u32le(src[12:]) - q[0], q[4] = interleave_in(w[:]) + q[0], q[4] = #force_inline load_interleaved(src) orthogonalize(q) } @@ -23,11 +45,7 @@ store_blockx1 :: proc "contextless" (dst: []byte, q: ^[8]u64) { } orthogonalize(q) - w0, w1, w2, w3 := interleave_out(q[0], q[4]) - endian.unchecked_put_u32le(dst[0:], w0) - endian.unchecked_put_u32le(dst[4:], w1) - endian.unchecked_put_u32le(dst[8:], w2) - endian.unchecked_put_u32le(dst[12:], w3) + #force_inline store_interleaved(dst, q[0], q[4]) } load_blocks :: proc "contextless" (q: ^[8]u64, src: [][]byte) { @@ -35,17 +53,11 @@ load_blocks :: proc "contextless" (q: ^[8]u64, src: [][]byte) { panic_contextless("aes/ct64: invalid block(s) size") } - w: [4]u32 = --- for s, i in src { if len(s) != _aes.BLOCK_SIZE { panic_contextless("aes/ct64: invalid block size") } - - w[0] = endian.unchecked_get_u32le(s[0:]) - w[1] = endian.unchecked_get_u32le(s[4:]) - w[2] = endian.unchecked_get_u32le(s[8:]) - w[3] = endian.unchecked_get_u32le(s[12:]) - q[i], q[i + 4] = interleave_in(w[:]) + q[i], q[i + 4] = #force_inline load_interleaved(s) } orthogonalize(q) } @@ -64,11 +76,6 @@ store_blocks :: proc "contextless" (dst: [][]byte, q: ^[8]u64) { if len(d) != _aes.BLOCK_SIZE { panic_contextless("aes/ct64: invalid block size") } - - w0, w1, w2, w3 := interleave_out(q[i], q[i + 4]) - endian.unchecked_put_u32le(d[0:], w0) - endian.unchecked_put_u32le(d[4:], w1) - endian.unchecked_put_u32le(d[8:], w2) - endian.unchecked_put_u32le(d[12:], w3) + #force_inline store_interleaved(d, q[i], q[i + 4]) } } diff --git a/core/crypto/aead/low_level.odin b/core/crypto/aead/low_level.odin index 38a0c84ba..a7ecef801 100644 --- a/core/crypto/aead/low_level.odin +++ b/core/crypto/aead/low_level.odin @@ -1,5 +1,6 @@ package aead +import "core:crypto/aegis" import "core:crypto/aes" import "core:crypto/chacha20" import "core:crypto/chacha20poly1305" @@ -15,7 +16,7 @@ Implementation :: union { // MAX_TAG_SIZE is the maximum size tag that can be returned by any of the // Algorithms supported via this package. -MAX_TAG_SIZE :: 16 +MAX_TAG_SIZE :: 32 // Algorithm is the algorithm identifier associated with a given Context. Algorithm :: enum { @@ -25,9 +26,13 @@ Algorithm :: enum { AES_GCM_256, CHACHA20POLY1305, XCHACHA20POLY1305, + AEGIS_128L, + AEGIS_128L_256, // AEGIS-128L (256-bit tag) + AEGIS_256, + AEGIS_256_256, // AEGIS-256 (256-bit tag) } -// ALGORITM_NAMES is the Agorithm to algorithm name string. +// ALGORITM_NAMES is the Algorithm to algorithm name string. ALGORITHM_NAMES := [Algorithm]string { .Invalid = "Invalid", .AES_GCM_128 = "AES-GCM-128", @@ -35,6 +40,10 @@ ALGORITHM_NAMES := [Algorithm]string { .AES_GCM_256 = "AES-GCM-256", .CHACHA20POLY1305 = "chacha20poly1305", .XCHACHA20POLY1305 = "xchacha20poly1305", + .AEGIS_128L = "AEGIS-128L", + .AEGIS_128L_256 = "AEGIS-128L-256", + .AEGIS_256 = "AEGIS-256", + .AEGIS_256_256 = "AEGIS-256-256", } // TAG_SIZES is the Algorithm to tag size in bytes. @@ -45,6 +54,10 @@ TAG_SIZES := [Algorithm]int { .AES_GCM_256 = aes.GCM_TAG_SIZE, .CHACHA20POLY1305 = chacha20poly1305.TAG_SIZE, .XCHACHA20POLY1305 = chacha20poly1305.TAG_SIZE, + .AEGIS_128L = aegis.TAG_SIZE_128, + .AEGIS_128L_256 = aegis.TAG_SIZE_256, + .AEGIS_256 = aegis.TAG_SIZE_128, + .AEGIS_256_256 = aegis.TAG_SIZE_256, } // KEY_SIZES is the Algorithm to key size in bytes. @@ -55,6 +68,10 @@ KEY_SIZES := [Algorithm]int { .AES_GCM_256 = aes.KEY_SIZE_256, .CHACHA20POLY1305 = chacha20poly1305.KEY_SIZE, .XCHACHA20POLY1305 = chacha20poly1305.KEY_SIZE, + .AEGIS_128L = aegis.KEY_SIZE_128L, + .AEGIS_128L_256 = aegis.KEY_SIZE_128L, + .AEGIS_256 = aegis.KEY_SIZE_256, + .AEGIS_256_256 = aegis.KEY_SIZE_256, } // IV_SIZES is the Algorithm to initialization vector size in bytes. @@ -67,6 +84,10 @@ IV_SIZES := [Algorithm]int { .AES_GCM_256 = aes.GCM_IV_SIZE, .CHACHA20POLY1305 = chacha20poly1305.IV_SIZE, .XCHACHA20POLY1305 = chacha20poly1305.XIV_SIZE, + .AEGIS_128L = aegis.IV_SIZE_128L, + .AEGIS_128L_256 = aegis.IV_SIZE_128L, + .AEGIS_256 = aegis.IV_SIZE_256, + .AEGIS_256_256 = aegis.IV_SIZE_256, } // Context is a concrete instantiation of a specific AEAD algorithm. @@ -75,6 +96,7 @@ Context :: struct { _impl: union { aes.Context_GCM, chacha20poly1305.Context, + aegis.Context, }, } @@ -86,6 +108,10 @@ _IMPL_IDS := [Algorithm]typeid { .AES_GCM_256 = typeid_of(aes.Context_GCM), .CHACHA20POLY1305 = typeid_of(chacha20poly1305.Context), .XCHACHA20POLY1305 = typeid_of(chacha20poly1305.Context), + .AEGIS_128L = typeid_of(aegis.Context), + .AEGIS_128L_256 = typeid_of(aegis.Context), + .AEGIS_256 = typeid_of(aegis.Context), + .AEGIS_256_256 = typeid_of(aegis.Context), } // init initializes a Context with a specific AEAD Algorithm. @@ -113,6 +139,9 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementat case .XCHACHA20POLY1305: impl_ := impl != nil ? impl.(chacha20.Implementation) : chacha20.DEFAULT_IMPLEMENTATION chacha20poly1305.init_xchacha(&ctx._impl.(chacha20poly1305.Context), key, impl_) + case .AEGIS_128L, .AEGIS_128L_256, .AEGIS_256, .AEGIS_256_256: + impl_ := impl != nil ? impl.(aes.Implementation) : aes.DEFAULT_IMPLEMENTATION + aegis.init(&ctx._impl.(aegis.Context), key, impl_) case .Invalid: panic("crypto/aead: uninitialized algorithm") case: @@ -127,11 +156,17 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementat // // dst and plaintext MUST alias exactly or not at all. seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { + if len(tag) != TAG_SIZES[ctx._algo] { + panic("crypto/aead: invalid tag size") + } + switch &impl in ctx._impl { case aes.Context_GCM: aes.seal_gcm(&impl, dst, tag, iv, aad, plaintext) case chacha20poly1305.Context: chacha20poly1305.seal(&impl, dst, tag, iv, aad, plaintext) + case aegis.Context: + aegis.seal(&impl, dst, tag, iv, aad, plaintext) case: panic("crypto/aead: uninitialized algorithm") } @@ -145,11 +180,17 @@ seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { // dst and plaintext MUST alias exactly or not at all. @(require_results) open_ctx :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { + if len(tag) != TAG_SIZES[ctx._algo] { + panic("crypto/aead: invalid tag size") + } + switch &impl in ctx._impl { case aes.Context_GCM: return aes.open_gcm(&impl, dst, iv, aad, ciphertext, tag) case chacha20poly1305.Context: return chacha20poly1305.open(&impl, dst, iv, aad, ciphertext, tag) + case aegis.Context: + return aegis.open(&impl, dst, iv, aad, ciphertext, tag) case: panic("crypto/aead: uninitialized algorithm") } @@ -163,6 +204,8 @@ reset :: proc(ctx: ^Context) { aes.reset_gcm(&impl) case chacha20poly1305.Context: chacha20poly1305.reset(&impl) + case aegis.Context: + aegis.reset(&impl) case: // Calling reset repeatedly is fine. } diff --git a/core/crypto/aegis/aegis.odin b/core/crypto/aegis/aegis.odin new file mode 100644 index 000000000..adecce91f --- /dev/null +++ b/core/crypto/aegis/aegis.odin @@ -0,0 +1,213 @@ +/* +package aegis implements the AEGIS-128L and AEGIS-256 Authenticated +Encryption with Additional Data algorithms. + +See: +- [[ https://www.ietf.org/archive/id/draft-irtf-cfrg-aegis-aead-12.txt ]] +*/ +package aegis + +import "core:bytes" +import "core:crypto" +import "core:crypto/aes" +import "core:mem" + +// KEY_SIZE_128L is the AEGIS-128L key size in bytes. +KEY_SIZE_128L :: 16 +// KEY_SIZE_256 is the AEGIS-256 key size in bytes. +KEY_SIZE_256 :: 32 +// IV_SIZE_128L is the AEGIS-128L IV size in bytes. +IV_SIZE_128L :: 16 +// IV_SIZE_256 is the AEGIS-256 IV size in bytes. +IV_SIZE_256 :: 32 +// TAG_SIZE_128 is the AEGIS-128L or AEGIS-256 128-bit tag size in bytes. +TAG_SIZE_128 :: 16 +// TAG_SIZE_256 is the AEGIS-128L or AEGIS-256 256-bit tag size in bytes. +TAG_SIZE_256 :: 32 + +@(private) +_RATE_128L :: 32 +@(private) +_RATE_256 :: 16 +@(private) +_RATE_MAX :: _RATE_128L + +@(private, rodata) +_C0 := [16]byte{ + 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d, + 0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62, +} + +@(private, rodata) +_C1 := [16]byte { + 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1, + 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd, +} + +// Context is a keyed AEGIS-128L or AEGIS-256 instance. +Context :: struct { + _key: [KEY_SIZE_256]byte, + _key_len: int, + _impl: aes.Implementation, + _is_initialized: bool, +} + +@(private) +_validate_common_slice_sizes :: proc (ctx: ^Context, tag, iv, aad, text: []byte) { + switch len(tag) { + case TAG_SIZE_128, TAG_SIZE_256: + case: + panic("crypto/aegis: invalid tag size") + } + + iv_ok: bool + switch ctx._key_len { + case KEY_SIZE_128L: + iv_ok = len(iv) == IV_SIZE_128L + case KEY_SIZE_256: + iv_ok = len(iv) == IV_SIZE_256 + } + ensure(iv_ok,"crypto/aegis: invalid IV size") + + #assert(size_of(int) == 8 || size_of(int) <= 4) + // As A_MAX and P_MAX are both defined to be 2^61 - 1 bytes, and + // the maximum length of a slice is bound by `size_of(int)`, where + // `int` is register sized, there is no need to check AAD/text + // lengths. +} + +// init initializes a Context with the provided key, for AEGIS-128L or AEGIS-256. +init :: proc(ctx: ^Context, key: []byte, impl := aes.DEFAULT_IMPLEMENTATION) { + switch len(key) { + case KEY_SIZE_128L, KEY_SIZE_256: + case: + panic("crypto/aegis: invalid key size") + } + + copy(ctx._key[:], key) + ctx._key_len = len(key) + ctx._impl = impl + if ctx._impl == .Hardware && !is_hardware_accelerated() { + ctx._impl = .Portable + } + ctx._is_initialized = true +} + +// seal encrypts the plaintext and authenticates the aad and ciphertext, +// with the provided Context and iv, stores the output in dst and tag. +// +// dst and plaintext MUST alias exactly or not at all. +seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { + ensure(ctx._is_initialized) + + _validate_common_slice_sizes(ctx, tag, iv, aad, plaintext) + ensure(len(dst) == len(plaintext), "crypto/aegis: invalid destination ciphertext size") + ensure(!bytes.alias_inexactly(dst, plaintext), "crypto/aegis: dst and plaintext alias inexactly") + + switch ctx._impl { + case .Hardware: + st: State_HW + defer reset_state_hw(&st) + + init_hw(ctx, &st, iv) + + aad_len, pt_len := len(aad), len(plaintext) + if aad_len > 0 { + absorb_hw(&st, aad) + } + + if pt_len > 0 { + enc_hw(&st, dst, plaintext) + } + + finalize_hw(&st, tag, aad_len, pt_len) + case .Portable: + st: State_SW + defer reset_state_sw(&st) + + init_sw(ctx, &st, iv) + + aad_len, pt_len := len(aad), len(plaintext) + if aad_len > 0 { + absorb_sw(&st, aad) + } + + if pt_len > 0 { + enc_sw(&st, dst, plaintext) + } + + finalize_sw(&st, tag, aad_len, pt_len) + case: + panic("core/crypto/aegis: not implemented") + } +} + +// open authenticates the aad and ciphertext, and decrypts the ciphertext, +// with the provided Context, iv, and tag, and stores the output in dst, +// returning true iff the authentication was successful. If authentication +// fails, the destination buffer will be zeroed. +// +// dst and plaintext MUST alias exactly or not at all. +@(require_results) +open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { + ensure(ctx._is_initialized) + + _validate_common_slice_sizes(ctx, tag, iv, aad, ciphertext) + ensure(len(dst) == len(ciphertext), "crypto/aegis: invalid destination plaintext size") + ensure(!bytes.alias_inexactly(dst, ciphertext), "crypto/aegis: dst and ciphertext alias inexactly") + + tmp: [TAG_SIZE_256]byte + derived_tag := tmp[:len(tag)] + aad_len, ct_len := len(aad), len(ciphertext) + + switch ctx._impl { + case .Hardware: + st: State_HW + defer reset_state_hw(&st) + + init_hw(ctx, &st, iv) + + if aad_len > 0 { + absorb_hw(&st, aad) + } + + if ct_len > 0 { + dec_hw(&st, dst, ciphertext) + } + + finalize_hw(&st, derived_tag, aad_len, ct_len) + case .Portable: + st: State_SW + defer reset_state_sw(&st) + + init_sw(ctx, &st, iv) + + if aad_len > 0 { + absorb_sw(&st, aad) + } + + if ct_len > 0 { + dec_sw(&st, dst, ciphertext) + } + + finalize_sw(&st, derived_tag, aad_len, ct_len) + case: + panic("core/crypto/aegis: not implemented") + } + + if crypto.compare_constant_time(tag, derived_tag) != 1 { + mem.zero_explicit(raw_data(derived_tag), len(derived_tag)) + mem.zero_explicit(raw_data(dst), ct_len) + return false + } + + return true +} + +// reset sanitizes the Context. The Context must be +// re-initialized to be used again. +reset :: proc "contextless" (ctx: ^Context) { + mem.zero_explicit(&ctx._key, len(ctx._key)) + ctx._key_len = 0 + ctx._is_initialized = false +} diff --git a/core/crypto/aegis/aegis_impl_ct64.odin b/core/crypto/aegis/aegis_impl_ct64.odin new file mode 100644 index 000000000..4813b37ec --- /dev/null +++ b/core/crypto/aegis/aegis_impl_ct64.odin @@ -0,0 +1,452 @@ +package aegis + +import aes "core:crypto/_aes/ct64" +import "core:encoding/endian" +import "core:mem" + +// This uses the bitlsiced 64-bit general purpose register SWAR AES +// round function. The intermediate state is stored in interleaved +// but NOT orthogonalized form, as leaving things in the orthgonalized +// format would overly complicate the update implementation. +// +// Note/perf: Per Frank Denis and a review of the specification, it is +// possible to gain slightly more performance by leaving the state in +// orthogonalized form while doing initialization, finalization, and +// absorbing AAD. This implementation opts out of those optimizations +// for the sake of simplicity. +// +// The update function leverages the paralleism (4xblocks) at once. + +@(private) +State_SW :: struct { + s0_0, s0_1: u64, + s1_0, s1_1: u64, + s2_0, s2_1: u64, + s3_0, s3_1: u64, + s4_0, s4_1: u64, + s5_0, s5_1: u64, + s6_0, s6_1: u64, + s7_0, s7_1: u64, + q_k, q_b: [8]u64, + rate: int, +} + +@(private) +init_sw :: proc "contextless" (ctx: ^Context, st: ^State_SW, iv: []byte) { + switch ctx._key_len { + case KEY_SIZE_128L: + key_0, key_1 := aes.load_interleaved(ctx._key[:16]) + iv_0, iv_1 := aes.load_interleaved(iv) + + st.s0_0, st.s0_1 = aes.xor_interleaved(key_0, key_1, iv_0, iv_1) + st.s1_0, st.s1_1 = aes.load_interleaved(_C1[:]) + st.s2_0, st.s2_1 = aes.load_interleaved(_C0[:]) + st.s3_0, st.s3_1 = st.s1_0, st.s1_1 + st.s4_0, st.s4_1 = st.s0_0, st.s0_1 + st.s5_0, st.s5_1 = aes.xor_interleaved(key_0, key_1, st.s2_0, st.s2_1) + st.s6_0, st.s6_1 = aes.xor_interleaved(key_0, key_1, st.s1_0, st.s1_1) + st.s7_0, st.s7_1 = st.s5_0, st.s5_1 + st.rate = _RATE_128L + + for _ in 0 ..< 10 { + update_sw_128l(st, iv_0, iv_1, key_0, key_1) + } + case KEY_SIZE_256: + k0_0, k0_1 := aes.load_interleaved(ctx._key[:16]) + k1_0, k1_1 := aes.load_interleaved(ctx._key[16:]) + n0_0, n0_1 := aes.load_interleaved(iv[:16]) + n1_0, n1_1 := aes.load_interleaved(iv[16:]) + + st.s0_0, st.s0_1 = aes.xor_interleaved(k0_0, k0_1, n0_0, n0_1) + st.s1_0, st.s1_1 = aes.xor_interleaved(k1_0, k1_1, n1_0, n1_1) + st.s2_0, st.s2_1 = aes.load_interleaved(_C1[:]) + st.s3_0, st.s3_1 = aes.load_interleaved(_C0[:]) + st.s4_0, st.s4_1 = aes.xor_interleaved(k0_0, k0_1, st.s3_0, st.s3_1) + st.s5_0, st.s5_1 = aes.xor_interleaved(k1_0, k1_1, st.s2_0, st.s2_1) + st.rate = _RATE_256 + + u0_0, u0_1, u1_0, u1_1 := st.s0_0, st.s0_1, st.s1_0, st.s1_1 + for _ in 0 ..< 4 { + update_sw_256(st, k0_0, k0_1) + update_sw_256(st, k1_0, k1_1) + update_sw_256(st, u0_0, u0_1) + update_sw_256(st, u1_0, u1_1) + } + } +} + +@(private = "file") +update_sw_128l :: proc "contextless" (st: ^State_SW, m0_0, m0_1, m1_0, m1_1: u64) { + st.q_k[0], st.q_k[4] = aes.xor_interleaved(st.s0_0, st.s0_1, m0_0, m0_1) + st.q_k[1], st.q_k[5] = st.s1_0, st.s1_1 + st.q_k[2], st.q_k[6] = st.s2_0, st.s2_1 + st.q_k[3], st.q_k[7] = st.s3_0, st.s3_1 + aes.orthogonalize(&st.q_k) + + st.q_b[0], st.q_b[4] = st.s7_0, st.s7_1 + st.q_b[1], st.q_b[5] = st.s0_0, st.s0_1 + st.q_b[2], st.q_b[6] = st.s1_0, st.s1_1 + st.q_b[3], st.q_b[7] = st.s2_0, st.s2_1 + aes.orthogonalize(&st.q_b) + + aes.sub_bytes(&st.q_b) + aes.shift_rows(&st.q_b) + aes.mix_columns(&st.q_b) + aes.add_round_key(&st.q_b, st.q_k[:]) + aes.orthogonalize(&st.q_b) + + st.s0_0, st.s0_1 = st.q_b[0], st.q_b[4] + st.s1_0, st.s1_1 = st.q_b[1], st.q_b[5] + st.s2_0, st.s2_1 = st.q_b[2], st.q_b[6] + s3_0, s3_1 := st.q_b[3], st.q_b[7] + + st.q_k[0], st.q_k[4] = aes.xor_interleaved(st.s4_0, st.s4_1, m1_0, m1_1) + st.q_k[1], st.q_k[5] = st.s5_0, st.s5_1 + st.q_k[2], st.q_k[6] = st.s6_0, st.s6_1 + st.q_k[3], st.q_k[7] = st.s7_0, st.s7_1 + aes.orthogonalize(&st.q_k) + + st.q_b[0], st.q_b[4] = st.s3_0, st.s3_1 + st.q_b[1], st.q_b[5] = st.s4_0, st.s4_1 + st.q_b[2], st.q_b[6] = st.s5_0, st.s5_1 + st.q_b[3], st.q_b[7] = st.s6_0, st.s6_1 + aes.orthogonalize(&st.q_b) + + aes.sub_bytes(&st.q_b) + aes.shift_rows(&st.q_b) + aes.mix_columns(&st.q_b) + aes.add_round_key(&st.q_b, st.q_k[:]) + aes.orthogonalize(&st.q_b) + + st.s3_0, st.s3_1 = s3_0, s3_1 + st.s4_0, st.s4_1 = st.q_b[0], st.q_b[4] + st.s5_0, st.s5_1 = st.q_b[1], st.q_b[5] + st.s6_0, st.s6_1 = st.q_b[2], st.q_b[6] + st.s7_0, st.s7_1 = st.q_b[3], st.q_b[7] +} + +@(private = "file") +update_sw_256 :: proc "contextless" (st: ^State_SW, m_0, m_1: u64) { + st.q_k[0], st.q_k[4] = aes.xor_interleaved(st.s0_0, st.s0_1, m_0, m_1) + st.q_k[1], st.q_k[5] = st.s1_0, st.s1_1 + st.q_k[2], st.q_k[6] = st.s2_0, st.s2_1 + st.q_k[3], st.q_k[7] = st.s3_0, st.s3_1 + aes.orthogonalize(&st.q_k) + + st.q_b[0], st.q_b[4] = st.s5_0, st.s5_1 + st.q_b[1], st.q_b[5] = st.s0_0, st.s0_1 + st.q_b[2], st.q_b[6] = st.s1_0, st.s1_1 + st.q_b[3], st.q_b[7] = st.s2_0, st.s2_1 + aes.orthogonalize(&st.q_b) + + aes.sub_bytes(&st.q_b) + aes.shift_rows(&st.q_b) + aes.mix_columns(&st.q_b) + aes.add_round_key(&st.q_b, st.q_k[:]) + aes.orthogonalize(&st.q_b) + + st.s0_0, st.s0_1 = st.q_b[0], st.q_b[4] + st.s1_0, st.s1_1 = st.q_b[1], st.q_b[5] + st.s2_0, st.s2_1 = st.q_b[2], st.q_b[6] + s3_0, s3_1 := st.q_b[3], st.q_b[7] + + st.q_k[0], st.q_k[4] = st.s4_0, st.s4_1 + st.q_k[1], st.q_k[5] = st.s5_0, st.s5_1 + aes.orthogonalize(&st.q_k) + + st.q_b[0], st.q_b[4] = st.s3_0, st.s3_1 + st.q_b[1], st.q_b[5] = st.s4_0, st.s4_1 + aes.orthogonalize(&st.q_b) + + aes.sub_bytes(&st.q_b) + aes.shift_rows(&st.q_b) + aes.mix_columns(&st.q_b) + aes.add_round_key(&st.q_b, st.q_k[:]) + aes.orthogonalize(&st.q_b) + + st.s3_0, st.s3_1 = s3_0, s3_1 + st.s4_0, st.s4_1 = st.q_b[0], st.q_b[4] + st.s5_0, st.s5_1 = st.q_b[1], st.q_b[5] +} + +@(private = "file") +absorb_sw_128l :: #force_inline proc "contextless" (st: ^State_SW, ai: []byte) #no_bounds_check { + t0_0, t0_1 := aes.load_interleaved(ai[:16]) + t1_0, t1_1 := aes.load_interleaved(ai[16:]) + update_sw_128l(st, t0_0, t0_1, t1_0, t1_1) +} + +@(private = "file") +absorb_sw_256 :: #force_inline proc "contextless" (st: ^State_SW, ai: []byte) { + m_0, m_1 := aes.load_interleaved(ai) + update_sw_256(st, m_0, m_1) +} + +@(private) +absorb_sw :: proc "contextless" (st: ^State_SW, aad: []byte) #no_bounds_check { + ai, l := aad, len(aad) + + switch st.rate { + case _RATE_128L: + for l >= _RATE_128L { + absorb_sw_128l(st, ai) + ai = ai[_RATE_128L:] + l -= _RATE_128L + } + case _RATE_256: + for l >= _RATE_256 { + absorb_sw_256(st, ai) + + ai = ai[_RATE_256:] + l -= _RATE_256 + } + } + + // Pad out the remainder with `0`s till it is rate sized. + if l > 0 { + tmp: [_RATE_MAX]byte // AAD is not confidential. + copy(tmp[:], ai) + switch st.rate { + case _RATE_128L: + absorb_sw_128l(st, tmp[:]) + case _RATE_256: + absorb_sw_256(st, tmp[:]) + } + } +} + +@(private = "file", require_results) +z_sw_128l :: proc "contextless" (st: ^State_SW) -> (u64, u64, u64, u64) { + z0_0, z0_1 := aes.and_interleaved(st.s2_0, st.s2_1, st.s3_0, st.s3_1) + z0_0, z0_1 = aes.xor_interleaved(st.s1_0, st.s1_1, z0_0, z0_1) + z0_0, z0_1 = aes.xor_interleaved(st.s6_0, st.s6_1, z0_0, z0_1) + + z1_0, z1_1 := aes.and_interleaved(st.s6_0, st.s6_1, st.s7_0, st.s7_1) + z1_0, z1_1 = aes.xor_interleaved(st.s5_0, st.s5_1, z1_0, z1_1) + z1_0, z1_1 = aes.xor_interleaved(st.s2_0, st.s2_1, z1_0, z1_1) + + return z0_0, z0_1, z1_0, z1_1 +} + +@(private = "file", require_results) +z_sw_256 :: proc "contextless" (st: ^State_SW) -> (u64, u64) { + z_0, z_1 := aes.and_interleaved(st.s2_0, st.s2_1, st.s3_0, st.s3_1) + z_0, z_1 = aes.xor_interleaved(st.s5_0, st.s5_1, z_0, z_1) + z_0, z_1 = aes.xor_interleaved(st.s4_0, st.s4_1, z_0, z_1) + return aes.xor_interleaved(st.s1_0, st.s1_1, z_0, z_1) +} + +@(private = "file") +enc_sw_128l :: #force_inline proc "contextless" (st: ^State_SW, ci, xi: []byte) #no_bounds_check { + z0_0, z0_1, z1_0, z1_1 := z_sw_128l(st) + + t0_0, t0_1 := aes.load_interleaved(xi[:16]) + t1_0, t1_1 := aes.load_interleaved(xi[16:]) + update_sw_128l(st, t0_0, t0_1, t1_0, t1_1) + + out0_0, out0_1 := aes.xor_interleaved(t0_0, t0_1, z0_0, z0_1) + out1_0, out1_1 := aes.xor_interleaved(t1_0, t1_1, z1_0, z1_1) + aes.store_interleaved(ci[:16], out0_0, out0_1) + aes.store_interleaved(ci[16:], out1_0, out1_1) +} + +@(private = "file") +enc_sw_256 :: #force_inline proc "contextless" (st: ^State_SW, ci, xi: []byte) #no_bounds_check { + z_0, z_1 := z_sw_256(st) + + xi_0, xi_1 := aes.load_interleaved(xi) + update_sw_256(st, xi_0, xi_1) + + ci_0, ci_1 := aes.xor_interleaved(xi_0, xi_1, z_0, z_1) + aes.store_interleaved(ci, ci_0, ci_1) +} + +@(private) +enc_sw :: proc "contextless" (st: ^State_SW, dst, src: []byte) #no_bounds_check { + ci, xi, l := dst, src, len(src) + + switch st.rate { + case _RATE_128L: + for l >= _RATE_128L { + enc_sw_128l(st, ci, xi) + ci = ci[_RATE_128L:] + xi = xi[_RATE_128L:] + l -= _RATE_128L + } + case _RATE_256: + for l >= _RATE_256 { + enc_sw_256(st, ci, xi) + ci = ci[_RATE_256:] + xi = xi[_RATE_256:] + l -= _RATE_256 + } + } + + // Pad out the remainder with `0`s till it is rate sized. + if l > 0 { + tmp: [_RATE_MAX]byte // Ciphertext is not confidential. + copy(tmp[:], xi) + switch st.rate { + case _RATE_128L: + enc_sw_128l(st, tmp[:], tmp[:]) + case _RATE_256: + enc_sw_256(st, tmp[:], tmp[:]) + } + copy(ci, tmp[:l]) + } +} + +@(private = "file") +dec_sw_128l :: #force_inline proc "contextless" (st: ^State_SW, xi, ci: []byte) #no_bounds_check { + z0_0, z0_1, z1_0, z1_1 := z_sw_128l(st) + + t0_0, t0_1 := aes.load_interleaved(ci[:16]) + t1_0, t1_1 := aes.load_interleaved(ci[16:]) + out0_0, out0_1 := aes.xor_interleaved(t0_0, t0_1, z0_0, z0_1) + out1_0, out1_1 := aes.xor_interleaved(t1_0, t1_1, z1_0, z1_1) + + update_sw_128l(st, out0_0, out0_1, out1_0, out1_1) + aes.store_interleaved(xi[:16], out0_0, out0_1) + aes.store_interleaved(xi[16:], out1_0, out1_1) +} + +@(private = "file") +dec_sw_256 :: #force_inline proc "contextless" (st: ^State_SW, xi, ci: []byte) #no_bounds_check { + z_0, z_1 := z_sw_256(st) + + ci_0, ci_1 := aes.load_interleaved(ci) + xi_0, xi_1 := aes.xor_interleaved(ci_0, ci_1, z_0, z_1) + + update_sw_256(st, xi_0, xi_1) + aes.store_interleaved(xi, xi_0, xi_1) +} + +@(private = "file") +dec_partial_sw_128l :: proc "contextless" (st: ^State_SW, xn, cn: []byte) #no_bounds_check { + tmp: [_RATE_128L]byte + defer mem.zero_explicit(&tmp, size_of(tmp)) + + z0_0, z0_1, z1_0, z1_1 := z_sw_128l(st) + copy(tmp[:], cn) + + t0_0, t0_1 := aes.load_interleaved(tmp[:16]) + t1_0, t1_1 := aes.load_interleaved(tmp[16:]) + out0_0, out0_1 := aes.xor_interleaved(t0_0, t0_1, z0_0, z0_1) + out1_0, out1_1 := aes.xor_interleaved(t1_0, t1_1, z1_0, z1_1) + + aes.store_interleaved(tmp[:16], out0_0, out0_1) + aes.store_interleaved(tmp[16:], out1_0, out1_1) + copy(xn, tmp[:]) + + for off := len(xn); off < _RATE_128L; off += 1 { + tmp[off] = 0 + } + out0_0, out0_1 = aes.load_interleaved(tmp[:16]) + out1_0, out1_1 = aes.load_interleaved(tmp[16:]) + update_sw_128l(st, out0_0, out0_1, out1_0, out1_1) +} + +@(private = "file") +dec_partial_sw_256 :: proc "contextless" (st: ^State_SW, xn, cn: []byte) #no_bounds_check { + tmp: [_RATE_256]byte + defer mem.zero_explicit(&tmp, size_of(tmp)) + + z_0, z_1 := z_sw_256(st) + copy(tmp[:], cn) + + cn_0, cn_1 := aes.load_interleaved(tmp[:]) + xn_0, xn_1 := aes.xor_interleaved(cn_0, cn_1, z_0, z_1) + + aes.store_interleaved(tmp[:], xn_0, xn_1) + copy(xn, tmp[:]) + + for off := len(xn); off < _RATE_256; off += 1 { + tmp[off] = 0 + } + xn_0, xn_1 = aes.load_interleaved(tmp[:]) + update_sw_256(st, xn_0, xn_1) +} + +@(private) +dec_sw :: proc "contextless" (st: ^State_SW, dst, src: []byte) #no_bounds_check { + xi, ci, l := dst, src, len(src) + + switch st.rate { + case _RATE_128L: + for l >= _RATE_128L { + dec_sw_128l(st, xi, ci) + xi = xi[_RATE_128L:] + ci = ci[_RATE_128L:] + l -= _RATE_128L + } + case _RATE_256: + for l >= _RATE_256 { + dec_sw_256(st, xi, ci) + xi = xi[_RATE_256:] + ci = ci[_RATE_256:] + l -= _RATE_256 + } + } + + // Process the remainder. + if l > 0 { + switch st.rate { + case _RATE_128L: + dec_partial_sw_128l(st, xi, ci) + case _RATE_256: + dec_partial_sw_256(st, xi, ci) + } + } +} + +@(private) +finalize_sw :: proc "contextless" (st: ^State_SW, tag: []byte, ad_len, msg_len: int) { + tmp: [16]byte + endian.unchecked_put_u64le(tmp[0:], u64(ad_len) * 8) + endian.unchecked_put_u64le(tmp[8:], u64(msg_len) * 8) + + t_0, t_1 := aes.load_interleaved(tmp[:]) + + t0_0, t0_1, t1_0, t1_1: u64 = ---, ---, ---, --- + switch st.rate { + case _RATE_128L: + t_0, t_1 = aes.xor_interleaved(st.s2_0, st.s2_1, t_0, t_1) + for _ in 0 ..< 7 { + update_sw_128l(st, t_0, t_1, t_0, t_1) + } + + t0_0, t0_1 = aes.xor_interleaved(st.s0_0, st.s0_1, st.s1_0, st.s1_1) + t0_0, t0_1 = aes.xor_interleaved(t0_0, t0_1, st.s2_0, st.s2_1) + t0_0, t0_1 = aes.xor_interleaved(t0_0, t0_1, st.s3_0, st.s3_1) + + t1_0, t1_1 = aes.xor_interleaved(st.s4_0, st.s4_1, st.s5_0, st.s5_1) + t1_0, t1_1 = aes.xor_interleaved(t1_0, t1_1, st.s6_0, st.s6_1) + if len(tag) == TAG_SIZE_256 { + t1_0, t1_1 = aes.xor_interleaved(t1_0, t1_1, st.s7_0, st.s7_1) + } + case _RATE_256: + t_0, t_1 = aes.xor_interleaved(st.s3_0, st.s3_1, t_0, t_1) + for _ in 0 ..< 7 { + update_sw_256(st, t_0, t_1) + } + + t0_0, t0_1 = aes.xor_interleaved(st.s0_0, st.s0_1, st.s1_0, st.s1_1) + t0_0, t0_1 = aes.xor_interleaved(t0_0, t0_1, st.s2_0, st.s2_1) + + t1_0, t1_1 = aes.xor_interleaved(st.s3_0, st.s3_1, st.s4_0, st.s4_1) + t1_0, t1_1 = aes.xor_interleaved(t1_0, t1_1, st.s5_0, st.s5_1) + } + switch len(tag) { + case TAG_SIZE_128: + t0_0, t0_1 = aes.xor_interleaved(t0_0, t0_1, t1_0, t1_1) + aes.store_interleaved(tag, t0_0, t0_1) + case TAG_SIZE_256: + aes.store_interleaved(tag[:16], t0_0, t0_1) + aes.store_interleaved(tag[16:], t1_0, t1_1) + } +} + +@(private) +reset_state_sw :: proc "contextless" (st: ^State_SW) { + mem.zero_explicit(st, size_of(st^)) +} diff --git a/core/crypto/aegis/aegis_impl_hw_gen.odin b/core/crypto/aegis/aegis_impl_hw_gen.odin new file mode 100644 index 000000000..5ec2f3d6e --- /dev/null +++ b/core/crypto/aegis/aegis_impl_hw_gen.odin @@ -0,0 +1,44 @@ +#+build !amd64 +package aegis + +@(private = "file") +ERR_HW_NOT_SUPPORTED :: "crypto/aegis: hardware implementation unsupported" + +@(private) +State_HW :: struct {} + +// is_hardware_accelerated returns true iff hardware accelerated AEGIS +// is supported. +is_hardware_accelerated :: proc "contextless" () -> bool { + return false +} + +@(private) +init_hw :: proc "contextless" (ctx: ^Context, st: ^State_HW, iv: []byte) { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} + +@(private) +absorb_hw :: proc "contextless" (st: ^State_HW, aad: []byte) { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} + +@(private) +enc_hw :: proc "contextless" (st: ^State_HW, dst, src: []byte) { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} + +@(private) +dec_hw :: proc "contextless" (st: ^State_HW, dst, src: []byte) { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} + +@(private) +finalize_hw :: proc "contextless" (st: ^State_HW, tag: []byte, ad_len, msg_len: int) { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} + +@(private) +reset_state_hw :: proc "contextless" (st: ^State_HW) { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} diff --git a/core/crypto/aegis/aegis_impl_hw_intel.odin b/core/crypto/aegis/aegis_impl_hw_intel.odin new file mode 100644 index 000000000..5334f3258 --- /dev/null +++ b/core/crypto/aegis/aegis_impl_hw_intel.odin @@ -0,0 +1,389 @@ +#+build amd64 +package aegis + +import "base:intrinsics" +import "core:crypto/aes" +import "core:encoding/endian" +import "core:mem" +import "core:simd/x86" + +@(private) +State_HW :: struct { + s0: x86.__m128i, + s1: x86.__m128i, + s2: x86.__m128i, + s3: x86.__m128i, + s4: x86.__m128i, + s5: x86.__m128i, + s6: x86.__m128i, + s7: x86.__m128i, + rate: int, +} + +// is_hardware_accelerated returns true iff hardware accelerated AEGIS +// is supported. +is_hardware_accelerated :: proc "contextless" () -> bool { + return aes.is_hardware_accelerated() +} + +@(private, enable_target_feature = "sse2,aes") +init_hw :: proc "contextless" (ctx: ^Context, st: ^State_HW, iv: []byte) { + switch ctx._key_len { + case KEY_SIZE_128L: + key := intrinsics.unaligned_load((^x86.__m128i)(&ctx._key[0])) + iv := intrinsics.unaligned_load((^x86.__m128i)(raw_data(iv))) + + st.s0 = x86._mm_xor_si128(key, iv) + st.s1 = intrinsics.unaligned_load((^x86.__m128i)(&_C1[0])) + st.s2 = intrinsics.unaligned_load((^x86.__m128i)(&_C0[0])) + st.s3 = st.s1 + st.s4 = st.s0 + st.s5 = x86._mm_xor_si128(key, st.s2) // key ^ C0 + st.s6 = x86._mm_xor_si128(key, st.s1) // key ^ C1 + st.s7 = st.s5 + st.rate = _RATE_128L + + for _ in 0 ..< 10 { + update_hw_128l(st, iv, key) + } + case KEY_SIZE_256: + k0 := intrinsics.unaligned_load((^x86.__m128i)(&ctx._key[0])) + k1 := intrinsics.unaligned_load((^x86.__m128i)(&ctx._key[16])) + n0 := intrinsics.unaligned_load((^x86.__m128i)(&iv[0])) + n1 := intrinsics.unaligned_load((^x86.__m128i)(&iv[16])) + + st.s0 = x86._mm_xor_si128(k0, n0) + st.s1 = x86._mm_xor_si128(k1, n1) + st.s2 = intrinsics.unaligned_load((^x86.__m128i)(&_C1[0])) + st.s3 = intrinsics.unaligned_load((^x86.__m128i)(&_C0[0])) + st.s4 = x86._mm_xor_si128(k0, st.s3) // k0 ^ C0 + st.s5 = x86._mm_xor_si128(k1, st.s2) // k1 ^ C1 + st.rate = _RATE_256 + + u0, u1 := st.s0, st.s1 + for _ in 0 ..< 4 { + update_hw_256(st, k0) + update_hw_256(st, k1) + update_hw_256(st, u0) + update_hw_256(st, u1) + } + } +} + +@(private = "file", enable_target_feature = "sse2,aes") +update_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, m0, m1: x86.__m128i) { + s0_ := x86._mm_aesenc_si128(st.s7, x86._mm_xor_si128(st.s0, m0)) + s1_ := x86._mm_aesenc_si128(st.s0, st.s1) + s2_ := x86._mm_aesenc_si128(st.s1, st.s2) + s3_ := x86._mm_aesenc_si128(st.s2, st.s3) + s4_ := x86._mm_aesenc_si128(st.s3, x86._mm_xor_si128(st.s4, m1)) + s5_ := x86._mm_aesenc_si128(st.s4, st.s5) + s6_ := x86._mm_aesenc_si128(st.s5, st.s6) + s7_ := x86._mm_aesenc_si128(st.s6, st.s7) + st.s0, st.s1, st.s2, st.s3, st.s4, st.s5, st.s6, st.s7 = s0_, s1_, s2_, s3_, s4_, s5_, s6_, s7_ +} + +@(private = "file", enable_target_feature = "sse2,aes") +update_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, m: x86.__m128i) { + s0_ := x86._mm_aesenc_si128(st.s5, x86._mm_xor_si128(st.s0, m)) + s1_ := x86._mm_aesenc_si128(st.s0, st.s1) + s2_ := x86._mm_aesenc_si128(st.s1, st.s2) + s3_ := x86._mm_aesenc_si128(st.s2, st.s3) + s4_ := x86._mm_aesenc_si128(st.s3, st.s4) + s5_ := x86._mm_aesenc_si128(st.s4, st.s5) + st.s0, st.s1, st.s2, st.s3, st.s4, st.s5 = s0_, s1_, s2_, s3_, s4_, s5_ +} + +@(private = "file", enable_target_feature = "sse2,aes") +absorb_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, ai: []byte) { + t0 := intrinsics.unaligned_load((^x86.__m128i)(&ai[0])) + t1 := intrinsics.unaligned_load((^x86.__m128i)(&ai[16])) + update_hw_128l(st, t0, t1) +} + +@(private = "file", enable_target_feature = "sse2,aes") +absorb_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, ai: []byte) { + m := intrinsics.unaligned_load((^x86.__m128i)(&ai[0])) + update_hw_256(st, m) +} + +@(private, enable_target_feature = "sse2,aes") +absorb_hw :: proc "contextless" (st: ^State_HW, aad: []byte) #no_bounds_check { + ai, l := aad, len(aad) + + switch st.rate { + case _RATE_128L: + for l >= _RATE_128L { + absorb_hw_128l(st, ai) + ai = ai[_RATE_128L:] + l -= _RATE_128L + } + case _RATE_256: + for l >= _RATE_256 { + absorb_hw_256(st, ai) + + ai = ai[_RATE_256:] + l -= _RATE_256 + } + } + + // Pad out the remainder with `0`s till it is rate sized. + if l > 0 { + tmp: [_RATE_MAX]byte // AAD is not confidential. + copy(tmp[:], ai) + switch st.rate { + case _RATE_128L: + absorb_hw_128l(st, tmp[:]) + case _RATE_256: + absorb_hw_256(st, tmp[:]) + } + } +} + +@(private = "file", enable_target_feature = "sse2", require_results) +z_hw_128l :: #force_inline proc "contextless" (st: ^State_HW) -> (x86.__m128i, x86.__m128i) { + z0 := x86._mm_xor_si128( + st.s6, + x86._mm_xor_si128( + st.s1, + x86._mm_and_si128(st.s2, st.s3), + ), + ) + z1 := x86._mm_xor_si128( + st.s2, + x86._mm_xor_si128( + st.s5, + x86._mm_and_si128(st.s6, st.s7), + ), + ) + return z0, z1 +} + +@(private = "file", enable_target_feature = "sse2", require_results) +z_hw_256 :: #force_inline proc "contextless" (st: ^State_HW) -> x86.__m128i { + return x86._mm_xor_si128( + st.s1, + x86._mm_xor_si128( + st.s4, + x86._mm_xor_si128( + st.s5, + x86._mm_and_si128(st.s2, st.s3), + ), + ), + ) +} + +@(private = "file", enable_target_feature = "sse2,aes") +enc_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, ci, xi: []byte) #no_bounds_check { + z0, z1 := z_hw_128l(st) + + t0 := intrinsics.unaligned_load((^x86.__m128i)(&xi[0])) + t1 := intrinsics.unaligned_load((^x86.__m128i)(&xi[16])) + update_hw_128l(st, t0, t1) + + out0 := x86._mm_xor_si128(t0, z0) + out1 := x86._mm_xor_si128(t1, z1) + intrinsics.unaligned_store((^x86.__m128i)(&ci[0]), out0) + intrinsics.unaligned_store((^x86.__m128i)(&ci[16]), out1) +} + +@(private = "file", enable_target_feature = "sse2,aes") +enc_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, ci, xi: []byte) #no_bounds_check { + z := z_hw_256(st) + + xi_ := intrinsics.unaligned_load((^x86.__m128i)(raw_data(xi))) + update_hw_256(st, xi_) + + ci_ := x86._mm_xor_si128(xi_, z) + intrinsics.unaligned_store((^x86.__m128i)(raw_data(ci)), ci_) +} + +@(private, enable_target_feature = "sse2,aes") +enc_hw :: proc "contextless" (st: ^State_HW, dst, src: []byte) #no_bounds_check { + ci, xi, l := dst, src, len(src) + + switch st.rate { + case _RATE_128L: + for l >= _RATE_128L { + enc_hw_128l(st, ci, xi) + ci = ci[_RATE_128L:] + xi = xi[_RATE_128L:] + l -= _RATE_128L + } + case _RATE_256: + for l >= _RATE_256 { + enc_hw_256(st, ci, xi) + ci = ci[_RATE_256:] + xi = xi[_RATE_256:] + l -= _RATE_256 + } + } + + // Pad out the remainder with `0`s till it is rate sized. + if l > 0 { + tmp: [_RATE_MAX]byte // Ciphertext is not confidential. + copy(tmp[:], xi) + switch st.rate { + case _RATE_128L: + enc_hw_128l(st, tmp[:], tmp[:]) + case _RATE_256: + enc_hw_256(st, tmp[:], tmp[:]) + } + copy(ci, tmp[:l]) + } +} + +@(private = "file", enable_target_feature = "sse2,aes") +dec_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, xi, ci: []byte) #no_bounds_check { + z0, z1 := z_hw_128l(st) + + t0 := intrinsics.unaligned_load((^x86.__m128i)(&ci[0])) + t1 := intrinsics.unaligned_load((^x86.__m128i)(&ci[16])) + out0 := x86._mm_xor_si128(t0, z0) + out1 := x86._mm_xor_si128(t1, z1) + + update_hw_128l(st, out0, out1) + intrinsics.unaligned_store((^x86.__m128i)(&xi[0]), out0) + intrinsics.unaligned_store((^x86.__m128i)(&xi[16]), out1) +} + +@(private = "file", enable_target_feature = "sse2,aes") +dec_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, xi, ci: []byte) #no_bounds_check { + z := z_hw_256(st) + + ci_ := intrinsics.unaligned_load((^x86.__m128i)(raw_data(ci))) + xi_ := x86._mm_xor_si128(ci_, z) + + update_hw_256(st, xi_) + intrinsics.unaligned_store((^x86.__m128i)(raw_data(xi)), xi_) +} + +@(private = "file", enable_target_feature = "sse2,aes") +dec_partial_hw_128l :: #force_inline proc "contextless" (st: ^State_HW, xn, cn: []byte) #no_bounds_check { + tmp: [_RATE_128L]byte + defer mem.zero_explicit(&tmp, size_of(tmp)) + + z0, z1 := z_hw_128l(st) + copy(tmp[:], cn) + + t0 := intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) + t1 := intrinsics.unaligned_load((^x86.__m128i)(&tmp[16])) + out0 := x86._mm_xor_si128(t0, z0) + out1 := x86._mm_xor_si128(t1, z1) + + intrinsics.unaligned_store((^x86.__m128i)(&tmp[0]), out0) + intrinsics.unaligned_store((^x86.__m128i)(&tmp[16]), out1) + copy(xn, tmp[:]) + + for off := len(xn); off < _RATE_128L; off += 1 { + tmp[off] = 0 + } + out0 = intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) // v0 + out1 = intrinsics.unaligned_load((^x86.__m128i)(&tmp[16])) // v1 + update_hw_128l(st, out0, out1) +} + +@(private = "file", enable_target_feature = "sse2,aes") +dec_partial_hw_256 :: #force_inline proc "contextless" (st: ^State_HW, xn, cn: []byte) #no_bounds_check { + tmp: [_RATE_256]byte + defer mem.zero_explicit(&tmp, size_of(tmp)) + + z := z_hw_256(st) + copy(tmp[:], cn) + + cn_ := intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) + xn_ := x86._mm_xor_si128(cn_, z) + + intrinsics.unaligned_store((^x86.__m128i)(&tmp[0]), xn_) + copy(xn, tmp[:]) + + for off := len(xn); off < _RATE_256; off += 1 { + tmp[off] = 0 + } + xn_ = intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) + update_hw_256(st, xn_) +} + +@(private, enable_target_feature = "sse2,aes") +dec_hw :: proc "contextless" (st: ^State_HW, dst, src: []byte) #no_bounds_check { + xi, ci, l := dst, src, len(src) + + switch st.rate { + case _RATE_128L: + for l >= _RATE_128L { + dec_hw_128l(st, xi, ci) + xi = xi[_RATE_128L:] + ci = ci[_RATE_128L:] + l -= _RATE_128L + } + case _RATE_256: + for l >= _RATE_256 { + dec_hw_256(st, xi, ci) + xi = xi[_RATE_256:] + ci = ci[_RATE_256:] + l -= _RATE_256 + } + } + + // Process the remainder. + if l > 0 { + switch st.rate { + case _RATE_128L: + dec_partial_hw_128l(st, xi, ci) + case _RATE_256: + dec_partial_hw_256(st, xi, ci) + } + } +} + +@(private, enable_target_feature = "sse2,aes") +finalize_hw :: proc "contextless" (st: ^State_HW, tag: []byte, ad_len, msg_len: int) { + tmp: [16]byte + endian.unchecked_put_u64le(tmp[0:], u64(ad_len) * 8) + endian.unchecked_put_u64le(tmp[8:], u64(msg_len) * 8) + + t := intrinsics.unaligned_load((^x86.__m128i)(&tmp[0])) + + t0, t1: x86.__m128i = ---, --- + switch st.rate { + case _RATE_128L: + t = x86._mm_xor_si128(st.s2, t) + for _ in 0 ..< 7 { + update_hw_128l(st, t, t) + } + + t0 = x86._mm_xor_si128(st.s0, st.s1) + t0 = x86._mm_xor_si128(t0, st.s2) + t0 = x86._mm_xor_si128(t0, st.s3) + + t1 = x86._mm_xor_si128(st.s4, st.s5) + t1 = x86._mm_xor_si128(t1, st.s6) + if len(tag) == TAG_SIZE_256 { + t1 = x86._mm_xor_si128(t1, st.s7) + } + case _RATE_256: + t = x86._mm_xor_si128(st.s3, t) + for _ in 0 ..< 7 { + update_hw_256(st, t) + } + + t0 = x86._mm_xor_si128(st.s0, st.s1) + t0 = x86._mm_xor_si128(t0, st.s2) + + t1 = x86._mm_xor_si128(st.s3, st.s4) + t1 = x86._mm_xor_si128(t1, st.s5) + } + switch len(tag) { + case TAG_SIZE_128: + t0 = x86._mm_xor_si128(t0, t1) + intrinsics.unaligned_store((^x86.__m128i)(&tag[0]), t0) + case TAG_SIZE_256: + intrinsics.unaligned_store((^x86.__m128i)(&tag[0]), t0) + intrinsics.unaligned_store((^x86.__m128i)(&tag[16]), t1) + } +} + +@(private) +reset_state_hw :: proc "contextless" (st: ^State_HW) { + mem.zero_explicit(st, size_of(st^)) +} diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index e95dcb67d..ae43957fb 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -26,6 +26,7 @@ import topological_sort "core:container/topological_sort" import crypto "core:crypto" import aead "core:crypto/aead" +import aegis "core:crypto/aegis" import aes "core:crypto/aes" import blake2b "core:crypto/blake2b" import blake2s "core:crypto/blake2s" @@ -170,6 +171,7 @@ _ :: topological_sort _ :: crypto _ :: crypto_hash _ :: aead +_ :: aegis _ :: aes _ :: blake2b _ :: blake2s diff --git a/tests/benchmark/crypto/benchmark_crypto.odin b/tests/benchmark/crypto/benchmark_crypto.odin index 72e6d0932..dfa491917 100644 --- a/tests/benchmark/crypto/benchmark_crypto.odin +++ b/tests/benchmark/crypto/benchmark_crypto.odin @@ -8,6 +8,7 @@ import "core:strings" import "core:testing" import "core:time" +import "core:crypto/aegis" import "core:crypto/aes" import "core:crypto/chacha20" import "core:crypto/chacha20poly1305" @@ -164,6 +165,43 @@ benchmark_crypto :: proc(t: ^testing.T) { testing.expect(t, err == nil, name) benchmark_print(&str, name, options) } + { + name := "AEGIS-256 64 bytes" + options := &time.Benchmark_Options { + rounds = 1_000, + bytes = 64, + setup = _setup_sized_buf, + bench = _benchmark_aegis_256, + teardown = _teardown_sized_buf, + } + + key := [aegis.KEY_SIZE_256]byte { + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + } + ctx: aegis.Context + aegis.init(&ctx, key[:]) + + context.user_ptr = &ctx + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil, name) + benchmark_print(&str, name, options) + + name = "AEGIS-256 1024 bytes" + options.bytes = 1024 + err = time.benchmark(options, context.allocator) + testing.expect(t, err == nil, name) + benchmark_print(&str, name, options) + + name = "AEGIS-256 65536 bytes" + options.bytes = 65536 + err = time.benchmark(options, context.allocator) + testing.expect(t, err == nil, name) + benchmark_print(&str, name, options) + } { iters :: 10000 @@ -423,6 +461,26 @@ _benchmark_aes256_gcm :: proc( return nil } +_benchmark_aegis_256 :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + buf := options.input + iv: [aegis.IV_SIZE_256]byte + tag: [aegis.TAG_SIZE_128]byte = --- + + ctx := (^aegis.Context)(context.user_ptr) + + for _ in 0 ..= options.rounds { + aegis.seal(ctx, buf, tag[:], iv[:], nil, buf) + } + options.count = options.rounds + options.processed = options.rounds * options.bytes + return nil +} + @(private) benchmark_print :: proc(str: ^strings.Builder, name: string, options: ^time.Benchmark_Options, loc := #caller_location) { fmt.sbprintfln(str, "[%v] %v rounds, %v bytes processed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s\n", diff --git a/tests/core/crypto/test_core_crypto_aead.odin b/tests/core/crypto/test_core_crypto_aead.odin index 90eedc0b2..dfa251413 100644 --- a/tests/core/crypto/test_core_crypto_aead.odin +++ b/tests/core/crypto/test_core_crypto_aead.odin @@ -1,6 +1,8 @@ package test_core_crypto import "base:runtime" +import "core:crypto/aes" +import "core:crypto/aegis" import "core:crypto/aead" import "core:encoding/hex" import "core:testing" @@ -17,6 +19,10 @@ test_aead :: proc(t: ^testing.T) { for impl in supported_chacha_impls() { append(&chacha_impls, impl) } + aegis_impls := make([dynamic]aead.Implementation, context.temp_allocator) + for impl in supported_aegis_impls() { + append(&aegis_impls, impl) + } impls := [aead.Algorithm][dynamic]aead.Implementation{ .Invalid = nil, .AES_GCM_128 = aes_impls, @@ -24,6 +30,10 @@ test_aead :: proc(t: ^testing.T) { .AES_GCM_256 = aes_impls, .CHACHA20POLY1305 = chacha_impls, .XCHACHA20POLY1305 = chacha_impls, + .AEGIS_128L = aegis_impls, + .AEGIS_128L_256 = aegis_impls, + .AEGIS_256 = aegis_impls, + .AEGIS_256_256 = aegis_impls, } test_vectors := []struct{ @@ -224,6 +234,190 @@ test_aead :: proc(t: ^testing.T) { "bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f615c68b13b52e", "c0875924c1c7987947deafd8780acf49", }, + // AEGIS-128L + // https://www.ietf.org/archive/id/draft-irtf-cfrg-aegis-aead-11.txt + { + .AEGIS_128L, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "", + "00000000000000000000000000000000", + "c1c0e58bd913006feba00f4b3cc3594e", + "abe0ece80c24868a226a35d16bdae37a", + }, + { + .AEGIS_128L_256, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "", + "00000000000000000000000000000000", + "c1c0e58bd913006feba00f4b3cc3594e", + "25835bfbb21632176cf03840687cb968cace4617af1bd0f7d064c639a5c79ee4", + }, + { + .AEGIS_128L, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "", + "", + "", + "c2b879a67def9d74e6c14f708bbcc9b4", + }, + { + .AEGIS_128L_256, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "", + "", + "", + "1360dc9db8ae42455f6e5b6a9d488ea4f2184c4e12120249335c4ee84bafe25d", + }, + { + .AEGIS_128L, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "0001020304050607", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "79d94593d8c2119d7e8fd9b8fc77845c5c077a05b2528b6ac54b563aed8efe84", + "cc6f3372f6aa1bb82388d695c3962d9a", + }, + { + .AEGIS_128L_256, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "0001020304050607", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "79d94593d8c2119d7e8fd9b8fc77845c5c077a05b2528b6ac54b563aed8efe84", + "022cb796fe7e0ae1197525ff67e309484cfbab6528ddef89f17d74ef8ecd82b3", + }, + { + .AEGIS_128L, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "0001020304050607", + "000102030405060708090a0b0c0d", + "79d94593d8c2119d7e8fd9b8fc77", + "5c04b3dba849b2701effbe32c7f0fab7", + }, + { + .AEGIS_128L_256, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "0001020304050607", + "000102030405060708090a0b0c0d", + "79d94593d8c2119d7e8fd9b8fc77", + "86f1b80bfb463aba711d15405d094baf4a55a15dbfec81a76f35ed0b9c8b04ac", + }, + { + .AEGIS_128L, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829", + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637", + "b31052ad1cca4e291abcf2df3502e6bdb1bfd6db36798be3607b1f94d34478aa7ede7f7a990fec10", + "7542a745733014f9474417b337399507", + }, + { + .AEGIS_128L_256, + "10010000000000000000000000000000", + "10000200000000000000000000000000", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829", + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637", + "b31052ad1cca4e291abcf2df3502e6bdb1bfd6db36798be3607b1f94d34478aa7ede7f7a990fec10", + "b91e2947a33da8bee89b6794e647baf0fc835ff574aca3fc27c33be0db2aff98", + }, + // AEGIS-256 + // https://www.ietf.org/archive/id/draft-irtf-cfrg-aegis-aead-11.txt + { + .AEGIS_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "", + "00000000000000000000000000000000", + "754fc3d8c973246dcc6d741412a4b236", + "3fe91994768b332ed7f570a19ec5896e", + }, + { + .AEGIS_256_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "", + "00000000000000000000000000000000", + "754fc3d8c973246dcc6d741412a4b236", + "1181a1d18091082bf0266f66297d167d2e68b845f61a3b0527d31fc7b7b89f13", + }, + { + .AEGIS_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "", + "", + "", + "e3def978a0f054afd1e761d7553afba3", + }, + { + .AEGIS_256_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "", + "", + "", + "6a348c930adbd654896e1666aad67de989ea75ebaa2b82fb588977b1ffec864a", + }, + { + .AEGIS_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "0001020304050607", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "f373079ed84b2709faee373584585d60accd191db310ef5d8b11833df9dec711", + "8d86f91ee606e9ff26a01b64ccbdd91d", + }, + { + .AEGIS_256_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "0001020304050607", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "f373079ed84b2709faee373584585d60accd191db310ef5d8b11833df9dec711", + "b7d28d0c3c0ebd409fd22b44160503073a547412da0854bfb9723020dab8da1a", + }, + { + .AEGIS_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "0001020304050607", + "000102030405060708090a0b0c0d", + "f373079ed84b2709faee37358458", + "c60b9c2d33ceb058f96e6dd03c215652", + }, + { + .AEGIS_256_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "0001020304050607", + "000102030405060708090a0b0c0d", + "f373079ed84b2709faee37358458", + "8c1cc703c81281bee3f6d9966e14948b4a175b2efbdc31e61a98b4465235c2d9", + }, + { + .AEGIS_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829", + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637", + "57754a7d09963e7c787583a2e7b859bb24fa1e04d49fd550b2511a358e3bca252a9b1b8b30cc4a67", + "ab8a7d53fd0e98d727accca94925e128", + }, + { + .AEGIS_256_256, + "1001000000000000000000000000000000000000000000000000000000000000", + "1000020000000000000000000000000000000000000000000000000000000000", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526272829", + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637", + "57754a7d09963e7c787583a2e7b859bb24fa1e04d49fd550b2511a358e3bca252a9b1b8b30cc4a67", + "a3aca270c006094d71c20e6910b5161c0826df233d08919a566ec2c05990f734", + }, } for v, _ in test_vectors { algo_name := aead.ALGORITHM_NAMES[v.algo] @@ -337,3 +531,13 @@ test_aead :: proc(t: ^testing.T) { } } } + +supported_aegis_impls :: proc() -> [dynamic]aes.Implementation { + impls := make([dynamic]aes.Implementation, 0, 2, context.temp_allocator) + append(&impls, aes.Implementation.Portable) + if aegis.is_hardware_accelerated() { + append(&impls, aes.Implementation.Hardware) + } + + return impls +} From b220df60b8f6ccb8c5713766e3296393d93eeffe Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Mon, 30 Sep 2024 21:32:25 +0900 Subject: [PATCH 19/81] core:crypto/deoxysii: Initial import --- core/crypto/aead/low_level.odin | 17 + core/crypto/deoxysii/deoxysii.odin | 295 ++++++++++++ core/crypto/deoxysii/deoxysii_impl_ct64.odin | 399 ++++++++++++++++ .../crypto/deoxysii/deoxysii_impl_hw_gen.odin | 21 + .../deoxysii/deoxysii_impl_hw_intel.odin | 434 ++++++++++++++++++ examples/all/all_main.odin | 2 + tests/benchmark/crypto/benchmark_crypto.odin | 58 +++ tests/core/crypto/test_core_crypto_aead.odin | 89 ++++ 8 files changed, 1315 insertions(+) create mode 100644 core/crypto/deoxysii/deoxysii.odin create mode 100644 core/crypto/deoxysii/deoxysii_impl_ct64.odin create mode 100644 core/crypto/deoxysii/deoxysii_impl_hw_gen.odin create mode 100644 core/crypto/deoxysii/deoxysii_impl_hw_intel.odin diff --git a/core/crypto/aead/low_level.odin b/core/crypto/aead/low_level.odin index a7ecef801..e90d07bc6 100644 --- a/core/crypto/aead/low_level.odin +++ b/core/crypto/aead/low_level.odin @@ -4,6 +4,7 @@ import "core:crypto/aegis" import "core:crypto/aes" import "core:crypto/chacha20" import "core:crypto/chacha20poly1305" +import "core:crypto/deoxysii" import "core:reflect" // Implementation is an AEAD implementation. Most callers will not need @@ -30,6 +31,7 @@ Algorithm :: enum { AEGIS_128L_256, // AEGIS-128L (256-bit tag) AEGIS_256, AEGIS_256_256, // AEGIS-256 (256-bit tag) + DEOXYS_II_256, } // ALGORITM_NAMES is the Algorithm to algorithm name string. @@ -44,6 +46,7 @@ ALGORITHM_NAMES := [Algorithm]string { .AEGIS_128L_256 = "AEGIS-128L-256", .AEGIS_256 = "AEGIS-256", .AEGIS_256_256 = "AEGIS-256-256", + .DEOXYS_II_256 = "Deoxys-II-256", } // TAG_SIZES is the Algorithm to tag size in bytes. @@ -58,6 +61,7 @@ TAG_SIZES := [Algorithm]int { .AEGIS_128L_256 = aegis.TAG_SIZE_256, .AEGIS_256 = aegis.TAG_SIZE_128, .AEGIS_256_256 = aegis.TAG_SIZE_256, + .DEOXYS_II_256 = deoxysii.TAG_SIZE, } // KEY_SIZES is the Algorithm to key size in bytes. @@ -72,6 +76,7 @@ KEY_SIZES := [Algorithm]int { .AEGIS_128L_256 = aegis.KEY_SIZE_128L, .AEGIS_256 = aegis.KEY_SIZE_256, .AEGIS_256_256 = aegis.KEY_SIZE_256, + .DEOXYS_II_256 = deoxysii.KEY_SIZE, } // IV_SIZES is the Algorithm to initialization vector size in bytes. @@ -88,6 +93,7 @@ IV_SIZES := [Algorithm]int { .AEGIS_128L_256 = aegis.IV_SIZE_128L, .AEGIS_256 = aegis.IV_SIZE_256, .AEGIS_256_256 = aegis.IV_SIZE_256, + .DEOXYS_II_256 = deoxysii.IV_SIZE, } // Context is a concrete instantiation of a specific AEAD algorithm. @@ -97,6 +103,7 @@ Context :: struct { aes.Context_GCM, chacha20poly1305.Context, aegis.Context, + deoxysii.Context, }, } @@ -112,6 +119,7 @@ _IMPL_IDS := [Algorithm]typeid { .AEGIS_128L_256 = typeid_of(aegis.Context), .AEGIS_256 = typeid_of(aegis.Context), .AEGIS_256_256 = typeid_of(aegis.Context), + .DEOXYS_II_256 = typeid_of(deoxysii.Context), } // init initializes a Context with a specific AEAD Algorithm. @@ -142,6 +150,9 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementat case .AEGIS_128L, .AEGIS_128L_256, .AEGIS_256, .AEGIS_256_256: impl_ := impl != nil ? impl.(aes.Implementation) : aes.DEFAULT_IMPLEMENTATION aegis.init(&ctx._impl.(aegis.Context), key, impl_) + case .DEOXYS_II_256: + impl_ := impl != nil ? impl.(aes.Implementation) : aes.DEFAULT_IMPLEMENTATION + deoxysii.init(&ctx._impl.(deoxysii.Context), key, impl_) case .Invalid: panic("crypto/aead: uninitialized algorithm") case: @@ -167,6 +178,8 @@ seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { chacha20poly1305.seal(&impl, dst, tag, iv, aad, plaintext) case aegis.Context: aegis.seal(&impl, dst, tag, iv, aad, plaintext) + case deoxysii.Context: + deoxysii.seal(&impl, dst, tag, iv, aad, plaintext) case: panic("crypto/aead: uninitialized algorithm") } @@ -191,6 +204,8 @@ open_ctx :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { return chacha20poly1305.open(&impl, dst, iv, aad, ciphertext, tag) case aegis.Context: return aegis.open(&impl, dst, iv, aad, ciphertext, tag) + case deoxysii.Context: + return deoxysii.open(&impl, dst, iv, aad, ciphertext, tag) case: panic("crypto/aead: uninitialized algorithm") } @@ -206,6 +221,8 @@ reset :: proc(ctx: ^Context) { chacha20poly1305.reset(&impl) case aegis.Context: aegis.reset(&impl) + case deoxysii.Context: + deoxysii.reset(&impl) case: // Calling reset repeatedly is fine. } diff --git a/core/crypto/deoxysii/deoxysii.odin b/core/crypto/deoxysii/deoxysii.odin new file mode 100644 index 000000000..2aff1d8b4 --- /dev/null +++ b/core/crypto/deoxysii/deoxysii.odin @@ -0,0 +1,295 @@ +/* +package deoxysii implements the Deoxys-II-256 Authenticated Encryption +with Additional Data algorithm. + +- [[ https://sites.google.com/view/deoxyscipher ]] +- [[ https://thomaspeyrin.github.io/web/assets/docs/papers/Jean-etal-JoC2021.pdf ]] +*/ +package deoxysii + +import "base:intrinsics" +import "core:bytes" +import "core:crypto/aes" +import "core:mem" +import "core:simd" + +// KEY_SIZE is the Deoxys-II-256 key size in bytes. +KEY_SIZE :: 32 +// IV_SIZE iss the Deoxys-II-256 IV size in bytes. +IV_SIZE :: 15 // 120-bits +// TAG_SIZE is the Deoxys-II-256 tag size in bytes. +TAG_SIZE :: 16 + +@(private) +PREFIX_AD_BLOCK :: 0b0010 +@(private) +PREFIX_AD_FINAL :: 0b0110 +@(private) +PREFIX_MSG_BLOCK :: 0b0000 +@(private) +PREFIX_MSG_FINAL :: 0b0100 +@(private) +PREFIX_TAG :: 0b0001 +@(private) +PREFIX_SHIFT :: 4 + +@(private) +BC_ROUNDS :: 16 +@(private) +BLOCK_SIZE :: aes.BLOCK_SIZE + +@(private = "file") +_LFSR2_MASK :: simd.u8x16{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +} +@(private = "file") +_LFSR3_MASK :: simd.u8x16{ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, +} +@(private = "file") +_LFSR_SH1 :: _LFSR2_MASK +@(private = "file") +_LFSR_SH5 :: simd.u8x16{ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, +} +@(private = "file") +_LFSR_SH7 :: simd.u8x16{ + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +} +@(private = "file", rodata) +_RCONS := []byte { + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, + 0x72, +} + +// Context is a keyed Deoxys-II-256 instance. +Context :: struct { + _subkeys: [BC_ROUNDS+1][16]byte, + _impl: aes.Implementation, + _is_initialized: bool, +} + +@(private) +_validate_common_slice_sizes :: proc (ctx: ^Context, tag, iv, aad, text: []byte) { + if len(tag) != TAG_SIZE { + panic("crypto/deoxysii: invalid tag size") + } + + if len(iv) != IV_SIZE { + panic("crypto/deoxysii: invalid IV size") + } + + #assert(size_of(int) == 8 || size_of(int) <= 4) + // For the nonce-misuse resistant mode, the total size of the + // associated data and the total size of the message do not exceed + // `16 * 2^max_l * 2^max_m bytes`, thus 2^128 bytes for all variants + // of Deoxys-II. Moreover, the maximum number of messages that can + // be handled for a same key is 2^max_m, that is 2^64 for all variants + // of Deoxys. +} + +// init initializes a Context with the provided key. +init :: proc(ctx: ^Context, key: []byte, impl := aes.DEFAULT_IMPLEMENTATION) { + if len(key) != KEY_SIZE { + panic("crypto/deoxysii: invalid key size") + } + + ctx._impl = impl + if ctx._impl == .Hardware && !is_hardware_accelerated() { + ctx._impl = .Portable + } + + derive_ks(ctx, key) + + ctx._is_initialized = true +} + +// seal encrypts the plaintext and authenticates the aad and ciphertext, +// with the provided Context and iv, stores the output in dst and tag. +// +// dst and plaintext MUST alias exactly or not at all. +seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { + assert(ctx._is_initialized) + + _validate_common_slice_sizes(ctx, tag, iv, aad, plaintext) + if len(dst) != len(plaintext) { + panic("crypto/deoxysii: invalid destination ciphertext size") + } + if bytes.alias_inexactly(dst, plaintext) { + panic("crypto/deoxysii: dst and plaintext alias inexactly") + } + + switch ctx._impl { + case .Hardware: + e_hw(ctx, dst, tag, iv, aad, plaintext) + case .Portable: + e_ref(ctx, dst, tag, iv, aad, plaintext) + } +} + +// open authenticates the aad and ciphertext, and decrypts the ciphertext, +// with the provided Context, iv, and tag, and stores the output in dst, +// returning true iff the authentication was successful. If authentication +// fails, the destination buffer will be zeroed. +// +// dst and plaintext MUST alias exactly or not at all. +@(require_results) +open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { + assert(ctx._is_initialized) + + _validate_common_slice_sizes(ctx, tag, iv, aad, ciphertext) + if len(dst) != len(ciphertext) { + panic("crypto/deoxysii: invalid destination plaintext size") + } + if bytes.alias_inexactly(dst, ciphertext) { + panic("crypto/deoxysii: dst and ciphertext alias inexactly") + } + + ok: bool + switch ctx._impl { + case .Hardware: + ok = d_hw(ctx, dst, iv, aad, ciphertext, tag) + case .Portable: + ok = d_ref(ctx, dst, iv, aad, ciphertext, tag) + } + if !ok { + mem.zero_explicit(raw_data(dst), len(ciphertext)) + } + + return ok +} + +// reset sanitizes the Context. The Context must be +// re-initialized to be used again. +reset :: proc "contextless" (ctx: ^Context) { + mem.zero_explicit(&ctx._subkeys, len(ctx._subkeys)) + ctx._is_initialized = false +} + +@(private = "file") +derive_ks :: proc "contextless" (ctx: ^Context, key: []byte) { + // Derive the constant component of each subtweakkey. + // + // The key schedule is as thus: + // + // STK_i = TK1_i ^ TK2_i ^ TK3_i ^ RC_i + // + // TK1_i = h(TK1_(i-1)) + // TK2_i = h(LFSR2(TK2_(i-1))) + // TK3_i = h(LFSR3(TK2_(i-1))) + // + // where: + // + // KT = K || T + // W3 = KT[:16] + // W2 = KT[16:32] + // W1 = KT[32:] + // + // TK1_0 = W1 + // TK2_0 = W2 + // TK3_0 = W3 + // + // As `K` is fixed per Context, the XORs of `TK3_0 .. TK3_n`, + // `TK2_0 .. TK2_n` and RC_i can be precomputed in advance like + // thus: + // + // subkey_i = TK3_i ^ TK2_i ^ RC_i + // + // When it is time to actually call Deoxys-BC-384, it is then + // a simple matter of deriving each round subtweakkey via: + // + // TK1_0 = T (Tweak) + // STK_0 = subkey_0 ^ TK1_0 + // STK_i = subkey_i (precomputed) ^ H(TK1_(i-1)) + // + // We opt to use SIMD here and for the subtweakkey deriviation + // as `H()` is typically a single vector instruction. + + tk2 := intrinsics.unaligned_load((^simd.u8x16)(raw_data(key[16:]))) + tk3 := intrinsics.unaligned_load((^simd.u8x16)(raw_data(key))) + + // subkey_0 does not apply LFSR2/3 or H. + intrinsics.unaligned_store( + (^simd.u8x16)(&ctx._subkeys[0]), + simd.bit_xor( + tk2, + simd.bit_xor( + tk3, + rcon(0), + ), + ), + ) + + // Precompute k_1 .. k_16. + for i in 1 ..< BC_ROUNDS+1 { + tk2 = h(lfsr2(tk2)) + tk3 = h(lfsr3(tk3)) + intrinsics.unaligned_store( + (^simd.u8x16)(&ctx._subkeys[i]), + simd.bit_xor( + tk2, + simd.bit_xor( + tk3, + rcon(i), + ), + ), + ) + } +} + +@(private = "file") +lfsr2 :: #force_inline proc "contextless" (tk: simd.u8x16) -> simd.u8x16 { + // LFSR2 is a application of the following LFSR to each byte of input. + // (x7||x6||x5||x4||x3||x2||x1||x0) -> (x6||x5||x4||x3||x2||x1||x0||x7 ^ x5) + return simd.bit_or( + simd.shl(tk, _LFSR_SH1), + simd.bit_and( + simd.bit_xor( + simd.shr(tk, _LFSR_SH7), // x7 + simd.shr(tk, _LFSR_SH5), // x5 + ), + _LFSR2_MASK, + ), + ) +} + +@(private = "file") +lfsr3 :: #force_inline proc "contextless" (tk: simd.u8x16) -> simd.u8x16 { + // LFSR3 is a application of the following LFSR to each byte of input. + // (x7||x6||x5||x4||x3||x2||x1||x0) -> (x0 ^ x6||x7||x6||x5||x4||x3||x2||x1) + return simd.bit_or( + simd.shr(tk, _LFSR_SH1), + simd.bit_and( + simd.bit_xor( + simd.shl(tk, _LFSR_SH7), // x0 + simd.shl(tk, _LFSR_SH1), // x6 + ), + _LFSR3_MASK, + ), + ) +} + +@(private) +h :: #force_inline proc "contextless" (tk: simd.u8x16) -> simd.u8x16 { + return simd.swizzle( + tk, + 0x01, 0x06, 0x0b, 0x0c, 0x05, 0x0a, 0x0f, 0x00, + 0x09, 0x0e, 0x03, 0x04, 0x0d, 0x02, 0x07, 0x08, + ) +} + +@(private = "file") +rcon :: #force_inline proc "contextless" (rd: int) -> simd.u8x16 #no_bounds_check { + rc := _RCONS[rd] + return simd.u8x16{ + 1, 2, 4, 8, + rc, rc, rc, rc, + 0, 0, 0, 0, + 0, 0, 0, 0, + } +} \ No newline at end of file diff --git a/core/crypto/deoxysii/deoxysii_impl_ct64.odin b/core/crypto/deoxysii/deoxysii_impl_ct64.odin new file mode 100644 index 000000000..c4d0edb03 --- /dev/null +++ b/core/crypto/deoxysii/deoxysii_impl_ct64.odin @@ -0,0 +1,399 @@ +package deoxysii + +import "base:intrinsics" +import "core:crypto" +import aes "core:crypto/_aes/ct64" +import "core:encoding/endian" +import "core:mem" +import "core:simd" + +// This uses the bitlsiced 64-bit general purpose register SWAR AES +// round function. The encryption pass skips orthogonalizing the +// AES round function input as it is aways going to be the leading 0 +// padded IV, and doing a 64-byte copy is faster. + +@(private = "file") +TWEAK_SIZE :: 16 + +@(private = "file") +State_SW :: struct { + ctx: ^Context, + q_stk, q_b: [8]u64, +} + +@(private = "file") +auth_tweak :: #force_inline proc "contextless" ( + dst: ^[TWEAK_SIZE]byte, + prefix: byte, + block_nr: int, +) { + endian.unchecked_put_u64be(dst[8:], u64(block_nr)) + endian.unchecked_put_u64le(dst[0:], u64(prefix) << PREFIX_SHIFT) // dst[0] = prefix << PREFIX_SHIFT +} + +@(private = "file") +enc_tweak :: #force_inline proc "contextless" ( + dst: ^[TWEAK_SIZE]byte, + tag: ^[TAG_SIZE]byte, + block_nr: int, +) { + tmp: [8]byte + endian.unchecked_put_u64be(tmp[:], u64(block_nr)) + + copy(dst[:], tag[:]) + dst[0] |= 0x80 + for i in 0 ..< 8 { + dst[i+8] ~= tmp[i] + } +} + +@(private = "file") +enc_plaintext :: #force_inline proc "contextless" ( + dst: ^[8]u64, + iv: []byte, +) { + tmp: [BLOCK_SIZE]byte = --- + tmp[0] = 0 + copy(tmp[1:], iv[:]) + + q_0, q_1 := aes.load_interleaved(tmp[:]) + for i in 0 ..< 4 { + dst[i], dst[i+4] = q_0, q_1 + } + aes.orthogonalize(dst) +} + +@(private = "file") +bc_x4 :: proc "contextless" ( + ctx: ^Context, + dst: []byte, + tweaks: ^[4][TWEAK_SIZE]byte, + q_stk: ^[8]u64, + q_b: ^[8]u64, // Orthogonalized + n: int, +) { + tk1s: [4]simd.u8x16 + for j in 0 ..< n { + tk1s[j] = intrinsics.unaligned_load((^simd.u8x16)(&tweaks[j])) + } + + // Deoxys-BC-384 + for i in 0 ..= BC_ROUNDS { + // Derive the round's subtweakkey + sk := intrinsics.unaligned_load((^simd.u8x16)(&ctx._subkeys[i])) + for j in 0 ..< n { + if i != 0 { + tk1s[j] = h(tk1s[j]) + } + intrinsics.unaligned_store( + (^simd.u8x16)(raw_data(dst)), + simd.bit_xor(sk, tk1s[j]), + ) + q_stk[j], q_stk[j+4] = aes.load_interleaved(dst[:]) + } + aes.orthogonalize(q_stk) + + if i != 0 { + aes.sub_bytes(q_b) + aes.shift_rows(q_b) + aes.mix_columns(q_b) + } + aes.add_round_key(q_b, q_stk[:]) + } + + aes.orthogonalize(q_b) + for i in 0 ..< n { + aes.store_interleaved(dst[i*BLOCK_SIZE:], q_b[i], q_b[i+4]) + } +} + +@(private = "file", require_results) +bc_absorb :: proc "contextless" ( + st: ^State_SW, + dst: []byte, + src: []byte, + tweak_prefix: byte, + stk_block_nr: int, +) -> int { + tweaks: [4][TWEAK_SIZE]byte = --- + tmp: [BLOCK_SIZE*4]byte = --- + + src, stk_block_nr := src, stk_block_nr + dst_ := intrinsics.unaligned_load((^simd.u8x16)(raw_data(dst))) + + nr_blocks := len(src) / BLOCK_SIZE + for nr_blocks > 0 { + // Derive the tweak(s), orthogonalize the plaintext + n := min(nr_blocks, 4) + for i in 0 ..< n { + auth_tweak(&tweaks[i], tweak_prefix, stk_block_nr + i) + st.q_b[i], st.q_b[i + 4] = aes.load_interleaved(src) + src = src[BLOCK_SIZE:] + } + aes.orthogonalize(&st.q_b) + + // Deoxys-BC-384 + bc_x4(st.ctx, tmp[:], &tweaks, &st.q_stk, &st.q_b, n) + + // XOR in the existing Auth/tag + for i in 0 ..< n { + dst_ = simd.bit_xor( + dst_, + intrinsics.unaligned_load((^simd.u8x16)(raw_data(tmp[i*BLOCK_SIZE:]))), + ) + } + + stk_block_nr += n + nr_blocks -= n + } + + intrinsics.unaligned_store((^simd.u8x16)(raw_data(dst)), dst_) + + mem.zero_explicit(&tweaks, size_of(tweaks)) + mem.zero_explicit(&tmp, size_of(tmp)) + + return stk_block_nr +} + +@(private = "file") +bc_final :: proc "contextless" ( + st: ^State_SW, + dst: []byte, + iv: []byte, +) { + tweaks: [4][TWEAK_SIZE]byte = --- + + tweaks[0][0] = PREFIX_TAG << PREFIX_SHIFT + copy(tweaks[0][1:], iv) + + st.q_b[0], st.q_b[4] = aes.load_interleaved(dst) + aes.orthogonalize(&st.q_b) + + bc_x4(st.ctx, dst, &tweaks, &st.q_stk, &st.q_b, 1) +} + +@(private = "file", require_results) +bc_encrypt :: proc "contextless" ( + st: ^State_SW, + dst: []byte, + src: []byte, + q_n: ^[8]u64, // Orthogonalized + tweak_tag: ^[TAG_SIZE]byte, + stk_block_nr: int, +) -> int { + tweaks: [4][TWEAK_SIZE]byte = --- + tmp: [BLOCK_SIZE*4]byte = --- + + dst, src, stk_block_nr := dst, src, stk_block_nr + + nr_blocks := len(src) / BLOCK_SIZE + for nr_blocks > 0 { + // Derive the tweak(s) + n := min(nr_blocks, 4) + for i in 0 ..< n { + enc_tweak(&tweaks[i], tweak_tag, stk_block_nr + i) + } + st.q_b = q_n^ // The plaintext is always `0^8 || N` + + // Deoxys-BC-384 + bc_x4(st.ctx, tmp[:], &tweaks, &st.q_stk, &st.q_b, n) + + // XOR the ciphertext + for i in 0 ..< n { + intrinsics.unaligned_store( + (^simd.u8x16)(raw_data(dst[i*BLOCK_SIZE:])), + simd.bit_xor( + intrinsics.unaligned_load((^simd.u8x16)(raw_data(src[i*BLOCK_SIZE:]))), + intrinsics.unaligned_load((^simd.u8x16)(raw_data(tmp[i*BLOCK_SIZE:]))), + ), + ) + } + + dst, src = dst[n*BLOCK_SIZE:], src[n*BLOCK_SIZE:] + stk_block_nr += n + nr_blocks -= n + } + + mem.zero_explicit(&tweaks, size_of(tweaks)) + mem.zero_explicit(&tmp, size_of(tmp)) + + return stk_block_nr +} + +@(private) +e_ref :: proc "contextless" (ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) #no_bounds_check { + st: State_SW = --- + st.ctx = ctx + + // Algorithm 3 + // + // Associated data + // A_1 || ... || A_la || A_∗ <- A where each |A_i| = n and |A_∗| < n + // Auth <- 0^n + // for i = 0 to la − 1 do + // Auth <- Auth ^ EK(0010 || i, A_i+1) + // end + // if A_∗ != nil then + // Auth <- Auth ^ EK(0110 || la, pad10∗(A_∗)) + // end + auth: [TAG_SIZE]byte + aad := aad + n := bc_absorb(&st, auth[:], aad, PREFIX_AD_BLOCK, 0) + aad = aad[n*BLOCK_SIZE:] + if l := len(aad); l > 0 { + a_star: [BLOCK_SIZE]byte + + copy(a_star[:], aad) + a_star[l] = 0x80 + + _ = bc_absorb(&st, auth[:], a_star[:], PREFIX_AD_FINAL, n) + } + + // Message authentication and tag generation + // M_1 || ... || M_l || M_∗ <- M where each |M_j| = n and |M_∗| < n + // tag <- Auth + // for j = 0 to l − 1 do + // tag <- tag ^ EK(0000 || j, M_j+1) + // end + // if M_∗ != nil then + // tag <- tag ^ EK(0100 || l, pad10∗(M_∗)) + // end + // tag <- EK(0001 || 0^4 || N, tag) + m := plaintext + n = bc_absorb(&st, auth[:], m, PREFIX_MSG_BLOCK, 0) + m = m[n*BLOCK_SIZE:] + if l := len(m); l > 0 { + m_star: [BLOCK_SIZE]byte + + copy(m_star[:], m) + m_star[l] = 0x80 + + _ = bc_absorb(&st, auth[:], m_star[:], PREFIX_MSG_FINAL, n) + } + bc_final(&st, auth[:], iv) + + // Message encryption + // for j = 0 to l − 1 do + // C_j <- M_j ^ EK(1 || tag ^ j, 0^8 || N) + // end + // if M_∗ != nil then + // C_∗ <- M_* ^ EK(1 || tag ^ l, 0^8 || N) + // end + // + // return (C_1 || ... || C_l || C_∗, tag) + q_iv: [8]u64 = --- + enc_plaintext(&q_iv, iv) + + m = plaintext + n = bc_encrypt(&st, dst, m, &q_iv, &auth, 0) + m = m[n*BLOCK_SIZE:] + if l := len(m); l > 0 { + m_star: [BLOCK_SIZE]byte + + copy(m_star[:], m) + _ = bc_encrypt(&st, m_star[:], m_star[:], &q_iv, &auth, n) + + copy(dst[n*BLOCK_SIZE:], m_star[:]) + + mem.zero_explicit(&m_star, size_of(m_star)) + } + + copy(tag, auth[:]) + + mem.zero_explicit(&st.q_stk, size_of(st.q_stk)) + mem.zero_explicit(&st.q_b, size_of(st.q_b)) +} + +@(private, require_results) +d_ref :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { + st: State_SW = --- + st.ctx = ctx + + // Algorithm 4 + // + // Message decryption + // C_1 || ... || C_l || C_∗ <- C where each |C_j| = n and |C_∗| < n + // for j = 0 to l − 1 do + // M_j <- C_j ^ EK(1 || tag ^ j, 0^8 || N) + // end + // if C_∗ != nil then + // M_∗ <- C_∗ ^ EK(1 || tag ^ l, 0^8 || N) + // end + q_iv: [8]u64 = --- + enc_plaintext(&q_iv, iv) + + auth: [TAG_SIZE]byte + copy(auth[:], tag) + + m := ciphertext + n := bc_encrypt(&st, dst, m, &q_iv, &auth, 0) + m = m[n*BLOCK_SIZE:] + if l := len(m); l > 0 { + m_star: [BLOCK_SIZE]byte + + copy(m_star[:], m) + _ = bc_encrypt(&st, m_star[:], m_star[:], &q_iv, &auth, n) + + copy(dst[n*BLOCK_SIZE:], m_star[:]) + + mem.zero_explicit(&m_star, size_of(m_star)) + } + + // Associated data + // A_1 || ... || Al_a || A_∗ <- A where each |Ai_| = n and |A_∗| < n + // Auth <- 0 + // for i = 0 to la − 1 do + // Auth <- Auth ^ EK(0010 || i, A_i+1) + // end + // if A∗ != nil then + // Auth <- Auth ^ EK(0110| | l_a, pad10∗(A_∗)) + // end + auth = 0 + aad := aad + n = bc_absorb(&st, auth[:], aad, PREFIX_AD_BLOCK, 0) + aad = aad[n*BLOCK_SIZE:] + if l := len(aad); l > 0 { + a_star: [BLOCK_SIZE]byte + + copy(a_star[:], aad) + a_star[l] = 0x80 + + _ = bc_absorb(&st, auth[:], a_star[:], PREFIX_AD_FINAL, n) + } + + // Message authentication and tag generation + // M_1 || ... || M_l || M_∗ <- M where each |M_j| = n and |M_∗| < n + // tag0 <- Auth + // for j = 0 to l − 1 do + // tag0 <- tag0 ^ EK(0000 || j, M_j+1) + // end + // if M_∗ != nil then + // tag0 <- tag0 ^ EK(0100 || l, pad10∗(M_∗)) + // end + // tag0 <- EK(0001 || 0^4 || N, tag0) + m = dst[:len(ciphertext)] + n = bc_absorb(&st, auth[:], m, PREFIX_MSG_BLOCK, 0) + m = m[n*BLOCK_SIZE:] + if l := len(m); l > 0 { + m_star: [BLOCK_SIZE]byte + + copy(m_star[:], m) + m_star[l] = 0x80 + + _ = bc_absorb(&st, auth[:], m_star[:], PREFIX_MSG_FINAL, n) + + mem.zero_explicit(&m_star, size_of(m_star)) + } + bc_final(&st, auth[:], iv) + + // Tag verification + // if tag0 = tag then return (M_1 || ... || M_l || M_∗) + // else return false + ok := crypto.compare_constant_time(auth[:], tag) == 1 + + mem.zero_explicit(&auth, size_of(auth)) + mem.zero_explicit(&st.q_stk, size_of(st.q_stk)) + mem.zero_explicit(&st.q_b, size_of(st.q_b)) + + return ok +} diff --git a/core/crypto/deoxysii/deoxysii_impl_hw_gen.odin b/core/crypto/deoxysii/deoxysii_impl_hw_gen.odin new file mode 100644 index 000000000..b0705ca62 --- /dev/null +++ b/core/crypto/deoxysii/deoxysii_impl_hw_gen.odin @@ -0,0 +1,21 @@ +#+build !amd64 +package deoxysii + +@(private = "file") +ERR_HW_NOT_SUPPORTED :: "crypto/deoxysii: hardware implementation unsupported" + +// is_hardware_accelerated returns true iff hardware accelerated Deoxys-II +// is supported. +is_hardware_accelerated :: proc "contextless" () -> bool { + return false +} + +@(private) +e_hw :: proc "contextless" (ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) #no_bounds_check { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} + +@(private, require_results) +d_hw :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} diff --git a/core/crypto/deoxysii/deoxysii_impl_hw_intel.odin b/core/crypto/deoxysii/deoxysii_impl_hw_intel.odin new file mode 100644 index 000000000..d268009a2 --- /dev/null +++ b/core/crypto/deoxysii/deoxysii_impl_hw_intel.odin @@ -0,0 +1,434 @@ +#+build amd64 +package deoxysii + +import "base:intrinsics" +import "core:crypto" +import "core:crypto/aes" +import "core:mem" +import "core:simd" +import "core:simd/x86" + +// This processes a maximum of 4 blocks at a time, as that is suitable +// for most current hardware that doesn't say "Xeon". + +@(private = "file") +_BIT_ENC :: x86.__m128i{0x80, 0} +@(private = "file") +_PREFIX_AD_BLOCK :: x86.__m128i{PREFIX_AD_BLOCK << PREFIX_SHIFT, 0} +@(private = "file") +_PREFIX_AD_FINAL :: x86.__m128i{PREFIX_AD_FINAL << PREFIX_SHIFT, 0} +@(private = "file") +_PREFIX_MSG_BLOCK :: x86.__m128i{PREFIX_MSG_BLOCK << PREFIX_SHIFT, 0} +@(private = "file") +_PREFIX_MSG_FINAL :: x86.__m128i{PREFIX_MSG_FINAL << PREFIX_SHIFT, 0} + +// is_hardware_accelerated returns true iff hardware accelerated Deoxys-II +// is supported. +is_hardware_accelerated :: proc "contextless" () -> bool { + return aes.is_hardware_accelerated() +} + +@(private = "file", enable_target_feature = "sse4.1", require_results) +auth_tweak :: #force_inline proc "contextless" ( + prefix: x86.__m128i, + block_nr: int, +) -> x86.__m128i { + return x86._mm_insert_epi64(prefix, i64(intrinsics.byte_swap(u64(block_nr))), 1) +} + +@(private = "file", enable_target_feature = "sse2", require_results) +enc_tweak :: #force_inline proc "contextless" ( + tag: x86.__m128i, + block_nr: int, +) -> x86.__m128i { + return x86._mm_xor_si128( + x86._mm_or_si128(tag, _BIT_ENC), + x86.__m128i{0, i64(intrinsics.byte_swap(u64(block_nr)))}, + ) +} + +@(private = "file", enable_target_feature = "ssse3", require_results) +h_ :: #force_inline proc "contextless" (tk1: x86.__m128i) -> x86.__m128i { + return transmute(x86.__m128i)h(transmute(simd.u8x16)tk1) +} + +@(private = "file", enable_target_feature = "sse2,ssse3,aes", require_results) +bc_x4 :: #force_inline proc "contextless" ( + ctx: ^Context, + s_0, s_1, s_2, s_3: x86.__m128i, + tweak_0, tweak_1, tweak_2, tweak_3: x86.__m128i, +) -> (x86.__m128i, x86.__m128i, x86.__m128i, x86.__m128i) #no_bounds_check { + s_0, s_1, s_2, s_3 := s_0, s_1, s_2, s_3 + tk1_0, tk1_1, tk1_2, tk1_3 := tweak_0, tweak_1, tweak_2, tweak_3 + + sk := intrinsics.unaligned_load((^x86.__m128i)(&ctx._subkeys[0])) + stk_0 := x86._mm_xor_si128(tk1_0, sk) + stk_1 := x86._mm_xor_si128(tk1_1, sk) + stk_2 := x86._mm_xor_si128(tk1_2, sk) + stk_3 := x86._mm_xor_si128(tk1_3, sk) + + s_0 = x86._mm_xor_si128(s_0, stk_0) + s_1 = x86._mm_xor_si128(s_1, stk_1) + s_2 = x86._mm_xor_si128(s_2, stk_2) + s_3 = x86._mm_xor_si128(s_3, stk_3) + + for i in 1 ..= BC_ROUNDS { + sk = intrinsics.unaligned_load((^x86.__m128i)(&ctx._subkeys[i])) + + tk1_0 = h_(tk1_0) + tk1_1 = h_(tk1_1) + tk1_2 = h_(tk1_2) + tk1_3 = h_(tk1_3) + + stk_0 = x86._mm_xor_si128(tk1_0, sk) + stk_1 = x86._mm_xor_si128(tk1_1, sk) + stk_2 = x86._mm_xor_si128(tk1_2, sk) + stk_3 = x86._mm_xor_si128(tk1_3, sk) + + s_0 = x86._mm_aesenc_si128(s_0, stk_0) + s_1 = x86._mm_aesenc_si128(s_1, stk_1) + s_2 = x86._mm_aesenc_si128(s_2, stk_2) + s_3 = x86._mm_aesenc_si128(s_3, stk_3) + } + + return s_0, s_1, s_2, s_3 +} + +@(private = "file", enable_target_feature = "sse2,ssse3,aes", require_results) +bc_x1 :: #force_inline proc "contextless" ( + ctx: ^Context, + s: x86.__m128i, + tweak: x86.__m128i, +) -> x86.__m128i #no_bounds_check { + s, tk1 := s, tweak + + sk := intrinsics.unaligned_load((^x86.__m128i)(&ctx._subkeys[0])) + stk := x86._mm_xor_si128(tk1, sk) + + s = x86._mm_xor_si128(s, stk) + + for i in 1 ..= BC_ROUNDS { + sk = intrinsics.unaligned_load((^x86.__m128i)(&ctx._subkeys[i])) + + tk1 = h_(tk1) + + stk = x86._mm_xor_si128(tk1, sk) + + s = x86._mm_aesenc_si128(s, stk) + } + + return s +} + +@(private = "file", enable_target_feature = "sse2,ssse3,sse4.1,aes", require_results) +bc_absorb :: proc "contextless" ( + ctx: ^Context, + tag: x86.__m128i, + src: []byte, + tweak_prefix: x86.__m128i, + stk_block_nr: int, +) -> (x86.__m128i, int) #no_bounds_check { + src, stk_block_nr, tag := src, stk_block_nr, tag + + nr_blocks := len(src) / BLOCK_SIZE + for nr_blocks >= 4 { + d_0, d_1, d_2, d_3 := bc_x4( + ctx, + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))), + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[BLOCK_SIZE:]))), + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[2*BLOCK_SIZE:]))), + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[3*BLOCK_SIZE:]))), + auth_tweak(tweak_prefix, stk_block_nr), + auth_tweak(tweak_prefix, stk_block_nr + 1), + auth_tweak(tweak_prefix, stk_block_nr + 2), + auth_tweak(tweak_prefix, stk_block_nr + 3), + ) + + tag = x86._mm_xor_si128(tag, d_0) + tag = x86._mm_xor_si128(tag, d_1) + tag = x86._mm_xor_si128(tag, d_2) + tag = x86._mm_xor_si128(tag, d_3) + + src = src[4*BLOCK_SIZE:] + stk_block_nr += 4 + nr_blocks -= 4 + } + + for nr_blocks > 0 { + d := bc_x1( + ctx, + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))), + auth_tweak(tweak_prefix, stk_block_nr), + ) + + tag = x86._mm_xor_si128(tag, d) + + src = src[BLOCK_SIZE:] + stk_block_nr += 1 + nr_blocks -= 1 + } + + return tag, stk_block_nr +} + +@(private = "file", enable_target_feature = "sse2,ssse3,aes", require_results) +bc_final :: proc "contextless" ( + ctx: ^Context, + tag: x86.__m128i, + iv: []byte, +) -> x86.__m128i { + tmp: [BLOCK_SIZE]byte + + tmp[0] = PREFIX_TAG << PREFIX_SHIFT + copy(tmp[1:], iv) + + tweak := intrinsics.unaligned_load((^x86.__m128i)(&tmp)) + + return bc_x1(ctx, tag, tweak) +} + +@(private = "file", enable_target_feature = "sse2,ssse3,aes", require_results) +bc_encrypt :: proc "contextless" ( + ctx: ^Context, + dst: []byte, + src: []byte, + iv: x86.__m128i, + tweak_tag: x86.__m128i, + stk_block_nr: int, +) -> int { + dst, src, stk_block_nr := dst, src, stk_block_nr + + nr_blocks := len(src) / BLOCK_SIZE + for nr_blocks >= 4 { + d_0, d_1, d_2, d_3 := bc_x4( + ctx, + iv, iv, iv, iv, + enc_tweak(tweak_tag, stk_block_nr), + enc_tweak(tweak_tag, stk_block_nr + 1), + enc_tweak(tweak_tag, stk_block_nr + 2), + enc_tweak(tweak_tag, stk_block_nr + 3), + ) + + intrinsics.unaligned_store( + (^x86.__m128i)(raw_data(dst)), + x86._mm_xor_si128( + d_0, + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))), + ), + ) + intrinsics.unaligned_store( + (^x86.__m128i)(raw_data(dst[BLOCK_SIZE:])), + x86._mm_xor_si128( + d_1, + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[BLOCK_SIZE:]))), + ), + ) + intrinsics.unaligned_store( + (^x86.__m128i)(raw_data(dst[2*BLOCK_SIZE:])), + x86._mm_xor_si128( + d_2, + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[2*BLOCK_SIZE:]))), + ), + ) + intrinsics.unaligned_store( + (^x86.__m128i)(raw_data(dst[3*BLOCK_SIZE:])), + x86._mm_xor_si128( + d_3, + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src[3*BLOCK_SIZE:]))), + ), + ) + + src, dst = src[4*BLOCK_SIZE:], dst[4*BLOCK_SIZE:] + stk_block_nr += 4 + nr_blocks -= 4 + } + + for nr_blocks > 0 { + d := bc_x1( + ctx, + iv, + enc_tweak(tweak_tag, stk_block_nr), + ) + + intrinsics.unaligned_store( + (^x86.__m128i)(raw_data(dst)), + x86._mm_xor_si128( + d, + intrinsics.unaligned_load((^x86.__m128i)(raw_data(src))), + ), + ) + + src, dst = src[BLOCK_SIZE:], dst[BLOCK_SIZE:] + stk_block_nr += 1 + nr_blocks -= 1 + } + + return stk_block_nr +} + +@(private) +e_hw :: proc "contextless" (ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) #no_bounds_check { + tmp: [BLOCK_SIZE]byte + copy(tmp[1:], iv) + iv_ := intrinsics.unaligned_load((^x86.__m128i)(raw_data(&tmp))) + + // Algorithm 3 + // + // Associated data + // A_1 || ... || A_la || A_∗ <- A where each |A_i| = n and |A_∗| < n + // Auth <- 0^n + // for i = 0 to la − 1 do + // Auth <- Auth ^ EK(0010 || i, A_i+1) + // end + // if A_∗ != nil then + // Auth <- Auth ^ EK(0110 || la, pad10∗(A_∗)) + // end + auth: x86.__m128i + n: int + + aad := aad + auth, n = bc_absorb(ctx, auth, aad, _PREFIX_AD_BLOCK, 0) + aad = aad[n*BLOCK_SIZE:] + if l := len(aad); l > 0 { + a_star: [BLOCK_SIZE]byte + + copy(a_star[:], aad) + a_star[l] = 0x80 + + auth, _ = bc_absorb(ctx, auth, a_star[:], _PREFIX_AD_FINAL, n) + } + + // Message authentication and tag generation + // M_1 || ... || M_l || M_∗ <- M where each |M_j| = n and |M_∗| < n + // tag <- Auth + // for j = 0 to l − 1 do + // tag <- tag ^ EK(0000 || j, M_j+1) + // end + // if M_∗ != nil then + // tag <- tag ^ EK(0100 || l, pad10∗(M_∗)) + // end + // tag <- EK(0001 || 0^4 ||N, tag) + m := plaintext + auth, n = bc_absorb(ctx, auth, m, _PREFIX_MSG_BLOCK, 0) + m = m[n*BLOCK_SIZE:] + if l := len(m); l > 0 { + m_star: [BLOCK_SIZE]byte + + copy(m_star[:], m) + m_star[l] = 0x80 + + auth, _ = bc_absorb(ctx, auth, m_star[:], _PREFIX_MSG_FINAL, n) + } + auth = bc_final(ctx, auth, iv) + + // Message encryption + // for j = 0 to l − 1 do + // C_j <- M_j ^ EK(1 || tag ^ j, 0^8 || N) + // end + // if M_∗ != nil then + // C_∗ <- M_* ^ EK(1 || tag ^ l, 0^8 || N) + // end + // + // return (C_1 || ... || C_l || C_∗, tag) + m = plaintext + n = bc_encrypt(ctx, dst, m, iv_, auth, 0) + m = m[n*BLOCK_SIZE:] + if l := len(m); l > 0 { + m_star: [BLOCK_SIZE]byte + + copy(m_star[:], m) + _ = bc_encrypt(ctx, m_star[:], m_star[:], iv_, auth, n) + + copy(dst[n*BLOCK_SIZE:], m_star[:]) + } + + intrinsics.unaligned_store((^x86.__m128i)(raw_data(tag)), auth) +} + +@(private, require_results) +d_hw :: proc "contextless" (ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { + tmp: [BLOCK_SIZE]byte + copy(tmp[1:], iv) + iv_ := intrinsics.unaligned_load((^x86.__m128i)(raw_data(&tmp))) + + // Algorithm 4 + // + // Message decryption + // C_1 || ... || C_l || C_∗ <- C where each |C_j| = n and |C_∗| < n + // for j = 0 to l − 1 do + // M_j <- C_j ^ EK(1 || tag ^ j, 0^8 || N) + // end + // if C_∗ != nil then + // M_∗ <- C_∗ ^ EK(1 || tag ^ l, 0^8 || N) + // end + auth := intrinsics.unaligned_load((^x86.__m128i)(raw_data(tag))) + + m := ciphertext + n := bc_encrypt(ctx, dst, m, iv_, auth, 0) + m = m[n*BLOCK_SIZE:] + if l := len(m); l > 0 { + m_star: [BLOCK_SIZE]byte + + copy(m_star[:], m) + _ = bc_encrypt(ctx, m_star[:], m_star[:], iv_, auth, n) + + copy(dst[n*BLOCK_SIZE:], m_star[:]) + + mem.zero_explicit(&m_star, size_of(m_star)) + } + + // Associated data + // A_1 || ... || Al_a || A_∗ <- A where each |Ai_| = n and |A_∗| < n + // Auth <- 0 + // for i = 0 to la − 1 do + // Auth <- Auth ^ EK(0010 || i, A_i+1) + // end + // if A∗ != nil then + // Auth <- Auth ^ EK(0110| | l_a, pad10∗(A_∗)) + // end + auth = x86.__m128i{0, 0} + aad := aad + auth, n = bc_absorb(ctx, auth, aad, _PREFIX_AD_BLOCK, 0) + aad = aad[BLOCK_SIZE*n:] + if l := len(aad); l > 0 { + a_star: [BLOCK_SIZE]byte + + copy(a_star[:], aad) + a_star[l] = 0x80 + + auth, _ = bc_absorb(ctx, auth, a_star[:], _PREFIX_AD_FINAL, n) + } + + // Message authentication and tag generation + // M_1 || ... || M_l || M_∗ <- M where each |M_j| = n and |M_∗| < n + // tag0 <- Auth + // for j = 0 to l − 1 do + // tag0 <- tag0 ^ EK(0000 || j, M_j+1) + // end + // if M_∗ != nil then + // tag0 <- tag0 ^ EK(0100 || l, pad10∗(M_∗)) + // end + // tag0 <- EK(0001 || 0^4 || N, tag0) + m = dst[:len(ciphertext)] + auth, n = bc_absorb(ctx, auth, m, _PREFIX_MSG_BLOCK, 0) + m = m[n*BLOCK_SIZE:] + if l := len(m); l > 0 { + m_star: [BLOCK_SIZE]byte + + copy(m_star[:], m) + m_star[l] = 0x80 + + auth, _ = bc_absorb(ctx, auth, m_star[:], _PREFIX_MSG_FINAL, n) + } + auth = bc_final(ctx, auth, iv) + + // Tag verification + // if tag0 = tag then return (M_1 || ... || M_l || M_∗) + // else return false + intrinsics.unaligned_store((^x86.__m128i)(raw_data(&tmp)), auth) + ok := crypto.compare_constant_time(tmp[:], tag) == 1 + + mem.zero_explicit(&tmp, size_of(tmp)) + + return ok +} diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index ae43957fb..0e7648f96 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -33,6 +33,7 @@ import blake2s "core:crypto/blake2s" import chacha20 "core:crypto/chacha20" import chacha20poly1305 "core:crypto/chacha20poly1305" import crypto_hash "core:crypto/hash" +import deoxysii "core:crypto/deoxysii" import ed25519 "core:crypto/ed25519" import hkdf "core:crypto/hkdf" import hmac "core:crypto/hmac" @@ -177,6 +178,7 @@ _ :: blake2b _ :: blake2s _ :: chacha20 _ :: chacha20poly1305 +_ :: deoxysii _ :: ed25519 _ :: hmac _ :: hkdf diff --git a/tests/benchmark/crypto/benchmark_crypto.odin b/tests/benchmark/crypto/benchmark_crypto.odin index dfa491917..9e8824c03 100644 --- a/tests/benchmark/crypto/benchmark_crypto.odin +++ b/tests/benchmark/crypto/benchmark_crypto.odin @@ -12,6 +12,7 @@ import "core:crypto/aegis" import "core:crypto/aes" import "core:crypto/chacha20" import "core:crypto/chacha20poly1305" +import "core:crypto/deoxysii" import "core:crypto/ed25519" import "core:crypto/poly1305" import "core:crypto/x25519" @@ -202,6 +203,43 @@ benchmark_crypto :: proc(t: ^testing.T) { testing.expect(t, err == nil, name) benchmark_print(&str, name, options) } + { + name := "Deoxys-II-256 64 bytes" + options := &time.Benchmark_Options { + rounds = 1_000, + bytes = 64, + setup = _setup_sized_buf, + bench = _benchmark_deoxysii_256, + teardown = _teardown_sized_buf, + } + + key := [aegis.KEY_SIZE_256]byte { + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + } + ctx: deoxysii.Context + deoxysii.init(&ctx, key[:]) + + context.user_ptr = &ctx + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil, name) + benchmark_print(&str, name, options) + + name = "Deoxys-II-256 1024 bytes" + options.bytes = 1024 + err = time.benchmark(options, context.allocator) + testing.expect(t, err == nil, name) + benchmark_print(&str, name, options) + + name = "Deoxys-II-256 65536 bytes" + options.bytes = 65536 + err = time.benchmark(options, context.allocator) + testing.expect(t, err == nil, name) + benchmark_print(&str, name, options) + } { iters :: 10000 @@ -481,6 +519,26 @@ _benchmark_aegis_256 :: proc( return nil } +_benchmark_deoxysii_256 :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + buf := options.input + iv: [deoxysii.IV_SIZE]byte + tag: [deoxysii.TAG_SIZE]byte = --- + + ctx := (^deoxysii.Context)(context.user_ptr) + + for _ in 0 ..= options.rounds { + deoxysii.seal(ctx, buf, tag[:], iv[:], nil, buf) + } + options.count = options.rounds + options.processed = options.rounds * options.bytes + return nil +} + @(private) benchmark_print :: proc(str: ^strings.Builder, name: string, options: ^time.Benchmark_Options, loc := #caller_location) { fmt.sbprintfln(str, "[%v] %v rounds, %v bytes processed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s\n", diff --git a/tests/core/crypto/test_core_crypto_aead.odin b/tests/core/crypto/test_core_crypto_aead.odin index dfa251413..961311cd6 100644 --- a/tests/core/crypto/test_core_crypto_aead.odin +++ b/tests/core/crypto/test_core_crypto_aead.odin @@ -4,6 +4,7 @@ import "base:runtime" import "core:crypto/aes" import "core:crypto/aegis" import "core:crypto/aead" +import "core:crypto/deoxysii" import "core:encoding/hex" import "core:testing" @@ -23,6 +24,10 @@ test_aead :: proc(t: ^testing.T) { for impl in supported_aegis_impls() { append(&aegis_impls, impl) } + deoxysii_impls := make([dynamic]aead.Implementation, context.temp_allocator) + for impl in supported_deoxysii_impls() { + append(&deoxysii_impls, impl) + } impls := [aead.Algorithm][dynamic]aead.Implementation{ .Invalid = nil, .AES_GCM_128 = aes_impls, @@ -34,6 +39,7 @@ test_aead :: proc(t: ^testing.T) { .AEGIS_128L_256 = aegis_impls, .AEGIS_256 = aegis_impls, .AEGIS_256_256 = aegis_impls, + .DEOXYS_II_256 = deoxysii_impls, } test_vectors := []struct{ @@ -418,6 +424,79 @@ test_aead :: proc(t: ^testing.T) { "57754a7d09963e7c787583a2e7b859bb24fa1e04d49fd550b2511a358e3bca252a9b1b8b30cc4a67", "a3aca270c006094d71c20e6910b5161c0826df233d08919a566ec2c05990f734", }, + // Deoxys-II-256 + { + .DEOXYS_II_256, + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "202122232425262728292a2b2c2d2e", + "", + "", + "", + "2b97bd77712f0cde975309959dfe1d7c", + }, + { + .DEOXYS_II_256, + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "202122232425262728292a2b2c2d2e", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "", + "", + "54708ae5565a71f147bdb94d7ba3aed7", + }, + { + .DEOXYS_II_256, + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "202122232425262728292a2b2c2d2e", + "f495c9c03d29989695d98ff5d430650125805c1e0576d06f26cbda42b1f82238b8", + "", + "", + "3277689dc4208cc1ff59d15434a1baf1", + }, + { + .DEOXYS_II_256, + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "202122232425262728292a2b2c2d2e", + "", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "9da20db1c2781f6669257d87e2a4d9be1970f7581bef2c995e1149331e5e8cc1", + "92ce3aec3a4b72ff9eab71c2a93492fa", + }, + { + .DEOXYS_II_256, + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "202122232425262728292a2b2c2d2e", + "", + "15cd77732f9d0c4c6e581ef400876ad9188c5b8850ebd38224da95d7cdc99f7acc", + "e5ffd2abc5b459a73667756eda6443ede86c0883fc51dd75d22bb14992c684618c", + "5fa78d57308f19d0252072ee39df5ecc", + }, + { + .DEOXYS_II_256, + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "202122232425262728292a2b2c2d2e", + "000102030405060708090a0b0c0d0e0f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "109f8a168b36dfade02628a9e129d5257f03cc7912aefa79729b67b186a2b08f", + "6549f9bf10acba0a451dbb2484a60d90", + }, + { + .DEOXYS_II_256, + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "202122232425262728292a2b2c2d2e", + "000102030405060708090a0b0c0d0e0f10", + "422857fb165af0a35c03199fb895604dca9cea6d788954962c419e0d5c225c0327", + "7d772203fa38be296d8d20d805163130c69aba8cb16ed845c2296c61a8f34b394e", + "0b3f10e3933c78190b24b33008bf80e9", + }, + { + .DEOXYS_II_256, + "101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "202122232425262728292a2b2c2d2e", + "3290bb8441279dc6083a43e9048c3dc08966ab30d7a6b35759e7a13339f124918f3b5ab1affa65e6c0e3680eb33a6ec82424ab1ce5a40b8654e13d845c29b13896a1466a75fc875acba4527ded37ed00c600a357c9a6e586c74cf3d85cd3258c813218f319d12b82480e5124ff19ec00bda1fbb8bd25eeb3de9fcbf3296deba250caf7e9f4ef0be1918e24221dd0be888c59c166ad761d7b58462a1b1d44b04265b45827172c133dd5b6c870b9af7b21368d12a88f4efa1751047543d584382d9ec22e7550d50ecddba27d1f65453f1f3398de54ee8c1f4ac8e16f5523d89641e99a632380af0f0b1e6b0e192ec29bf1d8714978ff9fbfb93604142393e9a82c3aaebbbe15e3b4e5cfd18bdfe309315c9f9f830deebe2edcdc24f8eca90fda49f6646e789c5041fb5be933fa843278e95f3a54f8eb41f14777ea949d5ea442b01249e64816151a325769e264ed4acd5c3f21700ca755d5bc0c2c5f9453419510bc74f2d71621dcecb9efc9c24791b4bb560fb70a8231521d6560af89d8d50144d9c080863f043781153bcd59030e60bd17a6d7aa083211b67b581fa4f74cce4d030d1e8f9429fd725c110040d41eb6989ffb1595c72cbe3c9b78a8ab80d71a6a5283da77b89cae295bb13c14fbe466b617f4da8ad60b085e2ea153f6713ae0046aa31e0ba44e43ef36a111bf05c073a4e3624cd35f63a546f9142b35aa81b8826d", + "83dab23b1379e090755c99079cfe918cb737e989f2d720ccaff493a744927644fec3653211fa75306a83486e5c34ecfe63870c97251a73e4b9033ae374809711b211ed5d293a592e466a81170f1d85750b5ca025ccd4579947edbae9ec132bfb1a7233ad79fae30006a6699f143893861b975226ed9d3cfb8a240be232fbf4e83755d59d20bc2faa2ea5e5b0428427485cca5e76a89fe32bdd59ab4177ad7cb1899c101e3c4f7535129591390ebdf30140846078b13867bbb2efd6cf434afe356eb18d716b21fd664c26c908496534bf2cde6d6b897799016594fb6d9f830ae5f44ccec26d42ff0d1a21b80cdbe8c8c170a5f766fad884abcc781b5b8ebc0f559bfeaa4557b04d977d51411a7f47bf437d0280cf9f92bc4f9cd6226337a492320851955adae2cafea22a89c3132dd252e4728328eda05555dff3241404341b8aa502d45c456113af42a8e91a85e4b4e9555028982ec3d144722af0eb04a6d3b8127c3040629de53f5fd187048198e8f8e8cc857afcbae45c693fec12fc2149d5e7587d0121b1717d0147f6979f75e8f085293f705c3399a6cc8df7057bf481e6c374edf0a0af7479f858045357b7fe21021c3fabdaf012652bf2e5db257bd9490ce637a81477bd3f9814a2198fdb9afa9344321f2393798670e588c47a1924d592cda3eb5a96754dfd92d87ee1ffa9d4ee586c85d7518c5d2db57d0451c33de0", + "88294fcef65a1bdfd7baaa472816c64ef5bef2622b88c1ec5a739396157ef4935f3aa76449e391c32da28ee2857f399ac3dd95aed30cfb26cc0063cd4cd8f7431108176fbf370123856662b000a8348e5925fbb97c9ec0c737758330a7983f06b51590c1d2f5e5faaf0eb58e34e19e5fc85cec03d3926dd46a79ba7026e83dec24e07484c9103dd0cdb0edb505500caca5e1d5dbc71348cf00648821488ebaab7f9d84bbbf91b3c521dbef30110e7bd94f8dad5ab8e0cc5411ca9682d210d5d80c0c4bdbba8181789a4273d6deb80899fdcd976ca6f3a9770b54305f586a04256cfbeb4c11254e88559f294db3b9a94b80ab9f9a02cb4c0748de0af7818685521691dba5738be546dba13a56016fb8635af9dff50f25d1b17ad21707db2640a76a741e65e559b2afaaec0f37e18436bf02008f84dbd7b2698687a22376b65dc7524fca8a28709eee3f3caee3b28ed1173d1e08ee849e2ca63d2c90d555755c8fbafd5d2f4b37f06a1dbd6852ee2ffcfe79d510152e98fc4f3094f740a4aede9ee378b606d34576776bf5f1269f5385a84b3928433bfca177550ccfcd22cd0331bbc595e38c2758b2662476fa66354c4e84c7b360405aa3f5b2a48621bdca1a90c69b21789c91b5b8c568e3c741d99e22f6d7e26f2abed045f1d578b782ab4a5cf2af636d842b3012e180e4b045d8d15b057b69c92398a517053daf9be7c2935e", + "a616f0c218e18b526cf2a3f8c115e262", + }, } for v, _ in test_vectors { algo_name := aead.ALGORITHM_NAMES[v.algo] @@ -541,3 +620,13 @@ supported_aegis_impls :: proc() -> [dynamic]aes.Implementation { return impls } + +supported_deoxysii_impls :: proc() -> [dynamic]aes.Implementation { + impls := make([dynamic]aes.Implementation, 0, 2, context.temp_allocator) + append(&impls, aes.Implementation.Portable) + if deoxysii.is_hardware_accelerated() { + append(&impls, aes.Implementation.Hardware) + } + + return impls +} From f3f5fbd37315f8ebe39c1fa404c2bcf905b8d316 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Tue, 29 Oct 2024 05:13:57 +0900 Subject: [PATCH 20/81] test/benchmarks/crypto: Improve benchmarks - Use text/table for results - Add more benchmarks --- tests/benchmark/crypto/benchmark_aead.odin | 96 ++++ tests/benchmark/crypto/benchmark_crypto.odin | 552 ------------------- tests/benchmark/crypto/benchmark_ecc.odin | 163 ++++++ tests/benchmark/crypto/benchmark_hash.odin | 101 ++++ tests/benchmark/crypto/benchmark_mac.odin | 191 +++++++ tests/benchmark/crypto/benchmark_stream.odin | 145 +++++ tests/benchmark/crypto/benchmark_utils.odin | 50 ++ 7 files changed, 746 insertions(+), 552 deletions(-) create mode 100644 tests/benchmark/crypto/benchmark_aead.odin delete mode 100644 tests/benchmark/crypto/benchmark_crypto.odin create mode 100644 tests/benchmark/crypto/benchmark_ecc.odin create mode 100644 tests/benchmark/crypto/benchmark_hash.odin create mode 100644 tests/benchmark/crypto/benchmark_mac.odin create mode 100644 tests/benchmark/crypto/benchmark_stream.odin create mode 100644 tests/benchmark/crypto/benchmark_utils.odin diff --git a/tests/benchmark/crypto/benchmark_aead.odin b/tests/benchmark/crypto/benchmark_aead.odin new file mode 100644 index 000000000..bfd888a43 --- /dev/null +++ b/tests/benchmark/crypto/benchmark_aead.odin @@ -0,0 +1,96 @@ +package benchmark_core_crypto + +import "base:runtime" +import "core:crypto" +import "core:testing" +import "core:text/table" +import "core:time" + +import "core:crypto/aead" + +@(private = "file") +ITERS :: 10000 +@(private = "file") +SIZES := []int{64, 1024, 65536} + +@(test) +benchmark_crypto_aead :: proc(t: ^testing.T) { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + tbl: table.Table + table.init(&tbl) + defer table.destroy(&tbl) + + table.caption(&tbl, "AEAD") + table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Size", "Time", "Throughput") + + for algo, i in aead.Algorithm { + if algo == .Invalid { + continue + } + if i > 1 { + table.row(&tbl) + } + + algo_name := aead.ALGORITHM_NAMES[algo] + key_sz := aead.KEY_SIZES[algo] + + key := make([]byte, key_sz, context.temp_allocator) + crypto.rand_bytes(key) + + // TODO: Benchmark all available imlementations? + ctx: aead.Context + aead.init(&ctx, algo, key) + + for sz, _ in SIZES { + options := &time.Benchmark_Options{ + rounds = ITERS, + bytes = aead.IV_SIZES[algo] + sz, + setup = setup_sized_buf, + bench = do_bench_aead, + teardown = teardown_sized_buf, + } + context.user_ptr = &ctx + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil) + + time_per_iter := options.duration / ITERS + table.aligned_row_of_values( + &tbl, + .Right, + algo_name, + table.format(&tbl, "%d", sz), + table.format(&tbl, "%8M", time_per_iter), + table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second), + ) + } + } + + log_table(&tbl) +} + +@(private = "file") +do_bench_aead :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + tag_: [aead.MAX_TAG_SIZE]byte + + ctx := (^aead.Context)(context.user_ptr) + iv_sz := aead.iv_size(ctx) + + iv := options.input[:iv_sz] + buf := options.input[iv_sz:] + tag := tag_[:aead.tag_size(ctx)] + + for _ in 0 ..= options.rounds { + aead.seal_ctx(ctx, buf, tag, iv, nil, buf) + } + options.count = options.rounds + options.processed = options.rounds * (options.bytes - iv_sz) + + return +} diff --git a/tests/benchmark/crypto/benchmark_crypto.odin b/tests/benchmark/crypto/benchmark_crypto.odin deleted file mode 100644 index 9e8824c03..000000000 --- a/tests/benchmark/crypto/benchmark_crypto.odin +++ /dev/null @@ -1,552 +0,0 @@ -package benchmark_core_crypto - -import "base:runtime" -import "core:encoding/hex" -import "core:fmt" -import "core:log" -import "core:strings" -import "core:testing" -import "core:time" - -import "core:crypto/aegis" -import "core:crypto/aes" -import "core:crypto/chacha20" -import "core:crypto/chacha20poly1305" -import "core:crypto/deoxysii" -import "core:crypto/ed25519" -import "core:crypto/poly1305" -import "core:crypto/x25519" -import "core:crypto/x448" - -// Cryptographic primitive benchmarks. - -@(test) -benchmark_crypto :: proc(t: ^testing.T) { - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - - str: strings.Builder - strings.builder_init(&str, context.allocator) - defer { - log.info(strings.to_string(str)) - strings.builder_destroy(&str) - } - - { - name := "AES256-CTR 64 bytes" - options := &time.Benchmark_Options { - rounds = 1_000, - bytes = 64, - setup = _setup_sized_buf, - bench = _benchmark_aes256_ctr, - teardown = _teardown_sized_buf, - } - - err := time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "AES256-CTR 1024 bytes" - options.bytes = 1024 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "AES256-CTR 65536 bytes" - options.bytes = 65536 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - } - { - name := "ChaCha20 64 bytes" - options := &time.Benchmark_Options { - rounds = 1_000, - bytes = 64, - setup = _setup_sized_buf, - bench = _benchmark_chacha20, - teardown = _teardown_sized_buf, - } - - err := time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "ChaCha20 1024 bytes" - options.bytes = 1024 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "ChaCha20 65536 bytes" - options.bytes = 65536 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - } - { - name := "Poly1305 64 zero bytes" - options := &time.Benchmark_Options { - rounds = 1_000, - bytes = 64, - setup = _setup_sized_buf, - bench = _benchmark_poly1305, - teardown = _teardown_sized_buf, - } - - err := time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "Poly1305 1024 zero bytes" - options.bytes = 1024 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - } - { - name := "chacha20poly1305 64 bytes" - options := &time.Benchmark_Options { - rounds = 1_000, - bytes = 64, - setup = _setup_sized_buf, - bench = _benchmark_chacha20poly1305, - teardown = _teardown_sized_buf, - } - - err := time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "chacha20poly1305 1024 bytes" - options.bytes = 1024 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "chacha20poly1305 65536 bytes" - options.bytes = 65536 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - } - { - name := "AES256-GCM 64 bytes" - options := &time.Benchmark_Options { - rounds = 1_000, - bytes = 64, - setup = _setup_sized_buf, - bench = _benchmark_aes256_gcm, - teardown = _teardown_sized_buf, - } - - key := [aes.KEY_SIZE_256]byte { - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - } - ctx: aes.Context_GCM - aes.init_gcm(&ctx, key[:]) - - context.user_ptr = &ctx - - err := time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "AES256-GCM 1024 bytes" - options.bytes = 1024 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "AES256-GCM 65536 bytes" - options.bytes = 65536 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - } - { - name := "AEGIS-256 64 bytes" - options := &time.Benchmark_Options { - rounds = 1_000, - bytes = 64, - setup = _setup_sized_buf, - bench = _benchmark_aegis_256, - teardown = _teardown_sized_buf, - } - - key := [aegis.KEY_SIZE_256]byte { - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - } - ctx: aegis.Context - aegis.init(&ctx, key[:]) - - context.user_ptr = &ctx - - err := time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "AEGIS-256 1024 bytes" - options.bytes = 1024 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "AEGIS-256 65536 bytes" - options.bytes = 65536 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - } - { - name := "Deoxys-II-256 64 bytes" - options := &time.Benchmark_Options { - rounds = 1_000, - bytes = 64, - setup = _setup_sized_buf, - bench = _benchmark_deoxysii_256, - teardown = _teardown_sized_buf, - } - - key := [aegis.KEY_SIZE_256]byte { - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - } - ctx: deoxysii.Context - deoxysii.init(&ctx, key[:]) - - context.user_ptr = &ctx - - err := time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "Deoxys-II-256 1024 bytes" - options.bytes = 1024 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - - name = "Deoxys-II-256 65536 bytes" - options.bytes = 65536 - err = time.benchmark(options, context.allocator) - testing.expect(t, err == nil, name) - benchmark_print(&str, name, options) - } - { - iters :: 10000 - - priv_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" - priv_bytes, _ := hex.decode(transmute([]byte)(priv_str), context.temp_allocator) - priv_key: ed25519.Private_Key - start := time.now() - for i := 0; i < iters; i = i + 1 { - ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes) - assert(ok, "private key should deserialize") - } - elapsed := time.since(start) - fmt.sbprintfln(&str, - "ed25519.private_key_set_bytes: ~%f us/op", - time.duration_microseconds(elapsed) / iters, - ) - - pub_bytes := priv_key._pub_key._b[:] // "I know what I am doing" - pub_key: ed25519.Public_Key - start = time.now() - for i := 0; i < iters; i = i + 1 { - ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes[:]) - assert(ok, "public key should deserialize") - } - elapsed = time.since(start) - fmt.sbprintfln(&str, - "ed25519.public_key_set_bytes: ~%f us/op", - time.duration_microseconds(elapsed) / iters, - ) - - msg := "Got a job for you, 621." - sig_bytes: [ed25519.SIGNATURE_SIZE]byte - msg_bytes := transmute([]byte)(msg) - start = time.now() - for i := 0; i < iters; i = i + 1 { - ed25519.sign(&priv_key, msg_bytes, sig_bytes[:]) - } - elapsed = time.since(start) - fmt.sbprintfln(&str, - "ed25519.sign: ~%f us/op", - time.duration_microseconds(elapsed) / iters, - ) - - start = time.now() - for i := 0; i < iters; i = i + 1 { - ok := ed25519.verify(&pub_key, msg_bytes, sig_bytes[:]) - assert(ok, "signature should validate") - } - elapsed = time.since(start) - fmt.sbprintfln(&str, - "ed25519.verify: ~%f us/op", - time.duration_microseconds(elapsed) / iters, - ) - } - { - point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" - scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" - - point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator) - scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator) - out: [x25519.POINT_SIZE]byte = --- - - iters :: 10000 - start := time.now() - for i := 0; i < iters; i = i + 1 { - x25519.scalarmult(out[:], scalar[:], point[:]) - } - elapsed := time.since(start) - - fmt.sbprintfln(&str, - "x25519.scalarmult: ~%f us/op", - time.duration_microseconds(elapsed) / iters, - ) - } - { - point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" - scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" - - point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator) - scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator) - out: [x448.POINT_SIZE]byte = --- - - iters :: 10000 - start := time.now() - for i := 0; i < iters; i = i + 1 { - x448.scalarmult(out[:], scalar[:], point[:]) - } - elapsed := time.since(start) - - fmt.sbprintfln(&str, - "x448.scalarmult: ~%f us/op", - time.duration_microseconds(elapsed) / iters, - ) - } -} - -@(private) -_setup_sized_buf :: proc( - options: ^time.Benchmark_Options, - allocator := context.allocator, -) -> ( - err: time.Benchmark_Error, -) { - assert(options != nil) - - options.input = make([]u8, options.bytes, allocator) - return nil if len(options.input) == options.bytes else .Allocation_Error -} - -@(private) -_teardown_sized_buf :: proc( - options: ^time.Benchmark_Options, - allocator := context.allocator, -) -> ( - err: time.Benchmark_Error, -) { - assert(options != nil) - - delete(options.input) - return nil -} - -@(private) -_benchmark_chacha20 :: proc( - options: ^time.Benchmark_Options, - allocator := context.allocator, -) -> ( - err: time.Benchmark_Error, -) { - buf := options.input - key := [chacha20.KEY_SIZE]byte { - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - } - iv := [chacha20.IV_SIZE]byte { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - } - - ctx: chacha20.Context = --- - chacha20.init(&ctx, key[:], iv[:]) - - for _ in 0 ..= options.rounds { - chacha20.xor_bytes(&ctx, buf, buf) - } - options.count = options.rounds - options.processed = options.rounds * options.bytes - return nil -} - -@(private) -_benchmark_poly1305 :: proc( - options: ^time.Benchmark_Options, - allocator := context.allocator, -) -> ( - err: time.Benchmark_Error, -) { - buf := options.input - key := [poly1305.KEY_SIZE]byte { - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - } - - tag: [poly1305.TAG_SIZE]byte = --- - for _ in 0 ..= options.rounds { - poly1305.sum(tag[:], buf, key[:]) - } - options.count = options.rounds - options.processed = options.rounds * options.bytes - //options.hash = u128(h) - return nil -} - -@(private) -_benchmark_chacha20poly1305 :: proc( - options: ^time.Benchmark_Options, - allocator := context.allocator, -) -> ( - err: time.Benchmark_Error, -) { - buf := options.input - key := [chacha20.KEY_SIZE]byte { - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - } - iv := [chacha20.IV_SIZE]byte { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - } - - ctx: chacha20poly1305.Context = --- - chacha20poly1305.init(&ctx, key[:]) // Basically 0 overhead. - - tag: [chacha20poly1305.TAG_SIZE]byte = --- - - for _ in 0 ..= options.rounds { - chacha20poly1305.seal(&ctx, buf, tag[:], iv[:], nil, buf) - } - options.count = options.rounds - options.processed = options.rounds * options.bytes - return nil -} - -@(private) -_benchmark_aes256_ctr :: proc( - options: ^time.Benchmark_Options, - allocator := context.allocator, -) -> ( - err: time.Benchmark_Error, -) { - buf := options.input - key := [aes.KEY_SIZE_256]byte { - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, - } - iv := [aes.CTR_IV_SIZE]byte { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - } - - ctx: aes.Context_CTR = --- - aes.init_ctr(&ctx, key[:], iv[:]) - - for _ in 0 ..= options.rounds { - aes.xor_bytes_ctr(&ctx, buf, buf) - } - options.count = options.rounds - options.processed = options.rounds * options.bytes - return nil -} - -_benchmark_aes256_gcm :: proc( - options: ^time.Benchmark_Options, - allocator := context.allocator, -) -> ( - err: time.Benchmark_Error, -) { - buf := options.input - iv: [aes.GCM_IV_SIZE]byte - tag: [aes.GCM_TAG_SIZE]byte = --- - - ctx := (^aes.Context_GCM)(context.user_ptr) - - for _ in 0 ..= options.rounds { - aes.seal_gcm(ctx, buf, tag[:], iv[:], nil, buf) - } - options.count = options.rounds - options.processed = options.rounds * options.bytes - return nil -} - -_benchmark_aegis_256 :: proc( - options: ^time.Benchmark_Options, - allocator := context.allocator, -) -> ( - err: time.Benchmark_Error, -) { - buf := options.input - iv: [aegis.IV_SIZE_256]byte - tag: [aegis.TAG_SIZE_128]byte = --- - - ctx := (^aegis.Context)(context.user_ptr) - - for _ in 0 ..= options.rounds { - aegis.seal(ctx, buf, tag[:], iv[:], nil, buf) - } - options.count = options.rounds - options.processed = options.rounds * options.bytes - return nil -} - -_benchmark_deoxysii_256 :: proc( - options: ^time.Benchmark_Options, - allocator := context.allocator, -) -> ( - err: time.Benchmark_Error, -) { - buf := options.input - iv: [deoxysii.IV_SIZE]byte - tag: [deoxysii.TAG_SIZE]byte = --- - - ctx := (^deoxysii.Context)(context.user_ptr) - - for _ in 0 ..= options.rounds { - deoxysii.seal(ctx, buf, tag[:], iv[:], nil, buf) - } - options.count = options.rounds - options.processed = options.rounds * options.bytes - return nil -} - -@(private) -benchmark_print :: proc(str: ^strings.Builder, name: string, options: ^time.Benchmark_Options, loc := #caller_location) { - fmt.sbprintfln(str, "[%v] %v rounds, %v bytes processed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s\n", - name, - options.rounds, - options.processed, - time.duration_nanoseconds(options.duration), - options.rounds_per_second, - options.megabytes_per_second, - ) -} diff --git a/tests/benchmark/crypto/benchmark_ecc.odin b/tests/benchmark/crypto/benchmark_ecc.odin new file mode 100644 index 000000000..16ca798dc --- /dev/null +++ b/tests/benchmark/crypto/benchmark_ecc.odin @@ -0,0 +1,163 @@ +package benchmark_core_crypto + +import "base:runtime" +import "core:encoding/hex" +import "core:testing" +import "core:text/table" +import "core:time" + +import "core:crypto/ed25519" +import "core:crypto/x25519" +import "core:crypto/x448" + +@(private = "file") +ECDH_ITERS :: 10000 +@(private = "file") +DSA_ITERS :: 10000 + +@(test) +benchmark_crypto_ecc :: proc(t: ^testing.T) { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + bench_ecdh() + bench_dsa() +} + +@(private = "file") +bench_ecdh :: proc() { + tbl: table.Table + table.init(&tbl) + defer table.destroy(&tbl) + + table.caption(&tbl, "ECDH") + table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Scalar-Basepoint", "Scalar-Point") + + append_tbl := proc(tbl: ^table.Table, algo_name: string, bp, sc: time.Duration) { + table.aligned_row_of_values( + tbl, + .Right, + algo_name, + table.format(tbl, "%8M", bp), + table.format(tbl, "%8M", sc), + ) + } + + scalar_bp, scalar := bench_x25519() + append_tbl(&tbl, "X25519", scalar_bp, scalar) + + scalar_bp, scalar = bench_x448() + append_tbl(&tbl, "X448", scalar_bp, scalar) + + log_table(&tbl) +} + +@(private = "file") +bench_x25519 :: proc() -> (bp, sc: time.Duration) { + point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" + + point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator) + scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator) + out: [x25519.POINT_SIZE]byte = --- + + start := time.tick_now() + for _ in 0 ..< ECDH_ITERS { + x25519.scalarmult_basepoint(out[:], scalar[:]) + } + bp = time.tick_since(start) / ECDH_ITERS + + start = time.tick_now() + for _ in 0 ..< ECDH_ITERS { + x25519.scalarmult(out[:], scalar[:], point[:]) + } + sc = time.tick_since(start) / ECDH_ITERS + + return +} + +@(private = "file") +bench_x448 :: proc() -> (bp, sc: time.Duration) { + point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" + + point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator) + scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator) + out: [x448.POINT_SIZE]byte = --- + + start := time.tick_now() + for _ in 0 ..< ECDH_ITERS { + x448.scalarmult_basepoint(out[:], scalar[:]) + } + bp = time.tick_since(start) / ECDH_ITERS + + start = time.tick_now() + for _ in 0 ..< ECDH_ITERS { + x448.scalarmult(out[:], scalar[:], point[:]) + } + sc = time.tick_since(start) / ECDH_ITERS + + return +} + +@(private = "file") +bench_dsa :: proc() { + tbl: table.Table + table.init(&tbl) + defer table.destroy(&tbl) + + table.caption(&tbl, "ECDSA/EdDSA") + table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Op", "Time") + + append_tbl := proc(tbl: ^table.Table, algo_name, op: string, t: time.Duration) { + table.aligned_row_of_values( + tbl, + .Right, + algo_name, + op, + table.format(tbl, "%8M", t), + ) + } + + sk, sig, verif := bench_ed25519() + append_tbl(&tbl, "ed25519", "private_key_set_bytes", sk) + append_tbl(&tbl, "ed25519", "sign", sig) + append_tbl(&tbl, "ed25519", "verify", verif) + + log_table(&tbl) +} + +@(private = "file") +bench_ed25519 :: proc() -> (sk, sig, verif: time.Duration) { + priv_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" + priv_bytes, _ := hex.decode(transmute([]byte)(priv_str), context.temp_allocator) + priv_key: ed25519.Private_Key + start := time.tick_now() + for _ in 0 ..< DSA_ITERS { + ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes) + assert(ok, "private key should deserialize") + } + sk = time.tick_since(start) / DSA_ITERS + + pub_bytes := priv_key._pub_key._b[:] // "I know what I am doing" + pub_key: ed25519.Public_Key + ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes[:]) + assert(ok, "public key should deserialize") + + msg := "Got a job for you, 621." + sig_bytes: [ed25519.SIGNATURE_SIZE]byte + msg_bytes := transmute([]byte)(msg) + start = time.tick_now() + for _ in 0 ..< DSA_ITERS { + ed25519.sign(&priv_key, msg_bytes, sig_bytes[:]) + } + sig = time.tick_since(start) / DSA_ITERS + + start = time.tick_now() + for _ in 0 ..< DSA_ITERS { + ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes[:]) + assert(ok, "signature should validate") + } + verif = time.tick_since(start) / DSA_ITERS + + return +} diff --git a/tests/benchmark/crypto/benchmark_hash.odin b/tests/benchmark/crypto/benchmark_hash.odin new file mode 100644 index 000000000..f9c560e6d --- /dev/null +++ b/tests/benchmark/crypto/benchmark_hash.odin @@ -0,0 +1,101 @@ +package benchmark_core_crypto + +import "base:runtime" +import "core:testing" +import "core:text/table" +import "core:time" + +import "core:crypto/hash" + +@(private = "file") +ITERS :: 10000 +@(private = "file") +SIZES := []int{64, 1024, 65536} + +@(test) +benchmark_crypto_hash :: proc(t: ^testing.T) { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + tbl: table.Table + table.init(&tbl) + defer table.destroy(&tbl) + + table.caption(&tbl, "Hash") + table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Size", "Time", "Throughput") + + for algo, i in hash.Algorithm { + // Skip the sentinel value, and uncommon algorithms + #partial switch algo { + case .Invalid: + continue + case .Legacy_KECCAK_224, .Legacy_KECCAK_256, .Legacy_KECCAK_384, .Legacy_KECCAK_512: + // Skip: Legacy and not worth using over SHA3 + continue + case .Insecure_MD5, .Insecure_SHA1: + // Skip: Legacy and not worth using at all + continue + case .SHA224, .SHA384, .SHA3_224, .SHA3_384: + // Skip: Uncommon SHA2/SHA3 variants + continue + case .SM3: + // Skip: Liberty Prime is online. All systems nominal. + // Weapons hot. Mission: the destruction of any and + // all Chinese communists. + continue + } + if i > 1 { + table.row(&tbl) + } + + algo_name := hash.ALGORITHM_NAMES[algo] + + for sz, _ in SIZES { + options := &time.Benchmark_Options{ + rounds = ITERS, + bytes = sz, + setup = setup_sized_buf, + bench = do_bench_hash, + teardown = teardown_sized_buf, + } + tmp := algo + context.user_ptr = &tmp + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil) + + time_per_iter := options.duration / ITERS + table.aligned_row_of_values( + &tbl, + .Right, + algo_name, + table.format(&tbl, "%d", sz), + table.format(&tbl, "%8M", time_per_iter), + table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second), + ) + } + } + + log_table(&tbl) +} + +@(private = "file") +do_bench_hash :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + digest_: [hash.MAX_DIGEST_SIZE]byte + + buf := options.input + algo := (^hash.Algorithm)(context.user_ptr)^ + digest := digest_[:hash.DIGEST_SIZES[algo]] + + for _ in 0 ..= options.rounds { + hash.hash_bytes_to_buffer(algo, buf, digest) + } + options.count = options.rounds + options.processed = options.rounds * (options.bytes) + + return +} diff --git a/tests/benchmark/crypto/benchmark_mac.odin b/tests/benchmark/crypto/benchmark_mac.odin new file mode 100644 index 000000000..a0d2cae90 --- /dev/null +++ b/tests/benchmark/crypto/benchmark_mac.odin @@ -0,0 +1,191 @@ +package benchmark_core_crypto + +import "base:runtime" +import "core:testing" +import "core:text/table" +import "core:time" + +import "core:crypto/hmac" +import "core:crypto/kmac" +import "core:crypto/poly1305" + +@(private = "file") +ITERS :: 10000 +@(private = "file") +SIZES := []int{64, 1024, 65536} +@(private = "file") +KMAC_KEY_SIZES := []int{128, 256} + +@(test) +benchmark_crypto_mac :: proc(t: ^testing.T) { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + tbl: table.Table + table.init(&tbl) + defer table.destroy(&tbl) + + table.caption(&tbl, "MAC") + table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Size", "Time", "Throughput") + + { + for sz, _ in SIZES { + options := &time.Benchmark_Options{ + rounds = ITERS, + bytes = sz, + setup = setup_sized_buf, + bench = do_bench_hmac_sha_256, + teardown = teardown_sized_buf, + } + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil) + + time_per_iter := options.duration / ITERS + table.aligned_row_of_values( + &tbl, + .Right, + "HMAC-SHA256", + table.format(&tbl, "%d", sz), + table.format(&tbl, "%8M", time_per_iter), + table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second), + ) + } + } + + table.row(&tbl) + + for key_sz, i in KMAC_KEY_SIZES { + if i > 0 { + table.row(&tbl) + } + + for sz, _ in SIZES { + options := &time.Benchmark_Options{ + rounds = ITERS, + bytes = sz, + processed = key_sz, // Pls ignore. + setup = setup_sized_buf, + bench = do_bench_kmac, + teardown = teardown_sized_buf, + } + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil) + + time_per_iter := options.duration / ITERS + table.aligned_row_of_values( + &tbl, + .Right, + table.format(&tbl, "KMAC%d", key_sz), + table.format(&tbl, "%d", sz), + table.format(&tbl, "%8M", time_per_iter), + table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second), + ) + } + } + + table.row(&tbl) + + { + for sz, _ in SIZES { + options := &time.Benchmark_Options{ + rounds = ITERS, + bytes = sz, + setup = setup_sized_buf, + bench = do_bench_poly1305, + teardown = teardown_sized_buf, + } + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil) + + time_per_iter := options.duration / ITERS + table.aligned_row_of_values( + &tbl, + .Right, + "poly1305", + table.format(&tbl, "%d", sz), + table.format(&tbl, "%8M", time_per_iter), + table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second), + ) + } + } + + log_table(&tbl) +} + +@(private = "file") +do_bench_hmac_sha_256 :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + buf := options.input + key := [32]byte { + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + } + + tag: [32]byte = --- + for _ in 0 ..= options.rounds { + hmac.sum(.SHA256, tag[:], buf, key[:]) + } + options.count = options.rounds + options.processed = options.rounds * options.bytes + + return +} + +@(private = "file") +do_bench_kmac :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + buf := options.input + key := [kmac.MIN_KEY_SIZE_256]byte { + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + } + sec_strength := options.processed + + tag: [32]byte = --- + for _ in 0 ..= options.rounds { + kmac.sum(sec_strength, tag[:sec_strength/8], buf, key[:], nil) + } + options.count = options.rounds + options.processed = options.rounds * options.bytes + + return +} + +@(private = "file") +do_bench_poly1305 :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + buf := options.input + key := [poly1305.KEY_SIZE]byte { + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, + } + + tag: [poly1305.TAG_SIZE]byte = --- + for _ in 0 ..= options.rounds { + poly1305.sum(tag[:], buf, key[:]) + } + options.count = options.rounds + options.processed = options.rounds * options.bytes + + return +} diff --git a/tests/benchmark/crypto/benchmark_stream.odin b/tests/benchmark/crypto/benchmark_stream.odin new file mode 100644 index 000000000..38c5a87c6 --- /dev/null +++ b/tests/benchmark/crypto/benchmark_stream.odin @@ -0,0 +1,145 @@ +package benchmark_core_crypto + +import "base:runtime" +import "core:crypto" +import "core:testing" +import "core:text/table" +import "core:time" + +import "core:crypto/aes" +import "core:crypto/chacha20" + +@(private = "file") +ITERS :: 10000 +@(private = "file") +SIZES := []int{64, 1024, 65536} +@(private = "file") +AES_CTR_KEY_SIZES := []int{128, 192, 256} + +@(test) +benchmark_crypto_stream :: proc(t: ^testing.T) { + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + tbl: table.Table + table.init(&tbl) + defer table.destroy(&tbl) + + table.caption(&tbl, "Stream Cipher") + table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Size", "Time", "Throughput") + + for key_sz, i in AES_CTR_KEY_SIZES { + if i > 0 { + table.row(&tbl) + } + + key := make([]byte, key_sz/8, context.temp_allocator) + iv := make([]byte, aes.CTR_IV_SIZE, context.temp_allocator) + crypto.rand_bytes(key) + crypto.rand_bytes(iv) + + ctx: aes.Context_CTR + aes.init_ctr(&ctx, key, iv) + + for sz, _ in SIZES { + options := &time.Benchmark_Options{ + rounds = ITERS, + bytes = sz, + setup = setup_sized_buf, + bench = do_bench_aes_ctr, + teardown = teardown_sized_buf, + } + context.user_ptr = &ctx + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil) + + time_per_iter := options.duration / ITERS + table.aligned_row_of_values( + &tbl, + .Right, + table.format(&tbl, "AES%d-CTR", key_sz), + table.format(&tbl, "%d", sz), + table.format(&tbl, "%8M", time_per_iter), + table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second), + ) + } + } + + table.row(&tbl) + + { + key := make([]byte, chacha20.KEY_SIZE, context.temp_allocator) + iv := make([]byte, chacha20.IV_SIZE, context.temp_allocator) + crypto.rand_bytes(key) + crypto.rand_bytes(iv) + + ctx: chacha20.Context + chacha20.init(&ctx, key, iv) + + for sz, _ in SIZES { + options := &time.Benchmark_Options{ + rounds = ITERS, + bytes = sz, + setup = setup_sized_buf, + bench = do_bench_chacha20, + teardown = teardown_sized_buf, + } + context.user_ptr = &ctx + + err := time.benchmark(options, context.allocator) + testing.expect(t, err == nil) + + time_per_iter := options.duration / ITERS + table.aligned_row_of_values( + &tbl, + .Right, + "chacha20", + table.format(&tbl, "%d", sz), + table.format(&tbl, "%8M", time_per_iter), + table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second), + ) + } + } + + log_table(&tbl) +} + +@(private = "file") +do_bench_aes_ctr :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + ctx := (^aes.Context_CTR)(context.user_ptr) + + buf := options.input + + for _ in 0 ..= options.rounds { + aes.xor_bytes_ctr(ctx, buf, buf) + } + options.count = options.rounds + options.processed = options.rounds * options.bytes + + return +} + +@(private = "file") +do_bench_chacha20 :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + ctx := (^chacha20.Context)(context.user_ptr) + + buf := options.input + + for _ in 0 ..= options.rounds { + chacha20.xor_bytes(ctx, buf, buf) + } + options.count = options.rounds + options.processed = options.rounds * options.bytes + + return +} diff --git a/tests/benchmark/crypto/benchmark_utils.odin b/tests/benchmark/crypto/benchmark_utils.odin new file mode 100644 index 000000000..6609adbf7 --- /dev/null +++ b/tests/benchmark/crypto/benchmark_utils.odin @@ -0,0 +1,50 @@ +package benchmark_core_crypto + +import "core:crypto" +import "core:fmt" +import "core:log" +import "core:strings" +import "core:text/table" +import "core:time" + +@(private) +log_table :: #force_inline proc(tbl: ^table.Table) { + sb := strings.builder_make() + defer strings.builder_destroy(&sb) + + wr := strings.to_writer(&sb) + + fmt.sbprintln(&sb) + table.write_plain_table(wr, tbl) + + log.info(strings.to_string(sb)) +} + +@(private) +setup_sized_buf :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + assert(options != nil) + + options.input = make([]u8, options.bytes, allocator) + if len(options.input) > 0 { + crypto.rand_bytes(options.input) + } + return nil if len(options.input) == options.bytes else .Allocation_Error +} + +@(private) +teardown_sized_buf :: proc( + options: ^time.Benchmark_Options, + allocator := context.allocator, +) -> ( + err: time.Benchmark_Error, +) { + assert(options != nil) + + delete(options.input) + return nil +} From 982ab11aa1fa1f1b690b1dbe0e6ad0d070a15bbc Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Sat, 2 Nov 2024 11:35:17 +0900 Subject: [PATCH 21/81] core/crypto/sha2: Use hardware SHA224/256 when available (AMD64) --- core/crypto/sha2/sha2.odin | 9 +- core/crypto/sha2/sha2_impl_hw_gen.odin | 15 ++ core/crypto/sha2/sha2_impl_hw_intel.odin | 260 +++++++++++++++++++++++ core/simd/x86/ssse3.odin | 2 +- core/sys/info/cpu_intel.odin | 2 + 5 files changed, 285 insertions(+), 3 deletions(-) create mode 100644 core/crypto/sha2/sha2_impl_hw_gen.odin create mode 100644 core/crypto/sha2/sha2_impl_hw_intel.odin diff --git a/core/crypto/sha2/sha2.odin b/core/crypto/sha2/sha2.odin index 1c1ce11b6..bf726c20c 100644 --- a/core/crypto/sha2/sha2.odin +++ b/core/crypto/sha2/sha2.odin @@ -15,9 +15,9 @@ package sha2 zhibog, dotbmp: Initial implementation. */ -import "core:encoding/endian" +@(require) import "core:encoding/endian" import "core:math/bits" -import "core:mem" +@(require) import "core:mem" // DIGEST_SIZE_224 is the SHA-224 digest size in bytes. DIGEST_SIZE_224 :: 28 @@ -397,6 +397,11 @@ SHA512_F4 :: #force_inline proc "contextless" (x: u64) -> u64 { @(private) sha2_transf :: proc "contextless" (ctx: ^$T, data: []byte) { when T == Context_256 { + if is_hardware_accelerated_256() { + sha256_transf_hw(ctx, data) + return + } + w: [64]u32 wv: [8]u32 t1, t2: u32 diff --git a/core/crypto/sha2/sha2_impl_hw_gen.odin b/core/crypto/sha2/sha2_impl_hw_gen.odin new file mode 100644 index 000000000..85c7f8b28 --- /dev/null +++ b/core/crypto/sha2/sha2_impl_hw_gen.odin @@ -0,0 +1,15 @@ +#+build !amd64 +package sha2 + +@(private = "file") +ERR_HW_NOT_SUPPORTED :: "crypto/sha2: hardware implementation unsupported" + +// is_hardware_accelerated_256 returns true iff hardware accelerated +// SHA-224/SHA-256 is supported. +is_hardware_accelerated_256 :: proc "contextless" () -> bool { + return false +} + +sha256_transf_hw :: proc "contextless" (ctx: ^Context_256, data: []byte) { + panic_contextless(ERR_HW_NOT_SUPPORTED) +} diff --git a/core/crypto/sha2/sha2_impl_hw_intel.odin b/core/crypto/sha2/sha2_impl_hw_intel.odin new file mode 100644 index 000000000..f16f353df --- /dev/null +++ b/core/crypto/sha2/sha2_impl_hw_intel.odin @@ -0,0 +1,260 @@ +#+build amd64 +package sha2 + +// Based on the public domain code by Jeffrey Walton, though +// realistically, there only is one sensible way to write this +// and Intel's whitepaper covers it. +// +// See: https://github.com/noloader/SHA-Intrinsics + +import "base:intrinsics" +import "core:simd" +import "core:simd/x86" +import "core:sys/info" + +@(private = "file") +MASK :: x86.__m128i{0x0405060700010203, 0x0c0d0e0f08090a0b} + +@(private = "file") +K_0 :: simd.u64x2{0x71374491428a2f98, 0xe9b5dba5b5c0fbcf} +@(private = "file") +K_1 :: simd.u64x2{0x59f111f13956c25b, 0xab1c5ed5923f82a4} +@(private = "file") +K_2 :: simd.u64x2{0x12835b01d807aa98, 0x550c7dc3243185be} +@(private = "file") +K_3 :: simd.u64x2{0x80deb1fe72be5d74, 0xc19bf1749bdc06a7} +@(private = "file") +K_4 :: simd.u64x2{0xefbe4786e49b69c1, 0x240ca1cc0fc19dc6} +@(private = "file") +K_5 :: simd.u64x2{0x4a7484aa2de92c6f, 0x76f988da5cb0a9dc} +@(private = "file") +K_6 :: simd.u64x2{0xa831c66d983e5152, 0xbf597fc7b00327c8} +@(private = "file") +K_7 :: simd.u64x2{0xd5a79147c6e00bf3, 0x1429296706ca6351} +@(private = "file") +K_8 :: simd.u64x2{0x2e1b213827b70a85, 0x53380d134d2c6dfc} +@(private = "file") +K_9 :: simd.u64x2{0x766a0abb650a7354, 0x92722c8581c2c92e} +@(private = "file") +K_10 :: simd.u64x2{0xa81a664ba2bfe8a1, 0xc76c51a3c24b8b70} +@(private = "file") +K_11 :: simd.u64x2{0xd6990624d192e819, 0x106aa070f40e3585} +@(private = "file") +K_12 :: simd.u64x2{0x1e376c0819a4c116, 0x34b0bcb52748774c} +@(private = "file") +K_13 :: simd.u64x2{0x4ed8aa4a391c0cb3, 0x682e6ff35b9cca4f} +@(private = "file") +K_14 :: simd.u64x2{0x78a5636f748f82ee, 0x8cc7020884c87814} +@(private = "file") +K_15 :: simd.u64x2{0xa4506ceb90befffa, 0xc67178f2bef9a3f7} + + +// is_hardware_accelerated_256 returns true iff hardware accelerated +// SHA-224/SHA-256 is supported. +is_hardware_accelerated_256 :: proc "contextless" () -> bool { + features, ok := info.cpu_features.? + if !ok { + return false + } + + req_features :: info.CPU_Features{ + .sse2, + .ssse3, + .sse41, + .sha, + } + return features >= req_features +} + +@(private, enable_target_feature="sse2,ssse3,sse4.1,sha") +sha256_transf_hw :: proc "contextless" (ctx: ^Context_256, data: []byte) #no_bounds_check { + // Load the state + tmp := intrinsics.unaligned_load((^x86.__m128i)(&ctx.h[0])) + state_1 := intrinsics.unaligned_load((^x86.__m128i)(&ctx.h[4])) + + tmp = x86._mm_shuffle_epi32(tmp, 0xb1) // CDAB + state_1 = x86._mm_shuffle_epi32(state_1, 0x1b) // EFGH + state_0 := x86._mm_alignr_epi8(tmp, state_1, 8) // ABEF + // state_1 = x86._mm_blend_epi16(state_1, tmp, 0xf0) // CDGH + state_1 = kludge_mm_blend_epi16_0xf0(state_1, tmp) + + data := data + for len(data) >= BLOCK_SIZE_256 { + state_0_save, state_1_save := state_0, state_1 + + // Rounds 0-3 + msg := intrinsics.unaligned_load((^x86.__m128i)(raw_data(data))) + msg_0 := x86._mm_shuffle_epi8(msg, MASK) + msg = x86._mm_add_epi32(msg_0, x86.__m128i(K_0)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + msg = x86._mm_shuffle_epi32(msg, 0xe) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + + // Rounds 4-7 + msg_1 := intrinsics.unaligned_load((^x86.__m128i)(raw_data(data[16:]))) + msg_1 = x86._mm_shuffle_epi8(msg_1, MASK) + msg = x86._mm_add_epi32(msg_1, x86.__m128i(K_1)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + msg = x86._mm_shuffle_epi32(msg, 0xe) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_0 = x86._mm_sha256msg1_epu32(msg_0, msg_1) + + // Rounds 8-11 + msg_2 := intrinsics.unaligned_load((^x86.__m128i)(raw_data(data[32:]))) + msg_2 = x86._mm_shuffle_epi8(msg_2, MASK) + msg = x86._mm_add_epi32(msg_2, x86.__m128i(K_2)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + msg = x86._mm_shuffle_epi32(msg, 0xe) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_1 = x86._mm_sha256msg1_epu32(msg_1, msg_2) + + // Rounds 12-15 + msg_3 := intrinsics.unaligned_load((^x86.__m128i)(raw_data(data[48:]))) + msg_3 = x86._mm_shuffle_epi8(msg_3, MASK) + msg = x86._mm_add_epi32(msg_3, x86.__m128i(K_3)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_3, msg_2, 4) + msg_0 = x86._mm_add_epi32(msg_0, tmp) + msg_0 = x86._mm_sha256msg2_epu32(msg_0, msg_3) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_2 = x86._mm_sha256msg1_epu32(msg_2, msg_3) + + // Rounds 16-19 + msg = x86._mm_add_epi32(msg_0, x86.__m128i(K_4)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_0, msg_3, 4) + msg_1 = x86._mm_add_epi32(msg_1, tmp) + msg_1 = x86._mm_sha256msg2_epu32(msg_1, msg_0) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_3 = x86._mm_sha256msg1_epu32(msg_3, msg_0) + + // Rounds 20-23 + msg = x86._mm_add_epi32(msg_1, x86.__m128i(K_5)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_1, msg_0, 4) + msg_2 = x86._mm_add_epi32(msg_2, tmp) + msg_2 = x86._mm_sha256msg2_epu32(msg_2, msg_1) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_0 = x86._mm_sha256msg1_epu32(msg_0, msg_1) + + // Rounds 24-27 + msg = x86._mm_add_epi32(msg_2, x86.__m128i(K_6)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_2, msg_1, 4) + msg_3 = x86._mm_add_epi32(msg_3, tmp) + msg_3 = x86._mm_sha256msg2_epu32(msg_3, msg_2) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_1 = x86._mm_sha256msg1_epu32(msg_1, msg_2) + + // Rounds 28-31 + msg = x86._mm_add_epi32(msg_3, x86.__m128i(K_7)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_3, msg_2, 4) + msg_0 = x86._mm_add_epi32(msg_0, tmp) + msg_0 = x86._mm_sha256msg2_epu32(msg_0, msg_3) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_2 = x86._mm_sha256msg1_epu32(msg_2, msg_3) + + // Rounds 32-35 + msg = x86._mm_add_epi32(msg_0, x86.__m128i(K_8)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_0, msg_3, 4) + msg_1 = x86._mm_add_epi32(msg_1, tmp) + msg_1 = x86._mm_sha256msg2_epu32(msg_1, msg_0) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_3 = x86._mm_sha256msg1_epu32(msg_3, msg_0) + + // Rounds 36-39 + msg = x86._mm_add_epi32(msg_1, x86.__m128i(K_9)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_1, msg_0, 4) + msg_2 = x86._mm_add_epi32(msg_2, tmp) + msg_2 = x86._mm_sha256msg2_epu32(msg_2, msg_1) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_0 = x86._mm_sha256msg1_epu32(msg_0, msg_1) + + // Rounds 40-43 + msg = x86._mm_add_epi32(msg_2, x86.__m128i(K_10)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_2, msg_1, 4) + msg_3 = x86._mm_add_epi32(msg_3, tmp) + msg_3 = x86._mm_sha256msg2_epu32(msg_3, msg_2) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_1 = x86._mm_sha256msg1_epu32(msg_1, msg_2) + + // Rounds 44-47 + msg = x86._mm_add_epi32(msg_3, x86.__m128i(K_11)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_3, msg_2, 4) + msg_0 = x86._mm_add_epi32(msg_0, tmp) + msg_0 = x86._mm_sha256msg2_epu32(msg_0, msg_3) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_2 = x86._mm_sha256msg1_epu32(msg_2, msg_3) + + // Rounds 48-51 + msg = x86._mm_add_epi32(msg_0, x86.__m128i(K_12)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_0, msg_3, 4) + msg_1 = x86._mm_add_epi32(msg_1, tmp) + msg_1 = x86._mm_sha256msg2_epu32(msg_1, msg_0) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + msg_3 = x86._mm_sha256msg1_epu32(msg_3, msg_0) + + // Rounds 52-55 + msg = x86._mm_add_epi32(msg_1, x86.__m128i(K_13)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_1, msg_0, 4) + msg_2 = x86._mm_add_epi32(msg_2, tmp) + msg_2 = x86._mm_sha256msg2_epu32(msg_2, msg_1) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + + /* Rounds 56-59 */ + msg = x86._mm_add_epi32(msg_2, x86.__m128i(K_14)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + tmp = x86._mm_alignr_epi8(msg_2, msg_1, 4) + msg_3 = x86._mm_add_epi32(msg_3, tmp) + msg_3 = x86._mm_sha256msg2_epu32(msg_3, msg_2) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + + // Rounds 60-63 + msg = x86._mm_add_epi32(msg_3, x86.__m128i(K_15)) + state_1 = x86._mm_sha256rnds2_epu32(state_1, state_0, msg) + msg = x86._mm_shuffle_epi32(msg, 0x0e) + state_0 = x86._mm_sha256rnds2_epu32(state_0, state_1, msg) + + state_0 = x86._mm_add_epi32(state_0, state_0_save) + state_1 = x86._mm_add_epi32(state_1, state_1_save) + + data = data[BLOCK_SIZE_256:] + } + + // Write back the updated state + tmp = x86._mm_shuffle_epi32(state_0, 0x1b) // FEBA + state_1 = x86._mm_shuffle_epi32(state_1, 0xb1) // DCHG + // state_0 = x86._mm_blend_epi16(tmp, state_1, 0xf0) // DCBA + state_0 = kludge_mm_blend_epi16_0xf0(tmp, state_1) + state_1 = x86._mm_alignr_epi8(state_1, tmp, 8) // ABEF + + intrinsics.unaligned_store((^x86.__m128i)(&ctx.h[0]), state_0) + intrinsics.unaligned_store((^x86.__m128i)(&ctx.h[4]), state_1) +} + +@(private = "file") +kludge_mm_blend_epi16_0xf0 :: #force_inline proc "contextless"(a, b: x86.__m128i) -> x86.__m128i { + // HACK HACK HACK: LLVM got rid of `llvm.x86.sse41.pblendw`. + a_ := simd.to_array(a) + b_ := simd.to_array(b) + return x86.__m128i{a_[0], b_[1]} +} diff --git a/core/simd/x86/ssse3.odin b/core/simd/x86/ssse3.odin index 07c846e7b..03ba5dcfb 100644 --- a/core/simd/x86/ssse3.odin +++ b/core/simd/x86/ssse3.odin @@ -21,7 +21,7 @@ _mm_abs_epi32 :: #force_inline proc "c" (a: __m128i) -> __m128i { _mm_shuffle_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pshufb128(transmute(u8x16)a, transmute(u8x16)b) } -@(require_results, enable_target_feature="ssse3") +@(require_results, enable_target_feature="sse2,ssse3") _mm_alignr_epi8 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u32) -> __m128i { shift :: IMM8 diff --git a/core/sys/info/cpu_intel.odin b/core/sys/info/cpu_intel.odin index 95b53dda0..c8b8282fe 100644 --- a/core/sys/info/cpu_intel.odin +++ b/core/sys/info/cpu_intel.odin @@ -23,6 +23,7 @@ CPU_Feature :: enum u64 { popcnt, // Hamming weight instruction POPCNT. rdrand, // RDRAND instruction (on-chip random number generator) rdseed, // RDSEED instruction (on-chip random number generator) + sha, // SHA Extensions (SHA-1, SHA-224, SHA-256) sse2, // Streaming SIMD extension 2 (always available on amd64) sse3, // Streaming SIMD extension 3 ssse3, // Supplemental streaming SIMD extension 3 @@ -115,6 +116,7 @@ init_cpu_features :: proc "c" () { _, ebx7, ecx7, edx7 := cpuid(7, 0) try_set(&set, .bmi1, 3, ebx7) + try_set(&set, .sha, 29, ebx7) if os_supports_avx { try_set(&set, .avx2, 5, ebx7) } From 93951ac72abdbbd4815589adaa395f391afe51a4 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Tue, 5 Nov 2024 18:48:10 +0900 Subject: [PATCH 22/81] core/crypto/sha2: Clean up the portable code slightly --- core/crypto/sha2/sha2.odin | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/core/crypto/sha2/sha2.odin b/core/crypto/sha2/sha2.odin index bf726c20c..8ab0ce005 100644 --- a/core/crypto/sha2/sha2.odin +++ b/core/crypto/sha2/sha2.odin @@ -271,7 +271,7 @@ reset :: proc(ctx: ^$T) { */ @(private, rodata) -sha256_k := [64]u32 { +SHA256_K := [64]u32 { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, @@ -291,7 +291,7 @@ sha256_k := [64]u32 { } @(private, rodata) -sha512_k := [80]u64 { +SHA512_K := [80]u64 { 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, @@ -334,6 +334,11 @@ sha512_k := [80]u64 { 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, } +@(private) +SHA256_ROUNDS :: 64 +@(private) +SHA512_ROUNDS :: 80 + @(private) SHA256_CH :: #force_inline proc "contextless" (x, y, z: u32) -> u32 { return (x & y) ~ (~x & z) @@ -395,27 +400,29 @@ SHA512_F4 :: #force_inline proc "contextless" (x: u64) -> u64 { } @(private) -sha2_transf :: proc "contextless" (ctx: ^$T, data: []byte) { +sha2_transf :: proc "contextless" (ctx: ^$T, data: []byte) #no_bounds_check { when T == Context_256 { if is_hardware_accelerated_256() { sha256_transf_hw(ctx, data) return } - w: [64]u32 + w: [SHA256_ROUNDS]u32 wv: [8]u32 t1, t2: u32 + CURR_BLOCK_SIZE :: BLOCK_SIZE_256 } else when T == Context_512 { - w: [80]u64 + w: [SHA512_ROUNDS]u64 wv: [8]u64 t1, t2: u64 + CURR_BLOCK_SIZE :: BLOCK_SIZE_512 } data := data for len(data) >= CURR_BLOCK_SIZE { - for i := 0; i < 16; i += 1 { + for i in 0 ..< 16 { when T == Context_256 { w[i] = endian.unchecked_get_u32be(data[i * 4:]) } else when T == Context_512 { @@ -424,22 +431,22 @@ sha2_transf :: proc "contextless" (ctx: ^$T, data: []byte) { } when T == Context_256 { - for i := 16; i < 64; i += 1 { + for i in 16 ..< SHA256_ROUNDS { w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16] } } else when T == Context_512 { - for i := 16; i < 80; i += 1 { + for i in 16 ..< SHA512_ROUNDS { w[i] = SHA512_F4(w[i - 2]) + w[i - 7] + SHA512_F3(w[i - 15]) + w[i - 16] } } - for i := 0; i < 8; i += 1 { + for i in 0 ..< 8 { wv[i] = ctx.h[i] } when T == Context_256 { - for i := 0; i < 64; i += 1 { - t1 = wv[7] + SHA256_F2(wv[4]) + SHA256_CH(wv[4], wv[5], wv[6]) + sha256_k[i] + w[i] + for i in 0 ..< SHA256_ROUNDS { + t1 = wv[7] + SHA256_F2(wv[4]) + SHA256_CH(wv[4], wv[5], wv[6]) + SHA256_K[i] + w[i] t2 = SHA256_F1(wv[0]) + SHA256_MAJ(wv[0], wv[1], wv[2]) wv[7] = wv[6] wv[6] = wv[5] @@ -451,8 +458,8 @@ sha2_transf :: proc "contextless" (ctx: ^$T, data: []byte) { wv[0] = t1 + t2 } } else when T == Context_512 { - for i := 0; i < 80; i += 1 { - t1 = wv[7] + SHA512_F2(wv[4]) + SHA512_CH(wv[4], wv[5], wv[6]) + sha512_k[i] + w[i] + for i in 0 ..< SHA512_ROUNDS { + t1 = wv[7] + SHA512_F2(wv[4]) + SHA512_CH(wv[4], wv[5], wv[6]) + SHA512_K[i] + w[i] t2 = SHA512_F1(wv[0]) + SHA512_MAJ(wv[0], wv[1], wv[2]) wv[7] = wv[6] wv[6] = wv[5] @@ -465,7 +472,7 @@ sha2_transf :: proc "contextless" (ctx: ^$T, data: []byte) { } } - for i := 0; i < 8; i += 1 { + for i in 0 ..< 8 { ctx.h[i] += wv[i] } From dc94452fb99c889df78e992b59540032a2be6e15 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Thu, 14 Nov 2024 18:48:20 +0900 Subject: [PATCH 23/81] core/crypto/blake2: Add the ability to easily alter digest size --- core/crypto/blake2b/blake2b.odin | 9 ++++++--- core/crypto/blake2s/blake2s.odin | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/core/crypto/blake2b/blake2b.odin b/core/crypto/blake2b/blake2b.odin index 74396b103..16b19e349 100644 --- a/core/crypto/blake2b/blake2b.odin +++ b/core/crypto/blake2b/blake2b.odin @@ -18,7 +18,7 @@ package blake2b import "../_blake2" // DIGEST_SIZE is the BLAKE2b digest size in bytes. -DIGEST_SIZE :: 64 +DIGEST_SIZE :: _blake2.BLAKE2B_SIZE // BLOCK_SIZE is the BLAKE2b block size in bytes. BLOCK_SIZE :: _blake2.BLAKE2B_BLOCK_SIZE @@ -27,9 +27,12 @@ BLOCK_SIZE :: _blake2.BLAKE2B_BLOCK_SIZE Context :: _blake2.Blake2b_Context // init initializes a Context with the default BLAKE2b config. -init :: proc(ctx: ^Context) { +init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) { + if digest_size > 255 { + panic("blake2b: invalid digest size") + } cfg: _blake2.Blake2_Config - cfg.size = _blake2.BLAKE2B_SIZE + cfg.size = u8(digest_size) _blake2.init(ctx, &cfg) } diff --git a/core/crypto/blake2s/blake2s.odin b/core/crypto/blake2s/blake2s.odin index 339ddf027..f7d3abe03 100644 --- a/core/crypto/blake2s/blake2s.odin +++ b/core/crypto/blake2s/blake2s.odin @@ -18,7 +18,7 @@ package blake2s import "../_blake2" // DIGEST_SIZE is the BLAKE2s digest size in bytes. -DIGEST_SIZE :: 32 +DIGEST_SIZE :: _blake2.BLAKE2S_SIZE // BLOCK_SIZE is the BLAKE2s block size in bytes. BLOCK_SIZE :: _blake2.BLAKE2S_BLOCK_SIZE @@ -27,9 +27,12 @@ BLOCK_SIZE :: _blake2.BLAKE2S_BLOCK_SIZE Context :: _blake2.Blake2s_Context // init initializes a Context with the default BLAKE2s config. -init :: proc(ctx: ^Context) { +init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) { + if digest_size > 255 { + panic("blake2s: invalid digest size") + } cfg: _blake2.Blake2_Config - cfg.size = _blake2.BLAKE2S_SIZE + cfg.size = u8(digest_size) _blake2.init(ctx, &cfg) } From 2f301e46dc21e6a4660ac669a5ffb20e2f2297dd Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Sat, 18 Jan 2025 13:51:04 +0900 Subject: [PATCH 24/81] core/crypto: Switch to using `ensure` --- core/crypto/_aes/ct64/ct64_enc.odin | 4 +- core/crypto/_aes/ct64/ct64_keysched.odin | 4 +- core/crypto/_aes/ct64/ghash.odin | 5 +-- core/crypto/_aes/ct64/helpers.odin | 24 +++--------- core/crypto/_blake2/blake2.odin | 28 ++++++-------- core/crypto/_chacha20/chacha20.odin | 25 ++++++------ core/crypto/_edwards25519/edwards25519.odin | 8 +--- .../_edwards25519/edwards25519_scalar.odin | 8 +--- core/crypto/_fiat/field_poly1305/field.odin | 4 +- .../crypto/_fiat/field_scalar25519/field.odin | 9 ++--- core/crypto/_sha3/sha3.odin | 33 ++++++++-------- core/crypto/_sha3/sp800_185.odin | 20 +++++----- core/crypto/aead/low_level.odin | 12 ++---- core/crypto/aes/aes_ctr.odin | 12 ++---- core/crypto/aes/aes_ecb.odin | 16 +++----- core/crypto/aes/aes_gcm.odin | 36 +++++------------- core/crypto/aes/aes_gcm_hw_intel.odin | 2 +- core/crypto/blake2b/blake2b.odin | 5 +-- core/crypto/blake2s/blake2s.odin | 5 +-- core/crypto/chacha20/chacha20.odin | 16 +++----- .../chacha20poly1305/chacha20poly1305.odin | 28 ++++---------- core/crypto/deoxysii/deoxysii.odin | 33 +++++----------- core/crypto/ed25519/ed25519.odin | 32 ++++------------ core/crypto/hmac/hmac.odin | 13 +++---- core/crypto/kmac/kmac.odin | 12 ++---- core/crypto/legacy/keccak/keccak.odin | 18 ++++----- core/crypto/legacy/md5/md5.odin | 9 ++--- core/crypto/legacy/sha1/sha1.odin | 9 ++--- core/crypto/poly1305/poly1305.odin | 12 ++---- core/crypto/ristretto255/ristretto255.odin | 38 ++++++++----------- .../ristretto255/ristretto255_scalar.odin | 8 +--- core/crypto/sha2/sha2.odin | 11 ++---- core/crypto/siphash/siphash.odin | 17 +++------ core/crypto/sm3/sm3.odin | 11 ++---- core/crypto/x25519/x25519.odin | 12 ++---- core/crypto/x448/x448.odin | 12 ++---- 36 files changed, 188 insertions(+), 363 deletions(-) diff --git a/core/crypto/_aes/ct64/ct64_enc.odin b/core/crypto/_aes/ct64/ct64_enc.odin index e099b3eaf..bee6de722 100644 --- a/core/crypto/_aes/ct64/ct64_enc.odin +++ b/core/crypto/_aes/ct64/ct64_enc.odin @@ -23,9 +23,7 @@ package aes_ct64 add_round_key :: proc "contextless" (q: ^[8]u64, sk: []u64) #no_bounds_check { - if len(sk) < 8 { - panic_contextless("aes/ct64: invalid round key size") - } + ensure_contextless(len(sk) >= 8, "aes/ct64: invalid round key size") q[0] ~= sk[0] q[1] ~= sk[1] diff --git a/core/crypto/_aes/ct64/ct64_keysched.odin b/core/crypto/_aes/ct64/ct64_keysched.odin index 591bf53e6..0f00bba57 100644 --- a/core/crypto/_aes/ct64/ct64_keysched.odin +++ b/core/crypto/_aes/ct64/ct64_keysched.odin @@ -41,7 +41,7 @@ sub_word :: proc "contextless" (x: u32) -> u32 { } @(private, require_results) -keysched :: proc(comp_skey: []u64, key: []byte) -> int { +keysched :: proc "contextless" (comp_skey: []u64, key: []byte) -> int { num_rounds, key_len := 0, len(key) switch key_len { case _aes.KEY_SIZE_128: @@ -51,7 +51,7 @@ keysched :: proc(comp_skey: []u64, key: []byte) -> int { case _aes.KEY_SIZE_256: num_rounds = _aes.ROUNDS_256 case: - panic("crypto/aes: invalid AES key size") + panic_contextless("crypto/aes: invalid AES key size") } skey: [60]u32 = --- diff --git a/core/crypto/_aes/ct64/ghash.odin b/core/crypto/_aes/ct64/ghash.odin index fe6e364fc..0c885d8ba 100644 --- a/core/crypto/_aes/ct64/ghash.odin +++ b/core/crypto/_aes/ct64/ghash.odin @@ -63,9 +63,8 @@ rev64 :: proc "contextless" (x: u64) -> u64 { // Note: `dst` is both an input and an output, to support easy implementation // of GCM. ghash :: proc "contextless" (dst, key, data: []byte) { - if len(dst) != _aes.GHASH_BLOCK_SIZE || len(key) != _aes.GHASH_BLOCK_SIZE { - panic_contextless("aes/ghash: invalid dst or key size") - } + ensure_contextless(len(dst) == _aes.GHASH_BLOCK_SIZE) + ensure_contextless(len(key) == _aes.GHASH_BLOCK_SIZE) buf := data l := len(buf) diff --git a/core/crypto/_aes/ct64/helpers.odin b/core/crypto/_aes/ct64/helpers.odin index b26817cb3..4f2d9800c 100644 --- a/core/crypto/_aes/ct64/helpers.odin +++ b/core/crypto/_aes/ct64/helpers.odin @@ -31,41 +31,31 @@ and_interleaved :: #force_inline proc "contextless" (a0, a1, b0, b1: u64) -> (u6 } load_blockx1 :: proc "contextless" (q: ^[8]u64, src: []byte) { - if len(src) != _aes.BLOCK_SIZE { - panic_contextless("aes/ct64: invalid block size") - } + ensure_contextless(len(src) == _aes.BLOCK_SIZE, "aes/ct64: invalid block size") q[0], q[4] = #force_inline load_interleaved(src) orthogonalize(q) } store_blockx1 :: proc "contextless" (dst: []byte, q: ^[8]u64) { - if len(dst) != _aes.BLOCK_SIZE { - panic_contextless("aes/ct64: invalid block size") - } + ensure_contextless(len(dst) == _aes.BLOCK_SIZE, "aes/ct64: invalid block size") orthogonalize(q) #force_inline store_interleaved(dst, q[0], q[4]) } load_blocks :: proc "contextless" (q: ^[8]u64, src: [][]byte) { - if n := len(src); n > STRIDE || n == 0 { - panic_contextless("aes/ct64: invalid block(s) size") - } + ensure_contextless(len(src) == 0 || len(src) <= STRIDE, "aes/ct64: invalid block(s) size") for s, i in src { - if len(s) != _aes.BLOCK_SIZE { - panic_contextless("aes/ct64: invalid block size") - } + ensure_contextless(len(s) == _aes.BLOCK_SIZE, "aes/ct64: invalid block size") q[i], q[i + 4] = #force_inline load_interleaved(s) } orthogonalize(q) } store_blocks :: proc "contextless" (dst: [][]byte, q: ^[8]u64) { - if n := len(dst); n > STRIDE || n == 0 { - panic_contextless("aes/ct64: invalid block(s) size") - } + ensure_contextless(len(dst) == 0 || len(dst) <= STRIDE, "aes/ct64: invalid block(s) size") orthogonalize(q) for d, i in dst { @@ -73,9 +63,7 @@ store_blocks :: proc "contextless" (dst: [][]byte, q: ^[8]u64) { if d == nil { break } - if len(d) != _aes.BLOCK_SIZE { - panic_contextless("aes/ct64: invalid block size") - } + ensure_contextless(len(d) == _aes.BLOCK_SIZE, "aes/ct64: invalid block size") #force_inline store_interleaved(d, q[i], q[i + 4]) } } diff --git a/core/crypto/_blake2/blake2.odin b/core/crypto/_blake2/blake2.odin index a012b7e70..89fbe3a7a 100644 --- a/core/crypto/_blake2/blake2.odin +++ b/core/crypto/_blake2/blake2.odin @@ -18,6 +18,8 @@ BLAKE2S_SIZE :: 32 BLAKE2B_BLOCK_SIZE :: 128 BLAKE2B_SIZE :: 64 +MAX_SIZE :: 255 + Blake2s_Context :: struct { h: [8]u32, t: [2]u32, @@ -82,16 +84,13 @@ BLAKE2B_IV := [8]u64 { 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, } -init :: proc(ctx: ^$T, cfg: ^Blake2_Config) { +init :: proc "contextless" (ctx: ^$T, cfg: ^Blake2_Config) { when T == Blake2s_Context { max_size :: BLAKE2S_SIZE } else when T == Blake2b_Context { max_size :: BLAKE2B_SIZE } - - if cfg.size > max_size { - panic("blake2: requested output size exceeeds algorithm max") - } + ensure_contextless(cfg.size <= max_size, "blake2: requested output size exceeeds algorithm max") // To save having to allocate a scratch buffer, use the internal // data buffer (`ctx.x`), as it is exactly the correct size. @@ -167,8 +166,8 @@ init :: proc(ctx: ^$T, cfg: ^Blake2_Config) { ctx.is_initialized = true } -update :: proc(ctx: ^$T, p: []byte) { - assert(ctx.is_initialized) +update :: proc "contextless" (ctx: ^$T, p: []byte) { + ensure_contextless(ctx.is_initialized) p := p when T == Blake2s_Context { @@ -195,8 +194,8 @@ update :: proc(ctx: ^$T, p: []byte) { ctx.nx += copy(ctx.x[ctx.nx:], p) } -final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) { - assert(ctx.is_initialized) +final :: proc "contextless" (ctx: ^$T, hash: []byte, finalize_clone: bool = false) { + ensure_contextless(ctx.is_initialized) ctx := ctx if finalize_clone { @@ -206,24 +205,19 @@ final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) { } defer(reset(ctx)) + ensure_contextless(len(hash) >= int(ctx.size), "crypto/blake2: invalid destination digest size") when T == Blake2s_Context { - if len(hash) < int(ctx.size) { - panic("crypto/blake2s: invalid destination digest size") - } blake2s_final(ctx, hash) } else when T == Blake2b_Context { - if len(hash) < int(ctx.size) { - panic("crypto/blake2b: invalid destination digest size") - } blake2b_final(ctx, hash) } } -clone :: proc(ctx, other: ^$T) { +clone :: proc "contextless" (ctx, other: ^$T) { ctx^ = other^ } -reset :: proc(ctx: ^$T) { +reset :: proc "contextless" (ctx: ^$T) { if !ctx.is_initialized { return } diff --git a/core/crypto/_chacha20/chacha20.odin b/core/crypto/_chacha20/chacha20.odin index c7812f7ab..1a4b5a507 100644 --- a/core/crypto/_chacha20/chacha20.odin +++ b/core/crypto/_chacha20/chacha20.odin @@ -45,9 +45,8 @@ Context :: struct { // derivation is expected to be handled by the caller, so that the // HChaCha call can be suitably accelerated. init :: proc "contextless" (ctx: ^Context, key, iv: []byte, is_xchacha: bool) { - if len(key) != KEY_SIZE || len(iv) != IV_SIZE { - panic_contextless("chacha20: invalid key or IV size") - } + ensure_contextless(len(key) == KEY_SIZE, "chacha20: invalid key size") + ensure_contextless(len(iv) == IV_SIZE, "chacha20: invalid key size") k, n := key, iv @@ -75,12 +74,10 @@ init :: proc "contextless" (ctx: ^Context, key, iv: []byte, is_xchacha: bool) { // seek seeks the (X)ChaCha20 stream counter to the specified block. seek :: proc(ctx: ^Context, block_nr: u64) { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) if ctx._is_ietf_flavor { - if block_nr > MAX_CTR_IETF { - panic("crypto/chacha20: attempted to seek past maximum counter") - } + ensure(block_nr <= MAX_CTR_IETF, "crypto/chacha20: attempted to seek past maximum counter") } else { ctx._s[13] = u32(block_nr >> 32) } @@ -101,7 +98,7 @@ check_counter_limit :: proc(ctx: ^Context, nr_blocks: int) { // Enforce the maximum consumed keystream per IV. // // While all modern "standard" definitions of ChaCha20 use - // the IETF 32-bit counter, for XChaCha20 most common + // the IETF 32-bit counter, for XChaCha20 historical // implementations allow for a 64-bit counter. // // Honestly, the answer here is "use a MRAE primitive", but @@ -109,14 +106,14 @@ check_counter_limit :: proc(ctx: ^Context, nr_blocks: int) { ERR_CTR_EXHAUSTED :: "crypto/chacha20: maximum (X)ChaCha20 keystream per IV reached" + ctr_ok: bool if ctx._is_ietf_flavor { - if u64(ctx._s[12]) + u64(nr_blocks) > MAX_CTR_IETF { - panic(ERR_CTR_EXHAUSTED) - } + ctr_ok = u64(ctx._s[12]) + u64(nr_blocks) <= MAX_CTR_IETF } else { ctr := (u64(ctx._s[13]) << 32) | u64(ctx._s[12]) - if _, carry := bits.add_u64(ctr, u64(nr_blocks), 0); carry != 0 { - panic(ERR_CTR_EXHAUSTED) - } + _, carry := bits.add_u64(ctr, u64(nr_blocks), 0) + ctr_ok = carry == 0 } + + ensure(ctr_ok, "crypto/chacha20: maximum (X)ChaCha20 keystream per IV reached") } diff --git a/core/crypto/_edwards25519/edwards25519.odin b/core/crypto/_edwards25519/edwards25519.odin index 0234ba05a..d6f01d497 100644 --- a/core/crypto/_edwards25519/edwards25519.odin +++ b/core/crypto/_edwards25519/edwards25519.odin @@ -108,9 +108,7 @@ ge_set :: proc "contextless" (ge, a: ^Group_Element) { @(require_results) ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool { - if len(b) != 32 { - panic_contextless("edwards25519: invalid group element size") - } + ensure_contextless(len(b) == 32, "edwards25519: invalid group element size") b_ := (^[32]byte)(raw_data(b)) // Do the work in a scratch element, so that ge is unchanged on @@ -167,9 +165,7 @@ ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool { } ge_bytes :: proc "contextless" (ge: ^Group_Element, dst: []byte) { - if len(dst) != 32 { - panic_contextless("edwards25519: invalid group element size") - } + ensure_contextless(len(dst) == 32, "edwards25519: invalid group element size") dst_ := (^[32]byte)(raw_data(dst)) // Convert the element to affine (x, y) representation. diff --git a/core/crypto/_edwards25519/edwards25519_scalar.odin b/core/crypto/_edwards25519/edwards25519_scalar.odin index f650b27d3..68c79a6e8 100644 --- a/core/crypto/_edwards25519/edwards25519_scalar.odin +++ b/core/crypto/_edwards25519/edwards25519_scalar.odin @@ -24,17 +24,13 @@ sc_set_u64 :: proc "contextless" (sc: ^Scalar, i: u64) { @(require_results) sc_set_bytes :: proc "contextless" (sc: ^Scalar, b: []byte) -> bool { - if len(b) != 32 { - panic_contextless("edwards25519: invalid scalar size") - } + ensure_contextless(len(b) == 32, "edwards25519: invalid scalar size") b_ := (^[32]byte)(raw_data(b)) return field.fe_from_bytes(sc, b_) } sc_set_bytes_rfc8032 :: proc "contextless" (sc: ^Scalar, b: []byte) { - if len(b) != 32 { - panic_contextless("edwards25519: invalid scalar size") - } + ensure_contextless(len(b) == 32, "edwards25519: invalid scalar size") b_ := (^[32]byte)(raw_data(b)) field.fe_from_bytes_rfc8032(sc, b_) } diff --git a/core/crypto/_fiat/field_poly1305/field.odin b/core/crypto/_fiat/field_poly1305/field.odin index c888f1e8b..caaece98e 100644 --- a/core/crypto/_fiat/field_poly1305/field.odin +++ b/core/crypto/_fiat/field_poly1305/field.odin @@ -28,9 +28,7 @@ fe_from_bytes :: #force_inline proc "contextless" ( // makes implementing the actual MAC block processing considerably // neater. - if len(arg1) != 16 { - panic_contextless("poly1305: invalid field element size") - } + ensure_contextless(len(arg1) == 16, "poly1305: invalid field element size") // While it may be unwise to do deserialization here on our // own when fiat-crypto provides equivalent functionality, diff --git a/core/crypto/_fiat/field_scalar25519/field.odin b/core/crypto/_fiat/field_scalar25519/field.odin index 430891641..933637c54 100644 --- a/core/crypto/_fiat/field_scalar25519/field.odin +++ b/core/crypto/_fiat/field_scalar25519/field.odin @@ -94,9 +94,8 @@ fe_from_bytes_wide :: proc "contextless" ( @(private) _fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element, arg1: []byte) { // INVARIANT: len(arg1) < 32. - if len(arg1) >= 32 { - panic_contextless("edwards25519: oversized short scalar") - } + ensure_contextless(len(arg1) < 32, "edwards25519: oversized short scalar") + tmp: [32]byte copy(tmp[:], arg1) @@ -105,9 +104,7 @@ _fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Eleme } fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { - if len(out1) != 32 { - panic_contextless("edwards25519: oversized scalar output buffer") - } + ensure_contextless(len(out1) == 32, "edwards25519: oversized scalar output buffer") tmp: Non_Montgomery_Domain_Field_Element fe_from_montgomery(&tmp, arg1) diff --git a/core/crypto/_sha3/sha3.odin b/core/crypto/_sha3/sha3.odin index 98e15b29d..52b3fbda9 100644 --- a/core/crypto/_sha3/sha3.odin +++ b/core/crypto/_sha3/sha3.odin @@ -122,7 +122,7 @@ keccakf :: proc "contextless" (st: ^[25]u64) { } } -init :: proc(ctx: ^Context) { +init :: proc "contextless" (ctx: ^Context) { for i := 0; i < 25; i += 1 { ctx.st.q[i] = 0 } @@ -133,9 +133,9 @@ init :: proc(ctx: ^Context) { ctx.is_finalized = false } -update :: proc(ctx: ^Context, data: []byte) { - assert(ctx.is_initialized) - assert(!ctx.is_finalized) +update :: proc "contextless" (ctx: ^Context, data: []byte) { + ensure_contextless(ctx.is_initialized) + ensure_contextless(!ctx.is_finalized) j := ctx.pt for i := 0; i < len(data); i += 1 { @@ -149,12 +149,9 @@ update :: proc(ctx: ^Context, data: []byte) { ctx.pt = j } -final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { - assert(ctx.is_initialized) - - if len(hash) < ctx.mdlen { - panic("crypto/sha3: invalid destination digest size") - } +final :: proc "contextless" (ctx: ^Context, hash: []byte, finalize_clone: bool = false) { + ensure_contextless(ctx.is_initialized) + ensure_contextless(len(hash) >= ctx.mdlen, "crypto/sha3: invalid destination digest size") ctx := ctx if finalize_clone { @@ -173,11 +170,11 @@ final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { } } -clone :: proc(ctx, other: ^Context) { +clone :: proc "contextless" (ctx, other: ^Context) { ctx^ = other^ } -reset :: proc(ctx: ^Context) { +reset :: proc "contextless" (ctx: ^Context) { if !ctx.is_initialized { return } @@ -185,9 +182,9 @@ reset :: proc(ctx: ^Context) { mem.zero_explicit(ctx, size_of(ctx^)) } -shake_xof :: proc(ctx: ^Context) { - assert(ctx.is_initialized) - assert(!ctx.is_finalized) +shake_xof :: proc "contextless" (ctx: ^Context) { + ensure_contextless(ctx.is_initialized) + ensure_contextless(!ctx.is_finalized) ctx.st.b[ctx.pt] ~= ctx.dsbyte ctx.st.b[ctx.rsiz - 1] ~= 0x80 @@ -197,9 +194,9 @@ shake_xof :: proc(ctx: ^Context) { ctx.is_finalized = true // No more absorb, unlimited squeeze. } -shake_out :: proc(ctx: ^Context, hash: []byte) { - assert(ctx.is_initialized) - assert(ctx.is_finalized) +shake_out :: proc "contextless" (ctx: ^Context, hash: []byte) { + ensure_contextless(ctx.is_initialized) + ensure_contextless(ctx.is_finalized) j := ctx.pt for i := 0; i < len(hash); i += 1 { diff --git a/core/crypto/_sha3/sp800_185.odin b/core/crypto/_sha3/sp800_185.odin index a08cb1d11..8390d8490 100644 --- a/core/crypto/_sha3/sp800_185.odin +++ b/core/crypto/_sha3/sp800_185.odin @@ -3,7 +3,7 @@ package _sha3 import "core:encoding/endian" import "core:math/bits" -init_cshake :: proc(ctx: ^Context, n, s: []byte, sec_strength: int) { +init_cshake :: proc "contextless" (ctx: ^Context, n, s: []byte, sec_strength: int) { ctx.mdlen = sec_strength / 8 // No domain separator is equivalent to vanilla SHAKE. @@ -18,7 +18,7 @@ init_cshake :: proc(ctx: ^Context, n, s: []byte, sec_strength: int) { bytepad(ctx, [][]byte{n, s}, rate_cshake(sec_strength)) } -final_cshake :: proc(ctx: ^Context, dst: []byte, finalize_clone: bool = false) { +final_cshake :: proc "contextless" (ctx: ^Context, dst: []byte, finalize_clone: bool = false) { ctx := ctx if finalize_clone { tmp_ctx: Context @@ -32,7 +32,7 @@ final_cshake :: proc(ctx: ^Context, dst: []byte, finalize_clone: bool = false) { shake_out(ctx, dst) } -rate_cshake :: #force_inline proc(sec_strength: int) -> int { +rate_cshake :: #force_inline proc "contextless" (sec_strength: int) -> int { switch sec_strength { case 128: return RATE_128 @@ -40,7 +40,7 @@ rate_cshake :: #force_inline proc(sec_strength: int) -> int { return RATE_256 } - panic("crypto/sha3: invalid security strength") + panic_contextless("crypto/sha3: invalid security strength") } // right_encode and left_encode are defined to support 0 <= x < 2^2040 @@ -55,7 +55,7 @@ rate_cshake :: #force_inline proc(sec_strength: int) -> int { @(private, rodata) _PAD: [RATE_128]byte // Biggest possible value of w per spec. -bytepad :: proc(ctx: ^Context, x_strings: [][]byte, w: int) { +bytepad :: proc "contextless" (ctx: ^Context, x_strings: [][]byte, w: int) { // 1. z = left_encode(w) || X. z_hi: u64 z_lo := left_right_encode(ctx, 0, u64(w), true) @@ -70,9 +70,7 @@ bytepad :: proc(ctx: ^Context, x_strings: [][]byte, w: int) { // This isn't actually possible, at least with the currently // defined SP 800-185 routines. - if carry != 0 { - panic("crypto/sha3: bytepad input length overflow") - } + ensure_contextless(carry == 0, "crypto/sha3: bytepad input length overflow") } // We skip this step as we are doing a byte-oriented implementation @@ -95,7 +93,7 @@ bytepad :: proc(ctx: ^Context, x_strings: [][]byte, w: int) { } } -encode_string :: #force_inline proc(ctx: ^Context, s: []byte) -> (u64, u64) { +encode_string :: #force_inline proc "contextless" (ctx: ^Context, s: []byte) -> (u64, u64) { l := encode_byte_len(ctx, len(s), true) // left_encode update(ctx, s) @@ -104,13 +102,13 @@ encode_string :: #force_inline proc(ctx: ^Context, s: []byte) -> (u64, u64) { return hi, lo } -encode_byte_len :: #force_inline proc(ctx: ^Context, l: int, is_left: bool) -> u64 { +encode_byte_len :: #force_inline proc "contextless" (ctx: ^Context, l: int, is_left: bool) -> u64 { hi, lo := bits.mul_u64(u64(l), 8) return left_right_encode(ctx, hi, lo, is_left) } @(private) -left_right_encode :: proc(ctx: ^Context, hi, lo: u64, is_left: bool) -> u64 { +left_right_encode :: proc "contextless" (ctx: ^Context, hi, lo: u64, is_left: bool) -> u64 { HI_OFFSET :: 1 LO_OFFSET :: HI_OFFSET + 8 RIGHT_OFFSET :: LO_OFFSET + 8 diff --git a/core/crypto/aead/low_level.odin b/core/crypto/aead/low_level.odin index e90d07bc6..c80574a0d 100644 --- a/core/crypto/aead/low_level.odin +++ b/core/crypto/aead/low_level.odin @@ -128,9 +128,7 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementat reset(ctx) } - if len(key) != KEY_SIZES[algorithm] { - panic("crypto/aead: invalid key size") - } + ensure(len(key) == KEY_SIZES[algorithm], "crypto/aead: invalid key size") // Directly specialize the union by setting the type ID (save a copy). reflect.set_union_variant_typeid( @@ -167,9 +165,7 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementat // // dst and plaintext MUST alias exactly or not at all. seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { - if len(tag) != TAG_SIZES[ctx._algo] { - panic("crypto/aead: invalid tag size") - } + ensure(len(tag) == TAG_SIZES[ctx._algo], "crypto/aead: invalid tag size") switch &impl in ctx._impl { case aes.Context_GCM: @@ -193,9 +189,7 @@ seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { // dst and plaintext MUST alias exactly or not at all. @(require_results) open_ctx :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { - if len(tag) != TAG_SIZES[ctx._algo] { - panic("crypto/aead: invalid tag size") - } + ensure(len(tag) == TAG_SIZES[ctx._algo], "crypto/aead: invalid tag size") switch &impl in ctx._impl { case aes.Context_GCM: diff --git a/core/crypto/aes/aes_ctr.odin b/core/crypto/aes/aes_ctr.odin index 20b75e57f..a74133235 100644 --- a/core/crypto/aes/aes_ctr.odin +++ b/core/crypto/aes/aes_ctr.odin @@ -21,9 +21,7 @@ Context_CTR :: struct { // init_ctr initializes a Context_CTR with the provided key and IV. init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := DEFAULT_IMPLEMENTATION) { - if len(iv) != CTR_IV_SIZE { - panic("crypto/aes: invalid CTR IV size") - } + ensure(len(iv) == CTR_IV_SIZE, "crypto/aes: invalid CTR IV size") init_impl(&ctx._impl, key, impl) ctx._off = BLOCK_SIZE @@ -36,16 +34,14 @@ init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := DEFAULT_IMPLEMENTAT // keystream, and writes the resulting output to dst. dst and src MUST // alias exactly or not at all. xor_bytes_ctr :: proc(ctx: ^Context_CTR, dst, src: []byte) { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) src, dst := src, dst if dst_len := len(dst); dst_len < len(src) { src = src[:dst_len] } - if bytes.alias_inexactly(dst, src) { - panic("crypto/aes: dst and src alias inexactly") - } + ensure(!bytes.alias_inexactly(dst, src), "crypto/aes: dst and src alias inexactly") #no_bounds_check for remaining := len(src); remaining > 0; { // Process multiple blocks at once @@ -82,7 +78,7 @@ xor_bytes_ctr :: proc(ctx: ^Context_CTR, dst, src: []byte) { // keystream_bytes_ctr fills dst with the raw AES-CTR keystream output. keystream_bytes_ctr :: proc(ctx: ^Context_CTR, dst: []byte) { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) dst := dst #no_bounds_check for remaining := len(dst); remaining > 0; { diff --git a/core/crypto/aes/aes_ecb.odin b/core/crypto/aes/aes_ecb.odin index 32476006c..cac62de5d 100644 --- a/core/crypto/aes/aes_ecb.odin +++ b/core/crypto/aes/aes_ecb.odin @@ -19,11 +19,9 @@ init_ecb :: proc(ctx: ^Context_ECB, key: []byte, impl := DEFAULT_IMPLEMENTATION) // encrypt_ecb encrypts the BLOCK_SIZE buffer src, and writes the result to dst. encrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) { - assert(ctx._is_initialized) - - if len(dst) != BLOCK_SIZE || len(src) != BLOCK_SIZE { - panic("crypto/aes: invalid buffer size(s)") - } + ensure(ctx._is_initialized) + ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid dst size") + ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid src size") switch &impl in ctx._impl { case ct64.Context: @@ -35,11 +33,9 @@ encrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) { // decrypt_ecb decrypts the BLOCK_SIZE buffer src, and writes the result to dst. decrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) { - assert(ctx._is_initialized) - - if len(dst) != BLOCK_SIZE || len(src) != BLOCK_SIZE { - panic("crypto/aes: invalid buffer size(s)") - } + ensure(ctx._is_initialized) + ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid dst size") + ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid src size") switch &impl in ctx._impl { case ct64.Context: diff --git a/core/crypto/aes/aes_gcm.odin b/core/crypto/aes/aes_gcm.odin index 8616821ce..d349aa353 100644 --- a/core/crypto/aes/aes_gcm.odin +++ b/core/crypto/aes/aes_gcm.odin @@ -36,15 +36,11 @@ init_gcm :: proc(ctx: ^Context_GCM, key: []byte, impl := DEFAULT_IMPLEMENTATION) // // dst and plaintext MUST alias exactly or not at all. seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, iv, aad, plaintext: []byte) { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) gcm_validate_common_slice_sizes(tag, iv, aad, plaintext) - if len(dst) != len(plaintext) { - panic("crypto/aes: invalid destination ciphertext size") - } - if bytes.alias_inexactly(dst, plaintext) { - panic("crypto/aes: dst and plaintext alias inexactly") - } + ensure(len(dst) == len(plaintext), "crypto/aes: invalid destination ciphertext size") + ensure(!bytes.alias_inexactly(dst, plaintext), "crypto/aes: dst and plaintext alias inexactly") if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw { gcm_seal_hw(&impl, dst, tag, iv, aad, plaintext) @@ -76,15 +72,11 @@ seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, iv, aad, plaintext: []byte) { // dst and plaintext MUST alias exactly or not at all. @(require_results) open_gcm :: proc(ctx: ^Context_GCM, dst, iv, aad, ciphertext, tag: []byte) -> bool { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) gcm_validate_common_slice_sizes(tag, iv, aad, ciphertext) - if len(dst) != len(ciphertext) { - panic("crypto/aes: invalid destination plaintext size") - } - if bytes.alias_inexactly(dst, ciphertext) { - panic("crypto/aes: dst and ciphertext alias inexactly") - } + ensure(len(dst) == len(ciphertext), "crypto/aes: invalid destination plaintext size") + ensure(!bytes.alias_inexactly(dst, ciphertext), "crypto/aes: dst and ciphertext alias inexactly") if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw { return gcm_open_hw(&impl, dst, iv, aad, ciphertext, tag) @@ -122,21 +114,13 @@ reset_gcm :: proc "contextless" (ctx: ^Context_GCM) { @(private = "file") gcm_validate_common_slice_sizes :: proc(tag, iv, aad, text: []byte) { - if len(tag) != GCM_TAG_SIZE { - panic("crypto/aes: invalid GCM tag size") - } + ensure(len(tag) == GCM_TAG_SIZE, "crypto/aes: invalid GCM tag size") // The specification supports IVs in the range [1, 2^64) bits. - if l := len(iv); l == 0 || u64(l) >= GCM_IV_SIZE_MAX { - panic("crypto/aes: invalid GCM IV size") - } + ensure(len(iv) == 0 || u64(len(iv)) <= GCM_IV_SIZE_MAX, "crypto/aes: invalid GCM IV size") - if aad_len := u64(len(aad)); aad_len > GCM_A_MAX { - panic("crypto/aes: oversized GCM aad") - } - if text_len := u64(len(text)); text_len > GCM_P_MAX { - panic("crypto/aes: oversized GCM src data") - } + ensure(u64(len(aad)) <= GCM_A_MAX, "crypto/aes: oversized GCM aad") + ensure(u64(len(text)) <= GCM_P_MAX, "crypto/aes: oversized GCM data") } @(private = "file") diff --git a/core/crypto/aes/aes_gcm_hw_intel.odin b/core/crypto/aes/aes_gcm_hw_intel.odin index 4cb5ab3b2..3982d1452 100644 --- a/core/crypto/aes/aes_gcm_hw_intel.odin +++ b/core/crypto/aes/aes_gcm_hw_intel.odin @@ -235,7 +235,7 @@ gctr_hw :: proc( // BUG: Sticking this in gctr_hw (like the other implementations) crashes // the compiler. // -// src/check_expr.cpp(7892): Assertion Failure: `c->curr_proc_decl->entity` +// src/check_expr.cpp(8104): Assertion Failure: `c->curr_proc_decl->entity` @(private = "file", enable_target_feature = "sse4.1") hw_inc_ctr32 :: #force_inline proc "contextless" (src: ^x86.__m128i, ctr: u32) -> (x86.__m128i, u32) { ret := x86._mm_insert_epi32(src^, i32(intrinsics.byte_swap(ctr)), 3) diff --git a/core/crypto/blake2b/blake2b.odin b/core/crypto/blake2b/blake2b.odin index 16b19e349..3b3fc6649 100644 --- a/core/crypto/blake2b/blake2b.odin +++ b/core/crypto/blake2b/blake2b.odin @@ -28,9 +28,8 @@ Context :: _blake2.Blake2b_Context // init initializes a Context with the default BLAKE2b config. init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) { - if digest_size > 255 { - panic("blake2b: invalid digest size") - } + ensure(digest_size <= _blake2.MAX_SIZE, "crypto/blake2b: invalid digest size") + cfg: _blake2.Blake2_Config cfg.size = u8(digest_size) _blake2.init(ctx, &cfg) diff --git a/core/crypto/blake2s/blake2s.odin b/core/crypto/blake2s/blake2s.odin index f7d3abe03..9bbd44541 100644 --- a/core/crypto/blake2s/blake2s.odin +++ b/core/crypto/blake2s/blake2s.odin @@ -28,9 +28,8 @@ Context :: _blake2.Blake2s_Context // init initializes a Context with the default BLAKE2s config. init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) { - if digest_size > 255 { - panic("blake2s: invalid digest size") - } + ensure(digest_size <= _blake2.MAX_SIZE, "crypto/blake2s: invalid digest size") + cfg: _blake2.Blake2_Config cfg.size = u8(digest_size) _blake2.init(ctx, &cfg) diff --git a/core/crypto/chacha20/chacha20.odin b/core/crypto/chacha20/chacha20.odin index dfab2bc65..e8d67eb3e 100644 --- a/core/crypto/chacha20/chacha20.odin +++ b/core/crypto/chacha20/chacha20.odin @@ -27,12 +27,8 @@ Context :: struct { // init inititializes a Context for ChaCha20 or XChaCha20 with the provided // key and iv. init :: proc(ctx: ^Context, key, iv: []byte, impl := DEFAULT_IMPLEMENTATION) { - if len(key) != KEY_SIZE { - panic("crypto/chacha20: invalid (X)ChaCha20 key size") - } - if l := len(iv); l != IV_SIZE && l != XIV_SIZE { - panic("crypto/chacha20: invalid (X)ChaCha20 IV size") - } + ensure(len(key) == KEY_SIZE, "crypto/chacha20: invalid (X)ChaCha20 key size") + ensure(len(iv) == IV_SIZE || len(iv) == XIV_SIZE, "crypto/chacha20: invalid (X)ChaCha20 IV size") k, n := key, iv @@ -67,16 +63,14 @@ seek :: proc(ctx: ^Context, block_nr: u64) { // keystream, and writes the resulting output to dst. Dst and src MUST // alias exactly or not at all. xor_bytes :: proc(ctx: ^Context, dst, src: []byte) { - assert(ctx._state._is_initialized) + ensure(ctx._state._is_initialized) src, dst := src, dst if dst_len := len(dst); dst_len < len(src) { src = src[:dst_len] } - if bytes.alias_inexactly(dst, src) { - panic("crypto/chacha20: dst and src alias inexactly") - } + ensure(!bytes.alias_inexactly(dst, src), "crypto/chacha20: dst and src alias inexactly") st := &ctx._state #no_bounds_check for remaining := len(src); remaining > 0; { @@ -114,7 +108,7 @@ xor_bytes :: proc(ctx: ^Context, dst, src: []byte) { // keystream_bytes fills dst with the raw (X)ChaCha20 keystream output. keystream_bytes :: proc(ctx: ^Context, dst: []byte) { - assert(ctx._state._is_initialized) + ensure(ctx._state._is_initialized) dst, st := dst, &ctx._state #no_bounds_check for remaining := len(dst); remaining > 0; { diff --git a/core/crypto/chacha20poly1305/chacha20poly1305.odin b/core/crypto/chacha20poly1305/chacha20poly1305.odin index 3ef2a5586..6706b3820 100644 --- a/core/crypto/chacha20poly1305/chacha20poly1305.odin +++ b/core/crypto/chacha20poly1305/chacha20poly1305.odin @@ -29,13 +29,9 @@ _P_MAX :: 64 * 0xffffffff // 64 * (2^32-1) @(private) _validate_common_slice_sizes :: proc (tag, iv, aad, text: []byte, is_xchacha: bool) { - if len(tag) != TAG_SIZE { - panic("crypto/chacha20poly1305: invalid destination tag size") - } expected_iv_len := is_xchacha ? XIV_SIZE : IV_SIZE - if len(iv) != expected_iv_len { - panic("crypto/chacha20poly1305: invalid IV size") - } + ensure(len(tag) == TAG_SIZE, "crypto/chacha20poly1305: invalid destination tag size") + ensure(len(iv) == expected_iv_len, "crypto/chacha20poly1305: invalid IV size") #assert(size_of(int) == 8 || size_of(int) <= 4) when size_of(int) == 8 { @@ -45,9 +41,7 @@ _validate_common_slice_sizes :: proc (tag, iv, aad, text: []byte, is_xchacha: bo // A_MAX is limited by size_of(int), so there is no need to // enforce it. P_MAX only needs to be checked on 64-bit targets, // for reasons that should be obvious. - if text_len := len(text); text_len > _P_MAX { - panic("crypto/chacha20poly1305: oversized src data") - } + ensure(len(text) <= _P_MAX, "crypto/chacha20poly1305: oversized src data") } } @@ -71,9 +65,7 @@ Context :: struct { // init initializes a Context with the provided key, for AEAD_CHACHA20_POLY1305. init :: proc(ctx: ^Context, key: []byte, impl := chacha20.DEFAULT_IMPLEMENTATION) { - if len(key) != KEY_SIZE { - panic("crypto/chacha20poly1305: invalid key size") - } + ensure(len(key) == KEY_SIZE, "crypto/chacha20poly1305: invalid key size") copy(ctx._key[:], key) ctx._impl = impl @@ -96,13 +88,11 @@ init_xchacha :: proc(ctx: ^Context, key: []byte, impl := chacha20.DEFAULT_IMPLEM // // dst and plaintext MUST alias exactly or not at all. seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) ciphertext := dst _validate_common_slice_sizes(tag, iv, aad, plaintext, ctx._is_xchacha) - if len(ciphertext) != len(plaintext) { - panic("crypto/chacha20poly1305: invalid destination ciphertext size") - } + ensure(len(ciphertext) == len(plaintext), "crypto/chacha20poly1305: invalid destination ciphertext size") stream_ctx: chacha20.Context = --- chacha20.init(&stream_ctx, ctx._key[:],iv, ctx._impl) @@ -153,13 +143,11 @@ seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { // dst and plaintext MUST alias exactly or not at all. @(require_results) open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) plaintext := dst _validate_common_slice_sizes(tag, iv, aad, ciphertext, ctx._is_xchacha) - if len(ciphertext) != len(plaintext) { - panic("crypto/chacha20poly1305: invalid destination plaintext size") - } + ensure(len(ciphertext) == len(plaintext), "crypto/chacha20poly1305: invalid destination plaintext size") // Note: Unlike encrypt, this can fail early, so use defer for // sanitization rather than assuming control flow reaches certain diff --git a/core/crypto/deoxysii/deoxysii.odin b/core/crypto/deoxysii/deoxysii.odin index 2aff1d8b4..cead770e2 100644 --- a/core/crypto/deoxysii/deoxysii.odin +++ b/core/crypto/deoxysii/deoxysii.odin @@ -76,13 +76,8 @@ Context :: struct { @(private) _validate_common_slice_sizes :: proc (ctx: ^Context, tag, iv, aad, text: []byte) { - if len(tag) != TAG_SIZE { - panic("crypto/deoxysii: invalid tag size") - } - - if len(iv) != IV_SIZE { - panic("crypto/deoxysii: invalid IV size") - } + ensure(len(tag) == TAG_SIZE, "crypto/deoxysii: invalid tag size") + ensure(len(iv) == IV_SIZE, "crypto/deoxysii: invalid IV size") #assert(size_of(int) == 8 || size_of(int) <= 4) // For the nonce-misuse resistant mode, the total size of the @@ -95,9 +90,7 @@ _validate_common_slice_sizes :: proc (ctx: ^Context, tag, iv, aad, text: []byte) // init initializes a Context with the provided key. init :: proc(ctx: ^Context, key: []byte, impl := aes.DEFAULT_IMPLEMENTATION) { - if len(key) != KEY_SIZE { - panic("crypto/deoxysii: invalid key size") - } + ensure(len(key) == KEY_SIZE, "crypto/deoxysii: invalid key size") ctx._impl = impl if ctx._impl == .Hardware && !is_hardware_accelerated() { @@ -114,15 +107,11 @@ init :: proc(ctx: ^Context, key: []byte, impl := aes.DEFAULT_IMPLEMENTATION) { // // dst and plaintext MUST alias exactly or not at all. seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) _validate_common_slice_sizes(ctx, tag, iv, aad, plaintext) - if len(dst) != len(plaintext) { - panic("crypto/deoxysii: invalid destination ciphertext size") - } - if bytes.alias_inexactly(dst, plaintext) { - panic("crypto/deoxysii: dst and plaintext alias inexactly") - } + ensure(len(dst) == len(plaintext), "crypto/deoxysii: invalid destination ciphertext size") + ensure(!bytes.alias_inexactly(dst, plaintext), "crypto/deoxysii: dst and plaintext alias inexactly") switch ctx._impl { case .Hardware: @@ -140,15 +129,11 @@ seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { // dst and plaintext MUST alias exactly or not at all. @(require_results) open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) _validate_common_slice_sizes(ctx, tag, iv, aad, ciphertext) - if len(dst) != len(ciphertext) { - panic("crypto/deoxysii: invalid destination plaintext size") - } - if bytes.alias_inexactly(dst, ciphertext) { - panic("crypto/deoxysii: dst and ciphertext alias inexactly") - } + ensure(len(dst) == len(ciphertext), "crypto/deoxysii: invalid destination plaintext size") + ensure(!bytes.alias_inexactly(dst, ciphertext), "crypto/deoxysii: dst and ciphertext alias inexactly") ok: bool switch ctx._impl { diff --git a/core/crypto/ed25519/ed25519.odin b/core/crypto/ed25519/ed25519.odin index 460a19563..deeb80685 100644 --- a/core/crypto/ed25519/ed25519.odin +++ b/core/crypto/ed25519/ed25519.odin @@ -81,12 +81,8 @@ private_key_set_bytes :: proc(priv_key: ^Private_Key, b: []byte) -> bool { // private_key_bytes sets dst to byte-encoding of priv_key. private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { - if !priv_key._is_initialized { - panic("crypto/ed25519: uninitialized private key") - } - if len(dst) != PRIVATE_KEY_SIZE { - panic("crypto/ed25519: invalid destination size") - } + ensure(priv_key._is_initialized, "crypto/ed25519: uninitialized private key") + ensure(len(dst) == PRIVATE_KEY_SIZE, "crypto/ed25519: invalid destination size") copy(dst, priv_key._b[:]) } @@ -98,12 +94,8 @@ private_key_clear :: proc "contextless" (priv_key: ^Private_Key) { // sign writes the signature by priv_key over msg to sig. sign :: proc(priv_key: ^Private_Key, msg, sig: []byte) { - if !priv_key._is_initialized { - panic("crypto/ed25519: uninitialized private key") - } - if len(sig) != SIGNATURE_SIZE { - panic("crypto/ed25519: invalid destination size") - } + ensure(priv_key._is_initialized, "crypto/ed25519: uninitialized private key") + ensure(len(sig) == SIGNATURE_SIZE, "crypto/ed25519: invalid destination size") // 1. Compute the hash of the private key d, H(d) = (h_0, h_1, ..., h_2b-1) // using SHA-512 for Ed25519. H(d) may be precomputed. @@ -178,9 +170,7 @@ public_key_set_bytes :: proc "contextless" (pub_key: ^Public_Key, b: []byte) -> // public_key_set_priv sets pub_key to the public component of priv_key. public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) { - if !priv_key._is_initialized { - panic("crypto/ed25519: uninitialized public key") - } + ensure(priv_key._is_initialized, "crypto/ed25519: uninitialized public key") src := &priv_key._pub_key copy(pub_key._b[:], src._b[:]) @@ -191,21 +181,15 @@ public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) { // public_key_bytes sets dst to byte-encoding of pub_key. public_key_bytes :: proc(pub_key: ^Public_Key, dst: []byte) { - if !pub_key._is_initialized { - panic("crypto/ed25519: uninitialized public key") - } - if len(dst) != PUBLIC_KEY_SIZE { - panic("crypto/ed25519: invalid destination size") - } + ensure(pub_key._is_initialized, "crypto/ed25519: uninitialized public key") + ensure(len(dst) == PUBLIC_KEY_SIZE, "crypto/ed25519: invalid destination size") copy(dst, pub_key._b[:]) } // public_key_equal returns true iff pub_key is equal to other. public_key_equal :: proc(pub_key, other: ^Public_Key) -> bool { - if !pub_key._is_initialized || !other._is_initialized { - panic("crypto/ed25519: uninitialized public key") - } + ensure(pub_key._is_initialized && other._is_initialized, "crypto/ed25519: uninitialized public key") return crypto.compare_constant_time(pub_key._b[:], other._b[:]) == 1 } diff --git a/core/crypto/hmac/hmac.odin b/core/crypto/hmac/hmac.odin index 4813a9938..f74d6492f 100644 --- a/core/crypto/hmac/hmac.odin +++ b/core/crypto/hmac/hmac.odin @@ -56,7 +56,7 @@ init :: proc(ctx: ^Context, algorithm: hash.Algorithm, key: []byte) { // update adds more data to the Context. update :: proc(ctx: ^Context, data: []byte) { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) hash.update(&ctx._i_hash, data) } @@ -64,13 +64,10 @@ update :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the tag to dst, and calls // reset on the Context. final :: proc(ctx: ^Context, dst: []byte) { - assert(ctx._is_initialized) - defer (reset(ctx)) - if len(dst) != ctx._tag_sz { - panic("crypto/hmac: invalid destination tag size") - } + ensure(ctx._is_initialized) + ensure(len(dst) == ctx._tag_sz, "crypto/hmac: invalid destination tag size") hash.final(&ctx._i_hash, dst) // H((k ^ ipad) || text) @@ -105,14 +102,14 @@ reset :: proc(ctx: ^Context) { // algorithm returns the Algorithm used by a Context instance. algorithm :: proc(ctx: ^Context) -> hash.Algorithm { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) return hash.algorithm(&ctx._i_hash) } // tag_size returns the tag size of a Context instance in bytes. tag_size :: proc(ctx: ^Context) -> int { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) return ctx._tag_sz } diff --git a/core/crypto/kmac/kmac.odin b/core/crypto/kmac/kmac.odin index 298cbf428..6f58e20a7 100644 --- a/core/crypto/kmac/kmac.odin +++ b/core/crypto/kmac/kmac.odin @@ -36,6 +36,7 @@ sum :: proc(sec_strength: int, dst, msg, key, domain_sep: []byte) { // tag is valid. verify :: proc(sec_strength: int, tag, msg, key, domain_sep: []byte, allocator := context.temp_allocator) -> bool { derived_tag := make([]byte, len(tag), allocator) + defer(delete(derived_tag)) sum(sec_strength, derived_tag, msg, key, domain_sep) @@ -59,8 +60,6 @@ init_256 :: proc(ctx: ^Context, key, domain_sep: []byte) { // update adds more data to the Context. update :: proc(ctx: ^Context, data: []byte) { - assert(ctx.is_initialized) - shake.write((^shake.Context)(ctx), data) } @@ -68,12 +67,9 @@ update :: proc(ctx: ^Context, data: []byte) { // on the Context. This routine will panic if the dst length is less than // MIN_TAG_SIZE. final :: proc(ctx: ^Context, dst: []byte) { - assert(ctx.is_initialized) defer reset(ctx) - if len(dst) < MIN_TAG_SIZE { - panic("crypto/kmac: invalid KMAC tag_size, too short") - } + ensure(len(dst) >= MIN_TAG_SIZE, "crypto/kmac: invalid KMAC tag_size, too short") _sha3.final_cshake((^_sha3.Context)(ctx), dst) } @@ -103,9 +99,7 @@ _init_kmac :: proc(ctx: ^Context, key, s: []byte, sec_strength: int) { reset(ctx) } - if len(key) < sec_strength / 8 { - panic("crypto/kmac: invalid KMAC key, too short") - } + ensure(len(key) >= sec_strength / 8, "crypto/kmac: invalid KMAC key, too short") ctx_ := (^_sha3.Context)(ctx) _sha3.init_cshake(ctx_, N_KMAC, s, sec_strength) diff --git a/core/crypto/legacy/keccak/keccak.odin b/core/crypto/legacy/keccak/keccak.odin index 6ca66b7ca..40fc2729f 100644 --- a/core/crypto/legacy/keccak/keccak.odin +++ b/core/crypto/legacy/keccak/keccak.odin @@ -40,37 +40,37 @@ BLOCK_SIZE_512 :: _sha3.RATE_512 Context :: distinct _sha3.Context // init_224 initializes a Context for Keccak-224. -init_224 :: proc(ctx: ^Context) { +init_224 :: proc "contextless" (ctx: ^Context) { ctx.mdlen = DIGEST_SIZE_224 _init(ctx) } // init_256 initializes a Context for Keccak-256. -init_256 :: proc(ctx: ^Context) { +init_256 :: proc "contextless" (ctx: ^Context) { ctx.mdlen = DIGEST_SIZE_256 _init(ctx) } // init_384 initializes a Context for Keccak-384. -init_384 :: proc(ctx: ^Context) { +init_384 :: proc "contextless" (ctx: ^Context) { ctx.mdlen = DIGEST_SIZE_384 _init(ctx) } // init_512 initializes a Context for Keccak-512. -init_512 :: proc(ctx: ^Context) { +init_512 :: proc "contextless" (ctx: ^Context) { ctx.mdlen = DIGEST_SIZE_512 _init(ctx) } @(private) -_init :: proc(ctx: ^Context) { +_init :: proc "contextless" (ctx: ^Context) { ctx.dsbyte = _sha3.DS_KECCAK _sha3.init((^_sha3.Context)(ctx)) } // update adds more data to the Context. -update :: proc(ctx: ^Context, data: []byte) { +update :: proc "contextless" (ctx: ^Context, data: []byte) { _sha3.update((^_sha3.Context)(ctx), data) } @@ -79,17 +79,17 @@ update :: proc(ctx: ^Context, data: []byte) { // // Iff finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. -final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { +final :: proc "contextless" (ctx: ^Context, hash: []byte, finalize_clone: bool = false) { _sha3.final((^_sha3.Context)(ctx), hash, finalize_clone) } // clone clones the Context other into ctx. -clone :: proc(ctx, other: ^Context) { +clone :: proc "contextless" (ctx, other: ^Context) { _sha3.clone((^_sha3.Context)(ctx), (^_sha3.Context)(other)) } // reset sanitizes the Context. The Context must be re-initialized to // be used again. -reset :: proc(ctx: ^Context) { +reset :: proc "contextless" (ctx: ^Context) { _sha3.reset((^_sha3.Context)(ctx)) } diff --git a/core/crypto/legacy/md5/md5.odin b/core/crypto/legacy/md5/md5.odin index 28b47e0b3..050501d98 100644 --- a/core/crypto/legacy/md5/md5.odin +++ b/core/crypto/legacy/md5/md5.odin @@ -53,7 +53,7 @@ init :: proc(ctx: ^Context) { // update adds more data to the Context. update :: proc(ctx: ^Context, data: []byte) { - assert(ctx.is_initialized) + ensure(ctx.is_initialized) for i := 0; i < len(data); i += 1 { ctx.data[ctx.datalen] = data[i] @@ -72,11 +72,8 @@ update :: proc(ctx: ^Context, data: []byte) { // Iff finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { - assert(ctx.is_initialized) - - if len(hash) < DIGEST_SIZE { - panic("crypto/md5: invalid destination digest size") - } + ensure(ctx.is_initialized) + ensure(len(hash) >= DIGEST_SIZE, "crypto/md5: invalid destination digest size") ctx := ctx if finalize_clone { diff --git a/core/crypto/legacy/sha1/sha1.odin b/core/crypto/legacy/sha1/sha1.odin index 1025ecb5b..5a2b57005 100644 --- a/core/crypto/legacy/sha1/sha1.odin +++ b/core/crypto/legacy/sha1/sha1.odin @@ -60,7 +60,7 @@ init :: proc(ctx: ^Context) { // update adds more data to the Context. update :: proc(ctx: ^Context, data: []byte) { - assert(ctx.is_initialized) + ensure(ctx.is_initialized) for i := 0; i < len(data); i += 1 { ctx.data[ctx.datalen] = data[i] @@ -79,11 +79,8 @@ update :: proc(ctx: ^Context, data: []byte) { // Iff finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { - assert(ctx.is_initialized) - - if len(hash) < DIGEST_SIZE { - panic("crypto/sha1: invalid destination digest size") - } + ensure(ctx.is_initialized) + ensure(len(hash) >= DIGEST_SIZE, "crypto/sha1: invalid destination digest size") ctx := ctx if finalize_clone { diff --git a/core/crypto/poly1305/poly1305.odin b/core/crypto/poly1305/poly1305.odin index ea0e6c907..3dd915da7 100644 --- a/core/crypto/poly1305/poly1305.odin +++ b/core/crypto/poly1305/poly1305.odin @@ -60,9 +60,7 @@ Context :: struct { // init initializes a Context with the specified key. The key SHOULD be // unique and MUST be unpredictable for each invocation. init :: proc(ctx: ^Context, key: []byte) { - if len(key) != KEY_SIZE { - panic("crypto/poly1305: invalid key size") - } + ensure(len(key) == KEY_SIZE, "crypto/poly1305: invalid key size") // r = le_bytes_to_num(key[0..15]) // r = clamp(r) (r &= 0xffffffc0ffffffc0ffffffc0fffffff) @@ -85,7 +83,7 @@ init :: proc(ctx: ^Context, key: []byte) { // update adds more data to the Context. update :: proc(ctx: ^Context, data: []byte) { - assert(ctx._is_initialized) + ensure(ctx._is_initialized) msg := data msg_len := len(data) @@ -124,12 +122,10 @@ update :: proc(ctx: ^Context, data: []byte) { // final finalizes the Context, writes the tag to dst, and calls // reset on the Context. final :: proc(ctx: ^Context, dst: []byte) { - assert(ctx._is_initialized) defer reset(ctx) - if len(dst) != TAG_SIZE { - panic("poly1305: invalid destination tag size") - } + ensure(ctx._is_initialized) + ensure(len(dst) == TAG_SIZE, "poly1305: invalid destination tag size") // Process remaining block if ctx._leftover > 0 { diff --git a/core/crypto/ristretto255/ristretto255.odin b/core/crypto/ristretto255/ristretto255.odin index c4d3f2615..20a002900 100644 --- a/core/crypto/ristretto255/ristretto255.odin +++ b/core/crypto/ristretto255/ristretto255.odin @@ -76,7 +76,7 @@ ge_clear :: proc "contextless" (ge: ^Group_Element) { // ge_set sets `ge = a`. ge_set :: proc(ge, a: ^Group_Element) { - _ge_assert_initialized([]^Group_Element{a}) + _ge_ensure_initialized([]^Group_Element{a}) grp.ge_set(&ge._p, &a._p) ge._is_initialized = true @@ -199,9 +199,7 @@ ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool { // ge_set_wide_bytes sets ge to the result of deriving a ristretto255 // group element, from a wide (512-bit) byte string. ge_set_wide_bytes :: proc(ge: ^Group_Element, b: []byte) { - if len(b) != WIDE_ELEMENT_SIZE { - panic("crypto/ristretto255: invalid wide input size") - } + ensure(len(b) == WIDE_ELEMENT_SIZE, "crypto/ristretto255: invalid wide input size") // The element derivation function on an input string b proceeds as // follows: @@ -222,10 +220,8 @@ ge_set_wide_bytes :: proc(ge: ^Group_Element, b: []byte) { // ge_bytes sets dst to the canonical encoding of ge. ge_bytes :: proc(ge: ^Group_Element, dst: []byte) { - _ge_assert_initialized([]^Group_Element{ge}) - if len(dst) != ELEMENT_SIZE { - panic("crypto/ristretto255: invalid destination size") - } + _ge_ensure_initialized([]^Group_Element{ge}) + ensure(len(dst) == ELEMENT_SIZE, "crypto/ristretto255: invalid destination size") x0, y0, z0, t0 := &ge._p.x, &ge._p.y, &ge._p.z, &ge._p.t @@ -306,7 +302,7 @@ ge_bytes :: proc(ge: ^Group_Element, dst: []byte) { // ge_add sets `ge = a + b`. ge_add :: proc(ge, a, b: ^Group_Element) { - _ge_assert_initialized([]^Group_Element{a, b}) + _ge_ensure_initialized([]^Group_Element{a, b}) grp.ge_add(&ge._p, &a._p, &b._p) ge._is_initialized = true @@ -314,7 +310,7 @@ ge_add :: proc(ge, a, b: ^Group_Element) { // ge_double sets `ge = a + a`. ge_double :: proc(ge, a: ^Group_Element) { - _ge_assert_initialized([]^Group_Element{a}) + _ge_ensure_initialized([]^Group_Element{a}) grp.ge_double(&ge._p, &a._p) ge._is_initialized = true @@ -322,7 +318,7 @@ ge_double :: proc(ge, a: ^Group_Element) { // ge_negate sets `ge = -a`. ge_negate :: proc(ge, a: ^Group_Element) { - _ge_assert_initialized([]^Group_Element{a}) + _ge_ensure_initialized([]^Group_Element{a}) grp.ge_negate(&ge._p, &a._p) ge._is_initialized = true @@ -330,7 +326,7 @@ ge_negate :: proc(ge, a: ^Group_Element) { // ge_scalarmult sets `ge = A * sc`. ge_scalarmult :: proc(ge, A: ^Group_Element, sc: ^Scalar) { - _ge_assert_initialized([]^Group_Element{A}) + _ge_ensure_initialized([]^Group_Element{A}) grp.ge_scalarmult(&ge._p, &A._p, sc) ge._is_initialized = true @@ -344,7 +340,7 @@ ge_scalarmult_generator :: proc "contextless" (ge: ^Group_Element, sc: ^Scalar) // ge_scalarmult_vartime sets `ge = A * sc` in variable time. ge_scalarmult_vartime :: proc(ge, A: ^Group_Element, sc: ^Scalar) { - _ge_assert_initialized([]^Group_Element{A}) + _ge_ensure_initialized([]^Group_Element{A}) grp.ge_scalarmult_vartime(&ge._p, &A._p, sc) ge._is_initialized = true @@ -358,7 +354,7 @@ ge_double_scalarmult_generator_vartime :: proc( A: ^Group_Element, b: ^Scalar, ) { - _ge_assert_initialized([]^Group_Element{A}) + _ge_ensure_initialized([]^Group_Element{A}) grp.ge_double_scalarmult_basepoint_vartime(&ge._p, a, &A._p, b) ge._is_initialized = true @@ -367,7 +363,7 @@ ge_double_scalarmult_generator_vartime :: proc( // ge_cond_negate sets `ge = a` iff `ctrl == 0` and `ge = -a` iff `ctrl == 1`. // Behavior for all other values of ctrl are undefined, ge_cond_negate :: proc(ge, a: ^Group_Element, ctrl: int) { - _ge_assert_initialized([]^Group_Element{a}) + _ge_ensure_initialized([]^Group_Element{a}) grp.ge_cond_negate(&ge._p, &a._p, ctrl) ge._is_initialized = true @@ -376,7 +372,7 @@ ge_cond_negate :: proc(ge, a: ^Group_Element, ctrl: int) { // ge_cond_assign sets `ge = ge` iff `ctrl == 0` and `ge = a` iff `ctrl == 1`. // Behavior for all other values of ctrl are undefined, ge_cond_assign :: proc(ge, a: ^Group_Element, ctrl: int) { - _ge_assert_initialized([]^Group_Element{ge, a}) + _ge_ensure_initialized([]^Group_Element{ge, a}) grp.ge_cond_assign(&ge._p, &a._p, ctrl) } @@ -384,7 +380,7 @@ ge_cond_assign :: proc(ge, a: ^Group_Element, ctrl: int) { // ge_cond_select sets `ge = a` iff `ctrl == 0` and `ge = b` iff `ctrl == 1`. // Behavior for all other values of ctrl are undefined, ge_cond_select :: proc(ge, a, b: ^Group_Element, ctrl: int) { - _ge_assert_initialized([]^Group_Element{a, b}) + _ge_ensure_initialized([]^Group_Element{a, b}) grp.ge_cond_select(&ge._p, &a._p, &b._p, ctrl) ge._is_initialized = true @@ -393,7 +389,7 @@ ge_cond_select :: proc(ge, a, b: ^Group_Element, ctrl: int) { // ge_equal returns 1 iff `a == b`, and 0 otherwise. @(require_results) ge_equal :: proc(a, b: ^Group_Element) -> int { - _ge_assert_initialized([]^Group_Element{a, b}) + _ge_ensure_initialized([]^Group_Element{a, b}) // CT_EQ(x1 * y2, y1 * x2) | CT_EQ(y1 * y2, x1 * x2) ax_by, ay_bx, ay_by, ax_bx: field.Tight_Field_Element = ---, ---, ---, --- @@ -501,10 +497,8 @@ ge_map :: proc "contextless" (ge: ^Group_Element, b: []byte) { } @(private) -_ge_assert_initialized :: proc(ges: []^Group_Element) { +_ge_ensure_initialized :: proc(ges: []^Group_Element) { for ge in ges { - if !ge._is_initialized { - panic("crypto/ristretto255: uninitialized group element") - } + ensure(ge._is_initialized, "crypto/ristretto255: uninitialized group element") } } diff --git a/core/crypto/ristretto255/ristretto255_scalar.odin b/core/crypto/ristretto255/ristretto255_scalar.odin index 1ecb490e0..75844b3f4 100644 --- a/core/crypto/ristretto255/ristretto255_scalar.odin +++ b/core/crypto/ristretto255/ristretto255_scalar.odin @@ -42,9 +42,7 @@ sc_set_bytes :: proc(sc: ^Scalar, b: []byte) -> bool { // scalar, from a wide (512-bit) byte string by interpreting b as a // little-endian value, and reducing it mod the group order. sc_set_bytes_wide :: proc(sc: ^Scalar, b: []byte) { - if len(b) != WIDE_SCALAR_SIZE { - panic("crypto/ristretto255: invalid wide input size") - } + ensure(len(b) == WIDE_SCALAR_SIZE, "crypto/ristretto255: invalid wide input size") b_ := (^[WIDE_SCALAR_SIZE]byte)(raw_data(b)) grp.sc_set_bytes_wide(sc, b_) @@ -52,9 +50,7 @@ sc_set_bytes_wide :: proc(sc: ^Scalar, b: []byte) { // sc_bytes sets dst to the canonical encoding of sc. sc_bytes :: proc(sc: ^Scalar, dst: []byte) { - if len(dst) != SCALAR_SIZE { - panic("crypto/ristretto255: invalid destination size") - } + ensure(len(dst) == SCALAR_SIZE, "crypto/ristretto255: invalid destination size") grp.sc_bytes(dst, sc) } diff --git a/core/crypto/sha2/sha2.odin b/core/crypto/sha2/sha2.odin index 8ab0ce005..bf9b81601 100644 --- a/core/crypto/sha2/sha2.odin +++ b/core/crypto/sha2/sha2.odin @@ -158,7 +158,7 @@ _init :: proc(ctx: ^$T) { // update adds more data to the Context. update :: proc(ctx: ^$T, data: []byte) { - assert(ctx.is_initialized) + ensure(ctx.is_initialized) when T == Context_256 { CURR_BLOCK_SIZE :: BLOCK_SIZE_256 @@ -194,11 +194,8 @@ update :: proc(ctx: ^$T, data: []byte) { // Iff finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) { - assert(ctx.is_initialized) - - if len(hash) * 8 < ctx.md_bits { - panic("crypto/sha2: invalid destination digest size") - } + ensure(ctx.is_initialized) + ensure(len(hash) * 8 >= ctx.md_bits, "crypto/sha2: invalid destination digest size") ctx := ctx if finalize_clone { @@ -238,7 +235,7 @@ final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) { endian.unchecked_put_u64be(pad[8:], length_lo) update(ctx, pad[0:16]) } - assert(ctx.bitlength == 0) + assert(ctx.bitlength == 0) // Check for bugs when T == Context_256 { for i := 0; i < ctx.md_bits / 32; i += 1 { diff --git a/core/crypto/siphash/siphash.odin b/core/crypto/siphash/siphash.odin index c145ab3f0..f9fe50cb0 100644 --- a/core/crypto/siphash/siphash.odin +++ b/core/crypto/siphash/siphash.odin @@ -219,18 +219,14 @@ verify_4_8 :: proc { */ init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) { - if len(key) != KEY_SIZE { - panic("crypto/siphash; invalid key size") - } + ensure(len(key) == KEY_SIZE,"crypto/siphash; invalid key size") ctx.c_rounds = c_rounds ctx.d_rounds = d_rounds is_valid_setting := (ctx.c_rounds == 1 && ctx.d_rounds == 3) || (ctx.c_rounds == 2 && ctx.d_rounds == 4) || (ctx.c_rounds == 4 && ctx.d_rounds == 8) - if !is_valid_setting { - panic("crypto/siphash: incorrect rounds set up") - } + ensure(is_valid_setting, "crypto/siphash: incorrect rounds set up") ctx.k0 = endian.unchecked_get_u64le(key[:8]) ctx.k1 = endian.unchecked_get_u64le(key[8:]) ctx.v0 = 0x736f6d6570736575 ~ ctx.k0 @@ -245,7 +241,7 @@ init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) { } update :: proc(ctx: ^Context, data: []byte) { - assert(ctx.is_initialized, "crypto/siphash: context is not initialized") + ensure(ctx.is_initialized) data := data ctx.total_length += len(data) @@ -269,7 +265,7 @@ update :: proc(ctx: ^Context, data: []byte) { } final :: proc(ctx: ^Context, dst: ^u64) { - assert(ctx.is_initialized, "crypto/siphash: context is not initialized") + ensure(ctx.is_initialized) tmp: [BLOCK_SIZE]byte copy(tmp[:], ctx.buf[:ctx.last_block]) @@ -336,9 +332,8 @@ _get_byte :: #force_inline proc "contextless" (byte_num: byte, into: u64) -> byt @(private) _collect_output :: #force_inline proc(dst: []byte, hash: u64) { - if len(dst) < DIGEST_SIZE { - panic("crypto/siphash: invalid tag size") - } + ensure(len(dst) >= DIGEST_SIZE, "crypto/siphash: invalid tag size") + dst[0] = _get_byte(7, hash) dst[1] = _get_byte(6, hash) dst[2] = _get_byte(5, hash) diff --git a/core/crypto/sm3/sm3.odin b/core/crypto/sm3/sm3.odin index 06a5ef2db..6487c5e8c 100644 --- a/core/crypto/sm3/sm3.odin +++ b/core/crypto/sm3/sm3.odin @@ -53,7 +53,7 @@ init :: proc(ctx: ^Context) { // update adds more data to the Context. update :: proc(ctx: ^Context, data: []byte) { - assert(ctx.is_initialized) + ensure(ctx.is_initialized) data := data ctx.length += u64(len(data)) @@ -83,11 +83,8 @@ update :: proc(ctx: ^Context, data: []byte) { // Iff finalize_clone is set, final will work on a copy of the Context, // which is useful for for calculating rolling digests. final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { - assert(ctx.is_initialized) - - if len(hash) < DIGEST_SIZE { - panic("crypto/sm3: invalid destination digest size") - } + ensure(ctx.is_initialized) + ensure(len(hash) >= DIGEST_SIZE, "crypto/sm3: invalid destination digest size") ctx := ctx if finalize_clone { @@ -110,7 +107,7 @@ final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { length <<= 3 endian.unchecked_put_u64be(pad[:], length) update(ctx, pad[0:8]) - assert(ctx.bitlength == 0) + assert(ctx.bitlength == 0) // Check for bugs for i := 0; i < DIGEST_SIZE / 4; i += 1 { endian.unchecked_put_u32be(hash[i * 4:], ctx.state[i]) diff --git a/core/crypto/x25519/x25519.odin b/core/crypto/x25519/x25519.odin index fcb7015f3..6805c3ff8 100644 --- a/core/crypto/x25519/x25519.odin +++ b/core/crypto/x25519/x25519.odin @@ -101,15 +101,9 @@ _scalarmult :: proc "contextless" (out, scalar, point: ^[32]byte) { // scalarmult "multiplies" the provided scalar and point, and writes the // resulting point to dst. scalarmult :: proc(dst, scalar, point: []byte) { - if len(scalar) != SCALAR_SIZE { - panic("crypto/x25519: invalid scalar size") - } - if len(point) != POINT_SIZE { - panic("crypto/x25519: invalid point size") - } - if len(dst) != POINT_SIZE { - panic("crypto/x25519: invalid destination point size") - } + ensure(len(scalar) == SCALAR_SIZE, "crypto/x25519: invalid scalar size") + ensure(len(point) == POINT_SIZE, "crypto/x25519: invalid point size") + ensure(len(dst) == POINT_SIZE, "crypto/x25519: invalid destination point size") // "clamp" the scalar e: [32]byte = --- diff --git a/core/crypto/x448/x448.odin b/core/crypto/x448/x448.odin index d3aad6ac5..43c5d25e0 100644 --- a/core/crypto/x448/x448.odin +++ b/core/crypto/x448/x448.odin @@ -127,15 +127,9 @@ _scalarmult :: proc "contextless" (out, scalar, point: ^[56]byte) { // scalarmult "multiplies" the provided scalar and point, and writes the // resulting point to dst. scalarmult :: proc(dst, scalar, point: []byte) { - if len(scalar) != SCALAR_SIZE { - panic("crypto/x448: invalid scalar size") - } - if len(point) != POINT_SIZE { - panic("crypto/x448: invalid point size") - } - if len(dst) != POINT_SIZE { - panic("crypto/x448: invalid destination point size") - } + ensure(len(scalar) == SCALAR_SIZE, "crypto/x448: invalid scalar size") + ensure(len(point) == POINT_SIZE, "crypto/x448: invalid point size") + ensure(len(dst) == POINT_SIZE, "crypto/x448: invalid destination point size") // "clamp" the scalar e: [56]byte = --- From 38665431dd173fb0d9096da59f0a7528ebe754f7 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Sun, 23 Mar 2025 19:17:18 +0900 Subject: [PATCH 25/81] core/crypto/_aes/ct64: Disable bounds checking --- core/crypto/_aes/ct64/helpers.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/crypto/_aes/ct64/helpers.odin b/core/crypto/_aes/ct64/helpers.odin index 4f2d9800c..7eec5bdc4 100644 --- a/core/crypto/_aes/ct64/helpers.odin +++ b/core/crypto/_aes/ct64/helpers.odin @@ -4,7 +4,7 @@ import "core:crypto/_aes" import "core:encoding/endian" @(require_results) -load_interleaved :: proc "contextless" (src: []byte) -> (u64, u64) { +load_interleaved :: proc "contextless" (src: []byte) -> (u64, u64) #no_bounds_check { w0 := endian.unchecked_get_u32le(src[0:]) w1 := endian.unchecked_get_u32le(src[4:]) w2 := endian.unchecked_get_u32le(src[8:]) @@ -12,7 +12,7 @@ load_interleaved :: proc "contextless" (src: []byte) -> (u64, u64) { return interleave_in(w0, w1, w2, w3) } -store_interleaved :: proc "contextless" (dst: []byte, a0, a1: u64) { +store_interleaved :: proc "contextless" (dst: []byte, a0, a1: u64) #no_bounds_check { w0, w1, w2, w3 := interleave_out(a0, a1) endian.unchecked_put_u32le(dst[0:], w0) endian.unchecked_put_u32le(dst[4:], w1) From 87db5f2df4ba2edda0839f616f48232b60530111 Mon Sep 17 00:00:00 2001 From: dogue Date: Sun, 23 Mar 2025 22:09:42 -0400 Subject: [PATCH 26/81] xlib: add proc binding for SetWindowBorder --- vendor/x11/xlib/xlib_procs.odin | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vendor/x11/xlib/xlib_procs.odin b/vendor/x11/xlib/xlib_procs.odin index 2d35ab179..780cf1b97 100644 --- a/vendor/x11/xlib/xlib_procs.odin +++ b/vendor/x11/xlib/xlib_procs.odin @@ -217,6 +217,11 @@ foreign xlib { window: Window, width: u32, ) --- + SetWindowBorder :: proc( + display: ^Display, + window: Window, + pixel: uint, + ) --- // Window: changing stacking order RaiseWindow :: proc(display: ^Display, window: Window) --- LowerWindow :: proc(display: ^Display, window: Window) --- From 2b8c76354d489de199a4b8d98290601e89df0645 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Mar 2025 11:31:05 +0000 Subject: [PATCH 27/81] Use `copy` over `intrinsics.mem_copy_non_overlapping` --- core/os/os2/path.odin | 18 ++++++++---------- core/os/os2/path_windows.odin | 3 +-- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/core/os/os2/path.odin b/core/os/os2/path.odin index e62ee11bc..47ac0236d 100644 --- a/core/os/os2/path.odin +++ b/core/os/os2/path.odin @@ -1,6 +1,5 @@ package os2 -import "base:intrinsics" import "base:runtime" import "core:strings" @@ -163,7 +162,7 @@ clean_path :: proc(path: string, allocator: runtime.Allocator) -> (cleaned: stri } case: // Copy the path element verbatim and add a separator. - intrinsics.mem_copy_non_overlapping(raw_data(buffer[buffer_i:]), raw_data(elem), len(elem)) + copy(buffer[buffer_i:], elem) buffer_i += len(elem) buffer[buffer_i] = _Path_Separator buffer_i += 1 @@ -182,7 +181,7 @@ clean_path :: proc(path: string, allocator: runtime.Allocator) -> (cleaned: stri } compact := make([]u8, buffer_i, allocator) or_return - intrinsics.mem_copy_non_overlapping(raw_data(compact), raw_data(buffer), buffer_i) + copy(compact, buffer) // NOTE(bill): buffer[:buffer_i] is redundant here return string(compact), nil } @@ -298,7 +297,7 @@ get_relative_path :: proc(base, target: string, allocator: runtime.Allocator) -> buf[n] = _Path_Separator n += 1 } - runtime.mem_copy_non_overlapping(raw_data(buf[n:]), raw_data(trailing), len(trailing)) + copy(buf[n:], trailing) } path = string(buf) @@ -389,17 +388,16 @@ For example, `join_filename("foo", "tar.gz")` will result in `"foo.tar.gz"`. */ @(require_results) join_filename :: proc(base: string, ext: string, allocator: runtime.Allocator) -> (joined: string, err: Error) { - len_base := len(base) - if len_base == 0 { + if len(base) == 0 { return strings.clone(ext, allocator) } else if len(ext) == 0 { return strings.clone(base, allocator) } - buf := make([]u8, len_base + 1 + len(ext), allocator) or_return - intrinsics.mem_copy_non_overlapping(raw_data(buf), raw_data(base), len_base) - buf[len_base] = '.' - intrinsics.mem_copy_non_overlapping(raw_data(buf[1+len_base:]), raw_data(ext), len(ext)) + buf := make([]u8, len(base) + 1 + len(ext), allocator) or_return + copy(buf, base) + buf[len(base)] = '.' + copy(buf[1+len(base):], ext) return string(buf), nil } diff --git a/core/os/os2/path_windows.odin b/core/os/os2/path_windows.odin index c8264cc2d..dd9b7748c 100644 --- a/core/os/os2/path_windows.odin +++ b/core/os/os2/path_windows.odin @@ -1,7 +1,6 @@ #+private package os2 -import "base:intrinsics" import "base:runtime" import "core:strings" import win32 "core:sys/windows" @@ -271,7 +270,7 @@ _clean_path_handle_start :: proc(path: string, buffer: []u8) -> (rooted: bool, s // Take `C:` to `C:\`. start += 1 } - intrinsics.mem_copy_non_overlapping(raw_data(buffer), raw_data(path), start) + copy(buffer, path[:start]) } return } From acb578f184c55f0d1b20ef844a506185684efeba Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Mar 2025 11:35:10 +0000 Subject: [PATCH 28/81] Fix #4962 --- src/check_builtin.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 023aeff73..a49302a69 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1675,12 +1675,16 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o } if (ce->args.count > 0) { Ast *arg = ce->args[0]; - Operand o = {}; - Entity *e = check_ident(c, &o, arg, nullptr, nullptr, true); - if (e == nullptr || (e->flags & EntityFlag_Param) == 0) { - error(ce->args[0], "'#caller_expression' expected a valid earlier parameter name"); + if (arg->kind != Ast_Ident) { + error(arg, "'#caller_expression' expected an identifier"); + } else { + Operand o = {}; + Entity *e = check_ident(c, &o, arg, nullptr, nullptr, true); + if (e == nullptr || (e->flags & EntityFlag_Param) == 0) { + error(arg, "'#caller_expression' expected a valid earlier parameter name"); + } + arg->Ident.entity = e; } - arg->Ident.entity = e; } operand->type = t_string; From 56e0ab7655337b8ce9738d214c21e5f06e91df09 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Mar 2025 13:11:41 +0000 Subject: [PATCH 29/81] Fix #4952 --- src/llvm_backend_const.cpp | 49 ++++++++++++++++++++++++++++++++++---- src/llvm_backend_expr.cpp | 3 ++- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index b916c0017..c011e62f4 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -1125,10 +1125,11 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo visited[index] = true; } else { if (!visited[index]) { - values[index] = lb_const_value(m, f->type, {}, false).value; + values[index] = lb_const_value(m, f->type, {}, allow_local, is_rodata).value; visited[index] = true; } + unsigned idx_list_len = cast(unsigned)sel.index.count-1; unsigned *idx_list = gb_alloc_array(temporary_allocator(), unsigned, idx_list_len); @@ -1139,6 +1140,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo i32 index = sel.index[j]; Type *cvt = base_type(cv_type); + if (cvt->kind == Type_Struct) { if (cvt->Struct.is_raw_union) { // sanity check which should have been caught by `lb_is_nested_possibly_constant` @@ -1164,9 +1166,38 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo } if (is_constant) { LLVMValueRef elem_value = lb_const_value(m, tav.type, tav.value, allow_local, is_rodata).value; - if (LLVMIsConstant(elem_value)) { + if (LLVMIsConstant(elem_value) && LLVMIsConstant(values[index])) { values[index] = llvm_const_insert_value(m, values[index], elem_value, idx_list, idx_list_len); - } else { + } else if (is_local) { + lbProcedure *p = m->curr_procedure; + GB_ASSERT(p != nullptr); + if (LLVMIsConstant(values[index])) { + lbAddr addr = lb_add_local_generated(p, f->type, false); + lb_addr_store(p, addr, lbValue{values[index], f->type}); + values[index] = lb_addr_load(p, addr).value; + } + + GB_ASSERT(LLVMIsALoadInst(values[index])); + + LLVMValueRef ptr = LLVMGetOperand(values[index], 0); + + LLVMValueRef *indices = gb_alloc_array(temporary_allocator(), LLVMValueRef, idx_list_len); + LLVMTypeRef lt_u32 = lb_type(m, t_u32); + for (unsigned i = 0; i < idx_list_len; i++) { + indices[i] = LLVMConstInt(lt_u32, idx_list[i], false); + } + + ptr = LLVMBuildGEP2(p->builder, lb_type(m, f->type), ptr, indices, idx_list_len, ""); + ptr = LLVMBuildPointerCast(p->builder, ptr, lb_type(m, alloc_type_pointer(tav.type)), ""); + + if (LLVMIsALoadInst(elem_value)) { + i64 sz = type_size_of(tav.type); + LLVMValueRef src = LLVMGetOperand(elem_value, 0); + lb_mem_copy_non_overlapping(p, {ptr, t_rawptr}, {src, t_rawptr}, lb_const_int(m, t_int, sz), false); + } else { + LLVMBuildStore(p->builder, elem_value, ptr); + } + is_constant = false; } } @@ -1205,7 +1236,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo LLVMValueRef val = values[i]; if (!LLVMIsConstant(val)) { GB_ASSERT(is_local); - GB_ASSERT(LLVMGetInstructionOpcode(val) == LLVMLoad); + GB_ASSERT(LLVMIsALoadInst(val)); is_constant = false; } } @@ -1237,7 +1268,15 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo LLVMValueRef val = old_values[i]; if (!LLVMIsConstant(val)) { LLVMValueRef dst = LLVMBuildStructGEP2(p->builder, llvm_addr_type(p->module, v.addr), v.addr.value, cast(unsigned)i, ""); - LLVMBuildStore(p->builder, val, dst); + if (LLVMIsALoadInst(val)) { + Type *ptr_type = v.addr.type; + i64 sz = type_size_of(type_deref(ptr_type)); + + LLVMValueRef src = LLVMGetOperand(val, 0); + lb_mem_copy_non_overlapping(p, {dst, ptr_type}, {src, ptr_type}, lb_const_int(m, t_int, sz), false); + } else { + LLVMBuildStore(p->builder, val, dst); + } } } return lb_addr_load(p, v); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index ea3db33f4..0c82180ec 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3493,7 +3493,8 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) { if (tv.value.kind != ExactValue_Invalid) { // NOTE(bill): Short on constant values - return lb_const_value(p->module, type, tv.value); + bool allow_local = true; + return lb_const_value(p->module, type, tv.value, allow_local); } else if (tv.mode == Addressing_Type) { // NOTE(bill, 2023-01-16): is this correct? I hope so at least return lb_typeid(m, tv.type); From ce026ff2c4ef1b29d3876f1ab5c866eda7995679 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Mar 2025 13:13:25 +0000 Subject: [PATCH 30/81] Fix #4949 --- src/check_builtin.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index a49302a69..fa3218759 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -645,6 +645,13 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan break; } + if (!are_types_identical(x.type, y.type)) { + gbString tx = type_to_string(x.type); + gbString ty = type_to_string(y.type); + error(call, "Mismatched types to '%.*s', '%s' vs '%s'", LIT(builtin_name), tx, ty); + gb_string_free(ty); + gb_string_free(tx); + } Type *vt = base_type(x.type); GB_ASSERT(vt->kind == Type_SimdVector); From fe6117fc633d59fa3cc7501a9e99590d4f82eca5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Mar 2025 13:14:54 +0000 Subject: [PATCH 31/81] Use `store` over `memcpy` --- src/llvm_backend_const.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index c011e62f4..80ba5406a 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -1190,13 +1190,13 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo ptr = LLVMBuildGEP2(p->builder, lb_type(m, f->type), ptr, indices, idx_list_len, ""); ptr = LLVMBuildPointerCast(p->builder, ptr, lb_type(m, alloc_type_pointer(tav.type)), ""); - if (LLVMIsALoadInst(elem_value)) { - i64 sz = type_size_of(tav.type); - LLVMValueRef src = LLVMGetOperand(elem_value, 0); - lb_mem_copy_non_overlapping(p, {ptr, t_rawptr}, {src, t_rawptr}, lb_const_int(m, t_int, sz), false); - } else { + // if (LLVMIsALoadInst(elem_value)) { + // i64 sz = type_size_of(tav.type); + // LLVMValueRef src = LLVMGetOperand(elem_value, 0); + // lb_mem_copy_non_overlapping(p, {ptr, t_rawptr}, {src, t_rawptr}, lb_const_int(m, t_int, sz), false); + // } else { LLVMBuildStore(p->builder, elem_value, ptr); - } + // } is_constant = false; } From 5e89e5ad8b6c8ac6599c6f435ecd66d6812c4dd5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Mar 2025 13:40:24 +0000 Subject: [PATCH 32/81] Use `store` --- src/llvm_backend_const.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 80ba5406a..5587a298a 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -1125,7 +1125,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo visited[index] = true; } else { if (!visited[index]) { - values[index] = lb_const_value(m, f->type, {}, allow_local, is_rodata).value; + values[index] = lb_const_value(m, f->type, {}, /*allow_local*/false, is_rodata).value; visited[index] = true; } @@ -1169,6 +1169,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo if (LLVMIsConstant(elem_value) && LLVMIsConstant(values[index])) { values[index] = llvm_const_insert_value(m, values[index], elem_value, idx_list, idx_list_len); } else if (is_local) { + #if 1 lbProcedure *p = m->curr_procedure; GB_ASSERT(p != nullptr); if (LLVMIsConstant(values[index])) { @@ -1190,14 +1191,16 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo ptr = LLVMBuildGEP2(p->builder, lb_type(m, f->type), ptr, indices, idx_list_len, ""); ptr = LLVMBuildPointerCast(p->builder, ptr, lb_type(m, alloc_type_pointer(tav.type)), ""); - // if (LLVMIsALoadInst(elem_value)) { - // i64 sz = type_size_of(tav.type); - // LLVMValueRef src = LLVMGetOperand(elem_value, 0); - // lb_mem_copy_non_overlapping(p, {ptr, t_rawptr}, {src, t_rawptr}, lb_const_int(m, t_int, sz), false); - // } else { + if (LLVMIsALoadInst(elem_value)) { + i64 sz = type_size_of(tav.type); + LLVMValueRef src = LLVMGetOperand(elem_value, 0); + lb_mem_copy_non_overlapping(p, {ptr, t_rawptr}, {src, t_rawptr}, lb_const_int(m, t_int, sz), false); + } else { LLVMBuildStore(p->builder, elem_value, ptr); - // } - + } + #endif + is_constant = false; + } else { is_constant = false; } } @@ -1268,15 +1271,15 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo LLVMValueRef val = old_values[i]; if (!LLVMIsConstant(val)) { LLVMValueRef dst = LLVMBuildStructGEP2(p->builder, llvm_addr_type(p->module, v.addr), v.addr.value, cast(unsigned)i, ""); - if (LLVMIsALoadInst(val)) { - Type *ptr_type = v.addr.type; - i64 sz = type_size_of(type_deref(ptr_type)); + // if (LLVMIsALoadInst(val)) { + // Type *ptr_type = v.addr.type; + // i64 sz = type_size_of(type_deref(ptr_type)); - LLVMValueRef src = LLVMGetOperand(val, 0); - lb_mem_copy_non_overlapping(p, {dst, ptr_type}, {src, ptr_type}, lb_const_int(m, t_int, sz), false); - } else { - LLVMBuildStore(p->builder, val, dst); - } + // LLVMValueRef src = LLVMGetOperand(val, 0); + // lb_mem_copy_non_overlapping(p, {dst, ptr_type}, {src, ptr_type}, lb_const_int(m, t_int, sz), false); + // } else { + LLVMBuildStore(p->builder, val, dst); + // } } } return lb_addr_load(p, v); From 660598ca8af9c670f31a26ed0af4401381573f92 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Tue, 25 Mar 2025 12:01:02 +0100 Subject: [PATCH 33/81] Fix #4968 --- core/os/dir_unix.odin | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/os/dir_unix.odin b/core/os/dir_unix.odin index f06bf8b37..c3dd844ef 100644 --- a/core/os/dir_unix.odin +++ b/core/os/dir_unix.odin @@ -5,9 +5,10 @@ import "core:strings" @(require_results) read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) { - dupfd := _dup(fd) or_return + context.allocator = allocator - dirp := _fdopendir(dupfd) or_return + dupfd := _dup(fd) or_return + dirp := _fdopendir(dupfd) or_return defer _closedir(dirp) dirpath := absolute_path_from_handle(dupfd) or_return From 4b6431729649cc729aeb3796f049d009be1ea6e7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 09:41:23 +0000 Subject: [PATCH 34/81] Make things rely less on `#if` guards --- src/linker.cpp | 50 +++++++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/src/linker.cpp b/src/linker.cpp index cf2ef638d..1568d049e 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -7,19 +7,15 @@ struct LinkerData { Array output_temp_paths; String output_base; String output_name; -#if defined(GB_SYSTEM_OSX) - b8 needs_system_library_linked; -#endif + bool needs_system_library_linked; }; gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, ...); gb_internal bool system_exec_command_line_app_output(char const *command, gbString *output); -#if defined(GB_SYSTEM_OSX) gb_internal void linker_enable_system_library_linking(LinkerData *ld) { - ld->needs_system_library_linked = 1; + ld->needs_system_library_linked = true; } -#endif gb_internal void linker_data_init(LinkerData *ld, CheckerInfo *info, String const &init_fullpath) { gbAllocator ha = heap_allocator(); @@ -28,9 +24,7 @@ gb_internal void linker_data_init(LinkerData *ld, CheckerInfo *info, String cons array_init(&ld->foreign_libraries, ha, 0, 1024); ptr_set_init(&ld->foreign_libraries_set, 1024); -#if defined(GB_SYSTEM_OSX) - ld->needs_system_library_linked = 0; -#endif + ld->needs_system_library_linked = false; if (build_context.out_filepath.len == 0) { ld->output_name = remove_directory_from_path(init_fullpath); @@ -154,16 +148,12 @@ gb_internal i32 linker_stage(LinkerData *gen) { build_context.keep_object_files = true; } else { #if defined(GB_SYSTEM_WINDOWS) - bool is_windows = true; + bool is_windows = build_context.metrics.os == TargetOs_windows; #else bool is_windows = false; #endif - #if defined(GB_SYSTEM_OSX) - bool is_osx = true; - #else - bool is_osx = false; - #endif + bool is_osx = build_context.metrics.os == TargetOs_darwin; if (is_windows) { String section_name = str_lit("msvc-link"); @@ -420,13 +410,6 @@ gb_internal i32 linker_stage(LinkerData *gen) { clang_path = "clang"; } - // NOTE(vassvik): get cwd, for used for local shared libs linking, since those have to be relative to the exe - char cwd[256]; - #if !defined(GB_SYSTEM_WINDOWS) - getcwd(&cwd[0], 256); - #endif - //printf("%s\n", cwd); - // NOTE(vassvik): needs to add the root to the library search paths, so that the full filenames of the library // files can be passed with -l: gbString lib_str = gb_string_make(heap_allocator(), "-L/"); @@ -496,19 +479,20 @@ gb_internal i32 linker_stage(LinkerData *gen) { } String obj_format; - #if defined(GB_ARCH_64_BIT) - if (is_osx) { - obj_format = str_lit("macho64"); + if (build_context.metrics.ptr_size == 8) { + if (is_osx) { + obj_format = str_lit("macho64"); + } else { + obj_format = str_lit("elf64"); + } } else { - obj_format = str_lit("elf64"); + GB_ASSERT(build_context.metrics.ptr_size == 4); + if (is_osx) { + obj_format = str_lit("macho32"); + } else { + obj_format = str_lit("elf32"); + } } - #elif defined(GB_ARCH_32_BIT) - if (is_osx) { - obj_format = str_lit("macho32"); - } else { - obj_format = str_lit("elf32"); - } - #endif // GB_ARCH_*_BIT if (build_context.metrics.arch == TargetArch_riscv64) { result = system_exec_command_line_app("clang", From e6718fcfcc979cedcdb01294003431519e7785f3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 13:09:39 +0000 Subject: [PATCH 35/81] Very very rudimentary support for `-target:linux_arm64 -subtarget:android` --- src/build_settings.cpp | 39 +++++++++- src/checker.cpp | 1 + src/linker.cpp | 167 ++++++++++++++++++++++++++++++++++++++--- src/main.cpp | 5 +- 4 files changed, 199 insertions(+), 13 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 6bee10674..30e29ab73 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -171,6 +171,7 @@ struct TargetMetrics { enum Subtarget : u32 { Subtarget_Default, Subtarget_iOS, + Subtarget_Android, Subtarget_COUNT, }; @@ -178,6 +179,7 @@ enum Subtarget : u32 { gb_global String subtarget_strings[Subtarget_COUNT] = { str_lit(""), str_lit("ios"), + str_lit("android"), }; @@ -946,6 +948,14 @@ gb_internal bool is_arch_x86(void) { gb_global String const WIN32_SEPARATOR_STRING = {cast(u8 *)"\\", 1}; gb_global String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1}; +gb_global String const SEPARATOR_STRING = +#if defined(GB_SYSTEM_WINDOWS) + WIN32_SEPARATOR_STRING; +#else + NIX_SEPARATOR_STRING; +#endif + + gb_global String const WASM_MODULE_NAME_SEPARATOR = str_lit(".."); gb_internal String internal_odin_root_dir(void); @@ -1652,6 +1662,15 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta default: GB_PANIC("Unknown architecture for darwin"); } + } else if (metrics->os == TargetOs_linux && subtarget == Subtarget_Android) { + switch (metrics->arch) { + case TargetArch_arm64: + bc->metrics.target_triplet = str_lit("aarch64-none-linux-android"); + bc->reloc_mode = RelocMode_PIC; + break; + default: + GB_PANIC("Unknown architecture for darwin"); + } } if (bc->metrics.os == TargetOs_windows) { @@ -1749,6 +1768,22 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (bc->metrics.os == TargetOs_freestanding) { bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR = !bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR; } + + if (subtarget == Subtarget_Android) { + switch (build_context.build_mode) { + case BuildMode_DynamicLibrary: + break; + case BuildMode_Executable: + case BuildMode_StaticLibrary: + case BuildMode_Object: + case BuildMode_Assembly: + case BuildMode_LLVM_IR: + gb_printf_err("Unsupported -build-mode for -target:android\n"); + gb_printf_err("\tCurrently only supporting -build-mode:shared\n"); + gb_exit(1); + break; + } + } } #if defined(GB_SYSTEM_WINDOWS) @@ -1947,7 +1982,9 @@ gb_internal bool init_build_paths(String init_filename) { output_extension = make_string(nullptr, 0); String const single_file_extension = str_lit(".odin"); - if (build_context.metrics.os == TargetOs_windows) { + if (selected_subtarget == Subtarget_Android) { + output_extension = STR_LIT("bin"); + } else if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); } else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { // Do nothing: we don't want the .bin extension diff --git a/src/checker.cpp b/src/checker.cpp index 9d822073f..c44c6ce5b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1149,6 +1149,7 @@ gb_internal void init_universal(void) { GlobalEnumValue values[Subtarget_COUNT] = { {"Default", Subtarget_Default}, {"iOS", Subtarget_iOS}, + {"Android", Subtarget_Android}, }; auto fields = add_global_enum_type(str_lit("Odin_Platform_Subtarget_Type"), values, gb_count_of(values)); diff --git a/src/linker.cpp b/src/linker.cpp index 1568d049e..5e2720eeb 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -130,6 +130,9 @@ gb_internal i32 linker_stage(LinkerData *gen) { return result; } + bool is_cross_linking = false; + bool is_android = false; + if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { #if defined(GB_SYSTEM_UNIX) result = system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s %.*s", @@ -141,12 +144,22 @@ gb_internal i32 linker_stage(LinkerData *gen) { ); #endif } else if (build_context.cross_compiling && build_context.different_os) { - gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n", - LIT(target_os_names[build_context.metrics.os]), - LIT(target_arch_names[build_context.metrics.arch]) - ); - build_context.keep_object_files = true; + switch (selected_subtarget) { + case Subtarget_Android: + is_cross_linking = true; + is_android = true; + goto try_cross_linking; + default: + gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n", + LIT(target_os_names[build_context.metrics.os]), + LIT(target_arch_names[build_context.metrics.arch]) + ); + build_context.keep_object_files = true; + break; + } } else { +try_cross_linking:; + #if defined(GB_SYSTEM_WINDOWS) bool is_windows = build_context.metrics.os == TargetOs_windows; #else @@ -155,6 +168,7 @@ gb_internal i32 linker_stage(LinkerData *gen) { bool is_osx = build_context.metrics.os == TargetOs_darwin; + if (is_windows) { String section_name = str_lit("msvc-link"); switch (build_context.linker_choice) { @@ -404,6 +418,44 @@ gb_internal i32 linker_stage(LinkerData *gen) { } else { timings_start_section(timings, str_lit("ld-link")); + String ODIN_ANDROID_NDK_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); + String ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); + + int ODIN_ANDROID_API_LEVEL = 34; + if (char const *found = gb_get_env("ODIN_ANDROID_API_LEVEL", permanent_allocator())) { + int new_level = atoi(found); + if (new_level >= 34) { + ODIN_ANDROID_API_LEVEL = new_level; + } else { + gb_printf_err("Warning: Invalid ODIN_ANDROID_API_LEVEL '%s', defaulting to %d\n", found, ODIN_ANDROID_API_LEVEL); + } + } + + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = {}; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = {}; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = {}; + + if (is_android) { + if (ODIN_ANDROID_NDK_PATH.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + return 1; + } + + if (ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + return 1; + } + + ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/usr/lib/aarch64-linux-android/")); + + char buf[32] = {}; + gb_snprintf(buf, gb_size_of(buf), "%d/", ODIN_ANDROID_API_LEVEL); + ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH, make_string_c(buf)); + + ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/")); + } + + // Link using `clang`, unless overridden by `ODIN_CLANG_PATH` environment variable. const char* clang_path = gb_get_env("ODIN_CLANG_PATH", permanent_allocator()); if (clang_path == NULL) { @@ -412,8 +464,11 @@ gb_internal i32 linker_stage(LinkerData *gen) { // NOTE(vassvik): needs to add the root to the library search paths, so that the full filenames of the library // files can be passed with -l: - gbString lib_str = gb_string_make(heap_allocator(), "-L/"); + gbString lib_str = gb_string_make(heap_allocator(), ""); defer (gb_string_free(lib_str)); + #if !defined(GB_SYSTEM_WINDOWS) + lib_str = gb_string_appendc(lib_str, "-L/ "); + #endif StringSet asm_files = {}; string_set_init(&asm_files, 64); @@ -602,6 +657,74 @@ gb_internal i32 linker_stage(LinkerData *gen) { gbString object_files = gb_string_make(heap_allocator(), ""); defer (gb_string_free(object_files)); + + + if (is_android) { // NOTE(bill): glue code needed for Android + String android_glue_object = {}; + String android_glue_static_lib = {}; + + char hash_buf[64] = {}; + gb_snprintf(hash_buf, gb_size_of(hash_buf), "%p", &hash_buf); + String hash = make_string_c(hash_buf); + + String temp_dir = normalize_path(temporary_allocator(), temporary_directory(temporary_allocator()), NIX_SEPARATOR_STRING); + android_glue_object = concatenate4_strings(temporary_allocator(), temp_dir, str_lit("android_native_app_glue-"), hash, str_lit(".o")); + android_glue_static_lib = concatenate4_strings(permanent_allocator(), temp_dir, str_lit("libandroid_native_app_glue-"), hash, str_lit(".a")); + + gbString glue = gb_string_make(heap_allocator(), clang_path); + defer (gb_string_free(glue)); + + glue = gb_string_append_fmt(glue, " --target=aarch64-linux-android%d ", ODIN_ANDROID_API_LEVEL); + glue = gb_string_appendc(glue, "-c \""); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_PATH.text, ODIN_ANDROID_NDK_PATH.len); + glue = gb_string_appendc(glue, "sources/android/native_app_glue/android_native_app_glue.c"); + glue = gb_string_appendc(glue, "\" "); + glue = gb_string_appendc(glue, "-o \""); + glue = gb_string_append_length(glue, android_glue_object.text, android_glue_object.len); + glue = gb_string_appendc(glue, "\" "); + + glue = gb_string_appendc(glue, "\"-I"); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + glue = gb_string_appendc(glue, "sysroot/usr/include/"); + glue = gb_string_appendc(glue, "\" "); + + glue = gb_string_appendc(glue, "\"-I"); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + glue = gb_string_appendc(glue, "sysroot/usr/include/aarch64-linux-android/"); + glue = gb_string_appendc(glue, "\" "); + + + glue = gb_string_appendc(glue, "-Wno-macro-redefined "); + + result = system_exec_command_line_app("android-native-app-glue-compile", glue); + if (result) { + return result; + } + + gbString ar = gb_string_make_length(heap_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + defer (gb_string_free(ar)); + + ar = gb_string_appendc(ar, "bin/llvm-ar"); + + ar = gb_string_appendc(ar, " rcs "); + + ar = gb_string_appendc(ar, "\""); + ar = gb_string_append_length(ar, android_glue_static_lib.text, android_glue_static_lib.len); + ar = gb_string_appendc(ar, "\" "); + + ar = gb_string_appendc(ar, "\""); + ar = gb_string_append_length(ar, android_glue_object.text, android_glue_object.len); + ar = gb_string_appendc(ar, "\" "); + + result = system_exec_command_line_app("android-native-app-glue-ar", ar); + if (result) { + return result; + } + + object_files = gb_string_append_fmt(object_files, "\"%.*s\" ", LIT(android_glue_static_lib)); + } + + for (String object_path : gen->output_object_paths) { object_files = gb_string_append_fmt(object_files, "\"%.*s\" ", LIT(object_path)); } @@ -654,6 +777,7 @@ gb_internal i32 linker_stage(LinkerData *gen) { if (build_context.metrics.os != TargetOs_openbsd && build_context.metrics.os != TargetOs_haiku && build_context.metrics.arch != TargetArch_riscv64 + && !is_android ) { // OpenBSD and Haiku default to PIE executable. do not pass -no-pie for it. link_settings = gb_string_appendc(link_settings, "-no-pie "); @@ -687,30 +811,53 @@ gb_internal i32 linker_stage(LinkerData *gen) { } } + if (is_android) { + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.len != 0); + + platform_lib_str = gb_string_appendc(platform_lib_str, "\"-L"); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.len); + platform_lib_str = gb_string_appendc(platform_lib_str, "\" "); + + platform_lib_str = gb_string_appendc(platform_lib_str, "\"--sysroot="); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.len); + platform_lib_str = gb_string_appendc(platform_lib_str, "\" "); + + link_settings = gb_string_appendc(link_settings, "-u ANativeActivity_onCreate "); + } + if (!build_context.no_rpath) { // Set the rpath to the $ORIGIN/@loader_path (the path of the executable), // so that dynamic libraries are looked for at that path. if (build_context.metrics.os == TargetOs_darwin) { link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,@loader_path "); } else { - link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,\\$ORIGIN "); + if (is_android) { + // ignore + } else { + link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,\\$ORIGIN "); + } } } if (!build_context.no_crt) { - platform_lib_str = gb_string_appendc(platform_lib_str, "-lm "); + lib_str = gb_string_appendc(lib_str, "-lm "); if (build_context.metrics.os == TargetOs_darwin) { // NOTE: adding this causes a warning about duplicate libraries, I think it is // automatically assumed/added by clang when you don't do `-nostdlib`. - // platform_lib_str = gb_string_appendc(platform_lib_str, "-lSystem "); + // lib_str = gb_string_appendc(lib_str, "-lSystem "); } else { - platform_lib_str = gb_string_appendc(platform_lib_str, "-lc "); + lib_str = gb_string_appendc(lib_str, "-lc "); } } gbString link_command_line = gb_string_make(heap_allocator(), clang_path); defer (gb_string_free(link_command_line)); + if (is_android) { + link_command_line = gb_string_append_fmt(link_command_line, " --target=aarch64-linux-android%d ", ODIN_ANDROID_API_LEVEL); + } link_command_line = gb_string_appendc(link_command_line, " -Wno-unused-command-line-argument "); link_command_line = gb_string_appendc(link_command_line, object_files); link_command_line = gb_string_append_fmt(link_command_line, " -o \"%.*s\" ", LIT(output_filename)); diff --git a/src/main.cpp b/src/main.cpp index 289a6150a..3549eb277 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1105,8 +1105,9 @@ gb_internal bool parse_build_flags(Array args) { String str = value.value_string; bool found = false; - if (selected_target_metrics->metrics->os != TargetOs_darwin) { - gb_printf_err("-subtarget can only be used with darwin based targets at the moment\n"); + if (selected_target_metrics->metrics->os != TargetOs_darwin && + selected_target_metrics->metrics->os != TargetOs_linux ) { + gb_printf_err("-subtarget can only be used with darwin and linux based targets at the moment\n"); bad_flags = true; break; } From dfd0f18f47cb1eeafe43fe341963095ef6fd0cbc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 13:19:40 +0000 Subject: [PATCH 36/81] Allow `check` for `-subtarget:android` --- src/build_settings.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 30e29ab73..7d864c26b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1772,15 +1772,21 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (subtarget == Subtarget_Android) { switch (build_context.build_mode) { case BuildMode_DynamicLibrary: - break; - case BuildMode_Executable: - case BuildMode_StaticLibrary: case BuildMode_Object: case BuildMode_Assembly: case BuildMode_LLVM_IR: - gb_printf_err("Unsupported -build-mode for -target:android\n"); - gb_printf_err("\tCurrently only supporting -build-mode:shared\n"); - gb_exit(1); + break; + case BuildMode_Executable: + case BuildMode_StaticLibrary: + if ((build_context.command_kind & Command__does_build) != 0) { + gb_printf_err("Unsupported -build-mode for -target:android\n"); + gb_printf_err("\tCurrently only supporting: \n"); + gb_printf_err("\t\tshared\n"); + gb_printf_err("\t\tobject\n"); + gb_printf_err("\t\tassembly\n"); + gb_printf_err("\t\tllvm-ir\n"); + gb_exit(1); + } break; } } From 518634405c3a4393e1c28739019fae4ab6c2e60e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 13:28:57 +0000 Subject: [PATCH 37/81] Add `-show-more-timings` for Android stuff --- src/linker.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/linker.cpp b/src/linker.cpp index 5e2720eeb..ea0abc5f3 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -660,6 +660,8 @@ try_cross_linking:; if (is_android) { // NOTE(bill): glue code needed for Android + TIME_SECTION("Android Native App Glue Compile"); + String android_glue_object = {}; String android_glue_static_lib = {}; @@ -701,6 +703,8 @@ try_cross_linking:; return result; } + TIME_SECTION("Android Native App Glue ar"); + gbString ar = gb_string_make_length(heap_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); defer (gb_string_free(ar)); @@ -867,6 +871,11 @@ try_cross_linking:; link_command_line = gb_string_append_fmt(link_command_line, " %.*s ", LIT(build_context.extra_linker_flags)); link_command_line = gb_string_append_fmt(link_command_line, " %s ", link_settings); + + if (is_android) { + TIME_SECTION("Linking"); + } + if (build_context.linker_choice == Linker_lld) { link_command_line = gb_string_append_fmt(link_command_line, " -fuse-ld=lld"); result = system_exec_command_line_app("lld-link", link_command_line); From db82a49576c8e691cf938f7a2a86446f14b73f7c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 13:30:18 +0000 Subject: [PATCH 38/81] Fix typos --- src/build_settings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 7d864c26b..0e040a4e6 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1669,7 +1669,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->reloc_mode = RelocMode_PIC; break; default: - GB_PANIC("Unknown architecture for darwin"); + GB_PANIC("Unknown architecture for -subtarget:android"); } } @@ -1779,7 +1779,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta case BuildMode_Executable: case BuildMode_StaticLibrary: if ((build_context.command_kind & Command__does_build) != 0) { - gb_printf_err("Unsupported -build-mode for -target:android\n"); + gb_printf_err("Unsupported -build-mode for -subtarget:android\n"); gb_printf_err("\tCurrently only supporting: \n"); gb_printf_err("\t\tshared\n"); gb_printf_err("\t\tobject\n"); From d48e7bb0b89d19a9b5b66b5b6f35852125bd3afe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 16:05:21 +0000 Subject: [PATCH 39/81] Migrate `ODIN_ANDROID_*` constants to `build_settings.cpp`; `-minimum-os-version:` for `-subtarget:android` --- src/build_settings.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++ src/linker.cpp | 42 ++++--------------------- 2 files changed, 77 insertions(+), 36 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 0e040a4e6..b61121976 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -529,6 +529,14 @@ struct BuildContext { String minimum_os_version_string; bool minimum_os_version_string_given; + + + int ODIN_ANDROID_API_LEVEL; + String ODIN_ANDROID_NDK_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH; }; gb_global BuildContext build_context = {0}; @@ -1725,6 +1733,69 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (subtarget == Subtarget_Default) { bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string); } + } else if (selected_subtarget == Subtarget_Android) { + String default_level = str_lit("34"); + if (!bc->minimum_os_version_string_given) { + bc->minimum_os_version_string = default_level; + } + BigInt level = {}; + bool success = false; + big_int_from_string(&level, bc->minimum_os_version_string, &success); + if (!success) { + gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); + bc->minimum_os_version_string = default_level; + big_int_from_string(&level, bc->minimum_os_version_string, &success); + GB_ASSERT(success); + } + + i64 new_level = big_int_to_i64(&level); + + if (new_level >= 21) { + bc->ODIN_ANDROID_API_LEVEL = cast(int)new_level; + } else { + gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); + bc->ODIN_ANDROID_API_LEVEL = atoi(cast(char const *)default_level.text); + } + + bc->ODIN_ANDROID_NDK_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); + + if (bc->ODIN_ANDROID_NDK_PATH.len != 0 && bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { + String arch = str_lit("x86_64"); + #if defined (GB_CPU_ARM) + // TODO(bill): this is a complete guess + arch = str_lit("aarch64"); + #endif + #if defined(GB_SYSTEM_WINDOWS) + bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("windows-"), arch); + #elif defined(GB_SYSTEM_OSX) + // TODO(bill): is this name even correct? + bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("darwin-"), arch); + #elif defined(GB_SYSTEM_LINUX) + bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("linux-"), arch); + #endif + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, NIX_SEPARATOR_STRING); + } + + if (bc->ODIN_ANDROID_NDK_PATH.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + gb_exit(1); + + } + + if (bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + gb_exit(1); + } + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/usr/lib/aarch64-linux-android/")); + + char buf[32] = {}; + gb_snprintf(buf, gb_size_of(buf), "%d/", bc->ODIN_ANDROID_API_LEVEL); + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH, make_string_c(buf)); + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/")); } if (!bc->custom_optimization_level) { diff --git a/src/linker.cpp b/src/linker.cpp index ea0abc5f3..1e6f045b1 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -418,43 +418,13 @@ try_cross_linking:; } else { timings_start_section(timings, str_lit("ld-link")); - String ODIN_ANDROID_NDK_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); - String ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); - - int ODIN_ANDROID_API_LEVEL = 34; - if (char const *found = gb_get_env("ODIN_ANDROID_API_LEVEL", permanent_allocator())) { - int new_level = atoi(found); - if (new_level >= 34) { - ODIN_ANDROID_API_LEVEL = new_level; - } else { - gb_printf_err("Warning: Invalid ODIN_ANDROID_API_LEVEL '%s', defaulting to %d\n", found, ODIN_ANDROID_API_LEVEL); - } - } - - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = {}; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = {}; - String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = {}; - - if (is_android) { - if (ODIN_ANDROID_NDK_PATH.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); - return 1; - } - - if (ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); - return 1; - } - - ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/usr/lib/aarch64-linux-android/")); - - char buf[32] = {}; - gb_snprintf(buf, gb_size_of(buf), "%d/", ODIN_ANDROID_API_LEVEL); - ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH, make_string_c(buf)); - - ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/")); - } + int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; + String ODIN_ANDROID_NDK_PATH = build_context.ODIN_ANDROID_NDK_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH; // Link using `clang`, unless overridden by `ODIN_CLANG_PATH` environment variable. const char* clang_path = gb_get_env("ODIN_CLANG_PATH", permanent_allocator()); From 8e884c6292135f80d9f4700a522313eddfd24f5e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 16:50:35 +0000 Subject: [PATCH 40/81] Remove `_PATH` on android environment variables --- src/build_settings.cpp | 100 ++++++++++++++++++++++++----------------- src/linker.cpp | 28 ++++++------ 2 files changed, 74 insertions(+), 54 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b61121976..eff6cef2e 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -217,9 +217,11 @@ enum CommandKind : u32 { Command_strip_semicolon = 1<<8, Command_bug_report = 1<<9, + Command_pkg_android = 1<<16, + Command__does_check = Command_run|Command_build|Command_check|Command_doc|Command_test|Command_strip_semicolon, Command__does_build = Command_run|Command_build|Command_test, - Command_all = ~(u32)0, + Command_all = ~(CommandKind)0, }; gb_global char const *odin_command_strings[32] = { @@ -532,11 +534,18 @@ struct BuildContext { int ODIN_ANDROID_API_LEVEL; - String ODIN_ANDROID_NDK_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH; + + String ODIN_ANDROID_SDK; + + String ODIN_ANDROID_NDK; + String ODIN_ANDROID_NDK_TOOLCHAIN; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; + + String ANDROID_JAR_SIGNER; + String android_keystore; + String android_manifest; }; gb_global BuildContext build_context = {0}; @@ -1734,68 +1743,79 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string); } } else if (selected_subtarget == Subtarget_Android) { - String default_level = str_lit("34"); - if (!bc->minimum_os_version_string_given) { - bc->minimum_os_version_string = default_level; - } - BigInt level = {}; - bool success = false; - big_int_from_string(&level, bc->minimum_os_version_string, &success); - if (!success) { - gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); - bc->minimum_os_version_string = default_level; + + { // Android SDK/API Level + String default_level = str_lit("34"); + if (!bc->minimum_os_version_string_given) { + bc->minimum_os_version_string = default_level; + } + BigInt level = {}; + bool success = false; big_int_from_string(&level, bc->minimum_os_version_string, &success); - GB_ASSERT(success); + if (!success) { + gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); + bc->minimum_os_version_string = default_level; + big_int_from_string(&level, bc->minimum_os_version_string, &success); + GB_ASSERT(success); + } + + i64 new_level = big_int_to_i64(&level); + + if (new_level >= 21) { + bc->ODIN_ANDROID_API_LEVEL = cast(int)new_level; + } else { + gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); + bc->ODIN_ANDROID_API_LEVEL = atoi(cast(char const *)default_level.text); + } } + bc->ODIN_ANDROID_NDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK", permanent_allocator())), NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN", permanent_allocator())), NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_SDK", permanent_allocator())), NIX_SEPARATOR_STRING); - i64 new_level = big_int_to_i64(&level); + #if defined(GB_SYSTEM_WINDOWS) + if (bc->ODIN_ANDROID_SDK.len == 0) { + bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(), + path_to_fullpath(permanent_allocator(), str_lit("%LocalAppData%/Android/Sdk"), nullptr), + NIX_SEPARATOR_STRING); + } + #endif - if (new_level >= 21) { - bc->ODIN_ANDROID_API_LEVEL = cast(int)new_level; - } else { - gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); - bc->ODIN_ANDROID_API_LEVEL = atoi(cast(char const *)default_level.text); - } - - bc->ODIN_ANDROID_NDK_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); - bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); - - if (bc->ODIN_ANDROID_NDK_PATH.len != 0 && bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { + if (bc->ODIN_ANDROID_NDK.len != 0 && bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { String arch = str_lit("x86_64"); #if defined (GB_CPU_ARM) // TODO(bill): this is a complete guess arch = str_lit("aarch64"); #endif #if defined(GB_SYSTEM_WINDOWS) - bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("windows-"), arch); + bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("windows-"), arch); #elif defined(GB_SYSTEM_OSX) // TODO(bill): is this name even correct? - bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("darwin-"), arch); + bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("darwin-"), arch); #elif defined(GB_SYSTEM_LINUX) - bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("linux-"), arch); + bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("linux-"), arch); #endif - bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, NIX_SEPARATOR_STRING); } - if (bc->ODIN_ANDROID_NDK_PATH.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + if (bc->ODIN_ANDROID_NDK.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK not set"); gb_exit(1); } - if (bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK not set"); gb_exit(1); } - bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/usr/lib/aarch64-linux-android/")); + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/usr/lib/aarch64-linux-android/")); char buf[32] = {}; gb_snprintf(buf, gb_size_of(buf), "%d/", bc->ODIN_ANDROID_API_LEVEL); - bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH, make_string_c(buf)); + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB, make_string_c(buf)); - bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/")); + bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/")); } if (!bc->custom_optimization_level) { diff --git a/src/linker.cpp b/src/linker.cpp index 1e6f045b1..29dc5afc6 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -420,11 +420,11 @@ try_cross_linking:; int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; - String ODIN_ANDROID_NDK_PATH = build_context.ODIN_ANDROID_NDK_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH; + String ODIN_ANDROID_NDK = build_context.ODIN_ANDROID_NDK; + String ODIN_ANDROID_NDK_TOOLCHAIN = build_context.ODIN_ANDROID_NDK_TOOLCHAIN; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; // Link using `clang`, unless overridden by `ODIN_CLANG_PATH` environment variable. const char* clang_path = gb_get_env("ODIN_CLANG_PATH", permanent_allocator()); @@ -648,7 +648,7 @@ try_cross_linking:; glue = gb_string_append_fmt(glue, " --target=aarch64-linux-android%d ", ODIN_ANDROID_API_LEVEL); glue = gb_string_appendc(glue, "-c \""); - glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_PATH.text, ODIN_ANDROID_NDK_PATH.len); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK.text, ODIN_ANDROID_NDK.len); glue = gb_string_appendc(glue, "sources/android/native_app_glue/android_native_app_glue.c"); glue = gb_string_appendc(glue, "\" "); glue = gb_string_appendc(glue, "-o \""); @@ -656,12 +656,12 @@ try_cross_linking:; glue = gb_string_appendc(glue, "\" "); glue = gb_string_appendc(glue, "\"-I"); - glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN.text, ODIN_ANDROID_NDK_TOOLCHAIN.len); glue = gb_string_appendc(glue, "sysroot/usr/include/"); glue = gb_string_appendc(glue, "\" "); glue = gb_string_appendc(glue, "\"-I"); - glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN.text, ODIN_ANDROID_NDK_TOOLCHAIN.len); glue = gb_string_appendc(glue, "sysroot/usr/include/aarch64-linux-android/"); glue = gb_string_appendc(glue, "\" "); @@ -675,7 +675,7 @@ try_cross_linking:; TIME_SECTION("Android Native App Glue ar"); - gbString ar = gb_string_make_length(heap_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + gbString ar = gb_string_make_length(heap_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN.text, ODIN_ANDROID_NDK_TOOLCHAIN.len); defer (gb_string_free(ar)); ar = gb_string_appendc(ar, "bin/llvm-ar"); @@ -786,16 +786,16 @@ try_cross_linking:; } if (is_android) { - GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH.len != 0); - GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.len != 0); - GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT.len != 0); platform_lib_str = gb_string_appendc(platform_lib_str, "\"-L"); - platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.len); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL.text, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL.len); platform_lib_str = gb_string_appendc(platform_lib_str, "\" "); platform_lib_str = gb_string_appendc(platform_lib_str, "\"--sysroot="); - platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.len); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT.text, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT.len); platform_lib_str = gb_string_appendc(platform_lib_str, "\" "); link_settings = gb_string_appendc(link_settings, "-u ANativeActivity_onCreate "); From 45ecafd7b1e4f6fd0a5f29ccfefcb9250bb91486 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 17:33:10 +0000 Subject: [PATCH 41/81] Really bodgy android packing system for `odin build` --- src/build_settings.cpp | 36 +++++++++- src/linker.cpp | 148 ++++++++++++++++++++++++++++++++++++++++- src/main.cpp | 22 ++++++ 3 files changed, 202 insertions(+), 4 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index eff6cef2e..bb7cb7208 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -543,8 +543,9 @@ struct BuildContext { String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; - String ANDROID_JAR_SIGNER; + String ODIN_ANDROID_JAR_SIGNER; String android_keystore; + String android_keystore_alias; String android_manifest; }; @@ -1816,6 +1817,32 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB, make_string_c(buf)); bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/")); + + + bc->ODIN_ANDROID_JAR_SIGNER = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_JAR_SIGNER", permanent_allocator())), NIX_SEPARATOR_STRING); + if (bc->build_mode == BuildMode_Executable) { + if (bc->ODIN_ANDROID_SDK.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_SDK not set, which is required for -build-mode:executable for -subtarget:android"); + gb_exit(1); + } + if (bc->ODIN_ANDROID_JAR_SIGNER.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_JAR_SIGNER not set, which is required for -build-mode:executable for -subtarget:android"); + gb_exit(1); + } + if (bc->android_keystore.len == 0) { + gb_printf_err("Error: -android-keystore: has not been set\n"); + gb_exit(1); + } + if (bc->android_keystore_alias.len == 0) { + gb_printf_err("Error: -android-keystore_alias: has not been set\n"); + gb_exit(1); + } + if (bc->android_manifest.len == 0) { + gb_printf_err("Error: -android-manifest: has not been set\n"); + gb_exit(1); + } + } + } if (!bc->custom_optimization_level) { @@ -1862,16 +1889,18 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (subtarget == Subtarget_Android) { switch (build_context.build_mode) { + case BuildMode_Executable: case BuildMode_DynamicLibrary: case BuildMode_Object: case BuildMode_Assembly: case BuildMode_LLVM_IR: break; - case BuildMode_Executable: + default: case BuildMode_StaticLibrary: if ((build_context.command_kind & Command__does_build) != 0) { gb_printf_err("Unsupported -build-mode for -subtarget:android\n"); gb_printf_err("\tCurrently only supporting: \n"); + gb_printf_err("\t\texe\n"); gb_printf_err("\t\tshared\n"); gb_printf_err("\t\tobject\n"); gb_printf_err("\t\tassembly\n"); @@ -2080,7 +2109,8 @@ gb_internal bool init_build_paths(String init_filename) { String const single_file_extension = str_lit(".odin"); if (selected_subtarget == Subtarget_Android) { - output_extension = STR_LIT("bin"); + // NOTE(bill): It's always shared! + output_extension = STR_LIT("so"); } else if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); } else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { diff --git a/src/linker.cpp b/src/linker.cpp index 29dc5afc6..7c1b045b6 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -742,7 +742,9 @@ try_cross_linking:; link_settings = gb_string_appendc(link_settings, "-Wl,-init,'_odin_entry_point' "); link_settings = gb_string_appendc(link_settings, "-Wl,-fini,'_odin_exit_point' "); } - + } else if (is_android) { + // Always shared even in android! + link_settings = gb_string_appendc(link_settings, "-shared "); } if (build_context.build_mode == BuildMode_Executable && build_context.reloc_mode == RelocMode_PIC) { @@ -866,6 +868,150 @@ try_cross_linking:; return result; } } + if (is_android && build_context.build_mode == BuildMode_Executable) { + String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); + + Array list = {}; + ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); + defer (array_free(&list)); + + switch (rd_err) { + case ReadDirectory_InvalidPath: + gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotExists: + gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Permission: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotDir: + gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Empty: + gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Unknown: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); + defer (array_free(&possible_valid_dirs)); + + + for (FileInfo fi : list) if (fi.is_dir) { + bool all_numbers = true; + for (isize i = 0; i < fi.name.len; i++) { + u8 c = fi.name[i]; + if ('0' <= c && c <= '9') { + // true + } else if (i == 0) { + all_numbers = false; + } else if (c == '.') { + break; + } else { + all_numbers = false; + } + } + + if (all_numbers) { + array_add(&possible_valid_dirs, fi); + } + } + + if (possible_valid_dirs.count == 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); + + char buf[1024] = {}; + for_array(i, possible_valid_dirs) { + FileInfo fi = possible_valid_dirs[i]; + isize n = gb_min(gb_size_of(buf)-1, fi.name.len); + memcpy(buf, fi.name.text, n); + buf[n] = 0; + + dir_numbers[i] = atoi(buf); + } + + isize closest_number_idx = -1; + for (isize i = 0; i < possible_valid_dirs.count; i++) { + if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { + if (closest_number_idx < 0) { + closest_number_idx = i; + } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { + closest_number_idx = i; + } + } + } + + if (closest_number_idx < 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); + return 1; + } + + String api_number = possible_valid_dirs[closest_number_idx].name; + + android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); + String android_sdk_platforms = concatenate_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, + make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) + ); + + + + android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); + android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); + + gbString cmd = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(cmd)); + + TIME_SECTION("Android aapt"); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "aapt"); + cmd = gb_string_appendc(cmd, " package -f"); + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); + cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_filename)); + + result = system_exec_command_line_app("android-aapt", cmd); + if (result) { + return result; + } + + TIME_SECTION("Android jarsigner"); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); + cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", + LIT(build_context.android_keystore), + LIT(output_filename), + LIT(build_context.android_keystore_alias) + ); + result = system_exec_command_line_app("android-jarsigner", cmd); + if (result) { + return result; + } + + TIME_SECTION("Android zipalign"); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "zipalign"); + cmd = gb_string_appendc(cmd, " -f 4"); + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_filename), LIT(output_filename)); + + + result = system_exec_command_line_app("android-zipalign", cmd); + if (result) { + return result; + } + } } } diff --git a/src/main.cpp b/src/main.cpp index 3549eb277..22121db73 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -408,6 +408,10 @@ enum BuildFlagKind { BuildFlag_Subsystem, #endif + BuildFlag_AndroidKeystore, + BuildFlag_AndroidKeystoreAlias, + BuildFlag_AndroidManifest, + BuildFlag_COUNT, }; @@ -624,6 +628,10 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Subsystem, str_lit("subsystem"), BuildFlagParam_String, Command__does_build); #endif + add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command__does_build); + GB_ASSERT(args.count >= 3); Array flag_args = array_slice(args, 3, args.count); @@ -1638,6 +1646,20 @@ gb_internal bool parse_build_flags(Array args) { } #endif + case BuildFlag_AndroidKeystore: + GB_ASSERT(value.kind == ExactValue_String); + build_context.android_keystore = value.value_string; + break; + + case BuildFlag_AndroidKeystoreAlias: + GB_ASSERT(value.kind == ExactValue_String); + build_context.android_keystore_alias = value.value_string; + break; + + case BuildFlag_AndroidManifest: + GB_ASSERT(value.kind == ExactValue_String); + build_context.android_manifest = value.value_string; + break; } } From eee450516e3ef03749f6f1565830ba726899413e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 17:45:04 +0000 Subject: [PATCH 42/81] Improve bodge for android execute build --- src/linker.cpp | 8 +++++--- src/string.cpp | 9 +++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/linker.cpp b/src/linker.cpp index 7c1b045b6..5880014e1 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -972,12 +972,14 @@ try_cross_linking:; TIME_SECTION("Android aapt"); + String output_apk = path_remove_extension(output_filename); + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); cmd = gb_string_appendc(cmd, "aapt"); cmd = gb_string_appendc(cmd, " package -f"); cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); - cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_filename)); + cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); result = system_exec_command_line_app("android-aapt", cmd); if (result) { @@ -990,7 +992,7 @@ try_cross_linking:; cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", LIT(build_context.android_keystore), - LIT(output_filename), + LIT(output_apk), LIT(build_context.android_keystore_alias) ); result = system_exec_command_line_app("android-jarsigner", cmd); @@ -1004,7 +1006,7 @@ try_cross_linking:; cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); cmd = gb_string_appendc(cmd, "zipalign"); cmd = gb_string_appendc(cmd, " -f 4"); - cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_filename), LIT(output_filename)); + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); result = system_exec_command_line_app("android-zipalign", cmd); diff --git a/src/string.cpp b/src/string.cpp index b001adf0e..88b679540 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -273,6 +273,15 @@ gb_internal String path_extension(String const &str, bool include_dot = true) { return substring(str, include_dot ? pos : pos + 1, str.len); } + +gb_internal String path_remove_extension(String const &str) { + isize pos = string_extension_position(str); + if (pos < 0) { + return str; + } + return substring(str, 0, pos); +} + gb_internal String string_trim_whitespace(String str) { while (str.len > 0 && rune_is_whitespace(str[str.len-1])) { str.len--; From 346836a098acbf8a79c6affc06f3a24c35761b8c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 17:45:35 +0000 Subject: [PATCH 43/81] Disable `-build-mode:exe` for `-subtarget:android` --- src/build_settings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index bb7cb7208..1823dc8b0 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1889,18 +1889,18 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (subtarget == Subtarget_Android) { switch (build_context.build_mode) { - case BuildMode_Executable: case BuildMode_DynamicLibrary: case BuildMode_Object: case BuildMode_Assembly: case BuildMode_LLVM_IR: break; default: + case BuildMode_Executable: case BuildMode_StaticLibrary: if ((build_context.command_kind & Command__does_build) != 0) { gb_printf_err("Unsupported -build-mode for -subtarget:android\n"); gb_printf_err("\tCurrently only supporting: \n"); - gb_printf_err("\t\texe\n"); + // gb_printf_err("\t\texe\n"); gb_printf_err("\t\tshared\n"); gb_printf_err("\t\tobject\n"); gb_printf_err("\t\tassembly\n"); From f13a075cd197a906fe6d5c500dc4f95244eef902 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 18:03:36 +0000 Subject: [PATCH 44/81] Begin work on `odin package-android` command --- src/build_settings.cpp | 217 ++++++++++++++++++++-------------------- src/linker.cpp | 146 --------------------------- src/main.cpp | 24 ++++- src/package_android.cpp | 163 ++++++++++++++++++++++++++++++ 4 files changed, 295 insertions(+), 255 deletions(-) create mode 100644 src/package_android.cpp diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1823dc8b0..21a692c47 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -209,15 +209,15 @@ enum BuildModeKind { enum CommandKind : u32 { Command_run = 1<<0, Command_build = 1<<1, - Command_check = 1<<3, - Command_doc = 1<<5, - Command_version = 1<<6, - Command_test = 1<<7, + Command_check = 1<<2, + Command_doc = 1<<3, + Command_version = 1<<4, + Command_test = 1<<5, - Command_strip_semicolon = 1<<8, - Command_bug_report = 1<<9, + Command_strip_semicolon = 1<<6, + Command_bug_report = 1<<7, - Command_pkg_android = 1<<16, + Command_package_android = 1<<8, Command__does_check = Command_run|Command_build|Command_check|Command_doc|Command_test|Command_strip_semicolon, Command__does_build = Command_run|Command_build|Command_test, @@ -232,6 +232,8 @@ gb_global char const *odin_command_strings[32] = { "version", "test", "strip-semicolon", + "", + "package-android", }; @@ -1489,6 +1491,107 @@ gb_internal bool has_ansi_terminal_colours(void) { return build_context.has_ansi_terminal_colours && !json_errors(); } +gb_internal void init_android_values(bool with_sdk) { + auto *bc = &build_context; + { // Android SDK/API Level + String default_level = str_lit("34"); + if (!bc->minimum_os_version_string_given) { + bc->minimum_os_version_string = default_level; + } + BigInt level = {}; + bool success = false; + big_int_from_string(&level, bc->minimum_os_version_string, &success); + if (!success) { + gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); + bc->minimum_os_version_string = default_level; + big_int_from_string(&level, bc->minimum_os_version_string, &success); + GB_ASSERT(success); + } + + i64 new_level = big_int_to_i64(&level); + + if (new_level >= 21) { + bc->ODIN_ANDROID_API_LEVEL = cast(int)new_level; + } else { + gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); + bc->ODIN_ANDROID_API_LEVEL = atoi(cast(char const *)default_level.text); + } + } + bc->ODIN_ANDROID_NDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK", permanent_allocator())), NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN", permanent_allocator())), NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_SDK", permanent_allocator())), NIX_SEPARATOR_STRING); + + #if defined(GB_SYSTEM_WINDOWS) + if (bc->ODIN_ANDROID_SDK.len == 0) { + bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(), + path_to_fullpath(permanent_allocator(), str_lit("%LocalAppData%/Android/Sdk"), nullptr), + NIX_SEPARATOR_STRING); + } + #endif + + if (bc->ODIN_ANDROID_NDK.len != 0 && bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { + String arch = str_lit("x86_64"); + #if defined (GB_CPU_ARM) + // TODO(bill): this is a complete guess + arch = str_lit("aarch64"); + #endif + #if defined(GB_SYSTEM_WINDOWS) + bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("windows-"), arch); + #elif defined(GB_SYSTEM_OSX) + // TODO(bill): is this name even correct? + bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("darwin-"), arch); + #elif defined(GB_SYSTEM_LINUX) + bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("linux-"), arch); + #endif + + bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, NIX_SEPARATOR_STRING); + } + + if (bc->ODIN_ANDROID_NDK.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK not set"); + gb_exit(1); + + } + + if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK not set"); + gb_exit(1); + } + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/usr/lib/aarch64-linux-android/")); + + char buf[32] = {}; + gb_snprintf(buf, gb_size_of(buf), "%d/", bc->ODIN_ANDROID_API_LEVEL); + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB, make_string_c(buf)); + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/")); + + + bc->ODIN_ANDROID_JAR_SIGNER = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_JAR_SIGNER", permanent_allocator())), NIX_SEPARATOR_STRING); + if (with_sdk) { + if (bc->ODIN_ANDROID_SDK.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_SDK not set, which is required for -build-mode:executable for -subtarget:android"); + gb_exit(1); + } + if (bc->ODIN_ANDROID_JAR_SIGNER.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_JAR_SIGNER not set, which is required for -build-mode:executable for -subtarget:android"); + gb_exit(1); + } + if (bc->android_keystore.len == 0) { + gb_printf_err("Error: -android-keystore: has not been set\n"); + gb_exit(1); + } + if (bc->android_keystore_alias.len == 0) { + gb_printf_err("Error: -android-keystore_alias: has not been set\n"); + gb_exit(1); + } + if (bc->android_manifest.len == 0) { + gb_printf_err("Error: -android-manifest: has not been set\n"); + gb_exit(1); + } + } +} + gb_internal bool has_asm_extension(String const &path) { String ext = path_extension(path); if (ext == ".asm") { @@ -1744,105 +1847,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string); } } else if (selected_subtarget == Subtarget_Android) { - - { // Android SDK/API Level - String default_level = str_lit("34"); - if (!bc->minimum_os_version_string_given) { - bc->minimum_os_version_string = default_level; - } - BigInt level = {}; - bool success = false; - big_int_from_string(&level, bc->minimum_os_version_string, &success); - if (!success) { - gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); - bc->minimum_os_version_string = default_level; - big_int_from_string(&level, bc->minimum_os_version_string, &success); - GB_ASSERT(success); - } - - i64 new_level = big_int_to_i64(&level); - - if (new_level >= 21) { - bc->ODIN_ANDROID_API_LEVEL = cast(int)new_level; - } else { - gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); - bc->ODIN_ANDROID_API_LEVEL = atoi(cast(char const *)default_level.text); - } - } - bc->ODIN_ANDROID_NDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK", permanent_allocator())), NIX_SEPARATOR_STRING); - bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN", permanent_allocator())), NIX_SEPARATOR_STRING); - bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_SDK", permanent_allocator())), NIX_SEPARATOR_STRING); - - #if defined(GB_SYSTEM_WINDOWS) - if (bc->ODIN_ANDROID_SDK.len == 0) { - bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(), - path_to_fullpath(permanent_allocator(), str_lit("%LocalAppData%/Android/Sdk"), nullptr), - NIX_SEPARATOR_STRING); - } - #endif - - if (bc->ODIN_ANDROID_NDK.len != 0 && bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { - String arch = str_lit("x86_64"); - #if defined (GB_CPU_ARM) - // TODO(bill): this is a complete guess - arch = str_lit("aarch64"); - #endif - #if defined(GB_SYSTEM_WINDOWS) - bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("windows-"), arch); - #elif defined(GB_SYSTEM_OSX) - // TODO(bill): is this name even correct? - bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("darwin-"), arch); - #elif defined(GB_SYSTEM_LINUX) - bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("linux-"), arch); - #endif - - bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, NIX_SEPARATOR_STRING); - } - - if (bc->ODIN_ANDROID_NDK.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK not set"); - gb_exit(1); - - } - - if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK not set"); - gb_exit(1); - } - - bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/usr/lib/aarch64-linux-android/")); - - char buf[32] = {}; - gb_snprintf(buf, gb_size_of(buf), "%d/", bc->ODIN_ANDROID_API_LEVEL); - bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB, make_string_c(buf)); - - bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/")); - - - bc->ODIN_ANDROID_JAR_SIGNER = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_JAR_SIGNER", permanent_allocator())), NIX_SEPARATOR_STRING); - if (bc->build_mode == BuildMode_Executable) { - if (bc->ODIN_ANDROID_SDK.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_SDK not set, which is required for -build-mode:executable for -subtarget:android"); - gb_exit(1); - } - if (bc->ODIN_ANDROID_JAR_SIGNER.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_JAR_SIGNER not set, which is required for -build-mode:executable for -subtarget:android"); - gb_exit(1); - } - if (bc->android_keystore.len == 0) { - gb_printf_err("Error: -android-keystore: has not been set\n"); - gb_exit(1); - } - if (bc->android_keystore_alias.len == 0) { - gb_printf_err("Error: -android-keystore_alias: has not been set\n"); - gb_exit(1); - } - if (bc->android_manifest.len == 0) { - gb_printf_err("Error: -android-manifest: has not been set\n"); - gb_exit(1); - } - } - + init_android_values(bc->build_mode == BuildMode_Executable); } if (!bc->custom_optimization_level) { diff --git a/src/linker.cpp b/src/linker.cpp index 5880014e1..ed82f2fe9 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -868,152 +868,6 @@ try_cross_linking:; return result; } } - if (is_android && build_context.build_mode == BuildMode_Executable) { - String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), - build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); - - Array list = {}; - ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); - defer (array_free(&list)); - - switch (rd_err) { - case ReadDirectory_InvalidPath: - gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_NotExists: - gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Permission: - gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_NotDir: - gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Empty: - gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Unknown: - gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); - return 1; - } - - auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); - defer (array_free(&possible_valid_dirs)); - - - for (FileInfo fi : list) if (fi.is_dir) { - bool all_numbers = true; - for (isize i = 0; i < fi.name.len; i++) { - u8 c = fi.name[i]; - if ('0' <= c && c <= '9') { - // true - } else if (i == 0) { - all_numbers = false; - } else if (c == '.') { - break; - } else { - all_numbers = false; - } - } - - if (all_numbers) { - array_add(&possible_valid_dirs, fi); - } - } - - if (possible_valid_dirs.count == 0) { - gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); - return 1; - } - - int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); - - char buf[1024] = {}; - for_array(i, possible_valid_dirs) { - FileInfo fi = possible_valid_dirs[i]; - isize n = gb_min(gb_size_of(buf)-1, fi.name.len); - memcpy(buf, fi.name.text, n); - buf[n] = 0; - - dir_numbers[i] = atoi(buf); - } - - isize closest_number_idx = -1; - for (isize i = 0; i < possible_valid_dirs.count; i++) { - if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { - if (closest_number_idx < 0) { - closest_number_idx = i; - } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { - closest_number_idx = i; - } - } - } - - if (closest_number_idx < 0) { - gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); - return 1; - } - - String api_number = possible_valid_dirs[closest_number_idx].name; - - android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); - String android_sdk_platforms = concatenate_strings(temporary_allocator(), - build_context.ODIN_ANDROID_SDK, - make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) - ); - - - - android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); - android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); - - gbString cmd = gb_string_make(heap_allocator(), ""); - defer (gb_string_free(cmd)); - - TIME_SECTION("Android aapt"); - - String output_apk = path_remove_extension(output_filename); - - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "aapt"); - cmd = gb_string_appendc(cmd, " package -f"); - cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); - cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); - cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); - - result = system_exec_command_line_app("android-aapt", cmd); - if (result) { - return result; - } - - TIME_SECTION("Android jarsigner"); - gb_string_clear(cmd); - - cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); - cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", - LIT(build_context.android_keystore), - LIT(output_apk), - LIT(build_context.android_keystore_alias) - ); - result = system_exec_command_line_app("android-jarsigner", cmd); - if (result) { - return result; - } - - TIME_SECTION("Android zipalign"); - gb_string_clear(cmd); - - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "zipalign"); - cmd = gb_string_appendc(cmd, " -f 4"); - cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); - - - result = system_exec_command_line_app("android-zipalign", cmd); - if (result) { - return result; - } - } } } diff --git a/src/main.cpp b/src/main.cpp index 22121db73..1456717c5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,6 +74,7 @@ gb_global Timings global_timings = {0}; #include "cached.cpp" #include "linker.cpp" +#include "package_android.cpp" #if defined(GB_SYSTEM_WINDOWS) && defined(ODIN_TILDE_BACKEND) #define ALLOW_TILDE 1 @@ -628,9 +629,9 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Subsystem, str_lit("subsystem"), BuildFlagParam_String, Command__does_build); #endif - add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command__does_build); - add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command__does_build); - add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command__does_build | Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command__does_build | Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command__does_build | Command_package_android); GB_ASSERT(args.count >= 3); @@ -2259,6 +2260,8 @@ gb_internal void print_show_help(String const arg0, String command, String optio } else if (command == "strip-semicolon") { print_usage_line(1, "strip-semicolon"); print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project."); + } else if (command == "package-android") { + print_usage_line(1, "package-android Packages directory in a specific layout as an APK"); } bool doc = command == "doc"; @@ -3322,6 +3325,13 @@ int main(int arg_count, char const **arg_ptr) { print_show_help(args[0], args[1], args[2]); return 0; } + } else if (command == "package-android") { + if (args.count < 3) { + usage(args[0]); + return 1; + } + build_context.command_kind = Command_package_android; + init_filename = args[2]; } else if (command == "root") { gb_printf("%.*s", LIT(odin_root_dir())); return 0; @@ -3360,6 +3370,10 @@ int main(int arg_count, char const **arg_ptr) { if (init_filename == "-file") { gb_printf_err("Did you mean `%.*s %.*s -file`?\n", LIT(args[0]), LIT(command)); } else { + if (!gb_file_exists(cast(const char*)init_filename.text)) { + gb_printf_err("The file '%.*s' was not found.\n", LIT(init_filename)); + return 1; + } gb_printf_err("Did you mean `%.*s %.*s %.*s -file`?\n", LIT(args[0]), LIT(command), LIT(init_filename)); } @@ -3393,6 +3407,10 @@ int main(int arg_count, char const **arg_ptr) { return 0; } + if (command == "package-android") { + return package_android(args); + } + // NOTE(bill): add 'shared' directory if it is not already set if (!find_library_collection_path(str_lit("shared"), nullptr)) { add_library_collection(str_lit("shared"), diff --git a/src/package_android.cpp b/src/package_android.cpp new file mode 100644 index 000000000..9e6ddeff1 --- /dev/null +++ b/src/package_android.cpp @@ -0,0 +1,163 @@ +i32 package_android(Array args) { + i32 result = 0; + + init_android_values(/*with_sdk*/true); + + int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; + + String ODIN_ANDROID_NDK = build_context.ODIN_ANDROID_NDK; + String ODIN_ANDROID_NDK_TOOLCHAIN = build_context.ODIN_ANDROID_NDK_TOOLCHAIN; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; + + + String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); + + Array list = {}; + ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); + defer (array_free(&list)); + + switch (rd_err) { + case ReadDirectory_InvalidPath: + gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotExists: + gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Permission: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotDir: + gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Empty: + gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Unknown: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); + defer (array_free(&possible_valid_dirs)); + + + for (FileInfo fi : list) if (fi.is_dir) { + bool all_numbers = true; + for (isize i = 0; i < fi.name.len; i++) { + u8 c = fi.name[i]; + if ('0' <= c && c <= '9') { + // true + } else if (i == 0) { + all_numbers = false; + } else if (c == '.') { + break; + } else { + all_numbers = false; + } + } + + if (all_numbers) { + array_add(&possible_valid_dirs, fi); + } + } + + if (possible_valid_dirs.count == 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); + + char buf[1024] = {}; + for_array(i, possible_valid_dirs) { + FileInfo fi = possible_valid_dirs[i]; + isize n = gb_min(gb_size_of(buf)-1, fi.name.len); + memcpy(buf, fi.name.text, n); + buf[n] = 0; + + dir_numbers[i] = atoi(buf); + } + + isize closest_number_idx = -1; + for (isize i = 0; i < possible_valid_dirs.count; i++) { + if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { + if (closest_number_idx < 0) { + closest_number_idx = i; + } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { + closest_number_idx = i; + } + } + } + + if (closest_number_idx < 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); + return 1; + } + + String api_number = possible_valid_dirs[closest_number_idx].name; + + android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); + String android_sdk_platforms = concatenate_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, + make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) + ); + + + + android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); + android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); + + gbString cmd = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(cmd)); + + TIME_SECTION("Android aapt"); + + String output_filename = str_lit("test"); + + String output_apk = path_remove_extension(output_filename); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "aapt"); + cmd = gb_string_appendc(cmd, " package -f"); + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); + cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); + + result = system_exec_command_line_app("android-aapt", cmd); + if (result) { + return result; + } + + TIME_SECTION("Android jarsigner"); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); + cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", + LIT(build_context.android_keystore), + LIT(output_apk), + LIT(build_context.android_keystore_alias) + ); + result = system_exec_command_line_app("android-jarsigner", cmd); + if (result) { + return result; + } + + TIME_SECTION("Android zipalign"); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "zipalign"); + cmd = gb_string_appendc(cmd, " -f 4"); + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); + + + result = system_exec_command_line_app("android-zipalign", cmd); + if (result) { + return result; + } + + return 0; +} From 1b5e83bfb628eda5a39f836c7b3116ad0666f607 Mon Sep 17 00:00:00 2001 From: Jonathan Tron Date: Wed, 26 Mar 2025 21:58:58 +0100 Subject: [PATCH 45/81] Prevent odin.js from printing empty line in the console for the ending "\n" --- core/sys/wasm/js/odin.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/core/sys/wasm/js/odin.js b/core/sys/wasm/js/odin.js index b3a49523b..d5faa5210 100644 --- a/core/sys/wasm/js/odin.js +++ b/core/sys/wasm/js/odin.js @@ -1325,18 +1325,20 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { } else if (!line.includes("\n")) { currentLine[isError] = currentLine[isError].concat(line); } else { - let lines = line.split("\n"); + let lines = line.trimEnd().split("\n"); let printLast = lines.length > 1 && line.endsWith("\n"); println(currentLine[isError].concat(lines[0])); currentLine[isError] = ""; for (let i = 1; i < lines.length-1; i++) { println(lines[i]); } - let last = lines[lines.length-1]; - if (printLast) { - println(last); - } else { - currentLine[isError] = last; + if (lines.length > 1) { + let last = lines[lines.length-1]; + if (printLast) { + println(last); + } else { + currentLine[isError] = last; + } } } From 6fda041e178bf44fae87cc56bef46db418dee0c7 Mon Sep 17 00:00:00 2001 From: Harold Brenes Date: Wed, 26 Mar 2025 19:25:06 -0400 Subject: [PATCH 46/81] Add `~{memory}` clobber to syscall intrinsics for platforms where it was not yet added. This fixes #4972 and #4588. As laytan asserts, there is no guarantee that a syscall will not modify memory that it just obtained from the user, or held onto via a previous syscall. Therefore this constraint should be required for all syscalls. --- src/llvm_backend_proc.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index a835ae2c8..3c4913d50 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2972,6 +2972,8 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu constraints = gb_string_appendc(constraints, "}"); } + constraints = gb_string_appendc(constraints, ",~{memory}"); + inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints)); } break; @@ -3034,6 +3036,8 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu constraints = gb_string_appendc(constraints, "}"); } + constraints = gb_string_appendc(constraints, ",~{memory}"); + inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints)); } break; @@ -3059,6 +3063,8 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu constraints = gb_string_appendc(constraints, "}"); } + constraints = gb_string_appendc(constraints, ",~{memory}"); + inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints)); } else { char asm_string[] = "svc #0"; @@ -3078,6 +3084,8 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu constraints = gb_string_appendc(constraints, "}"); } + constraints = gb_string_appendc(constraints, ",~{memory}"); + inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints)); } } @@ -3104,6 +3112,8 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu constraints = gb_string_appendc(constraints, "}"); } + constraints = gb_string_appendc(constraints, ",~{memory}"); + inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints)); } break; From 6689c722adbd5814876a98bb9b39790a42a4aeaa Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 09:26:33 +0000 Subject: [PATCH 47/81] `odin package android` --- src/build_settings.cpp | 4 +- src/main.cpp | 34 ++++--- ...ackage_android.cpp => package_command.cpp} | 88 ++++++++++--------- 3 files changed, 70 insertions(+), 56 deletions(-) rename src/{package_android.cpp => package_command.cpp} (65%) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 21a692c47..bdad1d633 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1547,13 +1547,13 @@ gb_internal void init_android_values(bool with_sdk) { bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, NIX_SEPARATOR_STRING); } - if (bc->ODIN_ANDROID_NDK.len == 0) { + if (bc->ODIN_ANDROID_NDK.len == 0 && !with_sdk) { gb_printf_err("Error: ODIN_ANDROID_NDK not set"); gb_exit(1); } - if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { + if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0 && !with_sdk) { gb_printf_err("Error: ODIN_ANDROID_NDK not set"); gb_exit(1); } diff --git a/src/main.cpp b/src/main.cpp index 1456717c5..54018b945 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,7 @@ gb_global Timings global_timings = {0}; #include "cached.cpp" #include "linker.cpp" -#include "package_android.cpp" +#include "package_command.cpp" #if defined(GB_SYSTEM_WINDOWS) && defined(ODIN_TILDE_BACKEND) #define ALLOW_TILDE 1 @@ -629,9 +629,9 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Subsystem, str_lit("subsystem"), BuildFlagParam_String, Command__does_build); #endif - add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command__does_build | Command_package_android); - add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command__does_build | Command_package_android); - add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command__does_build | Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command_package_android); GB_ASSERT(args.count >= 3); @@ -2260,8 +2260,10 @@ gb_internal void print_show_help(String const arg0, String command, String optio } else if (command == "strip-semicolon") { print_usage_line(1, "strip-semicolon"); print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project."); - } else if (command == "package-android") { - print_usage_line(1, "package-android Packages directory in a specific layout as an APK"); + } else if (command == "package") { + print_usage_line(1, "package Packages directory in a specific layout for that platform"); + print_usage_line(2, "Supported platforms:"); + print_usage_line(3, "android"); } bool doc = command == "doc"; @@ -3325,13 +3327,19 @@ int main(int arg_count, char const **arg_ptr) { print_show_help(args[0], args[1], args[2]); return 0; } - } else if (command == "package-android") { - if (args.count < 3) { + } else if (command == "package") { + if (args.count < 4) { usage(args[0]); return 1; } - build_context.command_kind = Command_package_android; - init_filename = args[2]; + if (args[2] == "android") { + build_context.command_kind = Command_package_android; + } else { + gb_printf_err("Unknown package command: '%.*s'\n", LIT(args[2])); + usage(args[0]); + return 1; + } + init_filename = args[3]; } else if (command == "root") { gb_printf("%.*s", LIT(odin_root_dir())); return 0; @@ -3366,7 +3374,7 @@ int main(int arg_count, char const **arg_ptr) { } if (!single_file_package) { - gb_printf_err("ERROR: `%.*s %.*s` takes a package as its first argument.\n", LIT(args[0]), LIT(command)); + gb_printf_err("ERROR: `%.*s %.*s` takes a package/directory as its first argument.\n", LIT(args[0]), LIT(command)); if (init_filename == "-file") { gb_printf_err("Did you mean `%.*s %.*s -file`?\n", LIT(args[0]), LIT(command)); } else { @@ -3407,8 +3415,8 @@ int main(int arg_count, char const **arg_ptr) { return 0; } - if (command == "package-android") { - return package_android(args); + if (command == "package") { + return package(init_filename); } // NOTE(bill): add 'shared' directory if it is not already set diff --git a/src/package_android.cpp b/src/package_command.cpp similarity index 65% rename from src/package_android.cpp rename to src/package_command.cpp index 9e6ddeff1..b5466118f 100644 --- a/src/package_android.cpp +++ b/src/package_command.cpp @@ -1,17 +1,22 @@ -i32 package_android(Array args) { +i32 package_android(String init_directory); + +i32 package(String init_directory) { + switch (build_context.command_kind) { + case Command_package_android: + return package_android(init_directory); + } + gb_printf_err("Unknown odin package \n"); + return 1; +} + + +i32 package_android(String init_directory) { i32 result = 0; init_android_values(/*with_sdk*/true); int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; - String ODIN_ANDROID_NDK = build_context.ODIN_ANDROID_NDK; - String ODIN_ANDROID_NDK_TOOLCHAIN = build_context.ODIN_ANDROID_NDK_TOOLCHAIN; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; - String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; - - String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); @@ -105,58 +110,59 @@ i32 package_android(Array args) { make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) ); - - android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); gbString cmd = gb_string_make(heap_allocator(), ""); defer (gb_string_free(cmd)); - TIME_SECTION("Android aapt"); - String output_filename = str_lit("test"); - String output_apk = path_remove_extension(output_filename); - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "aapt"); - cmd = gb_string_appendc(cmd, " package -f"); - cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); - cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); - cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); + TIME_SECTION("Android aapt"); + { + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "aapt"); + cmd = gb_string_appendc(cmd, " package -f"); + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); + cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); - result = system_exec_command_line_app("android-aapt", cmd); - if (result) { - return result; + result = system_exec_command_line_app("android-aapt", cmd); + if (result) { + return result; + } } TIME_SECTION("Android jarsigner"); - gb_string_clear(cmd); + { + gb_string_clear(cmd); - cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); - cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", - LIT(build_context.android_keystore), - LIT(output_apk), - LIT(build_context.android_keystore_alias) - ); - result = system_exec_command_line_app("android-jarsigner", cmd); - if (result) { - return result; + cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); + cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", + LIT(build_context.android_keystore), + LIT(output_apk), + LIT(build_context.android_keystore_alias) + ); + result = system_exec_command_line_app("android-jarsigner", cmd); + if (result) { + return result; + } } TIME_SECTION("Android zipalign"); - gb_string_clear(cmd); + { + gb_string_clear(cmd); - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "zipalign"); - cmd = gb_string_appendc(cmd, " -f 4"); - cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "zipalign"); + cmd = gb_string_appendc(cmd, " -f 4"); + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); - - result = system_exec_command_line_app("android-zipalign", cmd); - if (result) { - return result; + result = system_exec_command_line_app("android-zipalign", cmd); + if (result) { + return result; + } } return 0; From e29b5ae8edbd89b50e4c06fcf6a7a6719c89c1d7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 09:27:54 +0000 Subject: [PATCH 48/81] Use `u64` for the command kind just in case --- src/build_settings.cpp | 2 +- src/main.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index bdad1d633..100a01da9 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -206,7 +206,7 @@ enum BuildModeKind { BuildMode_COUNT, }; -enum CommandKind : u32 { +enum CommandKind : u64 { Command_run = 1<<0, Command_build = 1<<1, Command_check = 1<<2, diff --git a/src/main.cpp b/src/main.cpp index 54018b945..48bdb13fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -431,12 +431,12 @@ struct BuildFlag { BuildFlagKind kind; String name; BuildFlagParamKind param_kind; - u32 command_support; + u64 command_support; bool allow_multiple; }; -gb_internal void add_flag(Array *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind, u32 command_support, bool allow_multiple=false) { +gb_internal void add_flag(Array *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind, u64 command_support, bool allow_multiple=false) { BuildFlag flag = {kind, name, param_kind, command_support, allow_multiple}; array_add(build_flags, flag); } @@ -1676,8 +1676,8 @@ gb_internal bool parse_build_flags(Array args) { gb_printf_err("'%.*s' is supported with the following commands:\n", LIT(name)); gb_printf_err("\t"); i32 count = 0; - for (u32 i = 0; i < 32; i++) { - if (found_bf.command_support & (1< 0) { gb_printf_err(", "); } From e9fd565cfd7b89be8e9fbcf0270eb45bd60eeffb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 09:32:52 +0000 Subject: [PATCH 49/81] Fix flags for `odin package ` --- src/main.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 48bdb13fb..fa06a84af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -572,7 +572,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_TargetFeatures, str_lit("target-features"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_StrictTargetFeatures, str_lit("strict-target-features"), BuildFlagParam_None, Command__does_build); - add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build | Command_package_android); add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_DisableRedZone, str_lit("disable-red-zone"), BuildFlagParam_None, Command__does_build); @@ -634,8 +634,15 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command_package_android); - GB_ASSERT(args.count >= 3); - Array flag_args = array_slice(args, 3, args.count); + Array flag_args = {}; + + if (build_context.command_kind == Command_package_android) { + GB_ASSERT(args.count >= 4); + flag_args = array_slice(args, 4, args.count); + } else { + GB_ASSERT(args.count >= 3); + flag_args = array_slice(args, 3, args.count); + } bool set_flags[BuildFlag_COUNT] = {}; @@ -2273,6 +2280,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio bool strip_semicolon = command == "strip-semicolon"; bool check_only = command == "check" || strip_semicolon; bool check = run_or_build || check_only; + bool is_package = command == "package"; if (command == "help") { doc = true; @@ -2540,13 +2548,15 @@ gb_internal void print_show_help(String const arg0, String command, String optio } } - if (run_or_build) { + if (run_or_build || is_package) { if (print_flag("-minimum-os-version:")) { print_usage_line(2, "Sets the minimum OS version targeted by the application."); print_usage_line(2, "Default: -minimum-os-version:11.0.0"); print_usage_line(2, "Only used when target is Darwin, if given, linking mismatched versions will emit a warning."); } + } + if (run_or_build) { if (print_flag("-no-bounds-check")) { print_usage_line(2, "Disables bounds checking program wide."); } From caac504b8842714076fcaffbdad22466255b9083 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 09:53:44 +0000 Subject: [PATCH 50/81] Handle android flags to be more "optional" --- src/package_command.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/package_command.cpp b/src/package_command.cpp index b5466118f..de2fd9d3e 100644 --- a/src/package_command.cpp +++ b/src/package_command.cpp @@ -124,7 +124,9 @@ i32 package_android(String init_directory) { cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); cmd = gb_string_appendc(cmd, "aapt"); cmd = gb_string_appendc(cmd, " package -f"); - cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + if (build_context.android_manifest.len != 0) { + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + } cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); @@ -139,11 +141,15 @@ i32 package_android(String init_directory) { gb_string_clear(cmd); cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); - cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", - LIT(build_context.android_keystore), - LIT(output_apk), - LIT(build_context.android_keystore_alias) - ); + cmd = gb_string_append_fmt(cmd, " -storepass android"); + if (build_context.android_keystore.len != 0) { + cmd = gb_string_append_fmt(cmd, " -keystore \"%.*s\"", LIT(build_context.android_keystore)); + } + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\"", LIT(output_apk)); + if (build_context.android_keystore_alias.len != 0) { + cmd = gb_string_append_fmt(cmd, " \"%.*s\"", LIT(build_context.android_keystore_alias)); + } + result = system_exec_command_line_app("android-jarsigner", cmd); if (result) { return result; From 0e6cc6ec4ba1c5cee8815303cd5b98e14a30ee29 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 10:31:59 +0000 Subject: [PATCH 51/81] Use working directory for `aapt` commands --- src/build_settings.cpp | 4 --- src/package_command.cpp | 46 +++++++++++++++++++++---- src/path.cpp | 76 ++++++++++++++++++++++++++++++++++------- 3 files changed, 104 insertions(+), 22 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 100a01da9..1d20ed82b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1585,10 +1585,6 @@ gb_internal void init_android_values(bool with_sdk) { gb_printf_err("Error: -android-keystore_alias: has not been set\n"); gb_exit(1); } - if (bc->android_manifest.len == 0) { - gb_printf_err("Error: -android-manifest: has not been set\n"); - gb_exit(1); - } } } diff --git a/src/package_command.cpp b/src/package_command.cpp index de2fd9d3e..43db46521 100644 --- a/src/package_command.cpp +++ b/src/package_command.cpp @@ -10,11 +10,20 @@ i32 package(String init_directory) { } -i32 package_android(String init_directory) { - i32 result = 0; +i32 package_android(String original_init_directory) { + TEMPORARY_ALLOCATOR_GUARD(); + i32 result = 0; init_android_values(/*with_sdk*/true); + bool init_directory_ok = false; + String init_directory = path_to_fullpath(temporary_allocator(), original_init_directory, &init_directory_ok); + if (!init_directory_ok) { + gb_printf_err("Error: '%.*s' is not a valid directory", LIT(original_init_directory)); + return 1; + } + init_directory = normalize_path(temporary_allocator(), init_directory, NIX_SEPARATOR_STRING); + int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), @@ -116,16 +125,37 @@ i32 package_android(String init_directory) { gbString cmd = gb_string_make(heap_allocator(), ""); defer (gb_string_free(cmd)); + + String current_directory = normalize_path(temporary_allocator(), get_working_directory(temporary_allocator()), NIX_SEPARATOR_STRING); + defer (set_working_directory(current_directory)); + + if (current_directory.len != 0) { + bool ok = set_working_directory(init_directory); + if (!ok) { + gb_printf_err("Error: Unable to currectly set the current working directory to '%.*s'\n", LIT(init_directory)); + } + } + String output_filename = str_lit("test"); String output_apk = path_remove_extension(output_filename); TIME_SECTION("Android aapt"); { + TEMPORARY_ALLOCATOR_GUARD(); + gb_string_clear(cmd); + + String manifest = {}; + if (build_context.android_manifest.len != 0) { + manifest = concatenate_strings(temporary_allocator(), current_directory, build_context.android_manifest); + } else { + manifest = concatenate_strings(temporary_allocator(), init_directory, str_lit("AndroidManifest.xml")); + } + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); cmd = gb_string_appendc(cmd, "aapt"); cmd = gb_string_appendc(cmd, " package -f"); - if (build_context.android_manifest.len != 0) { - cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + if (manifest.len != 0) { + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(manifest)); } cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); @@ -138,16 +168,19 @@ i32 package_android(String init_directory) { TIME_SECTION("Android jarsigner"); { + TEMPORARY_ALLOCATOR_GUARD(); gb_string_clear(cmd); cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); cmd = gb_string_append_fmt(cmd, " -storepass android"); if (build_context.android_keystore.len != 0) { - cmd = gb_string_append_fmt(cmd, " -keystore \"%.*s\"", LIT(build_context.android_keystore)); + String keystore = concatenate_strings(temporary_allocator(), current_directory, build_context.android_keystore); + cmd = gb_string_append_fmt(cmd, " -keystore \"%.*s\"", LIT(keystore)); } cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\"", LIT(output_apk)); if (build_context.android_keystore_alias.len != 0) { - cmd = gb_string_append_fmt(cmd, " \"%.*s\"", LIT(build_context.android_keystore_alias)); + String keystore_alias = build_context.android_keystore_alias; + cmd = gb_string_append_fmt(cmd, " \"%.*s\"", LIT(keystore_alias)); } result = system_exec_command_line_app("android-jarsigner", cmd); @@ -158,6 +191,7 @@ i32 package_android(String init_directory) { TIME_SECTION("Android zipalign"); { + TEMPORARY_ALLOCATOR_GUARD(); gb_string_clear(cmd); cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); diff --git a/src/path.cpp b/src/path.cpp index 2c08ddd98..2217622c6 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -30,28 +30,80 @@ gb_internal String remove_directory_from_path(String const &s) { } -// NOTE(Mark Naughton): getcwd as String -#if !defined(GB_SYSTEM_WINDOWS) -gb_internal String get_current_directory(void) { - char cwd[256]; - getcwd(cwd, 256); +#if defined(GB_SYSTEM_WINDOWS) +gb_global SRWLOCK cwd_lock; - return make_string_c(cwd); +String get_working_directory(gbAllocator allocator) { + AcquireSRWLockExclusive(&cwd_lock); + + TEMPORARY_ALLOCATOR_GUARD(); + + DWORD sz_utf16 = GetCurrentDirectoryW(0, nullptr); + wchar_t *dir_buf_wstr = gb_alloc_array(temporary_allocator(), wchar_t, sz_utf16); + if (dir_buf_wstr == nullptr) { + ReleaseSRWLockExclusive(&cwd_lock); + return {}; + } + + DWORD n = GetCurrentDirectoryW(sz_utf16, dir_buf_wstr); + GB_ASSERT(n+1 == sz_utf16); + ReleaseSRWLockExclusive(&cwd_lock); + + + isize buf_len = sz_utf16*4; + u8 *buf = gb_alloc_array(allocator, u8, buf_len); + gb_ucs2_to_utf8(buf, buf_len, cast(u16 *)dir_buf_wstr); + + return make_string_c(cast(char const *)buf); +} + +bool set_working_directory(String dir) { + bool ok = false; + TEMPORARY_ALLOCATOR_GUARD(); + + char const *cdir = alloc_cstring(temporary_allocator(), dir); + wchar_t *wstr = gb__alloc_utf8_to_ucs2(temporary_allocator(), cdir, nullptr); + + AcquireSRWLockExclusive(&cwd_lock); + + ok = SetCurrentDirectoryW(wstr); + + ReleaseSRWLockExclusive(&cwd_lock); + + return ok; } #else -gb_internal String get_current_directory(void) { - gbAllocator a = heap_allocator(); - wchar_t cwd[256]; - GetCurrentDirectoryW(256, cwd); +String get_working_directory(gbAllocator allocator) { + TEMPORARY_ALLOCATOR_GUARD(); - String16 wstr = make_string16_c(cwd); + auto buf = array_make(temporary_allocator()); + size_t size = PATH_MAX: - return string16_to_string(a, wstr); + char const *cwd; + for (; cwd == nullptr; size *= 2) { + array_resize(&buf, size); + + cwd = getcwd(buf.data, buf.count); + if cwd == nullptr && errno() != ERANGE { + return {}; + } + } + + return copy_string(allocator, make_string_c(cwd)); } + +bool set_working_directory(String dir) { + TEMPORARY_ALLOCATOR_GUARD(); + char const *cdir = alloc_cstring(temporary_allocator(), dir); + return !chdir(cdir); +} + #endif + + gb_internal bool path_is_directory(String path); gb_internal String directory_from_path(String const &s) { From 1fc1a7fd51cec273619e1bcc80ae82fc7ed38032 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 11:12:44 +0000 Subject: [PATCH 52/81] Fix typos --- src/path.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/path.cpp b/src/path.cpp index 2217622c6..5a71c5463 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -79,14 +79,14 @@ String get_working_directory(gbAllocator allocator) { TEMPORARY_ALLOCATOR_GUARD(); auto buf = array_make(temporary_allocator()); - size_t size = PATH_MAX: + size_t size = PATH_MAX; char const *cwd; for (; cwd == nullptr; size *= 2) { array_resize(&buf, size); cwd = getcwd(buf.data, buf.count); - if cwd == nullptr && errno() != ERANGE { + if (cwd == nullptr && errno() != ERANGE) { return {}; } } From 9b3d381af048a0d12c45f4ea27ff435b3aeb698b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 12:55:41 +0000 Subject: [PATCH 53/81] Fix another typo --- src/path.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/path.cpp b/src/path.cpp index 5a71c5463..12f8d3d4e 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -86,7 +86,7 @@ String get_working_directory(gbAllocator allocator) { array_resize(&buf, size); cwd = getcwd(buf.data, buf.count); - if (cwd == nullptr && errno() != ERANGE) { + if (cwd == nullptr && errno != ERANGE) { return {}; } } From 18988b5f94ba3447167befad84b42ab23358ea38 Mon Sep 17 00:00:00 2001 From: Dave Voutila Date: Thu, 27 Mar 2025 10:36:40 -0400 Subject: [PATCH 54/81] Fix use of errno on OpenBSD. --- base/runtime/os_specific_bsd.odin | 2 +- core/os/os_openbsd.odin | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/runtime/os_specific_bsd.odin b/base/runtime/os_specific_bsd.odin index 5d198484b..466001ada 100644 --- a/base/runtime/os_specific_bsd.odin +++ b/base/runtime/os_specific_bsd.odin @@ -9,7 +9,7 @@ foreign libc { @(link_name="write") _unix_write :: proc(fd: i32, buf: rawptr, size: int) -> int --- - when ODIN_OS == .NetBSD { + when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { @(link_name="__errno") __error :: proc() -> ^i32 --- } else { __error :: proc() -> ^i32 --- diff --git a/core/os/os_openbsd.odin b/core/os/os_openbsd.odin index 3c377968c..6548a57dc 100644 --- a/core/os/os_openbsd.odin +++ b/core/os/os_openbsd.odin @@ -343,7 +343,7 @@ AT_REMOVEDIR :: 0x08 @(default_calling_convention="c") foreign libc { - @(link_name="__error") __error :: proc() -> ^c.int --- + @(link_name="__errno") __error :: proc() -> ^c.int --- @(link_name="fork") _unix_fork :: proc() -> pid_t --- @(link_name="getthrid") _unix_getthrid :: proc() -> int --- From 5274aa53b3eefc661e48fb66befd3e75f7bc4177 Mon Sep 17 00:00:00 2001 From: Dave Voutila Date: Thu, 27 Mar 2025 10:37:36 -0400 Subject: [PATCH 55/81] Fix linker invocation on OpenBSD. Firstly, we need to explicitly request pthreads and also need to mind the fact ports (like SDL2) install in /usr/local/lib. Secondly, since OpenBSD 7.4 the system enforces indirect branch targets on hardware platforms that support it. Until the LLVM integration in Odin can be changed to emit proper branch targets (e.g. endbr64 on amd64), we need to request the linker make the resulting program opt-out of enforcement. --- src/linker.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/linker.cpp b/src/linker.cpp index cf2ef638d..56e8d3034 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -701,6 +701,13 @@ gb_internal i32 linker_stage(LinkerData *gen) { // This points the linker to where the entry point is link_settings = gb_string_appendc(link_settings, "-e _main "); } + } else if (build_context.metrics.os == TargetOs_openbsd) { + // OpenBSD ports install shared libraries in /usr/local/lib. Also, we must explicitly link libpthread. + platform_lib_str = gb_string_appendc(platform_lib_str, "-lpthread -Wl,-L/usr/local/lib "); + // Until the LLVM back-end can be adapted to emit endbr64 instructions on amd64, we + // need to pass -z nobtcfi in order to allow the resulting program to run under + // OpenBSD 7.4 and newer. Once support is added at compile time, this can be dropped. + platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-z,nobtcfi "); } if (!build_context.no_rpath) { From d3f0b31fcc48772f1457fa1eb487fd7afcc6d43d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 15:08:53 +0000 Subject: [PATCH 56/81] Improve `or_else` type inference logic --- src/check_expr.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6fba64765..91d9e669f 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8977,8 +8977,14 @@ gb_internal ExprKind check_or_else_expr(CheckerContext *c, Operand *o, Ast *node o->expr = node; return Expr_Expr; } + + Type *left_type = nullptr; + Type *right_type = nullptr; + check_or_else_split_types(c, &x, name, &left_type, &right_type); + add_type_and_value(c, arg, x.mode, x.type, x.value); + bool y_is_diverging = false; - check_expr_base(c, &y, default_value, x.type); + check_expr_base(c, &y, default_value, left_type); switch (y.mode) { case Addressing_NoValue: if (is_diverging_expr(y.expr)) { @@ -9003,11 +9009,6 @@ gb_internal ExprKind check_or_else_expr(CheckerContext *c, Operand *o, Ast *node return Expr_Expr; } - Type *left_type = nullptr; - Type *right_type = nullptr; - check_or_else_split_types(c, &x, name, &left_type, &right_type); - add_type_and_value(c, arg, x.mode, x.type, x.value); - if (left_type != nullptr) { if (!y_is_diverging) { check_assignment(c, &y, left_type, name); From b9aa51849bb2352dea83dc0c2b5a10c9ef485284 Mon Sep 17 00:00:00 2001 From: G'lek Tarssza Date: Thu, 27 Mar 2025 14:25:20 -0600 Subject: [PATCH 57/81] Use Microsoft "best practices" for using `vswhere` See https://github.com/microsoft/vswhere/wiki/Find-VC for more details. --- build.bat | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.bat b/build.bat index a788a8c04..4c015e133 100644 --- a/build.bat +++ b/build.bat @@ -4,12 +4,12 @@ setlocal EnableDelayedExpansion where /Q cl.exe || ( set __VSCMD_ARG_NO_LOGO=1 - for /f "tokens=*" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath') do set VS=%%i + for /f "tokens=*" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') do set VS=%%i if "!VS!" equ "" ( - echo ERROR: Visual Studio installation not found + echo ERROR: MSVC installation not found exit /b 1 ) - call "!VS!\VC\Auxiliary\Build\vcvarsall.bat" amd64 || exit /b 1 + call "!VS!\Common7\Tools\vsdevcmd.bat" -arch=x64 -host_arch=x64 || exit /b 1 ) if "%VSCMD_ARG_TGT_ARCH%" neq "x64" ( @@ -152,4 +152,4 @@ if %release_mode% EQU 0 echo: & echo Debug compiler built. Note: run "build.bat del *.obj > NUL 2> NUL -:end_of_build \ No newline at end of file +:end_of_build From e7ae7b8fd452dd7a31532695c1b850842049bc52 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 28 Mar 2025 09:27:04 +0000 Subject: [PATCH 58/81] Command `package` -> `bundle` --- src/build_settings.cpp | 10 +++++-- ...package_command.cpp => bundle_command.cpp} | 10 +++---- src/main.cpp | 28 +++++++++---------- 3 files changed, 27 insertions(+), 21 deletions(-) rename src/{package_command.cpp => bundle_command.cpp} (97%) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1d20ed82b..1f5aba254 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -217,7 +217,10 @@ enum CommandKind : u64 { Command_strip_semicolon = 1<<6, Command_bug_report = 1<<7, - Command_package_android = 1<<8, + Command_bundle_android = 1<<8, + Command_bundle_macos = 1<<9, + Command_bundle_ios = 1<<10, + Command_bundle_orca = 1<<11, Command__does_check = Command_run|Command_build|Command_check|Command_doc|Command_test|Command_strip_semicolon, Command__does_build = Command_run|Command_build|Command_test, @@ -233,7 +236,10 @@ gb_global char const *odin_command_strings[32] = { "test", "strip-semicolon", "", - "package-android", + "bundle android", + "bundle macos", + "bundle ios", + "bundle orca", }; diff --git a/src/package_command.cpp b/src/bundle_command.cpp similarity index 97% rename from src/package_command.cpp rename to src/bundle_command.cpp index 43db46521..b3bca2b51 100644 --- a/src/package_command.cpp +++ b/src/bundle_command.cpp @@ -1,16 +1,16 @@ -i32 package_android(String init_directory); +i32 bundle_android(String init_directory); -i32 package(String init_directory) { +i32 bundle(String init_directory) { switch (build_context.command_kind) { - case Command_package_android: - return package_android(init_directory); + case Command_bundle_android: + return bundle_android(init_directory); } gb_printf_err("Unknown odin package \n"); return 1; } -i32 package_android(String original_init_directory) { +i32 bundle_android(String original_init_directory) { TEMPORARY_ALLOCATOR_GUARD(); i32 result = 0; diff --git a/src/main.cpp b/src/main.cpp index fa06a84af..c19bbde22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,7 @@ gb_global Timings global_timings = {0}; #include "cached.cpp" #include "linker.cpp" -#include "package_command.cpp" +#include "bundle_command.cpp" #if defined(GB_SYSTEM_WINDOWS) && defined(ODIN_TILDE_BACKEND) #define ALLOW_TILDE 1 @@ -572,7 +572,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_TargetFeatures, str_lit("target-features"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_StrictTargetFeatures, str_lit("strict-target-features"), BuildFlagParam_None, Command__does_build); - add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build | Command_package_android); + add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build | Command_bundle_android); add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_DisableRedZone, str_lit("disable-red-zone"), BuildFlagParam_None, Command__does_build); @@ -629,14 +629,14 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Subsystem, str_lit("subsystem"), BuildFlagParam_String, Command__does_build); #endif - add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command_package_android); - add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command_package_android); - add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command_bundle_android); + add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command_bundle_android); + add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command_bundle_android); Array flag_args = {}; - if (build_context.command_kind == Command_package_android) { + if (build_context.command_kind == Command_bundle_android) { GB_ASSERT(args.count >= 4); flag_args = array_slice(args, 4, args.count); } else { @@ -2267,8 +2267,8 @@ gb_internal void print_show_help(String const arg0, String command, String optio } else if (command == "strip-semicolon") { print_usage_line(1, "strip-semicolon"); print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project."); - } else if (command == "package") { - print_usage_line(1, "package Packages directory in a specific layout for that platform"); + } else if (command == "bundle") { + print_usage_line(1, "bundle Bundles a directory in a specific layout for that platform"); print_usage_line(2, "Supported platforms:"); print_usage_line(3, "android"); } @@ -2280,7 +2280,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio bool strip_semicolon = command == "strip-semicolon"; bool check_only = command == "check" || strip_semicolon; bool check = run_or_build || check_only; - bool is_package = command == "package"; + bool bundle = command == "bundle"; if (command == "help") { doc = true; @@ -2548,7 +2548,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio } } - if (run_or_build || is_package) { + if (run_or_build || bundle) { if (print_flag("-minimum-os-version:")) { print_usage_line(2, "Sets the minimum OS version targeted by the application."); print_usage_line(2, "Default: -minimum-os-version:11.0.0"); @@ -3337,13 +3337,13 @@ int main(int arg_count, char const **arg_ptr) { print_show_help(args[0], args[1], args[2]); return 0; } - } else if (command == "package") { + } else if (command == "bundle") { if (args.count < 4) { usage(args[0]); return 1; } if (args[2] == "android") { - build_context.command_kind = Command_package_android; + build_context.command_kind = Command_bundle_android; } else { gb_printf_err("Unknown package command: '%.*s'\n", LIT(args[2])); usage(args[0]); @@ -3425,8 +3425,8 @@ int main(int arg_count, char const **arg_ptr) { return 0; } - if (command == "package") { - return package(init_filename); + if (command == "bundle") { + return bundle(init_filename); } // NOTE(bill): add 'shared' directory if it is not already set From a9d073e0bb9993b23fb7f5ee652005bfd73a4de4 Mon Sep 17 00:00:00 2001 From: teapo <75266237+4teapo@users.noreply.github.com> Date: Fri, 28 Mar 2025 18:31:23 +0100 Subject: [PATCH 59/81] Update shell.nix --- shell.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell.nix b/shell.nix index 040c7696e..64e585dd3 100644 --- a/shell.nix +++ b/shell.nix @@ -4,9 +4,9 @@ pkgs.mkShell { nativeBuildInputs = with pkgs; [ git which - clang_17 - llvmPackages_17.llvm - llvmPackages_17.bintools + clang_18 + llvmPackages_18.llvm + llvmPackages_18.bintools ]; shellHook="CXX=clang++"; } From 73c3e60ce5a04370c3a7d0a9704083605b58f342 Mon Sep 17 00:00:00 2001 From: teapo <75266237+4teapo@users.noreply.github.com> Date: Fri, 28 Mar 2025 18:38:08 +0100 Subject: [PATCH 60/81] Use LLVM 20 in shell.nix --- shell.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell.nix b/shell.nix index 64e585dd3..33e90018c 100644 --- a/shell.nix +++ b/shell.nix @@ -4,9 +4,9 @@ pkgs.mkShell { nativeBuildInputs = with pkgs; [ git which - clang_18 - llvmPackages_18.llvm - llvmPackages_18.bintools + clang_20 + llvmPackages_20.llvm + llvmPackages_20.bintools ]; shellHook="CXX=clang++"; } From 327d9f134ddb664b38d4945fee2d0ecb9d259506 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sat, 29 Mar 2025 23:26:40 +0100 Subject: [PATCH 61/81] net: drop core:os dependency for Darwin --- core/net/errors_darwin.odin | 189 ++++++++++++------------- core/net/interface_darwin.odin | 108 +++++++++------ core/net/socket_darwin.odin | 243 +++++++++++++++++---------------- 3 files changed, 291 insertions(+), 249 deletions(-) diff --git a/core/net/errors_darwin.odin b/core/net/errors_darwin.odin index 2905b44bc..ccf1e0f7f 100644 --- a/core/net/errors_darwin.odin +++ b/core/net/errors_darwin.odin @@ -21,188 +21,191 @@ package net */ import "core:c" -import "core:os" +import "core:sys/posix" + +@(private) +ESHUTDOWN :: 58 Create_Socket_Error :: enum c.int { None = 0, - Family_Not_Supported_For_This_Socket = c.int(os.EAFNOSUPPORT), - No_Socket_Descriptors_Available = c.int(os.EMFILE), - No_Buffer_Space_Available = c.int(os.ENOBUFS), - No_Memory_Available_Available = c.int(os.ENOMEM), - Protocol_Unsupported_By_System = c.int(os.EPROTONOSUPPORT), - Wrong_Protocol_For_Socket = c.int(os.EPROTONOSUPPORT), - Family_And_Socket_Type_Mismatch = c.int(os.EPROTONOSUPPORT), + Family_Not_Supported_For_This_Socket = c.int(posix.EAFNOSUPPORT), + No_Socket_Descriptors_Available = c.int(posix.EMFILE), + No_Buffer_Space_Available = c.int(posix.ENOBUFS), + No_Memory_Available = c.int(posix.ENOMEM), + Protocol_Unsupported_By_System = c.int(posix.EPROTONOSUPPORT), + Wrong_Protocol_For_Socket = c.int(posix.EPROTONOSUPPORT), + Family_And_Socket_Type_Mismatch = c.int(posix.EPROTONOSUPPORT), } Dial_Error :: enum c.int { None = 0, Port_Required = -1, // Attempted to dial an endpointing without a port being set. - Address_In_Use = c.int(os.EADDRINUSE), - In_Progress = c.int(os.EINPROGRESS), - Cannot_Use_Any_Address = c.int(os.EADDRNOTAVAIL), - Wrong_Family_For_Socket = c.int(os.EAFNOSUPPORT), - Refused = c.int(os.ECONNREFUSED), - Is_Listening_Socket = c.int(os.EACCES), - Already_Connected = c.int(os.EISCONN), - Network_Unreachable = c.int(os.ENETUNREACH), // Device is offline - Host_Unreachable = c.int(os.EHOSTUNREACH), // Remote host cannot be reached - No_Buffer_Space_Available = c.int(os.ENOBUFS), - Not_Socket = c.int(os.ENOTSOCK), - Timeout = c.int(os.ETIMEDOUT), + Address_In_Use = c.int(posix.EADDRINUSE), + In_Progress = c.int(posix.EINPROGRESS), + Cannot_Use_Any_Address = c.int(posix.EADDRNOTAVAIL), + Wrong_Family_For_Socket = c.int(posix.EAFNOSUPPORT), + Refused = c.int(posix.ECONNREFUSED), + Is_Listening_Socket = c.int(posix.EACCES), + Already_Connected = c.int(posix.EISCONN), + Network_Unreachable = c.int(posix.ENETUNREACH), // Device is offline + Host_Unreachable = c.int(posix.EHOSTUNREACH), // Remote host cannot be reached + No_Buffer_Space_Available = c.int(posix.ENOBUFS), + Not_Socket = c.int(posix.ENOTSOCK), + Timeout = c.int(posix.ETIMEDOUT), // TODO: we may need special handling for this; maybe make a socket a struct with metadata? - Would_Block = c.int(os.EWOULDBLOCK), + Would_Block = c.int(posix.EWOULDBLOCK), } Bind_Error :: enum c.int { None = 0, Privileged_Port_Without_Root = -1, // Attempted to bind to a port less than 1024 without root access. - Address_In_Use = c.int(os.EADDRINUSE), // Another application is currently bound to this endpoint. - Given_Nonlocal_Address = c.int(os.EADDRNOTAVAIL), // The address is not a local address on this machine. - Broadcast_Disabled = c.int(os.EACCES), // To bind a UDP socket to the broadcast address, the appropriate socket option must be set. - Address_Family_Mismatch = c.int(os.EFAULT), // The address family of the address does not match that of the socket. - Already_Bound = c.int(os.EINVAL), // The socket is already bound to an address. - No_Ports_Available = c.int(os.ENOBUFS), // There are not enough ephemeral ports available. + Address_In_Use = c.int(posix.EADDRINUSE), // Another application is currently bound to this endpoint. + Given_Nonlocal_Address = c.int(posix.EADDRNOTAVAIL), // The address is not a local address on this machine. + Broadcast_Disabled = c.int(posix.EACCES), // To bind a UDP socket to the broadcast address, the appropriate socket option must be set. + Address_Family_Mismatch = c.int(posix.EFAULT), // The address family of the address does not match that of the socket. + Already_Bound = c.int(posix.EINVAL), // The socket is already bound to an address. + No_Ports_Available = c.int(posix.ENOBUFS), // There are not enough ephemeral ports available. } Listen_Error :: enum c.int { None = 0, - Address_In_Use = c.int(os.EADDRINUSE), - Already_Connected = c.int(os.EISCONN), - No_Socket_Descriptors_Available = c.int(os.EMFILE), - No_Buffer_Space_Available = c.int(os.ENOBUFS), - Nonlocal_Address = c.int(os.EADDRNOTAVAIL), - Not_Socket = c.int(os.ENOTSOCK), - Listening_Not_Supported_For_This_Socket = c.int(os.EOPNOTSUPP), + Address_In_Use = c.int(posix.EADDRINUSE), + Already_Connected = c.int(posix.EISCONN), + No_Socket_Descriptors_Available = c.int(posix.EMFILE), + No_Buffer_Space_Available = c.int(posix.ENOBUFS), + Nonlocal_Address = c.int(posix.EADDRNOTAVAIL), + Not_Socket = c.int(posix.ENOTSOCK), + Listening_Not_Supported_For_This_Socket = c.int(posix.EOPNOTSUPP), } Accept_Error :: enum c.int { None = 0, // TODO(tetra): Is this error actually possible here? Or is like Linux, in which case we can remove it. - Reset = c.int(os.ECONNRESET), - Not_Listening = c.int(os.EINVAL), - No_Socket_Descriptors_Available_For_Client_Socket = c.int(os.EMFILE), - No_Buffer_Space_Available = c.int(os.ENOBUFS), - Not_Socket = c.int(os.ENOTSOCK), - Not_Connection_Oriented_Socket = c.int(os.EOPNOTSUPP), + Reset = c.int(posix.ECONNRESET), + Not_Listening = c.int(posix.EINVAL), + No_Socket_Descriptors_Available_For_Client_Socket = c.int(posix.EMFILE), + No_Buffer_Space_Available = c.int(posix.ENOBUFS), + Not_Socket = c.int(posix.ENOTSOCK), + Not_Connection_Oriented_Socket = c.int(posix.EOPNOTSUPP), // TODO: we may need special handling for this; maybe make a socket a struct with metadata? - Would_Block = c.int(os.EWOULDBLOCK), + Would_Block = c.int(posix.EWOULDBLOCK), } TCP_Recv_Error :: enum c.int { None = 0, - Shutdown = c.int(os.ESHUTDOWN), - Not_Connected = c.int(os.ENOTCONN), + Shutdown = ESHUTDOWN, + Not_Connected = c.int(posix.ENOTCONN), // TODO(tetra): Is this error actually possible here? - Connection_Broken = c.int(os.ENETRESET), - Not_Socket = c.int(os.ENOTSOCK), - Aborted = c.int(os.ECONNABORTED), + Connection_Broken = c.int(posix.ENETRESET), + Not_Socket = c.int(posix.ENOTSOCK), + Aborted = c.int(posix.ECONNABORTED), // TODO(tetra): Determine when this is different from the syscall returning n=0 and maybe normalize them? - Connection_Closed = c.int(os.ECONNRESET), - Offline = c.int(os.ENETDOWN), - Host_Unreachable = c.int(os.EHOSTUNREACH), - Interrupted = c.int(os.EINTR), + Connection_Closed = c.int(posix.ECONNRESET), + Offline = c.int(posix.ENETDOWN), + Host_Unreachable = c.int(posix.EHOSTUNREACH), + Interrupted = c.int(posix.EINTR), // NOTE: No, really. Presumably this means something different for nonblocking sockets... - Timeout = c.int(os.EWOULDBLOCK), + Timeout = c.int(posix.EWOULDBLOCK), } UDP_Recv_Error :: enum c.int { None = 0, - Buffer_Too_Small = c.int(os.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost. - Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket. - Not_Descriptor = c.int(os.EBADF), // The so-called socket is, in fact, not even a valid descriptor. - Bad_Buffer = c.int(os.EFAULT), // The buffer did not point to a valid location in memory. - Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7). + Buffer_Too_Small = c.int(posix.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost. + Not_Socket = c.int(posix.ENOTSOCK), // The so-called socket is not an open socket. + Not_Descriptor = c.int(posix.EBADF), // The so-called socket is, in fact, not even a valid descriptor. + Bad_Buffer = c.int(posix.EFAULT), // The buffer did not point to a valid location in memory. + Interrupted = c.int(posix.EINTR), // A signal occurred before any data was transmitted. See signal(7). // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout. // NOTE: No, really. Presumably this means something different for nonblocking sockets... - Timeout = c.int(os.EWOULDBLOCK), - Socket_Not_Bound = c.int(os.EINVAL), // The socket must be bound for this operation, but isn't. + Timeout = c.int(posix.EWOULDBLOCK), + Socket_Not_Bound = c.int(posix.EINVAL), // The socket must be bound for this operation, but isn't. } TCP_Send_Error :: enum c.int { None = 0, - Aborted = c.int(os.ECONNABORTED), - Connection_Closed = c.int(os.ECONNRESET), - Not_Connected = c.int(os.ENOTCONN), - Shutdown = c.int(os.ESHUTDOWN), + Aborted = c.int(posix.ECONNABORTED), + Connection_Closed = c.int(posix.ECONNRESET), + Not_Connected = c.int(posix.ENOTCONN), + Shutdown = ESHUTDOWN, // The send queue was full. // This is usually a transient issue. // // This also shouldn't normally happen on Linux, as data is dropped if it // doesn't fit in the send queue. - No_Buffer_Space_Available = c.int(os.ENOBUFS), - Offline = c.int(os.ENETDOWN), - Host_Unreachable = c.int(os.EHOSTUNREACH), - Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7). + No_Buffer_Space_Available = c.int(posix.ENOBUFS), + Offline = c.int(posix.ENETDOWN), + Host_Unreachable = c.int(posix.EHOSTUNREACH), + Interrupted = c.int(posix.EINTR), // A signal occurred before any data was transmitted. See signal(7). // NOTE: No, really. Presumably this means something different for nonblocking sockets... // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout. - Timeout = c.int(os.EWOULDBLOCK), - Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket. + Timeout = c.int(posix.EWOULDBLOCK), + Not_Socket = c.int(posix.ENOTSOCK), // The so-called socket is not an open socket. } // TODO UDP_Send_Error :: enum c.int { None = 0, - Message_Too_Long = c.int(os.EMSGSIZE), // The message is larger than the maximum UDP packet size. No data was sent. + Message_Too_Long = c.int(posix.EMSGSIZE), // The message is larger than the maximum UDP packet size. No data was sent. // TODO: not sure what the exact circumstances for this is yet - Network_Unreachable = c.int(os.ENETUNREACH), - No_Outbound_Ports_Available = c.int(os.EAGAIN), // There are no more emphemeral outbound ports available to bind the socket to, in order to send. + Network_Unreachable = c.int(posix.ENETUNREACH), + No_Outbound_Ports_Available = c.int(posix.EAGAIN), // There are no more emphemeral outbound ports available to bind the socket to, in order to send. // The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout. // NOTE: No, really. Presumably this means something different for nonblocking sockets... - Timeout = c.int(os.EWOULDBLOCK), - Not_Socket = c.int(os.ENOTSOCK), // The so-called socket is not an open socket. - Not_Descriptor = c.int(os.EBADF), // The so-called socket is, in fact, not even a valid descriptor. - Bad_Buffer = c.int(os.EFAULT), // The buffer did not point to a valid location in memory. - Interrupted = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7). + Timeout = c.int(posix.EWOULDBLOCK), + Not_Socket = c.int(posix.ENOTSOCK), // The so-called socket is not an open socket. + Not_Descriptor = c.int(posix.EBADF), // The so-called socket is, in fact, not even a valid descriptor. + Bad_Buffer = c.int(posix.EFAULT), // The buffer did not point to a valid location in memory. + Interrupted = c.int(posix.EINTR), // A signal occurred before any data was transmitted. See signal(7). // The send queue was full. // This is usually a transient issue. // // This also shouldn't normally happen on Linux, as data is dropped if it // doesn't fit in the send queue. - No_Buffer_Space_Available = c.int(os.ENOBUFS), - No_Memory_Available = c.int(os.ENOMEM), // No memory was available to properly manage the send queue. + No_Buffer_Space_Available = c.int(posix.ENOBUFS), + No_Memory_Available = c.int(posix.ENOMEM), // No memory was available to properly manage the send queue. } Shutdown_Manner :: enum c.int { - Receive = c.int(os.SHUT_RD), - Send = c.int(os.SHUT_WR), - Both = c.int(os.SHUT_RDWR), + Receive = c.int(posix.SHUT_RD), + Send = c.int(posix.SHUT_WR), + Both = c.int(posix.SHUT_RDWR), } Shutdown_Error :: enum c.int { None = 0, - Aborted = c.int(os.ECONNABORTED), - Reset = c.int(os.ECONNRESET), - Offline = c.int(os.ENETDOWN), - Not_Connected = c.int(os.ENOTCONN), - Not_Socket = c.int(os.ENOTSOCK), - Invalid_Manner = c.int(os.EINVAL), + Aborted = c.int(posix.ECONNABORTED), + Reset = c.int(posix.ECONNRESET), + Offline = c.int(posix.ENETDOWN), + Not_Connected = c.int(posix.ENOTCONN), + Not_Socket = c.int(posix.ENOTSOCK), + Invalid_Manner = c.int(posix.EINVAL), } Socket_Option_Error :: enum c.int { None = 0, - Offline = c.int(os.ENETDOWN), - Timeout_When_Keepalive_Set = c.int(os.ENETRESET), - Invalid_Option_For_Socket = c.int(os.ENOPROTOOPT), - Reset_When_Keepalive_Set = c.int(os.ENOTCONN), - Not_Socket = c.int(os.ENOTSOCK), + Offline = c.int(posix.ENETDOWN), + Timeout_When_Keepalive_Set = c.int(posix.ENETRESET), + Invalid_Option_For_Socket = c.int(posix.ENOPROTOOPT), + Reset_When_Keepalive_Set = c.int(posix.ENOTCONN), + Not_Socket = c.int(posix.ENOTSOCK), } Set_Blocking_Error :: enum c.int { None = 0, // TODO: Add errors for `set_blocking` -} \ No newline at end of file +} diff --git a/core/net/interface_darwin.odin b/core/net/interface_darwin.odin index 4921bc3fe..9aa6cbd1a 100644 --- a/core/net/interface_darwin.odin +++ b/core/net/interface_darwin.odin @@ -20,60 +20,57 @@ package net Feoramund: FreeBSD platform code */ -import "core:os" import "core:strings" +import "core:sys/posix" + +foreign import lib "system:System.framework" @(private) _enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) { context.allocator = allocator - head: ^os.ifaddrs - - if res := os._getifaddrs(&head); res < 0 { + head: ^ifaddrs + if getifaddrs(&head) != .OK { return {}, .Unable_To_Enumerate_Network_Interfaces } + defer freeifaddrs(head) - /* - Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct. - We're going to have to iterate over a list and coalesce information as we go. - */ - ifaces: map[string]^Network_Interface + ifaces: map[string]Network_Interface defer delete(ifaces) for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next { adapter_name := string(ifaddr.name) - /* - Check if we have seen this interface name before so we can reuse the `Network_Interface`. - Else, create a new one. - */ - if adapter_name not_in ifaces { - ifaces[adapter_name] = new(Network_Interface) - ifaces[adapter_name].adapter_name = strings.clone(adapter_name) + key_ptr, iface, inserted, mem_err := map_entry(&ifaces, adapter_name) + if mem_err == nil && inserted { + key_ptr^, mem_err = strings.clone(adapter_name) + iface.adapter_name = key_ptr^ + } + if mem_err != nil { + return {}, .Unable_To_Enumerate_Network_Interfaces } - iface := ifaces[adapter_name] address: Address netmask: Netmask - if ifaddr.address != nil { - switch int(ifaddr.address.family) { - case os.AF_INET, os.AF_INET6: - address = _sockaddr_basic_to_endpoint(ifaddr.address).address + if ifaddr.addr != nil { + #partial switch ifaddr.addr.sa_family { + case .INET, .INET6: + address = _sockaddr_basic_to_endpoint(ifaddr.addr).address } } if ifaddr.netmask != nil { - switch int(ifaddr.netmask.family) { - case os.AF_INET, os.AF_INET6: + #partial switch ifaddr.netmask.sa_family { + case .INET, .INET6: netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address) } } - if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags { - switch int(ifaddr.broadcast_or_dest.family) { - case os.AF_INET, os.AF_INET6: - broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address + if ifaddr.dstaddr != nil && .BROADCAST in ifaddr.flags { + #partial switch ifaddr.dstaddr.sa_family { + case .INET, .INET6: + broadcast := _sockaddr_basic_to_endpoint(ifaddr.dstaddr).address append(&iface.multicast, broadcast) } } @@ -105,18 +102,51 @@ _enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: [] iface.link.state = state } - /* - Free the OS structures. - */ - os._freeifaddrs(head) - - /* - Turn the map into a slice to return. - */ - _interfaces := make([dynamic]Network_Interface, 0, allocator) + interfaces = make([]Network_Interface, len(ifaces)) + i: int for _, iface in ifaces { - append(&_interfaces, iface^) - free(iface) + interfaces[i] = iface + i += 1 } - return _interfaces[:], {} + return interfaces, nil +} + +@(private) +IF_Flag :: enum u32 { + UP, + BROADCAST, + DEBUG, + LOOPBACK, + POINTTOPOINT, + NOTRAILERS, + RUNNING, + NOARP, + PROMISC, + ALLMULTI, + OACTIVE, + SIMPLEX, + LINK0, + LINK1, + LINK2, + MULTICAST, +} + +@(private) +IF_Flags :: bit_set[IF_Flag; u32] + +@(private) +ifaddrs :: struct { + next: ^ifaddrs, + name: cstring, + flags: IF_Flags, + addr: ^posix.sockaddr, + netmask: ^posix.sockaddr, + dstaddr: ^posix.sockaddr, + data: rawptr, +} + +@(private) +foreign lib { + getifaddrs :: proc(ifap: ^^ifaddrs) -> posix.result --- + freeifaddrs :: proc(ifp: ^ifaddrs) --- } diff --git a/core/net/socket_darwin.odin b/core/net/socket_darwin.odin index 27927e973..a132a6a95 100644 --- a/core/net/socket_darwin.odin +++ b/core/net/socket_darwin.odin @@ -21,44 +21,45 @@ package net */ import "core:c" -import "core:os" import "core:sys/posix" import "core:time" Socket_Option :: enum c.int { - Broadcast = c.int(os.SO_BROADCAST), - Reuse_Address = c.int(os.SO_REUSEADDR), - Keep_Alive = c.int(os.SO_KEEPALIVE), - Out_Of_Bounds_Data_Inline = c.int(os.SO_OOBINLINE), - TCP_Nodelay = c.int(os.TCP_NODELAY), - Linger = c.int(os.SO_LINGER), - Receive_Buffer_Size = c.int(os.SO_RCVBUF), - Send_Buffer_Size = c.int(os.SO_SNDBUF), - Receive_Timeout = c.int(os.SO_RCVTIMEO), - Send_Timeout = c.int(os.SO_SNDTIMEO), + Broadcast = c.int(posix.Sock_Option.BROADCAST), + Reuse_Address = c.int(posix.Sock_Option.REUSEADDR), + Keep_Alive = c.int(posix.Sock_Option.KEEPALIVE), + Out_Of_Bounds_Data_Inline = c.int(posix.Sock_Option.OOBINLINE), + TCP_Nodelay = c.int(posix.TCP_NODELAY), + Linger = c.int(posix.Sock_Option.LINGER), + Receive_Buffer_Size = c.int(posix.Sock_Option.RCVBUF), + Send_Buffer_Size = c.int(posix.Sock_Option.SNDBUF), + Receive_Timeout = c.int(posix.Sock_Option.RCVTIMEO), + Send_Timeout = c.int(posix.Sock_Option.SNDTIMEO), } @(private) _create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Network_Error) { - c_type, c_protocol, c_family: int + c_type: posix.Sock + c_protocol: posix.Protocol + c_family: posix.AF switch family { - case .IP4: c_family = os.AF_INET - case .IP6: c_family = os.AF_INET6 + case .IP4: c_family = .INET + case .IP6: c_family = .INET6 case: unreachable() } switch protocol { - case .TCP: c_type = os.SOCK_STREAM; c_protocol = os.IPPROTO_TCP - case .UDP: c_type = os.SOCK_DGRAM; c_protocol = os.IPPROTO_UDP + case .TCP: c_type = .STREAM; c_protocol = .TCP + case .UDP: c_type = .DGRAM; c_protocol = .UDP case: unreachable() } - sock, sock_err := os.socket(c_family, c_type, c_protocol) - if sock_err != nil { - err = Create_Socket_Error(os.is_platform_error(sock_err) or_else -1) + sock := posix.socket(c_family, c_type, c_protocol) + if sock < 0 { + err = Create_Socket_Error(posix.errno()) return } @@ -86,10 +87,10 @@ _dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_optio _ = set_option(skt, .Reuse_Address, true) sockaddr := _endpoint_to_sockaddr(endpoint) - res := os.connect(os.Socket(skt), (^os.SOCKADDR)(&sockaddr), i32(sockaddr.len)) - if res != nil { + if posix.connect(posix.FD(skt), (^posix.sockaddr)(&sockaddr), posix.socklen_t(sockaddr.ss_len)) != .OK { + errno := posix.errno() close(skt) - return {}, Dial_Error(os.is_platform_error(res) or_else -1) + return {}, Dial_Error(errno) } return @@ -102,14 +103,15 @@ MAX_PRIVILEGED_PORT :: 1023 _bind :: proc(skt: Any_Socket, ep: Endpoint) -> (err: Network_Error) { sockaddr := _endpoint_to_sockaddr(ep) s := any_socket_to_socket(skt) - res := os.bind(os.Socket(s), (^os.SOCKADDR)(&sockaddr), i32(sockaddr.len)) - if res != nil { - if res == os.EACCES && ep.port <= MAX_PRIVILEGED_PORT { + if posix.bind(posix.FD(s), (^posix.sockaddr)(&sockaddr), posix.socklen_t(sockaddr.ss_len)) != .OK { + errno := posix.errno() + if errno == .EACCES && ep.port <= MAX_PRIVILEGED_PORT { err = .Privileged_Port_Without_Root } else { - err = Bind_Error(os.is_platform_error(res) or_else -1) + err = Bind_Error(errno) } } + return } @@ -131,9 +133,8 @@ _listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (skt: TCP_ bind(sock, interface_endpoint) or_return - res := os.listen(os.Socket(skt), backlog) - if res != nil { - err = Listen_Error(os.is_platform_error(res) or_else -1) + if posix.listen(posix.FD(skt), i32(backlog)) != .OK { + err = Listen_Error(posix.errno()) return } @@ -144,34 +145,34 @@ _listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (skt: TCP_ _bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Network_Error) { addr: posix.sockaddr_storage addr_len := posix.socklen_t(size_of(addr)) - res := posix.getsockname(posix.FD(any_socket_to_socket(sock)), (^posix.sockaddr)(&addr), &addr_len) - if res != .OK { + if posix.getsockname(posix.FD(any_socket_to_socket(sock)), (^posix.sockaddr)(&addr), &addr_len) != .OK { err = Listen_Error(posix.errno()) return } - ep = _sockaddr_to_endpoint((^os.SOCKADDR_STORAGE_LH)(&addr)) + + ep = _sockaddr_to_endpoint(&addr) return } @(private) _accept_tcp :: proc(sock: TCP_Socket, options := default_tcp_options) -> (client: TCP_Socket, source: Endpoint, err: Network_Error) { - sockaddr: os.SOCKADDR_STORAGE_LH - sockaddrlen := c.int(size_of(sockaddr)) - - client_sock, client_sock_err := os.accept(os.Socket(sock), cast(^os.SOCKADDR) &sockaddr, &sockaddrlen) - if client_sock_err != nil { - err = Accept_Error(os.is_platform_error(client_sock_err) or_else -1) + addr: posix.sockaddr_storage + addr_len := posix.socklen_t(size_of(addr)) + client_sock := posix.accept(posix.FD(sock), (^posix.sockaddr)(&addr), &addr_len) + if client_sock < 0 { + err = Accept_Error(posix.errno()) return } + client = TCP_Socket(client_sock) - source = _sockaddr_to_endpoint(&sockaddr) + source = _sockaddr_to_endpoint(&addr) return } @(private) _close :: proc(skt: Any_Socket) { s := any_socket_to_socket(skt) - os.close(os.Handle(os.Socket(s))) + posix.close(posix.FD(s)) } @(private) @@ -179,11 +180,13 @@ _recv_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_read: int, err: Networ if len(buf) <= 0 { return } - res, res_err := os.recv(os.Socket(skt), buf, 0) - if res_err != nil { - err = TCP_Recv_Error(os.is_platform_error(res_err) or_else -1) + + res := posix.recv(posix.FD(skt), raw_data(buf), len(buf), {}) + if res < 0 { + err = TCP_Recv_Error(posix.errno()) return } + return int(res), nil } @@ -193,11 +196,11 @@ _recv_udp :: proc(skt: UDP_Socket, buf: []byte) -> (bytes_read: int, remote_endp return } - from: os.SOCKADDR_STORAGE_LH - fromsize := c.int(size_of(from)) - res, res_err := os.recvfrom(os.Socket(skt), buf, 0, cast(^os.SOCKADDR) &from, &fromsize) - if res_err != nil { - err = UDP_Recv_Error(os.is_platform_error(res_err) or_else -1) + from: posix.sockaddr_storage + fromsize := posix.socklen_t(size_of(from)) + res := posix.recvfrom(posix.FD(skt), raw_data(buf), len(buf), {}, (^posix.sockaddr)(&from), &fromsize) + if res < 0 { + err = UDP_Recv_Error(posix.errno()) return } @@ -211,15 +214,19 @@ _send_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_written: int, err: Net for bytes_written < len(buf) { limit := min(int(max(i32)), len(buf) - bytes_written) remaining := buf[bytes_written:][:limit] - res, res_err := os.send(os.Socket(skt), remaining, os.MSG_NOSIGNAL) - if res_err == os.EPIPE { - // EPIPE arises if the socket has been closed remotely. - err = TCP_Send_Error.Connection_Closed - return - } else if res_err != nil { - err = TCP_Send_Error(os.is_platform_error(res_err) or_else -1) + res := posix.send(posix.FD(skt), raw_data(remaining), len(remaining), {.NOSIGNAL}) + if res < 0 { + errno := posix.errno() + if errno == .EPIPE { + // EPIPE arises if the socket has been closed remotely. + err = TCP_Send_Error.Connection_Closed + return + } + + err = TCP_Send_Error(errno) return } + bytes_written += int(res) } return @@ -231,15 +238,19 @@ _send_udp :: proc(skt: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written: for bytes_written < len(buf) { limit := min(1<<31, len(buf) - bytes_written) remaining := buf[bytes_written:][:limit] - res, res_err := os.sendto(os.Socket(skt), remaining, os.MSG_NOSIGNAL, cast(^os.SOCKADDR)&toaddr, i32(toaddr.len)) - if res_err == os.EPIPE { - // EPIPE arises if the socket has been closed remotely. - err = UDP_Send_Error.Not_Socket - return - } else if res_err != nil { - err = UDP_Send_Error(os.is_platform_error(res_err) or_else -1) + res := posix.sendto(posix.FD(skt), raw_data(remaining), len(remaining), {.NOSIGNAL}, (^posix.sockaddr)(&toaddr), posix.socklen_t(toaddr.ss_len)) + if res < 0 { + errno := posix.errno() + if errno == .EPIPE { + // EPIPE arises if the socket has been closed remotely. + err = UDP_Send_Error.Not_Socket + return + } + + err = UDP_Send_Error(errno) return } + bytes_written += int(res) } return @@ -248,26 +259,25 @@ _send_udp :: proc(skt: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written: @(private) _shutdown :: proc(skt: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) { s := any_socket_to_socket(skt) - res := os.shutdown(os.Socket(s), int(manner)) - if res != nil { - return Shutdown_Error(os.is_platform_error(res) or_else -1) + if posix.shutdown(posix.FD(s), posix.Shut(manner)) != .OK { + err = Shutdown_Error(posix.errno()) } return } @(private) _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error { - level := os.SOL_SOCKET if option != .TCP_Nodelay else os.IPPROTO_TCP + level := posix.SOL_SOCKET if option != .TCP_Nodelay else posix.IPPROTO_TCP // NOTE(tetra, 2022-02-15): On Linux, you cannot merely give a single byte for a bool; // it _has_ to be a b32. // I haven't tested if you can give more than that. bool_value: b32 - int_value: i32 - timeval_value: os.Timeval + int_value: posix.socklen_t + timeval_value: posix.timeval ptr: rawptr - len: os.socklen_t + len: posix.socklen_t switch option { case @@ -302,8 +312,8 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca t := value.(time.Duration) or_else panic("set_option() value must be a time.Duration here", loc) micros := i64(time.duration_microseconds(t)) - timeval_value.microseconds = int(micros % 1e6) - timeval_value.seconds = (micros - i64(timeval_value.microseconds)) / 1e6 + timeval_value.tv_usec = posix.suseconds_t(micros % 1e6) + timeval_value.tv_sec = posix.time_t(micros - i64(timeval_value.tv_usec)) / 1e6 ptr = &timeval_value len = size_of(timeval_value) @@ -312,12 +322,12 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca .Send_Buffer_Size: // TODO: check for out of range values and return .Value_Out_Of_Range? switch i in value { - case i8, u8: i2 := i; int_value = os.socklen_t((^u8)(&i2)^) - case i16, u16: i2 := i; int_value = os.socklen_t((^u16)(&i2)^) - case i32, u32: i2 := i; int_value = os.socklen_t((^u32)(&i2)^) - case i64, u64: i2 := i; int_value = os.socklen_t((^u64)(&i2)^) - case i128, u128: i2 := i; int_value = os.socklen_t((^u128)(&i2)^) - case int, uint: i2 := i; int_value = os.socklen_t((^uint)(&i2)^) + case i8, u8: i2 := i; int_value = posix.socklen_t((^u8)(&i2)^) + case i16, u16: i2 := i; int_value = posix.socklen_t((^u16)(&i2)^) + case i32, u32: i2 := i; int_value = posix.socklen_t((^u32)(&i2)^) + case i64, u64: i2 := i; int_value = posix.socklen_t((^u64)(&i2)^) + case i128, u128: i2 := i; int_value = posix.socklen_t((^u128)(&i2)^) + case int, uint: i2 := i; int_value = posix.socklen_t((^uint)(&i2)^) case: panic("set_option() value must be an integer here", loc) } @@ -326,9 +336,8 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca } skt := any_socket_to_socket(s) - res := os.setsockopt(os.Socket(skt), int(level), int(option), ptr, len) - if res != nil { - return Socket_Option_Error(os.is_platform_error(res) or_else -1) + if posix.setsockopt(posix.FD(skt), i32(level), posix.Sock_Option(option), ptr, len) != .OK { + return Socket_Option_Error(posix.errno()) } return nil @@ -338,42 +347,42 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca _set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) { socket := any_socket_to_socket(socket) - flags, getfl_err := os.fcntl(int(socket), os.F_GETFL, 0) - if getfl_err != nil { - return Set_Blocking_Error(os.is_platform_error(getfl_err) or_else -1) + flags_ := posix.fcntl(posix.FD(socket), .GETFL, 0) + if flags_ < 0 { + return Set_Blocking_Error(posix.errno()) } + flags := transmute(posix.O_Flags)flags_ if should_block { - flags &~= int(os.O_NONBLOCK) + flags -= {.NONBLOCK} } else { - flags |= int(os.O_NONBLOCK) + flags += {.NONBLOCK} } - _, setfl_err := os.fcntl(int(socket), os.F_SETFL, flags) - if setfl_err != nil { - return Set_Blocking_Error(os.is_platform_error(setfl_err) or_else -1) + if posix.fcntl(posix.FD(socket), .SETFL, flags) < 0 { + return Set_Blocking_Error(posix.errno()) } return nil } @private -_endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: os.SOCKADDR_STORAGE_LH) { +_endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: posix.sockaddr_storage) { switch a in ep.address { case IP4_Address: - (^os.sockaddr_in)(&sockaddr)^ = os.sockaddr_in { + (^posix.sockaddr_in)(&sockaddr)^ = posix.sockaddr_in { sin_port = u16be(ep.port), - sin_addr = transmute(os.in_addr) a, - sin_family = u8(os.AF_INET), - sin_len = size_of(os.sockaddr_in), + sin_addr = transmute(posix.in_addr)a, + sin_family = .INET, + sin_len = size_of(posix.sockaddr_in), } return case IP6_Address: - (^os.sockaddr_in6)(&sockaddr)^ = os.sockaddr_in6 { + (^posix.sockaddr_in6)(&sockaddr)^ = posix.sockaddr_in6 { sin6_port = u16be(ep.port), - sin6_addr = transmute(os.in6_addr) a, - sin6_family = u8(os.AF_INET6), - sin6_len = size_of(os.sockaddr_in6), + sin6_addr = transmute(posix.in6_addr)a, + sin6_family = .INET6, + sin6_len = size_of(posix.sockaddr_in6), } return } @@ -381,21 +390,21 @@ _endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: os.SOCKADDR_STORAGE_LH } @private -_sockaddr_to_endpoint :: proc(native_addr: ^os.SOCKADDR_STORAGE_LH) -> (ep: Endpoint) { - switch native_addr.family { - case u8(os.AF_INET): - addr := cast(^os.sockaddr_in) native_addr +_sockaddr_to_endpoint :: proc(native_addr: ^posix.sockaddr_storage) -> (ep: Endpoint) { + #partial switch native_addr.ss_family { + case .INET: + addr := cast(^posix.sockaddr_in)native_addr port := int(addr.sin_port) ep = Endpoint { - address = IP4_Address(transmute([4]byte) addr.sin_addr), - port = port, + address = IP4_Address(transmute([4]byte)addr.sin_addr), + port = port, } - case u8(os.AF_INET6): - addr := cast(^os.sockaddr_in6) native_addr + case .INET6: + addr := cast(^posix.sockaddr_in6)native_addr port := int(addr.sin6_port) ep = Endpoint { - address = IP6_Address(transmute([8]u16be) addr.sin6_addr), - port = port, + address = IP6_Address(transmute([8]u16be)addr.sin6_addr), + port = port, } case: panic("native_addr is neither IP4 or IP6 address") @@ -404,21 +413,21 @@ _sockaddr_to_endpoint :: proc(native_addr: ^os.SOCKADDR_STORAGE_LH) -> (ep: Endp } @(private) -_sockaddr_basic_to_endpoint :: proc(native_addr: ^os.SOCKADDR) -> (ep: Endpoint) { - switch u16(native_addr.family) { - case u16(os.AF_INET): - addr := cast(^os.sockaddr_in) native_addr +_sockaddr_basic_to_endpoint :: proc(native_addr: ^posix.sockaddr) -> (ep: Endpoint) { + #partial switch native_addr.sa_family { + case .INET: + addr := cast(^posix.sockaddr_in)native_addr port := int(addr.sin_port) ep = Endpoint { - address = IP4_Address(transmute([4]byte) addr.sin_addr), - port = port, + address = IP4_Address(transmute([4]byte)addr.sin_addr), + port = port, } - case u16(os.AF_INET6): - addr := cast(^os.sockaddr_in6) native_addr + case .INET6: + addr := cast(^posix.sockaddr_in6)native_addr port := int(addr.sin6_port) ep = Endpoint { - address = IP6_Address(transmute([8]u16be) addr.sin6_addr), - port = port, + address = IP6_Address(transmute([8]u16be)addr.sin6_addr), + port = port, } case: panic("native_addr is neither IP4 or IP6 address") From 61610fa03398019b31f98746f94db22be8f0f267 Mon Sep 17 00:00:00 2001 From: Steve Biedermann Date: Sun, 30 Mar 2025 18:11:41 +0200 Subject: [PATCH 62/81] Use the proper size for SizeOfStruct --- core/debug/trace/trace_windows.odin | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/debug/trace/trace_windows.odin b/core/debug/trace/trace_windows.odin index c9868e338..96507714c 100644 --- a/core/debug/trace/trace_windows.odin +++ b/core/debug/trace/trace_windows.odin @@ -49,7 +49,9 @@ _resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> ( data: [size_of(win32.SYMBOL_INFOW) + size_of([256]win32.WCHAR)]byte symbol := (^win32.SYMBOL_INFOW)(&data[0]) - symbol.SizeOfStruct = size_of(symbol) + // The value of SizeOfStruct must be the size of the whole struct, + // not just the size of the pointer + symbol.SizeOfStruct = size_of(symbol^) symbol.MaxNameLen = 255 if win32.SymFromAddrW(ctx.impl.hProcess, win32.DWORD64(frame), &{}, symbol) { fl.procedure, _ = win32.wstring_to_utf8(&symbol.Name[0], -1, allocator) From dcb683927ea9ebe6f53124ce56700ece68dce164 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 31 Mar 2025 10:40:03 +0100 Subject: [PATCH 63/81] Fix indentation --- core/mem/mem.odin | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/core/mem/mem.odin b/core/mem/mem.odin index b2a7158a1..d578dd477 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -1,4 +1,4 @@ -package mem +#package mem import "base:runtime" import "base:intrinsics" @@ -171,16 +171,15 @@ If the return value is: The comparison is performed as follows: 1. Each byte, upto `min(len(a), len(b))` bytes is compared between `a` and `b`. - - If the byte in slice `a` is smaller than a byte in slice `b`, then comparison - stops and this procedure returns `-1`. - - If the byte in slice `a` is bigger than a byte in slice `b`, then comparison - stops and this procedure returns `+1`. - - Otherwise the comparison continues until `min(len(a), len(b))` are compared. -2. If all the bytes in the range are equal, then the lengths of the slices are - compared. - - If the length of slice `a` is smaller than the length of slice `b`, then `-1` is returned. - - If the length of slice `b` is smaller than the length of slice `b`, then `+1` is returned. - - Otherwise `0` is returned. + - If the byte in slice `a` is smaller than a byte in slice `b`, then comparison + stops and this procedure returns `-1`. + - If the byte in slice `a` is bigger than a byte in slice `b`, then comparison + stops and this procedure returns `+1`. + - Otherwise the comparison continues until `min(len(a), len(b))` are compared. +2. If all the bytes in the range are equal, then the lengths of the slices are compared. + - If the length of slice `a` is smaller than the length of slice `b`, then `-1` is returned. + - If the length of slice `b` is smaller than the length of slice `b`, then `+1` is returned. + - Otherwise `0` is returned. */ @(require_results) compare :: proc "contextless" (a, b: []byte) -> int { @@ -207,11 +206,11 @@ If the return value is: The comparison is performed as follows: 1. Each byte, upto `n` bytes is compared between `a` and `b`. - - If the byte in `a` is smaller than a byte in `b`, then comparison stops - and this procedure returns `-1`. - - If the byte in `a` is bigger than a byte in `b`, then comparison stops - and this procedure returns `+1`. - - Otherwise the comparison continues until `n` bytes are compared. + - If the byte in `a` is smaller than a byte in `b`, then comparison stops + and this procedure returns `-1`. + - If the byte in `a` is bigger than a byte in `b`, then comparison stops + and this procedure returns `+1`. + - Otherwise the comparison continues until `n` bytes are compared. 2. If all the bytes in the range are equal, this procedure returns `0`. */ @(require_results) @@ -233,11 +232,11 @@ If the return value is: The comparison is performed as follows: 1. Each byte, upto `n` bytes is compared between `a` and `b`. - - If the byte in `a` is smaller than a byte in `b`, then comparison stops - and this procedure returns `-1`. - - If the byte in `a` is bigger than a byte in `b`, then comparison stops - and this procedure returns `+1`. - - Otherwise the comparison continues until `n` bytes are compared. + - If the byte in `a` is smaller than a byte in `b`, then comparison stops + and this procedure returns `-1`. + - If the byte in `a` is bigger than a byte in `b`, then comparison stops + and this procedure returns `+1`. + - Otherwise the comparison continues until `n` bytes are compared. 2. If all the bytes in the range are equal, this procedure returns `0`. */ @(require_results) From 70ddb74e402fe5c2c1b139c3e7a66a9eaf566930 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 31 Mar 2025 10:51:02 +0100 Subject: [PATCH 64/81] Add `mem.make_over_aligned` --- core/mem/alloc.odin | 28 ++++++++++++++++++++++++++++ core/mem/mem.odin | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index 6dcfb7888..48cc39245 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -888,6 +888,34 @@ make_aligned :: proc( return runtime.make_aligned(T, len, alignment, allocator, loc) } + +/* +Allocate a new slice with alignment for allocators that might not support the +specified alignment requirement. + +This procedure allocates a new slice of type `T` with length `len`, aligned +on a boundary specified by `alignment` from an allocator specified by +`allocator`, and returns the allocated slice. + +The user should `delete` the return `original_data` slice not the typed `slice`. +*/ +@(require_results) +make_over_aligned :: proc( + $T: typeid/[]$E, + #any_int len: int, + alignment: int, + allocator: runtime.Allocator, + loc := #caller_location, +) -> (slice: T, original_data: []byte, err: Allocator_Error) { + size := size_of(E)*len + alignment-1 + original_data, err = runtime.make([]byte, size, allocator, loc) + if err == nil { + ptr := align_forward(raw_data(original_data), uintptr(alignment)) + slice = ([^]E)(ptr)[:len] + } + return +} + /* Allocate a new slice. diff --git a/core/mem/mem.odin b/core/mem/mem.odin index d578dd477..5789309f7 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -1,4 +1,4 @@ -#package mem +package mem import "base:runtime" import "base:intrinsics" From b0228154d9675fcd6362715c329b553ee45205c8 Mon Sep 17 00:00:00 2001 From: Scott Campbell Date: Wed, 2 Apr 2025 00:13:45 +1100 Subject: [PATCH 65/81] Fix depth stencil not working on wgpu wasm_js build --- vendor/wgpu/wgpu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/wgpu/wgpu.js b/vendor/wgpu/wgpu.js index 7866c7131..f3d29eafd 100644 --- a/vendor/wgpu/wgpu.js +++ b/vendor/wgpu/wgpu.js @@ -528,7 +528,7 @@ class WebGPUInterface { return undefined; } - const off = this.struct(ptr); + const off = this.struct(start); return { view: this.textureViews.get(this.mem.loadPtr(off(4))), From 10bde208502490371c42b5136d40d7d0cadef3cb Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Wed, 2 Apr 2025 14:21:52 +0200 Subject: [PATCH 66/81] Fix #4980 Add nullptr check. --- src/llvm_backend_const.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 5587a298a..9401e4d55 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -33,7 +33,7 @@ gb_internal bool lb_is_elem_const(Ast *elem, Type *elem_type) { gb_internal bool lb_is_const_nil(lbValue value) { LLVMValueRef v = value.value; - if (LLVMIsConstant(v)) { + if (v != nullptr && LLVMIsConstant(v)) { if (LLVMIsAConstantAggregateZero(v)) { return true; } else if (LLVMIsAConstantPointerNull(v)) { From d0dd1b2d80ab32083f97a4753200758731155ade Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 2 Apr 2025 18:23:08 +0100 Subject: [PATCH 67/81] Add mutex for `lb_handle_objc_find_or_register_selector` --- src/llvm_backend.hpp | 1 + src/llvm_backend_utility.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 4fd1b8d1a..610fb72e4 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -165,6 +165,7 @@ struct lbModule { PtrMap func_raw_types; // mutex: func_raw_types_mutex RecursiveMutex types_mutex; RecursiveMutex func_raw_types_mutex; + RecursiveMutex objc_selectors_mutex; i32 internal_type_level; RwMutex values_mutex; diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index e06369be3..a21039360 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2096,7 +2096,11 @@ gb_internal void lb_set_wasm_export_attributes(LLVMValueRef value, String export gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) { + mutex_lock(&p->module->objc_selectors_mutex); + defer (mutex_unlock(&p->module->objc_selectors_mutex)); + lbObjcRef *found = string_map_get(&p->module->objc_selectors, name); + if (found) { return found->local_module_addr; } @@ -2118,7 +2122,10 @@ gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, Stri lbAddr default_addr = lb_add_global_generated_with_name(default_module, t_objc_SEL, {}, make_string(cast(u8 const *)global_name, gb_string_length(global_name)), &entity); + + mutex_lock(&default_module->objc_selectors_mutex); string_map_set(&default_module->objc_selectors, name, lbObjcRef{entity, default_addr}); + mutex_unlock(&default_module->objc_selectors_mutex); } lbValue ptr = lb_find_value_from_entity(p->module, entity); From 5eaff20f4a672760b4d90d596dd46be132634f41 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 2 Apr 2025 18:26:40 +0100 Subject: [PATCH 68/81] Add mutex for `lb_handle_objc_find_or_register_class` --- src/llvm_backend.hpp | 5 ++++- src/llvm_backend_utility.cpp | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 610fb72e4..f9f96a906 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -165,7 +165,6 @@ struct lbModule { PtrMap func_raw_types; // mutex: func_raw_types_mutex RecursiveMutex types_mutex; RecursiveMutex func_raw_types_mutex; - RecursiveMutex objc_selectors_mutex; i32 internal_type_level; RwMutex values_mutex; @@ -199,6 +198,10 @@ struct lbModule { RecursiveMutex debug_values_mutex; PtrMap debug_values; + + RecursiveMutex objc_classes_mutex; + RecursiveMutex objc_selectors_mutex; + StringMap objc_classes; StringMap objc_selectors; diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index a21039360..efe196e58 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2165,6 +2165,9 @@ gb_internal lbValue lb_handle_objc_register_selector(lbProcedure *p, Ast *expr) } gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String const &name) { + mutex_lock(&p->module->objc_classes_mutex); + defer (mutex_unlock(&p->module->objc_classes_mutex)); + lbObjcRef *found = string_map_get(&p->module->objc_classes, name); if (found) { return found->local_module_addr; @@ -2187,7 +2190,10 @@ gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String lbAddr default_addr = lb_add_global_generated_with_name(default_module, t_objc_Class, {}, make_string(cast(u8 const *)global_name, gb_string_length(global_name)), &entity); + + mutex_lock(&default_module->objc_classes_mutex); string_map_set(&default_module->objc_classes, name, lbObjcRef{entity, default_addr}); + mutex_unlock(&default_module->objc_classes_mutex); } lbValue ptr = lb_find_value_from_entity(p->module, entity); From 4a56b25b3a725692aade0ef7b22267df17b691cb Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Wed, 2 Apr 2025 20:24:45 +0200 Subject: [PATCH 69/81] Update vendor:sdl3 to version 3.2.10 --- vendor/sdl3/SDL3.dll | Bin 2418688 -> 2453504 bytes vendor/sdl3/SDL3.lib | Bin 268842 -> 269054 bytes vendor/sdl3/include/SDL.h | 2 +- vendor/sdl3/include/SDL_assert.h | 2 + vendor/sdl3/include/SDL_atomic.h | 2 +- vendor/sdl3/include/SDL_audio.h | 31 ++-- vendor/sdl3/include/SDL_camera.h | 4 +- vendor/sdl3/include/SDL_dialog.h | 4 +- vendor/sdl3/include/SDL_events.h | 4 +- vendor/sdl3/include/SDL_gamepad.h | 2 +- vendor/sdl3/include/SDL_gpu.h | 151 +++++++++++++---- vendor/sdl3/include/SDL_guid.h | 4 + vendor/sdl3/include/SDL_hints.h | 44 ++++- vendor/sdl3/include/SDL_log.h | 13 +- vendor/sdl3/include/SDL_main.h | 9 +- vendor/sdl3/include/SDL_mouse.h | 6 +- vendor/sdl3/include/SDL_pixels.h | 3 + vendor/sdl3/include/SDL_platform_defines.h | 2 - vendor/sdl3/include/SDL_power.h | 4 + vendor/sdl3/include/SDL_process.h | 12 +- vendor/sdl3/include/SDL_rect.h | 2 +- vendor/sdl3/include/SDL_render.h | 87 ++++++++-- vendor/sdl3/include/SDL_revision.h | 4 +- vendor/sdl3/include/SDL_stdinc.h | 51 +++--- vendor/sdl3/include/SDL_storage.h | 7 +- vendor/sdl3/include/SDL_surface.h | 179 ++++++++++++++++++--- vendor/sdl3/include/SDL_test_common.h | 2 +- vendor/sdl3/include/SDL_thread.h | 2 +- vendor/sdl3/include/SDL_tray.h | 26 +-- vendor/sdl3/include/SDL_version.h | 2 +- vendor/sdl3/include/SDL_vulkan.h | 2 +- vendor/sdl3/sdl3_audio.odin | 6 +- vendor/sdl3/sdl3_camera.odin | 2 +- vendor/sdl3/sdl3_gpu.odin | 6 +- vendor/sdl3/sdl3_hints.odin | 2 + vendor/sdl3/sdl3_pixels.odin | 2 + vendor/sdl3/sdl3_surface.odin | 7 + vendor/sdl3/sdl3_version.odin | 2 +- 38 files changed, 531 insertions(+), 159 deletions(-) diff --git a/vendor/sdl3/SDL3.dll b/vendor/sdl3/SDL3.dll index 6c9d438f91ae1602b99020a1f1a7d267123ee027..3bbfd4be8a762b582a3d8f0a932d31178ac9ed9f 100644 GIT binary patch delta 773913 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�{?n}!yX;L`Whxq*Vfg0fy z_JGV7Q=?cG)6+PI?Gd;-kSi)2>hvXN-x9iYhfhTi)T%MZYygdq;hHf)Z=()tK)X@D zUeJ%vaX<6md2U^n%e{EV-$2I^{sLV+&c|B;4Mpqz7Mg#G!>&MYpJ9CoZ92^=h1#8E z9fx|CvJOH2wV<)>1^1yaMUZ!IF51UX0<;x+8`=n6gz}+3pjFURWWNIX8Cn9pa1P_2 z6}-0hPc^2`gEAIyNneBR;TGy8=;%j$V$z{wk8*c41v;^Z&;0~w^rx&bQ0xGXnF8(a zTXYc8r7GfqFr`%Q?~R&?&T_&d}IL_#h&oXQ9?m0!fX3 z!Qj0pBZR40zZjL>8KSyj`yLA?M~Ld&4LP{T(#=14c&rDpc#WX>;U9@o{#=>s1dXa8o{!d3c**t;HaCSo6rYP zr^$RO-iP*KOwWU6wB*a_EhsF6l>_|%Erd3Oa#%K0s};*K8$5A|v!4b1{Kns^AwCaX zh0>t2&^YKIGz!`Y4Tm;C$YxQEyV z4O!18v;Z248PGbC8vmAq?;`M_iJXiMy$t0-A3`?hCbR&mJBjzRKx3gy=-KBuY$kNx z%3ablB^v(@zrmb@z$P|UDl~Z@Urr;TI;heop;Jioap)>8!$im%mtj2Atv(M`eV}`1 zxMq5=ET-K*FryIo2a;(IZCS-VTR8OdUHbb@R#Qvp*0;Q05aj(Gs{yneGC^&==dc>k zqDpS+UXW!nvUo6+o7Wa({~I*=H_q@EXgk6xpt(50Z=v(h6-axGYwb&@=HskV=tt-{ z^rrt6mTtO z?Zcq+=sX8QZCZ18IRH9}t~3sM16^q^=ozRxG&+p;>kP$)vm&9PBsKoE2G=7n7`gy8 zhVDZFP^~tcOl{~yTb2>}2w_!IxINWFSS8ddf@9u=o@hs+@$V<_LL>)XhwLhl=7!KQ z=o0iN^ab=abQ-GHp7$$(=0XRcZqVn@qb!SQ7Z`!SLTECy8S34E6a4`CFT&o3&LAug zx(2-kb?eCc@h(My5Xk4Hr2XKd39@1096^n#|4Xp=Y^feurL8W!;AMAnXP-bsUF%5B&^%Ga2Jw z?060=L*O##9CRK!3B8TU!x88{!iu4%CvYmCLN^if6KF9WZft{MCv(gKk{bW^BXAu8 zeW!5XyU^>1szWOgmJ2-%*`UkN0_d@6oQee+GL@AH-GOE*(fGF>oQA-i*l`lnWIFGd z3hjYLLeD@?Lhn7#F&~FQphRfy3mg^?{rWne-aagg>7l929tboqVnsn8BCI`h848E$ zPUDy@p%5qt8tTvOsR6VcGC_?nA*lgbnxF-HfydDDAEa^fT0Mr7`3?GeIcN9_6pIWi zp!#of*tgIV&=u%)=u4;xM#@s?L(BX8kmNYndnMmc9fB5*<$+``lm!(*XVKAo427Zh z*b2RlgV+e!aVqkmhjA)aL9f1G;WM)WJcYm|(AD?&p3Mr)t;P2+^Pu^-7kCZ2*PQF= zC1}%VRyuU-C5(np(ia>y0UG^r|_Js>N##tAvkH3(2n+0_cZ?91${5^jz2*UU0_{@BCfH@p{C!kEL z=v&rlXzX=X3FQ3)>j0F%&Dmo59Nbxx&+jg%ryr{j+5>HdI@IQ{51>wH7w<#25S9nk zH*w6jpbR_%%Yk+x%(4)SsLN5ap?9F!(5wC&HVb+$fb~2y1h>{{(0*tf^h5)WISOin zCuzf>MR-b(YylmQ*#<$Y5w$<`Gt?K_{tY+17|44yUn9{_LK^o19id0j&$WeiL!rS8qh`>jpSpLupkRMdPD~I_&>k;VD4;dbW|& z_-FWmS%AP9&^qWl=w0Z=>l{;uF5*FaF7(Ea9A<;IKntKb@9=4|Kv(f>B~yvUzg9cA zq%#rt9RjC8PvP88g6wEesn8yTjf761K|Klmjj+d|GmW?*CPMY`;4+?NF^vcNAW%bL zdO$s)DCmt6E@*qGHxv#%wilxzG!_biWt*j^VM>gNfX{ z>R>MX8?+eu1sXeu=TQ|cAV-D|k3A&81FQAW5 zwA0Yl##~P&&@~<@Ev5tDc?_|iLl5D2cR`zwXd$!*+6+0W^aJQ?guM@C;iTn3Ls8JT zp!Eo|j@`LK1<-+(t=g+YI8qdw^sn&eU_B*r*x(ywBoDcWL zc#MB_9%Fuwz(>k?#QO%?p3Zm3Wze%bxe1+v!ti3nN$A3E4m$!}go>d(PvA)@bOM9g zCnPogO~4^sdw^W{X>K?jfUS$h|{caZBshngH<XOb_T$jf;oPw$vMi=$ zU_1i9gZe-}Ks}(IBY4Ls=wYZmG&PqGA{?r_l+_Y?VHjs01bORRqYWU-uXwO#0x#f_ zsR3QQ%?-*6dIMn(#&Pp#m7aQ8~y zu@w5_2fkvDL%o;rF&%;)f%ZbNxbTXgW&OF>A4BsIwiS9CVH=^Nhw%AdKKLVUnpQzu zZt@M)3TQe$<68o~09m0shq!|0K^ccxuR-^qm!Ox?fYYH`U;kxM!^#x!CITlwU!%Vo z1HDkjb&&!sOW~F<4Eh!Q<6x*wJFd|I&`R`{anL(ZFK9JM&HuWC?;)@=v<8ZV)(nh0Ho znjq0~=#8fQ$o>-48>i_DsKrx!VopP6_{3ODCEy*Lrvp$!oQlt(hoD{12&fQx1=WvpNWxcF`E=e9vhp#tdIEly?~l+cr#(7Vuu9xNRik-^G^2F_&JpsDNl zHHQUCH2!^!L@fwhlg7hnCUh3J8#AE1@t(} zVv5CukchzgFLO!bp|ICjeV`2&xPp5?J)tP*L!74eQ12v+hR`EWODF^if-FN zwN=n%XazJHz2y=p1U;J-+5ydj)}vXz2K@lN1oiBR&;QcFAJLwtKy}bACP1ft=3^QI z4f%zY0(HfOHw?#S6bU_x zr^c-z-z<(93~hiKLp_^ujRrvNpxV&Xzo?)z{u#md6lpXZ!wqW9->gdL4#Mt2znGK4-I*Sv-gAQ zk7D^i4aczl8qN6~M%eG8G5$44<-pqrJO-h7tBzK7Q7{ygBng^ zorJXKSVy3hP%%l3e*@Dv@KXf7IhpkdG-oPn8&q!^s{pzNt%J@_=dgF7i7&8psAoDW z7n)q3?-6ZEH2%HWn6J?V2wV(Vpe!g8dKPDUCUg**20ewClOQub^Gb!<&EV`uLN|wC zG-O#!?g{qV)wHu zpl2<(4!;HGLsy^;(3en897QSg$`LNwap+Bi9fIoOeb>FvSbWq_1ocDM$I!tKEL`rb z;8UAe8=(q-S^~u`=9pG!C^Qf9ZNQVW*PshuVE*?KcoCyh zI`r@doahv&c`eoi=+s8m80adhI|bU0UT+w*939PI=uuSu0O)1tahnN%_NZsiH2&2F-yFqJ zjnLP{+)S#T;RaO?O{fw&yMU9q3$1^h^%Hafx(?Z)a_H%W9P<*inq@J40d`u%fv2G? ze6mvl4TTOs-Ee#LIix|mpo_SJDumkMo@p~QwHcrL51_}8rsaJw1k8i_L2p4%Ea%G4 zfi^%3p`IuCULYI#5Jxy0>W%DYL8qYSp&JR-5^@Zx$xLw3RT`}H9KV#wZJ0Fh;IwH`KVOyxlAuees^f1&6dIk!F=0N_?8psct zfx`Ge^YOmiUn4R8IbNUpeIyrV5dv>RZ$LMoB)o+8J@gp#4KxHQgB-8xor4k(b`p9N zIzm$8-w3c6fqU@!z^Bk>&?nGGaa@VppfgYb)U_{%t%DjO&3B_R!6y{8&C5vUF<3YzdBqf}mE-IjjM+9x_4qpc+um zV2z;B`X&=u$h=u2os2*)gi_CUv>KcPd= z=unQi7up9EL9JR@IPha|d@I&g=rAgABh&;_%zUUFvO9V1T})LL(f6wP%W0lbP04+=@(EZWPchOf*ngBN0lCc998-`^g|!c zeiw8fDuj+DaoA?)CS>^ltUH(k--kk=Jg6V^7Bn8pfi67E`z?fyqRnJO$DrBJ31}8{ z3VPlGp26>Tra}7=I1V}pje-tC!=Z~%GV}+IX%KWXg^Si7`tQ@MzEBsOw3rl(e_g?7 z1SUWoq1U0d(0wQrdiohov>7xN3WVN+{GqF(IHn(T4f09B_!ovj=C2XlydH&qha7LS z-G)9y*bQh4^gZ+u^bNEfDuen>k)R6q{hDu;1L8mGAxE18GZ^mGW-OZlgx>3 zgR-CkXfCu4nh(7Ty$yoC*C3O@rEu z<$_Lvo`X_Z7E?P+9!4T?HS{F(HS{>NbQ~v>2t7NV6%Q?k`al<;9*}tg$BcqLgxW)v z&%ki7?j(-d5*h*pK{KER(07mt(w^h}YCsVfsJ);c*K^o|;oQ2m%;v%PH)y)$IN!hi z0$%-&RRKNw0Ka|@EidA*E0FdoC-Ws_-^KTcrO>h6tmDv|k8#XHP~Dk4Iok`>n`vPd zfoHS%!T85e#sbz>Xy@y!jgWaED<67eE^8H3XFh8M^cb`Rx(ZpL{jdMYpa0DRmm`bU zpoftCOVGu>d=%->z|XlZra)6W@bON7e%{J4$3VC6c2x>=XE%opgBtF_@Ba-3+f;IO z4}f0Y&1WqR`mvbR3rfNyx;r#|7l(C*Zb6aIjL$f%HMAZIhIa0uFdF|FgNycZ)Bxy1 zM6JyVtP{m;=aYRL<9aS9p$9fi`M{ZQ>UdB4w~pT=^t+6h&C!eQH?I3u5f523d4v-q*(dc|J*Givv@ z?V~TxvL|)(Geqy>KMb?GivGQ|eRxCtV3l!{U$b8;t8DY%*jIN&JFTPN_jg&})m<@G zJ5Vo(55dR)1Q8XlYGLM_PK&5=YA*T8vN9 ze{1zLA8kxfA9~MqfMZFfpK2LN%LKjLM{8$^x>Z?aUTIsNZKy}j27F4ZuGt24qmqV< zthg8IZ?Fxj2UHNavO-24So$L!`|q@i*>8eg^ukv>MSR_WFbAk-Y63eUpa0#}g()k-?9?nQU4O-Os4C z_g&M>yA8pRQF_gZVEyI7_1MgY%7xPcsmv{9y+^DJ6 z2GW`y+Ssq@+nN^Dx|e1!%-`ofe=0?fuCg65FSwN97u)mGy5t)*Vte+PQKCPgX@i@# z4^marq;5-K-xU7&mj8WFo!GVc1_*nrwtjh?J%W2Ir6Wn z=qj`AxY_z?mfEeTEghfDxc`(&Y+ptTvvuWC+D@CcsZG{-^otqvBRHRQBal{>^5)>& zQ~Fjvt;wKqM7uYoYBN1Ut5y5VHY#4PV*kgFRv9}{mR3^&ZQo7xsxCGvfA!ypO0w-Y z+e+yW&m9UjRMhRDpD{NGw6s;X7u0Cz!mN1UV{rb(Ahj2LK|#b0uS6TQpA$6=i;O1* zQ3>6?F3=TzhlbZh#;qbeJH}w4?*;VP?sWhe4^kO7qG1GOQh#AtA74jnpe=|{Uy`SL z?F|aj->#$8?e!dOFxxJwDvC1anCqFX5z%MO))#8pJ4H~9-iw`ImC>9UcI*<>=fyXn zh_mWZHQQT8=-<@QdU?-C)SH{MPG0?V>I@#XJbxnCFsrWFHjgXYY8*p0_X-~C+>BZ` z4k2gv;!+3fQT-v+R-J=X<44+1Pir&wRJ-Mv0@V*Ir-fM7;1+5VcNwcGYIU8{iaN^Z zn;~Xfnc0>|1ue-i+RM~)Y-$v|!)1Eh;l6{dnEsa2#shkfx>|DV^8V@~ez~hUwnel) z@4nBRfZcSS3|8ZF#~pc6^&YoRrckT#iRx|9`>e)CkLyS4Y9V!hJx0f{WTDD5*l=9G zS6A!bD4({e#?#Ymn;I6YiZZ%l@IpP=U+dC%q>6v$cQ!DOrwwKEB&=c z0yN$+gLYKyt76yd`gMOT#`|WN-m0E9)T^dGtDe@!e_)u~A@&K=i|c8vS{Ci2beAvi zqd%l={Djsi)eZE+KOiA2#J+lg?j4{_Z~2^xwDA?SyJ`Tl2B?$WJ!eS09J80bb8CG` zfYvy$tBRERsvmVGvjWxO_iycI&|{bQhv=6AwDwIe90@kWcD-kxKHtv}+q3&=Vn$m! zgBOnIA@#NJ8ai#T51p?k)z>;%=2r5VUbUAl{nroFH1wxlJ}2-^Z2drOeW7~m;RhUd zquTm(_11lXbh+i23e?sF+G_7hXUP5`RUMTt*pVLgoTlOoIb2hHwTQZy?CX8!8VuX@ z;0)iOnse!>t;YL@^%f1Z8QwQr>dP8v{k(e|)-N>BG9MeYDUfnW3L9(piT5)k*lNdR zR~oVmh8J7JWfvQ=s;a2rBvPC`_0-j$GdRTFKGx50!}oCi5UR}hkR;lqzFsMo;ze%K z-)*S1^ZvfCUeZuY8h(AFGwnY8{M46UauR`8dGp{k_O`UO!r-sI7c&+?-&gNZo5B)o zgKAQ;D*hhqOFQ-Jt4|Honpj3$`dW8b|rOUe_(3 zb=6_HDr~ZQ*!$ICvsBn)?qRO|EGa6mt9zg;!#*mkk$c$Y>O@0T*dHdh!fdM!Gpew! z-NQbv4y&MQub^M0qLUD~U{heD>Pl1R?j!|LO)cJ}uWY1s9{oK%y{MRuxK=uOH$J4D zR;rbJTG^&nR?^CU)yfiDxuRBHrdtIo zht8_rk5pZyy&KRTHwtK_m0DRtD=}(CrxmkWSxhTq)XD-{nL{fTnaJuLwLT5&JJotB z){m+6C$avuT2I9Koq|A%p@N23>P!Q*4=ErD>rK^qIMzF<^&qVGQ|l(Ik5=nmSf8QR zfBT!$S*+G8u>PT1zk>C{YP}TeU#ay&YTc3(cu%1S0rfZ2`c|yBQS13wUrX!G7O76u zSC3E!I6GXO#8njJze`;~#`UyH*U%8U+;eEv7T?_L-~U+F>@XE?2?FV2Ym(^S|BT~W z^UmF@pKPKS>hvST*idvV#sB9M6Y>Tf)m;M@cJ@SR9zD~{lh|2g#56&y_6^eCZKcx~y zrLFjp4&IqmU=P}Y9_DjumbUmXO0?HzeRGi3veDDkVT-E6rf=4-25GG#KYW5sx@!&d39iI3Z(nE_y`K!yICL8RLdD`pwNoJI476Yd5d!| z;+^V!&AqX2b2=5j(pE}mP!n^G@fNMmn;oJmgvsw4eW8KERhZ z>vfxJVLd-ALx=Y#ololUHt}h7@9;9#nxl;{z$s zN*n!m4r)l}vkQHNb3{e=zxYzf7p2LiU9x5es-vGs9TM%`kd9#-t*RDDTbHWT>Fc1o zRQy7Xkixdnh8v$bk0@}TMMdCY=21!uXYM?0Q#sq>8&(uyx7)PIxs$4fAc{=M|3RB8 zG(@Spg;KsmS%j;Vv$T>xD;4u`Zbzu~ez>@&s`ZDko|vU#e?YO9sFl^UvO%r9MJu1H zl{aYRvRcWel?SxqUW~WsRHMv(TlFu3wWQv*hv?+fZ;Gjt|GRVlx?9!$&K(2W5^>BX z+TYmpVsQYWYP}oQuTX{+5wz~y zKk&wT&aBFN=&!ZZnudR{jmn~0!;vh0$JFv*}B*a{|9#=jaej-_n|yIx0$QJjFMwCZxKCiv4smNiiGK z#)?iT^WBeVy%pBSY||HpXsw&n+U_j%CaO+VLF$sNvt8dGqNPMss6A?8kH18_2&eee zY$&$R7Ck;x>o$7AdG72+ba4$w-eRZy-JN}}@c~_?d_w3l{~hamS^h%nbVNrf;a_PL zJ+Sf0hx!+xT2!(|3Er4X2R2Hz#|G{vU>NQ&n?&`F#1;jOf|CK=WH?x8c`Y$q>n*0;CPBD%jxq3-7|!x@Kqr7bijQhZf( z(qLA73pb^AN| z+pV=OPtAG2XM3cpnfmvm$*gKZv!nS=k#g#<5}bOQ6a48NM~gd1EAAyuqUdOGbKlXM zhiNTZ%%ESI&3ZL#tRaJXq5f;s*VT=sL%2c3u zEemMLrR7~(3TW9u%crzlpk-KuW*A7zGqfBepQNR)YFCAx-Nj9HD)vG5KQYrqd*}YEG^G3x1kqw7+lE z`$lNpEGcv=Qax{VJquX2ttJgRXNuG;T1{{&@{JTvh1(~M_^Zn9-QbU^tUet&t7)at zo>5VgCYiww-AnK>*mJMY<2bdWd73K&nnh>d+)fh@|D9#_G1sfA>~#hFTOasBGcE8ws>+rTTHixPpGDf3&*Hv1&I?)$`hEp_Z<-)T4(% zP3(y?XfDTx)0xho+4hZjLDj4iX4|Xk@suf=_Orh}g;GCaZ0$^rCg>ya07%vUf|5Bc z`2o<84HWkkKlR{?PSQ)YjA|0elhNpX{Nu!l>W4)&#!=*opX=)TvizI0H+}jM?b$C&S;c11YtsC)UlZw)8ir%1u77-Xnxp3)6q&rLh$TfXP2kqgGJC@c|&kPsP zFHX@D$yhoU+n3j*haLX&uhEtS|DA^&k1SKJR#oXsKhc_6OlP-J+TACs?2Q*_T|FSu z%+?VhG<;fvKT}(5rmgCSHF&3r8%c5P%4kMsdW^c^Ru9$8w(4gb>)utD+3_~^UO2;H{}Lw)aqLaX_4JNf=b-9K zgC7B9-&{inWh=8A%Jq*r(rL{(O09g{0eXD?Sr0V~9;+&!*JtAvY6o*_sh&H;KIjM4 z#?)Hz*R+;>P^B>P05<)t9ws<9EuBkA{M+JIh7(1;G|*Q(MFXMQsz26A3-bQ{H$APB z*4+E0=k$f0w9eiWpVN1D(jw};dV~h(Vp~PAz2@MYj}4dgTb;BQy-&pG&vn*b^cijR z)5|++%^Q64O;uIS0>dpemGOGXX#eJ6e?2#$L32w~jAn2y{1Zb3+F4z{!Kb}t~Dv(u+fkH z_p+*=gEHkcCI$PhT*!CKfp^vJb_BP|? zjcSjt)%8p_VHYXoW4z_KeXgo~I;q_A^&hX_?y5D`Unpu=V}Px!C_)uFr;JWC?MPSb zF!d0azEsygfF3aptmhwKu6M`3UcV5t?aUqjfY=Zk5F8)oT%=BgP673gdfjNPiPuiO zZM4?Hd(u^XK(zL7&zOwC9ldC5$!OEji%Ojlp!$e9^X$GEHTuv8n1)$qvn{y^Cs5JZ znN)?bO5YT%1-H}G7Td50Dh#6hMpp`Qb2fL!PyK4NmKAHLI z?EBAuk*;z3rJwa--L)jIcl9;hwWfi0?o?4imSLa9_M;DpXfSVPw@lYhch{QNOr7Ru zp!5fFM6dVtx({hj)-9v>X4{e`)MwbIjn&g1(t^6RqHQ)i6(=ysy0@O1HaH@rjHSLk z+!@C7`p_B&*Mi5Ng^P{`OUkedq%E z)G+$Y4*&k&6sgh3-h-l2tcF>A26L?1_Akox${t#@*HXP>Pig`+_Xaf>pJ=;fw)s(S z5xdLF{<3;+Vq84c`k)XqeKL~MFxFgr&Bxy5FLiaCQB9;JHGmL~lT#h<3e$)+2qV{A-qO_N&M8uBz5esJVOzVaGTm@cz4bIi*%GwQ}w6`SYn zYm(5biZb7agS6jUH7c)z>9vk=?Muw#=%X6n*tncH zFI6e#arD`%Zz5IJe(b65ZLev~v~vNfcH}+9UOM`>Lf16c2lv!EH(Ar14z=o#x$1z~ z$DY{h%BvM-+e!O7XY}PgwTLETDKydAp)YMS+Zvm5MtCLJ4%i2t)zA0TCQZ*=tNKpU zEA)d}{kSvK=zY!B|Af)|DfDTC`a7g_m8kow#k9d}T^*+Gqp63f6HBwkalsF(-F+^Z z7yLxC>66yp7wtouQnzhvrM6oWzNUue*u~nt(b`}=Yqr)zFOJcoynno@{~DvkHn_jL zvMP>V2=EG{-{9(Ro1dL!-ZkK1EzQf)a)4$Cr=>kDQMB}+r4KEGX&FV!G+JJxC5M)G zY1vB4=d_%piG*Hs%QTHM$g5zG@W-QAKHdKFdn_x52Hwo6I zd+q)U_RVQzwgoO|((Xe4&Y4+JieME6hN;RV5U@=WY z=pQ|V7`I9fe?)8j&{P%6R;HTEQFC#*x83L0nua7QEA>*zHsfFwOk=LM)u(^-S;{n$ zGL3y#pYw?JWJ=*mx3bYZfu{7q<{1J6jF%6|NVWgc?dm=m_TXJ z^t2Ni;`OC;7+sg^9r|iRo_KshoSuPsQBa&C zDA6;>n}Qy41a)enpXsZ`ST?W1QFT(iGxe_z%*EGzCoZKkoTox^EVrW1+UnG>)1NA& zo4^}hv%Ysut}-dy?yG+P(`M>J>(Q5JelebtQ~gve^-$g#+?qDfvDMM}*uKDYa`6%> zy6TcD%)W2qJjANI+%EJXcF*qWTfs7hsGHbWy7{4End!5D3vUM-vikbYYD%3|?4pb? z>a_Mzj1c;6pPXc0`zZZPtQOp1+dGs^O!w{dBO}zFO+zr9qqS;d&KvZX3F+hQVzYnz z1+z6U=N&yLPK);*`;I<3PHWNs4E^e=&DfQq<~&!`>q-Cg= zTEFh)%YzNJJE{|(WIq(bkF@E!`)^?evPTxthao z)S>A1_(h+w;urlVLZuUDJL$hG@U3N3#O+@82KVV!>i!L5f2yL-6xVuVGytrjP8e zz5GmmF1?&2GIt>y2yNm;J_0Esd?OfYjeZZqy@9;#r&82zz{drY>vj(dPwt2UK z>UrV<;iQmmpGyaS^bgouX1p8Y*>z5wYLc8=Esu`Z3 zWdbcP(K3jZXK0yDOBO9wT9(mL{g{x3l7@Qh0Ig+j6Q!ftS-SmhOKxY+sdhHbf2R*+ z^bAeZE*sQ@X;yNPk7@y5AK)X4r;?ppqQ5;rYZGGI|Ic>zyW52Ot*HAUmNL6v8NEPf zyKleUg6cz!rW5uUJc7ZSXL3++EYPwh{0 zt-DR@LudrEKKWk2nrDx{ye*YS)#)PqpxvB#fUsNFuCBji&A`((AX>$ z-FCX_4E0|byz8Zm0gk=u(q4RY*zrlVV{8kq$qp$n8Izk%J5R)TGA7pjG- zGxnLi3~yyuHPnY(XlSJ0fXE1|Hyrc(O8=dA=72Go$cgnqz|#o$m;*BWst(M1(00yI^V0#7Tsv7N?3(Ft5#I2HQG;K)mskK!a_rH+=jOKXESO}^fQ^%wu!%& zP7F19=jh`HYRQ%^{1t2Vtn2D*s&`Z}UQ&H`Y*LP?c{UBk>OG8a=TIPRr1zGJ)Vx=% zhuBT8(J-51x|ih$q=XxKk(1M<&OPTH-r?jGH z$}eVA-+TDC)E5rZ5{(rpbi1d2F-#lNqSjc=Q1-ND_&=n*30PFe(my;iFns_S282OS zHWd|j6c-4hAfSWblDNk`?$M~x8O6AO4ycpKL~}K^#_XDCV)SZ~>mJ1oFetb$F>z09 zLfm5F8lCS~eP+<)zVHA0Ki|jm98RC=>gw+5t-89p<|>{Wc<$rT4uS-S$25q4+K07X z-j~I_On9E>G2-;N&guF7|M%uC`m)wd{_knp8f$FmgA2YA-v*^Fl=o`ZNQ@SMYQ70-=f{CiYXH+&|)*^dp3Y&#Rj$50PxlKm{5 zAS&ASdD|Y;nR*9uMo?**B5bl#g-4)M#ZE$x#W8*~wkISx?RTa< zusxVDV;1lhAu$$WUH(|P=8YQ5-yO)_&~D&?FSDH1oBpJfIkAbwnD2UjMuUjbFZpT= z)9k|Y7M}O<9LDn_p5Mmsw_j%e(H(k?XAWZ7y4kPse+^>8k_J7Dz?i9JE<8?)Rk>(- zPbwo4usgGr_{@8(!K^p+0*do>GRo*Q3<^iF$4v0i@ZnpqGIboxVl#eyKs5ZZgVg_y zT47w8jhWbEVsIhhZ+Wu5e}*BU1_^<6n6N0C#xl^21#9@{gIQW$gNbr=VM*9oTQabf zOxuk8AGG6Vgx_mODlM;YHg9&E77sy-mRJYA_lm$V$p@#ya5vjWCMh9|GoVHqPpCs_ za`9*#h9cW}4_%n4W&~khi%Q+Rj|$jB_QsI?rqiTROYDmhSBAXm-cb}DHx{(#%ZISK zS_9uUgtgYq|DOLggf-GtzRXQSS#ogbm^9<03anXo(~QI3iX|;0A3l_|QX|T%BXHeV z!#^3yS}vVl8P3t)YkS+^fP~N67ZS>YhcQcSAyYvfaQDMxU&CMg16Afq!%=QI@=Io}mzb$zC;jCX?G_;Y} zBinJE7s7F?*|aPgTI2QKTj~SHh=c#*mijGl2V3gjXCe9Dw$w+ld2s1}AoxGF)a8I> z7I51vbexzG;NYtVd7lxmSse;BBP0&9EjLwT4Ml^zW&rW(y<+8s(XcbzekuU%Eu+~S zkHCRWKdf>Oq6^MjV#Md?A>d%SBoej%j=B) zY6;unjTh|!zk-pU%6&^euqVsGsB!%>9Qz%oq$E>ikoJ$xZg)grg``UeL0OIk52$E% zuPpnAGK7JB>m?$#zbXK{Nk?(S+);8t120l(keG1@#EjtUf9TzN5o|1^@NH*W^Z8_|BGhlqPyF9j?rgxTRx3jtM??E&vT3L4!& zEuS=swX7qhgyeIU*UZT)d@v5JdT|&>oY18{;M+#Aw%P~$<|tNIcjGV*8qK1kHlj8f zO9-UJ&e(Ss+y0GDI#s}gSDgQE-eWY2)A?w5?r0X(Skjhri(AX)G_1dgi0qPyK`5Biu?yj2^W|u$AvmVJ(}! zIvq@YcbH_doKGEw3S{~ZwZ|HcNs7112@hUAj`_Cn%W&l9BkK&iLS^@HEGod4y#}^p zkiGt>R>D$bWdu_;u;_l#o+J$8__m*Z^yHfm;#vG5oC&)>E|eiWROA2Nlp z@UZ-ly~9|z2Oq}9me^j##x&bw*c!}^++3bI9w%hq+zrA0VPMOyCEk6k-H>6C81?Hmk z;VN2j+HiLQUhyic)sFO}@|wd>Kf`pP|DoTFFPGv9iDOqaVc6~H7qt!16wf1E@GNNF zE*>#~jZ7Uf9=#ByUhl!JTp#>5C764>InJp!DVhU+k?kuF_I|YlMfjE_xPhCA&y_&V zrLxXcf)#D31cWO~aDe+yWcBklj3bJr0IId~sM#Io5{^^VoihH*|26(K#2dFbs0%H! zox*>J5A_QUS=%KX$L=I=GEMN^T%uhgnqvsdJ;xLr!ltieZyv2 zr(#S)qDfePFB(RaOMD^AO_82Vss|$f@HG}YYzI^^vcyFTF1&BOo5=-@?IM=z?nKY!%l;&?(i>e$t2&KZFM8%hk}2RcPbaVAd@%s=jjADq zpkdX}-8E5OoGlYnR}EdHQh1S|zrErqa6OemZ-Sn#hBhN8j?McLxTqRj3@r)>_b2F= z)zCnd@IZnttA;jF>pYU6bE}~lDu1j59S7(pZL#evS`r;s8#?q?qnBr|LcoP7d>xpsUJOtA6pJ=VKQVVVv-__HPOwp~li6m8biN*2c zK??PVxpx*b#474@<`O8hTrQe0mgeJ|N59S@y*jiE;hkP*(IHbY9`bjdM1;obYjfea z*hj~wzRnuuH9!`Y7^GWDWHKD(2s-i+#0|XSjMx~h_zXQUEqMkC_zjhGS8Nz!>U+u*Dy`%Lpk=A zxbL+BDZu`(V#82Wv%M?Mb0if61M?rcrs<#VUDPwoxFs))FP_S36QvD6Em%UYANggv85gusra<0YUBk_AAFk~Y7c|iP!Zs1!_tPP4M`h3Y{+xkBR+8&OEKBx z%yTvqJ0)ZPd&d4~%hX)Hdm0N5clTDyBy`Ui<1-8HSx03gwyi%dk~0hI)X&t6B#NQO zWNqT{e{gIZ{`Z0E>&kz1yra;_=GecAHG`!&_Fa;ZplB?(0Dy=2ujKD6<*O{LbsiO3 zW9bV%T8Bew`Q`vV@sT+W8Aymtg#=}et7?VZ@l@+(|15hE4nKj$5RQ3`sM#xcx?e6~BGk;=votSTF@s z1cs@#)@aC>G>MdnxiGlGevYYagDjB^<+w=F9^iOO&BOg2B)=tJ4IJ$Z>v? zj~9|-XFhICBP|ZcM%Fm{y#r(N=y3EXk=TV#jcirE-F* z2kwX$+@F#is64TQ3f&qcpR2Ac#_w36k;*z8mB)Jym^t_xEVK>5qQN_fRh4H|l+5Ao z;-aiU)n%PDorUHZQBWjym$9lQ6$51nk_|u~HarZ!LEsX0h_ZG=PQ#7eqbuL)AdSgP%Yr0gOF;;^}!l6Wm)ZzOiI%vwU zFq*}?Jj{fY5R!<&Yzatokf>nE^$e`cR61Q5Ky!zjDM0ht^fA238`H#av_Eviqhtp# zE-L~%7s*9Q^t|cfV`s2tx=S1QyE9lauZ;8#%9BcVvFirS!Pqd6%%;I!t7I>&3!+a1 z4K67VNuZRHIss_5%}SMf4-q6>E(q`M`BIHUf)A=0g|OMSljb^gM!CTNaPMZpk02bQ zCJCP^T9&aT#y;aVVs8UG;fC41{s97bdAOHNhXL`9KaRyCegd=L?Js5(}ojg5^79ut$dIO<<>C zHbEOzLvN_i1q2PMhL%VJdBYNdJ|5(u5JWSg)9@Zaf3AkkQgPQ1w4xfC_pXY(k-*!l z!7af?kSHSP>T2jimBc=R!bZ+5r7cw{93be7YUl?lw3whHs-f*~$)c4KG@GD#Qv92z z68@gRZL5)2sdYX{(CBLDe^e5`5Y!h?^T?D}M$i`DWr-s@QE{$zOT{X28d(V~jitnP*W3jUb0X43FfC z-(Zo$Vz$s}^p4^G>uI#~8vVD^=-XoF+d&$8^FkyNAO8x{j<2Lq3(n((wc6I-HWQfdtsEh=H~`s4`>M`)Z%jm!6orT}F)N*9rc?x--voyL?b z7~}TYtbsO~|9duT#XGI@V|fFh_!)=m>{G%p9Sw*fVQ~{mWo$e};ON>Ich~HAgcEI% zharg3OHBZ!QH9upWdM`ex3On|jpu(0^(Vft3@Im>_Rbh z@lkVFgS-M+6ltIga&N^_86Y4L+fgnYxF7~l;s!{nB|xNR}j-;(u{G_Zf7~JlC4bj-deQAVrs7ISR^Ny!W3fB9pFa(27SDP**aNFjUS5)?9mw zSIlQ|er-VkoDtt`<60XF*M7n4*kHAD{W9-rV+~A~DuW>hVo5c|;RqV_H&=G=%;(uy z<657h*kTTDJyaI}LgAu~e6NiKXXav(@@P|V;v9#L*a%8na@eFQZNqbLF$G^)j$=uF zmMD3KI3O*#Xg1Ce4Sp|Ux%p2T4=-S?8vHuYgj0csI3oKVHoams`J2TCkv7SR>VmPY zAN0!wEaF9NAhwYD#rFWEP&%8j3>If{L1mBlAruL2Gw+dOT5=1C#0(k8OtWMq;f2c?c zi(uFDa~~At-6B%s$YZ|4(iSWRr7uH_2mnolOAyAqYHzy*0UF+rmuQrYjQm6b&RZIj zu|T4E!edlC$G8b{(mHYM3*wpKO+u-*UP}}^z6d8crMI`8gh+ea0rG#pK9T&$0@lvA zEnQ28z27^MCoW{MUI!2uwvaU+uxTC^-ITX`gTA92+^KIKSz?}W zbbzR(=A2J4s3z`Y!YS5Nd{qUC_3My(iGDb~=nn;a5kYYcEZMFl=I)rsuPtQ#0{6WS zOLj61y8II2E&jaQB9?7hjE^kG*}EAKmxRtr%9;D(k(S{(;5Djopsg@4^K?t50Fn@7Uh}Wrp;1&Ekg{HpsZ6Dyqr{EvXoDcHE5uMw)#XG%tq5IVf5^WC@L| zvEWN&M#`~!XY07;m3VU1B{^5grXc=J2EG@__?=PX6xDH)&biz zu-6hh82@qa6)Qj=jJ^RGi$=wcB4x~IvFly%LzmzZS5NU?i&=P}Y;%WUb2hBrdZQ|Q z=3-VaI}}y{5%YA&_KCJ>d_K?Lp zxt#y9n00ILI=&r-s%~&?19tg?UBULYKjO2hMsm3^qrz^e=oZQQE@AO0o?|{!Z_vcG zv$wv1`6k!~jnz>sB2xOvB^ZUOMJd?7o)aU!;YXIR@NQkIqpOMCMNbAsGsM6pm_=`U zY_!6Xstt-ztr^9FKx+YX*iJ*!?wI1s(|G(lth3j#tVnKshc%D>G>cBZ3cXM=&osO67!X*B|Z@$!*KnCj;XEofAUV*baTHMD!+~Txc6% zcr!o)D>qwi8180(sgYS=>Y{iY{@=CJ>GfGrCEum4-eC|oWg?)3655D(KIdH)uN}uX zzROZ#M`TiM{h#=twqn_Pv{V*ReX}5-&25(BFqtzWxp6sb>*a$$*X69I?%qniVmWgJ zHO|1AbR71ob8F`~^z}0$c^l5!w!4}RiV!gCpxhTJ?1F^ie-@W6#5hvB<6s3=)P@6y z64zINFD3eK(kMOb*?LX&k9y6uNVSNqO|mNY?@Zb3a531}n%Ve9Bh zg~dFfm1M3$CDAUJc*M##x%E9*BKrrk!Nmb@*e&%)L4CYRE8AgK zRHZ>FI!i4SHssEf=0Gq;r#@#HHWCL^{2nIb_Z0e@|!e4$-8MvXID-^+vPI&LA61r~M6 zjKs}k)obye_b43OCu8AFpgF&Mid{&KGo{f>51|YQH7@j~t<}hbX>j+F`Za@q33o5p z8k^Vo7z=h0D{YsyR-OkTH?VN61eW?#78B4m()_rxNJi(So5z&cRw5diFZ!kifa|o@ z$P9b>xD0#t#Db#Spp3+CRv^~u10c>EvS()`r-xZtMsjw9r8i({{m{wk6B zh?{~q3y9S65DCbz+wv(dyWEav@thGLE7JtbKzs0GjvvJ35Tv{tltvu$2q9~t$ zIeQQzl**m>u}BrU$l@?J=!C9ONgFLn4~$EG#`&)UM#z4Zi~km38=ywq_N$udLH9Mz z@9akRts40ZYHQ}k^{wg-;oVpefo~Lkl(C>@9tG{`qpA{Rp}mcT8bY>}dRNtx5H0!u z1}-4lsz5iS;719$^c1U<+2KWQGGa(-E21Jg4IwXJ`gB2-01!sO85m}5GN9W{L?B*F z{}-sq6fn_x0nWO`Xh0x5MU5ko1>Wx#{DtlY=YP{{I2TmOpcZy|?j(trX~j~YO4WV#z-vcDf_F{xjlJcf`%PR ztp4tZV9@#-sgCZ5M@#>aqJcZ2t|XQB99R6^G2&nUNOBiEpZ7EngWfvCoV0TV*o=L~ zW$4MVGtU-2vk8AuDuf)`z|}X~wi60QEbRGxtUBC^cG#Ct+dzuDVsmNpYJClpMMG*b z3@ybhD2vhTdQlI8`QNHA2iY$9eFM`d8<{2oPeVKwJXi4i@^ARY#XAV^MtEMp(;Lrt zJb8F1-t)ZsTzDhGMR<nk{%&;1TX`Env0rB;d)xGaAoaJRA?< zd!9`QdlUoo=BcY$Q@_g@Bo~#5hYoIC%@P_PMqN>5Lj?q^X9}c%y1=6CZb@1y7^V^5 zMe}2;S+5?wRrF=$!5Z;VjNAAN0+J&w13LpBQ70W{Lg^XR60PU10dbhzcm=EJ`%rrF z4ZDUp19D%GMc94>umjQD?=#k--KHc7n?tZg(W)iix3T#s3P=x!Ls;xA>x14~Dqdg0 z8y?Lkea2#RAKLkn&)8eKUUnY!ISZ@3JCUp&#o`_$YT-D;bc6t9Vp4bB>vK3<*szGt z`gde+|mb(q&yeMFkXg*JYDJ?pFct&Dg4igoMq zM{8NZ=EX>z7^YT`bRkk&uq7o<3rF=Y0!h^VXY39$+T7V~yBI#7mw&}x3CK`s6&@re z)Z!gCutpKrcL!@qy!5~ngKH7_s?-wN*=U3zl+WA1Vs%RB*0mehNU!Gg9?FWW-;3m1 zf>GdCaOc)Cq`TXewh?VK@H=r7&4YRS&8&^?@^AdL&1{TrU@)DEkfFcr6tp-k`2lCI-I2P5)sjepec+NH4YLga56Ysia1{K^*AMOo7bjQ+^LTW)2uGId{~!X;iYQ_>0?E{pbM{?I<d7nk(rv75!vkLgL*}V~+V$0y9?Rt=TVzwcgI5lDrClq0udY3U_=D}NqpsaLp16ZWWQguK$Rfv-_AY_urtn+cC9Em~X3=K& z2{1igE14JXf}77^jZHMP)U}DOmI&K}Sr+2x&iWv|94<+Buvcrop(5u19!>Dt>v+gc zIL+N(4c$;_FlVh0l4fU94}NTGOa8Xm+!-%)sp7IFWG3?6~VPUHFU_?P4J{#Z(W16*rE{ z#iFVF@+&N4xq<1qYZvng7)=OH!x$=Z_~+d89c$Wj_Qy2!kUdB)Fnb*rPhUp@lrTwEqc|Q= z0r$F-SWh7LKGa5CKYQZhMFWksmhWcXx^b^_wwu*&y7VI|3t7IWZI)$ejaPM9+RCdO z6||qP{W|Zn8*ZB;z#ouI`xfIjhw=HlamMywE0RKJjDb$#p?a#5a0pD2O*XTx^kIIe zF3K=_4fUd3u>(-kgd!OIq#{5U$122&OFaddu}Kyr7cbe7XG|o9km}F^On5E-Hnta% ziD;PuZ0u&rRFib^B*~OXNaJpWa;ZWzm_idxrIb6-N@GZcqZ-K%q9As;@n)~HqQ{4P z${rRP`paaBFBcc+js8YO|JQ2%{vNmu4#bB{AOfJRN!vyn43z+`zC3m-SC%3nDVspo zW%}ha*(u{(rUR>kH7Q%s$fTMm7q6-0i(^2(?rONRDXM%2ksg|+&k&(zwHkC)aGpD_ z(_)Ftt6aoApVurkFN4c8(36+-gKC0(s|og|#8f81`mGj5ceKaE#)7dQt~ zXtL5GmZRzT*F~&h!w?X1neL&F$bm9dLXcu0+|SuQlJ9@6%>H89>eZv@M*l4kEZf_ z@EkD*DJC3&!xRWa-~^WhWrv4(jy zz-9P?e1n=RRYa~*n=94RKw$aauVk}*jhFZimecMTYYZ)#uPvtUGPARnPF$`YNLHL_ zl!rHQ4WQRqBEg7O@sWY0V{HxsXEc=ZJ*|vswl~<3@UfakDs`z0wkwS()UMN zq=EGx#J+NuY4fK%Wk1fAP90^M3wW;MxsB%`9^EnAvBVRBrvaW8c-rIHfoCtCQalxS zF5$V3=O!K(p1|WwQx{Jh9#!YN16DpL;W^R#1=^8V;a=Bt0fhl8tEdCp6goz~qw(Pv z_Cxl(+ER6<=O{~a_G02%5-~*oS}3eQ4zTp#MxoHb&`Mt}J9?QYewD8~z*>Zd0uj_n zsxFC?)K6{zgD<-HtplufbT)FVI*t2oG?MSZCIPtQMl+e%^0|x09b}nGG=046;+BK( zOj6R4uRX}}1{SxMgyG1>G$TS1E}#aK;tENCm4#0g>WpZi$ALtb&b34KNDnGra3*DY z!z_J(l!?EZ6CcLeNAfWxEGfMEv&2tp%fvM(ap)7it%S92@fw;7-liUqR}pF712#Nt z28+~UOEcI0I*^@rHY z;ZEd;#*YFwI)=*%WkZ}1{T}n&L#$DF_h->h!_@jxbm(KgjiL?DqIav&Wf0iJ=|}v* zA@suH1WBA)bA}pSK+%gI@lM~f)bQ8TXljWlHM%K9w|m4_e9xNWe*47OKFl2Qnlg_B0hmjBoptP`Od3GBpFc-&mD)-lxQZY; zL_5>qCJX+PLbA+`01~yn7)jGzk>wS$ogt-LnTy+g&JZ)i+;MiDaVyF&#@^Z6rQ|2) zHM4q=_aqeQ|D~iRA1Y|se6^qjugLAkV93q31M$O#4pG@eN}DF|ePbSZ9JheyMyEOU zjmb#TS{3}yf)}7P*FJJFX4}i~b4s(XZF9WG!Y=WqNA9DkJsyiZ&hP$$=;oq(qJrENtZaw1kC^o{8V<*ab7)ZtD0IPQCxMdV!vbu|7;&*1iS z9K2IiA84>qJ3fcOzdUv65A6uVU^^A2v35yN&R1bI5O;lkxDt(7s#qZ zn`Cc$6%o~{Gvw4ilzgMqcICa~7>1Y*4d;l6MBl!#EtZx68VyQK8jhE!8Kgmmq^xUie(ib&PN2TQf1ub;; z$mM|HARusB;Eqw$3D7r!p>aVZph468)Z0^2Abpzoyn8+-KK*+Z65k@ogf-TX{0T-} zm%9oMH008=U#`tQ8Y`6PhUs9Qx*)~g<$e{cO;|uPIb<7P&fgO#2^{_y1aSOU!J=Lm zK=^2sR5G55k@H98n%@<&WHW>uCc!>E5i_?Bj1BG@hZWy74k^XO1;fB#6W>_D#@EvO zsQku+Rw@LU<~sCult|v0R$mYa=6nf1<(kaaO1dz5tz`%sOgg7s8m2UF}= zUVM~I4y&cc(n?kuAk&`u5V4nd_hT#~a5dG$(_4pCe#>VbW6^)L7!jO%j`(hR5$CmfhlUCs?DzCyk!5 zOO4)1(Zx5PHMOI6o5JHWsiAvO5lCdJ{G2a5!PXG&80x?wAXn7=MasjhL_8F$X*` z5JNRpB)a>3>W=!dkbirMjm$fRZ;|T8o0lDv4@}^dOSB5n@L7zsS#_EYxMTdEi=mO` zH0^N5{9d4z6x1N|QjEqOb5@P%Ge1;Wxc?X#I)iW%`>zcvD>z`$9%qLyAF`;VC{A6EBtlU?Ll^RP}D!NKBfH=>= zIuI|u$8tzZTmqIS;haz0nHeFsc}0FE{?S?N+oywCv3@N6Yj@HjCS@w9?%*n@&W=#2 z-Z1D8aG7G4Ks^P4eP&(pNp1H&I+sd7(-18oq}fia%*2r$sfGSrKwb7IP2r8i6eMt& zeqRU*M^VOs)yZmBr@INKyfD|e{*-q;$D+J?qJZPhvHAw>MFnezwGrZ$KjkaVu?(*V zz9xS09BbFK)>HTip~G@UYq%rDD8F5nmT;}->=~A}Er+^+=x67l*pjBGJW%ss>l8 znftxo#G7AW%_3@SpsuV&52%jbphu=>x%MJ!$X8upHN6%Bf71n)?KKdArx#c{ zYf31LP#W<`7g@OS#2bL3`@Gc!7RR?-WYJ0qL8eMbUH;@E^Yz_Akh)heqb|9~>hso@ z*aBT_4&QN!b@1xfG>AXE#9nQ4?4HV(dSsLVreG`GCpK1GnMqyK+6uze5^6CBS69$Y zY+fL_ob$`rhJ8Gd@4k$-@9b^j`YWtnGrc5*>p!ykfw1nm^(O`f{_;~UQ3&1fiw@LN1$sDn5z4NWy%Eb9zv1c z=6*Ze@1^edD))P}`<=akr~ks5b^6Zz{h9mibib|c_YisyMMjhGjKMP<&s;nU@N9p; zH~zv>gD$`j9y{C^y8kpGUQ}dq*Dow0dNYCTlVLV6E0w0WPvrLmgtOzsvP}NMbv8Y$ znM^Cyu+zFbib8c|()m5XMl|Z{P5i)t zet|~grNHapviv`E3an9%x~|Ao#o6tN2u$BPx00E(;SbYDRY&<43ohae%eW^yMvUqU zw>$4tu{v8ze#Ota>Kv(Cy?$fEwc*+a$oIfW1wW?(d20um>DgW*Syo# z%{SOUt!{qGR{vY5wL5_t)FZdd!1jr zjdQNL*SYBqYtiQ6FVr=QthHSFdkA9BV>kRnFuUObUi)48i}Gs`^-vjG@(Z7F2adbj zCv#5kTFHFt9h?kSzQBLJgKk#SE0Q<=o%Pdg{+Sp4&L;Y-BBc~;G|01%i3i+ewRLNf zc$2$qvToHizUnTk+d5F{t;&Rtd|!k~mGzRGTSXU~$HQt|Kjs>hN#9d_^}5Dy-erZl zFFxSbKUj;pGe1CV(tI*pw|KQK+F!X2vYlrO<8Mx__3_zg&a+CYJ}@WWHXFM>z{!bNsDkMCpZ@w&rSz>?qmj0KmC`K8Y4ZA$CqH1z zyVroShgKImeyE6!ldy>_7hC*Qmc>A+(lMuL30T%U7{221({3nE2CN|+r%}0!)G)XY zf!zzlMN_XodDKIA-g$DDr#)oZt&bvamuc!4T3eyAFm00G@1dr&+;jyc^kEB2IF4&P z%w-xeCYbMj$m)9~AaLy=>mHbm1h}T*cnP`UY+^W1d&J_{iQh54%DL+i>uvnQjSxo& zKMmu@2qB#iI`YYn*h_&;Js6lt%0>5Ke8gj%rGImWJ07z{-S)fu;A7S&@bQmSlQPr; zUZYKO?()We!E5U$Kk_+$vDi8`#Ht!1ESK=RN+L1r8=R)vcloZrSi6AtC^@=n?Gp^AJL9?Y39Ie*#Sancug&h~BZlhg`byW`im>(K=by0px(kDrKgAEe z72#GPET)Ta?H*OmjwAJoBEB5N+dO4sO=;L@(@v6PTjD5=PcQt%H$8=`MF*)y;Wb_C zlRHODPutZ%yx61$62)2>a2qwhhY!zCgAE|$F(0~Qmk-hjScV>*g^UI3ORsYg_$A;Q z^o5vW{jUgV#82;%`xTT@Uxja2iH-=8F~%VMT>$X1E$)~SOC^1r==NXjcDBajlFAbvgb?nI?_w}WSBk?n+Oqzw@UThZap$)0Jb z{S0zTLQF@24b(e$xlH>3E7lhf0W^Hv(oMM`dHE@$>D#IoJs?5mrwo%{O@szVAxJn7 zpOlBcdEVY_HIOcO?^J_J-;Tg`eKNgNWiYjX=XRc9B+8K`4Js{qv7jj^VU*O)PsT4w z(Olr&ohD>`3b1hfjTG7tBbuG%le9`i-Yew_ep&d>zf-Oz4Oj75!(FB!Lx@R^eDKI+ z>LougwRDw%?0E4MyJ6}>@ERWv6pgr{0^-CqHIORK%Yb7M#ePIWr$g;dUX}ZraDSa* zPR&0}b$mbe5>QAgboQ+vy@s><443H-#L+x^oCIK8jPar6x+_RJy3g1FY8vsVF<+)r zV%vTzG4X2>4{BRhp>JG6pQ$WBvN1^s#)2*sP<38TQ@BtkxXmx~8#<-64#v85y_BS= zeWxO@ov?(N9o@I06xUs*B0%U1{pl3X^->D`jDv_FWujJpu6QePt$sqks=}OSh(&%? zm1!<+p>ri}6iGpA^T3dn?U#_fGP~-b&L3HL>-UgV0wE#0ZTVh!gj* zai*MZHR2b&l@?8=pQP^7P%LaCl}+SxF60_WDrvW#q!HU>!m~8(kyp4oKXa3! zwA8I=z`H0)^VSbvBq=%7xa^>Py&RO7eKQ*n6Hubr{fX~yshO)|ao#chnW8k)?TqCo z6lIXty?(*Gm5&nPbq0Z6K1!U<{}_M6N12efZU!_jakvp_mrPadF8q~!He2K5pPIsh&m-;FZEhm;o;Mx{AgzlcP*RCIo zZ_ki-&$aM8O9vo7Brcj3>~pb80=-z>uygBEJ*e>Zht$O|GIULZ~{!dz+N;A(ygY zbTktBDGOOTIQweF?ofWzq_k32QH*0h-y7o}#$!U279m5kz*vb3pSBgw-a64Nl)n+N05qz1~bd)2@ATtKm zL~PUCc3ALB2dVdQF!1cNV&qKK@xKxs=!!(`|DGsN6sw7_Lx66<*PUokbxwP_M)0_B zC8{YaBCc8+6GtI_)C$+uB0X}30FGm&g|w&ZKZjb z*ezue>>`{;u{zM|)5~SLvYY4BR$_JE?&ec#D}8%L0t*7u65-#8D$^C(*uG1k)& zOA(66Ygl>&e-NS6*JT~%k&#MdXib^ISU3@U07V@8o1%f!D^f|+T`S{nMk*1tPnW4Z z^=+6-+a9V7>uxJsZ^kOawYs^C_iCtwHkr<4^lJxV5*@lZ`QN6-F# z-&XGy$|J3RIX0f%968N}IPe$ui&xI+Dj)No~lkVcQSWmB(STf9~e+$Gqkr zAPOb8*vCBYDN&wXN-<*cV?L~v5}w`%v18I)#bYv)txcxdG2w|cO5o_8FA`-S2W4-e zf>wwIYM@j^sDVWy`0>`At(5(WZudt#KS^nncVh}EAr>~qBx=_eeS~3wRjA;a)R-Ic zH&EoOYUFxPWQiQlhNblFG|iScJye{FAG!&wR&ge)I4fi(O;nuy9-KVjj>Ch~Ud8cJaYjj;-73yx4^FU(BMay>J@|?$_Fh~t zj*jg5-X5e|H0wAFJL%hLx+amPtAyHnaLQC1uHqb(I4`L01 z;z+t^GD+t{!pXDi7kiNI(n9Aj?4fU`X^KR8LnSoLgHxg6tX6SGNt}KvPJa*1dKD*6 z#Tg)RTB|t89-M_L&LB5ZhC~Wbk)l;3{P3K^AQRBjm?>9h9lM8Mn5MO;PsfYK~bM zp{cBkLLN5D-@5I$k|(Ar%_fe6WbFAZIc(8;(g<8ro3yHAkp1O4%*b#7-t4&(rY`a< zOis3S=?u+j7*|5a(er57!e*R|F-T!nX&}e|{=miS}FP z7PK|~{3(4ebbp_z!5d}Z`xW>1#u~gAeW$p;3v2M1_)ds$e-Exfstar2Hkc8iOrGwr zKW!UMQc!)9>y*08C)D6&8A^EAgZ1?Ny;SfdCs`t;{TLPVuMA~oUVogYVE57i2{-+q zCj7%6)kYR^fUR-EF1caYgql{kVTVo$?&emW z+6CJ-S64o{ixM8_{mWx){pR{@_d{hxXkWgfixQ(-)|Kz*f;IlZ&-^sL^S=8R_EN^e z_X($VDQy;KLh3U}&R_>x89EC+3OoLI*tU~W1GmMO)`or)WpqI4Y?xl3SbNmfE09e4 z@_cNMgQxziZd(UYl+$22fsUECz_V@5RG|w9I(`8-Aa0jDZtbx{fA1ZfIJv)6rxpTwNaAl@aTCrIlk`V{VW|O4FWzEjBnVTb zItQtN{fGG$zs*V-uH)UoO9$Dr zO_q|-_LPwd35QMJJ|G_o#scyUVosVc&RB2+q143n@8M-EEW&?hUms_8t@!;4U!0|c zdcOzF4nH;)$JD#C6raeI_)J>=7Vt;|R3R#HI1ILRI|c@&@T*x$i`0Nn%B(_sj;Pi} zu>Xgbgl=FJiTtz)_7xG{=!m#aWVY{4#e%d+>$Xe(_9&=S@E5x&(Y(9ECy3AOrqtG+ zM_~o>7_6kAZQnY4g^$$d`HG#aGF@6|H%;%h}NP*iR%t@w_^Q8 z2QTifB>F~eLT7O3xq~Y`l;l<~T%g&Q=2c?>UGJw86kntxfj(*j&U|4tD_id}q+J|? zh4C3Zl)-u3<<=@aH;c9mOT6epf6o~D5sm_cf#!qnI57hsIr!;X{OE&mYwvo-t@y22 z96pLpXS6`VZ??k!OlsmB4gLE1gt#hbypM>bKOvu_WGl85u<+sGmDs6Pj&-2_Dl{a)v0{9;< zDh)cfA__$HohSJYm!0ODa10VE~65Gp( zy^eZ2ZRv6p&uM5@`?)2$rtx=!(mmy|Y9;p-pZ=;j3@ zO}zyxr2rXOxIj+-#sWL9+gmZ2_M$*JN#A^om$C3${D(7$_jt$NO2fp*a8f~coRf@O z`;Ikk?LJwIzoDhop+PkuQ35Ow9BN=0s(BdQ_~29ies3kL;e>zUKKhLkdvMQU>nj#M zsz*pOPs_zI zS}yhK3b}w3LGI|6PxFv|ia9&*GoqB8E4Jcz9|0fHk(!(aOe3Ffp5=-23GoW;|Of3-X zfTpQT;HHqqwv*5_^i%U5fkJ0p$e96UuXAu{(H#u*PXICm&XGVcH$5TNs|awX;B^kapPZKLn!O1Y zGw79BgaHl6c35>|MZ@3<{x<~N9}4NSoPWH@Cp`Ph6SOpV{$OU~G%U=={$c)!$FSFs zx@)%=fk(Il_2U{j|Mmq2Rkt;M!Qo?B%ZU7K@9{PRl~`>#A2?8H!Iun#YG|QP1Yb8$ zX{3A2j~^R|bC88f1owGa`PlbcxHv)&Ix?4UepzW+qZicyI|1RV%4vW_k)zSzE3`(0!L1t z!+i!T5jt^)Hyo@a*Iz|oh=T3WLufgtnW`zSSgWgt-6-DskQWSA(tJ6FF4AwB&C3Tv zxa)C?-yRI|2Ndo%M2XEQ|5)u%>A>kcTkT8j)xH$#=}UE}FIjQU+Z&>U{53Vm888zD z|H7a34eKHP`Vhzv;lqu!_{T$(WW#2hE@wbJ`N~F=QCmCP$5>|;AO)wm3Ob? z+Tlviu-}f*EQbRyS}qsE4JsLkl!;6}Zn)C0VHA#&r2A=~5%xw+&Tcd<<4;~u617ixyOGLZ_6Yv{#Ls-iNF}EC zx9a>8CTe^|_z%DsYXk9gFclEK&z+|I+eqJ6>g=g_Y)r9=wa8U8?w>%d5U+1QO8d@y zVgw2>mDd=h)UG|2oRHJ(LN=P!>t%qrwT5>Zr8KNj%NhZLhtAr{-6ed=D5Z(6^8x<; zD5aIQ7B3&Atc^Z%RSTX!ng$NTk}wGyt783c^o8Mbep&=yHd<*Ku#Et7rzRYS3)DNS z`H|5|jP@eGIT~jIcJd4C7-XiS9yxe zNoXPnRdzzW_!8~|u`=K1@4Ojq(tYrRYsX?92)M#y#wty9$BKFPu}ZvG^b;*#f*T-V z?Uz4r3HlLoEXe9fD~9f;uSf6=V=+G@G~{Jtp~{YG$ZwBT!n6mt?>Hqs&kHJj*ipd+ zoulhGlpkiU=n-?i#R)8KqHQU1oK4HWq!n*1R4`)6dT2hP(vAs7xrAG);cpUruh6+8 z231GAqeghUBRV5uZ*XL{g`*K-M%&-X(OYT*<`~~6^6rH>FXgUF%eZLOuefCX4=fhvI{>Y>V?s!#c5>{*J0~c); z+J1Pij>aCj3>ao-^H%rykyn*k?JW4jHo;abH?u#rE?R^O;T{WRM`RXZV{(pDjdP_A zrA(aQwI?VuwMl&01SPZS-FF_~INX()^cnRG$=}IRy)^_KlyJ<2jDF&`Vh?|R zqSC;>cmWL>E$TQoh98}%H1?SW8rXM!zH~%r$X3&9inq6NcO&d#h7RU2uPfm`C+K6+ zFokQI`hItrXSG}ix%cG zPSd|PguqWMG8fkIlw)N}EPkqV_N}yMapohE^j0zCSizarK@8mCMmAUcIrnWX!EA@`oHyvZ(rLHGsDWz#VMd=Sg`PRFd;YAe4n9VNbe zkw?x@!n2DnYRPkJ4{h2eue72{FZ77C{LARuN5uMPQ92a{+3bi|<_7E1HvK4Y|L(m4CLh1w^6qwK%k9q2&d$v4S|bIf0TDg^CS@T*DfuQX$L|--Eod^(aLBbe z<0=*q)1NCU0V!)K(ym0_?{E!_v6A+PwkeU~)(!F>jbe}9p!%cbIu4hizQv}iI@Jcd z(U{S4nEOx#H;csSs+{1uBDJb-uhB1~<#z6}354~s5wzeMd5@73-M_{ByJF|OA(Cgz=oTAD%Uu2Qvh*=xWK3yLjJY)halwSah^ zqU*&SPua$3Py|y6MMMv=MBA0FX#1h$S}+`tADYu#8{eyRCtdFCUV!hnbf3t# zEB4%tm%F+5G=W6-3DEt^bcBN*<77`u_X$w?WvV#=pezfBm&e=9`7*8MAXf{BHw*`@ zzC_L$0DX&d&y5+P`vj=wB}&hbyGU`@b`>h6i9v?gJCrYUq4hA4I}QCCOi5`>_p;<3zE?N!iBvt7-^d~%DS}JJ zC_3sjQEo0B&!O)p%KldJ^-r|vTjoQV^JKq8*;qL=^rWC{IW&65MXjdj9#l&WtK%g%CMdn7vuT+8rjq7aWupZmsZ?hM&Ap(dPrI3C z?U5E7&WJDw%s5FF5NAdh1ixW|RpKttUX*JUj4X2YFi$^b#MALnQ96r<=c&wO*+)8e zo~lijJ%e_h*J2Wjm1;fYtgH5Nd_GP&w`tx}eQ>(5j0R1XL;N#wcKLHO1zi1Ab|y-; zFBGY*Y4Bt@$Umk8ju;pM=hRt&V=HhZ%{2-PWp2`pvlKD~ZURTIihLF1dj|7>@r&As zG%f9M&&KblogJ@Rz%s#J-CdW_xG8dIwIMtu=dPFxjLF_$IfZt|wN)aSgD#w3ALo7; z5HwRaFy@bR=Os~mEZ{k(XK}MIg4b?LWHFVs}R;B z{D`m_;b(-?v~8xBH%*-?`%AlA>HDd2P-HDM3nu_GpEUQNmj%KJ01Vy?`gnHHG>nQr z&yo**{Z60>jCmL*9y8{qv(yeKb>~@7IJ-2F!#HEK)U;k}DK(kXo_?$8b9+JQFirNX z7iU7!Z{_^7WJM}kK%9DbpP1;^`7Aw|CVMzE?Qf)ih$d$GFJH|_4Js|gcN6^;eT$4V z<+GT+nl1B4V=H#n)TjEEuEYpM~BoM z>!L}Sb8?xiIg4-+;R?caggXd-BRp6}l?-y6bao64H^_drHy47{G@$tgIgDMybJ0P) zOnrlxmo0xe8%MVcvb(&BzdUO~?+x-GIi4q}l}}&J#1didDq1m99_qM#fl080!)3V~ zIn42#Ic8^TiqDaKL+VX}Gz|F=fa9?}uzLwytw6bR(a5Kj`15cf^KS;{xYarE_I~>n z{hA|JXqX3&gz2$v$D0p_LPT@Cd7LeNGRMJnS;mVCUidJpm`>Oxo+lt`Zv+2ex`77K{)OxlYpzTe=X3H(TuFb#~R%>jUp-#^=&QLydVYb{t z8$*6`i)cmYgy5(5F*WIA5M$ z{_1cSEOfCn@5pV41ffL>3W>SYGRIos<D7lBhi_AT9@*ggu^%K9>$GlD%q&nNT1d1H~llaTEs=2qG{*T-f8$FAkAC zVeb0v5LFM6T#FD$GK@b6_#^a0A_7{O)? zBda&BSL_bZ%O!GvuYym&Y|sXr+_rQnXZKUYQp_7a@28gd^<4~1-OlFPJjFWuwLB^c z#B{0sYaGZn@x*4%s~bwW2k78ZxXB&eLq$uWsQGRWv1Rz3x`!&@*KrVh>v>t$Xnm@& zOm=llFvi&66GTkeN{A5*pu2u24#V+FK1B-oI_&HKx(%{F7GoKOoT`Lt3liCrA^DxT#-hEe>bS# zUb+p84pwH2&l|Kz{S`S1WJdLy0S(1t22^wOcB?`lVa& zZB!~ZcU<2+v|@#v>JZh&I8)BquC{*2Uh2LQl;^pV7Oez#D&9f)E1~Z?wu6+F=!Nfh zkh}`LFl~oug_gFw&C9HkUCVxfn9K}NabMBq(YKFLr&aKO_1ZxTSIKb|`VA0mesL@2 z9E9r#cM$$Yc!2N};U5HY`Hlrr;A+`Hs_~Ahu9kxwKP0~Xl+f>lVZpSvJ1A+j+_2tX zyVTM_1IF=dmH}GqG=sGGXg&j)#DnTPsc^OI<>h8UF^*p$YJJ#2+BI@$=gY=V13B3X zVm4>6ACP}yZLFK(u7pFMGPpU}I;E+uDGsC*IV9rBU%(lM3z5bMJge0FnbOzDUTp?i z^5*QTWbG0yATIKh6s&7lKwRW8NmAZB=@f*iHl1%5}olCiCgP?9Z~s1Hl)eJVF>kWrPTXItbKfAvWW@mTA^P>^XS&v&w-l z{;YD~-S|k*f6M>iz$<=MIq?2pR1WN6MEwsA{N7kcfIjEIx3{Yt_?QXh-yC>@2~?T` zFW9bf;8ELE4*YS8%7JffQ91D8Eh-0IzeVN1Q?{rac+i%Aap0c0DhKx3LJPkI2M(I` zIS1|o0RkM@ZkEb{hyJW`;A6d9Xv}xAzkS8=T)^yR<2QcSn(v^Ow7SsGh5UYygCmCY zGp#h$)ohVrP^k#>5;w2AbdNncfeVkT$hQ%Q#0|? zyH`^FoR-)NBdI6w!_}G;6BsGF(vB}`E8P;r2f;W`zG1H zmXL)oHT3Z2@?0MwwdFW{HxeIR6u@<>TnIS?M+nFhyLs%z0NSug4w5tWmDLozb){c7 z$=z%N_{&nNwOL+MZuH)=_!91aX3>q`Elc+|!)+_;0r_pgqT}xgT4W6^zG{R)Lkx$G zQ@@*km*U+Qf)+My=w@xfYvT0vAugy^VovDoXd1dju4CWv2tP_-=A`%|v~i2vO8X7H z-6FTwt%kJ-)(7K>OJ7scRykH%jaF@yL$!>KZk1;QZTgyfDWchxe34pXp5DZA&Dr-{OKX0SJzK__5sZA(j8V}HF|tiFL$f_j6 z3B;79R;QJ#Dv*mk+J8g$8=+v7(!ZfASCY$4NP(FvsoG9?lr(iMjscf1N=?>M`YzcZ z?N~#0yXEHo*N(}WTL^z4+(&qf@B-lt!pCDYY&X_ud0U}_YDjZ;%e$?fw{)SzJ#wHM zjNcl=4KbVzCveKvd!<(rW$uw9Z1+Q*s(8@OJ#wsDhg!T_a1@5t`Yg9i&CGgzhMe|d z&)LbjyPEEmt+e(>Ps^HFXJk$9Gt_>cyef45AaIMEE)lqFz7FA8zb6qkN4$k*;SIlj z(+9cjDz{(8vCa|KcKPQ*Cf0p39=z&MtAU0ql?#=W@f3epuC0qeq+WOEtcVOAPlm&C zl*_$z5qTOWv&v_cE9rFkupI4C<4Re+A0juUa?>9V@%0^+bkTzrP^El%pZoD~GWM!s zy_ivkU)8PaVWk`yPjB<(C6d=PT6hEka?h!hcLZ9tsHwaDJc8w|Q@WZyC_R(b z7RZHm*8+uLJ?$2aJuTl4ulF?;lR55LUHE4ff+xW(&wUx*lpDC7+sJls*b2=&Bm1_G zn=SZ#S!g=5jy%C9bIz{xny&JsLdAM6(pVsKI^UEvH4y3{bSx1XCO9qmw(q8wdtmTy103NlS`fQX1H*UvOC^vIGje| zZ? zJNrD~p-5JXmpSsI?fk4y9u!z8hq$w)|DG#Ssav7EK<>Q+Q_9t+^rBE+?Y?{Qzwtuo z$8%6k_YWLZvIEU65;+3C@A74JUJ@Rp&EAq2fw=FJKqhBe-Z@kemC}X@_sh z{J=kz&y<}##HYUEv4cNQ+(o%X{Zn}1GeH<=EevS;m3AjIT8G)@d>glW7`(IHm1 zvsuZBA<@$~F}yBPCkEKi3za(AlyC`~sb*!-@JndOv@Eqe)wG5ck-5MmGsHMEm?8Qs zI&ew$^sE33RK++En5t4HiymIWFn^RuE|+Bw=~5JCA~zsOlX>LytKoACmw+M50izG?(>-v1w|_Zh)L`qdr6;-L_kpF$ZT^W^}O+i!C1 z(8GVrn&Swk5zZrAM!1G>3*j#WAwU{cyuV?dPtK>izhTuH-%9P>K8bD=a0L_n@re|9 zMebsMHcDwmKY#*{IV%-v_|sx>*CeE+~nAbZEEg_^_&bJlCdQqMoI zHlJ!nFcOOyW9V3#3k=T=z(6H9v6QGp^jOM60d?HX=^aYzIo^*kmF%brNal?1j3M9a zDEfpM!x}{r(NdpiFHfp+OJ@EH zAHjrxunJ*4!jA}>5q?J4{fOG%lB?LBodzi*fhOIO^Q>M4yHNaXIk0SMEk4CHdv7?w znOls~zZQ+XE%&nO4}@#C<)5UfU+kKCNA4t9Er@ZWn|I|+R!Uyjr&`EsqL|Agd*o^?cdc`r~O*V z6m?%NuZ^Id_vI$i!@IQRzC6HcXMH!aD~4wx;UT72t|fUrqO@YUW9@YheS}|@(jev? zcNTKTY%&{h%3v7pFumIFxjP@*w7%w%FW1P}6F@!VWiMB!Zal^X$>4Fr_j)vaNEIJo zZ>il9F8{Z&R?ao1UJqm+=WJ-?k;B~wz#q7Vraq7ZDjmcNeA)t)p2!kA%MDH&Ik*kp zxKm6TcQ`gAj8^>D(76Y4p!3EM%+$s>mo@b9fn34ww?^*}SD-X*j7^?mcZ&OFW6=*9 zQIm&qYunoO(1ek+=%L)zs5&{{HME=yU3er{ zsB0C?v$dIYA2r0M*~L#^yc$zlv5Z4~M)An$euMC%>_bnW-W~aKn{TQ5W4W^X*DFwg z={8ozv|Zt-rdv;6J(k@oUulSJb8H4Ay6_1N2R>%BbOCN0-wWe@tq%GR$My32-3oJP z%VW7kjebag%c1Lk!}!e>a25V~J#WXBOw7Q_3*tq61Gh#eeG#f~WCc}vA~(&*iQ?5S zR9;4LY-}XQp=R5FbX@^bCa)jz;vQ^v%Hee)3l~5S0m>sCm8#+s>TE`YYFOsG6)dMl z74iH_7_i}vWpK&@a#08po<8k*`m}lJ|GYNj!U=!aQuz_GC%eesX5F+UJ>D{sDxzmL zU$+HY6z)9$3NdjRqDo|Mv5((rUBW)z2OT2p<7vJF9g7cNUly~3Jx);!eUH*GB z1W!l}JTW(qbJeXX8J$t~SU{hveOLCOK1kg$+k#?L^oc2Oh%uU*OoN~mK3Bvwz%ZN| zr^rMTT)&miEwFT$3$1}eb&+#MISYz4P@r8jqrB^_RvEI24M5N?ibC%qdY>j!94dq3 zbP$^oXVnHDbVeD|6DhF4aI2O_@w|9!KU1v4V==fyY%38<17684)gnz8)*J)-O9V!F z#HLvFhC6}{%UTv@wS6SA?&W=cgh6s9uW(X}2+9Gs9Fp)itu<~@J z_?NPi)NmaIy_Uo6q?fNgp_i*TslEKLH_d$wlSN`L^{XLmsLn#>_Ndv5PQON1dRQ>H zin3&@zULo;UPj{2d---x@_PgO(J>2(Q7>UGV1orzvX>Y1q`_}wpNvre|GVMgS%|yi zl1er_*t}?}e=zn$cZi0^p$8)NmMPYXH#V*v60xUDv7!rHjj_KV7G2=ZyTH-X2P?ai z%UgIsoa~`~ZW&G?7P8xpXw^3%A*Xd9oD;Cl70wC2+q-C}jEB8j${c%a0M#M5A$TG9 zBLpLaBUDA;9Vhk>n2*1S!4>Z~pI`ZIwJ^MJF9k=nP>9JVxPN~YlnaSaf|;Dp^#fMZ z?YDB6-?x>yIMMrr*pWG12_O32Mdz{otJLm`Zo~Pl6nj6tBKMENZK=UWxtIU1 zL8w>te4O{ng%RPl1eqkqY58CXbI<{OloNfut8->-UZHZwP7^b3L;j!SI>BCLj8piFDk z#pKj2zG!xdP7VNJaG2r_mCt zEPc^Sbu4+_j`m3`%(JqZ#b-WBJKE73iB+(h*-rgVyG1`Bk74a7#)^4Z|E0wUZM@#9 z92h36Q2$O@ruiG;0m4&+e-PdwXmB`=4T6b+&EiRR2uOePNuzkukG~x}t%@fN4dp;` zH%^&`LTv!WP$)o@DI@&G2sd;-AfWAj!~OUayJ%`^%~GVS3be_Z)peU*feTr^!!Z;l z1gk?Kg)T8Rp5SbJ&9D+;h>ogzou zKy=J$>c~gYS!J(I2uFibxf}yD+1Xnk7Tb(08ZnVLc1w+Isv}M(* z1T;mbgkRpvR}oxx*5N(TfSok%N3o$2c{%gEx*fwAzFHa)E4fj$%xab&U*7or9dXTu zWdI)Q3*`}4?nToanT@o)7l_1p;g+ebPy~n*AuC{J@b)r6R8pZU6)8n`0X}@r!p7|loRrb%9Tj;MMVFxmvY(|ds%I+68PKW>AeG+D^+hrvmMzCeC{qEC)Pu2 zyTcp36+z>jS)|PP^Ygr2`rb98EM7ZgS6>$vp|!f{ z;YJI}u-aBL@la5PZFYK$;iBtu4HQ>3@ElDk%L=t!sIx26%adJ^@vT#|(v{Vh20W$T zU0J=d%U*pH*T;@2vnLQMJ|$`j1-r2%$$u(ky0PX>PalC^6AP~Te))Jxi^?2>i#zII z=bGXJxBi$(pHh94ZBzKT!ltF^ek*}wnN{-9hSP0k93e+{w!^;iKRUkNIwo7qcj@CU zVWaOIcNQ;sPo^s6ShCeI7dM()j{Rsg5f9NGEY9j1JWTRnJ$++curJgFrowV45LX`N zIL+1Z@q1CpIz}Hn*c$0ZIIZ?%o1QFN@>Y{onpgSX$x@K+J~&3nbb~ANbd~6=7pog_0=fzeT)r|5P`<1o!&cGF zCKeTY2G7yxPw4##?z{O%>hq)YvoG6W#T?z}OFuTmYP^Hn zuB(1*k0g(%5BU1bB7+KYOZXR&@`9slqAyyX!cD$i;MkHKB* z{6@}<|1&}Fi8fBq2|>(-`N+uJe*+v9e}G7X;)|+n7R=i#;}z5?tv8x@_i4ZclZrxA z3EpiHW19GtSX#D4+li&+Hl>9f+PcKjlCLRq+?VtG3sE3tREP`UbnPoXaE7qoEjSSZi z;XrlLSHMTDtxi4g+h(c-wG2>8N{d4*Aji+Xx19y#RH7aYs?(7Qta-Vo@6fNp_%4Tl zvT#IuTjhEvl@Dh%T6eFa*3FJv9bl(KSE#yH)%+U;F#3_ZfuA$9ipS4Md`YYWAMg9V zhE5YE(O}RYe(QK>-Dq_<`_s2RngyThs)r*Sj8{8jal{OF0|(o1qg55zXzAPP#eSY72`rE!&5)%xA)F-fWK}2Ru$S3$34ctKfBH}@RtK92L3)onKHt!W#9*uGY|Ye;+g|7@QajF8kq)E zW)-AccWD;(qPa%%tS}-s)iI8DZmg=zVx<6yK2>J@wM(df71mi>miAR))!HNtE2}ZE z=kdBqm#MSM(%*OJRaKT$ZpNLD*zl%L^W=xwLv0<%>xW&<)mSTS1=?ASRrYvy`#(^2 z{z0#+u_jW`5NcSRh50V60Q!Jd5kp&_SBf4pE6{}M%(HHa8N&(~P@b5HJJAfW1B8!q zRqlbWSOq$bw7#BZ3~OLOTVlre7`7+^ncodF6>kFstozLfr&Nd|AN_enWlKP|hEZ#t zc9A(P1BQ2rHB7oWts@}zCDJB`(Q>5qisu-hVSCOoggQWYztsq%GXP5-Vf1$d8z4ng zpw=~5SVp~Ij=rm9HE0h~;wr=b_8UwUSYn=4{EQ$NMRO6&qwI}QHC4$Cr*M%^+-)diD;%x1zoiDmHCeKA zYcw;!o_q{8c}nRu*;uP%VOnk+!POVFm=7!X2P38RQscPUz~6eUP{)mT<-b9j6PB6A zO*(*L+L*^gUF-_(Y1@`$$7W-VAh#1~CiY^-4{f19;Ttzk&gU&vzf z5>pm#rYx2r$~3a6-6juz8drxoIlp+}${j79>T$ACyeBQH!=6d&U($@aEHL8^);ZIg z`yOlVsWn^Yd)aGYt#^UF!yA^1ddlXe{PWs0RKDd8kgkW~ydB;Gm+;OHI)Dy6Jhhzi z4-Phg(S-XK2)8V*)W}y{0!>1JIkISD1(V{rVkGm>?k9aDt0*NOqal&Z)B81i0>DLa zaYoB}(_%vvC61ThvY~R5RswDthVN0z(Edo~Rdy5(Fh@mkX@`>=kN$f){T<1IyFaVL z<5T5h*^ALRT6F{SP-LW<&(}5PSvpmDfF#Wq+QQ2f$2HW4mgE>L5bC-EH}|!(Rw^Z! z^WXIx$b+ZT0o0*tgqnW^em7r^`&wl82?}VZlfXd<*m^q(t{6`9c#=yC=*N02Amhb* z4fl$O<>zQ`qH-fi3(V1a~w#LmXGVAdba)YLrRI zxKs85?g(5h$j@mKlHg5v?j6t0MPy9NM2)fupT|`^)Vw~6c0W=5-wqD7X-R!7x-YxX zAuMvNlmmU~c6~NY+m8k}V9Dj#GeMydNk#umvBfxy!Dua*jw}8QF}BlV8{&?)hYeWM z=&?0Li|6YV)aK?e2@1QSGTH*`QQR{2wVlYMUEeB3YRk2=1#=YpPD9kUm zakMy!g*RT_Tb1gkXKzI&%EMTEif$*EMuAczMqGenCMBLvPo9rCrU+MwM6tS|1Ca?1 z7p%X6>i{M|xiy(9w+y(2`6;JfC?pG&eCpni)rB@@ZbMcjH~@#|;8p;{Uuwer0GsOt zTPjdexU&VK8`Yy*4Ox;_PYt74l70usiJ!HD6*f#H*#~$*nzSmJ<8h2kSkuY>Oei0p zePFeSM6RvEm5>07-^Ur{pFlbrjg{|}^7J4Y3!1=2EU5F_XcHl1g0k^(cAQ;woQF%E z1f^Yg=&DlMQ#^poI63Q@odOMR1-?=lh$@AbZy=IC1DfJaiyN_;Z6z)Dx=9PoiG7p( z+IAF-o9WG-{L@%TCy*tp^o&lCB%k{;PxD*-^yj_l1>bJ%n-g-C~03>WlxP0LAo^<^-N?z z?oQ7?eS$ntV%zyUSxa;KLeqAMb|8d(2i;2Pyb+5&ddTu@R7%+(%d) z+Qnqv!(@FCt&WvYp)${w65ApVe`_k!fd$yDST5B4Rr=H7wk)9bB`e5bd-yJi;$fI8 z#lRG5YVB=mTW*{!*&CVG)T=#uBgL9Vw@3dq zwx(5hw+gk^lJg+u;p>0`)W)~}tnr^((Zlv={P9}R_#y9?h{iviV&u$d*y42j6GS5# zuYs02c3@R{JA$zr`=yy^U3{HDc&;%6s+LN5)dFxUl_C!S5rJ2e zsEiPSP!Aynp$9@*3VC;Afs)jm8g^v6Go}Tp-Geb2Z@8rVjtW{vHV8xXPruSgznG9v zdljKcX@vPE1htb@9RJcdUjZk#n7--6%1T|dG_?~8k!omZQztaNr!l=*En#*m|EQr` zov;)BF20`ElN&`vznU>l0aAjSnw`tHYp6p9ss&I8j}es5RkX; zX+akj=5YaMb*QYPM6v_#>3kRFr)v1Z9?a}vIT5l0GBVCh0wNc%#|{` zF-`i#%f)`Z#9;`waD`?Zv$);JS<6DRt;D2J)F_Yd6Y*Q(LRNaJR zMmSI!!TBwn>%rVAFD@Nj^hVA6-%bUEZz$qRFp3>-sA5m(40GO4yPgc^B$-q22_40m zXOZq^2%ld{PW3Tw=n(RX3Ihhb4TXkKF!sx;(;>VJ0Kt+b+P{RMbBl9d=Zk+}GTB1d|@$ERRRPo)`~B<9VV&f&~=CL%gv!T z4%19z;NM76HJ&9Tf`XT#3f2v#UZT0ZAoN(7aKvmNX2Cfx>0>Vz=6*tJOm3MVJH4d( zy#dOxfOr$2R*LsaO6|=O{Z9;MnllI&5Pn1W1K~EpJ%r-nbfY(G(r7(%7k;U zG>*=M!@X0?0?v}sNWS;clIk~bK?SpqnMBULq{3w8S#zfugG&n~MVaM*_v15~)0c(VU%_cA;4hfmg=pgR<1?H#Z~8Mzb;+zsMici^ z-#!0@T3d`S%Xj;i#`(&GBYdz-jq}E>R7NdKNM_OSN@;|O0-+pd-=8;(?uBTW8ZV!l zn$D@CZ-4^Y*GD;Mut77;lOiyjq^xUxeoG; zXuNw*=!bqROnZGP*aZNGD4pc|TK`6eI~Q*q0PvG|%Wpe{iLHPw91k7G!n!sfIqa!QA-+ z7R|hd>daVDnw<5N+74izo~giqU}GdLO#4E7==GFF3}ONPIa39rNrmZBEHfcvSfs>r zw0RKo*KVUTgIJi)j7OZ~3n_DGDYOxf$oUJ{>pDH6N?$-ws_}?gf5ALlJ&{1jEGD5+ zeni?CTHng~8KaqI8NyzK!w5GJULm-m8a@an>QzO{<{1N_h{ji9Y7pJB`|*EtOKfSJ z1ty$Q-Qr&w=_?abscv}#pM?^owRrr0yCveW+AZZC(}{tsqHi(2SnUlX7c{#QIAJup18fuZ&nr+8C;4Sgi~D`5E~(O-ko|Es@l7SonN%uj-#b#@R7 z^;uHAOf9~|bUvh5oz6R$Q+z(1*Ed5xpUwk{)#=;@82>$; z7sE*w4zN;#?5m}w^WZGeYxOeK>D>7NwH*RE&r6}SA<#g+{+qYft~OQ}dfaWMKZD7pqJZ)#M13B zgyK6u?slr!A9z*$_KO@tPwu9Z!`Z-S^I^!issUQfc$Z8rbH;^q<$$jGZ8rS3Z6adg zp{zE@wx(`IL$n1Aksi8c} zw#ZFnBr;GhxWuue`N~F-GVKIZbI@|eaQ!K+E5`L!UAd3COXe8Y?P>OzW8Bsx=CpH9 zwNA`w>uLn}15hq=OaLGWfgBR=3zbz9ZDP(;dN=~UEkprdLqeWS4Zmi7c)FB`MQq(>66hp_<@<`ey$P^KCynL`~O@@x*dU-W_Y+14H&e z6SzkLz2+)7Zs9z#+{bT>N^v-^-}ecuFl9PbLdpcgi8;Dm?cS&8qb{b|V*AweZj|v2 zi;?s3BpEK!v2R!lm;Jk;l+KwAdnyu~Pnko(scbl#+6eDBS(X;3vOox~Xe~Hy6}sDa z)5%okAids6ms43qt<$13HpsXCPOceOZxWb`dVyx+r-vVl@zg3m(xfz2qy1D2fAm=` z-eX;LJKMSxdk9(;&wler+$4z~68KhxP((;&7izkyenEUL;JMZLPX2!2ze;rOy> zFV!2vmfFv_30U@#n52C29m{IhUX9UaIyOAjHhWB0DP@RX?mXa0FY6>1i*#^To9oPPle@I*cZgquAUz_y**L|t zX7+t;sz>%)ZCVut%Lu+*2FN(lIn^2&JpL$Rj>Xp2sv!7*@+K)zau9{1voKOL#Y2EP)QDp>C_hTH{$uw#0ji+)IS?sak4}prxM<71A&Ql;~&Ux63^tn*++(hbLO~j zP*FKE;;0Sj=>+EE(npQu^v7e%kZ%U_OdN~@#?Q}Yn)e75<}giPW8ly25zZrAM<_yg ziQo(TSOiWe*<&K4G<(4^iiW@Y^od_K9-g^p2}*#O=6q@yrT8Rl0~mAMZL~Mv@8qpU zBp6Q7{tT7_gGh@^R!2LYGBa5}kBXCo{~q^g2~4bfEZ*vDtqaPL8T2+2?o@5bFAHW6 zeKwuR!fQ`@lEvCeRlKOlM5sTW9HfI2p^BAW&>s_7D^~C$`pUnB$pp^dsTd?HBZAhqcW6+eJD!`ZP_HIBmQ>y(Gmm0uI+{v_rtujVhY z@#HWWW_#frqQsQjRc$i#P4>IK=ZT*v)!nJ_6n0yiPUWYvX13AaBZO2zUP@Y&FMGat@1fZoUTN91=qx+~p9whBoA|Mw06q zD$arOrPDF0IE(p9b&gTOEcTRd$7(p6b@E%cx<(4 zcG7#<0^|)jf*+~tci|YfiT=jhd;S9Yeh#ZHg{`A2b6AX&dV;*?vM;2BqcnLg7Pl7< z(}uZhjq`$~5Tf93w=h@# zDOd5K?eken$1MPemQ#*4C%Xk~V}lH22Uk&i=wv(zSfZ|JE=C`JS6(-R)qPwgO{$kV zgY5>fV5)UfGHmJb0@lUxhLx+vaEe!^;Vf#ukPVh%R?@+R@R82R$C*U%7r4Kesw_eS z?p;hn7O{?!<6=6z2;Qt;A0S6!{&wvTfIM=duhFhr#8znK{%9cOcsTvGnCUAH!3zc+ zqzz?EIQJFjLonZP9`zjqP~LrOfIc0@K`r_vteWk^`A8d1X-n7?>HL2Bu!KFALZ;BO zrSSW0-Q1NbE<+D`?4g0n*hA@u+0=PCDtO=<%32O%-Jy@PWjU)`aVkzKh>tq5G56WM8l(33bh?uzt1Mh9EkvjeEW*C}~)AtpPMjWm+-~cD} z&bByR^W2=a4~u&3q1CI{i0Z|=HJS$J(#nc7hV$^K0yiqUgxJit5~9PA*c^RuH^r=m z#$f$!>b{z-fs^OQPsJ6K87)jc)4ppMlddFE*cvv#DyyH4X02f@Dnls zbrqAV%;_Aw2AE&3pCf((-9K~tB+0x?nPfJSkDIf?VZN?#whyM6--7u( z+d~__Wi911Gmt*B5`FxZMN3a#Q1o{&8L!_)d7I(AX}6XB;J=Ty(5>&7SJcHVVinH! z{P4A`$uD%jG1>}y96fcD@PCN}dxAVY_VvXC3dRH z5k`4GFdrQBaQz3?fM4A9Bg={`n1Ytv9BiW4Kk$ldmF4D`no~a~_e{VRtz}*r<9OOx zVWzY*jcL=(F?ZA$v#8#?s1IOf>W>=E(}$R-zY5PT!~7b}Ux%At7xBFKVCab`@qIMt zC)PJSdm!YhxR5~X`pd<)a_629bR|yw+zDB%E1q&%{HQo((bJz;`Lf+pxR<44D)(~w zXEF*HLm?Yj>#CL7s{=s{fHENd@(48$^vb8{>L74LlFB@ZKdsupe7x=Xb58mHqW51n zu+C-6>N&kT3VOFq18!exxRLdfT4m9ijUbVU{b>J27NcEFA2vcB8c%_n*lH;~nGSD) zhUS-Tbbk}8t@~~wWSwq7CeJy3@`jINg5mcBe#Xli<>~|KxEZvc^P@`p&%Re_|F`c2 z?R)Kq3<3?*=d}Or_f&BU3$U8>y^+KRf3K2wo9|T;uWd{xHmjBiNy=|vjQWi7gN@N8DBr~x^%>>ASqGNUFD|4H zE-PIY-f>@+ZejP9sY2g6!Q9+4fk=~@R4uv=VBW(-m{`^%zT?b z>wji#{NniGRhSgY!y;rk+RlepvXK|L{KAIWuKcA8znx;zFKl-uO+8Mwc7kj}cvads z@*!L52>Sg$m*FQhr0ie~{aTFX+&d>z6w*;#(qTG*KBGGw+QGh+u5_c6oiOBD|H!$w zFF%3ao6hZI&T_MHpzbAJ^w&<-uxymUynf~5yXZ>;)!M~2RoyRK1jQ~IU!^y?iSMGJ zv8uMf!dvpOg{GYcIqha6?Z>P(WyLR;^Pu&+S#YGyN|ivJIosw6STolyUSWoCwJS7# zX3)76^l>-#9qh267~PG`C`&CMZrCx+FWD=o&xv01UcN;48 zMGedVZersT2%p<{7JQYtX|}|%ghb&SrZv75Tj<= zoa69i)N3C$xOTFj81>I)lm-?MZ=#YjX23Gqg4ABt78KhOt@v;$-QI_xdu}Ox+{Zkv zcP`avc!kSR#C|mDpEs!GeikluTS{sBVZoYtgVye6JstcajEg7V^QyAhb{WMVU^OHw zqHzaU<&4XVH2<;Z9W8W5*$0s2umO`A_*+w~*z=Ar5K83Ph{Zm3n3ZrEq4_9*F^Dzq zQ`eW+r~agw4ub`YHwrz-Jo-K@#LicQcLJ zZ4vq9vVqbGqA9sp=y@!nUAY(+PZ!elT#T&C3q`*C01Iw}uq~1CJ_|@lZpIwfFQiI& zth1E3kS6A_@1$R#nmvq_SKkFR^e{eAzkqTMgJwb&&`*b9kz)(!*kRUP>M@ss@>y(# z2gF+RRvRva8MCxDMwzA}WAwv0Dkh(bj8RvOQKqTL7@d!3)3ph|wTgOzl@s>P98;q7 zYLE9h)~qsTqk;O~bT=PcXkT8Y`bS_Z%AQI|M_7cUpGP@Ic%|pjPe+)qzwJD=S)Ai? zVui6Wxb_|m*~M!rpMv&)sC@b z*O~BV=PbPoB$(CR!P4KorFF+x9PU6?j$s)cI)Ex3XV;~={dchwSb|Hx)~6Py*bJ+B z4RrL|DYgmjuagT{t&qDlFsclGe>q_bXFu%bG~oVO+)J0^b`ncJGpq%gd7MZp3RKh268LE{F*OmD4XQ+>2 z;;o+G>^1@5w?xJ5a6{|mTJh*BlMoG!b5EXHze^iGUEM~f+|1(m7z<53bvx79C*`cq zZ5tkgGgg&+4$N_S{|hq0PJ>^vsQVdE;n`l4c?QO(rn~?{Q&a-u8aDw#qEzZnu+=oh z{?)Fcnk_}{tvoZ4a}|D1H^0wv@JFu5C{P+@^68$(^cMvbC{@%Laf@bw;%|o6Gp2Av z4AASS=$^`%Z1Gk6PONx-6oVfC%I<8cdlvhM+^f^{v+zIuiawrY$&xRQ%P+)G`ZAv8 z7qT|e-l}xBkhS(|(H!bh*EmCr8wM(Drr-=`lpToV9MhfpoP*1sM^&17j&&@z221W@ z*QUVLZ__HSJf)42PEXH4DVJ1*V$ZYGjK3=L{*JyU`)EGtvKwo3v#|#Y-`kw=!!u&g zvN-c-dYxl{qeFC)e&s?y{ZTHuNvH5sKSDR@Fpq&~5`kug^KiXHq>E3PWAK&GXj8m! zL)ryH0q>r{^?Ak$zwZnjpmiYkT+e8Z?r?m9YmIf2AONC_lW75QIeOKQ?$i~<^1A0f zwb3BAB{lI0mE)t%VEZpWAHPu91(i9JHXb}v99<&Z(SB|S?LdLD5y&`an8o8hNkd+C z!)@pbw;d=07w_Vn3mh_xdJc{^pvr=^D(T(OJ^XU!Z`6lCWw3ZCRFcInZw`!Z=x<^4 z%EU2C`)v6>=ZmNyxQybb)^Q52<21q6p#o5*R^shzGtJhA8ee3-^}C`B5Pt-=ME4TO zUmu5KAJ#Hg2J&V^vtuW58kcw@@Gykadfsg-kGo}W z;hsF@;DrxpX7p}u8g96A`h+{$l(7$NpayD=+bNIq(f8K(()Z|{go|iDDtX^f&r8r@ z1&^j>mzZC*Ux3ZKI5C}fi?}f_1(~einRFe4I4fmu6;a$7<;p0!cZr3#ZXb;?3TB#M z_*H1Al@Vje?=owo8v)(7Qe_sm)!|ZwPB@K`1xC#K8ehmwH~b5mV$C@T1U>=ppIWkP z*!wg1v1dw^M2=u{UGky5msyS8KT1Au9mqu*XtQjTAfyAAj8M9D5)bv1w(3KS(p)^? zKs5df%1J63kYjA;m=2wdlKfNU$ta%i3YdbVgmj`7zp?OcEqGjx`=_7OHZY78uP@YB zw1zT9jk%}BV4I0DP>s1_ig}`RQe)1VQaw>($5O#>Oz##bvTuoN3_8H#8>3ZpRdp12 zg;gy3%?gyrxwC$^#u{YVZzLsMVU?t*ooVV7);^=38<)Cpwy$*J5!2u#mLKpV9BNSA zkw{!L1e$d`U**qz)aPorVydX4`uvPP$E(jfasO3OL-o1EYCK1%&nx+J2%e$O%5iGj z0rQ#Rr41+WO5U08z&dRM*lx8*;&rss-YgHQ#;J$NmL*eqX56Mu)P%Lmsx6>S4l z{T`(GT_E5Km9J8<5k0agW(Ma(bC`*8FgL#holy%4y2L^qP z;*T+mN^+EC9HqXt+P`o%q^Ko${5$#96zX-Ad4<*yC?cC=p3NQC`%ndN#+yDvR*lKpWU=*a(pUhh!Z6s=58~GIX{H(m2{Y5!;fX8uo zw9Z9F=Qwg!rq1=76Dj5zt5DV*xtogOjePWL8gmV^@1#(WMb?oR5LNG_p7|yecVA>D z2u_*!^}o8~P(M-ZcPQ487n_5JYbc<2(wv`*ndT5e0m5$xeB91rc;oM=k zm_6D>o5l?BZrN`f#=FOVIt+0rFd^z(`n`CAZwNRD%g?T-)lCK))6|c*)=i#_2P|U} z4Hx0HlmI5A&u(a+p-tW|0SGmJP*ae#Q_(q6Hfc*J+$5>oMqHq|5?x3&kZ;MUQ+gzUqCO`}?d zr%y6h@bu|0(+3M3xDx4%@5BUPI=S)$z9YP-dgVhV&_8IuLpGdv^4KM0K zYAxvB;pnmE2J<7Qo6Jc{enh@ES+LzD&?fGhZWc=MH(6b~Mk1M??hQ@7$*Q}hU;|aW z!3ypN{A)F7I%U#cI(3sZ@^J%8F;76pz4!!_I*iXb%lc68Empfloouo35CTl8TL$uD zc4`%`{{zDiSt+=qlgBK~(m}Uuuz_(Rt+~Y_ed55N%mu#kv=ms-o1XIm2Tc6`1t$C- z7z#WKh7C^LJO>4~zlj3<)B^2O!OHmT`reMV-)6O?@3N?ThR$=*9p-6gZG_FF@^@H* z6eK_a^lqcppMJcRApQO)Yn~C)N#9Z586z+-&TuEu@U+%LrKlg4Go5U> zJh0MTo%+8-_aqpcm0>*ui=Kpo@o<86dPvte!v}r+Vd1)2H4($*;`n$(w>5m=a&L?n zdm|&V(<5CZ-DEh%Y2xblk95;bh7XFyU>#|=o|yewN*itH7>UKUv$C}*qB}-1Lt><( z?$DK}^W$06)pVDr--~Udeox19hBZ#Pk!t3G8gQ&+T%;$0uRiKrnswBP)c*AGE_|Gk zYjG{?3QTh`WjntauXV9!_G_y&FH__&2rqCaog5d*QmqX=B7H@6iIKihc_{TtiBhka zO2u)n*4U)!%5N3UK92D{AzU}}AIRCoR=QoqoDyTOisEfxKpQ9z$8#eQ8cDb7C>L_L zMAwtMIHY3c1x-Ah2AX&c5mCtpW+|l8^zJWKJ|Hl;1W{geRr}&6v>hJ_>$+3aJ!pR_ zHl+dgSg&?P>AW~@fyPn{zY%JMP_Xc;7`#jr`sY*>`sjBQx(E0I1rnP;GIJ+9)VffV zKyH7tKiVhuDN%<{WyHX!z{|e~^8)(8$B^W!&^UD5Z&*57G%+u@%MMm@OGUAZrl8n0 zS5WMbanwX%H3CldHs^a*Nf-I*CIxUR0wE-JrFjaDS(>e<#|rD>wWtXOpZ)RTaNdO# z^oEZ9@Qij=zKW;bMXYWWkFh-2kdXKo-A;53*E96)#anu%n3 zJ?hEFlB(W@(W6aI{;htw4>{+(mg)D@`Qpe+xWSD4#P{&iQBKSr8rrfzWWh=x{PU9`bsQOO-ij~=kf1A~#xb}b6| z$&Vv*@59tKSVeMCPMH$JCFSzy{1Unx+_5FpIZGOHbxy1&w?W4w@?(p0+z%|^-##;B z8c!lrDu4E{g{@;GWjm7D_ z@bAe_EA>6@9YkqPr!&#gzg<8}uT3MzN0@TocH@ZA+4rgCBj(?fGWIioN29;)(*r=!_1$Pn#bxpQPtSYE~`P ztZGB>HCDJ#?Sf~2psrjsau>NKOt;07Jt6xTQ(E*!A7&r5!#dSe_)qcuJ}UFDu8xP& zW^h9adCXc$LwnJP$1JYm@hISb%8!q_nf{n7Rd?Y%0Y?GCnGoybo>(XM>IsSF+&6UN zF$-%_4~z-jcvd;&&GUQByRl-tA)a^2oGi4@aZ%wkJD@DbK;YNNL$`6Bp%k?27vE?o z>l?|N`aHpA)(c%qbkk%z(M{03IVj!Qif(GhT@R44KhL<6+7cl`rWsvNgF`w1ReBk7 z{s-#`%jiHJX?z%>$m^v5@FScnhRwb4WxU~{T8Q4<4~&xIrf5SGvU?G<#fxSq2KygFdR=vq(N^Hs^V&v8${9hfNX@K}^~<}~WM z7zm~o&VFMvN++fQC%eg<$gT5mRv%xnP=gn&j8uLywR(ZwjKe0;@E1@)&+9-NU$E?e z4>?$XaZjHi86x+bG01&!fei$W*GivZ)cPf>k$9lJAkQ;O95hp$HbGADT+MrB1`<41>pS40JevQHgA?}PxT759D58R5 zL6KrZ6a?fDRP5MWG{zD&LZY#Nf>Cl}*EMPqHBF;N6BDtEQ2`~2vBjt{b{A2j#@O}# z-`VFt^1koy&*yVIyF0V9eRpPdcDD~N`v+{^-f{fFKTbi;tJKvkEpK(>-(Pd`(=D7u zC6G*CNH5;^u~U5Zx^6XUt(U#5wHT_khMi=sHAAgoW$2GyL>V+#GCaklv2WVi(%(lM zui;1L2U}!`&wYRrUps>O{0{J{`lNn`o>xhW8UDEM6FMT)fyX|a2dOI$3?!2o)T=`KyD296+rgAT!g%W1c%Ti@5qg>Wa0LR*?AecW4B0 z9XXAUbJH;c4NsMB{~2)ifm^(Hmal&96zJuKqqxvH>9p4nW0~VCD_#-U*Pfqv4%5_} za31)=$uBz`^;Wwxd5OY8Ph*UwLw4{dOae{;BY%mO*2WoPajXX)2I7~iGpFd13qyiR- zXt^O!Dt-cl+Pc^KkPJDCZNT-dfxXlX!822RXr6dVj^z9mE)ns&U{WEEAf1j|Om*-H)kuE)l~a1}ORpbO#bnV8b~0B^0=w~YlqmjL zqpHwgMl$22rKeO~1;(EV4y_FKtVjtZ9(Gsimw1Fd5=HkpP{i}DJoB~Fd(FquS3o21 zt5m+$>g46ph`7GvdPBIl(3l^zI(2MVdCr74QP5Ry!;zHt7%JEU=!h5Li?^Vj?q*_Z z=a?AVcv%EXwa=iy2Xbo#KnGd$(ni0hHjw1U`AC%S_hbeG>Dh232+fEioOXsofQ!=&`GaRX01} z2%AAPM%YLU<~Z7knWZlTn}1B)1b1BVo|H_Ei`J5GxoD0rZD%>e;{p|G@|;quwPFGC zK$i)1P>DJck%mr|ugE;E49Sh=E>{&)-IMs!O&n}lop9OMZx z$@8yHuBEE{AZIG_P@r=kj|Y1hCauMYQt6&Em9D_lY$$ODO`2(QA}K91)Aqs5oi z7#}Mbaa9;At05Bc*8si?e z(UA8ERTv$sA*U6{WE8daI6lIW1+`7B27W4mmbvJ|RWVys19KGM!WzIjl5{YKADvDF8fqy-xTv}+@Rsr9t2A))aMKyq3$MW$`NT%Z$ zK99c5$M6mK#`=$`N^X!6>2i%oj@7_;1t@9&ACLCrc8r-!6{D+2I4W4QMxc%sjp5OZ zWg4!H$68Oi4avFQi03;Q%Tw>~z}st?Z~vZkXi&>Vaw7G9+PN(iub;Uhw9MT2c(Fr6 za)~<$z{`Cal+`h@AnpzZZ;$sW*;G%lE>5l=P4NzerV9ce!rs->qDg(9Z_~1YK6f5G zwj%zS1{fle2MZz#jqP=Ls55Kkdf1ADAe@KOx|6_1IJ5fdcaHG_XO?Dnil2985$c>) z+|`Bo+Rf&nE-XNw99<D1M1l z;9lkb8~$080?+tA;P)f>YZul;eey5fM90D-*R)4%&|+JFx+YT#xipA;3Rc985A^$B zfB}6|xVa$1PPC8a3v|pstWLD7th=~s(oSSb^isqS8&HY1W-u<)?@Oy~6_2C%IUO@6 zU2InkN>x@Mq$i4HsNAxSrX(A`ps9IC0O8VZIH`It$M(SVUMkpQKEjoyWMf`?NIJBR z_rPjcIvOJJq-BBuOilh&uz{0;%)`?Yu?c~Wk_yh}NTw_9;Eg;9;lW-+zLY&e?54dI zG}bj8eS7aJ}%n83x4uc zDSx47fy2HiC7G^Fyl6x1l9>tR7d;CYPBG}!1-UZZg9seI!yud5wm6hY{H#RO6!B{d z$74+{p*92&zZz@uskp+a2G-B6b{|aJLcK+!syrrjJ2+h%iJqeyOyRe`&?^6r73JrvD9>@3S$D`a_qK({3mh zw`t+ltls+VUF<|5SWjdq#az(Et|aL)cu1AVZOQ#SSW?&k1%?X}C5%`!5!$krDnIFZ zW$&DJqx7@)AxM&G-jo-3FyBC8imB5tmNfzTH(DTj1zqgH)}L>|4|!m;)^Ew5dazKB zP2SWKOOg4kHqZ)%i&SqO>B-(=NrL)bK+{8fjVJT#>2?S#@E$KhPW2Jnq@zr1l;40y z2T9htkX4R~$`}sBztISAuO{~`a$9uwB@T{=i&~qp=9g$L9OQZ<^I^tF+0q{!$gPCGDcD8&VHj;S9wM ziQTq8Mb#r_N1)~w?x6?)4}O*z&h*mPj-wI<2}gRH+?MP;u>rb#;cy-Qth?}U7dj*M z3Z;_QW}_+J6XIGg)=}3srbcpn<~F>%Fwu*(*IoQqI4qMr`LABg)8)yH$JU)-S8?9@ zE`Q*K>FO^hUfY{>RDW=TzwM2gwRSFF;LYOHf861}db41)w}jW>K0d62T|3_2hnYP0 zV>#JRQW@;4oQdfd(JnmShkZ!XYUXWyFe1isptR~MJVq1YWxWo}i@%m6Gnt^-;4>6;?N9waN1f|p<2cTJ>bSlwO zP8LwBZdzSQTY-#S(kJ~XUZ(ILd|AA6|LA56ASZRejB;U&%IBb8ohfqE)ImQ(9HLmn77xcYt*MC5O7u8-0=?LkeS~$ zu|V%AB_au6GUAs&5DUzBZ-JS-?3IWFq(2#Pu$g!DW3AP}X8y4s3sJvH=HL4noJ&81xkhV)C2x?UGSOBU{Rvyfaz1klmK#4e`ZdyUOrVIh%CMpUf>PGxm3@{bX z2;-1~af#2|YhRo1_h*KVy2~`GVaQov+&Rg&OOrN#vABRWLU;C_lKqKQcN0l?JB z!$k^u33PBasj6HYX~vBKtgUk@VNlGIk$gY^OXwK;XEpKSVMN@gn)rK>|04bkzzXpx zsKc7XpEcz-0$7a4yz^EoJt1NnbH7wLcjS?Qte)5Vi>P|_d3Xv*6?ud#4C93Q1|J*9 z!n1>}Yv>-@te~B$9JFyApz8aa%-?+n`KY#E8`A{l1-ps)!u_~di!0FsXj9e}>CQr1 zB*L&A4K5Qc5Xo8`Z)v+78wc}fa?hlL5)ccq`-n=C3F^g=rOXxCk3$v>cu*~I*2v*vd&lP`O)1_Vz~ zYW?COzOD{yTKkQLeOP_!Vr8OJKdA^j7?00E{`n}4Uw8ySyBv^Zg5SV~CDatK4>X!6 zjRM^lX_y7R`wTgzeo&Da&yUt+b?of;ox037*gG8Ya(5RYx+>FvX(#feJWW_8USYB# ziqWrl!+I=)%>ZSr6Up0opL(oayyJG_CQ_ZmyKZx46vrqL zuQ(=)R!;nEJygBkiCgQjfROvxG(gj>KsLm6=`Ir&<(ImL%=xSKJU*Dc(+#=~SozSA z$5UeYJ?Lkk9mHklxUSoH0b@eULKwIqec?Ib2wWU8sPv=`HUSS*l5YRFxDSyZ?MtRY zXGM>D{6#REZWqd@gs{fkX}_;NK3rdTKE?7tU-%4K$MO_#9=H5o(_EYh1zD*$+5oaO zs#vpgC}eKS@igo!k>GBdm>QqZ@S&d?z4(WnoLpkSgKn#f)`IpKTZQ`V=Y(fF`r5WY zs#aKhEymv4Oi(w>J~_h+t9`F++^r#tNs2?2?AbtN0{;b0Rj(W(WfcCU5>DJLAUe@g zgKEs5iaTqjf+0=C9vy|Y)70XN8bWt8p|^?u*^sqjhXcGjHFB z?NzUd;IA98x5CwfX?`vhCt;6?VmCtNIwFV|@BK=UH-bEEL7Rg4;>Ix4@x@ueqAR&i z_4+yI(UQP8dJyy33K%wq#`3$3S(tX1iVk;`i+-UzxCv{Zo$?PU9Lhz*P~NKv%S|e6 z%T(p~oyG4D{8;Rp-<_B@ZVIpRKL_4*{3`L2^~r}W0teANj2RPZosa{93J^0u4v0gE z7!c*lG0UukLOi1AKNky2kHnbg)386Mi$DbN)pDL6#v0;*ii!PL06!7N0wV`udkv$E zUOijVUlR2vq78`X!&aC)F6axTN?JMZd=Mmgou#a@g*VNtt<9R zE#ZvSF5RfGl4O_AItG@SmR0GPvWXqOFH&3ZZQ(4+Kg)(>Xl?%=7%!r^eRI~;1Zmk! zV*P+BSr`Yk^=^)0adhF><}BaNxp0rIGp*K|16sMIIsKKq?+!EnfxnohS98k*a*3& zl0{9pvWLuOJtE$eh(E*fP}PJm)wmtbJzKEe+J}c}Iyxsl4(FLISY+T=#j>PC;(T{W zVt5QlyjuVgt;6}@7Oal;eOnyYaDKl9Gy4Tg|5LH28MU-Ei%tsbtNhf43Ej38eIF)4;iO znZuzJc`QY4*_4;GVoi|FBcR%a@$l9x0iVp)?2DM_gVjYF-Bm{XyCovN&PT)}V3TCg zXm8M2G{O!iEj;e}!VGt@sR{4i1_DeIzN`(ao4gGBCAKO$+C|doL39QYorYC(s4I|i z#`3utg9>9xCys5zw$Qo!ITRpNP5A3JtYOQLH^llW#ICgfv3qktY-i(t)whpu!d?kg z^_s?fPz*~_@BEp66~p?*cR@IEL_IaPv&@kT5%DG>R~tzpZ#p`RJe&SZyNFd1zu4c1 zw{OeB?Hch3ZCN5dKec6bW3q~>i}`JuBpMkFqV48@C{u{$(&bdBuF4>(hxLaf>K`cDue8}JqFS+fDN-$dJ$B6E~L(YjDH-~Ws@MASl1 z)ljIxYrvUk(Il-Vej{mi5iuObgw?!W9BXC&puLF?ieuh(_4)g8EW~g9D#%V*E+QYh zXV{lo3GYr7aUY}J7)owjAfg`WH#V!IFVs9?pCA6Y0_ey4U zB8=Oshfb#svbUUSgx+##8hXoy+LHYNe*c5|?W@kwy1uM7ed7Ll&9s-Q&>dg1TDHZZeffApcMcRAP!tJ zh}INLTa7fW43{0SCp_Sd+iUsYPRzgI+Uv*xfZ;G#i_dRq9*);EjhEXI16?cMf3Boy zbrk0r|FRRSr`BBOM>?@|^}%c0FO`|pZ|~tPQ`v|{TNk2}@4osB`P8i@_veYVR8XDC zQMH5uJ_FFInYWM^r?Lp+M5;j~iNE!*5|L=L%H0G1N3>FKJkA^_ngL3Euss=kF1)3QxOsbMxl7(d+VgwW`a}(mN zy)rPtCsIYoGg}Vg##TzLOavfRVMaTXS#3JODIr{hfFo(vTs$JH5{)F3I6w-t9Jlrg zGCQN{!19%fckOXqSsL?bk^$=?($-Tp(t?Amz06Rz;rwhOwp)TQS;1_yR9aJrL05QC zXXYK71UVZqGJrIs3IXZCenJ6^0${?w03Hfpa_-bbp4pj2XD|5;`@#>%02xK8g^Gq^ zsD9*;)~SgzYU4&qeeFEZqp~GHQQuu_Jy4uzcxe}tnmFwa#Fs2mxzf60w!q>6TM8)8 zT6Fcf3FuBep#}s|H&}>*s7}A#7BJ)#rKV{(A1#<f?X%@UF~DUH?yR?#g=NR=H2R zLY$v84|6s$^)oN)iit1bJ6T|NaUP~W*tTa7d`rbZZb(ND{h^RINoPKOPfxzY{#LQ3 z!h&WLw>Qfujv%5ht}_oWMV-#h=Lfp85gvwoWHrkq-o4;Vb?+t)-{h@(u)2DB zq6g1|X?~qcYgZ&6-Gen|-WRARYu3!=pY>ot0qg_p4gM29wzq4wpw^0@^kMF$;A5 zAT3JBCJ2l$xpyn>FUh?{aSL*Pp}3obnN%r)E1n7P2#ezWk=)se`zg66!7Tz0TCK&J zg>#U-V$EFo)L1U+xbwX|S^dWOkMVF(l`g66dbxJg#%wkb`9!v!`(y3Uj7LdMxN+BB zY>;|_nZMf$>UOgmFYC=h`0idTv~m7FHK}~_hDxMD#gC}GOH>TpwKu~JaLK$|Z`MZL zEtwbeW^L6T2BOv(oyWHiW=hy0kLd$le*A5|xew&Emb|zR(%!L!*Uvytzk8H-%V3Mu z&%Wa~GO!kh9_1(cvPL{70}XTl>hW`r&*A?Av*o$jQjz3$GJfXI4%j=$`7lm-S2Qy; z(Q+yY-6Jrb4s?0S|Jr!ESk!f!x>CE%zOq)tg-Z1{JFHwW9VSd4X|{BjoCX`Et!Qa% zL;W4!CaPAZS@cq-4NV-j)UXwlJUQNNZd5I-DM9A^Ep%K-Jlf2^>&v`c<_-vsikq7m z94#V_P;P^l_hY_I>cOV2y86$qlNCpr3+HCC;+A@&;y!-|6*t;N#e*(68+pHe%&3la zA>BlVT|IuZA1pEsY~pwOp>gfkgyLn zhSgQ$iKIZM&i(3ncWRan#GV9DhwJ}=>a4Pl9mD=KQ#)9O{#gXGr+vYz@G zP){Rh(g@e^K|@(1wL@F}@le)OeL9Bk8p=ZKHuK9vSzP0nq6VEUQ0dvkuj}=d`qoo@ z52gBc;HksFjfObzcZNaJpIb9x3ne0TwlPY?N3Muy9fF8QA%aE}DYFIE9-H~0Y&OV6 zx>VqcvxK$TG!H);dy(ZZgHnR@HrI4KPGw0zC%bgYFf8VXK{PwyZS--kaKSk-T;yHgg%a%oO%627W@O$drqO$^8Av+<72oEaXum^3cYjwixcD|Kok=Nrg38tI3STpdEi%N&&?0HxTqZuf%;Vo-e*IMM z5ubBGpSOc%McCWY>K18*R^{drs#|^D90b673r_<;-h$msQ6>}z26N2O%<#LgYp&i?%1@4FP2Ar-Y_&@9j6^u> z4eh(c4P%&3r%c!m(n1E2^_;i`B?S}#?c`M^$YXsP(v(u5z^Z`007G+Ja#CRQqCjQ~ z#QiAcqDditZwzaejaaUhcv$f`;$Yzi_FL@^M#y6xHbGe0ddJJtv1!?1m%p0-2@vo#aN2=U8fB~zga{<1)ew(h+g6HGc8YK*JLxfqFZ3h!^1Lx6!TYh z(DJd&GX>ZCs_ZNC!_p}xO<%ZFrY+n!NMebOl;r$hff~AF+eo~GyAxu9N(?(7%b3|H zo=li5I_-E9A2^m}_!naTR@qhhL*+(O$t8U7x`3VdV-NpzELQpQhuk_AqQJGkx!*Xf z%-=kOM24kra1n1mj)k&ii(vYuvyL9x1EAh4H zb^?yWS-B-nIHOzsW)B#dS`LsnLf9pmkKm@i5=|Z`-vVW?hYL}e7bg401Y`g>9ipHn z8L*&tSxDPLz(j`*wB_oM*%Za-;)h1Og2j(|swbTaL`#;6{g)AvuQ@jsnWW)59!cm1{K6yO*M7z-OUStmi~1mX z_n&p$RK=9`F|)NqtOWwPzCURyLPb3&7^%N+q-aolgjOt7BDJv5eNREhLxbRx2=mHS zjkLxNuN(*39yYX88(NQQyj?cDh{}$@yYHi9Gg!gHmPENQ&wP#G=)Bt*-MV z7MNjIj5i@@w|V`y?kXr%#G2`dn7ca%wS?=hsTh|q6-kuCHk9cK3N@MyWp@?IE*nZe zesB`lXtjmEoW$BVcYJJ+$HH{~e8b~2nFs5lsj~Wkd6WmgKZ!Zpeaxq20=M`d8*bJ& z{J_6)=`u$*2tQ!1w%^xpm)zB}e6Go2%?%x^q6K_|>pXXKCPN{dV9dfCoSV<5X0g`o zOCQ-NmwZjzwEwcIsc77}Dob+eqe)FUajf4CLF;$noX`KxVx1a}uZ}BKlUvhZNzpT& zF6_xj!{Ov`dHd~Uv0^SC`98~1$83l3piGIH2a-c&8941FB9H+?<1;;gVG=}3LIdIc=z%z2dZY0172|<`B2=FEc z&i@6}r|e)|>xj+ek-6DTU{agxq@T@I{7E)D8tC^GEFp0^tS~uB@0RRI2Oru)4Tez< zVSf|BWa- z+##2R*3~XzDi8ep@e9GPDSj>Si^DGkzwV28mt5xU=jep8lH$3dpgj>R6?7*y3jf(L zo|DVM)oD}t54o@(v-_6c&1F5@o6K^B`Cuh&62?0skDJ<2Zw=%V@~|kq_aUE`$IJ~+ z)KaQaw*`*>?5)o2-t<;!IEP`eA9tE!WbD6h9)4c@K81(OW}oVxYiv{wz#*FOZh0)+ zc{`y1Sv;J~T|PouIaOHA;P}t9ENyF~MZ@=s4rq_M5WPd zz{ssg8U9qJ|3Do5fJei|~+vTV#M`K@qjQ41e(@A#afZmIbBN;n$RK z8DLpJDq{t|>`Q)XE;KdyUvgtUtKD%F;YodE{+4ruWm#~!8aY)VA_FW7o>qrPD&aB! zlWFjm{6o;v4$qR~`*b%<>iMjNww~f&3jeiymY{C&1rPn0#rZs1M|sBU>KGy8Evf!e zkQA5J@tlvrjvrdbSANW%W+a+(55T_K7=fNRH`z(71aE|O!7<;l;t_IEWdm)j3wTOF z7Y8v#L2xc{B>h-Lc}*l;6;jUw{I-ReoS&kP%2>?~aQ!@H>UymzK&y~(DseP`Lgn!4 zgnq5U5JfU4z<}{79)79D*k6TFT*N2OWBZ^UYgxdy+JD;F#BUd{Z|ZNvc|)-2v%kfp z04pxKY$Yg3UkHIf7w3S(WctE0B6$ZdoDX~0=0*Gu`u6{f+b_WCcBqKAS-?J3_u~Bb z1?-tyn-Rp5%)xNSC$`B5RPsU=m3(+9@$BU^5y7&;(Tog&Z73DvR#QWlixK!%YSS#! zpHw=SEm^=lF1krrXT31PLF;wgYCdQYTWG&L1)Hvm*i8RMP=AoQlBlCN;)IWMKwe+P z=Pza*98W*Ptz~={|7|gQU?_Qo_t(#uvD>0AJTB^&@^edA`?_aJ=ujuDY0;`Pe+PS7 zpnDIWv;vnTIZ0+M;!}-x239X963$DCqx<;vrL5Tge3FT8 zUdGyH*Xx3nvS}MBeY%4|os*<+gVM6O)j@IX@N)>1Q`{kL73c;%mKRaCs_5(lIf~4% zflb$~^}-hix;}aZIJli4;Esly9%r)}=bkd4Bicw@>x^X=%KZv0kvNiVHI6EBd&H?^{wd!cERYg7@Lfoge%JbN-gU`JVv0_x#+(YQ^L! z+}Pi|(Mq<*f4N;PvNxx_N>pIn;DbnDiA-SAL#|%MLhbv-nRwVL)-UW8HhF3Kf-HfY zP(|KC2>s>6o+B3~$caVIp*=r}o$()6u~se%kE0dj`cO(FS|0aJchsXPrIj78twTqe34SAwQv$VZI5&I0av8vmD%F;q5xJJy{6^q64!sdg6b#OosD|y+l7>@Hio80b-8^Vh;s##RO_GX3n2z7Q119P20bsJM3QI2n-S_ ziYrvaDUNW_QaZ{+vwS}OOV%f4kQc6AlZ{N%Rz@L>+pON`mahPzpd=+I0YRfHsnNhHS6N!ttTpRPP`z~!N=)|WPyzBDGy(hejB#Y=7L@-t8p9j=x zqlDc}{LXsT)c#~QS01o|`Gi{2{)IbP!F?cryUAChs_+M8ePL2Kx7)ycd%xe!6>6JQ zr?i5kaC76!Sn&(6;^Tg8t8vx83Hd98_7b6VB2} zzieQ=)RtUc?^|}>AAC{~juzgw%PKVwPsYswGqP!Mv_B%2&Emcr*$j_FH2^~Zc-sbW zn8m-{2t)0@1-7XZHz8~hyLIaBRy6=kXd``W-e`CFS< zST@8=*f(be`;Y_~XPae`B94F=c&aaanAj?{TV^NxA4NyjG_U+=av|kLf$sagko1~( zQD>o(Ip9l&prc`Jpjn1CqSHr$F8)mm?ruGSNK@q<5UE4(9$@j``kO@$^@B7K^KQ~Z z3U2Wk2ra1!{lFGDBq{Gm)=;G0J2O~sh|eIZL43<*W@^npxfo(v;&-HFLb`2LEz1 z3&{?Ui{kd{O2*QuR^*|j!4svxkk)`C{D=# zAovalR?lD+cwr2_km>-MA#-BSG@%L1P3&{W=smKQR^6Ym+1}(kmgo56HB^!JXT0z` z7OLJnonQHmMY|28!gDot~7`oE{HK0|WHy%RV5`U^AwjbUHFu*4$c zrrh13&%45lwlZ(+<|@=8eq}3bm_2L@ag6tIq8YW3kBGE!y-*gTR}NT0gpACeo`b=g zXnA5aP6hji5eltE=N#esE%DSzIjE)GyFsQvw+WwWR(Z<@q&L1_gGfOy5ISx(hE-E( z12Ux>s>x(2WJcB`^A5;BK`BcQ*#af+Y$+C}GWieR3Q9$d%@A*5a` zWUbVt*SOaX*w@CIc9mfQ?_go-oX_xn3`@4V#XIg~ zUDPX9@#QsHvVJd7($#BZPR2D@OHnaGoO zvDS8*_{?2wa!BM#YF>#}SVlXWgc^vzoOY^AU0VM8aYA*42kvI6*}G3;etGRdteHN~ z730FHxnJ7^Dc}bFtMs#9U|fpNz9f!KKldIyG%2TJP^?5m+V_bYS)$niTsu2avIgub z_zQyI(EASZ(x}H6{FY+U9J7`j1-hk_Y@g3H*}y!JhMlSm5@Uk^nF@&YH<)AL*pdv^ zyaVbOjNhID0QR1`zT`(I>sPEvpoFm_+J%BFU~Y_u&iJaV>A3lRimROD$5KL84Rst{ z5U_yUkdR^93`}!N5`W^VvEL@_lM-9b?qp1xd&o>&UruaFAWhRQIkEA9CjQwT)*%rA z#SW#_9O*AP&#W+7-;OIzT;d?}8Wgx)HPZ<5<8BCp_yg7f_fQ&RKq+`Hwmt()czK4k z^bNpvZ9Aa-0f(iS(85Vt1$f0?7G^S>MxN0C;l-L2z_80|3bwC66AAdAds%4qu~T62 zupDPjLacL=4S?n62CDPc(I?>7&t6R)%S_@F<62ES_5LvBo+=>n zLhFEmNJqOLTTqgk3-$qVLm`Q?*k&upc8UoI1z_4G+G-0zDcmI*rH9UA5KG3P#3h=i zejrR#Ex5n|)}NZcsse!3nmU!mNI1|Q0OclJ2p}Aplo??s1FL)_M<0NP{=^}4|6nzt@u-CH~u^9&EN z*x|$#-8a=^EVU2L9(Gb31`#hEwin2v$bZ(Sc@g$+ zz&>kk9ov|E`9^Ojs76cm-iSjV8YFFiTYLUBVw6hE45yY~feX(XDvpy-yhA zl#3-4NK$b84lVwZl}@>sv4n>gV_$vh89uz2)%AO_5Od|!)~d{Y53z6D(PytJ$7-b) z#d`n3*Az1!kIeb-6DSD!2m&=e z2b_aD(QuV=c+M0a8&X%&q*_Few zU#=NQF)g|-6tmR4!i>u$&G`-wthz)3{MZpJ$@Q)L{t*@!R9xbV`%nSc2S?^x(%2kb@HYdn=f-X*;Z2V+Kf~_Vz8Kn> z_Qm#8zGJU>-=l13N8pgk055gX6$TYhgj}8hsj)chHTt7Ik0xl0`^?s&wOqz^KdhE~ zcOtHi=>=+ot8ti3w=QyyOi#o@+J_@pux<}(fRwdG(%A8BP$F2Z1dgY#b_ zKjAydz(+mA3&>^clsc@KANd7*hR#&zdkp8bGIZ2N13+4`ZoW{)iyvoT@y^%$L?A5B zScNnX>Ju6%n@coT;HEz@7CXZdL8x&i8|~#xF(jP_`}wEGSzz2m9i2nKyo-$q@#RdK ziX_2Lq@vxDVh|895fy<#LoS-%=^*58B>Gl;6Mu1>)z`n!5*4IwG5d?pX7KQGObuYj z#+S2z>>&e*K$*yp-#_VW-DNrL=fqxjMowk&$o7|D?&uF1pn=em2&XcbAN@@kCk@cb zY{|czLJTnovXH32eM91O6?iJZ)smaCNQqm)r0a~%>>>iOxeXa2Nob}&x5{^W9S&pq zOtw0x=4yt5B!G?rugj?9j^21@6OTIqwiCSL`}F^6mXA zwt~T1E+;>}#kTL`U%_O;AASNky9N&-|Wq<|xtwV+#<-X1{+GFy%N;LD9s zWnpX)rCW3OoKq~udCqfKm*?ACjeY0wW2cy@PF4}Ih~U%nCm~i##KI14Rs$?_V*n9f z&*M&~*?>kxOOO^FWB?Gi?dZY@7&(ua$1<@S<|q+Gm4k3_G-Ds1f0{M)KC@Wj52?a8 z68>ciKYkj0ycSr3Gb}(?3vC#`6S|ey{s@XX!-5(i2-Le1WIAS4sHl5mDUX0Zeup5j z7*;6+-1-BbaRy^O>uLsYMi!+uRP2A`fwai!pOSpK;xt+v!@ujO$L;65ihCXi% zx;RSnHhfUv0>gqWQ}C*qB>cA%v=XW*(D4Ieu@BLRjkS9>GKN13vU8zNFHYXnwc(;XG?^ z;>Uhtu^ndtG;*QX2sE@sb4r;GI7pKhtFZ}ErtO*;=n@FE8a)tTbE@F1ET)A!a63;w z$AY76{gFIF6tA9T&qq-OX?Q&W5R@cJof>8J;TK&DWi0O|$KgPr1-$HYDzCU=E4;xb4g6 zOg$gZ)1hNk>m#h4sp8M!^*QX6HIh*~*H*T+Xb#1>ES+@)8nMqLi3bI!quhMy>%_y2fPX)Ba%o zEhqw&4#k2rci(J(Lb!#xsw~IEF4^lri`0gY3C7amNGym*pTm#;0VXcy2TVva9yp*| z>+|YRi#M0uV~PQlI%6ktN2^Wjbq8w9kKh+WmDTq7E2N59knkv6;$V+3)cduy9ilchx}rtO_wiK`f?(E3jB$GFn*!kHTfbuV%`GZxY@C1@FTe zc=xLC&JbR1>|wxES@j@!>Gr^BH8#b6NY={6@UtrHQeZ0=eOYu-k{l#d;(Snv5YC5E z5KiU)_-`@(DrKU85<+)-=}TgKdj)e1Fsu1HDf8=f#$CW3qG12}l4t!16RY#v_?XXSTWL48E?lZ`vL1*X^7x;&fYdag$w&cYM1o_Fig3JTmc-Eq2(Syv{W?)R>sE6R#H0pFV%tLbQZF zZDJzl*I-IB+sl>jy2cvV_lM&;Ihw=adYw&ose{2+aRS&PxsdbgU_yU-j~}@Xqm=uT zxa$pQ*vdEa1~+gv>FoHzj2q0=&gWfv5&8-^yubBLp5l=~3+}ip7vYomjGMTB>`@Yb zev`G!{s-MipQk42L6Z&-mVhX_Z!Hb?x4{cpV0bA>t_~??`y!NQ-X>pFXG>y{ljw&t zSQd@HjFWu=J;fJJg%=&1MAfd_@kj}PB`}Rxgnaj(A=$bw|1(Ip^1nhB{#VFH{}nRr zzd|A?#9|yHKga-S6atm7!Bt_sFt6yeRX&4gi48Ga>Vf@oH%-~!h@Y=X1Qfnw@Zob- z`TVJTgz|Zye4Z;G`$ya&SY1|I1Dnu!vz%V=?eGTPea=+(@%tOU$M`+N?hbf;`%I935HX(9q21p{eBPl#oKI&dU_u|v6A^T$o-av zUzxZtf-Hvgd3`axR#^)zTaQi?dBke`ZW`YTWOWoSeyU{t-tSL?dU!TLE$5&jrnf(j ziwAN1RVDg(*C1CObO-&GP2(f(u-blNs%_t)JtCkKO+H7Gv@>8G!9Tyl>W6mSU<){o zOb~<&n`b|uIjq3grV9A|2!8htOKbbZ`*JUOwgvDc%dy1#w}OK(eVtzKp(;oZB910Q zv>%K$XxSQ>UIBfuL|cs$-{)C(Sv~Kbk^Wg zfgeS=@ihSp6(Be$-Dx-hKBIuo0xW03N=4Or^BW}6{5`oC>;wv4zr+rs?gXW6k;Wo4phA5q%hkNNLv9Vd&HJx3vr zQK6J=Km4dyl}vk>0tBz7`vy*=y%>&r$K;6j*-}?ZB<{pz)X(!@qsNni+`wujaAe2Txt`02@6| z(b;!7pkIsm{kY*FYi4(s$30}-)gPbbOCPem*;AkY19Rhe%hDXDT3S_#{R!(;RLEXb zRAomvej!IJ92dwD1;=f2G=}3DIiOF~IH8Uzec|vXhXIcIQp7U zB>&T&*v41>1NA_cQ@rRO)}TJFUBHo(gb6sMfzJ@a5(hfiSd{e*6y9YB*F9!!>~3=N zV>Y$L4UB?JmtxIja#WO!eQvETouV8`v*m_}pxFuNfQ2zE) z7TqikJJ=9fQk^hun(5G^e9Zg90ah!8;$3#Tk?~KUrIe354B2Cde|SjhzmFhe_*Ars(Qn8k#1hRHKIGYm)*Q}9ezzdxUHbrLSAgI!r>bEk8rw zWO52An=Eb2FzyicKcm#pbq*ona1`d0bXZ~19j|*QQS)dLRxKN&4c6Li#*s77*Q71` zL|Z%C2T_4DeY`1JdFBD=rMCMuHfR zjY_c($7K}0>-rekC2rs&yTo-Ednp=)EO(I%Qc{^EZS0_(D(RXS97-b|RkabMN!%|< z3=TpF=^con+B1y$Q91gQ$ZrhIj|0)jeG&8lohh0_*^&1S$vlM)<{#ND`f3W8;j8~XP<*|H%QRnB|&S9{D!@@ zUiRtB4z`MM2dbqMd(+MDIjC@BL1t(?8LCjp^#m#xPIn!^Pujx#l(0v490;@-sz{{{ zCLvE$Vl)k|CK;d{50?)qe#K>8en!oUV|$gpz~?wely{T=sq`gka zDA)ljFghtE=}WQSLTq`#@zf1Z??zDmkW(HDB!cMy>2SHUt_Wemeh*Krr43Yjtm9*9X=AILR+U%EhS1`pw!Q&1&@-~hFg9^?ybh(kzv#pmG0doe5oHJ8@-n{-uk*t$Xo#<6m_BbG6%kzjWLrbbP;e=$9*eoNPTM`ZtAaW^ z50#JL(8cKNF+HAJE0SgPBnF2Afcd-gLX?L1AHrG(Yg~~0kMd=9!+0D)*)(41js^{o!Jdp#5rT`agbrv#H_p{1%I-Rjz-c+aZ@Z#rO4U^bCZEI+gAC}g@5 znNRsvH?6nJFk^oVE>6Ut zS$-1(_yc!s!c*sV~L%ttAueiLf?RVV}0<-8{7M z>Ne;3QV(rA?TQ9kI^B{tw*kNCq3xqS;=`jowdq=?P$m3n1HQmhYY8~n2hCofJB5!p z3yVMW=#+d%vD;gNQx|+yBI^DG~2a`qY>UCj^53mzHdknDO=>8N0nboI6= z{dofMG#KiKh77J4yn%XQxp=#lv&yXBbvbYnVNTrn-WgJS+=OM_lCPPQHLZ!&f)L-YQx$+ z>jIs++x$deeOX4yrOHBJ zhZutAu26hG-hN8zpdkE00W=27$S~}~6N?3!?IF^e0cT8*bPj=YNOS2N1?Nw=w-?0L zD8zniBz@}@-zPY!1K8GV#ha>lcPPGbN-m1Xm%okd)Wvz6K7(jiHpLejr=S*IQasAN z3=A=Nl^un>Phq0F^!Rv5Pm%(GI0Hy4@;Jo>!FsDqG$v2q-pwO=lP{2bDSdlMj~jWq z07MW6#S_t-JWo~vk{;e1Y;Kvj4G(>PK4PbIqMh~JAY!QEkfVENcsD=o|6}b^WpPAt9C!dnm1asc3a`5)qs}j%qDK)mmDuBGr<_8kB_C zYH4*9T_+8%rL?v--|wC|=b?Sy>-t~+>-$`uoSA#(H~V_eJ@?eALHB;eo2YtlVH=R= zd(fm`mv!X3Dt&$Up1N#S+aVZ>^-?T6TS-G4mYc^=^B@WFP#Nxv&!r&_z7`eoq4ijU zp?}^Cz?$2NDcBFedr)Wc3Kz4IVLWHWIuLIdkogRmYl;wl{y;tZScM6_APD<&}OvJZZtJ#K+6l&i1T)~36NC>%ZCSXVG3_AO7uioS}suy41fYmamzR&kIU=ik~@AI+- zET%K@Q?V;>CI(i1fxv_0&i#GxK~Zt5tqA@MSZ->@921Q5EIMGv_;Y+KAJCB1>9h$x z@qjM;y(#_StT8z}7VD*r2zQ@H9`P~1d@9+6=$dP7GIF0_lrUV1zY%`P*&Tw4f(s%lYa}4 z*|~*32xZ}l_+d{T9>!XjJ8t2rVTdM*e2(bJXNR#y=9}+w9>zj_I}kCjCqER%I-8yE z@&{oo(ziAdH}~L?jaXN6t9SXNM%Vxayvx@#V(onW$?>N_`#3)qc5b)c;1-K$|PkRw97PN6hD;2Xr(GO;!r&KhNHTD)U zVZZD0u(Cqc;9FZ@KhuSqnzEco)%3kT2Y-nYL!ASoSr<$abjlM!gxGjUayY&BVg1pR zO>f=r=K%CU@mw70p5!Oe7Tfd%=gMTy#NI1QOd}U(+G=<*$MNK5tdn`{dY;>i*?kwU zN7Tn+xE8@0nyY*B$Ov|-zD$B+?yY1;hCmvU9W%?49doZh$%vj^#%nZZ&zozveqqtK=w)l@e22r)-!-jE7n+HFQ8ukrKES*&jrGUs>XwOg=8bstGC56->i z9csmhvXF-p67&dOu`+JYLt3(lqbbM9 zdU-sC4E;`=Zr0zVz^(9L>It@R&b%m`@=1>KZPEky&MI&vpgWDUzy~9+1xO|$3?f~F zS>y(;877Yd;eiNc-+6wuB?}5Jz|^Z4W|jp3aK|#-=2#eP;vtc2viX-yJU5bs;nKzX zk=P5L>_$5m%Yt5B6n#&G9`v8p{O3s4HLM511fQ=sG1vo+;^BU3gAlC=+NQD;!mX`X zNKJZ_NKbju<{XoLA~BU%Tq`&6>8)6Ux&f}R7t;QhWbS%VFNKH5)jX;-iymZIJRhYk zo3+p+>MWn_?M*_oY2{jRiUKN9pRbNTfDVy?yy1!fO@y&|kYcGZtBS@l0 zwLwQ8&y(7)-u6_>f>lUPlD;$xKQ`yk3^}~pXs_x;vw=PocS_9rB=uLyS=+}z=+UEE8>0R#k&>%DjM84 z$T~iVX78Iu@=fhoLdc%R(6GBG5X(yw4uiiy)&5AF$?sdP>cE;!>n6o)f_4_%!@GtH z%o`Ii1TC4r7(X`8QyoEA+&mu9!NsPLd#~cs6i+|8gqEz_MuVbf5j1)N| z-lrF~9I-rB_iNydwdR^U-nbJ>HRbWlPAnQf+d8opKE1$*6m$5MP8hNB_`^YQn#yjY`&=?Oe8F#38DxC%B!Yo9)(zqAm#i~ zXEq=v?*m%emWa8(pekvtjEYbHJWLx-#^Wtu7 zmN|1d@6w&spXd#yCus__RLePlFv08@ljNv^dyOe}hbhlg-VZ#6WIcznmV!YnO7G?6 z$SI)MclGjfdd043dGvFrEh-TsZ&H0pk5qWHMr{PFJ8XWqJL?bC;Fcb&9)2Qwu%z0* z&Nbn%Jum^>58_0t=Wy^w-4giGGG8@8Y$`A)BcxjXC)o3wBC5S8_Z7sm?)an0WATD; zfplQ8eI=e2bx^$9DM@z*oAPJJvIvuB_Dd$di+LX5V|uX~DXQ_`7V|foe0<JizZK6$_g``!i~ganDsGRVa<{t)>w!5< zDY_BYp?j6AsL*D_iTSY3L&%0d2~o*PR3WD~>hPWkY=Wl<4&?7Aus)`>{7wS1qRF>U zWcSQ#U*j!pth2Ap0l&`#^C>n~$K=Zw+E|*YE&tZW(#;V&c*i8R!}J0FDTy^n{(TXA z9;$`q3i|lM^Rg_8GJWE7TVRE6oW7JMEj{JF_~tiMvOcs*94cMUrIuj@H_uoOh6?r^ z%TMdWrkjwK&-${^S_Lvkt&qob}pxJbe!3><|00rjSMqOJ)rdmTbBQHJ>-A zS<@J?O!uiQ$+_=uS(HOlGihmy8|xZO-LgK7(F%9K!(S{rGDVAPNCY-j%96t>u8zO|lz-;Z@{x^^`4_#R&%;u$pt zW_-;ul$~hw?a1I=`m+Y%A~0J+$e!ll0Yc+;a8f@i&m+bI&8gSmL3Nf>|r_ zFs$f9WAHk0G*pnwKD*~X@V1S-y+vg^v>VUs&+4`6rk~0wH)Yn(d7!+dlD8@3jaE?w z!C_dsdlv-a2O|W3(4R$SEJB$jVcCVzDHZpwGRS~h%*g_s%vd@5q37tmCt3?7O&Mre@t zQdxMdIGKO21l=rsYUyoxn*ppXA2oorLn~P}fc0!gLCF}h(a>@)yhP_0hic%kq4QMU zVF;V*shu(L*f7tUykH2kn6W@UIfShaa(543j996`6@K_xDfsm;&xl$Hae)}eMxXkf z6#C&$|6u5qxA9MhvSIc&=7FDa4*RlarGeNOk6$AaF+18RMOw^DR8@kJnU zPBMEygj_&Z6q(zBjUnbKb5kq{KT*cI@PYf5&pE({4riUQn0j+Ki}j+3hnp5^?YQp< zRs*v`-4Sx??mmJwtU(naO4SlY)l~yNV+0HCN!oWaZ2H@je$pSU(x0T?PlkSR^gQCj z54a{PIKw*HI%>@55#=90i$fnhwh9^uKY`GLUJXx;b7?1zBQ_2(+GF^)V_ERPI*6Dy z45_Zduq=2MCcS@^Wal#zbv!w+s~DH`Ja1XEU-KY-*_?o6eZ*XwQ}&w*@V!TX{|B`h zjs@W~U0arJnQhs$LYgEex_en-CtiUCOL0EpjyO@WJV*TxB#R*_> zOw_bpQL;Xsdhti$8$n9OX?!Zm!=1Hb2;WrUg|r2`d*c+O^M|STseC7m} z<}-8(ygtuMC$J9PyzZdHNCr7N+T>Bu1_NrqgWE1rD3R(B={GkifJpulu)8(y_AKjP z!vQz=37VsRo7C?R$k#v1UNu$cb)RExO{w`Q&tYOP`~S)3OoSnizcZ1I^*_Ae9*K-E zd4>B-VhK%CUSS@C@D0N^2HymHQ}E5g_aeU6@a4S1pP$4URiB%U8pS}{GFeBh22~qb zgTFTkd&m2K@Dr0*Sp4kFDcKKbzn9q`zt{t2M$_*LwKD6`?~AoEt7bo-J>Z;Y9TovJcZTb0ZxKQS(}J0nN*c{MF-sPhr9K zgd*xg>I~>6F?O7(e#wq4;rD@}bw#bdRcP>pzUH%HIQex3l$Il|ooNVTuLO7xY=im3 zkxvZ~+;>C`?&b6dvLs?j>HRynVK9P|<~1Fr!=D(64{Sbff2cTv5l@OG#=!bAG^W9bS;N~RgG|hT@u#|y zIuXWlDDgr>8&zOkYkSzqx=mT9`ANq-Wt&0#7RRCjWxLi?+KONkdm!XG$r-w!5+T#%*rCX&UR=`EQg3 z#;G7Q`Tbw^<^KD*P~^&Lsz$HsTi-$1g!7S)$>4)EGoWaupslorNWT`ztD> zVHiYezeI$8#((626$2{jG3W)20NLLQe=KoVqA!RNjOQ4gJabCDNa4J^&!3D@WoEMT zg+M3};`67o#_f(%h=AnYIkU@X#5oU9)rI**RE;m7s@@ItRwLeoU-H$Nw`PMQ`@V^om_PZyb4k zX$A|khoT;GUW@R2e&iE{LvVzQ>@&r-oT3`ZPOlSU`*d2LxrF||_=Qr1Grh`UNRK>! z!IpDqqX+(F){&=j)HN#NU59dH`5qSf-J40QRv)D5BZPngzK29XH$3ZS%Hfk|vIezJ zL$j8WL%<{ygGmT-5Je3)Dej$vu67n`t`Wr7&SI@h zcolCJYg%Q;HN}7#GopMPe>96d!=@`rdigy*@p;yIv|5YmU+<&#OuHr=1Qb$Vzppq8 zpv37~^o^WX>Y1%NZfoYyq9E3?;<(Vz0U-+#ryr*!3pN^hUoV&<&|m`58nGcYano$p zyWv)Jaw1~i5F6)!TBSHRs=BGM-u_oZvhYd#60UFO!`O8o!YE4`-?BMwi#lM|r@+TRmeAsZvPeSM&|J0^vvJ zuvIk%@1^o870L9g7-{?(URU8+FR*w!Rjkx9huCmUQ@>5!;~XxPRxV4YaZ#sBvyxW1 z%nv~;0=!tAsbKm3n`Aaf`+A`y;IDF7iGsNTDf>qtc4sPLDv@4&_kr0>5a`COFo=kL zpF`0NnhYw=*~d$2(Onj-g0vRm7k9Md^&>J~7a3B$(to_u>RI{3FRj|5FWCR(*&VVO zA$uFXp9;c95wqrv^PtBreD|G2IBE&0GV96;HG??)RGfbF>9l~0Bgrb0NRFKn8T}3I zfiWibBtC7px}pSAq}($REd~Jk#lB=@cryJN3`l!|;MeB*9VvsLs>@KRkRdq-nPn1) zrkC2B2@{_TLAF7~vCxQCS($UhvpCj^Og3k1m7E8j&;JacnagZ$_hbKXe?;yimT@9s ztcjYb68|`MS~59*n#%?^rFNL2-+p>23|6u&(9P7W2~DNK&PTt*dYP~9=9^z)PP}pz z^)gE}$9=`;zsx3@cfQB3zs$J#rDgfKuduGBpfW65xvZyIJI}Z0 zvWyyqXV4w%`J*O^DhANvRLtNF7P2OuAGBaRVIfPmP;Q734xUY@xE8>7EM!@x65e_d zYiMcsA83H{77-{&VhZw+i`cN}W@i!P^BDEZ)g|o>vW^j9Pz)3JRaa+UzjJo!hd$K#GV@x4B58d*mXFif64Uwon>sU_ zOm+F4C8+V|`C2ENZXPs-YfHhDeU87kl#OnxuVWr(@$J~iJQ}ZO9`iRak6-YS-Tigk z#9O?^)02%?93g)6gy|)w8yKQBZmksJwqJFQaR}Jb(qLwJ?HG}%e zPCLlE75PVlypBA-qo_9w>LQ{pRMeXWbrw-)D(Y>6I)bRf74?xpjVEfHqIw^drC~=Q zwIOnAMfO!>P(z3stf(e~>Pb}dzXQGjeU0VUqhv|kGot&Fs9z}RlLQ|jYLTLvj@sRI zvYp5uD)N&QuO#YO4gqlS}fxRM(S;IuX>2&CKHkd`s|c##eyvEWV%cJ;WFI zF7s%LuN%Hb1Mz1fzIpgo;QJ6?5xy_*UB_qM!cV-(rkHfz?k$#pA?c;JSaNkaY`OTu zYd^q{=mWL)IK$e^wdE|%+^UEVSPsFKDMkF1<*cQ-UlHF%_HIS|!gAJzhpm9s-4L^U_( zzx*~%MNo7H*0LAu5J5^CG87Nhq*;gHu^Rn4u61Q$hOz0xqe!`VwhgJn9yU&&97)qa z*DH{Eppg}&5Ma}@WOf|!HoSx2n1lbZar!U#Nln)OrjsMcj>~l^d9Opt2j}#ysBVLp zv1@Hr!&phh+sIFA_~A$1VJ+>1ZVXX)u#_(1&^(sri_TcO5W6P;zj6A6SUkXx8rSvx zsYp*|M-r?`dgc-~EjE3{m$cth3pr!AQzIXR<8uc(49;K(j&n#{a@WH%3EnjY8dcj+ z7*?#ZagjL%*PyT0R?RyA)gZsU4cCDGmVmgV4wII0ZLrgUBvI@ch|AHxUw6# zp4F>*#-<00oKCdo6OT{wF6&vHj*?ba(Jq~&nY(`=ddNO{&7*R;ob&ZWFx;iTPdZBM z)RX-6^(<6je^#`4PhrpfFYIf|-;k5M4DmLR;RPw$e@dRj`?-OQbL`>`H?TUbH&U8# zFzSfks4r@dOgZAW=!;^cVVl0Fn>2ic6N&h|;`mSba~oK5dlA$Mqq!A9t;Ugks0Udq zmJvm0)1ToxjqeJ+GPs||p+*TViwL>+ERMfRzs2#7=?5zS?`#BR8F2yOrxd~KQHtmi zIaGOM!3wTg{4LqMGLVee#rYUxAQ`|d8`;p5jlG;+OeU5bJ+Y`qv-Cthkm~V7Ig0)G zMyux$NBl=JjC9oUiA59P1a>otIbWfaXMdK3AKtQFl{$7(ryc5Ak}A0dIle@#Rcu+; zrGPg>!7YY7uYS?$kcY&2Z}4UiA~d$`IV<_1)-0U1tmstD2KotsKF1mE?)4 zO^Iwp4#?x*v#ZDmN(8l5--B^2lEYpQ5Sj#jy$ zmQL6lVY@@liimT6TwO(HkuusYq+?{8@h--}RN9hchVz>f{29F>R+WGME~{$4mF;5i zUBz8rbX2h+0c$pFdWkVVyP3-C%qJU$@?G^&)L5LBiYCj^IsT^8GjaM4Si8iwp~c8)EL3VK6P=W9Z>@;8#5I@cipY1F zgqX%}y~jcad^?`x!m(?PpmBn>)!2KBA3l0nc)*Ay56taFdm^8K zF-A0(Wb)EYd{@NBzRy}Wxx5QAVnM-!N^BuBlb%@_h|r}J3Nl!ER4NH$x%|`j*_Qfu zv3kLq(~gWQ(ceI96<7Av+Qb>qr9lloXB&&MCpM+6PQYSZ9)(;>ndmf-M8bWjC$atB zu^w6F&=d+EK~)=|PeIEV?UzU(Y3Bf%3#3qM82F3C1>A{*agf#9k#2lli4S;>T)%>A zk|Tix%9V4Stn$aySFja?d$QxBaJj%i`2Bg04_KuA?fMk$s0d-oShRyL-OdJA-3=GS zR*E0-eGtF3oz-tP1M|0JJwN*vT_PwJ>rrYDoQz0vt`f)%Qj;N0P3G-CVoByPJGlKL zR;PMT5e$h;dHI(n;3Z9J@a-S5Ps}}b@QfW0J)g3JFW!P956=ZR4Ngf8%}Jf(yO_ItLgCP5zYrwbgyvK zR0jMbYn`opWgdH3Zi^s19*@%~{oy~PtA8&*pURmRfuZM?6c_oyfnc41I6AtGCK3;w z5|}-Ls-S3)a_`sSIFlSNQTsuLX)z?KAaw=>QK%bvmrqz!OwSKt{tY!)en<`_ z(4ni)n4p4wgCmNnFVJx~J|RGdU z6zvYtA+P}hlRAU6L0o|7EA+ciQ*!krD25UTW0TRKV5;za8R?&QU$x(`+*Pjy8BYs@GCN!dqF<62^N3=7kS zS4We}!G+Xoe)%^FAV^bdp$~PVBGlP|EZm1iGI5n9jCb3|Qe$pm#-ll+V8YY9#Np5W ze+sRBwvUZ%B=>K`&;3BA;vWL4b+ggt7xKjYtf^0JG7smo_p{NyI^7w0VGF;qpFLxq zwS{*-!1|eQ&*07jY)>P#IYNML=?&tiV<~u66ybd>n|?Tgk3Y!%Fjt?RKk^XEFnLBL z2k^s(af&pD^J|A$hZ?K8Vpem^_M?kUC^$cn+m$yjVo@m7;YF->ZCPK~tyABXVnEYh zM%qI7r$tQnISAEgVlj_D!df(2xe4jKvi<>Lg_>I>S?RiTEAQjZA@_pyeAN*MujKJ> zkFYiY*P!bKE&UFD#2y}elr;$0t4NhZdY$(^%94G*BXhwzzUnC3-s}~!_^d<2O9MmT zJoPhd_PzD=zzQFIEj3&{#Uh&UiN}!1!8iEp$Jiu9cNf+WzZa3*PyX`sC_jZpkadtG zf$6QfDBkKb*4)&T5B&@*pi2?_WmxOyeMP#Y&QxCehg2lmjfd#Bh!=gv(#(G@5?s8j>zPRJ(1%E`4^k@on211gRI-kp+_H|{Ux2qL@^%&ZAz8<5#VoY8OV+WW zTh{T?9C*9=fL|?UD=;QzmVl3z$ID9CC6g_G&q=V;u%UWa7L z1Z3DRTB74nqAPfPQ*v@7YD)h6vVxm(7$Ed@} zj%h<7Q!RIJ8=*M6J1h8Zx!$= z-?IMIC&3MisGv0U+vKl9eBHC`HS?W(e*IevK~cQ^ckB>S{_S@xqIy9UjQZ&7E{P!1 zOD>6^nEAZp_bfE^?A~Bpi@Sj5cRsgOZcIf#b+kt4c`cSWAQzQZyLVY_}pzvF1mOwo62PGVraX}612M3M=G2UaLfjN<+3gD*|wkSEmH<==E!J!-DJcW7f*gZS##c(1ikxzr%`8D)R(K$Z$ z(fvs633?Th5{eC)GoU*vg5E8`8_pOx8~%XT4Dbf4!_%^|2q}ODDZN(}y-#3HSAzw05o0Xk>&kGaWeESXj17)7@htbn}k_7EW~3Njaz=nE(YtdmnVS__El zAbxBfz#m^@!PP_J>}fWtRVC6@l~&SD z?{<<;vPX{Ij(F_#f{M0V$iW{IOR{4REenyPVB!!vy%&H}gUve#Ghyq9(_Nb*cQJW! zdY8zMa$S6z7Dyx9Xo(KD#|?>ZV~-C7l3K-U5*ZJ^O?(WjI7FmKh;MTYObZw@U=&!t z!#EMf?*hn}yHSPqhGZ}0QVGH>Od@jgl&!a~^jV;6$7@Ji5!rNadtx4j1V?TetYV7U zeKY0uhZf3|W$%441Vr32`V!@~Kf4C$N)$grf0|`4X%IOgDYzF83OER)Lw%JSdPVGK zSjf}EM9!d%iYm5&gn-3NFretye*aC3HIn6ESwI)`ZBEEpVGPQH2ReO#3_8+@TI&}h zpaM|}piTk}nulnac~%q$E02Sv$FqV%YK?%jaNjt}RH>kUR)#iDXml zIp*21M>!`hc~T>Q+*ZGl;Hnd(5xmCf{YJu!dza~O6jzVXs92Sr$h&mtUZqRx_6=S|n%djF_e@Lu%P@K9vCr{l@%Fy#a}6lOE_{^(*j*Mahq6eA_Rq$I!bk z+^bYO4#z^(h6aaEBzd^Cu~YV(j^; z94HjGdLm<_hghw;ief9y%95UN(vjsy0GFR+S`_l*H`rFM3ndukvyavcqFX3IlO_e` zzy2TA!i4)2du~FaegyyFCMz>{ImJJ_#jXa(vUSEkXVc%j@4@qKvpNlq9*|8gM07sq zi56Rg7F&CcTSjCn7q{7@sv};dY)V0Mv8#ZOxx?yoZoHdlT$UM1;rO!qkALEmM zXH$H9$vlvM^E+#9_S?^W?m{I)m6g2RUDRXEX?*xyHlfxHPH8zOyw}~sorE{2&x)7! z@XL2u=)~fEmexb^|aHXpqOA>5i&xl@u0esXw*06f&UKJZ^MaCApi!Z$g z$ve5MN;US=i1TZ#r&PEp`VsLGW)5_Gf4LkUJ!-@;;v8im5HM5X99yYd_3{aivw>X!&irR^ies?<(Ak$`% zxVS{MMT$8wx}y^3V7NLXYWNW?WiIhX{Ke%p7+M_@pb9}X0{P}ws+AfR6wUf;9)t1S z^3yyxep{egi}1S+zwVD{ezbI!{HQJWS?fd^J7{Z<{2#?Q9!2?;;|TqrDQm(8X*SG% zF{CrJ>nkHO>!WzmhP zU+lSB-%cWy(x}SlN_3C-KS|H!SCg<){0sU9=JS4kL%i+$3;fXE;P<@F#ouhU=S%5< zd~_v?HGjR9Z>)s!HVX&`D%n8O=9LyLqWZfO|DX);3DgXhwq<3K*0L@w?bIM_bIKd} zn2P26YahGv4Q)i7ZTBj(_RHBNvyr^m?_5s3O?i7|P|9DsI% zKst)Xdi{9$+DdT=(>VUTn;1yNFOK{6LU9hM*IYfYA{bLGM)X zNH5K5wv_W3URrH))GvIomzHeK`-OkurOh|3=fk|UhWL5OTYDZ)UO~PaqVnN|IEux? z(k^R6VRf?7GZWMyyN;l>;u-OKFyr-nw5Illp3Gw(S{>eswul>Kp+U&mrc#m%*skDvqZ!e8= zVO%PY$QNcI#js`7BL~;o*!!*4(zZ;wc|}UwYGq6K>rZSf5<;=Zq9Z2n;$JYdIq2}r z`+y82fwo!Iu+0FKwpn}S@peK6jHOK^m9|;u8_Pg9sz5g@+csB(7U@Q#BYgT`A%Ub7 zC|it5Oc88@#Yh?SP8y0_+Xiok6ZTBqrs(vJ=H{TIpp7hmP4wW{+R@>zMYu-AP2aFxG+W8`5v|ISZ~ zY;S_}#XeL8N&$nkxPvo7nwqLh>j^}@v6mN~Tr|Ii3J(}hz!`t=?*3Zc2IFACWrk}3 z@RaZe#V#4>Q^-%pKlls&TBkMvGy>Cx$*TjMK^_y`e#L6S8PI_|mEDs`ZVP*NX@A7O z_17XsC3L6M1aPQ5!ZFulUdP*#YbP3&&LEJZr z`NsiTEmJ%%3D8Kx1gomGHP33myH~}4ncjd8sjBsSF3pgtR3eow-Y<5kkf(%Zk% zz}0B#t70vfSJ5}DCl;k)rF|cA7pdN>w(9dpZ9qUNCZpm6Kb-aSEWeGR z8Zr=nz$2wL6#Zo@!olO_sD{7Cp$U9}tHRh`%hBFi$)3uW(e`JZF>e-|e4p1N9` z`!e15fY<=75xqrLUCQ@aF&Dq;6l^AKMzN^u{VMnw|0?ujNOY^r5K1tX_s6h!$Im$| z=o9>~aIdgpZq2)a$rcy%(6qPS;M1#VUF;z!yg11Pku9nObx$Lg2)hbSm982B3hp5_ zwGz6`Sucn^MSlTw;={lnH7m?#2)9IqNw~_W@l)CG z{J;laMkI$TeDc|=X1f4u8q99<6rz*kzwPyFAT+Im-w+rbkCDyX?c+PR}imKw; zQ+8j+^k8+tkj5Swc+kTF#rhl)!N9T#J4q73IDxgNaD0T5)txjp;PEQlWw916jZuxV z3^t=tIs@8|#voGVPi%Cv;oEgULSs!Z9sWeoks$9;ORH6HE*OI}L$YwY0`fW55NVjzgnWZHf)cS!ck^QHaPU1L+$j+SKAVYiS`} zwg_4wmx?O2XaJ(8W^+D^8jb5@NCCuQTvrrBT>>GJy(u*;2%Yz;t*xupJ&16nq67UF zlfJ@RwY5>^t2KH5U~Ms`rYpf(SgqL*0Huxu9S-LlQ>s8 zZ~Nh=l>wi@gZV_z!qSxcP*6h>%n?x5&CyVNw<5pu`a5qJk_S zKg9;*GFc}o2t-UMn%50Tfr1PmKP%i2d%%Ze@1QUl3NzHeI2EP=`5EiR1S}$}SwSW$ zNVox+tRNM1bECBZ8BdUNzsUlasUWwvq5$lY>6oZ6^0vn#gro|McUqWsTk^d$fWrHedq{*cAl}A#Wp% z$i61)U*(i1B^WG|SkFN1Q>Y*5l1ftp^(mo>6>2q2_bQFQY;osog@WxM*ewL63S%k3 z-c+!SMiTQ3)O3YSY6!YF98T!4?>>J_Ku`U~+FIa~5a7S}2r8 zsD1`2oKQEZgDZt`Dq~d*l$SzXE`YaS7s`%h4TVyuU`0k6ue|FnkMH4*I@>_79}t)- zk8cT;qfj*CtH?GRr~?W$iBKOIsNIB0Q7BqE+3YfBQw`W#3KmVU7Yx`Eg4I^AD@J4; z4b)VH`ipMd#2Tn)33csPSsrBu%ELe-7-)s4Aev92yu-d)OrJT*G?JjsbKdF*k}WGNx_;BY@z`>ODKPZ!Xcom z@FNV=PKCNjmxtOJsBMJ0_=_wL;yF>3*&B#Eo7_2DtYC!%dyK$T&gK(roq`1#ksUBl z;}j}~P$vx3NJ2fQP_*t=?PH;V>ZVZk6oM@?V66$(R>49ISgHZ5s$jJVHQYe?5$e&; zGG`G6s*ZsYC_WVawLS0_ZlHbu)h>=J7}z_mH2$>FT^>gjY&*gJgTPdI9H6>*L!n{} z)J_BSjzY~LRDpq7MW|s46>Fg8+6~wX3f7Zg^9|Tcf;Cn!n*r-(pi&jepHRsLsu!Vd z{3OdG)j(A-P>mGo;-@w29-@{3t4FYW1xq(zUuX`E=lCL6Fk1#3&NOat~I!Gcs|GYwRG1NFK>J^BRR zdKjoBgu42pjBBoe`g^^nhh5EPQx)tu!Tb!^vjqDH?CW$|IIg zvlVKwfqKh8g(}oALcL=*V08%AUBQ+au#pDrA*vXKPj5kpXARU{s(4?8T5X`38mLPO zbz?WYMH#5Gg!=pkl!qPnUJTf+b?%()RIq%4Jw#wCXWIz2mSDIaW1#jKsKpAEO{mWd z)OHqflvpB8{2p%^R{DFKCH*^g}{TeN}6`MwKro)hCJdj7XRcUPwF#~zCUvg76Np3Dg_^`_L z(t|6!_mg@lah6xM)S6dYG2YD)=|gu3;#cv`ky>a?&m0t;OVXwml|;_r^L$#Q*2J`r zFOSqd?wpFdE!M&x!Pvr5el3Z)V~ZF{=bX-fWV-iKe3hgHND&=`vogRd#FfsoVr&k7 zt(8{0`gw%uF(*JWx`}>e5r40h)@(qU@pht;0G28XMEUo$F@_ALQl1NaeIt$~>A4gL z>Nga-7aFr|IBB7YiDWXsiyDjzI%N-dXlt!=%m%t&0#QOakwfg|@LjN%Ka%@@x+$}o zP>wC(%jEB;>YNkjomu?N)>=q?OTz_lz#gxSGhQ8bLV`wVD#(iG$6IR|rg^++8?8t8 z7|`9~wNht+7t$trfpwINeSICcS^^UTp--3SCvrUS*K{JM7yXn!=9}7RtpjfmQwh(u z9J-6^)RqOu`PDXBE#IB+lC^&-Ki67o#v4az@3j67na2^0JXtQ42Q^*6`6c$jF}Nf{ z&#F{?V$)v?Oz}L!Z$xR~Os4{aihsR7U-~Bt;qBXM_3eFK#AN-~Wc|e`y?-R+aUs$V z8IBj_sb!1K5qO-l^USC@p`BB4S{c_lw%eSb&NiG@+B|0l(sLEA(@LC8;GDZOCHId^ zU-2%^sw=9vPm$8VaJTF&qAU@o4BHt$d8V1dJpYQW%=ybZML)++x7Ff9`upwk!G=1{ zX{}eeJPUqhK2n_hd5d;hn5jQcZl}cuKSmi1+mCA0?XeI#vE)9+9u-y0KWL}5!g<`6 z?X*eu*0?`lEj*$c>6`Dl8mVHD{Tz!;=fSVgk)CQ)%O+Yik1hC4$7&uA@SE0K^ElQ^ z^LRh*$wxG|xS-sO5;qmwVR&p9ox1OiJKWKLr*;ED8iy^~HlLl9%3^*!HoaDdpwQOcRY*$>)g;TK#v@1fT$5`Xw9|H}t_8lvGM4J4M6 zrSMByC+)-PG(e^3590Ld@|1Nqw(8Ylv~lfc;i>>``!}@~u7MAXGjr*=0x90}?C4+* zv1XAc`c>xTocpFZrqiVBzSHIW_hZ0sXzUN4*1}Q+s|n5eHt-ZTqUcoRo8io@Jv{4s zmWN*C4Z3Re>#CDpu)_BRo5&jklA)(=dW2Yffe-1b{oeRTgkmiuwZurtdw70=f}|0H zUbS@wtbnt@X7}+a|MYY4O!&u3Lh3Y3HS~`nc;t>C&_t?&5B@y=L^o}Msc|`iv=-h{ zN&f7ee}}&t&QHRxU4G#l@nm#!D{mlB0xv>WWp*CV>YVIAIX@3feJ1U9u$*r2p z<8^u3sXW#HXPhp_H>KkoFT7drrziMyb0m(;GcEtPNkhJKyd{wDjMdhd@2$&EvTDpU z)Ug8PQzGtQz=J#_`fhJKZr-q>jL$@CgS#=M+fM( znmVUjOsza+9?nus5i}o~nj*oam7JEC%2pBLa`O0x6WR88@M&>c?j;_vWZxU6;X77JTry- zbU+N*8!LMt>^8F3kanE)_MQulbwD!a1W}n!7|VicDx6fJRk&z>p*Z1hB+@v`#Ro*o`Nd=Lveh|a+sLhB+=S;tCiZ$Gh7*(WJ`pjf8tFDZMl$Wr!f zWe*iImEEE25hCNDzl`5Sh!UyF!y4rwM#L)nCS{KmQOf>-vfD(cvVW}XsUq+n_H^O# z4||5VbwK9F<$t0mJHY!TX}8SZ|G;DWXzAVye!x`9O@~8*`JO&n8*{{a{Fgpjm^t7* z?%!8yWWK$Xx1!(6cxtMz7He0`<*DI;QuPZde#yBW3+X!2Jfq(x)%9{|34MU$!`oZ+ zEA$&`~QKSC%+dpyX0bta6dPTx1ETF6=Jy4QfJ|y$%O4Uuk&pBCnRL z)v{anVX*SB=9`>-0>%78{!au$=D-qt!P%#}m;%#(ONFF?BZncWrIH9)RN?WIM2Ka< zLfK{mvhHA!P%+1S0(~S?ok06Th#UvbQHA!JGGSMQAL0O|y^>^kh$?_BMhUW9hs|{a zeT~>&@(B8s{RsIjgiJ$oi!x8wqm?shFFF1mv<*C#mPm|sGw9v-ZPh^q*OK8LGCl1?-#Yk#l zG{h&=VXW<$cO;4SKf#>FbPP_G+ZGy$B=Ph78R4zyGDI!qm;lFFA)oADunGhCA>qM zA=oBuNh0qN% z70yBcl{^dL)1UO$hO|B1*Mc4U6-&f(C@onGGs;)f))`gu!<)?gCsut`=dsva0@6U_Q z``7k{Xn7aX!y2?|fEI6l@f)5vK#L3ud6)D>R1ON&Er_KqY*I|jO{o4ZUok+735faz zT?*VpEO*5M{?!2O`5FV_Ftg#D8fph##36aBS#iO9^gyl5eCR74J4j0jy4jPKdu6nv zCJikybkB7^-#iH0s&)MQAgv`H1$jJ3TWX$vg)bSbwP?{1D_{Mx*f5Q{?^)653g+l@ zm4jx=WnD#MDUi?we(;i7*p?%9 zqgG6{#!UCmOw_-N({JF)Jhjr!)9Yo9MWP;HPk~`1T?u=T)bg0Ayb?j!-~BI_=2LM{ ze9#{u?x%xVS4jJ82##JlQ+xmM;i=9(g<=#=$=yRxBnE3oMBxM{#?BtpObSTyDb6vY ziY4xdV@#kU(NFj3PI5*#awf$mnO^NK@NGl1#zBr5QH~iAw&KJXk}7~uh{=-s9p4yR zr2+RHsx7m3#33{;A_P+z%ZmsTKp^1?S8|}tpH4fUWRLb?ljQzjs*l`%Y{4sguA^Go ze5BXIc$V7;F>H3R+Lg0qht;qI)RI zSECsiX*dHarC}P^hG|U`TEl8B%u#Vql6xKW7qyWZ2sbgOtr}+MVwjc7X=~+>Kz%5< z6Mis7;E)?>;_K73P&>5?^tKq8COUhELf=s7Z&iexZ@u3`1lGdWRczPR{-fj`W+Ap4 zQ7X1ubWv^$Hb0OXdxOT3AWtMlYJ5h)HnA+|`HzD2p-g!rSEHBlD#NrUu?=NJt5rn9 z{~1wlxQS<75luow|07%c%y6x*eFcEl!VM~vb8r76xx$W6zG+*ugO@AEtqxDhaLpAfUBefd#0*Z;E zzyP>@4M{#xPdG3SG3|nUBTdq~X}{Bus*l@JfFn{? zkA8Bbg!DKBh}Y~1v`T^GAQvhM3{Wiv`V}wUE6_m&s!E`-3KUAMG*sk_wY#IbP2O=E z)Icp(sIe~q6{%1phzC?ZBdRz!0`!^z8l*r6KoEa!m6?iCpb!JJLB(W~AUox%fkM@$ zsE#UBj6(gC;ZEPfIWnpmMpWep5OEV-I29;Xfp!_7?-c0!W$vQ*RDsSAD4jrdM{g+v z5-MIcPL1X`d#QWhjsyk~%9!kht@u}4*{ zV!H&{1EvzHzd}iIkWewpK=oHqZ8T6XsHm=H0#rwV=Bo5{GeAe-h~!K$Kvo61K%k%B zrJ^t-LhPZ!%K+|Hz-R;LuYg~JAa*FATv^LzczU$EK=u*98SrSSJ8z#ONDyA927CDdEtHX0Fz8@P5V zp@R%ubGrg|A>bJrTX39a0I!d7=dg|f)-`~)5hhYzop37^F3-SyYT)h=0PkZu-6d0~ za7SkYHwrjABBc3670s&#a5FprxZMC|E8y1zY@#A8GH`JQZlA)bYbJZ}ImjdbH$D4eH(`wD5Hl0nYJYYKP8z`bMO?hwEk zU@wK94%HzxDd2B#5b+9FW&p<W@A z`T_&k3my>uCkD`=fRhQ>N&)>0T(W`dqj0YnxB&_`oN)Ix$P5M=xSA3th3>j2U~dB$ zqJX=RWpPjeX(6K;>9@n(CG!>)i8DYmaMutf2(J?^SK&ep+!g~jS>Y~1fr?$#{Raxj zD5WV1DA%^K-%mAwzs-^nt_4uxW+~hcpo<`di!vf?Z{Ut99BFJ(xXuc;bGK1*`uAYIjH&Vd91~5zki7t*S zV1@zw3GZVlfeW+3)i7}72opIZx^ODoL<9Gcf%}1q(i!m0VpTGByi2EmU&BG9Dd0>4 zm}vm_Dd4*<;E3{<6t2rm;OZ;fTm#q5z}0~}BAjC2tO_@u;``bDjx3ri1L$P{$EgUT z4WPdQ5?$<2xWxwU^iX%n^isG-i`;epIf6tAh%V+R+%h-LE>;-8MhbY$0IpHM76k0B zfUDg=G19;>h0_h(ScN0H@K(5u1}@yd{f4?Dp}Ro_u(<+~gE+HRmdrK-czuXFho`90 zodI*2!fCUEdRRcI*0k<2#Y!%_l zglnR3MFuX;zztWp*#<62;RX`!#@omsglEwyv8I_z&;(2D%Kvlb?gE;;@Av(FpXdMMd6s+c zlruAD&YU@O=FAyA!VhIhxrVR1J9|x)V4l%C$$2tcGJ3?))K&WSD%jWHj}~!JF7HQ) zE+ZQ(uY?Bc{wygX=$m$EyGw`t3QcT-6c(uFoe!Y4#p=#J z2VJch&d|xNRZjtZ%L0%Mdh#q-yo8ay@}u^?ylA!*RP!WyqRMFIgxV;SD zkdw*}w(!U~Qlq5X-wK17fU4s;bRvq3X2dBriz9ysEeye2d&3a|HIZ&d7ZMs&&T*>u zhkVf-sdHc?RHbAfvxAya5d8Tx{>>bzeOuv@lrHL6zFg8Sv~U}}^v7;i0Uak$BTo_O z1`nR5*|ALGUFS*>`d)m*T&YE)eJ4fa{i#}{j10ISj2+CMfHyr(+)u=_^cLSbSGo`p zAX;|}JBL&Y+R-?s9(JkaZ}QFaq;UOr{O~-fn+-~IBuGw7S8m{la-2ATpA1`;Ua)1E zBWzjXOm$PBMvSXEf1fBUS}bJILg()-#+k5aDR*16U~l@Pvh(7OKr!8zet^aPBTPlgpX>vyR(1!V{Z_~ zGEa7vsjhBGfuuWuUv1zyW~ro`yG+s<@uP3|kHUnSfp)n{p!68(qK8eLe%oJ@od%W|_J$|l@ND)(?;@2dgO+mP+b2jYb+Rk~?G zc11^>#@$(3|i8@cu4%0ML<9%0N2ozpnDLJHC2Ve#O%k_}t3R#&kxg{^ZK< z+Tgt7(sDz^2mJLs=y4V-;OFwBDTbsEczV86hnxsZ z%9nc9CM67<2vl8rB<%9;s(p_-kL4qO-D1qa=AG>{p78RN$H?R70X6yD#Zq74xl&x7 zL?@z9r~hW`xeNU?Lk zOVUJr-5g{$@0_H;YV+JNXxWsv9ko()2}P#7W_)>p)N9Bk z1ekY#wP_bIbrIKY{?SF;x;Y(>86l?p-69RhM_0NP|3n&7-n-iCpb+a`SGrXqoq*-w zZI((MYy-@~u&pfJjQxCYi6+$W%xw&Pq%i^ z#NrZrR1DfbI94|AKnK8-#k|7@Ps{^^!Z?+Zn6|6w3C>JVm32tYoEV)oMl(wp9H8`% z^@78YiovlwVwn_XtEHKuP(+*-u9=@8pr-bn?ht^Kf#>i%R9pX`r(`7H6PCC_K8ury&`b+ZeUmQ`1r;l5qgNc(oiTJ#BI(@ z&R3R`+_0OUS|PPIICgQ*m!+{2x2KSvS*^R-ZJYC}7U1s+xTAim1w7oOrGSGrE#L|Q zs@vuW#?(lQTV9#Cy%u2O$6uD-4ctMl?y5{~4!7j_EB~X7PBRRnY8kq;{F{wVoFGB6 z*!i1{juz#z(b=<7inh^!wBMCpoT0gz>^n@DokhLt5(=ZZ=%a^Xg*+TWAzW_6Gyaq1V_1yEc>zkg`Iux}VY0=1R zZ@izM!GByOg$+B4;?+l;AjD`+EC)c+`IDw~^u2Q@StVvmn#&$ii=)E9=S6IZy3QR- zEJG}|DYn=ZJ7=e}|7vNGhg^R%3A1-#53VkHpZ~T_iZ#gVdEhHj{6t~yEd0D$+u*wR zM2jO=1QjPG0wk(nC*wSDK3v-4$V{{-xX*c|2oiM>8=th-sbD*hj44r9&1v<1qzj;| zS`NPT6{)GQFvyo*M6vA4sf_l6(hDN)Pvz0;rOO6mLoU54)vmEo@kXKAUH%wI|37F(IeMt!VMEzJ<3b1WKA<}AMd*X`(|dP&}{$F)Brh6aJ-@O%B}+; z2cboG!w_iFAu?6@9#P)l@hIHtXNJ#ZQ+^h)2IUaqkTOL%g>?42ey05Q0mPN;K9ao# zMB49qnetcR#hiPIK$>&0#_-me@^cI^gvymvZw-;ArIV2^U0F|9$xup!i!Adtg?8?#4W(ey)w_eKqfG-UPHu@RQT^&x*EH} z7G)bDB3(H>A#}M}@x$7qhPD(gM?G`_ru$s=FzVT3Z#8sDoP>gm~(7 z%PY{>KP#*+0+N4qNZDhxFF^#})+Q-Rk*K=PBr2-&v4)xpascEuVe3J5Yb}^r8&f`h z@u1Z3seNUhVpRseA;IQ~qBQ$H^i+vyi5GH|k`LLmaYc&9!Y4^RZCs&Q@vuJ`oT4a% zj@10arllFkoUW`?`IaxG*uIguKO(}Edl&yDYXF9lz0kv)aBA*>QUek`0SKfH@C(3j zARv+?*aj};0v0bvW;~aZ$i}~ZL&{irYqEcY{a)0Ijo{aJOfO7c`^@lNrN8v4gt3;F zd*)Maep71XwG-ckpYkbhO6_V;1u@_vFw%%EDY@`1_9hO8dw?!21zT^@7_mR{voaiQ zSI0pBgly6zXV+7R*5LpPHeI{IVibYFIlG7->9FKPpu>j(vpwLQxDS1I6sO^dIa|A> zIO1^SDiWZC;=}-Y0#PW)VF@z@csV9EvpDL^j57r$hLihEFQrF}BPqT(iEi;CW-jcA z=Uq3-hJAnW-ET=z{vvZyz!tqJzbZ{y$~5>&IjY7j;8Xr3S@l2gpZ^8(a?7V8N4rtN(!i!DB;0KftMm?;1mOo0l4Fm3N)S!^F;s6!`psBk^z zDe&w>v08;oN4#>=%ZA_#?P7+U}}-u3}LgoWp}}6k_W!y=(}Zh zbNcqdcU$_dn;k*l4Bzp*XtPw?@WvH>ezO!|DA)4`o2B-?1R8n~do!N!q14Kl! zTy)uhyWCU-Wq;NGx(djPPC0M)dBa;uGD{;m{IG0K^y1sf^I7J@LdxRxg2 z%-oQIAPmSW%5}#;kES=26HWK0DEG@k3s@ca|5L6xGCZ1=rzn3mJww+&?ZGt>L-4&e?2`Gv2 zdv>5YDW=qWsR@tfho&kAv7jFQEEdRckF>G|)@&pdr;R(2UeNX!QbO#=4&#p=`PS>* zv!`pYz$Ct`1`UQgbIB$r16<$?a=>L{ws-5o(r=IpDyI4HiJFS&fmkk$^hi;%eaOXT zGwVIZ_Sd-%6{C~0@M34Uj=Pdj>B)RvD{KooHnjF#ds>kc*K%$ zXYS|e3Mmm&qd;GB>oR|0fH})iqNzpE>;~D<^hx}XK0~r`C#7%@nyM6I*{(Jr*Q_B_z~ zUzr-ui%M)=;aE*Xg?enEYT+Wf3cS;a1|7e;Me5T2Rf`LaIMi2GL(P~&x@4_akrqlU zN2(7-v?-4~>!c|6#Ox8y$842?oU^w|WA!cc5Om=bwETt{+)}*(!ot@b`s)5b{YCpc zBR=n_->%@k+n}dB%^Pi#`qZ5OXTFJf2jO((Adu)|$(Z{$eFy=r&3S^HMtG0ISg1%ZNqadwJXhD;bB^^hmZJFisU(;O6B_J z`P9#(nua?w_`=U5b4WQ7xdb{(LC|U+e5%)G@bjNZ5nUqa zB0I#g#GGC41DiT4olSUt6xKQ&v8D|N>>(6!kT3YlA zvnYo0Y;;P^YqlKWOUo%wwf$2tJ3pkpFw~b{a!M`rK0IKD)EW~;@(wAcW0GhO7*g=I zVWK?)oT%DpU$^PGi)-iX)f!d{m7hks&n|r94k^-i{sidl6BfbSaq$i*THlYCA=F@; z$fcc96JPJj*seRJS-$z>-H8i#f=46M#hp?p>{@T{gi64~TYN6HjQn_lcH?B_grUH@ z^O2|BIp=&XMe5(;uY4}W)cr{H25|%$K_JN<>PGD=*@HfP)DYRe$fg%p3YU(Cjs{MJPz;#N@OkuK@j^JOiXz@q7 zUYN3ja^U^abr$!KdZ-&t&*cAN%7?u)y6dVbZxJqTAR2iAVAYpuYMt012e(~DeL_c7 z22*%Hgu{V6Rjtpa8mO8Y0G*b|Pr_*mSSKBqI-%}-$pG3j<>3wpu*>)EAX5E{HUu1t z&S1b;3SN)G1H;W>R8pB^Q4GFHCtji`crS;gdvMlyf2z*bZRq0No?yao2@ehHQFYmN zVf9TeFRg=Nxp^7Pio%_-lo@4`K`tU~6nPktIJ7|*nb373n-HdcRD);jmSXCVo;>d} z)C|t~O!-uwg8t2jhqqk8Ki(}xK5Y}LXVpSG4H4764+Z$MR@hWGpMZC8?GzLU4VyZc z(j}h54f%4y1ozkDne2LX?_+9So;cA@jM zQ;S7|P{Zdv(B5rghjO!_pcp*+g%+`v$uq#fxalquCR%ix<%q!({hf zyeO;kZDZxz+m&xyD&IbJz2RUVQ^=$aH1VC6o+0oIVgk@DO$ zrnrp!fz=xT;{8;wHR4tHzy%Y-#UEAT0=6gJN*S@w>hkf$`y31P>OwNL>J>wCKk3WP z^%ICMSH}S>TGM>7%YpIv6$0=Wj@u`c;}Epeq8KC3oo=Yh_Y_J&$t%O)7`Q;b`4Kor z1!^ZMK^i&;#Bu7pXmDAqVz)Lp;SDc&6=V&8C!d6j%5czpzjGtEHm`d<@*R96@jVBhH_`nL5b^aMIacO z4xsn!?HWM-ptzKTN7+zr2~YX+Z~8$0c@jwuP!bG^SaSC#;(jW3$DP#TrXntV9MSg+ z86t5Z0yKi2uLXQ8Qb2$!2wsu_LIl9qv>@^m`HGfEL5T7-G5N97h!V_?s&@oY#9Z=h zK_2KJsMNw()rL*Ubg^a^d-N52{voNWc9%4SP#hJ+z9K-sm#$gS{}$!0(Ps#uH~|03 z6^L!JF-W^hi&1w~rai2M&>a6R0{4KH&~3++Z)pnu29yrMX@s2DNUaa+sf>3)Ij`L@ z5Lv^5U?M3yF~G3*kCS#eUudFF6jFZB3&d#sHwj@&E<^rO`QpP;-H;5_L5+JdDc^Hg zO0!KkBg_m4;(da6@b*6!oeF7U>1$9%r9zrmx(Y9(IIz?PmJgx&-K-|+F7=tZVxitL zCE=3IGbKTt-vD<#0QPTyt(;URJ_$Y6)iM$_GnEtRFqt2sPT%FN`k#}vBVA}oTA=!#VXl7R^;&2~0Hqwr(FE2ooAqV=Ex=A0`F- zIOw6PUlvJQ>K|f<(lV}pfO3S^bBCarzExzh8q>$2&w_OzNvgL6EHz^sjrGetw2=11 zWXC1r0*c@puApcw$b<4(v{V6F5RF*b74)z^oFEAv05%W)4)8EDqUDG>9hIkJ5!5}< z9_IN$I#EAz)7N0Kg8YT!Qh30*JXF=J15xljw2sFQJo4T!^rV&AVDd>bcQ3MF=eyN2F(n1KiC0a;| z7DBi^rG>Oc2$ma}{euv8S_|6?j)SoNVWz=_rj{pXV7(W7R*QNYQ5I!?X&0(lfjqK1 z#=h>l0byV|+LWrXot5?8jN}(jNMYksgNTvR+?||Cbtg-X6#%16-hB{8BxMsJL@gs- zA(JU&99--oY?3Q%D8kIb5x&|2E=Q4(Cg!h$jQsT!eLX(!q!iKr^Fv~ZaDM|HAp3Y? zg`-O!l%tYh6VPtaD8Mbf^#Qj)>)!3B8#cC@7YeNTiUd|BNrZ00{|LyClMVgrx8im0aWi{6;)% zbdS?v+yXj?!W_FO%+hfeaU*Mldtsu`=O=n`bCxSI8}=z~Q+ul?fL1^}5C@Gka4+s6 zs?<&!Dau5GDvJ4&tUevPM1Z2Gnwv^0|2r*$*p#BIMS3Kc)HiD2IN2`xq;825-LhZX z6?82?zgHtL5o2bfm0qVr(KTmZMK_`chnN2NhXE)MGa21zQljRFgV~;AeZ!#UN3UdB z+fG;xG{Uq3lZ%qGL)5e|`$}0jHPBUWUyN^hF9Xx|Y>2!hE+{4Df=q*Yu@NENb&+q4 zp*;L+sg5lO2vbjr?$|}MKw{o4tQr$uKZ)>crU?W;js!qasYZvf73GF#RA&l^ikrCv zqaqqRaq$=}#ubQ}1ho^Kh-$Zty2{eGlDS!Zp=mp<4if7xQYeZK)&JUAvhXUg6x)4-H{4)jsc8tW`;8P8F}YzS&U@|=L#OF_H_lt} z5#LBnJBEo)D}rV!N?`FTt7H*dv5N!n4HP(*iwMVZk_qV>7AN*E|;|oirpj4C$NeJr&&`|@>(dV579SvUx0ck>+!R3!YumO!V zREkFs#ARz&Ftl!EyzT`lBy1@yQc3djQ1s+5;4E(EHG4R)s@P+!$v2*sa{I5x#Dan# z2LOGLoK5LEz!YXHgipekXP5CshHC)c_yn0Q?Ou zn5W~yl>?|c;NQ?x^^+%45MUo=(G_kyBX#XJ2UDr5!fQK;3U?&9DNp9A4tFrYt^Z^S z7hDg%@{Ba4%P!0#fJBnGQ;_}NB5^QkuhxGuMP=`RB1{2^S`6IpS z^W|}RPg`Lcxl4j*25YoZGFUJ;3`93ZvjdenOHWP7rXGV`tqV=Rw-+^1R-#60eidj+ ztd6Ens9E#02xwmmG-A9(G&qE2p$d8%L3HUO2y*}kv#6&>U0$aXV}ofJ(8{@sRv>oA zf`@4Z-hUYddI7FBT@T;yR{25#kRz$k(qF0~$&4AGbkeJ896*t^oAQ zKUeh}=5hA`cIm8X0N+F-)xA9Og4CJRvm-7@k##K4@f64hsQF^xROT$T@YNTjxKON0 z(UgWLY+zf_lv~SDn4X`zAcb|*2)8aE_!I2!f6}U;9h-Jp?vCD1cmi#}&>@$Y22J?9 z`9-OLp@%OYa8Y_eKZ_r@2){;s`IU=OSgrW6Ld4n~vk`f)DN$&OEp~XT^~UmuOHyc< zkBDwo2q_GkA2&=Ris5rWy*`GgUy>RI9{Eb_s5M2EE>eFDR$Z)W{oh#fdq9&qjX(F3RI7#$ zV2PrOfm>RfHsWi3!hTJBdM$q&$|9jS&>&i_HmxelqLo#;1ZCa4@E^+Zrn0_zG6l7K zFs`|$QLgkL1$YnUNcK>A1mqXa3d2E;Y0v2t<^;Mpy;E~C0PM9u!O%h0W=Z?#C= z?fAy$LBY1qp-dO7<{^wO-5lXV!K`;F0C@0x6+nz{;wBnXcR4q#q@g|4^0yEbnnU>) zR?GhwM*+gsN#||Vp=(l+pp~3p>`eB@sr#tP0!CI9Fk3624i(Vw-xSc53h=EKso2*7 zc@Y04bwPze=MbOV<5wv#^tVKpI`$w?N%9|LnbMa%d9z=o)nUC*6&FRuZWf5~eF^0T z@$Y|?IvVDIx4RESg+dESp4@#tvj@%XeOuvci7Gh6`e8 zvMv0Vh<#%*VmEX1Z_;eT2iy3b-=taI(>em+))BmmD#dyy)5n4l{CQQ1_N#>tGB6xC zg0EAh_8q!FG-#F)Dt3~CMcZxnsqOgWP10+HHxk1SaXLW=>RCw2 zuA1+7U%*;Nu-@irrP82UleJi4O+B^PrWD)$4DWMV3gO2~rS2ZI%Hbxjpm?77yA&2( zj!)CaHHn6OEaMKr#K&Shlx7t2ZkhvEUf9dI^1C$7FzOI5|6OVy>;*SGSVfcEOKUaA z+$HMEJfTdA^|}ODr73(;nbe|HwnhD`f6K3s_t{fvB6Dd+k)KtjmWvQ4G&hUCyq*~rY z^y-IOxcQ3IJ>=n^+TIQJ+z+W1y6;T!Ed7(ec14Owp!J^GzN3qn=7CCy1O57tR@mj( zrd$jHw9c?7%a-GX#Qy+w?Qeikyl6Rpa77Bsi2VjGHmEn?F*KH*Dav8!<|#SMybu@# z9h~lS`bSIWQY<4$8(gCP*@Hr8&(h(fQZT%i^RZWP#HJ;me-$^COojtY7m>WwKn%~O z3#jY95xkDZ++&hN??%8`t!j~kGchth{Y>+Y@xeQn~~rW7a45L@lQFj3@N(W2TZIjDA@uLMOtS?!5HlG;X#t5$8m z6N^fB*|>a36gvcWF%3D0#wb)Oo_4AcHEO6rmA+w$A8MycqhgBIs!?{WRYMf5)kExB zt4G-hAJhs)iFfcW2QC7gDIxQGY_SK<_d4HKh7X5sD&TBhUb{r9>3x|H0hJA@DygBuqm zs_iik)i#|FbSg#=9cro^3}kRnzdo99blSxq|XJE!N)~k z_eM3%?j;z}=nFuQ+DVISg-D1CLQ66jw2SBf%3BA~r9qU_{y;yE?5(`k?ErZiYzrxrLOVY|x6@3{I-dn3AGKewd^)#DX^Nj*Y6MEhwX_$FMm zA$u0uki$pblEMPC&L@$yAQBB9!t-z8TC5$@z@~E#EJlCRO>d*g`&Uc}t@|ph!(3v> z3AJ?}hFuJS1&!pGxFzeKKdTm(jm`etA@A+2E- zZE(HzVg$ujicI3LAufmZoMr<)wl%WK=G|8yfcO4 zlGoc(WW){;9$Z8ZQz~}EzRO*q)d%N|Zh9E45|zWXL0c}FVnk3|Z{q5wcJ=X`OK z-?<}M+B10ZE1Q9uj3atnddQ$Fn}~fuA`#4dbnz9e8jb^sFfGGVnBMZNyD;qhhHtwI z7v`7lO5*}+X#;0LHZW*EFtOCZ2i%jMw&@5?!RDA8RLbIbjgXEtHSET+gbW9}u`#$5 zJ8j&VM5kU2)m4t5wqXK;-&%o&O9#aWYKs{T_0|Z9M$nyFsPTR+GL-hApaLd6<3O??~jrT08A2i!N9mR!Y4nj+RgX$1>~-Y(%#wwHa@0A2P7v$C)d)x~|8)=cOf z+M}^%GX0d#yzVcI>SD6%Q&=V$*oEPeXDnir)3nEEgH<(5K1!DYd{t=arxndb@Js|F z<5uG71s><|pFVezOrN#~7eCXVDSg}>9{)fJw|!}`Un*CNAL8Im(@Pc{<;_95G8opL zP^V$rtAL$_nOs-_%eaYb>EnJ(EBeKNi=Q*oavxC2>CtKMnQuxk~f*vrnykc6ooA-Srg<6`L$u4eW zKx)Ax?-a*8+=X^A#j%Gd-;t_IEtsWGRep60WR8J8WznexW4#;$17H9O`$<@QrYL2O z0!nID4)d*#q%i#%e&mtVECdLQMZ04inLa6wiA+hwG2zLH+`mFn`j84EqaYLe;sfcKAK$o34nq%IP7p^+Ey0PS@lA4GH)wUm+)Wptbwf|+D!XlStL%+v?!m( zH>x{zzfF|I2@$l}GK9H13ymVKuc=mWaHH|3K9Vc?S_E{kKL4{lK~1vp|UaQg=n zMPOEdvUM)r$dJM@Gfdez6CcWVrp8$+n!43S@*SkGGx*p^G9Jv^-!}zXcEF3ZwIM)@ zK@*sGNS%+0f~ZjQr{Q!_dz(!h-lUGJj7mckAjvz|f>)zMVo#~3se!;v6lMKD>;$4K zitVBiy7AQd614{Mp+qt#qvl&>%8^JhVJN~B`<*EkVpWOy5`dY-MGt6?wtD)l87064 zB0}6F-J)`K+5H8~nCDQZmV4ZF5?V`GWw@$C@?layO@7sb)v=vKu{0A4 z`>YamH84R)x{9MNIlFQ&tmuXX1T3LNAD(Twcvh@@A5m=%W3=DG?tjWPf&qhMu^7z+ zkepoxKn5%rJ7xRR7FJ+l{5CzpGOV`dXP=#C4{Vh>2J`=>H z`hO_YoRoEa5TI{>J>+BMyJ@guB^BZ}Y9;l7@EJ+FfZ%5qHUBf({MtmgrHgGcF<}W0 z9bl1laGknP_VoR!(~KLHIA19V zoVT3_oOgrZqit1WX}rU|C?Kr#L+7Xw{G>OFgoB1Zy;-uM^-A8>hc&F>hg}81&r-zy zbk)qC_hGHOO}Sn6$2pRk7D*S#ucJFsUo^Em zGdmrhI{nz_a`-nJw@c5-1LP_2sWJmTHg!`CI;M zqwO$uAYDuR%SM5iMPtyQmp>5=f<_8*Eht)L;hlEforQ7oSn!0H=tVzwZF)o!S<$|08s&r2{(7MX^B1=l;ScY#3V7~Y`<8``EO`OpZl&$58B!~wokQ{&`A_}6O( zffQ_*UKR@myt@XQWw`c;cc{ts>X-A|HQ6}*Ts}OA)#W)sEW`M^S51C0h=tg;`$6xw z7~~?>5vn(~_guXY^QZ=)@5^C8-^tCQ7seo+n>o|Up|k?-P(Ib-QV52o@IIjyViU~; z<~1z9k#s(RacD`&g8`Wd0A(#jH$00DS0^K~v;q(;_BmQF%yIR?TONq+P0^S5s$ld& z>sKp#VFN!M%<8i|g(y0EBdzARM+j@uZ8pq zE|&ZEt}*3f=;^MThPDg!58$&ySY4whUS17h&1+<|ppAyW{7YyCsf<5t!q0}V^M)z+ zoS%oX=6a9UK^dHRg*M`;UZJ79aV^%`aQ`JfvKGSui&`wd_TVOBq`};8ppDMjq%!;; zwO{Sl#M!Mji#6D=r{Kckwp*ez2J{CON53OFV;Sh7`jD7;2c40u#Z50v z(Xz5YmI+LlmXu_k>Or0iPQ@ zsxHgW*Wy#^vif|+G`|R2Chm_)Q?3aDO{0a@UA6t$O3d`XAu4pU4=PmghQN$gQWdiZ z`wLC_S&O4Nuo5$W{!j_#=v0B34++c;E$LxuL&7dwB^O;s7=9IzrR4DgB6G3_{`K-9 z93=urBsE7NhP0VbE{gdj7XQ;@n$anZwysJ1m^O(|hi4k7$7_Q=p^!GUI5^v2mBmLh z`tZv3*rG2>vE=u-m5tl0AV!ky`Q9ADv6Vgqjx~_^h3N`J#uHWOhNX*!arHF_;Uq04 z@>Ux?f^4*)(S&Lc?@-4MbPAp;NNs72qL9U|5KX~3%CS~_k6PhUfI3Kq#zBb~G;Gw0 zEQ&On0)5d+9G!I;t3RQ>o`=m6kTLCmz7l^;^j1P|pt<`->Mfd3AJ>nMLXWDAt3}fA z>|NT$|W5d6Ygf==NQE^hKS+L+9L~!UKObd4) zLGC>x2+@?cQoI}Rp52(#m+wCC(Y>FDp^k9vOar-JgD_WJM9#hEYk(b>by&fITLP$l zMw8roH37uxlY6f=0h>!5G^~;Ph*S04R7@fjKRfYSN+)Mm^eOAy|Oh_qUS~}`Dykx9R zT%4WrcgDvzMY9-v4}LNlg8X)VEt-Yu{kd-p>#r~4BV$-S!>SoPCx!)iFr4e*8)De| zhSN>Br2$Nq3i$E{thc_a^I`+m$za$Y&FjRnriL}q+!D(g874U)_X#qW9#MrtGY~ zF^_4+;xW68Y{nYsn{azGmc|p)Yk6p!@9O1ag6^U~cgD+t?A}fS*?qi9ke%pXO_-~8 z{%zlHpuK`8Q((u3Fh@Jlwd`|zbaQLk=P=z|`CyU-$Hk4Nz@*qR3A^9;#+ovzPAt`S zW<4TR?Ag05l1gvQ!-Visa~3hUT~*ck{VJ+n5OAQb)FNn&kQbAKvA9K#mWlfyiBfSWpIBAkt~=Uu+XFox-jX#o+`PsY zwq!5#`3>4%S9u;kix#}o4drcFA^lhn}isgK791Esflrmi- z8BI)1H?=69T_Zby-k}L~GyEZF;+%BwF!17Cgawcgf~G?`HgsDaz6k}i=*M##iF)do zNJ>OJPyH-Hq*u?+Aw3w4nVg^XYRlOb74`S?Q*U_$d1)M)w@R-S42zA~l`~;)sK|jl z8Y@j9FQe|PE1DRJ-BE3k<+4h3OA6Ha*J)5yQFqxg1MLeNtQ6-3VyzZ;0&$N^1(pPx zuoD#rDG_%<4S$vd>1Ah#k_(5!ShGOmb`FsaW6x61E8b#C!P0e^7>&qd2^DRx;A;h@ zL}oOjhWa`HJXUeFfIuS4JHQ5=18V3CwJ!zyH52z^vKAe&HgI7e`I6}5UpfN=e=dCj z18$LvhNJ=1pdRA^ZLoAF!9urqkx(3<|G1c`uze6oYTF#dA$?%`$A-%Sz=oQ;&0%#% zv^b*~ba0VSM!2T{!JZ(}7E*RFb;&igp`KyjMY8?AKKuQ}uT!4-WjLni(qx=azsE+C zSiG-AKaiQf4|FWt=ZqBV;*De%Xk8X`fJ|;Z*|9YGm`qOfbxgZCO}C zDz+aWEJZJ;vCtMaQD+27&RSbll5l;IB>MtLxMGAL;Y;97Y8h|cjx{sPzQV_}V+{s6 zzZ8JFz>#Dw6>hU;!z7JFJUB0S>3LzXkl~mU^^Zl&7MZgTqKLs-5%E++GXJ3+i)#L6 zo5y;$<`U36?94Qd@mI&kB5(0VSjHHBKEQ{!XR%G(t?69Zn)eQf4*D7p@`j7nj0Xg4 z0e{#YbErodKi!`7F^7s&)>yR0UZH;x6_5GHivPJ^K*JCUK8l4Hy5z%nK-=*WKiiH) z+JZmUC_V>))zF{&l0oObXLTP`u!5p){!jy+G&VxAP|a8vPZQ$AidC4Ok#|d= zaHm+al3%V0>m+sGINB%?>i{}5*Yu<%;k)Uf=*g@ zs>QfTMU1-g6VcI~A;*q^c}j|6R92Emq$m#%jlBdYdjN}e72*^x{Etn6zAQ>rCXv1j zE?khx!l!g(by1h49a)F?+gk<11cFG?dSZ%_9%D&Syg^-;G?)+wT`*(uk}h^E68Xc9 zthKFqk?0>P~qo`;C9piPaBVQYb1xhvy~@7M19UN~i<5+6l_r zN#_Ndh@_y#sFDR+q&XUhOxiFRy+0NEhBQa^&{E!PiJQLk1?o&7h*vt{mhdRJ%l-Z}S1)EvFz-uai+) zL9hdK4YgxtD*@m4(F46gQ4T1B)u{Lu*nLO91VQB?<^H z2?)p4H>dIkU0GOP%PbUP+MZ7PC@1iuxi}zOjyQEU4kQ!(wW8YWMQ>9uK2E6hh5Muu z^;u4JwnmA|(I}$vExw`~3kgOpaMlv_d*q^<4Ji(8ZM(6)K7v0fj!S%N3edlSS9D{8 z49{%hbyFe8U*cU;S#AAhz9NxLFKHsC?!-O?C^a_Lnj_uObZab zyo~oYvuGR6emjPQ4HQ>Py01SQqYT4cRzJdpG!-noIAeeGF3qF^h;YXBWBFg1@+^3_ z&kEOP&uw!ny}*KNNE5M7mlXi*z9S3!e8<&4u%S$o{eFN^w9AfDl|BKfinlVD;RYo~ zN)jFX%Zs5+0vheO{k3}lsmAf1Xcj{sw<|pz6PFHRjTJoLxe-3t`#!GT0H#Y1A|HR0 zFLk$>K0aenj@b7b?LR-TjN5N9eSC?6`!A zt82J-GE2eTb?M3AWLiJ^&hRIo$JO3^Suz{1-?7Hbn$;7@Ps@MnOf7D{n3zo605_e!VQ{$4iuG zbIIBrkEAxmsMu#{PVJcPONu=Vjeltt2WH4JxtLNP#2*vV~usgX+HfV5@1BtoE_E zTQ~(@)|@s`kW<|;kazFF29LCD6P1iYNh5lSN_L4wEiAKzd}Ti{Q5@49zMmXzV5JZ| z?xd({7$u5EBCvjU5*!p3Ni15DzZ&`Tdp%fVzXrp8alMA7@WA*rU}zuPG(CjL~1JvY~fvDsGZLZ$1Vf8$2BCVl^KW}k7HwKKT zH)(u=4@21ry90z}!2$uQOwHZBww0ee69G#EShO0;)!~PW?Kvof@C3y4nv39GnWg7Y zaZ_V$CqEU?QcW$tF*TkWlZ9QPn`l8wjBO0U3sGVd4L$3g7ocQQ%iA+ZNsjX$_;<9-j~+$z4_c6bE_b0;L{aN*-@RdK zQh38O8qQ*iZ`jPHp$F6%*t$h|BPi!k@)?#qlOj{FF<_FgRRHuPXQ`R4REH?RT#A*i z`DwAetfizmgdkv@4?2OJL$Rtya@=`}vOQluUIW!DdhsdL5qO^w3B6->B!L~9Jo84X zY19Fr8PB2n(bmGUH5C05MFWwDEpa?&rP!m0EmDu%bXS(@N!9Rt&Q*=%tg--CHmdSW z>ODR;15!LTIRcOv2s}_`1R8+9ABci;Q0o~I@&xo3MM1R?(4V^J2!>-XC>8>STk)2h zPGDD(j=_>}fif<~E1n9e8Sq@cM0>7Wj3;&oL7Vsw?H2w+;I)xKLm{Hb9D%aZS=1A1 zJl=2~0~HmER|h;gHA|k0103p7LHR;)@iS%1JwStG^b;;m!f2;DN-QX7i`&f~Fh9rP z2Xm{#R$TXrH=AJBYONo9un@4v2;h)BR?+}dqnBYczyJn5INF2L#lu}?3(&Vh$?z13 z@Pyi)H21VkXBu?~0obtv9gR9!CIL-yemdwY_7rfjatFcJfP*&?mTHm?UEM`3!BRJo zc8e{1*>ppQEfIi{pcDLopo2}t0oErPa)%zIu@Z%V&xJB)^L1h}%?gntxfznfAvn6G zSY1^uJWhneC}-$F^(eN1-Rawk@I;aRQ-r%UQ~XRH7Phk4T0efP5A(Mz&`KV%fVxqw zT@5f30Kx#ku66kkJ9W8w%Tr}t-#j00_#3gBhnHWeM%K_f z(C%RVrlSPB%(-X)tD_I^iQQp1owBG!!)PJbD^uMeUP{#R)BKBpth4tgU)I3orq6Tz zAlAU^UHbTuHygx0GQ9Z_KR1ZYH`M>gIbtwtp*LLL%$E#d>kR`p^TtDAU=XmGPZ`QK z8=l(4!-uhcUR{e&#dX{|jIA+D`xj@!*(1ZW4>%jaMj2{+z@Hz%HW;S8&)G<#fb3^&Fuh{|z3Gn%FOhg^Wi>E$mn-H=&KHxWAM zo>r!lY~24HNJr{qHlmf~z6@i|{t$Kswa3I&kcj<{x~4_v!)STjyopVN8*6bgSo1B( zk8|?uDeOH%`5u013Bw&Qdw6CRGt={p7ue)~6F!Vz&0;kvGRnqcd7l{B%Xl7NZKkp` z3Y|ZdS?T$m!nzvE_eArhnQ{ytGnGkRX-eMJ@;%OHr?EDAN|Lh_av`4ATFN05Nnl#d zV0Zt2h*O+pFS0m&2r8treEmDz+V+ezZEt2ksSl~tS*#Y7+G;iH&tIR#M*P1|sOM~) zv(H=>C{TkAiQKc553{RbNr8ukRFlM{|&9{^k-3}jd{$A0<$)--TZ!r+=yRU z$o#`Ud-g_!S$a0e?1&}z#H93yOI5%*Bi29rzXCL1(!T@LY101+(2ZyQ9iZ=@`QHFC zygb4AU?FQ^sQJ{>u0fUK8dMXVyo-aq?Lwy*RDlI7$%6=w?|y}~KT6}oILs155D1UrE7xjtzG*FMM~KO5 zEH~r+>sU|vFu%gu({t73pW!yiQD1A)l^C+&fIy;a^O*>LVPq*~oNP zKBc%ZH6ktAVA7vEjG1p$?t#NR=NV~FVK&cnMc#G4^0k9_%{OehM?rJ=)U9l%VfI}fu#Np>SaU~vesWuT z9=}D;Lg(7g*lvBuZ7_|OzhJu7MND^VKhxFN#dJxBv>APglUZu)Xy?L6{5gS_wLdYr~?XPo#PyU=0)J!!wVczOlaNQj-=lWw2SFgDv&R!D{!IY!o81nS0 zjOuvJ31HpzhP!|At$SIp;fFu@#XT&WzqN-&8!WEC#?=G)A6m+pe^g6(`KlIJeAS8U z1N4SjSG0g(S9oC|>&BJ6EXMG#ObfhFRxL2s75G&3Ku=fT<=>siUQ=&41ryVKAp6~= z{Lw!4G`hvJmn*1!RnV8JmTHSish%}-c6~Pz-($JDpA{MIU*?+*pf=|(^HT?y(-7|Z ze)OyM-Q`y;zOL(g)Gyk1;x80G-+85&9ngo2Ji>GpCzy2PLd7v7#d-8bdc8 zWz%9p>uDgded#ITopME>jA3DBr6235vx}&T+<^1s|>qyV=V;Zw-d6IQpbAq*r z*-^I&%4WR(pP={;jjV!_5y{ObSP+#~t@H@K`vhxHtqM+5p|d_nG@0Z#Xup{OwZ4pe zwo|NjjEGVC1*Juwbjf((rtRSdwD$WtH?SheyMvT_PO)DMWwrTRU$Ke*Cs-Y8KMt!` zt^Yf$bzzUg+7$YKhjlmPaadA_)BYU`)7K-kq(y)27JGrV7(&}E3bz!r`zna@U79rn(x_`sB<-|y878#pqiezCZ!((u94^uAok?@I4_)Ise1oOrmE38(j-PJ)p_bgmppX=wvzaU1TO|v-yd0~e>eZCJZ=2{yF9^i zRUTZ|MO@*3EC>3FN=|Z7`fu_y=yBil-;O zAc$Z3nT7bR^>Ft!DqoM+EoDayZy23dOWA%y$Sq8`!+vMFzy4&pXZ~WkMn5y%u?H?* zeg)R6gLJN`c?gq9SV?3~%T>0Rh3*9(@9iP$e)p7h2fbz8X1%OSl4Ndr2Zi|DV=-Zc z*cQajVO{8&zpW<}_g`dV<$jo_+++2;iV>u~>3r@U4B-qHoz7+V*(iOD*UPU9tw5&( zO;FsD1)G~VD;}`tJ!{k}b45JRB7SM&oM(`)dDe*h)fLgUsmKxD)S2TWf8teR*acU_ z^IF7!ru?<{R&>1FKH!V=s#n+H^#+tJ3sQ_7L4$`V0d^1Sag@?+zoA{jw zlXZUt%dlK83X`KlZ`YP}^CM)PHB#2SP*>JPh0D4hqO^RWyXwh0?*_82Z$nwPp^>ah ziI#O!8oO{3UP~?u%>Vkjm<6K-Q)L(W4CZ0A<hT!9TR$V!QYJ!Db z1HPxO>`xz%_1jgK@SE{=QF0?g+%Y~XN?vQCqTJL9t}Lk4B<8ItN3Xl*t=M|}gngh~J8lkNmgj3gwSF$wT<~hVl@@iGzG^LwScG_~1X_O#Sk4oIOB2pl1m)9>ohG zjkDIW#BE(rwSZXpw}{mTt_wa@>u(apLFB-4tO4)XSVJh5V@>(SHnIoX2!-G6pPDZbXyRKx{!n^hf(D5v?|nRm1Kg=T}YTBz@S- zLJiT&HAK(E!(u#M@grZ+T8`jp&E=JbEqnhrNcYaBN%!Cv{7?(|qT$y){DYQqlSry8 zfqN1SJi>N5*wKjE~n_L5(ZQ|tl`hVy%Or_d{2vpZJwWW#mgI(8YBBxo= zjrK8ys9k(YYk8-~_|LCbaPvA=(+f!m&rl>aV5X0QVs8J`OUe5lAz0ova4@}0*B_i=oV*-?ql_U+_f4O5-Yi1u=KeOTk|8a@wc_}o&7&%*I?G~duc z{@l>^Gd?U{u1D>i7ca-t(@npTyfj{xCc-AfOG$ZHKoK$Tzd zr<3IVhHwAn+?ga_)Q2u>ChIP@ly#F^$-0ZJWnJSIvhI3Y7stKbPS#~~ly$##l650H z%Q{;JSvS3_EArKDvTk6qtkb8;x`OUt%Vt?uVsS;5rOCPly=C3MGG*P~ezLB9x~v;N z(8a4~rpi~t8oej_&}gv}ueQhGVKJ6qOe{?Y2G(|$Taz;TXm>f9dg@wtxfMM-50hK) zem!K844lvRkVEx?>S=Ilycu`*n3bdei;yU9AjcaPInwXg+X4q97D^+)G*pW`!O-<> zXJ(pQ`|pY)5dVFoba&>>H>-DMSAMCd+`=&bO&-uoUScSJgKy|1H`J7B=b-J8Odp>X zR8K>0{b;#^@lU)oPnR!H{pAd~Zm1ZiRRa`ES}Sn)Sai?Dg-nL0@KrH6U`kMPj(*+Q zvbSu}*9_huSYck>9H0uS_eB%!{G~qf0Ro$usiDW7DU)dE{325h(;K$0=V$uLF;A9P zDejWWoIe__jRol$If}~(vX66AKY6%b2+5}HZ4GASlnbHYkJP49{W0s{nL7#E#byKK zoAiPH3F7SsYSY%hfwB-(`9QhCaBB@;J4nk>G)NXpu}zaTMpQgmKFCeIWiRK+!E$GP zV9qK*5|KLuNi5uG=Mh8YBZhZY^3tJlq^p>EyvZ;*fIdJAVvz|lh~=Ayfl&6m%ufxI zABx(Ym1}vqxY(b=weryQpBj!W=S3sr(}us6@pU8R<`J&W0N>ob?BCBdPB6VRy&-ie zPa7>qR`qt}P(@D*CWDS{$@gY4UoMZ4LkyD&c!M$WU8+&kSUEyt(T{a~foH;!$^i-r z_{q>madvx3PS%I{y`&A1a&3s5sT?AL&FvW{|I5(8!6!W}ch)LIyhAp9JRrtH5a2l! z3Z6$BD$eln^1Fg#<(`$pjg{j%BYoSZ_feC9bhj-KnDlS!TF{O&npIrpdZtlOZ-+wa5^^8M1EOY+1K&F1XlySr<1`)-B7$ z{*qiC7&%9vw~5EwLbSc|7Pn243yf>yL!74Ra=6|&t3!yhg;kEw8;7bwRPzWV2S#s<-*W zh4L-q*60x4p+Iipj9M&j)w8ebh3GPjqi7bZ$y-|Ga3@;%FTGJ872p+U-R-T(r%JwoNvK-pZ48iHl@i!^N_$l|$AAFO+q8FS$Cphk_0+ zkace_m33Q|$-3D~WL?AxSES#|vhIsjvhLf}vaVu{tQ)%$v(j2uq;;LF>+qVaJF-F6 z&Dn^lYQ3z>eN&6%BVLxj4;(y9G_%vEUkX}y^-H3Kdi)Cx-2bpzZqB!^l$*$>LP_;` z$f9)F8yezNSIRZ@wYG+Y;FfkvQK_f>$8OL<=#_mIMP3;a!UNty=8^v&U*7>1)zSUE zgEGQaLEFhqZfMPfH5{*VBh<{%!)F{3Deqdk{y>t_T8@x*tfDE$yPe*Qw5&JVmRJr3B{N6qS0HLEA~@iXs9 zD_NTWVU|VSV&URnel0~fKYd^F(uNpK|0`idCNpaoZ?;^j!z*S>-rV(p^iOCB`(Mak zu^{gLP*S{hNT7Y~J1Io}HO3B~wNf{p`?0h`|GvM-Ymnq`g31|=P1y#Ue~>eArLv!aa@V0T>lbc)>6q(r@A(8`v!5;W^Zo%RJs|u(dU0Uuk2k{%Lq*DDgFHdzI^9pjJI@f9gG?{9~hNv0KD4{v*m5^v1 zWvn<&Ufb1VeK*GuZbfm-x*+EVUrQz0sBFy>X8-S&r&nB2ug(uvOJ8ZD#y_^8WAvwv zQTM-b(;quWe=A|7=;+`4Y^X<#p|SJbT=RJ7AvL6&SvW+w>Egk zD$JC>k~IEbOB(YxlIHRklBQ_2hsk@cku>|hlQaj`Le#B;`t>b@5&!v!q%71N>V(f#z+J=Fm<_Gp<6G=661k$*d}OLp)|;fsYosL><{3*s1~j#t!TopQntd0Dwz%TMfU++ z|EsitM<`fgAGuSC_NvnY^Q5mgOF7PCJEiv8!1>KomCpDs>J=*8EAt=l`o+>05v5Jl zS!_L0Z0nPCJ&X*Am`l;@>X%}vpMjD}<5711a6WLiB$oIm?v^@IL00dU#_MJ#@Sq>1 zi#-J1|4@%X3-g4UjSTgv+tN-3VcYs2R!amu25nfr>+xZGFuU#Am|OQsJ9V$bbDw=` z<9FC6g+0B*igppZBdQQ_;yyI6K3=HOv_$aEK4kLEM*Q(U(E6ewS4yO4|H6jV;i$*| z9D-0uD3yY#Oc|w8Z?$pI5Ej0+RPv#Q*itIB77cNIzhogiv_q&5%7(nEO%X_I+c1bY zQx8a?T3u4CbMQeaO&f3{T4m`YDobz13s7a!8eLK}AACr%s!2UOgGKVPL#kQm^dadv zkDj#&qt@WVl1w?6co@n#r7ScnYILx4C{2Wky+<6C%-+S|I0}#}B$sYkg!5sAWEN3O zM^&{p@u<|W&NJaP%#TdCQR#|qO&I^>n3P6IHaM;-*7IS( z<>^yVU6V>Bv6xT$Q5GMU+EWg9ABPP>&AIju|6qM7!lF<9S4)X$2xYU^N$I**PO!?V zjh!!^lKN{y4p>BW8GRm-1bF2JYE3m^B>s+h!{k)SmwTOodVRvox1N!j)mde($^FeU zlGqQ>b(CS_>@vFZ<$4UPg>Kc(Ac|nyX^DjvC$o~=ib&fHS6*67yy&x6qe3-g6B-B;umW^E_LKs&AOQy(XCdsQ2}s1$l`nWUM17;?5k(u_SIY33hQ{@7J^>~FBnKawW_%CkAv(a{#~PdZzgY{@q-w zW3j;>7?@_OH^4qjGvAkK-ZL`I(K<}n!Gk~ZLqQnR?2r-1#5DK(nPy*IHINU{u|@&o zPZ-HaPDd?Ig$8JpS$vs}H8uW3?ryw9$3E4aSmk^{&sJzdt{xS*w6}kEZ~&&>(w{H* z;}K0~h=G-8eT_kg(-^xm`R*wH&=uY+rEae)H-$Ofw{HY8vTQ+z2xqQ0v+0BPhB8fb zJ*HWKUsyQP3=hMu{BTdky!_a6#<*c1y^>GzVeVOwOUUGu5JtS9(<3llTX5(^`7$8|w$oG#`xpBTiV$&Z4x z`u~@~i86elwU{E&Qc+CPCz@$`#xPC2`b=|{9}NK;&W&T5;|-antPy@VVqtH0z{jdT>i#7|UfbW4?(ljBI}5tK&4-7wQ>`Iv*d6%JqHSxhk3^XoF9pa4)rDnjjolEyM4FmP~W3 zwI^pju~?MM?227Eg?p35MY5ZDzgX5N&~#Ac5AO~*8BPYQxK4a&EQ^geci<-3>@&mg zuU}{yUh7787#iXk{3>Eu|2oeD1%BvlyhR)f*QFicxp620{8QuD0Q#22u`%>*)qu6> zOvB5+_|@LutXi-{2w3>#aMemq>?{^aZj|06rBQ*z{-Oa(6r%l1LnaK5evMdEoslI1 z0V18ZX~ddYn!vB7vc(O>5*egHW=12nw@$BpBEvL#XU4NGbquPX3h-7uYaL#?SBOh- z?Vh~$$mRv}=g${Q5TvqRj%S^zC^3y$PH-eJk;6&h_%}TaEeY+0REx!pS&FdIQBfjM zV`{fVCdj;Vrm-O53~j~!`_WL&4~dX_7#SduQ_tTQ5s z?eWt6J;eD-TQtVYa#bza1H&yQH&g($EH=d}bbQhdhaQ-BS+-TWomgvIqNmNgJ_DXZ`iP=AERnzX)9B|7=Pnpklv8-?m*O_3 zxDHDb)D%bn|3%;{n?0dXZyPbj9q~2u-!fQx{n-BgJUWww>8JEG;+!TMQ|GFAk*K%&VwAY#%gtAcYgI- zHLf~ya5Iw$@k$Es;J?<<{if0%d-?f-A7N5S?8XeX;26|E(M-I8>jxrd_2kROlYLSr zI*n13jlo}vjTX+yaE5r1(@y6c;Cp`)dVi6f&MUxoC`yFUi4*u9Z@+`E>?r)=;azH= z!0bf)lHr|hs&6lys4TK?CLbMoD_lnayWztgmQ(~3UP6FsaDHj4C&jj&F$8!5vf5xszbL!o35* z{@wT~D{J-)omZn1Ds*I}MzT!1%k7qH1R%f>JbKP0}&ctlQdQ?&B4N&`)&a0__ zo_7^Ky{rMZTJ5h>aa?`JsJx29-mL~xkMUupJ}kq*-q;>|VG$@OER zPU2lFrV|nR%dx+W{<1uq4bZ0YYuRk2_7m>NVVAVK_@rF+m-dKrXb%|SwdH(x9{beq zo$mg0yv$@MKf?Wcu^rmc{9rFAH!W}TYrR;4&g(W0>y7W}TfAFu)=;YMND)_11Y_j$W@79M!={DZvK?dz!InMuFlh%)ZDUYb!f=2g7RMJJmF;>K`zzf`&|BtFO=jN6!> z2M$l8$96JT;^SYG`B~aMqb}c{4jr=>1YQ!IW6rhr2+6c}#ck64aaVK?oTtVm2}1`M zF=B`V&#@xfP;nO98}xA{%Ywbc!8ON|2MsgNKfH z^&+g^$}gjgIDFleq;izJ_##o_v-+_sHoPRCmeSLwz)bmVm+oKSm(eb^z?ji)v{$|l z?qwT@@@vvkdI*fJ|4$5@80vff$J@ACp`b_ML;w6Nc~eGQ?--L+C^){pm=30;@qhvB zoGl{_=h4$Pdqq7Hl!jyJiVv#LT9mnzySaHlUYFud$8CxNKs1GZ1 z03ifx(GPJ%)4q`-B%>YLmMUP(tNG*P_)K0+9tk0dv9c}mwDL)R>Lq7vAWZ25c+ycC zQzA#vpOTI#5pY}W{f6f_a&f1@9y*Oj`PkHyTH-LSYgf)Aw-ggsm{Z8rnHVn?x#dN; zJP0x8&9I{V2HuiQ1ux~;EA0I~!%lI zy3{&3)4msu9Gu*{M^}I2<&5$)d3iA*Qd)I!!GNcdd{99yH_DIezn79600rEv2brA9 z$3DxVY$84?jJQ5Z*@>YBk4RIoMaEC@>4>eTfInWVonmlaApcc&gD-x$*Y6V${B}c7~CJ-bRed;N#rV9J_5^ z&m+?Dl!q#aC9)AF4GIZF+k7P+$?S<#IHf{4ru-qyLwz8q!$X&j$6`+nakw2+HFWPqW=|kf`bbns0R}Ef@*#9Dpby7cdkQ+N-0v$Cno?I0&hD!sz52iB^f^wI7U)|Q z?{OVs-nI0cn%ixlxtvqJLtThbv`UGc!z%}~aUm|yR?mMH(o-iGK-T^U?d(TBVF>FW z{f-iNhTTE4`40fK*#0JF5+12Q_iTC?2({7iy-s4hRZmTe5u|J{uRoN<=|X1m%%OOP zV%H!1rJE^rlD8V zTg}yBwsSteIE)3!&qL;B*ag3pD|PB|ui@;?y8DL{aDOJf;3P)k0sM>MEMD7*R}5#% z1FMGpE7SON)G0<;q zj(rB&sytVJKgYhAhAZWfH$o9Y$B0|-k4Lf$+n=oC92@SYZDbp^H|VI1g%VaHyXjh z5g|m`pF=%>sdI}_DkFvd`+72&yo~6I23?UuXQ2UNh!I9lMhwc~YMn|jj?CE^=Xx7Yl1W#+Yw(@UBv&iAwp&4h{ zFNmitE(kfcgPN+E^3RuvzahvWe$(wf=tYKhRcB{iKh%6^V+iT#^v$Fe-_YG?1UEJBNWDJMVAQpRdu!8~B} z9#}Bue=-}7P3ZT#FK_h<85=}w*1E?(?yX)?uaJkjv3l*DD?)%n8VVefiqrL9I1h3u zYDj;9bCm~-V?l#Xs<0pd+b=vA;whnR@H|Oi&m80=3BT&^0JvrRs=qn*1*&>`jOLFE zp?)qH#}b05?r}A4uKmV6Z(Tm#bE{A~_BZk$$D!{}{g5{u59>$8i+uQa7N*6_Y&^@Y zhpU^wx`xL;h&g79jr5U1npx`T`hmMQvNqw~-Utfkg8{Cg8!o!oH%zKSm0$fb#} zV>TGi8&726jl8>)mT)gWCIjd3^UzB$*Q`)lK2PEV0P5cr3Ksb%PGm{lcl0JOjryK| zA(BDGtBzQP35`&K5bNS|Mh)G_)RpoRgQ%EAwbO zB^GIU`zZL|zC@^A2^Vf<$it+bYq=Xix}IyD^(V7mwdQY-Bh(W17SgjN$kmoiqcdnK z#AtBj8mgtHH!vA8WqQejicw_--!;77G*;j5$Z7=A)Zz4Mr)?S=qG#j3GGT%~;27oX z#jl*M>8zJdH);v*FpHH04_YPAn=0taY1OncSMkuh{ zu!O~je5HnlAXIusu;CXJx}MKn!n)`?wKDSEOJKN&hU3B#wn4u=-pJo^utR~@;z{~u zlGKTUSb=T6fph8`tefA+danpNzbyvGJs%H?45kg1$MAv2D+t(|fF0DA=r5>nC&Akj zJPtY)@IO}JD+wM$aDT*}LOydm4||`*$$xb);vOMY&-kT-k>|e8p4ShA!}&g2uU{5x zadW@2ytUC8_7S_G)%T7vI3^iF7O5JnkgntCEeo`2nU5F zsbOSo`vf4RPZV`6ngZn;U^*+XC=1$S#Mn)3WAl$|J-#K8RFq9F+6H&(Wuq~yCDb=VMsW%`Tg?9W>2CYIwbGdolkdZ z_*>saPRg5Fc)&Vlww*o!#Ygu7{z+HyuPXPZdw$3FK@!uARTyxAyX+;kI-`_9xb6>? zgCf3$QqyC=4$B+lk~539KzG4~Q%yybS%{)Et;V*@R4hJlM19dP-cV+ zoEo9bMHIz3@IG#OD=@1FTktB3D<83x;RxJDky7uKM&%FO5`{~=HOfJ#F^Jny#cqn} zJ|&Yu5p2JLb`rW0atLuiGV}X8YMv>Ui!NMO<9{ninowfjY1vyel&dh6WDAuf zm6%8_qbMSLHliqoB@b141aft#2^@+*d26LF2ujmN*|umZp_-a_i2tqI}iLqr$% z)XY$$%ZP503-^HH7TA$B%0+Yqs;(~u#FmOk9Z@adty!p zZ3SEFMTuwOX&h1icuz<92{?4EDHNpBVC8_mSOdVyA`mN-;+aU{k-r)%9kJ|?FjdOe zYLwvWI2ZaL&Rs#gLUGLG0Y5NH`WL8-r~1UJpyHXEx>h5X)$>$*$$V)o?3fV`*^qBh zc3eVw?F`SvTln}NSh$71bJMNdQjinJ7=*x@>B>05-~WNd+IG#o=~fx(BsgEKf^1BM z<*mQU(<0PbrK>JcK?Y?5Dq97`t0>a6Mrv!1Q&D84#mI-CLTtKN(2JttR|$H)giIkR z)yTRJ0|`47uz>=bLd$v2jVz>XL0A=nh$mJf`n^4-{6=bzpv&Zt8(9g2pE znrYXB?M>n^?o>l5vo(< zjMgtQ3~ylJsZJKD?*Ye1C$s3Efn%1FHPY+h_{_-?Y!{vf#da%b+{~W}iG2lr(j6MA zpy2@B_J9IaP!2#E4aW*T|}3Jv5r0?ribpCNm^i7(oMeGTWP@)KKFtGcIki_9+yqaI(Q1sv=e1yp&5(f_*KuGd6JevF2d~jYff>m&htgfZ`;~jJ zgH+;~%KIp4doaT9TiG+Z%OCNGZLD6qs#kpxWj~1Dq6Th&p#;tKiwaeGFY(3mXv%ST zbL_>WnMQ4mLUM}b4L)TX`i*@HX4V8&ibO-ni;g2WO_UQfC)WhO;0a#)bZ|dhRHeqw z_5|CX4qiz7B#1W^!TA$v2$#w%vK$|csmPkT~!|nTTxoPwMe=Kr%?Au zJ}8ZlYita^MB!K^GATxy_LUmS>RY&J2Me{W79qHyb}L~z40}kBw=--%Yu3n%z91Ov znY328;W-o;Ogm6HBDg`?4S=#&xI6xAq(ZlOc9S2jrK_KT!u7#pi_$@Wq2Pk-ULeDy z3sY8l6tptD1d6iLN_%5V7djQJ_;6M*%R z7T$0tYrw{jHsM|5huR#6G0yL?(GS<<}ol`W;RFsa{8?B}krN@&4A{PvZ83%4M6=T&qn;L|1%N{1%66xhm zgq>9$qjy^Ee$-(MO0UD@$@WpKB1dIPDt&1zu9;LFI+SJK?}`V!TF;?rqlvCY4iPs% zW}zVVKj{G=m=>Fmd0(GZ1T&{)?{JbMQpYuZ8XIK?MwW>fD?oj?s~tvQtKFCSU!w98 z72e(xWjLAI>YjUmDPw%``dMv1hM&a24$3hqMkd<0yFC?q4fLs-(1T>@>O!Hx;%mYE(S*OcPX;I0_{_I82l@eYL7T(Bp@xVi!&tR9aEYxp5<~s6&J0IOQtz zYE(Lkd&=DhWvx=n3X4KnroB|zfxb-HFwqOB&)`;mz-@{Zvd9gaFw|DmSyT@G;r{!% zc*ry(t~JG8 z)zP#J?~?pHtx4e=vu0jB$XSdLr*iBVSu4`qr=WqF+@&cmCr|UW7VZhLru;k=70HyX zAVr1ABjXAsfHDc*6FIES4q$O~TD-|r&EZ0i&#@l_xBxHHTMH8*R&vo}V(_SXegt?x zldLPSWZ}gG`vGP0t3vr$RxG4XEAe?J>Jy8N7$)ior_he7WkW=DNnfj+qCT$bVq$`U z-hlR0b|0u=53r2j5KnI)4pH8Qpd$8QDrYD$XnapgIz>#iGoU4XK#h9auob&P!}yg_ z7U~OGVh^<1vv9s(Kih0e_2h6$6t3saA8b!c6ec0my!}~pGVxgE_;}F_$Qs(B1KQ%^ zv{-SM=&V4DcRupg8}$Xv!$s+4_bIgvE>8W~^VB9O%xDEs^TSB1PevlNhafdAwwPD! zXEUHH1?Jju4SkPzo_Bz~);q)A3ol~N)Mmz_c5f!pyV_Q}tEVHpcMnJSxlDVuIm{YaX;^=5tE{2&{ZG;<-0xv0AH zS#~Tm9K=8ki5{Sb(Kgp~3$AQaW^B4CEn$CV$`QnFC#N6fhYqrqE6P|?8%=6z-cs|h zNot>dp87lMc)@Kys0!_dBdPgF8N^+?RQp2*@1gF84r|SEOlwUtATP&0$0w~6YAtY! zruh_2NGvSY=C>BtX=m9l+NILH&r<4<)%td|r56TX0cSEv;bP z8lm=KaC;8jajPc$&WIM_ZBV}tm2C*O+J~D+f(DL#lcb1!uu1uxz>CipT!)wy0|vz# z?sAOaZymxY`?x1xcZdb&3;@p}k(~>O&xMs}v;a}#iU@mqf{w$IyO&hx3T62d#O}2b zKj_H=53|PU$tEZX9}K_a2EF!+&gVa)?8K`2X~U>a#9of(WDSmnAD?fyzJjIWsk3estZBn`abPUS#Y#Kg$9fB8 zOx`0Bxctde3H-+2t6;;m`TRizi<6c%5p+RnF^wfikVOY$ri1QYSF~9*o-1<>e{h5~Y1Ydh75T&9 zJ8rROQR)J({RrxA0YDIqKcl_<(b%HSzU6sGS+@2l|L`d5<{y0V3yF5fyB*XKGh)!x2xlUX+mo;o7+yXc&R}IERUPcqyh9WlK*gmMZwY{ za`n~+HLWttwT!z?usHoBA4~>LvIe$Yc0Xd@47a7h5l_TX%_%grQS5Xz(lb=>IE}T@S?pzQX^)DjzcB zOTPhLnM~KDx1-c8NF78bsYHUBb}SMUu%ssGMD6_s0Hx;NABYRw^EDdHR1867%A*DC_Y4-kTr37a<6r6dcKOgx!$*#)6UgJvurO(YV82Mp&+TbE`wZ(AmSfV49a}Sk zU}-gnMk2iGGJ~%>J7on`gw=_yq3sk$|2Yg3eu zGWcgcUv`$I=pv@`qi0#Vexe?0b>~>mvEwMb97PIJ%BG0yL^-VP!Ux6~L(+Bizo4`52IpC)lr+L={XKwcCo`C~n=vBc(a!VK=L{_oPSX-Q zP7G4r*T|o!@A=2)SycVUTC|_ndqTiqu|_I~UpcUWifK3o^V-knStMHwAj00Ku#FpV z^&5-K9!j3P)xw0Bs&reA7)6E=1WbXOq*;;SS&9cU6)D76nLxRfa=e_nK?`35g^>Yu z&DVVDPwW?6i>&sYM!HIpy-nYFJsmc}G?jx`T2v5LyUCf5DRM>F~5pIOV4x7}tK zN7oUSv;uDIvcQI#H2Z0{Wxy8Hf?b+S7=?s^MZzd+${BUz($OBy+zYI|*7nao2p{p4 zD8mav09%eh79e+(naC?P9lMpwc#%d~LJt7hrQd;1^DdK8_8o|p8jb)!e+WBT6Sh_j z+wKX&qPs(SheD~eF|b;YgH%;+yo8y_%Lr0tA&&AKQi16c=!1|v_NbkQ`O`)*iwv9b zfo}mmMTYNH&m!_f#HgNE@lkqTM?S%w=%V|T0vKcM20h@Qn2gWjVl1~n^k)26WVrgb zSyR|fQ_zrqbcwaLmBA}`z;*dsOcbA5bjlkT@>;1Ci-;zl6+4% z>l5IpkJVzbdK~6$M3_jCpGSbw8xJO77g|IoinRN3l+_ROAxtshg{=br$6E0~0HU;q zTMi;Sa2~k=49}{cQR-&`K5B+re#;$~S;IOXzD=U)pmK8}-*K6R^r?7+G=E%!3_GL* z!gh3cfEg#XpFwGoEef(4IM$;2$~HoyB8V-@>H_PR>5$Y|dwm0Bg_6|&5|96d)sO8* zg!2$%@%fnng^vQK!FVB!0I;aTdzGEhZ!#Y77k*)3-M;D$s%Q-?XGq~9C96*no?bA> zggny=;JXizfhTom1XWczMM+#C5D{f7oD~97kqfhQdGRM`#2kA|OzV|zAQP)4 z*kXXU#N(f0ri4|^2tuG-xswI?GoG|(IY2||vK(MFL2u5C!Zy&;*>%k@zP z5j~H^0vb!XvIS8g?-P~vM5AGrou#dZiV9J2N_iO@lc3*O)E$+cooo-#*-N_l@Rq+> z0{M`x`alyV4e^)~SnX)mEFZUt=k>&!$u#lm3tUm-qC0rBa(rBme5>n00MRvFo9jFQ z3HC~~pTiUu%i5N2al4A!phXN|2Jz;s8{Lig;`(hv!NxAklRT6e73*SYL zZy*tlQtdhp%LB3`koB)5BQ9QRwb^}@V6m~QI@*EiXoAQ#_-MZ~R->pesWf>{RDQ?o z0b1cWaioLJa{SPZQl?F(`F)gbkYrYxrcKNQ>OA@jIWPykGsAwA zYA%_CP!zpQBJ}|=Do8RFL^+8JBb5-U@ni*yNuVbs0tM~!;1UW0YEj5`{5z9fk-Yg8 z*pb(#3MRM!ZANjOS5eSd`Di~_da$1Y4_L*5Sr$8l4z`K#cKXqR!bQV<^Cjg6Ahq=|S&XvU9F`x*U_v$@6eGx_E}Saf(gMMt}&h%csJ%CjxkWt`PtN2703&)(R$i=$qhK}M# zT`W*{=5v0<#iFfK?jY)sE@FO}As9iqg=J%Pg4q{=VuHC82;i%5=%ahd0^^X{A*iPP zT}!+0o`13)krlT=ZO~aYBdMrTdC_at8Ts`yzU@z(o@{WIpZybaok5&cve3Yj&r_++ zP+3z&yDs{Sx37f8S$PYzrk{C2E5Dlv*Q<22sMbns4Ez04ezuZzN$N%DKb?LGJxidE z|5UBWRALiY&xVkNOH|@o-s36@G4=<7eGfN{35w!NuClbql{Z1DiHDL^6yne7LVW)p zUU?O@d6)ZKV{Lr>Do7wk_*d|**H|oTXVS=nj*ZQdUp}I|I*iY_hHXxODFcS_FA=W0 z^$9<8jkO(*4XaY_4Wu&pJyMBO%h}%KJ?N-{Yau$~Ax1W!@Q@&LPN7gFO*UvDMZP@& zA9l?Y8Dc>JguL*Pm+!$zBV{*^PRN@?FDH9L@*Y0-FBa17hh)(yFE2o6yLuea(Pj5k z_kFu`;5u^B7mMlC2FcV9z?|Tm%PaZezgRO{6*h~*h>S6SF8M1b_04`7Ie8sw54v&- zP!}%=LKT)5twK%BZ;wTz58+VLKz&P{D2)S@b)-Rcn*W1Hqd)dcsUTW3_EoM>wL`=1 zOjDn%;S^{SJE+1076hGGjW|NMbC6{cc26=zk?umbgKgYH6vZ$j2^ef)^A-Z3`o!Lz zC(%%rU5JIUC}a(BNN>$YO??OrmE!OQ-HjnDj_SQ^)M|gB9G6hdv?JqX;tGQ{L~v__fo3|dR5 zwI{EcH5fEJ^47IzDmts1BXyFkzvC9!h zK5w!X+7v$ZCTs6C0s|$#bc2QZVPS$I90;3BwR+@F&FaK%1Q?biRU?8qra$Bmr541G+-Bao z2G{x7+pLxCKYyYTnjWD_^)R!qV6?OEgCOxe={XrGzOcBDPBW*ZndYhH;WVF|BCjL% zG_$+7D9!vY112d}X^u4FkS(oEnB&)xUya6ah(5ae!40?dU2Ml*FwtAqWZCow+?Rp& z8PLEI8Ew$}D{#)jqkJLcJvF2Wh0s}-Cm~DK5EF%bP%C7y8gdUGWkIcwIcmsH6!JVm zY){BdQGxP@qL8FoAw$)WHz*{uR!AQ;B%eZXQ0b{`XQ?5BDCGCNT0w2q zpi~MfdlJ&aC~L;yw-CP%@!N#o5&Ztd&kMB}iC;2)z47DwqkS{|d*(ryRN%O0*E|gm zjq&aFW#S#CwGrD?uQy?=&%j!YqfMQ8ei|%3$j);)_It9^l`Ci7z=}kcoOv^Cey6Ac z-z;|tIr8t5&&TR6Ay3u(PGC3~ob&r35b|p`dJ-8s2g1Y#{TxG-l1ong85}#%DGSKCA0Z4nz00WS88JQwcidVPEWh*biD`@m8ih7AE96q&3dKT%vLmlm_&6 z*?C-c9#$r|eCRGLehk~%j7i{=n|Fz^>`NB<`^!ib7oMPOcfur1WdaLz#}Gk%cUWxpQtpDOPM!vfRbW2tczEE?V`- z9?C{}O52GZuE|NcJ8h6^bwiX+q`>_~8qjEHEM<6yuN7`1;p5|d6Kqv}zL==me866a zGgImEm zRje%taO9CqC!Ap20K)~Jqby@!707_=rQa8Wzl=89!-G>Kp|doPR|I1{75@OhH$x z&7-v325m&Sx}Qca@Xz-snb2M^%APJIxhy786A|R&CNH)^Nxg~OgV#x-W{?^PU7$kQ z0umVCTafr4+J}-7nm{X|1Qd%!y$WR+k*A4GlPB3jPC-McLDe~?%vVo?4)I6#ScLa) zzaY)d`+5EQ*i<-?*6H)rb$UpW2iDPlB3ny;-SSW2aI!myuCjm6f6upIk72n5d>EbX?T z%62UPab-Ia;=PuI2J+I+WvMTS{(Kp^PgS$k8I*p99}PYXdJHKL&xmS~DhTTwG6W@} z)UX3S`a|@O2_2l{YDR5HEX2n>z+%pN=b8uXb#2U*CK$h9R{ASf*j9~LNi$aB>I}6?dlfPNG@0--$?1u3d_`bhc>$*u7 zC=JZZUT;b~QKl^9e*dsE-J6{E_=mOgT@{bfX2fpN4#sNDc#cZ;<7@w6-9m#fuR(H6 zkX&crpcYO{LUI?2x%`;5@~P+Lt5L3a(=`KlVd*huZkvDN(;u_6(0=Geh!};4FE1r=yC3yxIL zzMlxRojaE&%H2YjtD%(E&IW==9||3|bNQRN=l#f~<=@Fgp(kP6^N@HPCy?Hm0Hlv` z7qeC#rfdEVU#FEDYD@TOt^8)aHD}Q5*h`6%tq=@`kKt7}p$=Ki7vkKh|13bX*h=7N z6aO~fq?5-s(Ey@6Y9KZ{UBxaY&8P5@cItJt zaQ|6DJ6Bts;+4v_pNR7;BSQF2gWOVg z_#D4!kRx;vC%MTeH?;kE0@>U@zvJ)t!XkVgpMrrf;ZP?$2#<0%=Bddu6#H)hq(XnB zt{Z(!IO~O*w0t|f^rw960YMf-iJmxA#h*mcsb|iEAExV#M%kiU_#HoFltXmZ6a0!% zj?tZP@H*b|gt)d+lDJpz*TPhK)?jXo zR54HX93RNUk^eWEiDfv;+sF8JA9J#H1bv0ziAYNn|S*=a+|OhgK%v;jI0;wbUE!(kaOw0uVvp6UQ|bR^lyH| zta%xWsdM8J?T=``z*Fm3mQV!Ji}!^;nyeG{C*uYyQkjnDQ2pcwK&DkyP?{IiX>v-$xe7kfPfoIR1fsl2dILxp5E|7p!T4Xj3Dhtj&@?#%Yn>QqEj!ye*!<)g60{FY}i>g-tE5wPkYjZc#eBVN^N4>Muv?x|DN&Nsi2l z0iNAUtEvG)7ZCcu=pU^UjwGYQ=@1UpLI;ceQ#cuR!{x&$O>rjaKzL5>{9!&#lGBGf z0M)!4PBUV=R0NNhedU333Oi1rFxwvp7(oFr0z{#tNypT(<_KgI+=OnDLa6wg-?1sV z^08$JUE)C&w=lV-w=on&kM7BHnT-2WLg0DS<1U#s@?c@aS)E|;5IQwx1GIx{X_jb9 z?;RvZD(SuY!-OEhre*QfpqQb_BBmDy+$?LbogJO~BYbik{+Y z5&IgIBUktZS&sECM4^-`-*F$4+|+C$)bnVYS%U4Y_KwCfZZ*mArtnZqr3~c@mVhNESpxcTC2!?EOil z&b1FSK{3m<2W1zT&q0^T!bK`dvc5v8xlSy-&I>OJ-^ zZC4*mhTTR!?{nW^TL^7HN)+aNdDB^OJClXtioFwL!!MnP(e5c5ez&z~CF-|ORQ~*sJ{4tx92Ldl0ee_rd<)e+o+1U85X+v;he^s;*+3;Gh3vpL#Mos@OFq#o zcS@M*fs;;;c0H}^MmP*%*vW!XR~ao9Wp2>M%5nUpS#D}0>Uo~cqI99#`2gys(uw}i zZ7zO=CMc#ZJ{avQw!@Af)*h$)p06e^rZ`FW5U&pmTVgIQ)&Z0_)BqU=;wfE>wZ%S| z_3c+W22wmxo9#r1P0gr#H#Ix7f_zkh!@Qr0M)N5cZ7qXf;!;i$6M$5zwWu{%&rew- za*$8rKx_*gr)E<<#h;FaPVD0a$Inlz{b)yq+m<9 z>Cff$m_H1X!)$a@A$VVbMb@*k6f()O&;$$Y1>y&?z?Q?2n%rJqv=0sso0KV&k|-F* z!`2GCYXuZBmm-qImiB>8oJPENnEC+p_G&(C1r!pMdCHnZ9R7nud5)U+&DInNU}UH~ z^|cN@^jbOE4t?9vMVq59R$l%ZYwVklLKEoVNU4E>G$Trk|0R?=~s>(jxPeh%qfbO`0MFQDD8-)aoxi6L@`?Kv4b#5~%G zF$JdQ{E0P%9^6V4x?m7(fSv?$wCv_#$K%S5F9ka`ARw(VT@&mp!+NTW0nb=@@IY|RJLkA=b>S8 zn*Pr;KRz@}uCG@>#1pZru8h8#>GW!YY6H z)%Q`iWKmkYuATFGxcs_Sx2KHHiInTuu{q%>6|GMdZQOh=PMwL`Q(#Do#{O(T%atB++|)o`U@k)~ zS{EO~LF)FJ0#Y!yru#WpHINInwq;t3i@RWqhPb6}*a1!T8o^dSfk9)I77>g;fzd^g za|u>h1IrJ=F_wH{$H4!PiLXrQ7Atav6eALG^lxi((V5DW`hb&E_OkLX8_80z4|2aX zRRmTjk7Cq7eF?7!3$@r>-MahMR0*oaRqtQ^7XR|=Yx_x)qCH4)FF~r{ybS7ryb;2y zqm9_)4T3kT2&PdLSr%T>>G<$?Im?!T?4!j0pdwv9D^Ocl)~AwoP~pE5{Kj(HtzInP ztyTD8f}aua0|MSug>NKyG2qyAk~PUpyAO&iRycBs4CK!#lDgxwr~2+i-l(x$SFQ(; zr@IN>GI}BuRcor@L^-nb$_{s*721@ZT{O2}pH}=?9&g+sdElgU_#oG`F8E@P;L< z3ao%0?~rz_Ya{;ve+>yP=84srvVEx9(Y$tkt`H0;3?Ha9Lr zoZ^V0BU3(|Ru!|ub>d!M`sx2*SZAgyY~^c;OD7RAYjO^{Qc&%!|K z@u%FFF|fPC->7uDnnDe zvugY2q}KAccG+@k0bGN7*7nPJwf)|$efb?+wqP6luYj_CwGp=ss_kDrtd?KyYk2QZ z`N=sr_-8%scg2pZh40!^+i!NIjH->`e$JQw&`G|j4{YPhzv?VU=w&$eca~kYIWN>k ztv9*0KVeL5|M~pd{*;!r{nJ|2_Sf6^@af~=>OMA7Yv_)d+cHl~lcQ}DX4a1M=#AR` zdjCqK=f4se{jYHTukbk^)uwm;(^~!jdBB0Oa`XK&47cQ7xK3^3*Zgvt9MNFZH?`16 zVn3=4a@lc3PZzm)pgXY^sw=6LFW$hDt@P zpoJ0|FcQZWR{72#6x~khz?Fub*x03Uw#<}et@e;JwX1wt8~A12I<-cg2_bcOYpXm@ zm#~k2Z{TAr=X&u7c2*fk%XBYy}5W=oFTPuqjbx$;84?BJTj#R|53Q^5og zv8$}KFB@s(!uI9;13#TBZ?#Q$f=%7s^=O+sy?4|Oj}5FHUhiN2UH|fr zHrK*8xV$ZOH2iM1+)#J(7Vp?oenD@jW8&ZRl!xfQ@HKJYJo$|Gqjf%-60anx6f=*S zAshII7j-f>^^&(~d+|fPcF;>8!>u%Dh~VqPVs)dMx5q_9k zLjk^p70WX?&!gNJ&p+-hN9(^1_vJtKmS52Q{fIa3BM-3r@s`+*H{bHq9I=qU-$%}h zY>W*AIinqKQgu2k^?)I62a={BiW1JXedRW~Qzv+GU%5r#-T$D)5-!me`Y75$U#@({ zXZMv8+l)E^VU0V94N!tMjVE=!xH5jHumVHZmNFOphUHU?iS2=BFR2tK6q@skedXC& zJs;FhZl^uKm-Um^hMpB$DM;7>$M-G%LwAwY!mV@M0I-T!wK4ysgxBuW@u`WtCIG#~H;V%xAGyLsOAbEVpP&u#r zwm@iuWbUJ6KJ9WJ5yU(%0ZT06BES90Tq~d{`wG0i*9yDN-bb=VX*7aHrwV0hCyG+8 zI1lmx!{q*1^`EAv`=9i3a%GE#m?cesS7jgs520}_&xGj}7cwUQrSG)nGKKL)Xd zZCx?_?uH?CW*SYv(HykcH?)f193@+{M(#aY&S<*6O4d}u(7NBS&Oq@Y zf$UR_Yv^Y03dd*LDUkLEKw2Ts}aKq=p;m2 zPz`1t0Y|HtiPf0X2>1qJUK4Vkit{DG+N+4k)reaOIEE1S)*xOXSb&O{T8;RCfE@^t zjBGZwh8jEsP+2Oe))NM zMw8YM8Y*K8o;Dz^)t=@9bfMCYa36t1h4Afs;W)XI?GTdwcSm@)A0lCwE!|h&+FKYV z3iPUB0{yRg_nT{qKsztcEGk-$|AE$>(9rXLgzf;-T@EF_Np+`MdFS!6U(lz2*ZHqZ z;H8%l<7I2oZ)lFE3be5=arJm3Yn zbN3D&daw|ai4tMMTs}lp2>ZpDOLRPB06{tPA?5l-Uy-{bYvf%H$e_#AA5-$Rcc^iy4Rb}oFKRNZvPP28+-FD6Xf*RH>p!i=eJ3H!7&vk#$*)AX{)0j+>j|#Jvb@0_k0~|S>jKV6+2YOo z#w4sH1W*s?+mnaAB=<1=c3aR)gA~K@*k^|DnJ>wW^glN;^G{!rQ}iq0xb%{|G$QvC zM5@XK-AvGRH+(|(c0)5?GFfio{oO5~tk2~;Cd=8;i^wya@NF?XMz%S-- z?Nqt5EvJUwla3K0h^qbPhkrzd?xJn~-OX-ht7%g=Tdty&{|~f-ga%IR0zp{af1Xj@ z=s&xrqW{FyC*MFNWoPr)X>z}4GkLCef4auzQQyNlbQLP;WOx4F zG}KtzTkve?&bLpKd-^Z<3pEB#8tfX-od@U3t?Io>5cJ}dvotX0k4f9CCz0x~O#O>L zmoF!z<1R1?zXA;s;ZX<~?1^$*1wqe)Y9%%riXls?C&EeH5-EL{#gFC7-)eLD`~vxX z-K`DI@ab}rRy&X9&5&C~y}thG@h&?A^ZV!5--e=@9S-M^_59Nra-z09KR!cls{3di z*UpqX=^X2L+DtjhJYn5!%l*a3L!Av<*_sd$oeWskG`*|(D2~3@REf1U} zCz^}aQjC`ydv-5mhbZ0F@&U8t7;_&rB&a$hTnSjq9kb-AQ4-dEJW%QK2rP#!`3@OG zsfB5G*dA`X<5Qn^nl1ab-8dGCHmnz@C6}zR@3$*T-FyPUgk+gapu@@n0Vn~0tAHER z_{+29V6Oqs!;bw)hBk_CnJu@p{ip!_tdc!Z?BN0WSps0M#0_P}i`B57J+LYzX+ky3 zC1A8@FC(tF|M{MfN;eRoB&1V?yFN!VD{@PeY_gCVZz)r;tmV;8E@H;T$Ip?OZt=H# z)*LxpJA<#7BiGjj&*e^h!|u%?-0W1PnTS-TG{6^oFffIglCG=I<+*aaZQpa%l`-KD zs*DWeJbG$%ZP);#)4WRsgsNke2lCGp!l475(>###lL5gFvF$z-1pzUb?I{hgosPU% z?(05=@+0nDfE-pA4*9wat%;Y+mCe1oV9JaBmJNeDm^sanS4X)x8%0Og1FvVBGq6hW zf24g0TvS!`|I8ak5E$Mt7Zeo)6%}`sTo6%42OScW+|3QsOmkN#Ep6%G$+-{8Ottl4Da;^3Ikb` zIz5mWCjL$UD8ttkD`na?#UQJCRqRt7Q!k3=BkDb`>P2ALKtT%4U*SQ2YVW>+6__G| z#eyH5sthJ*p?R84rY8tGfY|B6`kydhLN=&NZ6aqcQ$XcB4gsjw#V3I!y?+S*Xqp^7 zAcYcve!>a<5k!{f#PT7|-qAfb<^VuSFx~TJR&eG`_A9|&iyd>+lbHd|y!KZ0G4_Zs z_0Kb3?S~S(MLv_z-M1Vhz*HXPl4DJ&h^xCxZe*Oor@Q1AOxOE`@NF)+W{YOnnx~b+ zXTv3Z_+u}(9zr8~74XPLDIkIeF9YH>t9W3&G`!BJtLO#YmMS;US4OwhJ0y(gr1Yvz z{QRER-N&nb$-8CCX~xlfWwu=1_#OW~Tdu~M`3T7hqQ;;}%}RbVTaGYFJYc$9CE?vQ z_sSQxiXWl;C{6kwRk_;xAxg|`ScMcsj$5&LBB()*-wdk`kdJT_!u|lO~GoUzh z?K56=hFqin=wC#>tNxC01D!RQcQMdez^BHm*V;(;}Lr$w)@~PJgef?TxA$Rsh$YG!IRylHe zsoSS~N{(DT%=W3sL!{XCQyrpR9a6(TttwwxO@))$K$wg|6k3~I&5gNoh~!z# zE9c6e@}$%%J}wof1<>4Ka0BZS9STkK-S?bS&;VQt6=uSkl}^??ljs(XiEiOIdLuNg zB-M8{y&O}$pZp^*RoxC+IV&CpO06Py(1M!##nR%%pgnxJ(c$7l;zh4!$e_3O;9eom zsviEnWqz^L#i!4d>$IN&m@#Wu&f9**tS;WrG3WdZboomMsMW+Ba9{`#%5vBkJn9X- z+Y{%A9~uig_)#C0BrhrSh9;il#WUqN)5e}5JaU#?uf}Q+(Q3HpTNLwDc+oiJnRIq9 z-uxZNM$D3Hx`JQD7*9P7wyiE*lA(*V<_t}79uje`0{-Z6Zva7G<)M4d(^zjJoX(qtd<)<%qM5z0nIKl+J(LzhiT1A0Fi?&Q+tH)*JsPsV|u_ZvX1qC zUzB(1bN)c;atPQ7)Ej5Zk^L2BuCp#Q~V{_yPSM0MWf_EJErS^Vhz{ zn=S~yQQabIu_$8eE6=3htBWKBpPl@V6zl;)Bz!kXh&%L<@Ke1G22XG3mm2tRIk=ku zFFDgukRK_BcM$NYM4ppa8y@PGTi_|AAe;a~3aW}XT?&5tK}bQ3%`XWlScgZs5TNpf zKiItWCCK$Va-?et@XyOY=D+--;3qXU+9M)y7^>s7-G}nCzE3{ z%U$2S@TGbLf(I#bn5ivZ>M3$fQ&YTjQLx2&CLL^Oij1f?;k`V(UQ0&^Pt7$6&9$tS zjt?rYrNlNrP%RBRPPIg`E9aiq+G@@Py_RO6_ED~#bxyh4G<*UA;v_U|6277l#FY`e zs}aNz0pZ(g_-YzHa|)`wNg1w=hV#{N8Nk&N5hI+xhP&5QWFgZ5Tx1#U7Ks%MjQ^}7 zNk6q(8S*3{g}QtZq1~1m7x=EZ(CXMgUd8-59SWUv^4w z9^>)?XbXLk3e`^7pMykgCQ7~C?>#FEHPncScv0J8M;1fpa71+qei{~9c|$K#1lpo` z3Tn%UM2KF%a18J=KlK7l5QjIkn3A27SOXra>6&#H-*AfHfp>sQ>lp?<~Y7S) znZfEn0Uk>}YW{l^%MD43!|Dw+B8o!uIRM0TP<(TViBWc9q6n|ey1xJqr*Z;zSBNrn zPm!ojE6O_Nln{oP;&X+6mY;W2rk^)(^HOKG>+iuI6v$Wh2!@pfBSMPeI6K1)I zi)lt2aSQJ>{b5J2ydw@0oAdAv(-hcQu*?##iEk42 z55mH#Exq>wKgfrd&~A$=s3?UIHwpW$z*;VJ4DsArCRZ`mxt2_oVpc~}3bs{1Q8zH3 z04(mLLopx63v3xBhww)4%2n&E)@d6NEiTd{+J$Ab?+V&wI<09aUfw~V*H#`wH#89o z6KY$8P>ydm9DF|krJy!>8DdiucXFEmJh&To5{KTwgofe=ca>AyRrG*)<`95XQyDG6 zG*Ux3X`cC^BZLRMCx^TC;VVPP3dUS$bXv}IK;YQlg(lz>wJr`MqpDN@sd-F*rq15` z0`w|{187j$2hAt|)YOeX*miff@i+M<2PU1mO&^$}A3?}Gi%93K)0w`A8S|Iaa`w7ty zTgB1_L^MURs;?7ep}B5Zl!^r@6SzpB;cq9wb~PfV>GK5B8X7+98u*xX+UPRFllc0l z05>VYQ5yX(ct>1LL;OMdDiy}3 zQAK>ha``jKXD+Y$Ar?cM%;jA_lp9Iu3ZM3&+*R_v!;gI^&y+rYhxb|`kFJ{c?Y}-Q z#HOt`^ul-i(hBSb7ktN`tdOf#u(U&dtvuo*xk`9rgwgw`Dp;a>Q+#XFzV4Z}A-vm1 za$VQrwp2*wCG=?5Tve<7gX?ra)ziagmjQNCDDGL6Um`tqzF*9Ex1o38~8tv zyI^2}b!{(((A$-eK&|8y^T#bv zHBb$Y6+IH>KHXcHmjQ;Oq;AV!9Y}ikW@HkTLvx^h#D_#@heycB5ReKPc^NPJ&HeBT z;mFT|xkactctfvl@h3dLvqtVBeYS-seGXmF#4UX7=kmg!X$2xt)%GA!bwaswt(+wF z*v#KqE7z@B3z5=im(ZDqrW(Fv1jCXo{LotYJ?ovXAr>S;h55+l-;8H|ArEWOY#QVT z2Pq2u5+?dh5k~~@3DeoCRsjOrz~0c9?Nnn}>DRT#2Npk_%B^3@W0NeYVtP);A>IH_ zus)QJgq^kNYnG6-aw8ixrh*;r*v4Q(CG)d4bnG_%{g-lD^T*$dpeYozM_EwXz?_bQ zutY3&xPJ$g+PoaiSIswtWYD>p4DGyu+RsNM21RbkAlgU4A{9vWBvf6-z&$%?^rgw} zIBiL<^%Tk=O*Ki^0bt6ZPK%X!cj$que9KpIg1rYS4sGxZHf(p`j0FPW(A@0f;N}et z!-lg{nNJ=yx2rFmw{dsHUQr(Iz1$W;(1HD625p_ZF!9BmAaz?h;~}QHFQRt>ag2Ri zwiw!u)3n08miQl1Bi_anil*VTSb90G0{5DkRZeLdEIEGc~YdMvIk-o!sxFV~3bLn5gtlu$8hcte9AXjHEx*TqfwkL%^Apy9hj zUG&|Bx)>^R{|z{?J9jgGeS_RnYQC8lY>=x3HT+i4Ohyl><_7WKH^?=E9`DrZkYGK6 zc-4)7#b|U@2o@d0UnJN=jjkAFp#Ev$Z*7!oSGn1-T#9;W=r0Mq)xx)Jl%s zD9^l{GKoTkA5xD220i^^Yz(2`e%Zv+zLp2ZZ2~kEH4L$6PE;>xRB8%wP!x>=Y)4%b zU2;WlsB;tl>1%nSv~wfx{*Bze_M031p(J-y9h*e~_7n#Yp*!@)ZK8h}UPC%X0Kg}kt|H>1;LE+Gx z1FKso1V5*8ME%I&%g5g^Me@jP@{7_pL$U9S4dJ0DX4i_tV0fp>1A@VtLRwF``yoOXUWoiXC*6}xqYK?2ZdL?*d6hj#}iAPTzo}h3jzBF0qSL-6>~SB={)6&cw&Egw3x*wheK&2 z+bX1^A5Ao)p!y$oQJpr5N9~kDjPLU1JLSlbZKF{k7tsSlJVla<&mQH&cgl_yNyE)_ zEoc-jKM$)^32J)Ls{1zGt0;;Y=cxO}(h-81G46VOC>hd^#WvARRq(>Pd2M9`e z@$Oo@&9`#c@R%}8Z(xuO^<4e3(xZC_EEyC)SstBFr8j-=Mmz=;Up1nur|*i_fmQzs z5}9i2HLs~bMSV!^kU>|P7NHLx0RqK5zeWiE_FFlk^`1GVa&DOV>ilSWR0TC%>;QKv za(xLEOC@fL-w;IcK@exVKMgF) zXun7;qxS}sWwZ(i6my5j5FYrw95Ha>tp7Qq%A#yq&Q-ek6-O;G=@whbwuWu3iT0=) zdvpA-j3{>0)D<6^3|@u&z(8&6kUDCypyExPrYd~p_p+Z$W0&q%+!+i|e{m;^?Rdi) z)w7ta8<7}n7NEHHtwTPdu#`iehh$4($4Y!=Yvc2U;i7@cxjiU}uHLqodEcg0;KTZM*hNXtcGT6;L~>FTPFQWzGAl=32SBF?S_6x zoiF+2-Ev#s`(GeX$|GKTj~vNV@(iKw9iQ>A0u(X-H1E9!vx15*{7qB1yxHSuQ6p!M zU(QqGgmYyH`h8ZnN>oP& z1@J0+VL;*Ib-c}9IaV6CmXFyB+Y^J=a`#@jX7m6Io5{IY00WmA;8Glpu87W15+I$} zcCN%v?Zp_}D~>UsPe2r`Az9^Cw{9? z{#mC^d%iiAhVUBI*&mhp!{L|I2j%!c_c*Zxvw=^GW^DGnXD<2 zwHlB2u@+YU8Wt?xg_{MJ3HJ(II^0>fy;XU2vo&1$`WkOzw)T-SBlt42^}ICgDj!$D z8Y3-<;O|$k9&B3&W<4sx{Q*N37vc88t%K_USRx#QX^>Jpufv^z+XJ@=t|j2LBlyR@ z*7{P^6@Jtg=`uv}Dt^{;QOjY>BpYrNTpu_GTrAvPxQ%f9a*(yU^xb71TM?n=MtR<@ zXf+z6L!+#Q`>>dD32rakmvD>VIsx7ojz*|uPi&!{E&kT)l9c`DCX+WNS~UPaWP{w%)CN9mahQ!hHj`9BwAu z7`RZF1bSMV53^cpNIkhH&uabMB#l_?=~~S?#N?lfIe<0Q-Td+Ve*xytCBSHt6qV=s zuDbPmqcmu?#}#FrZjye?p_knf-&@D}z0@~b_jRgo-7g)R;*lFzPn-NJ?$ktT+iZTb zv9*Q&fgPIv@@!9|Ce~y>SI=I(?LF*0_1le{PGv;8IK%Bw#>YC{OQLBXQ5pY&QTCGikNMVS9&`?Up1lBQQ4p^+IwZZp=j^btgr*deSbYRzoOA5XY9Q)H7uEe zB`58B_@wG5-c)5eBAZ7H4+Ei`{^ zI*<-{a+2HbC%S6z9qWr23{xo{gGkxlf~h4%fSd60@Rz*>Sr6~-+c&%rzT1cQ9T|Rl z@0Bc{lY0wBKe@PXUxo(WTkz_&-(CBTWLzWUX@Mlz?tM>QJCcl(>t?VarY=pQ?SE!8W|gV#<i zvLHpdO3G{Y0rvg__R#%O&$_4SH>iV2E$gB54vL09hca38P|hJEbh#go9%^t>igLt` zhK^2>A5@Gg=W`R5Y%649quSBNo-ec5C zzKtd&vYe+r^4xp`9VU-$-T=m^+;$(lCN9ttGS>W>{$gp17hyMxtTN!M9Dn!Zv6bNh z5a5Sl^24LU>~br^590R}U{{C98E_?MhRMS(4wG+Rhx-|HXMx)d*ok3sD<1^RD4>_i z2>0YXey&}hH}YQlWtjZhRWukRspQvtva1%_ixus~>dGnb$;tPj1~ZBJII`?QO~#5W zp}C}dSJqC@Xq@GvLdy4L5~>d|TH8rQRZ_n%>h>RFL~1lz4}r^@PinMiKdv(R@)ndD zO-+a-2oL3dX+vkzYT?S1|8b;n{&S?*kA{;{3(LgMjT9&d8YoEC+Wfomyg-ddlT(MH zRjnu#y5B6;X?h6TQ6xDtALAR4$F4Jl2Rh^!2s(Zt;k-shC=>sJ{&162Ro%L0d z(p2`GZfEW4YpRmLJasx*`%0!=1DIz(XX|;R=}Nz{H{X}V+exF}930(h)Tj^Rwyp@j zuQ&6&)zw;CGJV*Sc{+Euer7cN*}d$obGNd$kJB0du$T39Q}cA@@$YS2B$-yGG0#VR zt))iO>ds|vpQnhod&U5o|G0>$`&pcyCTf6v}T+JEJA8#FM3Tw_hbthovXew#O_@r!WZPT7+%rhm^+FLS> zh-LiuY1Tu0)tlBmrt^(;f{l%tXZ|E>56RTGp-!;rZR_`@!}WE7)%BU@gDKWj$<#B3 zdB8z2nhNXa$dBqU&&q6Tx@1a?X8hg^Yo_T;E#`SW$2!KxG&GWVF3z^zG?_B1G0!2z z`kTq5R2FYPn)rgnR$tSnjCtN)Y|SxC@^K#do;6Ln^By1bp0%>XIiLNWb(tgbD5=rn z;xo6o#|ml@Wjl#`)EADGqw-e$1BDA(+~%z1UT-{|x@*G+zi-{($**avZk*lt1FNU; z2f>SG^QbYwzMjHbwuy61(o1HZxY3qo`a0dr-5YJyC7cOgx6!uSbfl}9PuOH@Wm?qL z>{++TR>#!xy&T>}id zt^)@CssZF*JxzAo#`#L?BKfKVwxLq~FCO26wu;86j=$Ipb>ITw{6?zzW!?zh^^omNDg7ERI%In)jl=V>?R-+n6`SE0+)lVPaEswwaO|qh z;Kj29&tq^q;nu({hI7HOYrx~VY_BcM_a%yY8?OIvHbV!vW^gs&tZ-hyr{OsoZgHy*Yw))cLi}Ax&YWK_ zEA|&smGMaqWiUSP`(n;MBHW%cjh473V{LhSI_7_hy-i-SAv1u$ndanXP|mk|aM5xy z%zEHRM$Zs+K8#7h4-H!K`=~DX<*k^H$Xk2SPsebFGQe6kI0A#Q5#whUZEWnQ4UI}# zV8C%D*-xJ`{tvUo11kf?v@c4`0DZ&^FnQ)hF$t`RUf($+`I$*ayY~>bcyk{6O=(GU zy9HwYh8bO26jo9)&HMgxm82zsg-mlVnuBTcFMGn?X=lKZc-a#U%kG`%YLk`Ijs_9Y4WxkvFIEkz~TRgEiRP7Hv=+*?}p#;-GGyQuuh$f&yP#! z`%z5t%o2V6v=UiLQF!|mQgzY}{^zWT)M1nnNstT7l7vj;Oof>q@hvx5e9H;3$Q2(e z&xGPWgkmd%A~%|rX7H&;20WtFjCCX#+9#iojwR9Az^hKcspwqt)}AQ8WST;0C5s2v$tf7TMKFTIRx@dTP zrZjfZTxS6$Fec1D3#o`slb?6GR|40}T1v~%`^W3u~Oq%K)G2Z<`ER*+p6xTP z{}zjG5DUzwQ%p~UNQB;_m0Da8QZ|VmM7OWP~t zp1)4n<{Kl1AAu2B(^EUngvc|)F`dvqP@(&jcEq#ljExzML437XN1Lw8o$^Iq&vI#=we&A|6}PU z1~RO9?c&z!wmSZY%l)3D>$a6fbE-Qc(#U_lYMWIaX0qX*VN%Nd6b5sU_nzM1#j0&a zd5HT@Zaf!D-HPR23b4i~J^lxMM8!wXlh^U@Q0~_f$>uH*BMg z##cNIZrPkh>8~3+>$dG%%F3ovTO>W3{%NbszrSzuBhN?oY-4p~W&Y%j1_Xtmobtd{ z*MHr;vfOyqJrKFQ%NyRe_5DAv%(?R~mM3rh-&n>}y!kxG&yB{C{~N=){!M;=p5scR z1$W!7e>q=%&(^1EXTl?ey-f7RH%)9$p9ms6%1Kz6yN83jn!7K-lh2* zF-Sa89z=adu!b)k z#cD|rA8%R6elki=vOMD@b`2|(^LTF`rbw^2`86Ll#6Roj8#vvWJAH3${*sxkmO9Vn z56tXE>5;-aRA4c|XOuw0^k2N#V!!8*t)Z>w@+lQqb?GyOFRuWyUJ6$$u$5I_xCA!x z*7jj`Y`LY>I_^C6dy3YPtnvjpnnr>C{Kc1v)*$(@)m19}_`e1F-cJkmvmc9;@9e6D z0W46uCtJ<8e3OEf4l*6Dz$N#SE+9*2C?FI|g?-iofsA?iyEl<_55N zM(N|FJlw*DORbjjSr)cQ%38wXgV0-Vmh`FRmi(&bfb>`D$)Pmn)j@#c>O2Za; z09UjfMKS+(fkBQMov z?KN3kj$jciwv6I>CPr{qTR*8VeRC^r?m`MlrcYH!Ns*b6R>+p>c>?7kPo?e~J zmTLU%xlo87PJ6Hnq$@|q^{CG_k65XfDWA8n=A=NaQ zB6{yXl!fX{L0KnCrv!_9x=SMCpQOPAS33(@>9;W6rxuHr^27MFTC9OF$MZ!k_NLK) z@n~PHxb%roM)L->*~UtPVTV+cn*I0WzPZtt(S50@{BCW=q*fDng*vQR?H-vL4J1`3 zXb%W#MF3O^(KM3}sKb^=?;PoCD0mo>b6F-+p=NpZEYTgBzubkck}fyOKAqx;sLN7} z@=qfI4fpJF-y#UJdVuk)7zovB#^0x>i}CMcSfkK%rWH;xcF(4bP(#3$FUBvvfZ-mHdE51=s!6i8g+y9!r#3Y2kX@c@5!8 zg7t8qE1-Zs=z!+}7M9U~cfij?v_*&H2kgnKQ2Yj_FQOl*G@P%j&zc0*yX7Zxmah&8 z<`?Uu77~NGu>qcygL&NstdXQzJ-r&RT%+{EtNh1?EHdy(Nm-DVGWTr+(qNf4qGw5v zr+Xu2H&z6u9@{zJx1i@A;xJrb_;+Z~{+mVqW%2Am7r2?G39n26E}PeAU7i z26W~;@)oDy*r1yB245JK|x&J|f+K{o_cz`=KPyG=Y#VxN(Qh8jN=0 zPJ5*0RTlD22UFevOzleyFJgOF(=@0*kyZxe+ymv1J`*&ErySBzhkOc%Gs4}|M3MfX z0~Zp|-4iAN4yiv);7Ltc)i#oj8?516gu69fW1Cja_D3C(piv3CnnmOJvZgH7^%=56 z$@^OQ$JExSuM_nI9Tu#?N(eS^JkM{&YNRLV zxF5>3KI-X^qH;)O9kLY=CHZ2`!&Vb)TGpTFg|QqM;<|1kZyE=Qt2>eRj$NOsn+ZLkd~>_A3>||RbPx6DavUon=i-U zq&oBukEjJ>`K6XDURpMYhqYocO|w=aJ8!-ZmVaa;r!dfgsRyYyb$A(^ej-=~eMq}4 z{scIZ&BwQ5m3)I=K#>}T@OiD+`z`)lVuW4*O?*NZa?x=AXaw{V7XlZOXhW%skZmpr zyFzCOdD-O|7|)s+eNW>Yn7U>f=dD?th_1tpXuWqxVWe)sZPLEk0(6qR^_)6%8vmg+ zi>mT9(GO4_dFSLtpGOyvaWA9ne1h)?V%p9BFMCs@S6^K09mtZ zyiVz$YXE6P1ta;BHmqK^WjbaJFo>lg#WF*OE!JRI^njgo9Y(t>pu=|2A>7rh<#(h8 z!#c?!wc|)WDUn6FqIFzz;GEt$bB>fMAwE` zpU`1f0Mo*KuR}=7N`tJ^A%S#BnFjjcbzZA2Yu_F0Y?Eh0qaFPh0zb;cxt1kj4NM)T6W>NN#eSbF zdK^xk$Xm4)EBk}LUUY}lorAqPaf0d~E|l@^PDwaA!QxCfGSSa5$4GmG<9xhClJ!&Z zQZe2mHL9%hrByOPqa3HR2sh!SmA~8)difhK^Y9XP5-~ZHhmJWeB+{OJ-3XO|VGG3S z98#?A$)Fr%V!QtsrJ#^f5J)NTCDu`MjM<3Zn{|xVJkj+dehTH*LgA{iDRlNhhrTJG z^32;ZF}D2IockMHHRR5?{P^7HY-B=E$x8~b zsKU=MOkMYP3j7!5zd|L-Lpti5+F=j{mDpIpF zsm_F_6I7>igqHez)kj=*zsdgMBS!{LF7TAi>U`d4*(_6nyrG5%o%1wpo?c zilLH$Pfunn6h?MyqeE}dm8Mvh=$a6+CYjuo%(5(fetHCRNXnj)YHEa$8#}W2@GFOj z3AEfV;>fFhSQ{tZENaCNiTCQr+EtlN6o{jex{FD~@pQY;elGHzd-{m` zbz$mW6omlgi-aMqS3RTzH1gitJe4(fawcm)R6mG$B z>Yy~s@I?f7dapQ@>}>R=h<7;=&&x=8T4022TS}9C;QOU2-a&CrLYdc zoepR??HKN4tHggxVV(TmZin#iBh$@a#JHAU#0S2}YDWHe0h!3l8Ar**N8Av)RwY)s zh0oAiYSN=e{G%7ybnD~7@^tyCO=OA3c4m>jmK2Pfea7%!o!JFbdZaIJmdc{*R(E2@ z2|9x)8oCt3TcG}Vj;0TgeJ712Md+Z^RU7%#R2Er#BT&uqi#HKDRQj{&+i^KyCGQAp zw#RX?$CJ-_K`N_aX}@2~Re(ClBJt~~tbWj;hg1P{?J;aAoa2#ctey1TKAw@rLaSU4 zL}e-2G}FRS6goKrZK}jSBYgS1G}hRE!C4A=ObvU;_ouPCb!T^^k64CgoSC(l?ekqWj z?8*k2On7-Aoux>}PH|T{8&z{tC&6q-IwGizn}>?epjkWez9bE2MDhwaSYBeC6Ei`e zCF={!n9(u4j721&js6w|J@Y9|wK9|U=cEIT>um~QH4r+=xaw6s@FidR62n{{a^9dkT^c&L4cq0QzOuSJr;Y$Ap4IE)YP z&XT2%j`Iz8`oEhj(!aKAAb;AO)emj+UoPWc<%vDmB-fh@Zg_EBYuGp_f@;^bnyrbB~4IZdJ!}Vvh{%oi}+vrb+{!G=MJ@n^L{h5hp7m6rX2ehl?Yk)qp zVd+?A_z><>xOH$_;P%1of;$3t2JTn5zu=z0-GsXYXCB9A^klC}Gnez?o@|(}`9;V; zpCP7NHyQ!BYI=?ZOLu^PH%jOg#N*cd$XComB2@hAI!7*usZddk|%I5HG$>Y z_7V=6;oxliyR>?dRTY&shDeGt_`W`@e(F;4Y|Ho$J^BhP1X-2=?Sw*4HUg_BMr)~= zM5%H74$qLHgw*J9Q%JQsw__kr=*!xgM&e~kUslz0)Dg(v>&r&^`cWL84B`PVvz@+M z+rzVp^CK^_TE45v;~B^wyv*W4KZeJV_l+iP-w0_NJCL{Q#~MUmDMH6F5C3-qFybhi+Y<3# z!fpe2|NiVH*K6@$*!p!Upoi3r($|UnDy@aV8u#@_v^+KxwOW#{zIy)-`H~=0-4G~F zD8xrO-I?ef-R9l^2^}L$C~#3v(bD@u**yja@sJHng7^F7c%=zfOX$o`dy4c^BB_Ou zz^o>K24Dw)H;gDxiZCyWRpjgKkN z3FT5v4ngg#uvf14P*T);08@(>}lQxc;1N(k9&0S|ix$m4`eeirf$A*(Im-GQuohLHY*bX!XC z?oIDgCJ=eBLsACkD_&vYroZC@`7V07hnFAe@-Q0o_y(0*4sa+IdC`- zmKf-{KNMR-rdQ$vJ(q^Dk)}Fx8laPmq8|GTngY_bVRUlTZFw6AGQ5g=<&wJcF|V`O z23v_ux$;x7w+ni-i<7Ajnj&swFH?&u{+&q${`d8EZ4dL%M zlJ#wUel|5mtu2#5OZ`>BX&KlQQnx>k#&D<+qD#ow#&3;e-$*03@lQsvAEd6!xN9`F zs7%ZFq0wxu^zK&A8)Ik-?CZ^*{^MAhG3IK2v6e)e6JgCnqJH_Sf}WXY<#nkOKQW$7 zuF_tkhIyz^-c(R0fm-d{i4U2;T1SrsO!e=CWvJOCJNh!zLXGmupP;_V z&xm=GDXdE6=!P2dM~LdbkpY=HvSGtO{>>DY*t|z$jry_9(no)$(vu>!jS)dAD=XO}WR#qlgvctdfGRZbNA9j@$-hOy4fO4CczUQF+l`7)nA zmA&SOFI;X)&_MlvQ$27 z!HxHs;W1p;2h7kE&H>jOZX8@5+_!K=aHrv}!daIy!ykBB@O+AA5}8|!bq*LaDGgJ5AtZ3ZuFhbW++Q!GyUzD+_`;#7WC?}G`xlHS-Jg_zW^kF|K5 zP8Us>h@?ne9V9-au(pP;I`y|z#0(6|BA~BGCk(qGhWeBSTq5={k_e`_#+O2D79lK_ z^5{X4EuzibN~*gU_O)_FYRjvyF5bKca!MoR*(Yd>8d8wz4(3@6~u!Civ$S-}jW;NE~6z7iW!a2MdFtmHLkW8=jXX00sGr;B>! z-1hjLUMg89gv#?9qGOPAtK*j-p@4|>r`&f?I@3#yeg@|1lIcKWGFpR0TQf!li?-%t zwPl6??h|E`XVR`cs-p%dh4qPQSxKIsixSFwYkDc2-7ZVeL_I+>be_53`770? z%WdANGmF!oWhtzs<;y3kawW=*PgtEwR3<)AEh@<~*HU1&*`+6_vi`iSKkL>Jneho5 zrYFHCs-w=Om(Ha(xD1h?)eklo^k8@OB&6tmBRwg~H?+V}Z|Z?(A#hzS2?KQ6Gy1cU z{%o$5i8VX6nmnJT3vw<^X{MJ}h_zNNFC|y0Us7zCR!pX_q{@_25QI@q{gR@>3Y}uQM!txNd_AdLdxc}7bN4GpfAnT@6wcj?u% zS!P5|aR7xkcIZJ>3rUmcYt8dTDnCYb{eS7xG44Yos69620b(??E z>FVguTeSoIM7)jb1ajk(3SpiD3ae{0jS98$dvnRGc(r3seWi@b4G0PVI-q zh@nL+cK0c1;ZP3Ef$;@cIIEfl2iBcqNC1}J%bKoEMD4SeB$?iW zkNzM-xp+lRVv6Ig@{#Ycex}b}@!<#F!}21werX1Ahp?CwAagO4ge765LQ*urLJ8df zkH8aV9z5!+m}w9u51xC-;`rw>@=G6{*4|!m|fuZ|)*Ut(KR?bD;1SM;KS}g7?`k zLBCfPBHQ5*#Is8T-}nIwb%%?i%ULC# z-gTG&y7mM3P8jhSkYyTm^`VpDm4gD2pP_-aN_AtI{ zB@26Dj|Q_6tlED<;(}cfa+OB)`#w=Qz1g+%rc5+W{hEpYH)260GMkcF@3nB3J~1 zozW;-5QRP1vuh2TU~KeW6``%Lbr*mIvK|c9!1NNGrlC2ZKbCp_wXAW_?-fN%{RlQp z=I^d$U-;SpQ?~^1lrLE0#xI2lo@2fR!Q>#FCybL(ZIbb_<{G{W;rj;hPrqPIf>!zo zrojXY58_w8VBGhjFPKiV@a!+4mQt^>VA^pfK82}Kq*>4*A(fTEFj&LYFT*vp@FQQc zy0&aEK!x4ip@(@G$SZusb_dL@05~ye5Xet`#cDP_6)KqD*{%~l2zZ3cjWy;wHQebk z+{FN1YaN)^Cnj#o2W9Y&19<;+Y-4k$S!aITzq|uVBFkwQQhreG=9C(zQX$;+5y8KP z6;*YYKew-Etj~E3wvb@U5n4!U)Ib#60a0-I8h$+Cr#y!jhMH+FD4m)ciO33#vJ+8u z^XFf!XJJ9v8mtDv8v65->)E5#1mHKvR(2D#8$X#)-IAaqwhzF{L<;pPVap{`t&TpP)U9lt(KONF<9Y1CwvIG%gr~y}=5LOi zKMBfoIdvXj6WB2n6`waP%-H~Et#P@`DRstBQNH=}8Nf)6jqXQxf)T8kIPzbs%o zOul8lw|BEuru29pPvjo+X3P*ZTM}^?!6eUCEH~_az9J-4>{W*2 zk1(^3^wn|C?h`D)D1CH{A3Mn&ORJ9ZBd1tRY3fnW-BYZMkL2pio18~(TV3?Lah{zt znxbp^@XkN5VWyomeE8-c*tgY3^?&5esY|)9>BLx{=Xx&p8BRX$B4WIF!E^5-d&MZ# zJ-~ZkVjWB;tNZW|FR|PjAAId=*iP#tsE6h&&LGoN@cZrc~)Iv4RGMIvJXFYjlF7Wg_oAUvazQ9m3;WxU)gX| zze+xykl$E@(SPS*tzbVn>`A!J!i-YA?|4s@&Gx^%Migu#^`PfB6;&YJ^ziAwL#aH& z;|VHZ{zj?CR$lc6N+)(JZ+nA{k@C0j^*7jl>EUMn#!Yr!st#j*x7bK&(>I=7w^)iv z8n%)9{Q-sO-5We#{lO|2tLz{%QJ4m$W4xp4y&y{=3Vv;Q9Ja_N2 zTvNT*hSN=+MYJwCSFBNptLHK&Ig}h9Otj)o<^*6N@sQe%ulSqUrCl-nm%rKIh#fPr zw>)GJE%D3H9aF~QAUqD4jWg3Un-6-#svEt0+9TH368oAS!6~(80^k0K#hdE;`gs0& z#B7rE>S|BLr>v!^fE}@D?N%aBnpN9k!PJ0QpYIet?-;Ng#;R1({J=a zqHs+&`Y8v@TPVkq$qEcM!qjp7kqjuU0H5lfE1pheZZs`q)5)$3JhA?QP3b&g8I9il0D-L2hwkzE+4CP-wYWhLs4E(SBEDaDRF&F@t1=JoNzsZ1Yv zHnye>X?br$&6*+qq``EblqHoQcXyM+{k9PoUXopu;Dp`D%5{gFcBPC-!tSh^@ypVk z_%yc0uSmr+%ND=FNl*V|+;>aL6R=GS$%{n>K`lEHu1xh$rd>xnGzR<-*SvQ`TuY)q zM=Issu6$?SSJCO>{eTm85uA7>VMxLgX8|GK_)UfELUSfdF~&<-0~NbZe0!g)UKlID zI@7Mg8W~LrZmokd!d)C1ipx($0TKr%j^h(YC&ZT`Nrk@^`85f*4{+K0W3r|;M53Vo zSxjomv<=f=m(ig&nN$7#_5PiM~9OGHWgYAGmy6aVG)j;B%rBiotoEagaAifp$gL zhTbAOnr>d_hxP||@wkJP`D93HL^9O+aPG(aB`UEb-cFZJHH7zZcX;dDb8rr*oTODc zV3h<(MW-?=8}&q6w&u%SDUBUer+1&zm9r-nT80@Z3Ag0At*AvRK@JpfvT{rbwkwC# zOpzgoxUL>6cB$H7`4t5oHQCot>=r$8P+UHmcQ%SP-tHsM8jN;GW^yuUrMeF(tEJOS z$@xrkPu^fehqc$GoG0rDaraZ>QNr@9^(Z7VvV+Bq_4%TNzl~l3*sui-#q|(EC98!1BZ62-DFBQ4?2DYH=||5IMd zni?9FNuK*LvW|vB_tp(}=Aa=MG85uX#s|x@s8G^|>|G#l^=UoF)LuL~K*!LhzIXQ= zR|jc-2QsvB9wL-roq%RrRQxyA^AuyMaszfpm%VA)VC2A$=r|{p?;S@mHW5 zwBm6hZU)kqHsmyvVdSj=l!kiuPpEc8BX8|&blpEO$E3cX`6PHc7}YvuNr35^3Mr-^ z90`6C_EGfLkSD=AsQ3b2sd(RrLD7;?6sk>d3~Y@;?JUjdY@8GDkAl5MW%da|X_cet zXeve*UH_8v*qGIh8f-4`!puq;!(>!bJxX&tl}^0c9|lS1n4Io@Xrn=PZ-FDB;)ILE zX$VHaX&1TNN{dL)zr%-%@CdlSgAseF{UjIo5R-Go6%jaRvL7mR1A>-U=m;7S;Nl5aW`RF)UFuq%1b`+o&2(@%NvmQg~zEgQ@X;YSHAlGO)}{fkfIzYadlAs!V`mA z>vAb}DkjCxp%lm)j^bLBqw1hgkyHdjY%9KwSSM^ z7?x%_Aj6pN($E8?YDLk8o1H$LP@-aPqWq=YL6@$zavwlOV(XrNX_HU^G#mUy>23PF6L~%C2%0#4tqO6F63h3U?CM)}r zegW@dvY2-h8T{v|3Pc?i!{}`~wy-k%E09*axA!rn- z4emJ`l!#hSj`O0?o8ST)pvMWRZZEhJVs|^U?bCPT2(`g6;(}ppCByb?FtIl{Fye$^ zhFSNy8WcH36c|Pa7?Mpt*b5$oOuvH4_S)TnHixOe?oP=D^~>P~J5DFsO(zTf4zW*v zM7#QL$S`BDo!;!S^Oyr7KmB1DJpVa(!Sufc*fR5EIaE2}nA7K})4K<{@k!n}*8NFn z`X-!qAgcysOi3#(R0%c!`a{p1w!7^EpWBKRB{nKL3`WQ3>m(y}2qu(B3rZpdN@7@; z2Vf-ultO#X-{@4^qD9c6MQxX_Sc*=9Cvn?q7v|!$ARS8|(B{(B!V7(5v8v(!sqprQ z*48yX(6Hgrgp6o3%@@l4zVf^Sh(@kQU#GqAKR?{249Q0vXYD!pFmN~aH@GAB+RM{? z;JdwVnEd}}dlR@Qt1f<=nE^os9@LBCj*5ojLSnh#!pNXAIVh&(T4K17m8Rf|jx?f7 z593nS&9c(By)3QFrA-DDP?SY;FT?#oTu@(?A!YvGbDsgkmbc&k_xbtpVV>u%=iYnH zx#ymH?z!yPYQOE`O=ZY_(&``ZS${Qbfh{Wvnaxq+E+$Yam7qaLNJafH# z&XeAX5Do`k_bH?ViKZXN$64gcN5FYXGMyZO9Y6?@&G>biG&y^kl$Z~hT7$N@J91!%Y{sGg*gnPH> zZjm7(6YIT&^>(7)JhEfb_AP9hc4%Q^TB|M#%Yuv+nJ2xQ1un1)RanCIQ^-E)Jqn?s zs@VdS;z&ERz|Wn`5b2QK%dD*u4r|c64sg;;y;WHT1`f}EdL8{0iHM^FJ&h>|>;+TL z5z<+Lrfx!SXqHb-quE_IO>gVm-z8Z|PD5eK!#zB)ER?oy2=~BhNH147u6ycnGC67L zV7sTzT2X)gM4T0Z54I9vJKNEPChmgBhJnmGTmiP@I(#-VYe^HmoF@_-J}b=A!uIPN z_Vi^)rmAHY0Kmkm%f;N>QlCEH|mXfe1RS`b&p7<3Y?9|SuHAa(%# ztlH&KSpE_V2*wgZ#vWoajSv}SNR#5`&lRg`H; ztc_AR1+w|mp5cEL$gbs)p?ECO#2 zmmEHeo7)>36ZS_*+mD)bh314z#g39_g|t_Tb3Ku_QXr+HNRdIT@n|ZAG4vkXZH%Qg zWT>PKIDYB=E}evxA;RJjri{XSSw1F14NRzI_)~ul0S6Au+!xy-G3!mV6f@Awyw*hM zDmv4UbItDN%`7rx&l`|1j^jCDOu+HpgUXaHM4e<;Ev{Z)@;uJ5&{Zsu<`@Py;t<>s zt@<6sTK@=^UO9>vdo)>{8||LM&34be#>k5K_04c=X#JjgIlE(95bF|eoXF2Bab<=b zhpU5toshZVlgV<}l$(jG%CJd0JlGtT3)e?QwL^;I`LpyTM!PB4niWhRrgD?r(9{B)Q{+ZqZLaqz^$=v^4`eH; z&Zd|mvr?8B6S9nvdzS=NFJq+b<{_GN-#&C>MC9HSOppaiA8cjts4-FyUpB9SmnA?9 zV8lM@KX8#~-4h@#T~tYoPzJYvVK!C??P_i+tu_g*Y@d<#2b^Da=A?#Fpi+Py?|&RO z$=dxUyp4eea`YinwJ1V?Nu`5;n?geb|LxN9@6elM-M!v|Tv)H9Ix`WHG{>Gg2&KcI ze%^G_i54p39-}2z(tLVKX0i&8`Yl*^~VD> z*-~dveJPONX(@Swz=o2VETsjsClDYl--W-a&Xf3?Jc6QI_XBtqq$k)Z;KfjNDf$h* zm;E3{gzmM-SAKz9o^GW8`f92cYflXq-RwPoY}v3>=dV;Q?t^KlJdP&f7bmdD`poL` zq}xgwV)=#Ztn7ZX-=cAamQNkhe&djjhACfpKSB%>B({9zTjZ<-J#8q}^aFJ&PB2mY z;dUM#yy4WQ9WdEmL5^aS{P9_APyMu^QZ*H%ZFc&nZsh6Z^0Y%sX9?sn+SiMY24?o5 z*)1g`3WAEx^001*t;r}0uV(IOgg*_KCdk&Zd7tc#)k8Agr#CXylr z`oRo_5=h$v#KkQlOxh0d%Ho*Y9*dXjG%jLL@mgg1P9&dbwKQfgT6!y9{Aqs;*&;d0xbc8 z@&G<@r*P};t^&KfBkq(6dG%o!=1O${E$bv2(}o&TMQTnJ;JRtFRQHY4D&iJW8X5T1 zHqByGd*vU>{p26ZbqI+xd5l;!*OvRgi;WY-THHAF0P2(pc-3-~zQRn{Tjn9?6>)uO z*#5&8>+cB0r+u)GZ6$?UD}tm|dxZ*@eAS|}#i2%=@dC?MztdL|*T`K-oePo{Q@KDQ z8y{@OU9hQFd=N~Y&V!A)%f(g{rf~=tQNhygvE|cXe_)!{Hz?UKt?$?Xu>&7O(O2D#K`--s8v*cKaXgTLz7lF}il#(*LN@W)5m z9T$b)*>M*9fd$g;86|`5z74RL{mjS1BXR%g))40si*er1!(jJq6C)Rq+rZt%V7;zr zh~2ZZA*@vIDDl-hF8IdS`@_F?)=+y$7Xy^o@u(&y?D9~%XPaodFO1F(CpwE7qqNjq zl9sSEZlh1#L$8U&Q~e<->r?mA7piX~{~mTSu~^fY>fV`p3Ib$_M^6UhM|aAg+i%dF#FiA*j+M7TS8UK_8+3&R-7zfUQ9NMrjtQ%9 zI2)iZ@ZpQMn6NW8ODsio5nq?lSpcJj-r;JX4}%fiy#@%^JMK4dR5mc!e#%6T8f+hJ z#EHPWsk8rTq}ujIOtnM_4MS^-9D)rXG*w z!r)swxqu$?s>V(%Yr2rJh+E`oS2`3|+%L;PdHZp6sLuITMuB}14KVa z)6YBi#@ENYC3 zf+p`i6k_+Y@G|)qROpPOuvvFd(_@vZQ6th`M#$~QUO>I@s^_AQZi5IIyaZlc4OJDi zY5;rA87SbeRUM9|LdTXTjmbm=R(o?uGY8P(Q2s20Q9^^1ScyPb2%vqpk?t10Aa^2S zRsogl*IKl9)_oN92OzwHG|&;wf{yTZYmHic;;%?)N!&|7o})}1KO>M)3;N=A;0yGD zP_GZ%FRlC03&9wGk^u5;uXGV|+b>E@QgxO}ObVHeLaOLKfH{{4)~Y=EQ$&ACsb{p5 zI)+k6vn(AyT1BPa9&nX@0l%tEtuj#Cs%}uGJxC`itumvDQWctBb-)d072QYxu>t;80W;=Yr~#zv9um$h zM?@vGs{%sO>RM)&Qdt1n-9+T7q-LU23|y68x}Ca*l)O|oiakSre#7T^ls%K~TByV= z4b%s7&WQx*F3}Te`pO%W0-(*L?)F4m)w(P20yr%+NK_DRbeLR;q%-dVWynAeP+E{2 zz#YXOLQzsC6BbRTfW+g}OGp4*1ipjnq{-#TigM|Oh{?jT&xL?uDxv@(`IHohI_oq( z08C;z0xYPMkQq359WNIsu|f%{t}FDFi9eHR6w%7b#fX|L;wvc2L44l!Yo>M)QQ_@w zuVzqx5m_bz*_?DkM`DhksmY+JLkK=hrIt`Xc*aPUF?Xmo0%g{3g68I&^+ZM46mS8F zKz&FKa6y9M2)v)80!4HXjEVrYg;f01Gl1wAlH3klA%GAx;@5@V5jfz6Opx978m9(; z@KCU&2!H2XM3uJ#H6qt!&}iZ%APT4MY*{HgN*fRt)VHwDB zHfq^}FqocDv>+d36p81YX+&V&Mar2L!JE)#v=;D#PLL%Ie~Gd&`p84crJ02P1{!BD z7=zHVq0PbWBvrs~@D~&SM6Cjeh&&=UWvoR1#@bsVAKv2W2i&C+zI&$`Ec8pjzCdLQ z<|kEN$DxG9#6K%Daam4u9{!B_6o1_FQK&i(Nz;pwqZWwD0%V)3KzoP!&sPIJ=UgKc zMBixbIeNWF0W%9w9_BU7zZ8Z^NAc*@cp9e} z7`<885{kz_%_zZpK4NFkEI7-7+zIK30wlBxb+o=who2e5GG+ifW>KnmVhl4ZXOMQ- zPB?yd3`atZNH{y2-kXc}>YywNYE&m^4+XWuCV4RaW5BCAcL!DdK5Y=(H0Zi83|MZD3zk_^Qhr2+a~ zu&D5WT?)he<2F9Q<^lGjJtKYQ!tK{P1Qg7%8YQ>W+oQ{&+Ul6r&_gYj6d5EdkrAXf z{8Pt7=1Z%40D{;A$1aGw*htw2UxN;4`p=(60qtkOyn;bL$p zRe~i`FXKibwZg-&)e{W>=zR!uX?um$CE>s-l7l(wrAFR(hC=jeG&Gq0gwvlW`V&Wg z;_1(9oXkiu$TGFT5LvhcMicqUd)KIAtHV+zx;t666bd7gth*=lj>~PWXWHsr`}Kzv zLs+3)Xt0U&hoKAi{Rt3w43^hDN-Z)p%pB5T-J`)pZDC7(w@BXs|1)h?8a0FNP?-)^ zOvVI5$O7RKvVWA(amfqU6SUn4m8u@Fj5;rFP{t_)zaopZdUrwX(VaMvhP`aEQh?#v zhat;QE%F#_?(EWz{vj|8{u=8Ks7J_O%PN#WMgU_U9GI6;jI_H@*q4x*Lp+&)&DKl1 zv!yM#8Jz?Yy-k9Rg+(1{Af!ayvp`org3xq62amtBeyU^BKnJRW^za3heNc>oee>HElH z(c`on(F5#M^Obv7sCsw3hifoDlrX=Gd-z~kvOS|Sp}rn_j;m!9a`>!@Hioc$rK#vJ z$K?Q{J&llEkE^_C8@&iNU;)@Lgsu)qZgOQs2F$%l1zH56S2U8A_eDW5*q~h94=*Yr z12k+35+c8;BJ#R7R75`H-nf-k`cW?Il_kJZDGx1ox7m$4Xn82%v0QGwC?z);P!3?E zwB7h?%?&6eYe9=c@zhnI<6OBzr0v_(eu^wu0?lQyod_ zTq^bw?#czgVb^}3upz7fC@dEU#HBq7Lfq!Hh}*mxaRH?|{v9%b!!-yz%+4Oi0A+y# zEkzZBrQN>mfi}|y+kE?3T~SiTKKMQs8wh1>fq*SufthI|ySmV~Xrm#%j1t$c2~B#!u3i|ESousW*^lf8yTthva>DTi3I&db(w%LS zCX}v2@z!1ak=8>_HQ0C4!fOBw)Pu_xg829A*9lv;*E1Ognsmw)8&77l=nx>u%oaQAh^rnfzs$E7rb)(ATWH>oz2S zZAQImdTW0@RO!9+Nn_;KX;Pu%h}gfv)*sqOK}3Hq5Z(SMTA^pbIW$&uken+%-HVPz>Rb-N0q)!r3q2(pOJ2R4blmW1Lmni zTT`0F{2G`q&rUN5Ft)j-odIcD=qziC=qth=Ziu=FT5C6tma zoP2_u@%oLWQih?F(j=gtb(cyQUdn=Vw8<@|RGLD=;dce&0l^z`Hw5bdJi&Ov@kHT? z!xN8Zb{*1+Kq2Z3X`waDW1rC)M$D9$qQXg%YX`UwV)*i ztYdECrl7P;i?p0vDjRgC#WWRT+n~n3LvoRv4<-O2n*k}A_&e>Q!Y~di1d+IQKC?+> z!_*Z43|f{nA;KID)Ts$d>83IQ*xcGw{%v%rlWKF=3^tNws;#=rX_{ulqhFsjupKwG z_i2cG)U;+S8Ftb6B2;ensKS0*6@+vgk}IBOi@PHND-c+r2H=Vgq^d+fr5aEv0`4K; zo*Hn^1aDW#-(=HCGyQ1Dlu_1Q!f?YZpOKc+CNLc?v&~duBCc8teP{SctB5(8Y!iG; zFr_fr=Hg)5Vk~-hm7_OfZF5U--0V1+hRU-JM4ZB&VUcyOx89oT?YOVQmV^$sqb^OR z_=r1cSC>w~kq7q-AZMG%sdq2X5bVcwIgXNgWUwWBWAKc|grPqgEshdz6NFq{ky1_r zFy@z7h>=-13+X7)QCi)I5|ge#?^*{3+L(ZIU@zwbm+BwG<}>p5l+`BLGenPlGMs@j zM4}}bSbJTw>=kBv*2?$zr_FZ0oJG3RYR|3^+B06DlyK zBW4`v45etCuz|`ON z7sY~a+oKg63=Q`Y2pXLU{Sl0Jf)(7v;|4fsD2{8z`6RW*1~{|~{$;p7I6p?NhZ9G7 zxta3EQ39sII-rzGFkNbfRIRi!3<~NY84?h9=@>Y;L^fmdHJ*R{Nl+7=eo{8?)LIkr z3=Pi$0*BUOWG4qlR{Q z+)3s)a1I#sxRba{ShG`V%X3ns0B8Y@t0#z+4A3V^Y>k5#hq3;a_bVq4i8>kz;f@Am zLbmXfhTl5IOnTWFBOe#%kQFkvKq-&Gv>0WGVj|R__M+fpRB)4w04kV% z$(K<~Yqc0p5K(}%<+tj*%2Y~xW@`OFi+wN*Hul2+oNNdC8y>XBUch#`Agry|-*sXU z5LqO>=a3!QJ3W?xDECn)bTbPsQN+6<0y! zt2lILOjxxI1(@xe*r+jK#b$gN@%1=tX3+-A$rR5UFzul@VYC(sp5iwQ042N0JQ z(#-RKMK)$NL*FfH5GAeJjv^us!M1>Ay}n$G+N!Zsu6-p9meIC6BmkdO1lCFDfBZ8i z1mhq|?I7MY^!@o$QQRHGPFo|tM~821eLVcJ<^d|Xr!f#jtDF*0Us4a z*Aifx6L!%!MqI^kSyY<4Ymm3AH1{zbLDpMyKy!OQb5)?Zd!V`V(y9$8gDC9|tmiO* zYvjGsmK7C4(EmCJ9`&rdNd<>-g{-oIgdij26*!+%$3hUAN;x=Z?IxZtZi2f%T7wCz z1$}}V?JJ2qX{2dH-K0plGL=whH)#NWL_5?@vs6=2-Chg899E~-euv2r^;++{=p+b2 zr=^VkcysO5M_xfM;jQ#XB#DVQZ|J*8bls}W_;zDCT1M#WGW6Z8QpqC#Kv0cki%KB{ z)c9Hoq2XU+P6!vhJkQDSxb!)c4Fl*x4ksCs*gf)agzOQ_N`4^%|MZ+bu6>>YVp~VB!ySVp- zHkW=YCLpYtG#GCC-R5NSDlNZ7$~3G)hQapgugqSTIenzG0(YVzs0A(xFn?1m<G})^YQfpp+vrkjCH(DO!3%BO1k3w@oVHOu&@s0+*;gn)pK6_!*)~Hl+d{EiiZ_NG zOfHv4`Pc`0+C2wHRtR7IAI_k?A(Zi8zpg9-Y1qDs1BuIvA=APhg|?eQv9P&hpuHlR zfF}WgaOvxm#D>t{Z70+g3Y34{;BR5M`d35aZm{j?d)CE1x@7F+ZIAJYEK2s)yH>=} zX3W2?;mLoj!6D~4N} z@+i-k2+KaXp+U}7oc|?~PsRlXes5v~l@kTDsKXGEn7NoY~g7@^p^7Hz?l}RdF2vRF zUU9}hkhKfmX{kL#Qr5}PHz7PpoNk!y^Y=8T@0ZboL7}Uc_vj@<4xGZk z-;L3F-z()^>vb<;=K}x=pq7v2t}ueX;0vB7F^+1_e+oXI`o}c^eG?0{#^ozzkb_|r z{O?|W0Q|p(`mcfh(fgl)-uf3nTj~+i^$2PkAo_E4z7NzDC^|^&+K;5VTxxe>e4fjv ziPK*hFMc2D=s9XW(Xq`Rg3*%cKFOkT>3x93w#qD+GWt(xiRo7DHPr{U-;>XQImPS; zQceLjQI!flz*UnmGx{s1@L^jq1NqflgWQR-5l-@!J-$jvqqG79rkG!|lmYIC;QiC2 zYM`@m0{n^f{=SQG0!LQB>m64;t@kz3$`JyY!I_8P1t?;Y@0%PKp(SYpw;H}AOmyFm z`B%;>GyVl)KG5yJ%j)`n^ZKXy_hCb6`5@YCpzHB;In!(zL&O>uTj(k2X;*jZF~qx4 z3G-qchOiQJg+*Fj1>!f!drNVjo9NKDaY4F$Y!&oE8-$AhT65h*e}R$=l%frx`=2T4 zL4a$I33dAifN^%(2{jD-4P267lK>fVD?p=##>%FE3EMO1JYT_@u+{Jr>1%0u{y&GS zw)U+cH8-e#Idys)EIN=b?u@iv)g*rm8*w65_=^X_!*cjj)JW_1U~5?;c=n1-yh3Yt zcej{z*ZOW25GMzj?6E$|hYnS0R*-8aU87Xi++?@YT12tAqYhG(5h}Xj_Wq%!gliF* z7P$gzqNNl5Pg?b>Kx#pIe`=LJ-FFb(9vFE)WwW~l)*l6w9!V`sj`IzS_Eoe{GU*PO z>~9!bgaSIhOmueG>74+sx^Wou)iefar$nfEU?;me@6i$>jRV z(?ZYMmQdsMOcZ2{d_508L`w~DU8K<_LLWRq=J^lJkhbr$t)`^}{E*HGf+RH`y8zyi z7Nd`)q1`hUqu>!)E{@FheioAwRAf;ks2Ek{Y0DgNBZ!q)KGCL9AG3W2Em^BY*#DDr zWATD0s{8uE*#hUrP!Nu~{cBplrHp@zjc6SN4m6t%b{l=t_ASME;FTL8L;&Uch9~)n zv-ddonHe8hoN_&~SX%xOP<5EyGYb1gSnPU{?3vMLD{@$!pc~w`f`#}Q$$-FZ2*kD( zu_6k!HFfQ!L-5s$wQEFT|LW+UMdgBY0qft9mFN?PZ6z(||8>uh@bZcdBm!6U(6M`1_1^!4V7t0jSGCF9TIGgOniOG zz##PyG+f8^GTO%>&3TT% zqEo0o*@%<2KdB*B5n#>I61NC4CET$4M(K);w*DcG%Ua8BV3CJD9jWZk;_}_!m&Tgy z!*Fb9p(fToSZlJ6(mtSKl(r9s!AF#q96#8N8oMu?L=3(UjfSGtr$<#$boGZzz*&H~ zkhQdX4l>I9LjZy~Arm2nHdVwYf&fTcT`{1DPG(KhK_9x-Mf*|v32yX`(luk~B;ympv4yXAXmdl>#q5BBX zBLo5ByGoq921=nGdmQRP&34bnp*+LjpizUlspD^4W48MWTsj@Sh3tCYiK8Su@{ zq5y&iyu?szTA|M$Y7N$YIN2in2So;JY zm`(4&sNm;UKsC4m2N_^xZF#v|OLo-v@jmOYu(+1yR%-Er(++zM0Td)aQbgT{$@bh6 z__$w$sD0iD#d(hV$m~9xLFY20my0~{=Mer(&w@Xnm~y~m2)L{E#o)WTA`_0ZOKGDZ zveBL<_R~SPK?WTEH6`qel~1Du&0$pVs2C_5PONWCfN_*b6N3N)mX(lW4C$Wz5Ng6U zeHXYRBAUEz=}p%;DZij5$UI$Jl7lv5|&BPaoaa z^{~q)oLe7-eS30yeFB>`(yD`ER&WMLuVmxRI-sjb!bJ-iq_ju-jIMo8;7lWKdv0!y zJU+j^Dbi9TS>Hw^f*ZMm4oTK@gorIo!gL&-geZVsZhd1cX>JyvZ)bHpg7=-6?@%l- zZodh<&3dui1cSV=B2#V-G*7U8d`XE7E60za?>(d4g2MoP9>v(b1c#D#&w==gI&7gZ z3}IEVH5>6&zf69C9n#9*nf_1oEm>A_$nt6=2)J#&(;PbfpNwbOA044VmcCV?B8_i(& zwp7}bLV)3GlDkqDs9!nQbi$X|v;Q0z1GPjKBpLzX%w${U&Z7TDe7UoXfNM@0*3iAL@B2c!jvF1EEQKIj8% z`fyt+2_)p{%(j;L6`P)TQ!!*M!Ox3>8aJ_whLJ()l|DXLXUk{I36-!_HzhcVon~oE z1#zNXR0!-};GzseUSk8Jz)GgXm~h-AZTTIh3h;IND_k3xS+koQ zd6LWTU~}YMTySHO23MJ(#O(Dpxru}qkR#+KTIuBeq!pYI?v9$`+o-#1#8zL}-Q*u) zb(c(Gznf^~w~>671q)a=hlEn$aC=M^5aeGvUi@wj87qD_!14j%se7nt*d(1O2qN`L z5HLJeJ{}7dALIu)63$u7A>qomAXhmOW}5crUg?Gcc?#tVZm9+cfnE zq;&KtrhsQBlzux3rY^Yq9mev3cegg6G;1DCvw9RC;mtZ}=l6nRB=)Fwot}U0&8BMK z?av$eFkJXPh(F@PKGyay^FklM64af9=HpP*oHD`Baq}o@$3dl06z^7_we;WoiKu3Y z%gaMaAIYDt&-!`)Is)SH(2<0kaE@Ze)pz-O+i z?sD?+9wlwhEo+Qa9}h>WT_bjMY{(9KYkLjdQQ4Ta&}u_tb~FuSVV;)7Pm9v&0+OI{ zqE8oI_rma36He(OJsA%bDo@rX+@Z(P)9x2nH{nQ1m@q01`~?2v*%6=#F0$B6xy5C` z4QmU{HYP;l_&|ThR-W0M4QampDFH+W01?(n9oTE=&D~MFZ41`E`C>I19xVe)-W8p_ zkfN7I@$oHKqIqredLE0kNeM8XgjCff7nkVdD4yAsxJ{>PraN%2E#?yuekH3CI;p8+ z9*Emxi`gRLin1!X)RG12c4k%Xc%&us)AdUqDIg0()%V*8$W~lN)oc4#y2_>+fd$iR z6C7ACV4F$_X7}eWwPE4@ProL@9-*+F{da6`!=BMvvVW{}-2`kn!?%ZQkd$xS0XJi$ zi3bs4K#W7#@IWY~Ga@uoSy7ug8-Zpexi%mR0pZG&>U;)i>|KQPqGHiAp*f0)qMD=X zn~1AITpx;qSzlLj1$mh@edr zw7EC$*?~RR?9)(ju{JvU=_zJ=Od+Z+R9+9|Uvyx7v^HtSg%0eV#(VB#fZoB{O z%9du}m#Duq47$AU>E=Py4Yv}??q>XYSJtxe_g%$q#%yu0@Y!cdv%2wC-B_qL-JcKX z#u5fJ87#V##x1?E=+Z`~&{3_rfj2z{UQL~O9iW48QJT@Oiq5=x5@{;B@{8TrXsxyl z@86vb*8bd@FYC^p(sECJtUGJtJqcASXT$it?rf@eSr=@;%nRc)da(4?8|dRwmr57r zzr3v)ldV4a1Dr;o#a*~xIP2B9tL*3qmQs$Udjur4ao>jeoRKiqj5%ip-BJN_y$k%g zaMnSyny&~4Cw5Qhe0MktAMg`;*$wu1y=dAG#{hOtXEg0~Qc?lonx3F;u~J^+;^ z4jAI?wSK(oqpX(>_rUOkN7&OCP>2g2ig{BX^vOV1qQx z7qzDos~FPVv|uUIK`l+0658*Ge2jgnX;s>Xwq^t*`AYxCYV0oal@Sr#^*Cz>OHs_` zqn^UO5|DXl*+X)J5A>VZDb&jf83>-C={OjOQsN_e9G+P`l%x)z&(uAX13t3hLfLGC zvKC+Fgdal!kRO(50=t@oh^eL*Wg3J`rH2tow?C9nWfqcFD8QZirDXyay(x8LO8p)p zp$6`Q9}iL9FC9dA7mARgyggE+Aj%BeAB8HnZ3`*KFSJem=r4~;RW9h}D-dFU=~6IK z8qmBT{KA?p8E$bb1u^<^eYN!qETZji%G3AjnZ`G9_oEO3S4t#T+q2a)xTN#`Pk#U*4era@Cj z+#ny!!AuX6(`*{%KJa=@BOQ)`39XihXDe-65`U7Gzln^Xe=xP#irfQ*@YsH=Q)^@a zhENu2bFfl`Ef&mK!{GbZHifV0$2yEExdEA)^3h!}xBSpVdxmgouUy0jI1Hp%sHaps zC*Syl_ayWaJ<**fM1*xH^8k1CW5YEg`0z;9*Mf!ZyUPHb*|sFuBp=65kbKi%TM|HK ztLgCR=w`1S9~Z>F;sEGuZ5z-TcGz+HNzkA^NYLQ(6qihK&1i2F9X!sQ0HQhuh0RhN zkc!4h|3c{fRi)vw1y!!(=Dc2i*3SE28%!g?ZFu+oY+UcO->LvqOt5&pEesBB=^6#_61E*8^Ea6E5S=XQq zII3q1E1@YV-fW8vBK`8CCixiOIgrI@e&SUFS&M)iY5T-Hh~cp?m~f5y`&#{|=y zg5^b?^7Kh`sC~>7^oR0&7cgjC)*z+5$KTVl4t#4Adv$n$vL+PB^!+*Cxee5Ein^lU zzLq!`$H>3CPh{Y(m9Z$pD6=L?IE*m~u_vQu7=6NprjH@g5|@GnRSr+rvlD}s0I;E+ z;_M2nvVl;_F0qHH&UGluNcZ{(080RryA?D^<}0fUtN6yj?6J0(%z?}gwB_QlDqIwJ zCkd!jpzPxR9n890-X2d|2l)#8h>LaHBK#WUm;kjUFQ8>KpwjXn$WLlm1w2KR*2gD- zsCVCK6|IjfPacSSz<~PsN*dgVn`}dZ(2LUYkx)V4!a6L?vvH3D96KXP9-0uOv>C7K z?IFKULnq88_3{un+qM(>0a1aa#HdX&%E3#VoVF1Wc*8s~gl9yv4uP9)svUWVme*=I zWA5?r8TFcv4Ht*blzZqM5FyRD>$?detjq?Xc{LTTQn9X!f?$lx%7JC=Fw(eXh<4th zd(n02>dBGIcSyTZlaRM-re&RJ4|$GFr|f% z{y_{I>%FN7*wKL|TswsI&`mg8#d{55hIUD`3XtrPZlvf26dzjrpk| zta+1UikR*z3Ry!D?=LMv9X_U1?m2%{V>nIj- zj!|v~%LFjQIpcCDvnq>G27#8%YPm;HCAElOgDccuUy6!}WYmK?lAYcf4ey9N* z7CfQ!oyGhEBkQ8s!V8QnL;KArKGDR+h0l6KjAYSI=%-VX+mCSgglv!kvKr)JQD!;X z2wOpcH2cc=1rs~gsA!0rxx+A{%tuLG$PYfjMzkp(NeVcK?;xTA<*fPzo=?2|myx{R zFxIv4(FK*Rts2~V2KNfzq0&zNe8DhgY4k>nDAH(GiyX3m`Bc7$RD;|NA<+n|$1#YGxgRhN#H0x^Cf3TWAbq6{$ zqdspO$3D?cILm*CV{LqO&w;Q73YdEE3vn#ezge(=cENU}w)*gvBiW*scVDff9hqUi z(u94`igYa(i@Na+<@Bq3>qxdh%jWPdPqKsl-P(xEtF|HY`g+`J6zi!Ce3|zh#X4%g zGV%CPEV=6lRS&Wi9w3w-yxd5I!&5*iV7-shJG2r8(!B&!uaDf;oVOT_+(%Ax{b<%y z`_pMYZZr$&5LT}tuBJYU&U@_H26)5bu$CW}t_{P{SgarPAJtXrK| z#iO2L&9&z`?wIftsHMyMsyfBvYmBVu#Cp0)mmD3Bb~FQ}c_uab2D`s-oD$8qJk3V< zyVWl%x1#BXSFZ>%2UU&S2PQ`=Xkct=ccOx=0lg0zdfF%YKu?qXgvYinbrg!cPgwH-s!hSE5U1Pb!^X>D&=IiS5#8=a1#*;@KjN zwBy;y>b0)?0IeBGkn%GHdK14fru>Jh{%&SoqX>!_L$}s{>L<^Y-Szi zgQnvG($+kFI$Pe_xF4OeTucg>lELDL8%7)=J=MW&Tr-0`qbt}~#V5~T6PnLZ7x??$ zqi(99)cxg7eq;vguIr3+^%B_t;~8&J{a|;xKD3t?ML0I8bYQvDl?v&}Wx*6-59~ce z40zCAq+}>oPGs$y%xVd%QF7^GyZ~QEa>laI3p_KCjTqy{(Y*BQPB<4JP9kkDk31rb zQIc>gBIcL-x$30c2imfnS{Sm|Xi(56=b6V(cz(fCg6A7Nd3dgz=hL2NvaTWYGXH&^ zg~xi-6OEa?p}Ns%jQc3-GuND$0iz+fW+rut>@$a2^q5X0@A((WyI*timuIqWx>Y$< zeA7%8D?RQd67zS^kpEnD^7}KH$@3ykk8{Tpo^5&J3($?P_Y`R=->$A-^y42_oczNV zSfA!bHTtu<(Vrvw_6sbcU(ywHaP3%4y+RO=Fd8FIBsC?s_g>1O&9uClghrf7(z&7; zjBFMt2lrI*=U!x8n!lws$GN^v?UiLt{?Ut||4B$!^dj4-3vMWJ`6Xu5o(SD>WSxo_$*o zV~018tNSGo-F7v6uo~Ww!kbd~dusS=Rf1XFT8Hqei_RUJ<}kCSXv{3-{d!DaNWhS z+5K`UtVK;&5^lW+3>yM$L_rBJ(SkF%zS3aA4HDa#D!;vO!^wY7X06|x$G+2D*Ghcn zJQmr!b5C$_Fc%2_*lmD9QEwlqQEnAgao_o@jpil~o6kZ+M`|Sx7dF0geInl?Rh*PD zAAACOI1;EvUji)6&VttWzS*W}OaA73*2yRRA_5y;ck(^+Sx4{1^yU8oFQ3nfG#j{M z0Sni@^BTXk06T#lhVhmQfnPg2@F5G?z`#$RsB~F}1_YaJ^Rab4hM93>YAs*CkPYx0 z5{vWYn-(=_%R8_2Y09NV%(qcHBzH^DJ&m&8A{Xzvh&7MvErN@vzgknL95Yo`pE#Wu zGL~3TJh)yI?3HA{2$#RAmNO=#QtPm@tZM37Ww}Ivva2b7V-Xvp-C4!2En+QwN6jEP z8NH=^_B;<<%pTDO2l0W6S-Ad92t&7|M$z%OpMA*0Thb)2vfO}Zpl;xb zvk)$Ncuhwn4zNo+Q}OhzbSdvIK_e~C)$>qRoOHUXQ(&l9BQMN3 z;z`k##=lw0+O?Q0g0OS$cm4MU*iH8+?TtKCC;vL5c}wnNVSW~VkH~Lg$P6rY?`C^= z_MD;Im?Vgi=ZDE5ueTMxNw6LGk z-(%S>+6KT$mUZ~6#JwsOi%SsM+R2+QV;v*zRG=H|e#c0dvZePCc;i=}7?3SJO8pAc zi!Y=4Wl!ZVFJm3F8!Pym%UD8SLKY+`(2uw|svh-1qvKBQpUMU_JrhYBB@>PCJ_V5T z404HL_u!LLSqDoH_K)=H(MTA3rwyZFu=|}o*#Is@lpnxt-HJrm$9Z%O*Z12yuP@5! zUR;k9gi7UPVr)sB5Y)jPbV&^&_LmaTK&1Lb1PKh7+!=sPsV&wY#~cHna;N)pGH>(> zYj0_uKT)=$%F%TN zk7+3N0-k5P#czue&yt*o_H7sVG_S=$C##~VPbJD}|Mq~ePFB`T`t;Hr zsD*J3lSurXK|4AuXMHrfGiUDbXVcg+?X>~CBn`{4W-;7*1u*5g6TqDl${(OR{Z1T% zYfGnnNmYlkpQX5bWlLpE9B4>{nSpC>Ay~z~X(9|`t1Pbxd)}R{LYZ9?HqRYau9*M8 zES7JUl}?Hls(%!dgKKF~D^)w&U0j87^e%CO!09)6;R+V$w_uNx=2=WXfiXAvjTNl9 zrDsFIhUhY?p~$9a4-tF$Va1aNA1e@ADWXURLbn@2|w-GUdjO z?^m*hnsKwr{XL2+bcT=+eX5hXR#tG8R!$kN>JA)*xTv0YfQhMRK%5W>^iU=^k^;rO zPxp_Zz@Q=l-Xg(5_a!%4ev0%x`<2XRc^ezdTPlw6el`|tIe8s$LE>pOH^ONBz5;y2 zL$oo63V8|#uF)UfC?sN^!eQ}8dNDiHyZ~aOJ7?>;t&uYTY1EwSC}&GGC)t#KzY~AN zt%b^WeXFTdT0Rt|=(je~2z@rFSXmFAsrD;VBN#1=EIw-=J&!?yIaVBO6qce8gm1A4PHkkkB)kcad3C z%fSisO|qZT%twvdjqM<1`~fFVliA>@7icjA0z8$}bXlZF60YaQCVSwP!^9$$o%fyY z+2SGv6e`Vt_v&nMRSl>o0%*3Fq6XY1R4r7n%)t*Bl#+zy8{cTaG;Gd*n7-!zFJ2Mg|LSI#belz(*W9K)9o$7v+-|cyBvvAAYi|W^SJG!ozcOj%Ur>9QF(5<~Q@5 z+-7I(TH;Pnmoe8WbWW%+$4dJu0M75_GQQW&BF6RtF$%Uap#W^sx+k>sKUgi1p|M*g zXi;5n10f8QelXL$VXo9yD_MoFkS4jj(4g z%i&b^(W@9Mc{aV~;}r-s@v=WejkQ}*Su8)l3M@C`GS{tUgDts(P*r4hvN!0W0zMccO6$K=%5o)E}p=jD6qggT0mHMk;uEi5lYd z8sf|{)K{d}$)ub3aQY)p?dVw(=dD?}p<7ztY_GaZEYNaO`;*drZ2ndRkC z+CGmk#VmV0O3{Lk^#B%;py!?ExHiwCFynr0vu4Ru59xrn2LmkTW+BzW22S=PT_FYd^B{f#= zJx7X><0NYat5Cp~!y%NTLpiNpV{L|2UKFiFIq46SW8FmssC@FRUy%NX9AeY%hNNz# zu19AVQGn4^asYk(^+lfc8tdLLRV`3j9x$E%{2F`2XUB`^ww^goe)TmLXPEwOJ+Y!; z$O>&L7BG6IEOI(w;TI6ips@9d5h=Q6LX(>ZMeZ%>S-+lYreW?(yx6E|sq^9&`1`N3 zpmvXeC(+)_E=>SPf;beuJbNB0)6!Dd>)8wZ`0K1y>$gg}vKWwD!5vH0G3cG!=eYh2)<%2e9G{Hema!{| z4*kA5=P$(WREHUKkEuxMwUWR61{T&Y7xKMtK(uF4`*$IzZ-_teuXY&4u}9Nu!9XeXaiAM zMK#&|njPaqIqR$49Lrzf?D59iMp9daFb)hZRQ3$#`#Ec+T``g?oK5U~00KX_^P)x+8?0zT9dB%DygiQzdck7wGO$)>;X+l1N zP*Wkg;jml?E^GHYeVE6;&4N3BnBTyoG!}?7K!c_VJ<8V<)DJ;2CCtW`GVf>Sj?dm^ zoi#oU_Tw|=CnrDo4r^iYVu2pPco?3pctV>7di25XAUq@SB;a`-&&zlg;IZI=r0QYE z^DWY5<0-^*3eP1xxA3^|G;9{=0gU$Of!}6$=(htNbp@{e#f)nS1;YLGYc(Gl1}#`M zt8t?rP0@y>Dyt@2f26n9q;FX#y^)5R(z810y`B;2i6@s$tSKLp7v>6na|7$%Eh86Q za`y)kYrv~(_@x|x-djU)ryhuV{h60TEPsHo5xFk08mr%?6xIQsp8_S2D+ih|k>DJq z6KKB>36wpg0mLjoQO9edo)xA0%|c%AgiJS2fT1-G9f47T$s)OsM;_gOcs$4UP9`z%;{`UD^QKKRDd zO9bE8apGaVF<=Q_iv*VCi17eZ4IE$1R8`%&%D{*v&%9Z~SBo6rVUfG4`Kmi5F)}Ib zF?GSX#N95phTb2E(Xh6tW!cU+AOZ9hjn$M^O4$-!;7)per>c-qG0E%dac+d9yr6`rnm%y|0a znTY2FJSliG@NB@d8PAV+4&eC}&pkZ8ZIBmFS3LdkB;t7s&!>2H;>p8v9M6^3g9AMj zywpgy4US+WFpszy^}44pYxbZsKW?PV2e>M}?%PJ4>UZ)NKJi1=(z3TE;vGahK*cph zzx|7Q67W+(QEauUOr4`vKv;Dv)5?Ct_&$w7s#AzLiYQ`}qq_3mh*rL#<3W+x!vAug zpKI!GB>?m4hU!$I(@i8B^FTNN3_v%cI1=ABj^^DzVpD@{a5jz#=1lg&K5R-z6inlm z0Zm{#4X;@*d<(hiBld)rXK>d?te4g_nm_h2Td9rf$$$QswST;8&q|lnBWHeZ*pKy% z_DSvv>#@GkzR4kwTZTeznV758rzD}+bQXdP0xBNmO+R7rK3{Fe_;32!$(Me@-q%ig zlDGYo8GR2Hsg&!hOc=@Me#+*BWPdIoZ1rrl08qOD6|_~1MCT&z_ZgtORmh`1W4olJ zZ6ZhgXRy#`Tb#V%=d5MNqi|qS!(2nr2gxl+-|(48x^E(q{_>TR5Br?8n9OUE)?RNM zj=2*jx%;;Mrof*FHhP5Mm!O|0^fJti)Y064-4(YKq}hSdeBmo0SJWoM7|br)nyx{Tz1bzwPJkzF?u@mk-vU$%5ezi!w(q)}Tq`b`<>amrlO$3pP+%f?RO&Ni(jb z_zdScUoeBu_g|xL{g9;bW;RI|S?J_Rn^}y{t&c@(&D^n>HECnq3{;v6?iN{rxe=^p z41B2o+gkxf!vTJCGaJ*iET3@c1Q7wFm4?=)QD&L>q%T>EMx$VHWmW}+DG>cP=kr&; zWV>4T#jyx;!V;#p57pqj*AsT%A56MJBfKOjF9q`WuOL?WU*pTZVi&Z{hVkiJur<9u zg0I`ca0Yw=Ke~kt(6-yh1GnN}ku%TVqqJ8O{=`<+zs0=Q{9(8(*}epNV!_onFa`m( zz)7$9^EESd!HrtsQ=C*b$#>uZCOMB6Z)L4J41~E21f$`k8-$nRvvT0QwbUkfPu}m! zvISmS>(4bW=pJjb9l>S$2}Rs2@V8t(?rYY*#Ykh#)TknmNF#e~%H?l-&AJVGITz!G z`PjGsQWynwf{ww(El&U5PCb!-B)d=hWa6`FX1r zZ&gGc@_P+Feeo6GX!@~}*Z-D{)cz-nPyCiW(@EY-z2teqD64FbG%3ADfd=hVE>RWXLcfAzDjnjiss9&IGkhA_YK(Ar4f|* zf6slB1pWR0e;tk{Is>nmzls;Qf z>aO)q_*=VR;PV}FQ8T=hs2)6hmlQ0~CZ0k{khc03O!5IpyANp-dRLZksr&0Cbf_$0 z^=6ddzW(LyPQ}Jd)Bvabl-ui`@MhUkQ0M}zH0p$igEJD@`}kqeza%@NYS5m&K`i=r z6*8n`OTl3uAOTSf?8p57Q;iu{DjItA8&snwausAtfn7UQ=E^s`zCt#s%q3H<(zTT< zB+%ZG!<+7wqPiWyY+D|37fK z64JCyfOKt*6PNc$VO=*Ls_2af6^7W~t5a~rrHbBo_BC=QuX&|ilMnIiJyP4SPL(k7 z;dtcLY22g|hDuN2+o_(5mMHI+o<8mZ)OwzXm;x6Q{Zp=t|s5~qtMzqxI4$HSdHH#6i!Npx*BkG;HuNvl~ z#_S5~OPqe7gw@eK9^V7|HfS}( z)CVME+s2d&{M9aKIMt3;4I-U5t5@@p1j$VKuCIEs;-EAwF>S9HD5YWz_N>Sc^D7)c zA}T+^31s-Wih(+^9za^IDj%qq(}LQy*vpR}lsfB5i@C=kDWKOZ;=3_Go=_Mq#w}6B zRq#?1H)uKKC9NQxtD+y81A$$%ukx3_dP3I=aCo6{9dU9kqGX*pJHo7>5XWF%Whz<&PduoUifa+kWw zdMiUa^6(=#iAt+1{H&r2{x*$yfEyeC@xYW(YH0b~BTyp@-NjcQk(y|i@FPd0&f1mS zaRerdD|yqS5M-^}Nze-DoKD&}RX$~QfuN!-eBu+AmbR0p9F>Aw4?#L~_7n7%0xgC* zJ<12G=PA(w>aQ)3@+yAIdHzw9v6hz{l>)1869aTL<+|LUe9{Ymn-y!WHC3qjf83IElpIp}0X+50|2*-buq zd0BdeR~Y{(cm?-Y;=T2N9jE#kA$bAqUdKi`$H#tU*%Qa6!0IA&GM#h>QVq2qTgGc2 zgGuJ^ywfqM!GKjeDry&k+PzA@7oMo7UGZwvZV(`rr@$s;B=W|l?^gAh)P1`;fjeol zjDL4bYS_~II!)CcCM2wbgrrCcm|h!?k^mSHn-m*ZGiUtMANaq=V3~L72Og3OL+DjM z@L{=9!=NwLi!D^IXn=j=V`tgWW7xbGBSz`=F<+Al;bEsAD%y|_>#tXPxCyvOOhqvp zR-p~0OaHGu9K`|j!YlFK*SCuvzJ$Ro@8Ncl z6i|gqA%7!JYMk(>#JL$(Y5yK~po-#)P?KD56yTE%73LSKg^~#GIGR)AH`EKdp^c9QgINasY{n?Td2z7HIG$ZT6hf}s_e z#kOXT8)ED|D+2du>AOS4w{y*s>&@B5=j2PZV?1`y*jAKqM{T&eMY0!%2?0p?hDmJj z;3H`p2FV;YIjQB>GadmP_hATeF5tvtU#YS{FRR_b1^dg^XyJy4DZ< zwx4V5s&C+pqMJA7?T+IJ*Hh?X%PU)+SdZI>WrikzP)f;xokuP=JK1zrP>45Ba|xjl$`(I z+5HEwMyjT?{`6iTWtYDLqNML0hmp~kJE+Q6>=LW~=_$-ortJdR#cCM<+ZrK{a@+JB z?^`H^X@BLGLY(dReiL6?h@tBQIB33DI$Hi`vOvdHK3SI2WLaD}Ss)+tfGS1ye)27U zUMNlI?*cyz$|R()Hz2iv>^A#b*jkk4>fli_eYdK2CW z&^mYB!grsP0y_n4fy_7Kmf0U;b*V@_le8JokwlBA9a>|C!(1DYS8={w7-p!Ew>I+{ zr=*G1htp*{>F=1H8v)&0xz~v=IR)P>37h%GQ&KBk;AVc|6#CHd4S#$JoBpfc@VZ5K zW`D!G6+tqc`3;|1BsI|P=Sz#EE?At3iptlhW)^kw#K=}MQv~%CKE&n^i<6hmLIB*^ z#76p>tHVWLdJZlYIXt&SolJ0t=7>5xuQ}Y^#f0MClQRZK0lbvqLbO=ijuC5<&c@oj zjw`1Mb&yEO1Y5mKPZ&cAI;7$pZ*Uqmj9-%wS|7mD%4Ia>{oCY69 z+D#sOAH|__iEL>L2l+x~w=m-xy z{Xo5MKbR=Q;tsx;;K08jw#6U3;u~I$h>?MbJj`13zV5OMcnG?^&$lmb@9XD_#62l- zuRv=R<=2BmBrd83yHnSRvy5ReM!B!o-hn`b7`dmQe=858c9C;TDJ+Jf2E7zDkD_4F zkVKs2I5Z()gp*M5PtQrMJll(Sw-sOV)927m?ItP^E6>AoSf1Am=S_c>jP4s?YxK)L zKJ90zVckpT9ge6fDSC)yaNKtokuYNw^dV*1`m@wNm=fQD0TC!F?uf*p3AQi`Lp=(I z<-oZN0$mxgfqR^nT531&4(Bo19{M*`*Y=AD3_d79c4v1CsL`L*VCdG3)k}17o|6c zt$n%jS^>Fo7vbES4N-wojvnxO}AP^tSf32fw zwX8IGC`?C9lV49m`*JL%MT!@0PN6La?Yi=Pk+!nY_BQi*y(?0>XA4w>@c0)0=8DvK z=;xxHLh4*Y394USNg;49-|WuDD(u9D>zSxz?|J2wbS8U=+EK56umH7eJdZcKD!t#P zIbh;k5%LEWR}DX_)KR}7p9s%!-s6dj4FaPxN>%n|FF$ux8a<#Xj7mU}2f1QOT|MDR z(x>)w29gy%jP)K$%`Wfh@*Ot3xX_8wdNjB; z?@l4*LRr)nj{uu+Tu(s*}C$%|5bFwg>nxi%**^pR{EenEP0rc>F zKJ-_q(XdYib~tIpRJhW>E~JtOsB)O&KUCDYHPw05`>)qoeiO9fNCmC9JRj&`exG0Y zRhkU4*!#K^*<~dP0(~o2f4o<_vZ&YP7zejkj76g~l=tB*B5zV}9QvlyW82e2&kSi& z-k^&7_Cd3rI5Hg~)iO0zyZ@0YY!Xkpx{m+< zz1EYUXLM4!a~9OP>&#bb{lp?_UA6IlYwbR>qSjZ{RJVfvo9f04KIx`Zx84p)@>;F8 z&JeZES;05nl(H-ZFsD}<@}9E|C)*AszJEm%&w z={?&pL)1gcf$i&+*IwZ4Qe?u}ENla6goIe-&6ohtlNGGJU6 zKm!A}7X4E`Wk0T?>f6-?)$W2^LM*NyT&i#VcxDwZBALl?Jn0Xqs}?eaKgem{mM1*> z4=KnGicXC_<0im~NlXhu8shH#AqB*e5>&QsLL5A*h_z%}?N^2@Xd3KfAvS{S!)rRN zHB08cGFn>1nk&!>KXzMc+8!EJ z5C&XWNt-*pqJ_RpNJ65?BbG{lhJ)s#|EMBI-UqCfQ+d#za3kZ+-}zIT7gUBbFqt{; zS5ZF7$L6!FTrf_2Xbj}y-yG#`3hZsN5Amjo)Du3@CMi-!309zVN-$6OBB)afqMGHC z`5r}T&+lE7ynB#EN(!k4*Tz_E%;cw)O^^7 zG$7?%*(m-0gueId3g`_8`UjIt25EyA#0DAYgaaJsi=&~3Ud}&>n?Ok5q|E|%e zpiOpC*zgoo`ilwW6xKrP!dKUU!#3~tFl%0?kI55=!irR_;ra-vV*W>}=n35C4$f%% z;ArGGs$V zZ4XUDZJVRqS8(c87Iyq(;H3NOY2ZY}!xZ(@{H8z~FtnyIw)Q{PMK|h=kIAbMtV>QQ zH~zsuk*8=fY#;M8;n^vr7=gf;6IOJHwFkC{h6Lhr+|Y0`m?w=O*24&O2R-sAOqXrm zMYCYTxqb%!_MX(B?>A=D=rdX)ku5YeLL<&zZ7Fm|2j?rlKNMxwguMuS6dJ#@30NVkiNMl;6(cc-DO>pnCciL_--z zyXyH$3UW0sL9SzKoVl>p!0(oanrkw0O(}sjQunhoBz6OB|K&H~l0T1*k^Q?_=cN8N z@3o82f-Pt6I+WyVCC~tv;4MrkZYY!i89_MBFwzxbk<8s#6qKf+A|CZX3aK(RANIAbX8zs-nEoaw@T>3eB$ zH99nS1>KBqbY@@zKlMPWS9?2!K!$^p33^=NEv|0%RGz_6gX`bY5X<*tF#r*o6gt}c z7meTnlulQ3)1kLBnY4*7f_U>~PgmnF!R_?{YJ(=lO}XZdW^7WMs6`V~52#Fvr%8_Y zQ1nm$r5;!-(!w*=N#zC1qv1mV{zN~grIBCzTdG;(-@ZUPI*yoxa$zxar!Ut%l)`-X zj=^Y0P?$UszFWue?hmCX-NWhJ@=)rbOUvLtJ(QZ)7y-qxlVTm6fSJ>3te{w|a>CFa z{=Ik6IJdF1;i#o^&EVZ1fyd~~r#_Nu*4l(}%7w5MD%j2GeDx!#Zu1pT9s@kdpPr2e z_+%s&Yo}_u?xD~41PvigJHPP=78Eh*f}~LY(C}0d69_Idz#AMUt0Fw#`n^INDW7>hJx2g$uv}j@uSOWgOie}CvQmCr4(g8 zapa|k5etZa*wO|lCo*6VE`m^>weo2oZ9zIgG%o|9bXdTBOW{PnYQAw zRJV5Zc>+2dK^7`+gxXY7J*knQez`@rbricqXVY1YJr-^&lN$LrwI?{uBfDi;_`x!%abWc^ zAcip`RZJ2dy`pJ%UZC3`&+Rc>TU>{?EP#0<31<2kdkXLL;XKr!I(Ys##$EEI2#9BY1$L-3{=Cpe&}bF zpdUpjv=P;me^!?A*;*D-<;q*&AsP?j-)LD25B&_BJatoY_%$tSXt~zXLKk~pHUSba4i5QWROmJ2W5lv z`w?rsaM4L@9q~wiVeIs~+$s5WyvE5d;%tpAKHYqT?sB6TS=>1N6fd^HAihOP+ncX3 zi;sy}EK)xBjry9H#nWABnw8=}GzetBSos$m07-p6P?LgQ@l-}rI4b-#KCV* z1X3-IN-!a?CFtSTqf|aTlfkQT$!( z82F6r(%a=>~3 zsGHJJ#zFYMpO%mZ#ui9xLE0c?0e~paYl2rU3&tN8H~cwRSmMMP*PcAdm4yve`5vcH zL}%1UqtAFwRe>riQ2B&%uE7ohcfgkCTx$eec`>z)c_9PlZZz6JeF*L?Upc)0QAmrJ*CmW?K_=z$-b|@+M)DdA-YJO^bU@6` zj}abzm9{r4Mey;fCkP;xmdRRAwA*Hr%AFOrX;aO+Bh2aDccvJ!`PP1bsGB0XA0 zJfD4I4O(;XwQTDue_riSZ7&PB+b&*61m59EEOtApT-!@oic!Ean}wcHDNM-+qVvfP zec%vKf}H-u-xR;+6tDzLBlGjsqcBVx5mWpI%`ljjv)u?nOq#700)$?~xPzS} zo9cHcY8pl1a$2{vseGV2Gw8Zb|$3crJs8q<&cpLlO@ zULGtcdJB+MgeMEUIRg}exe|_rfkMLXh1;UZbP$i~L3bVrRvmaU6`?2zN74C257xPL zb9`f@iE8hL6|d+I?3UEA^2@5A+H(eDtZw(^mpoXTCWVv879(}HC(s8rI^~&A*(d!` zDe|zZ6bR-u_lr#6e-@9RjC4cdHrTj5%lzuAWNOZk^Ht->AWE1IAnO`Js2gJ z()UDQ9n%mOOM2#-Gv@ z@I^|`5zc3+^I4uh+4()+`CQT7`EuL&+~|CkSKtBx&OG~mYXEKTY*O!?-0Z^|TWUJL z3!P2h;C#+;K8HG=QS?k+QWx#3iC;DRT=0AL0nYg1SB&59_+7>C9DarP9mQ`Meyj1@ zfZrDUcHp-UzZl#kk$$6rf&1%OY?WmLJv8<~rtEQgwn1C{fkd7PP6Hd)pipIfPaaU6 z@#?V^!A&XnsWJPf>dc_kT}T z9oV6FB^IW8HkhxLSZz-eEiNuS;NRrt+nx>hFA{6yQt#e9u4AmEE|eVV7D=CR8E8yS zx5%5(2_-0#d;76`mo3P*xfN@|U-+>v>u#pxBqP>mWWJQVNST_>57c627bH-V5AkQy zb(8&hkw0s!Gx_mSf7V_X^oID3dD;*6sXuvZ&|3q|Bh#J?#0&T(vI$a_;PPnIBg;a( zsXg@VfU00iFyqK*h|Kcs&AXzQGybfRE}f|*Oz6jdtIfh{yoa=O2>>cbJ68LuF4@6# zSVvbDlprEVNJQ7i7>19q_l?Y+QlE8l)h(FCzir5hbfc>Bd5zeqHrutR#Nyz!NDKRK zWj#LCn#_t-YXU1A=N&Xd?J?n~i=`23oxLTPd1|#;d}m{pRQv0C;Fjmd*n$rL3hrJz zVbX6cR1BXz;jNmmw`yg2i(NxA5|tJ}9D}P3Y;bhV*L(~s#a&HU`=!r9cIDHle-{v-hHs0kDZ7{=(`mLv9$DB2}92be;-5vMLX+Mn#EebtibO8kYt}~%| zhN|aWa!SvZ9?_bUV#k~@tu&qa%XCJ8KQtjWiyLz!-X$jvrfV(*$(ALKLir*%$H4My zqz(FPm)P{9y5z(89?4c1Zyna9|D{b)P={ET0&pg$Add!`VRMRmT91OG>49q+g|6WQ{#h&brptkI_p<+P#hzX7a3XHbEP}{|RTkUB2`2 z$?o2cWwkJ=ze^V-Kjs@3268EgE!b|UFiMnqi?d>TAlAbO7>HghP6&4S@%rg58q4VIZ)DZ0*oWdAUn05!Rloj-z=X|*_On*`U* ztH0wequ3!`r!@Z4DE7YY&`92GG<)0K1a7`<4u3GgN8+t#x_a}%(Ja09L9K1K2iU8xTjwe9#>uR{?(!CHOlC%1 z+je|$GCQc77S6kjV}X3aI~bh5+o~UT-T_;aCO(36Uwp%p#<5PihU$02qW$HC4R=MC zU~-ZLVW5-z+Nazr zNDbJo@-|3 zbxZF!zkgGoBkjEP40h5bteTE*o5gzS_(L^fgezY%lcoE_;*|tyl@z?vO^dgXq58|xYFUIgV|;xHT)5W zsZ2;pT_~L#tQLjJ7sCr2?1aS?cFgu-EIgPu4i+b(@*!o#Qs!VgXYk0mn8j0P@XWca zPox);o8$q(5m?r+bURqJ8LlKLcCZEF1;E>gmlF;af){5g*XDE2d2EnwU@jjuk9DjQ z{0^;om*~75Bn5*#;;<6YO6^sT|1giW^8BSOW(Rh|!Q4KNHPwANkJp&b8r8APbJfU~ zAV#=p>xmQcFr`9-llP#M^HkUpt?T)E%44wHDU8aSN%$VI7G@ zr`%^pxx&J!w=g*xzdx4`w6ILm-=fl}S&n%=YM@@=%^o3CUD`>k2REsMAx6npcGkh_ zVUs!=p{KKXwN}2uH^#!j_RruAQ&|hkihGckyp?hfjX~%VK!GdPqe_(vWe7Q1d=R8Q zoswKY0AhCFdpdpRif_zA9FZ(nbg9p1T&M=c!XTkq2sDP@jgx;f$p6I24;;+jStdO!^}~;yT?Q1ZJn=6#&JwrU!NH3BzN?wTr2&EkIOmhpsK(b zr6YXX#alZE3pBwsqg)1N>8u~rrCyMRfSthb*FY2QAy*Vf0|!A8FCN)8n= zWCRcwk&T`}(<~x#2qK+!9>ako4mQJE-b|Y4;q;Vt6hm8BfDv(xxAz@XHi#rf{2g^g@UwRzkK# z(+gzbB-DJd=xAWuER=Ymn0DQ#ltD;=F&u0&c{te8S=1b}k(zQBb-;V%9uK@Y*oTPf zM#F~tqc2e9M+hgFmlSs@4nU#X@a{yF7)X^Ud8UT?2;LVNij??Kd{jCMkM6xriWGe(ZmL!sB4CD@C)qG_GoLN#=gko)Wc25pb zOVpW$q8)N5MU#0^CL7*p+Z-{n+wo9-?C2zR&{QJbc?Ic8PM7h13$aG)r|_){nZM3^ z3NKj5-fF*jG9k-FqTT((l%0U1(kOu}jt=5@kn+}~d!*~AQB;O4O9>6}qE3A9BGyOu zK_~v@A~rzx<9+^g5rkcn@AHmXEP;Q0qpD>2HaLvNChg8?$byXFw@i7sJBlVYE^SiH zfsOK`IP2Kp=;RpdSEqrBc)pzz6Y-TV36F#nJI-dKkGxF!OE-nZ*)ntR*o(6PfetnT z*osS;&2!}(BaWB55VSCp%|=OZ9pu>H5Qyu;&!S)wXKG@yzI3A~2lJUgZN6lp%+aJP zGl_ZAOAFQHZVjqpvMr|?2_o9;rO<&nBFG0p;^p)ATv6>vQGIh86ivAlp8UjNK~)6^ z8#4f<(V1=WsF-x^+tHLPLEg8a&?9*_RKW&_)nO}_hzchLQV>4IkpTAPJO0qnM1i6X zmNSV^I)yn{eKe>G9njNfyg)|B(PGO*!=7loQlA9k0^3v|Fts$%!9Et*NXj=5p{JBp z(5L{*T#;+N$tL<5BSKv+7IKlxWHaWVS|QXqqywR=H%Q=3v!bDZr^*jxk^PKfwTPE4 z8q{f8wcXS}s|e9&#|6h>q{kX_^w}}NeUl*+ZI_HzK+F@Lql|=c32K{zS?WcoZu5Rl zYfL$<(qL;&Wk(kW#K;9y2|C3R?aXnO5dFJ>fDk#>5*(erxg&QtAijac>8%5q}$j z_K(m_bl2-?^b>d#I4#kkaDwuMKnQbKyaXJfq1w^Jp0YaaB+QEJR79ej;HSa~G ztuse7<%psjYtl9G|}e$#choBsDd&_u~(kk89U!8vsM$9+R-vA`xuX-CqR1g0YrBD2%ofg zk`)d%@>aL`2+(I{QeVrgJwBYyDZC@`4x}aoqd(&u>@g-5nhmux3qT|)>V}7deLacy zTg-YUF2bq>=@b?88sBt6b!Q8d3xq_%?3w;lo8qe9bp%qcG!kZ|?k>S!jsBAyaPpK_ z7|eZr%Tr_Te!h&~UCjI&^g`*FZA8E*tRni;H>g_MHatvXn$NYPmPDgW|A*2zMqSu_qn zZ!7`&T~{*Bg0%SKlgM)fRsj7cnI6v11fo?*M)_Zgi#EuQ=-D~W`gW?aG2xy=IM$AG z8;Z+A^%*4~=!V_IE&|<62m-|>u(ZP{K$Ah)^%;d0q>?i!oW}nEedWWum8;S#Or;~B z`^0(cGuBnYQvrzuAr+9UB0u2alosaV^VZ0T0S8PWbsRQgDDL#eCBQ@(4Wbt?OmvGc zmKqCY7uD#~WI|({dL*oxrEHGE@j0Sf0?9BHl}lp~g19Nl_h_k6zLS;dixMJtQr-0n z>j5?d1v^Dg;T9KCD#mX!?4~7Ax#OdQLCrs=!?#^cE)Rh#0|L=4w1&98jd<$BcJwDq zp6`+F(CQaqy9-42p-VvrfO2N#8M7$IUYMN*I@lLj(nRmgu1uDQWZRsJ?)>ujArx;L zzHJH5S;Bf*fS2eWnn~?IsPb-LdXDakg~egEP^p=Jpa@)T`6ZF#Fru{Wl+ox1(o!Es zl-!lFCa8;4lJe(6;_C+Bf{7xMB}OQNpxj4VaVU}^X5k)`*(ih>f_rSUU}qAj9C-xK z`{D*An6MGKKGUwmQT)zJMc!}|r?Q8s#dW6Q2Bs>rouy4tON&0Jml$Q* zE{vo5Z;3ep$Lgl^0TP(TVDAWdWoHch0UCIdt@9e^1qS{8HQ6lx8fDzke!)?wbVhBP zLA6Z!^oxoEy$W{ys#*-7L<34MTC}DJ9OAZ*S)-A6aIvN{%LQfR3^j|W9;F~A5~ zJmp6`MP6mIcsr%6cZSSzu*qY9*GLX`3?fjS1vEXlei_Ts{>xV`gWlrS41RnW_{Dcd z@mim-=fSD)`!7uBp?h@4c13)8>uz{!l;O=$T%OzC*LlQpR=>;L>tNpD`#T5ha>!Ao z76jh1_ca8Pz0bR6qPyctIT$A(z~pkq6ncbItgrw$4Wh8`I$yRN@>JV(ei)#16R-1| z%USIfqx~zG>eOh=dRo;QEHTMTQmKzYuH8+MLp+G$r!L`5RUuXErSMQQ#}Z3{BZ{PEw6a_rcs{i8!IcIsA0PSLxTbI#GTYBuHmJ{I=KV` z8wpXj!8JPdPi^YnKuVH~8z5*Q(PvagMTk>LRFt+Q6&it3B54>LN$C!iGYq2inZF|_ z4*Tz-7Y(%)y=Z(dZxB#y>Ba{N0J5^Z%gvn1f=qKgE_6weI3UQ4joZ|?m z*5FM;aI;SwX2Y0iB@TN}G3n?S_g-qc>uIIuzl6 zc2z#DA9^)9^|ltylF;ztNGj?Spd<1Kxy`P++*6}Ej=Dd!Yj%>ryqJ&R1ft!hZ8^bzFvxBL9MS)RZ$^P%Mtn0ha<{u z(*!&Z#87-U$0|F1!AJOv^x(U;Vd)VImF&7Ket z7>K*sab=Ck)@AcXVh4M@NH%1~1iQktlA?Dt03OZMralw5Oq^8ef@uPstGmOcxK`>j zmy{YN=t0~?pg?}T@e&Yz;0WY8YOtBG?L4gCaAbNNvQ%sX9TJ#vK4LXU&(%>J6 zir@yb0$-ufITn)znIxK_^q&k{hg@9L<(mGYs(!&}zI-)n;(q7?7N=eO@M_k|U8eU1 z{GZhpiXe@q1t|4VYqA@mL~8q*t!NE`59|3 zdEBy#d;hfm2KZslEl#@>;Kw(8#s-cFLdW24r0}!2#5R!b_85T`Nv@gply*cjTgyjM z_eada%mLNN%~0RM&lU%!9#S*jO5fs1pELhPT~TsR z{Cx29!><*79q_Aq^Ph8pUkAfYnWB`$4oKhJOoaA7=2MLbX zCngfin7K;2NC@%A7iCB+pOY67(_z?6Swq3g7P=gvj8lktf%G;J8;mmL_D4Mb3)XTR zWhvem7rBvM%)aRkM~cb8o}j$+ve_wJrkd zzvp0n8iAHnHN&53hG8OuG?+;A-W&R9wG4YGCOT_^*zpTj_kEGWB(G7I&#UGZxCly4 zr}ad%K00FDNIFMU7@ak4q|*H!^?!x4p9=~d&N0c0sJ~5-n?kfWteJuX>(trr+##;7 zNZHz*Z{MP=#aFCn{ypoXDmZWyD3}1)>5yx#52!E?zFl28YUc;0D%F_s?Md)&>~R5HS5NSjj(#lV^G;vzk)tu*0$p z;%hdr{_(?5gUpW4a%??4jyxi495 zi*GW~JLD8ZPf0@r%{tJ{8St1#qM`Xv)0pIscB43DJ&d#WV6cEr_u`+9?XJ-Xow5TTe~ahn*KedEw&K2|JXJ$48{Or-|$+xlu9EK=mXbhua_-SF2; z!iUGo@|W|R%EC^XvRubL&|vF_JZ^75R-@0ROsT(Xm3JzV8@B7pQ~#i*);ZWEG_^8u zrFe>ozGjl{MZ$_r zY`FFcAF+wmP1takP=k~UDc!Kq`=r1VoeSmLP(XEtH--6|NzUAazKf@QnD-&X(J=}v z5`owaqdV+JAi{<5=Kd4BU=s_m6#gQ%cNvQi948-Gi>&hJEAiJPFC^@PBv=KPCxFPX zayg;6cM$HFGT%U^v}YQm)-S?c6T}hYh-muJr)ketBk#<3lAYBvU9^Lf$Z!da@zcnQ z(@*#C!=|ASHgB>|ET8%flPsGuuv@H=+jAsYC+n9VL5zaKk7#b+2w}ar9iAB~8x|vH zQVlB`wgktJ%?){zKoMa&+N@W1~CvW{V)*eWw>a- zh*S_1pv&{(h%gKc6bX*wBSwEHJ{TB>V|#mr+ZXNdMCR1_LouZs z*u5e%G_V-vzKD~Jogomwb{|Hw1O4UU5msZM;$59O3Q`4Q5<+Jw^{SSCW8w{*qRaz8 zd7wXJQIG}L}4+a;!qHsuo|P|tSJ#nNgnXU7#(UvETF}N8arFn3d#ovZ3k3jJr3?TOY$fe)ab7<+M z__}vvA76`goV0flTC>lo?dT?X;b+ut>+mFul!JW>1jx)mxIw=>*TI&HPpoTsr9A?p zad)olqb{v`>FlAh5bFX3Wt3XXHJlNi6fp@A#qZ-Bu!;OiwA_TO&gg0s-Org%b$3Sx z7nIHj%I!H?Tijz)j=9^*i5rT{!sXns{RD>}RGlu9h!_~Jj`pgZ~@N(oGCt7MAiAfQmyx9vf z#T@e+6|o=3ib)bJ@H`VA^1uk_Jv@M~!1wqm=mbH0tOKXS06Ue@!1x$B-s0grBxIx% zN<3;)0kW(Q^|Tr1;!)u5Jw<_VrxhO~4pISdG-atnS@4|pn~I!up1g2a#gIiA192Qp z_Q5L2{-j9gRaX*mB-?y!;2Ol>glypVVB$)kV+Wf>M|wzE`!l8pU5$ppt)2j&ItqoW<|?F zM9Z*g2EE;T$6=ur5QPmv4zP{2rw2kHn~J^{pDScdp&#O%D}u8oxv3>6Mcc-~W)V|tb4VXmC=FSKcniGs9 zX~w_pMWw+qVyJwzO8X@u z@D*cFoyK7DTtwnUW8e4R$Tuhwh@w$1Cx10(dke*qqSv1G->m)=NxB{T*#Aa8n}bM5 zp*8ki|Bd{WBCAtm^Z!O3rbsnmM)@5unQXdIYeUN zPlGwbY_NrBx;5!MI`A;^_d3{tOR_4RVQB=*gzn^GW-UBd|66UA>H9> zu8O}?apy3lJUSUsAK(pa3VKz)h$M0P3_IS_j?(&?{wz?x=v}p}H{lYr8>Nt!t7N@M`Rp=H%2H4<51K8_L@d|+$m#^ltBJamrI&R{302nl(_tW# zn2f7S1C;JObqDhsH-2^rsAYe7zD}(s|GR5pE!TsZO^py;7&C|L_+(SbfVeIFt!5h{5HvQMHKL<^O++ zmi5{5{0-^Pd!_`&L`?0OQb&0JUuEUhz*$>Z?xGqe0Vg{UVP(g)O003n<+l}A&5gX_6 zkGRWD_U6E<-R=Py=Hrw|e4x?=>7m!2kw``UO9}-WvyZsrh>Lov&%7fP3_ePkFAjp{ zfvBZ+S)79zl!6m!d5ud@G4O#8sCt|EmYuAw|3+j`mY2Q2Ink=9AR<0NhUB6E`lZ z1aEKKkR0tEg7gr5lcL5$zMNQC`6~v^Kj8;w!s?|FkgVI(F|>9!8b`` zU+ne7_Q4o|i2`}Gv2zS~J8Mcb>_UtYYXAlMRbvbR%`?(*Ta9vZC`KNGcoSlCDp`pG zNV$wkJB6UMXAm{PlO#rt+P}#a?vhqveL|OkIf))ojyCP=>yX;n9%sFAUmH~%Cv^20 zxT>_GVK_oXK~o;U(v{WeIY5n~3vCY!L)oxE)Mwx#)N*J5Lz^N21|C+?pJJ_*i=1#I zgeebs!fu?Jtvp4E4u9}H>FNz$*+yo@2`m-k?tpNuYVvV8~+bG?pK zJrU+$|8`Z8DggdO6e%`}`i%MrP@Z2Q0Qq1CAm1bj?p%;KyNgKsDz4tg zCf6i)jg>887zhms`5>Nee?T0I1tj7k!gFF^p&A09;2qPR5g(dTQ$P4B+6p1DaxDQ! z`XyjtUDk*E>g<6$3jI)&;4YiU1J_L-{Q}H7jq-0K$XAp*Bn|Y{H?pKFo#n#On`v#(Ns#D?AIRb)9=Tus>{GM__JMWe{-3C+bjsVV~?F;aL$g+N8z zq#?Q8Jy-%7dJCeuGwA$TwBb+hGK}o#%wf)rIINol8){oF zHt9Co63ifFYJo~qTY_Mg@8Wxog<7KLSTW`;h3o*kMpi5F4o0UyHuzh6jx*Z0=YH0p zNi1;0UIH0l`lPYYR^29PppBgyd`IOi8&dR{JG}3H7H#=RM8-$J{I`=UaiC5HG!$PL z0x~7mU=V--#0zHT8025|%b`seRN`P&kOs>b5l#6t7BdH{hXJ8E76~}A(F@y0dAM)r z@Mw6b2}PoLQs}%G$aahxD}pau=SkfA0F0D-*Wqs+U~lM3YxD08K%{)WHa~TMbkk5`aZqAb_3;ls+{HIz&qz;jOF zVJBUJEUqWD8hAc3+2+EG%0t=dAk*M7lNC5dJ`6lCL7Y?AKu*)~At*mQTfos%LLhb1 zEetl0IZ5F9;z+fMV(VdxPg170qkWD(W6jH{zV9ILe_X7Ewh8O-HQqROY|QwS31i34 z8#mT!96R2aG!}$;f_2_Ft1*er|ELxS!vo`NEmOBc*%zbt^{(684bqLH5`DNGfwfCA zc0nZjAnSrL|H6FeEhG({mt=7K6cd^u;^~Phc3kJVXFE>dn5LpmyYQWK3 z+zs#=SX@``aVON6#J|j8O|)ZqVGc+m`unHX7hDGus^HSnpu?=8 z*IroOAjs9+M%l{y9cH1HhYK;Ju~>9Xu1We%dsS39SQ#SW*|trYp2)N*n{xq+%gdv5ccpR+qrfi ze2|l7NRLqL54uwMQK4jU23vP# z?@Z(7eFcvSE4*uER6E#RV2eps7W2;B$9JK!^Ir-tQoh3z$M20%kMs+sqI$$THA5Ov z_}XyH;(mef!J(EV+sq+S?IvdR%EPZ z--KySvMuNCO`o}(sEO>3LI|L23IudHA-EYzD2+Dxrqqc&e4p$kBaHfN`1HbI%1Yn^ zI|Dx7auhxu{zMnXWX%|AZw`2Hb)dKIz>8B(Xm4}N;aJkLnV)7Be&4tC(}cD1(^P5g zr}+xc6Cr+@nh3k!(oYkP_=osy3H8$)!q0;D#z@x@zjwp@G=CxOQiT1Br$(!*DgL>* z*5sz2*pgnZZTvLFNEM2w3BR}TTY%ph{PyE_8NX8eCWiZIlH2)dcB0fKc-CtVX!udh z0GT&9#v1onAL*xgf?r0IpT?^*fZ{hE@5c;KGj{XS4DINr*@U01gP*1@o|8KHY4#zm zE2OK-yQ_c}9bz9g6Rs-Hsy5+SOa6trj!r|UV4TpkN+W5AB0mbu<9|vc4rByOb7OBVX~~>1TE8Y%vNZR zoySTcxateZTTT-`zkt>COC{0>5l$J~MN_LQs~(~3yo}ZqLjP#$U1(TtBANjlL>*G_sF<*`O3DZe9|?kNTgiVv z&VpJ-e~Y^xLJvcgta#TXy=$S;m>`oW2Ay_+sZz8xQ=vTa1m6F{?O6y`5tQ%t!xq{%7sZj}KgQPkiLw@nRBD7^gROsc z5n_^M0S*k`M1HuCHBF>)k@G=r8gUky`H5t02>I`)q90(x5&>T%RJ#0}Jg_u=h?-kN zO}3#Pj=ZRYlzZ->}VY(+D#r@zy}Bd3!({Ig(W9h5Gz6Q-L9~c zpffb4@Vm)|$b}I+_aqC}t#82ZoMiK=pTkI#Jy`;HXQER-^4X_YcWneeaEjHnjDjpL zMxUJ@el^DWQ3jxaWke^LtZTBUCg({z-UVq)W8g}3e(T8WBm~cc!?%wT@j^4pO$nqD zY<+b~Q+ly3q8O`47$bi~>B%}lgc7v-`?Z+K2HQvfLIBAJ7cr?0l?$(5Lrh~9QF5I1 zjmn=F2YqKE&n#lC>WiXmUI`}05q-8c*=l$Z8+Cf_ZMwjM(wr$`{w)#!)-*;zC2?lz zq%z<>wOSl_nG{1#xN`RTq6?`4P4;tkn)Rtp4YcybR3Ji6;gI3f)2zK`1aUi&-ZQ`C zTTf%|jr)@4o@VtuqQCUk#6;|B$M2j5AJE`SUhNDU03|MRmx<3m!|Lc- ze8tb4VYLFcG$gYI9XK%*ZP-KWGFi;i6V}ykYAT(%A^+UTg@6^gmze;}+>Q?$Mqq?RKrDowUef<-Tq(SULkY7BLwT7WtLaaP|c<3FBdf!gK# z{8<*{-eIvDT!Qm|&$7l^6K{Bq_4h0&E_1|L+yAhR&ppTb`i+LA18~;rHXJX?SVYQh zeb@0D=U9iZv1qq46{2+&d!OPH*hvQf6O@0TcvXi$pYe<6_pVK6q!L!UXEK5X8< ztO1ciE5ej%*f%&4sRNjws}uoA$ao(V2;QhlZhAPfz_TekEuu~-36)VKFe9g@#{{^2 zRJ~l`R54JiJl*vWfKi0WnjTFRh5EE!R(e~cQRdI(H!gqyvpGu}F4D>(83ZK)T6!Wf z!DR?RDUX?_#!$PJX0OCdS7XLej9$c?N4aWG6)HA2ngm5k&W|)?u$4?FYGn#U(2o?9 zzK^~URhZ(LE2^j|Zh#lQ;v(w>Qu6CX7J$dIi>ztYB}l2=rp-%Jc#BJr1vq>9vOeP@ z0m4eXK;#MyCl_8IAr<8D&<-kJw1#N;7B%S>Q5j07{J9g&wQiw~kpGF?LX>=db3yb? zHsQk@_5;d-+eC(Ndc@-4$n}fbL8<2cNi;B;Iy@peYfBivc8S#N6JLJ8sN&B6(OZ67hhGCm7a7U$SW_SHWb&B)9EQM%fjENBPkwo zI+4_3H~BOyU}%MZspdGoCpKi zZk^!%zcMBj`IBNU#}t)LRWtWM84=v@D+`gzkZ_NytNRU{qKG=IU!G%4f5hkg%7)b> z(wlMC92D);P2fxu54?`!E4u6OHcO93=GVh52|eMW}*(T0z>&cd|e z{G;nEqB#N6XH=nfsnaREAbJ2=7HD|{nE0>BOHaZh z8gI(_UvR`5yqzEx3Uva8*W2Qz+4D9<|6T>63LE=unWttCN#>QaYQSm=fUa4i97cfC z;OicH#o+5}%y6f{*Uus*R9JqK#g~numLfaMNSv8c(Nnul({vnapY#Y$KYn9PYY=s! z)xcM&gL>j#(L~<-cQCTMYVw5Nu}iDV`1s#hjBa>MzWsOBAG;x!TkJhNCf#EF8&XGW z%>Re7?~aS=_~KdWDCnY~*db!CF?PWc3m_J7UAvAN6E)Rz zjmA}s5etePP3#&`qh5l>_KRTM_dRnLH2J*u$K&%^?#!8f=FFKhGiS~~<7$;4FDzZU zL1XPmmVk?r_|3naz4$+W!ko!xyyhLbq4TsS4|&`jh;zG^@G*B_-^3#ERS1ysYw!bi z>Id>_cnQ$50f!0#Z{=r4Z^!>q&0!CD>^Pe8i2x_P7UJy+n?ybnCY=`>Kas z19*Cg{FC#Eb7j2Qec9?gtEzU2KGmHvEU@-_PaLGzs>H9{$0G z1y~cCB7$8msmz-`lC9EeSAOu392C>OGQ}Ytljd$s#9bW3sRLNFP}UKac28gh8Df`r zx}ef|Gz&!0obPz**)CVA%?zJ_A9y zSX$v)g|l(L(Jp@^@e_~H;_fc|(PP=G;iEUsNDC7dq*oA#0-g66Ii?ztDHc@zl<2fc;(HGz(m4SH;|ZJ{#fDxPvyk^8Au&3 zZm)MUsZ0MRqUdBo+8u7l&uZ9-kD!VjN2!y#c~JH!CPE#i#l@bNyhw|iT^@JQ(K24} zR9@m-cD#)D|DU|rx50xl9JC%r+@7Ew9pGJ$orv*5O%@ zGH!o`I$k(X#_PS7EoN6-Xat8n8tYHzw>awcC*308Y1wmU+R=u|hlCO8PuL?s*a$Rx zuue2P5ub`Jvflg3_^a3QNW-_&Xj>8ZRL|y>!OXI}p<16)09pG!B1E_ra%RV+?#(yK zcn7=OFmS~~+FC0_$*4naPk{~?#{t+FdYV!UDdbD-U_v_z`L}l1cbW~9Qiu6NouVOJ zdT45h9V)v#v~-Q0^_P}ETQi6)a853B=8qrCo(*3^?E32*3{Aau~EQ-gBLxR0J)iRiM2sNl5P0bk1kK?7FzJe)H*t8ED+ zjsuCA9JpCot-q&?2UljtgMIImkp_~{eyGjIlxE5@VOtmSqc!34=-tZ!QorV2F06HW zd#vivTRYKPB}9T)qzkk;Y?j>EK{Q-MMCg%$$0^*v2-RF$84gAMjK^KDYz#@7Yrg`B z>bVKuILqM@dc<{=aGzE!j<76zF?nPjjzS``BZ%8R{FDpJtugZN3UvK63Fy+t^YyN5 zv6Q@x2UlV3TW#4`$*IXzwb%Tos0__h#`$j4|5n+C5USF}EQrqpr^6=N0SQG*rcC4; ztFSSWX(F#&mCce~X7Q}5?0e~#65hm(wQ>&F3A%G*wVWk5tZwWR=bIq5M()hy_UtEW z$4T|?pUQYocb4L|%mG;RQ<-hIJDaBSY`qCZXC9{g=mCdF|KYqJkFLh*xgQ)0wjhMC z(9V2XHI^-%p0U=*TI=TVHbyo#ebqfNS|$=-c)tp^vR^(DX{0trW^rrj^{e28*n@b_K3R0i?(872Hqp`wPF1SMXjnfP?4UT7w0rcfoln z?(Bd!H-j{0>Ed2`$&AZ^{s6RmYD|v_ih(}mbt?N3(Ov@@7L!Pf4Y2h0F#g!z9p(yQ zUdp6aUqI_4Ar_F)`yqoNiy7{ZLaXoHz-uYk`iBxG^Fhg-B!BVOoUksLr z7mcfRwYs+f7@HP0fY2bk4FP&wdXDHZC(T1>kXm}UHoXc>=A~N&l}7$KvWinBvOB^} zUaYzFM;uS|VpDak_+c*=7HB5I0uGefpI~;* zBTFZz)Ho>kJ5U~F?O{?|eGSz|nFU1VHza0#s3e@GAiBlkUtY{9^=k^NKy-tf)N5zd z-?o%s`vc&E-e^B6pIT=PjVPvF*`9M+i z_?)I@Xq)p%Cbrb$k2P;#*+TtlmB7-Y)x4TFYbkv)n47&>vZM^Ifr{HbV!n@X6yzFK4l($Nu9R4j2C;em!{tbYcVSYVK3pS*;pT{BFXw+2lH1o zSyXFn5|49*!q_!uCt+X?x2@}67G0OBIHviG-E^i*ha$(+U!OoFM=rX`r}?njQb90Z z>%#)2z!1LIhqaS_kLNFZSVHicPl^4Cq0%VVA8D;!Z>kvtB$=Kj#~q)R@o}|SGagml zMc=7EZbbW=EzfC0g^MkGYuCqWz}sAER^;OD$OR7_oKQQ!qsjjf{BbSj$4d*H4F>hA z^AE|ee->Q^g4(!U!=K3c83u z13eMfxYG1wJq|n&{J<{vpOM;N z50x~+NtK}nrJ2*5P=qv&7_t9J5qZv;PrmP5yB*nl&wB1TeYSb{0g&VOL$M#RWZub7 z9C~xPFgD>-(k)jUKJ9Xy>C-%SG4EHKwH);$NE-uCAOr^431z^|p~1*w6n^9J zOT}*%exKm?1%BV*HxIuY{FdX#@uM(;m52Yw&pVt_7q~ST(gN9*4VkmgP z7Ta%KJh0Y)1SwEbMO5m9x_uKNLc~qO_1YdLM|iOqIcL-rA{-JG9Rt$FF6xe_SU&{# z?H(V|KMEKZWTGDBpZGD8@xm3f8l4tlQK5Kpf#>_Nke)+Os&-*2>$a}+y3a8fj>X+q zKo6(}VFe|tsFE92dMyN~nlONpRU{E8NPyhMt-Y)wR{~YP#M}9^dM>|V#8?f9e7ryF z7S#uOp5`2L6d*8_NKP;m!ymYv3TGmmo%&!onqy8qkSPe^s=CW^TFBH+roR|i6qogEonxpzC#HNuy%9ySXrL2aZ zcz_vbkCW3ieJluJxqDS;@a6nMT-U|-YqDWWU z+7%c1Cjaj2#CaXoH)c7?ZF-Jk_#=U}D=xX|5r}~sgb^GH1gz1|KpX%(G1j6WbO%#a zEx)Pf(NBqR*MYy#j2yL|c_ z-yFz7oYU?;W1ge1h7rjlDLJ_6 zscC#mD2vCQ+uxzAO?A(suRyq2B&Fj#^Uk$bymdVmQvJkL0p6{F=Nx^-r_^J!rC-PM zNA=hwmyNx^v)D3N;$W>vo>tUBg(d8g&n8 z%|rj3rskbK$Y+GH_R_)xzB`Nsn6eURb$l@`CGh2qShISGh@}qKQo)Xh zBU(@FMI3Nd-G&jBUqst`Ch!N1SS_h{0(T3?cVGgq7tT6*<{TsZqe)4}wT^f+k5%RVA)lx*wStM$SF)*LD zd2wx9Sa!3@GbuTe-b|tMfMt%h%pzz`G&uAL^{5EpA_SC_(~WTX%FhzEDW18GjWuDiuIhGNO`-8La|DlU%KBpC)zTE*Q~z~mG-+FHELwsD ztD)T(jJAcjLSTeetHHSoV*LHf1AaD=)$OfGRc4c2?yW^3={OHjL~&pJQc(-Xt93ZG zvE)$asBTHrB^uov%_0!}sXMcI*XAt9Wg1naN&}wOob`{;O2L8aO+=xkwBZc}udiQ5 zN|*~y07`vX?+k`1^l{2~R7>W?JzB8uE9D`KZ(ru>8IryIRmCh?>|=ZDp)<4c4#>#k zFI%t>Q*JEs?^{pH|4T>ycTRyHv}A{z?R#IXZN*GpTD_K28N~(puk6K#@?Y_Wtyn-O zErfPq)%k-6)v6j#->kjaw4aP^gS1957E2{4Z$Z+g)1?#Yti7*jA415C%TB)H%UiLU zHHYmW*0Yd`AbvtU&>{wP+fb7qZpAtnwSrbsc=5gyuXv5tETo&8jRsXWQ!d>!!WOZ^ zYnT7pg@B`-OhRFUa`OYHnv%bxu>O;ii(XqhQ%h`^3anET_~F zLwU`%EZWWcS7&U3K-+fAK0c}~3rx?dgnhs(>Jl(7Qm-vTO)y>N_)Y{|V4AMaeYq2b zJ3l3%1L{ z2$wl}Pl`c;sADtGEgD;WePBW3FJ}V}YsdVeJdis^e-yg(P87P-NdY#jhOeC=C+vi@ zBp!c>!lNx#!xt1D^)p0ot09NNS0kL?+~VrRH@9O-y-;ArDSMT;+T@~s)vK7SnbP(M z=*b&5S7CuKJBvd3Bci>QxMKhCAJB>7QWkU-W@PeVoHvSV&T$ZC;nj+tKH^z*l$N`kkc8}B)tK4ilb1f*;0zL z8EAoHH8ZeG{bAA@+<8ueohh<~(DxC#T>Xas7RBmF(BuPso1e%k|nGn)CWO5RyL-9bKT%`SF(?q&>QA$h8n*+j&& z0EA927V)_m*eBJ3CW)Xj5fn!2`Sve3%5YMEJeG3cGVE$^qx3C5pEL83I78b6-BGg82 zVZ$Ruel69SZ()x7qSVS=(<=&YswFn7PvR{ufmS(Pz!qhoFV*31!5JEul&;kHx8NKNOhZGB zd<&+|h7_@lz_kgSvuHQm7(^aMF(_ve{?!p$5N#2lb5fh26DCti^h>dsP_aw|l~;7p zX3Fmjh2#iJC&=$WHId&~BvWNAyF5pB@yKqNBfAY+b|MHSQ3*OcXHfy=m+`M4ksxPL zA%%?6O1cC$N=nj7N~V&&(?W_6LKW|blH$H_5fyJtL4ZNChO0b1hJ~e<(jzYP{Iylz z5cgQ&1i9&T#~=^FMh%?1ei2T{K>EE0g);)q!e50G_sRA7THGi&UnCP$s6fCsd#Lb{ zdI)?IQiLx;^F@hbv!c>9@2$q7XfxvRF2b1z=XcSBPvj;xU>VHv(;EsXFC zU$?d*tVr`c(0r=q>(E(*J<@y!w6HSGce|Yka}onw9~>imTM?FyOl=*7mk1KRnOd9Z zG!?!QEzG3(u4_Kx%n0kD`Di|XFB7L_sCIK%suE>t__#TU(W-yOPj_ZD(|xoeCTTGfG?bQ!nEJt5do>oO--7c_X3f`)t^nm^ZPk3I(lzgH&AUv?CQtJ{ zrVAK3Sp}NUQwuAEPaW+o1iSf5H1uAgt9KQ3sk-&uHQ=>VAgyMOx@>y{n*eVs zbMO}t)lrvJEgMH&rs1~Y+q#&w0;w**WLM3%P4l^9J~*1S1QP)XibzwW!7GuL8#+Pr zHP^<JV?4@(`d?s zCPUM_Rr@Y0olLYRfgP{s^thqb5ZwwaYiB27n=W8Y#`y<<2_g2kppXralOSVECb7aQ zwS!p-~Z*aIO@s`~*{ler*Q@Ta#{+R&CgNIW*^4&=5u{7J9PxojGgK@l!Kub=rjrv$ zigGE5R91tEPsO=!$#_EdlAv`Wm1^eO<5@G4%PMhF>57xeKc<|51OwIkweK(nc*EKp#_^i13Xe5O!&?>DZ>E@Sk)PUPFY( z{3m_IYEaAMfhXDB$5PXwLNgE}Ld(f^EP&qoNf?_NIgHNJxIf1Sx3kafEgMf zuL3Yy0|+jR7_ca!6VInwiYlVSh$zcQ2GcSbPTD?}W!hRJhnTclG(iK^1l6d&3(uLi z!fNqBK==P2$N{>xg^3XGk5s>Jy zh3o1#2)K;i8WDj${>p<2(}cx&R88nD0#3q3$}-VabZq&)0G(0e1SkzwF5VHJi#=)2 z#wsT|A_cvT)aspj&(&hJaKy4NrQGpK=fASrLyLWa_LEY<%tCO6g`)KGH?6gAsJA+%H^Hd5}Mb1KPA= z*ICV|MU6k9j=?6fFcN+gq3VljVx+rL$RF*BMT}{CX@xxpo=g_MnD2i)Mhr1d6aL&Ci;3KKx`a=9<2h z(poOZTX520xY`Ig?1HGN)nS~L?;V0}u7EbzpbrVUxB}{=L3LDzR6w=8g!+Hcnv~j` zM>8b8GumqSn}n}wu{I_QtjnMv5K0jicn@Z8?a*XPbQXa^SAOYJ4&=($(gqnHBPQcu}S`IFwPGuugw zwh-Xq1fE7QC8+i_-dxGcvz%pU;~jI^%y6F82U`rj5qx_eRXu-4kvPQvf;;O{5Ni>sLWj!U>-CT&v#`&6LC=VIVFZ5+0y6yZ;U)H|vqwiet z^xZ?V<-EEeM+~dVFxLG~i8mmq>&!5;e_Rfpd1HaKN29x8?G>iP4I5Fo8uA*|w20Ew zm(BTS{a9V8X&67zk2TYcUfZ9=2DfMjLv%+$%+wL5)pcuVtfkS8WdcG7v|!BxKDIv_ z!0v%cFrmgBDE7zg?>#O^qB@)S)&9&^y7n=D(VsPR`x0@8NvYo}ym1oq_L15=beu7g zQP?Ot(3dHaI#b~zlUQWamGC5BQ^WF@G8VbQP^{VjGxAZo=mj+Op}T_JajJq-TDx53 zV}2@$HLTmayr?UzjBIH13F?FYFcgZo9xyu$^TKL)YwnlK6qoK);uh#2C$n%l3LdTY zqmYv30CjvTo|(+X_>_F)3a zEak*7;KbG-9<_oG+O(vJi}%67Z_5wfCu-S~7N0+a1oa_iPMka%=YNN0#96ynQpXP? zMa3i7*TBpXUkOJewRrUu=9xYYNySyBebi(%XAPl~#EjIz%SG%H>YAoRvNM_xXSh6{ zM2bA>M?8IY8chpF1{(IpQ>nnUrggEY`9tV22}D8{+bTOFo?5>m`?OE#no_PmX^K(< z?eeCzB%?st3NNL7OwI1@p*CpF52diqo}JEO7+U4;&}OZygEcfn*3bg>B7hJn0)YTa z4GooIs@JkFTJtU{Z^2iA%2S2N9m%nBl@F8`QGv`3$V(ve6=orU%zZ=3k(o}|1Tx39 z(uo~F(cDfsm2ki#|I*-Jn7zEJ9J9vx-y$c%W+b)&|BX#cdGYG8>KZoD3F^Sef8%l} zvR1Q^A#XW|_4S+>B8V&$Pz^int83V4uLZO~z`NLSLDocQtKJe?%4!F8(D`^?2)+vJ zJg@tf(At$3LH!S!RDXeZl0df9X`GW1!7QtW8>?JzQ#y61p(aF}3Zc_?fKcWEeHrJU z2f>jXb1V~gbj!(l2}(o8WYnFyg9;Qqp*5^KiW6OMevl{zcRfW96shxD{JRIhKjrk_ z>j@K`<{XWU4G_Bhh7bB zYQIa;a_GNEy2*0BWGFLr$WH$+9{)f@tyQ(CC}P0C~C#^X+qr+Rf6zde-o@cb)K z;A0m0UrV{(An@V6M+;bqfOqjR%)n<4W8UdMVt3TRBBAB59li=AjH8qeBrGq_mlTvi zx@BrLA;ytPQ!cHy(06zsig2h|k@y*S#u)*EX&OM-G=x>yjup-5_ZrT;(&G^Z zmN}e8zzodr#A>Z_T}(w7017@81E6Mq!UyKcOX`_9@1pG#5(Jl5QXNimV+Ai=1Cv2S zu&3T58au7#<7+<}-R6~XUN=*Tl3JqSwiO56+xu z-wL7~34~|VWwcjdv23Owv3hEcGBB}5kq`Pi{fU$Xs@fO5#Mb$wlQcm zizK)VO~^W-)_he8lTOk!dXsK06}qP?R_}cGNcNuV6O2GL|3xXUIf{iUx5&5VMJa7j zRL;cFBy71@7G?0{Q7kikm`T&zG#4{a-;#OvRpu1$d^}pbNv1H~(!Bp}$hdbs|0-z8yCG@sdZ74a9FOe$(-rkKYRXKEdx>{C4A)kKZ|!FC4?ZZ7@6=10t*4UN<_a zv0O4PFpAmKa0r7CTQ$&~9RoEWXbla!$Wz{Dk#U`@&bVTuAAtn0kDgW^2ctR8PVMGl z)s%`Qu)#AJBr+0@`%DR57SQX;6w2i{j&@1#EqZ^^5+G9<$cz^{%jiTc<`($ z_E?Y|tSlQ=AQA=#RDuN~Fl;BHyS9jT9Lw6Kvqdz34HFUHv6FNx6&Hv&kcZ^-=HWP+ zGb+~4#p4&DDmm@iBf+Rv?K(vqnK(>rxRZpcZqRBUspFb~B4zTyUTsqqLb}G%p;_ zm@bds8_#^J(7tq<%aKLvxnTk{rfTQ#`V&}V-2k34f%S0t0G!OSsDS@80jD~4ka0}* z^Z~_lNEE=_vapAc(4cCa+C7%uS%QRx+O|ME7@eq3BF<-+xWw~;a!-xWI^t6?!^L(3 zws1}qm-!|G9Ww>?ThFNe$dx!|w)qW2E>bp^)53A-uzmq1!Vy^b07xs=$-Y%!7euA~ zMLl;*TyzztZfeZX&}>q!D4kQ%Cg| zlWQgQ#wP_w5(&Jzq%3OEnI||o-j=}-Q67W;FP@8YdYZFh8B|N|;hkw_~wYmRf z79ezF;_2SsbBD>b;so4Hu_U2IIMn_anF<4P@X-R(I-gIT%w(zGBAz{&EtTrF;if69 zPThl9j(8vt+!BSD1pq9XMjLbQ)t+Jm)Gp6m$cIc}-5XT)#weMY{=i;RSJ)#xB$m<8 z#TbafFt%tPNTN7>)A{8otXnlxYwT@5Bdk?Z-COe}Q&~q};u9E7mle^#8YcP}dY^K~ z_`6ohS4?G*(%pW%U@D7{cJ|{hrm`?;K|fwE75n=s{dlib7UTP6OWIy4P$ygyx(6vB zXw51CIwXVdKopmK4AqF3!{4Mb-x^isRaEZ>g6rn+uryYH%kj_BSRg(%r?HyVc84QZ z>}L2Q=UQRB<1}_CrmuL@N_!|e^Zs(Gx@8M(7{`LO(TkVGxLJgLdMLx}5Ht@)>ovL0 zD!&GVZXNa2^O)(ZeuMQ;$t2aKiy-gfrnCnQd8+!ud&!et@%7Vj zS?FXY2A<_n33L<|io+;i5qqHGZd$x$5_tcgGpJf+bvaI}Naj0@k=F;? zxujVtWE<;z?G;W)%rF^>HT(P^T0dhKg@ot`(%ge8C=xnk>X@MP5#;n&KcU@5i{AE9 z)UlFQ$Mx{R)*zW1NV4Eig5J2(N+6Iq9-9?WR1| zgb$0TNRtj~waaVgQiBVSmtB5=G>{?09Y^ZH6SNi)Pve^L0$MiGkY`4WH7XQi8Idvh zi}uBdOqLRt6#A~j!{acaWg-rS;D<00Lm1jXmA4w6l5*uA(`m>Kf7aP7r4Gp2r=nq% zQfq)ttcE`&gs0yXva1~5>U&Z}OvTpaDYdJ%>ki#$kza`o+S4FE;d!%9?8rm97hY&K z1Ld^AOX7`?1GKAJ;w?$Kc~)=Gz<=-ho-B65F16$Ah(0(!GLudo51qxD_|-utsvlnh ztIRrVh8T~_2|#}YR1?73f1br>&Vpk1s#*M_Su9*Ef8ubG2<0E~1hazy-kvQG;*F=7 z(5qrI+O-B+>x^uRw+ZynWmELuv03FY&y>fkOffHCM9hVVX^H(4xtnrgVO07A?ziAM z2D|**Op%ItLNmQQSy^=?`|M&VPnpevq}4O|yxDBXNa`z5GqD6yUrr?A$l5HbAb){j zj*eJMqrLn=;PvgwXSdYW0>=ev^Iu6Apd}B~1+9i3si1=wXf8RUz88(?Yui-y;sfTe zkT5FFY`G#>8So-XruWI~i)NL6s5Bk((CEmJA>8lPN{Q2(?}BM3SF~f z=&1^-bG*1j=1H)44K`=ZbcJnjOGm*bJf?bCR*?LNk)3tCI!-o=zvC-1SmX3_hAL=^ z+PkP!JGi<6zj2qUb_5{avWtq0ZTbK!9^XN=g(`65$tM2dfVVSIPt4w&1 zj_$_Q17V^72e0#-8m+d4?t!_LHicMD8&@AxbJ41j&}hrT0)8@+`PU0Ya#S$YA5C?X zXAm3*>+bofB5PdXME$jkC?}r^rw!D zu|%2UO7on^isgN?C7Tk&=j3cfWY|2Z6`irC3Ls8tHQ+J`7bMDK#j|=ow7oSVK7{tbe z;a4|^F6C>W!Nt=j@OxRTfin(zd3DLfGhOf)OD^Tt^lE}-a|T)(OH%EVcuO&K5K=40 zThj3yOuXggvyNt6_P~j0^g5<-eg-O}R))4XHWX@5PaciM^%~50kQh90H4$D2^kmx^ zT*;1$au7a`#@a)XKRiZrPOM*?B_3~u<7Nkd84M*M7m-nq!D=a6~+_;~aaV#Mu&i!!qy;FlUJ^ zX>)0gv4QqBk8|wpoY?6lMvL|(JfA>3tmNKym>YTnTo4r;i?x~A(zi6LzymFaAZ7`( zvD1NqquAjO6&uEOIUeyd=1jzbdjNjJVF4Z!4s{AvdfLm3G^am8evU1RiaGtADVGlhF-fr|W z#u55y)<1$}m0Hoc)Z9z8)aR(O@Zt7Sxjn0$@=t0SIPn2?9Hj|aLNR>+oVDl4A zjTd9v&&%<_?B#@RGCnIKXld5HL~+@ z)r()whJH^5f0NC;J=ct*L68@nS>)v8>SSybdGa$}KZgZ$9xn#hOjKz@07(Vv*h_2o^a zO+MOBx<8J0T+Hez+o3;z^|j!ByR}L7gk^aFpSPGbl)8`Q+Ym{nP^^4t;q!clF5WWI zRdpK7|6a^GV-Xc;VNF_xY3+cXmZ82Ax@qL72T=66bR?GS67Szk{Q%Av*z^I0Hc5{V z@=+}WZR1-kEV?e00An@|W-V4Zkoex$`1%9rb6b2k>FK`YKa*-5+z`M zeuv5TZj6IDdN0*0ibO0+u~1#nla#&nw^ClZg!x5Md5+0rGD^hyc|O(>;N3pPti{wH zP0A4s#tSsy;rr|Y-p$Htg@%a&I|%{AbE-eK0#bd{M>wN5x6+g&EhlIKpTL({S!_6R zEm`T1X3F)e#P&%JZu^t?7ZHPz-%Q)Du#D!;OIe-RMZl%Djj9<0#O8!ZBcwvu@V}bM#bSBV{6aa(e`tw;ak-*%i+Gg`x$OUw?Dv{V`%JJO+WD#Ijqx_~Ho~ zrR}I5rXZ_)n3m%?8-p|wFHrj+O4F-H`I(i>$GO+bC;Y)mR?9VuQcrmCgjZk18YNtR z{=_cc)e}^%s;9`mfRKR&JpFps7x+jaKBlIrTJ z=TG>ORV+H%ZhAv!CC1fYDQ8ffY}8JD4|RE)&o9ED>(u)3!?C*6D!=|U?RQ{!Y#Yw2 zt!9d^-=D5nRa6-SGD0bIQuDEhf~9lAp}ga2Hawgfsy%9|rg)%xs3U(w1u>G$Illyv zlB*a|V!i#|0RH=G)*w1o2SK6iB*6>B{Id{m5aOdaB;(nW_)((Zif$4EOGF>ZJ2edB7(qBmAk&Zxib&$=4ofWxSyH1yqLN*dyD5Ev&Lsb@C0ZjQ4L)8Fkze zM;Rv`z)x;_gCG2ib@6!mhgR5iN*sLW5AOXrTPA(}!1m4O><+Hsmhcr{qOkpc*_M69 zawMsl%4>eZf+d5>qrYJfrIQzJO}=F(byD{`yS}ID>2LGLKOn{6TegQkvTc&b_cu_z ziq>zsVf*nXECQwOGi-%BU;#zCna11g!o9;oX|@5o*m6l4dfE11H>)8@|6Jg@y~wJ^ z1)F^@qy_o>Z^$azc>W;ecS^MM;BU4izp`pN>C+6BvYS$me4G6w z3_VEo5AmQgtc!H>ARm8*U6A(t#A6HDm(tJ!wg-i5pHAw!UrVw7SKG4RD8+_f_|Ef4 z(eoGn`aDw9`;MQ#fD~tQZF4SCirn42?PZh^zT4(^g$S9>vU4lK%RVk0@bj($p{c z)e`oL^u-r^{e8AwlD@FTKVWZk(l?*-_=ia0_o<_<`!{KI&Dx~ZbuldWXU}w1-&;iFIYi%U5&!Nb zw9=X`;wN6>O5dY}fTKlW_ZD*H75lDI&Kg%I{+(W_WxM@~s4aGtZTlN4X5LEMNjq98 ztIM=v2nmi+aDJI>rlhz?wPw%Nib)mU_s`;zJ}$P?Fc>zMZ>*#YHQMLE%%L^PpArW@ znZw=n$_nYnCALj^%v!eGVV*rG!Yk=h)VIDZV=Cea0~k z>f3I}N^?na@#2a}=_>8@v<){YAmZ5Rwkkf#T_85i_P7?+p<}Aey|!{t@|ZgrEk=E{ zfiP*Z?GJyYrcR2PWP1^ygzKchiM9rTN+oA0{{vg&x|CGOav*)kdrhS4yRk!}#-XB}*zA%I8KX${COK?wsfyApEMbUIjn7!E>d=1exa>0Q!@1BJ=-a}rQUt`>q$x{-o3rj zNP>Y0#EjrSv`1!-df6s)Q0nWX!#zb+`GqKDlXNeUPmflXN&OPJYe%K26p+Z2sOCn@o~OJ`-X zl-7+GcUGE6(cQRj7iEZaqbpDEg0`o3!dbjF3(Xq zNH4nBMs!ucI4^hR)8{I^Y!|yJLv&JbEN_*7W`7l0suN$)9nJRa z#M{k7vzPWjvp09tn*DbVG<#dL?T18a_WUS;OwM{KtE3$r__w{31yaKfwkExm8am0; z-qyK~;;ECI+i4-Q+uCmRrI0agY|r{Bp*pF3Yny+P@|h&9Z(+-SPw|zc45nG1jKNA5XK771KQ;^hY9KS|Bf;0MwP%(NH&MB2c%k4nHyxsPnDEqbGslh6WJDOqTxk zr$~QGZ~SaSrVzr;)ut+4mP&p3=v0u%C|`|48vEiT38e9`7N1Dp?`!exX&{jawfLhn z#UkDGAsX2%b?~u)JeVYfc=HxB0a#$tD5Ix|8$JYOJXH9^57DY+3P1B9D5HVGo6b_c zmu52#%1Go*W-B+PI9a0(SJ~EY4mI(frw!DxO(#Xx;Po=lIvcbDX*}%9K)RtKV{zvuK;Drtc0z4p!S5ucUJJPces6-k{lk7@N^e!_5F>iSv%6}bkk#T zj&~m~Z9r;Ht4h1cgsT!SyL@IWU$k6_)Q#f%mMcDWN8$1x_953Cz{9b$HrG$p5~bpC zq$6~H2QquoSpH_Y5?s5LBflz8pTo9NM2Q#TXv)>HJeEhVP^NZG+~($F-rMBU8)54k zV42b8P+F=vYov)*U)a|9YbdaV*PpR%3AK=B@IeQ;F}eMR3pZYx)BIb9@;57#REU3IzAc;8Uo+q2UjU=YMi<0hF3lI5}u4PhqCqiZ*t>m zrIj@QChxjhsnufw!d2Z2(ZwDpZ5sI>PbYtBBOHk}h18*+{5P$*3$PcIu5X73sB&j~ z$V*>%d*E|K?|qa1yjrR2sVli>Pn%&LZfFJv$mQ{0_xRtdmE~TYi?oIgIHaxiGupK& z;w#rE!Bq@T+?)<&1;-ZgyfsQ4>DD0r=NhGf^k5LLzE&|wCkF8bYcZ?L8^p)0ReDKv z2l2eMil5;hjBr}%V59iSKz@I%(%AcADd@x6t`MJ+8fJ?#t;C=r=s$ut=SpDYw_5P$ z{|WvRJ%ty-VB-D8l;XGBC5M{kwbD0x#Fui#>|9yB$1iiGmTt4{8CM$W0`_dhs58#H z4dRW z>ZI!z_~B2`=E|RO^%LcXs-27O**n3e`L@lr&6|`qI>~8^?fPb=vQ8@7WV^FP8R;D8 z{Rl%PwKn?811|M;3yJ!xnnU#uCTgBPAqH4NPSN6)?X{WVLz_}Pl1VzrnG5UO`VHfYKvhrfY?yNq0uh* z5kk)p=&PRM^S@SNO&t+xhyA&{V$v_b`B)st-VnBq-~3wfukD6V75ax%#qMIC)7mvt zT{DpKeaN}rH%fi)L)?u{q^`NrBL0M$LV;MPerM*xzEMK`<{=o`=s4lB%Fj-?IYGYx z;A(SqH>2ITKJKh0w{|G-U>YcG%w;TQebiq{~`>hfq zo#ww-`^=Vo!8)1KwZ>_Y_xD3lEE0^`(z-zuzjC z;iJOnnAobp5xsW95LEH>vHU33`=N0*UI*swrO`C3j#9`n4P6qY{s zorJj};XCQJP&y1@Y@q6`TDqn9sL!#9hO*HL_wquUzmv}}kiPNuP%~P2{==oD2Z>8y}fwO4#h)mKp7w>eN8y%da+eD zJ?1~`P<-4ijsyeHU&6+`P2HhuBJ=CfnaMQNxkTOpvb!cQ$@|9(k zq(Sre)?-Q^$?2-?%`v5_fyRzAQ)d>p?vX4 zu(7p`c)>}fZ-8GAQEE5n;zeT?EPFk@3aP#g4FM?-ArA@R?N2F*(wBAdFqg70vR^Po zF9dGVA~6HN2gZ>cOD147b#Gu_3Up+tX_7Y$;oVLv!>aY4N?a!EW(Tvy_x4u4_q5WY zQ4IlGfTM~_X)^j{G1$Mksc#lO`-y%^a7Zc7(SXyoa{n_*obril4M@5}$BZ8RKyz1he3QqDpbjP~bDq7WL|)~bV)k{b zM^aj0i7763($tHIaSIO|p+f>3r^=5)`Gj-Ij{3tshg_Hzp-m}P!{@kSYM1*3h>4~O zj1D1KS5h6y0DipNZ%Qrc;|cuz-;_Bm?gqKy5w3`|x+wNjkcRp^0r<`l)9|Oz6jf6 z5c(yEk74&3sOL@3E2E^War~q6N}ZI_EmVrToBE7eV$t8z{LUc$2oRqy=!XP{te2*= zvuJbyf>m34M9m7`3%ACx4naTYKm_$!_K$Aa^rbrCPkY2fo;rXMUtwV8%>q<-Mhs$^{TSeAUP-7oQsv! z*a_QXTVJBgbCv>j*?b==K9!}D@wV3gC~YfAOUPbl^usDyB*97cmM;Jf0%Xu|S)lswqs@e-y-Q-3yHqnp`=sLfNY;zFQyL;rPDjM2#+2W2@GI}X z%7<4oHE8$YIv3#bAlW7!04IV~GGRVgxRd{aKdeiIJ1ML~g*#bpv5udpW~y7w!m08} z1ypHeE4NoO#YlIq@K~cML>_`L@$`3c@l)e_ml4JAdM(d1npSlBa0vR_J*_JB(GP1u z5nkx=$hL5m_qYnT*5gZKv>qoLB^5osXD#)3O+L}XRL`%{mVbA<@9n{&+y4N{efMwX zHV<_BiZxodZxP?5upIGC(Qnt_C5U?n=ntEzh3ohH3!dbFr|7@_7d$2GeMkJs74W36 z*fo4;b<@B)OoIhi6W^3V!qPXZMLn*=9oBpeFRE^8D&=hAat%{b;AkK8CeT8?`Rzq? zy(h5JkARLY{`4YWUISe`eKr5FhN->JnH_Jt*l?w$=;G7pPeaX%+|?6Ze0~*m@d4`M zU2vjHi>Qlpg**8s{K21AxRZi6RJfB3D_8MJo~BlH(=SlANv9CEkkU>SagrY3?f0|D z_da03!&mV$o~B09{-3zr(-bQueat(1nVQ7LAnvq!Ff*Adx_Zq@bhRsWdKYNt-l;9&8JnRQYczf|pGAtdiRyO(co;-lM zKFRRD_tJqkU|M}DtF4yDO-eY!k>HZ}rUd&B;1gt% zU;0t_F<3w*hLa*F8KX7HceijS845Mn6@(ur_%;W;=>GxNvQMsvpY4dhS&I)YFbE?i z1tgqu4ZjkO2MJuI?2kBOrV`0>Gj~=@-Mrpx0;?yrIr@u2Q{-Bk`7p(F&ZsVRaVqxJ za2jb@$~&1%^`(cO*e04x;ks_8iFxlL^qwTwcjQ`3u1}!_F;n!_XXIT)0dZEia-hjP z(>2D}-*AvuhFoeF9{tZ87SBx$yW9isH!e&QwBW z%M={mc(EWf!{r>2YYMtJeDf@aPF_&ljL4VmXiVH#JNDk$7zkHOPtyeUvf$@buR38I}QV4E-H>{I1csemo%M zn93AxqU&TtA#5fSl8P{_jg;5(1tRWYV`!0i!GoCs7PgjVyc7*)pXqGuf5+ILzw$S= zl*TOQ%>zumYdJ5ZLeW1-Cq*A7>04SIxsMUFNG#~sOu<%99xd;uT}Sz(IwsS=YgwZI!`jZL z?;xsi1uCu>L#fri*+kyj;9mnLKw|LE6z(L$3Jq2X^QfUdQtlfu^?7 z{&;>S(9~c0p$ZQTGBv6(w~FMX>62m?a7zT3c;rJ3p&*AdKY zoJ&I??4u1F#yWZ{S!=*HD8<0LqETpoM_9mJK0eq~r>(CBqxMt7ZlQ#*%XdV)zu@+L zptcsT?^XR}bIbS}tg#N7!i1eFfpfP|!xv$p-sv(PknlUr#NLd=;V) z)izM`gIgyT;RpH7LqCzic*hV^^T5L*nunP8L*Yh8&ctVmAL63s$?|}8{G$+)clB&Q zu?`<|$mmCrCa;5$a8vX2#v+ZO20q4Rv_%x(#_$@Weohn|_sQX%|2(uH|D}h1A$<8y zlML0$bIO02B@o1r^+2WZ>2lJ zJ}L*z(;VOGhl&i5%%eO*Eccec9T%8~dx*yQCd>qf4?Lf602LhpxH0P)s;{oV1%J{O zcA7F4rOW5QSVT>3Cx=x-to)LcJNW&M-+6?mhxHN#KHqmX|90{T)N@Z*qN6ThA?1#0 z<&J-_dqHgpyCxiuzy2%#x1_@*?=44GVPg=BiV~T8P@be?xuagW!$XUAJO66(`H1|d z$ze07j=!axLk-TMUS|*Ay1Y-miW2f)rW{Ow4t|~vFBQZaWA$t;-&)VqUYgmTtMwq@ zd#&YN>zitKN<|LFtVY0yMv5N3PaqG%4U+K)yP(O4zr7vD=ZP}yB8oPKo!4q(_#wf{ z$MBOiG=^Jq*1!}Zby&kYG%y8MRW;#K#uFwJ8kqc~{j2%12BwyYYXC2C261UMNG^;C z%uDT!aty09>ZTDum((9aI`Oo_px>7`xFBF_6BN*Ta$j{O-BK zw`K+(&wtz}n99w6bmW+8{)@ZE@}EyEM6`V(K8VOScP0N{m?=p5eI>8i$W%9=p`ag) z8Vw=kb|>3Q2HK&O>=y0_@vxnE#hA{GQ~$JsE^T# zLq4ahc7u9hrEgq7_X()~@k6&Blz&4TBshG}!J#+y`3-BZa~}razkbh39vN;5Nq>Y8 zX}(6`{pNmQWk z1x>Cc?yCO_ZhS#Af;N1QYhmyw>HpBeZX)dF6Mi+^q}(I6A{JtqP=rFsty&jyJy9-6#Ms+5GrPL%*32Bnwn8LqVVjI?xvpfJ z*=EJ2|MT_vyg%W5fBznjPtW)B^?toCpZEQC-k&%Wqj(I3Ti}zvfJ#wRn0BK~Xv;OqMZ1o|h|;Gi8yisvA;sTa z3(4?BQtioAvh%^o@2>KOW zHTm)|PJ3`8+t5ptgi{;Xo?hbM#6@G|f;LTV>XskHoB5zKgR;JuE||h9KpB;VjgTNS zYcT#a%^=(SFXVI%HYF2Vxe@H1{?>KGCGrYQT5p|!Gh^yTHoUj!*X{)OQsM=Dw={#PGpn+7TGlQ zFgb%|=2kqEU*Ojtpz`3>8EOu+23ddk)hPCEAJM26h(3%jqZY-a-M~)u5r+s@i)BWI_jiX#Ur>q(L6~u|Y^I5Xi!oDCrO2ljvn748V3(c2?)4QT zg!qB1Z$C`Pr~bp1_QOhp|3B=LexiSm;p>qkBlOG5=-;VmUu_Nq(Z0Ggf-qedfPUkP zXfUF~v>xl3Lw{7Pj_cXr{^E;5S`jPlF9ry)MeK+E;uxV%5ep0zy@kKlv5}#ohkFes zR0}&J10v=221B?B+AZtY;!tsUS2ty{r5yxJ(KnRWXHgc({Zb{kt`Fo`(EG8FbsQiL z6`abY(#aFuzdPuCpfDz}ej<7G6TMoGJ-$pK0Uc*a8mDhF0 z8yRmwDMjznp!UuZO~HL10`&#s6kDB6mR>d)39n}TX;*Re+f&pIS5{oQ?BA@o@&AR~ zto(#>(SmHOsBbX#C96LgbU{GmV#+PhKNG5smuJPhmP63@dlJN#V`yPoM7j?RK@mW? zZqv(?A;?Fusgv1&|52v1nrhm8+P7no*7UmKho#-(C)(eos)~ zD&`k1_85FSA6g9w#%qM46Y*j<81d zHW#ps;iCVujVopP9Te-7aF^Q5f{*R|>w7ncF)M$^DY|AjQQ=q%7 zm2j-$a$GHDvbqI%@a=NE|8m0X@miT*k2g)tW3|IXlkY~7qXk$)sI~yNG5=RvfHo_b zdAR7_It4OR`!`mwXNRNO$0;-ik*(YA^*`0VE3D;eZy7fTvxlx=Zx0uJg;xf$ zN}#1De9;H%0tpImBml+pfoVG!4y#q`CpTa(NgsSnzxtG1*)JPkgcWUIoI<4a!9g$J zo%IDYI*2T)^wnm;HquwO6cBOlYJ`0`e(e>akM;M203CHCX|LRYRshSc_*`Lmox6d$ zYbsVW5ZMYu>DcjrYiEkuLbo{Y*61`h@h7EFAzk>Z9B^pDb6#6$juk-SFy6+CtK3I;t6~naG2&-MRBQ31Y z2+?e*1h2T7S=|96=(38&V4W2LeZe18f3H3;QQ4?yoZL|H$M2_LTdrTtl$vd9CWj9a z{3jAN1_%8NO??4wJ4I={tg|C`O_xor39n{S5B>-fZgk)^vHtHUPW;bUTFplGu15Bj z*BPk)?ndgU^}aylYj zP|gkr)4oNBJadLNW=J&og@2Y&SW-IFm+c-U`WZ6dgFgR#q&`*0eaqREQKDp711Z%# zJ=q2abw^_83)(?Ru6wUQin{j}K&gA=H|k!5tnKee+AC>#hRmVTc?xo>bmc%~P8E_H zo>$>xyT}~$zse4#aUZOeO4vQlc!2y0Fj*8Q2b<&^dh;JyqoopJ!aim>)jeP5c)TK2 zyNG4%Y_u5Yd{gFe#8*71T4T+SK<%tS14g&q;U+WLiILL^p<#}i$ z(Jn(?x5FJ(BN)P86=4+#3rXk^rac5%cDpd`n}nBLv~S8@rRJ@BN_vYCt)Gih_8c4m8wKzfN8U$ei|u_R&PJDO0E(p>hE8Iy>|Li zwtfuiL+TQ^L4Al>!oD0Mdb?<3-%uZZS;Br9BbqEuq+naJXONJW?1i!!sa;8_EkUgN zYq6Z%|G}oN%uO!Ua_Z?^AVEIVk;N|6B24=&^s{}#v_}Xpx@eD(m&%}1C||->J&%Jh z@APC}JTG>)T!!6f-)eoqNSuqqwD&N$z5r8ej3{-hL85)Da8Bq0nCR+-7)+BhWR=?v zw8UgAlF3;dkwI)60)has-Y>#r)Nd4Ibz`>{dFv%? zSqze@7t)S8L3N(mPUgXV9{}|QZU`Skkw#pHj){C4Tw~yy4!}@v@N-bX0C=>0c{J{C z%0u>JR6Y0)Na19?EEvIOs@-K@8+262P#}H;VDfRRpcMrkJouxf%sf`?J$t}$*{!Lk z;)kwD4oTg~mUjkez*&nCv57K@M#dG24rH>PJefVG*!>3?pUlR619w3qAV;{@PO~Fp z#m<4wiql8%<|Mr(5a%=uG&#_YLAEMijrP?JSlaS3 zuPQ=Pt#Ok_6~Tkg5LLWHW(|R11~W6$AXQzx``yE zbx7S|+0szmtx{g^jKeTH?t8eZa>qaIZ;Gwygo6G%ikM-X=-vCbMRIbO-c!7;ha>;R zikW=H=2`qr{9+hld7(2*_u)F0G!7ew&AIH2apJJvq3}STe^k!J3EDt;5oH3(V#DE- zl87SwX#Xh}YS&$JIZbx@Bo+h2O-y!Qz{T6^k&G9`- zRWNZx5h|7O2t<}1sAq>|C-tL!PwQ9hf;vQ{Eg~HEEz;VNYpT4cqRBAp3usFfBt|Bk z6h{p?RE4O%;#a|6jK{KB!UA@0yy!nX=PP<|gJ~Jw6{s5~$}l9;k@3gW%It*&+l7WO0oL64smS!gQ@jygnXHM?D=`qSwRAT*}1j;mzdc z{7h!6_L}TT5Pu3WWKq~1tjuJ$;>12ezf9&8FM4>SkqdpKmN5GW65?GL;AD9wi-{LI z$GR&{qxF%dZlqd785Kb$7wsfcMFGV}LiDQ!BNlR^;;R70yD!4VMK^#u4m17?0Z&wi zOjZ?-Q$S@evitEEpf7+GMOZ(~R0Lx~*On?ey7y)HH9@tHG|h$aiI$=zxS^0Exb<8! z%-9Pi9^6E-^Q|7OA9hKm@7 z3>KkH#K3?Y>I;q#DbnSDC~d`Dn9#&*A)qEkUob)$7%Z0c|5XU-<7xN=a%369xu7Wp$%Ri@Y(7ZAcK^g97lDd`ZRVN@gsR`~}n(;5J73J_-f| z^WX}_cYZoMmmnI&;iQIP-!nk;^8WzP+GrNBM+suriOC0Hdm-TmTH>2cn%JJe!s5@g zaHxxdKsE%c27Gc{kx&B5RySlr(;ixe3|a#M&&_3Q`4rLIX$&Z)T8-E`ItHx6&Z_p+ zG)gs0&9SV$A&r$y5ob>vhl!@#apQFccLvd~sYM|t7C>y}K4K5$j=RgJ^cp7fXYg9x zX7Pm*W`vJ>Z7k>Lyz^MzRMB&4TUerxrO0ZHFo)@;VLBpHchE@v7{yKk!Ht4+PFc2; zdHK~oG8u$eBWaFejW)jfG5YU%6uS!V&Syr@jq1>B~&<4l-wGGlo))_K0`L#w+lARhAS?kKeLEo}fA0BNpT4u7A6 z7uqPv-J>y35i8yF6cDAGo(z+I?Yq<(6=@woTDocU(a)1wQI*_HkCL4z-86oZNEIQx zMI?9An-HAZP5(_n7yM4%h8b&Ra!+Zjmw+g>=fycJC`t6Pj3Wv9IDpbe4uMH&Lv*ub zZQjShtS`_a?do^Y&v(>5vOVdzm=a`F>RJStcpuqC7Ao$;VAdDlDnb+jgO-w@ej5B? zl}YF$kIj}nac%Kr9|YW!i)80psbAHDiWQc>kJfv_A@3vKB*mxt$c2huWdNl?NP&qr zibZ5cePpi|zwp)Zr~1eNvI@OOFiiRa>a~!HD`(>~7U(0RAVfP?fo7+!yMTspIo$I# z0%S@(0YmkNe1<$SzEGlJwWpQe1rj{_#HY6-Zn9$n~je zADIO)UXJ?6wW+N04D^xrXR(ACqK9V>SY`J?lN&^aFl5b47*H|?r?O2muyoisiyfFD znqv>lQW6NApvpLCPpzHBuWOVOl1uwK>; zI1Tfk@K1Mr0kfov-Gplk*axZNQDJkAHDk6o!LHRn43+EpK4e$tiS1eK9C4m-FpG_u zi*5d#EVgN`*sIkr3{LApA1E3>&K0*fzJ!rr-8xn~Pjq8N^F*U#DhVc&z?~hLhxtdZ zOm=0S7|_azEdFUEw{Fa5zUU&{evx&bkJ--`FS4Zhh)}_cY{PspQ@HXX6Vi~63}d&7 zCgdabUoP~ixcbnvl_U>tQ9jPG!iXJG^u4a-C>(U?%Kwx+Uif2=e*zR~L&g7hNT6~C zyAq~PVTQ{L^5i;lvEq8dCG@fwEA-I50XzK~BXW`0E5u${eG$1>(G+iLCQoqQ0zqSy zb@^5F(O+nnlTbMwX<7{P@oPRAf|lfAt_G`72fVgqa4_AN4MXKrCt3vk+) zrZI}wak@#eU7WU)fCNfEt_+nb4`f?gf zg_*U>6*~&AWU#)u;;6tr2v(o}9u1PhbUq-y`)f638>6)qN+I{yPp?8)i=Nn`pYI5g*%#sZg! zz1oR#8KVL~Cut2qjW4mZC8B$qIwg~-j|)2U65G5)95^(90?Q9X3PMvZPGc~5hZ)7j z5Y$UH$J-ty4ue>&oX^i^`la|efGkrh=QHzJ_);-Rcz+&yd#TvbITURWikC5F9{YMJ zW+nQ0?DwT&OuxR!1;}|!m9xUi@2cb@1}$fWwThk`^ZHFJXPM|T@*t8Bal{+S?oHcd zF8iUSynvi4KbAq`bOj10_oh_Y{P?V}c`o~D8O{nP&t+Yg4VD^-(@$kF&yOQGhCN_~v!(S993L<)YN_II@@5fJ3^kttwy>fI?twhDTrb=esC{AGSTf~1to#7XCMYU1*6gz$>ZS$$P+zgJ7MUosu{b+BH zE}uQ=5pLSouS%p21qJV@KHx4cPgl?5k#G7nD`~VFrgK9WS(9L}CqqXV0%4HPtIO@{ zATTN?UciRIDJ3X3Wq9zb-FWTY6qc5cAECZFi|x-B2RnyhP>XV>eQg$dm@m$AzKKCA z+-h&8uonwN4`&)r!<`Xh<*fzS7M#NQ6x_X9fD`r4aQ;jRYb+243b$vnKC8rN%RKm_ z&p&|(Q`)Z4T3|BeEWsC6K1StK!0Rd?vY!$8m9- z%=!g{45l62;9sFima3AsVW_wsGW7~twja=fy@Ek*@L-BSc1L(@N{~H{^N*Er>R&ir z@`Y()G7DZU`i*LWV|{)Q#i6Mywn)^LxhItM#V(N7-MXl}QW}MWS6V=b*P#`QDwr1p zKsvZ)Cfl)E?CiP|k}Q!VAI)Udt3{t@w<_+8TW8R_oZDkusv2g%08RhHT;TtfYA93< z88cXqHKPBZj^xRoao=J9c}MOhGCdSJ6({a5y>4tv_6_mhG$hlBnznUeEQUz>X!+Y|LuFtI10 zG=n9t6(^6~J{_I}Ttc~D&=n=p=mmZdEjfyx^2=aP2w*PP2i!vmy^G^64FObi=R%G= zKC!?9;=VVNbMI`0r4Ws2hAm`!)3HS5V_{!BBycPCqO&6+%c| zn<*Cts!1hWV6>=)G_tuq71!48+8`QdW`Hh>r=QK-N`M8r$KQZ*_n1SPPyTG?25J0H z_c(#n&^^ldWcN53^#zO8Jq}sXE52Yi_}*kFUWzqNC!{q^9_hv4a-?UI1tPtI3yc}6 zVcKN&aS5(wc!xBuPc5rB7aJr_X5W{H3xtEEY|JL{J;5NOx7BU4_^gv(;mupkBML{= zMi-sKM(ePmV-f3wh=B!SZmwCA-G)p{bJ@aI#WSvXByo-yxL#bF%btHtEb~5l{Z{k3 zRzn6BIG4!UWZD9geia=-V~<`Jy{sd)i;jZ1`0B0ZVYEDTKDy{q#5#NUEA8g~6-XcC zvh*Edg1PPgp|!0=Yp1OBtTpfr{6x#e_XlU?o{z6zw~D*OHjb{XzeVND(V_b8XVzXH zioe+jN1|A#kHvEL!r?fxbLcYC84LG!KrkU6_8e>aSnTXRTDH5Y*o8bN+Z8@%?OQ4i z&~|uvy)#zUa3R*J40yh7h*Na2|D>v0)>WU0-`TmI&oR@-OZFFB$T73^M?{lr)2&C% z5qfLEk!nabT19vJvUz6fZmSq$Z-3+XE%xwpv6p@70y7IaEUvQe0?EO{V&(sM)Y<+i z_g^0oi|y@Ke07UWEff2bd+W9`@s!Yh$&p*Q?|=P4iU{IyP>qMF;Rm`+T^9-asPbC^ zVsr>T;;LXkqMy3~7XOFG*G`Go?L9i|gU9G>iXHOo%eqx&N8kn|B_Qk1XT?b!gwqMuu$v-o zjSingMbgW9?H44rxqS02d{1q3QDbz`AH|vW5$hZW76g`3{_9}apUc926=PivlA!g# z^?_x%?A2ez6VlR6h)dBA>l{)1>?+B&4Vlj5S{MB$9NH`8=mmFgCi8d*iOetcJapcPiHV_!9jqR?@Swc@@Qi5oc!6+wA4i+F%Zdw8R` zOvqfT2z8Hzt}i#?M8V=dH5(4&RmCNo^PC1tS>9i)!Jy-aJhgOn+lUqz!7anOO9uA&RQPt^@cCsW^1 zi;*aWCcnjOdMjy@)0>N&ai!`@i`c_f(hK@$!RV%{WuZ}p#(|4if|Jx=7@NViI!R%z zyTe0VVx`NlUUHI_*?GU0=B&xq*6pI(^ptNzC|{OnjoHh}G?wiwnFC^=Q};16N|4s0 zhAAAzdvX$D&v_b{+!QPXQF`rp#mIu2O*D*_SoA zO2aKfp^OW)?&{0!Xw>0@ID|kHRc!jCKOpQh?p_>+ooOVLDEo^Sq_4E()0Z=JKW4$_ zK4e{_y96`t$2tYj)R`5Tmb}XM|3a3zDzYX;uU^q>#G)=VZV?inf8 zeRPLa>!kiZAIyd|QuvS4kJRfQp)^fVio3%)w~+=35ALv;ZKTzPh(695Av^F;2b8sD z!sd8@^!XHFZFGgavdeHGOBQz(~0K{_+p#)b#_+|Uut@?9tJ7i zBj*OC{AW&bhlg`yxL_97i!~d^-(YVVqya*^8|;cf>fhlU{K2Oh@ih)BOmuN+6h1h9 zodvd)B7{@3*!;Fq2jTs6r9m6so9%2XowEP4PQ#L3H@f4ahOvIBc+tHnNXQ^mu;?NY z^>uDAd##<6DwJPk+V+yK&rtDy7YcEX@STK8| zz2qq@2xdpxOCyBfVAje_@)lfzSr<2Hf}#I>XS~rd`Jy#^A>;}xc9VLxyN|-rY&>{{ zuHMXX$5-cnvR1!i7Ldcg1S{b*dll7 z4PpOPt49Z^wVg{_WE6hNRjf_y#(Id-K#%G`lrP-i8CZuqJm8Y9vdlIW=?(_6m7>(! zY2y#b2Hmni_Jt_<2@?a^by4ycLIRnygi`7l$ofc9$JW+MaEnj$v}fl$r1sJD~Q!tku?hdluv25xV|?V`C2^NV!bU>}uV)m-NTYXm>z^GeK2>CfM zvoJJ({o^6|3f=+C%TqE7|KiR4iX z-&wz^R4(%CzlZO*CUjVFTq%kzeNVO6xMqzbE>OcKN|6BF6;bR>N9@agT{lRPs@I3& zBIVD&RsGCKj4C>bEB30VWBj|O;C`>fCSN3`e0`{X)o3&-h~pJMG_Xa-4uvE5{Mu)` zRYqO-W<>9Yqt+au*J!yLRM!tTPQtGY?w9NpqNCh3`T%PW>RqEh!Au2Z1KPeher&r* z^6o+j(om@6c~lYI4q9`=QFBN_n7HGw5@x(*#SM1Vgrpz$BXjYVB;yC9;-RQ)S5#iV z!3KCs0RazDUj0Dd*N6kU+N+w$)P)^n}Uo(=Pn zyxX^yb?XuQKUB|fZ|XI+z(<-dEV|5Y`bfPTMk8Zb&z%l#EZ8g=#9?x6yadHCm=3j9 zUbM?KHqngnLER5*fm!l5+L0Z#hVb`~tFpiDKCIL%nWwBr^;6zo=`D}~UqIuKsAzwv zX#eDmOTo1`Lq~aHKxZ8F!-SWg`C}En)TX$XKZ_JqxYQ4ymeSUmQQe9Mm&dW7j*|J= z-zS0=xlmtih@z$dH*|VZ`O2q)gj*Jiwb^k{39HGek$V97LQ=W!D$-7hXX`skJ%qq` zcBG>;Usp6uZo}v^Y2n|nex0PQLU9~R>V&u5F^T1Mk~)VCC(nvqE0H&ItC2@7?Sv^| z62?1p=dUkRp1kvS2K1VBgD0`8og_(jk0Pvi;8V?7`AUIpmc*i2ON*NE5U;l|mObk$ zd4^Ad40lL2)fwkfb!*OcXvY3G6e1LhM&&Ze!{6Xli*(&p?GE@ND3rWn*{i1Ws)e~e4+k7Z^4(i-9B1U90xG)*X&!1i{QyxaJlM&EQ9?YgPim~n=E-&q>lMvFwq zioxnD{B0V~`gV~%6}&vy?JiPq;IWCfno)nFiwBjBEGnpv`OjA~vM91KAgXZKFT;v( zj=VOyF!>E+-x)SEK$<8FnaH*WNIpW$f9#6@sZ(2WFhqYKy78Ie`Y+#+606wV04bQP zJ9d?N=!z%M4CLadqV)|BC3KZ$2~er%D$OL7Zh_KIg3C$f(oKpKDo(Jm-K3!;f4Q3! zLRi^N>gq0skQd!J*r9lcUExrN23)%P>`B(DyY#&9k&z_?q50h(! zyGtHI*a_wm1isfzQ7V0&l-3EZ$I0Hve0oS)!Cb*Q_mEG9`LDT4BOE|y5RTr zQ8_n6`)t4Pu)j0U7M+afb`qhF2zylD2TdTpPkxMT4VE_AJB@W_jhm&xY-WhmUid7U zEeer*?MtGaS;k9J2>T{PS}j~0#U}PdC@V&>4|__1!uV0_Qco#J_`VERFGz*Lr)BJ= zUTE=?N3v7Bq~*S6zm)st*7)4%SGe_mSXt3BT4frB6}q;=s!{ikk6?3pOS_GoMpMD< zo23Wf?p`xWdWX@hOCOBLPerrYeK4-P=W4yvM;c>i|CWohb#OoFik-XX2r9=vL=6zK z-HTT2M$foP`*C{~9EzdCFH!9IP|00b*q+S-cmF-=e|3kpXRnd&VXo`a-g+TaI;0iu zoVIRwMmpdqq#m~pA0|B#1kL+wc$8Ew^bKXLM@ZKk#$t%cO6N%?cK2Cl2WA*4g}DBX zL9DW3@#+H>JyM#bANvnJZCe(Vf66XufUck)J33N&+58tqzzy#59nW>$*I^cq=3^0B zog0uhYlnBY=8lp~b_O3%e1Z`l>82**lU?lHXvyl6*Ne)zJ|&|3fkUL;x;|p}Ix~*o ze04OcXnlF*I_r|r(qKCuzn-dA6KQRUs8h7cNz19odU1^Oxt)FnzT}%SV2R_hR{DwB zM~T**G00lI(?MA($kM}ER{L?%8oLhj?_zqD?SH>KJlkB?Hv_#u#}nGPyVf^jrMK*a z@&-14qU2+pIYDY=C%kgo3O3eG*b%_W;-qJ~PYrO^_&E-89Hx&f$JZvF2L(g}C~=M( zlT+K@3rQh21_yjT0rN6He1mKqp@unP^2b@jOC*YV%tgb@l53!h>RgD8c!P*-TESLjzs3=Z4L4tMX20Uk@ z@sEzj$bJn}EH06=1LO=I1XQTD|KeyZ%yr}xh+2|x_DR>SrEExo)YtyI21nL$qqzFz zDbj=CZ^02Z3XWqXG-x%MFUOm95MEFC5nC*WOq)Qk@o>nrO*TNXk*xoW_n#;W>JRyE z_?U%Hl>&ld5hYsloCn0V!Yevo63{`Ird##2dxvAM0r(+))9Xg5lx>|VnJ2U&jSC5M zUDX{RDPYI#-0QkW@Em)6_Q%dd9BfAek7A<_bn63QKJ!>+PqNRs%v;fG_}J<)O&Vf1 z;Ej)9IUNlYIWQ}hZja!ryB3*$dzr;;R#Fz8b@a=P@2 z@X9`RbGp<^I8?=?8L0QgRcruZP8DlA6IFS^3@Ckg$_jGMPDr_Cy^$=GK1l7;tctdnO;c6P!AcQ$nnnjGmWnYOtmxoI1md7HPEbY6ZSD zE={mh*ipL~jY(NFJz|fWqxX)ax`I_xmfvNJz zW@cR>br<4KvYRWU0@J9oiWAd7GQf$cD;eO#B%WofS4xfUFTaS|QKH;<|fJ12;uHoVz*YCa2EC1nWH=Ce0eN%-W*eD-LSRMzpt z95`Q92Jh}Xz!%iFQqzj@e!l+|P+C@D!G7-U?C;f*moO@uwO=C*6!h8b`8Cqmjz@5x zO;kSO81{3{75RfB%6N7fU9exM`>%qyNQK;7c3>T%HY%50 zUx$1XbFt-y;lh+d?3E%ZNx1eE`?m;h?DaSESdW3|!vpN4_0n*A`#*28E9)^u&b!To zVkuNwd)tf|cJ8I9!B{@gWSxt$FN-KDIBBl7jw?okWdG{D*2=Z#eGgba*&y|^6UNVA z^&6$d?M|U@lt(RLcbE3V2PqESVL2s|kIOd5^UJ~uwHxoUH%hR)k$Hz50qTZL$E!un zIEQiUNJS+0PiJgQz;U;U2GTD68z(O`jF@nQPwsMm+y-n2bunUZuL36x84eTDt zYJP*PGh`^?XKu6Uo6%(S|Bd~#8A*1do{fA7ll!mgS^7&73v!$)HzDoN5=@g41xC5>{$U;Ky+s;nzwZuz>CvU^l`T@9y}K&-n6T2equz?Zy29PmH+2B8Z%0K@fag@ zd{~5r(-p5^UGSZW6uIm<`Ahv$HQ6)p+lb7YmAGW+Ibu*cupWOq(hR*m04_qN=@EB3Fg#x+qDwaEd4zEd(Z4;|}F`Bui zKj1P%|78J<_TwQIDWtX0jbZr@>~q?#a~WZOh5P^6YiQqwO=Nc4rS{I1*KeYXZ@CT6 zythl6g{3#xzU@+|Fr=2<*^U9Lrk3@1T`CdMuCub&QSxGbw*K@w>aj5JC-&D4>8NSJ zk5nfd%7=tz-wjFX1?zu#pXyYPn8-L-hUoK-%}#;|eBWv4V;cz-M#w^QmO z?7PC2?v!>5PFGmxH!<}7V=Np0rj&14x~DZQGoH$%3OLG)<=ad}VpSvokfbV-cNIwp zBvTd1ONt~El2}EuLXm_+GE$MGE0QQk!WGFBMUo21n1PCDlp@N2C{mFOP$apKaGfr) zq$rR2^e|n}9=7Q%seK2tqW<5D6#t?U#j^b#cK9vHZ{!qwogOcDRJO!th{JT_6iKNf zLA#|Jp-6Tpk~l~#ie$YaNrWV4x3%lr6257W_PTZ3JCeapxbwVq@4GZs?fE_X?>+Qp zrtQ{_yQC;Vcx@Y-yGQy$Si7GE?nQIFyoRmcD|Pf7SA#bEGU~_>GMtYp+8T$|Ver5j zYvo>Py4HT*H#b>OsnpYjZ`!S-O}p8p5_TfLLDBi&-MV*6rQP=S8&BV4G5e(udG|1X zzf^30rs^hZ|CuyEr*1>$!6yxyS1Ng#TGjtYi{gn@|EG_eKa-61_I*#@WP1-PK3ab~ zDET^c>|WLyOI1gs${QW!&xtr3#d-l654TGCaEH;fnsxj_ddqD@AGtPml#8YOQIu)D ztrx$LJX^U2e(9*ma-%cp0bg1l9hbHX!sp$r+fPyncm0^{tCZ3N?7DS2C0!6^^<@8? zl8S|z5VpDsRcL((J6|P@5}plVKBv)`{}9XyPGceD<6!pjY1Gd(!R+E`DMj!JX3w6% zP@=JiHRTKzlZAd+*6OdN+xEH#AEEA`U&9i~#ZK(xd1;kUyN8XrAmy}~{UMsdi6gKF zU2L4Phn>41eIR_in_0e6DCH)Mofs9h~Yyx`lh|}5GHLA)6cz%_WSKb;Y1j7p^go8%-r^eSeJb#;j@8X zWwYRml1JqA_Z{iST9I&JrU5Q`?P{#{p=&P8rua8D>$e`0yUB3*6E+y8V4-EcY}fSP zLM$_VBC+C&QlA0cAZs?7JSoyx4Vlwyd=cjSM#r3KaG`s`#aId;f2LmujhXtq&mLTq zygIsbp&6YkzQK-71MRV_*7)@dKCbdzv+-jOYyTSQh`prApy^$|`^Unwdt$Gvst&zE zuM^t(bgSzXDbmh<{aZKLxF4kj!jgB{=^v$omK8HvW2zffUT#SFrySQD*d2>1KV_(Y z1}}T&Oufs`e_@QySGlp`N&93z?uZ}lfqBD#oiD8T(Y`=y2ThqgTtJR~OR~afEXC#D z3FVt0HAcB4wvy+|XR*Pi+wgX4jiv4s?QWpk!X}qC=N%*}K6oA)m0#urt|eZiok~!s z{pKxVI5h_I1-Lz_-2(}Qds6#0Of)z?sr`_f4&pKcP1M{nO2v1{$LaFgTfgaAW|D&+{j2XE>y(34|<6)9~oVnOi@ z;PEvP$8W?53h_l3isM=QSK@dQCMAyNxao0RFyny?J24?qg>H6;hR=hyuvk8t#<%k5 zj}}vSIlk0vEOuir)}oJ|kIy^RN_~YMZmg^p3y?l;?B`lZ6#i?^nn?a-duzy52_GnJ zCs`w}N!zuSA+6A3;;#?K7dXm7{QFv~*#E@wHpfRCQymriJdT?=e#!0kabC%B2*)23 zv}o$M;66u39s!Z#KJL+Wjyt&Cdd~ZC?!~bk$2gAai-g|mBpb(YoFk(}qgl-bJ2?7r zeDsIn;2`If9ItV7n}w=oZ}ddQ#sD#n9FekA;Q<};DUo3t2kcaSjX`%j*fpT z0kz{8z%iU-4966Xxg6JV+{y7Ekiyqga=}j=8#%h(R|4|j*qLJ}$7qgm98)>waeSHM zUXDjNp6B?}{Z4ZDnmb(ZfTPntJYbH!I1b?$%W)pZ#T>VA+|BU_$MYO-aJD*wpm^AZqZh|Oj(s?e;W&q5Cdc(0KjLUP!3{MWZ*lyKqr*cbz;+zX978w`;TXqp z4##Yc8#uc06n*5Zr0g99Et;RWppxT3jvsN{$#FBs)g03}zQ8e(V+cnxM<c`J4Iiywz~L^QV$>-*P<8v6SOGgqRL!Ugm<8 z95Xp4a*W}5{{rW|cz{FHLdtO_$AOKk>Q~9zvXeJpYdNNJjN#aeqZdb4j*WMfh*Q%* ze}a>ea(8))e1+o~jt4ou#c`d27TlzvI5cn%6z^~+mz^Sy;h4xVlVbtL5{^4L?&Elz zV-3eU93OFPCy@Wh+Rm~;qZ!C?ILAbe^EfW%xSHc;j(a&C<@giF`y5^El^5y6F@)m~ zLTcJx;DSVs85~z~+|2OEHE9342``%ekz8pm%r9_4s|<6e&26trjxxFCb$B#y&5_TuQr z(Us#p9?=?(CphloxRaw7&r-Erao`Q4w~Q!%eYikXIL}+S8yr>n3%r5K<=BJcI*!{p ze!%fdjx#yl;CPEXqM-xXmvHVNy1NtKsd95anU}Wk{xUD)JbpsYUL73_mX6h2Fd}~Z1PD6TstV)d zNulFi&d0}3h$pUDu0#-YJaGf(V-ycNnp=3Uo@5`wIlU-FaD43WpirbCVb6ZnHveG% z+RNZ8rS)ros)$3g&Sv z<9KC_5^eaLXODlik2w|tHJTfbc^TQ)J;BL7hKHj`k^Ohp)G7u|ne~-sX|`jl;pv&? zqD0Mva*vire!8&C!6QzWM!MDC!0e$q6)G{T8~aRu||K) z+tDL7nLL=EGcS8~R?_^8dC6wD&rZ(jZca{1nm#Xi+We%fxh-C#B+bi8CT}zyJN^IM zDc(HoF2p*^(c`wkyJtv3R_2U^Ss6JA<07M{Wi85ru}7*L8;!;~tAocfp&PNG0~4~7 z=Vy>s@1Wj2diAhzNzP_yG+V1W`C13!-l^7}v8l=C=VHd2BVtCFXQn4-rFF?RXXRvM zq-SQcv6D?kHn(3VleNOvBRWm!8N%9a_VBlcZuSUm*Z%(qiw*h0!=I&o;gMm@c*o&u~V;J3JsQj_3RURJJy?Z=XNBEnd4hSBuvNoY$?f?)}ok-L6YXh~mTD zCTi1AVRUOP-@0ETxC-l~g#SU?S&+ z&pGE<#?heKA64wtHw-CLco~Gp2xA4W4Pi_ z6Y`Z}U&1lt$kYCqzu@*9HD4;cjAP8(#L-uTyrWp$Ic76y>W2KCb6${N?1w%gK{Cx!tA8^inGLSA-72L_?=6wne`BXu}eg(NVnsM2g$=1JoJiXjrPWKd2!CuvqP;v)aG@Lo2&w++V{JN>oj_qE~uY!oCo?5!MsknT^z5vR^z0tF@Z|rJ z7AR&$JTRphlCGjs|M zX``Tq<4%qtdPQ#d>dLzz$>-S{X`V?|G2JsxeY5#5db&8eOO|+kq4gF0z2pdP z6s9`(AlfS5#CeFn7n{7o)8q?-thnc~h0LW^ibL32Ut8fh#m*ALHGS;T+mM&3ocnX0 z$9WgdcXHm7^MjoC=DddUp`15z{v79q&PvSe1UbB!nh-8%uLv|P5#n5pke$5}!4`ea zRed)bZs*XV&o1YCzHT4Y*^4bH@HDkg9+ zk$`6CsJxc*-Q4~<=VhGVwz2=uhBtGr`loSG{IBKiwFc z+uLw6=W2vI+PLq;xf-6`$k0}14SRW=XS?>{+|MxN9VJ3s7cX{rou|o?$1R3)i*1}w z=Dd{i1kP(XpTc<~=hHYB1C*CbafOe#f*PTZIaec8%DEb$PdKmS?my*REo`50zBbT{g%zW)mGY3kwDIUG&QrNZ zWt^)KE9YE|*ip{ah#lj6Eq8yM^Hd&Qg~BZwH3BEN!fx*1BJvhbrUCygG zH*{07?z9a*%XtX5|61nA>?khyhASj;{vGGJoDWA6NLf>&ax{TY@*lYVZf^fQ=arma z;`}b>Gc-EAnSHmx^HYnVyAo%?{JojHRJpwkcd+4F8}4YsTibAF8}6cTOG|*RHVQf$ z-o}ROZFpN7-p+;_ZMeJ4lOMlv2O9;^hD$cw!-m_1D=8SFrYPqz-Mv^tiRWPZ-0oi1 zZks%}+Bvkt^g>`JSo5!444!(xi z#_R9li!d6^C#-O?$+PuX0lW4%0`aEx!^x&fJJxv76lHyPifOKn=@WgNUY_XTVBGiP zm}1KypQ-6>?0;GR_4KXe{3`1@7tSxic~2MITx=aZ*VJgoa%)V9?A<(5ceZf9$;wp!DL`ORmrS{K zA}haS%C~l1VX~OqBIAY(4KP>Ly?@hh@sw`q?{qipK43k*!}OKlK)-ylZrpFO*jpXn zHBEIj{BSDgwoW|x_x?P?rHgAP`C79-F+M7HOL@~>`oa-fSSNJv?y~LG@yqfE2K2Uh20sgT~!KU_> zkTr@Z6#i0>)khTWiab<_5}G zVWzjQL{9cC^A57sF7uu%u;nj#yYs2p@I3EKPiyUK-leU&3{9eyF;vHy=JcHGtl2Y@ z&DmHwn~{^5nVgnwUNAd(A+4ENH@@w?*`B=Yv+z)z>@|i;vKq$vS=Dz0lI%N6zv9jv*XNx++Ukp`0(}Je>1r8+i=paU2sl zrgF^Sn9DJbqy5_cK32~Uy@v_zp+jb8N2Z%&lV_xwqqApf6mFf`#*}HtoJze7Eb(J+ zT<=lp9b<3J_|&_^+hTZDiM^8a7{hX|w&>wDJdSg_Th2a7< z0-A6oLTUs=&eZ@zZFroGeufQS%em_R&Zq1#PC96#Q2mqwhO9RBng}I=YJ|+3s}T;h z;W0Km^+`^H@;oj;6_@`?I9Fr5+s6K&jeWI^eXWgsqm8}OkjGh0;cLuXpuSPK4NtV; zc{Y5f4KK6dwKiNcv?T@Q@HJ*GXh}lO)f9+%>_AST3>*8kHuk%1?8`V;{jX`USHjoa zwei3Z`8bIv!~o9K6pFI3Pvl$;AlJse#KwNN%6a&jGF2eIpGH$-#Y_4#K0XF*o+SrHK*!MxhW}(2;07JQg z8lfl~2QfDGi8l7BHax?I=i2bR=X@-3*QvhYS{sE}-t?*wEU~fQZezdA#{P_r{Z4ML zzTm&%79~&A07`8X$~bSya~u0w8-CY@YocuO+=iP&Z3H1U+>5u}Y6Qbo`%N7?w2Dy( z>)GEVSrSznsx0_>$HrxbjeQ>HEopDVOKkLa+VE1&d408LDs2>MI9CIxIagocppEpNf3-IDjW+Hz zqm>s_-HV)CTHeq`A)IqH0#Tf+`f)b;88-HLHoSy$HH&sD+(I9BkpIeT6l!evUCz}A zXvWyQkqr;wTrGs*oU4T}QRYa0RUv~bs1aIgM%Wk#jW<#TS$}QauQ;;h~(X?xQ$Y z-#C$TwHl||*jw^!JSeeI*lpuMDd%l@wT&64L{Q~-Imbei{Ff1{*sJ_5=X56m{w$ij z@rnW$Xbcmc_OOg|)jnq8(;ima@R&Ho9?MShU#$(#h=0;O>fha`1X#$Lq$speJ>XpR zFqFTcnk8|Q6@4|yYi#Vd@fT3@ypl&qc2D&`jz>Vv!(8s68bFB+-_5z|;s2xTU*MxE z&Od(qIlG&^=CXt&BpX7`LV$o=mJl!sLIl)+C@G{h-d6}36lIH1<8`B=Mn#Q^PE^#W zXyZLvE3sN#m9|uE&9_pe^%f;ov{qM}R;L=3*T=*AnP=wAnKNf* z&YU@C2bl2%0reL?L1)N{U(IYaJk89qjvXmubY?m9Gmjh*v$aDyQSZP?uwJtoP`cwM zR*Km}#Qf9BZ*ihFpQ##WrtX4Z<1kH-0v|8LyoaJH*WClfnIZxg)j z<8AC*ZSUi4ocI6#C;izZ^Yj002ip(+`?yPtY4zvph&0BzTBwKZ<^?)Dg{?f`Dp&l% z?ZLg{-tsQJLx(i-HqP4wZ#%5*wc0Pu+xpGS*XV7}W-;}PahI$dxYL;)-Nnq?KHgfl z1!-pUZtYjk+eY3d?iSyEG49;tKu=b>_h=6DHpbgV-ga1go%T!dHqG1E_1fOU+dqsk35`HCGIVS$Y4&OK(>%Y|;`$2DeD6IS&-FnOUBl9~Q z9^cRLT{^tOZcxr{bPpRThgrJb;iNe_ z+l{=v7u%e{caVhmzfU5gMMu~8GUHX@GIjJC-b(j?azjD5#e4{!flwDJMdBiCPVU%#kwno%(@wn!an z7jJubo041co5hujYnPrW*UFu>q0QWIDjpJ?Z}MZ0^Al^QnOLa2X2Zsf=Oo%_vEG`? z8u148TH9i-UwhVRZLQ||4S34BaU7oFoN^Y*2hVd> zuai$$&OK$_di4NCmC^o-#}$u0*sPn5Ky$-c>#=%|Mgo!tn=NbCpK?ADZC$(WwAMB* ziJz_Ac)q#*l#Mtg>(q&<=JH>tANT09)wW>+JGE^)Y&Bm5Oz5NU8pDitp6~FhdPtd-l7NncHK3&bCg{#f3tIxU1xX(3hmlZ z;{5NpvG)H~A2)XGM|Ta{HBk8aCw4vPkNm@~n}?nM-5GiL8@n#~*7@JlODdbg!BuT| z48LUUnloto%BIT4@(!4|%B;p>%o(+6O(r({9B<;;KeCJeo>Ey+c;wpiS8q6FV~Z^2 zqc)s#_FDW-*Xqh^wr^Wqxiwdub=vqbxz$t5Q&IQUN}uiXHlQsjJLV`X%b&4i`EnTz z@9v#<=HctlIlC1rK385+IjID^YHiywcP z-2Qf3l0<+~X?hTmN#aF zC*y3e?u*-*u{d7+bu(8m_h*Ig&I;d`6<%7Y4`2evuV;>EPEwo=COdR8S2Fi9PhuW$ zCO~Os>%N*yy+i91c$lrb&@i+1$Mt8j!OGzhW~(7;WVTL0oY}guPcZWlQ5UmSf_=;r z`2cn^S4mdwPgLjFa;RoLfFm?BTRUiHHaWb9c|7w@=4$4B%+@Nr>hXGi`1+0Be*+t= zwz-+vnv6*>TTQ8MIyrT0II9rD(`GMpl;cCGWnQf{TrWibD3Tj_-@Ce zIo%z1aQa)-b|Q^^KpUEQ+wJC8H+cuU_Lr%5Ym4i%rZYOTa@t@q`=$BFUbBvHd)a4| z=NZY=#rlNMC3;)O+XQb@yu~t7b(#{qwN7LobDFoY4))`1inr#aZ0BuCZ>tG4K_$GK z1Jb;u%e1{gZ^ai|D#vU;`t!=ubCQG0$5SsCrPcmO3}30E6!Er{w_|y0^0tb%)x4d? z+gje%^R|Jv&Ae^V+ax8}a1n1ic)N+WoxI)5+b-U2;cYi>xAL}!x7&Ez%iBKQ_Vad! z+T!AVjSbcgb}_%h+acbjc}rL6lJWDll($v9t>$fvxAnYj=B>P%}H-f>{m05Z=ygjlepXtubdO^JJMA{<@f_Xryjt zYlPLqj1ipLKlQR<8b|13p3dCQJd-)a%mU`}y+8)Dwe;knHFnDdzZALvt-&s?e)`5@*-=7X8z%=4HN%nO)1l5AMWhA!rM<{sulnfsU*GpCrBFz;qQjCn8f;mrG( zk6=#vhx8FIWkV_RGUjULBbn=%moqmoAI;p%yn?xvxskb@d8Otgb+X}S?9k1840A8@ zam@Y9YngX4pTWGFc|G%9=1ZCPF&k<`lEiB`AL$bC@DRlsDfyU7IXu8z%^YN|W6ou6 zU=A}kGmmC&WiFD8{Zl&|O4y;3Il|n{T*2JOJdHWUJdb%d^8)6*%!`@#F`ogJ`={{V zbqN?e#xj{b%rRykb3Jo_xsf@@9B0mDPB2H9JDBI?a{t@ShBMfqm)YP!TR*dhc_*`v zc{g)_c`tL2c^`8wv;Sj#z>%;zel)>sn8yy)%mxqo>X<#u4a`2~X668MD|3*!ojI4e zlR1)PLpK}dG50YWJc>*)2bc$#gUo}>xy)(i2s3_dQr+#$V=iS*8a&FZWZdmnD&ob{>%x>pSi>GuhsrtmOpckWLf`$ zZ0NHh)aeK*<{Bx~5A^*znAQb+J7@UShqZ_%vW)QE{ z4y=iVP7c49<99RP$lS}k)VitcXTvYqVJGv$%+?*wq0GBE{90yfrozX(m&2`Fv|c^{ zKZoz*@cXz^BmaMOk^hk$N|_&Fu4euNa~<sW#v6Br0 z?9k18By%rwin*Wp4dy;R!T|G54*x&q-OTSY?`2ND#fE)sc!k;joi34IF_$vG$Xw05 zi@A<@8*>Bmqs-0B?=!b*PSVY6XlI8(=1%5knY)?)#N5mL0dqg|+sr$e-(%j*{8#3^ zic$W*V}mtSVoj~=;|SJmwl%Y1O^x`!*Cn)`<9G9QZB4b5a(F9;TeD+9=4u%(&;N2Z zSW_P}nCm!!vze{wv=DOxhi_qSX1<@fmH9E|cIKm)JHhIv@@Y17v%_=D&3s=jf51Wh z^>TQpMzW?xtht?7x%4t(g(b?dYfGGudG`JG3!ZbCL2$i1u>$;~c(^ z*_s&{;2q|1xc>)zidHaNlULQur9ULK!|7~@^A0PSt2u#Fn5`MgeC9e1=U$hr8Os6= zZ{YA-n46h@!n`;6p3Xp+4Xy03lG&Obo6g+M;TxH)*{@m5ogCiIT*s&IVCHTPzl=GV zeotp$6dSDBriIMC9N}u_e&$uo)^uA9^G*&wpSg=mbRzR^4nIvZZYtTKiXHZ{!>P>s zn6GC}vHtbUOR-jn!~SDjH+tQ&&^|pI(FE^Y)v@Em>W3!PUdFj z^O#$i&tYz7{wcFHNnI#eUMijJa4S1>GdD5!G7DyUUmx*k=6(*pj=7Z2`N)(jhhM_s zevV%RmiwpO>|o76hS{N*BkbkyW0?0bcQgA*KTqDwT*`bmb2W3X70&6GSp9z;J2bO{ z$qr+f8#w$}i}?uWGdFYi70j*7zhG`>K9{+Zd8^g`$9RWj?9j~)$6E<-_;}`C4sT)Z zXMUb}C-ck9yP5l#_cHgZ@`rIB8(w7xzoCot_sn&ife3Rcho8Wl;PL$)=4uXqiMgKn zH_Xk<$p@?i*l?Q_fp=KW+{xj$Gj}te$V_}nW;6G4_yx?Z9A3}dufvmc4I8T2p^kYc zC(ywhUF0V-hk1u{m`geQBIZ`! zp~+m$;j5XOIeZ**9f!x6{W5)d{%hILzz%mY$C)o=?%@O{Gq-d2I_6I14b0ulZsuO* z51ISHD-1vv8+Nk8J&!=k$#$miv2i9@GWj0u@= zF}*lMon$Os;W@MpZ2dLj-`UB^Fd5HaCwtN|ElxTCmmVO_h?U!9zb)yVwtvf%q`&oN zPg15~{gvV$t`1j+#}}m~9vmUgP8_zr1#Wr?dIK7S_COy)!%%pkn@s46h3+KPpXZ?l zXyCpAnz^ljo`n7l?YX~z@*XIliO{;AmC{zI`j}FBuep>ek1eGsP%ZQ;=+NUzDRF!$ zb)JcEsOr2@+627?ZEP>4=b^y)rL^<%QrZvgzN!>oVK1fcu1c1YtFx4RP##nTO@T&V zTS{fnx0?}mT`7%)s-Pa|L8#`2QkoAP1}%l&hdzRCys?zFL61Y*p;b4P(y`Fin@j0l z=waw_Xu+0JS^`~>ytS0BhkBtWpxZ<#-2*)Xy#&1t?ScLadAduf5Q;!m&@|{N=y%Xx zp%0;!+e&FYbn)#-7uo^627Ls53H<;C@4x{<W;W`WouL3-O`1p&{smyOAO2)O(OA=-7Kp>11g3eWi2|bk}{Q zNxBdJ*aiI+`WpHks@Yab2SX=AYoLdJh0=ize!7$vLdQd=K>g5j(C%lDX=oVw7Fzb} zQd$9>1g(MAL1#gKh2DdPpiiLavpD~kJX=b4Lia(B7-jS%bhfLE&WEnLtc*U}R7TC$ zmC+AfWiey5vt9P(E3RcIuE)G+6>(cbwlq!pFqneN9Z_cE%e*@5jydZ z2;Bue2E72yUJ#+fp+=|$x*Y0U5J}Q?_{XhK<)R4P0)5pGp>LoQej1?<)<$Ru!jDu? z&Ua&|YdI<=MxMQ>3-Z%!PvKlIN3-9JQ`Qcy8if)>7nr!Pj0P|o+4mk!2khw&%BU}g zXxb+z9gO2*hec=*1Iqm^vm!JL39MYTWL4LS3;z0-b$>qMg@;Z(^^dP^^CRB>`V9iH z@*;DR?5cOcVHjKaXKiIhV=E&xLw=;K>P$7hh^>yOHr}#T#bT6zZ4j-cwzVV25o*P~ z{ET%ir?j0?rG^>ks7T(N&WOdv~^BW%Y>TaUxGRQdJ7 zCYx#*xvF{TV(FK1`l+}(9kxalcK|jV7sqXE#y^uZ=yYtBo_n1(m0;RoYf=gBbJ~<2 zT@;~?tGzU1qbvbDh(M3H-oQ>3SE+kkbkFphEVYeERZQn@Sl@Q09Cpj$LaTek`GN~B zXjv`C6XAlWF0zenYpRwWs&-!LupOs%ZrW{4+OOJS(|$47Iu{!>BiXKV*}rl;bz(;| z6j$LyqCa0Xp5iycwpRP}42`FEq>nzg>gM>OkH)L94BON|xeGR19Z(}d`4d|0k&(D_ zW%~G~5=xrS!Kl+$J%6Lzfhv@Zs@pa*d^Y|`UFgc=^Wd}kY{e9=qM~bXBneKWXQHaa zC$C(BpEgB=zKPU>&5Vusv5u;kno{V2O+Mg;O>9V-2Z^pJ6LQ3ZNppg`t{^I2Pnu=Z zm!O2A1gBvyelOHVqJ-#vNZV1*@o#BE1Tw_WACH!Z13JvY$#|+-)B-j6sHoOUMK$4s zfhVt{Ye&=QCv(%mL4U#*_cn^Q4ztN^hNI%u4znT|3(LJ>)@(G<&moHm|CTm5k`eUa zQB5udH+mD%92e!Z1gUX6el8W-#PRKHcwOYJacSS$03~ow@CWEA_O-D%?NW21doOZx z!=+|%5&l8OVlORj3(|s?0C`usVz*vqRvq0qpXfBmO2WZ1OIX-2i15!LS;gcb+1bd; zp}bmr$kiw$ZvsCIZyr}3K8&aa8XBejZ7lwKnK>&-sA&06tWZ1HS(iyrm5G6cFr#aO zG}k4AA;>7PEUs0*&YXFh!sLlx?(DFTZj?|;?t?n4jH-1 zPgO$!8oMKibB=~3J6!Itset|j|53QZ8?-Vp>{r|@@A^jTgOcHP&csPd2Q-)15n)Gi zCxo5ZGh#dxq=$xb>E4zQ-PshRz{;GoJK>5Mksw9d0u(`ojG#hBP$45VC4)w;n{w~< zr@Xk>)Pe0n`m>3C26f8}%?Z*R#G8&9mY2i@;IG9@TDFrsx*;E3j!0iY{d^=2mQ}XJ zhkAjFXbDjnr0Ru?+vZVxE^Jh!OF@R)S;jfgiev=b6u<*GLIbEci*Tp5 zoD;CI5LcKL<&9H`PJ%9C2OEpmuP_fvrY7O@2)Ox7Nryr&74~~5w>O8p-CkwyK-ho` zEAvv>PB)F}^pSr@F-iL;&^}H$n`N3KadCw9{TNtDQGx5KqRB6=y3!n#Y+Q;e3dM_c zIoR32da&@HbK{}LU`!u&AvI#|_e!W+`WK=04F{=UC`7?sxs%*jg zmuzS-n1M1NY-vIUV9_?%tc&VVxjXEUT7DE(tnq|qxm1yrE&lqG;R;1dH;%%^n zr46~4;TgubsLf0Ec&gpF$(zWDdm42b1r%;V<%8lX4aBL)bR3yGr%lJpL%dunxG9t{JO+8N51msS zNh{HXP;F^6iNlpybr@9<*qpfQ2vBgP)phs@Kl(+vE!cOdEHb2lM#5=Bi)HgM$~{z$ z{m3pw6(3G$ux2SIhyeU*7)^tAs02|~c2?)fOC7M?3RxY9jm6|^%sD205sU(-ar-KB z)m9*XC2Yhdx~?&c)co4mYlzmD>C;X4x5dWkemWho*0$uMy9`tCNiUybl+hM6^^ndY zmz%?ek1yNU$jzbLMgFvR&@7zSSTB)s=I-Xv4B9 zn^D}o*<5#od6BAWMEy(h*v3UJDb541x*`VFfPEN$eqVjrk=@H@2F?fNhE3g-=*qq*kPHiYm z4!i7EY71!qen0yHlR(lJIkK^M{CczE7;~IK=R%vz z9!eW(U8O-2pw~FAjm6{}%;@4+n&`MM(YHtknWL6HiVMENRW(lMNQP%vUcL?=aqSJ} zLFJ8e40;4=<486Z@84ifEKi#T9TGLDj~#3*D!b5s#;Odu6H2p#jm0rt=B$O`w~3}g z^D8;8I|>!=gsoB9P_gy%5T|=lPAEDxN1RIMnH{uFu{5#QE&|Y@1u~;P? z!XKjsdzY-^3Z?gGzF>aLv$~Y zwKoT2!FS#et|hdm={;y;actI39c=mG+HBl|d)oDIwssDK#p3dt%%7CYPk#iU&Zs^< z8;dV)!W~5TZ@6KDQtV)7Bjl!#Q9>Rya`KRWsGK})5sJTu9uL|l_vv#*%n8V`6|N8WAc>j}dEbHH(u2vkdya#-Qqn zI@eB?=NB_hHXnV5CA)g>$PUd%eeUZR&<>m>kPUddX6(; zV^Jy0L(5Z@1~r-njh&=(X=8DrKy_~{HmC(!E*;cq_bcvzEzXf-xSj2BjF6W?8-1yq zgeUH9#QmMD{==iF<4l9LY%r)-rXg=A(LvVR%RP=Kf^{ODf@b%crX+tID{EOAlQ zVJ`ZPcW7gA{O#sXW|~77aX_t8bRjw!hu0J)n@zlZyBVELdkp#s^b|*OGEUpjXp}=C z+3aHG9mvk$AX<(O4E(^B-kXiZhC9p|;{Wb2M<+Wbx#$|GO?t^YsW#j=W4I`7_d*>U zJDVNxWG$)1I6La1$02JhZf7-5f?7AahUZD(PZM41Y4k)FrR7dk`|HQfeaco2`*&*R zvU$K<7C2)=%Lg8bYh@gXh9|ga7G#}v8;jSsnjan9v%*D_8eLR3O_z(Ejam7J&1#!P zlUrg`Q9F}L7LPKjDVX*TdIvly@#&rBq;lGA;MoE$SdMRFall<>#lqCD4Jv*XBT;s6 zaE>ghAoVaoO25B3vvU|SY$b}G#k>U-6|#2jV9O6X@7Mw#$lAG$#kEVKW5o+S zsP-wOly@rzmpo{*vDn{(Q9=x5vK)G3ralH6i+T5;l}}%5Q0Zoa_OgS6<@syDghH1= zfg3Y@iG#DoZE^UuLDsm<&IVq0iD1MoC&-Eh3RB@kfq3g4bXJ2m8DyZq5;2`i8;kw- z;4n-$)I*Q3gN?PqU>w4Z72%656A1+ z!KN(U9@SA zEF$E@#zwx2@}CSQ^iUy89oM<&M(8=|D|gmZfa1wlwg+I}!D&bzJKN(KC;I5bAus&| z?W=#aXL(xn=<;aVa;fKf7lm(t=3)ox2t$ge!&W72$e;|jvn`Hz;TJfffle2#x!OhR zIf8?W@Z1HhR37>-*%_Kwx#$qcnsl6=|tw#7Pe z`h+`e7^h`?M6%Z`E>GO#qHd_}Kz*1t7LUUr6u-qq0%|=FkD+?asKfBzY{TRSF}O;+ z=c1dTK`YG+i<2KTryoD~7Z-gF)z)FBs%OCAw(0I&+P!bOXub@SO$M%RrwtEt96q?4 z%A_Yge$ad|*|^6=%ZFUF@ycV4cYHW95z+cd}Pjd(=td;%3&;;VR7=q zX2r>akGSaiM_p8XFmfL8P-Lh|4M3&suh4vH#}PSM4oIuiV3ca7lOqlI+E~2(uzApd zeJ`N;rd*VgiK#LAEXBWj(M7w|4&-pM8VSxKo3A+X5%Zv#sn=b!asWA;r*qbVbJHQS-1H7du(4S2sCh_v z#|$_90;->{vu0!Qi$~?ie6*X4A~z-2!N%g_M=_t?g}~-wH}y#eysBQ(iyGRkZBM{H zz!9a7o$c|AB0PX?3*iAQ9*xw5)A@tBDbJ5$lV<^+g5j{@yI>nD zZKx?S+|IT*LOhOBkTBgeDeA`36V7{v#T$>CCnh_Di{65UlmoKTmQQw@dYAxn)Z-#g zEp8JJaZ@iecA-wt!Rl)E;xU_>N)E^RH#JB=pKW8+f}+(_69f}Hbu^*Li!0JcspW2Z zA6l;xmKn*m;Z8W?Bi`@Bhy3I9IK|Mg6$v9Un@y~E0@H=*bKNxNJoiYaX=8Es6J}Y+ zZg}|#%qP@ej3lAw>h(d|SX4e~9<(O0-c8>^;X~mdd%YGsNoxuz+qg4PRiqu~NBY>= z5l=m)#f6Kwgt&z2XA2k4K8Z=7o~zyTYp7c$D2o?GC;1hqN803QWmw+*XIaoFhc(fY3 z)=l?9)}vKBs|Uy*;&xr$sN?$-qtI>SptT;rNvUkd!O3*z=F;4jJeq;ALvR;{U+DVv zL+lVffo*rR#$XuHn48>G1F7MVDjl!l*I*ms%*t>(|0qry?vB>F>F874v}CM4Ksy`x z;?GZ+k!0dDH(dfXEryTUS5WbO*iMi(l%fo`vm=ho_b~cV9AILDn=Xaapowpk{4HT+ zdlB|NYab{i$r<@zrs!DK}!xp2Graf9^ho`C+Gm_+%$$B zh2y(Wi*&9IQgy43CZNGB-Bn28mQpPyb(++5t zj8N%EU6vGenP&+%=SiJv?Ii zGrJ8kJ8>t8)<35eb?hNGx_87_>vJ!Rh|F1+JMxxM2qIUjYMf3=Y z2pTD(42%Chhk?Yv(^$_By|YXonT^Gfzmcmu`rPy~H0?<3;Na!Cv>a!10nX-3oK3Sc zb258=<)%j=>ts6kf8^AB(oNGLE2qp&+F+}Kv0u7rDP&y-4z~G)pK{X_$nvwXIP!V( zu*K;++|;@i-TQKVWDb_SA)23oTio5 z(SqCkA^1SnQ*Q^`{CfV5<^r<(9BlKef6t8vkLX4%M>c3K^-wAAIQ{_|D9G}2u)GK` z2<}U}=^Mxz1Us00dj936Paw-jGp=B1Fe*^ha4~tTb_j`v_qgdC$co@#E76ZoIyhR( zr^n9hW4`OA8z9Ta&W5-rWtJxgKX=ppUu0Yytj0Dj>ig17&qFGifQJHDzmn6UZI6D1 zx_7j$3DU>Tj(939FAe_JO+P?9rPAayC?~8Ya^XRf+cPrCbTB8>_Z>Qj@7*IaQ#KYi zyofGl@M||-lFC#s8;iGIG=Ey&hf`gMdNH_yFVPH(BVK|-kIzFhFjg}gwS$et_Ls~P zLneCSt1)PMsxc}mUpAu$Ncao%8pp_HdxSGymbVvJ8?_2*{fXX%jm7U@Hm@k}o8_T9 z@D(usO3q}4#c4at8_T;Uc<7KS4?V&THWs6QYfhg)b3C*d@~lD%Ip{Ll@bIk`9eKts z*1)lH;0Wxd!Q+?+vDw7qzctIsQwMwKs`(!3l&PV|w6WOpTXW9wiFyw`aj1u$V+SY8 z*$yn`Zo{*`rt#zmljjxFG4VzZT>)9^E^RE%{+&4|*>RkQ-h*13kOMiGYr$Y{xPTmX zIhMmbMcMHldK}s;eUV!yBQuC6SMm_ju*WxiF7g=%=>cSI9W|cpp_`zgrsxSOA)A3` zuJCN*bPv4%>01YR+nQzLBdlNNp=Ho#yw2Ii;_~04?})c}=x@;apCZ@tnd?v?ZmdQt z+p@JD{3Mz_8tG$adpx7iM};jRqp&t;6dHabB!|Q5((zE^SspqOvKn4H8$}*5b0^lI zg*SNU3&`^`xidMktVS_SA)8&Cw-fzwBPO@cfOKj&>{{%>ZsQA<&h^k_2x||Kp!7re zJ8U>Xc2@B)(*@g`kTuG1aE@y^ZljPGUY{$0EGGx6X?zTSF*cTuMdR@6g7ni4va?w8 z2lJ4biK{&HG1PpFE@vlWXS*IGn@zm_2lJ?f@yk5)OK3MoaW=w#_v^3C|rXy%f?cp@WSVCc(IkELs(@b_@CGiW8^=#J8YBHsXCsV8vKiEri zp`FL#IHU~)AbB~oOWIK2*-Sr*gPVy`FIALzi$>OoutBm|@tS$);=u|peL2oct;gw9 z9n85&6nW`hNVoj@{M&5ejn~ZRnvR&4j-G`>N!!Dhl5o{kl77hYJjX6DhDec^!OKgX&)3TNXmp{U9=l@;u$BfJcBJ`D1N4w z?uP7VRdPQRJ4wgOW_uiCG!{m*mEmm@ynl)}5^}{+17^X@zD^V_)UJ|1cCag_4Fk=L zkGOWgoH!?bjhA|%oxEQ=8)k^i)*y{-iO^U~kc`Ft#$p{`vG`=btSk>->80nSCh9EP zSWNgo^g!mNScGwzmrgiYJ2+UKK`i(<+e_{?ltqQ~L8h@l)oH_XESnE{7Am?aoXSt+ z#q}&i7$a!RfSvB8d!TpZzR*4t4f~T=`xqe4u2CxBQ3UQ)89^^Jj5CZd8Np$fGZR>P z<46qGrJapvfTH*;VI*BTSTazQDol)O499qus3l5+7vsgHOK{NfQTnJehNxKcXL&uI z>!lN+?zncavAFxsn3Nd22@ef#M(e5^WSNwa(}qVnHXoxnhl+7-icuHx8#ya&c+2w^ zoLi{+6zoXVy%NQLfvry3aA-2z&WPi;B8em4z*?om?Oysj)XOoPEOR%GY&P-g8|L%_ zP2r`@5Utj`aWd@fcuS-;A7^1a*}}xkU3gGI$kSwKvy80jiBEAIY+E=%8E$7=9Px`? za^>(nUc4)f3c(RBkJ_GiayR;s|h~<-=UIoKAMwRePOJ15bHr&ac>4&VI75!>+1Z zKABJBDu&d1cB)y*vPr*|IhZDui9)IbWCm(+e(@y1VMo!~SiJETZb15e?WOIIc`9-) zpJ5E+;1Tiy-qf>>0Oub6S?+L>);syO{h}Jkp8p_R{^( zdg+MW+nL`4ZHzAT&_a}rdL8dQ)NN>+^2Z^_aIbK zWk+tp82t?|ZH3g3gAE-!r!sd?~_ zheAU-rw+Tk1^OR$LymRuxGs04emz&OSjIAI9I0ArE$>jgiK2JrC(SAbCrL zlFN4nh-?35&Z&(53#~R3TPF`omT?!^Y~uaD$;K(iM_)nKu*|`#{$c8(!bb-~)~%j{ zRk>o(55j)~S@)w3R_WwYD&nL0^3w*Q^vMQ;A)m~7_ z>u_cvtG}|bcovDQ>G-*iI-wayT3g9aLF=UrEkZUs;vn3Xu9)|} zS#es&Mj!Prd)D_$sMCP={d(o^Uk%}1Y9jYvf%;0-A7&oa_~{>rTSxibUHM0 z8jkhFG6tDzG`MmCrRzeROvqXZWn*!}pt-KxJlRJ_K-S^gSd9L_jGmTC`sg3f)(!e3 zI9O(B7hadb8isg>kFJF*KL_(6)1??=LRSA}V{r#|R^EZYhoP#3-kFWXTX0C4m-%QZ z6lVuJ8^wM+qzzDU6SlQJDy|tds0U#<%ZT$Cw3XvIm~+>7xsNtL)+;u4HkJiw*{+Z{ z??YrFu?dH8g^%`eVs_SoIq0@kZMrndO#BdA?EsB$V${3&dkIFbyvvn`HTJcQTp6TkA&mC#-*kzv2$ z{o7H7oQMp!^N-?Syjg#bkJdtJ94a$|v8CkGp(SVQBgkgN@mrCE`y-sa#%(@22eKcM zsBWBA7Nar9L=umGgyll!t2i#Gu1z0< zomF4(6)(-kt^TD$#S|Vc!SaV9NKdk~SnF!|iN~BmRLzCWQaxqvN3#6+vETWoYk9$z~Tb_nKvk z((m|a%Dc$2bd=8shOyXmXo9lMg1w*jD1Gdli6^evYes^pe`7}KKgjiY;<3HvxTO4d z4HP~P=~j5Cq8l&ncWT>$uhEf9yF9wq07-shADS3xldp8am*7k7n502CCaP81Bk7?8 zGW)}$PuW~ynO@#a-bQ0wE{$s|5J!H30fG6ckFJL5XUT*y?6R}GM$rVBpZVx2sBsGW zWLW&-6I8GG9v@u{neCioynibBb*N6-kZ?9T;>aCgkVN>sl}5-KkUCiQicR{yDE)(v zO7~;fcDPDANe%-i)`#C-`3SNSv$MKQuI29zs6hhO&*OCs!o1EzD6KLr`*hqXJ8U=- z8>_DdwTRz+YEDhYF*?2rsykmFu$}cI1IKMSb&T@U{m>@qFZ0||p!gx!x;PCPZfAQO zJsQW$i|C~aH|C2C|1k3+_0#=y8MK=d$gsHeALjTOJrfZIg)h*VbTSUOX&hy2;_v@3 zZ=XRk(H}ztDh_<)pvYlEp^UJ2>@#!Y0uyKRFvxyzl9xeU7wUayb0&^B>7V%OSr^t| zyaw%-{^~jiDt;ffw6s;@X0#iPS0@^>_5exy7m)uVnLaLPgb~7=c6^`#J|k%$>-PN^ zlX7Vis(b|3hx>E$&`9EDKRp6%Q;A}hbA-i7pPO^b)0_P?<~sk#+`5g$8=sqpMEW}X z6u8t+)feld&ajyJh555c*F}C>aIv5IIXuJS_Akuwk@Tr3G5iWon!__J-u%K`cBJ{J zpIV{jOLY1U9_OcVLs+1N#jZgtc9pNv#UDZE4XH)6IC>k4Gty=>l6cThw?QdRFvH@3 zv^g%)*yE>5q3<|6!{WU(mTZQ%;hKYL)r3D*SlC!ia%{9dcNL_*d;K&FwX&~+IpU+#>}>e(*5GR1S8aVh4Q|IXlzwOBmmGwabm-HR&6zl2?pNm2 zNY`$h0jP)lGb}Fn%AC6({yJv7puI9&9wZj6N`3|Uj^ku=CXVq!eK^)Xt)y{Oilj-6Gjxw1gq_b<#N zq>KPHx&oB8936}^f;9tnA7eFUQ?afhSc^BzHd^nyqwmNI&=g2LYF1|*y*79@wEQxC zFxiYaek+n#IBXUN2ZI3$g#xtYGI7$dSu$1ryA0~#6tdaoe;53d;Xr`qL&MTv<^p%9 zl79-(!- zn-~t!;MaJoavz>($PAA1(kL|2K@@Qg9xO`xH0UYLd^X$T8i6EMEY;+sQ5oXal}F#9 zIe%hch+Lt2f!a;fg>(8SbOOg6;i=LfhdOO~pb*Os zP#jVZNw5C$&l(C85{l`2w zS-;0m7eVz`=%cfD_!@-}n-!qB(8$a(>Zar~p{^@+!DRD~;^0iiV*xr9vZo{YPG~o$ zlg)^e%tYcvdi7~Pt%CF-J)Ai#0Cd{2Se7UbdcX{j8;>+cX2fi4V7fNab~|26?xu)w zD}@?yR^@l-hQ$y2%-|8}PyAH+DGG45JYac~htWF<)oDjweq=+pmWeA?e1nIciBSQ1 z0or>N5>rE>kmBJ&oTW}(qB7jh_Bg8L#a*QO(&eA^!zPsuzKGEAJ}%NhT$G%SgXJ~V zBAXYKM!X`z79S2!H4wjb$eEN_^)#(|Z42y@pH)|q&XQJHB3Q*BzozD!5|9o#w ziX_$t=&w+m!!s=A{(vEH?Dznk4E1n$hQ(PwU|=QJd|n9cli{ij$ya31wX*4(sJF3CwWaaWFHSdi65Lbz` zMW9W*!)$iMlZDwlqe*+HcOlhq!StmfI;FnGf|%W9Z` zYgRT^=EVV80_~Q&P}e2q8o>!@h{z-frz7NFMK10#!q9IP^l25nP-RzhkJr{ZA}Um8w;dgP9g zcsAQ3soS7?J!x0U8fM_>{#60`651={C-4{+O9jT^gyi6aNPDmoeTNK_JH$vp@&%B; z3$~=nS%ET~el@NzX+$QZgPk3b5bj7A?8t;nQ}!vp2+*`%9Ib7|s@-N(gh*_0MH?e@ zHx{cw@9^F;EPilBXDo{S5@SQC?ndOU81DrQO~rb$YGvC2dxNwi7t+VhnRwzXcQkTD z;}Zee4{eeDSaVs?a+OisbiLuPz0Q#K!Y2dx@dce$HrwKg_ubL5l+acmg^(hWUa@y@BSE|S0H{>CFwNC#BlFRJJCBq z))>{nyuU)=pA5ekppPNX%{V~SxHKzX|5AX$ zmThPyNuK>O>X)?POl7l7VWu)s z3C-W44=%%EnK!y98T%Lq2U#x}IoQg_V1U{ooe%8O&V1s!K0wul>?cn0{Se)v_npm% zaauCv*Zj=W23(a%5WivXPmS+}wd&T%bKgU@gpm-3gkV@0EA*%n6} z=#Nf}q`X1;Gh|IgWmuf+kB+bDa-o@Y2k8+`(8+RKFV``YP{uA^@kb-$dh&wwIz&Qd z1eK=c2+G)mD-d0oq|tcy6|%q1V7KX&FCogU(JNn6^W27Yqa{JAf%Nw@a3$E8D?+R| zNT);k-bGeg3|<{J+yyxdG9o&uRB4d@4cT8Tv)P0%7@b&|n1B+2QVXr4!|U`Jn>aEU zEi12YKq}DuRr*}mSR~;P>B8XM^Hb!pTRUV}JQ<9xj>Kl-MQg~sO^0V#%m_sf9v7Y$ zq)Mnwh09|sp^Qyj37<$8-dD_75TpT4Bg5ivp=fmBAU;`^P#;iIYeev2F3hOOr*vIs z2I*a>`gXZxAcyf@G>*kw z8KjS)?2md#Tm7nF6|Lu;uwjI45yi84(J2RZorfw9SzqRGGD@%$L#1}SO4M42w?jsJ zMR|S{6Yi%3Y2NA})os;>lwomhesp|f@WddkJqdN5!!s0{dIN_IE%OMA zy9%PXadmjvlbsPS&=lq^*I5Nxf|hD^zD zJ3HcVi!|_uAbkm0lcF{jUyq7b%ouz4|hcnkQN%3W{Ew^mA93_7MwOY2eiHhCN1?eJb!$HV!J3HbaT<&KiT`>0Tl=j9+3??8#)qcfIa@t6u9 z3gQQza2l=f5f-10jxL&M?g`TMkX{Rgec-zwP8&{h#z!1q6s=g5`eTr0{Rvm@y?Uok zMk2#_EMWIhS6VK9FDXdnAEMH$J_MzbVex8FbmD=1{|wR>kky_z+1Z}h!o=j_=&_Nm zH<9{V=zQ+exyrD(y*N6fwf>DDodb2La9NzF3pSg2$btSTuO=`km-OlT`2eN94AOpR z$4I~12w$v67Vnpbf^y5Y72*Ty_*icckI?0#^@rg5OK7w5 z$F~Qv*q)y83La$bD4>^W$KadTqe;9oCR&stJG`JES%soKr8=S0f(QeL>M@TqJ8H2d6G>U~$c=x9Zvd_y&z5{yh z0ToMy+u0t+z~lWxGemfg-zUHg^bnakqK>iXPg}emjhUi_$-z&yNqGP7upCt!|Xl$=8CK+Vsu8jLh zk?7+vllPA;y5{;|=9g?(E?v=?f4NN3!^ToDq95IqE06~V^hhOyD&QH^j56;BhWnbL-uDZ}lY zi6c(0j82W1H-~5?w1xdMEFPOPUI(1WP(gHWsGCgZU|3 zesS?#WwfrcaStjxWWQ~+*~BU{if@~}5u)REh3KNkkX?0wVL8T*9A#^Py;Is%)$#n; z)`pAB7GE`@O?fn`CNIs6Xk5*C59tLjjc=nU-o=%p(nPTjg(_7q?+m~%VT?G6@ln); z*ta3N3u<^=muZH@S<&d!)pT4g^+TIwxI7P77%6!V)FW-O&JAl0AD>H4aXK>G&W<=Z zcbRm>w^7{qrST1$-yD@oxqUhx4wn09K|T5*MAtypw=3*yl=-O)A0#Sh#g8;$bfbQo zP8K>E$Q(3~^O{j~*Gc5jw_{koBE`1uv zrO#xz+$TCF$z$-_J@iYxPdlqe5AuA;?i|B^a4dSX`5P1SCQd}FTP|i* zN5>f-ipJ{b@f=K+G zTzV3k_KeO?4gfHlb<>NEL`IO>t2dgvVqWFS*`VQ+C ztu!($BGaSCMLOo>(@v=IS$$j?7S~Tl12?cTpXRR0r!E;TC!ltX!oVl2Yz?q)<9O1? z&W?EUmSad>80fum+nrvLPvZ~I$Kns9DZ_?6RIm#j*N!}8Pa`a?(=E?7*dmL=XJA?+ z+T{fULK_TDz8 z)*i{q+nPrMr{>eK>+&u z`7v~R@zweCDinKOA83Zf>9J@eGKd5E7TV0=85VcNFw7b_E1%|UK%sJYhQ+6`=mm>X z*W}Yrug#~{7j*g#R&yhmzs8l(aeY1&+>r6huy|lrbZ#WQDWCp%1!^#-lVS0nS(tlG zV;_B+^QknY_mg3Gwio4r>yeq$hFeRUkFf%il*4&+L>t~G!976U zM$C-G@m|Ra|3S0@PmT((lY(0H`&S9$U@skv0Z9-nzdmi87NpbKg0#9RKqsO%fK9Hg zh>PX5cuqdgPxEk1)nMKhzh|L;^hp*;8x}&pn@?Xs%`fTG<6!xG9zJ2rMyn(GTR#06 zvX*_OY;4H6td(lP^8Z8JyMRkI{&Bp&sl98ryX=|0XWw@ymq3QrY5Gby*!M}d%;#t zOiOQ7XqHij+Gvn^>4bZGC+Q8$3G0ZjA7G-@1eAlsgo6fyg05$IJ~Q>ja1<-nkp>0 zs(xM^o~X9tR*f&PhX7UU^r-T@%7fJ^{%I$93Ye=DV&|$xs=&8k7z?)aEeokK@t-@% z65!lm@?$uZvGW)!4)NDl|JX_H0vkD=V9py~9pXPey0ep<{B5V)Pv5N5tLbmR{Q0w! zc!A#j)F#m~hI#DFW0u1T_**BL3-r%wRW3i~I=o1XErYRKi#pzmXZ?b3s$Q#UfdJ4u03uURks#( zFyo_;wvP4nEvYUMXTVX|F!rjCp|mZLwV>)XJ?VMgT*+`Qr>aDbK}FX0=kh&fKDwg3 zm@3zVn5RT~mg1AOZq62`S1oEP@R?g>sIElL0@gftc;m*y(A#D!OQarCv6)ku=ea7S zYD?rtU{#XmhZM+=iK=VBuBRKmMc2JVUj-?|0S<1zQs14EmTBq=olYD7&qQ;i9i_TQ ziF5@M*Q+LCRy^C z%;WTVV-GB~}nkn0fK zW8TzJ4#Xo*ZRYXkC$^>J0VViC73!$dbvV2+_XvNF;#2_d5<0L%*1vANaD=}mYI|M4 z>0KUtWBfXtvsY*MIu%GKtW~Pp3mj1**ML47P^N7gyl4l@5NYatEO}{a88WVp9i3_B zF1^7p#t!iJ8|ub6k|uN^DDUpqA!BZzXiR)$iR=L>H6HXtPOs0-d2n{loqu+2)&Tzn z-Q@HVDFgZrcyudxzpSX2I@)og@<@M=X!2aFwjlTPWS&QXh9b$!!-brkiudFL# zkms!x0qHL~^2D89B!^o#ve!eufR8`(J2AFsbi|u zOn1iA{SQt0l28_L_sv-SO7u+4_b7|*BrnF+1a2*nBY{=U;lujK9wQCREs>*ve$}d; zko*{SzRo;m3vnXs&JsBr=-xxk_Pm%eY9N+X3I*Q<=1~P_jq=;Tt~YgSTKa#KX~N2I z2i|)C%#pDk<$HqxZ|QnkdX$OUh0I$JaVi(qonvxYiM$SueOtFa z&vTrSL64WnJ-~U45^=`NjCc|1qjl*oI)y1O&qtA&qE-oahJea^y1*yv}y(_!tTJ189yD3pD*E;aIpx?vhp-_lDwE288(5? z#uB**ST|ufy*c~(;WK5NHJR5-%_em4)1DTDDBU}JAzW`X)!U3LH_cn`?V4| z6Lfe-O(;6g?bu#7Nd=wmd(M zMeNMyn4pBXRhnkzCBf!r)ajPkC%VuCz7|VHM+Yo=3zJXe|TmmM3pjYmEuXZwckAE(Y z(dz{NWi^@6Zs|3~ExTC8_Qta(;HLJ_ac;Q*Ox~jFw7pS(qW`Fx6mIyeyUC630PA$y z8`Dq3z9%%yEmMGe$np;FI<=FWy1GDyFDu0Nr^^Kwc{AxmE_R$GO?nC346zw;Z^@Qzw09mExjRnRJ`%m99%aU0uD5%ZK{+t4VEjOWRM}vXM2~-gtH>uBWGvwha_~#1`hf@wZA3e2LGl$ba@Gv2Vca-Wg@2A-na(owW(Gf*#>g$v%S%Nn7?yfrj17iwDsf~ z==4TtnBQBI?BtP8fYn6X8z-IbudH@^WG1j$=+1fLq?0fOQtFZ6z-pnx8zsa2od>7u zJTk7cC)dP0uWnqzNec7juUNs|Jv}lCSk1M)u@fWf?%U5JhXbp*PVZ7D)8`e0jC9EF ztMLUqayhu*6FuW?Z=7>77F?{KN8SNRrrX|l@MJ7_Im9EgK$hvYH$FcZ3odlHN0x&= z+qh}uys=Nn-)nH-IFCFFB23ToEm|!jJaP=MT5Wr?)ir^U9yt+Mt+u`KRtVD?9_Nu} zV71luM)3$dGL8h3w*wa9%qo5=<4kB^f=5;ZtKAN7{CKjz^T@#29+?fS zhUa-)z4zmkYV|sNI}*2pl;FpHF%A*cSKiX+d*sv$>=|Nvy(UMl^2n{gYNW%PYjRES z8jmal)~0HEqYKv48oZDA5n!#xG20t+hxyBEGXL?&nDguv+4g!xPT$~>&NJ;5+2PF< zxh68#BfEjMt=e9$*FoE>#&;d@1y*ffwLRkW|D)~UogR4#Sj*M+-2T49_V>Nr z_LS4NXnW)btYpC2{v6(Hdo=VDIv!wce|i3Yv^~7nBRhfBA?5iN9a1djk(YthAvwI! zcC3HD;z0XS83{sP8i$Yd*LSzQ?hT#Z)vlGaTUD4fd=vftc4ei~#ak+=FO3r?`ny%< zEO(DNZ+taY?H)Uq%1t2fl}@+4(QBN)S6#MOsa)Q>RGOIX^oDz^-&Y(s1XBt)rFFLF zl;+a?V#HL5B<@x1G|-&H_K{Q=)6*S2pqe^=zFTazQ*=CzwM3lPDOoj+bH?BF;zfWD_J)B;DAMItj z({pS6z%AbZtG$Vw*X@me>Xyok-QGOkqP?k|Si(4@x7uraqwiUm+Cx+|n@b1As+_|;e_PTYpH`+{4KR5QerCdA``cbFb-WWVVZTbZsDJjI}#&p~3b-SHM zE(BK7eK~JTKO2iWQ{j?es009<2As^}uSn?RC>5-8^z9u$pdry0AwcPf)Q%el=$oIf%y6w%T*SUv! z!~j;O=Ja|`;%@XvKVa=iY_F%->Ghr@GTtL^0qpF|J&Emg38&ZVX7Un`{0^+Cw7t1* z)}=4=$k@vdABoo=?LGMV$bgwyM(3@q@-6~LNG z+v}+eFY(CNz?w>@*PXsR;*ouTwQ|^AZx`-ntcbu`J8aK+ZKs>PzPy0E!0Pp#UibRJ zmprl-SiQdOxzk(ck>`Qcrby1~^+VqE$c?~SKb&5-DZR}jzXGdGw%2V6ed&>hfYm13 z>o(b5@5v%rv`1m>rX60lDe;>}y6(2yWP9DF^zZmZv&U|e?aemT1Pe>$HDI;L_PV!@ zm6XbT!0N4?-duNv#HvbV8?buoJYUuZpMAjHMYuRo*jOmx`cjz(te)HHjX7uftLoC- zN@Z~O(p=x|^m@%p_rRUC``9~Y+nZ}%O+0|T^MUrEmhE+mB8OudfYlRbJ!}huvk<&`$H(+f* zwl}W15Qiv}O67fEt!c@e*K1nj;!@cFtToN{dQG#v?pqVM$^J`V^{uvN-x@2GD9H7# zId9y05hmxlQdtD7O(&G|#s-yq3y$D!wb!zA&g&gTctNSm1XgQouUq50uT-W3t2MUQ zt+BmsO=v}_%m-F$Y_D6BTvaLuJYl!S_Ij(4r%Giwu$p6gz1750rPB6AyFIoy+Fb0f zk49cCl{;U<`2XVEc6isTh4L!yQ)_#cd2vl&io*FXUv-)M1m>tR>g@7nY%}XRm@$7% znJl#8yVOP8Vo|YUL6YNe_^#$zXjNIRATH(DBQRdQ*gv$v(@s2RwLE2u_dNIPi1Vy< zIL}&(^Q<*E&+3(`Y(>VKE={?OjuHQvHF9W~e0x}#Ec;tG&-TX5h`;_QU)M4j4T|<6 zU0uV%!*0rtsV@_sieYM6db^DARm6YDQORJLY&*J4Cae5yT1lJLtxVr{P?^kN9V*@F z?J~xxm*8TM?bSGO%iuCx<-#L~vI~b}+tE!o;(cV!@u-vkoAGV?b(M11v1PLJxH4SP zt4CRsL0tY3m%M!Dcg!%m@I+>yZAgsYF2Nf%!b8jCQZU)92=5)Rz0rG$zq-9MaPkzq zxFtIZqirmcv?`&_Xkt>8kB%;rtyXL^wnzBFv1RfnYi{ZD%3zi|>vdHZOLaquRFC|} zBSFTGQ~ZTBiF3>3O<+BRW_zR4RDYMD$+OF3JDgeCX`8sv&!u2`?wn? zKZa&I^O#puapw*y4+HC2!#uC@;B;2(%rcn|th-#C-ZiLL25oO^oZaNF9uiW|bdv zYZ>0zp;v@_uU3ToaxS;g?=pXVZTd#^IJ3|pvYf*k7hmQtKPGk)mJ!G@L!LM9Ho|#K z^`?-U(X|09pTirkU520J87#Ec7~7CSJ%tW$w7wj7{iHD&KZ6;};Pfu@#xcBB3wLRm zH;$Q?OmUx6qq>Kw49DS^N|wv>YWAp`)$S^jr9i)SNzINHv9<+K+}*}I+wwAFC2)FG zAtoZWuuS#<=Z&#>F*6@NjB`hsTm;PR!Td0+e(h{t+`I$A^N$4M&}sfFYJ+!{$vEI` ztLK};8*fbW?^he2TPE$}$ixf|ZAX4n+Tih=o$@Dsip@a9RPA{0jPj>^Rwipy3@vNv z^U5GSuU>U$(`GCa$GFUAvRxI%W0;8A>|Z#-*^BvK%-LppEum_!TnHN4>q&EX<6Dd-$3cOvUO5Tu=0xOqXXRC>9ONp`dE=w2aVMVs_p?fPxw-NbcN8#xNgOTCLuJu~A{clzRG|LUGK zKb{lrw!OerwYkvcZEE9kPwe38(AeHpfN#JDulCAhFr%Yxozt6#L^#x{ZgS(%%@T=L zV~16}syu5xmeLQeP7m`v`nXL?-TRz4&?~NfUfj!%%G5@JTeXyb3w*~BwDfsp)aH!3 zq(xn>a(rN`sdW_h|Kqr~u|U*=5(U;fj%^>sr)h9A+r(Y?1pM}nG77uh zlN#|P!yrD%AHYP_;p56Kzw<#iJXT&DaNS)YcjL|U^LDh8*<0{prS>LVP%O zGCmG_*eu-pix0@|hYPgDt{!^sVR8Bn^UBe{+{HvypV1=ds%$Tn4c+iXczg^f+bPo_ z_ns|GjJn7)1+%)CxE&a(QuCyTL2oRr#ZLJzk7=v$vJyjkucuj|P-r$EvQ_(dG~rb; zjr#GY^r2q)1n90GN4XAfJ}WY^eb(HzLxoX&tLtXmojS>jX9m%&yD^1c_56l<2otwn zwoFs^t|Nxy2OJjQi6dt@w9M&UV~S)9=57fdBPzkfnGT_yo$%+T|vB_0Jo?&;BKovSWz+8u~`<%QB7EBaUX}d(yHgRu+nyHKzEwK+%TUB z)ZJ?GGQ8{ja?DAOp6yO=9xg^PD{}>_3#1y$uMi^(_rWp+!&uPi^&6o|^`|e?8=(dk z%fQtl2QG6-{eo6f#+NL`_xH*hV1}wgZ3%eZTlu=aUb%zyMq38*3aK|Xp|dDzaEt2z zueiZh7Ib>o&G>X5CcNEQ)(1DyXPcWIe)0E0Uje+OmJ7QEt{l41R4PKc(6I(V*I=nF|st(R) zdu8R#c-;pxIJ_|z8IBLn^~!Rviy88~+V`VZES`v;0*!e6Puwe411qn?8^5W_+_!n< zEHK`y8waV_R)1Qne2 zxmOb9x|I%ZTz;*;%NZkzWW=s9;&F`?y!g<3!H#(-*)(3#Nv{lk90w+$9p#L7ul4sB8d;7x1IDQWJ@M711?}*12)tl(8s4okv9p=xU4cCr zD^z)%-cjB-<~sjj2P6%z^jLsd!vgtUZD#f2h#4!c^Y34KF$z2Z>MHeQJG}Apb$QN9o|)g&&l8}%u?K~*(QY}2kVFb#2N`KM3-~AT!_uo26+2^*S0XBok+k%xo?JPkqjI}$_4EMhmhE+z=vwTm%#kC# znj=^1elBRnj4NkgWscpBBd$A8vYJzfpDN0ifhrZlm|A*A8ROF#SnT1Cu-HFF55fZZ z9%IH?K}XCu{sx?#ihu8w-@!%}%J-@et^nJ4jN5PU``c%~LFcd&lU7r2ti1uxP$=^h z2-N6lZRs5abO$i88Xp?TRU)oq@KyK8t#A;Cr?W@mQE{~a<7gxOhFA96=#@2taiUYb zQfPa7DQ&`mAC5@XgNjTK=?vh{h+SCA@pe37j+a=d_;Qfu=vsPbS@Y3<>%BVa>2LfpQD+g8N0!T1 zKzGtOHbYz;)iPe75{yr0;cTB?m^e3iUb)19^%Rf88^6u+PpAzHESDRBt`ggp?Tx87 z;dEg99Bkd^S~aL`2@fYZV_dS4cBlkc`-VKP@-*ONSarF?fIiQQx?0AVFHlu3qX6>Z z(K>VIrQV*G3-TBrv5w_(GH_Oy7h{Eq+H!db=zKVqu)T5RY=7sWv9fac1a$AJR|cnd zT~r_!Vco@RWB=0LEfTz4@O6^!$6;A!T^&#sfpr3-NT^hD-)v!(dV4AQ?lxjdR%pbTiwOux~X~IoJDv=$qnW5HPD?1Ryb^Sj+n9HR@^Ka{0z4& zeW8|*vF%p>;P#R%m)&4pw|e7%xvFPJ;%u;+V{&-od}N5q;&K@P8oKLA$@7k}WfidU<#|WG$fKz5QEZ%6Mh3KZWQ^@Vg}};}=N zqxd%elxX(1a@n)HT&nibiy_aek?rESF;|7W4AxzURZ>-s(+tXg4#F(k(kGl{e3%&g z%q_ubt74qOQXdM9|5+Zw>zFxpoMPqw1}jyiDz>Y@^wocr%SMh!r8~W&j4^Z`UKW9x z?TXcfVvO1RjsV6i7_)k!K0gnRt6JpAPsd@mqfS?+HqxnIaTceS)A+h$*x$X4bjRtZ zt~mWv*wi5^X-uvBjb*d1nyqRh>d+#FQ$>zEuC}eE?I3kR5~mZ?Y~PN)5(j*N);RG7 zGO8XmH!$(aOF@NvXVxwM@PXFta)peGZ};ziw)}y;Dj3q!u0{DdAY{eReB~bk5fwvE z*V5;eLAs+}WAE+Q>cbfGLa?3{IJ|Mh9k`m3=#15rtn50 z>$gl(P=cK*@S@`iyt4x3ittlrbAQtxhu93(rP7@~uZ+2N6$d0zRw0W(hjaD8Z=P3~ zaHQ?)Q6WJvpw4ehz0>dSt;`IN<(OJ}XMug^WBp6lSI7z7DkRiPH#5(xUEwsGkegf} z4fr|y{n?FRJ?=}C86S`< z96MS^KJ$~u^RPLZ?+MZS($onRvI+cY)+0D)ZhL$*NNO7nky=+DG0#b*_1kreLxNeT zR0=FR5S56Zgki!ainf6yihrs3zm1su*_qymD%Bs6(GK@T$r)D`Z?x z_M%N##_(T)JIs1iSD|9Vok3}l37t{Pif}ya9#bL5f;IeI=kUfs3vgjDcv^+TfOmgA z#d%&$VH5i3p%ro%$Q{Qxyngo)9s%oTp3_d5D;auH!NeW_rm1?(dWuay9I;tetPvlD zQh~d{LQX(SuPVtEQvC~ju3~e~r!TAf##P9Xz(wWi@NWaXa+Tl54CX&J~b)Z#)!3JdB(U|ooCc;o!L z{YQ5TUREI!K;!_7u|MA1-gK@68YYV)ZoGZB-+!8KN`*v0Qe`wRX<_wVS1-=E{vzT$ zd=c?BoO`-ee-Y7aMqEO1EMc(AERSFPwl{{}i(w@N`Un%(O>J*ne~h*bxdAl=sKNHer}tn#6SxU$7DzFJ!yB~=(E-P1SIEcUPnAJU*Yd13 z*3zpwa%Hd_({{babNBl9k7k!uNSo!D+JoxF)xI@8K;ad0D`{UK?RTkn2vUN7t|O2B@rSj-I;YrxbB3>D zquNk`Q@my+D4+w%8||0)t543nSAo-Y_zJ1Ypt@TeRj4;Gs@P_bWWjuoslg$-v#h?T zTWjn+&|hw>T;gwxCihmz8({n)dagRXs}5hLXy}3qT-Y>QUIH#{E2WJ?(aoHQZf3Bw z52FV)m-Pvf^j1m+EVJr#c$fOoys1s3Fi;TkcPTRNxzF#3W=krij~j(p!0F8y=GtG( zuc@mM;DrRq(n{G1>JG(3`*1R4S0B7C_aJoD{ml4LWtGxXrKvs=X@WGB-;S$U)5nVS zXJ)Yi^vKk5WLRq)BR9^z-#_}?#7|i7z<1^tar(^Z)%J*=>6zk6`3hJaYo1qm)FH@M zSdc(>Flyv^F{A5J|Ad2lzv56Dtn6&=Hr!)Mr-zd%QDSiLd#0sjfL*~2Sk(h-$1ixoM%@w3X1>02qI z52%#yn8D$Vk_T~NCwWYz^f=be;P5&_Y@bT`1z0sWyw2e6QYkk8D}%#x6y+F2g`FX3 zd*kwlFp=TOmGS|I9HD22!y6x~4Cyl~<@j)=Y-R?BHwG?4D}onSN;9x(aCn^|a7v{- z1gs1WuQMb@R!Ze4JA=dP4DMl-awD*6aCqa)hcOMAg_SaSk=;y(Hy(OeH8Wl*--5)E zY^Lpv_RCR&@4-r00jvxTZ``vSZ*ab`61RHV=`q{u3KG{;O7Ezh!QnZLmtq<(b4;V{ zjovG8Op)4JDPMyD1NAgIym8|S^!$mBDrEzRF@wV!udTq%jNwl)pFoNk9NuWZ62~>N zrBe0qs{ERLnrCBdn${~593zi=9bDSWm!+AB;7I9-dr(M zd#@c)C5Mcxk`VJhIkGAw8y$gab8W(H6#d#ntO+YQxk|=>+(^`U4eU(RjYrmmY&fY( zz5tyk)fht`$MtY4;nXoz@(Q@bnnHD@4pUdU3ip8F`!-g--N>_KY?aKh^8L$5K0^A} zz^bddq6lx~?5JMcowdG~!->Z6%xPGZ;9*SBkB|HJH)nX)RsMs`fw9)W+*SU=%=Ivc z+2i?_k@g*5CH(MjM+1s4ZA^NK?%eK*ood|gjG z$b!FZ*H@d`u8pq4nuWJqS1n(G7cmPDM4o?XO$Ql)45tFMpdNb~o0S^Fkm)}0l)3Qg zKpbwsN8o47(PR0STBPI6)lvyii8&?J1uiMTs%otzRZ+Q*}MV%vQL} zgDaQl9u*f<*rTde48FfwUI9N?tEZaxxI}5q`@RoW%WeGlwg13e!ZXQg`4t?Fgyz+Lf9XW@1HS8h@`gDvB5NKtcCPk!G1r~;&-nf3zyZ(r z%X3v6@MN`|3r3)dvCsIgt*}P=^yX@L9-Mzp4b=GI8GpT5y6jp1CFa15&-#a-tJcK; zderLPZKbAZ96J25QsZhA^}z#`7H@^L9_q7H|9tVSO7D*etyaHE)s2V^`bI=+4LE&o zwX6h>W73Xz4p+rgfe0?3>m`btQK#6Q$M3&Y%Yxsl#lYmMKUW*vgxG)?96|mTGrC_< zjSK}Fm{%_>-Cjb2IM4jy3WX_#IPMxyHX=wN*0eu8~&( z7Na>O)y8eB{bglVt7ezg$ZJ3?v*;Rs=Ujy+bgq#Y@SKaSYK{MDy{w-1cQyx3e%^n& zIq(=FwSg0A*hprVIsAi zw@AD=?c~J|L2p0vXI9E;UDxq7(i5oFLTNikXK&@X@bnrMwsYCoEC#Da!M6DGZR}=7RF9@{K>H%E65(f#81SyaP8IZlKu=(<}nDxejm;80EZ1dwU`J=A= z-LrA)B?y2Z2!jZSfjCHjBuIg@ar!#{6FpM5pf=#U6~#ahgg_WXKn%p24}QgOwC>_w zgnS@*FRB1(kO5gBi;bVw`==l0TY~Z+29h8Hs>nW!_;SR74+KDPxiRPs|DOF*k7E2F1F}FKLp~4yK@b9A5CO5~|7`TX;VMl( zjr<@Bq#5~}n+Lz;@9XkppF>~`0>B3X#tm=#5Ae93hXnx;1fk|v-uB<)GA6#`cY6Zs z5CkC*1`*@hcl={LnO9Ih5Ijih20r7Pcl>8Z*J44x4}Jok>+7W+G=LMqf51#|H)say zz`NkTpm0XLbOi^45#T@I8ZaL`3|;^qf?c5ehI%;^i~^T}1>i~W#tpcJvK<3|gDx}c zWgr*{&H|T%TfluF1wI73LCKBvav&H6P6t>*Fn9*M0X_pigR(jG(i0p8hJg#gwO}D=2Csup!ER7; z3nl~{1kBhAFKo~f_K4AuoqO$#l(Ok zz)4^txD3n&i@_@J3V08E4J3~B3G@boz$suFmZKd#4@Q9V!FAvs z@C;QW~=^gdb0}KEma4xt4+zOU~SHKQXI3E)O`h(%%9B>7=72FTjfKR|~;Jy=i z!2obF2!l((%qafd57vNp!A|fO@EY~l*ikX~4~T)gz$)-A*aqL1p~ooFa_KKmV)NRQLHc+_#Es3 z-UOx+3j6E2_}Op!CY`3SPeFUt>8D%{!z>^a4mH0*aCKdJ;3u=z4QekFd0k-w}AwB9&85Rf}$k$q~KsM983gPf_Y#CNP+jk zk3b&BqAJ6`F5n<=A~*+J1LlLr!3OX-_yrWM!tw*Xz@cC;I2|;BSzsY}47>(D1;2m} zPt;2tI24Qk6TxNR2C(1>EdR$bumNlbzkyCqVs?U~z!-22h=IGnD)2hUfL}nnr?9nv z0bnFJ58MP6gU7)eAOrS*j!$DkKwoe?m;kPP8q0q+2Ihk$APLrj&EOmGD=28jP6TuV z2Z4d$L@*kh1ug=!!QEgLcpH2Kz5+jiy`aPDdf5;32gid`!NuU3DE`d>cY%jM61)OF z06&7lXVBSz!@%)iJeUHm2lK(bU#1GI0Z}w)4(m@F7OC=9&7^N zgTFwBwb)O91HiH16mTh+0p_iZVwPjzRq!Qfm8zF&&>J*>!C(wH2V4TK1#`h7umU^- zUIXue4A=$Qy@+)M90&%2;ovmzA8I1-En=YbnQ94rN^!8-6R$h?Z> zpT&UdHB2E0fFr;NFd57Si@<7-2A_dnLEH7{w7}tD6lelBgNMNz;0Ms*bu0$Z9}EZQ zfob4&kN}T@mtM#6e-8sYLGcC@0R6#M+7r;m0C(u5PIRTCUBftdE z1a1Kjf;He>@GWTj4!Tv)7YqRtz;tj6SPGs4X|Nsa0o9wZn87h%^d>C-i!pE=SO}6} zEqDuj0{#Y`cX9j%jt1kvB_Iaw0!gqAYysbb4x6#Uf?i-C7!A$?SAknV0z3{jf?t96 zJuLs;?_q5P!@yW@K8S*OU@3SCyaT=muJ`Nlj!Z01a0D0$&IVV2Tfic)3cL*72RpzX zQ2qf9X27vvEVu|<2kwmG-!kwl*Z@8Udx3WgS^`TBw-~=!lM9;&&o554yRj>(s2C`r;==3pWDd+?GgW=$8 za1FQxECegSv*2~G1#Ac3fnUI0;Mt0f4fF;FgF#>@7`+wCKa7F%z*KM*m<8?xOTcpQ zBzO_L4L$%FuoLV8e}ckKFp;1N)Pw!OAs`4&0FB@ra5=aEECEk|6!`EHEdT#vpu;vS z9}om#a3#14JPTd}o55G$XHfKMy>tfyz=@y{OaxQG3=jtk!7}h9NP&&ueefCh9{dJc zWia7U{Hp=`fPP>g7y?FuQ^7=VF_;Ff2Xny!a6fnyJOf?m6Q z9-uE60EU6FU;>C%pzyF7N~0P5`691aLmM48*|A zU_N*lJOkE)E#ND#3#fa|I)TohCpZWU1Vh0XaL#r&HX96F17?Hy+nWb}>A$R<>)Gb# ze(--fqWz?%vnP+bbjmps&YsjfFIew#N2h&@dil5RznCeP;_P$Qj_pD$I~`X?zp`U{ zenP%Tjf5Tf2LFtuhJ0Hb`Ii2HnRrQ!xWBW@#tOUPjBAY~zcgd`LL&Zpwe2Q8R2bJm zGj_Eif%Qe*B!I#T93$S1SkaX=GTD)@Rl9Do<^#!J{qF+xPMEyu>RCX}%E42+Lpo+SR6)mLR%Y1X_523H4 zmQu%2&8f$~{#YpL?a9vKez}){)zl5tt<)XVUDP(e=n<7tds2hc5cM4DH0o?>g1Q>2#*go+=nA({ zcT+q3s^c}(eW?AZ!>Hq^lc_Q4oz&&jHPlViZNH*JP=DVsu!mao8%Ip-M;%0Mq+URs zPQ8P=jJk%piMpNo6SZh}RF9}?x7J?NqV{^N9!Y-zbtW}IO;TT_ZlnH6?ee>>w?Ea( zML3auT9gB`smrJvs2@>(ptjnhE9^wAqxPaUP*0+sN1Z~QLw%GQeU$@Ss9#ZcQ47#V zslQUHj~bv3qK>1UM{T0sO7(J%{#~r+>~~tDvWP+fI)REL))dc%%fgIJ&ziq4xsKsbyIz8S$8g5p?-%RU;S;SuA?TYOO=jB zhC3O!jyi=JriQreN7DD>2nSg!DRmMzS4c`J1zbv5-q>TIo1JaeH7x>AOr1iVL5))r)K%1V)GgHS zsDD#STdDf7X!kJ(L=LA8riQ5(P^VL8Qs+^ZQ(vNPqy9?m&{{X7o*JMIQmVSPkqm^X z5$bi+dDNBE6m=6dL;aiDsX&jg7xh?bh}xHPU<$n1wO+%7In;ZpN$Ps)7V1~jU#YFQ zm-SM8)B)5G^&Dy!PQY~OW{w{(bk$SbNF7W)oZ6RKMJ=NKx>s*KUs2zurl^ln@1@S6 zUPK+gH>xW*mVp5E@4t2YJL*>ItJG(ytEfw<3#c=w5o#y4xE1v$HXsw_K$^Oa`ZP5` z4RcoCNxzCc<_pwK)X%9|YMVcGL%LIsrH-LS&*Q)~)HwB2PWfPJKdO&fN-d!N^p_sd z=hV&Am#9xums1yLjmiuLBGglX-u z8W^xLY+?_$oodBLvV)pN?Mt0aT}WL?eStcWx}Ca-dX!S*%klM3xTY9)onG&EjctDJ z^!nO@){U)>H?EynU)lWrg!)@sHD5EaKGe3Pw)Ln<7fl>KY3kGo=S~_c&2OGx|61$j zr5D#X7B%{=s)?yPGkQ|-8AsErnEG>Hr_+7Z1k-gYZV9*UX zvbmwaJS$%;H?%%C zRCK$Q8p;hNazokNQ1A{bUpzOI&JDTeTdCpPP%<~PJ2w=#)5x|M5`r zUrPL2%pPx=CH8N9k2P9fZYac|e@&eB&&0(4D!D$F_&-Z#|5>eF@?R3|ruY_GEePd? z;<+I^-;P|YXpvPSkQ)l;h7!4(J8%pPfcISrvEmpPIDr-;6xc{56_`l?{ zV`-*#uLErx5d&~61Vl(|jN$UYg3~X&q2&)%aqAMt(#!k}d*6!Xq z90)Q!Yya4V`GLy03oU=nFb*l~(tOs=wGP1?E_NuWC(G!>?)YUavJp zjlZsaXoJ?^8(Oo}*hcN+Z!+IoTB8{bB;IC1T5F0Le@A=YCaq~|(jT-BW|{t9t?r++hNu~8@Mj$lD^)+i zvJAL)>4X3^Lyi5yihk9aq^7B{-*h}h4eVxqYML7UUB|Q3^qzuPRIPZ)KUl$^T9bci z4gamx?J6`^#&9dG?$%nRKx>8?Y@>ast=23xR-}En9plt=abeV~IMH4wWT?Il+Q+Ew zj@n14ajLtMjt8kJYL*%*(dj8_h8l9~c)}gk18D}bRJTXRW7H%yP0do>rL2e=F4I0q zb$eM4Rm!!GP_t1E1S@nxn(C|6K1Iz?rHU0&Q`8JqsyPB`oSLNuYIJ&n8qILPSF01k z)C4s{_0{S0AT>!%Q?t}?XPqxbO;FukbUaB7b~Qb=e?1@ppU&X+YfVsN^^AAZ8lZ-# zNotxJ?5^|0sY$B42g_5Frj8Q4#z`m0zFK2ccTerZ)U@UI)A2M_dTAe_#*GQ7`mWJL zZyioi1AVj)QRCD!)xEz?4^orVG}YIa>C`wiMfDw^)8ksBc#nk+xC2@P)EG5Gl>>Ep zf*R_leTtf)h7Z#5I5kTRH84Nbcd+v4*n;K&W-v8LO;de`=z>9Nn3|$ysDVRuz6do= zb@ykSnxwi9LtJ&N0W|;(QB%|mHF&sA4^uN#IYP(d)Ff2~=y-sdpk}G=BXxQVI!TQ< z#en-Loe-kNs99=YAk(QyYTAkib$W!Fp^9wBreVXTmvqGqUp;jECFrN&Ou@gy}(4WF#zDXKf9eNd@d)shUz2%X@g zMyPSBjMV8NYJ{4m$|$B&Bh(Z%Lk%|Sd|_zRT-6xJP=lj&hB!4zl`%T*qb8_u4^Ts=M|B{= zfSjSdj~b+=s99?4Or0-H4TZIjQOPkvrpBpRs(UiiscEYFKROe%8M#0w1~1eaqb8{Ci*!6hjZov%B-MAZ&KIG^sY$9YqSM3FnAWId7?4YJ1|Ky@ zOLUe^_ds1d4c(D67mL-iR;p22Z#fG4d2Z|ZDm zs_!lBlhp9r+WXR46I6Le`_Lw>@-FjH_yX8eG zso!-xu!rf?@E7adxnxtl}ct_@^MmlNlD=`&M59$G2 z_SOjjkJezR)(q8GrhS?k@M<5Trm2B)9ZyhW71~ECwFat~ZYnkzU$qV-sqPx>!_*ix zMU`5e9;C*oDXP@5Jk{M<`xG_YMf}Q;sr3UJCJVZ@XBi(d7 zOHFrYz8(UAs2OVDD8$wH6KVkJ9;h`! zm7w+ss_$s+(^U5$?PJum<&V+v@UdF6)YNg>2L@|RK+Oa5ECZ3_bwY|79HM=aDko?k zqXtgYK0|d6Wja-c(Nkr(_F-yjIL{9FPSOc-veq~?Lyd%VJWUObpr`sqvK-Ynik>Qs z+Q+Ew(b|VckJSTd27+U>k5IGJn3azj9H;ZescCA6r#BLYXB{>!-)S5VH9>Wc*YN~3 zWBJpW{|v2xGqp-sYlND%`~)3OQ?pd}S!O(nm)Nm_v$ck(acY|Cp2&1+lA5IkC+YMU zHAR(kbUa9nQB$U3UWf>8Zhp_6ch26754%3S;GJtCp$EKn)lNK8;l) za;Xl-scCB9G96FP5QWKWviGq}=M#bv-(rAR| z1hUl7W4i7nHIURkLiIh)bZTIg_F-z^3GGuL*Oan&^9$1*i!sUZoXNn{bGlp!(M6c$k`|2A|jQ z6gBpO_Oe!MoGK}Lr5L{iUetjUHSm)5?w1*-3V&(`sc~wCDzE7LA!?QyewFpT#`>tS z^*k%$dtE1_slE-`C#mv=_6cf;zrDl!&7Gyj`J3DKw$7iS#?tiE&^z?+@T^E;lMV#m z)taRyHftYvPivCudtduFHTZ${zAaiaRNsf%2R_mop@u%zKKAheEWki`tM(~smYV#8 z1&kLTLiZicXq%vhKhr)-l`phUTe@BQ$d_6J{N)^@2EW#EH-9O|sJ?G>JWEaNG(Ao} ze5(^8)F6K=r>JiJW=>Fp{Ouf}27lD$Q&h=nAE(Ctt9_Ol_=)*VHO8z#&k^6HWAZEW zQWL*vpP@!}Yw!DAYl0fyqrLkNt#NATPkL(jFYPnb7buYkYEtNI48tEe-maix{WkYHdXbv0Do9^O4VY@03`qBc^;QO8rm)QQx|)C;H) zY7=!D^(tzNI)ge(YgFbi5U1WjT|iw(O;DFomr++zlhmGv=>|PXznZ#+nxd{V6$@uQ z0~@Jn>SpQ|YKFRlx{JD-Dxc~R7f_3+9jI=qms+J%b?bEu_^92fJ*j=D0qOv1ka{e2 z2z3}WL~W#wqmHMBq2>>}i407pMyN6B9O@m^h18|gmDDGxtEua#8>ySATdA2(YxT+Q z9SrQI7G?CTtfKa$_NNY^j-yVdPNUAEE}$->uBNW1ZplRTh;}frn_BRhj=QOKR3EiF zwI{U?H9&2k_NNY@2C2tVheSCLqK>16sgtP@>NIMMI*U4odIxnObtyGTO;J^^q5h21 z!(H9cG@}{nZfeozTn^Np)c({V)N$0w)M?aN)CJUK)Ya7WTBCSp0G9)GH?`;sP5`w# zwGXv{I)G|zt3&7;spF_&YJ@t?RO9C+->K0UV{vMNx|*7%W~f=JZ0EW{^-%-VAaxvd zGIbhtme!~&U|<<_HFZ683v~x|H?`Nx6T>NM&sQ!f%(z`!zUikhZo zsJp4|uk?s}Qu|YfP{Y&+HAam?%?FSMEMsIfbv<9vq$#=1ly1wh_ z(Vh%9PzO+lP{&axQ>Rg9Q5R5?)D$&M-9g<&l^tBCb8l(=PhNxj`gc_sH zqQN4tT>U!!HQ#;|67z|{g=8S31Y^uMyO~2iY%Qu{2s*f6=2C1QMjL$!;{~;PY zrLFm!Mo!i0rpCrWAC1)Z}#S_a$U#mS2(InBY&YYtzW5UnXl~Ji|ZCa}x!E1DTLR72Wsq1t+%y=qF zA7lHk)f%J5Ilp`?7rLJ5`40?Y23ym^IhbO`3{__6f&prT8lRb8VUj*{qmHMj)`TQx z>A2;!8l5_HYahLdqo7*LQW`j`7|6`i`Q&!3K5B>>wtUNZcZbfOWV+B>lhP`2hq2+4 z`a_~aT8uD!uPzv)Ca6hjhH5RWP(tSqF3}pH7kX=iz7{^S$jl#=024y@am4vcOa8AW zFwAmss_%YXk2QhT+7w!<<4LCL3G0Zpog)mMU10S7q`ph^|71b}2j?%E&;z={2sQqH zu=YN1R*w1q|1~pbh>ANUVd6}Mma;cOGI5Z9nc9PpO!h_y#X%A#_d#eW4qDSv_E;el z2cgxJ8|`W{aof!b#X-ATCJqLn_&(qF^}ee)pU>y<`TZW>Z;!{T=j(dk*Pr+G=f2OG zGt;EZD+6VmNbV6$>``r}D^<{VoJTJbiSCa$5Nd@jEA_(i4|{d5@FyM8J|kz5?b%hP zm04vej$d!<3$ zWhstpf`y{3?|ot!YB~H!%6tJ4FOm1Lt&mfO%91kpm%Uz|V18ix1oKrLqNNX%MWvIl z@uV`^(<7MX<_@>96*5}Et+wSj!SdrDRCj24e@(BwE*g7S`wR*@+J>RBq)a+C?keL` z6(^AGVy_qUy3ul+K&I*GPkQarR9w?5>6^pbkD2MN$tnxVqB6CMy~b+ zXU-3XujSt$Oe)JGJJ|M@R|d+G(i~y0m*(54AZtkeCpy2n_HG(c&x2g zQaYMwO8NgU!L4req-U6qS86RCf+VV`K03iatZ&}1Xmr|K0$M@ zCIX{RDpDFqE3<>CuA9%|Xsa-3jLR?az1gVyxg!4DSNc3UMD%5ltiHsGFPnLXDsJkK(DzGdbDjbCV47;9O&$TD?_Wp12hdc37`sbxv& zWNbNgd5ygt(^uGlcco=^f@S_H%V45q@oGzRjb-v$%hYw2UZZ7hvSs0V%h0zhW-T)} zSmti5(SP%KlMMt@EW?{Ei?>*oZnZSOvvh8=Ox|vpnr7)ux6IsOnY~lXIm_H#mifCa zgL^cyV1^A8e{X4;lrxoouypRTOx~}YrPpU``2kD!kCv&tW%@zO%%3c?4_W5?Io1>& zwhSJzEIz97xt88zmf6QGb5H2?dCK{g!IPHZQyrHJ087mYEMNb4AO-N0#BomS(M``!CD%zhQL$e`*7{b(Z=6SQb9B3_iCETP=(0 zElXcm=D)Pel`OMgY58l*;2XkiEho3-e<_y_R@@FYklM~Ny}hN^(K6G?GS}HMzk_9A zN6XN$EOoJTx>~y3EK@sMCcA5S7fY{)Z%uYr%lvMZh21TSHI~jEmhPUG>7-?*)-u;i z%e^hVK9;GyEKADb-nMM|TDtzPtnv1>Oz)@cr|fT8P&)hDaz+^{-Cx^yPMLCTIdy=g zcc5kVAgwpR($61kO>l_vP|M;#OEbtadAMb&&e9ufnLWbNInuJA%%!w^lx29dW$748 z=h%q69Y4+nQpa1SPq56KXqg?V<&!LP^_GQUmcek#@HdvFw52)4(mB=A9buU|&C)wv z$o-c+!v=CAwZfT}C8asbmYoL6qOvqv@x;sdFv8^OR#OGv{08FMx9Y2N&8v zX{@Dlv1RHKOK+TIcD!Z&Qp?~n%P?bEy4=!SY3WR`OkQQ_PP9y2ZRt(wnH?*)U+NmI zc&(*#ou%7onVM|rU9Z=Dy`Hs9-(Z=!(K2_FmZw-|Z|zlf78 z)+skA&8;@xLD@;^D0?XTDhDc0P>xVGD90$rDJNO_{0C)rAaaQQ%+&HMWnMW)IagUw zE>s4}P+3%#lxC_{@Ddh>u5y}ST809$SgsCqK{kGS&6`i(! z`ZtN4Um2gM?KN=QrtrI7J$Cq{M|H=4p>1}p?l^MSrtiMvv%=BO|0Z!Z8iOuE<5ic! z%h1)xM|YvS(Y@$5^y;B=(7EUWbRimxE<)qcrRWMY1N|P&M1Mf{q5DzQ^6`mY)i*WW z^L?+Y>JB_GU)|Nca|iEA`?})SHH&+Sb3yEUvn$ka#OMY{e4u7z>Q$KB+vq|pk>vtubo3@K?t@w+v z_`4KojmIAu#b30=%;@#JvZypuY=7R(mPMs^iD(Kzun?#JVC{+;~9;2D2r!p+&7)dF66X-%PD*@geIB$`kh-@GImPwT*8+)ovTKk)=s;-d*@JfrnjMRA{{(hKnnR+lx% zX@g=}TxVd`mc`>lH}9$TAICROK;rVkoYnzKaYu3t`4i8e4Ij-w;~A~Lp)4LxU}IT4 zr}gEuZ{3efAbMk-D7z46x_JgVa2($}1C5&(>}{7;ddi|QSg7}{()`($c`mr^9vsQ| zg3?nuOKb!8rS0s;Ny$Kacup^9IezlQKkDW@Z?6aE+V2mAS}rLaecbDF!2ECZQ?|Yz zKRAs0u^k|<^oly5mXn{@a$1>H260(GQY>jXxmN2di^}+8D$AxL*7VxG$?4R4JO5v{ zeo~qH$d==Uc;>V{hF$j6n_Z^9Zn|{gDVK$jzO?;xc*MSPYyGAR zcj&!q!t1tuw&`SV&zixRXY5Nspl8^9!Iq~~+XV`mZ8;^6Z2pA%ZXX@h=+_lCUA}tH zu1%#KdOLn;t*!U;j<#O5?;cUThjy~%`0qlSt@n|}-NS9YU$h)gE5EIcznioz-Ql); zURPVzr=H256U7fP6Lf^+xwc}9mP=ah6Zd?*ok02`>TQ`oefD`9Uw4&lug#4!(U#rs z^!hbg?$I%t;M`LC`peeu5xwWG^8>w-`pVYGDbruKFFW6~FBi(n+3(t4cYbJJ&i~ZD z?EV~;eUlq)Q=Gc}o>8i9m1RnqR(i^eGOL{Xs69G)JwlVTyh>S^Yp<_5%yOB=2R^@+n=NC(Z1}Pz8V;)JVEIxGs;tMvA;KZs+Q*}3(7#btgO6B%W?bc<96Zfdhi;U ztlcqMD6f}g{CLS|Ij4-@ITo}Wment5In~?t6V_O!ueQ(sm|jmCUnPmiYj9QrafO)i z^UvACHi*l)q%E5#>`bN%wo4q}Y`L=XEG@^k@7%4*GQP?FWPjvp8@ncEfmYBr4<_l` zrH{+adOdy#URqWTwXBabv#PATPRooJjc@wu0C55(t+1^ow4tnQj<7S9_r~(4Ls_|p zmbbH)O|q=qPs`iu_-4T7fNhb|a!2jpgtF`2{`Ob-WZmZ<+rrTpz-f}J>e$Xk@?4t_JfaZ1?j?w*8d|R(n7H?`Av~%yh{b02d zT}kxl-d$AE0~M?(i|eww|7stP&tK-#vbdgua9#WOH*x=;M{(c81An6fq`uv{!Rg(N zc9gH^vQ?s|Z%MSWEUx_&w`m`b6D{npb=*I_dzB90I9p#hy?dOg*{Lk91B5kO#gm6@ zPSok!J|3@V@>gYX=||35(rtes&NO>qSvkJzwW(_ z$4i=NY+pZ4G4R0=s>q=zq+&aGHkZ!q~B+)I0G(Ee0 z{W#I2|Ht+h;!KM(%Hq1Dse9YU<3vl3l*KjC{L@>-w>qS<_ww50OO^>P#7mlNZr>oz zwD?l{c$}zNUKZCx3$M42$B7nJw2S-Q&0(#$9A>&JSv7fh#fLPTZ6A+U)a|&FeQ;_0IMJXhaXEjo z{L)dJ>E=gi9M>h?{3z9UoM@_N`vEqu=)POWw;a;VPg44c_J4DxhqP}HXIeO-eLPNd z^P@CM=)ZZAYCKLfe`5Q7NYvhc#nZOBK%;m`H{VXu5sDLa&S_siPBeXS`*@saZbDgH zS2Q!xZ+{`qG;?iPT=%|s>(=p!n-dM6*lO>$I;6op?d!*hn%NrnqnS!_5AJWg-$KyovrLwptTKI9Rxa@zNY52=l7bLEk<`VJYV$X=jOPbuS zEUp6-yKf!ea!6CX+Q%i)=>E&}F1w%|nf=-+>+4~RukR)a-a0=g*el~ujW>s59^GYxyUk8e(Nud=u%nsc{~Z#kq}p81mKmP48u zw3EL7PwEBjD058vj^ZVCPbiCPqQUU?@i@^ST^5h~KWlSb-v1x6dGEJ8p-5<}Q(8EG za|0WXJG!iWJWez}sVuIEnr!>{H}UnhkccA7uN^Q}#>!+{>0TlrxoihkGq&u#}&A-z$bf4b; z-YMSZ_+)ozZ92Md@8R`hKd`BctVl-dhc#!xzVnMa7w?P?Sm)~CyeIz|7 ze8;xTD+|iZDjQF|t0TN;nO0sk^Mygb>iv90b+DWvnjXye>e`h5bC3^gY z9~zMFy!?N0{OC@z|F&rho&M=3)19}AO%w)F5I&5C;Dx*L&Eb)F;lpTx z#NpgsjhTio!0&fAW)4Py_r;)U;^rT8Ko+mkm#44i>~LksZ2Blj?-+3{;5b1a3B z3m&|R{u1~cJgOHB=qL?uM^lIk_wFtKUa2Qqh3VwxVNkV-{7FqAzcHVqmDDf6V-Mix zzII|@xDjQ$GW!FK*#Wu4g}}yl~$`*&4iXESiHCUW69lGw?yQ6#w9%yj^;OLJI|9m&2Gn zUN{mN1`|Gly5WU?M}6_a-3Ku<@D4l> zt))-lE2xAQu0S1js^z!KV~#$K8Ph=c5*mpYE<@w+Aw1}Kn{^7VI>8<~bD}XPqG)+x z26@~C!V`yb3*v=C(NwuRpmUNvq{1goV*lmD7ATxuZ@mYrhckoj%mDhx;Dv|$hRNfF zC!&7%G`t1PWB}n4XbxU@{K*_-yznfv8t=h*NbaD5k2&@fodKMJ61&t!oP&4p!pc)Q zbahQvYQN8#PYz^}8!nJ4|URZw`6T=J7L^JRK{5SID(241Lx-pZOjqnwe!#igf za{!XPPs97rT;c`zn#P5nqY=b~)gw7K(iR?x3iuSf6D`CGv!l4<@X$B+QdmnN4>uuM z7Vj)FYv4diC3xOw9z;Tf{0Yg)Hy7~ojRp`e!tE}! zPdDKdlp-#C5sj3#uzsvf$WLRgLjxE<_!O$c3s;~tUbqsC!585z7wf9P>PxJ5;3Bk; zIsx2>WGl@$4)1uo1rF?wBxx6}y_Eg$K}MxZd5m7B2Ms=|z5oYi?7g0X4fNL)2 z(C$V;@P#X_58y2mY@Hmu@haZb(7$m1t9eDm3on{PpR~W?mQ|)c(K>uF;l2@cW zG`HEt!WuM=^{pTmx8|_>D0{TH3Eqb;MWgm{Euuw-ue{W^FiyA@M9zgyaeC; zlZ}V)&WBifxsZFvm|f=RIe-tTFTg_|w(%6a9JR3Q!n+7r6iXFSL8?!bM27BY>m+Y?sJ`Z7ACN7rEt-_#8ZSkq!obM9~AM znMW{^I(g_V);ch`L_NIwCGkA}^O(N}_CgVMe#Jga9C$vGjxz8;^#!;|y?ND`dr&kO zJZP!)DLC#g+7{0GtJZ<5ki38iyZEp1hGHKM3p@$+#S5pR6kb?TFT7wG_dRjp95fCu z-0g3+zObKq7aqEtTb4S)8&DoE{O(Q89o`pn+dFIl1>xPOh!@U9C42#HT&2tVt}!1V zd1e%0hxhE3IWUEST245egI3~&)$j8d#yfCdRJSK@&*8H7+5a>JjQM0WFEDsv8=8a{ zp8f%=f%o7O- zWGYMn9~gdI;hu^Lvz7+JrpgMl5ifidIh=zK9#mBky`4(I8`bCFGl`1mZFm4rtgeWj z|7n=pwt~-SSP3|_Lq#;PJiNSPg(-19vankxsqfdCB&N7Sg-I~5a8kDlGlJ~0a5);n zAqwFRJKF&qI9z=ijzRSdCX`>E@8N}iMHBGCf1;^);es9&W+py>NBTW0Of!3y+@r!w zM6!Rv577*~@GCSAZ}zM(y-^EZxB#uh3m2kw_yDGp6{dy(gioWsc;P3g4qt+UYuSQ5 zc>arV`p_u_VLw#FyKput;f34n#R~1oUc#QJ2R;e!`W5XNI1m4@Z-tq|YUSarZiQ*X z=im=0dTBm@RYA?NqHxoJ?0?_AYQ-4$;0lw%3y(%4@WM12gBQ+26G%w-?co(>8eZ6; zuEON;4lE%#$ijyQS43}63$V`-jKNE}3-42(Kf>oA97#s<9u2;TH7C0_VGT89_@j1mkc>~F2vC7gF6_2uOo4jane_o3iO4hCz}*1Pad6uqN``=896z^5uMeEk$o zJKGV$Kb&go=V9%L$n)=}F;63D9KfSavz5{?uU=Stx()`PMp1qECYnW}!d5g7FC245 z1s}a~Tf*O?m3ZNCBYEE7({Ra1pJibg0}89qGQ4omnH46)3lB$Y@hSKSlBF)d#iKaw zY)t_BoW-Hzt+xwvNa_fepy&-POf=Y}9XLY0=VM+$@?}&A4;*cM3cih`qawWGZ0oad zr{7wigwLoC;3=Msd+<~BC3xmJ_F#JOMHD3j?>v|NpUMHrVGcQuy~n5E7f4QZ37$8` zW}Sg+k$g>P&aW_gAn7Ox??JL1dALO50eoM55&nSWU^*A@%s?`+`~}?q?`ok4&$-ZE z$iT1Eo3RyUUnI9y3O1pEEW5D7MLeGI!t0QS&%%dMGk2D-h+6Q%{ufimyYN&rpoh;r zin$flGh^XDPy=503ChSyzyX)o8GCTfID5hi@Es&=g}uiU#|sZaGw>;RJ(5qtvJ$(j z!pz;fHsS`K!a@og;L8~@#S7m;Yw^N^FXsV*PrN7aFMQ5tFud^Csk{>6)3D?3*#GDt{I0^hbh|zI0bGY9p%Uyd zjqG>5MD8ZJ7xdch*#oE zK7}l17LvEd!aaV^UNRfuo+yP+!a5{xv4t-pLtMBB^^n=a&i8WA_Nqq7%xj-dz9|v$2%W?n*5Du7aA1o<&0h+KcFHUge1KbG*@~s(o zC2GVAr>hsffpWw{__sge=`(~AA7sn$S@_U{?0F)_Fj$tz^h$JD)`&wTg` zN|BveSYdkonVI5UI0MQ1`8@m#ldZMGSO@UKg3LLsbviM=EVVaJzQ6})g4RKzD?R=h($a1oN{L;#y!VULLm z4}X>O#C8aWqgH(SRqp@oUgOYFaNwONdJ_TrEoT{tyKqDcd%qut2)^+KZ%ptZoEuh{ zG)r25r@qA@-HAGI_rKc-B;lQCom(4m)jPZlleF+#)Z+l3rCvp4G=r58{`4WY5MJ1$ z$TfTtzAv7c6=B^+y!db!g>Qe%TQR(_4GqMbPb$pGXaUIyUqj3A!qupV7k2a4a@r|$ zgGnS8gtwxxc;O?c5ifiL2p+Ia zrRhuk6ufBL%IGWT419LSN;83Y0PDI}8khPhczKUXGZvqPA0YXDQn80$Y3A=rM=VzX zp1oUTw8tL2eD})eJKI^c@DVfsUx05QSqW2HX?h{) z$Awp*W%B*sEaoXBAB_u->s4u5*h}F#sEE(NSCPD0hOnZy?bLw>ppgtFdq~?ZYG(*nxFO5=ucorv+iN`T%~b-t1Lrx}p+E2zN&t@xuQghXI6>_GT6F!fQ|+ zJ_~O{^4J#s31#uZNA{^SGxp{AFJ>{C#|7bbeMtoGzzg@SG#fYv8TciV*_YrU`&F7g zJR5{-k&71|*sszI!3)Q#&%o#RuQaPkD1cA@y3&5_0DpB5`#*;Z?m?Ai{2^q`b2|h3 z9L9D?9D0XWnj~@IbR_$igHNh2z%F(63?<=pNDfyP9(V-jfLk;L&qlKBA-wF!%IN1o zGCt-tBr{8!jdE>PyfaY2yKW=uErR1(+J8_2J8r=lLIE>dw*&a3-4Dof$V&nhv9_ zcVO^a9x@zEVOLN08(yhC3tN#aZwWS>W4#A|MlvyTZl!quiO<6${PT2R_<{N&ync+0 zXW<^_Tc3oB)H@e&&m&3HgY%Je8p1D7^zIoBywKK3!LyOXJ$RjZKa1Ijq_H!$(%glj z?BKiVi}0L_Y&-+MQg1Gf8yVKZ{^0etKh`>-m&F1JSg_$G-NjO3>sgs)9yHiz(5 z3BHK}dFjHzMgrxXUk3x6`@z@xtC{9^Qr5A=!>BybCoG7e0cP;)PXraOm*DJy8iSOd>;a!qZT+t?*tX ztCjaL&Yg%#!v3faUU(%Mh!;*p^?2a}r~zMqA0zo-!O3wjkqnTAHzJAW;36c01@KpQ z**Y#f7x^I_iTMew#tXaO%?$8Kcs`O&GjJvvcxY|J>U&sTys$GGiBG~WkR0R^+;xT> zSeQnJI>IwhH$3!B1BJd6JU9o*UtE;DskQu}XO1HE01o z3*SL&kKp4OIDRItoOt1g`?y1ng#=UGa;@D4Oq>cE+35?;6j&AtC=NUxYrso#S4FpvUs73a(Lk# zD0&fs$q%d-UZ6e$??FY*gz(i5NeKVyhdz%;3LWSugky?y$`T2;`H20-3ol0t@WPwX zGJFocjG`AUc>TwANwaYHCpL*RtY6CtQD68j8i^OKUq^kPf*A83W`+;pVV~PuC&i) z9#v+wY#Ds7rpg3I@czGu>9r>Va9_Ic!XyLt~7n7>s*53!ms;6}`$8 z;5GYK*{=iPqbS8Jh0pxD%GBe9uObg0!lzvZtKm+8A0v67mEhn5m_1u5{QkfyQ^J4m zV>%sF#dok+BKQhwNxs3ZZ$541i5m!l+; z6xJP9Wd`7dV~}4@A%l4aHQ_q_{0L93}#f`^@C`$@r_>$wYfUzvmpPz!Ye_#qmH7hdBJ<5W|) z2Ht^kc;N$R4!$(J${hV0+i4p95y{dOVDFQw?0ZIdI+EFY@KY3h5dybA#jb<{Pe#$J zEBs8oZ%*aVA-NF3Z`GR-Rc1Jf9;@*7)9hgBGpfuLNM@gfe^Ot7zdh3q?7Bm-yR1r4kOw^Ihbie%s-tR8K>0}nmh zCYORG6rBUO?Qg9Y7Ep?Tg>Rsd`0%$r4JgP*Bf=4$ZQ#Mx>WlEFb4h{*<~;8CF}6+` zKA=7ik2v2Zor2dRNg@ZIMbdu&hhJcy4Z?ZI^^d8I%yV)9A3*0q-7`2A$x3A4^=Jfj zgukE$yzs8EtQ=n0{UXi~UbqX&yaCBu zY~jnOzzl@78CC)>OrauPcmis}3tLc!A+-^!ui!z17xqE@@WMI~Ug%%J{?}9RDP)m{ z7yce)@OfBwrF~sU!H3XXo&g2eZ$g!siFe`Es12Wmi;!$t0IRRE6Dz=;6Ky;R#~^u) z$oiPIC_1rlm#gg-22!eefrW4v&m zn|O^lmM_8J?WhJXd;HR6STxs^kGtX~_M6%-b5LAVJm#ha;BW_Ki8JxquwuK`cJnPTsR-ej0&qpxtlbeQ4PUwGsb_FXEj)Rhg5} zIJ|HLD&d8HM~M?z_Bq^sNWK&oRy@q!Q%ATBTIfqhn4U-~2|q*iG!}k|#^JM%@L)kQ znDE3$Sry{K;b;LqHMh!~kED+96VymtxDMs;CAbO654{NeuO6#1-MAq94%Ok!<5i|J zk`Ii8KcNmo*&1k`;Nanfol#T={(>eE7bfOanOS%T_C(RdV8wi%8N`L#pq8OL|J^59 zBD9o&h37v-5>ygijK<%xu;IQhhd4r;>-e}$xua6L+JhJ;_E8hrja?j|Hl zEqwiXZcEwtFsmeTtq$6SPfFy_u`=SB(O*+gTeeOLUWO#0 z47}6-I|oOW9bWS;rQ8tc;2n4sl7WRSs1t34iM705;2r3$W&fokj5+;Zd=W`w;RDFU=VA4~ZAZce{5jkp^=kI%x>f1p0zgI^;# zq~=HNte;4fxC8ys{3V@w@NY;e72(fFK1vtXY~=1BYhf?s(Ab4@k+dzquA5jz-nI)5 zKtre_{2dyJ&%wVUxkZccjGvjb{QKV`=CEJ%_JD_0Cd^nGq~JeLbgx6FDiOWS5xB@U$)o(}zBVm!kprEbQMcVRF=Q z;T^j$F23ORNSK{=O_(Ax5I&1ac;Q>fp;A$}8~@kgj_euyMty4cggF(BWdLC_nuHfF zMmc-{d)6ePSG*+rVNX_+xJf3=JIJ4L3Ikwn>zy!-_#7PECt>E{g^hb9%tE|yCR&Ym z_D-0peMs8D!*BXB8{+0y3A5LJ3Db&q;j2jMgfQQa6=Gmv?_b-o++QbrbFP~(9t|>Z z?g1=2z5wq(Fkw32g=Rp))Zm5Pk&92lZ%|6&2Pe!iC~+!pN}-P&ym0?R*bcl44?2`H zgipcbKuON0Bh1pnm>JoHaOfarunT(z10>5XytOW2rqWor`(TzAFICwz zxH&#yUPATw5Oz3$bFddb6$_6zk<}$GyaY|a3-3_xi^*$2IAmxddIqH7HYeHS9C#d( zl}N*Dk$j?&g^#N*z;BV%G4%;E3yIIe^M`R4@T!=BOOVVyfD?wZ|5C^fPnZjSqm|%% zB=G_~Ep5FAZ$|PNk?`P?6Q(aKAv_$_;ZyKzBm;YJ4vGeYt2JJP+nr*^a!&DiFi?<6 z9^CQNglV872lhwOkqe(f^2JF3eu1QZ38qF^FPw;^eip7f%|5tFut)i8q33n_y59uF4Ap+Ly_D;Lw(F-G>`_u>rp*E3lF{69-=IK3CRaW z!j6~lbfb>&64VEufeVo&5x}d)aTZReA2@crJzE+0M-(LrSD@(k|Ad(BF0~gNc)a>F z9IakB3l$km_$X?_7huQBba~;ID8azOuQMcy7mm7uN#Z^DFp{%UxPtrtEeeuR5&o1i%ZLkqM62=UYF>np)Da$nT8Rq>BXb6`ggGQX`6m45HLL`2 z;U}mcz69^~ueJM{hqaS!)-K%ndK*u|Q&9ACKF~)pvn*VSk~_%U&HF(lb&}8@%3m@-8jjZs8F;(;9Bf8XCxC6J=1e-ehX)ms zB+_s?TFVyX;1fs&D8Lo!Ls&Dz)=$C)L~_3IFpnddK>@bf3#J4I{ock?uo1~@vTz=f zgbJ`#<0V*guZ<^R1Csh4yiMad_@ep%ZoHTMmrACIdlE^fE*ys>o`JJ8o`)^!L%31B znMqp|wS|pHCXqjCt6qz61x|N5?F63Z8{zNj*3X$zVCS z8bx0r!A|$vxC86dr{KlvGjKYResXX=ihln?0rMV`PK&V9EbR!^BUyHC($<9|qBzfg4>MUWWZ?oNCp>^_G+u;lNFFSFMQOUB=&1)s zAgS-cDJYs5d=bfH0=Ndrz(u%8y?KyZ(dRF@kc5Y;Pr=dZJva|VKcEg%ji%T{ujA8qPw|*@BBS9>6u~{UWB*L%QE^KNKwy9Hu@ECm@+w7S7gq9xl~*2tU_& z3HF&|SH*?Hko1{`m#ELcIdj;5S-Jv+l}H9C!kUNm5Wyix;%PWd<2l%(K7{L$3{Zmm zK4ROt@M85DI0H#PdAL-4_=wMaOhNX^JWAF`D!FikdJj%RQYQx&Xgq+e8ZW_ab8Xus ztVdEm4W}TPWDYJ>9||9%EWiIJi5ZM!1}QjNy$2_&&%)X2^RNZU03lqj@e=I(xb4S* z{nfj02$BPvhT}D!f&LV|kb})gIt}1TjTd2?dh-M)7D=K>I9PoOj#lr%Sx63P9C*O+mJlPaxOcZQ=2lhwO zj|+#XPs8!*Gd^Y>iZX&L^g;+XBFWl3%?A!BT6Q=N$x3A46eP*z;1fvd6kscg5`z7n z(TTxPNc!~PEaXe2Jf;=NgQ5gGKWjU3V1M;4Y(!Eg3ukLQ4;QHq;2QNsxJkWPKoUp> zc432hZvprJWD1gX7PcUnSqRr_yaYQwrwPG&BuS^?B^uAb+tugb6Y2}F6-6rnJ3g=d z!2Xfv`R`&*(hF%gUVR46K+!`3F4lMe*J`{3JHMcv!u`~{aG3fuoPeaCES#k))v$T+h ztJN1_&5O2D5)MH!gESnEB%utPq47Lisy>7pQFM40@l-|8Qxy(F(PZF+MeKjHEEHzz zg*;q}Bp$+=W_u=*a1@fPJvbRf=LWVQIhY~rwAj{hU>%YqQm|3uSvVU>+x%kg{{6g6da-6gA>$e;fqMx25=3M0gA8B zGZjguIk*_fH<|*t5=rACY*TLnPA`%=E*yfSP8yC;pMg`<=U@wxfkU`f<0a@PUbc-L z*hjq!#~^vt%D^ca&%qawBpSdrBz4Ry99SfA7d9ffjk9o`#tRZdl4uCmTJM_@Ch@8! z0UMC)r3WWyJPT*2&%*`k1Nc6QmKwHc+$?4LkPMcDgOSup!O`kHIBlt~%TD1%6wM5- zMA5RtHudH&y!s*OC<*J4)K9}k^;!5F8p~Hg0c_QH33mIdJ=95fCaR~7=VPYmg&b@_ z(LTWrui1_qcsP>%PQkN~B;moCNCwNp#TpOb=Sb?8V8>;)z5`D{Qa=qFQS|S>vY2KR zonE*BNhR|)vPRJ|!XYSn2EZ{I&%oP}B$R_oQHHi5Y(rAtENA6Vv~q9=iuzg3{Xdn0 z43>jWAgNSCBK76@ zj~Rlbqcm(p(jW_ey@E2Gy08IB+=I8N&%wVS890RNQ8WOodBfIE!g}>-I2FkX<=}ju zzoHq#)kp>?!kyo=ohD%elCAOJ1M2f|6_SpMuqL#1lCU00KWW&gJ_~0f87mJLtM>!U z8Z8vzCiUhmIzrJ~E;tQI5;?dU$t_xhHGkKE;ZPI}3}+*$lZP!D58+1j<{xb3KiGfC zC`n-eiuMwYL()+OPDfHF2j{CVz!mC4___KL?6=Y;*Ydi2&x}!YZr}tYw{aHEQD1=XAy$R`$NYq3 z0JAz_PDaw$gV&*GHt8J!d{#%z6?x)^`4M_U&;AD+w;q1u!%owu( zMKgxme`-5*U>%CGhK)!P&BFVUB$S7rp(qL1ah)as>ygw?!$u_iWZ`TSwS}Mg{1r8Z zyZy&jO2P&tjXgLSNrNn$hoqwdY(-M11p9qvy$c(W^qGY-kW4HOTadI3;pa&D^h=n| zpKI2z9z|Kh@fy#-Sx6e^VJn)#3r`6SYPAP51sjpH&BA6BP$z(`NZOWQ=k+=k?7v>0 z|1O0_B=>6;&PLG^!F4EFAz1f?^(i1QU#$DKmqRGH!B&!m@RuruS zOnl9_^7)U0>5pVE7oMa(4acj`z!#AW9KiQAUWA>#v7I`wPJIfFKr%58PDavy7A{B9 zPYC_>dZ7dpZMJ~}`=cl!I7H)VI1R~ca&R@0Sr*~;-)a)DPJIfFKv5F#Ius=V-$L_7 z%JUzyNiUf1*drvJrr{+>8f4%+Bm)=V3XO+wz4{Uy{Jou73O1tXFv8hL`pLruND>O* zn(x_vxlp9A35howxSf#flM9C-iKpRs^%*z|Nu4}wQ6IwfNa~kh%@4Lt5;h=7$bVQ^vh^J}3dtUOa2k@fIXDN&>chF} z3qN!JZ=?_<@e4CX(%6L!>OFXzsWu+>ZW=Zssgs5C)ED4t^+njJ!q#!%SxCOU=fP>T_^DlI<(N73xE{eN}a|iVhrwWRf17 zhNPbye8T6is4-ljK7<>QR5FQb(+`PvVS{=PK8|F|3UIZ?i}2uTJ6H;iL((<_XQ|J_ z#Yo2W15B%4D8ZU-Y=a~mjHFTu-j8Je@~{O-ry<;^-fT;vC`uF#L((=4Cuuwj=czBi z)@`fp?|&#!=-0t6mkS$^bmYOwNIJ^Gc^WUk6&erWMva^8s!dNM^^Wgrbdef=e?2e+D!Fm*R1RK?7;XL&P*oq|4671aBwsqi1 zNaAVekJk$sc)R)>Y(_Fb06XnaZ9-l~9ax7Xo`U1lXJ9juIst6ecnQ|*XzM3oz4|n4 zwB9#aOf!;<0wI!REW)3V%-A?IM$zj6yia`|wjfC;gr6g+UxJA)x_z*ZdKdago(EYt zuM7JxjSCcBN76WipQ|sy&O7PS!8#Pp9^Qp`1v7cL3dsbDu%@f^NjMtGcf~z87s&() za0QCS@-dyd*#-{W56J}=4pX0ojYtO0!sSRh3gJeLo1M9XkkoPEI3x*W;C&j;!&W5E zj1sKt&T2?UDa^G<8f0M$Y9s3q?zW3={DMc9U9`%DiKLQz7n z5y@MzEW95{{d^DZ|HWDe;2QNsxJkX)m3taVgCrb>WCj^HUE?`8Uwr|#BAHAHcHYgl zbzmPP$+>V8S|-2$*~3gmGC&s2KvF3W7i&C#D>Yt(n>22AuQuI~)K9{}Ncu^^(ds>T zo%$@iUws}f_O%eeHR_9SlX_Fb>`^p(I9PoOj#lr%CsFiT09R-{gzMFpVCSB?67Xy! z^?eUBSubSa{p#~@0g{;oaECo?0|$;$@4+Y47ho%jmK_e-)7DSHMiiYb_@ep%ZroF! z|NLOK>4&1j0f}~Em zm(Qych3M9TEl8Fngq?cZ1`h0xWB?ZqK~ZBkMtug(Ly~9#u0T>hgzMFp;GjM>p%k2k zqVNCaFmsS}T7WB1)EIW!OOt^8QIrH6ralcDQ8WQKPkjOYh-CI=?`pFzidGjksP~{h zi@zl6JY239LiiJs50K41WR0Xw3SO%|3tLdMTCh`JO%(2jqD0|nB>i}B7K+A#D{P#9 z|BI>lmF*}A8<14;;4~yz=U|J*L-?b{&A!YGMKgorkhIOf=}3~u!6(!gU@MY3CD>y> z_Foz&_hVob4GbqEX`F?#)#u@2^#NRoWXp=MUq8FlE*yrWZ5obOpMlfW=iq$x1t0Ue z7DBjQeF=8%Z##0}AS8*V;0PoGd+D2lheIr|WY6 zpF|;AF4%~q(=2>keF3gkUxYs)sc#ObHbarjJ`HE7&%^hSY-JJF9B6$K)}ttCcrR*| z|NkqGS&XF90IpGAgl$MNH3wCjlaUPO!P`)@TJS~n0sKsT3GOz))=9#l>eKLA^;y{L z^Os~Az*fCbg1a58jo|N9W&lCc7~M&rf9xc@h4!3^Rp z5t6}Da5R!mJvd9_dAM4A5pF_K#~e;u6t#uZki0v}!TJA(rLzx^YI^+ep>5yWhEglV zR2!u*6vD>PA}K~MKP#m{rI$^EBE7gHAryl}QVcdiF%d#(C`w9$zJy{Zq&5bnWUJrv zx##@x?DM&I&b{}%-7|M*YZp`|h1a{B!TZ7g{NGg4jo^199_(@y&jFn@iI;;;l*aX- z@;Th3hut5*6`-LB;Y;2A2%ZQkAIHl;=S*X7BVTkt78jpu3k7gz(8WTy3REV7r+|MV zJP%YRiR(e#o5LmNxeDQvTn^#BE=TYfn>`aFybP*Q3a_^>m<-+zx|j)b?}9E6!DB%e zj^VkWGD-X`=sa0`093}D&m$VB0YN+({D)Zl!TFwjD$TI53v@sZ=UreA2;fT41;TiM z+aJY~LFMCk5$Ihmg+F!sGk8Dv4d}^vK$Q#Q0iX&+J;GG*PlUe()h>&7g9@1{S^$0v z@F38MqIfarn~*fF2VE?O&%V(1Rv1qNm5<}4E~oJU@buk@xrmE`4i4eLE=Tcr(1qi; z*5xE#3o4(%JHhWc-1=g>KZwr(?GNM8Zhs8VaXEQ0_y2ors8Aa32i4T{;;9$3KZtv{ z9L6=E3&-#*w?BbjaXE#*1(nI-|J;85K#b`Eek1W9KePTv2~$BAi{s^>N~C2_>$AAD zw>>z3PXd(>;X6SSGlAWPYCXeHV?u8Wo*5xcd0J@mz z!@;1+h4B#3{wSX6avU!MzXA9=w?B&yxNQ2;6QIg@A;Ms{5yi7WGdY3Zb^FtJhs!zK z>N0z95Z?r9eH_2+_NVZAP~|eX!R11-Ua0}-U2!}i%TP} z>+snwhw(_4V|Wp0BB$_r@Gp!TK<6}9FrPsCgZLbm!&h+s*RY{NG5mmgA%Q;vJ=J7z z1NbNE$BDo{5$*%pAHieY{urL+assad4Mzs=1^qW3)1QxX!2kC@K|&w!PlU(n1!@|@ zvs_N#WuP)?{GHpM#RptA1Lz^}=LfzTbe<@l>T(>v3;z7T-goYWEG`{rFA%_$E{E|D z@K1ziy8Q|Kirb&U>s`*^2Jn09|7a!ny@h+Y9L8gTdB*xrmn0;9f}Jwcw8#-Vc6j zuHrck^u8X!Q$YLUcpm5iNxaVO&)}VIe-1YpWXl9_CFt0&M;PK>h~mjE$MHOulXwUC zy@Fd`Z4VCO9-s?{@c_``6U9^A{y466`;&ON+n>fe!2kC@IYN`cu6B43=uIe!C%gS| zJkRAMUIMyU8gFs?v$%AKty}0>Ki3lF+atzOMIe{0s?4<~wx{VCp<#G-;8Rja4PjWegFLgPB z?*;#RKfK88PvP}0XYfv!bGXTHcTQY6+^zp%HioztqIjyyaXioEB!183G~VKJ79Vig zj9}h?KX33kE{E|Dm!o*9%kdE&7jPR%yxiq9-VXkR!cA^)wZ@%Y4&fU?>qHFCa{Ckb z6_-=E9#kfWn~Zel!6zx}|Nn*veccNYJl5qHUI;okh1a|N8NAcw9BwkoofKDqZp#qv z>-I@9aMr12J)v-p6^W;72A;7=|*$mJ-W4C?AQp67BBFLybOH-ajZ z#RuGeGln}3xGnkrzl1TM6UFc>mlJrA%PG9x;V#$OlCv5_~{z7W8bpaa5qfZHF%<6Vy9r$EOh@j6iX3@*OW4p{(q29*in zD$s=^c$mvEk1*YBBygR}DZI+%3~oKnu3|yl8+5S<9tJvT49@~xEP)rfoWko}&fwND z+bcob1N_f_!h|89gQIw=%W*u< zt#5XfxS9LE4;y}K@YC*vBwhkKX&P^IIg9@TRn*+l*jxtwvW;hh*7+o^cl&d=WV|gO zz!ji#hHwq|fB!K?c-h}zg5dR_3uJHusB&fka{|xf)ti3E8`aFCjJ(cm?Q>(8zy79X%lzwaPb3$pJhZ22(zU7lSI7 z##>#^;meQ7x4%gl{{x!Tf!6tE8t4v6;P!3&2Jrje2p8H76UU!}4#?s^kEL6=m^|&| zd^3?Oj}I|SuDa4g;c8ZvVMT@6~26L>kq zC?o#|Q^@i~J@fhNnEZjGp81}6iH!wp$m?JkIfM6uDrBniO>+u#SCui|-7ja(BDR+k~S@vM})gDVA;WH@YMDjK$Cuc9oH)DF+mZfk# zXj}uA=9?!#70TkqeeC`q{tVO;8T=Edj2!5jZx(V+c`&5OQGAofmtkz&gg<~9viv7Z zC!5PSIdmk;NvI^t2Vj88T+U<#J%&f{U!dO^Zz3!{P)iwkFX%2XSLB=H2k;vEy%6C; z(4@=Y^Zw6GM%?yFo0E7c=#G$&u4XLhUinN&ki)nJ^jl40c-i%~R}#bW%?qH_P<~`M z*P^`KFr4v^vSCK#n}0#wC0E@*YuGREgG!YdnQw-Iehp6)FLODK&mH9|jc0;}DS;P3 zl4Io_qZtCSd@iga$3}DiKg-7Eq5L^qya=|FW6#iu;YVcR>_C1Db&HQV3l`FXBT`<*}h~*^R8rWO*2jB*$9j! z@Lo{m%&iOu%+_$=*0(XPWVtJ>B8TxU;5Q5}bvcdqyKE-rn^Pt-{wfq=<8DyS;5{yz z+gU(B`-6Cb%W?dS%SpV#wu{HN%`ghuzU zQ0N7`Oz;cD|)XvayW~x$OhAm>j}S&tysFVo7}6EZfQ$ZvUX2A0a&3Qek8Y$wZC)bb{D zEq{atkAQM=41WWf)LHx=_!IfDd~<@wmzme`+lg>@s3ptS!UD2us zQtXf6Utj?zmD|pxm1Oxs*i4phg?h3)-R)1{F3&Ljab5^LlW(p84M7wqT$bN+IgNh- zbzKfOP1+p9l`h9{=Vy7d8OAwr4Q!^OaOz|Sw_o8F+Fi{Kg1oR-OL7tqCI`3vYnmh)d?PLO5qIKIT#ki+f;`AV41 ze)(&tC1-Jqm+39CT<{7#K$ZtVJz4I(kXx5l%GW~$S)Kyj$QgXpBEJEi2@;0e4St_P zzS;E}C!&x%FU2?wZ|nOlayePv;Ih2kW%;nhwv61$Wx1=%avzuF;foo6opd-Gceoei zCtQ|OF3X>|EQepW$I9EF3+Kt|uE?(?zD5gY}bN1hLU zMe(t#?fx*n19YA^Uf}k7DZ))_c!QzV@;|VVED!pG+lw5<fb7P{;SeLo@bAhO@jIe7dimy@|1s%!LB0)Y$?{@YNKWHZ zzOr2!!mC`);F7Ox<-&N9%W?cW=@~M{lv^j^KwuWs>-P(37s*XeaLt^n`phG?3*- zTz9}SK6#HV6T{#XX_g)T>N z9mFZ0!fQbdFpUe$k)RyJvq8O;#LM0OEdC4p-~X)8A-{kR4*0Vw_##NEb_E6IcF-h> z&MoC@>qqzlCtuBkW1T_#W_YA-wuXx|=04gWEQ97r>KTj^nkU@)`V_+n>YN zG`IVscmcGgSLEd_3i$hvY!LX*CbX0+{|;(F4j%x0s3iAnSzxLuBUeEUIf5Ssl~3Yz zpifEUK!xG$&@5!|Yc?a?4U8?;}32~wQLH+hxEMvAZ;)JnP0u?zwGEr@`DUIV(PO&+Jmq7((| zo^Yk@(m1}O+Fm%0=Y#&bq1@=I0u#KEiHy&M?&L5Y4Vq`zGrQPW!wd3m$dUttxYxnI zo$y$fWB5Ur6ZmzP(>Uj{TyeGStq>mRatuENI%fiZJeVFD$Mb)NaKR8eOC$J0movE6 zHFnZP@Cxu}GCp>wZG8}54Ej)7UI-J%@e8K$DN){2$YDJH`T|o5&KpaMH3WDvsKs%-)8!n#=0>|eiZh@!Kt6e#y+8;*4LUZ7 zo5x&>@$XO(W)9(rH!=PikN8d8w@^i`<#`Yx%S)h!EH}NGiAI)Bf?BeC3)GQi50;SQ zcqyzR%cE|gvSc|9_2j^Kk6Mi9UOt8c@c%&HHfQmf6YTylp5t;7pL44n0(lxF=q>pN zs3Xfi!&3F)Z3X5R&|Q|pZ`^KsD~&fpjmN}MXg7(60cs?l3IPrd<9?tXl9xe)799LB z1Sp@ucTcumoxlr0f1*_`ox)wgdE}N*$Q%mdeb9^jW-7halP~@Xg%7~^u1umk3d~}9 zrduZ#AG{Oha$T3M>cmdsiB7N5#&K&VyyoPH$(Fn zLx5j_3bI@u$?_7INlxQ>m`j#B-$kX#@emz;ptC2=K#D$%*9U5FyJ$XR%t5eUqn47t>}nGaU4(m^>P)Zs83E2cBbbBg;LYhAj7mDYvlxM+tX>TA#qpp0^hZ;^)Bc34Cdt zz0D$c0;u)!B&g%0a^v~j_hk7rSVxvGfX(DIzV`)t{tUj%d(ll6c>!yFS89rnhwWTI ze&%InGY88>uTXA0Klj6Jp`0wQg^uJ5-u^0cg7P_>dfjF@_9pY`6nYNd13JH_aOiDj zH5>A%rF0nw%XdNrSw8U{#*7@re?gY==3RykG$$hXahH>LH|P_P$b0k_sCVOdD`!FG)k6p#YBggRjpm~tPhkr!NCh)9>N5V3)e96b$ zW@P!FH9Sp`<>06E23Z~s-KnTNWF6P?*ie`XgUNB+<}+LCAU^L4TF1d*ybtOrBOm=G z?*(MJ|Noc=l#yS6Ze%&}74wNKZ-$X%c?ZPFIqbFh+O{l+Uw1i;3pUwq4B&~7!-Kcl9K};1IFY}wf;T{Svb<><t}8kavGQYVtXi#|8v>=N|*1jw^I<`2jNrsyI}Z+ot*eK{vs+qrk)`q2l2fS z;T=^TwTt0n|0s{}Aq2Qs2Iu|FgyMw&z8Z$nO8NZVyvvd0)sRr@@%wvh_oi{Pe>k3F z<(RQ#^D3Dj64B!p4dU=8E77)4|4zi<~DM;{1DxKQCr{q2+7pZD{?bfMh@by zK;Qdi@qWK=Q}6-4Rj=D@q*$)|1ms;e+E@l z{=zFQH0wC{3*4s(7bZt=>#{=so6aEq3pBY*(?T->^vy;N9~H0_3gOp4!;!-OxonOo zG&h2O%i;MjoeIe>LxSunv^bKkW<%}?OUZJ7SVNBDr=dGpKD7mvCCejWJUNB`2fA1m zpW3p}|K=o&pD3p%CNo#?zem%0vT4P&S{2&o{|FmdsOAN^aoa*Oj2yr{K*JHn(_BvA zGusuKiIdomZwLKt*f`z_TJv)_+}`$zJhua7D4)ceAVA*K!7DUFj;D5P$hScyS$+um zkmapzfAEAta}B7gqj| zG&+e1b_|7ZSMXbmr@pG@M)?%Wk*d1ob)ku3MP9b?4h}{I1Jsy!OIE z6Qg|KqC#^z=mKH99Mm#%F>3>8e+WPBauzr4W%mbg@DkRRFum&$Hi9OU>0M|_`q6HjR`93a2nGk*(bl0Tu<@ehh$63&j$^9R&w|W#m?(s!km&ElmS=*1L#kl1x zI~?*ykjDk&PobQg!R;Tk$A<9xprK6TouGHc96sS88bL+Fc%;iQ+~*Oy+Ilg})pwz?;FJP`J^P%w~p3E`&{F`4*@r%ex>i&S!|Y^&EPLEFTYD$RT_U z_&tp`LYTRgox}Zqz`bCeVp#>h8*%wuTcIdEdmbm^fG|G(Y1=CyT$QwM(-C|pG*CwV z?O7^I<>bGif^44SIRMn)6y6OZJzh{a?|CK~Sw6gulad3t61tJ)jZj6Ff0<90l5_Zi z7wo)|7eOui#s&x>yVsrtDjA0M7wEDJAiG&;-xmZ7%2Vv5Ogh9UNTDLIKKA zydLzBnZZ3?xAP$UMxl8D{5u7=Sz^aBh(8D2x>yu}>{x)y)` zz0h3swml$<-+{_FC&G=F+P7V~7^>JWPlal-{4&&#<#%BUIgNh@T_A_2zsEb|Dco83 zWAHDG^OrIHs!^1X0^NSHS#Go36I3RNkA2_X9bvoyR6c_{udtPl;GJpSQK>}WgF-WJ zC3g{TyGi^N=)zfi$tt_XL{@SCKg5Rr0zUR5d(t4j#^ork1;5+z*pF?Q7(V23c6Fh- zY>hi9o&f&GGk6lj?&RYcJmwR6gDlS$cXAsjED*d9S<6n)k4uuc(WmZW_@ni9a%FJS z4Q`_0D?#^k6n_NUX}!D_8p!f38D>7`mm7c1dO(&dJ-&2fBaA12x-^dWLKXYX7re`T z#d91d%HjI2?K@iz7jCjW7r=Ldzk1>{Bq=ZNgoR{z+c&(X^Wf9JwdK7q;ZvyQVi|l0 zG#utT#%{Ci_8|TU*0rY$zHy6v?~mbq%DgL@@0kan&l5vsgUKfexx8dj358WO(GoLYEL9jf$-h@VQRb`s>yQRHtq;=0AB}w zui(X?pO(m5U?XL=Z1W1uGe2_zHsqC%cTZd2pOBlA<$9kC+j(MPIOJBp(E_qu30ZO&?^M?Pjmvj% z%ko4kKM#p}`5`7=3=7Hf3Rp#!bFhgldp-YPqS3MleiH_e)A)>>&0*Xh^jGfXyCKNI zzW-$Ml7qMd^dg7w<)Fqy@Na+7>gHSwSNv^iU^Y4WABze2vl{;inq2($SyKsl(|Mc5eIP)VyB(m_WcgC4B+EBKA9Bni z)Phc$!vhc6agAaR{EOlLfi9NCtq<88#20`bSR!~FsC*2s1I>>NZfA=8V?%g0sC*K4 zKdi`j`j$IPcnka|9~?Qn$mE!4a->m_$(u&TlcAg}-whqf3A`UP1SYS@%mrOIg*SjI zl*M_CZ4Tf|KxJZ$i&+2N3km$1%PD+hzAY5Q4}t!DSORw|DDoGRFdhoJKoqAzCk+-B znWjZW_9x-E5_VHjc_0{uQoawG-^Kc`@E~;L1^G?rPEO;Ki*3t7_+`)q()b7PTZT(Y zicBpRkdKBWS)K_?$nwLmkt{EOZR8X#^-App0{9Zp7)Njl^gtp1>#}K5WIBQVsIc4> z`fwuoYKW5M8W>NO?}6#$1YQJ#nRN0GFpTUebSx_}6WIviDCj>V$g^Pv`{f0YB&YB- zO*w`;C5k73dP1HH(^lghU=W0I2PRnUbje-D-9EFRmu$SkEXW1D+L=0!Hvu_2qI z7-O>R!EUlVAM#kk=f5S zxL?R!437Ynk>|lC8X*4w^<;Sm7BbTZ`)0Dl;)fxR zLUIzy$?{33Gpot+*$^hnmqCOq-vCi^3_k{b&*42T%egZc|I+(;;~`X>S!9A_`4Z?x zmit2$If`$A1X=Ffon9f!&%rWs3b#6oxpN#dA72Q%a2)>&ek0GOJm}vRq|WC4A9)U4 z!NWxikL+P*X$+U2YsWQ+-vS++#*@xtF$!~1To$%v0(dy+Vln)I%NgA4e0yvVUjr%= z#p_^vIqQG?0@mXyW-#5A!=o>>t6K~o1YJ0IQIWY3{0rcXp#52V>BV+`1it}(Me$j^ z?EWym-sKox<8lU9dzWy#sC)4S(3+pYO?zu`;VBkJT$Xd-e@29dTuL|I$FcYwQ03CN ztdDI#06*<=5(oO)W97vzduc-cW%l3z{sZ*QVh&$$xoa7I)a4}p%ViVc_5)owfwzEe z<19Y%3cFvGrVXe}5TEUG0{;yD zFb!lssEoO?$g~E(JRS-4+*vWa3RLOLmE8Y%)%M^3z75p9aeUNOc9w?l0Px2i?*)IQ z8&qTlLEeLW(}K&cW|<|+Cqfr;2oHrM7nYxbC1m+4SmUvgCA1mrYKrd#{iH%ZW(X6L zcP%*trHr?{{2E$EmOlmU&)`8rnc138_;1ihu_nr`4SExjUxsazk-cyEvX6}{e)?K& zy9f9g4{moIlZY&Lg(`9wKLcug5?_3Mktt+<0>2OH>NGxOxb4vpz87XvIr)eYG>j~t z0GsY({SOiD1-}r!=mxrrLh@i(LXP5xU;r1BKOM<1k>#HuPR`*|MzKJVeUlfE6Zj=q zMo!_1(YB0y&uGR!#|!tc@eJfK97%lq7~9Ga9t1k6{2{C(%ilqkoWGyZz$P&j*neIbl@xSYdp-pU2qQXzcN zZT4+9f<4f9%PS$nB$dB}ZR9Ne7xWY)cb&)^6%~@(-OkEK#{B*VHfq?A7sC{C8Xo}N z)6q#xOi)hZcR({)zG*TSX4#e}!8URn|1*WRV{&jR6BjmdE6Oq0MwVZNh6h>y6$_-at!bD z_)^Ki`|vq;@&rtl)6*D#vfSt{W;j_cg9JH%F9KaGf@?s-5yQ{8{YkvhHhAck-Q^*ON27fs4 z@1WM_@al)`{>(#+Q?~>!PziYyRFdU|wcLtiIRiChx%e@AZ~*@XYHLV z_s8%aP;Z&peAf)h30(aoW%T#IqJ)uiSfM)bsW)B)Q@EI1`V`|$4&Ywkk2jv-asuBz z*LH6l|MN6G_b?ZGhKUTD=?VGR=jnE`d>S;TOc;9``JxYxvbaSZZ;@0eh-*OI6~n*6 zF#Ve?{L_5q2PewmDKF47QSo5w8BMik%dvb-2FkMj8){sgv>h!vZ|8ht}B_CWV!n)AY;#LXQK}rat;QQ<^51YHXkt`Kr=sv=ejKKhAEVh_d|jl z`j{SC&1*b8n>9RJfIcUdH^S^k_z4>R2NpiU`fom=+hO|Y{E7wq4)mdr{53?$Sv+Gs zEue=IcrEDhTweMaZ!DCNm%|Klaszish8a$UlRdtuOHalOI? zw?T$1&wy=Yc^~X1n=dE>x;x_dFHjGeFZtFCbj~nd0V8+-h&R$TsEy_}>@& z%=d@j&mp|R<@C?o|Dj)*6jVa40gbC{wljw8m)pTQmBE`qAH8I8tt{rz8s3+owYS|g9%MTN-n@32HI#*2TaHDq}!Y$nV9Kt0*~ z!JGiSugiO&f&Frm9KHBBlMb)?(^f+EzTry+FUaToMVFH0OQ8>0?gxX(IoxSC%jXDs z0S_-U40)-ENvuGtjJ-M?joH@=~ZJ%OAO%!T;C1*eqaw z6n8j^i?n1;;L)HDBjwLwGiBsoAV-!DYf)_SX44Zbiam208xwi*k(02LLUJ0`k>&lM z2NTn>*z^T;T?Ef_If>V~Y|1$n^c*1X0e!|SAAK}Ez=h?$&~Y|nsW8mn;J;MhTU}1z zO>K)!B?n~j^meuz6ZivAB{KMi_I7^^F9dydx{3&egn9!$A-c%m`j%L zgN5V-&Kt<>M2qF2S5gVGJPtOIWB66=FXtOs+^CxQF^>k|)2?Dz$zj|dmds^1@cuze zQnKvT4W6eS9Gt@&huD=Xi-%vs?MfN>q-%@KOtM@9b>tX6=Q_rgERVaM zNk^9Ng^}b0j^9vhTF=$!XX!+n|3ylEwvN>@pm{7eWKwE?*A; zdP`nW!)i#DS3`HQycv3t4+#Ym` zd^YHXFx~*FTzWDye2Tq0%pKgK5P60Vt?YYp7;b&9ZG8~;0R8+>{t6nN z=7AIc4&_urZaRaBNe;~5{?D=De+!LIy3e*aguMssDwf7q&Ef(NQ)|5OLA#1&arxt% zhzkVqL!k8|fj5A9E`!HC!LYWXqWIV+Su<1~4}6MYnCEd)!cwT=1^L{0+?Ql|b+XvZ zCd;2giY#x1G+AEvEUO+lT~}=W1y#b#XL7-AdQP790(TQ-Cj!$@nTay!oaIb}oC0V`~mXPI@u!fw$C%sAo+VH-B-+qJ1tIFXaOKjz$ z_^dbWka=Ok_n;rCWbxFu>~O?!k9X`4gz=B>vZ^H+dtCM&l_ks5pbuI85k`{bM$4E( zWcjl+bBHW|1$AWk`!wUfgbji@1gpq$_yfk7EME@W$a3EgxjV@6 zoWbRvy4wjqxz4`XB=MN__RS`ZPyLLwan44^ad6avb+(Z4J+l^8P}W&xRCP_6E5PxyI!f zp7j;$JcSbYn6K$lvOMP-x|A$$f|2Ab?)M$@gB-=#A9&+Z&K8?pKf2o+AM+D;#Ced8FTi_gJBa{?w{jevOEa1KaT$g z{(b)^iwyY7Ha-Na=n46{zZgogd>3pd-{lb=hXyv1I173VkN#b3_U_?1zm9SJhjknD zz!}2ne`)0l+|#&pKizmbA6ntlU?ltHJ}`wG!T$sO+J-Fl8W_s?9E(d2u-%0VD4cbW z7s&D}Fo2xG8)5e}J~F`_4{>X9Qh5qgljHao@RwdwVwN9PVjsQn`G=R7b(}{Y2iwT< ztBp!b0~vcJ%|>(82!9I|^kh z10iw{4}coV%P+%3vit_jobU0U4G13&oG3cQ*gX>DEAP*)f ze0h@+{|zRBk0|3}v`p>|ak4z9X^E*N%h$m|vOK}#%Q80N_-9Zz=5XK$YDWv?S)h+! zGx*6POH4N^l*F4r6D^CoG_yH^{{+3`rJI+S7mq42)s#=+Yg?4~-xtL2tDs}O3}IeN z+nOYDAMvRRFs7CTru#DErD2Jpquhg(s;6XtRv`C&+rllWJNlI8ZD znOtP~5tvEN;*v9L4<+yxC|tlZCT?*i^UGsHVI_1U%b&vlvb+O^k#l%t_YyOnEI;0Z z3y|dnP)APT4WM4k;Qr?_JTy$c3A&Nx+s-R7y~winFkhl<$nQanoW`TWbR#E~_g8UJ zvb^9zZdb~r@UV;QM2q1Mz`rnl`eHkuLcOREXfkGSpbr%aGpX^EzW&_e`JZsj<#wV) zA|5cn|nX?Ef(wpd7ri#0;#aLNBvo;)kx{z9%Q}3Q(Ce{^@F4 zIl04N))E>ZpFP-PF=69uHhM!I2S@N+&|`8E&l*zVKcFV?^Vc!y7SVcq?De)x5D$hr zj+IM>F+a%i^{|R8r(h#l-U;>OogTp(&TM{#dlBCYIv{~hzJZppKZIw2T9d#xj^tts z`K|YO(i6r7eS0H&l*Q}ljYe^OHSfpF|Msv#t1KiX1n||#Hob52WrWY zn@Y@UQ*Aef?qHpVE>upwfL`oHmJg3}VzS%Eq%~xDG;AZs@R_riM6^I2m|#|u<)siMr*Z2?xiIf|LEH~&IaYoK=91-< zSj76TP*+>xf9#gRmpoQtwsRu+erO=eIS6pD-1%`1<~yMfz6*lvm%BVcg~)RCYtTP}--KErx&AD<22 zUM-JfnR~dhGV~&kmU$X}%@v%#| z&Dfv7hrP)?&67_UcY4dcIpJHuzZl*Pno#EL68;AbL)nRWfR9^hZ`~mFT#n;*%Nc?t z4Bv8QY}fZo%nUZd_-D{+mBRy9P>AP$c>z>WM*ak<$?`WYXK}|gWw?XnaZpMbc@_l8 z@@$urxa&%W*n5i$69#?KF>g=;t&If8eBZqXdR?-Sda1RlDUR=+`c{0^uma=7<; z+kgnZAGAM#fBk~nk|E3CeqY*iMzQx1UzTx!3?8(R2}mJ%7|bBc-+aTZNtO%0<5nZf zr@}h2e1Xdm++_*9e{t>UQ}}sN`Vz z8;FqQ(rq@&A(!RY&vx?4Wxv?g2k;TUx}_SA1@%e{Fa6cClWQp(U%^6Vru-eG$yuDg z-JJ+mfd3ed&v!Y3hq)ZX(_K#BI+s&;mCG6I{bnnaRT#6w)f(?{+3YMacZ0v?W3S%M z@Hig2i(4zj*y9&Ktx4g%pvsxwOUwh{AB%hbVdqT*uLPCP;GQ|otBnYu`=7Q(VY~_S zyB_89|7K2bG5HdxCCkHLAvuPR-))Z#;g`U#5bm|dRw9Bc{;@fPXM)Nk{^9=L;5ITi zwAa2M&v7}4-v__j_pwTX-!feCFY|^86~Hmje!0Vb?tbCesaYDW^zYPig$uO=Qjtr&7iO!?-6(}RM9JPlS8Z%n&xDA3UnmL@m{E8Wi(An&6%JdT7>a|BTGG#rPiidsks2=zR5!b z9@o6oq{#BUu!@|(uYrCMjXe3NQnQi$@=Dl8mOp`VR?iIH1O6S+f{M1JJVP18anR44 z;w`;W^E(?g)KosAoEOPKTy%7)=}wjpKowaoX;o?llLNT;m{R|DeFgAKpeHE#Z|$eI ztHS88^1fV{GOsR^)O&g($ek>$3~iyXqQ zLYx-MuOH6^$a1R_O3eat5Z~Uh)WkTa+_n>C$g=l&X9}?)x9ma}k>#^s8##=>KAAbe ziL&^-B(HKkW@$10Bln1G=wYIC7IK%Q`s&2fC*#WsiWYv5l1-`~q!0C%~>ULb}Kffgdu zyVP_BH7taegZ8I!`cm$i7G#gmzYpWV?2Y1GpaXJvd0$#j<>d5br6x$0zlLt)EdKWj zZaa=O{g_Ps8K#?gFTniSgR8yg$hkf*^mass~q zyUFtSYv?XoBL||Trh+Udp^7Yj4FkwoJpWo+$?}}SJ+Gs;I8Oxs2kKpOJ&l5jFzbJs zFlm?_n>Y@QV1}Q{nBixja4Fv~;O}l=@{r{}Aw)JKOU)UeA5Ld+v(X&O{va+I$7)Ir z;G1uv5DC%w0Ap(Jkj#J*tGQfM=+S0Vg5ba{t+8V3)tD3RrA7)*}h ziKR_UfE>ra!+4IBe{IslOef2|%9@zDWO*c{$ezM9NVAc^GdnjikPg%q7cHLS_8%3CiQ|yOxFXlYnGX8lqp|Dq(=}4BFLU(ci zx9eSIdXeQJeW@T>z6r*YGLZe2|!Sm}az zBj{7pEN*ud=hyH54-x(uWDhV`Gg+W;IgDs?03p!t#Bi zIhZV0)i5E+@`Yn*Jz0JS49Ci=AwZV@f*?6~BNqn$Q!$Tl`Z&6j7v#K&^aNQBLjze( zPqMAa;fl%3UM?nI3xmn>V=$2{zXUVM@-mo9&f@*r&pG9%rZE1q*-&@^QsfjK6K7_w z;FiOccQF~s;pvPk_-{^l*WFZz{qiyQm6_dS`Q7^&zBH>U9{50+8OeTm3rr--+aW>D zJ;42+n#rW#0D1U>+)iXU4ui>Z(}(Pd{+r4N zR37xNpX3jq@B{vO7XBStlLH@?ne#vsHiqYVZeuP!dnGSWNInm$$T9rR$9C*9ct7}0 zw5vHGCp{e+IwttzB5s_zTd#f{;)A zj@eEbIRp#I@=)mJmD6HE#b&y_A1}yTxc4cP#D76GSw8-Ix}7Xv0C92zKMJaJ61V@s z<`BLQ{8bXa3FSHE4+*k-$Bi$T^eveV}su{Eu+%Ph5mTVLS;m58}9Rt8GmHUj=GS6wiQiP9z_I zj%2yXHWn;$0CxrrfqXS|;r#O9KQpn(a;u*`-ly3JvJnPdSiT>Y(Y^9Zu!bxjg3V;P z`WF@!viv!eavr%JT9eJMyo>%uBR=As_yO=gOTeo@*9v+&%FK^YL7^PJd?&XM9}dW8 z*V7vI%VDV2iSQxN+o;*a`#R`E5u5~n9^hub+ujP|+rjTq{4(e-WvB4B;AtaEDE`B~ z5Wr`<9L7(=I=WOIn&YHoc|7bR$MHPSpWII3wV-om@P3!gpWFqY{ULlU=(ddi$^GBx zFI&3+{sA<`SseV^wnlyk{F#iO1ue1i7f?$jkUVF}sncJe$A0+=DE*iT zi+lXb9n^;5!!@AACxQ2ReDN2Y{blB`|9GJ#7smf6>jDit0f8o4qXIZ_ow!m&2w8T2t#7{us1BgLfa+)StcP@TR65 zv|oN0I#OPK3M$D-+_;e~AHXr#Oy%SaZhr<(&TH!V50>$~re+`L_Arf`@;gDAnl&7d zz^{V;uUv6G=)%GLre=15%}Klh%2)Hl2Dy+5k>$=1CWr9f;D3Bq)YQCC+>~!v_};SE zYs&B8XliQNkSj`?ng!%Aj)5*FzXE!SP2o9Bn(`mVX(j#^{0WOo%9`>g+4#91{y!K@ zmTMtKPU3x_bDE}2&B?IT;{}EOu!=0-7@)hz^8K)nEI$E-v?hrkK7tnTmYT&KkF=GL zpNAQgkr%;SatilrMlbRWXcX6jdOC-_P;nrG4$>gGypF-hVfU6(`@_!x|rOx zbyHKihEF$ePY9AD_&QJ-ISmWBfcz1xB4_YbZEW{O@hzb8aa?q)-5Ulj2>SF=ZrqmfXTRJMD#<~7WjiV~iHY2v@}Nqj z@R1eV1?RC!;x*ufxR}Dx9h#b6WcfH4MwTChI9Z+#wd5533{(mE;^Vn%*e_oN%g9l@ z82n}Xgr;T(Xb9pRo0?-fQ9evXJ8}PyWJ9wthU-E9Mnevq$n8XH>BwjGg zx#Z%w9rRwW?D1!q1`Z%!4z1)6UJ3Tv!Ur6~*;6h*b`mE{mKR$5uZxX^xZq?~_D{_O*>F&T8mQT!U%Lx*>`_#tV z9gJfN_z5Y5FCOoX3XX&7%YTE%8cOdbFgKvDSd*`TsUPxFFx~{!WSQ?>va?(QdN~!s z_k#``#V@%ziGK#YEKB38iB5el-UB0Olkaab);;{s$3`6g4fa#;qzrR2=m{o*zX84f z)|n2dW>&4}<+W5$^#y&G-LY%W#3tAcPN{ z;xy#N<3ZPS2(N(QIvD;H^cCvz1(jS0l*kLjJF|83{8j!&HLKEQ-Iqk>?2Z4d0YuegKuHalf#0#$G(} zfB9Bkuz=oekKtXQQAt~b!=^LeQ}}%hz7f(iD$jzR8#ow#3sgt$b6bYVpxchF5d*B$YJ~dsE)h@tnoacumZy5IQHG{&L3`Ya{|x4gHCW~jN&gLLj4pD zS2-gjF9Can<5TZ+rZs?{2Ay#X7tC;{cm~)1YiwwE6L{QRP7dK#(3(i#ZuexEIUFpA z8$b=kag6EHG|4AMobmwPtgOyq@4eg`m~VME*njYLA5ZIGzy1#reur)B;Q3F6c@cDg z1Ri-m^QHsi?;ha#C8u%qEO#B?fi+HjKlVQ8o*BLjG!h})30fa!Hn00YCnj&Q_+Oev zH{l)7b0Y`9o`;;3FJB1-l*<#rPnK_i09lT>&p@2Blo!KVavXmP_FUqES|@vPnVUm+7N~Pk+`G;>m>WTlP6U4oc02f-XPlhC){tkN9!2m4^=?n`6QD-ryXG-(oQ-@R)RU9=Z&0J=IT{6x zTo5mHa~$sk`@p#W^G^2S5l-gwzl3W*2aDjjZkA`nc#7p<^1ZND2gZMc8uiTQasp*P z9tmnEh-bRx5xmOH3A_bVN6uMjQ9z?P3wc!v9pngp9@J<|ZlJf9aF&ZQ%nhKk4C5H+ zN|ApB)i;Y-jG%HqE(0xOc^d4aeR&gjKH{>sR0uvctAc z545nLXh^Py4zhgkGERc*#s7eA$)4rBRsefC@N73n@gg^4%bc=;TP!=v0cau1{{_9U zH1P~`45*<1zUc)ghw-zZXEXWe7kMILU-<&4CI|6s&pz;x~|5JoL zpaYnf`AGtHyI#_)-&ogBbPP=~^A@akxd(~uVre3M%#_5JvI7)h3INpMpl z%TK^$wTV}Peq@vXQT~{pxD`s?VwJMt$G3x4Zv=OL+c}sAj{$WeglnOOM&&gymn`4C zmY?g$5&Q?(SH!y+<^<5b0sI)~U)hM^FWzPTwUJ_@_j^ty4?e}s0X)^sVO;O#82%b` zfE3Pn-`y8agx;Kt{2dgNorkR+$@&`rE(;d1rk|AH2v`6$EO3HJB@BnZQk&e;U; z7|?LZcfb}7EZ0CgSzZkL$ns0z+04&=xD~u)`3>-slej~fHq+Smv6E$M2LG$4A=!dB zS+0h)cpX5w2cHL;jv(F(s$;ffm?OZhkLQB^el&)ITkU-< z6CyN$J(u`~&zv2?cwn3Jk~xTP1$|MG`~a-u!19-{jV%8JX|lW*%qMi>b6)MhWXk0M zU(hC5zVZv^e-0a0vhg}JkmU|&C8u%UFP+YL@jkGBLfXcAe4x1u;pr*o#YF@!{D!CM zEN;p8!0(tEI^n^;?%+v@oW}chvM~AWy0L!XJ`GVGkdshPmXB=bnkCD}zy@*v&xP?@ z_@)$m>n;``S+<~>9Kr8^+LS{-GD2i|Gjx*W&%x@=4k?2FC(RFYjQe#k5@h*ESgmp# z0W~U{pE(1{=&;8NZJ_|`QhK3VTs~xpo7Vi zey7*$Aioa1w=zxmZSawka;I}Jx#u5@9ObeHHjw2@KyAut7`~PJzrxjj(rYTo*TZCT z7$-oZBCpv^rzn>{gidl2d%K)Qp}N+tPss3yyMp`L8Id(0@%sK}@F@R%GLk}rTEo zIPO;Bv9DqI+PW?2lI>ITB;3JOrm^khG@$ivki;dvf9&CINxKM$R2#wC?^N;Enq(9`5sTb&|`X&<>}xjNAS@XJEP*qkugk-%CU9R zCG?IBIdQ4SgvfFVB4qiPfqigb>tX+=yp5v?>`aVsBs=h;Nk~aAT%of@-*v$EboIf**wD(H9Nx?!^bS+ z1Sk*St;?P1Na0m4&?dL%1n%)7XZ$69jE0bcVW^IyY8f{kw>_&tAIi2r(p zVW(U^a1|XQd+?2rppNa=>74e(AA#v$n(*H+=L>!zjSqW+k)T{Y2K?jzeg)Q1=M{_4 z|4q(-2jpWQq)PZf@bBcqMtIa(j|o#QkAr%02>$@nsUz?BfW=9<{3o=L&3e`f=6vNPQ7%UzO_nqEW1B|hb^Fr}S#E>19B5^l{%j0l!;7bZ7M=WTpG>obo#kdQX+{En1)5{|pNvdX%D!?RPbMGR zrBVC<==zpBGBZsjcH{{tFndE5Z%v#)Gj&;Kgf2;-+fi$&f& zFw;~~F7H1m(=?Dh_!3Yp!B>1k63zr4*^5sGO_}`5k(p*V&D1MECL)BFhmvN?e{f;2nGJ5FR&wsTv>e?l?YlrnUnMJJb@ zOrz{8mq8Udh?`*u_2oxTryg03L5Li)2tR`so!s|q4$jWJhG%nK=&EXq)aoHEDwVO*^gU6Qz_?M&FIpOd;~On zZBdCZ8#GVyO_dBgmE;I)Bg@M`*S);yIu4fNa>d(WB{_x1UhiD@^6DFy0?Or0u!Ee$ z2&G?lXd9xhSZmjf`0Y$?=(p4sGZglm)sWDBav5&RBl;m9}NOGC`Pd@lsZQT!rk zO~_YO(1!#<@%@?Z{t2IXQ(7dD5B6L!PuU&CsW~&+~wM8g!Ba_!Y2U zqv7H@hVffol;WY_Bm424plOnipU0}E6Y^Owk{rZ0f~G+BJfCSM)4uG5ITjlVGeJ`z z2j?>-l*kZJZgMkat3_KUoKO#^=sWMqag@XIS=?*TEKY68{N&|MFpWxa>Pt zFFVWE!box$&jwA0eA@Ti#n@TC2zu{ek>W0IS*C*n48*07!|gMG-v`aHoO5uNnas}e5fCN&@fgtUR^G2q zmZ>1iS7&6IYO;JY#K{r7090RoAv=qc;{LDjCTw6Mfe+2evY%e%?EEaVjveH1L6+$x z%NBUKA|iM@=;>G<+Aqs&qaFEF=+(u^;0HlhkX%;6iIU~9C0Ul4%tnZf$3Z_h$}bPd zG6n1`e*nYDNqmlv4pB#b?eHu!l5%+iRH_axJi@52rMfT${U{3+=eo~fcWnVdTa+cXamTv^l z544XT2i2G7pO(evKWIo{1r+b$9)SCt?hL7H&Sa?BS)OoK7Vi=BjEAQ}l^VsHzi=2OxX!380&p{LD2hIdSp^Wew4eeA{%^5LvEt}n7eB$tu`jkvD;uqBB=AnqJjv(Rac1l+Uk;uhxt#C=pgQu-dKMS^%6~v7 z+05f$psA5tVq8J&EB9Q$w36j)sQQunzn3rrw1fQNA}a3VZvye*jhsDM9uDKl0bC85 zOS$I~t`s$jb0ALk;^#qADUVpnd{Zuuf*s@_e$wK9n#(8g{>xa596-*4DA|jrfu=yN zdy%tbXSor)ya5@sfBPPyE*)5+!suJv8q z-f1U*FZzkQAvuUYNpm%kQ)w=TuKlx3fDLm%wlM|S_5*T$VYdC=z8C)nbLh2vSW&jA zC(9!tPL_AUI{ zwj`Us^=5eSJp;1MaI*Z7FWZ!nb~wu$OwPRuqxos?~w$a3oRY|}=T z4-aIUE^-`O+t0{0mFz4JJu}->ljV!gVrQ~^E378VkH7}9e9}k`PL_W>JKOX$CAN<` zmy;pOxn+zlS?)NGj*>$cWSiTd(v(1TcL%V!0llF1{?P*&o)WQ zW$RKpL6-NsEZgiO%g0~A@OCS)eKFZbmZ!sTvb^95i#cQ?&c-g#FQL=&gltnzxqSMS z%xmUhCV(e_{V8Z1cgy9wCuZ9pE{otNK_5zye}~rYCARmFH<0-o4D%0+RJJB%o6A85 z4&io)a^N)XeU;OYJOL`$L9T=_S-ugf$zl9H*dv4&T;+4}}QXi!T9vaz(C&B<1o}*g=-N+-$DPHg|$XG=kSnrPDp= z93C`{_7CM15zfAeg*ndRk|Uf2I^$57gMz+JT~0$MJ(YXh%wpFw2^|=J3R}o2oO3Iq72vq|Q;YuvdEisrH9gymC(GHlu~NxiJn;@zIGqUL>GwGI zi3mQ}a^~2B_m4Q!=fUCo7!~%FQ_w}0E2^1}o+Y-YkiBF};W6;DA;;YZTxFs_x@@(+Xru?RpEjtA2xj*xO9DxyJc`xYRAfG!g+l-=Io(myzurb@zEn%q1 zF?{DzrjMM&2QQ;O9rEC-K?^pF)1YTsdDRN$U*E%!Sdncmdcny-eAi3N*%jOaaQ;fp zlt#UHF|?E8_&3l!!@QhrZh%(G!*~;@Jc&K8I5~~KUB$hjSBdR8uhUWT9E-37I@pNg z^{eRwS>Ev`3yPe^-@VNoE8}O^GMD5S-u$j}fD}IHedkj2;7ivzt>_@ENozbEM_S+3i{{eT?9KW=6Id-FmAH-EumBg@%e zGNfd=1lq`c{M~li;RNLKzvk*7%a?z{z2!iw#10$3qjx+YZ-pIX`77uo%YQ&mIwAl2 z8&?6@{GM$-hjtDoZ~BvyA&Rx z=in0C-;jOeG_L=b^+6r^nyef%f-L_BLgXmECpX7=_QQ3c&kDECD~HA z6K1j@&vhS&;i&~2fL@33L!i&|$fpBvmPzse!Q2V$?~ggK5`iMJ}k!+XLB>bkC#x7QHkLl zP?J?+d+GohCCi^f3t9dZ){*6(2Iug#-6gj7lDjN66!MPbARNGpH$e{Na-XAe`1@X- zknlG!f-HAJIa%HdlgaYMLvl&_R|DKaTo+ zc>S+%DipATJQ@a(<%v*Aj$(6sj`JrpI3M&B?8O(IkYnN=79eguk)h^3AIIy#z76BA zKzBWPR4K=zzFc0){10a%#74i9oSnV+4A4`gybb~xCAQnhdHmQ90w^z^@a zjvTt2%ND9Rfc!AbA*z7y7wgG;5R_8bQ9QnC3P5TKfW9EYA1q|pucnqPUNO^4VNVci{j+9+=v)ydGHiQk&G?= zHjhed$f@f&8?w9`Vq|jza~``HkUD3{t}wVDctf9ogmBSKgtP{Erly#2OA;W44q`TB+4-6 zl-M3d_LBYhZcrV0H~1-+dp^eHMfTvUU_4pg1yjlLZm1!f$GOxWXa3a?!MqK1JRpAr zE6GWG`xDMkM{u{fj8-8x6PyhNWclPL=>%Dh*0RvZaubx3Tkd2AiS zeiIwL^Gj^ML@p-FUq4HuWVxuGxh2a-f$ID59Z*(KVmn11PnNHom&3DWiS0|DXHAgh z2~ba#uYnee4TTx7nk?S~8_4n;=paY2C&p#Of#pXaMV9}X&vcOGJ`3m^_2n!mCd-4N zl56T~m9v3Ro4>wh+U30_pN==^vy z=>9LC{T64$4srzyB8OD=HfK$J`90V|mcN8{atc56j_w~E80W6#>flnBFN1AG{8VHS zs-TmN2;K;Ky_Uq&-s51LeHd50PdPb)bJjUmL;yeS<`|BB;FQbx>z(Yy^V}T6Cw}Nm zWdL6d_V+)B3Gah?n#6-Quo%zbPb+abG|@SE(MHP2aU9;nkTMeTT+qHT{H>eQ*!qY| zS|^4_e(W4Lh?_w5;~#VVAHA8gxE)fAko+@rk<<8Jm`s-Uen!X1@?TKbm;1kIVPWhH%D;7&GIk1n13~z zX5*?K837iH{4)5-^5&mdJY@Nh4n~VC4}$4r`ShQ;#ggS&pzHQ<`3KMgX?#!GIm-y%2|An5e{;<2-<(%OF}xRaxtiZ;6q@?eDE_vS z`^jUR7*77lG*K=ex7%qmfJ2b7)F`1IIu7IKI{X%xk`mj$kaNiL?=XlgAKb;Ajx1+F z8QF`^0d+{e0V*h$pMt6682$ltGHGnxvB#PF2!0LpKtg4EogBnN|6*#m&-?Km`)G)_ zP$M|pE!WJXQF-tFxn^=d7V-hPrWy37)^WTA^u=@X!d|&%Eh8Z>hi(12|HldE9hhq$ zIEZfqy_^c;m2SEG+QA&)&=T7R_s%s{XW+ptpv4=n!@=r0`Q1N!EgN_s8V!%T7vzYRK={6cZAF_g=% zKn^*9BmLbD;qSp7>HfKvx!db(B=EV1SzkjwFapd+*a{~!OjCAeAmywV7PPOApX+Lso`Az=N|9wfM0ZT z0vDg)lzZ__ZVuzVCo`Z6agZOVy9q(DW<~C4{;_uz;8OaoY%0u`u(E5ns z^0T$*7%lt)P>1jTB>e1b7|%JmCJ1(;c)xRUePPYv_>95-$XuOdQ{Lt&^j8|0&KBn0yP2pdGmyf`?kX5FnIX z=k&;r*ML2|xX1O*e0y*d>~BB9-@!}{ETa-g%32U~_A(c^=eI48IDxgp#;)x>Fv&kGeUEn?ZHt;@fgf1+OLL z!yrr!;H#mMCp>v2L@2iuw!&OC%Z*0 zgeaFM!!~jlpY1Zm4>GKEJX_++KxY}4!`gb3`vkx5kKo52bDr2@*z-6Y zv<_nj!m1}Y*cf_*v!8Ub7a#Ey2j(}R@>qx;&bwB)0oIb^_{V3s(~;Bo@8>u$**wp5 z!Ej%R?d9Y$vi!_^+9$`bbzcJ&7jX~AW)VH2L-GrYDd+B%z<)P7*)%ciprH=q@Dk3L zHz4IFnw=cOdzLyUU|OgTc7416^lKe?>@xQE@%mq3BGk~M5Pk$yN&XEyoQ?b!4APk` zr%|vQ#S6f06pvlOU5|F;iO{At@grcjiGPET+QfgYu(++N(Kt_uu$K9jXC_!&ntOcB zSIi$dj04{=LS#AfJLhte&w#m<2k~s^BFmpaZ#p4+cCx_9@^sJ%L@dIKpx(*X{*Y_x zs3hM6adH?x2dX1?Z|6Qhr{#koNcQ0AU^j|i1iMXq?XFzYt~T*aV5lF)&w*t(O6dM0 zQ=mri!4OlUIFaU(<83s#eK(iQEj(Y~yilm;$m~1g&H*z6I=CGERW56!{-$p%Zf9-??T3 zSso85vOEbokKq2Va2NC(SYmrFIfpDi2P4SxatM*-w;@7KV)G9}O_n<$Mwavb%{8mZ z@^O$P2k@&V&%Pfd@NlbJp8aGKz|XlkhTnm;)A(~M{4Ip&wLGkQ9$zR>VtYP$4q1K~ z>d6UQ(j(8lWBTzkkmA6y>6vFb$nss#lTox37D53V@^TnNj^nKT^6a1Ey?7Pq_ME`m zd*zv$qj-lC4?2(oa4QYrdRWK4@?Mpb<#P_s5 zjX8N{19jwTNRgvCRvz!$I%kl=cjY=m7r`Ha&Mb)s=26ZW%M&3$mJiI&Gv#Et4^)!n zVyGf}@jVbflDG45BdjIM2lmY~Z5A5}_d^F+o(+bbq*g=lq8-k1&S5_Fm z0^ylj7WL=^uFYA21)z23Pu1o5KlnSb3V z;%tn*!KoC&^TGaE4nH=H;iaJ%j^F4!b;=WOa_WSz1?pS^Uv)E6n9nrf*TMc#4j0_w zWG}WLPMg*(7H4xSy=Fr`_VzrpjU2#}AWW7|yo1po%LmNlNr>#h&CqZRZ&KpWJv>2? z>y8=&0-|Ww?GFug1>})WO>O$+z;4SE}6sY2C{rHl#=B+P<9OWe}#Dv;sH4h z)5&R-Kg>;o7o0IXaz74%MoT{BQD@x*@u;ZttQf@g(8)B(XFSH0L+9ktk8^d9 zLpbLN=Aq}Y4Cxc>_$0k1`|*V^c|3nAgJ(mCa@qS7ol|{045DQDI*5_OIIET^q@!M( ztYb=!*JODhl#>1UnO;*#I{C2-Lir%^AS;pPb5?&cIe?@jl> zcn0X-6_-y)P)?ij842cp2OB{)O5UbdWIulA16C=o;gk5v^~~Av+{N%+Fq15Af+#tO zpZ<{gWcmILj3ilp5Jr*Z1_+VkIAbIC29A}n(aJL`*f2aGe+mWU6y5_GYQB@l6oRrB zpXBBMz8W-)VZ7QcPvC#ta`O?dl0o~1@FF+I@s&wNLihg=!F=po1@dcPKWpKCK?g9K zxzm9?_xR>doH`MF@fIfs@qn$|B`dgU@YkTLCWWv1lp7Q$CU1c_S+)Y7vC!C%?}cq- zIR+i%IQ{^1;3U4W&1p1@hkwqccoO^K%rCf|lD+r>P^W|Vps%^NP%iiVhMN*u9uC2i zxc@6$@Evo*1M=fLxUrC9c=q?snMHBCo74Edoz4NGI1ak&$sfR|(h}Qe{y>}L2>x`J zQ$K|V{lsl}GdDW?=1v*2+i&Tal8wnXYd*g5Am=Aos%bL<(m$&JQaF# z;4oeSsvpPOpqO&`v}{g*EN_GnWcgdDAj<_-PQD4VQGm~cYO?$^%q7bUp@|&FDP@fo zo|BtzR+HuVkR-?P;dykFD@e}oM<-6w@bB>!@BzNw>*{P|E0Mo!^NhdFiR?kDG)UX;tbAV5yzYfi~GHMAqIJ2T%jkmVI; zG5_1xh@VBTN4mYnz6iBUZsGY{kt$g$Am7Fz|xJqFTR_FbXtk+r|-!( zIj3`G_$WFX;|%2L2Us7}k?)w5Z#Ix4xL1u+N51k=t{lqc(NXpxhwx9Jc4X_jXIVsS z$eZi)O(!{pE9bc#!UGnuVkwt%7PH#PUc404kleW}-}K}F@(;^d?PUK7F1eSvukafZ zKOXkFoAJ1}?9BH+69&G=oO70beANc0QW!t8*~u}y5k>^Kgz&jrDJRQi5F-ci-Jm-1 z?$3CPEO)_FvT5U3klmfoV`NeI_D_MRC;^YMW0Y;GJ zabI&VvU~-E$ss%obTE0(H%t>*-V2>%V||-%dbB%d>A~5*IN6IwbvikS3->r9(eq7;Zd77KU*#&(5 zgAF~Y$R@|xS3JrX6OKYJat!;ubc(#~umbbxfCBrw{nL1rkF%z{6~A)?CvgP7 zLUVO)t<4P(e?s1^SP z+PM>->vzt+437hKZalux&0$;vsxQafEFW=90YB;=W(FN&6`0$PEwDd8Qib0D?U2Cx zALry=_#!t4@qEy*H{kt-J7?Al4+C|=k1q$cQ;8RX>bKymGJ+r`+lFeC+An3s3@gr_-z&k;m zXvdq+rVb;z1zT5~Q0B7Ur;TIo>#i`A@Ks98+K(FJ~w6T>R3d z?(pIPW1SHif!iQRqw=el6`1Md)p#G&ljX}RI2rPI{0`_BlxuPDa%be^l5yN)2J$tn z7U2odn}T!k^;gg#cAkn481MAjgD-@2=Wu(*U7#tDmrmsB;188s@QO)H6LsSFrK_F1 z60f?($%C$C?m_bfZfrmB+p*Tz0V!S$?0cCN;mH!yT3@r7f!`9^2w7Cht@C(AG0 z>U4S~KIJwikHELyNv56Y__n(XOar+SpB>xh{+My1=>Xxs@Tix7-|Lf*X{P@F++_|hFoOqPWl`M~Z z+$oob&gBFs_v5pzr&zIUl;QK{G2i4-_^kN_CPW^I{R_F&$dQHuvv&zs3)wVt-7haN zb;>IW%pWguhf{uur{Z~p>N4>>*B3pjKm+!H%wF7?n z!vd~gcn&*S@DaI>3R@MT4Xrk?T&+@rXV zKd+*~j&}~^0cHH~ zAbLuU;u8luxfK6+WT6>Fc?VuUgabdzx8dXdM;F=)){9^NUmi-E!<_PVe3;)kun$jA zw*UQiLhs>)riHVYZ#cfttR+vyKVDL3QsfR?S6=A+!^3#**g_MgT;5etXllsvh|3uv zawqbciRI z=v9U0h{=VfCnGTkuYm$`0-t=1v+oETy0*{+>5%*>=*HECCr+{3ZVcchCp~+E0xQ%^-V|e#GQfNlQ>b`uR z8-5lvigA3*ea;yV$5Ww(edQDX!%31$EyCXrV8c`wnqxu3I~-pMdS!^4?3MFzyoJ9lH9}w;p;#hor)g-```bnAuIqLtO5T3 z2^vb{qaG?W?c^bN)EwrRTd({mBq`s3e+BKE#^zxs%cp`)rVQ7(S^f@Gzw2SH|K5){ z8*;Im<0(h0dGOcp2DN2i_ZF{?*fcY@9UT*?9z>2s=2l5S|aJ(}2GN9bgB}Uf`7H z;9J~09j|tC8_rnh)ER=eLkDf9a7lwx?rY#0&Rj&Jqj(vPix<;dUg^r0frs)6TnFm4 zJfM+br`(5MhJ7=+W8$wtolD_MTX=HPzIfa+t|0PweA{v-SIH|_7uJP5*%0=7flGu+ zy>OqE+}p_>d=Ctv&K&$2=#}eg{4eNW{#Kr9K_fI7KkepvywS}`yx*%%onH9))wEBW zF>KYp!F+PY^4)K;GI=0^FHJaeR)Lqlz$jA{1NC?ulcahoCkE;GNTCD8=T?I!K0y-oy+kiw>SpGHwQ61d(UluaC7;ga&SsreR?2gJoH_M0gC^G4bc>V7o{0FM}{)amJ z2I$O!J&VlH{fbPKhWz-n{fq1~3*fC_zmmb7p!(*3A~P5CN=g0#)X^Qdq?eO@_zI|} z&GG|_%zEn}r=d=K)WJpey}cao12rmN-@C}HW{0WxV^E`8@EwN~*-yt+_%}#XrxQQj zr^uwp^>}zjk$uU@pMyHR4G-}YnVcZ6{}r}?j}2dDk=YJ9u@69Q)pE;}Xp}Ee%y!bUYuf+%C71`6*3peM}iKYC&ihsy2;@^MaS10XkEG{fE z+i0{2-&jl~au`3-ugJ_KNAXvO74erb+{5vYC6x2w^A21wz!^DtHfV(A;JH4ghx+n> zBk0^{P7*&f&^gID1Fa(7N^^!qo;uh$8+q?33==!VMiiOaQ;W9d;)YN_cuyPpsRgH@ic0>oi_B%9 z-}_bIP+5_QP%h5~mCwPeL2E@Gc%F0ie*6&3rM~RFkdY(Hr$Le&z}B#foL-mW4WRFH zkpCXdSyIW2DKbyNcrL#>yaIHvINs&v(n}}@&lrA`!#9@~nO@}S_>4=P_ABujm$4uz zABmp=E@{iu5mtg4m2asivhN4e@n@i+Zo^$}mV=kGGjFTNF;Jb=_$yF5U3k(sr+g~j ze**h(;1FI0Gs!7@@RgQRsrQx44QS^fcoyjUU}AU;#MogS-Um9EylG;QX`nobzXR>N z14lxfkpBJ`{|qhEN#jYAIEiEUAr*fIdY!SuA`H9AnX>>s6WVzrI)txt?y%HBPyF zqMPNQo8_C`EYESXyu{7&TW-dd`NiFk54hGjfb4a%e6pM6(V(-GZ*a@yS~trtxLIEB zW;x|%d5@j>q^d&Z6sJ*n5a{gvIOyb6A8#)Cxtn!p0q@!s@)i_+6b>T)ic=7Rzu{eY z1p@F1#Gneiu(OEw(cxow2VREx@G#s7*Fauzfysbw@O$3^^F4eFZ}jE8vL%Ek;g){9 zgAWtnVmJeigTo;o4g~$Ty+3d6zyaO@^BLX&ozRo*Ex0#s$6oA#6gds_)+F&D{D1yi zwQX~Wr(12G)xKLZ;DU+;{>IYAKx0{Bu(6^s z)EI7zG)5a^jZKa5#@5C}Bb5SuO({w*?pkabdo_9*3mUzRgBqRvLXDN|Q^j62>{r(q zZ)$ByG_7k&Hu1506Jfu|f|>=<1$7JB7pn#Se&v5n{C^Kz`F}Oy96r&wt})rz)|hH+ zZ%j9KHTG)qG!-;?n+7%cn@XDkO~Iy$rchI5Q@E+BDbiHaRM!-1YHIqwIuP$`G#%09 zb<1PRo0i9yw=Pc{ynNkqlkUscE%W1H{5xN9QD_O#6x#z=y0~j;ua<(A(w4H8ik8~z zKlB}%Rl1^LMWx2fQ_S}!8&eglJ!gZ@+oN((RqeD5zN3zB=d^k;D1#WtG6qp+Qo~R* zF@Wpne>;6Ipx32MW%Rg`-qP3F_t*RS*X~>I8+uXuQWGe)ds^8LX{c+6H>_(&HFPy_ ztY|;e8zqnM9#~wlxN>o1addHfabj`X;&!IR)5v%8*;86O^b=pnK~xO( zHx;Nhz0o(iXQ;o~SNp=dzLRSIS?8O&pJ$PGQDD_i8+_+=D~s#g!u|OUX=9pVt+7OG zU98vqg8AP0gXa6^m(CB&FPk5nUopROe%1WQ{F?dE`E~PS^PA?!=eN!;T^LvxTv)L% zw6JDjt#^wrCwtIR|I*T>fu&_jE0%_q+6%Gv=5KucYG340zPzZv8O3o58oUijx}Ku* z|65i6TT}mMB|59B&RvcFTMo`*Fs!fs_M8QlgqOsYB$t?Ge{-lg+MH-kH+z=`S^jYr zy{9G65^jmLBwNff|IlTDWo65P%PN+cM1R9S^v7@9OIHL|lraQed!*wHtqok+rh~_7 zYX7^z_l?HT>t%fyvuVcWu9i#&@87L_gvEGk<>Vc2UXqgZpCBd=>tHn%mWn%n6^ zS97nWo}~p#y-WW$CKZf_b6G~0)-A2wu*G*|FB9>aHukR#ec>BhyZTdKMeV*%eBL68 z5?;HDi52TsBv-VpFi9`p<4n!OhrYI)|G!07d*)i-(Av%Geam~9l-IPX+2}^!3q8|b z-v9W2XTNsLd%oKT@CT;GOO4RN%7x*DRSQcSf(;eUx?7}EG@b#q4{h?j-P1dOuLB$X zk?;A7*Ddc_K4?X7MM&3!e}I`xZxRjZ2JfQaqKZY8i^7XSOQK8KmZX-XnGH{~ml+8( z2b(LHmvD1cbA;KcYmPNLE2MJO#H6pJTlc_#RS#|T?ccL|&<*>A2AJyZwU2D|-FHZ@ z1)c>33%m;kE$}ZWt?j?r_jhf{C%!;!r_~0N zzWob0vG4%CNu0aag0clcZgZgpl?%cPYD1fSN7gR*+IK{^c=~*XOCEki+|zhc56!8OXW0ZvMby~U7`IW z{K12qs};DPEx^P* z-%HTl3XD1?#UB>kB3J&LoFdlQ1icT@7?F z!2Gwb18wL+4_xSj4-wo!0y9Wq0nDA#o#m)bI=3*Vo24}!%WRzP!T=}6tn@-_E7ncx z#%AB2v}QYDFYJdtHfDwm!5>ga2PLTRoRb234uVf%Z-5%cB0(Kfk%?SHqs2&*CVHkP jeK|p9CsO%_IS9IqyI>N;zqy+Qd7xvUbg$L3$S(Z=$Y~!G delta 740518 zcmbrn34Dy#_dh<*OhS;!OeB+qiENVyi7aA?JtGMd5@HEz4MDZElti`EM3a!|V{Dg> zZkD3eO|^Dy39+w1i&mAE>XSz8G^))1eeRu!w4cxS`~SUuKd;xg_c`Z%&pr3tbJyoS zH$|71Nkx@RTGUzcTHGbgn$YQJ!Nj5Kn!A5t5g$bN#&cN2s_4fEJ0z^)&m9t0M~~&t zA4HGg{MFIvJX{++3*p3}Yn#^_wyya);I`saqvIMUg6{RN^W4f2mQb0uy5M!&Czohc^w#LnNgRU!`iI zn$T!*coV<)f^jnnfK0rCO!bId4Q8?GkaiOmdf}l7L?cwdtMe~arAmz-JGx*rXxks) zzeN!$)z=7Tu-WP+K3o%Mq?(Hy+prJRp$)^LR4O$9J5B7Qx>;+et*VE|uSv(J|58cr z)Nzw0=c|PJD26H;{Jka?s`+_wqSq3S3H2TYtCU6Guopd|M<7}?_8TA7G5oXGW|@M_ zgDl0@!?NVt7P~eU+B*%$?**$Ya*d_5ywKYs&oZT2iuZ+?M^*sP1OSU|xGB+T_>iN{ z6Uu0jPdW`7?gg{k9)Z@sok(sgFr_#RFLBH*V00yRl+0o`JRvT@M-b2ExuRpFiu1<` z{sT9^i{Q_7^V0?Y2In7j8bSnrx|?qj{GY6Dz~j3-gOP54hX9;#^Dhd14>$iRtOf-S zxcT1*e!QE%Pw;oS`R@sSfSbQo@T~%H!fAL-0P48`B>?P%5~>|jP_s_MHyt8XrR6iG zSnQtt;kp)E7a5dHTRjkxyj6(x@ItglLmt&5+FQq?L5QZ-=g}}kqXabu(cc@XI#aqt z#3ze%DH|n=EucnC+<-qh@KFs_VTXHLVF& zIdgJQcV$~d(Hx*y?Ad|J6K3@alfGfAyqc(Mg4x$zu@qE!byPoW%Ay*qHa#HO-#c?s z3Hc~~<8DYSH9S3?^!x8HH z!R-Bp!x1cLR6-AP8@;B6n|XQ{A=os}yM<&;%^ft@JkXqL9%LSDk*~v<^DOe5O4vCg z`Hw8y3pH8tLyLSQTfS_O@9d@)l_gK{%Cb%HQch*~qXG&&&GO^w&`cS2&#lRXZ59O~ zb!oX-XL)Rym{Bt})8=7oMDg+1tp%8q52sZD1v{se9$7FK_QfgGHaa@+~PWfQT{xpuX1qTHUf%5s~$oGH&EhjHsDTlBW z&i?vLIe^@%KPo~vMzK>};E`>MGoh@-`|`}A%p=Vs%)>{G98p0%cj@7Rp#!MnW)1ab z>q|k%_h2!Vf&Ni{J**;?^PPt4@o4(8)-xdzea<|LOL#a0TJi<-3pWu#KP{+l6Vev) z38#%9nk{6mpv@COnFtn(V2KD=fC!h0V4VmS#Iro#=FM{PM85JV=_O~GQnKuxi*G`- z-SGU)V7AV;gZgYMcG-83X4my#)}e8@`j-GUym9-q79DhGsTgz&-EI+Fn~EUIZjqFg zjZs>eMxKH&vwe_+F3I9F1h=A$UU^Qg1l9zs@+UjnINKT=pi{Ljhe;C6BS(!KHlhOV zVSy62|KLg-p#ZMCs2mC+y$?_SH8iZ6=5#s<3>7v5MamHHP+j0x1ngA{%)R9_#Kdt$ zgrEv50b05N)J9OnN0kx-m4UaMn&i`2wn9s${FBqrs&3l#l=S8kD1qL!1ZybG zR96mw<)eBg`A7OKBYNkj^e&*k?;oj|huS>k9~FU6RrS+jp&5FLMCG-6PG_xUmjk9V zgs3b1SiGT~TJdM&4Wa67&DlIdl2pQW82YP|LYOunr`7J?sVol_2XC2FjO<$^^}Mn! z5WWPbDt#YS0o4kB4`y!!L~ABh1+z^7F_Of73<&XFLt`pDE>Y>wn0W>!H1LAo(6r~6 z!?#6{AIk}B;;*ivdVR=y(;4lu>`{v$YIa~#zlvTS@P@)R7H5T}_@LfW{7B0_4ea8T zf5+*x)vG?j=FIS89zjV-^}CUqrel(1H>@Fz?b@XXvh3a&G}b78dQ(MbfiItT8Wvv* zX5)iGV-_M`U1$*istyec^cE)^bT4wL(N4XYTwY<(pklORs)9Ft7IaYxnd+xfjbB8A z^?;y~@Z5nB8AZe0N_UA)hR2PJ?A3|nIL)oBa zaY4WPYoNbej!MW#en9<>Px5Ky-Z=Jlvk@6>!!c~jhrmR%*f*_0V3wa)WFO`I7}hy7q=^RoIFhUBW+*f`m~KizkyMK3 zB+6dhR7!d$9h2umcE`hbvjzh`9P+QT)J4HX-68 z>za^ARkr+4zM~|Oq3qgSASmPXRJGcthSrTOL%IVw;?zG&lwG+81tz*0!FL;F}g5ie+E;H3)d>NKeSKHSdwM zkwz5!0E{OOo|Hw?2yHM?OsjlUCFKP}xy@l86A@SXXjD7&wCGa4^I*qJ&4&EZ6qRi= zqXBC7@~Gzp1j+(l83(K0;clr@R*d5XPE-m#TqU2xBPW%y2$Ru=X^Sb{AXmD4hjqCj zjE#!wqE7W-E27>_ZLQU)bX#vhrIDD)o2b9DeNsl|v84ssvoQnn>}%k}B0&rT&COH=m_hCEcs{UN31)j zLOqqnz9{!MV=1*lb?F6{pI{z7qT)chDG>(teCeXoiFgb=UAyHW#umHh3IrA#X81d? z0!DkEWXefCtkk^igD#Q_3AD(^l|wL3mJA*rmbpw!hpi^jU!dJ*mtN&<8zo&K2xcRx~g;~4-v^Iaq3EMA+j?L|6$FfyaaJs zTugx`y$p?88wx3yN0lDdm23t`7n%xS1B-lC`85p9sk{J_;jBwuG>V|TU#(h5puyz_ zO1Rb%`VqUfI*_Wu(>f4ZSY(e&I$zIVirQK=A-#M(n#DJ_9 z!51RfDS`?Fm~Oy{ut4{|WZouWYJi+3f^L!F#Wv3gh-Q~QD9~owtuKq6Yj+G zxy_W9R8(TJlDyVb1m(F=exOop6_zi#pewzMXI=wG5y_OlMWIq*80E}zA5~QaXt4L6 zKk^=G2+y1M8T->yW&{;ZfjN>-qX^a>#Ik97BG@E>5J1m%?a2Tl8&dEDqAv%vQj4cG z;K4F~BLHum2sVgdn+VDga3d6=(P)3b6UK9|s#o}oOeYL7oTye|k!J{R7>55hO4VbK zWYtBKq!CI&ik2gr1VY<9*CW7Fk_bAAAWZ~WBFGiNND(}XzykL_IYtK~9aqjlCRzXn zI;_VEOilA>>d)H%jeWdNf-sBU8cTNxm#aD z4vg7qBc=T)=7V%12?a++T5A9Sx7^|H`i~N^GzO793gioPQ3P%0>c@FjSHsgabl^Zro97Q9uPh%?I za7-gGJmFk(T0aprSMXm#f&Qxi4Ogj zM4NewYrMNt(=iuvZde;{W`P zOZ^*xk^rgpp73R;?h-p6QskB7`y_b-JDC^|aPB7j9Uf{VkzusmF+{Jt&K@O3cYRq% zn?=$-U*y&i^EC_^iHeqleMPfYm_)0L+~kA3CtEQQsF=;zsH7OFEh|gvs+s$z4?CO` zqCPN=DM{U=To%*1lXcG-GA=6ps1lFGCDkCG4f486rR~&I^!65efhotL%ebvHAi?m~ z0GMqV(%R}N?H0O}O2xLSto>X|t~$w-NF!31k}{OL(H>BhNh*y>Rgn{71DF>1P1R9hwS=%_B^YFw1~nV>fA*DMuNCO2jabPL@i+LX&)4=Nj)Y zm%{cE8iS2*&gDT|3sQ$tI}cjy!#tE=p1klo@~9MxH6PO^WMe+)F_&5u65RHNru&|u ze(iuQo(7CCYWn1TC}5qIOi^@2&jDXc-cIYJ+NWd3Qga6kw%8|`c39?IU&ZDBr6||= z$`55OXlAt(Z|6H51>v*>wBQf0>{{n()b%fRZq_;bDBUPp>)SS)%1MU3j5@U}+gcMX z-)Y7Dsi_jNEC9s3<7+YEB{{;OWYLUsG~ePKf#)?)P~{ezH4TOHyiAX_v>2uD zHOfDi_Z5bZK`p^%w_Zb4?kpIf)7RJerVYHK)A!Zi(fRfsTWs}G&Gs&~daGvF%d+R^ zRr|^rmndRO8!l&DF=MN-xSOi5o}6*cmNu~1>aQv^$r-=d(#Fae)wZ+=)d5zWKI0sv za0$--jSD8KC4azh?0RO(`@rjrOa(71D?j6sB|rO0dZ)dGjXU+uv)I$}3LB)`KG_JP zR7YC!RTkanm6^KF50RBr=It0Aot93g%(@=swqgRwX#+cCoJ)s~hFNvX$}^G=mlbaY z9lMF=}-fm6BGhE?M>KOtbkz0709D!)8 z6__G-eG{u4nj3S3T^oJH=~PyCM@zRA)9M-}ENn(8FOowc^!%M9XcwG>V?XnT58t;x zs@$w1ZbdaFmPeH@UCUCxb38(GH!dO5-@Sva}nX#?SH6FpXnrMQd9 z3ooE_B^^i^Svwg|H1J}@FbjQ>SFTRHynsqYU@3ziQA25)LomDcIRxm5y7WhweA;r* zvn?X@57CaUs1n7KXan%9R1HMQ(L$Q>0l^}V!m8w?a^@C|3y&;Vh+gO87xheh08b@h z)U#p4JVBjPj&gQBfuS6nC<-$htI4AH{YDEBzTI*{pgHtYKrxPAa2npI4}E1VL!bnZ z4w%*u^u`(k|s6?VwD}VW9lK}NBt>d?Qp~`a>xrrioxs$#nzSVBBROLR3cvCxR5Nu z**&{(xHg&sn`bu)4tmBRpnuA5ge3v5IaXRV!O|J_OvhdgKf2)wX-AcpZm`cfwj0`@ zMy)EYk@$or*AqF^^utnk0LE)=A9{Q!^MS&5C+`64+GmLP?VnWB+9)?3^7w#PHSsEZ z(KYlfJJrO6-t@-&^MF;j__357a6&keKnh7klU6zqG8ox@(8=E5D-~dFYPr z8EuCn!KynJUEE=1@=(^Ti@B2r2xjbS%2mpo&wNyw2g^mF3>q-x;}}AfS3dRO%b#Y& zHBLU6^a4xKl(4V5nCf?-`1xXX4e{0#|E!q#c5SN8YtQ1lW{xv_K*KQYPiqcC-l25J zyN#(tRz7B%pn8I8hI1YNl5iME4PUt^M+rs4E@-=5wDy~QROz~{w69?|>~#_Me!+h1 zn&>eFIXS{!)P=HyZeCq-*SYhJ1We?c#3fQ5&0R@Xg2LsIDlJ{amS3=fZprHJ*0GPe z#pi5U>lU=;pj*&lQr1;~b)ZrKUigA=Bz)K*L7B*lBnmLfMLYK;Yo3~{j#$Trr{-91 zHH0(fpS0K~I5DzRQ6swuQYNN+8bvwHqsJ(Ekbur|L@ihnWh&GVX|kv*xdx}slJ_5= z6(t7OL&~SLlV>+nK`oNk3XkxJRA4|o!>K2gc?6OpPbiZixM)_Qvy-lLH6)>n+5(6& zqlj`isZ{>P`k3?7PrTShb5Qs|V%@X~R?pvP5>f37!L*hIc)u5`GS9Tu)F;`bT_F~Z zCzSQq2w1g^6t#^-&B-UT&{s}SbX#@aY$A@?2<$}63N-~e0%+k~-F%(73 zpimmT6+Nf?cGazvuH;K7&fmhFMa{q_N<(ZGf{-a=l6X}4+ojIft88a_Qt}sIQq`k{ ze1ND$a|==}cypsXTPw4mYnHu-{QqU{p5+gVDfGW4;?CkS-T$14c$m3XL**rO={+zYiioi z{Q4I*wMR=$xzmTO?9o&+^^p(zrbmkASv=SDh?IWWWbCPzyf^QGG~0wQ)QEJM3q zMi+UZpbxFq%U}kJW+axSN0qy3s@^^+^k&jNLqdyDik_>dvUECF5NeU^`KXMg*`|

cUkX(=3rS0l8i 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�! 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

hOGA(rY(OD$haUoxH_e7(1;KQLdT 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

3m!n3;+Y~Pcw)b7r8u76hz3Ow%zxsV_$#;A# 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 Y8VL7(K^O~$_|d!ApDM#GGdGL>1C&#ixc~qF literal 268842 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 diff --git a/vendor/sdl3/include/SDL.h b/vendor/sdl3/include/SDL.h index 861c404f5..9d2168877 100644 --- a/vendor/sdl3/include/SDL.h +++ b/vendor/sdl3/include/SDL.h @@ -20,7 +20,7 @@ */ /** - * Main include header for the SDL library, version 3.2.0 + * Main include header for the SDL library, version 3.2.10 * * It is almost always best to include just this one header instead of * picking out individual headers included here. There are exceptions to diff --git a/vendor/sdl3/include/SDL_assert.h b/vendor/sdl3/include/SDL_assert.h index 09b3b478f..6c90acc02 100644 --- a/vendor/sdl3/include/SDL_assert.h +++ b/vendor/sdl3/include/SDL_assert.h @@ -149,6 +149,8 @@ extern "C" { #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" ) #elif defined(_WIN32) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__arm64__) || defined(__aarch64__)) ) #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #0xF000\n\t" ) +#elif defined(__GNUC__) || defined(__clang__) + #define SDL_TriggerBreakpoint() __builtin_trap() /* older gcc may not support SDL_HAS_BUILTIN(__builtin_trap) above */ #elif defined(__386__) && defined(__WATCOMC__) #define SDL_TriggerBreakpoint() { _asm { int 0x03 } } #elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__) diff --git a/vendor/sdl3/include/SDL_atomic.h b/vendor/sdl3/include/SDL_atomic.h index 03e3fb134..78b5e0fa5 100644 --- a/vendor/sdl3/include/SDL_atomic.h +++ b/vendor/sdl3/include/SDL_atomic.h @@ -498,7 +498,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_AddAtomicInt(SDL_AtomicInt *a, int v); * * ***Note: If you don't know what this macro is for, you shouldn't use it!*** * - * \param a a pointer to an SDL_AtomicInt to increment. + * \param a a pointer to an SDL_AtomicInt to decrement. * \returns true if the variable reached zero after decrementing, false * otherwise. * diff --git a/vendor/sdl3/include/SDL_audio.h b/vendor/sdl3/include/SDL_audio.h index 956938215..c6acf885f 100644 --- a/vendor/sdl3/include/SDL_audio.h +++ b/vendor/sdl3/include/SDL_audio.h @@ -781,7 +781,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_IsAudioDevicePlayback(SDL_AudioDeviceID dev * Physical devices can not be paused or unpaused, only logical devices * created through SDL_OpenAudioDevice() can be. * - * \param dev a device opened by SDL_OpenAudioDevice(). + * \param devid a device opened by SDL_OpenAudioDevice(). * \returns true on success or false on failure; call SDL_GetError() for more * information. * @@ -792,7 +792,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_IsAudioDevicePlayback(SDL_AudioDeviceID dev * \sa SDL_ResumeAudioDevice * \sa SDL_AudioDevicePaused */ -extern SDL_DECLSPEC bool SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev); +extern SDL_DECLSPEC bool SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID devid); /** * Use this function to unpause audio playback on a specified device. @@ -809,7 +809,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev); * Physical devices can not be paused or unpaused, only logical devices * created through SDL_OpenAudioDevice() can be. * - * \param dev a device opened by SDL_OpenAudioDevice(). + * \param devid a device opened by SDL_OpenAudioDevice(). * \returns true on success or false on failure; call SDL_GetError() for more * information. * @@ -820,7 +820,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev); * \sa SDL_AudioDevicePaused * \sa SDL_PauseAudioDevice */ -extern SDL_DECLSPEC bool SDLCALL SDL_ResumeAudioDevice(SDL_AudioDeviceID dev); +extern SDL_DECLSPEC bool SDLCALL SDL_ResumeAudioDevice(SDL_AudioDeviceID devid); /** * Use this function to query if an audio device is paused. @@ -832,7 +832,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ResumeAudioDevice(SDL_AudioDeviceID dev); * created through SDL_OpenAudioDevice() can be. Physical and invalid device * IDs will report themselves as unpaused here. * - * \param dev a device opened by SDL_OpenAudioDevice(). + * \param devid a device opened by SDL_OpenAudioDevice(). * \returns true if device is valid and paused, false otherwise. * * \threadsafety It is safe to call this function from any thread. @@ -842,7 +842,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ResumeAudioDevice(SDL_AudioDeviceID dev); * \sa SDL_PauseAudioDevice * \sa SDL_ResumeAudioDevice */ -extern SDL_DECLSPEC bool SDLCALL SDL_AudioDevicePaused(SDL_AudioDeviceID dev); +extern SDL_DECLSPEC bool SDLCALL SDL_AudioDevicePaused(SDL_AudioDeviceID devid); /** * Get the gain of an audio device. @@ -1583,6 +1583,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PauseAudioStreamDevice(SDL_AudioStream *str * previously been paused. Once unpaused, any bound audio streams will begin * to progress again, and audio can be generated. * + * Remember, SDL_OpenAudioDeviceStream opens device in a paused state, so this + * function call is required for audio playback to begin on such device. + * * \param stream the audio stream associated with the audio device to resume. * \returns true on success or false on failure; call SDL_GetError() for more * information. @@ -1714,7 +1717,7 @@ typedef void (SDLCALL *SDL_AudioStreamCallback)(void *userdata, SDL_AudioStream * audio to the stream during this call; if needed, the request that triggered * this callback will obtain the new data immediately. * - * The callback's `approx_request` argument is roughly how many bytes of + * The callback's `additional_amount` argument is roughly how many bytes of * _unconverted_ data (in the stream's input format) is needed by the caller, * although this may overestimate a little for safety. This takes into account * how much is already in the stream and only asks for any extra necessary to @@ -1759,13 +1762,13 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetAudioStreamGetCallback(SDL_AudioStream * * The callback can (optionally) call SDL_GetAudioStreamData() to obtain audio * from the stream during this call. * - * The callback's `approx_request` argument is how many bytes of _converted_ - * data (in the stream's output format) was provided by the caller, although - * this may underestimate a little for safety. This value might be less than - * what is currently available in the stream, if data was already there, and - * might be less than the caller provided if the stream needs to keep a buffer - * to aid in resampling. Which means the callback may be provided with zero - * bytes, and a different amount on each call. + * The callback's `additional_amount` argument is how many bytes of + * _converted_ data (in the stream's output format) was provided by the + * caller, although this may underestimate a little for safety. This value + * might be less than what is currently available in the stream, if data was + * already there, and might be less than the caller provided if the stream + * needs to keep a buffer to aid in resampling. Which means the callback may + * be provided with zero bytes, and a different amount on each call. * * The callback may call SDL_GetAudioStreamAvailable to see the total amount * currently available to read from the stream, instead of the total provided diff --git a/vendor/sdl3/include/SDL_camera.h b/vendor/sdl3/include/SDL_camera.h index c4d05962b..5f3911fdf 100644 --- a/vendor/sdl3/include/SDL_camera.h +++ b/vendor/sdl3/include/SDL_camera.h @@ -239,7 +239,7 @@ extern SDL_DECLSPEC SDL_CameraID * SDLCALL SDL_GetCameras(int *count); * there _is_ a camera until the user has given you permission to check * through a scary warning popup. * - * \param devid the camera device instance ID to query. + * \param instance_id the camera device instance ID. * \param count a pointer filled in with the number of elements in the list, * may be NULL. * \returns a NULL terminated array of pointers to SDL_CameraSpec or NULL on @@ -254,7 +254,7 @@ extern SDL_DECLSPEC SDL_CameraID * SDLCALL SDL_GetCameras(int *count); * \sa SDL_GetCameras * \sa SDL_OpenCamera */ -extern SDL_DECLSPEC SDL_CameraSpec ** SDLCALL SDL_GetCameraSupportedFormats(SDL_CameraID devid, int *count); +extern SDL_DECLSPEC SDL_CameraSpec ** SDLCALL SDL_GetCameraSupportedFormats(SDL_CameraID instance_id, int *count); /** * Get the human-readable device name for a camera. diff --git a/vendor/sdl3/include/SDL_dialog.h b/vendor/sdl3/include/SDL_dialog.h index 460038ff2..ddb9e24d5 100644 --- a/vendor/sdl3/include/SDL_dialog.h +++ b/vendor/sdl3/include/SDL_dialog.h @@ -84,8 +84,8 @@ typedef struct SDL_DialogFileFilter * - A pointer to NULL, the user either didn't choose any file or canceled the * dialog. * - A pointer to non-`NULL`, the user chose one or more files. The argument - * is a null-terminated list of pointers to C strings, each containing a - * path. + * is a null-terminated array of pointers to UTF-8 encoded strings, each + * containing a path. * * The filelist argument should not be freed; it will automatically be freed * when the callback returns. diff --git a/vendor/sdl3/include/SDL_events.h b/vendor/sdl3/include/SDL_events.h index 1323e9f0b..56a2194b3 100644 --- a/vendor/sdl3/include/SDL_events.h +++ b/vendor/sdl3/include/SDL_events.h @@ -132,7 +132,7 @@ typedef enum SDL_EventType /* Window events */ /* 0x200 was SDL_WINDOWEVENT, reserve the number for sdl2-compat */ - /* 0x201 was SDL_EVENT_SYSWM, reserve the number for sdl2-compat */ + /* 0x201 was SDL_SYSWMEVENT, reserve the number for sdl2-compat */ SDL_EVENT_WINDOW_SHOWN = 0x202, /**< Window has been shown */ SDL_EVENT_WINDOW_HIDDEN, /**< Window has been hidden */ SDL_EVENT_WINDOW_EXPOSED, /**< Window has been exposed and should be redrawn, and can be redrawn directly from event watchers for this event */ @@ -1108,7 +1108,7 @@ typedef enum SDL_EventAction * \param numevents if action is SDL_ADDEVENT, the number of events to add * back to the event queue; if action is SDL_PEEKEVENT or * SDL_GETEVENT, the maximum number of events to retrieve. - * \param action action to take; see [[#action|Remarks]] for details. + * \param action action to take; see [Remarks](#remarks) for details. * \param minType minimum value of the event type to be considered; * SDL_EVENT_FIRST is a safe choice. * \param maxType maximum value of the event type to be considered; diff --git a/vendor/sdl3/include/SDL_gamepad.h b/vendor/sdl3/include/SDL_gamepad.h index 264f763b2..99f8b6593 100644 --- a/vendor/sdl3/include/SDL_gamepad.h +++ b/vendor/sdl3/include/SDL_gamepad.h @@ -29,7 +29,7 @@ * "joysticks" now are actually console-style gamepads. So SDL provides the * gamepad API on top of the lower-level joystick functionality. * - * The difference betweena joystick and a gamepad is that a gamepad tells you + * The difference between a joystick and a gamepad is that a gamepad tells you * _where_ a button or axis is on the device. You don't speak to gamepads in * terms of arbitrary numbers like "button 3" or "axis 2" but in standard * locations: the d-pad, the shoulder buttons, triggers, A/B/X/Y (or diff --git a/vendor/sdl3/include/SDL_gpu.h b/vendor/sdl3/include/SDL_gpu.h index fa870a579..9f516d73f 100644 --- a/vendor/sdl3/include/SDL_gpu.h +++ b/vendor/sdl3/include/SDL_gpu.h @@ -35,13 +35,14 @@ * can render offscreen entirely, perhaps for image processing, and not use a * window at all. * - * Next the app prepares static data (things that are created once and used + * Next, the app prepares static data (things that are created once and used * over and over). For example: * * - Shaders (programs that run on the GPU): use SDL_CreateGPUShader(). - * - Vertex buffers (arrays of geometry data) and other data rendering will - * need: use SDL_UploadToGPUBuffer(). - * - Textures (images): use SDL_UploadToGPUTexture(). + * - Vertex buffers (arrays of geometry data) and other rendering data: use + * SDL_CreateGPUBuffer() and SDL_UploadToGPUBuffer(). + * - Textures (images): use SDL_CreateGPUTexture() and + * SDL_UploadToGPUTexture(). * - Samplers (how textures should be read from): use SDL_CreateGPUSampler(). * - Render pipelines (precalculated rendering state): use * SDL_CreateGPUGraphicsPipeline() @@ -130,7 +131,8 @@ * It is optimal for apps to pre-compile the shader formats they might use, * but for ease of use SDL provides a separate project, * [SDL_shadercross](https://github.com/libsdl-org/SDL_shadercross) - * , for performing runtime shader cross-compilation. + * , for performing runtime shader cross-compilation. It also has a CLI + * interface for offline precompilation as well. * * This is an extremely quick overview that leaves out several important * details. Already, though, one can see that GPU programming can be quite @@ -888,6 +890,10 @@ typedef enum SDL_GPUCubeMapFace * Unlike textures, READ | WRITE can be used for simultaneous read-write * usage. The same data synchronization concerns as textures apply. * + * If you use a STORAGE flag, the data in the buffer must respect std140 + * layout conventions. In practical terms this means you must ensure that vec3 + * and vec4 fields are 16-byte aligned. + * * \since This datatype is available since SDL 3.2.0. * * \sa SDL_CreateGPUBuffer @@ -1361,6 +1367,7 @@ typedef struct SDL_GPUTextureLocation * * \sa SDL_UploadToGPUTexture * \sa SDL_DownloadFromGPUTexture + * \sa SDL_CreateGPUTexture */ typedef struct SDL_GPUTextureRegion { @@ -1489,9 +1496,16 @@ typedef struct SDL_GPUIndirectDispatchCommand /** * A structure specifying the parameters of a sampler. * + * Note that mip_lod_bias is a no-op for the Metal driver. For Metal, LOD bias + * must be applied via shader instead. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateGPUSampler + * \sa SDL_GPUFilter + * \sa SDL_GPUSamplerMipmapMode + * \sa SDL_GPUSamplerAddressMode + * \sa SDL_GPUCompareOp */ typedef struct SDL_GPUSamplerCreateInfo { @@ -1530,14 +1544,14 @@ typedef struct SDL_GPUSamplerCreateInfo * \since This struct is available since SDL 3.2.0. * * \sa SDL_GPUVertexAttribute - * \sa SDL_GPUVertexInputState + * \sa SDL_GPUVertexInputRate */ typedef struct SDL_GPUVertexBufferDescription { Uint32 slot; /**< The binding slot of the vertex buffer. */ Uint32 pitch; /**< The byte pitch between consecutive elements of the vertex buffer. */ SDL_GPUVertexInputRate input_rate; /**< Whether attribute addressing is a function of the vertex index or instance index. */ - Uint32 instance_step_rate; /**< The number of instances to draw using the same per-instance data before advancing in the instance buffer by one element. Ignored unless input_rate is SDL_GPU_VERTEXINPUTRATE_INSTANCE */ + Uint32 instance_step_rate; /**< Reserved for future use. Must be set to 0. */ } SDL_GPUVertexBufferDescription; /** @@ -1550,6 +1564,7 @@ typedef struct SDL_GPUVertexBufferDescription * * \sa SDL_GPUVertexBufferDescription * \sa SDL_GPUVertexInputState + * \sa SDL_GPUVertexElementFormat */ typedef struct SDL_GPUVertexAttribute { @@ -1706,10 +1721,13 @@ typedef struct SDL_GPUTransferBufferCreateInfo * A structure specifying the parameters of the graphics pipeline rasterizer * state. * - * NOTE: Some backend APIs (D3D11/12) will enable depth clamping even if - * enable_depth_clip is true. If you rely on this clamp+clip behavior, - * consider enabling depth clip and then manually clamping depth in your - * fragment shaders on Metal and Vulkan. + * Note that SDL_GPU_FILLMODE_LINE is not supported on many Android devices. + * For those devices, the fill mode will automatically fall back to FILL. + * + * Also note that the D3D12 driver will enable depth clamping even if + * enable_depth_clip is true. If you need this clamp+clip behavior, consider + * enabling depth clip and then manually clamping depth in your fragment + * shaders on Metal and Vulkan. * * \since This struct is available since SDL 3.2.0. * @@ -1740,8 +1758,8 @@ typedef struct SDL_GPURasterizerState typedef struct SDL_GPUMultisampleState { SDL_GPUSampleCount sample_count; /**< The number of samples to be used in rasterization. */ - Uint32 sample_mask; /**< Determines which samples get updated in the render targets. Treated as 0xFFFFFFFF if enable_mask is false. */ - bool enable_mask; /**< Enables sample masking. */ + Uint32 sample_mask; /**< Reserved for future use. Must be set to 0. */ + bool enable_mask; /**< Reserved for future use. Must be set to false. */ Uint8 padding1; Uint8 padding2; Uint8 padding3; @@ -1791,6 +1809,8 @@ typedef struct SDL_GPUColorTargetDescription * \since This struct is available since SDL 3.2.0. * * \sa SDL_GPUGraphicsPipelineCreateInfo + * \sa SDL_GPUColorTargetDescription + * \sa SDL_GPUTextureFormat */ typedef struct SDL_GPUGraphicsPipelineTargetInfo { @@ -1809,6 +1829,7 @@ typedef struct SDL_GPUGraphicsPipelineTargetInfo * \since This struct is available since SDL 3.2.0. * * \sa SDL_CreateGPUGraphicsPipeline + * \sa SDL_GPUShader * \sa SDL_GPUVertexInputState * \sa SDL_GPUPrimitiveType * \sa SDL_GPURasterizerState @@ -1836,6 +1857,7 @@ typedef struct SDL_GPUGraphicsPipelineCreateInfo * \since This struct is available since SDL 3.2.0. * * \sa SDL_CreateGPUComputePipeline + * \sa SDL_GPUShaderFormat */ typedef struct SDL_GPUComputePipelineCreateInfo { @@ -2104,7 +2126,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUSupportsProperties( * \sa SDL_DestroyGPUDevice * \sa SDL_GPUSupportsShaderFormats */ -extern SDL_DECLSPEC SDL_GPUDevice *SDLCALL SDL_CreateGPUDevice( +extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice( SDL_GPUShaderFormat format_flags, bool debug_mode, const char *name); @@ -2152,7 +2174,7 @@ extern SDL_DECLSPEC SDL_GPUDevice *SDLCALL SDL_CreateGPUDevice( * \sa SDL_DestroyGPUDevice * \sa SDL_GPUSupportsProperties */ -extern SDL_DECLSPEC SDL_GPUDevice *SDLCALL SDL_CreateGPUDeviceWithProperties( +extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties( SDL_PropertiesID props); #define SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN "SDL.gpu.device.create.debugmode" @@ -2275,7 +2297,7 @@ extern SDL_DECLSPEC SDL_GPUShaderFormat SDLCALL SDL_GetGPUShaderFormats(SDL_GPUD * \sa SDL_BindGPUComputePipeline * \sa SDL_ReleaseGPUComputePipeline */ -extern SDL_DECLSPEC SDL_GPUComputePipeline *SDLCALL SDL_CreateGPUComputePipeline( +extern SDL_DECLSPEC SDL_GPUComputePipeline * SDLCALL SDL_CreateGPUComputePipeline( SDL_GPUDevice *device, const SDL_GPUComputePipelineCreateInfo *createinfo); @@ -2302,7 +2324,7 @@ extern SDL_DECLSPEC SDL_GPUComputePipeline *SDLCALL SDL_CreateGPUComputePipeline * \sa SDL_BindGPUGraphicsPipeline * \sa SDL_ReleaseGPUGraphicsPipeline */ -extern SDL_DECLSPEC SDL_GPUGraphicsPipeline *SDLCALL SDL_CreateGPUGraphicsPipeline( +extern SDL_DECLSPEC SDL_GPUGraphicsPipeline * SDLCALL SDL_CreateGPUGraphicsPipeline( SDL_GPUDevice *device, const SDL_GPUGraphicsPipelineCreateInfo *createinfo); @@ -2329,7 +2351,7 @@ extern SDL_DECLSPEC SDL_GPUGraphicsPipeline *SDLCALL SDL_CreateGPUGraphicsPipeli * \sa SDL_BindGPUFragmentSamplers * \sa SDL_ReleaseGPUSampler */ -extern SDL_DECLSPEC SDL_GPUSampler *SDLCALL SDL_CreateGPUSampler( +extern SDL_DECLSPEC SDL_GPUSampler * SDLCALL SDL_CreateGPUSampler( SDL_GPUDevice *device, const SDL_GPUSamplerCreateInfo *createinfo); @@ -2408,7 +2430,7 @@ extern SDL_DECLSPEC SDL_GPUSampler *SDLCALL SDL_CreateGPUSampler( * \sa SDL_CreateGPUGraphicsPipeline * \sa SDL_ReleaseGPUShader */ -extern SDL_DECLSPEC SDL_GPUShader *SDLCALL SDL_CreateGPUShader( +extern SDL_DECLSPEC SDL_GPUShader * SDLCALL SDL_CreateGPUShader( SDL_GPUDevice *device, const SDL_GPUShaderCreateInfo *createinfo); @@ -2469,7 +2491,7 @@ extern SDL_DECLSPEC SDL_GPUShader *SDLCALL SDL_CreateGPUShader( * \sa SDL_ReleaseGPUTexture * \sa SDL_GPUTextureSupportsFormat */ -extern SDL_DECLSPEC SDL_GPUTexture *SDLCALL SDL_CreateGPUTexture( +extern SDL_DECLSPEC SDL_GPUTexture * SDLCALL SDL_CreateGPUTexture( SDL_GPUDevice *device, const SDL_GPUTextureCreateInfo *createinfo); @@ -2490,6 +2512,10 @@ extern SDL_DECLSPEC SDL_GPUTexture *SDLCALL SDL_CreateGPUTexture( * Note that certain combinations of usage flags are invalid. For example, a * buffer cannot have both the VERTEX and INDEX flags. * + * If you use a STORAGE flag, the data in the buffer must respect std140 + * layout conventions. In practical terms this means you must ensure that vec3 + * and vec4 fields are 16-byte aligned. + * * For better understanding of underlying concepts and memory management with * SDL GPU API, you may refer * [this blog post](https://moonside.games/posts/sdl-gpu-concepts-cycling/) @@ -2521,7 +2547,7 @@ extern SDL_DECLSPEC SDL_GPUTexture *SDLCALL SDL_CreateGPUTexture( * \sa SDL_DispatchGPUComputeIndirect * \sa SDL_ReleaseGPUBuffer */ -extern SDL_DECLSPEC SDL_GPUBuffer *SDLCALL SDL_CreateGPUBuffer( +extern SDL_DECLSPEC SDL_GPUBuffer * SDLCALL SDL_CreateGPUBuffer( SDL_GPUDevice *device, const SDL_GPUBufferCreateInfo *createinfo); @@ -2554,7 +2580,7 @@ extern SDL_DECLSPEC SDL_GPUBuffer *SDLCALL SDL_CreateGPUBuffer( * \sa SDL_DownloadFromGPUTexture * \sa SDL_ReleaseGPUTransferBuffer */ -extern SDL_DECLSPEC SDL_GPUTransferBuffer *SDLCALL SDL_CreateGPUTransferBuffer( +extern SDL_DECLSPEC SDL_GPUTransferBuffer * SDLCALL SDL_CreateGPUTransferBuffer( SDL_GPUDevice *device, const SDL_GPUTransferBufferCreateInfo *createinfo); @@ -2782,7 +2808,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGPUGraphicsPipeline( * \sa SDL_SubmitGPUCommandBuffer * \sa SDL_SubmitGPUCommandBufferAndAcquireFence */ -extern SDL_DECLSPEC SDL_GPUCommandBuffer *SDLCALL SDL_AcquireGPUCommandBuffer( +extern SDL_DECLSPEC SDL_GPUCommandBuffer * SDLCALL SDL_AcquireGPUCommandBuffer( SDL_GPUDevice *device); /* Uniform Data */ @@ -2792,6 +2818,10 @@ extern SDL_DECLSPEC SDL_GPUCommandBuffer *SDLCALL SDL_AcquireGPUCommandBuffer( * * Subsequent draw calls will use this uniform data. * + * The data being pushed must respect std140 layout conventions. In practical + * terms this means you must ensure that vec3 and vec4 fields are 16-byte + * aligned. + * * \param command_buffer a command buffer. * \param slot_index the vertex uniform slot to push data to. * \param data client data to write. @@ -2810,6 +2840,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_PushGPUVertexUniformData( * * Subsequent draw calls will use this uniform data. * + * The data being pushed must respect std140 layout conventions. In practical + * terms this means you must ensure that vec3 and vec4 fields are 16-byte + * aligned. + * * \param command_buffer a command buffer. * \param slot_index the fragment uniform slot to push data to. * \param data client data to write. @@ -2828,6 +2862,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_PushGPUFragmentUniformData( * * Subsequent draw calls will use this uniform data. * + * The data being pushed must respect std140 layout conventions. In practical + * terms this means you must ensure that vec3 and vec4 fields are 16-byte + * aligned. + * * \param command_buffer a command buffer. * \param slot_index the uniform slot to push data to. * \param data client data to write. @@ -2868,7 +2906,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_PushGPUComputeUniformData( * * \sa SDL_EndGPURenderPass */ -extern SDL_DECLSPEC SDL_GPURenderPass *SDLCALL SDL_BeginGPURenderPass( +extern SDL_DECLSPEC SDL_GPURenderPass * SDLCALL SDL_BeginGPURenderPass( SDL_GPUCommandBuffer *command_buffer, const SDL_GPUColorTargetInfo *color_target_infos, Uint32 num_color_targets, @@ -2978,6 +3016,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUIndexBuffer( * * The textures must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER. * + * Be sure your shader is set up according to the requirements documented in + * SDL_CreateGPUShader(). + * * \param render_pass a render pass handle. * \param first_slot the vertex sampler slot to begin binding from. * \param texture_sampler_bindings an array of texture-sampler binding @@ -2986,6 +3027,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUIndexBuffer( * array. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_CreateGPUShader */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUVertexSamplers( SDL_GPURenderPass *render_pass, @@ -2999,12 +3042,17 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUVertexSamplers( * These textures must have been created with * SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ. * + * Be sure your shader is set up according to the requirements documented in + * SDL_CreateGPUShader(). + * * \param render_pass a render pass handle. * \param first_slot the vertex storage texture slot to begin binding from. * \param storage_textures an array of storage textures. * \param num_bindings the number of storage texture to bind from the array. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_CreateGPUShader */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUVertexStorageTextures( SDL_GPURenderPass *render_pass, @@ -3018,12 +3066,17 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUVertexStorageTextures( * These buffers must have been created with * SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ. * + * Be sure your shader is set up according to the requirements documented in + * SDL_CreateGPUShader(). + * * \param render_pass a render pass handle. * \param first_slot the vertex storage buffer slot to begin binding from. * \param storage_buffers an array of buffers. * \param num_bindings the number of buffers to bind from the array. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_CreateGPUShader */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUVertexStorageBuffers( SDL_GPURenderPass *render_pass, @@ -3036,6 +3089,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUVertexStorageBuffers( * * The textures must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER. * + * Be sure your shader is set up according to the requirements documented in + * SDL_CreateGPUShader(). + * * \param render_pass a render pass handle. * \param first_slot the fragment sampler slot to begin binding from. * \param texture_sampler_bindings an array of texture-sampler binding @@ -3044,6 +3100,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUVertexStorageBuffers( * array. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_CreateGPUShader */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUFragmentSamplers( SDL_GPURenderPass *render_pass, @@ -3057,12 +3115,17 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUFragmentSamplers( * These textures must have been created with * SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ. * + * Be sure your shader is set up according to the requirements documented in + * SDL_CreateGPUShader(). + * * \param render_pass a render pass handle. * \param first_slot the fragment storage texture slot to begin binding from. * \param storage_textures an array of storage textures. * \param num_bindings the number of storage textures to bind from the array. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_CreateGPUShader */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUFragmentStorageTextures( SDL_GPURenderPass *render_pass, @@ -3076,12 +3139,17 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUFragmentStorageTextures( * These buffers must have been created with * SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ. * + * Be sure your shader is set up according to the requirements documented in + * SDL_CreateGPUShader(). + * * \param render_pass a render pass handle. * \param first_slot the fragment storage buffer slot to begin binding from. * \param storage_buffers an array of storage buffers. * \param num_bindings the number of storage buffers to bind from the array. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_CreateGPUShader */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUFragmentStorageBuffers( SDL_GPURenderPass *render_pass, @@ -3245,7 +3313,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_EndGPURenderPass( * * \sa SDL_EndGPUComputePass */ -extern SDL_DECLSPEC SDL_GPUComputePass *SDLCALL SDL_BeginGPUComputePass( +extern SDL_DECLSPEC SDL_GPUComputePass * SDLCALL SDL_BeginGPUComputePass( SDL_GPUCommandBuffer *command_buffer, const SDL_GPUStorageTextureReadWriteBinding *storage_texture_bindings, Uint32 num_storage_texture_bindings, @@ -3269,6 +3337,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputePipeline( * * The textures must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER. * + * Be sure your shader is set up according to the requirements documented in + * SDL_CreateGPUShader(). + * * \param compute_pass a compute pass handle. * \param first_slot the compute sampler slot to begin binding from. * \param texture_sampler_bindings an array of texture-sampler binding @@ -3277,6 +3348,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputePipeline( * array. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_CreateGPUShader */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeSamplers( SDL_GPUComputePass *compute_pass, @@ -3290,12 +3363,17 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeSamplers( * These textures must have been created with * SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ. * + * Be sure your shader is set up according to the requirements documented in + * SDL_CreateGPUShader(). + * * \param compute_pass a compute pass handle. * \param first_slot the compute storage texture slot to begin binding from. * \param storage_textures an array of storage textures. * \param num_bindings the number of storage textures to bind from the array. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_CreateGPUShader */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeStorageTextures( SDL_GPUComputePass *compute_pass, @@ -3309,12 +3387,17 @@ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeStorageTextures( * These buffers must have been created with * SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ. * + * Be sure your shader is set up according to the requirements documented in + * SDL_CreateGPUShader(). + * * \param compute_pass a compute pass handle. * \param first_slot the compute storage buffer slot to begin binding from. * \param storage_buffers an array of storage buffer binding structs. * \param num_bindings the number of storage buffers to bind from the array. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_CreateGPUShader */ extern SDL_DECLSPEC void SDLCALL SDL_BindGPUComputeStorageBuffers( SDL_GPUComputePass *compute_pass, @@ -3389,7 +3472,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_EndGPUComputePass( /** * Maps a transfer buffer into application address space. * - * You must unmap the transfer buffer before encoding upload commands. + * You must unmap the transfer buffer before encoding upload commands. The + * memory is owned by the graphics driver - do NOT call SDL_free() on the + * returned pointer. * * \param device a GPU context. * \param transfer_buffer a transfer buffer. @@ -3399,7 +3484,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_EndGPUComputePass( * * \since This function is available since SDL 3.2.0. */ -extern SDL_DECLSPEC void *SDLCALL SDL_MapGPUTransferBuffer( +extern SDL_DECLSPEC void * SDLCALL SDL_MapGPUTransferBuffer( SDL_GPUDevice *device, SDL_GPUTransferBuffer *transfer_buffer, bool cycle); @@ -3430,7 +3515,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnmapGPUTransferBuffer( * * \since This function is available since SDL 3.2.0. */ -extern SDL_DECLSPEC SDL_GPUCopyPass *SDLCALL SDL_BeginGPUCopyPass( +extern SDL_DECLSPEC SDL_GPUCopyPass * SDLCALL SDL_BeginGPUCopyPass( SDL_GPUCommandBuffer *command_buffer); /** @@ -3848,6 +3933,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WaitForGPUSwapchain( * freed by the user. You MUST NOT call this function from any thread other * than the one that created the window. * + * The swapchain texture is write-only and cannot be used as a sampler or for + * another reading operation. + * * \param command_buffer a command buffer. * \param window a window that has been claimed. * \param swapchain_texture a pointer filled in with a swapchain texture @@ -3866,6 +3954,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WaitForGPUSwapchain( * * \sa SDL_SubmitGPUCommandBuffer * \sa SDL_SubmitGPUCommandBufferAndAcquireFence + * \sa SDL_AcquireGPUSwapchainTexture */ extern SDL_DECLSPEC bool SDLCALL SDL_WaitAndAcquireGPUSwapchainTexture( SDL_GPUCommandBuffer *command_buffer, @@ -3922,7 +4011,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SubmitGPUCommandBuffer( * \sa SDL_SubmitGPUCommandBuffer * \sa SDL_ReleaseGPUFence */ -extern SDL_DECLSPEC SDL_GPUFence *SDLCALL SDL_SubmitGPUCommandBufferAndAcquireFence( +extern SDL_DECLSPEC SDL_GPUFence * SDLCALL SDL_SubmitGPUCommandBufferAndAcquireFence( SDL_GPUCommandBuffer *command_buffer); /** @@ -4004,6 +4093,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_QueryGPUFence( /** * Releases a fence obtained from SDL_SubmitGPUCommandBufferAndAcquireFence. * + * You must not reference the fence after calling this function. + * * \param device a GPU context. * \param fence a fence. * @@ -4054,7 +4145,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUTextureSupportsFormat( * \param device a GPU context. * \param format the texture format to check. * \param sample_count the sample count to check. - * \returns a hardware-specific version of min(preferred, possible). + * \returns whether the sample count is supported for this texture format. * * \since This function is available since SDL 3.2.0. */ diff --git a/vendor/sdl3/include/SDL_guid.h b/vendor/sdl3/include/SDL_guid.h index e2f32ffc9..312c42c03 100644 --- a/vendor/sdl3/include/SDL_guid.h +++ b/vendor/sdl3/include/SDL_guid.h @@ -71,6 +71,8 @@ typedef struct SDL_GUID { * \param pszGUID buffer in which to write the ASCII string. * \param cbGUID the size of pszGUID, should be at least 33 bytes. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_StringToGUID @@ -87,6 +89,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_GUIDToString(SDL_GUID guid, char *pszGUID, * \param pchGUID string containing an ASCII representation of a GUID. * \returns a SDL_GUID structure. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GUIDToString diff --git a/vendor/sdl3/include/SDL_hints.h b/vendor/sdl3/include/SDL_hints.h index 8f2d074d1..9c8ad3f82 100644 --- a/vendor/sdl3/include/SDL_hints.h +++ b/vendor/sdl3/include/SDL_hints.h @@ -2191,6 +2191,28 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES "SDL_JOYSTICK_ZERO_CENTERED_DEVICES" +/** + * A variable containing a list of devices and their desired number of haptic + * (force feedback) enabled axis. + * + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form plus the number of desired axes, e.g. + * + * `0xAAAA/0xBBBB/1,0xCCCC/0xDDDD/3` + * + * This hint supports a "wildcard" device that will set the number of haptic + * axes on all initialized haptic devices which were not defined explicitly in + * this hint. + * + * `0xFFFF/0xFFFF/1` + * + * This hint should be set before a controller is opened. The number of haptic + * axes won't exceed the number of real axes found on the device. + * + * \since This hint is available since SDL 3.2.5. + */ +#define SDL_HINT_JOYSTICK_HAPTIC_AXES "SDL_JOYSTICK_HAPTIC_AXES" + /** * A variable that controls keycode representation in keyboard events. * @@ -2349,8 +2371,8 @@ extern "C" { #define SDL_HINT_MAC_OPENGL_ASYNC_DISPATCH "SDL_MAC_OPENGL_ASYNC_DISPATCH" /** - * A variable controlling whether the Option (⌥) key on macOS should be - * remapped to act as the Alt key. + * A variable controlling whether the Option key on macOS should be remapped + * to act as the Alt key. * * The variable can be set to the following values: * @@ -3585,6 +3607,22 @@ extern "C" { */ #define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER" +/** + * A variable controlling whether SDL should call XSelectInput() to enable + * input events on X11 windows wrapped by SDL windows. + * + * The variable can be set to the following values: + * + * - "0": Don't call XSelectInput(), assuming the native window code has done + * it already. + * - "1": Call XSelectInput() to enable input events. (default) + * + * This hint should be set before creating a window. + * + * \since This hint is available since SDL 3.2.10. + */ +#define SDL_HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT "SDL_VIDEO_X11_EXTERNAL_WINDOW_INPUT" + /** * A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint * should be used. @@ -4360,7 +4398,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ResetHints(void); * \sa SDL_SetHint * \sa SDL_SetHintWithPriority */ -extern SDL_DECLSPEC const char *SDLCALL SDL_GetHint(const char *name); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetHint(const char *name); /** * Get the boolean value of a hint variable. diff --git a/vendor/sdl3/include/SDL_log.h b/vendor/sdl3/include/SDL_log.h index a56476c6d..3fd7ec2ed 100644 --- a/vendor/sdl3/include/SDL_log.h +++ b/vendor/sdl3/include/SDL_log.h @@ -41,8 +41,8 @@ * "system", "audio", "video", "render", "input", "test", or `*` for any * unspecified category. * - * The level can be a numeric level, one of "verbose", "debug", "info", - * "warn", "error", "critical", or "quiet" to disable that category. + * The level can be a numeric level, one of "trace", "verbose", "debug", + * "info", "warn", "error", "critical", or "quiet" to disable that category. * * You can omit the category if you want to set the logging level for all * categories. @@ -56,6 +56,15 @@ * - Windows: debug output stream * - Android: log output * - Others: standard error output (stderr) + * + * You don't need to have a newline (`\n`) on the end of messages, the + * functions will do that for you. For consistent behavior cross-platform, you + * shouldn't have any newlines in messages, such as to log multiple lines in + * one call; unusual platform-specific behavior can be observed in such usage. + * Do one log call per line instead, with no newlines in messages. + * + * Each log call is atomic, so you won't see log messages cut off one another + * when logging from multiple threads. */ #ifndef SDL_log_h_ diff --git a/vendor/sdl3/include/SDL_main.h b/vendor/sdl3/include/SDL_main.h index 2e7a2ebb6..905d78e96 100644 --- a/vendor/sdl3/include/SDL_main.h +++ b/vendor/sdl3/include/SDL_main.h @@ -28,6 +28,9 @@ * should look like this: * * ```c + * #include + * #include + * * int main(int argc, char *argv[]) * { * } @@ -38,9 +41,9 @@ * This is also where an app can be configured to use the main callbacks, via * the SDL_MAIN_USE_CALLBACKS macro. * - * This is a "single-header library," which is to say that including this - * header inserts code into your program, and you should only include it once - * in most cases. SDL.h does not include this header automatically. + * SDL_main.h is a "single-header library," which is to say that including + * this header inserts code into your program, and you should only include it + * once in most cases. SDL.h does not include this header automatically. * * For more information, see: * diff --git a/vendor/sdl3/include/SDL_mouse.h b/vendor/sdl3/include/SDL_mouse.h index 18856e20e..864135d2b 100644 --- a/vendor/sdl3/include/SDL_mouse.h +++ b/vendor/sdl3/include/SDL_mouse.h @@ -353,7 +353,7 @@ extern SDL_DECLSPEC SDL_MouseButtonFlags SDLCALL SDL_GetRelativeMouseState(float * * \sa SDL_WarpMouseGlobal */ -extern SDL_DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window * window, +extern SDL_DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window *window, float x, float y); /** @@ -514,8 +514,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_CaptureMouse(bool enabled); * \sa SDL_DestroyCursor * \sa SDL_SetCursor */ -extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 * data, - const Uint8 * mask, +extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 *data, + const Uint8 *mask, int w, int h, int hot_x, int hot_y); diff --git a/vendor/sdl3/include/SDL_pixels.h b/vendor/sdl3/include/SDL_pixels.h index b6f38acbe..4127ac06c 100644 --- a/vendor/sdl3/include/SDL_pixels.h +++ b/vendor/sdl3/include/SDL_pixels.h @@ -676,6 +676,9 @@ typedef enum SDL_PixelFormat SDL_PIXELFORMAT_EXTERNAL_OES = 0x2053454fu, /**< Android video texture format */ /* SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') */ + SDL_PIXELFORMAT_MJPG = 0x47504a4du, /**< Motion JPEG */ + /* SDL_DEFINE_PIXELFOURCC('M', 'J', 'P', 'G') */ + /* Aliases for RGBA byte arrays of color data, for the current platform */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_RGBA8888, diff --git a/vendor/sdl3/include/SDL_platform_defines.h b/vendor/sdl3/include/SDL_platform_defines.h index 7e9a0a92a..6b240a8be 100644 --- a/vendor/sdl3/include/SDL_platform_defines.h +++ b/vendor/sdl3/include/SDL_platform_defines.h @@ -471,8 +471,6 @@ * \since This macro is available since SDL 3.2.0. */ #define SDL_PLATFORM_3DS 1 - -#undef __3DS__ #endif #endif /* SDL_platform_defines_h_ */ diff --git a/vendor/sdl3/include/SDL_power.h b/vendor/sdl3/include/SDL_power.h index 4056ce3c8..694fb0924 100644 --- a/vendor/sdl3/include/SDL_power.h +++ b/vendor/sdl3/include/SDL_power.h @@ -79,6 +79,10 @@ typedef enum SDL_PowerState * It's possible a platform can only report battery percentage or time left * but not both. * + * On some platforms, retrieving power supply details might be expensive. If + * you want to display continuous status you could call this function every + * minute or so. + * * \param seconds a pointer filled in with the seconds of battery life left, * or NULL to ignore. This will be filled in with -1 if we * can't determine a value or there is no battery. diff --git a/vendor/sdl3/include/SDL_process.h b/vendor/sdl3/include/SDL_process.h index 2cc77395b..511b2f9c5 100644 --- a/vendor/sdl3/include/SDL_process.h +++ b/vendor/sdl3/include/SDL_process.h @@ -103,7 +103,7 @@ typedef struct SDL_Process SDL_Process; * \sa SDL_WaitProcess * \sa SDL_DestroyProcess */ -extern SDL_DECLSPEC SDL_Process *SDLCALL SDL_CreateProcess(const char * const *args, bool pipe_stdio); +extern SDL_DECLSPEC SDL_Process * SDLCALL SDL_CreateProcess(const char * const *args, bool pipe_stdio); /** * Description of where standard I/O should be directed when creating a @@ -173,13 +173,13 @@ typedef enum SDL_ProcessIO * standard input when `SDL_PROP_PROCESS_CREATE_STDIN_NUMBER` is set to * `SDL_PROCESS_STDIO_REDIRECT`. * - `SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER`: an SDL_ProcessIO value - * describing where standard output for the process goes go, defaults to + * describing where standard output for the process goes to, defaults to * `SDL_PROCESS_STDIO_INHERITED`. * - `SDL_PROP_PROCESS_CREATE_STDOUT_POINTER`: an SDL_IOStream pointer used * for standard output when `SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER` is set * to `SDL_PROCESS_STDIO_REDIRECT`. * - `SDL_PROP_PROCESS_CREATE_STDERR_NUMBER`: an SDL_ProcessIO value - * describing where standard error for the process goes go, defaults to + * describing where standard error for the process goes to, defaults to * `SDL_PROCESS_STDIO_INHERITED`. * - `SDL_PROP_PROCESS_CREATE_STDERR_POINTER`: an SDL_IOStream pointer used * for standard error when `SDL_PROP_PROCESS_CREATE_STDERR_NUMBER` is set to @@ -215,7 +215,7 @@ typedef enum SDL_ProcessIO * \sa SDL_WaitProcess * \sa SDL_DestroyProcess */ -extern SDL_DECLSPEC SDL_Process *SDLCALL SDL_CreateProcessWithProperties(SDL_PropertiesID props); +extern SDL_DECLSPEC SDL_Process * SDLCALL SDL_CreateProcessWithProperties(SDL_PropertiesID props); #define SDL_PROP_PROCESS_CREATE_ARGS_POINTER "SDL.process.create.args" #define SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER "SDL.process.create.environment" @@ -320,7 +320,7 @@ extern SDL_DECLSPEC void * SDLCALL SDL_ReadProcess(SDL_Process *process, size_t * \sa SDL_CreateProcessWithProperties * \sa SDL_GetProcessOutput */ -extern SDL_DECLSPEC SDL_IOStream *SDLCALL SDL_GetProcessInput(SDL_Process *process); +extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_GetProcessInput(SDL_Process *process); /** * Get the SDL_IOStream associated with process standard output. @@ -344,7 +344,7 @@ extern SDL_DECLSPEC SDL_IOStream *SDLCALL SDL_GetProcessInput(SDL_Process *proce * \sa SDL_CreateProcessWithProperties * \sa SDL_GetProcessInput */ -extern SDL_DECLSPEC SDL_IOStream *SDLCALL SDL_GetProcessOutput(SDL_Process *process); +extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_GetProcessOutput(SDL_Process *process); /** * Stop a process. diff --git a/vendor/sdl3/include/SDL_rect.h b/vendor/sdl3/include/SDL_rect.h index 8998de6f4..eb2d34a69 100644 --- a/vendor/sdl3/include/SDL_rect.h +++ b/vendor/sdl3/include/SDL_rect.h @@ -371,7 +371,7 @@ SDL_FORCE_INLINE bool SDL_RectEmptyFloat(const SDL_FRect *r) * * \sa SDL_RectsEqualFloat */ -SDL_FORCE_INLINE bool SDL_RectsEqualEpsilon(const SDL_FRect *a, const SDL_FRect *b, const float epsilon) +SDL_FORCE_INLINE bool SDL_RectsEqualEpsilon(const SDL_FRect *a, const SDL_FRect *b, float epsilon) { return (a && b && ((a == b) || ((SDL_fabsf(a->x - b->x) <= epsilon) && diff --git a/vendor/sdl3/include/SDL_render.h b/vendor/sdl3/include/SDL_render.h index 891e99452..3352545d4 100644 --- a/vendor/sdl3/include/SDL_render.h +++ b/vendor/sdl3/include/SDL_render.h @@ -490,6 +490,9 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Rende * This returns the true output size in pixels, ignoring any render targets or * logical size and presentation. * + * For the output size of the current rendering target, with logical size + * adjustments, use SDL_GetCurrentRenderOutputSize() instead. + * * \param renderer the rendering context. * \param w a pointer filled in with the width in pixels. * \param h a pointer filled in with the height in pixels. @@ -508,9 +511,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderOutputSize(SDL_Renderer *renderer, * Get the current output size in pixels of a rendering context. * * If a rendering target is active, this will return the size of the rendering - * target in pixels, otherwise if a logical size is set, it will return the - * logical size, otherwise it will return the value of - * SDL_GetRenderOutputSize(). + * target in pixels, otherwise return the value of SDL_GetRenderOutputSize(). + * + * Rendering target or not, the output will be adjusted by the current logical + * presentation state, dictated by SDL_SetRenderLogicalPresentation(). * * \param renderer the rendering context. * \param w a pointer filled in with the current width. @@ -1318,6 +1322,11 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture *texture); * To stop rendering to a texture and render to the window again, call this * function with a NULL `texture`. * + * Viewport, cliprect, scale, and logical presentation are unique to each + * render target. Get and set functions for these states apply to the current + * render target set by this function, and those states persist on each target + * when the current render target changes. + * * \param renderer the rendering context. * \param texture the targeted texture, which must be created with the * `SDL_TEXTUREACCESS_TARGET` flag, or NULL to render to the @@ -1351,25 +1360,39 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer, SDL extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_GetRenderTarget(SDL_Renderer *renderer); /** - * Set a device independent resolution and presentation mode for rendering. + * Set a device-independent resolution and presentation mode for rendering. * * This function sets the width and height of the logical rendering output. - * The renderer will act as if the window is always the requested dimensions, - * scaling to the actual window resolution as necessary. + * The renderer will act as if the current render target is always the + * requested dimensions, scaling to the actual resolution as necessary. * * This can be useful for games that expect a fixed size, but would like to * scale the output to whatever is available, regardless of how a user resizes * a window, or if the display is high DPI. * + * Logical presentation can be used with both render target textures and the + * renderer's window; the state is unique to each render target, and this + * function sets the state for the current render target. It might be useful + * to draw to a texture that matches the window dimensions with logical + * presentation enabled, and then draw that texture across the entire window + * with logical presentation disabled. Be careful not to render both with + * logical presentation enabled, however, as this could produce + * double-letterboxing, etc. + * * You can disable logical coordinates by setting the mode to * SDL_LOGICAL_PRESENTATION_DISABLED, and in that case you get the full pixel - * resolution of the output window; it is safe to toggle logical presentation + * resolution of the render target; it is safe to toggle logical presentation * during the rendering of a frame: perhaps most of the rendering is done to * specific dimensions but to make fonts look sharp, the app turns off logical - * presentation while drawing text. + * presentation while drawing text, for example. * - * Letterboxing will only happen if logical presentation is enabled during - * SDL_RenderPresent; be sure to reenable it first if you were using it. + * For the renderer's window, letterboxing is drawn into the framebuffer if + * logical presentation is enabled during SDL_RenderPresent; be sure to + * reenable it before presenting if you were toggling it, otherwise the + * letterbox areas might have artifacts from previous frames (or artifacts + * from external overlays, etc). Letterboxing is never drawn into texture + * render targets; be sure to call SDL_RenderClear() before drawing into the + * texture so the letterboxing areas are cleared, if appropriate. * * You can convert coordinates in an event into rendering coordinates using * SDL_ConvertEventToRenderCoordinates(). @@ -1397,6 +1420,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer * * This function gets the width and height of the logical rendering output, or * the output size in pixels if a logical resolution is not enabled. * + * Each render target has its own logical presentation state. This function + * gets the state for the current render target. + * * \param renderer the rendering context. * \param w an int to be filled with the width. * \param h an int to be filled with the height. @@ -1420,6 +1446,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer * * presentation is disabled, it will fill the rectangle with the output size, * in pixels. * + * Each render target has its own logical presentation state. This function + * gets the rectangle for the current render target. + * * \param renderer the rendering context. * \param rect a pointer filled in with the final presentation rectangle, may * be NULL. @@ -1536,6 +1565,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ConvertEventToRenderCoordinates(SDL_Rendere * * The area's width and height must be >= 0. * + * Each render target has its own viewport. This function sets the viewport + * for the current render target. + * * \param renderer the rendering context. * \param rect the SDL_Rect structure representing the drawing area, or NULL * to set the viewport to the entire target. @@ -1554,6 +1586,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderViewport(SDL_Renderer *renderer, c /** * Get the drawing area for the current target. * + * Each render target has its own viewport. This function gets the viewport + * for the current render target. + * * \param renderer the rendering context. * \param rect an SDL_Rect structure filled in with the current drawing area. * \returns true on success or false on failure; call SDL_GetError() for more @@ -1575,6 +1610,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, S * whether you should restore a specific rectangle or NULL. Note that the * viewport is always reset when changing rendering targets. * + * Each render target has its own viewport. This function checks the viewport + * for the current render target. + * * \param renderer the rendering context. * \returns true if the viewport was set to a specific rectangle, or false if * it was set to NULL (the entire target). @@ -1613,6 +1651,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderSafeArea(SDL_Renderer *renderer, S /** * Set the clip rectangle for rendering on the specified target. * + * Each render target has its own clip rectangle. This function sets the + * cliprect for the current render target. + * * \param renderer the rendering context. * \param rect an SDL_Rect structure representing the clip area, relative to * the viewport, or NULL to disable clipping. @@ -1631,6 +1672,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderClipRect(SDL_Renderer *renderer, c /** * Get the clip rectangle for the current target. * + * Each render target has its own clip rectangle. This function gets the + * cliprect for the current render target. + * * \param renderer the rendering context. * \param rect an SDL_Rect structure filled in with the current clipping area * or an empty rectangle if clipping is disabled. @@ -1647,7 +1691,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderClipRect(SDL_Renderer *renderer, c extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect); /** - * Get whether clipping is enabled on the given renderer. + * Get whether clipping is enabled on the given render target. + * + * Each render target has its own clip rectangle. This function checks the + * cliprect for the current render target. * * \param renderer the rendering context. * \returns true if clipping is enabled or false if not; call SDL_GetError() @@ -1673,6 +1720,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer); * will be handled using the appropriate quality hints. For best results use * integer scaling factors. * + * Each render target has its own scale. This function sets the scale for the + * current render target. + * * \param renderer the rendering context. * \param scaleX the horizontal scaling factor. * \param scaleY the vertical scaling factor. @@ -1690,6 +1740,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderScale(SDL_Renderer *renderer, floa /** * Get the drawing scale for the current target. * + * Each render target has its own scale. This function gets the scale for the + * current render target. + * * \param renderer the rendering context. * \param scaleX a pointer filled in with the horizontal scaling factor. * \param scaleY a pointer filled in with the vertical scaling factor. @@ -2247,15 +2300,21 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, /** * Read pixels from the current rendering target. * - * The returned surface should be freed with SDL_DestroySurface() + * The returned surface contains pixels inside the desired area clipped to the + * current viewport, and should be freed with SDL_DestroySurface(). + * + * Note that this returns the actual pixels on the screen, so if you are using + * logical presentation you should use SDL_GetRenderLogicalPresentationRect() + * to get the area containing your content. * * **WARNING**: This is a very slow operation, and should not be used * frequently. If you're using this on the main rendering target, it should be * called after rendering and before SDL_RenderPresent(). * * \param renderer the rendering context. - * \param rect an SDL_Rect structure representing the area in pixels relative - * to the to current viewport, or NULL for the entire viewport. + * \param rect an SDL_Rect structure representing the area to read, which will + * be clipped to the current viewport, or NULL for the entire + * viewport. * \returns a new SDL_Surface on success or NULL on failure; call * SDL_GetError() for more information. * diff --git a/vendor/sdl3/include/SDL_revision.h b/vendor/sdl3/include/SDL_revision.h index 18f7c4d6c..f99e03a95 100644 --- a/vendor/sdl3/include/SDL_revision.h +++ b/vendor/sdl3/include/SDL_revision.h @@ -48,9 +48,9 @@ */ #define SDL_REVISION "Some arbitrary string decided at SDL build time" #elif defined(SDL_VENDOR_INFO) -#define SDL_REVISION "release-3.2.0-0-g535d80bad (" SDL_VENDOR_INFO ")" +#define SDL_REVISION "release-3.2.10-0-g877399b2b (" SDL_VENDOR_INFO ")" #else -#define SDL_REVISION "release-3.2.0-0-g535d80bad" +#define SDL_REVISION "release-3.2.10-0-g877399b2b" #endif #endif /* SDL_revision_h_ */ diff --git a/vendor/sdl3/include/SDL_stdinc.h b/vendor/sdl3/include/SDL_stdinc.h index 4e15a3c64..b2728da2f 100644 --- a/vendor/sdl3/include/SDL_stdinc.h +++ b/vendor/sdl3/include/SDL_stdinc.h @@ -1299,8 +1299,11 @@ extern "C" { * * If `size` is 0, it will be set to 1. * - * If you want to allocate memory aligned to a specific alignment, consider - * using SDL_aligned_alloc(). + * If the allocation is successful, the returned pointer is guaranteed to be + * aligned to either the *fundamental alignment* (`alignof(max_align_t)` in + * C11 and later) or `2 * sizeof(void *)`, whichever is smaller. Use + * SDL_aligned_alloc() if you need to allocate memory aligned to an alignment + * greater than this guarantee. * * \param size the size to allocate. * \returns a pointer to the allocated memory, or NULL if allocation failed. @@ -1323,6 +1326,10 @@ extern SDL_DECLSPEC SDL_MALLOC void * SDLCALL SDL_malloc(size_t size); * * If either of `nmemb` or `size` is 0, they will both be set to 1. * + * If the allocation is successful, the returned pointer is guaranteed to be + * aligned to either the *fundamental alignment* (`alignof(max_align_t)` in + * C11 and later) or `2 * sizeof(void *)`, whichever is smaller. + * * \param nmemb the number of elements in the array. * \param size the size of each element of the array. * \returns a pointer to the allocated array, or NULL if allocation failed. @@ -1357,6 +1364,11 @@ extern SDL_DECLSPEC SDL_MALLOC SDL_ALLOC_SIZE2(1, 2) void * SDLCALL SDL_calloc(s * - If it returns NULL (indicating failure), then `mem` will remain valid and * must still be freed with SDL_free(). * + * If the allocation is successfully resized, the returned pointer is + * guaranteed to be aligned to either the *fundamental alignment* + * (`alignof(max_align_t)` in C11 and later) or `2 * sizeof(void *)`, + * whichever is smaller. + * * \param mem a pointer to allocated memory to reallocate, or NULL. * \param size the new size of the memory. * \returns a pointer to the newly allocated memory, or NULL if allocation @@ -4243,14 +4255,14 @@ extern SDL_DECLSPEC int SDLCALL SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STR /** * Seeds the pseudo-random number generator. * - * Reusing the seed number will cause SDL_rand_*() to repeat the same stream - * of 'random' numbers. + * Reusing the seed number will cause SDL_rand() to repeat the same stream of + * 'random' numbers. * * \param seed the value to use as a random number seed, or 0 to use * SDL_GetPerformanceCounter(). * * \threadsafety This should be called on the same thread that calls - * SDL_rand*() + * SDL_rand() * * \since This function is available since SDL 3.2.0. * @@ -4701,7 +4713,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_atan2(double y, double x); * * \since This function is available since SDL 3.2.0. * - * \sa SDL_atan2f + * \sa SDL_atan2 * \sa SDL_atan * \sa SDL_tan */ @@ -4810,7 +4822,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_copysign(double x, double y); * * \since This function is available since SDL 3.2.0. * - * \sa SDL_copysignf + * \sa SDL_copysign * \sa SDL_fabsf */ extern SDL_DECLSPEC float SDLCALL SDL_copysignf(float x, float y); @@ -4943,7 +4955,7 @@ extern SDL_DECLSPEC float SDLCALL SDL_expf(float x); * Range: `0 <= y <= INF` * * This function operates on double-precision floating point values, use - * SDL_copysignf for single-precision floats. + * SDL_fabsf for single-precision floats. * * \param x floating point value to use as the magnitude. * \returns the absolute value of `x`. @@ -4964,7 +4976,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_fabs(double x); * Range: `0 <= y <= INF` * * This function operates on single-precision floating point values, use - * SDL_copysignf for double-precision floats. + * SDL_fabs for double-precision floats. * * \param x floating point value to use as the magnitude. * \returns the absolute value of `x`. @@ -5016,7 +5028,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_floor(double x); * Range: `-INF <= y <= INF`, y integer * * This function operates on single-precision floating point values, use - * SDL_floorf for double-precision floats. + * SDL_floor for double-precision floats. * * \param x floating point value. * \returns the floor of `x`. @@ -5073,7 +5085,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_trunc(double x); * Range: `-INF <= y <= INF`, y integer * * This function operates on single-precision floating point values, use - * SDL_truncf for double-precision floats. + * SDL_trunc for double-precision floats. * * \param x floating point value. * \returns `x` truncated to an integer. @@ -5131,7 +5143,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_fmod(double x, double y); * Range: `-y <= z <= y` * * This function operates on single-precision floating point values, use - * SDL_fmod for single-precision floats. + * SDL_fmod for double-precision floats. * * \param x the numerator. * \param y the denominator. Must not be 0. @@ -5409,7 +5421,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_pow(double x, double y); * instead. * * This function operates on single-precision floating point values, use - * SDL_powf for double-precision floats. + * SDL_pow for double-precision floats. * * This function may use a different approximation across different versions, * platforms and configurations. i.e, it can return a different value given @@ -5469,8 +5481,8 @@ extern SDL_DECLSPEC double SDLCALL SDL_round(double x); * * Range: `-INF <= y <= INF`, y integer * - * This function operates on double-precision floating point values, use - * SDL_roundf for single-precision floats. To get the result as an integer + * This function operates on single-precision floating point values, use + * SDL_round for double-precision floats. To get the result as an integer * type, use SDL_lroundf. * * \param x floating point value. @@ -5499,7 +5511,7 @@ extern SDL_DECLSPEC float SDLCALL SDL_roundf(float x); * Range: `MIN_LONG <= y <= MAX_LONG` * * This function operates on double-precision floating point values, use - * SDL_lround for single-precision floats. To get the result as a + * SDL_lroundf for single-precision floats. To get the result as a * floating-point type, use SDL_round. * * \param x floating point value. @@ -5528,8 +5540,8 @@ extern SDL_DECLSPEC long SDLCALL SDL_lround(double x); * Range: `MIN_LONG <= y <= MAX_LONG` * * This function operates on single-precision floating point values, use - * SDL_lroundf for double-precision floats. To get the result as a - * floating-point type, use SDL_roundf, + * SDL_lround for double-precision floats. To get the result as a + * floating-point type, use SDL_roundf. * * \param x floating point value. * \returns the nearest integer to `x`. @@ -5742,7 +5754,7 @@ extern SDL_DECLSPEC double SDLCALL SDL_tan(double x); * Range: `-INF <= y <= INF` * * This function operates on single-precision floating point values, use - * SDL_tanf for double-precision floats. + * SDL_tan for double-precision floats. * * This function may use a different approximation across different versions, * platforms and configurations. i.e, it can return a different value given @@ -5969,7 +5981,6 @@ char *strdup(const char *str); their prototype defined (clang-diagnostic-implicit-function-declaration) */ #include #include -#include #define SDL_malloc malloc #define SDL_calloc calloc diff --git a/vendor/sdl3/include/SDL_storage.h b/vendor/sdl3/include/SDL_storage.h index 8b89ace18..6837ebaac 100644 --- a/vendor/sdl3/include/SDL_storage.h +++ b/vendor/sdl3/include/SDL_storage.h @@ -450,7 +450,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_CloseStorage(SDL_Storage *storage); * * This function should be called in regular intervals until it returns true - * however, it is not recommended to spinwait on this call, as the backend may - * depend on a synchronous message loop. + * depend on a synchronous message loop. You might instead poll this in your + * game's main loop while processing events and drawing a loading screen. * * \param storage a storage container to query. * \returns true if the container is ready, false otherwise. @@ -636,10 +637,10 @@ extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetStorageSpaceRemaining(SDL_Storage *sto * Enumerate a directory tree, filtered by pattern, and return a list. * * Files are filtered out if they don't match the string in `pattern`, which - * may contain wildcard characters '*' (match everything) and '?' (match one + * may contain wildcard characters `*` (match everything) and `?` (match one * character). If pattern is NULL, no filtering is done and all results are * returned. Subdirectories are permitted, and are specified with a path - * separator of '/'. Wildcard characters '*' and '?' never match a path + * separator of '/'. Wildcard characters `*` and `?` never match a path * separator. * * `flags` may be set to SDL_GLOB_CASEINSENSITIVE to make the pattern matching diff --git a/vendor/sdl3/include/SDL_surface.h b/vendor/sdl3/include/SDL_surface.h index 0752f5307..7bff7cfb2 100644 --- a/vendor/sdl3/include/SDL_surface.h +++ b/vendor/sdl3/include/SDL_surface.h @@ -73,7 +73,7 @@ typedef Uint32 SDL_SurfaceFlags; * * \since This macro is available since SDL 3.2.0. */ -#define SDL_MUSTLOCK(S) ((((S)->flags & SDL_SURFACE_LOCK_NEEDED)) == SDL_SURFACE_LOCK_NEEDED) +#define SDL_MUSTLOCK(S) (((S)->flags & SDL_SURFACE_LOCK_NEEDED) == SDL_SURFACE_LOCK_NEEDED) /** * The scaling mode. @@ -82,6 +82,7 @@ typedef Uint32 SDL_SurfaceFlags; */ typedef enum SDL_ScaleMode { + SDL_SCALEMODE_INVALID = -1, SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */ SDL_SCALEMODE_LINEAR /**< linear filtering */ } SDL_ScaleMode; @@ -120,6 +121,9 @@ typedef enum SDL_FlipMode * format with a pitch of 32 would consist of 32x32 bytes of Y plane followed * by 32x16 bytes of UV plane. * + * When a surface holds MJPG format data, pixels points at the compressed JPEG + * image and pitch is the length of that data. + * * \since This struct is available since SDL 3.2.0. * * \sa SDL_CreateSurface @@ -153,6 +157,8 @@ typedef struct SDL_Surface SDL_Surface; * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateSurfaceFrom @@ -181,6 +187,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurface(int width, int heigh * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateSurface @@ -195,6 +203,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurfaceFrom(int width, int h * * \param surface the SDL_Surface to free. * + * \threadsafety No other thread should be using the surface when it is freed. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreateSurface @@ -221,11 +231,17 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface); * the same tone mapping that Chrome uses for HDR content, the form "*=N", * where N is a floating point scale factor applied in linear space, and * "none", which disables tone mapping. This defaults to "chrome". + * - `SDL_PROP_SURFACE_HOTSPOT_X_NUMBER`: the hotspot pixel offset from the + * left edge of the image, if this surface is being used as a cursor. + * - `SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER`: the hotspot pixel offset from the + * top edge of the image, if this surface is being used as a cursor. * * \param surface the SDL_Surface structure to query. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface); @@ -233,6 +249,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surfac #define SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT "SDL.surface.SDR_white_point" #define SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT "SDL.surface.HDR_headroom" #define SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING "SDL.surface.tonemap" +#define SDL_PROP_SURFACE_HOTSPOT_X_NUMBER "SDL.surface.hotspot.x" +#define SDL_PROP_SURFACE_HOTSPOT_Y_NUMBER "SDL.surface.hotspot.y" /** * Set the colorspace used by a surface. @@ -246,6 +264,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surfac * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetSurfaceColorspace @@ -263,6 +283,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface, * \returns the colorspace used by the surface, or SDL_COLORSPACE_UNKNOWN if * the surface is NULL. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetSurfaceColorspace @@ -291,6 +313,8 @@ extern SDL_DECLSPEC SDL_Colorspace SDLCALL SDL_GetSurfaceColorspace(SDL_Surface * the surface didn't have an index format); call SDL_GetError() for * more information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetPaletteColors @@ -307,6 +331,8 @@ extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_CreateSurfacePalette(SDL_Surface * * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_CreatePalette @@ -321,6 +347,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfacePalette(SDL_Surface *surface, SDL * \returns a pointer to the palette used by the surface, or NULL if there is * no palette used. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetSurfacePalette @@ -344,6 +372,8 @@ extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_GetSurfacePalette(SDL_Surface *sur * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_RemoveSurfaceAlternateImages @@ -358,6 +388,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_AddSurfaceAlternateImage(SDL_Surface *surfa * \param surface the SDL_Surface structure to query. * \returns true if alternate versions are available or false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_AddSurfaceAlternateImage @@ -383,6 +415,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasAlternateImages(SDL_Surface *surf * failure; call SDL_GetError() for more information. This should be * freed with SDL_free() when it is no longer needed. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_AddSurfaceAlternateImage @@ -399,6 +433,8 @@ extern SDL_DECLSPEC SDL_Surface ** SDLCALL SDL_GetSurfaceImages(SDL_Surface *sur * * \param surface the SDL_Surface structure to update. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_AddSurfaceAlternateImage @@ -423,6 +459,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_RemoveSurfaceAlternateImages(SDL_Surface *s * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. The locking referred to by + * this function is making the pixels available for direct + * access, not thread-safe locking. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_MUSTLOCK @@ -435,6 +475,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_LockSurface(SDL_Surface *surface); * * \param surface the SDL_Surface structure to be unlocked. * + * \threadsafety This function is not thread safe. The locking referred to by + * this function is making the pixels available for direct + * access, not thread-safe locking. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LockSurface @@ -453,6 +497,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface); * \returns a pointer to a new SDL_Surface structure or NULL on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_DestroySurface @@ -471,6 +517,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP_IO(SDL_IOStream *src, bool * \returns a pointer to a new SDL_Surface structure or NULL on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_DestroySurface @@ -495,6 +543,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP(const char *file); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LoadBMP_IO @@ -516,6 +566,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStre * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_LoadBMP @@ -534,6 +586,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *f * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_BlitSurface @@ -550,6 +604,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceRLE(SDL_Surface *surface, bool en * \param surface the SDL_Surface structure to query. * \returns true if the surface is RLE enabled, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetSurfaceRLE @@ -572,6 +628,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasRLE(SDL_Surface *surface); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetSurfaceColorKey @@ -588,6 +646,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorKey(SDL_Surface *surface, bo * \param surface the SDL_Surface structure to query. * \returns true if the surface has a color key, false otherwise. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetSurfaceColorKey @@ -608,6 +668,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasColorKey(SDL_Surface *surface); * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetSurfaceColorKey @@ -631,6 +693,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, Ui * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetSurfaceColorMod @@ -649,6 +713,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, Ui * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetSurfaceAlphaMod @@ -669,6 +735,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, Ui * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetSurfaceAlphaMod @@ -684,6 +752,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Ui * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetSurfaceColorMod @@ -703,6 +773,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Ui * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetSurfaceBlendMode @@ -717,6 +789,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface, S * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetSurfaceBlendMode @@ -738,6 +812,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, S * \returns true if the rectangle intersects the surface, otherwise false and * blits will be completely clipped. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_GetSurfaceClipRect @@ -757,6 +833,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, co * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_SetSurfaceClipRect @@ -771,6 +849,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceClipRect(SDL_Surface *surface, SD * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip); @@ -787,6 +867,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipM * \returns a copy of the surface or NULL on failure; call SDL_GetError() for * more information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_DestroySurface @@ -806,6 +888,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_DuplicateSurface(SDL_Surface *surf * \returns a copy of the surface or NULL on failure; call SDL_GetError() for * more information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_DestroySurface @@ -831,6 +915,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ScaleSurface(SDL_Surface *surface, * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_ConvertSurfaceAndColorspace @@ -857,6 +943,8 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurface(SDL_Surface *surfac * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_ConvertSurface @@ -878,6 +966,10 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurfaceAndColorspace(SDL_Su * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety The same destination pixels should not be used from two + * threads at once. It is safe to use the same source pixels + * from multiple threads. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_ConvertPixelsAndColorspace @@ -907,6 +999,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ConvertPixels(int width, int height, SDL_Pi * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety The same destination pixels should not be used from two + * threads at once. It is safe to use the same source pixels + * from multiple threads. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_ConvertPixels @@ -931,6 +1027,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ConvertPixelsAndColorspace(int width, int h * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety The same destination pixels should not be used from two + * threads at once. It is safe to use the same source pixels + * from multiple threads. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL_PixelFormat src_format, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch, bool linear); @@ -946,6 +1046,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surface, bool linear); @@ -966,6 +1068,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surfac * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r, float g, float b, float a); @@ -989,6 +1093,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r, * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_FillSurfaceRects @@ -1014,6 +1120,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRect(SDL_Surface *dst, const SDL * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_FillSurfaceRect @@ -1087,9 +1195,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SD * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety The same destination surface should not be used from two - * threads at once. It is safe to use the same source surface - * from multiple threads. + * \threadsafety Only one thread should be using the `src` and `dst` surfaces + * at any given time. * * \since This function is available since SDL 3.2.0. * @@ -1112,9 +1219,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface(SDL_Surface *src, const SDL_Rec * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety The same destination surface should not be used from two - * threads at once. It is safe to use the same source surface - * from multiple threads. + * \threadsafety Only one thread should be using the `src` and `dst` surfaces + * at any given time. * * \since This function is available since SDL 3.2.0. * @@ -1137,9 +1243,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUnchecked(SDL_Surface *src, cons * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety The same destination surface should not be used from two - * threads at once. It is safe to use the same source surface - * from multiple threads. + * \threadsafety Only one thread should be using the `src` and `dst` surfaces + * at any given time. * * \since This function is available since SDL 3.2.0. * @@ -1163,9 +1268,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, const S * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety The same destination surface should not be used from two - * threads at once. It is safe to use the same source surface - * from multiple threads. + * \threadsafety Only one thread should be using the `src` and `dst` surfaces + * at any given time. * * \since This function is available since SDL 3.2.0. * @@ -1173,6 +1277,28 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, const S */ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); +/** + * Perform a stretched pixel copy from one surface to another. + * + * \param src the SDL_Surface structure to be copied from. + * \param srcrect the SDL_Rect structure representing the rectangle to be + * copied, may not be NULL. + * \param dst the SDL_Surface structure that is the blit target. + * \param dstrect the SDL_Rect structure representing the target rectangle in + * the destination surface, may not be NULL. + * \param scaleMode the SDL_ScaleMode to be used. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety Only one thread should be using the `src` and `dst` surfaces + * at any given time. + * + * \since This function is available since SDL 3.4.0. + * + * \sa SDL_BlitSurfaceScaled + */ +extern SDL_DECLSPEC bool SDLCALL SDL_StretchSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); + /** * Perform a tiled blit to a destination surface, which may be of a different * format. @@ -1189,9 +1315,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety The same destination surface should not be used from two - * threads at once. It is safe to use the same source surface - * from multiple threads. + * \threadsafety Only one thread should be using the `src` and `dst` surfaces + * at any given time. * * \since This function is available since SDL 3.2.0. * @@ -1219,9 +1344,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceTiled(SDL_Surface *src, const SD * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety The same destination surface should not be used from two - * threads at once. It is safe to use the same source surface - * from multiple threads. + * \threadsafety Only one thread should be using the `src` and `dst` surfaces + * at any given time. * * \since This function is available since SDL 3.2.0. * @@ -1256,9 +1380,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceTiledWithScale(SDL_Surface *src, * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \threadsafety The same destination surface should not be used from two - * threads at once. It is safe to use the same source surface - * from multiple threads. + * \threadsafety Only one thread should be using the `src` and `dst` surfaces + * at any given time. * * \since This function is available since SDL 3.2.0. * @@ -1290,6 +1413,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface9Grid(SDL_Surface *src, const SD * \param b the blue component of the pixel in the range 0-255. * \returns a pixel value. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_MapSurfaceRGBA @@ -1321,6 +1446,8 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGB(SDL_Surface *surface, Uint8 * \param a the alpha component of the pixel in the range 0-255. * \returns a pixel value. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.2.0. * * \sa SDL_MapSurfaceRGB @@ -1350,6 +1477,8 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGBA(SDL_Surface *surface, Uint * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); @@ -1374,6 +1503,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface, int x, int y, float *r, float *g, float *b, float *a); @@ -1397,6 +1528,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface, * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); @@ -1417,6 +1550,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int * \returns true on success or false on failure; call SDL_GetError() for more * information. * + * \threadsafety This function is not thread safe. + * * \since This function is available since SDL 3.2.0. */ extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixelFloat(SDL_Surface *surface, int x, int y, float r, float g, float b, float a); diff --git a/vendor/sdl3/include/SDL_test_common.h b/vendor/sdl3/include/SDL_test_common.h index 3ab1ad01c..91efe8ac3 100644 --- a/vendor/sdl3/include/SDL_test_common.h +++ b/vendor/sdl3/include/SDL_test_common.h @@ -177,7 +177,7 @@ extern "C" { * * \returns a newly allocated common state object. */ -SDLTest_CommonState *SDLCALL SDLTest_CommonCreateState(char **argv, SDL_InitFlags flags); +SDLTest_CommonState * SDLCALL SDLTest_CommonCreateState(char **argv, SDL_InitFlags flags); /** * Free the common state object. diff --git a/vendor/sdl3/include/SDL_thread.h b/vendor/sdl3/include/SDL_thread.h index 277535fcb..e981b5429 100644 --- a/vendor/sdl3/include/SDL_thread.h +++ b/vendor/sdl3/include/SDL_thread.h @@ -139,7 +139,7 @@ typedef enum SDL_ThreadState * * \since This datatype is available since SDL 3.2.0. */ -typedef int (SDLCALL * SDL_ThreadFunction) (void *data); +typedef int (SDLCALL *SDL_ThreadFunction) (void *data); #ifdef SDL_WIKI_DOCUMENTATION_SECTION diff --git a/vendor/sdl3/include/SDL_tray.h b/vendor/sdl3/include/SDL_tray.h index 0b05db25b..1780b0ba5 100644 --- a/vendor/sdl3/include/SDL_tray.h +++ b/vendor/sdl3/include/SDL_tray.h @@ -118,7 +118,7 @@ typedef void (SDLCALL *SDL_TrayCallback)(void *userdata, SDL_TrayEntry *entry); * \sa SDL_GetTrayMenu * \sa SDL_DestroyTray */ -extern SDL_DECLSPEC SDL_Tray *SDLCALL SDL_CreateTray(SDL_Surface *icon, const char *tooltip); +extern SDL_DECLSPEC SDL_Tray * SDLCALL SDL_CreateTray(SDL_Surface *icon, const char *tooltip); /** * Updates the system tray icon's icon. @@ -172,7 +172,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetTrayTooltip(SDL_Tray *tray, const char * * \sa SDL_GetTrayMenu * \sa SDL_GetTrayMenuParentTray */ -extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_CreateTrayMenu(SDL_Tray *tray); +extern SDL_DECLSPEC SDL_TrayMenu * SDLCALL SDL_CreateTrayMenu(SDL_Tray *tray); /** * Create a submenu for a system tray entry. @@ -196,7 +196,7 @@ extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_CreateTrayMenu(SDL_Tray *tray); * \sa SDL_GetTraySubmenu * \sa SDL_GetTrayMenuParentEntry */ -extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_CreateTraySubmenu(SDL_TrayEntry *entry); +extern SDL_DECLSPEC SDL_TrayMenu * SDLCALL SDL_CreateTraySubmenu(SDL_TrayEntry *entry); /** * Gets a previously created tray menu. @@ -220,7 +220,7 @@ extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_CreateTraySubmenu(SDL_TrayEntry *e * \sa SDL_CreateTray * \sa SDL_CreateTrayMenu */ -extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_GetTrayMenu(SDL_Tray *tray); +extern SDL_DECLSPEC SDL_TrayMenu * SDLCALL SDL_GetTrayMenu(SDL_Tray *tray); /** * Gets a previously created tray entry submenu. @@ -244,14 +244,14 @@ extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_GetTrayMenu(SDL_Tray *tray); * \sa SDL_InsertTrayEntryAt * \sa SDL_CreateTraySubmenu */ -extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_GetTraySubmenu(SDL_TrayEntry *entry); +extern SDL_DECLSPEC SDL_TrayMenu * SDLCALL SDL_GetTraySubmenu(SDL_TrayEntry *entry); /** * Returns a list of entries in the menu, in order. * * \param menu The menu to get entries from. - * \param size An optional pointer to obtain the number of entries in the - * menu. + * \param count An optional pointer to obtain the number of entries in the + * menu. * \returns a NULL-terminated list of entries within the given menu. The * pointer becomes invalid when any function that inserts or deletes * entries in the menu is called. @@ -264,7 +264,7 @@ extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_GetTraySubmenu(SDL_TrayEntry *entr * \sa SDL_RemoveTrayEntry * \sa SDL_InsertTrayEntryAt */ -extern SDL_DECLSPEC const SDL_TrayEntry **SDLCALL SDL_GetTrayEntries(SDL_TrayMenu *menu, int *size); +extern SDL_DECLSPEC const SDL_TrayEntry ** SDLCALL SDL_GetTrayEntries(SDL_TrayMenu *menu, int *count); /** * Removes a tray entry. @@ -307,7 +307,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_RemoveTrayEntry(SDL_TrayEntry *entry); * \sa SDL_RemoveTrayEntry * \sa SDL_GetTrayEntryParent */ -extern SDL_DECLSPEC SDL_TrayEntry *SDLCALL SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags); +extern SDL_DECLSPEC SDL_TrayEntry * SDLCALL SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags); /** * Sets the label of an entry. @@ -348,7 +348,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, con * \sa SDL_InsertTrayEntryAt * \sa SDL_SetTrayEntryLabel */ -extern SDL_DECLSPEC const char *SDLCALL SDL_GetTrayEntryLabel(SDL_TrayEntry *entry); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetTrayEntryLabel(SDL_TrayEntry *entry); /** * Sets whether or not an entry is checked. @@ -481,7 +481,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyTray(SDL_Tray *tray); * * \sa SDL_InsertTrayEntryAt */ -extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_GetTrayEntryParent(SDL_TrayEntry *entry); +extern SDL_DECLSPEC SDL_TrayMenu * SDLCALL SDL_GetTrayEntryParent(SDL_TrayEntry *entry); /** * Gets the entry for which the menu is a submenu, if the current menu is a @@ -501,7 +501,7 @@ extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_GetTrayEntryParent(SDL_TrayEntry * * \sa SDL_CreateTraySubmenu * \sa SDL_GetTrayMenuParentTray */ -extern SDL_DECLSPEC SDL_TrayEntry *SDLCALL SDL_GetTrayMenuParentEntry(SDL_TrayMenu *menu); +extern SDL_DECLSPEC SDL_TrayEntry * SDLCALL SDL_GetTrayMenuParentEntry(SDL_TrayMenu *menu); /** * Gets the tray for which this menu is the first-level menu, if the current @@ -521,7 +521,7 @@ extern SDL_DECLSPEC SDL_TrayEntry *SDLCALL SDL_GetTrayMenuParentEntry(SDL_TrayMe * \sa SDL_CreateTrayMenu * \sa SDL_GetTrayMenuParentEntry */ -extern SDL_DECLSPEC SDL_Tray *SDLCALL SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu); +extern SDL_DECLSPEC SDL_Tray * SDLCALL SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu); /** * Update the trays. diff --git a/vendor/sdl3/include/SDL_version.h b/vendor/sdl3/include/SDL_version.h index 55014e3c1..a3b6ae82d 100644 --- a/vendor/sdl3/include/SDL_version.h +++ b/vendor/sdl3/include/SDL_version.h @@ -62,7 +62,7 @@ extern "C" { * * \since This macro is available since SDL 3.2.0. */ -#define SDL_MICRO_VERSION 0 +#define SDL_MICRO_VERSION 10 /** * This macro turns the version numbers into a numeric value. diff --git a/vendor/sdl3/include/SDL_vulkan.h b/vendor/sdl3/include/SDL_vulkan.h index 5a487561a..710afbe63 100644 --- a/vendor/sdl3/include/SDL_vulkan.h +++ b/vendor/sdl3/include/SDL_vulkan.h @@ -226,7 +226,7 @@ extern SDL_DECLSPEC char const * const * SDLCALL SDL_Vulkan_GetInstanceExtension extern SDL_DECLSPEC bool SDLCALL SDL_Vulkan_CreateSurface(SDL_Window *window, VkInstance instance, const struct VkAllocationCallbacks *allocator, - VkSurfaceKHR* surface); + VkSurfaceKHR *surface); /** * Destroy the Vulkan rendering surface of a window. diff --git a/vendor/sdl3/sdl3_audio.odin b/vendor/sdl3/sdl3_audio.odin index 43a8a34d2..045f4780e 100644 --- a/vendor/sdl3/sdl3_audio.odin +++ b/vendor/sdl3/sdl3_audio.odin @@ -83,9 +83,9 @@ foreign lib { OpenAudioDevice :: proc(devid: AudioDeviceID, spec: ^AudioSpec) -> AudioDeviceID --- IsAudioDevicePhysical :: proc(devid: AudioDeviceID) -> bool --- IsAudioDevicePlayback :: proc(devid: AudioDeviceID) -> bool --- - PauseAudioDevice :: proc(dev: AudioDeviceID) -> bool --- - ResumeAudioDevice :: proc(dev: AudioDeviceID) -> bool --- - AudioDevicePaused :: proc(dev: AudioDeviceID) -> bool --- + PauseAudioDevice :: proc(devid: AudioDeviceID) -> bool --- + ResumeAudioDevice :: proc(devid: AudioDeviceID) -> bool --- + AudioDevicePaused :: proc(devid: AudioDeviceID) -> bool --- GetAudioDeviceGain :: proc(devid: AudioDeviceID) -> f32 --- SetAudioDeviceGain :: proc(devid: AudioDeviceID, gain: f32) -> bool --- CloseAudioDevice :: proc(devid: AudioDeviceID) --- diff --git a/vendor/sdl3/sdl3_camera.odin b/vendor/sdl3/sdl3_camera.odin index d86d98746..7d46bd2bd 100644 --- a/vendor/sdl3/sdl3_camera.odin +++ b/vendor/sdl3/sdl3_camera.odin @@ -27,7 +27,7 @@ foreign lib { GetCameraDriver :: proc(index: c.int) -> cstring --- GetCurrentCameraDriver :: proc() -> cstring --- GetCameras :: proc(count: ^c.int) -> [^]CameraID --- - GetCameraSupportedFormats :: proc(devid: CameraID, count: ^c.int) -> [^]^CameraSpec --- + GetCameraSupportedFormats :: proc(instance_id: CameraID, count: ^c.int) -> [^]^CameraSpec --- GetCameraName :: proc(instance_id: CameraID) -> cstring --- GetCameraPosition :: proc(instance_id: CameraID) -> CameraPosition --- OpenCamera :: proc(instance_id: CameraID, spec: ^CameraSpec) -> ^Camera --- diff --git a/vendor/sdl3/sdl3_gpu.odin b/vendor/sdl3/sdl3_gpu.odin index da561b62b..ec414f98e 100644 --- a/vendor/sdl3/sdl3_gpu.odin +++ b/vendor/sdl3/sdl3_gpu.odin @@ -516,7 +516,7 @@ GPUVertexBufferDescription :: struct { slot: Uint32, /**< The binding slot of the vertex buffer. */ pitch: Uint32, /**< The byte pitch between consecutive elements of the vertex buffer. */ input_rate: GPUVertexInputRate, /**< Whether attribute addressing is a function of the vertex index or instance index. */ - instance_step_rate: Uint32, /**< The number of instances to draw using the same per-instance data before advancing in the instance buffer by one element. Ignored unless input_rate is GPU_VERTEXINPUTRATE_INSTANCE */ + instance_step_rate: Uint32, /**< Reserved for future use. Must be set to 0. */ } GPUVertexAttribute :: struct { @@ -611,8 +611,8 @@ GPURasterizerState :: struct { GPUMultisampleState :: struct { sample_count: GPUSampleCount, /**< The number of samples to be used in rasterization. */ - sample_mask: Uint32, /**< Determines which samples get updated in the render targets. Treated as 0xFFFFFFFF if enable_mask is false. */ - enable_mask: bool, /**< Enables sample masking. */ + sample_mask: Uint32, /**< Reserved for future use. Must be set to 0. */ + enable_mask: bool, /**< Reserved for future use. Must be set to false. */ _: Uint8, _: Uint8, _: Uint8, diff --git a/vendor/sdl3/sdl3_hints.odin b/vendor/sdl3/sdl3_hints.odin index a7398a124..987010c57 100644 --- a/vendor/sdl3/sdl3_hints.odin +++ b/vendor/sdl3/sdl3_hints.odin @@ -123,6 +123,7 @@ HINT_JOYSTICK_WGI :: "SDL_JOYSTICK_WGI" HINT_JOYSTICK_WHEEL_DEVICES :: "SDL_JOYSTICK_WHEEL_DEVICES" HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED :: "SDL_JOYSTICK_WHEEL_DEVICES_EXCLUDED" HINT_JOYSTICK_ZERO_CENTERED_DEVICES :: "SDL_JOYSTICK_ZERO_CENTERED_DEVICES" +HINT_JOYSTICK_HAPTIC_AXES :: "SDL_JOYSTICK_HAPTIC_AXES" HINT_KEYCODE_OPTIONS :: "SDL_KEYCODE_OPTIONS" HINT_KMSDRM_DEVICE_INDEX :: "SDL_KMSDRM_DEVICE_INDEX" HINT_KMSDRM_REQUIRE_DRM_MASTER :: "SDL_KMSDRM_REQUIRE_DRM_MASTER" @@ -197,6 +198,7 @@ HINT_VIDEO_WAYLAND_MODE_SCALING :: "SDL_VIDEO_WAYLAND_MODE_SCALING" HINT_VIDEO_WAYLAND_PREFER_LIBDECOR :: "SDL_VIDEO_WAYLAND_PREFER_LIBDECOR" HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY :: "SDL_VIDEO_WAYLAND_SCALE_TO_DISPLAY" HINT_VIDEO_WIN_D3DCOMPILER :: "SDL_VIDEO_WIN_D3DCOMPILER" +HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT :: "SDL_VIDEO_X11_EXTERNAL_WINDOW_INPUT" HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR :: "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR" HINT_VIDEO_X11_NET_WM_PING :: "SDL_VIDEO_X11_NET_WM_PING" HINT_VIDEO_X11_NODIRECTCOLOR :: "SDL_VIDEO_X11_NODIRECTCOLOR" diff --git a/vendor/sdl3/sdl3_pixels.odin b/vendor/sdl3/sdl3_pixels.odin index a9dec79fb..a636d13ff 100644 --- a/vendor/sdl3/sdl3_pixels.odin +++ b/vendor/sdl3/sdl3_pixels.odin @@ -277,6 +277,8 @@ PixelFormat :: enum c.int { /* SDL_DEFINE_PIXELFOURCC('P', '0', '1', '0'), */ EXTERNAL_OES = 0x2053454f, /**< Android video texture format */ /* SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') */ + MJPG = 0x47504a4d, /**< Motion JPEG */ + /* SDL_DEFINE_PIXELFOURCC('M', 'J', 'P', 'G') */ /* Aliases for RGBA byte arrays of color data, for the current platform */ RGBA32 = RGBA8888 when BYTEORDER == BIG_ENDIAN else ABGR8888, diff --git a/vendor/sdl3/sdl3_surface.odin b/vendor/sdl3/sdl3_surface.odin index 7abbd4ab5..526940147 100644 --- a/vendor/sdl3/sdl3_surface.odin +++ b/vendor/sdl3/sdl3_surface.odin @@ -22,6 +22,7 @@ MUSTLOCK :: proc "c" (S: ^Surface) -> bool { } ScaleMode :: enum c.int { + INVALID = -1, NEAREST, /**< nearest pixel sampling */ LINEAR, /**< linear filtering */ } @@ -45,6 +46,11 @@ Surface :: struct { reserved: rawptr, /**< Reserved for internal use */ } +PROP_SURFACE_SDR_WHITE_POINT_FLOAT :: "SDL.surface.SDR_white_point" +PROP_SURFACE_HDR_HEADROOM_FLOAT :: "SDL.surface.HDR_headroom" +PROP_SURFACE_TONEMAP_OPERATOR_STRING :: "SDL.surface.tonemap" +PROP_SURFACE_HOTSPOT_X_NUMBER :: "SDL.surface.hotspot.x" +PROP_SURFACE_HOTSPOT_Y_NUMBER :: "SDL.surface.hotspot.y" @(default_calling_convention="c", link_prefix="SDL_") foreign lib { @@ -96,6 +102,7 @@ foreign lib { BlitSurfaceUnchecked :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect)) -> bool --- BlitSurfaceScaled :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect), scaleMode: ScaleMode) -> bool --- BlitSurfaceUncheckedScaled :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect), scaleMode: ScaleMode) -> bool --- + StretchSurface :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect), scaleMode: ScaleMode) -> bool --- BlitSurfaceTiled :: proc(src: ^Surface, srcrect: Maybe(^Rect), dst: ^Surface, dstrect: Maybe(^Rect)) -> bool --- BlitSurfaceTiledWithScale :: proc(src: ^Surface, srcrect: Maybe(^Rect), scale: f32, scaleMode: ScaleMode, dst: ^Surface, dstrect: Maybe(^Rect)) -> bool --- BlitSurface9Grid :: proc(src: ^Surface, srcrect: Maybe(^Rect), left_width, right_width, top_height, bottom_height: c.int, scale: f32, scaleMode: ScaleMode, dst: ^Surface, dstrect: Maybe(^Rect)) -> bool --- diff --git a/vendor/sdl3/sdl3_version.odin b/vendor/sdl3/sdl3_version.odin index 9a1f21add..9143a977b 100644 --- a/vendor/sdl3/sdl3_version.odin +++ b/vendor/sdl3/sdl3_version.odin @@ -4,7 +4,7 @@ import "core:c" MAJOR_VERSION :: 3 MINOR_VERSION :: 2 -MICRO_VERSION :: 2 +MICRO_VERSION :: 10 @(require_results) VERSIONNUM :: #force_inline proc "c" (major, minor, patch: c.int) -> c.int { return (major * 1000000) + (minor * 1000) + patch } @(require_results) VERSIONNUM_MAJOR :: #force_inline proc "c" (version: c.int) -> c.int { return version / 1000000 } From b0316b7076c9954383574f65fc135db16f17c1c0 Mon Sep 17 00:00:00 2001 From: Laytan Date: Wed, 2 Apr 2025 21:13:10 +0200 Subject: [PATCH 70/81] ci: update to LLVM 20 on MacOS and Linux CI and releases --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/nightly.yml | 14 +++++++------- build_odin.sh | 2 +- ci/build_linux_static.sh | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ede32f093..15bfe81cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,14 +93,14 @@ jobs: - name: Download LLVM (MacOS Intel) if: matrix.os == 'macos-13' run: | - brew install llvm@18 lua@5.4 - echo "/usr/local/opt/llvm@18/bin" >> $GITHUB_PATH + brew install llvm@20 lua@5.4 lld + echo "/usr/local/opt/llvm@20/bin" >> $GITHUB_PATH - name: Download LLVM (MacOS ARM) if: matrix.os == 'macos-14' run: | - brew install llvm@18 wasmtime lua@5.4 - echo "/opt/homebrew/opt/llvm@18/bin" >> $GITHUB_PATH + brew install llvm@20 wasmtime lua@5.4 lld + echo "/opt/homebrew/opt/llvm@20/bin" >> $GITHUB_PATH - name: Build Odin run: ./build_odin.sh release diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 314711efb..dfacc2712 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -49,12 +49,12 @@ jobs: - uses: actions/checkout@v4 - uses: jirutka/setup-alpine@v1 with: - branch: v3.20 + branch: edge - name: (Linux) Download LLVM run: | apk add --no-cache \ - musl-dev llvm18-dev clang18 git mold lz4 \ - libxml2-static llvm18-static zlib-static zstd-static \ + musl-dev llvm20-dev clang20 git mold lz4 \ + libxml2-static llvm20-static zlib-static zstd-static \ make shell: alpine.sh --root {0} - name: build odin @@ -93,8 +93,8 @@ jobs: - uses: actions/checkout@v4 - name: Download LLVM and setup PATH run: | - brew install llvm@18 dylibbundler - echo "/usr/local/opt/llvm@18/bin" >> $GITHUB_PATH + brew install llvm@20 dylibbundler lld + echo "/usr/local/opt/llvm@20/bin" >> $GITHUB_PATH - name: build odin # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to # not link with libunwind bundled with LLVM but link with libunwind on the system. @@ -130,8 +130,8 @@ jobs: - uses: actions/checkout@v4 - name: Download LLVM and setup PATH run: | - brew install llvm@18 dylibbundler - echo "/opt/homebrew/opt/llvm@18/bin" >> $GITHUB_PATH + brew install llvm@20 dylibbundler lld + echo "/opt/homebrew/opt/llvm@20/bin" >> $GITHUB_PATH - name: build odin # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to # not link with libunwind bundled with LLVM but link with libunwind on the system. diff --git a/build_odin.sh b/build_odin.sh index 773958d5f..19bb82a11 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -25,7 +25,7 @@ error() { # Brew advises people not to add llvm to their $PATH, so try and use brew to find it. if [ -z "$LLVM_CONFIG" ] && [ -n "$(command -v brew)" ]; then - if [ -n "$(command -v $(brew --prefix llvm)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm)/bin/llvm-config" + if [ -n "$(command -v $(brew --prefix llvm@20)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@20)/bin/llvm-config" elif [ -n "$(command -v $(brew --prefix llvm@19)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@19)/bin/llvm-config" elif [ -n "$(command -v $(brew --prefix llvm@18)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@18)/bin/llvm-config" elif [ -n "$(command -v $(brew --prefix llvm@17)/bin/llvm-config)" ]; then LLVM_CONFIG="$(brew --prefix llvm@17)/bin/llvm-config" diff --git a/ci/build_linux_static.sh b/ci/build_linux_static.sh index f821cbb59..2eb99116e 100755 --- a/ci/build_linux_static.sh +++ b/ci/build_linux_static.sh @@ -1,8 +1,8 @@ #!/usr/bin/env sh # Intended for use in Alpine containers, see the "nightly" Github action for a list of dependencies -CXX="clang++-18" -LLVM_CONFIG="llvm-config-18" +CXX="clang++-20" +LLVM_CONFIG="llvm-config-20" DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value" From cab323976023fe682cc6101b205fc6dba5e98b2a Mon Sep 17 00:00:00 2001 From: Laytan Date: Wed, 2 Apr 2025 21:17:45 +0200 Subject: [PATCH 71/81] ci: fix macos llvm 20 --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/nightly.yml | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 15bfe81cf..9ffdf0c8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,14 +93,14 @@ jobs: - name: Download LLVM (MacOS Intel) if: matrix.os == 'macos-13' run: | - brew install llvm@20 lua@5.4 lld - echo "/usr/local/opt/llvm@20/bin" >> $GITHUB_PATH + brew install llvm lua@5.4 lld + brew --prefix llvm@20 # Verifies it is LLVM 20 - name: Download LLVM (MacOS ARM) if: matrix.os == 'macos-14' run: | - brew install llvm@20 wasmtime lua@5.4 lld - echo "/opt/homebrew/opt/llvm@20/bin" >> $GITHUB_PATH + brew install llvm wasmtime lua@5.4 lld + brew --prefix llvm@20 # Verifies it is LLVM 20 - name: Build Odin run: ./build_odin.sh release diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index dfacc2712..b137c0ee8 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -93,8 +93,9 @@ jobs: - uses: actions/checkout@v4 - name: Download LLVM and setup PATH run: | - brew install llvm@20 dylibbundler lld - echo "/usr/local/opt/llvm@20/bin" >> $GITHUB_PATH + brew install llvm dylibbundler lld + brew --prefix llvm@20 # Verifies it is LLVM 20 + - name: build odin # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to # not link with libunwind bundled with LLVM but link with libunwind on the system. @@ -130,8 +131,9 @@ jobs: - uses: actions/checkout@v4 - name: Download LLVM and setup PATH run: | - brew install llvm@20 dylibbundler lld - echo "/opt/homebrew/opt/llvm@20/bin" >> $GITHUB_PATH + brew install llvm dylibbundler lld + brew --prefix llvm@20 # Verifies it is LLVM 20 + - name: build odin # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to # not link with libunwind bundled with LLVM but link with libunwind on the system. From 85b3a79a258d1e39d3cf83b3e56d11ffee7924be Mon Sep 17 00:00:00 2001 From: Laytan Date: Wed, 2 Apr 2025 21:22:18 +0200 Subject: [PATCH 72/81] ci: brew update? --- .github/workflows/ci.yml | 2 ++ .github/workflows/nightly.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ffdf0c8c..860ba08a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,12 +93,14 @@ jobs: - name: Download LLVM (MacOS Intel) if: matrix.os == 'macos-13' run: | + brew update brew install llvm lua@5.4 lld brew --prefix llvm@20 # Verifies it is LLVM 20 - name: Download LLVM (MacOS ARM) if: matrix.os == 'macos-14' run: | + brew update brew install llvm wasmtime lua@5.4 lld brew --prefix llvm@20 # Verifies it is LLVM 20 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index b137c0ee8..76052743c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -93,6 +93,7 @@ jobs: - uses: actions/checkout@v4 - name: Download LLVM and setup PATH run: | + brew update brew install llvm dylibbundler lld brew --prefix llvm@20 # Verifies it is LLVM 20 @@ -131,6 +132,7 @@ jobs: - uses: actions/checkout@v4 - name: Download LLVM and setup PATH run: | + brew update brew install llvm dylibbundler lld brew --prefix llvm@20 # Verifies it is LLVM 20 From 4eef57c6f1f7e64f774e6982902dc5e85e740a38 Mon Sep 17 00:00:00 2001 From: Laytan Date: Wed, 2 Apr 2025 21:24:12 +0200 Subject: [PATCH 73/81] ci: ok, had to brew update, can we now request @20 directly? --- .github/workflows/ci.yml | 6 ++---- .github/workflows/nightly.yml | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 860ba08a5..1a1d18231 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,15 +94,13 @@ jobs: if: matrix.os == 'macos-13' run: | brew update - brew install llvm lua@5.4 lld - brew --prefix llvm@20 # Verifies it is LLVM 20 + brew install llvm@20 lua@5.4 lld - name: Download LLVM (MacOS ARM) if: matrix.os == 'macos-14' run: | brew update - brew install llvm wasmtime lua@5.4 lld - brew --prefix llvm@20 # Verifies it is LLVM 20 + brew install llvm@20 wasmtime lua@5.4 lld - name: Build Odin run: ./build_odin.sh release diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 76052743c..eb67eb209 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -94,8 +94,7 @@ jobs: - name: Download LLVM and setup PATH run: | brew update - brew install llvm dylibbundler lld - brew --prefix llvm@20 # Verifies it is LLVM 20 + brew install llvm@20 dylibbundler lld - name: build odin # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to @@ -133,8 +132,7 @@ jobs: - name: Download LLVM and setup PATH run: | brew update - brew install llvm dylibbundler lld - brew --prefix llvm@20 # Verifies it is LLVM 20 + brew install llvm@20 dylibbundler lld - name: build odin # These -L makes the linker prioritize system libraries over LLVM libraries, this is mainly to From c5980ba6c4ffaa570ea7bd629dc6e1886ec0456c Mon Sep 17 00:00:00 2001 From: Harold Brenes Date: Wed, 2 Apr 2025 16:39:25 -0400 Subject: [PATCH 74/81] Add linux build tag to core/sys/linux/sys.odin --- core/sys/linux/sys.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index 5fc4a0efa..985623e85 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -1,3 +1,4 @@ +#+build linux #+no-instrumentation package linux From cd5bef4f610ec3ee32957cbca354ccbfef310921 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Apr 2025 09:33:14 +0100 Subject: [PATCH 75/81] Rewrite objc SEL/Class register handling code --- src/llvm_backend.cpp | 45 +++++++++---- src/llvm_backend.hpp | 21 ++++--- src/llvm_backend_general.cpp | 2 + src/llvm_backend_utility.cpp | 118 +++++++++++++++-------------------- 4 files changed, 96 insertions(+), 90 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 6f3abc607..396b94f98 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1126,30 +1126,51 @@ gb_internal lbProcedure *lb_create_objc_names(lbModule *main_module) { return p; } -gb_internal void lb_finalize_objc_names(lbProcedure *p) { +gb_internal void lb_finalize_objc_names(lbGenerator *gen, lbProcedure *p) { if (p == nullptr) { return; } lbModule *m = p->module; + GB_ASSERT(m == &p->module->gen->default_module); TEMPORARY_ALLOCATOR_GUARD(); + StringSet handled = {}; + string_set_init(&handled); + defer (string_set_destroy(&handled)); + auto args = array_make(temporary_allocator(), 1); LLVMSetLinkage(p->value, LLVMInternalLinkage); lb_begin_procedure_body(p); - for (auto const &entry : m->objc_classes) { - String name = entry.key; - args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); - lbValue ptr = lb_emit_runtime_call(p, "objc_lookUpClass", args); - lb_addr_store(p, entry.value.local_module_addr, ptr); + + auto register_thing = [&handled, &m, &args](lbProcedure *p, lbObjCGlobal const &g, char const *call) { + if (!string_set_update(&handled, g.name)) { + lbAddr addr = {}; + lbValue *found = string_map_get(&m->members, g.global_name); + if (found) { + addr = lb_addr(*found); + } else { + lbValue v = {}; + LLVMTypeRef t = lb_type(m, g.type); + v.value = LLVMAddGlobal(m->mod, t, g.global_name); + v.type = alloc_type_pointer(g.type); + addr = lb_addr(v); + LLVMSetInitializer(v.value, LLVMConstNull(t)); + } + + args[0] = lb_const_value(m, t_cstring, exact_value_string(g.name)); + lbValue ptr = lb_emit_runtime_call(p, call, args); + lb_addr_store(p, addr, ptr); + } + }; + + for (lbObjCGlobal g = {}; mpsc_dequeue(&gen->objc_classes, &g); /**/) { + register_thing(p, g, "objc_lookUpClass"); } - for (auto const &entry : m->objc_selectors) { - String name = entry.key; - args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); - lbValue ptr = lb_emit_runtime_call(p, "sel_registerName", args); - lb_addr_store(p, entry.value.local_module_addr, ptr); + for (lbObjCGlobal g = {}; mpsc_dequeue(&gen->objc_selectors, &g); /**/) { + register_thing(p, g, "sel_registerName"); } lb_end_procedure_body(p); @@ -2637,7 +2658,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { if (gen->objc_names) { TIME_SECTION("Finalize objc names"); - lb_finalize_objc_names(gen->objc_names); + lb_finalize_objc_names(gen, gen->objc_names); } if (build_context.ODIN_DEBUG) { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index f9f96a906..3e01ada5f 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -143,11 +143,6 @@ struct lbPadType { LLVMTypeRef type; }; -struct lbObjcRef { - Entity * entity; - lbAddr local_module_addr; -}; - struct lbModule { LLVMModuleRef mod; LLVMContextRef ctx; @@ -199,11 +194,8 @@ struct lbModule { PtrMap debug_values; - RecursiveMutex objc_classes_mutex; - RecursiveMutex objc_selectors_mutex; - - StringMap objc_classes; - StringMap objc_selectors; + StringMap objc_classes; + StringMap objc_selectors; PtrMap map_cell_info_map; // address of runtime.Map_Info PtrMap map_info_map; // address of runtime.Map_Cell_Info @@ -222,6 +214,13 @@ struct lbEntityCorrection { char const *cname; }; +struct lbObjCGlobal { + lbModule *module; + gbString global_name; + String name; + Type * type; +}; + struct lbGenerator : LinkerData { CheckerInfo *info; @@ -239,6 +238,8 @@ struct lbGenerator : LinkerData { lbProcedure *objc_names; MPSCQueue entities_to_correct_linkage; + MPSCQueue objc_selectors; + MPSCQueue objc_classes; }; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index b7f70893f..ce2c70661 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -171,6 +171,8 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { } mpsc_init(&gen->entities_to_correct_linkage, heap_allocator()); + mpsc_init(&gen->objc_selectors, heap_allocator()); + mpsc_init(&gen->objc_classes, heap_allocator()); return true; } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index efe196e58..0decbcdb8 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2094,48 +2094,71 @@ gb_internal void lb_set_wasm_export_attributes(LLVMValueRef value, String export } - gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) { - mutex_lock(&p->module->objc_selectors_mutex); - defer (mutex_unlock(&p->module->objc_selectors_mutex)); - - lbObjcRef *found = string_map_get(&p->module->objc_selectors, name); - + lbModule *m = p->module; + lbAddr *found = string_map_get(&m->objc_selectors, name); if (found) { - return found->local_module_addr; + return *found; } lbModule *default_module = &p->module->gen->default_module; - Entity *entity = {}; - if (default_module != p->module) { - found = string_map_get(&default_module->objc_selectors, name); - if (found) { - entity = found->entity; - } + + gbString global_name = gb_string_make(permanent_allocator(), "__$objc_SEL::"); + global_name = gb_string_append_length(global_name, name.text, name.len); + + LLVMTypeRef t = lb_type(m, t_objc_SEL); + lbValue g = {}; + g.value = LLVMAddGlobal(m->mod, t, global_name); + g.type = alloc_type_pointer(t_objc_SEL); + + if (default_module == m) { + LLVMSetInitializer(g.value, LLVMConstNull(t)); + lb_add_member(m, make_string_c(global_name), g); + } else { + LLVMSetLinkage(g.value, LLVMExternalLinkage); } - if (!entity) { - gbString global_name = gb_string_make(permanent_allocator(), "__$objc_SEL::"); - global_name = gb_string_append_length(global_name, name.text, name.len); + mpsc_enqueue(&m->gen->objc_selectors, lbObjCGlobal{m, global_name, name, t_objc_SEL}); - lbAddr default_addr = lb_add_global_generated_with_name(default_module, t_objc_SEL, {}, - make_string(cast(u8 const *)global_name, gb_string_length(global_name)), - &entity); + lbAddr addr = lb_addr(g); - mutex_lock(&default_module->objc_selectors_mutex); - string_map_set(&default_module->objc_selectors, name, lbObjcRef{entity, default_addr}); - mutex_unlock(&default_module->objc_selectors_mutex); + string_map_set(&m->objc_selectors, name, addr); + + return addr; +} + +gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String const &name) { + lbModule *m = p->module; + lbAddr *found = string_map_get(&m->objc_classes, name); + if (found) { + return *found; } - lbValue ptr = lb_find_value_from_entity(p->module, entity); - lbAddr local_addr = lb_addr(ptr); + lbModule *default_module = &p->module->gen->default_module; - if (default_module != p->module) { - string_map_set(&p->module->objc_selectors, name, lbObjcRef{entity, local_addr}); + + gbString global_name = gb_string_make(permanent_allocator(), "__$objc_Class::"); + global_name = gb_string_append_length(global_name, name.text, name.len); + + LLVMTypeRef t = lb_type(m, t_objc_Class); + lbValue g = {}; + g.value = LLVMAddGlobal(m->mod, t, global_name); + g.type = alloc_type_pointer(t_objc_Class); + + if (default_module == m) { + LLVMSetInitializer(g.value, LLVMConstNull(t)); + lb_add_member(m, make_string_c(global_name), g); + } else { + LLVMSetLinkage(g.value, LLVMExternalLinkage); } + mpsc_enqueue(&m->gen->objc_classes, lbObjCGlobal{m, global_name, name, t_objc_Class}); - return local_addr; + lbAddr addr = lb_addr(g); + + string_map_set(&m->objc_classes, name, addr); + + return addr; } gb_internal lbValue lb_handle_objc_find_selector(lbProcedure *p, Ast *expr) { @@ -2164,47 +2187,6 @@ gb_internal lbValue lb_handle_objc_register_selector(lbProcedure *p, Ast *expr) return lb_addr_load(p, dst); } -gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String const &name) { - mutex_lock(&p->module->objc_classes_mutex); - defer (mutex_unlock(&p->module->objc_classes_mutex)); - - lbObjcRef *found = string_map_get(&p->module->objc_classes, name); - if (found) { - return found->local_module_addr; - } - - lbModule *default_module = &p->module->gen->default_module; - Entity *entity = {}; - - if (default_module != p->module) { - found = string_map_get(&default_module->objc_classes, name); - if (found) { - entity = found->entity; - } - } - - if (!entity) { - gbString global_name = gb_string_make(permanent_allocator(), "__$objc_Class::"); - global_name = gb_string_append_length(global_name, name.text, name.len); - - lbAddr default_addr = lb_add_global_generated_with_name(default_module, t_objc_Class, {}, - make_string(cast(u8 const *)global_name, gb_string_length(global_name)), - &entity); - - mutex_lock(&default_module->objc_classes_mutex); - string_map_set(&default_module->objc_classes, name, lbObjcRef{entity, default_addr}); - mutex_unlock(&default_module->objc_classes_mutex); - } - - lbValue ptr = lb_find_value_from_entity(p->module, entity); - lbAddr local_addr = lb_addr(ptr); - - if (default_module != p->module) { - string_map_set(&p->module->objc_classes, name, lbObjcRef{entity, local_addr}); - } - - return local_addr; -} gb_internal lbValue lb_handle_objc_find_class(lbProcedure *p, Ast *expr) { ast_node(ce, CallExpr, expr); From e412d3b4c15d24c644723ea89960f3507a0b6618 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Apr 2025 09:48:30 +0100 Subject: [PATCH 76/81] Minor clean up to `lb_handle_objc_find_or_register_internal` --- src/llvm_backend_utility.cpp | 49 +++++++++--------------------------- 1 file changed, 12 insertions(+), 37 deletions(-) diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 0decbcdb8..4064b3134 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2094,9 +2094,9 @@ gb_internal void lb_set_wasm_export_attributes(LLVMValueRef value, String export } -gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) { +gb_internal lbAddr lb_handle_objc_find_or_register_internal(lbProcedure *p, StringMap *objc_map, String const &name, char const *prefix, Type *type) { lbModule *m = p->module; - lbAddr *found = string_map_get(&m->objc_selectors, name); + lbAddr *found = string_map_get(objc_map, name); if (found) { return *found; } @@ -2104,13 +2104,13 @@ gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, Stri lbModule *default_module = &p->module->gen->default_module; - gbString global_name = gb_string_make(permanent_allocator(), "__$objc_SEL::"); + gbString global_name = gb_string_make(permanent_allocator(), prefix); global_name = gb_string_append_length(global_name, name.text, name.len); - LLVMTypeRef t = lb_type(m, t_objc_SEL); + LLVMTypeRef t = lb_type(m, type); lbValue g = {}; g.value = LLVMAddGlobal(m->mod, t, global_name); - g.type = alloc_type_pointer(t_objc_SEL); + g.type = alloc_type_pointer(type); if (default_module == m) { LLVMSetInitializer(g.value, LLVMConstNull(t)); @@ -2119,46 +2119,21 @@ gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, Stri LLVMSetLinkage(g.value, LLVMExternalLinkage); } - mpsc_enqueue(&m->gen->objc_selectors, lbObjCGlobal{m, global_name, name, t_objc_SEL}); + mpsc_enqueue(&m->gen->objc_selectors, lbObjCGlobal{m, global_name, name, type}); lbAddr addr = lb_addr(g); - string_map_set(&m->objc_selectors, name, addr); + string_map_set(objc_map, name, addr); return addr; } +gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) { + return lb_handle_objc_find_or_register_internal(p, &p->module->objc_selectors, name, "__$objc_SEL::", t_objc_SEL); +} + gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String const &name) { - lbModule *m = p->module; - lbAddr *found = string_map_get(&m->objc_classes, name); - if (found) { - return *found; - } - - lbModule *default_module = &p->module->gen->default_module; - - - gbString global_name = gb_string_make(permanent_allocator(), "__$objc_Class::"); - global_name = gb_string_append_length(global_name, name.text, name.len); - - LLVMTypeRef t = lb_type(m, t_objc_Class); - lbValue g = {}; - g.value = LLVMAddGlobal(m->mod, t, global_name); - g.type = alloc_type_pointer(t_objc_Class); - - if (default_module == m) { - LLVMSetInitializer(g.value, LLVMConstNull(t)); - lb_add_member(m, make_string_c(global_name), g); - } else { - LLVMSetLinkage(g.value, LLVMExternalLinkage); - } - mpsc_enqueue(&m->gen->objc_classes, lbObjCGlobal{m, global_name, name, t_objc_Class}); - - lbAddr addr = lb_addr(g); - - string_map_set(&m->objc_classes, name, addr); - - return addr; + return lb_handle_objc_find_or_register_internal(p, &p->module->objc_classes, name, "__$objc_Class::", t_objc_Class); } gb_internal lbValue lb_handle_objc_find_selector(lbProcedure *p, Ast *expr) { From 4ebaed1fddd21a42623bfeff32558496e424326c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Apr 2025 09:54:44 +0100 Subject: [PATCH 77/81] Remove refactor --- src/llvm_backend_utility.cpp | 49 +++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 4064b3134..bfeebfcbe 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2094,23 +2094,22 @@ gb_internal void lb_set_wasm_export_attributes(LLVMValueRef value, String export } -gb_internal lbAddr lb_handle_objc_find_or_register_internal(lbProcedure *p, StringMap *objc_map, String const &name, char const *prefix, Type *type) { +gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) { lbModule *m = p->module; - lbAddr *found = string_map_get(objc_map, name); + lbAddr *found = string_map_get(&m->objc_selectors, name); if (found) { return *found; } lbModule *default_module = &p->module->gen->default_module; - - gbString global_name = gb_string_make(permanent_allocator(), prefix); + gbString global_name = gb_string_make(permanent_allocator(), "__$objc_SEL::"); global_name = gb_string_append_length(global_name, name.text, name.len); - LLVMTypeRef t = lb_type(m, type); + LLVMTypeRef t = lb_type(m, t_objc_SEL); lbValue g = {}; g.value = LLVMAddGlobal(m->mod, t, global_name); - g.type = alloc_type_pointer(type); + g.type = alloc_type_pointer(t_objc_SEL); if (default_module == m) { LLVMSetInitializer(g.value, LLVMConstNull(t)); @@ -2119,21 +2118,41 @@ gb_internal lbAddr lb_handle_objc_find_or_register_internal(lbProcedure *p, Stri LLVMSetLinkage(g.value, LLVMExternalLinkage); } - mpsc_enqueue(&m->gen->objc_selectors, lbObjCGlobal{m, global_name, name, type}); + mpsc_enqueue(&m->gen->objc_selectors, lbObjCGlobal{m, global_name, name, t_objc_SEL}); lbAddr addr = lb_addr(g); - - string_map_set(objc_map, name, addr); - + string_map_set(&m->objc_selectors, name, addr); return addr; } -gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) { - return lb_handle_objc_find_or_register_internal(p, &p->module->objc_selectors, name, "__$objc_SEL::", t_objc_SEL); -} - gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String const &name) { - return lb_handle_objc_find_or_register_internal(p, &p->module->objc_classes, name, "__$objc_Class::", t_objc_Class); + lbModule *m = p->module; + lbAddr *found = string_map_get(&m->objc_classes, name); + if (found) { + return *found; + } + + lbModule *default_module = &p->module->gen->default_module; + + gbString global_name = gb_string_make(permanent_allocator(), "__$objc_Class::"); + global_name = gb_string_append_length(global_name, name.text, name.len); + + LLVMTypeRef t = lb_type(m, t_objc_Class); + lbValue g = {}; + g.value = LLVMAddGlobal(m->mod, t, global_name); + g.type = alloc_type_pointer(t_objc_Class); + + if (default_module == m) { + LLVMSetInitializer(g.value, LLVMConstNull(t)); + lb_add_member(m, make_string_c(global_name), g); + } else { + LLVMSetLinkage(g.value, LLVMExternalLinkage); + } + mpsc_enqueue(&m->gen->objc_classes, lbObjCGlobal{m, global_name, name, t_objc_Class}); + + lbAddr addr = lb_addr(g); + string_map_set(&m->objc_classes, name, addr); + return addr; } gb_internal lbValue lb_handle_objc_find_selector(lbProcedure *p, Ast *expr) { From ce5b7cccab8d217e09bb543ffe0f63cbadc5be75 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Apr 2025 10:04:14 +0100 Subject: [PATCH 78/81] Fix `lb_add_debug_local_variable` to use the correct procedure in LLVM 20 --- src/llvm_backend_debug.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 926daaae4..53c007d8d 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -1089,7 +1089,7 @@ gb_internal void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, T #if LLVM_VERSION_MAJOR <= 18 LLVMDIBuilderInsertDeclareAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); #else - LLVMDIBuilderInsertDbgValueRecordAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); + LLVMDIBuilderInsertDeclareRecordAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); #endif } From 5be052f288385e48582a7f51c459c40153bfbc6f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Apr 2025 10:20:08 +0100 Subject: [PATCH 79/81] Fix #4995 --- vendor/x11/xlib/xlib_procs.odin | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vendor/x11/xlib/xlib_procs.odin b/vendor/x11/xlib/xlib_procs.odin index 780cf1b97..203cf5782 100644 --- a/vendor/x11/xlib/xlib_procs.odin +++ b/vendor/x11/xlib/xlib_procs.odin @@ -190,8 +190,8 @@ foreign xlib { display: ^Display, window: Window, mask: WindowChangesMask, - values: XWindowChanges, - ) --- + changes: ^XWindowChanges, + ) -> i32 --- MoveWindow :: proc( display: ^Display, window: Window, @@ -255,11 +255,11 @@ foreign xlib { display: ^Display, window: Window, cursor: Cursor, - ) --- + ) -> i32 --- UndefineCursor :: proc( display: ^Display, window: Window, - ) --- + ) -> i32 --- // Windows: querying information QueryTree :: proc( display: ^Display, @@ -273,7 +273,7 @@ foreign xlib { display: ^Display, window: Window, attr: ^XWindowAttributes, - ) --- + ) -> i32 --- GetGeometry :: proc( display: ^Display, drawable: Drawable, @@ -357,19 +357,19 @@ foreign xlib { mode: i32, data: rawptr, count: i32, - ) --- + ) -> i32 --- RotateWindowProperties :: proc( display: ^Display, window: Window, props: [^]Atom, nprops: i32, npos: i32, - ) --- + ) -> i32 --- DeleteProperty :: proc( display: ^Display, window: Window, prop: Atom, - ) --- + ) -> i32 --- // Selections SetSelectionOwner :: proc( display: ^Display, @@ -1012,8 +1012,8 @@ foreign xlib { DisableAccessControl :: proc(display: ^Display) --- // Events SelectInput :: proc(display: ^Display, window: Window, mask: EventMask) --- - Flush :: proc(display: ^Display) --- - Sync :: proc(display: ^Display) --- + Flush :: proc(display: ^Display) -> i32 --- + Sync :: proc(display: ^Display, discard: Bool) -> i32 --- EventsQueued :: proc(display: ^Display, mode: EventQueueMode) -> i32 --- Pending :: proc(display: ^Display) -> i32 --- NextEvent :: proc(display: ^Display, event: ^XEvent) --- From 511c18629749de61e3755152a440ed80cd46ed1e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Apr 2025 10:23:35 +0100 Subject: [PATCH 80/81] Fix typo --- vendor/x11/xlib/xlib_procs.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/x11/xlib/xlib_procs.odin b/vendor/x11/xlib/xlib_procs.odin index 203cf5782..2a8d6832b 100644 --- a/vendor/x11/xlib/xlib_procs.odin +++ b/vendor/x11/xlib/xlib_procs.odin @@ -1013,7 +1013,7 @@ foreign xlib { // Events SelectInput :: proc(display: ^Display, window: Window, mask: EventMask) --- Flush :: proc(display: ^Display) -> i32 --- - Sync :: proc(display: ^Display, discard: Bool) -> i32 --- + Sync :: proc(display: ^Display, discard: bool) -> i32 --- EventsQueued :: proc(display: ^Display, mode: EventQueueMode) -> i32 --- Pending :: proc(display: ^Display) -> i32 --- NextEvent :: proc(display: ^Display, event: ^XEvent) --- From d9f990d42e2a1bccf3e7be8ba02efa6504e9af9b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Apr 2025 10:55:35 +0100 Subject: [PATCH 81/81] Fix #4975 --- src/check_decl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 5607ea725..250e8b854 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -628,6 +628,10 @@ gb_internal void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr Operand x = {}; x.type = entity->type; x.mode = Addressing_Variable; + if (entity->kind == Entity_Constant) { + x.mode = Addressing_Constant; + x.value = entity->Constant.value; + } if (!check_is_assignable_to(ctx, &x, e->type)) { gbString expr_str = expr_to_string(init); gbString op_type_str = type_to_string(entity->type);

YFRg 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