From 83f039cdf796358d3d9b5f225c4015089b0167bb Mon Sep 17 00:00:00 2001 From: Christian Baars Date: Sun, 5 Mar 2023 16:46:18 +0100 Subject: [PATCH] Berry: add tensorflow lite for microcontrollers (#18119) Co-authored-by: Christian Baars --- lib/libesp32/berry/default/be_modtab.c | 4 + lib/libesp32/berry_tasmota/src/be_TFL_lib.c | 47 + .../mel_freq_extractor/library.properties | 7 + lib/libesp32_ml/mel_freq_extractor/src/mfcc.h | 315 + lib/libesp32_ml/tf_lite_esp32/AUTHORS | 9 + lib/libesp32_ml/tf_lite_esp32/CODEOWNERS | 4 + lib/libesp32_ml/tf_lite_esp32/LICENSE | 202 + lib/libesp32_ml/tf_lite_esp32/README.md | 80 + .../examples/hello_world/README.md | 59 + .../hello_world/arduino_constants.cpp | 20 + .../examples/hello_world/arduino_main.cpp | 20 + .../hello_world/arduino_output_handler.cpp | 54 + .../examples/hello_world/constants.h | 32 + .../examples/hello_world/hello_world.ino | 123 + .../examples/hello_world/main_functions.h | 37 + .../examples/hello_world/model.cpp | 237 + .../examples/hello_world/model.h | 31 + .../examples/hello_world/output_handler.h | 26 + .../tf_lite_esp32/examples/magic_wand/LICENSE | 201 + .../examples/magic_wand/README.md | 114 + .../examples/magic_wand/magic_wand.ino | 708 + .../magic_wand/magic_wand_model_data.cpp | 2588 ++ .../magic_wand/magic_wand_model_data.h | 24 + .../examples/magic_wand/rasterize_stroke.cpp | 157 + .../examples/magic_wand/rasterize_stroke.h | 22 + .../train/train_magic_wand_model.ipynb | 1 + .../examples/magic_wand/website/index.html | 474 + .../examples/micro_speech/README.md | 84 + .../micro_speech/arduino_audio_provider.cpp | 194 + .../arduino_command_responder.cpp | 89 + .../examples/micro_speech/arduino_main.cpp | 20 + .../examples/micro_speech/audio_provider.h | 49 + .../examples/micro_speech/command_responder.h | 32 + .../micro_speech/feature_provider.cpp | 127 + .../examples/micro_speech/feature_provider.h | 52 + .../examples/micro_speech/main_functions.h | 37 + ...icro_features_micro_features_generator.cpp | 116 + .../micro_features_micro_features_generator.h | 32 + .../micro_features_micro_model_settings.cpp | 23 + .../micro_features_micro_model_settings.h | 43 + .../micro_speech/micro_features_model.cpp | 1596 ++ .../micro_speech/micro_features_model.h | 27 + .../examples/micro_speech/micro_speech.ino | 216 + .../micro_speech/recognize_commands.cpp | 159 + .../micro_speech/recognize_commands.h | 159 + .../examples/person_detection/README.md | 69 + .../arduino_detection_responder.cpp | 76 + .../arduino_image_provider.cpp | 199 + .../person_detection/arduino_main.cpp | 20 + .../person_detection/detection_responder.h | 34 + .../person_detection/image_provider.h | 40 + .../person_detection/main_functions.h | 37 + .../person_detection/model_settings.cpp | 21 + .../person_detection/model_settings.h | 35 + .../person_detect_model_data.cpp | 23148 ++++++++++++++++ .../person_detect_model_data.h | 27 + .../person_detection/person_detection.ino | 132 + lib/libesp32_ml/tf_lite_esp32/library.json | 15 + .../tf_lite_esp32/library.properties | 13 + .../tf_lite_esp32/src/TensorFlowLite.h | 26 + .../tf_lite_esp32/src/esp-nn/.gitignore | 57 + .../tf_lite_esp32/src/esp-nn/.gitlab-ci.yml | 55 + .../tf_lite_esp32/src/esp-nn/LICENSE | 202 + .../tf_lite_esp32/src/esp-nn/README.md | 55 + .../tf_lite_esp32/src/esp-nn/include/esp_nn.h | 46 + .../src/esp-nn/include/esp_nn_ansi_c.h | 47 + .../src/esp-nn/include/esp_nn_ansi_headers.h | 309 + .../src/esp-nn/include/esp_nn_defs.h | 83 + .../src/esp-nn/include/esp_nn_esp32s3.h | 233 + .../src/esp-nn/include/esp_nn_generic_opt.h | 47 + .../activation_functions/esp_nn_relu_ansi.c | 30 + .../esp-nn/src/basic_math/esp_nn_add_ansi.c | 97 + .../esp-nn/src/basic_math/esp_nn_mul_ansi.c | 42 + .../src/esp-nn/src/common/common_functions.h | 255 + .../esp-nn/src/convolution/esp_nn_conv_ansi.c | 179 + .../src/convolution/esp_nn_conv_esp32s3.c | 463 + .../esp-nn/src/convolution/esp_nn_conv_opt.c | 179 + .../convolution/esp_nn_depthwise_conv_ansi.c | 100 + .../convolution/esp_nn_depthwise_conv_opt.c | 291 + .../esp_nn_depthwise_conv_s8_esp32s3.c | 543 + .../esp_nn_fully_connected_ansi.c | 50 + .../esp-nn/src/pooling/esp_nn_avg_pool_ansi.c | 72 + .../esp-nn/src/pooling/esp_nn_max_pool_ansi.c | 66 + .../esp-nn/src/softmax/esp_nn_softmax_ansi.c | 88 + .../esp-nn/src/softmax/esp_nn_softmax_opt.c | 108 + .../src/esp-nn/src/softmax/softmax_common.h | 104 + .../src/tensorflow/lite/builtin_op_data.h | 22 + .../src/tensorflow/lite/builtin_ops.h | 194 + .../src/tensorflow/lite/c/builtin_op_data.h | 525 + .../src/tensorflow/lite/c/c_api_types.h | 147 + .../src/tensorflow/lite/c/common.cpp | 321 + .../src/tensorflow/lite/c/common.h | 1110 + .../src/tensorflow/lite/context_util.h | 53 + .../lite/core/api/error_reporter.cpp | 38 + .../tensorflow/lite/core/api/error_reporter.h | 59 + .../lite/core/api/flatbuffer_conversions.cpp | 2472 ++ .../lite/core/api/flatbuffer_conversions.h | 412 + .../tensorflow/lite/core/api/op_resolver.cpp | 68 + .../tensorflow/lite/core/api/op_resolver.h | 140 + .../tensorflow/lite/core/api/tensor_utils.cpp | 50 + .../tensorflow/lite/core/api/tensor_utils.h | 28 + .../experimental/microfrontend/lib/bits.h | 102 + .../experimental/microfrontend/lib/fft.cpp | 52 + .../lite/experimental/microfrontend/lib/fft.h | 50 + .../microfrontend/lib/fft_util.cpp | 70 + .../experimental/microfrontend/lib/fft_util.h | 34 + .../microfrontend/lib/filterbank.c | 134 + .../microfrontend/lib/filterbank.h | 63 + .../microfrontend/lib/filterbank_util.c | 220 + .../microfrontend/lib/filterbank_util.h | 50 + .../experimental/microfrontend/lib/frontend.c | 72 + .../experimental/microfrontend/lib/frontend.h | 64 + .../microfrontend/lib/frontend_util.c | 85 + .../microfrontend/lib/frontend_util.h | 52 + .../microfrontend/lib/kiss_fft_common.h | 48 + .../microfrontend/lib/kiss_fft_int16.cpp | 10 + .../microfrontend/lib/kiss_fft_int16.h | 33 + .../experimental/microfrontend/lib/log_lut.c | 30 + .../experimental/microfrontend/lib/log_lut.h | 40 + .../microfrontend/lib/log_scale.c | 83 + .../microfrontend/lib/log_scale.h | 39 + .../microfrontend/lib/log_scale_util.c | 27 + .../microfrontend/lib/log_scale_util.h | 45 + .../microfrontend/lib/noise_reduction.c | 51 + .../microfrontend/lib/noise_reduction.h | 46 + .../microfrontend/lib/noise_reduction_util.c | 45 + .../microfrontend/lib/noise_reduction_util.h | 50 + .../microfrontend/lib/pcan_gain_control.c | 56 + .../microfrontend/lib/pcan_gain_control.h | 47 + .../lib/pcan_gain_control_util.c | 92 + .../lib/pcan_gain_control_util.h | 57 + .../experimental/microfrontend/lib/window.c | 70 + .../experimental/microfrontend/lib/window.h | 49 + .../microfrontend/lib/window_util.c | 73 + .../microfrontend/lib/window_util.h | 45 + .../tensorflow/lite/kernels/internal/common.h | 1227 + .../lite/kernels/internal/compatibility.h | 122 + .../lite/kernels/internal/cppmath.h | 40 + .../tensorflow/lite/kernels/internal/max.h | 35 + .../tensorflow/lite/kernels/internal/min.h | 35 + .../kernels/internal/optimized/neon_check.h | 20 + .../lite/kernels/internal/portable_tensor.h | 122 + .../internal/portable_tensor_utils.cpp | 86 + .../kernels/internal/portable_tensor_utils.h | 623 + .../kernels/internal/quantization_util.cpp | 416 + .../lite/kernels/internal/quantization_util.h | 292 + .../lite/kernels/internal/reference/add.h | 400 + .../lite/kernels/internal/reference/add_n.h | 86 + .../kernels/internal/reference/arg_min_max.h | 88 + .../kernels/internal/reference/batch_matmul.h | 275 + .../internal/reference/batch_to_space_nd.h | 101 + .../internal/reference/binary_function.h | 91 + .../internal/reference/broadcast_args.h | 56 + .../kernels/internal/reference/broadcast_to.h | 97 + .../lite/kernels/internal/reference/ceil.h | 37 + .../kernels/internal/reference/comparisons.h | 280 + .../internal/reference/concatenation.h | 141 + .../lite/kernels/internal/reference/conv.h | 287 + .../lite/kernels/internal/reference/cumsum.h | 175 + .../internal/reference/depth_to_space.h | 79 + .../internal/reference/depthwiseconv_float.h | 100 + .../internal/reference/depthwiseconv_uint8.h | 319 + .../kernels/internal/reference/dequantize.h | 78 + .../lite/kernels/internal/reference/div.h | 247 + .../lite/kernels/internal/reference/elu.h | 37 + .../lite/kernels/internal/reference/exp.h | 38 + .../lite/kernels/internal/reference/fill.h | 38 + .../lite/kernels/internal/reference/floor.h | 39 + .../kernels/internal/reference/floor_div.h | 35 + .../kernels/internal/reference/floor_mod.h | 44 + .../internal/reference/fully_connected.h | 323 + .../kernels/internal/reference/hard_swish.h | 168 + .../internal/reference/integer_ops/add.h | 145 + .../internal/reference/integer_ops/conv.h | 254 + .../reference/integer_ops/depthwise_conv.h | 291 + .../reference/integer_ops/fully_connected.h | 201 + .../reference/integer_ops/l2normalization.h | 67 + .../internal/reference/integer_ops/logistic.h | 121 + .../internal/reference/integer_ops/mean.h | 79 + .../internal/reference/integer_ops/mul.h | 133 + .../internal/reference/integer_ops/pooling.h | 264 + .../internal/reference/integer_ops/tanh.h | 117 + .../reference/integer_ops/transpose_conv.h | 224 + .../internal/reference/l2normalization.h | 90 + .../kernels/internal/reference/leaky_relu.h | 69 + .../kernels/internal/reference/log_softmax.h | 256 + .../kernels/internal/reference/logistic.h | 132 + .../kernels/internal/reference/lstm_cell.h | 422 + .../internal/reference/maximum_minimum.h | 64 + .../lite/kernels/internal/reference/mul.h | 214 + .../lite/kernels/internal/reference/neg.h | 37 + .../lite/kernels/internal/reference/pad.h | 169 + .../lite/kernels/internal/reference/pooling.h | 303 + .../reference/portable_tensor_utils.cpp | 809 + .../reference/portable_tensor_utils.h | 333 + .../reference/portable_tensor_utils_impl.h | 244 + .../lite/kernels/internal/reference/prelu.h | 111 + .../reference/process_broadcast_shapes.h | 140 + .../kernels/internal/reference/quantize.h | 89 + .../lite/kernels/internal/reference/reduce.h | 526 + .../kernels/internal/reference/requantize.h | 70 + .../internal/reference/resize_bilinear.h | 228 + .../reference/resize_nearest_neighbor.h | 102 + .../lite/kernels/internal/reference/round.h | 51 + .../lite/kernels/internal/reference/select.h | 151 + .../lite/kernels/internal/reference/slice.h | 80 + .../lite/kernels/internal/reference/softmax.h | 233 + .../internal/reference/space_to_batch_nd.h | 109 + .../internal/reference/space_to_depth.h | 80 + .../internal/reference/strided_slice.h | 121 + .../lite/kernels/internal/reference/sub.h | 479 + .../lite/kernels/internal/reference/tanh.h | 129 + .../kernels/internal/reference/transpose.h | 111 + .../internal/reference/transpose_conv.h | 219 + .../lite/kernels/internal/runtime_shape.h | 158 + .../kernels/internal/strided_slice_logic.h | 211 + .../lite/kernels/internal/tensor_ctypes.h | 47 + .../lite/kernels/internal/tensor_utils.cpp | 25 + .../tensorflow/lite/kernels/internal/types.h | 1065 + .../tensorflow/lite/kernels/kernel_util.cpp | 594 + .../src/tensorflow/lite/kernels/kernel_util.h | 330 + .../src/tensorflow/lite/kernels/op_macros.h | 38 + .../src/tensorflow/lite/kernels/padding.h | 115 + .../lite/micro/all_ops_resolver.cpp | 123 + .../tensorflow/lite/micro/all_ops_resolver.h | 38 + .../micro/arena_allocator/ibuffer_allocator.h | 100 + .../non_persistent_arena_buffer_allocator.cpp | 170 + .../non_persistent_arena_buffer_allocator.h | 104 + .../persistent_arena_buffer_allocator.cpp | 52 + .../persistent_arena_buffer_allocator.h | 58 + ...ecording_single_arena_buffer_allocator.cpp | 85 + .../recording_single_arena_buffer_allocator.h | 78 + .../single_arena_buffer_allocator.cpp | 199 + .../single_arena_buffer_allocator.h | 165 + .../src/tensorflow/lite/micro/compatibility.h | 32 + .../src/tensorflow/lite/micro/debug_log.cpp | 30 + .../src/tensorflow/lite/micro/debug_log.h | 31 + .../lite/micro/fake_micro_context.cpp | 106 + .../lite/micro/fake_micro_context.h | 56 + .../lite/micro/flatbuffer_utils.cpp | 84 + .../tensorflow/lite/micro/flatbuffer_utils.h | 65 + .../lite/micro/kernels/activation_utils.h | 57 + .../lite/micro/kernels/activations.cc | 120 + .../lite/micro/kernels/activations.h | 63 + .../lite/micro/kernels/activations_common.cc | 158 + .../src/tensorflow/lite/micro/kernels/add.cc | 165 + .../src/tensorflow/lite/micro/kernels/add.h | 77 + .../lite/micro/kernels/add_common.cc | 106 + .../tensorflow/lite/micro/kernels/add_n.cc | 215 + .../lite/micro/kernels/arg_min_max.cc | 116 + .../lite/micro/kernels/assign_variable.cc | 101 + .../lite/micro/kernels/batch_to_space_nd.cc | 112 + .../lite/micro/kernels/broadcast_args.cc | 91 + .../lite/micro/kernels/broadcast_to.cc | 123 + .../lite/micro/kernels/call_once.cc | 88 + .../src/tensorflow/lite/micro/kernels/cast.cc | 114 + .../src/tensorflow/lite/micro/kernels/ceil.cc | 75 + .../lite/micro/kernels/circular_buffer.cc | 117 + .../lite/micro/kernels/circular_buffer.h | 48 + .../micro/kernels/circular_buffer_common.cc | 97 + ...rcular_buffer_flexbuffers_generated_data.h | 22 + .../lite/micro/kernels/comparisons.cc | 618 + .../lite/micro/kernels/concatenation.cc | 263 + .../src/tensorflow/lite/micro/kernels/conv.cc | 166 + .../src/tensorflow/lite/micro/kernels/conv.h | 116 + .../lite/micro/kernels/conv_common.cc | 202 + .../tensorflow/lite/micro/kernels/conv_test.h | 113 + .../tensorflow/lite/micro/kernels/cumsum.cc | 175 + .../lite/micro/kernels/depth_to_space.cc | 142 + .../lite/micro/kernels/depthwise_conv.cc | 99 + .../lite/micro/kernels/depthwise_conv.h | 80 + .../micro/kernels/depthwise_conv_common.cc | 202 + .../lite/micro/kernels/dequantize.cc | 88 + .../lite/micro/kernels/dequantize.h | 38 + .../lite/micro/kernels/dequantize_common.cc | 67 + .../micro/kernels/detection_postprocess.cc | 807 + ...n_postprocess_flexbuffers_generated_data.h | 25 + .../src/tensorflow/lite/micro/kernels/div.cc | 208 + .../lite/micro/kernels/elementwise.cc | 430 + .../src/tensorflow/lite/micro/kernels/elu.cc | 151 + .../lite/micro/kernels/esp_nn/README.md | 11 + .../lite/micro/kernels/esp_nn/add.cc | 203 + .../lite/micro/kernels/esp_nn/conv.cc | 345 + .../micro/kernels/esp_nn/depthwise_conv.cc | 347 + .../micro/kernels/esp_nn/fully_connected.cc | 193 + .../lite/micro/kernels/esp_nn/mul.cc | 125 + .../lite/micro/kernels/esp_nn/pooling.cc | 233 + .../lite/micro/kernels/esp_nn/softmax.cc | 209 + .../tensorflow/lite/micro/kernels/ethosu.cc | 27 + .../tensorflow/lite/micro/kernels/ethosu.h | 28 + .../src/tensorflow/lite/micro/kernels/exp.cc | 79 + .../lite/micro/kernels/expand_dims.cc | 149 + .../src/tensorflow/lite/micro/kernels/fill.cc | 140 + .../tensorflow/lite/micro/kernels/floor.cc | 50 + .../lite/micro/kernels/floor_div.cc | 130 + .../lite/micro/kernels/floor_mod.cc | 128 + .../lite/micro/kernels/fully_connected.cc | 159 + .../lite/micro/kernels/fully_connected.h | 104 + .../micro/kernels/fully_connected_common.cc | 83 + .../tensorflow/lite/micro/kernels/gather.cc | 224 + .../lite/micro/kernels/gather_nd.cc | 205 + .../lite/micro/kernels/hard_swish.cc | 75 + .../lite/micro/kernels/hard_swish.h | 30 + .../lite/micro/kernels/hard_swish_common.cc | 86 + .../src/tensorflow/lite/micro/kernels/if.cc | 121 + .../lite/micro/kernels/kernel_runner.cc | 122 + .../lite/micro/kernels/kernel_runner.h | 81 + .../lite/micro/kernels/kernel_util.cc | 260 + .../lite/micro/kernels/kernel_util.h | 137 + .../lite/micro/kernels/l2_pool_2d.cc | 142 + .../tensorflow/lite/micro/kernels/l2norm.cc | 148 + .../lite/micro/kernels/leaky_relu.cc | 95 + .../lite/micro/kernels/leaky_relu.h | 43 + .../lite/micro/kernels/leaky_relu_common.cc | 79 + .../lite/micro/kernels/log_softmax.cc | 148 + .../tensorflow/lite/micro/kernels/logical.cc | 44 + .../tensorflow/lite/micro/kernels/logical.h | 35 + .../lite/micro/kernels/logical_common.cc | 63 + .../tensorflow/lite/micro/kernels/logistic.cc | 111 + .../tensorflow/lite/micro/kernels/logistic.h | 42 + .../lite/micro/kernels/logistic_common.cc | 119 + .../lite/micro/kernels/lstm_eval.cc | 1459 + .../tensorflow/lite/micro/kernels/lstm_eval.h | 154 + .../lite/micro/kernels/lstm_shared.h | 67 + .../lite/micro/kernels/maximum_minimum.cc | 132 + .../tensorflow/lite/micro/kernels/micro_ops.h | 135 + .../lite/micro/kernels/micro_tensor_utils.cc | 67 + .../lite/micro/kernels/micro_tensor_utils.h | 56 + .../lite/micro/kernels/micro_utils.h | 40 + .../lite/micro/kernels/mirror_pad.cc | 215 + .../src/tensorflow/lite/micro/kernels/mul.cc | 67 + .../src/tensorflow/lite/micro/kernels/mul.h | 74 + .../lite/micro/kernels/mul_common.cc | 184 + .../src/tensorflow/lite/micro/kernels/neg.cc | 60 + .../src/tensorflow/lite/micro/kernels/pack.cc | 117 + .../src/tensorflow/lite/micro/kernels/pad.cc | 237 + .../tensorflow/lite/micro/kernels/pooling.cc | 99 + .../tensorflow/lite/micro/kernels/pooling.h | 85 + .../lite/micro/kernels/pooling_common.cc | 170 + .../tensorflow/lite/micro/kernels/prelu.cc | 75 + .../src/tensorflow/lite/micro/kernels/prelu.h | 39 + .../lite/micro/kernels/prelu_common.cc | 105 + .../tensorflow/lite/micro/kernels/quantize.cc | 41 + .../tensorflow/lite/micro/kernels/quantize.h | 37 + .../lite/micro/kernels/quantize_common.cc | 239 + .../lite/micro/kernels/read_variable.cc | 87 + .../tensorflow/lite/micro/kernels/reduce.cc | 72 + .../tensorflow/lite/micro/kernels/reduce.h | 64 + .../lite/micro/kernels/reduce_common.cc | 374 + .../tensorflow/lite/micro/kernels/reshape.cc | 118 + .../lite/micro/kernels/resize_bilinear.cc | 116 + .../micro/kernels/resize_nearest_neighbor.cc | 126 + .../tensorflow/lite/micro/kernels/round.cc | 76 + .../tensorflow/lite/micro/kernels/select.cc | 197 + .../tensorflow/lite/micro/kernels/shape.cc | 67 + .../tensorflow/lite/micro/kernels/slice.cc | 157 + .../tensorflow/lite/micro/kernels/softmax.cc | 90 + .../tensorflow/lite/micro/kernels/softmax.h | 69 + .../lite/micro/kernels/softmax_common.cc | 168 + .../lite/micro/kernels/space_to_batch_nd.cc | 121 + .../lite/micro/kernels/space_to_depth.cc | 127 + .../tensorflow/lite/micro/kernels/split.cc | 128 + .../tensorflow/lite/micro/kernels/split_v.cc | 130 + .../lite/micro/kernels/squared_difference.cc | 247 + .../tensorflow/lite/micro/kernels/squeeze.cc | 118 + .../lite/micro/kernels/strided_slice.cc | 210 + .../src/tensorflow/lite/micro/kernels/sub.cc | 168 + .../src/tensorflow/lite/micro/kernels/sub.h | 60 + .../lite/micro/kernels/sub_common.cc | 109 + .../src/tensorflow/lite/micro/kernels/svdf.cc | 106 + .../src/tensorflow/lite/micro/kernels/svdf.h | 99 + .../lite/micro/kernels/svdf_common.cc | 516 + .../src/tensorflow/lite/micro/kernels/tanh.cc | 204 + .../lite/micro/kernels/transpose.cc | 122 + .../lite/micro/kernels/transpose_conv.cc | 344 + .../kernels/unidirectional_sequence_lstm.cc | 1387 + ...unidirectional_sequence_lstm_test_config.h | 244 + .../tensorflow/lite/micro/kernels/unpack.cc | 112 + .../lite/micro/kernels/var_handle.cc | 93 + .../tensorflow/lite/micro/kernels/while.cc | 133 + .../lite/micro/kernels/zeros_like.cc | 88 + .../tensorflow/lite/micro/memory_helpers.cpp | 173 + .../tensorflow/lite/micro/memory_helpers.h | 57 + .../memory_planner/greedy_memory_planner.cpp | 448 + .../memory_planner/greedy_memory_planner.h | 165 + .../memory_planner/linear_memory_planner.cpp | 53 + .../memory_planner/linear_memory_planner.h | 49 + .../micro/memory_planner/memory_plan_struct.h | 73 + .../memory_planner/micro_memory_planner.h | 91 + .../non_persistent_buffer_planner_shim.cpp | 66 + .../non_persistent_buffer_planner_shim.h | 129 + .../lite/micro/micro_allocation_info.cpp | 353 + .../lite/micro/micro_allocation_info.h | 139 + .../tensorflow/lite/micro/micro_allocator.cpp | 940 + .../tensorflow/lite/micro/micro_allocator.h | 357 + .../lite/micro/micro_arena_constants.h | 28 + .../tensorflow/lite/micro/micro_context.cpp | 130 + .../src/tensorflow/lite/micro/micro_context.h | 161 + .../lite/micro/micro_error_reporter.cpp | 41 + .../lite/micro/micro_error_reporter.h | 39 + .../src/tensorflow/lite/micro/micro_graph.cpp | 248 + .../src/tensorflow/lite/micro/micro_graph.h | 104 + .../lite/micro/micro_interpreter.cpp | 319 + .../tensorflow/lite/micro/micro_interpreter.h | 196 + .../src/tensorflow/lite/micro/micro_log.cpp | 47 + .../src/tensorflow/lite/micro/micro_log.h | 44 + .../lite/micro/micro_mutable_op_resolver.h | 652 + .../tensorflow/lite/micro/micro_op_resolver.h | 73 + .../tensorflow/lite/micro/micro_profiler.cpp | 115 + .../tensorflow/lite/micro/micro_profiler.h | 138 + .../lite/micro/micro_profiler_interface.h | 38 + .../lite/micro/micro_resource_variable.cpp | 148 + .../lite/micro/micro_resource_variable.h | 87 + .../tensorflow/lite/micro/micro_string.cpp | 317 + .../src/tensorflow/lite/micro/micro_string.h | 33 + .../src/tensorflow/lite/micro/micro_time.cpp | 63 + .../src/tensorflow/lite/micro/micro_time.h | 36 + .../src/tensorflow/lite/micro/micro_utils.cpp | 91 + .../src/tensorflow/lite/micro/micro_utils.h | 143 + .../lite/micro/mock_micro_graph.cpp | 66 + .../tensorflow/lite/micro/mock_micro_graph.h | 60 + .../lite/micro/recording_micro_allocator.cpp | 256 + .../lite/micro/recording_micro_allocator.h | 132 + .../lite/micro/recording_micro_interpreter.h | 94 + .../tensorflow/lite/micro/system_setup.cpp | 138 + .../src/tensorflow/lite/micro/system_setup.h | 59 + .../lite/micro/test_helper_custom_ops.cpp | 112 + .../lite/micro/test_helper_custom_ops.h | 50 + .../tensorflow/lite/micro/test_helpers.cpp | 1913 ++ .../src/tensorflow/lite/micro/test_helpers.h | 298 + .../lite/portable_type_to_tflitetype.h | 75 + .../tensorflow/lite/schema/schema_generated.h | 20139 ++++++++++++++ .../tensorflow/lite/schema/schema_utils.cpp | 62 + .../src/tensorflow/lite/schema/schema_utils.h | 33 + .../src/third_party/flatbuffers/LICENSE.txt | 202 + .../include/flatbuffers/allocator.h | 68 + .../flatbuffers/include/flatbuffers/array.h | 243 + .../flatbuffers/include/flatbuffers/base.h | 496 + .../flatbuffers/include/flatbuffers/buffer.h | 142 + .../include/flatbuffers/buffer_ref.h | 53 + .../include/flatbuffers/default_allocator.h | 58 + .../include/flatbuffers/detached_buffer.h | 114 + .../include/flatbuffers/flatbuffer_builder.h | 1214 + .../include/flatbuffers/flatbuffers.h | 270 + .../include/flatbuffers/flexbuffers.h | 1903 ++ .../include/flatbuffers/stl_emulation.h | 509 + .../flatbuffers/include/flatbuffers/string.h | 64 + .../flatbuffers/include/flatbuffers/struct.h | 53 + .../flatbuffers/include/flatbuffers/table.h | 168 + .../flatbuffers/include/flatbuffers/util.h | 725 + .../flatbuffers/include/flatbuffers/vector.h | 389 + .../include/flatbuffers/vector_downward.h | 271 + .../include/flatbuffers/verifier.h | 304 + .../src/third_party/gemmlowp/LICENSE | 202 + .../gemmlowp/fixedpoint/fixedpoint.h | 900 + .../gemmlowp/fixedpoint/fixedpoint_neon.h | 331 + .../gemmlowp/fixedpoint/fixedpoint_sse.h | 384 + .../gemmlowp/internal/detect_platform.h | 166 + .../src/third_party/kissfft/COPYING | 11 + .../src/third_party/kissfft/_kiss_fft_guts.h | 168 + .../src/third_party/kissfft/kiss_fft.c | 408 + .../src/third_party/kissfft/kiss_fft.h | 125 + .../src/third_party/kissfft/tools/kiss_fftr.c | 159 + .../src/third_party/kissfft/tools/kiss_fftr.h | 46 + .../ruy/ruy/profiler/instrumentation.h | 203 + .../xdrv_52_3_berry_tf_lite_micro.ino | 930 + 466 files changed, 125929 insertions(+) create mode 100644 lib/libesp32/berry_tasmota/src/be_TFL_lib.c create mode 100644 lib/libesp32_ml/mel_freq_extractor/library.properties create mode 100644 lib/libesp32_ml/mel_freq_extractor/src/mfcc.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/AUTHORS create mode 100644 lib/libesp32_ml/tf_lite_esp32/CODEOWNERS create mode 100644 lib/libesp32_ml/tf_lite_esp32/LICENSE create mode 100644 lib/libesp32_ml/tf_lite_esp32/README.md create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/README.md create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_constants.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_main.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_output_handler.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/constants.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/hello_world.ino create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/main_functions.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/model.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/model.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/hello_world/output_handler.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/LICENSE create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/README.md create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand.ino create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand_model_data.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand_model_data.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/rasterize_stroke.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/rasterize_stroke.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/train/train_magic_wand_model.ipynb create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/website/index.html create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/README.md create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_audio_provider.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_command_responder.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_main.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/audio_provider.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/command_responder.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/feature_provider.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/feature_provider.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/main_functions.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_features_generator.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_features_generator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_model_settings.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_model_settings.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_model.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_model.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_speech.ino create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/recognize_commands.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/recognize_commands.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/README.md create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_detection_responder.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_image_provider.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_main.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/detection_responder.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/image_provider.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/main_functions.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/model_settings.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/model_settings.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detect_model_data.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detect_model_data.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detection.ino create mode 100644 lib/libesp32_ml/tf_lite_esp32/library.json create mode 100644 lib/libesp32_ml/tf_lite_esp32/library.properties create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/TensorFlowLite.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/.gitignore create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/.gitlab-ci.yml create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/LICENSE create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/README.md create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_ansi_c.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_ansi_headers.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_defs.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_esp32s3.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_generic_opt.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/activation_functions/esp_nn_relu_ansi.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/basic_math/esp_nn_add_ansi.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/basic_math/esp_nn_mul_ansi.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/common/common_functions.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_ansi.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_esp32s3.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_opt.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_ansi.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_opt.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_s8_esp32s3.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/fully_connected/esp_nn_fully_connected_ansi.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/pooling/esp_nn_avg_pool_ansi.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/pooling/esp_nn_max_pool_ansi.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/esp_nn_softmax_ansi.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/esp_nn_softmax_opt.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/softmax_common.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/builtin_op_data.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/builtin_ops.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/builtin_op_data.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/c_api_types.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/common.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/common.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/context_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/error_reporter.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/error_reporter.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/flatbuffer_conversions.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/flatbuffer_conversions.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/op_resolver.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/op_resolver.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/tensor_utils.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/tensor_utils.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/bits.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft_util.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank_util.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend_util.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_common.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_lut.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_lut.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale_util.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window_util.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/common.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/compatibility.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/cppmath.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/max.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/min.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/optimized/neon_check.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor_utils.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor_utils.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/quantization_util.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/quantization_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/add.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/add_n.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/arg_min_max.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/batch_matmul.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/binary_function.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/broadcast_args.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/broadcast_to.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/ceil.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/comparisons.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/concatenation.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/conv.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/cumsum.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depth_to_space.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depthwiseconv_uint8.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/dequantize.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/div.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/elu.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/exp.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/fill.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor_div.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor_mod.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/fully_connected.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/hard_swish.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/add.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/conv.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/l2normalization.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/mean.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/mul.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/tanh.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/transpose_conv.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/l2normalization.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/leaky_relu.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/log_softmax.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/logistic.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/lstm_cell.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/maximum_minimum.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/mul.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/neg.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/pad.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/pooling.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/prelu.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/quantize.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/reduce.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/requantize.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/resize_bilinear.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/round.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/select.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/slice.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/softmax.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/space_to_depth.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/strided_slice.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/sub.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/tanh.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/transpose.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/transpose_conv.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/runtime_shape.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/strided_slice_logic.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/tensor_ctypes.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/tensor_utils.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/types.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/kernel_util.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/kernel_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/op_macros.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/padding.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/all_ops_resolver.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/all_ops_resolver.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/ibuffer_allocator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/compatibility.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/debug_log.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/debug_log.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/fake_micro_context.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/fake_micro_context.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/flatbuffer_utils.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/flatbuffer_utils.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activation_utils.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add_n.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/arg_min_max.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/assign_variable.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/batch_to_space_nd.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/broadcast_args.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/broadcast_to.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/call_once.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/cast.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ceil.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer_flexbuffers_generated_data.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/comparisons.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/concatenation.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv_test.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/cumsum.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depth_to_space.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/detection_postprocess.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/detection_postprocess_flexbuffers_generated_data.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/div.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/elementwise.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/elu.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/README.md create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/add.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/conv.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/depthwise_conv.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/fully_connected.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/mul.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/pooling.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/softmax.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ethosu.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ethosu.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/exp.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/expand_dims.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fill.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor_div.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor_mod.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/gather.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/gather_nd.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/if.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_runner.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_runner.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_util.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/l2_pool_2d.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/l2norm.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/log_softmax.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_eval.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_eval.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_shared.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/maximum_minimum.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_ops.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_tensor_utils.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_tensor_utils.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_utils.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mirror_pad.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/neg.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pack.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pad.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/read_variable.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reshape.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/resize_bilinear.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/round.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/select.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/shape.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/slice.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/space_to_batch_nd.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/space_to_depth.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/split.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/split_v.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/squared_difference.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/squeeze.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/strided_slice.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf_common.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/tanh.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/transpose.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/transpose_conv.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test_config.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unpack.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/var_handle.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/while.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/zeros_like.cc create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_helpers.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_helpers.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/greedy_memory_planner.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/greedy_memory_planner.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/linear_memory_planner.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/linear_memory_planner.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/memory_plan_struct.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/micro_memory_planner.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocation_info.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocation_info.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocator.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_arena_constants.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_context.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_context.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_error_reporter.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_error_reporter.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_graph.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_graph.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_interpreter.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_interpreter.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_log.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_log.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_mutable_op_resolver.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_op_resolver.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler_interface.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_resource_variable.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_resource_variable.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_string.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_string.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_time.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_time.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_utils.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_utils.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/mock_micro_graph.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/mock_micro_graph.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_allocator.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_allocator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_interpreter.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/system_setup.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/system_setup.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helper_custom_ops.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helper_custom_ops.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helpers.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helpers.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/portable_type_to_tflitetype.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_generated.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_utils.cpp create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_utils.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/LICENSE.txt create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/allocator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/array.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/base.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/buffer.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/buffer_ref.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/default_allocator.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/detached_buffer.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flatbuffers.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flexbuffers.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/stl_emulation.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/string.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/struct.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/table.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/util.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/vector.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/vector_downward.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/verifier.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/LICENSE create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint_neon.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint_sse.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/internal/detect_platform.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/COPYING create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/_kiss_fft_guts.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/kiss_fft.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/kiss_fft.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/tools/kiss_fftr.c create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/tools/kiss_fftr.h create mode 100644 lib/libesp32_ml/tf_lite_esp32/src/third_party/ruy/ruy/profiler/instrumentation.h create mode 100644 tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tf_lite_micro.ino diff --git a/lib/libesp32/berry/default/be_modtab.c b/lib/libesp32/berry/default/be_modtab.c index 50c4152b5..d85c26177 100644 --- a/lib/libesp32/berry/default/be_modtab.c +++ b/lib/libesp32/berry/default/be_modtab.c @@ -50,6 +50,7 @@ be_extern_native_module(partition_core); be_extern_native_module(crc); be_extern_native_module(crypto); be_extern_native_module(ULP); +be_extern_native_module(TFL); be_extern_native_module(mdns); #ifdef USE_ZIGBEE be_extern_native_module(zigbee); @@ -171,6 +172,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #if defined(USE_BERRY_ULP) && ((CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) &be_native_module(ULP), #endif // USE_BERRY_ULP +#if defined(USE_BERRY_TF_LITE) + &be_native_module(TFL), +#endif //USE_BERRY_TF_LITE #if defined(USE_MI_ESP32) && !defined(USE_BLE_ESP32) &be_native_module(MI32), &be_native_module(BLE), diff --git a/lib/libesp32/berry_tasmota/src/be_TFL_lib.c b/lib/libesp32/berry_tasmota/src/be_TFL_lib.c new file mode 100644 index 000000000..bfc4c2b54 --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_TFL_lib.c @@ -0,0 +1,47 @@ +/******************************************************************** + * Tasmota lib + * + * To use: import TFL` + *******************************************************************/ +#include "be_constobj.h" +#include "be_mapping.h" + +#ifdef USE_BERRY_TF_LITE + + +extern const char* be_TFL_log(struct bvm *vm); +BE_FUNC_CTYPE_DECLARE(be_TFL_log, "s", "@"); + +extern const char* be_TFL_stats(struct bvm *vm); +BE_FUNC_CTYPE_DECLARE(be_TFL_stats, "s", "@"); + +extern bbool be_TFL_begin(struct bvm *vm, const char* type, const uint8_t *descriptor, size_t size); +BE_FUNC_CTYPE_DECLARE(be_TFL_begin, "b", "@s[(bytes)~]"); + +extern bbool be_TFL_load(struct bvm *vm, const uint8_t *model_buf, size_t model_size, const uint8_t *output_buf, size_t output_size,int arena); +BE_FUNC_CTYPE_DECLARE(be_TFL_load, "b", "@(bytes)~(bytes)~[i]"); + +extern bbool be_TFL_input(struct bvm *vm, const uint8_t *buf, size_t size); +BE_FUNC_CTYPE_DECLARE(be_TFL_input, "b", "@(bytes)~"); + +extern bbool be_TFL_output(struct bvm *vm, const uint8_t *buf, size_t size); +BE_FUNC_CTYPE_DECLARE(be_TFL_output, "b", "@(bytes)~"); + +extern void be_TFL_rec(struct bvm *vm, const char* filename, size_t seconds); +BE_FUNC_CTYPE_DECLARE(be_TFL_rec, "", "@si"); + +#include "be_fixed_TFL.h" + +/* @const_object_info_begin +module TFL (scope: global) { + begin, ctype_func(be_TFL_begin) + load, ctype_func(be_TFL_load) + input, ctype_func(be_TFL_input) + output, ctype_func(be_TFL_output) + log, ctype_func(be_TFL_log) + stats, ctype_func(be_TFL_stats) + rec, ctype_func(be_TFL_rec) +} +@const_object_info_end */ + +#endif // USE_BERRY_TF_LITE diff --git a/lib/libesp32_ml/mel_freq_extractor/library.properties b/lib/libesp32_ml/mel_freq_extractor/library.properties new file mode 100644 index 000000000..9b173d75a --- /dev/null +++ b/lib/libesp32_ml/mel_freq_extractor/library.properties @@ -0,0 +1,7 @@ +name=MElFreqencyExtractor +version=1.0 +author=Christian Baars +maintainer=Christian Baars +sentence=Feature Extractor using mel frequencies +paragraph=Uses ESP-DSP library. +architectures=esp32 diff --git a/lib/libesp32_ml/mel_freq_extractor/src/mfcc.h b/lib/libesp32_ml/mel_freq_extractor/src/mfcc.h new file mode 100644 index 000000000..524d3c6e0 --- /dev/null +++ b/lib/libesp32_ml/mel_freq_extractor/src/mfcc.h @@ -0,0 +1,315 @@ +/* + mfcc.h - mel frequency extractor for ESP32 + + Computes features for slizes of audio data similiar to speechpy + This is intended to provide a stripped down implementation that can work with Edgempulse trained models + + based on: + https://github.com/astorfi/speechpy + https://github.com/AIWintermuteAI/Speech-to-Intent-Micro/blob/main/inference_code/Wio_Terminal/wio_speech_to_intent_150_10/mfcc.cpp + + Copyright (C) 2022 Christian Baars + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .@ +*/ + + + +#ifndef MELFREQUENCYEXTRACTOR_H +#define MELFREQUENCYEXTRACTOR_H + +#include +#include +#include "float.h" +#include "esp_dsp.h" + + +class MFCC{ + private: + int num_mfcc_features; + int frame_len; + int frame_len_padded; + int num_bank_bins; + float * m_frame; + float * m_buffer; + float * m_mel_energies; + float * m_dct_matrix; + float * m_mel_fbank; + + uint8_t m_amplification; + float m_preemphasis; + + float * create_dct_matrix(int32_t input_length, int32_t coefficient_count); + void create_mel_filterbank(int samp_freq, int low_freq, int high_freq); + + static inline float InverseMelScale(float mel_freq) { + return 700.0f * (expf (mel_freq / 1127.0f) - 1.0f); + } + + static inline float MelScale(float freq) { + return 1127.0f * logf (1.0f + freq / 700.0f); + } + + + public: + MFCC(int num_mfcc_features, int frame_len,int num_bank_bins, int samp_freq, int low_freq, int high_freq); + ~MFCC(); + void set_preamp(uint8_t amplification); + void set_preemphasis(float preemphasis); + void mfcc_compute(const int16_t* data, float* mfcc_out); + void log10_normalize(float* out_buf, int out_buf_len, int noise_floor_db); +}; + + +MFCC::MFCC(int num_mfcc_features, int frame_len, int num_bank_bins, int samp_freq, int low_freq, int high_freq) +:num_mfcc_features(num_mfcc_features), + frame_len(frame_len), + num_bank_bins(num_bank_bins) +{ + // Round-up to nearest power of 2. + frame_len_padded = pow(2,ceil((log(frame_len)/log(2)))); + + m_frame = new float[frame_len_padded]; + m_buffer = new float[frame_len_padded * 2]; + m_mel_energies = new float[num_bank_bins]; + + //create window function + // window_func = new float[frame_len]; + // dsps_wind_hann_f32(window_func, frame_len); + + m_amplification = 1; + m_preemphasis = 0.0; + + //create mel filterbank + create_mel_filterbank(samp_freq, low_freq, high_freq); + + //create DCT matrix for mfcc mode + if(num_mfcc_features != 0){ + m_dct_matrix = create_dct_matrix(num_bank_bins, num_mfcc_features); + } + + //initialize FFT + int ret = dsps_fft2r_init_fc32(NULL, frame_len_padded); + if(ret==0){ + MicroPrintf("Framelength: %u, (rounded: %u)", frame_len,frame_len_padded); + } + else{ + MicroPrintf("dsps_fft2r_init_fc32 error: %d",ret); + } + +} + +MFCC::~MFCC() { + delete []m_frame; + delete []m_buffer; + delete []m_mel_energies; + // delete []window_func; + + delete []m_dct_matrix; + + // for(int i=0;i(noise_floor_db * -1); + const float noise_scale = 1.0f / (static_cast(noise_floor_db * -1) + 12.0f); + for (size_t ix = 0; ix < out_buf_len; ix++) { + float f = out_buf[ix]; + if (f < 1e-30) { + out_buf[ix] = 0; + return; + } + f = 10.0f * log10(f); // scale by 10 + f += noise; + f *= noise_scale; + // clip again + if (f < 0.0f) f = 0.0f; + else if (f > 1.0f) f = 1.0f; + out_buf[ix] = f; + } +} + +void MFCC::set_preamp(uint8_t amplification){ + m_amplification = amplification; +} + +void MFCC::set_preemphasis(float preemphasis){ + m_preemphasis = preemphasis; + // Speechpy computes this over the window of a sample, here we will compute only over the slize !! +} + + +void MFCC::mfcc_compute(const int16_t * audio_data, float* mfcc_out) { + + int32_t i, j, bin; + int coefficients = frame_len_padded/2 + 1; + int data_clipped = 0; + int data_clipped_low = 0; + float conv_factor = m_amplification; + float clip_thres = 0.99f * (float)(1<<15); + + // MicroPrintf("%d %d %d %d %d %d %d %d",audio_data[0],audio_data[1] ,audio_data[2] ,audio_data[3] ,audio_data[4] ,audio_data[5] ,audio_data[6] ,audio_data[7]); + + //TensorFlow way of normalizing .wav data to (-1,1) for speechpy's MFE + if(num_mfcc_features == 0){ + conv_factor /= (float)(1<<15); + clip_thres /= (float)(1<<15); + } + + for (int i = 0; i < frame_len; i++) { + m_buffer[i] = audio_data[i] * conv_factor; //mfe -1..1, mfcc int16_t as float, both with additional pre_amp factor + } + if(m_buffer[i]> clip_thres){ + m_buffer[i] /= m_amplification; + data_clipped++; + } + else if( m_buffer[i]< -clip_thres){ + m_buffer[i] /= m_amplification; + data_clipped_low++; + } + + if(data_clipped>0) + MicroPrintf("Clip: %d __ %d",data_clipped, data_clipped_low); + + // MicroPrintf("%f %f %f %f %f %f %f %f ",m_buffer[0],m_buffer[1] ,m_buffer[2] ,m_buffer[3] ,m_buffer[4] ,m_buffer[5] ,m_buffer[6] ,m_buffer[7]); + + //pre-emphasis + if(m_preemphasis!=0.0){ + m_frame[0] = m_buffer[0] - m_preemphasis * m_buffer[frame_len - 1]; // roll through the frame "back" to the end + for (i = 1; i < frame_len; i++){ + m_frame[i] = m_buffer[i] - m_preemphasis * m_buffer[i - 1]; + } + } + else{ + for (i = 1; i < frame_len; i++){ + m_frame[i] = m_buffer[i]; + } + } + + // prepare buffer for FFT + for (i = 0; i < frame_len_padded; i++) { + m_buffer[i * 2] = i diff --git a/lib/libesp32_ml/tf_lite_esp32/CODEOWNERS b/lib/libesp32_ml/tf_lite_esp32/CODEOWNERS new file mode 100644 index 000000000..b235a44e8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/CODEOWNERS @@ -0,0 +1,4 @@ +* @tensorflow/micro @ddavis-2015 + +/.github/ @advaitjain +/ci/ @advaitjain diff --git a/lib/libesp32_ml/tf_lite_esp32/LICENSE b/lib/libesp32_ml/tf_lite_esp32/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/libesp32_ml/tf_lite_esp32/README.md b/lib/libesp32_ml/tf_lite_esp32/README.md new file mode 100644 index 000000000..a0612ee98 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/README.md @@ -0,0 +1,80 @@ +# TensorFlow Lite Micro Library for Arduino-Espressif32 + +This repository has the code (including examples) needed to use Tensorflow Lite Micro on an Arduino. + +## Table of contents + +* [Table of contents](#table-of-contents) +* [Build Status](#build-status) +* [How to Install](#how-to-install) + * [GitHub](#github) + * [Checking your Installation](#checking-your-installation) +* [Compatibility](#compatibility) +* [License](#license) +* [Contributing](#contributing) + + +## Build Status + +Build Type | Status | +--------------- | ------------- | +Arduino CLI on Linux | [![Arduino](https://github.com/tensorflow/tflite-micro-arduino-examples/actions/workflows/ci.yml/badge.svg?event=schedule)](https://github.com/tensorflow/tflite-micro-arduino-examples/actions/workflows/ci.yml) +Sync from tflite-micro | [![Sync from tflite-micro](https://github.com/tensorflow/tflite-micro-arduino-examples/actions/workflows/sync.yml/badge.svg)](https://github.com/tensorflow/tflite-micro-arduino-examples/actions/workflows/sync.yml) + +## How to Install + +### GitHub + +The officially supported TensorFlow Lite Micro library for Arduino resides +in the [tflite-micro-arduino-examples](https://github.com/tensorflow/tflite-micro-arduino-examples) +GitHub repository. +To install the in-development version of this library, you can use the +latest version directly from the GitHub repository. This requires you clone the +repo into the folder that holds libraries for the Arduino IDE. The location for +this folder varies by operating system, but typically it's in +`~/Arduino/libraries` on Linux, `~/Documents/Arduino/libraries/` on MacOS, and +`My Documents\Arduino\Libraries` on Windows. + +Once you're in that folder in the terminal, you can then grab the code using the +git command line tool: + +``` +git clone https://github.com/tensorflow/tflite-micro-arduino-examples Arduino_TensorFlowLite +``` + +To update your clone of the repository to the latest code, use the following terminal commands: +``` +cd Arduino_TensorFlowLite +git pull +``` + +### Checking your Installation + +Once the library has been installed, you should then start the Arduino IDE. +You will now see an `Arduino_TensorFlowLite` +entry in the `File -> Examples` menu of the Arduino IDE. This submenu contains a list +of sample projects you can try out. + +![Hello World](docs/hello_world_screenshot.png) + +## Compatibility + +This library is designed for the `Arduino Nano 33 BLE Sense` board. The framework +code for running machine learning models should be compatible with most Arm Cortex +M-based boards, such as the `Raspberry Pi Pico`, but the code to access peripherals +like microphones, cameras, and accelerometers is specific to the `Nano 33 BLE Sense`. + +## License + +This code is made available under the Apache 2 license. + +## Contributing + +Forks of this library are welcome and encouraged. If you have bug reports or +fixes to contribute, the source of this code is at [https:://github.com/tensorflow/tflite-micro](github.com/tensorflow/tflite-micro) +and all issues and pull requests should be directed there. + +The code here is created through an automatic project generation process +and may differ from +that source of truth, since it's cross-platform and needs to be modified to +work within the Arduino IDE. \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/README.md b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/README.md new file mode 100644 index 000000000..aac6402db --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/README.md @@ -0,0 +1,59 @@ + + +# Hello World Example + +This example is designed to demonstrate the absolute basics of using [TensorFlow +Lite for Microcontrollers](https://www.tensorflow.org/lite/microcontrollers). +It includes the full end-to-end workflow of training a model, converting it for +use with TensorFlow Lite for Microcontrollers for running inference on a +microcontroller. + +The model is trained to replicate a `sine` function and generates a pattern of +data to blink the built-in LED in a fade in/out pattern. + +## Table of contents + +* [Table of contents](#table-of-contents) +* [Deploy to Arduino](#deploy-to-arduino) + * [Install the Arduino_TensorFlowLite library](#install-the-arduino_tensorflowlite-library) + * [Load and run the example](#load-and-run-the-example) + + +## Deploy to Arduino + +The following instructions will help you build and deploy this sample +to [Arduino](https://www.arduino.cc/) devices. + +The sample has been tested with the following devices: + +- [Arduino Nano 33 BLE Sense](https://store.arduino.cc/usa/nano-33-ble-sense-with-headers) +- [Arduino Tiny Machine Learning Kit](https://store-usa.arduino.cc/products/arduino-tiny-machine-learning-kit) + +The sample will use PWM to fade an LED on and off according to the model's +output. In the code, the `LED_BUILTIN` constant is used to specify the board's +built-in LED as the one being controlled. However, on some boards, this built-in +LED is not attached to a pin with PWM capabilities. In this case, the LED will +blink instead of fading. + +![Animation on Nano 33 BLE Sense](../../docs/hello_world_animation.gif) + +### Install the Arduino_TensorFlowLite library + +To install the TensorFlow Lite Micro for Arduino library, see the +[how to install](../../README.md#how-to-install) instructions. + +### Load and run the example + +Once the library has been added, go to `File -> Examples`. You should see an +entry within the list named `Arduino_TensorFlowLite`. Select +it and click `hello_world` to load the example. + +Use the Arduino IDE to build and upload the example. Once it is running, +you should see the built-in LED on your device flashing. + +The Arduino Desktop IDE includes a plotter that we can use to display the sine +wave graphically. To view it, go to `Tools -> Serial Plotter`. You will see one +datapoint being logged for each inference cycle, expressed as a number between 0 +and 255. + +![Serial Plotter with Nano 33 BLE Sense](../../docs/hello_world_serial_plotter.png) diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_constants.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_constants.cpp new file mode 100644 index 000000000..927f8d9be --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_constants.cpp @@ -0,0 +1,20 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "constants.h" + +// This is tuned so that a full cycle takes ~6.6 seconds on an +// Arduino Nano 33 BLE. +const int kInferencesPerCycle = 200; diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_main.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_main.cpp new file mode 100644 index 000000000..c70a2bcea --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_main.cpp @@ -0,0 +1,20 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "main_functions.h" + +// Arduino automatically calls the setup() and loop() functions in a sketch, so +// where other systems need their own main routine in this file, it can be left +// empty. diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_output_handler.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_output_handler.cpp new file mode 100644 index 000000000..d41092549 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/arduino_output_handler.cpp @@ -0,0 +1,54 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "Arduino.h" +#include "constants.h" +#include "output_handler.h" + +// The pin of the Arduino's built-in LED +int led = LED_BUILTIN; + +// Track whether the function has run at least once +bool initialized = false; + +// Animates a dot across the screen to represent the current x and y values +void HandleOutput(tflite::ErrorReporter* error_reporter, float x_value, + float y_value) { + // Do this only once + if (!initialized) { + // Set the LED pin to output + pinMode(led, OUTPUT); + initialized = true; + } + + // Calculate the brightness of the LED such that y=-1 is fully off + // and y=1 is fully on. The LED's brightness can range from 0-255. + int brightness = (int)(127.5f * (y_value + 1)); + + // The y value is not actually constrained to the range [-1, 1], so we need to + // clamp the brightness value before sending it to the PWM/LED. + int brightness_clamped = std::min(255, std::max(0, brightness)); + + // Set the brightness of the LED. If the specified pin does not support PWM, + // this will result in the LED being on when brightness_clamped > 127, off + // otherwise. + analogWrite(led, brightness_clamped); + + // Log the current brightness value for display in the Arduino plotter + TF_LITE_REPORT_ERROR(error_reporter, "%d\n", brightness); + delay(33); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/constants.h b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/constants.h new file mode 100644 index 000000000..f45289320 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/constants.h @@ -0,0 +1,32 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_CONSTANTS_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_CONSTANTS_H_ + +// This constant represents the range of x values our model was trained on, +// which is from 0 to (2 * Pi). We approximate Pi to avoid requiring additional +// libraries. +const float kXrange = 2.f * 3.14159265359f; + +// This constant determines the number of inferences to perform across the range +// of x values defined above. Since each inference takes time, the higher this +// number, the more time it will take to run through the entire range. The value +// of this constant can be tuned so that one full cycle takes a desired amount +// of time. Since different devices take different amounts of time to perform +// inference, this value should be defined per-device. +extern const int kInferencesPerCycle; + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_CONSTANTS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/hello_world.ino b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/hello_world.ino new file mode 100644 index 000000000..ca6536b1e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/hello_world.ino @@ -0,0 +1,123 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "main_functions.h" + +#include "tensorflow/lite/micro/all_ops_resolver.h" +#include "constants.h" +#include "model.h" +#include "output_handler.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_interpreter.h" +#include "tensorflow/lite/micro/system_setup.h" +#include "tensorflow/lite/schema/schema_generated.h" + +// Globals, used for compatibility with Arduino-style sketches. +namespace { +tflite::ErrorReporter* error_reporter = nullptr; +const tflite::Model* model = nullptr; +tflite::MicroInterpreter* interpreter = nullptr; +TfLiteTensor* input = nullptr; +TfLiteTensor* output = nullptr; +int inference_count = 0; + +constexpr int kTensorArenaSize = 2000; +uint8_t tensor_arena[kTensorArenaSize]; +} // namespace + +// The name of this function is important for Arduino compatibility. +void setup() { + tflite::InitializeTarget(); + + // Set up logging. Google style is to avoid globals or statics because of + // lifetime uncertainty, but since this has a trivial destructor it's okay. + // NOLINTNEXTLINE(runtime-global-variables) + static tflite::MicroErrorReporter micro_error_reporter; + error_reporter = µ_error_reporter; + + // Map the model into a usable data structure. This doesn't involve any + // copying or parsing, it's a very lightweight operation. + model = tflite::GetModel(g_model); + if (model->version() != TFLITE_SCHEMA_VERSION) { + TF_LITE_REPORT_ERROR(error_reporter, + "Model provided is schema version %d not equal " + "to supported version %d.", + model->version(), TFLITE_SCHEMA_VERSION); + return; + } + + // This pulls in all the operation implementations we need. + // NOLINTNEXTLINE(runtime-global-variables) + static tflite::AllOpsResolver resolver; + + // Build an interpreter to run the model with. + static tflite::MicroInterpreter static_interpreter( + model, resolver, tensor_arena, kTensorArenaSize, error_reporter); + interpreter = &static_interpreter; + + // Allocate memory from the tensor_arena for the model's tensors. + TfLiteStatus allocate_status = interpreter->AllocateTensors(); + if (allocate_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed"); + return; + } + + // Obtain pointers to the model's input and output tensors. + input = interpreter->input(0); + output = interpreter->output(0); + + // Keep track of how many inferences we have performed. + inference_count = 0; +} + +// The name of this function is important for Arduino compatibility. +void loop() { + // Calculate an x value to feed into the model. We compare the current + // inference_count to the number of inferences per cycle to determine + // our position within the range of possible x values the model was + // trained on, and use this to calculate a value. + float position = static_cast(inference_count) / + static_cast(kInferencesPerCycle); + float x = position * kXrange; + + // Quantize the input from floating-point to integer + int8_t x_quantized = x / input->params.scale + input->params.zero_point; + // Place the quantized input in the model's input tensor + input->data.int8[0] = x_quantized; + + // Run inference, and report any error + TfLiteStatus invoke_status = interpreter->Invoke(); + if (invoke_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed on x: %f\n", + static_cast(x)); + return; + } + + // Obtain the quantized output from model's output tensor + int8_t y_quantized = output->data.int8[0]; + // Dequantize the output from integer to floating-point + float y = (y_quantized - output->params.zero_point) * output->params.scale; + + // Output the results. A custom HandleOutput function can be implemented + // for each supported hardware target. + HandleOutput(error_reporter, x, y); + + // Increment the inference_counter, and reset it if we have reached + // the total number per cycle + inference_count += 1; + if (inference_count >= kInferencesPerCycle) inference_count = 0; +} diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/main_functions.h b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/main_functions.h new file mode 100644 index 000000000..a1ea715c6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/main_functions.h @@ -0,0 +1,37 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_MAIN_FUNCTIONS_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_MAIN_FUNCTIONS_H_ + +// Expose a C friendly interface for main functions. +#ifdef __cplusplus +extern "C" { +#endif + +// Initializes all data needed for the example. The name is important, and needs +// to be setup() for Arduino compatibility. +void setup(); + +// Runs one iteration of data gathering and inference. This should be called +// repeatedly from the application code. The name needs to be loop() for Arduino +// compatibility. +void loop(); + +#ifdef __cplusplus +} +#endif + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_MAIN_FUNCTIONS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/model.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/model.cpp new file mode 100644 index 000000000..f04a9f661 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/model.cpp @@ -0,0 +1,237 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Automatically created from a TensorFlow Lite flatbuffer using the command: +// xxd -i model.tflite > model.cc + +// This is a standard TensorFlow Lite model file that has been converted into a +// C data array, so it can be easily compiled into a binary for devices that +// don't have a file system. + +// See train/README.md for a full description of the creation process. + +#include "model.h" + +// Keep model aligned to 8 bytes to guarantee aligned 64-bit accesses. +alignas(8) const unsigned char g_model[] = { + 0x1c, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x14, 0x00, 0x20, 0x00, + 0x1c, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x1c, 0x03, 0x00, 0x00, + 0x2c, 0x03, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x60, 0xf7, 0xff, 0xff, + 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xbc, 0xff, 0xff, 0xff, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x34, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x76, 0xfd, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x32, 0x5f, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00, + 0x34, 0x02, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, + 0x6c, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xfa, 0xfd, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xfd, 0xff, 0xff, + 0x88, 0xfd, 0xff, 0xff, 0x8c, 0xfd, 0xff, 0xff, 0x22, 0xfe, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x21, 0xa5, 0x8b, 0xca, + 0x5e, 0x1d, 0xce, 0x42, 0x9d, 0xce, 0x1f, 0xb0, 0xdf, 0x54, 0x2f, 0x81, + 0x3e, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0xee, 0xfc, 0x00, 0xec, 0x05, 0x17, 0xef, 0xec, 0xe6, 0xf8, 0x03, 0x01, + 0x00, 0xfa, 0xf8, 0xf5, 0xdc, 0xeb, 0x27, 0x14, 0xf1, 0xde, 0xe2, 0xdb, + 0xf0, 0xde, 0x31, 0x06, 0x02, 0xe6, 0xee, 0xf9, 0x00, 0x16, 0x07, 0xe0, + 0xfe, 0xff, 0xe9, 0x06, 0xe7, 0xef, 0x81, 0x1b, 0x18, 0xea, 0xc9, 0x01, + 0x0f, 0x00, 0xda, 0xf7, 0x0e, 0xec, 0x13, 0x1f, 0x04, 0x13, 0xb4, 0xe6, + 0xfd, 0x06, 0xb9, 0xe0, 0x0d, 0xec, 0xf0, 0xde, 0xeb, 0xf7, 0x05, 0x26, + 0x1a, 0xe4, 0x6f, 0x1a, 0xea, 0x1e, 0x35, 0xdf, 0x1a, 0xf3, 0xf1, 0x19, + 0x0f, 0x03, 0x1b, 0xe1, 0xde, 0x13, 0xf6, 0x19, 0xff, 0xf6, 0x1b, 0x18, + 0xf0, 0x1c, 0xda, 0x1b, 0x1b, 0x20, 0xe5, 0x1a, 0xf5, 0xff, 0x96, 0x0b, + 0x00, 0x01, 0xcd, 0xde, 0x0d, 0xf6, 0x16, 0xe3, 0xed, 0xfc, 0x0e, 0xe9, + 0xfa, 0xeb, 0x5c, 0xfc, 0x1d, 0x02, 0x5b, 0xe2, 0xe1, 0xf5, 0x15, 0xec, + 0xf4, 0x00, 0x13, 0x05, 0xec, 0x0c, 0x1d, 0x14, 0x0e, 0xe7, 0x0b, 0xf4, + 0x19, 0x00, 0xd7, 0x05, 0x27, 0x02, 0x15, 0xea, 0xea, 0x02, 0x9b, 0x00, + 0x0c, 0xfa, 0xe8, 0xea, 0xfd, 0x00, 0x14, 0xfd, 0x0b, 0x02, 0xef, 0xee, + 0x06, 0xee, 0x01, 0x0d, 0x06, 0xe6, 0xf7, 0x11, 0xf7, 0x09, 0xf8, 0xf1, + 0x21, 0xff, 0x0e, 0xf3, 0xec, 0x12, 0x26, 0x1d, 0xf2, 0xe9, 0x28, 0x18, + 0xe0, 0xfb, 0xf3, 0xf4, 0x05, 0x1d, 0x1d, 0xfb, 0xfd, 0x1e, 0xfc, 0x11, + 0xe8, 0x07, 0x09, 0x03, 0x12, 0xf2, 0x36, 0xfb, 0xdc, 0x1c, 0xf9, 0xef, + 0xf3, 0xe7, 0x6f, 0x0c, 0x1d, 0x00, 0x45, 0xfd, 0x0e, 0xf0, 0x0b, 0x19, + 0x1a, 0xfa, 0xe0, 0x19, 0x1f, 0x13, 0x36, 0x1c, 0x12, 0xeb, 0x3b, 0x0c, + 0xb4, 0xcb, 0xe6, 0x13, 0xfa, 0xeb, 0xf1, 0x06, 0x1c, 0xfa, 0x18, 0xe5, + 0xeb, 0xcb, 0x0c, 0xf4, 0x4a, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x75, 0x1c, 0x11, 0xe1, 0x0c, 0x81, 0xa5, 0x42, + 0xfe, 0xd5, 0xd4, 0xb2, 0x61, 0x78, 0x19, 0xdf, 0x66, 0xff, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x77, 0x0b, 0x00, 0x00, 0x53, 0xf6, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x77, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xd3, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x07, 0x00, 0x00, + 0x67, 0xf5, 0xff, 0xff, 0x34, 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xb2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb5, 0x04, 0x00, 0x00, 0x78, 0x0a, 0x00, 0x00, + 0x2d, 0x06, 0x00, 0x00, 0x71, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x9a, 0x0a, 0x00, 0x00, 0xfe, 0xf7, 0xff, 0xff, 0x0e, 0x05, 0x00, 0x00, + 0xd4, 0x09, 0x00, 0x00, 0x47, 0xfe, 0xff, 0xff, 0xb6, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xac, 0xf7, 0xff, 0xff, 0x4b, 0xf9, 0xff, 0xff, + 0x4a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x8c, 0xef, 0xff, 0xff, 0x84, 0xff, 0xff, 0xff, 0x88, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x4d, 0x4c, 0x49, 0x52, 0x20, 0x43, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, + 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x96, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xca, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0xba, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x04, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x4c, 0x04, 0x00, 0x00, + 0xd0, 0x03, 0x00, 0x00, 0x68, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, + 0x98, 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xf0, 0xfb, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, 0xdc, 0xfb, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x4a, 0xce, 0x0a, 0x3c, 0x01, 0x00, 0x00, 0x00, + 0x34, 0x84, 0x85, 0x3f, 0x01, 0x00, 0x00, 0x00, 0xc5, 0x02, 0x8f, 0xbf, + 0x1e, 0x00, 0x00, 0x00, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, + 0x61, 0x6c, 0x6c, 0x3a, 0x30, 0x5f, 0x69, 0x6e, 0x74, 0x38, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x80, 0xfc, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x10, 0x00, 0x00, 0x00, 0x6c, 0xfc, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x93, 0xd0, 0xc0, 0x3b, 0x01, 0x00, 0x00, 0x00, + 0xc2, 0x0f, 0xc0, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x74, 0x66, 0x6c, 0x2e, 0x66, 0x75, 0x6c, 0x6c, + 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x31, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x08, 0xfd, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0xf4, 0xfc, 0xff, 0xff, + 0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xe0, 0xdb, 0x47, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x04, 0x14, 0x47, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x74, 0x66, 0x6c, 0x2e, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x5f, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff, + 0x14, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x50, 0x00, 0x00, 0x00, 0x6c, 0xfd, 0xff, 0xff, + 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xfb, 0x4b, 0x0b, 0x3c, + 0x01, 0x00, 0x00, 0x00, 0x40, 0x84, 0x4b, 0x3f, 0x01, 0x00, 0x00, 0x00, + 0x63, 0x35, 0x8a, 0xbf, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x74, 0x64, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x32, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x72, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x50, 0x00, 0x00, 0x00, + 0xdc, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x60, 0x01, 0x4f, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x47, 0x6d, 0xb3, 0x3f, + 0x01, 0x00, 0x00, 0x00, 0x5d, 0x63, 0xcd, 0xbf, 0x0d, 0x00, 0x00, 0x00, + 0x73, 0x74, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, + 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xe2, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x50, 0x00, 0x00, 0x00, 0x4c, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xd5, 0x6b, 0x8a, 0x3b, 0x01, 0x00, 0x00, 0x00, + 0xab, 0x49, 0x01, 0x3f, 0x01, 0x00, 0x00, 0x00, 0xfd, 0x56, 0x09, 0xbf, + 0x0c, 0x00, 0x00, 0x00, 0x73, 0x74, 0x64, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x52, 0xff, 0xff, 0xff, + 0x14, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x44, 0xff, 0xff, 0xff, + 0x08, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x28, 0xb3, 0xd9, 0x38, 0x0c, 0x00, 0x00, 0x00, + 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x32, 0x2f, 0x62, 0x69, 0x61, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0xaa, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x00, + 0x9c, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xdd, 0x9b, 0x21, 0x39, 0x0c, 0x00, 0x00, 0x00, + 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x33, 0x2f, 0x62, 0x69, 0x61, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x48, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xf4, 0xd4, 0x51, 0x38, 0x0c, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6e, 0x73, + 0x65, 0x5f, 0x34, 0x2f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x1c, 0x00, + 0x18, 0x00, 0x17, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, + 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x5d, 0x4f, 0xc9, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x86, 0xc8, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x5f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x32, 0x5f, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x30, 0x5f, 0x69, 0x6e, 0x74, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, + 0x0c, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09}; +const int g_model_len = 2488; diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/model.h b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/model.h new file mode 100644 index 000000000..488f47b3a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/model.h @@ -0,0 +1,31 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Automatically created from a TensorFlow Lite flatbuffer using the command: +// xxd -i model.tflite > model.cc + +// This is a standard TensorFlow Lite model file that has been converted into a +// C data array, so it can be easily compiled into a binary for devices that +// don't have a file system. + +// See train/README.md for a full description of the creation process. + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_MODEL_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_MODEL_H_ + +extern const unsigned char g_model[]; +extern const int g_model_len; + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_MODEL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/output_handler.h b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/output_handler.h new file mode 100644 index 000000000..14e9d7076 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/hello_world/output_handler.h @@ -0,0 +1,26 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_OUTPUT_HANDLER_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_OUTPUT_HANDLER_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" + +// Called by the main loop to produce some output based on the x and y values +void HandleOutput(tflite::ErrorReporter* error_reporter, float x_value, + float y_value); + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_HELLO_WORLD_OUTPUT_HANDLER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/LICENSE b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/README.md b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/README.md new file mode 100644 index 000000000..fd6b7bd96 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/README.md @@ -0,0 +1,114 @@ +# Magic Wand + +Magic Wand example for [TensorFlow Lite Micro](https://www.tensorflow.org/lite/microcontrollers) on the [Arduino Nano 33 BLE Sense](https://store-usa.arduino.cc/products/arduino-nano-33-ble-sense). + +## Table of contents + +* [Introduction](#introduction) +* [Hardware Requirements](#hardware-requirements) +* [Installing the Sketch](#installing-the-sketch) + * [Arduino Desktop IDE](#arduino-desktop-ide) +* [Building the Wand](#building-the-wand) +* [Using the wand](#using-the-wand) +* [Viewing Gestures in the Browser](#viewing-gestures-in-the-browser) +* [Pretrained Model](#pretrained-model) +* [Recording Gestures](#recording-gestures) +* [Training](#training) +* [Deployment](#deployment) + + +## Introduction + +This project shows you how to recognize gestures made by waving a magic wand, using machine learning to analyze accelerometer and gyroscope data. It demonstrates the three main stages of an end-to-end machine learning project: + + - **Gathering Data**. Using a Bluetooth connection to a web page, you can capture gestures, label them, and download the results. + - **Training**. A Python notebook on the free Colab service shows how to use TensorFlow to train a model to recognize gestures from your data. + - **Deployment**. You can deploy your trained model to the Arduino board using TensorFlow Lite Micro and the Arduino IDE. + + ## Hardware Requirements + + You'll need the following: + + - Arduino Nano 33 BLE Sense board. These are available as part of [the TinyML Starter Kit](https://store-usa.arduino.cc/products/arduino-tiny-machine-learning-kit), or separately from Arduino or resellers. Other Arduinos won't work unfortunately, because the Bluetooth and sensor code rely on accessing the particular hardware of the Nano 33 BLE Sense. + - MicroUSB cable. This is included in the TinyML Kit, but you'll need a USB-A adaptor too if your computer only has USB-C ports. + - Computer. The Arduino toolchain runs on Linux, Windows, and MacOS, so you should be able to use most laptops, desktops, or even a Raspberry Pi. For the training process, you'll also need an up-to-date version of the Chrome web browser so you can use the Web Bluetooth APIs. + - Stick. We'll be attaching your Arduino to a 'wand', but this can be practically anything, as long as it's roughly a foot (30 centimeters) long. + +## Installing the Sketch + +You'll need to ensure you can successfully connect and load sketches onto your Arduino board, +using the desktop IDE. +Once you've made sure you can load a simple sketch successfully, you'll follow these steps: + +### Arduino Desktop IDE + +If you're running using the Arduino IDE application, you'll need to fetch the latest version of this sketch. +To install the TensorFlow Lite Micro for Arduino library, see the +[how to install](../../README.md#how-to-install) instructions. + +Open up the magic_wand.ino file in the Arduino editor, and make sure the Arduino board is visible and connected to the right port. You'll need to search for the some libraries that the sketch depends on, using `Sketch->Include Library->Manage Libraries` from the main menu. The [Arduino_LSM9DS1](https://github.com/arduino-libraries/Arduino_LSM9DS1) lets us access the accelerometer and gyroscope readings from the board's IMU, and you need at least version 1.1.0. We'll be using Bluetooth to communicate with the web page, so you should also search for [ArduinoBLE](https://www.arduino.cc/en/Reference/ArduinoBLE) and make sure you've got version 1.1.3 or newer. + +You should now be able to press the upload button to compile and install the sketch on your board. + +## Building the Wand + +The 'wand' itself can be as simple as a stick, it doesn't need to do anything other than keep the board at its end as you hold the other end and wave it about. A cheap wand from an online retailer will work. A simple piece of wood or ruler works just as well. + +You should place the board at the end of the wand, with the USB socket facing downwards, towards where you hold it, so that the cable can run down the handle. The sketch is designed to compensate for any rotation of the board around the wand's shaft, so as long as it's parallel to the wand's length the board's twist won't matter. Use sticky tape or some other easy-to-remove method to attach the board to the wand, and hold the cable in place along the shaft. The end result should look something like this: + +![Image of board attached to wand](../../docs/magic_wand_attachment.jpg) + +If an ASCII-art diagram is more helpful, here's what you should aim for: + +``` + ____ + | |<- Arduino board + | | + | () | <- Reset button + | | + -TT- <- USB port + || + ||<- Wand + .... + || + || + () +``` + +## Using the wand + +The wand can be used with or without the Nano 33 BLE attached to the Tiny Machine Learning Shield. It is easier to use without, as your hand will not tire as quickly. The wand should be held as you would a pencil or pen, about 8 inches from the USB socket. Use your wrist to make strokes, not your arm. Strokes will need to be made somewhat quickly, without stopping during changes in direction. + +## Viewing Gestures in the Browser + +To preview and record gestures, we'll be connecting the sketch you've just uploaded to a web page, using Bluetooth and Chrome's WebBLE API. The code for the page is [in this repository](https://github.com/tensorflow/tflite-micro-arduino-examples/tree/main/examples/magic_wand/website), but it's all implemented using browser-side Javascript in a static HTML page, so you don't need to host it on your own server. Just dragging and dropping the `index.html` file into your browser should work. + +If the sketch has uploaded successfully, the Arduino should be advertising itself through Bluetooth. On the web page, press the 'Bluetooth' button to connect, and you should see a dialog appear asking you to pair with a device. After a second or two, there should be an entry that looks something like "BLESense-2F00". Click on that to pair, and you should be returned to the web page. + +If everything is working as expected, the Bluetooth button should turn blue, with "Connected" next to it. Now try moving the wand and look at the square below the button. As you gesture, you should see tracks appearing as lines in the web page in real time. Try doing small circles, or a 'Z' like Zorro! + +## Pretrained Model + +The sketch comes with a model that's been trained to recognize the hand-drawn digits zero to nine. This is based on a small dataset recorded by Google, so your accuracy may vary, but if you bring up the Serial Monitor in the Arduino IDE you can see what the model predicts for each gesture you make, with a confidence score between 0% and 100%, as well as ASCII art of the gesture outline. + +## Recording Gestures + +As you get familiar with the wand, so should notice that the gestures you have performed start to stack on the right side of the web page. This is where the data you'll eventually want to use for training is stored. When you leave or refresh the web page, these gestures will be lost, so make sure you use the "Download Data" link to save them locally if you've generated a number of them. + +The gestures are automatically split up by times when the wand is kept still. These pauses act like spaces between words, and so when you've finished a gesture you should stop moving the wand so that it ends cleanly. + +To get started, you should pick a couple of easy gestures to perform, like a 'Z' and an 'O'. As you make these gestures, you should see them appear in the right-hand stack of gestures. You can look at the shapes shown there to understand whether the gestures came out cleanly. A good rule of thumb is that if you can't tell what the gesture is by looking at it in the stack, then a model will have a hard time recognizing it too. + +Once you have ten or so of each gesture, scroll through the stack to review them. If any don't seem very recognizable, or are too 'sloppy' (which is very subjective unfortunately), then you can press the trash can button on the top right of the image to remove it. If you removed any, try recording some more so you have at least ten of each gesture. If you are happy with a gesture, click on the label at the top left to type in the correct name for it (for example `O` or `Z`). + +After you've reviewed and labeled all of your data, you can download it as a JSON text file that can be used for training. + +## Training + +Once you have data, you should [run the Python training notebook in Colab](https://colab.research.google.com/github/tensorflow/tflite-micro-arduino-examples/blob/main/examples/magic_wand/train/train_magic_wand_model.ipynb) and follow the steps to create and export your own model. + +## Deployment + +The Python training process should give you a `magic_wand_model_data.cc` file. Replace the file of the same name (but with a `.cpp` suffix) that's in the sketch you're using with this version. You'll also need to update the `labels` and `label_count` variables near the top of the `magic_wand.ino` to reflect any changes you made to the gestures you're trying to recognize. + +Upload this modified sketch, and you should be able to perform gestures and see them recognized in the Serial Monitor of your Arduino editor. diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand.ino b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand.ino new file mode 100644 index 000000000..881e2ee96 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand.ino @@ -0,0 +1,708 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include +#include + +#include + +#include "magic_wand_model_data.h" +#include "rasterize_stroke.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_interpreter.h" +#include "tensorflow/lite/micro/micro_mutable_op_resolver.h" +#include "tensorflow/lite/micro/system_setup.h" +#include "tensorflow/lite/schema/schema_generated.h" + +#define BLE_SENSE_UUID(val) ("4798e0f2-" val "-4d68-af64-8a8f5258404e") + +#undef MAGIC_WAND_DEBUG + +namespace { + +const int VERSION = 0x00000000; + +constexpr int stroke_transmit_stride = 2; +constexpr int stroke_transmit_max_length = 160; +constexpr int stroke_max_length = + stroke_transmit_max_length * stroke_transmit_stride; +constexpr int stroke_points_byte_count = + 2 * sizeof(int8_t) * stroke_transmit_max_length; +constexpr int stroke_struct_byte_count = + (2 * sizeof(int32_t)) + stroke_points_byte_count; +constexpr int moving_sample_count = 50; + +constexpr int raster_width = 32; +constexpr int raster_height = 32; +constexpr int raster_channels = 3; +constexpr int raster_byte_count = + raster_height * raster_width * raster_channels; +int8_t raster_buffer[raster_byte_count]; + +BLEService service(BLE_SENSE_UUID("0000")); +BLECharacteristic strokeCharacteristic(BLE_SENSE_UUID("300a"), BLERead, + stroke_struct_byte_count); + +// String to calculate the local and device name +String name; + +// A buffer holding the last 600 sets of 3-channel values from the +// accelerometer. +constexpr int acceleration_data_length = 600 * 3; +float acceleration_data[acceleration_data_length] = {}; +// The next free entry in the data array. +int acceleration_data_index = 0; +float acceleration_sample_rate = 0.0f; + +// A buffer holding the last 600 sets of 3-channel values from the gyroscope. +constexpr int gyroscope_data_length = 600 * 3; +float gyroscope_data[gyroscope_data_length] = {}; +float orientation_data[gyroscope_data_length] = {}; +// The next free entry in the data array. +int gyroscope_data_index = 0; +float gyroscope_sample_rate = 0.0f; + +float current_velocity[3] = {0.0f, 0.0f, 0.0f}; +float current_position[3] = {0.0f, 0.0f, 0.0f}; +float current_gravity[3] = {0.0f, 0.0f, 0.0f}; +float current_gyroscope_drift[3] = {0.0f, 0.0f, 0.0f}; + +int32_t stroke_length = 0; +uint8_t stroke_struct_buffer[stroke_struct_byte_count] = {}; +int32_t* stroke_state = reinterpret_cast(stroke_struct_buffer); +int32_t* stroke_transmit_length = + reinterpret_cast(stroke_struct_buffer + sizeof(int32_t)); +int8_t* stroke_points = + reinterpret_cast(stroke_struct_buffer + (sizeof(int32_t) * 2)); + +enum { + eWaiting = 0, + eDrawing = 1, + eDone = 2, +}; + +// Create an area of memory to use for input, output, and intermediate arrays. +// The size of this will depend on the model you're using, and may need to be +// determined by experimentation. +constexpr int kTensorArenaSize = 30 * 1024; +uint8_t tensor_arena[kTensorArenaSize]; + +tflite::ErrorReporter* error_reporter = nullptr; +const tflite::Model* model = nullptr; +tflite::MicroInterpreter* interpreter = nullptr; + +constexpr int label_count = 10; +const char* labels[label_count] = {"0", "1", "2", "3", "4", + "5", "6", "7", "8", "9"}; + +void SetupIMU() { + // Make sure we are pulling measurements into a FIFO. + // If you see an error on this line, make sure you have at least v1.1.0 of the + // Arduino_LSM9DS1 library installed. + IMU.setContinuousMode(); + + acceleration_sample_rate = IMU.accelerationSampleRate(); + gyroscope_sample_rate = IMU.gyroscopeSampleRate(); +#ifdef MAGIC_WAND_DEBUG + float rate_frac; + float rate_int; + rate_frac = modf(acceleration_sample_rate, &rate_int); + TF_LITE_REPORT_ERROR(error_reporter, "Acceleration sample rate %d.%d Hz", + static_cast(rate_int), + static_cast(rate_frac * 100)); + rate_frac = modf(gyroscope_sample_rate, &rate_int); + TF_LITE_REPORT_ERROR(error_reporter, "Gyroscope sample rate %d.%d Hz", + static_cast(rate_int), + static_cast(rate_frac * 100)); +#endif // MAGIC_WAND_DEBUG +} + +void ReadAccelerometerAndGyroscope(int* new_accelerometer_samples, + int* new_gyroscope_samples) { + // Keep track of whether we stored any new data + *new_accelerometer_samples = 0; + *new_gyroscope_samples = 0; + // Loop through new samples and add to buffer + while (IMU.accelerationAvailable()) { + const int gyroscope_index = (gyroscope_data_index % gyroscope_data_length); + gyroscope_data_index += 3; + float* current_gyroscope_data = &gyroscope_data[gyroscope_index]; + // Read each sample, removing it from the device's FIFO buffer + if (!IMU.readGyroscope(current_gyroscope_data[0], current_gyroscope_data[1], + current_gyroscope_data[2])) { + TF_LITE_REPORT_ERROR(error_reporter, "Failed to read gyroscope data"); + break; + } + *new_gyroscope_samples += 1; + + const int acceleration_index = + (acceleration_data_index % acceleration_data_length); + acceleration_data_index += 3; + float* current_acceleration_data = &acceleration_data[acceleration_index]; + // Read each sample, removing it from the device's FIFO buffer + if (!IMU.readAcceleration(current_acceleration_data[0], + current_acceleration_data[1], + current_acceleration_data[2])) { + TF_LITE_REPORT_ERROR(error_reporter, "Failed to read acceleration data"); + break; + } + *new_accelerometer_samples += 1; + } +} + +float VectorMagnitude(const float* vec) { + const float x = vec[0]; + const float y = vec[1]; + const float z = vec[2]; + return sqrtf((x * x) + (y * y) + (z * z)); +} + +void EstimateGravityDirection(float* gravity) { + int samples_to_average = 100; + if (samples_to_average >= acceleration_data_index) { + samples_to_average = acceleration_data_index; + } + + const int start_index = + ((acceleration_data_index + + (acceleration_data_length - (3 * (samples_to_average + 1)))) % + acceleration_data_length); + + float x_total = 0.0f; + float y_total = 0.0f; + float z_total = 0.0f; + for (int i = 0; i < samples_to_average; ++i) { + const int index = ((start_index + (i * 3)) % acceleration_data_length); + const float* entry = &acceleration_data[index]; + const float x = entry[0]; + const float y = entry[1]; + const float z = entry[2]; + x_total += x; + y_total += y; + z_total += z; + } + gravity[0] = x_total / samples_to_average; + gravity[1] = y_total / samples_to_average; + gravity[2] = z_total / samples_to_average; +} + +void UpdateVelocity(int new_samples, float* gravity) { + const float gravity_x = gravity[0]; + const float gravity_y = gravity[1]; + const float gravity_z = gravity[2]; + + const int start_index = + ((acceleration_data_index + + (acceleration_data_length - (3 * (new_samples + 1)))) % + acceleration_data_length); + + const float friction_fudge = 0.98f; + + for (int i = 0; i < new_samples; ++i) { + const int index = ((start_index + (i * 3)) % acceleration_data_length); + const float* entry = &acceleration_data[index]; + const float ax = entry[0]; + const float ay = entry[1]; + const float az = entry[2]; + + // Try to remove gravity from the raw acceleration values. + const float ax_minus_gravity = ax - gravity_x; + const float ay_minus_gravity = ay - gravity_y; + const float az_minus_gravity = az - gravity_z; + + // Update velocity based on the normalized acceleration. + current_velocity[0] += ax_minus_gravity; + current_velocity[1] += ay_minus_gravity; + current_velocity[2] += az_minus_gravity; + + // Dampen the velocity slightly with a fudge factor to stop it exploding. + current_velocity[0] *= friction_fudge; + current_velocity[1] *= friction_fudge; + current_velocity[2] *= friction_fudge; + + // Update the position estimate based on the velocity. + current_position[0] += current_velocity[0]; + current_position[1] += current_velocity[1]; + current_position[2] += current_velocity[2]; + } +} + +void EstimateGyroscopeDrift(float* drift) { + const bool isMoving = VectorMagnitude(current_velocity) > 0.1f; + if (isMoving) { + return; + } + + int samples_to_average = 20; + if (samples_to_average >= gyroscope_data_index) { + samples_to_average = gyroscope_data_index; + } + + const int start_index = + ((gyroscope_data_index + + (gyroscope_data_length - (3 * (samples_to_average + 1)))) % + gyroscope_data_length); + + float x_total = 0.0f; + float y_total = 0.0f; + float z_total = 0.0f; + for (int i = 0; i < samples_to_average; ++i) { + const int index = ((start_index + (i * 3)) % gyroscope_data_length); + const float* entry = &gyroscope_data[index]; + const float x = entry[0]; + const float y = entry[1]; + const float z = entry[2]; + x_total += x; + y_total += y; + z_total += z; + } + drift[0] = x_total / samples_to_average; + drift[1] = y_total / samples_to_average; + drift[2] = z_total / samples_to_average; +} + +void UpdateOrientation(int new_samples, float* gravity, float* drift) { + const float drift_x = drift[0]; + const float drift_y = drift[1]; + const float drift_z = drift[2]; + + const int start_index = + ((gyroscope_data_index + (gyroscope_data_length - (3 * new_samples))) % + gyroscope_data_length); + + // The gyroscope values are in degrees-per-second, so to approximate + // degrees in the integrated orientation, we need to divide each value + // by the number of samples each second. + const float recip_sample_rate = 1.0f / gyroscope_sample_rate; + + for (int i = 0; i < new_samples; ++i) { + const int index = ((start_index + (i * 3)) % gyroscope_data_length); + const float* entry = &gyroscope_data[index]; + const float dx = entry[0]; + const float dy = entry[1]; + const float dz = entry[2]; + + // Try to remove sensor errors from the raw gyroscope values. + const float dx_minus_drift = dx - drift_x; + const float dy_minus_drift = dy - drift_y; + const float dz_minus_drift = dz - drift_z; + + // Convert from degrees-per-second to appropriate units for this + // time interval. + const float dx_normalized = dx_minus_drift * recip_sample_rate; + const float dy_normalized = dy_minus_drift * recip_sample_rate; + const float dz_normalized = dz_minus_drift * recip_sample_rate; + + // Update orientation based on the gyroscope data. + float* current_orientation = &orientation_data[index]; + const int previous_index = + (index + (gyroscope_data_length - 3)) % gyroscope_data_length; + const float* previous_orientation = &orientation_data[previous_index]; + current_orientation[0] = previous_orientation[0] + dx_normalized; + current_orientation[1] = previous_orientation[1] + dy_normalized; + current_orientation[2] = previous_orientation[2] + dz_normalized; + } +} + +bool IsMoving(int samples_before) { + constexpr float moving_threshold = 9.0f; + + if ((gyroscope_data_index - samples_before) < moving_sample_count) { + return false; + } + + const int start_index = + ((gyroscope_data_index + (gyroscope_data_length - + (3 * (moving_sample_count + samples_before)))) % + gyroscope_data_length); + + float total = 0.0f; + for (int i = 0; i < moving_sample_count; ++i) { + const int index = ((start_index + (i * 3)) % gyroscope_data_length); + float* current_orientation = &orientation_data[index]; + const int previous_index = + (index + (gyroscope_data_length - 3)) % gyroscope_data_length; + const float* previous_orientation = &orientation_data[previous_index]; + const float dx = current_orientation[0] - previous_orientation[0]; + const float dy = current_orientation[1] - previous_orientation[1]; + const float dz = current_orientation[2] - previous_orientation[2]; + const float mag_squared = (dx * dx) + (dy * dy) + (dz * dz); + total += mag_squared; + } + const bool is_moving = (total > moving_threshold); + return is_moving; +} + +void UpdateStroke(int new_samples, bool* done_just_triggered) { + constexpr int minimum_stroke_length = moving_sample_count + 10; + constexpr float minimum_stroke_size = 0.2f; + + *done_just_triggered = false; + + for (int i = 0; i < new_samples; ++i) { + const int current_head = (new_samples - (i + 1)); + const bool is_moving = IsMoving(current_head); + const int32_t old_state = *stroke_state; + if ((old_state == eWaiting) || (old_state == eDone)) { + if (is_moving) { + stroke_length = moving_sample_count; + *stroke_state = eDrawing; + } + } else if (old_state == eDrawing) { + if (!is_moving) { + if (stroke_length > minimum_stroke_length) { + *stroke_state = eDone; + } else { + stroke_length = 0; + *stroke_state = eWaiting; +#ifdef MAGIC_WAND_DEBUG + TF_LITE_REPORT_ERROR(error_reporter, "stroke length too small"); +#endif // MAGIC_WAND_DEBUG + } + } + } + + const bool is_waiting = (*stroke_state == eWaiting); + if (is_waiting) { + continue; + } + + stroke_length += 1; + if (stroke_length > stroke_max_length) { + stroke_length = stroke_max_length; + } + + // Only recalculate the full stroke if it's needed. + const bool draw_last_point = + ((i == (new_samples - 1)) && (*stroke_state == eDrawing)); + *done_just_triggered = ((old_state != eDone) && (*stroke_state == eDone)); + if (!(*done_just_triggered || draw_last_point)) { + continue; + } + + const int start_index = + ((gyroscope_data_index + + (gyroscope_data_length - (3 * (stroke_length + current_head)))) % + gyroscope_data_length); + + float x_total = 0.0f; + float y_total = 0.0f; + float z_total = 0.0f; + for (int j = 0; j < stroke_length; ++j) { + const int index = ((start_index + (j * 3)) % gyroscope_data_length); + const float* entry = &orientation_data[index]; + x_total += entry[0]; + y_total += entry[1]; + z_total += entry[2]; + } + + const float y_mean = y_total / stroke_length; + const float z_mean = z_total / stroke_length; + constexpr float range = 45.0f; + + const float gy = current_gravity[1]; + const float gz = current_gravity[2]; + float gmag = sqrtf((gy * gy) + (gz * gz)); + if (gmag < 0.0001f) { + gmag = 0.0001f; + } + const float ngy = gy / gmag; + const float ngz = gz / gmag; + + const float xaxisz = -ngz; + const float xaxisy = -ngy; + + const float yaxisz = -ngy; + const float yaxisy = ngz; + + *stroke_transmit_length = stroke_length / stroke_transmit_stride; + + float x_min = 0; + float y_min = 0; + float x_max = 0; + float y_max = 0; + for (int j = 0; j < *stroke_transmit_length; ++j) { + const int orientation_index = + ((start_index + ((j * stroke_transmit_stride) * 3)) % + gyroscope_data_length); + const float* orientation_entry = &orientation_data[orientation_index]; + + const float orientation_y = orientation_entry[1]; + const float orientation_z = orientation_entry[2]; + + const float ny = (orientation_y - y_mean) / range; + const float nz = (orientation_z - z_mean) / range; + + const float x_axis = (xaxisz * nz) + (xaxisy * ny); + const float y_axis = (yaxisz * nz) + (yaxisy * ny); + + const int stroke_index = j * 2; + int8_t* stroke_entry = &stroke_points[stroke_index]; + + int32_t unchecked_x = static_cast(roundf(x_axis * 128.0f)); + int8_t stored_x; + if (unchecked_x > 127) { + stored_x = 127; + } else if (unchecked_x < -128) { + stored_x = -128; + } else { + stored_x = unchecked_x; + } + stroke_entry[0] = stored_x; + + int32_t unchecked_y = static_cast(roundf(y_axis * 128.0f)); + int8_t stored_y; + if (unchecked_y > 127) { + stored_y = 127; + } else if (unchecked_y < -128) { + stored_y = -128; + } else { + stored_y = unchecked_y; + } + stroke_entry[1] = stored_y; + + const bool is_first = (j == 0); + if (is_first || (x_axis < x_min)) { + x_min = x_axis; + } + if (is_first || (y_axis < y_min)) { + y_min = y_axis; + } + if (is_first || (x_axis > x_max)) { + x_max = x_axis; + } + if (is_first || (y_axis > y_max)) { + y_max = y_axis; + } + } + + // If the stroke is too small, cancel it. + if (*done_just_triggered) { + const float x_range = (x_max - x_min); + const float y_range = (y_max - y_min); + if ((x_range < minimum_stroke_size) && (y_range < minimum_stroke_size)) { + *done_just_triggered = false; + *stroke_state = eWaiting; + *stroke_transmit_length = 0; + stroke_length = 0; +#ifdef MAGIC_WAND_DEBUG + TF_LITE_REPORT_ERROR(error_reporter, "stroke too small"); +#endif // MAGIC_WAND_DEBUG + } + } + } +} + +} // namespace + +void setup() { + tflite::InitializeTarget(); // setup serial port + + // Set up logging. Google style is to avoid globals or statics because of + // lifetime uncertainty, but since this has a trivial destructor it's okay. + static tflite::MicroErrorReporter micro_error_reporter; // NOLINT + error_reporter = µ_error_reporter; + + TF_LITE_REPORT_ERROR(error_reporter, "Started"); + + if (!IMU.begin()) { + TF_LITE_REPORT_ERROR(error_reporter, "Failed to initialized IMU!"); + while (true) { + // NORETURN + } + } + + SetupIMU(); + + if (!BLE.begin()) { + TF_LITE_REPORT_ERROR(error_reporter, "Failed to initialized BLE!"); + while (true) { + // NORETURN + } + } + + String address = BLE.address(); + + TF_LITE_REPORT_ERROR(error_reporter, "address = %s", address.c_str()); + + address.toUpperCase(); + + name = "BLESense-"; + name += address[address.length() - 5]; + name += address[address.length() - 4]; + name += address[address.length() - 2]; + name += address[address.length() - 1]; + + TF_LITE_REPORT_ERROR(error_reporter, "name = %s", name.c_str()); + + BLE.setLocalName(name.c_str()); + BLE.setDeviceName(name.c_str()); + BLE.setAdvertisedService(service); + + service.addCharacteristic(strokeCharacteristic); + + BLE.addService(service); + + BLE.advertise(); + + // Map the model into a usable data structure. This doesn't involve any + // copying or parsing, it's a very lightweight operation. + model = tflite::GetModel(g_magic_wand_model_data); + if (model->version() != TFLITE_SCHEMA_VERSION) { + TF_LITE_REPORT_ERROR(error_reporter, + "Model provided is schema version %d not equal " + "to supported version %d.", + model->version(), TFLITE_SCHEMA_VERSION); + return; + } + + // Pull in only the operation implementations we need. + // This relies on a complete list of all the ops needed by this graph. + // An easier approach is to just use the AllOpsResolver, but this will + // incur some penalty in code space for op implementations that are not + // needed by this graph. + static tflite::MicroMutableOpResolver<4> micro_op_resolver; // NOLINT + micro_op_resolver.AddConv2D(); + micro_op_resolver.AddMean(); + micro_op_resolver.AddFullyConnected(); + micro_op_resolver.AddSoftmax(); + + // Build an interpreter to run the model with. + static tflite::MicroInterpreter static_interpreter( + model, micro_op_resolver, tensor_arena, kTensorArenaSize, error_reporter); + interpreter = &static_interpreter; + + // Allocate memory from the tensor_arena for the model's tensors. + interpreter->AllocateTensors(); + + TfLiteTensor* model_input = interpreter->input(0); + if ((model_input->dims->size != 4) || (model_input->dims->data[0] != 1) || + (model_input->dims->data[1] != raster_height) || + (model_input->dims->data[2] != raster_width) || + (model_input->dims->data[3] != raster_channels) || + (model_input->type != kTfLiteInt8) || + (model_input->params.zero_point != -128) || + (model_input->params.scale != 1.0)) { + TF_LITE_REPORT_ERROR(error_reporter, + "Bad input tensor parameters in model"); + return; + } + + TfLiteTensor* model_output = interpreter->output(0); + if ((model_output->dims->size != 2) || (model_output->dims->data[0] != 1) || + (model_output->dims->data[1] != label_count) || + (model_output->type != kTfLiteInt8)) { + TF_LITE_REPORT_ERROR(error_reporter, + "Bad output tensor parameters in model"); + return; + } +} + +void loop() { + BLEDevice central = BLE.central(); + + // if a central is connected to the peripheral: + static bool was_connected_last = false; + if (central && !was_connected_last) { + // print the central's BT address: + TF_LITE_REPORT_ERROR(error_reporter, "Connected to central: %s", + central.address().c_str()); + } + was_connected_last = central; + + const bool data_available = + IMU.accelerationAvailable() || IMU.gyroscopeAvailable(); + if (!data_available) { + return; + } + + int accelerometer_samples_read; + int gyroscope_samples_read; + ReadAccelerometerAndGyroscope(&accelerometer_samples_read, + &gyroscope_samples_read); + + bool done_just_triggered = false; + if (gyroscope_samples_read > 0) { + EstimateGyroscopeDrift(current_gyroscope_drift); + UpdateOrientation(gyroscope_samples_read, current_gravity, + current_gyroscope_drift); + UpdateStroke(gyroscope_samples_read, &done_just_triggered); + if (central && central.connected()) { + strokeCharacteristic.writeValue(stroke_struct_buffer, + stroke_struct_byte_count); + } + } + + if (accelerometer_samples_read > 0) { + EstimateGravityDirection(current_gravity); + UpdateVelocity(accelerometer_samples_read, current_gravity); + } + + if (done_just_triggered) { + RasterizeStroke(stroke_points, *stroke_transmit_length, 0.6f, 0.6f, + raster_width, raster_height, raster_buffer); + for (int y = 0; y < raster_height; ++y) { + char line[raster_width + 1]; + for (int x = 0; x < raster_width; ++x) { + const int8_t* pixel = + &raster_buffer[(y * raster_width * raster_channels) + + (x * raster_channels)]; + const int8_t red = pixel[0]; + const int8_t green = pixel[1]; + const int8_t blue = pixel[2]; + char output; + if ((red > -128) || (green > -128) || (blue > -128)) { + output = '#'; + } else { + output = '.'; + } + line[x] = output; + } + line[raster_width] = 0; + TF_LITE_REPORT_ERROR(error_reporter, line); + } +#ifdef MAGIC_WAND_DEBUG + TF_LITE_REPORT_ERROR(error_reporter, "tx len: %d", *stroke_transmit_length); +#endif // MAGIC_WAND_DEBUG + + TfLiteTensor* model_input = interpreter->input(0); + for (int i = 0; i < raster_byte_count; ++i) { + model_input->data.int8[i] = raster_buffer[i]; + } + + TfLiteStatus invoke_status = interpreter->Invoke(); + if (invoke_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed"); + return; + } + + TfLiteTensor* output = interpreter->output(0); + + int8_t max_score; + int max_index; + for (int i = 0; i < label_count; ++i) { + const int8_t score = output->data.int8[i]; + if ((i == 0) || (score > max_score)) { + max_score = score; + max_index = i; + } + } + float max_score_f = + (max_score - output->params.zero_point) * output->params.scale; + float max_score_int; + float max_score_frac = modf(max_score_f * 100, &max_score_int); + TF_LITE_REPORT_ERROR(error_reporter, "Found %s (%d.%d%%)", + labels[max_index], static_cast(max_score_int), + static_cast(max_score_frac * 100)); + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand_model_data.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand_model_data.cpp new file mode 100644 index 000000000..77c8a05e8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand_model_data.cpp @@ -0,0 +1,2588 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +unsigned char g_magic_wand_model_data[] = { + 0x20, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x44, 0x01, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, + 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xec, 0x06, 0x00, 0x00, + 0xa4, 0x03, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x3c, 0x78, 0x00, 0x00, 0x38, 0x78, 0x00, 0x00, 0x08, 0x77, 0x00, 0x00, + 0xc4, 0x73, 0x00, 0x00, 0x04, 0x72, 0x00, 0x00, 0x14, 0x5e, 0x00, 0x00, + 0x4c, 0x5b, 0x00, 0x00, 0xdc, 0x0f, 0x00, 0x00, 0x14, 0x0b, 0x00, 0x00, + 0x24, 0x08, 0x00, 0x00, 0x9c, 0x07, 0x00, 0x00, 0x10, 0x78, 0x00, 0x00, + 0x0c, 0x78, 0x00, 0x00, 0x08, 0x78, 0x00, 0x00, 0x04, 0x78, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x00, 0xfc, 0x77, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x64, 0x65, 0x6e, 0x73, 0x65, 0x00, 0x00, 0x00, 0xa6, 0x89, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x5f, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0xee, 0x89, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x31, 0x34, + 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x4d, 0x4c, 0x49, 0x52, 0x20, 0x43, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x58, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x54, 0x76, 0x00, 0x00, 0xdc, 0x75, 0x00, 0x00, + 0x30, 0x74, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0xd0, 0x6e, 0x00, 0x00, + 0x88, 0x5a, 0x00, 0x00, 0x98, 0x56, 0x00, 0x00, 0xd0, 0x0a, 0x00, 0x00, + 0x60, 0x09, 0x00, 0x00, 0x80, 0x06, 0x00, 0x00, 0x64, 0x05, 0x00, 0x00, + 0xfc, 0x03, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, + 0x3c, 0x01, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xd4, 0x04, 0x00, 0x00, 0x94, 0x03, 0x00, 0x00, + 0x68, 0x02, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x03, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xda, 0x8a, 0xff, 0xff, 0x00, 0x00, 0x80, 0x3f, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x38, 0xfb, 0xff, 0xff, 0x19, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x19, 0x02, 0x00, 0x00, 0x00, 0x78, 0x8a, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, + 0x61, 0x6c, 0x6c, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0x54, 0x8a, 0xff, 0xff, + 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3b, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x36, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0x8a, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0xf4, 0xfb, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x04, 0x00, 0x00, 0x00, 0x34, 0x8b, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x2f, + 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, + 0x64, 0x64, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x0a, 0x00, 0x00, 0x00, 0x1c, 0x8b, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x0b, 0xe6, 0x3d, + 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x08, 0x00, + 0x0c, 0x00, 0x10, 0x00, 0x07, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3c, 0x8b, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc8, 0xfc, 0xff, 0xff, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x00, + 0x08, 0x8c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x14, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x61, 0x76, 0x65, + 0x72, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x69, 0x6e, 0x67, + 0x32, 0x64, 0x2f, 0x4d, 0x65, 0x61, 0x6e, 0x00, 0x02, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x40, 0x00, 0x00, 0x00, 0xec, 0x8b, 0xff, 0xff, + 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0a, 0xc3, 0x18, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xaa, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x9c, 0xfd, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0xc0, 0x8c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x14, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0xb8, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x32, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, + 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x32, 0x2f, + 0x46, 0x75, 0x73, 0x65, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, + 0x72, 0x6d, 0x56, 0x33, 0x3b, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x32, 0x2f, 0x62, 0x69, 0x61, 0x73, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x32, 0x2f, 0x42, 0x69, + 0x61, 0x73, 0x41, 0x64, 0x64, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, + 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x32, 0x2f, 0x43, 0x6f, 0x6e, + 0x76, 0x32, 0x44, 0x31, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x14, 0x8d, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x0a, 0x50, 0x3d, + 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xd2, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc4, 0xfe, 0xff, 0xff, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xe8, 0x8d, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x14, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, + 0xa0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x31, 0x2f, 0x52, + 0x65, 0x6c, 0x75, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x62, 0x61, + 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x31, 0x2f, 0x46, 0x75, 0x73, 0x65, + 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x56, 0x33, + 0x3b, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x2f, 0x62, 0x69, + 0x61, 0x73, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x31, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, + 0x64, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x76, + 0x32, 0x64, 0x5f, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x31, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x3c, 0x8e, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x07, 0xdf, 0x24, 0x3c, 0x01, 0x00, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x07, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0f, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x4c, 0x8f, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x2f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x6f, + 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, + 0x46, 0x75, 0x73, 0x65, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, + 0x72, 0x6d, 0x56, 0x33, 0x3b, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x2f, + 0x62, 0x69, 0x61, 0x73, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, + 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, + 0x64, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x76, + 0x32, 0x64, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x32, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x94, 0x8f, 0xff, 0xff, + 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0xb1, 0x5b, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xba, 0x90, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x5a, 0xdf, 0xff, 0xff, + 0x44, 0x05, 0x00, 0x00, 0x31, 0xee, 0xff, 0xff, 0x10, 0xf3, 0xff, 0xff, + 0x31, 0xec, 0xff, 0xff, 0x86, 0xea, 0xff, 0xff, 0x34, 0x01, 0x00, 0x00, + 0x98, 0xfe, 0xff, 0xff, 0xe1, 0xe9, 0xff, 0xff, 0x36, 0xf0, 0xff, 0xff, + 0xd2, 0x90, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x64, 0x65, 0x6e, 0x73, 0x65, 0x2f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, + 0x1c, 0x90, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x41, 0xaf, 0xe2, 0x38, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x91, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xfd, 0x11, 0x10, 0x9c, + 0x0c, 0x05, 0xf9, 0xfd, 0x09, 0x10, 0x02, 0x1b, 0xee, 0xfc, 0x18, 0x08, + 0xc5, 0x0c, 0x12, 0xf8, 0xf8, 0x12, 0x87, 0x08, 0x26, 0x1f, 0x08, 0xdd, + 0x14, 0xb7, 0x20, 0x09, 0x18, 0x01, 0x9a, 0xfb, 0xd9, 0xf4, 0xda, 0x8f, + 0x02, 0xe6, 0xdd, 0x28, 0x90, 0xeb, 0x10, 0xfe, 0x06, 0x13, 0xae, 0xd7, + 0xf7, 0xad, 0xf7, 0xc1, 0xe4, 0xba, 0x01, 0xa4, 0x03, 0x03, 0x01, 0xe1, + 0xaf, 0x13, 0x0e, 0xde, 0x14, 0x21, 0xad, 0xc1, 0xab, 0x1b, 0xbf, 0x14, + 0x98, 0xb1, 0xe7, 0xa5, 0x20, 0xdf, 0xae, 0x18, 0xbf, 0x29, 0x0b, 0x1c, + 0xa6, 0xc9, 0xa1, 0xcf, 0xb3, 0x17, 0x12, 0xcb, 0x9f, 0x9f, 0x07, 0xb3, + 0xbf, 0x27, 0xc9, 0x05, 0x1c, 0xdf, 0xac, 0xb5, 0x05, 0xb8, 0xad, 0xb2, + 0x16, 0x14, 0xda, 0xfd, 0xa1, 0x15, 0xb1, 0xba, 0x06, 0x01, 0xa4, 0x0f, + 0xa3, 0x21, 0x1c, 0x02, 0x22, 0xbe, 0xfc, 0xb0, 0xad, 0x22, 0x0c, 0xac, + 0x04, 0x15, 0xbd, 0xd8, 0x09, 0x19, 0x03, 0x0d, 0xb9, 0x0c, 0xdb, 0xba, + 0xce, 0x1e, 0x06, 0x21, 0xf7, 0x11, 0xc5, 0x15, 0x15, 0xeb, 0xbc, 0xd3, + 0x1b, 0x13, 0x12, 0x08, 0xbc, 0xd0, 0x1a, 0x12, 0xc9, 0x00, 0xbb, 0xad, + 0x17, 0xa7, 0x08, 0x14, 0xd5, 0xbe, 0xdc, 0x21, 0xa6, 0xdc, 0x1d, 0xc7, + 0xb9, 0xbd, 0xc5, 0xfe, 0xc3, 0xb5, 0xe5, 0xa9, 0xaf, 0x1f, 0x17, 0x1b, + 0x1b, 0xc2, 0x08, 0xb1, 0xcd, 0x0b, 0xe4, 0xd0, 0x12, 0xd7, 0x0c, 0x07, + 0x2b, 0x03, 0x25, 0xfc, 0xfd, 0xcf, 0xfd, 0xa6, 0x2d, 0xc3, 0xab, 0xf9, + 0xfc, 0xde, 0xfc, 0xf3, 0xc7, 0x94, 0x01, 0x13, 0xb3, 0xaf, 0x1e, 0x03, + 0xa9, 0x15, 0xc1, 0xea, 0xf8, 0xad, 0x14, 0xa7, 0xbb, 0x9a, 0x0b, 0xd6, + 0xcf, 0x11, 0x0d, 0x15, 0x9c, 0xc1, 0x14, 0x07, 0xab, 0xc9, 0xca, 0xd3, + 0x22, 0xa2, 0x93, 0x09, 0x13, 0xe2, 0xb6, 0x1a, 0x2a, 0x90, 0x02, 0x13, + 0xac, 0xb0, 0xc5, 0xb2, 0x0f, 0xbe, 0xd1, 0xd8, 0xa6, 0x0f, 0xe1, 0x10, + 0x26, 0xd4, 0xc8, 0x15, 0x16, 0x06, 0xff, 0xae, 0xee, 0xcd, 0x11, 0xbb, + 0xc3, 0xc3, 0x2d, 0xca, 0xd9, 0xc7, 0x16, 0x22, 0xdc, 0x25, 0x14, 0x0f, + 0xb7, 0x00, 0x20, 0x0d, 0x2d, 0xf0, 0xa9, 0xfd, 0xcf, 0x0f, 0xbc, 0xf5, + 0x0f, 0x10, 0x92, 0x19, 0xcb, 0xcb, 0x8a, 0x0d, 0xc6, 0xaa, 0x0a, 0xc9, + 0xbc, 0x97, 0xc8, 0x1d, 0xfa, 0x18, 0x12, 0x87, 0xd8, 0x8c, 0xc5, 0x12, + 0x1c, 0xc9, 0x0e, 0xa9, 0xe2, 0xa9, 0xcc, 0x0f, 0x14, 0xff, 0x15, 0x1c, + 0xab, 0xb5, 0x07, 0x03, 0x24, 0xbb, 0xec, 0x0d, 0xa3, 0xea, 0x0e, 0x24, + 0x15, 0x14, 0xf7, 0xea, 0x11, 0x8c, 0x16, 0xcd, 0xda, 0x00, 0x08, 0x12, + 0xee, 0xe7, 0xf7, 0x03, 0xbf, 0xc8, 0x22, 0x1d, 0x07, 0x09, 0xff, 0x9e, + 0xe5, 0xc2, 0x11, 0xd2, 0xe2, 0xd3, 0x39, 0x12, 0x12, 0xbe, 0x17, 0xf0, + 0xcf, 0x04, 0xf9, 0xa6, 0xda, 0xdf, 0xcd, 0xfc, 0xf2, 0xdb, 0xbf, 0x0f, + 0xc0, 0x0f, 0xb6, 0xf6, 0xcd, 0x17, 0xb3, 0x18, 0x18, 0xc6, 0xd3, 0xe7, + 0x08, 0x1d, 0x14, 0xbd, 0xa8, 0x12, 0xb8, 0x12, 0x12, 0x01, 0x81, 0x0d, + 0xb2, 0xbd, 0xcd, 0xae, 0x1d, 0x35, 0x08, 0xc2, 0xd9, 0xda, 0xf7, 0x02, + 0xc7, 0xa7, 0xc9, 0x10, 0x03, 0x14, 0x0f, 0xb5, 0x27, 0xcf, 0x35, 0xc1, + 0xb6, 0xca, 0xc0, 0x05, 0xf2, 0x15, 0x1e, 0x17, 0x18, 0xa7, 0x09, 0xa6, + 0xdb, 0x21, 0x27, 0xd1, 0xc0, 0x13, 0xb8, 0x24, 0x1d, 0x19, 0x05, 0xc6, + 0xd8, 0x17, 0xa8, 0x0b, 0xa9, 0xd2, 0x9d, 0x19, 0x0e, 0xdc, 0xad, 0xaa, + 0xae, 0xc4, 0x00, 0xb7, 0x0d, 0xf6, 0xbc, 0xd6, 0xd3, 0xdf, 0xa9, 0x0f, + 0xf3, 0x15, 0xd3, 0xc6, 0x16, 0x07, 0x05, 0xfb, 0xbc, 0xc8, 0xc3, 0x1e, + 0xf4, 0xfb, 0xe5, 0xb4, 0xf9, 0x1c, 0xb4, 0x0d, 0xfc, 0x0a, 0x04, 0x16, + 0x1a, 0xe3, 0xc8, 0x07, 0xd1, 0xe1, 0x12, 0xb0, 0xb5, 0xb0, 0xcc, 0x06, + 0xe1, 0x04, 0xa8, 0xd7, 0x1c, 0x1c, 0xda, 0xa8, 0x14, 0xb8, 0x0e, 0xd8, + 0xbf, 0x16, 0xd2, 0x04, 0xfd, 0xfe, 0x2a, 0xc5, 0x26, 0xba, 0x21, 0xba, + 0x0d, 0xe2, 0x15, 0xb0, 0x17, 0xbf, 0x0e, 0x1a, 0xb8, 0xc2, 0xf4, 0x0b, + 0xfc, 0xe7, 0xa3, 0x1e, 0xb9, 0x05, 0xdb, 0xa2, 0x0a, 0x1b, 0x9f, 0x0e, + 0xe0, 0x9d, 0xa9, 0xbc, 0xa6, 0xca, 0x15, 0xbc, 0xce, 0x11, 0x2c, 0x90, + 0x0b, 0xf1, 0x19, 0xa0, 0x09, 0xfd, 0xfb, 0xb3, 0xa7, 0xbb, 0xc0, 0xfa, + 0xd0, 0x1e, 0x04, 0xf2, 0x0d, 0xbe, 0x10, 0x06, 0xbe, 0x21, 0xf6, 0x1a, + 0xe6, 0x11, 0xf5, 0x25, 0x2e, 0x1b, 0x19, 0x03, 0x1c, 0xe5, 0x96, 0x92, + 0xae, 0x93, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x64, 0x65, + 0x6e, 0x73, 0x65, 0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x00, 0x00, + 0x04, 0x93, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xb4, 0xf0, 0x3d, 0x3c, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x94, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0xe9, 0x01, 0x00, 0x00, 0xfb, 0x07, 0x00, 0x00, 0x42, 0x05, 0x00, 0x00, + 0x3c, 0xe7, 0xff, 0xff, 0x6e, 0xf8, 0xff, 0xff, 0xa8, 0xf0, 0xff, 0xff, + 0x13, 0xfa, 0xff, 0xff, 0x06, 0xfe, 0xff, 0xff, 0xca, 0xfd, 0xff, 0xff, + 0xcd, 0x02, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0xc1, 0xf8, 0xff, 0xff, + 0xfb, 0xfe, 0xff, 0xff, 0x13, 0xfb, 0xff, 0xff, 0x99, 0xff, 0xff, 0xff, + 0x75, 0x05, 0x00, 0x00, 0x73, 0xf4, 0xff, 0xff, 0x3e, 0x08, 0x00, 0x00, + 0x41, 0x07, 0x00, 0x00, 0xae, 0xee, 0xff, 0xff, 0xc3, 0xf3, 0xff, 0xff, + 0xa3, 0xfa, 0xff, 0xff, 0xf1, 0xf5, 0xff, 0xff, 0xdb, 0xfe, 0xff, 0xff, + 0xae, 0x03, 0x00, 0x00, 0x25, 0xfe, 0xff, 0xff, 0xb8, 0xfd, 0xff, 0xff, + 0xa6, 0xf5, 0xff, 0xff, 0x51, 0xee, 0xff, 0xff, 0xcd, 0xff, 0xff, 0xff, + 0xd2, 0xef, 0xff, 0xff, 0x80, 0xf6, 0xff, 0xff, 0x90, 0xfd, 0xff, 0xff, + 0x8c, 0xfe, 0xff, 0xff, 0x42, 0xf1, 0xff, 0xff, 0x43, 0x00, 0x00, 0x00, + 0xa6, 0xff, 0xff, 0xff, 0x05, 0xfb, 0xff, 0xff, 0x7e, 0xf1, 0xff, 0xff, + 0x93, 0xf5, 0xff, 0xff, 0x65, 0x03, 0x00, 0x00, 0x92, 0xf2, 0xff, 0xff, + 0x13, 0xfa, 0xff, 0xff, 0xd4, 0xeb, 0xff, 0xff, 0x81, 0xef, 0xff, 0xff, + 0x9f, 0xfb, 0xff, 0xff, 0xa5, 0xf6, 0xff, 0xff, 0x14, 0x01, 0x00, 0x00, + 0x29, 0xfe, 0xff, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x2b, 0xef, 0xff, 0xff, + 0x96, 0xec, 0xff, 0xff, 0xa0, 0x02, 0x00, 0x00, 0xbd, 0xf4, 0xff, 0xff, + 0x8e, 0xfb, 0xff, 0xff, 0x23, 0xe7, 0xff, 0xff, 0xa9, 0xf6, 0xff, 0xff, + 0xc4, 0xf5, 0xff, 0xff, 0x41, 0x02, 0x00, 0x00, 0xe4, 0xf7, 0xff, 0xff, + 0xbc, 0x00, 0x00, 0x00, 0x1d, 0xf4, 0xff, 0xff, 0xea, 0xf9, 0xff, 0xff, + 0x59, 0xf7, 0xff, 0xff, 0x1a, 0x95, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, + 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x32, 0x2f, 0x52, + 0x65, 0x6c, 0x75, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x62, 0x61, + 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x32, 0x2f, 0x46, 0x75, 0x73, 0x65, + 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x56, 0x33, + 0x3b, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x32, 0x2f, 0x62, 0x69, + 0x61, 0x73, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x32, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, + 0x64, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x76, + 0x32, 0x64, 0x5f, 0x32, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x00, + 0xd8, 0x94, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x4c, 0x5d, 0x06, 0x39, 0xf5, 0x73, 0x03, 0x39, + 0x79, 0x31, 0x0a, 0x39, 0x60, 0xd6, 0xf8, 0x38, 0x45, 0x5f, 0x24, 0x39, + 0x7d, 0xca, 0xfa, 0x38, 0xa6, 0x58, 0xfa, 0x38, 0xb0, 0xa4, 0x0c, 0x39, + 0x88, 0xf1, 0x01, 0x39, 0x62, 0xe2, 0xe0, 0x38, 0x08, 0xe8, 0xdd, 0x38, + 0x54, 0x03, 0x14, 0x39, 0x6a, 0xad, 0xe7, 0x38, 0xf6, 0xf4, 0xf1, 0x38, + 0xe4, 0x84, 0xee, 0x38, 0x80, 0xba, 0x17, 0x39, 0x74, 0xe1, 0x23, 0x39, + 0x91, 0x30, 0x1f, 0x39, 0x5d, 0x23, 0x18, 0x39, 0xca, 0x32, 0x0f, 0x39, + 0xe6, 0xac, 0xf1, 0x38, 0xcf, 0x67, 0x18, 0x39, 0x83, 0x61, 0xe2, 0x38, + 0xec, 0x4b, 0x1e, 0x39, 0x77, 0x65, 0xf6, 0x38, 0xfb, 0xba, 0x0a, 0x39, + 0x88, 0x47, 0xdd, 0x38, 0x8e, 0xda, 0x06, 0x39, 0xa1, 0xc4, 0x18, 0x39, + 0x1c, 0xcf, 0x13, 0x39, 0x1d, 0x16, 0x0e, 0x39, 0x8f, 0x16, 0x04, 0x39, + 0xec, 0x47, 0x0d, 0x39, 0x6c, 0x30, 0xbb, 0x38, 0x46, 0xe5, 0x00, 0x39, + 0xe9, 0x16, 0xf9, 0x38, 0x5c, 0x5d, 0xd1, 0x38, 0xb6, 0x54, 0x13, 0x39, + 0x2c, 0x83, 0xd3, 0x38, 0x24, 0xe1, 0xce, 0x38, 0x37, 0x2f, 0x1f, 0x39, + 0x0d, 0xcd, 0xf9, 0x38, 0x8d, 0x4a, 0x07, 0x39, 0x70, 0xc0, 0xf9, 0x38, + 0xa6, 0x21, 0xe0, 0x38, 0x19, 0xf1, 0xe5, 0x38, 0x87, 0x56, 0xf1, 0x38, + 0xee, 0x11, 0x16, 0x39, 0x44, 0xc2, 0x0a, 0x39, 0x9d, 0xdc, 0x0c, 0x39, + 0x25, 0xf1, 0xd6, 0x38, 0x2c, 0x2e, 0xec, 0x38, 0x6e, 0xee, 0xc6, 0x38, + 0x65, 0x77, 0x0f, 0x39, 0xf9, 0x7e, 0x1c, 0x39, 0x51, 0x7b, 0xec, 0x38, + 0x0f, 0xac, 0xfd, 0x38, 0x75, 0xef, 0xde, 0x38, 0x13, 0xa4, 0x15, 0x39, + 0xcd, 0x7a, 0x21, 0x39, 0x5c, 0x79, 0x0d, 0x39, 0x50, 0x85, 0xf6, 0x38, + 0x5e, 0xf5, 0x0f, 0x39, 0x87, 0x0a, 0xd5, 0x38, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x98, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x43, 0x2b, 0x15, 0x0a, + 0xef, 0x23, 0x2f, 0x08, 0xf1, 0x1e, 0xf0, 0x11, 0x20, 0x22, 0x2f, 0xfd, + 0x05, 0x25, 0xf8, 0xf8, 0xd0, 0x13, 0xf1, 0xda, 0xfa, 0xc7, 0x11, 0xe4, + 0xee, 0xff, 0xea, 0x1f, 0x08, 0x23, 0x35, 0xd1, 0x3d, 0x30, 0xe2, 0xf8, + 0x0f, 0xf6, 0xed, 0xe3, 0xdc, 0xf6, 0xe2, 0xbb, 0xe4, 0xe1, 0xb6, 0x38, + 0xc1, 0xeb, 0x40, 0xe3, 0x13, 0x04, 0xf2, 0xea, 0x04, 0xe6, 0xfa, 0xe5, + 0x18, 0x1e, 0x03, 0xd4, 0xf3, 0x0e, 0x14, 0x21, 0xe9, 0x24, 0xf0, 0xf7, + 0xfb, 0x05, 0x00, 0x0f, 0xf9, 0x23, 0xe3, 0x26, 0xda, 0xff, 0x13, 0xce, + 0x00, 0xe9, 0x1f, 0xf0, 0xf8, 0xe7, 0xeb, 0x0b, 0xdc, 0xf7, 0xff, 0x33, + 0x0f, 0xf8, 0xf1, 0x26, 0x12, 0x07, 0x1a, 0xde, 0xd6, 0x0b, 0x02, 0xfa, + 0xd3, 0x41, 0x27, 0x0a, 0x10, 0x18, 0x1e, 0x04, 0x35, 0x13, 0xeb, 0x15, + 0x06, 0xe3, 0x24, 0x1a, 0x2b, 0xc5, 0x0c, 0x35, 0xf2, 0xf4, 0x11, 0x13, + 0x0d, 0x01, 0xe1, 0xbf, 0x9e, 0x07, 0xdc, 0xdf, 0xde, 0x34, 0x39, 0x18, + 0xf6, 0x26, 0x00, 0xdc, 0x04, 0xf7, 0xf2, 0x23, 0x09, 0xe0, 0xf8, 0xce, + 0xf7, 0x30, 0xd5, 0x35, 0x23, 0x01, 0xe7, 0x28, 0x02, 0xf9, 0x19, 0xd3, + 0x11, 0xff, 0xe4, 0xff, 0xcd, 0x4b, 0x32, 0x35, 0x04, 0x7f, 0x13, 0xd8, + 0x48, 0x01, 0xf0, 0xfc, 0x18, 0x06, 0x18, 0x09, 0x3f, 0xfc, 0x19, 0xb2, + 0xf6, 0x3a, 0x0b, 0x1c, 0xf1, 0xf5, 0xee, 0xf0, 0xf9, 0x27, 0x09, 0xd0, + 0xf3, 0xe6, 0xee, 0x38, 0xa4, 0xef, 0xdc, 0xfd, 0xf2, 0x8d, 0xef, 0xe5, + 0xf9, 0xd0, 0xe1, 0x02, 0xe9, 0x31, 0x21, 0x9b, 0x60, 0x39, 0xd5, 0x1d, + 0xf8, 0xc2, 0xce, 0xd2, 0xc8, 0xb0, 0xdf, 0xc3, 0x11, 0xca, 0xa9, 0x51, + 0xc2, 0xcb, 0x1e, 0xe4, 0xf0, 0xe8, 0xd1, 0xc3, 0xe8, 0xc3, 0xd8, 0xd4, + 0x20, 0x1b, 0x29, 0xc0, 0xfc, 0x1a, 0x1c, 0x07, 0xfa, 0x17, 0xee, 0x06, + 0xf6, 0x0d, 0x2b, 0xf1, 0xef, 0x34, 0xdd, 0x36, 0xcd, 0x19, 0x0d, 0xb5, + 0xf1, 0xc3, 0xff, 0xe6, 0xe5, 0xdf, 0xcf, 0x16, 0xfd, 0x05, 0xe3, 0x0e, + 0x19, 0x3a, 0xe1, 0x24, 0x20, 0xe4, 0xe5, 0x23, 0x2f, 0x0a, 0x10, 0x02, + 0xeb, 0x07, 0x12, 0x1e, 0xc9, 0x2f, 0xfb, 0xe6, 0xeb, 0x02, 0x13, 0x02, + 0x07, 0xfc, 0x0c, 0x1a, 0xfa, 0xf2, 0xe8, 0x53, 0x12, 0x09, 0x07, 0x06, + 0x05, 0xb6, 0xfb, 0x0c, 0x13, 0xff, 0x49, 0xec, 0x05, 0x14, 0x57, 0xfe, + 0xd9, 0x29, 0xe6, 0xd6, 0x0e, 0x00, 0x04, 0x04, 0xf7, 0x61, 0x1e, 0x7f, + 0xe4, 0xef, 0x09, 0x28, 0xe8, 0x15, 0xef, 0x1f, 0xf9, 0xf1, 0xae, 0x0a, + 0x27, 0xfe, 0xed, 0x0c, 0x08, 0xe9, 0x1d, 0x04, 0xde, 0x2d, 0xd9, 0xf0, + 0xcc, 0xf2, 0x20, 0x15, 0xdc, 0x00, 0xfa, 0x03, 0xde, 0xf5, 0xdf, 0x11, + 0xf8, 0xec, 0xf3, 0xfb, 0xfe, 0xeb, 0xd1, 0x25, 0x23, 0x10, 0x1e, 0x0d, + 0xda, 0xbd, 0xf3, 0x3c, 0xea, 0xe9, 0xea, 0xf5, 0x2e, 0xef, 0x09, 0xc8, + 0x03, 0xe6, 0xd0, 0x2f, 0x11, 0x03, 0x0f, 0xfe, 0x14, 0x08, 0xce, 0x29, + 0x31, 0xeb, 0xe5, 0x0d, 0x08, 0x08, 0xfb, 0xfa, 0x03, 0x13, 0x62, 0xe8, + 0xe2, 0x19, 0xec, 0xe2, 0x36, 0xf8, 0x0a, 0xf7, 0xf2, 0x31, 0x11, 0x4c, + 0xf5, 0xef, 0xde, 0x10, 0xde, 0x01, 0xf8, 0xcb, 0xf7, 0xfa, 0xe1, 0x11, + 0xf8, 0xfc, 0x16, 0x06, 0xf3, 0xb9, 0xfc, 0x22, 0xfa, 0xf7, 0xf1, 0xf8, + 0x1b, 0x08, 0xfe, 0xe4, 0xfb, 0xf5, 0xcf, 0x13, 0xf1, 0xba, 0xcd, 0x33, + 0xda, 0xca, 0xa5, 0xe5, 0xfe, 0x9c, 0xe2, 0xfa, 0x2a, 0xe4, 0x13, 0xfd, + 0xdd, 0xbd, 0x27, 0xe4, 0x9e, 0x10, 0xd3, 0xf0, 0x04, 0xfa, 0xee, 0xce, + 0xf3, 0xb7, 0xc9, 0xe9, 0xc9, 0xee, 0xdd, 0x41, 0xdc, 0xd7, 0x25, 0x19, + 0x09, 0xe2, 0xbc, 0x30, 0xfc, 0x3e, 0x38, 0x17, 0x06, 0xd9, 0x45, 0xdd, + 0x1d, 0x16, 0xe9, 0xe3, 0xeb, 0xf4, 0xee, 0xad, 0xf1, 0x73, 0x15, 0x60, + 0xe5, 0xf4, 0x03, 0x20, 0xd0, 0xdf, 0xab, 0x14, 0xef, 0xd6, 0xbb, 0xe5, + 0x1b, 0x05, 0xde, 0xef, 0xf1, 0xc9, 0x09, 0xf0, 0xa2, 0x0e, 0xc4, 0x08, + 0xfe, 0xf1, 0x02, 0xf5, 0xfb, 0xbf, 0xd8, 0xf1, 0x04, 0x1d, 0xe6, 0xfa, + 0x0c, 0x12, 0xfc, 0x35, 0x1d, 0xf6, 0xdf, 0x1b, 0x59, 0x13, 0x06, 0x09, + 0x00, 0xff, 0x1c, 0x23, 0xc5, 0x2a, 0xee, 0xde, 0xee, 0xfd, 0x14, 0x0e, + 0xfb, 0x06, 0x0b, 0xfb, 0xf2, 0x25, 0xeb, 0x0a, 0xe7, 0xf4, 0xf8, 0x13, + 0x16, 0xec, 0x00, 0x21, 0x1b, 0x0e, 0x3d, 0xfa, 0xfd, 0x31, 0x2f, 0xf1, + 0xea, 0x22, 0xe0, 0xe9, 0x03, 0xed, 0x04, 0xf7, 0xdd, 0x54, 0x36, 0x7f, + 0xea, 0x19, 0xf5, 0x18, 0xe4, 0xf9, 0xd1, 0x10, 0xf1, 0x02, 0xbc, 0x12, + 0x1c, 0xf3, 0xff, 0x11, 0x0c, 0xda, 0x0a, 0xeb, 0xec, 0x09, 0xd7, 0x04, + 0xdf, 0xcb, 0x13, 0x09, 0x07, 0x01, 0xf9, 0xf9, 0x0a, 0x16, 0xdd, 0x3f, + 0xd4, 0xe4, 0xf4, 0x07, 0xfa, 0xf3, 0xc4, 0x2b, 0x63, 0xff, 0x39, 0x1b, + 0x13, 0xc1, 0xe5, 0x43, 0xed, 0x0d, 0xf4, 0xf2, 0xdf, 0x02, 0x43, 0xc3, + 0x03, 0xab, 0xde, 0x1a, 0x2c, 0x04, 0x31, 0x20, 0xff, 0x09, 0xeb, 0x23, + 0x19, 0x00, 0xc9, 0x25, 0x32, 0xf2, 0x13, 0x2c, 0x27, 0x01, 0x5e, 0xd3, + 0xef, 0x56, 0x04, 0xea, 0xf7, 0xf6, 0x28, 0xf7, 0xfa, 0x03, 0x03, 0x2e, + 0xfc, 0x14, 0xf5, 0x33, 0xc2, 0xf0, 0xfb, 0xf9, 0x01, 0xf1, 0xf3, 0x0b, + 0x2a, 0xfe, 0x0c, 0x2d, 0x09, 0xc4, 0xf4, 0x15, 0x17, 0x0a, 0xed, 0x10, + 0xf0, 0x02, 0x39, 0xbd, 0xec, 0xcd, 0xdf, 0x05, 0x0c, 0xf3, 0xe4, 0x07, + 0xdc, 0xdd, 0x8b, 0x03, 0xdf, 0xa2, 0xf0, 0xea, 0x37, 0xe5, 0x00, 0x0a, + 0xcf, 0xdc, 0x11, 0x09, 0x9c, 0x17, 0xfc, 0xf0, 0xf1, 0xe2, 0xef, 0x05, + 0xc9, 0x9a, 0xd1, 0x05, 0xd4, 0x0b, 0x13, 0x21, 0xea, 0xe2, 0x22, 0xf6, + 0x06, 0x13, 0xc9, 0x21, 0xf4, 0x22, 0x35, 0x00, 0x03, 0x1b, 0x23, 0xd6, + 0x19, 0xfc, 0x01, 0xda, 0xfe, 0x04, 0xfe, 0xd5, 0xdf, 0x41, 0x26, 0x64, + 0xe3, 0x17, 0x06, 0x11, 0xc6, 0xd9, 0xc1, 0x11, 0xdb, 0xd7, 0xb0, 0xf6, + 0x24, 0x05, 0xf2, 0x02, 0x00, 0xd7, 0x0b, 0xf5, 0xc9, 0x05, 0xc8, 0x15, + 0xcb, 0xec, 0xef, 0x05, 0x05, 0xd7, 0xee, 0x09, 0x33, 0xbd, 0xd5, 0x09, + 0xfd, 0xee, 0x52, 0xc4, 0x0b, 0x09, 0x00, 0x19, 0xd3, 0xad, 0x02, 0xdd, + 0xdc, 0xfe, 0x0e, 0xd8, 0x0a, 0xfd, 0x1e, 0x06, 0xf6, 0x2f, 0xd9, 0x0b, + 0x11, 0x2c, 0x05, 0xe5, 0x12, 0xcb, 0xe4, 0x0b, 0xd2, 0xdd, 0xff, 0xe3, + 0xd4, 0xf4, 0x4b, 0x16, 0xf5, 0xd8, 0x23, 0x0b, 0x56, 0x0c, 0xfc, 0xf9, + 0x36, 0x0a, 0x1d, 0x03, 0xee, 0xee, 0xff, 0xf4, 0xfe, 0x14, 0xed, 0x0b, + 0x17, 0xc6, 0xe6, 0x08, 0xef, 0xe7, 0x20, 0xe5, 0x05, 0x02, 0x24, 0x13, + 0xc2, 0xd1, 0x19, 0x1d, 0x05, 0x04, 0x10, 0xef, 0x2d, 0x00, 0x22, 0x04, + 0x03, 0x0c, 0x14, 0x21, 0x19, 0x1e, 0xf8, 0xe7, 0x16, 0xe9, 0x0c, 0xa2, + 0x10, 0x05, 0x20, 0xc9, 0xf1, 0x0e, 0xfd, 0xe6, 0x12, 0x0e, 0xe6, 0xfd, + 0xe6, 0x19, 0xc0, 0xba, 0x0b, 0xb1, 0x23, 0x0a, 0xdb, 0x1e, 0xbe, 0xe8, + 0x1b, 0x2e, 0x20, 0xee, 0xf6, 0x17, 0x25, 0xca, 0x29, 0x2a, 0x16, 0x09, + 0xc0, 0x0d, 0x16, 0xfe, 0x00, 0xf3, 0xfc, 0x08, 0x26, 0xed, 0x8e, 0x18, + 0x16, 0xd6, 0x2b, 0x02, 0xe3, 0x41, 0xb9, 0xdf, 0xe3, 0x12, 0xfe, 0xf6, + 0xe4, 0x07, 0x3c, 0xe3, 0x0a, 0xf6, 0x24, 0xd9, 0xf2, 0x31, 0x17, 0x11, + 0xe0, 0x2f, 0xb1, 0xf9, 0x26, 0xd4, 0xd5, 0x0b, 0x2e, 0xc3, 0x1a, 0x30, + 0xb7, 0x2f, 0xc0, 0xeb, 0x10, 0x24, 0x02, 0xd6, 0xff, 0x03, 0xef, 0xc4, + 0xed, 0xdf, 0x1d, 0xc1, 0xf3, 0x15, 0x1a, 0xf4, 0x1a, 0xe8, 0xf8, 0xde, + 0xcf, 0x0e, 0xf4, 0xe7, 0x40, 0x00, 0x16, 0x30, 0xe5, 0x10, 0xcf, 0xff, + 0x03, 0xf8, 0xd1, 0xfb, 0xf4, 0xd7, 0xe9, 0x0f, 0x02, 0xdb, 0xdd, 0xdb, + 0xe0, 0xef, 0x3a, 0xe5, 0xed, 0xc9, 0x24, 0xde, 0x22, 0x0d, 0xff, 0xf6, + 0x42, 0xe2, 0x0a, 0x30, 0xe5, 0x0a, 0xe6, 0xf1, 0x00, 0xd5, 0xe2, 0x1c, + 0xfb, 0xf8, 0xca, 0x08, 0xfa, 0xdc, 0xec, 0xeb, 0xeb, 0x42, 0x37, 0x03, + 0xd3, 0xd7, 0xe6, 0xe8, 0xe4, 0xdb, 0x1a, 0xf5, 0x66, 0xf8, 0x1c, 0x7f, + 0xfe, 0x0d, 0xde, 0xdd, 0x24, 0x08, 0x07, 0xfe, 0x17, 0xd4, 0x0d, 0x02, + 0xd4, 0xde, 0x13, 0xe0, 0xef, 0xfb, 0xfa, 0x0d, 0xf5, 0x0a, 0x06, 0x08, + 0x13, 0x0e, 0x04, 0xce, 0xf7, 0xec, 0xeb, 0x04, 0xe9, 0xd8, 0x0c, 0x0f, + 0x1f, 0x10, 0xef, 0xed, 0xf4, 0xed, 0xed, 0xfc, 0x05, 0xeb, 0x18, 0xef, + 0x26, 0xe9, 0x08, 0x06, 0xef, 0x2c, 0x33, 0xf3, 0x01, 0xfd, 0x24, 0xec, + 0xf2, 0xfa, 0x1c, 0xf4, 0xf4, 0xbb, 0xf8, 0xe2, 0xe5, 0x59, 0x2f, 0x1b, + 0x08, 0xec, 0x0c, 0x06, 0xec, 0xc7, 0xe5, 0xeb, 0xf9, 0xed, 0xe8, 0xfc, + 0xfe, 0xe0, 0xfb, 0x1e, 0x16, 0x1d, 0x0e, 0xdb, 0x01, 0xf1, 0xf4, 0x16, + 0xda, 0xdb, 0x10, 0x39, 0x4c, 0x08, 0xff, 0xdf, 0x47, 0xfe, 0xfc, 0xd5, + 0xc6, 0x12, 0x11, 0xe3, 0xd2, 0xe7, 0xed, 0x14, 0xe4, 0x15, 0x07, 0xf0, + 0xec, 0xce, 0xd3, 0x19, 0x13, 0xe8, 0xf4, 0xfd, 0x0b, 0xfc, 0xe6, 0xad, + 0x34, 0x2d, 0xf2, 0xdd, 0xd4, 0x16, 0x30, 0xf3, 0x25, 0x4a, 0x07, 0x22, + 0x3f, 0x01, 0x1b, 0x25, 0xda, 0x12, 0xec, 0x1a, 0x1b, 0xb8, 0x02, 0xee, + 0xef, 0x13, 0xf4, 0xf5, 0xed, 0xdf, 0x0a, 0xdb, 0x0d, 0x53, 0x2b, 0x04, + 0x37, 0xfb, 0x02, 0xdc, 0xdd, 0x00, 0x01, 0xda, 0xf8, 0x0a, 0xef, 0x1a, + 0xeb, 0x01, 0xea, 0xfe, 0xe9, 0xdb, 0xe5, 0x13, 0x11, 0xc7, 0x04, 0x1c, + 0x08, 0x13, 0xee, 0xb6, 0x30, 0x3d, 0x05, 0xf0, 0x25, 0xe9, 0x09, 0x0e, + 0xdb, 0xd6, 0x14, 0xcc, 0xe8, 0xd1, 0xff, 0x0a, 0xef, 0x1b, 0xec, 0xf4, + 0x1a, 0x06, 0x1f, 0xdd, 0xf6, 0xfa, 0xfb, 0x17, 0xfa, 0xc5, 0xd5, 0x0c, + 0x5f, 0x10, 0xf8, 0xfb, 0xe6, 0xeb, 0xfa, 0x0b, 0x06, 0x0a, 0x19, 0xf4, + 0x03, 0xf6, 0xe9, 0x10, 0xee, 0x2d, 0x33, 0xf1, 0xfa, 0xf6, 0x1d, 0xf1, + 0x0b, 0xee, 0x33, 0x01, 0xf2, 0xd2, 0xf4, 0xe9, 0xf2, 0x54, 0x33, 0x26, + 0xfc, 0xd1, 0xe0, 0x1b, 0xe7, 0xf5, 0x14, 0xe5, 0x24, 0xe4, 0x00, 0xf8, + 0xfe, 0xea, 0xe2, 0x02, 0xf4, 0xe7, 0x17, 0xce, 0x34, 0xe7, 0xf7, 0x7c, + 0xf2, 0xea, 0xf5, 0xf9, 0x7f, 0x37, 0x05, 0xca, 0x02, 0x3f, 0x50, 0xb4, + 0xd8, 0xde, 0xf6, 0xf3, 0xcb, 0x16, 0xf1, 0xef, 0x24, 0xf9, 0xe3, 0x13, + 0x18, 0x04, 0xcd, 0xb1, 0x12, 0xf2, 0xd8, 0xfb, 0xf7, 0x8f, 0x10, 0x07, + 0x24, 0xdd, 0x0a, 0xfb, 0x2e, 0x5c, 0x26, 0xd1, 0xab, 0x0b, 0xc6, 0x00, + 0xf4, 0xf4, 0xf4, 0x02, 0x0f, 0x7f, 0xee, 0x1a, 0x0a, 0xc9, 0x09, 0xd1, + 0xce, 0xea, 0xdb, 0x0c, 0x0f, 0x07, 0x1b, 0x07, 0x09, 0xce, 0x42, 0xfd, + 0x06, 0x4b, 0x3b, 0xd0, 0xed, 0xc7, 0x15, 0xfe, 0xf0, 0x11, 0xd6, 0x08, + 0x23, 0x06, 0xeb, 0x1a, 0x0c, 0xf7, 0xd5, 0xd3, 0x10, 0x00, 0xd5, 0x0c, + 0x05, 0xad, 0x16, 0x23, 0x1c, 0xf6, 0x05, 0xff, 0xf1, 0xfc, 0x16, 0x35, + 0xe3, 0xe7, 0x15, 0x1c, 0xe2, 0xfa, 0x3b, 0xd4, 0x56, 0x05, 0xfc, 0x15, + 0x0c, 0xfc, 0xfe, 0xc9, 0x10, 0x39, 0x02, 0x02, 0xef, 0x07, 0x07, 0xe8, + 0x1f, 0xfd, 0x15, 0xae, 0xe5, 0xec, 0x05, 0x4c, 0xcf, 0xce, 0x32, 0x11, + 0xcc, 0x34, 0xd8, 0x05, 0x23, 0x18, 0xe4, 0x21, 0xf5, 0xdc, 0x15, 0xac, + 0x29, 0xfb, 0x1b, 0xf5, 0xaa, 0x1d, 0xe8, 0x0e, 0x0d, 0x17, 0x44, 0xfb, + 0x13, 0x20, 0xed, 0x3d, 0xea, 0x03, 0xf9, 0x04, 0xea, 0x05, 0x1f, 0xbb, + 0x2e, 0x11, 0xa5, 0xe8, 0xed, 0xe8, 0x00, 0xe4, 0x0a, 0x36, 0xfe, 0x04, + 0x48, 0x02, 0x28, 0xb5, 0x16, 0x1a, 0x33, 0x9c, 0xf2, 0x48, 0x5b, 0xda, + 0xeb, 0xfe, 0x0d, 0xf6, 0xc8, 0x1e, 0x0d, 0x11, 0x0b, 0x0c, 0xec, 0xfd, + 0x02, 0x10, 0xcb, 0xdf, 0x29, 0xe7, 0xe8, 0x0c, 0xe3, 0xe1, 0xf5, 0xef, + 0x0e, 0x02, 0x08, 0xf8, 0xea, 0x7f, 0x5e, 0xec, 0xcc, 0x14, 0xec, 0xf5, + 0xee, 0x16, 0x1e, 0xe9, 0x23, 0x46, 0xb5, 0x1a, 0xf0, 0xec, 0x15, 0xe7, + 0xf8, 0xe1, 0xe5, 0x1d, 0xd8, 0x10, 0xfd, 0xef, 0x1f, 0xe4, 0x40, 0x06, + 0xe3, 0xfd, 0x2f, 0xd3, 0xeb, 0xdf, 0x10, 0xd8, 0x12, 0x05, 0xee, 0xfa, + 0x39, 0xf3, 0xe2, 0xee, 0xfc, 0xfe, 0xb9, 0xe4, 0x57, 0x05, 0xf5, 0x6d, + 0xf7, 0xc2, 0xe2, 0xcf, 0x42, 0xde, 0xe7, 0x00, 0xf6, 0xda, 0xf4, 0x0b, + 0xed, 0xdc, 0xca, 0x0b, 0x02, 0x0a, 0x05, 0xd1, 0xe8, 0xf1, 0x0e, 0x13, + 0x4d, 0xe6, 0x04, 0xdc, 0xdf, 0xdc, 0xd0, 0x00, 0x1a, 0xd1, 0x39, 0x2a, + 0x9d, 0xcd, 0x1a, 0xe4, 0x57, 0xf4, 0xd5, 0x30, 0xe0, 0x0d, 0x25, 0xe8, + 0x0f, 0x1c, 0x26, 0xfb, 0xfd, 0xcf, 0x32, 0x6b, 0x33, 0xdc, 0xc9, 0xe2, + 0xf3, 0x1c, 0xd7, 0xfe, 0x5f, 0xf3, 0x7f, 0x2c, 0xe5, 0xe7, 0xe6, 0xea, + 0x05, 0x09, 0xf5, 0x29, 0xc5, 0xda, 0xcd, 0xff, 0xed, 0xbb, 0x20, 0xf2, + 0xee, 0xe7, 0xf7, 0x38, 0x4d, 0xf7, 0xe9, 0xe8, 0x05, 0xf3, 0xc7, 0x07, + 0x47, 0xae, 0x16, 0xea, 0xda, 0xde, 0x0c, 0xf0, 0xb1, 0x05, 0xed, 0x0c, + 0x0a, 0xdb, 0x0f, 0xd7, 0xfd, 0xf6, 0x01, 0xf5, 0xf7, 0xf1, 0xd7, 0x10, + 0x3b, 0x0f, 0x19, 0xf2, 0xea, 0x67, 0xb8, 0xea, 0x21, 0xb7, 0xe9, 0x32, + 0xd3, 0xfd, 0x00, 0xe7, 0xf0, 0x1d, 0xf4, 0x46, 0xf1, 0xde, 0xee, 0xc7, + 0xe4, 0xff, 0xee, 0xf5, 0x20, 0xca, 0xf3, 0x08, 0x1d, 0x03, 0xa0, 0xde, + 0xe9, 0x22, 0xf7, 0xfa, 0xbb, 0xce, 0xe9, 0x11, 0xd4, 0xd6, 0xb0, 0xd5, + 0xe0, 0xcb, 0xf0, 0x32, 0x1a, 0xe9, 0x15, 0xe3, 0xe6, 0x3a, 0x2a, 0xe2, + 0xd9, 0xfe, 0xcf, 0x16, 0x31, 0x11, 0x0e, 0xcd, 0xf9, 0x3b, 0xc7, 0xe4, + 0x37, 0xf5, 0x11, 0x3d, 0xbe, 0x1b, 0x16, 0xd1, 0x0a, 0x05, 0x35, 0x39, + 0xfc, 0x2c, 0x1d, 0x0f, 0xf5, 0xf4, 0x0e, 0x11, 0xd8, 0x0f, 0x14, 0x26, + 0x41, 0xf5, 0xfb, 0xf1, 0x17, 0xe2, 0xf6, 0xe1, 0x13, 0xe9, 0x53, 0x0e, + 0xe4, 0x13, 0x0c, 0xe7, 0x24, 0xe5, 0x09, 0x6d, 0xe3, 0x46, 0x40, 0xed, + 0x21, 0x3f, 0x23, 0xf2, 0x0f, 0x06, 0x45, 0x5f, 0x28, 0xd9, 0xd6, 0xf1, + 0x19, 0x22, 0xe0, 0xf8, 0x72, 0x3a, 0x62, 0xfd, 0x0f, 0xff, 0xdf, 0xd9, + 0x17, 0x04, 0x16, 0x25, 0xdb, 0x12, 0x14, 0x0f, 0xfa, 0x06, 0x49, 0x19, + 0xd8, 0xff, 0x1e, 0x38, 0x3f, 0x05, 0xf9, 0xdf, 0x51, 0xf7, 0xdb, 0x27, + 0x33, 0xdb, 0x37, 0x0f, 0xf9, 0x04, 0x00, 0xe1, 0xed, 0xf8, 0x16, 0xd1, + 0x10, 0x1f, 0x15, 0xe9, 0x03, 0x14, 0xbd, 0xfb, 0xf6, 0x05, 0x11, 0xb3, + 0xd6, 0xfe, 0x0f, 0x05, 0xf3, 0xeb, 0x23, 0xff, 0xa1, 0x17, 0xad, 0x30, + 0x0f, 0xf2, 0xe2, 0x28, 0xee, 0xf9, 0x1e, 0xd5, 0x25, 0xf6, 0xe2, 0x27, + 0xaf, 0xd4, 0xe0, 0xee, 0x0a, 0xda, 0xe6, 0xaa, 0xfa, 0x51, 0xd6, 0x21, + 0xf5, 0x0c, 0xfb, 0x02, 0x8d, 0xe5, 0x93, 0x42, 0xed, 0xf7, 0x07, 0xe8, + 0x1d, 0x09, 0x06, 0xe1, 0x04, 0x11, 0x0d, 0x09, 0x2f, 0xf5, 0xe5, 0x07, + 0x02, 0x08, 0xe6, 0xa2, 0xcc, 0x03, 0x1c, 0xfc, 0xf0, 0xf2, 0x1f, 0xfc, + 0xb0, 0x0b, 0x98, 0xeb, 0x19, 0x0a, 0x0d, 0x28, 0x3e, 0xe8, 0x1c, 0xf1, + 0x1a, 0x0e, 0xf0, 0xfd, 0x43, 0xc9, 0xc9, 0x03, 0xdb, 0x0d, 0x2e, 0x0a, + 0xea, 0x01, 0x21, 0x1e, 0xd8, 0xcd, 0x0e, 0x02, 0x9c, 0xe6, 0xe5, 0xea, + 0x2c, 0xf5, 0xf1, 0x13, 0x23, 0xe1, 0x14, 0xd4, 0x0c, 0x0e, 0x05, 0x0e, + 0x26, 0xe5, 0xdf, 0xf0, 0xcf, 0x3f, 0x0f, 0x01, 0xfd, 0x22, 0xf8, 0x28, + 0xfb, 0xdd, 0xf2, 0xf3, 0x29, 0xeb, 0x15, 0x00, 0x16, 0x04, 0x2f, 0xe4, + 0x58, 0x16, 0x17, 0x0a, 0x14, 0x1b, 0xfe, 0xfb, 0x2c, 0xea, 0xd1, 0x25, + 0xe7, 0xfc, 0x5c, 0xed, 0xd9, 0x0e, 0x1a, 0x11, 0xe5, 0xd8, 0x11, 0x11, + 0xb7, 0xfc, 0xe1, 0xef, 0x2c, 0x09, 0x04, 0x0b, 0x16, 0x04, 0xed, 0xb2, + 0x34, 0x10, 0x2a, 0x01, 0x17, 0x05, 0xb6, 0x02, 0x11, 0x17, 0x20, 0xdc, + 0xf8, 0x1c, 0x01, 0x15, 0xa6, 0xed, 0x43, 0xc8, 0xe3, 0xf3, 0xd8, 0x07, + 0x1a, 0x22, 0x03, 0x31, 0x08, 0xef, 0x0d, 0xa3, 0x54, 0xf4, 0xc5, 0x06, + 0xe3, 0x94, 0xcf, 0xfb, 0x0a, 0x81, 0xf6, 0xd0, 0xff, 0x38, 0xbf, 0x29, + 0xbc, 0xed, 0x2e, 0xeb, 0xc4, 0xc2, 0xbd, 0x2a, 0x02, 0xf5, 0xeb, 0xfb, + 0x23, 0x19, 0xe0, 0xbc, 0x25, 0x1e, 0x1e, 0xfa, 0x21, 0xdf, 0xed, 0x15, + 0x05, 0xce, 0x11, 0xe6, 0xf5, 0x0a, 0xf8, 0x14, 0xd4, 0xf7, 0x2a, 0xd6, + 0xfc, 0xfc, 0xf3, 0x0c, 0x11, 0x27, 0xfe, 0x10, 0x2e, 0x03, 0x35, 0xe1, + 0xce, 0xf8, 0x27, 0xdc, 0xc3, 0x22, 0xeb, 0x35, 0xec, 0xee, 0x0e, 0x13, + 0x1c, 0x33, 0xd8, 0xdc, 0x1c, 0x2c, 0x04, 0xf8, 0xe2, 0xc7, 0xf8, 0x1a, + 0xfb, 0x00, 0xd5, 0xdb, 0x2c, 0x0a, 0x64, 0xdd, 0x53, 0x3c, 0xd5, 0xe2, + 0x16, 0xe2, 0xec, 0x1b, 0xfc, 0x16, 0x4c, 0xfe, 0x0e, 0xdb, 0xea, 0x20, + 0xd5, 0x1f, 0x43, 0xee, 0xf4, 0xc2, 0x0b, 0xe6, 0x02, 0xe8, 0xe9, 0xd3, + 0x2c, 0x18, 0x2e, 0xe8, 0xd4, 0xf1, 0x17, 0xfb, 0xc9, 0x15, 0xef, 0x25, + 0xe2, 0xf5, 0x28, 0x0d, 0x1d, 0x23, 0xe1, 0x01, 0x14, 0x05, 0xfc, 0xe3, + 0xd0, 0xec, 0x10, 0xfa, 0x0a, 0x04, 0xf6, 0x11, 0x07, 0xf5, 0xe6, 0xdc, + 0x04, 0x0f, 0xed, 0x0a, 0xc9, 0xee, 0x16, 0xed, 0xea, 0x17, 0xb7, 0xf2, + 0xc2, 0x2d, 0xe9, 0xdf, 0x01, 0x3b, 0xea, 0xf7, 0x16, 0x04, 0xc8, 0xd0, + 0x0b, 0x40, 0x19, 0xf6, 0xc0, 0xb2, 0x09, 0xde, 0xe6, 0x28, 0x29, 0xde, + 0xfd, 0xf9, 0xfd, 0x04, 0x1f, 0x1a, 0x15, 0x9e, 0xd2, 0xe2, 0xe9, 0x05, + 0x06, 0x00, 0x03, 0xf9, 0x97, 0xeb, 0x9c, 0x0a, 0xf5, 0x3d, 0xf9, 0xd7, + 0x1a, 0xf3, 0xdf, 0xee, 0xfe, 0x22, 0xff, 0xe3, 0xcf, 0xed, 0x28, 0xe8, + 0xd9, 0xfb, 0xf3, 0x00, 0xe5, 0x19, 0xff, 0xf7, 0xfd, 0x39, 0xd1, 0xef, + 0x2d, 0xf3, 0xd8, 0x8b, 0x06, 0x54, 0x21, 0x00, 0x40, 0xfa, 0x5e, 0xb7, + 0xe7, 0x01, 0x41, 0xe5, 0xe4, 0x28, 0xfb, 0x19, 0xe9, 0xfc, 0x15, 0x12, + 0x09, 0x56, 0xe0, 0xe4, 0x19, 0x09, 0x15, 0xed, 0xf3, 0xe4, 0xed, 0x29, + 0x18, 0x09, 0xe7, 0x0c, 0x01, 0x2f, 0x7f, 0xd8, 0x3e, 0x43, 0xe9, 0xfb, + 0x2e, 0xeb, 0x02, 0xba, 0xc9, 0x20, 0x00, 0xdc, 0xfc, 0xeb, 0xe2, 0x2a, + 0xbd, 0xce, 0x42, 0xed, 0xd9, 0xec, 0xed, 0x0b, 0xe8, 0xdf, 0x06, 0xb5, + 0x20, 0xf7, 0x39, 0xcf, 0xea, 0xd8, 0x31, 0xee, 0xf2, 0x31, 0x02, 0x21, + 0xef, 0xee, 0x1d, 0x0f, 0x22, 0x2a, 0xdd, 0xdf, 0x1c, 0xf0, 0xf7, 0x00, + 0x04, 0xdd, 0xfb, 0x0b, 0x2c, 0x25, 0x04, 0x00, 0x02, 0x65, 0x04, 0xe6, + 0xf2, 0xfd, 0xf3, 0xfe, 0x06, 0x02, 0xe3, 0x0c, 0x3c, 0xd3, 0x00, 0x18, + 0x03, 0xfe, 0xe8, 0xe6, 0xdb, 0x22, 0xf7, 0xed, 0xf5, 0xfc, 0x13, 0x1e, + 0xf0, 0xfa, 0x1d, 0x22, 0x15, 0x5c, 0x0e, 0xdf, 0xc3, 0xb9, 0xd0, 0x15, + 0xf5, 0xcc, 0x01, 0x1b, 0x2f, 0x07, 0x11, 0x0a, 0xe2, 0x2a, 0x0d, 0xa8, + 0xdb, 0xda, 0xd6, 0xef, 0x0c, 0xed, 0x1e, 0x22, 0xd8, 0x13, 0x41, 0x50, + 0xfa, 0x2d, 0x0d, 0xed, 0xeb, 0xb5, 0xb4, 0xf5, 0xfd, 0xe2, 0xb4, 0x07, + 0x1c, 0xf7, 0xfa, 0x21, 0x03, 0xd9, 0x06, 0xed, 0xdd, 0x0b, 0xc8, 0x05, + 0xe5, 0xc6, 0x1f, 0x12, 0xec, 0xdc, 0x0d, 0xfe, 0x13, 0x2e, 0xea, 0x42, + 0xd3, 0xd7, 0x01, 0x0a, 0x04, 0x06, 0xe9, 0xf2, 0x67, 0xeb, 0x4f, 0x30, + 0x0a, 0xdc, 0xed, 0x0e, 0xf7, 0x20, 0x03, 0xf9, 0xd8, 0x23, 0x52, 0xc8, + 0xf3, 0xab, 0xe1, 0x0f, 0x0b, 0x03, 0x20, 0x52, 0xe6, 0xf3, 0x03, 0x34, + 0x01, 0x1f, 0xe2, 0xe3, 0x40, 0xf6, 0x23, 0x3b, 0x2a, 0xdc, 0x47, 0xc2, + 0x09, 0x35, 0x17, 0xd6, 0xd0, 0x17, 0x3c, 0xdd, 0xf1, 0x10, 0x12, 0x14, + 0xf8, 0x22, 0xfc, 0x37, 0xd5, 0xea, 0x24, 0xf0, 0x1a, 0x17, 0xe9, 0xf4, + 0x3e, 0xfd, 0xf9, 0x24, 0x0d, 0xc2, 0xee, 0x0a, 0x16, 0xfd, 0x25, 0x0e, + 0xe6, 0x12, 0x31, 0xc9, 0xfd, 0xcf, 0xe2, 0xf4, 0x02, 0x44, 0x17, 0x03, + 0xe7, 0xe2, 0x81, 0x06, 0xe8, 0x9d, 0xe6, 0xf3, 0x33, 0xf7, 0xff, 0x04, + 0xf5, 0xf8, 0x15, 0x08, 0xac, 0x14, 0xee, 0xf8, 0x05, 0xe1, 0x0c, 0x1d, + 0xee, 0xab, 0xd1, 0x0a, 0xef, 0x31, 0x0f, 0x07, 0xcf, 0xde, 0x0b, 0x07, + 0xf3, 0x27, 0xa5, 0x34, 0xfb, 0x1c, 0x02, 0xf5, 0xf7, 0x42, 0x17, 0xde, + 0x00, 0xd7, 0x15, 0xff, 0xd6, 0xf8, 0xf0, 0x3b, 0xf8, 0x47, 0x2b, 0x40, + 0xca, 0x2f, 0x06, 0x03, 0xf0, 0xe3, 0xd9, 0x0b, 0x09, 0xda, 0xa6, 0xfc, + 0x31, 0x06, 0xe7, 0x0e, 0x00, 0xd0, 0x06, 0xfe, 0xd8, 0x0f, 0xea, 0x17, + 0xc9, 0xe4, 0xd9, 0x0c, 0x18, 0xeb, 0x04, 0x0b, 0x0c, 0xf7, 0x17, 0x12, + 0xd8, 0x37, 0x2b, 0x14, 0xf0, 0x0d, 0x08, 0x2e, 0xd0, 0x25, 0x03, 0x0e, + 0x36, 0x27, 0x06, 0x0d, 0x21, 0x0a, 0xd3, 0xe9, 0x12, 0xb9, 0x05, 0x25, + 0x02, 0x30, 0x10, 0xb9, 0x50, 0xe9, 0xff, 0x38, 0xfc, 0x65, 0x10, 0xed, + 0xfb, 0xe9, 0xde, 0x10, 0x07, 0xfe, 0x4b, 0x11, 0x1f, 0xdf, 0x31, 0xed, + 0xd4, 0x1e, 0xdf, 0xeb, 0x1d, 0xa1, 0x1d, 0x27, 0x00, 0xff, 0xdf, 0xfd, + 0x00, 0xd1, 0x00, 0xfc, 0xec, 0x27, 0x10, 0xee, 0xf0, 0xf5, 0x03, 0x29, + 0xe9, 0x10, 0x0a, 0x02, 0x38, 0x10, 0x08, 0xd2, 0x23, 0xeb, 0xbc, 0xfc, + 0x06, 0xa3, 0xf2, 0x0a, 0x11, 0x44, 0x0e, 0xe4, 0xec, 0xda, 0xe1, 0xed, + 0xe0, 0x02, 0xe0, 0xe1, 0xf1, 0xe4, 0xc6, 0x3d, 0xe6, 0xec, 0x07, 0xb8, + 0xd0, 0x30, 0x2a, 0x14, 0xef, 0x01, 0x9e, 0xef, 0xd7, 0xc2, 0x93, 0x59, + 0xee, 0x68, 0x3b, 0x2a, 0xbe, 0xef, 0xfc, 0xfc, 0x11, 0x53, 0xf0, 0xca, + 0xf2, 0xa5, 0xc8, 0x69, 0x01, 0xc3, 0x3f, 0xaf, 0xb5, 0x13, 0xf4, 0xc2, + 0xf2, 0x5a, 0x07, 0xe9, 0xca, 0xd3, 0xa4, 0xe8, 0xe4, 0x2e, 0xde, 0x1d, + 0x22, 0xc3, 0xeb, 0xd9, 0xd6, 0x04, 0xa8, 0xc2, 0xec, 0xb5, 0xd4, 0x3e, + 0xe3, 0xef, 0xed, 0xcc, 0xde, 0x2e, 0x10, 0x09, 0x0e, 0x0c, 0x94, 0x01, + 0xd5, 0x92, 0xaf, 0x2e, 0xf6, 0x4c, 0x52, 0x03, 0x1d, 0xaf, 0xe5, 0xe7, + 0xcc, 0x1c, 0x1f, 0x3d, 0xf6, 0x11, 0xfb, 0x21, 0xff, 0x2d, 0x10, 0xf0, + 0xf5, 0xec, 0x0f, 0x09, 0x2c, 0xfd, 0xaf, 0x00, 0xec, 0xa4, 0xea, 0x37, + 0x0d, 0x1c, 0x0e, 0xcc, 0x02, 0x81, 0xf0, 0x00, 0xfe, 0x5c, 0x17, 0x0c, + 0x24, 0xf0, 0xf0, 0xaa, 0xdd, 0x45, 0x54, 0xf4, 0xc7, 0x9a, 0x0e, 0xee, + 0xe0, 0x11, 0xbe, 0x1c, 0xdc, 0xcb, 0x19, 0xd4, 0xfd, 0xf5, 0xfa, 0xf8, + 0x16, 0x83, 0xb9, 0xd2, 0xb7, 0x21, 0x13, 0x3d, 0xf0, 0x12, 0xfa, 0x22, + 0xfa, 0x2b, 0xf7, 0xde, 0xde, 0xc1, 0xf8, 0x03, 0x46, 0xfd, 0x8f, 0x25, + 0xed, 0x94, 0xec, 0xe3, 0x2a, 0x5c, 0x1f, 0xe2, 0x2b, 0xdd, 0x18, 0xfd, + 0x18, 0xee, 0x02, 0xd7, 0xfe, 0xd3, 0x26, 0xf5, 0xef, 0x58, 0xf5, 0x17, + 0x04, 0x23, 0xf2, 0xe0, 0x0d, 0xf1, 0x01, 0xf8, 0x3b, 0x08, 0x00, 0x28, + 0x0a, 0xfe, 0xfa, 0xe1, 0xe1, 0xf0, 0xd7, 0xe9, 0x31, 0x0d, 0x17, 0x11, + 0x3d, 0x1b, 0xeb, 0xe8, 0xe2, 0x4e, 0x9e, 0x13, 0xce, 0xe1, 0x19, 0x0a, + 0xc1, 0x0b, 0x20, 0xdd, 0x20, 0xca, 0x20, 0x18, 0xe4, 0x1e, 0x4c, 0x0b, + 0xfb, 0xd1, 0x04, 0x07, 0x15, 0xe5, 0xe7, 0xc9, 0x22, 0xdc, 0x39, 0xfb, + 0x0f, 0x0f, 0xf9, 0x10, 0x13, 0x1c, 0xe3, 0xe8, 0xed, 0xec, 0x0d, 0xf5, + 0x28, 0xf0, 0x1c, 0x11, 0x17, 0xe8, 0xcb, 0xcf, 0x2e, 0xe7, 0x18, 0xea, + 0xfb, 0x10, 0xf4, 0x09, 0x03, 0xfb, 0x08, 0xd9, 0xdd, 0x2e, 0xdb, 0xe9, + 0xd2, 0x24, 0x14, 0xd9, 0xfb, 0xe3, 0xe8, 0xf1, 0x7f, 0xe8, 0x20, 0xf6, + 0x11, 0xfd, 0xfc, 0xe9, 0xc0, 0x14, 0xd8, 0xd1, 0x10, 0xd9, 0xfd, 0xf8, + 0x1f, 0xf5, 0x4d, 0xe0, 0xf2, 0x1a, 0xe6, 0xe7, 0xe7, 0xef, 0x53, 0x0b, + 0xc0, 0x16, 0xf3, 0xde, 0xf3, 0xc3, 0x0c, 0xe9, 0x13, 0x0b, 0x54, 0x1a, + 0x31, 0xcd, 0x05, 0xf0, 0x12, 0x05, 0xf2, 0xdb, 0x12, 0xef, 0xed, 0xe2, + 0xfe, 0x04, 0xf8, 0xfe, 0xca, 0x22, 0xd9, 0xdf, 0xfc, 0xca, 0xe1, 0x0e, + 0x7c, 0xeb, 0x2d, 0x03, 0x15, 0x02, 0xb7, 0xbc, 0x27, 0xef, 0x06, 0x18, + 0x09, 0x0d, 0x02, 0x0d, 0x11, 0xd7, 0x0e, 0x01, 0x1b, 0x53, 0xf8, 0x16, + 0xfd, 0x02, 0xf7, 0x06, 0x1a, 0x2c, 0x06, 0xd0, 0x3d, 0x0f, 0xf9, 0xdd, + 0x37, 0x00, 0x09, 0xf1, 0xdd, 0xd3, 0xae, 0x0f, 0x03, 0x08, 0x0b, 0x26, + 0x39, 0x2e, 0xc6, 0xd7, 0x0f, 0x73, 0xaf, 0x32, 0xde, 0xd3, 0x23, 0xeb, + 0xec, 0x03, 0x11, 0xe2, 0x20, 0xdb, 0x20, 0xff, 0xfe, 0xee, 0x33, 0xf9, + 0xfa, 0xc9, 0xc6, 0x13, 0x16, 0xf8, 0xd6, 0xf0, 0x27, 0xc8, 0x20, 0xf1, + 0xec, 0x1f, 0xfd, 0x11, 0x0d, 0xe5, 0x03, 0xbf, 0x09, 0xe2, 0x00, 0x0e, + 0x4d, 0x27, 0x0f, 0xd9, 0x31, 0xff, 0x03, 0xe7, 0xf8, 0x03, 0xac, 0x37, + 0xde, 0xdf, 0xc3, 0x2f, 0xe7, 0xf9, 0x05, 0xd0, 0xfb, 0x09, 0x15, 0x09, + 0x13, 0xfa, 0x49, 0x0b, 0xdc, 0xf1, 0xe8, 0xdd, 0x11, 0xe5, 0x25, 0x04, + 0xb0, 0xf1, 0x2b, 0x22, 0x24, 0xeb, 0xab, 0x4b, 0xd1, 0x21, 0x09, 0xfb, + 0x15, 0x05, 0xf2, 0xf3, 0x24, 0xa5, 0x1b, 0x18, 0xf1, 0x06, 0xfa, 0xfc, + 0x17, 0x18, 0xb5, 0xfc, 0x44, 0xd5, 0x2b, 0xd2, 0x1c, 0x08, 0xe7, 0x3b, + 0xcf, 0xeb, 0xb0, 0x4c, 0xec, 0x1d, 0xce, 0x2b, 0x00, 0x01, 0x10, 0xe4, + 0x13, 0xef, 0x17, 0x13, 0x09, 0xe9, 0x38, 0x1f, 0xe3, 0xf0, 0xd4, 0xec, + 0x0c, 0xeb, 0x25, 0x08, 0xc9, 0x02, 0x2d, 0x1f, 0x04, 0x15, 0xf3, 0x2f, + 0xf5, 0xeb, 0x2a, 0xf9, 0x2e, 0x2a, 0x18, 0x3f, 0xfa, 0x0d, 0x39, 0x2b, + 0x32, 0xe7, 0x13, 0x51, 0xda, 0x51, 0x08, 0xc3, 0xda, 0x0e, 0x01, 0x64, + 0xb9, 0xba, 0xd7, 0xfb, 0x3f, 0x37, 0x17, 0x50, 0x13, 0xf3, 0xbf, 0x31, + 0xb6, 0x05, 0xef, 0x0a, 0x03, 0xcf, 0xc1, 0x27, 0x56, 0xf6, 0xb4, 0xf7, + 0x16, 0xfd, 0x04, 0xda, 0x2f, 0xe9, 0x39, 0xf4, 0xa7, 0x95, 0x8c, 0xd6, + 0xdd, 0x2a, 0xf7, 0x1e, 0x0a, 0x12, 0x13, 0xe5, 0x31, 0x30, 0x0f, 0x4a, + 0xf0, 0xcd, 0x3a, 0x15, 0x2a, 0xcf, 0xee, 0x25, 0x07, 0x23, 0xf2, 0xed, + 0xf1, 0xd6, 0x2b, 0x34, 0xd4, 0xc7, 0xd1, 0xe9, 0x03, 0x09, 0xfc, 0x2d, + 0x02, 0x38, 0xb7, 0x3a, 0xe5, 0xb3, 0xf9, 0xb9, 0xb4, 0x07, 0x0b, 0x28, + 0x1a, 0x13, 0x27, 0x18, 0xc2, 0xcb, 0xf9, 0xe2, 0x12, 0xdf, 0x36, 0x00, + 0xb8, 0x0a, 0x1d, 0x25, 0x0e, 0xdb, 0xe9, 0x45, 0xe9, 0x1e, 0x38, 0xbf, + 0x23, 0x0b, 0xd7, 0xd7, 0xf6, 0x81, 0x09, 0xd5, 0xcf, 0x2d, 0xf8, 0x04, + 0x28, 0xdb, 0xde, 0xfb, 0x71, 0x28, 0xf9, 0x1e, 0x27, 0x19, 0xdd, 0x14, + 0xb5, 0x0d, 0xfc, 0x21, 0xf9, 0x35, 0xe7, 0x28, 0x08, 0xb1, 0xdc, 0xdd, + 0xe8, 0x0d, 0xfa, 0xf2, 0xff, 0xe7, 0x43, 0x21, 0xd0, 0xda, 0xd4, 0xe2, + 0xcc, 0xe5, 0x15, 0xfd, 0xde, 0x02, 0x14, 0x0f, 0xe1, 0x55, 0x00, 0xff, + 0x3e, 0x13, 0xfd, 0x0b, 0xf0, 0x1a, 0x00, 0x09, 0x07, 0xec, 0xec, 0xf4, + 0x02, 0xef, 0xf6, 0xfe, 0xeb, 0x10, 0x3d, 0xe3, 0x14, 0x4c, 0x01, 0xe5, + 0xbe, 0xee, 0x23, 0x23, 0x25, 0x3a, 0xf7, 0x06, 0xf2, 0xc9, 0xd9, 0xfe, + 0xf0, 0x33, 0x05, 0xde, 0x15, 0xb8, 0xa3, 0x07, 0xf0, 0x58, 0xa6, 0x0f, + 0xfe, 0xc3, 0xe9, 0x06, 0x10, 0x29, 0x0e, 0x2b, 0x3f, 0xc8, 0xb8, 0xa2, + 0xce, 0x40, 0xc6, 0x00, 0x48, 0x0f, 0xe6, 0x01, 0x07, 0xe5, 0xb9, 0xe2, + 0x39, 0xe3, 0xf4, 0xca, 0xc4, 0xd7, 0xf6, 0xef, 0xd5, 0x09, 0x19, 0x05, + 0x9c, 0x71, 0xf8, 0x9f, 0xc4, 0x00, 0x16, 0x2a, 0xef, 0x01, 0xff, 0x55, + 0x49, 0xe8, 0x19, 0x23, 0xfa, 0x33, 0x05, 0xdf, 0x01, 0xf5, 0x28, 0xeb, + 0xe3, 0xfb, 0x18, 0xe1, 0x0d, 0x15, 0x4b, 0xe4, 0xa2, 0x0e, 0x33, 0x0b, + 0xc2, 0xba, 0xee, 0xd2, 0x4b, 0x00, 0xff, 0x2d, 0x0c, 0xf4, 0xf6, 0x13, + 0xe9, 0x1e, 0xee, 0xa0, 0x25, 0xe6, 0xea, 0x29, 0x04, 0x3f, 0xd8, 0xfc, + 0x1a, 0xf6, 0x1c, 0xdb, 0x3c, 0x3d, 0x51, 0x53, 0xf8, 0xbb, 0xee, 0xd5, + 0x06, 0x3b, 0x18, 0x24, 0x2e, 0xef, 0x26, 0x12, 0x17, 0x16, 0x0a, 0x01, + 0x11, 0xe2, 0x5b, 0xf0, 0xd9, 0xba, 0x0d, 0xf2, 0x28, 0x3b, 0x46, 0x06, + 0x81, 0x00, 0x1b, 0x0c, 0xdd, 0xcc, 0xed, 0xda, 0xde, 0x38, 0x19, 0x02, + 0x4e, 0x07, 0x12, 0xd2, 0x0d, 0x2a, 0xd2, 0xaf, 0xfb, 0xdf, 0xf3, 0xda, + 0xdc, 0x1b, 0xda, 0xfa, 0xf3, 0xbb, 0x50, 0xf7, 0xd8, 0x4b, 0xdd, 0x13, + 0xc9, 0xe8, 0xce, 0xfd, 0x05, 0x3e, 0xfe, 0xce, 0x21, 0xe2, 0xfc, 0xf4, + 0xba, 0x0b, 0x02, 0xf4, 0x08, 0x97, 0xd3, 0xe6, 0x1c, 0x48, 0xb6, 0x1e, + 0x16, 0xb2, 0xfa, 0xf3, 0xa8, 0x4c, 0xc0, 0x4b, 0x1a, 0xf3, 0xc0, 0xf4, + 0xe8, 0x43, 0xef, 0xdd, 0x48, 0x10, 0x1f, 0xe8, 0x04, 0x15, 0xd6, 0xda, + 0x11, 0xdc, 0x03, 0xc0, 0xea, 0x15, 0xf7, 0xff, 0xe3, 0xef, 0x17, 0xe6, + 0xbb, 0x1a, 0xc9, 0xfa, 0xef, 0x06, 0x03, 0x56, 0x04, 0xde, 0x09, 0x2a, + 0x1d, 0xdb, 0xe1, 0xf5, 0x04, 0xcb, 0x06, 0xec, 0xec, 0x0e, 0xf4, 0x21, + 0x35, 0x0c, 0x01, 0xbf, 0xd3, 0xf0, 0xf2, 0x01, 0x25, 0x02, 0x2a, 0x4a, + 0xe2, 0xe6, 0x0e, 0xf0, 0x16, 0xd8, 0xda, 0x56, 0x19, 0xfa, 0x20, 0xef, + 0x2f, 0x14, 0xf0, 0xd7, 0x06, 0xd2, 0xeb, 0x2a, 0xed, 0x0e, 0x16, 0xc3, + 0xd5, 0xfb, 0xef, 0xeb, 0x47, 0x0a, 0x4c, 0x56, 0xcd, 0xfa, 0x39, 0x10, + 0x01, 0xe2, 0xd3, 0x3e, 0x0d, 0xc6, 0xbd, 0xfc, 0x05, 0xc4, 0x15, 0xc9, + 0xfa, 0x0c, 0xfc, 0x39, 0x23, 0x15, 0xe9, 0xd3, 0xde, 0xe0, 0xed, 0x16, + 0x2f, 0xe5, 0x31, 0x2e, 0xe7, 0xb2, 0xda, 0xda, 0x08, 0xfa, 0xee, 0xed, + 0x13, 0xf8, 0xfe, 0x02, 0x1b, 0xf7, 0xc4, 0x03, 0xdb, 0x0c, 0xf3, 0x0f, + 0x1c, 0xed, 0xf9, 0x01, 0xd2, 0x32, 0xe8, 0xdc, 0x68, 0xc3, 0x50, 0x1c, + 0xdc, 0xcc, 0xf2, 0xe2, 0xf7, 0x32, 0x0b, 0xea, 0x26, 0xd6, 0xf8, 0xd5, + 0x21, 0x00, 0x2c, 0xd9, 0x13, 0xe1, 0xf0, 0x18, 0x17, 0x03, 0xf6, 0xd1, + 0xbb, 0x1f, 0x0a, 0xd4, 0xfc, 0xc0, 0x22, 0x1a, 0xe4, 0xf5, 0x13, 0xf4, + 0x19, 0xdf, 0xe6, 0x0c, 0xfd, 0xe1, 0xe5, 0xe7, 0x0d, 0x01, 0xfe, 0xc0, + 0xd0, 0xfd, 0xe8, 0x08, 0x0d, 0x07, 0xd3, 0xe3, 0xf6, 0x13, 0xe5, 0xf0, + 0x7f, 0xd0, 0x4b, 0x1f, 0xca, 0xb2, 0xcc, 0xb6, 0x0f, 0xec, 0xf5, 0x57, + 0xf0, 0x15, 0x0c, 0x2a, 0x1b, 0xdb, 0xfb, 0xff, 0x02, 0x35, 0xe9, 0x30, + 0x14, 0xe5, 0x18, 0xda, 0xf7, 0x1a, 0xf5, 0xce, 0x40, 0x1e, 0x4f, 0xcf, + 0xfe, 0x11, 0x09, 0xf6, 0xed, 0xbb, 0xb7, 0x70, 0xd9, 0x1d, 0x4c, 0x17, + 0x2a, 0x63, 0xed, 0xe5, 0xfa, 0x15, 0xf9, 0x2a, 0xdc, 0xe4, 0x24, 0xd9, + 0x25, 0x04, 0xda, 0xde, 0x3b, 0xfa, 0x33, 0xc8, 0xf4, 0x22, 0x33, 0x0a, + 0x23, 0xeb, 0xfd, 0x36, 0x01, 0x10, 0xd0, 0xfa, 0x17, 0xc1, 0x2c, 0xcb, + 0x1a, 0x1d, 0xf9, 0x3c, 0x08, 0x03, 0xfa, 0xea, 0xd7, 0x10, 0xfb, 0xf7, + 0x58, 0xf0, 0x55, 0xf0, 0xe0, 0xfb, 0xf7, 0xf2, 0x12, 0x32, 0xf4, 0xf8, + 0x06, 0x06, 0x03, 0x28, 0xe5, 0x32, 0xe5, 0x35, 0x11, 0xd0, 0x14, 0x0b, + 0x1d, 0x09, 0x1a, 0xfd, 0xdd, 0x16, 0xf1, 0xee, 0xeb, 0xf6, 0x16, 0x33, + 0xe7, 0x14, 0x0c, 0x21, 0x24, 0x18, 0x2a, 0x04, 0xfe, 0x02, 0xe4, 0x01, + 0xf3, 0xd6, 0xfc, 0x15, 0x4f, 0xb3, 0x54, 0x04, 0x1e, 0x3f, 0xf5, 0x0b, + 0xe9, 0xfd, 0xfc, 0xf3, 0xfd, 0xf1, 0x0b, 0x1b, 0x09, 0xe4, 0xe5, 0x1d, + 0xe6, 0x24, 0xf6, 0xe1, 0x12, 0x01, 0xf8, 0x04, 0xe1, 0x1b, 0xca, 0x27, + 0x1b, 0xd5, 0x05, 0xf2, 0x00, 0xef, 0xfe, 0x08, 0xe9, 0xfa, 0xf4, 0xfc, + 0xb5, 0xff, 0xf4, 0xf8, 0xf6, 0x0b, 0xf0, 0x18, 0x0f, 0x09, 0x07, 0x16, + 0xe0, 0xe3, 0x2a, 0xfe, 0xde, 0xec, 0xda, 0x1e, 0xf6, 0xfc, 0x3b, 0x23, + 0x21, 0xe1, 0x01, 0x0e, 0xd8, 0x48, 0x01, 0xdc, 0xe5, 0xed, 0x34, 0xee, + 0xa7, 0xf0, 0x07, 0x0e, 0x51, 0xf5, 0x1e, 0x4c, 0xd3, 0x12, 0xfc, 0x0e, + 0x02, 0xfb, 0xd7, 0x1e, 0x63, 0xda, 0x2f, 0x4d, 0x34, 0x00, 0xdf, 0xee, + 0x02, 0x2f, 0xda, 0xf6, 0xe6, 0xf9, 0x0f, 0xfc, 0xe1, 0xf6, 0xd4, 0xfb, + 0xe3, 0x05, 0xfc, 0x2a, 0xe4, 0xe4, 0x26, 0xf1, 0xe9, 0x00, 0xea, 0x04, + 0xfc, 0xf2, 0x64, 0x22, 0x18, 0xc8, 0xf8, 0x0e, 0xfa, 0x12, 0x0c, 0x01, + 0x81, 0x04, 0x2d, 0xea, 0xc0, 0xe5, 0x08, 0xee, 0x0c, 0x2e, 0x2b, 0x02, + 0xee, 0x05, 0x08, 0x1c, 0xcc, 0x30, 0xd3, 0x1a, 0xf0, 0xc2, 0x14, 0x11, + 0x02, 0xfc, 0x0e, 0xea, 0xdc, 0xeb, 0xec, 0xd8, 0xe0, 0xe1, 0x02, 0x4c, + 0xf1, 0x00, 0x1a, 0x13, 0x29, 0x29, 0x37, 0xf5, 0xcb, 0x05, 0xfa, 0xd5, + 0xf2, 0xe8, 0xd6, 0x40, 0x47, 0xe5, 0x6b, 0xf3, 0x1e, 0x3b, 0xf0, 0xe8, + 0xe4, 0xf9, 0xe4, 0xe6, 0xf0, 0x0a, 0x01, 0x45, 0x21, 0xeb, 0xce, 0x11, + 0xbe, 0x2b, 0x1b, 0xff, 0xee, 0x03, 0x0b, 0x10, 0xdc, 0x07, 0x8f, 0x15, + 0x01, 0xef, 0xee, 0xfb, 0x03, 0xe4, 0xff, 0x07, 0x09, 0xf8, 0xdd, 0xde, + 0x94, 0xed, 0xfd, 0x12, 0xf7, 0x11, 0x08, 0x05, 0x18, 0xed, 0xea, 0x06, + 0xcd, 0xba, 0xf0, 0xdd, 0x0e, 0xf0, 0x0a, 0xfd, 0x11, 0xb7, 0x02, 0x01, + 0xdb, 0x0b, 0x1a, 0xef, 0xdb, 0xff, 0xed, 0xff, 0x0d, 0xdf, 0xe5, 0xf6, + 0x21, 0xec, 0xd2, 0xf2, 0xfb, 0xfa, 0xeb, 0xff, 0x06, 0xcb, 0x0a, 0xe3, + 0x0a, 0xf1, 0x1e, 0x0c, 0xe1, 0x10, 0x30, 0xef, 0x15, 0xe1, 0x1e, 0x0e, + 0x21, 0x07, 0x2e, 0x07, 0x05, 0xfb, 0xf5, 0xb2, 0xee, 0x46, 0x1d, 0x27, + 0x0e, 0xfd, 0xfe, 0x00, 0xc3, 0xc7, 0xe0, 0xff, 0x04, 0xd6, 0x1a, 0xf3, + 0xf8, 0xd1, 0x10, 0x1b, 0x15, 0x09, 0x16, 0x0b, 0xf2, 0x02, 0xdb, 0x34, + 0xf5, 0xbf, 0x10, 0x03, 0x1d, 0xe0, 0xef, 0xdb, 0x0b, 0xe2, 0xfb, 0xc9, + 0xf3, 0x01, 0x10, 0xf0, 0xec, 0x04, 0xfa, 0xf3, 0x1b, 0x06, 0xeb, 0xf1, + 0xe9, 0x05, 0xc9, 0xec, 0x00, 0xe3, 0x03, 0x05, 0xec, 0x10, 0xc6, 0xd7, + 0x2c, 0x2d, 0xfe, 0xee, 0xf1, 0x03, 0x23, 0xf1, 0x25, 0x22, 0x15, 0x21, + 0xe5, 0x0c, 0x15, 0x11, 0xf3, 0x10, 0xe0, 0xf3, 0x1d, 0x05, 0x1f, 0x0f, + 0x1e, 0xdb, 0x23, 0x03, 0xfb, 0x13, 0xd4, 0x05, 0xe9, 0x18, 0x18, 0x28, + 0xea, 0x08, 0xf2, 0xdd, 0xe0, 0xee, 0x28, 0xe0, 0xee, 0x07, 0x00, 0xfd, + 0x0b, 0x23, 0xe8, 0xf8, 0x11, 0xea, 0xe0, 0x33, 0x04, 0xc7, 0xf0, 0x10, + 0xe7, 0x0a, 0xe4, 0xf2, 0x02, 0x0d, 0x00, 0xf8, 0x13, 0xef, 0xf4, 0xee, + 0xe3, 0xc5, 0xea, 0xd6, 0x08, 0x25, 0x0d, 0xfe, 0x11, 0x0d, 0x02, 0xef, + 0xdd, 0x0b, 0xfe, 0xe2, 0x05, 0xe8, 0x07, 0x13, 0xfd, 0xf5, 0xdd, 0xf4, + 0x14, 0xe2, 0xd3, 0xf3, 0xf7, 0x01, 0xf9, 0x17, 0x0e, 0xf0, 0xec, 0xfd, + 0xe7, 0xcb, 0x24, 0xe0, 0xd3, 0xd7, 0x48, 0xec, 0x29, 0x05, 0x26, 0x22, + 0x16, 0x08, 0xf3, 0x1f, 0xff, 0xfe, 0xfc, 0xe1, 0xf9, 0x0f, 0x15, 0x2f, + 0xf0, 0xd9, 0xd4, 0x15, 0xf8, 0xf8, 0x1c, 0xde, 0x0b, 0x17, 0x02, 0x0b, + 0xe7, 0xd6, 0xfb, 0xf7, 0xef, 0xf8, 0x0f, 0xfb, 0x0c, 0x01, 0x0b, 0x7f, + 0xf4, 0x0a, 0xfd, 0xf6, 0x16, 0x0f, 0xfd, 0xe4, 0xfc, 0x0d, 0x01, 0x06, + 0xff, 0x2f, 0xfc, 0x21, 0xf4, 0xfb, 0xe6, 0x1b, 0x21, 0x02, 0x0c, 0x18, + 0x14, 0x11, 0x01, 0x15, 0xc6, 0x0f, 0xec, 0xe9, 0xfc, 0xfc, 0x0f, 0x23, + 0xe0, 0x06, 0x02, 0xee, 0x1f, 0x1c, 0x1e, 0x1f, 0xfd, 0x42, 0x03, 0xff, + 0xf5, 0xf0, 0xf2, 0x25, 0x0f, 0xc7, 0x65, 0x1c, 0x29, 0xf7, 0x28, 0x05, + 0xec, 0x1f, 0xfb, 0xe7, 0x08, 0xfd, 0x34, 0xf5, 0xfa, 0x1c, 0xfb, 0x1f, + 0xfe, 0x07, 0x03, 0x0c, 0xf6, 0x0f, 0xfe, 0x1a, 0xe0, 0xfe, 0xbe, 0x13, + 0x19, 0xfc, 0xfc, 0x09, 0x18, 0xfd, 0x09, 0xfb, 0xff, 0x03, 0xe9, 0xee, + 0xea, 0xe3, 0x0c, 0xff, 0xf3, 0xf6, 0xf0, 0x00, 0xda, 0xf8, 0xfb, 0x1e, + 0xee, 0xfd, 0x0a, 0x0d, 0xd0, 0x03, 0xf0, 0x06, 0x2e, 0xfc, 0x06, 0x15, + 0xfc, 0xf8, 0x0d, 0x08, 0xf5, 0x5f, 0xef, 0xe7, 0x17, 0xe2, 0x22, 0x06, + 0xbd, 0x1a, 0x25, 0x0e, 0xe8, 0xea, 0x04, 0x2e, 0xdd, 0xf8, 0x02, 0xfb, + 0x0e, 0x0d, 0xc7, 0x02, 0x46, 0xf0, 0x29, 0x00, 0x05, 0x42, 0x37, 0xd9, + 0xf2, 0x42, 0xe8, 0xe8, 0xe1, 0xed, 0xd5, 0x25, 0xe4, 0xe2, 0xd6, 0x13, + 0xdb, 0xee, 0xe8, 0x2c, 0xe7, 0xef, 0xfd, 0xf7, 0xa1, 0x02, 0x02, 0xf0, + 0x1d, 0xfe, 0xf8, 0x0d, 0x06, 0xd5, 0x01, 0x08, 0x08, 0x32, 0xec, 0xfa, + 0x16, 0x04, 0x14, 0xe1, 0xb7, 0x0b, 0x09, 0xed, 0xfb, 0x0d, 0x23, 0x15, + 0xbf, 0xe9, 0x05, 0x0f, 0xba, 0x28, 0xe1, 0x1a, 0x0f, 0xd0, 0x1d, 0x1e, + 0x0e, 0x06, 0xf3, 0x11, 0x06, 0x0d, 0xce, 0xf5, 0xe4, 0xb7, 0x17, 0x10, + 0xe9, 0xe4, 0xc3, 0xf8, 0x17, 0x06, 0x3e, 0x02, 0xc4, 0x30, 0xf1, 0xe5, + 0x06, 0xc9, 0xf9, 0x1b, 0x0c, 0x33, 0x7f, 0x14, 0x37, 0xd9, 0x07, 0xdc, + 0xcb, 0x18, 0xd1, 0xde, 0xfa, 0xf4, 0x2d, 0xdb, 0xdd, 0x02, 0xd7, 0x0f, + 0xbc, 0x0f, 0x44, 0x03, 0xb3, 0x04, 0x06, 0x08, 0xac, 0x17, 0xb9, 0x0e, + 0xfc, 0xed, 0x09, 0xfb, 0x15, 0xf2, 0xef, 0x14, 0x0e, 0xf9, 0xb3, 0xea, + 0xc8, 0xb9, 0xf1, 0xf9, 0xfc, 0xed, 0xed, 0xfd, 0x00, 0x08, 0x18, 0x06, + 0x06, 0x1d, 0x0d, 0x00, 0xf3, 0xef, 0xf9, 0x23, 0x0f, 0xbf, 0x17, 0x1c, + 0x2e, 0x0f, 0x07, 0xe7, 0xc6, 0x2b, 0xf6, 0xe8, 0xd2, 0x0f, 0x1d, 0x23, + 0x09, 0x08, 0x00, 0xf8, 0x16, 0x00, 0x17, 0x2d, 0x27, 0x2a, 0x09, 0xee, + 0xf6, 0xe5, 0xf6, 0x2b, 0x20, 0xe4, 0x74, 0x1a, 0x3d, 0xfe, 0x0d, 0xf2, + 0xd8, 0x2a, 0x00, 0xe7, 0xfc, 0xf7, 0x26, 0x18, 0xdb, 0x0a, 0xe3, 0x21, + 0xec, 0x07, 0x10, 0x1a, 0xe0, 0xe0, 0xff, 0xfe, 0xae, 0x04, 0xc3, 0x2f, + 0x06, 0xf6, 0xf2, 0x17, 0x21, 0x0f, 0x00, 0xf3, 0x05, 0x14, 0xcd, 0x04, + 0xb9, 0xe2, 0x12, 0x24, 0x02, 0x00, 0xeb, 0xf3, 0xec, 0xf4, 0xf8, 0xfa, + 0x07, 0xeb, 0x12, 0xed, 0xcd, 0xf9, 0xcf, 0xfe, 0xf6, 0x0d, 0xff, 0x0a, + 0xf9, 0xd3, 0xce, 0x21, 0xf4, 0xfa, 0xec, 0xf9, 0x01, 0xf8, 0x13, 0xd9, + 0xbf, 0x19, 0x1c, 0x21, 0xdd, 0xfc, 0x23, 0x11, 0x0d, 0x27, 0xd7, 0xf6, + 0x44, 0xee, 0xcc, 0x10, 0x1a, 0xec, 0x42, 0xfe, 0xfe, 0x1c, 0xf1, 0xea, + 0xd7, 0x2f, 0xff, 0xe4, 0xdc, 0xfc, 0xe2, 0x21, 0xca, 0x38, 0xd0, 0xf9, + 0xfa, 0xdf, 0xef, 0x0a, 0xde, 0xfe, 0x0c, 0xec, 0xab, 0xf4, 0xec, 0xf7, + 0xe7, 0x09, 0x12, 0x09, 0xfe, 0xcb, 0x08, 0x24, 0x11, 0xec, 0xe9, 0xe7, + 0x01, 0x0e, 0x04, 0xd2, 0xc6, 0x1a, 0x0b, 0x0e, 0xdb, 0xe8, 0x2c, 0x16, + 0xcb, 0xec, 0x38, 0x04, 0xe2, 0x0c, 0xe8, 0x28, 0x09, 0xbb, 0x0c, 0x29, + 0x21, 0xeb, 0x0b, 0xdd, 0x04, 0x0f, 0xd5, 0xe8, 0xce, 0xed, 0x1b, 0x0e, + 0x07, 0xfc, 0xf0, 0xe5, 0x04, 0xc0, 0x35, 0x46, 0x03, 0x10, 0x3e, 0xe5, + 0x12, 0xf8, 0xf5, 0x3d, 0x03, 0x1d, 0x7f, 0x1b, 0x4b, 0xdd, 0x17, 0xba, + 0x0d, 0x30, 0xf9, 0xe4, 0xe8, 0xff, 0x13, 0xd7, 0xdf, 0x44, 0xe2, 0x21, + 0xe1, 0xd4, 0x0e, 0x18, 0xb3, 0x09, 0x1d, 0xef, 0xcb, 0x14, 0xa8, 0x13, + 0xe4, 0xf2, 0xec, 0x25, 0x24, 0xdc, 0xf4, 0xcc, 0x12, 0xf5, 0xc8, 0xde, + 0xc5, 0xdd, 0x00, 0x05, 0x01, 0x09, 0xf6, 0xd7, 0xde, 0xc9, 0x04, 0x21, + 0x13, 0x06, 0x21, 0xd5, 0xe2, 0x23, 0x1d, 0xef, 0xe6, 0xe7, 0xd1, 0xff, + 0x10, 0xdc, 0x0a, 0xdd, 0x19, 0xdf, 0x0d, 0x13, 0xf4, 0x46, 0xdc, 0xdf, + 0xfd, 0xd0, 0xc6, 0xca, 0xef, 0xf3, 0xff, 0x11, 0x19, 0xe5, 0x13, 0x0c, + 0xdc, 0x0d, 0x35, 0x1d, 0xd4, 0x21, 0x05, 0x14, 0x3f, 0xd6, 0x14, 0x0a, + 0x37, 0xe3, 0xf5, 0x07, 0xe9, 0x27, 0xf0, 0xb5, 0x12, 0x39, 0x0a, 0x0e, + 0xdf, 0xe8, 0xe8, 0x16, 0xe9, 0xfc, 0x15, 0xd1, 0x14, 0x05, 0x18, 0x0a, + 0xf6, 0xd1, 0xf2, 0x09, 0x0b, 0xd0, 0x01, 0xfc, 0x09, 0x0b, 0xf2, 0x29, + 0xeb, 0x3d, 0xd6, 0xe4, 0x2f, 0xff, 0xf0, 0xd3, 0xcb, 0xbe, 0xfd, 0xd9, + 0x2f, 0xf8, 0xfb, 0xd9, 0xf9, 0xf2, 0xe4, 0xbe, 0xf6, 0x02, 0xf8, 0xec, + 0xd8, 0x03, 0xe1, 0xc8, 0x04, 0xc9, 0x2d, 0x00, 0xe2, 0x26, 0xe6, 0x0e, + 0xed, 0xf2, 0x11, 0xe5, 0x20, 0xfd, 0x01, 0xe9, 0x14, 0xfa, 0x07, 0xee, + 0xf6, 0x04, 0xdd, 0x09, 0xf2, 0xfa, 0xf3, 0x00, 0xfa, 0x2c, 0x17, 0xce, + 0x0c, 0xe2, 0x22, 0xf1, 0x19, 0x2f, 0x16, 0x21, 0xf7, 0x30, 0x28, 0x15, + 0xe7, 0xe9, 0x04, 0xe6, 0x50, 0xf0, 0x00, 0xe7, 0xf4, 0xf9, 0xea, 0xea, + 0x16, 0x19, 0xd3, 0xfb, 0xfd, 0xf1, 0xf0, 0xeb, 0x0b, 0xd3, 0x1a, 0x11, + 0xfd, 0x0f, 0xea, 0x05, 0x16, 0x09, 0x1f, 0xed, 0xe5, 0x0e, 0x1b, 0x0f, + 0x22, 0x0f, 0x2c, 0xd2, 0xea, 0x1f, 0x0a, 0xf6, 0x29, 0xd9, 0xec, 0xff, + 0xfb, 0x0b, 0xe7, 0xf1, 0x1e, 0xca, 0x1b, 0x1e, 0xd0, 0x3f, 0xcc, 0x26, + 0xfa, 0xe4, 0xce, 0xe1, 0xf1, 0x21, 0x2e, 0x0f, 0x2e, 0xeb, 0xf7, 0x1a, + 0xdd, 0x18, 0x24, 0x2b, 0xe8, 0x25, 0x0e, 0x0b, 0x3f, 0xfb, 0x28, 0xff, + 0x46, 0x0e, 0x0c, 0x0b, 0xdd, 0x41, 0xf0, 0xde, 0x1d, 0x3e, 0x13, 0x2a, + 0xd4, 0x02, 0x09, 0x01, 0x21, 0x0e, 0x1b, 0xd5, 0x10, 0x3d, 0x04, 0xfe, + 0x1f, 0xe4, 0x01, 0xee, 0xd2, 0x0f, 0xee, 0xf3, 0x52, 0x10, 0x19, 0x7f, + 0xef, 0x36, 0xe3, 0x05, 0x2b, 0x10, 0x04, 0xe0, 0xd9, 0xbe, 0xc7, 0x2b, + 0x29, 0x29, 0xf9, 0xf2, 0xce, 0x3c, 0x15, 0xca, 0xc6, 0xe2, 0xfa, 0x0a, + 0x04, 0xde, 0x01, 0xe6, 0x0c, 0xf9, 0xf1, 0x15, 0x18, 0x34, 0xfb, 0xf7, + 0xcf, 0xb7, 0xc2, 0xcb, 0xf5, 0xad, 0xfb, 0x42, 0x16, 0xf8, 0x37, 0x1d, + 0xd4, 0x21, 0x1c, 0xfb, 0xa8, 0x02, 0xfd, 0x31, 0x65, 0xcf, 0x07, 0x1d, + 0x3a, 0xe8, 0xea, 0xde, 0xeb, 0x48, 0x10, 0xd3, 0x19, 0x11, 0xc5, 0xce, + 0xee, 0xe8, 0xf7, 0x4a, 0x08, 0x17, 0x2b, 0xee, 0x06, 0x22, 0x0b, 0x37, + 0xbe, 0xb8, 0xfe, 0x06, 0x23, 0xe6, 0xee, 0x16, 0x37, 0x11, 0xf0, 0x09, + 0xfd, 0x29, 0x06, 0xe1, 0xde, 0x08, 0xd8, 0xe7, 0xb9, 0xd9, 0x05, 0xe1, + 0x3f, 0xea, 0x0e, 0xdb, 0xf8, 0x05, 0xe6, 0xb0, 0xe1, 0x1d, 0x02, 0xf0, + 0xeb, 0xff, 0xd8, 0xcd, 0xf5, 0xbd, 0x15, 0xf6, 0xc4, 0x1d, 0xe0, 0x51, + 0xd7, 0xd4, 0xf3, 0xef, 0x12, 0x0b, 0xe7, 0xe5, 0x05, 0xf2, 0x06, 0xd6, + 0x12, 0x01, 0xe0, 0x02, 0xea, 0xaa, 0xe8, 0xe8, 0xc6, 0x47, 0xd2, 0xfd, + 0x1e, 0xc8, 0x1c, 0xf9, 0x23, 0x2a, 0xf6, 0x45, 0xeb, 0x0e, 0xf9, 0xcc, + 0xc8, 0xdb, 0x10, 0xec, 0x57, 0xef, 0x08, 0xfd, 0xdf, 0x06, 0xe3, 0xfd, + 0xe1, 0x0b, 0xb9, 0xf9, 0xf5, 0xf1, 0xf9, 0xee, 0x14, 0xd8, 0x1c, 0xf3, + 0xd6, 0x04, 0xec, 0x42, 0xea, 0x03, 0x29, 0xf9, 0xcb, 0x11, 0x08, 0x2b, + 0x1e, 0x16, 0x36, 0xc8, 0x09, 0x2e, 0x03, 0xf2, 0x17, 0xd3, 0x02, 0x03, + 0x3e, 0xfe, 0x09, 0x08, 0x09, 0x05, 0x08, 0x05, 0xee, 0x47, 0xe1, 0x1d, + 0xea, 0xe5, 0xef, 0xef, 0x05, 0xf7, 0x1b, 0x42, 0x20, 0xe7, 0x3b, 0x03, + 0xce, 0x0b, 0x3b, 0x2e, 0x08, 0xfc, 0x36, 0x37, 0x7f, 0x08, 0x18, 0xf5, + 0x2f, 0x27, 0xea, 0xdd, 0xdc, 0x6a, 0xed, 0x05, 0x2a, 0x18, 0xcc, 0x05, + 0xe2, 0x14, 0xf9, 0x45, 0x04, 0x15, 0x23, 0xe2, 0x03, 0x41, 0xf9, 0x0a, + 0x1b, 0xec, 0x0e, 0xeb, 0x09, 0xff, 0xf2, 0x03, 0x38, 0x0b, 0x1a, 0x22, + 0xb7, 0x45, 0xd9, 0xfd, 0x07, 0xf4, 0xdf, 0x08, 0x31, 0x2e, 0x22, 0xef, + 0xed, 0x00, 0x06, 0xf6, 0x05, 0x08, 0xf2, 0xf1, 0xe1, 0x0b, 0xf6, 0x14, + 0x02, 0x15, 0xed, 0x0d, 0xed, 0x1c, 0xf6, 0xef, 0x04, 0xe0, 0x0e, 0xeb, + 0x04, 0xf3, 0xfc, 0x05, 0x04, 0x3c, 0x0f, 0xdd, 0x30, 0xfb, 0xdd, 0x0a, + 0x11, 0x26, 0xd9, 0xf3, 0xed, 0x3c, 0xd9, 0xf2, 0xd3, 0xec, 0x28, 0x15, + 0xcc, 0xe5, 0x2a, 0xe2, 0x0c, 0x06, 0xfb, 0xf6, 0x07, 0x0d, 0x32, 0x0f, + 0x2c, 0x29, 0x2a, 0xed, 0xfd, 0x02, 0xe2, 0xfb, 0x19, 0xe9, 0xfc, 0xe2, + 0x0e, 0x1a, 0xfa, 0x26, 0x03, 0x1a, 0xe2, 0xee, 0xbe, 0x18, 0xe5, 0x02, + 0x23, 0xd8, 0x28, 0xe4, 0x09, 0xc6, 0xf9, 0x17, 0x24, 0xfd, 0xbf, 0x36, + 0xfe, 0xee, 0xf7, 0x12, 0xfe, 0x02, 0x16, 0xde, 0x46, 0xf7, 0x0a, 0x16, + 0xc0, 0x17, 0x11, 0xe7, 0x06, 0x3b, 0x08, 0xfb, 0x52, 0x02, 0x53, 0xbe, + 0x11, 0xeb, 0xf6, 0xca, 0xde, 0xef, 0xff, 0x1b, 0xd8, 0xde, 0x0e, 0x1f, + 0x07, 0x16, 0x1c, 0xc9, 0xb2, 0x22, 0xf0, 0xf4, 0xfe, 0xe6, 0x7f, 0xe0, + 0x0a, 0x08, 0x07, 0xe7, 0xd1, 0x01, 0x0f, 0xe3, 0x0b, 0xf9, 0x44, 0x06, + 0x00, 0x2f, 0xf0, 0x42, 0x01, 0xf8, 0xf9, 0x02, 0x27, 0x0e, 0x05, 0xd6, + 0x28, 0x10, 0xec, 0x1b, 0xe4, 0x03, 0xfc, 0xfa, 0xf6, 0x46, 0x18, 0x02, + 0x63, 0x00, 0x30, 0xbd, 0x20, 0xe2, 0xfc, 0xe8, 0x36, 0x13, 0x27, 0xbf, + 0xff, 0x03, 0xd9, 0xe6, 0x14, 0xb4, 0xdc, 0xd0, 0x17, 0x1f, 0xd8, 0xf4, + 0xf3, 0xff, 0xde, 0xe6, 0xce, 0xfd, 0xe6, 0x12, 0x0b, 0xd2, 0xf7, 0xef, + 0x24, 0xd8, 0xed, 0xdd, 0xcc, 0x3f, 0xf2, 0xd1, 0x10, 0xf2, 0xd3, 0x15, + 0xe8, 0xf3, 0xe5, 0xef, 0xe3, 0x32, 0xe6, 0xe5, 0xd4, 0xe0, 0x2d, 0xf3, + 0xeb, 0xd8, 0x46, 0x07, 0xf1, 0xde, 0xf3, 0x16, 0xe5, 0x13, 0x30, 0x2c, + 0x16, 0x19, 0x20, 0xe2, 0xf5, 0xe8, 0xf2, 0xf1, 0x1c, 0x03, 0xe9, 0xee, + 0x18, 0x1f, 0xf6, 0x13, 0xf8, 0x0d, 0xfd, 0xfa, 0xde, 0x08, 0xf6, 0x18, + 0x10, 0xd6, 0xf4, 0xeb, 0x1c, 0xcf, 0xea, 0x05, 0xcc, 0x07, 0x02, 0x09, + 0xff, 0xd8, 0xf3, 0xf4, 0xdf, 0x1f, 0x1f, 0xe6, 0xf4, 0x0a, 0xca, 0xd8, + 0xf5, 0xd4, 0xff, 0xe7, 0x13, 0xd7, 0x05, 0x0a, 0xed, 0x15, 0xca, 0x08, + 0x08, 0x13, 0x12, 0xdf, 0xeb, 0x26, 0x02, 0x0e, 0xd2, 0xef, 0x0e, 0xdc, + 0xc3, 0x09, 0x32, 0xf3, 0xe0, 0xfb, 0xeb, 0xf8, 0x03, 0x19, 0xec, 0xee, + 0x2c, 0xeb, 0xec, 0x10, 0xf5, 0x1c, 0xd7, 0x09, 0xf9, 0xd2, 0xe3, 0xdd, + 0xd0, 0x0a, 0x08, 0xfb, 0xfa, 0xf3, 0x12, 0xf1, 0x02, 0x24, 0x64, 0xfa, + 0xf7, 0x10, 0xe4, 0xe0, 0xf4, 0xc1, 0xe7, 0xe3, 0x7f, 0xee, 0x1c, 0x5e, + 0xd7, 0xff, 0xde, 0xfe, 0x1c, 0x11, 0xf5, 0xee, 0xc8, 0x06, 0x14, 0x1a, + 0xf0, 0xe3, 0x44, 0xfa, 0x03, 0x55, 0x2a, 0xdf, 0xfe, 0x0e, 0xea, 0x16, + 0x2d, 0xe2, 0xf3, 0xcf, 0x15, 0xed, 0x24, 0x0b, 0xbd, 0x28, 0xc3, 0xf2, + 0x0b, 0xdf, 0xd8, 0xe5, 0xd2, 0x08, 0x19, 0x18, 0xf1, 0xff, 0x19, 0x17, + 0xdb, 0x43, 0x06, 0xee, 0xe1, 0xd9, 0xe6, 0x17, 0x29, 0xd8, 0xd6, 0xe4, + 0x28, 0xc5, 0x37, 0x0d, 0xfb, 0x3e, 0xd5, 0xd4, 0xe8, 0xea, 0xf6, 0xf2, + 0xc7, 0x1a, 0x33, 0x22, 0xee, 0x05, 0x0b, 0xfe, 0xfc, 0x38, 0x68, 0xe8, + 0xf1, 0x12, 0xcb, 0x11, 0x0b, 0xec, 0xfe, 0xd1, 0x61, 0xf9, 0x14, 0x62, + 0xe7, 0x57, 0xce, 0xe1, 0x20, 0xec, 0xfc, 0xf6, 0xba, 0x1d, 0xe0, 0xd9, + 0xb9, 0xc6, 0xb1, 0x0e, 0xed, 0xed, 0x18, 0xe8, 0x0b, 0xf7, 0xe0, 0xe4, + 0xcd, 0xb0, 0x12, 0xeb, 0x07, 0xe5, 0xde, 0xf0, 0xec, 0xe6, 0xde, 0xc0, + 0xf6, 0x00, 0x14, 0x12, 0xda, 0x12, 0xeb, 0xe9, 0xe1, 0xd3, 0xd2, 0xd8, + 0xce, 0xf6, 0x47, 0xf2, 0x0b, 0xbd, 0xeb, 0xef, 0xea, 0xea, 0xc2, 0xf2, + 0x2b, 0xfe, 0xf7, 0x13, 0xcf, 0xf2, 0xf8, 0xe1, 0xf3, 0xb9, 0xd8, 0xe5, + 0xe1, 0x2d, 0xd1, 0xe0, 0xd6, 0xea, 0xce, 0xf8, 0xf5, 0xe9, 0x77, 0xe7, + 0xe4, 0xff, 0xec, 0xde, 0xcd, 0xb9, 0xf7, 0xee, 0x52, 0xdf, 0xe5, 0x70, + 0x1f, 0xe7, 0xf1, 0x9e, 0x0a, 0xf2, 0x02, 0x0a, 0x24, 0x21, 0x11, 0x06, + 0xf1, 0x16, 0xfc, 0x15, 0x05, 0x00, 0xf4, 0x13, 0x2d, 0x1a, 0x09, 0x0b, + 0xf0, 0x1a, 0x03, 0x17, 0xe2, 0x1a, 0xe4, 0xe0, 0x1a, 0xe9, 0x08, 0xea, + 0xf2, 0x02, 0x0b, 0x0a, 0x02, 0x2f, 0x0f, 0xf2, 0x2d, 0x08, 0xf5, 0x0b, + 0x03, 0x0e, 0xe2, 0x0b, 0x12, 0x39, 0xee, 0xd6, 0xdb, 0xe3, 0x19, 0x16, + 0xce, 0xf4, 0x1a, 0xe6, 0x0b, 0xf0, 0xf2, 0xd3, 0x0b, 0xfb, 0x23, 0x14, + 0x2d, 0x16, 0xfd, 0xee, 0xfa, 0x00, 0xf8, 0x09, 0x09, 0xf5, 0xf2, 0x11, + 0x2a, 0x19, 0x1c, 0x07, 0xee, 0x12, 0xe5, 0x15, 0xe4, 0x0f, 0x0f, 0xf3, + 0x10, 0xde, 0x0e, 0xef, 0x0c, 0xf9, 0xe4, 0x1b, 0xf8, 0x25, 0xc4, 0x39, + 0xec, 0xe4, 0xf6, 0x0d, 0x13, 0x09, 0x03, 0xf4, 0x56, 0x04, 0xf5, 0x08, + 0xce, 0x29, 0x1d, 0xee, 0xf7, 0x4b, 0x0a, 0x0a, 0x3a, 0xff, 0x0e, 0xec, + 0x15, 0xe5, 0xfe, 0xf4, 0xf2, 0xd6, 0xf1, 0x24, 0xeb, 0xd7, 0xf9, 0x13, + 0xf6, 0x09, 0xf7, 0xe6, 0xd7, 0x19, 0xe7, 0xe0, 0xdf, 0xf8, 0x7f, 0xed, + 0x00, 0x2b, 0xfc, 0xed, 0xe1, 0x04, 0xf3, 0xfd, 0x01, 0xd9, 0x42, 0x12, + 0x06, 0x2e, 0xe3, 0x3b, 0x08, 0xfd, 0xf1, 0x18, 0x02, 0x05, 0x15, 0xcd, + 0x38, 0xfc, 0xf7, 0x0a, 0xe2, 0x24, 0xfb, 0x06, 0xfe, 0x44, 0x04, 0xfc, + 0x51, 0x0d, 0x0c, 0xd9, 0x31, 0xf4, 0x08, 0xeb, 0x2f, 0x14, 0x25, 0xd4, + 0xfc, 0x01, 0xd4, 0xea, 0xe1, 0xd1, 0x0b, 0xc4, 0x3b, 0x14, 0x06, 0xe0, + 0xe9, 0x0c, 0xf9, 0x0f, 0xce, 0xe5, 0xe2, 0x0f, 0x11, 0xb2, 0x07, 0xf8, + 0xe4, 0xbb, 0xd5, 0xe9, 0xe1, 0x3f, 0x10, 0xcd, 0x4c, 0x01, 0xcf, 0x12, + 0xee, 0xd7, 0xca, 0xcd, 0xc6, 0x1c, 0xd6, 0xd0, 0xec, 0xec, 0x14, 0x34, + 0xb8, 0xca, 0x1c, 0xf0, 0xdf, 0xd4, 0xd2, 0x10, 0xf4, 0xf1, 0x0b, 0x1c, + 0x28, 0x23, 0x26, 0xdf, 0xf1, 0x01, 0xf6, 0xff, 0x07, 0xde, 0xf3, 0xf8, + 0x0b, 0x1c, 0x04, 0x0a, 0x0c, 0x19, 0xea, 0x2b, 0xce, 0xf3, 0xf3, 0x06, + 0xfd, 0xbd, 0xe1, 0xfa, 0x00, 0xd6, 0xc9, 0xfa, 0x3a, 0xed, 0x3d, 0xf9, + 0x25, 0x0d, 0x13, 0xf5, 0xfb, 0xee, 0xcc, 0x1a, 0xe6, 0xd2, 0x24, 0x26, + 0x13, 0x37, 0xe9, 0xe6, 0xfe, 0x26, 0x0b, 0xf4, 0xc9, 0x08, 0x1a, 0x2d, + 0x0d, 0x00, 0xfa, 0xf6, 0xf0, 0xed, 0x5c, 0x0c, 0x5f, 0x15, 0x18, 0xc3, + 0x32, 0x19, 0x10, 0xd7, 0x09, 0xb7, 0x51, 0xf7, 0xf8, 0xf2, 0xfb, 0x00, + 0xd4, 0xe8, 0x4e, 0xea, 0xfb, 0xdb, 0x1d, 0x0e, 0xd9, 0x11, 0xdc, 0x26, + 0x34, 0xd4, 0x1e, 0x18, 0xf9, 0xfc, 0x07, 0x0e, 0xd6, 0xe7, 0x04, 0xec, + 0xac, 0x02, 0x11, 0x4a, 0x4c, 0x43, 0xef, 0xf2, 0xcb, 0x1d, 0xf2, 0xe7, + 0x10, 0xf7, 0x40, 0x24, 0xe7, 0xe0, 0xda, 0xd1, 0x4e, 0xfa, 0xf3, 0xf8, + 0xf9, 0x10, 0x0f, 0xe1, 0xf6, 0xe2, 0xf0, 0x17, 0xe8, 0x01, 0xfa, 0x21, + 0xe8, 0x06, 0x85, 0x40, 0xdd, 0xf0, 0xf5, 0xf5, 0x1d, 0xfb, 0x54, 0x87, + 0x0c, 0x15, 0xea, 0xd2, 0x00, 0x11, 0x37, 0xf9, 0x31, 0x39, 0xf1, 0x08, + 0x7f, 0xf4, 0x2c, 0x18, 0xe9, 0xee, 0x33, 0x05, 0x18, 0xed, 0xf7, 0xee, + 0xc1, 0x01, 0x29, 0xd1, 0xf5, 0xe1, 0x0f, 0xfd, 0xec, 0x1d, 0xe5, 0xdc, + 0x0e, 0x01, 0xdd, 0xf7, 0xce, 0xda, 0x08, 0xe7, 0xd5, 0x00, 0xef, 0xf6, + 0xcd, 0x04, 0x09, 0x18, 0xf6, 0xe1, 0xe6, 0x37, 0x12, 0xd5, 0xf6, 0xcf, + 0x19, 0x18, 0x4e, 0xa8, 0xde, 0xee, 0xe2, 0xef, 0x35, 0xaf, 0xe1, 0x08, + 0xeb, 0xff, 0xf0, 0xd8, 0x0c, 0xb2, 0xf3, 0xdf, 0xe9, 0x0b, 0xf6, 0xfb, + 0x18, 0x1c, 0x1e, 0xb0, 0xc6, 0xf1, 0x14, 0xee, 0xf5, 0xed, 0xf6, 0x0d, + 0x0c, 0xfb, 0x0a, 0xe9, 0x04, 0xc3, 0xe9, 0x14, 0x69, 0xf2, 0x41, 0xf6, + 0x3b, 0xf6, 0xe7, 0x11, 0xd4, 0xf1, 0x4f, 0x0a, 0xe2, 0xfb, 0x24, 0xaf, + 0xf7, 0xf7, 0x66, 0xed, 0xf4, 0xc6, 0x22, 0xe9, 0xf2, 0x51, 0x0e, 0x17, + 0x45, 0x9b, 0xe1, 0x1c, 0xcc, 0x8e, 0xb7, 0xff, 0xd4, 0xb5, 0xc2, 0xb7, + 0xed, 0x0a, 0x06, 0x3a, 0x1a, 0xe3, 0x0b, 0xc2, 0xaa, 0xde, 0xb3, 0xee, + 0xf1, 0xe1, 0x2a, 0x08, 0xdd, 0xd3, 0xe0, 0xdf, 0xf4, 0x29, 0x1f, 0xdf, + 0xea, 0xda, 0xdd, 0xf5, 0xd7, 0xd1, 0xd6, 0xed, 0x09, 0xea, 0xec, 0x1f, + 0x32, 0xf9, 0x02, 0xcc, 0xed, 0xc8, 0xf3, 0xf2, 0xe4, 0xed, 0x0a, 0x2a, + 0xef, 0xfb, 0x12, 0x18, 0x29, 0x30, 0x4c, 0xd9, 0xfe, 0x10, 0xe0, 0xe5, + 0xdd, 0x42, 0xfb, 0x01, 0x2e, 0x03, 0x0b, 0x2f, 0x1a, 0x1d, 0xee, 0xd6, + 0xcc, 0x06, 0x27, 0xef, 0xe3, 0x02, 0x23, 0x7f, 0x00, 0xdb, 0x11, 0xde, + 0x03, 0x1b, 0x34, 0xfe, 0x2b, 0x0a, 0xfe, 0xf6, 0xcb, 0xf7, 0xcb, 0x10, + 0xf9, 0xf8, 0xe5, 0x11, 0x0f, 0x04, 0x02, 0xf5, 0x06, 0x05, 0xfd, 0xfc, + 0xbc, 0x0a, 0xdf, 0x39, 0xfd, 0x0a, 0x26, 0x10, 0x39, 0x0c, 0x21, 0x06, + 0xd4, 0xfb, 0x0e, 0xfa, 0xf9, 0xff, 0xf4, 0xef, 0x00, 0xdd, 0x27, 0x10, + 0xed, 0xf4, 0xf9, 0xca, 0xfd, 0x1b, 0x01, 0x0e, 0x07, 0xdf, 0x34, 0xbb, + 0xef, 0x1f, 0x26, 0xf3, 0xd6, 0xef, 0x0f, 0x37, 0xdf, 0xdc, 0x0d, 0xd1, + 0xc9, 0x1b, 0x11, 0x0b, 0x59, 0x07, 0x49, 0x1b, 0x15, 0xf1, 0xf6, 0xbe, + 0x07, 0x5b, 0x10, 0xf1, 0xb9, 0xf6, 0x0f, 0x02, 0xf9, 0x07, 0xfc, 0xd9, + 0x34, 0xeb, 0xfd, 0x1f, 0xf6, 0xfa, 0x06, 0x0a, 0xee, 0x00, 0xf9, 0x15, + 0xfc, 0x11, 0x13, 0xd5, 0xdf, 0xc0, 0xee, 0xe0, 0x12, 0x25, 0x06, 0xf9, + 0x0b, 0x05, 0x66, 0xba, 0xd2, 0x1e, 0x13, 0xd4, 0xf7, 0x28, 0x4d, 0xca, + 0x17, 0xf7, 0x19, 0x05, 0xf2, 0x0c, 0xca, 0x29, 0x14, 0xd2, 0xd9, 0x04, + 0x09, 0xf3, 0xd9, 0xc5, 0x30, 0xf0, 0xe7, 0xf9, 0xff, 0xaf, 0xf2, 0x36, + 0x23, 0x1d, 0x2f, 0x24, 0xed, 0x2d, 0x33, 0xdc, 0xe0, 0x10, 0xe9, 0xee, + 0xd4, 0x19, 0xc4, 0xe8, 0x47, 0x56, 0xec, 0x0f, 0xcf, 0x29, 0x01, 0xa2, + 0xbf, 0xf5, 0xf3, 0xeb, 0xdb, 0xcc, 0xed, 0x73, 0x33, 0xd3, 0x1b, 0xe0, + 0xeb, 0xdd, 0x17, 0xee, 0x1d, 0xf5, 0x07, 0xe4, 0x1b, 0x0b, 0xd8, 0x14, + 0xfe, 0x05, 0xf9, 0x09, 0x18, 0xeb, 0xf4, 0xc2, 0x28, 0x04, 0x08, 0xe6, + 0xe4, 0xd7, 0xfe, 0x41, 0x2c, 0x42, 0x30, 0xfd, 0xf1, 0x1f, 0x02, 0xc5, + 0x26, 0xde, 0x00, 0xee, 0xe3, 0x09, 0xe3, 0x2a, 0x04, 0xb9, 0xf7, 0xe6, + 0x02, 0xf1, 0x04, 0x08, 0x17, 0xbd, 0x19, 0x07, 0xa6, 0x0a, 0xad, 0x46, + 0xf2, 0x2a, 0x1d, 0x0d, 0x29, 0x16, 0x29, 0xd7, 0xf5, 0xe0, 0xc5, 0x0a, + 0xbb, 0xdf, 0x01, 0x40, 0x31, 0x0a, 0x17, 0x2a, 0x34, 0x5e, 0xf0, 0xe5, + 0xdc, 0xeb, 0xf0, 0xff, 0xb3, 0xe1, 0xe3, 0x67, 0x08, 0xb6, 0xda, 0xd8, + 0xe0, 0x1f, 0xfa, 0xe9, 0xf8, 0xfd, 0x2b, 0xfe, 0xf8, 0x2c, 0xd1, 0x37, + 0xfd, 0xf7, 0xef, 0xfc, 0x0c, 0xc4, 0xf7, 0xe8, 0x22, 0xee, 0xfb, 0xf2, + 0x96, 0xeb, 0xba, 0xa0, 0x28, 0x36, 0x1c, 0x11, 0x14, 0x9a, 0x10, 0xef, + 0x1b, 0xdc, 0x04, 0xe5, 0xfb, 0xfd, 0xcb, 0x03, 0xa2, 0xf0, 0x4d, 0xbd, + 0xde, 0xc8, 0x1c, 0xc7, 0xdd, 0xaa, 0x11, 0x00, 0x9b, 0xf6, 0x2c, 0x1c, + 0xd0, 0x0a, 0x2f, 0xfe, 0x28, 0xb3, 0xcd, 0xeb, 0x01, 0x12, 0x1c, 0xd7, + 0xe0, 0xf8, 0xcf, 0x1e, 0x2a, 0xf9, 0x7f, 0x13, 0xff, 0x18, 0xce, 0xe4, + 0x07, 0xf1, 0x17, 0xf2, 0xf2, 0x36, 0x30, 0x18, 0x1c, 0x43, 0xf3, 0xf9, + 0x38, 0xa4, 0xf1, 0xec, 0xd3, 0xf2, 0x23, 0x06, 0xd9, 0xee, 0xd8, 0x22, + 0xe8, 0xee, 0x50, 0xa5, 0xd1, 0xd6, 0x18, 0xd6, 0x02, 0xce, 0xfb, 0x0e, + 0x82, 0xdd, 0x3b, 0x1b, 0xf5, 0x1c, 0x17, 0xeb, 0xc0, 0xde, 0x24, 0xc4, + 0x38, 0x16, 0x44, 0xcd, 0x0a, 0x21, 0xd2, 0x05, 0xfb, 0xc4, 0xda, 0xfa, + 0x0a, 0xf9, 0xc8, 0xd1, 0x0e, 0xf3, 0x26, 0xf3, 0xb2, 0x08, 0xbd, 0x5e, + 0x09, 0x36, 0x2e, 0xc3, 0x17, 0xbd, 0x4d, 0xdd, 0x23, 0xf9, 0xfe, 0xf7, + 0xb4, 0x11, 0xf5, 0x34, 0x1e, 0x3c, 0x17, 0x07, 0x3e, 0x44, 0x01, 0xe4, + 0xf9, 0x05, 0xfd, 0xf4, 0xcc, 0x09, 0xbe, 0x59, 0x0f, 0xf4, 0xf1, 0xf4, + 0xe1, 0xe6, 0x35, 0xe3, 0x67, 0x18, 0x34, 0xcb, 0x24, 0x39, 0xb4, 0x25, + 0xec, 0xd5, 0x03, 0xdb, 0xfd, 0x04, 0xe8, 0xe3, 0x29, 0xfd, 0x23, 0xda, + 0x9b, 0x26, 0xc3, 0x43, 0x22, 0x2f, 0x1a, 0xef, 0x2c, 0xf9, 0x18, 0x33, + 0xdf, 0xff, 0x07, 0xf3, 0xf3, 0xf9, 0x38, 0xfa, 0xd7, 0x26, 0x03, 0x20, + 0x24, 0x31, 0xfb, 0xee, 0xef, 0x01, 0x0a, 0xd3, 0x3e, 0xdb, 0x31, 0xbb, + 0xfb, 0xfd, 0x07, 0xfa, 0x06, 0x16, 0xdc, 0x2b, 0xf5, 0x33, 0x0b, 0xf4, + 0x30, 0x03, 0xf2, 0xdf, 0xe8, 0xc7, 0xc2, 0x21, 0xe1, 0xb1, 0xe7, 0x1e, + 0xec, 0x00, 0x1a, 0xe0, 0x78, 0xcf, 0x4d, 0xb3, 0xf4, 0xdb, 0x08, 0xdf, + 0x21, 0x13, 0x02, 0x26, 0xd0, 0xc2, 0x03, 0xfc, 0x08, 0xd7, 0x51, 0xf0, + 0xe2, 0x24, 0x03, 0x27, 0x07, 0x1f, 0xf2, 0xed, 0xfc, 0x07, 0xf0, 0xe1, + 0x43, 0x01, 0x26, 0xc8, 0xf8, 0xfd, 0xee, 0x0d, 0xee, 0x1d, 0xf8, 0x2f, + 0xff, 0xdd, 0x08, 0xe7, 0xfd, 0x16, 0x2d, 0xec, 0xdd, 0x00, 0xe8, 0xf6, + 0x1b, 0x2f, 0x19, 0xea, 0xeb, 0x70, 0xc5, 0xe2, 0x0b, 0xf2, 0xd7, 0x0d, + 0x03, 0x08, 0x04, 0xff, 0xf2, 0x12, 0xff, 0x3a, 0xe9, 0xba, 0x16, 0xf6, + 0xee, 0x2d, 0x12, 0xc6, 0xb8, 0xff, 0x83, 0xf9, 0x06, 0xd7, 0xce, 0x1a, + 0x05, 0x09, 0x0a, 0xe4, 0xe5, 0xef, 0xe8, 0xda, 0xdb, 0xc0, 0xd1, 0xca, + 0xf7, 0x23, 0xe4, 0x1c, 0x08, 0xf9, 0x04, 0xf7, 0xeb, 0x27, 0x38, 0xf0, + 0xf9, 0xea, 0xdb, 0xfe, 0x1b, 0x30, 0xe0, 0xf4, 0x0e, 0x62, 0xfb, 0xea, + 0x25, 0x07, 0xee, 0xfc, 0x08, 0x09, 0xe1, 0xd1, 0x33, 0xf6, 0x18, 0x32, + 0xe7, 0x12, 0xf3, 0x27, 0xfd, 0xbd, 0x52, 0xcd, 0xa3, 0x36, 0x25, 0x17, + 0x08, 0x37, 0x09, 0x05, 0xee, 0x14, 0xfe, 0xeb, 0x5d, 0x01, 0x45, 0xe1, + 0xee, 0x06, 0x07, 0xee, 0xf3, 0x16, 0xe2, 0x16, 0x04, 0x3c, 0x08, 0xf9, + 0x39, 0x23, 0x12, 0xd7, 0xe1, 0xa4, 0xde, 0x0e, 0xb1, 0xf1, 0xbe, 0x18, + 0x16, 0xe5, 0x22, 0x0b, 0x7f, 0xf6, 0x49, 0xea, 0x09, 0xe9, 0xe8, 0xb8, + 0x1d, 0x05, 0x1d, 0xed, 0xf2, 0x13, 0xd9, 0xf6, 0x12, 0xe5, 0x68, 0xe6, + 0xd5, 0x18, 0x21, 0x17, 0xfd, 0x2a, 0xef, 0xef, 0x08, 0xf8, 0x10, 0x11, + 0x4e, 0xfb, 0x37, 0xf5, 0xfc, 0xf0, 0xf5, 0xf9, 0x15, 0xfe, 0x22, 0x23, + 0x08, 0xfd, 0xf9, 0x08, 0x00, 0xee, 0x02, 0xf9, 0xe5, 0x15, 0x0c, 0x05, + 0x07, 0x05, 0x14, 0x05, 0xf7, 0x0f, 0x31, 0xdf, 0x1b, 0x1c, 0x0c, 0xde, + 0xfe, 0xfc, 0x04, 0x02, 0x09, 0x11, 0x16, 0x0d, 0x37, 0xf1, 0xf7, 0xfc, + 0x2a, 0x47, 0xf3, 0xe6, 0x04, 0xe4, 0x00, 0x09, 0xe7, 0x1e, 0xf1, 0x11, + 0xe2, 0xfd, 0x38, 0xe5, 0xfc, 0xea, 0x0a, 0x2a, 0x19, 0xf2, 0xec, 0xd7, + 0x2f, 0x0b, 0xfa, 0x01, 0x23, 0x12, 0xf8, 0x09, 0x00, 0xd5, 0x13, 0xf8, + 0xe8, 0xec, 0x0d, 0x3d, 0xfc, 0x0a, 0xfd, 0x15, 0xb3, 0xfb, 0x29, 0xd0, + 0x2c, 0x37, 0x23, 0xe8, 0xe6, 0xee, 0x0e, 0x0d, 0x2d, 0x1b, 0x2c, 0x1f, + 0xf7, 0x1f, 0x26, 0xfb, 0x04, 0x2f, 0x4f, 0xfb, 0xea, 0x05, 0xd9, 0xee, + 0xd7, 0x04, 0xfa, 0xf1, 0x29, 0x1d, 0x14, 0x09, 0x07, 0x35, 0x4c, 0xc6, + 0xf2, 0xfd, 0xee, 0xee, 0xdd, 0x18, 0x15, 0x0c, 0xeb, 0xe4, 0xec, 0xfc, + 0xea, 0x20, 0x7f, 0xb5, 0xb3, 0xff, 0x36, 0x02, 0x12, 0xbf, 0xf8, 0x19, + 0xfd, 0xe7, 0x21, 0x07, 0xc9, 0x19, 0x00, 0xe4, 0xd1, 0xcb, 0x05, 0xd4, + 0x3e, 0x1b, 0x01, 0x27, 0xff, 0xfc, 0x1d, 0x0e, 0x30, 0x29, 0x2d, 0x00, + 0xee, 0x01, 0x02, 0x09, 0x01, 0x0f, 0xe7, 0xef, 0x19, 0x1a, 0x0b, 0xe9, + 0x2c, 0x16, 0x4e, 0xe1, 0xf1, 0xf0, 0xe7, 0xd3, 0x16, 0xed, 0x0d, 0x36, + 0xfc, 0xf9, 0xf3, 0xd9, 0xfe, 0xd6, 0x00, 0xf8, 0xed, 0xee, 0xf2, 0x07, + 0xfa, 0x0a, 0x04, 0xd2, 0x23, 0x04, 0x0f, 0x24, 0x0b, 0x25, 0x0a, 0xf8, + 0x0b, 0x00, 0x12, 0xf6, 0xd9, 0xff, 0xbb, 0x1c, 0x03, 0xca, 0xda, 0xc0, + 0xf6, 0x03, 0xf0, 0xc1, 0xe7, 0xfe, 0xe1, 0xe6, 0xa9, 0x3b, 0xf2, 0xca, + 0xfd, 0xbf, 0x61, 0x09, 0xdd, 0xdc, 0xf6, 0x37, 0x10, 0xcf, 0x21, 0xe0, + 0x15, 0x00, 0x1f, 0x08, 0x1b, 0xe3, 0xed, 0xf6, 0x03, 0xd3, 0xf2, 0xee, + 0xda, 0x0d, 0xe2, 0x2f, 0x0f, 0x03, 0xfc, 0xd8, 0xe0, 0xdf, 0x30, 0x02, + 0xfe, 0x22, 0x09, 0xfe, 0x0a, 0xfa, 0x0b, 0x0e, 0x0b, 0xe9, 0xf9, 0xd8, + 0xe5, 0xdd, 0x02, 0xf8, 0x07, 0x0d, 0x26, 0xf9, 0xf5, 0x08, 0xf4, 0xfc, + 0x2a, 0x05, 0xf2, 0xe4, 0x0f, 0xee, 0xe9, 0xe8, 0x24, 0xbc, 0x03, 0x00, + 0x19, 0x1c, 0x10, 0xf5, 0x2e, 0x02, 0xf6, 0xea, 0xf3, 0x07, 0xc7, 0xf9, + 0xee, 0xc3, 0x13, 0xfa, 0xf4, 0x01, 0xe5, 0x26, 0x06, 0xd4, 0x0c, 0x0f, + 0xe4, 0xfb, 0x06, 0xfd, 0x26, 0xd7, 0x18, 0xd1, 0xed, 0xe3, 0x17, 0x05, + 0x19, 0x0e, 0xf9, 0xc7, 0xe9, 0xef, 0x12, 0x06, 0x21, 0x0e, 0x57, 0x01, + 0x02, 0x2d, 0xf4, 0x0f, 0x23, 0x12, 0xf3, 0x03, 0x56, 0xe8, 0xe0, 0x42, + 0x2f, 0xd1, 0x0c, 0xdf, 0x37, 0x1c, 0xf8, 0xe8, 0xef, 0xf5, 0xe3, 0xd6, + 0xe2, 0xe3, 0xf4, 0xdf, 0xd5, 0x01, 0xe9, 0x11, 0x06, 0xf5, 0xdf, 0xda, + 0xdc, 0x12, 0x1d, 0xe7, 0xfe, 0xf1, 0xd8, 0xf9, 0xe9, 0xe7, 0xab, 0x0a, + 0x16, 0x47, 0x27, 0xf8, 0xe4, 0x24, 0xe3, 0xf5, 0xf4, 0xf5, 0x1a, 0xf8, + 0xc4, 0x0d, 0x08, 0x11, 0xdf, 0xea, 0xd9, 0xd8, 0x05, 0x04, 0xf7, 0x01, + 0x01, 0xf9, 0x13, 0x04, 0xe3, 0x07, 0xba, 0xe5, 0xef, 0x12, 0x06, 0x1e, + 0xef, 0xfb, 0xef, 0xf3, 0xd3, 0xe0, 0xea, 0xcd, 0xf1, 0x04, 0x2f, 0x0c, + 0x01, 0xf2, 0xd9, 0xe0, 0xe9, 0x15, 0xfb, 0xe6, 0x38, 0xf6, 0xb9, 0x48, + 0xfb, 0xf1, 0xe1, 0x00, 0x1f, 0x25, 0x22, 0xea, 0xef, 0xd5, 0xef, 0x00, + 0xdf, 0xef, 0xf0, 0x20, 0xed, 0xf1, 0x37, 0xef, 0xe9, 0x2e, 0x09, 0xde, + 0xf1, 0xd5, 0x1f, 0x06, 0x30, 0xe5, 0xdd, 0xec, 0x3f, 0xe1, 0x0d, 0xd8, + 0x0f, 0x29, 0x0f, 0xe3, 0x04, 0xef, 0xee, 0x13, 0xe7, 0x24, 0xdd, 0xe8, + 0xe5, 0xfa, 0x18, 0xe8, 0xc5, 0x00, 0xdc, 0x15, 0x03, 0xe1, 0x02, 0x11, + 0x11, 0xf3, 0xf7, 0x27, 0x19, 0xe1, 0x11, 0xe5, 0xf0, 0xf7, 0xfd, 0xfc, + 0xf1, 0xcd, 0xe8, 0xef, 0xce, 0x10, 0x24, 0xfe, 0x04, 0xc8, 0x6d, 0xf6, + 0xfa, 0x37, 0xe6, 0xf3, 0x0d, 0xe1, 0xd9, 0x00, 0x7f, 0xde, 0xd7, 0x63, + 0x2b, 0xed, 0x02, 0xb3, 0x19, 0x27, 0x1b, 0xd8, 0xfc, 0xc3, 0x07, 0x25, + 0x23, 0xf2, 0xed, 0xe5, 0xf2, 0xc2, 0xd1, 0xe5, 0x0d, 0xfc, 0xef, 0xee, + 0xe7, 0xf6, 0x0b, 0xbb, 0x0d, 0xfb, 0x11, 0x00, 0xfd, 0x32, 0xe5, 0x25, + 0x25, 0x05, 0x1e, 0xf3, 0xde, 0xca, 0xc5, 0x0c, 0xfd, 0xcf, 0x08, 0x1c, + 0xfa, 0x11, 0xdd, 0xf6, 0xfe, 0x10, 0xe4, 0x04, 0xa3, 0x2a, 0x0c, 0xfd, + 0x14, 0xf2, 0x2d, 0x00, 0xb6, 0xe2, 0xf2, 0x11, 0xfa, 0x28, 0x54, 0x07, + 0xd3, 0xe5, 0xff, 0x1a, 0x41, 0xf9, 0xcd, 0xe5, 0x4f, 0xcb, 0x09, 0xce, + 0x10, 0x02, 0xed, 0x10, 0x0d, 0xf6, 0x0e, 0xe3, 0xaf, 0xfe, 0x1c, 0xe6, + 0x12, 0x58, 0x05, 0xfc, 0x43, 0xf8, 0x1d, 0x05, 0x7f, 0xe8, 0x20, 0xb9, + 0xff, 0x21, 0x25, 0xf0, 0x12, 0x16, 0xf5, 0xeb, 0xfe, 0x1d, 0x01, 0xd9, + 0xcb, 0xda, 0xc4, 0xd4, 0x11, 0xd8, 0x1b, 0x16, 0x00, 0x3a, 0x48, 0xad, + 0x16, 0x0c, 0xeb, 0xe4, 0xaa, 0x3f, 0x1f, 0xcf, 0x29, 0x05, 0xe8, 0x05, + 0x0f, 0x06, 0x60, 0xd8, 0xd9, 0x32, 0x25, 0x10, 0x15, 0xbd, 0x25, 0xfa, + 0xc8, 0xf2, 0x1c, 0xe8, 0xcc, 0x0f, 0x28, 0xe5, 0xce, 0x12, 0x5c, 0x0b, + 0x65, 0xf9, 0x1a, 0xf4, 0x06, 0x20, 0x19, 0xef, 0x39, 0x22, 0xe3, 0x05, + 0xf4, 0xfb, 0x10, 0x28, 0xf8, 0xe2, 0xed, 0xea, 0x03, 0xaa, 0x1b, 0xf6, + 0x06, 0x13, 0x2a, 0xf2, 0x2a, 0xf4, 0xc4, 0xe4, 0x00, 0x09, 0x1f, 0x18, + 0x1c, 0xf1, 0x0c, 0xf9, 0x04, 0xc4, 0xf6, 0x30, 0x0d, 0xfb, 0xec, 0xf0, + 0x07, 0xff, 0xf8, 0xdb, 0x23, 0x39, 0x02, 0x17, 0xea, 0x1e, 0xf2, 0x20, + 0x4f, 0x0e, 0x1b, 0x03, 0xce, 0xfb, 0xe9, 0x04, 0xc8, 0xc8, 0xe0, 0x0a, + 0xd7, 0x23, 0xe0, 0xed, 0x0d, 0x46, 0xe1, 0xf9, 0xa7, 0x3d, 0x13, 0xc5, + 0x13, 0xfe, 0x49, 0x03, 0xb3, 0xc3, 0xe0, 0x69, 0xee, 0xde, 0x5a, 0xf9, + 0xe7, 0xf0, 0xfa, 0x2b, 0x2c, 0xf6, 0xca, 0xf7, 0x3b, 0xcf, 0xe1, 0x13, + 0x0a, 0xf2, 0xfa, 0x0e, 0x0b, 0xc8, 0x04, 0xe5, 0xeb, 0x1c, 0x25, 0xfc, + 0xf2, 0x4a, 0xf2, 0xf8, 0x57, 0x2c, 0x1a, 0x04, 0xe7, 0xd6, 0xf6, 0x1d, + 0x17, 0x10, 0xd8, 0xd4, 0x05, 0x08, 0x0e, 0xf8, 0xe5, 0xe1, 0xf5, 0x20, + 0x2d, 0xea, 0xfe, 0xe9, 0x0a, 0xea, 0xfe, 0x0a, 0x16, 0x40, 0x0e, 0x0c, + 0xec, 0xc9, 0xde, 0xcb, 0x06, 0xc3, 0x05, 0x3f, 0x0f, 0x04, 0x31, 0xf6, + 0xea, 0x37, 0x2e, 0x35, 0xa5, 0x1b, 0x05, 0x64, 0x42, 0xc8, 0x05, 0xfd, + 0x0f, 0x22, 0xfc, 0xf2, 0x06, 0x42, 0x30, 0xd8, 0xf5, 0xd4, 0xd2, 0xd2, + 0xd9, 0xea, 0x02, 0x20, 0x0c, 0xfc, 0x04, 0xe7, 0xf3, 0x01, 0xfd, 0x2a, + 0xf8, 0xe4, 0xe8, 0xfe, 0x1b, 0xe4, 0xeb, 0xff, 0x31, 0x25, 0x06, 0xe7, + 0x21, 0x1c, 0xff, 0xee, 0xfb, 0x0f, 0xff, 0xd7, 0xc1, 0xda, 0xfd, 0x17, + 0x3e, 0xf8, 0xdd, 0xf5, 0xf2, 0xe3, 0xdd, 0xae, 0xd1, 0x1e, 0xba, 0xd3, + 0xd5, 0x19, 0xf6, 0xc9, 0xf5, 0xe3, 0xf1, 0x03, 0x0e, 0x10, 0xc0, 0x50, + 0xec, 0xc9, 0x02, 0xe8, 0xb3, 0x0d, 0xed, 0x18, 0x08, 0xf6, 0xfd, 0x96, + 0xe1, 0xef, 0xde, 0x10, 0x27, 0xce, 0x3f, 0xd0, 0xb3, 0x36, 0xe7, 0xd0, + 0x0e, 0x01, 0xfb, 0xf1, 0xb7, 0x1f, 0xbb, 0x59, 0xde, 0x23, 0xec, 0x06, + 0xe2, 0xdf, 0x0c, 0xe4, 0x35, 0x06, 0x06, 0x01, 0xe2, 0xf5, 0xe6, 0xee, + 0xf3, 0x06, 0xd5, 0xd4, 0xf2, 0x07, 0xfd, 0xb0, 0x17, 0xe0, 0xea, 0xf9, + 0x26, 0xec, 0xd6, 0x55, 0xf4, 0x24, 0x2f, 0xf4, 0xdd, 0xfc, 0x23, 0x2d, + 0x33, 0x15, 0x15, 0xe5, 0x10, 0x2f, 0x0d, 0x11, 0x0a, 0xee, 0xe3, 0x0c, + 0x2d, 0x02, 0x07, 0xd5, 0x25, 0x2d, 0x13, 0xfa, 0x0a, 0x4d, 0xed, 0x39, + 0xed, 0xfa, 0xf8, 0xec, 0x05, 0xea, 0x1b, 0x4a, 0x24, 0x01, 0x42, 0x11, + 0xf4, 0x2c, 0x24, 0x52, 0x14, 0x4a, 0x0d, 0x7f, 0x6f, 0xff, 0x1f, 0xc0, + 0xfa, 0x3a, 0x07, 0xd7, 0xe8, 0x43, 0x29, 0x30, 0x1a, 0x11, 0xea, 0xcd, + 0xf4, 0xf7, 0x08, 0x58, 0x39, 0xf3, 0x25, 0xe5, 0xeb, 0x1d, 0x03, 0x20, + 0xec, 0xed, 0xf3, 0x04, 0x21, 0xf8, 0xfb, 0xee, 0x32, 0x19, 0x21, 0x00, + 0xc7, 0x39, 0xe0, 0x1c, 0xf8, 0x10, 0x12, 0xee, 0x11, 0x16, 0x3b, 0xd8, + 0xee, 0xe7, 0xe8, 0xfe, 0xe6, 0xe8, 0xed, 0xf7, 0xfa, 0xdc, 0xf0, 0x0b, + 0x23, 0xfe, 0xfe, 0xd7, 0x01, 0xe7, 0xf0, 0xf9, 0xfb, 0xe9, 0xfd, 0x02, + 0x05, 0xf5, 0x15, 0x07, 0x29, 0x30, 0x38, 0xd4, 0xdc, 0xf3, 0xe4, 0xd7, + 0xf7, 0x1d, 0xf1, 0x16, 0x34, 0xe4, 0x10, 0x11, 0x0a, 0xf4, 0xd5, 0xde, + 0xdc, 0xf8, 0x1a, 0x01, 0x04, 0xce, 0x1c, 0x7f, 0xf1, 0xd7, 0x05, 0xde, + 0x17, 0x23, 0x3e, 0xe6, 0x2b, 0xe7, 0xde, 0xfe, 0xa7, 0xe1, 0xca, 0x0c, + 0xf7, 0x01, 0xfc, 0x0f, 0x23, 0x19, 0x08, 0xf8, 0xfb, 0xfe, 0x00, 0x02, + 0xc9, 0x08, 0x16, 0x25, 0xf4, 0xce, 0x09, 0x10, 0x33, 0x12, 0x22, 0x23, + 0xd2, 0x02, 0x1f, 0xf4, 0xe4, 0xf9, 0x17, 0x10, 0x0c, 0xc1, 0x36, 0x06, + 0xfe, 0xeb, 0xfc, 0xd9, 0xe5, 0x2a, 0xfd, 0xfa, 0xff, 0xf3, 0x27, 0xc0, + 0xe2, 0x1a, 0x1f, 0xea, 0xcc, 0xdd, 0x26, 0x2f, 0xbd, 0xd3, 0x06, 0xe1, + 0xc8, 0x1d, 0x0c, 0xed, 0x60, 0xfb, 0x4b, 0x1c, 0x0c, 0xfc, 0xf4, 0xaa, + 0x14, 0x25, 0xfb, 0xf4, 0xb8, 0xfc, 0x01, 0x28, 0x01, 0xf4, 0xe3, 0xec, + 0x47, 0x00, 0x05, 0x14, 0xe4, 0x12, 0x16, 0x02, 0xd3, 0x06, 0x2e, 0xeb, + 0x1c, 0x06, 0xfd, 0xe0, 0x01, 0xda, 0xfe, 0xd5, 0x11, 0x30, 0x1a, 0xee, + 0x07, 0x03, 0x5e, 0xaf, 0xc7, 0x35, 0x0f, 0xe2, 0xf3, 0x26, 0x46, 0xc8, + 0x16, 0x00, 0x33, 0x00, 0xea, 0x15, 0xe0, 0x25, 0xf9, 0xdf, 0xf9, 0x04, + 0x0e, 0x20, 0xd9, 0xcb, 0x22, 0xeb, 0xf9, 0xdb, 0xf3, 0xda, 0xf4, 0x25, + 0x09, 0x19, 0x22, 0x3c, 0x07, 0x3e, 0x50, 0xe0, 0xff, 0x21, 0xe9, 0xe4, + 0xec, 0x20, 0xc0, 0xfa, 0x44, 0x1d, 0xf9, 0x04, 0xf0, 0x1e, 0xf8, 0xe0, + 0x9a, 0x0c, 0x2a, 0xed, 0xf2, 0xe9, 0x06, 0x3a, 0x1a, 0xd5, 0x0b, 0xdb, + 0x04, 0x02, 0x23, 0xd2, 0xfc, 0x1a, 0x26, 0xfc, 0xeb, 0x11, 0xbd, 0x22, + 0xfc, 0xff, 0xfb, 0xfe, 0x17, 0x09, 0xdd, 0xe4, 0x26, 0xff, 0xee, 0xea, + 0xc6, 0xc8, 0xe7, 0x17, 0x26, 0x3f, 0x1f, 0x01, 0xff, 0x1d, 0xe2, 0xd9, + 0xea, 0x52, 0x3f, 0x21, 0xc9, 0x62, 0xb6, 0x49, 0xfc, 0xef, 0x04, 0x09, + 0x1c, 0xd4, 0x0c, 0x0f, 0xf7, 0xe5, 0xcc, 0xd8, 0xdd, 0xb0, 0xe7, 0x1d, + 0xe1, 0x45, 0x17, 0x48, 0x54, 0x38, 0x09, 0xda, 0xc8, 0x75, 0xff, 0xe4, + 0xed, 0x04, 0x16, 0x08, 0x48, 0xd5, 0x39, 0x13, 0x39, 0x05, 0xbc, 0xf3, + 0xc9, 0xcf, 0xfc, 0x00, 0x07, 0x18, 0x21, 0x51, 0x23, 0xc7, 0xd5, 0xf5, + 0x0b, 0x44, 0xfc, 0xad, 0x0d, 0x3b, 0xef, 0x24, 0x14, 0x20, 0x07, 0xf6, + 0x07, 0xed, 0xf5, 0x08, 0x1d, 0x06, 0xe4, 0x2d, 0xbc, 0xc9, 0x00, 0xe7, + 0x00, 0xcd, 0x1c, 0x1e, 0xe8, 0x02, 0x21, 0x26, 0x07, 0x06, 0x91, 0x10, + 0xd1, 0xe9, 0xbc, 0x2b, 0xbb, 0xe4, 0xf5, 0x09, 0x05, 0xeb, 0x37, 0xbc, + 0xcc, 0x1f, 0x54, 0xe9, 0x02, 0x5a, 0xd2, 0xef, 0x1a, 0x9c, 0xf6, 0x32, + 0xd6, 0x41, 0x60, 0x2a, 0x10, 0xcf, 0xe9, 0x72, 0xe0, 0xd5, 0xf3, 0xf4, + 0xa5, 0x17, 0xb2, 0x03, 0x7f, 0xdc, 0x62, 0xe8, 0xef, 0x4f, 0xdf, 0xb7, + 0x24, 0x3e, 0xd6, 0xf8, 0xa2, 0xe8, 0xd6, 0x42, 0xdf, 0xc5, 0xaf, 0xee, + 0x26, 0xe5, 0xd0, 0x37, 0xe6, 0xef, 0xd7, 0x45, 0xd5, 0xfa, 0x37, 0xfc, + 0x0e, 0xea, 0x5f, 0xdb, 0xd4, 0x1a, 0x4b, 0xff, 0x12, 0x72, 0xd6, 0x00, + 0x0b, 0xde, 0x44, 0x4a, 0x8d, 0x2b, 0x55, 0xd0, 0xcb, 0x54, 0x2d, 0xca, + 0x02, 0x2e, 0x3a, 0x1a, 0xce, 0x5f, 0xab, 0x10, 0x09, 0x1d, 0xff, 0xe5, + 0x08, 0x05, 0xda, 0x20, 0x38, 0xf4, 0xc2, 0xef, 0xc1, 0x94, 0xd9, 0x2a, + 0xfe, 0x21, 0xf1, 0xda, 0x6d, 0x26, 0x0d, 0xe9, 0x25, 0x59, 0xed, 0xb2, + 0xf4, 0xf8, 0xb0, 0xd6, 0xff, 0x25, 0xcd, 0x11, 0x52, 0x10, 0xe7, 0x00, + 0x9c, 0xee, 0xab, 0x12, 0xff, 0x0c, 0xef, 0x76, 0x35, 0xa5, 0xd0, 0xd4, + 0xbf, 0x2d, 0x19, 0xb9, 0xed, 0x68, 0x17, 0x47, 0x02, 0x1e, 0x9f, 0x0b, + 0x21, 0x15, 0xfc, 0xb0, 0x03, 0xe6, 0xdf, 0x38, 0x28, 0xd6, 0xaa, 0x0a, + 0xc0, 0x8f, 0xcb, 0x06, 0x0e, 0xf4, 0x40, 0x0b, 0x22, 0x08, 0x1a, 0x0b, + 0xde, 0xe3, 0x16, 0xf2, 0xec, 0x02, 0x32, 0xf0, 0xf2, 0x19, 0xfe, 0xfb, + 0x09, 0x06, 0x04, 0xe9, 0xfe, 0xe8, 0x0f, 0xf9, 0x0a, 0x08, 0xea, 0xe9, + 0x2f, 0x04, 0xfc, 0xf6, 0xe7, 0x2b, 0x04, 0x02, 0xea, 0xfd, 0x1e, 0xfa, + 0xff, 0x15, 0x2c, 0xf1, 0xea, 0x02, 0xec, 0x03, 0x01, 0xe1, 0x0a, 0x14, + 0x0a, 0xf2, 0x0d, 0xfa, 0xec, 0x16, 0x0b, 0xce, 0x04, 0xff, 0x1d, 0xfd, + 0x0e, 0x0c, 0x2c, 0xfb, 0xe9, 0xf2, 0x13, 0xeb, 0x00, 0x09, 0x78, 0xfd, + 0xf7, 0x13, 0xff, 0x06, 0x10, 0x0d, 0xf9, 0xf4, 0x3c, 0xf4, 0x23, 0x29, + 0x2c, 0xfc, 0x0a, 0x01, 0x28, 0x02, 0xf7, 0xfb, 0x08, 0xfb, 0xf1, 0x1d, + 0xe5, 0xe7, 0x34, 0xff, 0xd3, 0x3d, 0x54, 0xe2, 0xb8, 0x09, 0xe1, 0xec, + 0xea, 0x1b, 0x0b, 0xe1, 0x36, 0xf7, 0x2f, 0xfa, 0xca, 0x4d, 0xde, 0xd1, + 0x15, 0xfb, 0xeb, 0xf9, 0xe0, 0xf7, 0xe4, 0x1c, 0xe1, 0xdc, 0x37, 0xf9, + 0xd7, 0x42, 0x1d, 0xe2, 0xc3, 0xe3, 0xbd, 0xfa, 0x19, 0xc4, 0xdf, 0x20, + 0x27, 0xd2, 0x2f, 0x08, 0xf9, 0x57, 0xf0, 0xc7, 0xe8, 0x02, 0x0c, 0xcf, + 0xde, 0xf1, 0xf9, 0x1a, 0xfe, 0xf7, 0x1b, 0xfd, 0xde, 0x4f, 0x64, 0xe9, + 0xdc, 0x11, 0xc1, 0xfa, 0xf3, 0x14, 0xfe, 0xf0, 0x41, 0xf8, 0x2f, 0x39, + 0xff, 0x55, 0xd6, 0xd3, 0x2a, 0x12, 0xfd, 0xe5, 0x1e, 0xf5, 0xdc, 0x04, + 0xc0, 0xaf, 0xcd, 0xef, 0xb0, 0xf4, 0x28, 0xe8, 0xc0, 0xee, 0x13, 0xdb, + 0xc5, 0x03, 0x00, 0xd6, 0x20, 0xeb, 0xfa, 0x14, 0xf4, 0xf5, 0xed, 0xca, + 0xf0, 0xdf, 0xdc, 0xf2, 0xc7, 0x0e, 0xf0, 0x0a, 0x03, 0xd9, 0xe9, 0xce, + 0xdb, 0xf7, 0x2b, 0xec, 0xc9, 0xbe, 0xf1, 0xeb, 0xe9, 0xef, 0xda, 0x09, + 0x20, 0xea, 0x32, 0x08, 0xe1, 0xfc, 0xeb, 0xdf, 0xe0, 0xda, 0xe2, 0xde, + 0x2a, 0x01, 0xeb, 0x01, 0xd3, 0xda, 0xe7, 0xd3, 0xe7, 0xe8, 0x7f, 0xf8, + 0xdd, 0xd5, 0x0b, 0xf9, 0xe5, 0x0b, 0xd1, 0xe3, 0x73, 0x13, 0xfe, 0x5e, + 0x1b, 0xf9, 0xf6, 0xc6, 0x1e, 0x0b, 0xe1, 0xe7, 0x01, 0xe0, 0xd2, 0x7f, + 0x0a, 0xdc, 0xda, 0x20, 0xf4, 0xea, 0xf7, 0xcd, 0xf0, 0x0b, 0x14, 0x30, + 0x39, 0xf5, 0x1f, 0xda, 0xd8, 0xf5, 0xde, 0xf1, 0x0d, 0xe5, 0x3b, 0x12, + 0xa4, 0xd7, 0x0b, 0xf1, 0x3d, 0xd1, 0xa3, 0x76, 0xd7, 0x23, 0x0f, 0xdd, + 0x23, 0x0c, 0x06, 0xd2, 0xff, 0xa8, 0x26, 0x29, 0xf9, 0xe6, 0xf3, 0xf4, + 0x0a, 0xfd, 0xdb, 0xf1, 0x69, 0xe9, 0x44, 0x05, 0xdd, 0x0c, 0xef, 0x26, + 0x07, 0xda, 0xdd, 0x34, 0xdb, 0x00, 0xc5, 0x39, 0xf3, 0xde, 0x0a, 0xc8, + 0xdb, 0x15, 0xf8, 0x30, 0x0d, 0x00, 0x02, 0x09, 0xfe, 0xd5, 0xcf, 0x13, + 0x18, 0xd9, 0x2a, 0x0e, 0xc3, 0x01, 0x0b, 0xca, 0xcc, 0x03, 0xdd, 0x23, + 0x20, 0xd3, 0xfe, 0xe1, 0x17, 0x08, 0xfe, 0x0a, 0xec, 0x0b, 0xed, 0x19, + 0x23, 0xfa, 0x0b, 0x1d, 0xd3, 0x5e, 0xe9, 0xe3, 0x31, 0xdf, 0x3b, 0x42, + 0xbe, 0xde, 0xfc, 0xf6, 0x1a, 0x27, 0x09, 0x39, 0x22, 0xf6, 0xe0, 0x0c, + 0xf9, 0x10, 0xf0, 0x03, 0x17, 0xd1, 0xc1, 0xfe, 0x0f, 0xff, 0xf4, 0xe8, + 0xf1, 0x24, 0x07, 0xdd, 0xf1, 0xdd, 0x06, 0x21, 0xc3, 0xd2, 0xd0, 0x0a, + 0xd9, 0xf9, 0xc4, 0x3b, 0x0c, 0xde, 0xfd, 0xf0, 0xfc, 0x1a, 0x15, 0x08, + 0xf2, 0xfe, 0xed, 0x0f, 0x13, 0xec, 0xf7, 0x13, 0x13, 0x4e, 0xd4, 0xdd, + 0x3d, 0xe8, 0x1f, 0x2f, 0xc0, 0xe4, 0xed, 0xe4, 0xff, 0xfc, 0xf8, 0x3f, + 0xf4, 0x42, 0xe0, 0x21, 0xf0, 0xb8, 0x09, 0xc4, 0xe9, 0x29, 0x0e, 0x30, + 0x19, 0x11, 0x03, 0xf6, 0xa6, 0xeb, 0xf7, 0xeb, 0x32, 0xef, 0x3e, 0xd6, + 0xca, 0xfa, 0x0d, 0xf7, 0x03, 0xdd, 0xdb, 0x55, 0xd1, 0x2b, 0x3d, 0xeb, + 0x34, 0x47, 0x09, 0xf1, 0xfd, 0xb6, 0x18, 0x10, 0xe9, 0xd2, 0xf5, 0x02, + 0x2d, 0x06, 0xdd, 0xec, 0x65, 0x02, 0x1c, 0xc1, 0x19, 0x31, 0xe8, 0x02, + 0x05, 0xe5, 0xf1, 0x41, 0xf5, 0x21, 0xde, 0x1a, 0xe9, 0xd2, 0x27, 0xbb, + 0xd7, 0x15, 0x09, 0x3a, 0x06, 0x0e, 0x0c, 0x11, 0xde, 0x07, 0xf3, 0x0e, + 0x3f, 0x02, 0x35, 0x07, 0xb5, 0xf2, 0xf2, 0xf4, 0xd8, 0xdb, 0xb1, 0x29, + 0x10, 0xe4, 0x10, 0xf3, 0x06, 0x18, 0x1a, 0xde, 0xe2, 0x17, 0x02, 0x10, + 0xfe, 0x03, 0x0e, 0x11, 0xfb, 0x19, 0x06, 0xe2, 0x3b, 0x20, 0x15, 0xdc, + 0xc8, 0xda, 0x04, 0xef, 0xf7, 0xb8, 0xd1, 0x32, 0x20, 0xe9, 0x0b, 0x35, + 0x01, 0xf9, 0xf8, 0xef, 0xcd, 0x9c, 0xb4, 0x35, 0x34, 0xe9, 0x05, 0x25, + 0xfa, 0x0d, 0x09, 0xef, 0x34, 0x1b, 0x11, 0xfe, 0xde, 0xde, 0xf9, 0xd0, + 0xf6, 0xdf, 0xbd, 0xfe, 0x4e, 0x36, 0x1a, 0xcb, 0x3a, 0x22, 0x16, 0xce, + 0xee, 0xee, 0x06, 0xf8, 0xf2, 0xf5, 0xe8, 0x14, 0xc6, 0x05, 0x21, 0xf5, + 0x22, 0x21, 0x03, 0xfa, 0xb6, 0xf0, 0xfd, 0xdb, 0xd6, 0xfc, 0x06, 0xd5, + 0x2b, 0xfd, 0xc1, 0x1b, 0x02, 0xee, 0xb7, 0xd0, 0xd8, 0x16, 0x0c, 0xaf, + 0xca, 0x55, 0x4b, 0xcb, 0xdc, 0xe5, 0x08, 0xeb, 0x81, 0xf5, 0x9c, 0x79, + 0x02, 0x0b, 0x13, 0x21, 0x1a, 0x1c, 0xe2, 0xc0, 0x01, 0xd2, 0xe8, 0xca, + 0xf2, 0xf7, 0xcf, 0xd5, 0xe9, 0xa1, 0x95, 0xd4, 0xec, 0x3f, 0xbf, 0x3b, + 0xfa, 0xb5, 0x1b, 0xe2, 0x21, 0xf9, 0x10, 0x1b, 0xee, 0xd1, 0x04, 0x06, + 0xb3, 0xed, 0x04, 0xe6, 0x2f, 0x01, 0xf1, 0xe2, 0x1f, 0xf4, 0xc3, 0xd1, + 0xd6, 0xe3, 0x06, 0x03, 0xed, 0x31, 0x44, 0xc8, 0xf0, 0xb7, 0xff, 0xf7, + 0xe9, 0x00, 0xdf, 0x60, 0xe5, 0x02, 0x1e, 0xed, 0xcf, 0xe8, 0xb3, 0x1e, + 0x08, 0x3b, 0x3d, 0x27, 0x1f, 0x0e, 0xa4, 0xe9, 0xe8, 0x38, 0xfb, 0xbf, + 0xed, 0xf7, 0x23, 0x1e, 0xf3, 0x0d, 0xfe, 0xc2, 0xb9, 0x35, 0xa3, 0xf7, + 0xf0, 0x02, 0x03, 0x05, 0xef, 0xce, 0xe0, 0x15, 0xe9, 0xfd, 0x05, 0x3a, + 0xf3, 0xd1, 0xb6, 0x00, 0xf7, 0xa9, 0xc0, 0x54, 0x43, 0xc2, 0xe7, 0x24, + 0x1b, 0x37, 0x9b, 0xef, 0xe8, 0x05, 0x12, 0xca, 0x1f, 0xd2, 0xe4, 0xfc, + 0xd8, 0xe5, 0x9a, 0xfc, 0x26, 0x15, 0x1a, 0x0c, 0x22, 0x29, 0x11, 0x08, + 0x2d, 0x11, 0x01, 0x07, 0xfd, 0xdb, 0xf2, 0x07, 0xcc, 0xe0, 0xfc, 0xe0, + 0x2f, 0x0c, 0x16, 0xca, 0xb4, 0x09, 0xe4, 0xef, 0xd5, 0xf0, 0xf5, 0xc9, + 0x11, 0x0d, 0x33, 0xc5, 0xf8, 0x30, 0xeb, 0xff, 0x3b, 0xdf, 0xf4, 0xf1, + 0x08, 0xfe, 0xc3, 0x02, 0xfa, 0xd2, 0xff, 0xfb, 0xde, 0xfc, 0xda, 0x1e, + 0x07, 0xef, 0xb8, 0xc8, 0x0e, 0x1d, 0x1b, 0xe7, 0x21, 0xe7, 0xcb, 0x01, + 0xcf, 0xc3, 0x0b, 0x0d, 0xdc, 0x1f, 0x0a, 0x07, 0x34, 0xf1, 0x1a, 0x0a, + 0xfb, 0x00, 0xdf, 0xfe, 0xe2, 0x15, 0xf5, 0xef, 0xf2, 0x06, 0x12, 0x13, + 0xe1, 0x16, 0xfd, 0xbb, 0xff, 0x14, 0x35, 0xe3, 0x0b, 0x07, 0xfc, 0x10, + 0xfc, 0xc0, 0xde, 0x02, 0x13, 0xf5, 0xb3, 0x09, 0x16, 0xe0, 0xec, 0x08, + 0xf4, 0x06, 0xe1, 0xff, 0x15, 0x06, 0xea, 0xd3, 0xe4, 0xcd, 0xe2, 0xde, + 0x1b, 0xea, 0xd4, 0x04, 0xd7, 0xe3, 0xe5, 0xc1, 0x33, 0x10, 0x23, 0xf7, + 0xd9, 0xe3, 0x06, 0xee, 0xee, 0xc9, 0x08, 0x06, 0xe0, 0xf3, 0xe5, 0x05, + 0xf1, 0x00, 0x2c, 0xf8, 0x33, 0xe7, 0xd4, 0xee, 0xf6, 0xeb, 0x06, 0x0c, + 0xfe, 0xfb, 0xce, 0x14, 0xed, 0xf5, 0xe5, 0xf7, 0xd2, 0x2c, 0x27, 0xec, + 0x17, 0xd6, 0x0b, 0xff, 0x0c, 0x15, 0xfe, 0x19, 0x00, 0x26, 0x20, 0x2d, + 0xf5, 0xf4, 0xd0, 0xff, 0x1c, 0xd6, 0xe7, 0xf6, 0xf9, 0xd4, 0xf1, 0xe9, + 0x23, 0xff, 0xde, 0x06, 0xf3, 0xec, 0x0a, 0xe5, 0xf7, 0xf7, 0xef, 0x20, + 0xf5, 0xe4, 0xee, 0xff, 0x29, 0x0a, 0x2d, 0xe5, 0xdd, 0xfd, 0x14, 0xde, + 0x07, 0x0b, 0x3b, 0xed, 0xf9, 0x40, 0xe8, 0x0b, 0x42, 0xd4, 0x05, 0xfe, + 0xf6, 0xf4, 0xe8, 0x06, 0xfc, 0x15, 0xe9, 0x15, 0xe0, 0xf1, 0xe5, 0x31, + 0xfe, 0xf1, 0xd7, 0xed, 0xfb, 0x40, 0x35, 0xf3, 0x13, 0xe8, 0xeb, 0x0e, + 0xd0, 0xe6, 0x06, 0x28, 0x01, 0x54, 0xfd, 0xff, 0x39, 0xed, 0x21, 0x02, + 0xfd, 0x0e, 0xc8, 0x19, 0xe3, 0x22, 0xe4, 0xdc, 0x0f, 0x14, 0x0d, 0x30, + 0xdb, 0x20, 0x1e, 0xc3, 0x23, 0x09, 0x12, 0xe1, 0x18, 0x54, 0xf4, 0xff, + 0x29, 0xfa, 0x06, 0xef, 0xce, 0x01, 0xe7, 0x07, 0x1f, 0x14, 0xf1, 0x7f, + 0xe2, 0xfc, 0xd9, 0x10, 0x2e, 0xf9, 0xfa, 0xee, 0x3c, 0x16, 0x0f, 0x1d, + 0xa4, 0xca, 0x0c, 0x03, 0xe7, 0x0f, 0x21, 0x04, 0xe3, 0xfc, 0x14, 0x40, + 0x0a, 0x29, 0x10, 0x00, 0xcd, 0x08, 0x0d, 0xd6, 0x12, 0xba, 0x39, 0xb6, + 0xff, 0xf2, 0xeb, 0x09, 0xfc, 0x24, 0x1c, 0xe7, 0x3f, 0x09, 0x03, 0xd5, + 0x4a, 0x10, 0xfd, 0xe2, 0xee, 0x87, 0x38, 0xf7, 0xe3, 0xc8, 0xf0, 0x37, + 0xee, 0xe5, 0x42, 0xe2, 0x3e, 0xde, 0x34, 0xa2, 0x16, 0x2f, 0x06, 0x0d, + 0x5c, 0x0c, 0x39, 0x19, 0x8a, 0x82, 0x01, 0x0f, 0xd5, 0xd4, 0x02, 0xef, + 0xe9, 0x0d, 0x1c, 0x26, 0x0b, 0x2c, 0xfc, 0x19, 0xe6, 0xf4, 0xf5, 0xed, + 0x1c, 0xc7, 0x36, 0xc0, 0x05, 0xe3, 0xeb, 0x04, 0xe0, 0x3b, 0xf5, 0x13, + 0xfc, 0x17, 0x24, 0x0c, 0xdb, 0x36, 0x58, 0xe2, 0xf6, 0x1e, 0xd8, 0x01, + 0xef, 0xf7, 0xe8, 0x44, 0x24, 0x3c, 0x1f, 0xfa, 0x02, 0x2a, 0xe8, 0x9e, + 0xf6, 0xe3, 0xe0, 0xe2, 0xfc, 0xfd, 0x24, 0x13, 0x03, 0x0d, 0x17, 0x2e, + 0x2c, 0x28, 0x1c, 0xdd, 0xd8, 0x19, 0x99, 0xee, 0x37, 0xa1, 0xc8, 0x20, + 0x0d, 0xf5, 0x19, 0xf3, 0xbe, 0xee, 0xc7, 0x8f, 0xf5, 0xd2, 0xf5, 0xa7, + 0xf4, 0x4e, 0xc6, 0x25, 0x09, 0xea, 0x0a, 0x08, 0xd7, 0x1c, 0x31, 0xde, + 0xe9, 0x0b, 0xd8, 0x0a, 0xe8, 0x0e, 0xe8, 0x2c, 0x17, 0x23, 0x17, 0xde, + 0x28, 0x23, 0xc4, 0xa6, 0x25, 0xf7, 0xe0, 0xcc, 0x63, 0x15, 0x1b, 0x29, + 0xb3, 0xce, 0xe5, 0xb5, 0x9d, 0xba, 0x39, 0xda, 0xcc, 0xde, 0x09, 0xce, + 0xcf, 0x44, 0xfc, 0xed, 0xe2, 0x18, 0x01, 0x2e, 0x16, 0xfa, 0xe1, 0xcc, + 0xf2, 0xc6, 0xae, 0xff, 0xd8, 0x22, 0x05, 0x18, 0x2a, 0x06, 0x0f, 0xa5, + 0x16, 0xfa, 0x0a, 0xfe, 0x98, 0x81, 0x4e, 0xbe, 0xda, 0xfa, 0x14, 0x48, + 0x4d, 0xdb, 0x56, 0x0a, 0x0c, 0xff, 0xd1, 0xc6, 0xf2, 0x2e, 0xed, 0x26, + 0x46, 0x10, 0x34, 0x04, 0xdb, 0xb3, 0xc0, 0xdb, 0xe8, 0xda, 0x26, 0xc3, + 0x84, 0xdc, 0x37, 0x20, 0xf8, 0x43, 0x0a, 0x1c, 0xf6, 0x18, 0x3c, 0x1a, + 0x1f, 0xfd, 0x2e, 0xf3, 0x1f, 0xed, 0xba, 0xec, 0xc0, 0x0c, 0x1c, 0x12, + 0xd4, 0xd0, 0xd8, 0xf1, 0xb5, 0x06, 0x20, 0xe3, 0xda, 0x11, 0xbf, 0xc8, + 0xdc, 0xd5, 0xff, 0xda, 0x1b, 0xdd, 0xf4, 0x0a, 0xdd, 0x12, 0xcd, 0xf3, + 0xfe, 0xfc, 0x00, 0xf4, 0xec, 0x2b, 0xec, 0x26, 0xbb, 0x0a, 0x33, 0xf1, + 0xa7, 0x25, 0x2e, 0xef, 0xec, 0x00, 0xd8, 0xe4, 0xfc, 0xee, 0x14, 0xe9, + 0x33, 0xf1, 0xd2, 0x0a, 0x00, 0x48, 0xed, 0xde, 0xee, 0xd8, 0x18, 0x0c, + 0xa7, 0x0f, 0x18, 0xf5, 0xf1, 0x07, 0x1e, 0xf4, 0xe6, 0x14, 0x4f, 0xf6, + 0x0c, 0x1a, 0xdb, 0xdb, 0x03, 0xbd, 0xec, 0xf1, 0x73, 0xe3, 0x08, 0x6a, + 0xe8, 0x08, 0xda, 0xe1, 0x0e, 0x08, 0x06, 0xf4, 0xb1, 0xf0, 0x16, 0x37, + 0xee, 0xe9, 0x47, 0xf1, 0xe4, 0x66, 0x29, 0xd5, 0xda, 0x0a, 0xba, 0x17, + 0x40, 0xc0, 0x02, 0xc5, 0x2b, 0x05, 0x08, 0xf6, 0xbf, 0x25, 0xdb, 0x1a, + 0xc6, 0xdb, 0xf7, 0xef, 0xd8, 0xf1, 0x0a, 0x47, 0xd4, 0xe9, 0x19, 0x15, + 0x9e, 0x52, 0x12, 0xe7, 0xd7, 0xd9, 0xcb, 0x23, 0x4e, 0xe3, 0xe2, 0xd6, + 0x26, 0xdf, 0x2c, 0x00, 0xc8, 0x59, 0xf0, 0xed, 0xd7, 0x04, 0xf4, 0xf5, + 0xb3, 0xdd, 0x18, 0x36, 0x05, 0x03, 0x30, 0xeb, 0xee, 0x4c, 0x62, 0xea, + 0xd3, 0x0a, 0xbe, 0x19, 0x3c, 0xd0, 0xf3, 0xca, 0x4a, 0xf7, 0x30, 0x36, + 0xe8, 0x44, 0xfd, 0xe6, 0x0c, 0xf1, 0xf7, 0xe1, 0xc8, 0x0b, 0xf2, 0xe4, + 0xb9, 0xd3, 0xbc, 0x13, 0xd7, 0x0a, 0x42, 0xe0, 0xc3, 0x06, 0xf4, 0x05, + 0xd6, 0xc6, 0xff, 0xae, 0x05, 0xe3, 0xe3, 0xf0, 0x12, 0xdc, 0x09, 0xc2, + 0xb1, 0xe0, 0x29, 0xf3, 0x0f, 0x02, 0xeb, 0x0c, 0xc9, 0xe4, 0xf2, 0xfb, + 0xe1, 0x10, 0x43, 0xf0, 0x07, 0xcd, 0x11, 0x41, 0x16, 0xe3, 0xcc, 0xff, + 0x2a, 0x0e, 0xee, 0x0a, 0x1b, 0x10, 0x45, 0xbb, 0x0b, 0xbe, 0xc9, 0xd1, + 0xf1, 0x1b, 0xf1, 0xfa, 0xcd, 0xc3, 0xfe, 0x05, 0xf7, 0xdc, 0x7f, 0xfc, + 0xf9, 0xdf, 0x00, 0x14, 0x03, 0xdd, 0xea, 0xd6, 0x6a, 0xfe, 0xd7, 0x74, + 0x32, 0xf1, 0x09, 0xba, 0x01, 0xe1, 0x0e, 0x0a, 0xe5, 0x05, 0xda, 0x08, + 0x19, 0x2e, 0xf6, 0x1f, 0x25, 0xf8, 0xe1, 0x0f, 0x38, 0x13, 0x11, 0xd4, + 0xd3, 0x10, 0x0e, 0x33, 0xe1, 0x12, 0xf8, 0xed, 0xf0, 0xe6, 0xc2, 0x06, + 0x09, 0x04, 0xfc, 0x06, 0xf3, 0xf7, 0xf3, 0x07, 0x3c, 0x1a, 0xe7, 0x20, + 0xec, 0xd7, 0xe2, 0x17, 0xff, 0x18, 0xf6, 0xed, 0xf5, 0x08, 0x32, 0x1b, + 0xdc, 0x08, 0xf9, 0xf3, 0xcb, 0xff, 0xd4, 0x27, 0xfc, 0x0b, 0x0f, 0x29, + 0xe2, 0xfe, 0xe3, 0xee, 0x20, 0x24, 0x05, 0x0b, 0x1e, 0xfa, 0xe8, 0x1a, + 0x24, 0x07, 0xfc, 0xe8, 0xe3, 0x17, 0xfb, 0x1d, 0xea, 0x1d, 0xfb, 0xf3, + 0xf9, 0xf0, 0xea, 0x17, 0x0d, 0x05, 0xf5, 0x06, 0xdf, 0xd8, 0xde, 0x1a, + 0x01, 0xff, 0xda, 0x00, 0x19, 0xe2, 0xd6, 0x06, 0x48, 0xfd, 0x1b, 0xec, + 0xc7, 0xf3, 0x12, 0x12, 0xee, 0xfd, 0xde, 0xf5, 0xf6, 0xe0, 0xe9, 0x20, + 0x28, 0xf6, 0xf6, 0x16, 0x21, 0xf9, 0xd6, 0xf3, 0x0a, 0xe8, 0xd1, 0x18, + 0x17, 0xe0, 0xc6, 0x06, 0x08, 0x04, 0xf4, 0xef, 0xe0, 0x31, 0x7f, 0xf7, + 0xe5, 0x10, 0xe1, 0xf0, 0x06, 0xe3, 0x0d, 0x1a, 0x19, 0xfa, 0x41, 0x54, + 0xf7, 0xe6, 0xec, 0x15, 0x0e, 0x07, 0xd9, 0x0a, 0x1d, 0xdb, 0xd2, 0x04, + 0x27, 0xf9, 0x15, 0x07, 0xe8, 0x10, 0x1e, 0x0a, 0xed, 0x10, 0xe8, 0x08, + 0x06, 0xdc, 0xf3, 0x12, 0x1f, 0xeb, 0x07, 0x26, 0x03, 0xf0, 0xe3, 0x00, + 0xf2, 0xf7, 0xca, 0x1c, 0x01, 0x01, 0xe7, 0xfc, 0x41, 0x13, 0x09, 0xeb, + 0xda, 0xd6, 0x05, 0x10, 0xc1, 0xee, 0xc9, 0x04, 0xfc, 0xd2, 0xf6, 0xf2, + 0x07, 0xd1, 0xd5, 0xeb, 0xf0, 0x0b, 0xf0, 0xf2, 0x2c, 0x16, 0xef, 0x27, + 0xeb, 0xaa, 0xc9, 0xff, 0x0e, 0x29, 0x03, 0xf8, 0x07, 0xdf, 0x34, 0x1e, + 0xbb, 0xfb, 0xbc, 0xe0, 0xeb, 0xdd, 0xf5, 0xcb, 0xe8, 0xf0, 0x16, 0x34, + 0xee, 0xfe, 0xe9, 0xe5, 0xf9, 0x05, 0x10, 0x18, 0x0a, 0xf6, 0xc4, 0x01, + 0x2e, 0x05, 0xfb, 0xf8, 0xee, 0xeb, 0xf7, 0x1a, 0xbf, 0x1c, 0xbc, 0xf4, + 0xf1, 0xd2, 0xe1, 0xf8, 0x07, 0xd8, 0xea, 0x05, 0xec, 0xd3, 0xca, 0x05, + 0xed, 0xed, 0xa3, 0x3a, 0xf9, 0xc0, 0x06, 0xd9, 0xec, 0x15, 0xe1, 0xe2, + 0xfc, 0xee, 0x23, 0xe5, 0xde, 0xdc, 0xee, 0xf8, 0x1e, 0xf3, 0x1a, 0x17, + 0xe0, 0xd4, 0x2e, 0xfd, 0x25, 0xc3, 0x81, 0x1e, 0xa3, 0x4d, 0x06, 0xd2, + 0x04, 0x05, 0x17, 0xea, 0x12, 0xaa, 0x1d, 0x05, 0xd3, 0x51, 0xf0, 0xe2, + 0x13, 0xeb, 0xc4, 0x08, 0x3a, 0xb9, 0x19, 0x27, 0xf4, 0xbd, 0xe8, 0x0d, + 0xdd, 0xf5, 0xaf, 0x18, 0xd2, 0x0b, 0xd3, 0x1b, 0x13, 0xca, 0xfe, 0xeb, + 0xe6, 0x25, 0xff, 0x07, 0x23, 0xcb, 0x04, 0x1a, 0xe6, 0xf6, 0xbb, 0x10, + 0x09, 0xb6, 0x12, 0xbe, 0x00, 0x36, 0x11, 0x07, 0x19, 0x16, 0xf4, 0xf3, + 0xe3, 0xee, 0x27, 0xe3, 0x2e, 0x2d, 0x0f, 0x4f, 0xd6, 0x01, 0x25, 0x23, + 0x3e, 0xb7, 0x2d, 0x1d, 0xe9, 0x1e, 0xf0, 0xea, 0xff, 0xe5, 0x08, 0x0e, + 0xe2, 0xe4, 0xe8, 0x0a, 0x14, 0x41, 0x2e, 0x4e, 0x30, 0x10, 0xe8, 0x3c, + 0xb8, 0x06, 0x1c, 0x36, 0xda, 0xc2, 0x0b, 0x55, 0x72, 0xed, 0xc4, 0xf6, + 0xf8, 0x2e, 0x01, 0xfd, 0x12, 0xf2, 0x18, 0xf7, 0xf4, 0xe0, 0x90, 0x06, + 0x1a, 0x1b, 0x12, 0xe3, 0xbe, 0xf4, 0x2d, 0xe4, 0x49, 0x20, 0x19, 0x5c, + 0xcd, 0xd3, 0xfa, 0x12, 0x36, 0xe5, 0x0c, 0x1d, 0x0a, 0x02, 0xe2, 0x0a, + 0xf9, 0xd9, 0x0c, 0x0e, 0xdb, 0xf0, 0xed, 0x01, 0xfa, 0xe3, 0xea, 0x08, + 0xf8, 0x0c, 0xcc, 0x41, 0x01, 0xbd, 0xf9, 0xae, 0xd9, 0x17, 0xeb, 0x27, + 0x34, 0xf8, 0x47, 0xf3, 0xd6, 0xcf, 0xf6, 0x10, 0x25, 0xf5, 0x25, 0x1d, + 0xf4, 0x0c, 0x31, 0x04, 0x21, 0xac, 0xcf, 0x14, 0xcf, 0x2f, 0x01, 0xd6, + 0x10, 0xff, 0xf7, 0xce, 0x0e, 0xaa, 0x04, 0xd2, 0xd2, 0x34, 0x0a, 0xdb, + 0x3a, 0xce, 0xde, 0x2b, 0x3f, 0xd0, 0xdf, 0x24, 0xf1, 0x0d, 0x15, 0x10, + 0xdf, 0xe3, 0xf2, 0x09, 0xf8, 0x1e, 0xeb, 0x17, 0x2d, 0xd9, 0x1c, 0xe1, + 0xf1, 0x05, 0xf0, 0xef, 0xf3, 0xe0, 0x1a, 0x16, 0xf2, 0xbd, 0xe6, 0x4d, + 0x0e, 0xca, 0xfd, 0xfb, 0x1e, 0x25, 0x3a, 0xea, 0x34, 0xd4, 0xed, 0x04, + 0xe2, 0x56, 0xfa, 0x07, 0x3a, 0xf8, 0x1b, 0xf7, 0xd6, 0x14, 0x19, 0xe6, + 0xfa, 0x35, 0x44, 0x06, 0xe7, 0xf4, 0x44, 0xd5, 0x24, 0xd9, 0x15, 0xc4, + 0xf3, 0x07, 0xed, 0x18, 0xff, 0xd5, 0xe6, 0x0d, 0x17, 0x09, 0xe3, 0x22, + 0x09, 0xcb, 0xe9, 0xe2, 0xf0, 0xa6, 0xa3, 0x01, 0xf7, 0x04, 0xcf, 0x43, + 0xe7, 0x17, 0x1e, 0xf2, 0x00, 0xcd, 0xfa, 0xda, 0xdd, 0xe3, 0xfb, 0xf0, + 0xf4, 0xef, 0xcb, 0xf3, 0x17, 0x22, 0x06, 0xef, 0x67, 0xeb, 0x0b, 0xf3, + 0xf2, 0x38, 0xeb, 0xef, 0xe9, 0x0d, 0x13, 0x01, 0xe6, 0xe8, 0x1d, 0xdb, + 0x24, 0xfd, 0x15, 0xd0, 0x17, 0x2c, 0xee, 0x18, 0x0c, 0xf5, 0x0f, 0xc5, + 0x04, 0x26, 0xf1, 0x0d, 0x3e, 0x0a, 0xec, 0x09, 0xb3, 0x0d, 0x3a, 0xd3, + 0xc7, 0x63, 0x3b, 0xf9, 0xe5, 0xdc, 0xfa, 0x07, 0x9b, 0xed, 0xc1, 0x2e, + 0x20, 0x03, 0x04, 0x30, 0x00, 0x05, 0xce, 0xd4, 0x18, 0xdf, 0xf4, 0xde, + 0xd6, 0xf3, 0x12, 0xef, 0xcf, 0xd9, 0xcd, 0xe6, 0xe0, 0x02, 0xaf, 0x5d, + 0xf5, 0xb6, 0xf7, 0x04, 0x3b, 0xf2, 0x1e, 0xea, 0xe0, 0xc7, 0xef, 0xee, + 0x21, 0xd8, 0xf3, 0x99, 0x10, 0x2b, 0x1b, 0xce, 0x3c, 0x00, 0xe7, 0x29, + 0xcc, 0xfe, 0x11, 0xda, 0xbd, 0x29, 0x79, 0xdc, 0x06, 0xd5, 0xeb, 0xfc, + 0xe5, 0xe3, 0xbc, 0x0c, 0x2a, 0xff, 0xfe, 0x18, 0x28, 0xf4, 0xd7, 0x02, + 0x0d, 0x20, 0x18, 0x2e, 0x2e, 0xee, 0xcc, 0x0d, 0xe2, 0x1b, 0x1f, 0xb9, + 0xdf, 0x14, 0x17, 0x22, 0xe0, 0xfe, 0x2b, 0xf4, 0xf5, 0x1f, 0xbb, 0x05, + 0x12, 0x04, 0x0b, 0x1a, 0x04, 0xb7, 0xc6, 0x04, 0x0c, 0x04, 0xf4, 0x0c, + 0x03, 0xcb, 0xc1, 0xdd, 0xf0, 0x81, 0xeb, 0xf6, 0x03, 0x38, 0xbb, 0x30, + 0x08, 0x12, 0x09, 0x16, 0xcc, 0xcb, 0xef, 0x09, 0x17, 0xc4, 0xd5, 0xdc, + 0xfe, 0xd3, 0xb2, 0xfd, 0x23, 0x20, 0x17, 0x11, 0x3a, 0xf1, 0x03, 0xe3, + 0xf4, 0x06, 0xfc, 0xf9, 0xf6, 0x0c, 0x21, 0x06, 0xd6, 0xf5, 0x0d, 0xf3, + 0x2f, 0x1d, 0xfd, 0xef, 0xfb, 0x1e, 0x17, 0x0d, 0x08, 0xce, 0x20, 0x1a, + 0x0f, 0x11, 0xf4, 0xe6, 0xf6, 0xf0, 0x1b, 0x24, 0xdb, 0x26, 0xfd, 0x04, + 0x07, 0x07, 0x0c, 0xd3, 0x30, 0x02, 0x22, 0x03, 0x11, 0x37, 0xf7, 0x17, + 0x01, 0x0b, 0xe1, 0xf7, 0xfd, 0xb9, 0x2f, 0x19, 0x29, 0x01, 0x23, 0x09, + 0x13, 0x25, 0x4b, 0x12, 0x96, 0x2e, 0xba, 0x00, 0xeb, 0xe2, 0xdd, 0x1d, + 0x1c, 0x0c, 0x3c, 0xf6, 0xda, 0xe1, 0xfb, 0x29, 0xe4, 0xf7, 0xda, 0xa5, + 0xea, 0xdc, 0x05, 0x1a, 0x42, 0x2d, 0x37, 0xdf, 0x0e, 0xfd, 0x08, 0x36, + 0xb4, 0xf9, 0xe6, 0x17, 0x06, 0xff, 0xf5, 0xfb, 0x35, 0xec, 0x22, 0xe9, + 0xf4, 0x3d, 0xdb, 0x12, 0xfd, 0x17, 0x22, 0xe1, 0x35, 0xd4, 0x3f, 0x99, + 0x0b, 0x1d, 0x07, 0xf6, 0xf9, 0x00, 0x10, 0xf2, 0xc9, 0x22, 0x89, 0xe8, + 0xc4, 0x0d, 0xbc, 0xe6, 0x1e, 0xeb, 0x0c, 0xf8, 0x0f, 0x02, 0x0c, 0xdc, + 0x0b, 0x31, 0xf2, 0xe7, 0xb3, 0xfc, 0x17, 0xcc, 0x1f, 0x1a, 0xf1, 0xce, + 0x35, 0xfb, 0x61, 0xdd, 0xc9, 0x26, 0x21, 0x81, 0xd1, 0xe9, 0xe4, 0x0b, + 0xd9, 0xcf, 0x17, 0xf4, 0xca, 0x08, 0xd6, 0xfc, 0xe2, 0x39, 0x1f, 0xc7, + 0x25, 0xce, 0x16, 0xf3, 0x2f, 0x18, 0x05, 0x01, 0xe6, 0xfd, 0xf6, 0x02, + 0xbb, 0xff, 0xfc, 0xe4, 0xde, 0x02, 0xe9, 0x03, 0x04, 0xf4, 0x30, 0xf5, + 0xee, 0x25, 0x04, 0xe9, 0x06, 0x26, 0xf3, 0xd5, 0x37, 0xef, 0x3c, 0x2a, + 0x15, 0x03, 0xe7, 0xec, 0x04, 0xbb, 0x0a, 0x01, 0xfd, 0x04, 0xfa, 0x13, + 0x15, 0x19, 0xf7, 0xce, 0x33, 0xed, 0x2e, 0x07, 0xfb, 0x3c, 0x14, 0x28, + 0x28, 0x0b, 0x0f, 0x05, 0xd3, 0xc5, 0x1e, 0x18, 0x18, 0x06, 0x2d, 0xbd, + 0x2c, 0x2a, 0x28, 0xdf, 0xf4, 0x4c, 0xba, 0xe4, 0x9c, 0xff, 0x02, 0xdf, + 0x0b, 0xbb, 0x47, 0xcb, 0x12, 0xfd, 0xfb, 0x4c, 0xf9, 0x1b, 0x2f, 0xa6, + 0x17, 0xdb, 0x10, 0x2a, 0x3a, 0xe5, 0x14, 0xf0, 0x0c, 0xec, 0xf2, 0x14, + 0xb8, 0x07, 0xef, 0x10, 0x15, 0x23, 0x0d, 0xcd, 0x3e, 0xda, 0x21, 0xd4, + 0xf8, 0x49, 0xfc, 0x20, 0x45, 0x46, 0x25, 0xe4, 0xc5, 0x17, 0x0c, 0x0f, + 0xf8, 0xea, 0xfa, 0xe3, 0xce, 0x03, 0x0e, 0xf1, 0xe6, 0x13, 0xc7, 0xf7, + 0x04, 0xe3, 0xf2, 0xd7, 0x22, 0xe9, 0xfd, 0x0e, 0xdd, 0x2d, 0xda, 0xf4, + 0x18, 0x0e, 0x17, 0xf7, 0xf7, 0x49, 0x00, 0x0e, 0xbc, 0xfe, 0x09, 0xf4, + 0xb8, 0x3c, 0x41, 0xe2, 0xee, 0x05, 0x99, 0xfd, 0x05, 0xf9, 0xe8, 0xfd, + 0x1e, 0xe9, 0xe9, 0x0a, 0xf9, 0x3d, 0xec, 0xe5, 0x0c, 0xde, 0x12, 0xb4, + 0xd0, 0x1f, 0x1b, 0x05, 0x0a, 0xfa, 0x2f, 0xe3, 0xe6, 0x27, 0x51, 0xfe, + 0xff, 0x0b, 0xe6, 0xdb, 0xf4, 0xd7, 0xee, 0xe5, 0x6c, 0xf7, 0x0f, 0x2c, + 0xea, 0x1f, 0xee, 0xef, 0x18, 0x09, 0x08, 0x03, 0xd3, 0xf9, 0x23, 0x39, + 0xfa, 0xe9, 0x40, 0x02, 0xe9, 0x48, 0x43, 0xd5, 0xc0, 0x07, 0xda, 0x23, + 0x3c, 0xfa, 0x16, 0xe2, 0x2b, 0xf2, 0x31, 0xf4, 0xb8, 0x4b, 0xcf, 0xed, + 0x00, 0xe0, 0xf2, 0xe5, 0xce, 0x04, 0x0a, 0x2f, 0xe3, 0xeb, 0x18, 0x13, + 0xcf, 0x4d, 0x0c, 0xd5, 0xd8, 0xeb, 0xa4, 0x2c, 0x18, 0xd0, 0xe0, 0xed, + 0x29, 0xc4, 0x3f, 0x07, 0xe7, 0x5e, 0xd2, 0xe3, 0xe0, 0xeb, 0x06, 0xd3, + 0xce, 0x1a, 0x0e, 0x3e, 0x03, 0xfc, 0xf1, 0x01, 0x03, 0x43, 0x5e, 0xe5, + 0xe3, 0x03, 0xb3, 0x0c, 0xed, 0xe4, 0x02, 0xf7, 0x62, 0xfb, 0x3e, 0x56, + 0xea, 0x4c, 0xda, 0xe8, 0x16, 0xeb, 0x04, 0xe8, 0xcd, 0x1f, 0xd2, 0xde, + 0xb9, 0xc1, 0xcb, 0x18, 0xbd, 0x02, 0x1a, 0xe7, 0xbd, 0xe7, 0xbc, 0xdc, + 0xd6, 0xd6, 0x00, 0xd8, 0x12, 0xc8, 0xd9, 0x04, 0xb1, 0xe8, 0xe1, 0xca, + 0xc6, 0xe8, 0x18, 0x0c, 0xe2, 0x31, 0x05, 0x04, 0xe8, 0xe9, 0x02, 0xd5, + 0xe0, 0x22, 0x47, 0xed, 0x1a, 0xb8, 0xef, 0x05, 0x01, 0xe6, 0xcc, 0xea, + 0x2a, 0x06, 0x05, 0x1e, 0xd5, 0x32, 0xdb, 0xe4, 0x10, 0xba, 0xdc, 0xdb, + 0x1d, 0x2f, 0xe1, 0xfe, 0xc2, 0xc6, 0xe2, 0xda, 0xd3, 0x08, 0x7b, 0xeb, + 0xe5, 0xe4, 0xc2, 0xe7, 0xc6, 0xdd, 0xd4, 0xf9, 0x7f, 0xe0, 0xeb, 0x60, + 0xf2, 0xee, 0xd8, 0xbb, 0x05, 0xd0, 0xf1, 0xea, 0x30, 0xb1, 0x05, 0xf8, + 0xfb, 0x20, 0x42, 0xe5, 0x20, 0x06, 0x27, 0x0b, 0xa7, 0x2f, 0x13, 0xfa, + 0x0d, 0x2b, 0x04, 0x30, 0xcf, 0x05, 0x2b, 0xe1, 0x2b, 0xf8, 0x03, 0x02, + 0xf6, 0xfc, 0xe9, 0xe8, 0xfb, 0xd3, 0xef, 0xf2, 0x40, 0x12, 0xf1, 0x31, + 0x0b, 0xe4, 0xf8, 0xda, 0xad, 0xf4, 0x8f, 0x07, 0xf4, 0xcb, 0xde, 0x3d, + 0xda, 0x24, 0x39, 0xd0, 0x1a, 0xc6, 0xfe, 0xc8, 0xee, 0xe5, 0x04, 0xd5, + 0x18, 0xc7, 0xdd, 0x04, 0x2f, 0x2c, 0x05, 0xaa, 0x44, 0xed, 0x1b, 0x0c, + 0xd1, 0x01, 0x0b, 0xfd, 0x09, 0x16, 0xd8, 0xf4, 0xf4, 0xeb, 0x1e, 0xe8, + 0x32, 0xf4, 0x20, 0xff, 0x06, 0x16, 0xfb, 0xdb, 0x10, 0xf5, 0x0b, 0xb8, + 0x40, 0xf9, 0xcb, 0x17, 0x07, 0xe9, 0xdf, 0xe6, 0xba, 0x31, 0xea, 0xd0, + 0xc0, 0x60, 0x41, 0xd1, 0xe7, 0xdd, 0xee, 0xf9, 0xa2, 0xe4, 0x88, 0x4b, + 0x19, 0x41, 0x21, 0x26, 0x07, 0x01, 0xe9, 0xae, 0x05, 0xe6, 0x19, 0xe6, + 0x02, 0xdf, 0x08, 0xe4, 0xd3, 0xd0, 0xad, 0xb6, 0xc3, 0x39, 0xba, 0x2a, + 0xed, 0x81, 0x0b, 0xf9, 0x39, 0xec, 0xf4, 0x18, 0xfd, 0x07, 0x07, 0xea, + 0x20, 0xed, 0xff, 0xdd, 0x2e, 0x21, 0xd5, 0xc6, 0x14, 0xf0, 0xeb, 0xea, + 0xb2, 0xec, 0xcf, 0xf2, 0xcb, 0x47, 0xfe, 0xe0, 0xff, 0xcf, 0xf0, 0x02, + 0x12, 0xea, 0xce, 0x39, 0x39, 0x39, 0x13, 0xd4, 0x2d, 0xef, 0xc3, 0x0e, + 0x19, 0x25, 0x50, 0x19, 0x23, 0x29, 0xda, 0x02, 0xe9, 0x3d, 0x30, 0xf3, + 0x01, 0x27, 0x07, 0x2b, 0xea, 0x11, 0x21, 0xbc, 0x2b, 0x1d, 0xec, 0xee, + 0xf9, 0xff, 0xe1, 0x0a, 0xea, 0xa7, 0xd7, 0x20, 0x4f, 0x11, 0x04, 0x3d, + 0x26, 0xd6, 0xd7, 0xd7, 0xf1, 0x97, 0xd2, 0x1e, 0x0e, 0xd6, 0xcf, 0x52, + 0xf2, 0x2c, 0x15, 0xe2, 0x10, 0xe1, 0xf0, 0xe0, 0x0b, 0xe9, 0xdd, 0xd0, + 0x07, 0xcf, 0x97, 0xfc, 0x2e, 0x11, 0x0f, 0xf4, 0x2c, 0x16, 0x11, 0x0c, + 0xf8, 0xcd, 0x01, 0xfd, 0x13, 0x07, 0xe0, 0xfb, 0x27, 0xff, 0x05, 0xf2, + 0x16, 0x13, 0x10, 0xf3, 0xff, 0x0f, 0xe3, 0xe0, 0x35, 0x0a, 0x25, 0x06, + 0x0c, 0xfc, 0xef, 0xf6, 0x00, 0xd1, 0xf5, 0x16, 0xdf, 0xef, 0x0b, 0x24, + 0x0a, 0x23, 0xff, 0xfe, 0xdc, 0x10, 0x37, 0xcf, 0x00, 0x0b, 0x15, 0xf9, + 0x05, 0x07, 0x00, 0x01, 0x11, 0xff, 0x22, 0xf9, 0x3a, 0xda, 0x11, 0xdc, + 0x29, 0x26, 0xf9, 0xfb, 0x04, 0x8e, 0x21, 0xdd, 0xea, 0x3c, 0xea, 0x18, + 0xf0, 0xf5, 0x59, 0xd5, 0xee, 0xc5, 0x0e, 0x28, 0x14, 0x11, 0xe7, 0xfc, + 0x3e, 0x08, 0xf0, 0x16, 0xf5, 0xed, 0xcb, 0x08, 0xf7, 0xa4, 0xd9, 0xf5, + 0xdc, 0xe6, 0x12, 0x29, 0x23, 0x2d, 0x00, 0x14, 0x95, 0xdd, 0x15, 0xed, + 0x16, 0x01, 0x30, 0xcb, 0xf6, 0xf5, 0x0f, 0x0a, 0x4e, 0x28, 0x1a, 0x0f, + 0xf3, 0x2d, 0x23, 0xeb, 0xfa, 0x10, 0x3a, 0x06, 0xe2, 0xef, 0x2b, 0x1b, + 0xfc, 0xcb, 0xd5, 0x1a, 0x22, 0xfb, 0x31, 0xfa, 0xf5, 0x36, 0x43, 0x90, + 0xda, 0xf2, 0xd5, 0xee, 0xf6, 0x06, 0x35, 0x11, 0x03, 0x14, 0xde, 0x2e, + 0x38, 0x1d, 0x67, 0xdd, 0xbc, 0x07, 0x54, 0x19, 0x43, 0xcc, 0xe2, 0x11, + 0xed, 0x15, 0x35, 0xf9, 0xd7, 0x0c, 0x39, 0xb0, 0xe4, 0x03, 0xdc, 0xaf, + 0x79, 0x20, 0x10, 0x25, 0xd9, 0xed, 0x14, 0xfd, 0x1e, 0x17, 0x37, 0x13, + 0xe0, 0xef, 0x21, 0x24, 0x05, 0xec, 0xdf, 0x2d, 0x2d, 0xed, 0x2d, 0xe0, + 0xc9, 0x27, 0x7f, 0xa1, 0x02, 0xdb, 0xdb, 0xee, 0x37, 0xcf, 0x19, 0x1b, + 0x08, 0xd1, 0xd2, 0xc6, 0xf0, 0xa9, 0x01, 0xd2, 0xe9, 0x07, 0x1b, 0x00, + 0xf5, 0x30, 0x0b, 0xb8, 0xde, 0xff, 0x32, 0x0b, 0x0e, 0xe8, 0xf4, 0x01, + 0x1a, 0xe9, 0x18, 0xfd, 0xc6, 0x14, 0xcf, 0xf9, 0x0a, 0xdb, 0xfe, 0xc4, + 0x04, 0xf3, 0xda, 0xec, 0xba, 0xbb, 0x10, 0xe1, 0xa4, 0x3d, 0x08, 0xf1, + 0x18, 0xb8, 0x76, 0x0f, 0xb8, 0xb0, 0xe8, 0x47, 0x12, 0x24, 0x36, 0x08, + 0x60, 0xfe, 0x1c, 0x09, 0x08, 0xd7, 0xda, 0xf0, 0xea, 0xbd, 0xec, 0xf5, + 0xa1, 0x0d, 0xf9, 0x25, 0x15, 0x1d, 0x05, 0xdd, 0xd0, 0xf4, 0x3a, 0xf4, + 0xf0, 0xf9, 0x06, 0x0c, 0x22, 0x06, 0xf5, 0xe8, 0x2d, 0xe3, 0x01, 0xdd, + 0xfe, 0x4e, 0xfd, 0x13, 0xf0, 0xf7, 0xf5, 0x01, 0x01, 0x3c, 0x0d, 0xf2, + 0xfa, 0x0d, 0x0f, 0x07, 0xd9, 0xf2, 0xf8, 0xe2, 0x0f, 0xe1, 0x07, 0x03, + 0xf0, 0x05, 0x0d, 0x19, 0x16, 0x07, 0x08, 0xc6, 0x18, 0x33, 0xf1, 0xfd, + 0x05, 0xfd, 0xeb, 0xd9, 0x11, 0xda, 0xdb, 0xcf, 0xc2, 0x0d, 0xbf, 0x27, + 0xd4, 0xcf, 0x43, 0xed, 0x13, 0xe2, 0x0e, 0x14, 0xf7, 0xea, 0xfd, 0xc7, + 0x05, 0x11, 0xcc, 0xef, 0x0e, 0xfd, 0xfa, 0x17, 0x19, 0xfa, 0xfc, 0x00, + 0xf5, 0x33, 0xf4, 0xfb, 0xf4, 0x10, 0x0e, 0x40, 0xd0, 0xdf, 0x07, 0xd2, + 0x12, 0xc5, 0x03, 0xe2, 0x06, 0x21, 0x17, 0x28, 0x30, 0x2b, 0xdb, 0x23, + 0xf7, 0x0f, 0xe4, 0x14, 0x21, 0xf9, 0xe9, 0x09, 0x05, 0x03, 0x40, 0xf0, + 0xbd, 0x5e, 0x47, 0xfc, 0x00, 0x4a, 0xd6, 0xfd, 0x05, 0xeb, 0xff, 0x24, + 0xec, 0xe7, 0x07, 0x09, 0xf9, 0xe3, 0xf5, 0x2c, 0xf8, 0xe2, 0x0d, 0x0b, + 0xdc, 0x0f, 0x09, 0xc6, 0x18, 0x00, 0x02, 0xfa, 0x03, 0x04, 0x05, 0x1b, + 0xfc, 0x0d, 0x06, 0xf7, 0xc3, 0xf6, 0xf1, 0x06, 0xfa, 0xbc, 0xdf, 0xfe, + 0x43, 0x2a, 0xf1, 0x13, 0xf8, 0x21, 0xf7, 0x1f, 0x29, 0xff, 0x11, 0xfd, + 0x11, 0xf8, 0x47, 0xe2, 0xbc, 0x2e, 0x58, 0xf6, 0x0c, 0x30, 0xfc, 0xec, + 0x16, 0xf4, 0x1b, 0xf8, 0x16, 0xe6, 0xfa, 0x27, 0x07, 0x18, 0x19, 0xdd, + 0x0a, 0x41, 0xf9, 0x1c, 0xdd, 0xc2, 0xe1, 0xd1, 0x02, 0x35, 0x1d, 0xd5, + 0xe5, 0x2d, 0xff, 0x26, 0xd0, 0xec, 0x05, 0x08, 0xeb, 0xc2, 0xf4, 0xf9, + 0xf5, 0xcc, 0xea, 0x25, 0x11, 0x13, 0xff, 0xc2, 0x41, 0x30, 0xda, 0xf3, + 0xfe, 0xd0, 0xd1, 0xb5, 0xf7, 0x81, 0xcb, 0xc6, 0xdd, 0x32, 0xb5, 0x3f, + 0xca, 0xc9, 0x1a, 0x02, 0xf6, 0xea, 0xe1, 0x3c, 0x0d, 0xcb, 0xe1, 0xcb, + 0x03, 0x2b, 0xf4, 0xeb, 0xf7, 0x21, 0xd9, 0x27, 0x09, 0xca, 0xf9, 0xe7, + 0xf5, 0x55, 0x14, 0xf1, 0x0d, 0x15, 0x1c, 0x2a, 0xd1, 0xe1, 0x07, 0xe1, + 0x0e, 0xc7, 0xf9, 0xed, 0xed, 0xef, 0xf6, 0x37, 0xea, 0x02, 0xaf, 0x1c, + 0x3c, 0x18, 0xe1, 0x13, 0x35, 0xe1, 0x07, 0x0b, 0x3b, 0x30, 0x0f, 0xfc, + 0xea, 0xee, 0x04, 0x26, 0xe5, 0x2b, 0xfd, 0xd2, 0x1c, 0xe2, 0x12, 0xd9, + 0xe6, 0x00, 0xfa, 0xf9, 0xf3, 0xe7, 0xab, 0x0c, 0x02, 0x14, 0x15, 0x34, + 0x0a, 0xed, 0xdf, 0x12, 0xf0, 0x10, 0xcc, 0x0e, 0xda, 0xf3, 0x3e, 0x11, + 0xd6, 0x20, 0xcb, 0xf0, 0x2a, 0xed, 0x03, 0xfc, 0xe1, 0x2a, 0x35, 0x3a, + 0xe6, 0xfb, 0xca, 0x01, 0x3b, 0x1e, 0xd3, 0x16, 0x36, 0xe6, 0x12, 0x1c, + 0x30, 0x0e, 0x0b, 0xf8, 0xfe, 0xf7, 0xf4, 0x00, 0xec, 0x20, 0x08, 0xf7, + 0x24, 0xe4, 0x05, 0x07, 0xf4, 0xfa, 0x08, 0x1f, 0xc8, 0xed, 0xe9, 0x41, + 0x05, 0xf4, 0xbc, 0x1b, 0x2a, 0xee, 0xad, 0xd9, 0x4e, 0x22, 0x0d, 0xa0, + 0xb6, 0x47, 0x39, 0xd5, 0xed, 0xf6, 0xaa, 0x03, 0x15, 0xeb, 0x9c, 0x76, + 0x2c, 0xd6, 0x01, 0x0c, 0xea, 0x36, 0xd9, 0x27, 0xfa, 0x9a, 0xce, 0xef, + 0x03, 0xf7, 0xda, 0xf5, 0xdf, 0xeb, 0xde, 0xf5, 0xf3, 0x3c, 0x7e, 0xe2, + 0xf8, 0xfd, 0xca, 0xf5, 0x15, 0xd1, 0x18, 0x1a, 0x16, 0xef, 0x45, 0x7f, + 0xd3, 0xdf, 0x02, 0x0d, 0x02, 0xf1, 0xeb, 0xfb, 0x29, 0xe0, 0xcc, 0xeb, + 0x26, 0xfc, 0xf2, 0x0f, 0xf1, 0x12, 0x27, 0xda, 0xe6, 0x12, 0xa5, 0x13, + 0x46, 0xb2, 0xef, 0x4d, 0xf7, 0xc4, 0xe1, 0x10, 0xb4, 0xdd, 0xea, 0x27, + 0x00, 0x34, 0xf1, 0x2e, 0x0e, 0xeb, 0xac, 0xd3, 0x1e, 0x3a, 0xdc, 0xf9, + 0xed, 0xc4, 0x1b, 0x22, 0xeb, 0x19, 0xdd, 0xcf, 0x5b, 0x60, 0xd8, 0xbb, + 0xe9, 0xe2, 0xfd, 0xfe, 0xdb, 0xe8, 0xca, 0x24, 0xd1, 0xfc, 0xfc, 0x4e, + 0x10, 0xf5, 0xa2, 0xe0, 0x07, 0x7f, 0xa5, 0x3f, 0xe9, 0xb6, 0x46, 0xf0, + 0xe8, 0x10, 0x93, 0xd4, 0x16, 0xfd, 0x1a, 0xa6, 0x0b, 0x05, 0x22, 0x1a, + 0xe3, 0xe5, 0xca, 0x08, 0x2f, 0x35, 0xe4, 0x1c, 0x2c, 0xd8, 0x24, 0xe7, + 0x29, 0x07, 0xf8, 0x0c, 0xf6, 0xc6, 0x01, 0xfa, 0xa4, 0x17, 0xf3, 0xef, + 0x4a, 0x1e, 0x1b, 0xd2, 0xf5, 0xeb, 0x11, 0xea, 0xf4, 0x13, 0x22, 0xf8, + 0x10, 0x22, 0xf3, 0x35, 0x0f, 0xe7, 0xb8, 0x0c, 0x3f, 0x25, 0xf5, 0xc0, + 0xe2, 0xf3, 0x1a, 0x1e, 0xe8, 0x12, 0xf7, 0x02, 0xcd, 0xec, 0x9d, 0x10, + 0x0e, 0xfa, 0x10, 0x1b, 0xda, 0xfb, 0xe8, 0xf1, 0x08, 0x1c, 0xf7, 0x26, + 0xdc, 0xf4, 0xa2, 0x1c, 0x0a, 0x33, 0xf9, 0xad, 0xb0, 0x4c, 0x22, 0xed, + 0xd5, 0x01, 0xf5, 0xeb, 0xa3, 0xdc, 0xa9, 0x5f, 0xea, 0x1c, 0x46, 0x19, + 0x00, 0x0f, 0x0d, 0x04, 0x08, 0x14, 0xef, 0x20, 0x39, 0xde, 0xce, 0x02, + 0x23, 0x19, 0xed, 0xe9, 0xff, 0xf6, 0x0f, 0xf7, 0xff, 0x0b, 0xe3, 0x07, + 0xdf, 0xec, 0xda, 0xf6, 0x4f, 0x25, 0x1c, 0x0f, 0x56, 0xd2, 0xf7, 0x01, + 0xec, 0xfd, 0x03, 0x07, 0x31, 0xdb, 0xc6, 0x29, 0x39, 0x0d, 0x44, 0xed, + 0xf2, 0xd7, 0x1a, 0xff, 0xd4, 0xd3, 0xd9, 0x0d, 0xe2, 0xc6, 0xf5, 0xd3, + 0x40, 0xdf, 0xcd, 0x36, 0xd6, 0x0b, 0x0e, 0xf2, 0xec, 0x06, 0xf4, 0x0c, + 0x16, 0xf5, 0x16, 0x1f, 0xe8, 0x26, 0x3f, 0x02, 0x07, 0xd8, 0x44, 0xf9, + 0xea, 0x33, 0xd3, 0xee, 0xec, 0xc0, 0x00, 0xd9, 0x45, 0x3d, 0x46, 0x45, + 0x71, 0x13, 0x0d, 0xea, 0xc7, 0x24, 0xff, 0xff, 0x1b, 0xdb, 0xc2, 0x2e, + 0x1f, 0x01, 0x4f, 0xfd, 0xf7, 0xe2, 0x0e, 0xfc, 0xd3, 0xf3, 0xe4, 0x15, + 0xd9, 0xd5, 0xf1, 0xbb, 0x30, 0x15, 0xfa, 0x1f, 0xfd, 0xe8, 0xfb, 0xe1, + 0x22, 0x1d, 0xc8, 0x01, 0x39, 0xb9, 0xb3, 0xed, 0x0a, 0x00, 0xf5, 0xe7, + 0xf5, 0xfc, 0x0a, 0x0c, 0xac, 0xf1, 0x11, 0xe0, 0xe2, 0xd1, 0xf7, 0x2a, + 0x49, 0x34, 0x1a, 0x12, 0x04, 0xfb, 0x04, 0xd6, 0x2b, 0xea, 0xd8, 0x15, + 0xe9, 0xc2, 0xb4, 0x1c, 0x18, 0x48, 0xfd, 0xea, 0xe5, 0x32, 0x15, 0xed, + 0xaa, 0xf0, 0x1d, 0xdd, 0xe5, 0x81, 0xe9, 0x31, 0xea, 0x07, 0x2e, 0x1a, + 0x0d, 0x1a, 0xf1, 0xe8, 0x07, 0x06, 0xfa, 0x11, 0x31, 0xce, 0xd4, 0x12, + 0x1a, 0xfd, 0xf4, 0xf3, 0x0b, 0xf8, 0x02, 0x00, 0xc2, 0x08, 0xfa, 0xe5, + 0xec, 0xdf, 0xeb, 0x10, 0x2f, 0x0c, 0x09, 0x04, 0x2c, 0xd4, 0xfd, 0x00, + 0x03, 0xee, 0x29, 0xeb, 0xf1, 0x3a, 0x0b, 0x02, 0xc8, 0xf6, 0xfc, 0xe8, + 0xd9, 0x10, 0x10, 0xf1, 0x0a, 0xf6, 0x2a, 0xf5, 0xe3, 0x3a, 0xcb, 0xec, + 0x14, 0x06, 0xdd, 0xfb, 0xe4, 0xd0, 0x02, 0xfd, 0x24, 0xfc, 0x0d, 0x1e, + 0xeb, 0xf7, 0x36, 0xf7, 0xd2, 0xca, 0x19, 0xd7, 0x2d, 0xec, 0x08, 0x2f, + 0x1b, 0xf3, 0x1f, 0xfc, 0xce, 0x23, 0xda, 0xb7, 0x13, 0x15, 0x0b, 0x00, + 0x15, 0xe3, 0xc8, 0xff, 0xee, 0x05, 0x13, 0xec, 0x12, 0xf4, 0x1d, 0xf7, + 0xc0, 0xda, 0x1c, 0xe8, 0xc1, 0x13, 0x03, 0x13, 0x11, 0x13, 0x29, 0xe4, + 0xf1, 0x24, 0x0a, 0xf2, 0x21, 0xef, 0xea, 0xf1, 0xf5, 0xff, 0x09, 0xb3, + 0x09, 0x0e, 0x10, 0xe6, 0xf9, 0x11, 0x11, 0xd0, 0xe7, 0xf6, 0x36, 0xf9, + 0xf1, 0x0f, 0x0e, 0xb6, 0x23, 0xb0, 0x4c, 0x02, 0x9f, 0x39, 0xd6, 0xf0, + 0x2e, 0x18, 0xfb, 0x1d, 0x3c, 0xf1, 0xf0, 0xbd, 0x17, 0xf7, 0x0e, 0xda, + 0xfa, 0x1f, 0xe2, 0xe0, 0xff, 0xb8, 0xb4, 0x1f, 0x0a, 0xff, 0x9d, 0x47, + 0x28, 0xa3, 0x3f, 0x04, 0x2b, 0x4f, 0x2c, 0xe4, 0x01, 0x0a, 0xff, 0xee, + 0x01, 0xf1, 0x47, 0x00, 0x36, 0x2f, 0x1e, 0xf4, 0x0b, 0x3c, 0x1b, 0xd8, + 0xf9, 0x2a, 0x97, 0x0a, 0x0f, 0x0c, 0xf0, 0xe6, 0x35, 0xc3, 0x24, 0x13, + 0xdc, 0x4e, 0xa4, 0xf6, 0x23, 0x18, 0x18, 0xe8, 0x12, 0xfb, 0xd6, 0xc2, + 0xf1, 0x14, 0x36, 0xce, 0xef, 0x34, 0x1b, 0xdc, 0x99, 0xd9, 0x22, 0xbb, + 0xca, 0x1a, 0x02, 0xff, 0x11, 0xee, 0x1c, 0x10, 0xde, 0xf1, 0xc5, 0xea, + 0x02, 0xe9, 0xbe, 0x02, 0xf7, 0x25, 0x14, 0x02, 0x1e, 0xcd, 0xe3, 0x05, + 0xcc, 0xa7, 0x0b, 0xfa, 0xb1, 0x81, 0xd5, 0xe8, 0x36, 0xe2, 0xaf, 0x23, + 0x50, 0xdc, 0xfe, 0x12, 0xc9, 0x18, 0xbe, 0xd3, 0xfe, 0xe4, 0xbb, 0xcb, + 0x05, 0xea, 0xe6, 0x31, 0x03, 0x19, 0x16, 0xad, 0x26, 0x36, 0x27, 0xf5, + 0xd5, 0xaa, 0xf0, 0xe7, 0xe4, 0xf7, 0xf0, 0xfd, 0x37, 0xde, 0x15, 0x6b, + 0xfc, 0x02, 0xf0, 0xd6, 0x1b, 0xdd, 0xda, 0xf9, 0x23, 0xe7, 0xfa, 0xa9, + 0xe8, 0x04, 0xd4, 0x0f, 0x13, 0xe4, 0x0e, 0xe4, 0x11, 0x4f, 0x01, 0xfc, + 0x1b, 0x27, 0x20, 0x00, 0xca, 0xf0, 0x09, 0xe9, 0x28, 0x89, 0x0f, 0xef, + 0x13, 0xf1, 0x16, 0x12, 0x2d, 0x1e, 0xe2, 0x99, 0xcc, 0x33, 0xe1, 0xd0, + 0xfd, 0xf6, 0xd9, 0xd1, 0x1b, 0xcd, 0xc6, 0xcc, 0xb3, 0x27, 0xb9, 0x01, + 0xcb, 0xdc, 0xfc, 0x19, 0x28, 0x9f, 0xfd, 0x03, 0x13, 0xbf, 0x35, 0xdd, + 0x1c, 0x26, 0x28, 0xcc, 0xd7, 0xdb, 0xe5, 0x0a, 0x2e, 0xd4, 0x06, 0xee, + 0x12, 0x3f, 0xfc, 0xe7, 0xf4, 0xff, 0xfe, 0x2c, 0xd9, 0xe1, 0xf1, 0xf8, + 0x09, 0x81, 0x03, 0xbd, 0x49, 0x13, 0x20, 0x14, 0x30, 0x3a, 0xff, 0x1a, + 0xc2, 0xd6, 0xf0, 0xf4, 0x32, 0x15, 0x4f, 0x31, 0x15, 0xec, 0x1a, 0x14, + 0x27, 0x19, 0x2c, 0xf3, 0x13, 0x34, 0xd8, 0x04, 0x09, 0xd1, 0x13, 0xf8, + 0x29, 0xc8, 0xf2, 0xf4, 0x0c, 0x09, 0x12, 0x5d, 0xef, 0xdc, 0x15, 0x42, + 0xa4, 0x2b, 0x1a, 0xe0, 0xb8, 0x15, 0xc6, 0x2e, 0x3d, 0xc5, 0xdf, 0x03, + 0x2d, 0xf1, 0xfb, 0x06, 0xef, 0xff, 0x12, 0xaf, 0xe5, 0xb4, 0xed, 0xe3, + 0x3d, 0x4e, 0x0e, 0x2c, 0xd7, 0x04, 0x06, 0x0f, 0x39, 0x19, 0x2c, 0x28, + 0x24, 0xe8, 0x07, 0x25, 0x22, 0x1d, 0x16, 0xeb, 0x2f, 0x3c, 0xe7, 0x24, + 0xbb, 0x0d, 0x0b, 0xe0, 0x57, 0xeb, 0xfa, 0xbf, 0x2e, 0x12, 0x14, 0xad, + 0xed, 0x0e, 0xeb, 0x28, 0x0d, 0xc3, 0x08, 0xb9, 0x02, 0x50, 0xeb, 0xd6, + 0xee, 0x17, 0x17, 0x1c, 0xd5, 0xcc, 0xef, 0x15, 0x1d, 0xa3, 0xf2, 0x0b, + 0x21, 0xff, 0x0d, 0xfc, 0x06, 0x2e, 0x07, 0x8d, 0xf0, 0x56, 0xcb, 0xd0, + 0xf9, 0xd2, 0xf6, 0xa4, 0xee, 0x96, 0xcf, 0x99, 0xc1, 0x29, 0xbc, 0x0f, + 0xf6, 0xa0, 0x2c, 0x4a, 0x2a, 0xc6, 0xf0, 0x0d, 0x22, 0xd7, 0xed, 0xa2, + 0x11, 0x37, 0xf0, 0xc3, 0xf9, 0x06, 0xef, 0x02, 0x1b, 0xf7, 0x24, 0xe3, + 0xe1, 0xe6, 0xf7, 0xdf, 0xda, 0x13, 0xeb, 0x2e, 0x11, 0xdc, 0x14, 0x41, + 0x03, 0xc5, 0xf8, 0xf2, 0x29, 0x20, 0x20, 0x10, 0x37, 0x9e, 0x2d, 0xb5, + 0x0b, 0xfb, 0x65, 0xc7, 0xe1, 0x2c, 0xc7, 0x21, 0x9f, 0xeb, 0x21, 0xbb, + 0xcf, 0xf4, 0xcf, 0xe3, 0x0f, 0xf6, 0x26, 0xf4, 0x88, 0xfe, 0xad, 0x35, + 0xf5, 0x07, 0x81, 0xd6, 0xec, 0xe6, 0x5b, 0xa8, 0x25, 0xe6, 0xdc, 0xfd, + 0xdb, 0xa9, 0xd5, 0xb3, 0xa1, 0x05, 0x28, 0xc5, 0x52, 0x17, 0xcf, 0x3a, + 0xd8, 0x15, 0x49, 0xe6, 0x8b, 0xc8, 0x9c, 0xfa, 0x05, 0xf3, 0xd9, 0xbd, + 0x4c, 0xc9, 0x1f, 0xe8, 0xf9, 0x21, 0x50, 0xcf, 0x18, 0x19, 0xf0, 0x24, + 0xa7, 0xd7, 0xdc, 0xc2, 0xbc, 0x4c, 0xbb, 0x10, 0x30, 0xe5, 0x24, 0xe7, + 0xa8, 0xff, 0x88, 0x18, 0x01, 0x18, 0xe4, 0xcb, 0x22, 0xdb, 0x1d, 0xac, + 0x37, 0xff, 0x0a, 0xec, 0xc4, 0xcc, 0xc0, 0xd7, 0xbb, 0x12, 0x06, 0xe7, + 0xe4, 0x1a, 0x10, 0xf2, 0xe2, 0xb1, 0x0f, 0xf3, 0xc2, 0x2b, 0xa8, 0xf1, + 0x2c, 0x65, 0x27, 0x12, 0x3f, 0xab, 0x07, 0xac, 0x16, 0x2d, 0x24, 0x0b, + 0x36, 0xc7, 0xa3, 0xf2, 0xf1, 0x05, 0xdd, 0xec, 0xd0, 0x1a, 0xdc, 0x29, + 0x0a, 0xc9, 0x1a, 0xd6, 0x1b, 0x22, 0x24, 0x0c, 0xf6, 0x41, 0x04, 0xc8, + 0x3d, 0xf3, 0x0e, 0xdc, 0x47, 0x24, 0xe3, 0xe8, 0xf9, 0xbf, 0xdb, 0x15, + 0xe2, 0x04, 0xc8, 0xe0, 0xcd, 0x20, 0x09, 0x24, 0xe9, 0xdd, 0x06, 0xfc, + 0xca, 0x15, 0xaa, 0xf4, 0x40, 0x40, 0x2b, 0x17, 0x27, 0x0d, 0x34, 0xa3, + 0x15, 0x16, 0x5d, 0xd7, 0x02, 0x31, 0xd8, 0x32, 0xf6, 0x02, 0x11, 0xe8, + 0x09, 0x47, 0xe9, 0x20, 0xaf, 0xf9, 0x51, 0xd4, 0xed, 0xf5, 0xd1, 0x05, + 0x17, 0x21, 0xd6, 0xfe, 0x02, 0x15, 0x3a, 0x84, 0x50, 0xec, 0xda, 0x0f, + 0xe5, 0xb8, 0x01, 0x40, 0xf6, 0xa7, 0x28, 0xe3, 0x1c, 0x0e, 0xcc, 0x37, + 0xdd, 0x18, 0x40, 0xf1, 0xba, 0x20, 0xb9, 0xd8, 0x1d, 0xf6, 0xe7, 0xef, + 0x11, 0x06, 0xf4, 0xb5, 0x30, 0xfb, 0x4e, 0xbf, 0x15, 0x24, 0x00, 0x1d, + 0x17, 0xe2, 0xf9, 0x01, 0xd9, 0x2b, 0xd3, 0x31, 0x04, 0xfe, 0x3d, 0xe9, + 0xef, 0x23, 0xf4, 0x2d, 0x23, 0x2b, 0xc2, 0xdb, 0xe6, 0xeb, 0xe3, 0xfe, + 0x04, 0xc8, 0xbb, 0xe3, 0xfc, 0xe5, 0x1f, 0xfa, 0x03, 0xf4, 0xf5, 0xee, + 0xc6, 0xd7, 0x0e, 0xd1, 0x00, 0xf3, 0x13, 0xf8, 0x00, 0x11, 0xda, 0x08, + 0x1b, 0x06, 0x0e, 0xea, 0x02, 0xf7, 0xb7, 0x0d, 0xc8, 0xc0, 0x19, 0xee, + 0xc6, 0xf9, 0x3f, 0x04, 0xf6, 0x04, 0x02, 0xfd, 0x05, 0x1d, 0x02, 0xe0, + 0x2c, 0xff, 0x15, 0x0e, 0xf6, 0xff, 0x05, 0xff, 0xef, 0x28, 0x10, 0x05, + 0xfe, 0xf6, 0xf7, 0xfd, 0xfc, 0xef, 0xfe, 0xf4, 0x0e, 0xed, 0x2a, 0xff, + 0x03, 0xde, 0xf6, 0x1b, 0x0b, 0xf9, 0x03, 0xec, 0x39, 0xf1, 0x06, 0x4d, + 0x05, 0x0d, 0x0b, 0x0a, 0x2f, 0x12, 0x0a, 0xf4, 0x15, 0xfa, 0x12, 0xc7, + 0xe6, 0xff, 0x24, 0xdd, 0xfd, 0x27, 0x06, 0xf4, 0x13, 0x16, 0x0e, 0xe9, + 0x0a, 0xe5, 0xee, 0xc8, 0x07, 0xd7, 0x1c, 0x12, 0xde, 0x1c, 0xed, 0xca, + 0x26, 0xf2, 0xec, 0xf3, 0xe3, 0x24, 0x17, 0xf0, 0x28, 0x0e, 0x0e, 0x1b, + 0xaa, 0x2a, 0x17, 0x07, 0xdd, 0xf6, 0xf9, 0x15, 0x43, 0xde, 0xf5, 0x07, + 0x10, 0xcc, 0x24, 0x17, 0xfc, 0x30, 0xfc, 0xd6, 0xc2, 0x08, 0x1a, 0x23, + 0xec, 0x03, 0x1b, 0xfd, 0xe9, 0xf5, 0x2a, 0xe8, 0x0b, 0x28, 0x17, 0x05, + 0x18, 0x23, 0xe1, 0x06, 0x1c, 0xd6, 0xda, 0x0b, 0x26, 0xc9, 0x29, 0x44, + 0xe4, 0x22, 0xce, 0xdb, 0x15, 0x01, 0xf6, 0xf7, 0xfc, 0xee, 0xf7, 0xfe, + 0xde, 0xce, 0xce, 0xda, 0xf2, 0xee, 0x0f, 0xde, 0x12, 0x03, 0xf9, 0xd1, + 0xdf, 0xe8, 0x27, 0xe2, 0x14, 0xe3, 0xf2, 0x10, 0xf8, 0x07, 0xd6, 0xf2, + 0x13, 0xe1, 0xf8, 0x09, 0xe7, 0x11, 0xdf, 0x22, 0xce, 0xd1, 0xef, 0xce, + 0xb3, 0xe7, 0x0d, 0xe7, 0xda, 0xd4, 0x08, 0xd9, 0xf5, 0x36, 0xfa, 0xf9, + 0x3c, 0xe2, 0x02, 0x1a, 0xd3, 0xf0, 0xda, 0x0d, 0xe1, 0xf4, 0x12, 0x10, + 0xe6, 0x0c, 0xdb, 0x0c, 0xe7, 0xe6, 0xd5, 0xe1, 0xf8, 0xe1, 0x31, 0xe7, + 0xe2, 0xd7, 0xda, 0xeb, 0xd4, 0xcc, 0x07, 0xf2, 0x5a, 0xe0, 0x02, 0x7f, + 0xf6, 0x0a, 0xf1, 0xc6, 0x2c, 0x24, 0x1b, 0xe1, 0xf3, 0x2f, 0xf0, 0x1f, + 0x0a, 0x04, 0x0c, 0xfa, 0xe2, 0x34, 0x0e, 0x07, 0xff, 0xd8, 0x19, 0x0f, + 0xf5, 0xf1, 0x05, 0xfa, 0xe9, 0x05, 0x11, 0xec, 0xfd, 0x1e, 0x14, 0xde, + 0xc3, 0xe7, 0xee, 0x16, 0x0f, 0x20, 0x05, 0x01, 0xfd, 0xdc, 0xff, 0x08, + 0x04, 0x00, 0xf2, 0x18, 0x04, 0xa1, 0x12, 0x10, 0xff, 0x27, 0xe3, 0x0a, + 0x14, 0x02, 0xdf, 0xfe, 0x0f, 0x28, 0x16, 0xce, 0x3b, 0x0d, 0xd2, 0x11, + 0xd5, 0x24, 0xd3, 0x1c, 0x0b, 0x06, 0xf2, 0x01, 0xe2, 0x10, 0xd3, 0xbf, + 0xf4, 0xe2, 0x0d, 0x05, 0xde, 0xd7, 0x00, 0x09, 0xcb, 0xec, 0x04, 0x15, + 0xcb, 0x1e, 0x1e, 0xda, 0x9b, 0xaf, 0xfc, 0x08, 0xd6, 0x1f, 0xee, 0x34, + 0x2b, 0xf5, 0x1e, 0x11, 0x0c, 0x36, 0x02, 0xe1, 0x05, 0x05, 0x18, 0x08, + 0xfc, 0xfb, 0xf8, 0x19, 0x18, 0x27, 0x26, 0xd9, 0xec, 0x25, 0x0a, 0x11, + 0xcf, 0xd3, 0xec, 0xd9, 0x7f, 0xfd, 0x0e, 0x4b, 0x13, 0xdd, 0xfa, 0x1b, + 0xfd, 0x1c, 0xcd, 0xd7, 0x19, 0xfa, 0xc5, 0x19, 0x0b, 0x2f, 0xe9, 0x04, + 0x27, 0xec, 0x1c, 0xe0, 0x34, 0x37, 0x48, 0x4c, 0xed, 0xde, 0xca, 0xd6, + 0xc7, 0x2b, 0xe7, 0x36, 0x31, 0xfc, 0x03, 0x0c, 0x01, 0x07, 0xf9, 0xe6, + 0x10, 0xf8, 0x1f, 0x15, 0x17, 0xdc, 0xf7, 0x18, 0x26, 0x1d, 0x31, 0xdc, + 0xa8, 0x26, 0x2a, 0xfd, 0xb2, 0xc8, 0xf9, 0xe8, 0xf2, 0x2b, 0x04, 0x2d, + 0x1f, 0x27, 0x2a, 0xdc, 0xfb, 0x27, 0xee, 0xe4, 0xf1, 0xe1, 0x1e, 0xdb, + 0xf7, 0x08, 0x0d, 0xf7, 0xe2, 0x00, 0x20, 0xf3, 0xff, 0x37, 0xee, 0xf6, + 0xd2, 0xd7, 0xbb, 0x1e, 0xf7, 0x24, 0x10, 0x28, 0x20, 0xde, 0x05, 0xf5, + 0xd9, 0x19, 0x00, 0x14, 0xc1, 0xab, 0xf9, 0xdc, 0x20, 0x16, 0xf6, 0x1a, + 0x34, 0xdf, 0xf1, 0xf3, 0xe6, 0x34, 0xe8, 0xf5, 0x2e, 0x14, 0xd2, 0x05, + 0xde, 0x24, 0xe7, 0xe7, 0x12, 0x04, 0x0b, 0xfb, 0xf5, 0x0b, 0xc6, 0xd4, + 0xf3, 0xcd, 0x13, 0x04, 0xf2, 0xf8, 0x00, 0x15, 0xd4, 0xe2, 0x0e, 0xe9, + 0xbe, 0x2f, 0x15, 0xff, 0xc1, 0xce, 0xeb, 0x11, 0x27, 0xc5, 0xd8, 0x09, + 0x0a, 0xe3, 0xea, 0xee, 0x07, 0xcc, 0x06, 0x0f, 0xdd, 0xfd, 0x0f, 0xed, + 0xc5, 0x02, 0x2a, 0xce, 0xf6, 0x07, 0x36, 0xe9, 0x05, 0x1c, 0x06, 0xf8, + 0x12, 0x18, 0x23, 0x02, 0xfd, 0xce, 0xb8, 0xfe, 0xd9, 0x9b, 0x05, 0xf1, + 0x02, 0xf7, 0x00, 0x08, 0x10, 0x84, 0x11, 0x01, 0xe3, 0x33, 0xfa, 0x04, + 0x19, 0xfc, 0x36, 0xee, 0xfc, 0xc7, 0x00, 0x0a, 0x12, 0x1d, 0xff, 0xf9, + 0x16, 0xfa, 0xf0, 0x17, 0xfb, 0xf5, 0xea, 0x03, 0x0b, 0xdd, 0x01, 0x03, + 0xd7, 0xcc, 0x12, 0x18, 0x0c, 0x02, 0x19, 0xfa, 0xf9, 0x06, 0x34, 0xd0, + 0x13, 0x35, 0x0b, 0xfd, 0x24, 0x26, 0x16, 0x06, 0x40, 0xf5, 0x23, 0xa9, + 0xf5, 0x05, 0x3b, 0xe1, 0xe6, 0x22, 0x19, 0x0e, 0xd3, 0x13, 0x20, 0xd8, + 0x09, 0xfb, 0xfe, 0x9c, 0x0f, 0xd2, 0x28, 0x13, 0xaf, 0x37, 0xff, 0xdf, + 0x0d, 0x00, 0xe2, 0x05, 0xf9, 0x34, 0x20, 0xe2, 0x2b, 0x25, 0xed, 0x20, + 0xbe, 0x15, 0x23, 0xfb, 0xff, 0xfa, 0x2f, 0x13, 0x34, 0xcb, 0x81, 0x32, + 0xfc, 0xbb, 0x1d, 0x1d, 0x08, 0x30, 0x14, 0xdb, 0xa8, 0xc6, 0xe3, 0xe7, + 0xec, 0x15, 0x39, 0xec, 0xfe, 0xe6, 0x3d, 0xe0, 0x0f, 0x2e, 0x1b, 0x0f, + 0xd3, 0x1d, 0xd3, 0x0b, 0x20, 0xee, 0xd4, 0x1a, 0x22, 0xb7, 0x33, 0x23, + 0xa6, 0x2e, 0xae, 0xf8, 0x11, 0xfd, 0xd3, 0xd8, 0x02, 0xf3, 0xf8, 0xfe, + 0xfb, 0xd5, 0xdb, 0xd4, 0xdb, 0xe2, 0x0d, 0xef, 0xda, 0xf3, 0x03, 0xda, + 0xfd, 0x0b, 0x1c, 0xc4, 0x4b, 0x0e, 0x19, 0x20, 0xe7, 0x1d, 0xcc, 0x13, + 0x08, 0xf7, 0x0f, 0x22, 0x00, 0xe0, 0xd5, 0x24, 0xe1, 0xc8, 0x12, 0xb7, + 0xc5, 0x03, 0x22, 0xd0, 0xf0, 0xab, 0x07, 0xd3, 0xd7, 0x41, 0xef, 0xfa, + 0x3c, 0xbe, 0xf1, 0x26, 0xe3, 0xf6, 0xce, 0x28, 0xf5, 0xd0, 0xe5, 0x05, + 0x0b, 0xe5, 0xdc, 0x16, 0x03, 0xea, 0xec, 0xe3, 0x10, 0xee, 0x18, 0xdf, + 0xad, 0xd2, 0xcd, 0xf5, 0xe7, 0xed, 0x11, 0xeb, 0x49, 0xea, 0x20, 0x3b, + 0xf2, 0x2f, 0xef, 0xdf, 0x2f, 0x3a, 0x19, 0xe4, 0xdc, 0x18, 0x86, 0xf1, + 0x23, 0x35, 0xf8, 0x29, 0x48, 0x0f, 0x16, 0x00, 0x33, 0x16, 0x04, 0xc6, + 0xd7, 0xe6, 0x2c, 0x10, 0xe2, 0xe8, 0xe9, 0xe9, 0x1b, 0xf4, 0xf9, 0xce, + 0x0a, 0x19, 0x08, 0x2b, 0x0a, 0xec, 0xb4, 0xef, 0xfc, 0x16, 0xd1, 0x0d, + 0xe9, 0xd9, 0xd9, 0xd6, 0x07, 0xd6, 0xdf, 0xe5, 0xee, 0xf5, 0xee, 0x1d, + 0xfa, 0xf0, 0xc0, 0x1b, 0xf7, 0x07, 0xeb, 0xd7, 0x15, 0xdd, 0xfa, 0xfb, + 0xd5, 0x16, 0x94, 0xda, 0x19, 0x01, 0x02, 0x24, 0x34, 0x21, 0x21, 0xef, + 0x1c, 0x21, 0xd7, 0xc8, 0xe2, 0xf0, 0x27, 0x27, 0xf6, 0xcb, 0xe6, 0x1a, + 0x22, 0xde, 0xe3, 0xcb, 0x05, 0x0d, 0x01, 0x16, 0x13, 0xb2, 0xf6, 0xee, + 0xe5, 0xea, 0x1a, 0xfa, 0x57, 0x00, 0xb7, 0x26, 0x12, 0xf3, 0x43, 0xcb, + 0xe7, 0x0f, 0x34, 0xe9, 0xd9, 0xc7, 0xfb, 0x03, 0x81, 0xc6, 0xe7, 0x4c, + 0xfe, 0xf1, 0xf6, 0x22, 0x2c, 0x26, 0xf9, 0xeb, 0x09, 0xee, 0xd9, 0x17, + 0xe0, 0xda, 0x00, 0x04, 0xd4, 0xc2, 0x0b, 0x10, 0x05, 0x26, 0x1a, 0x06, + 0xfc, 0xe1, 0xf0, 0x01, 0x1e, 0xd0, 0x25, 0xf6, 0x14, 0x04, 0x2a, 0x51, + 0x21, 0xfa, 0x0d, 0xc9, 0xe3, 0x1f, 0x09, 0xfc, 0x4b, 0xee, 0xb9, 0x23, + 0x08, 0xf0, 0x59, 0xcc, 0xde, 0xd2, 0x52, 0x0e, 0xed, 0xf1, 0x05, 0x48, + 0xad, 0xa6, 0xdd, 0x48, 0x2f, 0xda, 0x08, 0xf4, 0xc3, 0xec, 0xd3, 0xc6, + 0x37, 0x2d, 0x09, 0x0d, 0x48, 0x0a, 0xf3, 0xe6, 0x2d, 0x18, 0xed, 0xba, + 0xca, 0xee, 0x0a, 0x1e, 0xd0, 0xd7, 0x0b, 0x07, 0xd3, 0xf2, 0xbf, 0x18, + 0x0c, 0x25, 0x27, 0xfb, 0x03, 0xda, 0xce, 0xd0, 0xec, 0xff, 0xf9, 0x02, + 0xc3, 0xc5, 0xe8, 0xe5, 0x1c, 0xe4, 0xec, 0xc8, 0x27, 0x2b, 0x0e, 0x00, + 0x0a, 0xf4, 0xca, 0x33, 0xc4, 0xca, 0xc0, 0x36, 0x03, 0xdd, 0x22, 0x01, + 0xc0, 0x01, 0xbd, 0xed, 0x14, 0x20, 0x11, 0x29, 0x3e, 0x17, 0xe3, 0xf4, + 0x1c, 0x29, 0xeb, 0xc6, 0xe0, 0xe8, 0x27, 0x34, 0x1f, 0xc6, 0xde, 0x33, + 0xef, 0xe0, 0xd3, 0xfa, 0x39, 0x18, 0x22, 0x03, 0x2e, 0xeb, 0xcb, 0xd5, + 0x09, 0x11, 0xdd, 0x1b, 0x33, 0xe5, 0x11, 0xe4, 0x06, 0x25, 0xfb, 0xef, + 0xff, 0x1d, 0x26, 0xfd, 0xc4, 0xd7, 0x0d, 0xdf, 0x1c, 0xbe, 0x02, 0x04, + 0x0f, 0x37, 0x13, 0xf9, 0x26, 0xb8, 0x9a, 0xcc, 0xfa, 0x32, 0xe9, 0x07, + 0x04, 0xce, 0xec, 0xc1, 0xdd, 0x81, 0xdb, 0x01, 0xe8, 0x3e, 0xa2, 0x34, + 0xdc, 0xec, 0xef, 0x11, 0x13, 0xb1, 0xf1, 0x22, 0xe6, 0xbd, 0xf1, 0xe9, + 0xfc, 0xc9, 0xb9, 0xca, 0xf6, 0x0e, 0xe4, 0x14, 0x21, 0xdd, 0x1d, 0xe2, + 0xe1, 0x2b, 0xee, 0xe8, 0x0d, 0xff, 0x02, 0x14, 0x0d, 0xda, 0xff, 0x34, + 0x28, 0xb7, 0xff, 0xb2, 0x36, 0x38, 0x0f, 0xef, 0x08, 0xfb, 0xf7, 0xe1, + 0xe4, 0xe9, 0x01, 0xe7, 0x2a, 0xff, 0xe9, 0x36, 0x05, 0x0d, 0x11, 0xd8, + 0xd8, 0x2d, 0x2c, 0x01, 0xf9, 0x0a, 0xc7, 0x12, 0xb6, 0xe9, 0xae, 0x28, + 0x1e, 0x23, 0xf7, 0x12, 0xd8, 0x1f, 0x06, 0x00, 0x11, 0xfa, 0xfa, 0x1c, + 0xd3, 0x07, 0x01, 0x0d, 0xe4, 0xdf, 0xda, 0xf9, 0x08, 0x08, 0xca, 0x1d, + 0x0e, 0xf8, 0x0f, 0x15, 0xe1, 0xeb, 0xc7, 0xd8, 0xde, 0xb3, 0xf2, 0x10, + 0x18, 0xf6, 0x19, 0xca, 0xb6, 0x1c, 0x03, 0xe4, 0x2b, 0xf3, 0xfb, 0x35, + 0xf2, 0x01, 0xf4, 0xed, 0xfa, 0x1d, 0x51, 0x10, 0x31, 0xf9, 0xc8, 0x76, + 0xcf, 0xdb, 0xb9, 0x22, 0x4c, 0x1e, 0xde, 0x14, 0x09, 0xd3, 0xc5, 0xb4, + 0xf2, 0x19, 0xea, 0x2d, 0x20, 0xc6, 0x33, 0xe5, 0xfd, 0x1a, 0x12, 0xc7, + 0xe4, 0xd8, 0x15, 0x23, 0xf9, 0xc9, 0xdc, 0x1a, 0x1c, 0x95, 0xda, 0xd9, + 0x15, 0x23, 0x07, 0xf3, 0xfc, 0xb5, 0xaf, 0xde, 0x05, 0x2f, 0xea, 0xe5, + 0xf9, 0xc2, 0xfa, 0xce, 0x09, 0x9e, 0x01, 0xca, 0xc7, 0xe6, 0xd6, 0x17, + 0x22, 0xf3, 0xe4, 0x33, 0xd2, 0x9c, 0xdd, 0xfd, 0x1f, 0xd4, 0xee, 0xf9, + 0xf2, 0x0a, 0xc2, 0xb6, 0xe0, 0x17, 0x0e, 0x32, 0x1c, 0xfa, 0xfb, 0xe2, + 0xf8, 0x42, 0xd8, 0xe4, 0xe3, 0xe7, 0x12, 0x1b, 0x24, 0xd0, 0xa4, 0x6b, + 0x18, 0x9f, 0xdd, 0xba, 0x42, 0x2a, 0x13, 0x22, 0x0f, 0xf8, 0xc8, 0x07, + 0x29, 0x17, 0xc1, 0x23, 0x27, 0xe1, 0xff, 0x21, 0x0d, 0x01, 0x0e, 0xf8, + 0xdf, 0x13, 0x26, 0x0c, 0xdd, 0x0d, 0x12, 0xf0, 0xf6, 0x01, 0x13, 0x1c, + 0xf9, 0x11, 0xf2, 0x2a, 0xf8, 0xee, 0xd6, 0x3e, 0x04, 0x0d, 0x05, 0x08, + 0xd4, 0xca, 0xfe, 0x0f, 0x24, 0xa9, 0x4b, 0xce, 0xf0, 0x7e, 0x22, 0x19, + 0xf5, 0x1d, 0xf0, 0xf0, 0xfe, 0x08, 0xe9, 0x19, 0xea, 0xec, 0xf3, 0x37, + 0xd9, 0x0f, 0xe8, 0x38, 0x07, 0x27, 0xe0, 0x1c, 0x06, 0xee, 0xf0, 0x11, + 0x16, 0xfb, 0xf3, 0xf2, 0xfc, 0xdc, 0x26, 0x1f, 0xda, 0x10, 0x02, 0xef, + 0xeb, 0x0a, 0xf9, 0xca, 0xd0, 0x16, 0x22, 0x0d, 0x30, 0xdd, 0xfb, 0xf0, + 0x08, 0xf4, 0x25, 0xf9, 0x34, 0xda, 0xca, 0x2b, 0xe6, 0x0e, 0x46, 0xed, + 0xfc, 0xe1, 0xfc, 0x3a, 0xdb, 0xc8, 0x06, 0xf6, 0x8f, 0xc2, 0x07, 0x4a, + 0xd8, 0xda, 0xd7, 0x12, 0x40, 0x0d, 0x20, 0xf4, 0x32, 0x24, 0xd6, 0x14, + 0xfc, 0xeb, 0xfb, 0x11, 0xfc, 0xf3, 0x23, 0x04, 0x1a, 0x3f, 0xe7, 0x1f, + 0xe3, 0x30, 0x0c, 0xf4, 0x5d, 0xfe, 0x47, 0x2b, 0xe6, 0xf7, 0xb8, 0x04, + 0x08, 0x04, 0x21, 0x0a, 0xfc, 0x13, 0x1b, 0xd4, 0x23, 0x12, 0xda, 0x38, + 0xd4, 0xed, 0x6e, 0xec, 0xee, 0xb4, 0x15, 0x3b, 0x0c, 0xcd, 0x08, 0x07, + 0x84, 0xf9, 0x20, 0x34, 0xdc, 0xe4, 0xe2, 0x33, 0xeb, 0xb7, 0xad, 0x04, + 0x37, 0x32, 0x0c, 0xf4, 0x25, 0xe8, 0xa7, 0xe2, 0x0e, 0xf6, 0xfd, 0xec, + 0xf7, 0xe7, 0x1e, 0xf9, 0xbc, 0x04, 0x24, 0xe1, 0xc3, 0x0e, 0xc7, 0x01, + 0xe1, 0x14, 0x14, 0xf8, 0x04, 0xb4, 0xda, 0x2d, 0x09, 0xdc, 0x1b, 0xe2, + 0xd0, 0xb6, 0xd1, 0x17, 0x03, 0x81, 0x4a, 0xe8, 0x19, 0x3b, 0x15, 0xec, + 0x20, 0x0f, 0xe9, 0xef, 0xae, 0xd9, 0xc2, 0x27, 0x2d, 0x16, 0xc6, 0x30, + 0xe9, 0xd1, 0xd4, 0x15, 0x10, 0x22, 0xfb, 0xfe, 0x07, 0xd2, 0xba, 0xcf, + 0x00, 0x0a, 0xfb, 0xda, 0xe6, 0xbf, 0x1a, 0x14, 0x95, 0xe4, 0xe8, 0xd0, + 0xd5, 0x10, 0xe2, 0x01, 0xd1, 0xfc, 0xff, 0xce, 0xf8, 0xfa, 0x17, 0x07, + 0xd8, 0xd1, 0x04, 0xf2, 0xde, 0xff, 0x0d, 0xf6, 0xec, 0xec, 0xef, 0x08, + 0x18, 0xf3, 0x04, 0xe3, 0x01, 0xee, 0xf2, 0xf5, 0xe8, 0xf4, 0x0a, 0x10, + 0x22, 0x05, 0x10, 0xf3, 0xe6, 0x14, 0xfe, 0x01, 0xe4, 0xf3, 0xfd, 0xee, + 0xe6, 0x02, 0x2b, 0xf4, 0xfb, 0x0d, 0x00, 0x1a, 0x0c, 0xf3, 0x07, 0xfe, + 0x10, 0xf7, 0x00, 0x1c, 0xee, 0x0a, 0xf5, 0xe2, 0xf7, 0xfa, 0x10, 0x03, + 0xfd, 0x08, 0xfe, 0xf7, 0x00, 0xef, 0x12, 0xfa, 0x0e, 0x13, 0x3e, 0x00, + 0x03, 0x04, 0xf2, 0x0a, 0x03, 0x0b, 0xf2, 0xef, 0x3a, 0xf0, 0x27, 0x3b, + 0x12, 0x0d, 0x00, 0x15, 0x1e, 0x0c, 0x02, 0xf8, 0xf8, 0x08, 0x0a, 0xfb, + 0xe0, 0xed, 0x20, 0xf6, 0xe2, 0x3c, 0x19, 0xf9, 0xd4, 0xfa, 0xe2, 0x01, + 0x08, 0xef, 0xeb, 0xef, 0x1c, 0xea, 0x15, 0xf6, 0xce, 0x3a, 0xdc, 0xea, + 0x0b, 0x13, 0x07, 0xdc, 0xea, 0x1b, 0x03, 0x09, 0x0c, 0xfd, 0x1b, 0xfb, + 0xe7, 0x34, 0xfc, 0x13, 0xf9, 0xfb, 0xf3, 0x05, 0x21, 0xdd, 0xfa, 0xec, + 0x1d, 0xde, 0x24, 0x0b, 0xf7, 0x40, 0xd1, 0xe7, 0xee, 0x0b, 0x0b, 0x12, + 0xff, 0xe7, 0xff, 0x0e, 0xfe, 0xf6, 0x12, 0xfc, 0xfc, 0x2f, 0x3f, 0xf0, + 0x1d, 0x0b, 0xdc, 0xf1, 0x00, 0xe4, 0xee, 0xf3, 0x42, 0xef, 0x20, 0x31, + 0x03, 0x31, 0xe6, 0xde, 0x1f, 0x08, 0x02, 0xe3, 0xea, 0xe7, 0x0b, 0x0f, + 0xce, 0xce, 0xea, 0xeb, 0xce, 0x0b, 0x1d, 0x02, 0xc3, 0xf1, 0xe2, 0xd3, + 0xef, 0xdf, 0x08, 0xe3, 0x21, 0xd4, 0xde, 0xf1, 0xdd, 0xef, 0xf6, 0xc9, + 0xf5, 0x1d, 0xee, 0xf5, 0xe3, 0x29, 0x0a, 0x19, 0xed, 0xf9, 0xf5, 0xe3, + 0xde, 0x04, 0x2c, 0xf8, 0xd9, 0xde, 0xf1, 0xfa, 0xff, 0xee, 0xf7, 0xf9, + 0x31, 0xea, 0x10, 0x10, 0xed, 0x02, 0xde, 0xdd, 0x01, 0xfe, 0xfd, 0xfa, + 0x08, 0xff, 0xe1, 0xf0, 0xdb, 0xe6, 0xe1, 0xd5, 0xe1, 0xeb, 0x4c, 0xf0, + 0x06, 0xde, 0xf2, 0xe6, 0xdf, 0xe0, 0xf6, 0xf2, 0x74, 0xee, 0xec, 0x7f, + 0x05, 0xf9, 0x05, 0xdc, 0x15, 0xf6, 0xfa, 0xdb, 0xf6, 0x11, 0x1d, 0xd9, + 0x19, 0xff, 0x20, 0x0a, 0xfa, 0x23, 0xc3, 0x25, 0xf4, 0xef, 0xec, 0xb9, + 0xd9, 0xff, 0xfc, 0x00, 0x02, 0xf7, 0x10, 0xf9, 0xa7, 0x01, 0xb4, 0x36, + 0xfc, 0x23, 0xde, 0x2a, 0x09, 0x04, 0x28, 0xd6, 0x39, 0xf0, 0xee, 0x09, + 0xb3, 0xef, 0xcb, 0x17, 0x1e, 0xf3, 0xfb, 0xaa, 0x11, 0x4f, 0xdf, 0x05, + 0xf0, 0xf0, 0xee, 0xf1, 0x81, 0xe5, 0x99, 0x55, 0x09, 0xe1, 0xee, 0xec, + 0xe9, 0x0b, 0x03, 0xe7, 0x15, 0x00, 0x1b, 0x05, 0x0d, 0x06, 0xd2, 0x1a, + 0x05, 0x00, 0xe8, 0xbf, 0xd3, 0x04, 0x0d, 0x07, 0xfa, 0xde, 0x0b, 0xf2, + 0xa8, 0x0b, 0xa2, 0xf6, 0x14, 0x1d, 0x06, 0x01, 0x40, 0xcd, 0xf8, 0xe2, + 0x14, 0x08, 0x17, 0xf5, 0x0d, 0xd7, 0xe1, 0x05, 0xc3, 0xf6, 0x3f, 0xd1, + 0xe5, 0x06, 0x17, 0xfb, 0xd7, 0xcf, 0x08, 0xf4, 0xb4, 0xda, 0xfa, 0xee, + 0xff, 0x18, 0x20, 0x19, 0x19, 0xd8, 0x11, 0xd8, 0xea, 0x21, 0x0f, 0x05, + 0xfe, 0xf3, 0xf3, 0xfb, 0xfd, 0x0f, 0x52, 0x04, 0x02, 0x20, 0xda, 0x13, + 0xf6, 0xee, 0xfd, 0xee, 0x16, 0x01, 0x14, 0x04, 0x17, 0x28, 0x07, 0xe3, + 0x5b, 0x00, 0x19, 0xf3, 0xf0, 0x2e, 0xfd, 0xed, 0x17, 0xe7, 0xd1, 0x14, + 0xe9, 0xf9, 0x56, 0xec, 0xe7, 0x1e, 0x12, 0x17, 0xe8, 0xe1, 0xfd, 0x24, + 0xa8, 0xeb, 0xe5, 0xe6, 0x23, 0x16, 0x1a, 0x0b, 0x2b, 0xf1, 0x09, 0x9f, + 0x44, 0x33, 0x39, 0x01, 0x16, 0x05, 0xba, 0x27, 0xe6, 0x03, 0x00, 0xf4, + 0x07, 0x33, 0xfd, 0x00, 0xb6, 0xe7, 0x37, 0xcc, 0xe8, 0xfd, 0xeb, 0x2e, + 0x1a, 0x2a, 0x09, 0x34, 0x16, 0xee, 0x3a, 0xa3, 0x53, 0xf6, 0xc9, 0xfa, + 0xdf, 0xc8, 0xdd, 0xfd, 0x18, 0xd3, 0x05, 0xd8, 0x0f, 0x44, 0xc9, 0x1d, + 0xbd, 0xe3, 0x3c, 0xda, 0xd0, 0xce, 0xd7, 0x3f, 0xfe, 0xf4, 0xef, 0xe2, + 0x2f, 0x0e, 0xe6, 0xcb, 0x40, 0x21, 0x2c, 0xec, 0x14, 0xe7, 0xe8, 0x3d, + 0xea, 0xdf, 0xf7, 0xe7, 0xe0, 0x20, 0x02, 0x04, 0xe9, 0xe2, 0x33, 0xe1, + 0xe8, 0x0c, 0xda, 0x2f, 0x38, 0x26, 0x04, 0xf5, 0x2f, 0xf1, 0x29, 0xe4, + 0xe1, 0xd8, 0x10, 0xc3, 0xf5, 0x14, 0xff, 0x13, 0x0b, 0x0b, 0xdd, 0x04, + 0x25, 0xe3, 0xcf, 0xd3, 0x15, 0xf9, 0xf3, 0xfe, 0x0a, 0xce, 0xdb, 0x15, + 0x56, 0x16, 0x0b, 0xcf, 0xff, 0x0e, 0x0b, 0xec, 0xe2, 0x0d, 0xf5, 0xfc, + 0x0a, 0xd0, 0xe8, 0xfc, 0xf9, 0x5d, 0xf0, 0x1a, 0xfb, 0xc7, 0x22, 0xe9, + 0xea, 0x0d, 0xf0, 0xf9, 0xd6, 0xc9, 0x00, 0xd4, 0xfa, 0x1d, 0x29, 0x14, + 0x14, 0xeb, 0x0f, 0xe3, 0xec, 0xd3, 0x27, 0xda, 0x24, 0xfc, 0xf4, 0x1f, + 0x0c, 0xea, 0xe7, 0x0f, 0x22, 0xf1, 0xe5, 0xcc, 0x26, 0xff, 0xea, 0x1f, + 0xff, 0xc4, 0xff, 0x22, 0x51, 0x27, 0xfd, 0xdf, 0x24, 0xe1, 0xf3, 0xe3, + 0xe6, 0xdd, 0xe2, 0xe8, 0xcb, 0xec, 0xe4, 0xd4, 0x20, 0x1d, 0xd9, 0xc5, + 0xd9, 0x1e, 0xf0, 0xd5, 0x03, 0xc0, 0xf3, 0x21, 0x09, 0xf7, 0x9e, 0xd5, + 0x45, 0x43, 0x08, 0xe2, 0xdc, 0x03, 0xfe, 0xd8, 0xf3, 0x1a, 0x19, 0x10, + 0xfb, 0xf7, 0xf3, 0x34, 0xf9, 0x1b, 0xf2, 0x08, 0xf6, 0xc9, 0x24, 0xd2, + 0xf6, 0xed, 0xf3, 0xe8, 0xf2, 0x02, 0xed, 0xe0, 0x04, 0x45, 0x33, 0x1e, + 0x31, 0xf2, 0x0e, 0xcf, 0xed, 0x08, 0xfc, 0xd9, 0xf9, 0xe1, 0xfb, 0x14, + 0x16, 0xf8, 0xe3, 0xf2, 0xf6, 0xf7, 0xe3, 0xe3, 0xff, 0xde, 0xdd, 0x51, + 0x14, 0xde, 0x09, 0xd4, 0x35, 0x3e, 0x1e, 0xe4, 0x33, 0xe9, 0x30, 0xd5, + 0xf0, 0xe6, 0x19, 0xee, 0xd2, 0xfa, 0x1e, 0x12, 0xff, 0x20, 0xf3, 0xfa, + 0x10, 0xff, 0xe9, 0xe3, 0x38, 0x1c, 0xe4, 0x12, 0xf5, 0xf5, 0xd5, 0x15, + 0x51, 0x16, 0xe1, 0xcf, 0xe2, 0x17, 0x1a, 0xd7, 0xf5, 0x20, 0xfa, 0x02, + 0xfa, 0xe7, 0x13, 0x06, 0xec, 0x53, 0xef, 0x0b, 0x13, 0xd0, 0x17, 0xff, + 0x0b, 0xf3, 0x3d, 0x11, 0xf2, 0xd7, 0xf8, 0xe9, 0xf6, 0x0e, 0x34, 0x0e, + 0x02, 0xdf, 0x1b, 0xea, 0xf0, 0xeb, 0x2f, 0xe3, 0x14, 0xe2, 0xfe, 0x14, + 0x1d, 0xeb, 0xc7, 0xf6, 0x05, 0xfb, 0x00, 0xd5, 0x6c, 0xf8, 0xd7, 0x7f, + 0x01, 0xe3, 0xf2, 0xf4, 0x64, 0x36, 0x0b, 0xdf, 0xe4, 0xf8, 0xc9, 0x21, + 0x37, 0x04, 0xf1, 0xf3, 0x1a, 0x1d, 0xfc, 0xfe, 0x40, 0xfc, 0xf4, 0x12, + 0x09, 0xff, 0x04, 0x19, 0x03, 0x22, 0xef, 0xf5, 0x2a, 0x37, 0xf3, 0xfb, + 0xe9, 0xdb, 0xf2, 0xe6, 0xc2, 0xf4, 0xd2, 0x08, 0x02, 0xcb, 0xff, 0x2a, + 0xfe, 0x17, 0xf4, 0x13, 0xc5, 0xf2, 0x86, 0x27, 0x03, 0xec, 0x23, 0x16, + 0x04, 0x01, 0xe3, 0xf0, 0x1b, 0x2c, 0x14, 0xf9, 0xfb, 0xfb, 0xfb, 0xf7, + 0xf1, 0x01, 0x96, 0x2a, 0x3a, 0x33, 0xf3, 0xeb, 0x16, 0x01, 0x07, 0xd5, + 0x38, 0xdd, 0xff, 0x06, 0xe8, 0xed, 0xe9, 0x1e, 0xe6, 0x26, 0x0f, 0x05, + 0x19, 0x34, 0x1b, 0xfa, 0xee, 0xd7, 0xd7, 0xd7, 0xc4, 0xef, 0xf6, 0x3f, + 0x39, 0xf6, 0xdf, 0xfe, 0x0c, 0xe4, 0xdc, 0xbb, 0x5e, 0x20, 0x00, 0xba, + 0xbf, 0x10, 0x19, 0xcf, 0x02, 0xc9, 0x01, 0xf4, 0x06, 0x02, 0xe4, 0x4b, + 0x00, 0xe7, 0x00, 0x04, 0xfc, 0x1e, 0xd6, 0xff, 0x00, 0xa9, 0xeb, 0xef, + 0xee, 0xff, 0xe9, 0xbc, 0x06, 0x00, 0xdc, 0xf9, 0xe7, 0x51, 0x7c, 0x03, + 0xea, 0xfb, 0xfe, 0xdf, 0x22, 0x12, 0x1c, 0x3b, 0x08, 0xd9, 0x28, 0x5e, + 0xe0, 0xef, 0xf1, 0xee, 0x1d, 0xeb, 0xfd, 0xf3, 0x36, 0x05, 0xd8, 0xc6, + 0x39, 0xf9, 0xf4, 0xf8, 0xf5, 0x05, 0xfb, 0xc6, 0xf8, 0xc1, 0x0f, 0x07, + 0x2e, 0x03, 0x16, 0x40, 0xf6, 0xd2, 0x16, 0xe6, 0xcf, 0x05, 0xf7, 0x2f, + 0x26, 0x0f, 0x27, 0xee, 0x19, 0x25, 0xb7, 0xde, 0x48, 0x18, 0xef, 0x13, + 0xf6, 0xe1, 0x12, 0xfc, 0xfd, 0x21, 0xf5, 0xe0, 0x3d, 0x5c, 0xe9, 0x02, + 0xee, 0xea, 0xe9, 0x06, 0xd8, 0x11, 0xf1, 0x3e, 0x23, 0xb6, 0x1e, 0x52, + 0xf2, 0x20, 0xcc, 0xfc, 0x00, 0x7f, 0xb0, 0x3d, 0x20, 0xee, 0x2f, 0xf8, + 0x20, 0x1e, 0xdd, 0xcb, 0xe2, 0x3b, 0x00, 0xf6, 0x22, 0x11, 0x1f, 0x2f, + 0xe8, 0x1a, 0xce, 0x08, 0x1d, 0x0f, 0x10, 0xc7, 0x2b, 0xf8, 0x04, 0xc9, + 0x2a, 0xe2, 0x01, 0x16, 0x01, 0xf4, 0xf1, 0x12, 0xbc, 0x00, 0x0c, 0x00, + 0x29, 0x29, 0x16, 0x04, 0xf7, 0xdc, 0xe5, 0x03, 0x27, 0xb0, 0xee, 0x06, + 0xfd, 0xe2, 0x23, 0xef, 0x18, 0x08, 0x21, 0x00, 0xd2, 0x39, 0x01, 0x16, + 0xfb, 0x22, 0x14, 0x01, 0xeb, 0x13, 0x22, 0xf2, 0x48, 0x0a, 0x2a, 0xc9, + 0x00, 0xfc, 0xd2, 0xe9, 0xda, 0xd7, 0xe6, 0x38, 0x54, 0xdd, 0xe7, 0x2f, + 0x21, 0xe3, 0xfa, 0xde, 0xa9, 0x08, 0xa1, 0x12, 0x27, 0xb4, 0x45, 0x5f, + 0xf3, 0x09, 0x2a, 0xdb, 0x33, 0xf5, 0x01, 0xb5, 0xd2, 0xed, 0x14, 0x05, + 0x11, 0xd5, 0xd1, 0xed, 0x1f, 0x29, 0x2b, 0xc0, 0x28, 0xee, 0x35, 0xf2, + 0x07, 0xd7, 0x13, 0x07, 0xef, 0x22, 0xc6, 0x10, 0xd5, 0xfc, 0x17, 0xf6, + 0x23, 0x21, 0x03, 0xf1, 0xfd, 0xfd, 0xdb, 0xd1, 0xcf, 0xfc, 0x02, 0xce, + 0x2b, 0xfe, 0xcd, 0x0e, 0xfe, 0x03, 0xdf, 0xd3, 0x02, 0x2e, 0xf3, 0xd5, + 0xc3, 0x54, 0x4d, 0xf1, 0xef, 0xd7, 0xfe, 0xf4, 0xb3, 0x02, 0x8f, 0x37, + 0x2a, 0x1a, 0x20, 0x01, 0x1a, 0x01, 0xc3, 0xa7, 0x21, 0xdc, 0x01, 0xf5, + 0xf9, 0x09, 0xf3, 0xb0, 0xb5, 0xd6, 0x93, 0xc6, 0xce, 0x22, 0x23, 0x48, + 0x10, 0x92, 0x16, 0xe1, 0x52, 0xff, 0x09, 0x08, 0xec, 0xe5, 0x4f, 0x34, + 0x08, 0xed, 0xdc, 0xdf, 0x43, 0x22, 0xf8, 0xd9, 0x1c, 0xdc, 0xd7, 0xcc, + 0x0d, 0xdf, 0xc1, 0xf2, 0xdd, 0x39, 0x08, 0xea, 0xdf, 0xc3, 0xf5, 0xfb, + 0xfa, 0x0f, 0xbf, 0x11, 0x33, 0x09, 0x1e, 0xdb, 0x2a, 0xe1, 0xac, 0x27, + 0xfc, 0x0c, 0x35, 0x06, 0x20, 0x32, 0x0c, 0x09, 0xdc, 0x29, 0x15, 0x04, + 0xec, 0x0d, 0x2b, 0x06, 0xe1, 0x11, 0x18, 0xdb, 0x50, 0x17, 0x02, 0xe3, + 0x0c, 0xf7, 0xf2, 0x06, 0xfc, 0xf3, 0xd6, 0x33, 0x3d, 0xd0, 0x00, 0x35, + 0x17, 0xc0, 0xd4, 0x0e, 0xd8, 0xb0, 0xc7, 0x1d, 0x25, 0xd6, 0x15, 0x43, + 0xfd, 0x2b, 0x00, 0xe1, 0x1d, 0xfb, 0x00, 0xcb, 0x0c, 0xff, 0x0a, 0x32, + 0xf2, 0xe3, 0x81, 0x07, 0x1c, 0x1e, 0x0e, 0xce, 0x31, 0x1a, 0x2e, 0xf4, + 0x2b, 0x8c, 0x07, 0xf8, 0xef, 0x14, 0xd2, 0x01, 0xe5, 0xf5, 0x1d, 0x0a, + 0x36, 0x17, 0x02, 0xef, 0x12, 0xf8, 0xeb, 0xe1, 0xde, 0xe0, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x32, 0x2f, 0x43, + 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x00, 0x00, 0x00, 0x40, 0xe0, 0xff, 0xff, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x9e, 0xa1, 0x50, 0x3c, 0x50, 0x1c, 0x4c, 0x3c, 0x90, 0x93, 0x56, 0x3c, + 0x35, 0x30, 0x41, 0x3c, 0xa1, 0x39, 0x7f, 0x3c, 0x7a, 0xb4, 0x42, 0x3c, + 0x18, 0x5c, 0x42, 0x3c, 0x76, 0x61, 0x5a, 0x3c, 0x4b, 0xc4, 0x49, 0x3c, + 0x8d, 0x97, 0x2e, 0x3c, 0xb0, 0x47, 0x2c, 0x3c, 0xe6, 0xd2, 0x65, 0x3c, + 0xac, 0xdd, 0x33, 0x3c, 0xb5, 0xd8, 0x3b, 0x3c, 0x74, 0x2d, 0x39, 0x3c, + 0xce, 0x97, 0x6b, 0x3c, 0x44, 0x76, 0x7e, 0x3c, 0x9e, 0x2d, 0x77, 0x3c, + 0xa1, 0x3a, 0x6c, 0x3c, 0x19, 0x59, 0x5e, 0x3c, 0xc3, 0xa0, 0x3b, 0x3c, + 0xe8, 0xa4, 0x6c, 0x3c, 0xff, 0xc0, 0x2f, 0x3c, 0x98, 0xca, 0x75, 0x3c, + 0x0c, 0x4b, 0x3f, 0x3c, 0x14, 0x69, 0x57, 0x3c, 0x15, 0xcb, 0x2b, 0x3c, + 0x1c, 0x64, 0x51, 0x3c, 0x09, 0x35, 0x6d, 0x3c, 0xd0, 0x81, 0x65, 0x3c, + 0x13, 0x9f, 0x5c, 0x3c, 0xc9, 0x18, 0x4d, 0x3c, 0xea, 0x5e, 0x5b, 0x3c, + 0xac, 0x53, 0x11, 0x3c, 0xc3, 0x23, 0x48, 0x3c, 0x4f, 0x62, 0x41, 0x3c, + 0x0a, 0x8b, 0x22, 0x3c, 0xc3, 0xc3, 0x64, 0x3c, 0xe5, 0x35, 0x24, 0x3c, + 0x1a, 0x9d, 0x20, 0x3c, 0x85, 0x2b, 0x77, 0x3c, 0xb7, 0xef, 0x41, 0x3c, + 0x02, 0x12, 0x52, 0x3c, 0xec, 0xe5, 0x41, 0x3c, 0xeb, 0x01, 0x2e, 0x3c, + 0xb8, 0x84, 0x32, 0x3c, 0xb5, 0x5d, 0x3b, 0x3c, 0x91, 0x04, 0x69, 0x3c, + 0x63, 0x74, 0x57, 0x3c, 0x4c, 0xb8, 0x5a, 0x3c, 0x85, 0xdf, 0x26, 0x3c, + 0xa1, 0x5c, 0x37, 0x3c, 0x6d, 0x71, 0x1a, 0x3c, 0xa0, 0xc3, 0x5e, 0x3c, + 0xde, 0xfe, 0x72, 0x3c, 0x86, 0x98, 0x37, 0x3c, 0x19, 0xf1, 0x44, 0x3c, + 0x34, 0x14, 0x2d, 0x3c, 0xfe, 0x59, 0x68, 0x3c, 0xe2, 0xbb, 0x7a, 0x3c, + 0xae, 0xab, 0x5b, 0x3c, 0xc6, 0x63, 0x3f, 0x3c, 0x3a, 0x87, 0x5f, 0x3c, + 0xba, 0x65, 0x25, 0x3c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0xe4, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0xf6, 0xff, 0xff, + 0xf1, 0xf8, 0xff, 0xff, 0x38, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff, + 0xf6, 0x01, 0x00, 0x00, 0xac, 0xe7, 0xff, 0xff, 0x7c, 0x01, 0x00, 0x00, + 0x71, 0xf6, 0xff, 0xff, 0x29, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0xf2, 0x01, 0x00, 0x00, 0x4b, 0xfe, 0xff, 0xff, + 0x55, 0x02, 0x00, 0x00, 0x8a, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, + 0x8b, 0xff, 0xff, 0xff, 0x19, 0xfb, 0xff, 0xff, 0x22, 0x00, 0x00, 0x00, + 0x7d, 0x5f, 0xff, 0xff, 0xf6, 0x05, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, + 0xbd, 0x00, 0x00, 0x00, 0x8f, 0x0d, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, + 0x28, 0x02, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x98, 0x02, 0x00, 0x00, + 0x1e, 0x05, 0x00, 0x00, 0x3f, 0xfb, 0xff, 0xff, 0x0a, 0xfe, 0xff, 0xff, + 0xb1, 0xfd, 0xff, 0xff, 0xca, 0xe4, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, + 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x31, 0x2f, 0x52, + 0x65, 0x6c, 0x75, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x62, 0x61, + 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x31, 0x2f, 0x46, 0x75, 0x73, 0x65, + 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x56, 0x33, + 0x3b, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x2f, 0x62, 0x69, + 0x61, 0x73, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x31, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, + 0x64, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x76, + 0x32, 0x64, 0x5f, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x00, + 0x88, 0xe4, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0xdb, 0x41, 0x9f, 0x38, 0xf6, 0x51, 0xd5, 0x38, + 0x08, 0xc1, 0x94, 0x38, 0x91, 0x9e, 0x9a, 0x38, 0xe4, 0x51, 0x82, 0x38, + 0x5f, 0xb3, 0x8b, 0x38, 0x68, 0xf6, 0x99, 0x38, 0xee, 0xff, 0x86, 0x38, + 0x30, 0x75, 0x3f, 0x38, 0xa0, 0x86, 0x46, 0x38, 0xc9, 0x2e, 0x59, 0x38, + 0xb7, 0xa2, 0x88, 0x38, 0xa5, 0x7e, 0x99, 0x38, 0xe0, 0x8b, 0x8b, 0x38, + 0x23, 0x88, 0x8c, 0x38, 0x05, 0x82, 0x7d, 0x38, 0x84, 0xa4, 0x8d, 0x38, + 0xed, 0xff, 0x86, 0x38, 0xa7, 0x18, 0x5c, 0x38, 0x3d, 0x7d, 0xe7, 0x37, + 0xe0, 0x04, 0x68, 0x38, 0x08, 0x0e, 0x9a, 0x38, 0x87, 0x1d, 0x58, 0x38, + 0xb6, 0x3d, 0x54, 0x38, 0xb1, 0x4c, 0x4c, 0x38, 0x8b, 0x42, 0x9d, 0x38, + 0xc6, 0x03, 0x62, 0x38, 0x4d, 0xd9, 0x8d, 0x38, 0xb2, 0x5b, 0x2f, 0x38, + 0x5a, 0x58, 0x78, 0x38, 0xe0, 0x0b, 0x80, 0x38, 0x26, 0xc3, 0x69, 0x38, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xe7, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0xf9, 0xf0, 0x22, 0xca, + 0x13, 0x05, 0x05, 0x14, 0x04, 0xe6, 0x10, 0xf4, 0xe2, 0x0f, 0xfa, 0x81, + 0x24, 0xfb, 0xde, 0x14, 0x03, 0x01, 0xc0, 0xdc, 0x13, 0xef, 0x0f, 0xc2, + 0x1a, 0xcf, 0x1a, 0x22, 0x1b, 0xf4, 0x16, 0x00, 0x08, 0xe3, 0xf8, 0x04, + 0x0a, 0xee, 0x09, 0x02, 0x10, 0xfb, 0x0b, 0x1d, 0xff, 0xac, 0x2d, 0xf3, + 0x10, 0xf1, 0x02, 0x0a, 0x01, 0xb8, 0x0a, 0xf7, 0xd7, 0x0c, 0x00, 0x8f, + 0x16, 0xbd, 0xf6, 0x17, 0x04, 0xe1, 0xda, 0xe4, 0x0b, 0x9f, 0x08, 0xa8, + 0x1e, 0xda, 0x17, 0x11, 0x1b, 0xbe, 0xca, 0x00, 0x0d, 0xbb, 0x02, 0x12, + 0x0c, 0xb0, 0x07, 0x06, 0x0b, 0x06, 0x0f, 0xfb, 0x07, 0xb6, 0x2d, 0xff, + 0x10, 0xe6, 0x06, 0x07, 0x07, 0xa7, 0x0e, 0x11, 0xef, 0x03, 0x09, 0xd5, + 0x01, 0xb7, 0xf8, 0x0d, 0x01, 0xb5, 0xf0, 0xff, 0x0a, 0x96, 0x05, 0xe7, + 0xf4, 0xfb, 0xe8, 0x07, 0x00, 0x9e, 0xb8, 0x02, 0x0d, 0xd7, 0xfa, 0x0b, + 0xe5, 0xc0, 0x02, 0x0a, 0xf1, 0x04, 0xe4, 0xe8, 0x03, 0x02, 0xf3, 0x05, + 0xec, 0x02, 0xc2, 0xc0, 0x07, 0x05, 0xfb, 0xd1, 0x02, 0xd7, 0x03, 0xfd, + 0x05, 0x07, 0xfe, 0x00, 0xbc, 0xfd, 0xb1, 0xa1, 0x02, 0x04, 0xf2, 0x00, + 0x05, 0xc6, 0x03, 0x12, 0x05, 0x06, 0x03, 0xf7, 0xa8, 0xfa, 0x8d, 0x81, + 0x06, 0x01, 0xe5, 0x0d, 0xfe, 0xa8, 0x00, 0x05, 0x04, 0x06, 0xfa, 0x00, + 0xfa, 0x07, 0x0b, 0x09, 0x07, 0x09, 0x00, 0x0f, 0x06, 0x07, 0x08, 0x03, + 0x09, 0x07, 0xf9, 0xf8, 0xe3, 0x06, 0x0a, 0x05, 0x05, 0x06, 0xfa, 0x0f, + 0x06, 0x07, 0x06, 0x0d, 0x0c, 0x03, 0x0c, 0xf5, 0xc5, 0x00, 0x00, 0xfa, + 0xff, 0x00, 0xdc, 0x07, 0x02, 0xf8, 0xfe, 0x0e, 0x02, 0x05, 0x05, 0xed, + 0x08, 0x04, 0x08, 0x04, 0xfb, 0x0b, 0xf5, 0x02, 0x04, 0x04, 0x07, 0xfa, + 0x04, 0x05, 0xfc, 0x03, 0x05, 0x09, 0x03, 0x04, 0x06, 0x05, 0xfd, 0x00, + 0x07, 0x04, 0x06, 0x01, 0xf8, 0xf8, 0xfa, 0xfe, 0x02, 0x01, 0x03, 0x05, + 0xfb, 0x05, 0xe4, 0x07, 0x00, 0x00, 0x05, 0x0a, 0xe9, 0xd8, 0xd3, 0xfd, + 0xec, 0xc8, 0xb1, 0xa2, 0xf5, 0xdf, 0xf8, 0xcc, 0xfd, 0xb3, 0xdf, 0xf9, + 0xb5, 0xce, 0x96, 0xd3, 0x8b, 0xa1, 0xca, 0xe5, 0xd2, 0xac, 0xb2, 0x12, + 0xc4, 0xc1, 0xdc, 0xe1, 0xf0, 0x03, 0xcb, 0x81, 0x8b, 0xee, 0xfd, 0xf4, + 0xed, 0x03, 0x93, 0x0f, 0xed, 0xf9, 0x05, 0xbb, 0x0e, 0x0f, 0xf1, 0x02, + 0xf2, 0xdd, 0xde, 0xde, 0x0b, 0x00, 0xfc, 0x06, 0x0a, 0xe5, 0x14, 0xd8, + 0x16, 0x15, 0xfc, 0x03, 0xde, 0x07, 0x05, 0x09, 0x0d, 0x12, 0xef, 0xfd, + 0x14, 0x10, 0x12, 0x0a, 0xf5, 0x04, 0xd9, 0xd1, 0xea, 0x19, 0x10, 0x12, + 0x00, 0x11, 0xb4, 0x00, 0x01, 0x11, 0x08, 0xed, 0x12, 0x00, 0x06, 0x01, + 0x01, 0x17, 0x04, 0xfd, 0x09, 0x07, 0x03, 0x00, 0x08, 0xf5, 0x0d, 0xfc, + 0x0c, 0x04, 0x1b, 0xfb, 0x0b, 0x0b, 0x0a, 0x09, 0x09, 0x04, 0xfc, 0xfe, + 0x0a, 0x02, 0x0f, 0xec, 0xf9, 0x02, 0x14, 0xf1, 0xf9, 0x14, 0x0f, 0x0c, + 0x0a, 0x10, 0xd7, 0xff, 0x10, 0x0c, 0x19, 0xe4, 0xf7, 0x00, 0xec, 0xca, + 0x14, 0x0f, 0x09, 0x08, 0x05, 0x07, 0xd5, 0xef, 0x0c, 0x07, 0x06, 0xe8, + 0xf8, 0xfc, 0xe2, 0xbd, 0x0a, 0x14, 0x0b, 0x0a, 0x03, 0x0b, 0xe1, 0xe6, + 0x16, 0x0b, 0x15, 0xa3, 0xf9, 0xfa, 0xf3, 0xd6, 0x0c, 0x1c, 0x09, 0x07, + 0xf9, 0x10, 0xe9, 0xf8, 0x0f, 0x07, 0x09, 0xb3, 0xee, 0xf9, 0xa6, 0xca, + 0xe4, 0xfc, 0xde, 0xe8, 0xcb, 0xff, 0xeb, 0xf0, 0x09, 0xc8, 0xe5, 0xc8, + 0xfe, 0xfa, 0xca, 0xdb, 0xf5, 0x0c, 0xfc, 0xfc, 0xc2, 0x06, 0xdf, 0xed, + 0x0b, 0xf5, 0xfb, 0x0c, 0xf1, 0xf5, 0xfe, 0xd2, 0x01, 0x0e, 0x00, 0xfe, + 0xe7, 0x0e, 0xcd, 0xf2, 0x07, 0x00, 0x0a, 0xf8, 0xc2, 0xbe, 0xc3, 0xc3, + 0x0b, 0xe4, 0x08, 0x04, 0x89, 0x9f, 0xd8, 0x0e, 0x97, 0x06, 0xf1, 0xcb, + 0xc1, 0xab, 0xd6, 0xde, 0x0b, 0x07, 0x07, 0x05, 0x9c, 0xbe, 0xb8, 0x05, + 0xc8, 0x02, 0x05, 0xd2, 0xa5, 0x9e, 0x0b, 0xc0, 0x0a, 0xfa, 0x08, 0x03, + 0x81, 0xd7, 0xc4, 0x07, 0xd0, 0x00, 0x02, 0xdb, 0xed, 0xb0, 0xd9, 0x1d, + 0x0a, 0xe4, 0xfb, 0xfb, 0x0e, 0xe1, 0x0e, 0xfb, 0xf8, 0x06, 0x02, 0x06, + 0x81, 0x8d, 0xf9, 0xf4, 0x05, 0x02, 0x08, 0x07, 0xed, 0xe8, 0x01, 0x08, + 0xd7, 0x0f, 0x04, 0x9f, 0xae, 0x9e, 0x13, 0xc2, 0x05, 0xf5, 0x01, 0x02, + 0xf2, 0xbe, 0xf8, 0xff, 0x96, 0x06, 0xf2, 0x93, 0xf7, 0xe7, 0xf5, 0xff, + 0x08, 0x07, 0x07, 0x03, 0x0d, 0xff, 0xff, 0xf7, 0x04, 0x09, 0x07, 0x12, + 0xcf, 0xb8, 0xe2, 0x01, 0x1b, 0x0f, 0x05, 0x05, 0x09, 0x15, 0x0a, 0x06, + 0xea, 0x08, 0x0b, 0xf0, 0xce, 0xbf, 0x07, 0x05, 0x0e, 0xff, 0x08, 0x09, + 0x06, 0xc1, 0x0a, 0x0c, 0x97, 0x0a, 0xf5, 0xf5, 0xf4, 0xe5, 0xf7, 0xff, + 0x0f, 0x06, 0x0c, 0x00, 0x0a, 0x02, 0x07, 0x0a, 0x02, 0x07, 0x0e, 0x07, + 0xe1, 0xa4, 0xfe, 0x0a, 0x15, 0x1d, 0x10, 0x0f, 0x0a, 0x02, 0x08, 0x0f, + 0xed, 0x0f, 0x18, 0xf6, 0xe7, 0xac, 0x17, 0xff, 0x16, 0x0d, 0x0a, 0x12, + 0x0c, 0xd3, 0x08, 0x13, 0xbc, 0x0b, 0x01, 0xf4, 0x81, 0x82, 0xf1, 0xf3, + 0x18, 0xfc, 0x0a, 0x10, 0xe7, 0xd5, 0xf8, 0x10, 0xdb, 0x0f, 0x04, 0xdf, + 0x9e, 0xbc, 0xf7, 0xaf, 0x02, 0x06, 0x0f, 0x0e, 0xd6, 0xd6, 0x9c, 0xf7, + 0xd1, 0x0d, 0x0a, 0x87, 0xe5, 0xf4, 0x06, 0xa3, 0x02, 0x1e, 0x0f, 0x0a, + 0xff, 0x07, 0xb4, 0xeb, 0xea, 0x0c, 0x17, 0xca, 0xe8, 0xec, 0xf4, 0x06, + 0x0c, 0x13, 0x11, 0x0f, 0x04, 0x09, 0x0a, 0x04, 0x0c, 0x12, 0x0c, 0x0f, + 0xe5, 0xf1, 0x0d, 0xc3, 0x07, 0x1f, 0x0d, 0x09, 0x0a, 0x13, 0xcc, 0xf4, + 0x0f, 0x11, 0x13, 0xe0, 0xeb, 0xf3, 0x1a, 0xcf, 0xec, 0x15, 0xfc, 0x04, + 0xfd, 0x0f, 0xc2, 0xf5, 0xfb, 0x02, 0x07, 0x00, 0x0d, 0x03, 0x27, 0x0b, + 0x0b, 0x0c, 0x06, 0x08, 0x15, 0x15, 0xfc, 0x05, 0x12, 0x0b, 0x14, 0x1f, + 0x07, 0x0a, 0x1c, 0xf2, 0x0f, 0x16, 0x0d, 0x07, 0x0c, 0x1c, 0xf5, 0xfb, + 0x15, 0x1a, 0x16, 0x0d, 0xfb, 0xff, 0x18, 0xe8, 0xfc, 0x15, 0x07, 0x08, + 0xf8, 0x09, 0xdc, 0x11, 0x01, 0x0f, 0x17, 0xfe, 0x9d, 0xe2, 0xf4, 0x81, + 0x09, 0x06, 0xfe, 0x05, 0xe4, 0x00, 0xbd, 0x03, 0x03, 0x03, 0x0d, 0x9f, + 0xef, 0xe2, 0x06, 0xa1, 0x0d, 0x21, 0x0c, 0x0c, 0xe9, 0x13, 0xc0, 0x06, + 0x16, 0x0b, 0x1b, 0x11, 0xe5, 0xee, 0x14, 0xd6, 0x09, 0x0f, 0x03, 0x06, + 0xb5, 0xf9, 0xb9, 0xde, 0xf7, 0x0a, 0xe8, 0xec, 0xbf, 0xab, 0x0f, 0x23, + 0x0e, 0x05, 0x0d, 0x06, 0x02, 0xf8, 0x18, 0x07, 0x08, 0x0e, 0x1f, 0xe4, + 0xc7, 0xaa, 0x0c, 0xee, 0x05, 0x05, 0x05, 0x02, 0xdb, 0xff, 0xe9, 0xf1, + 0xfc, 0x05, 0xef, 0xf5, 0xcf, 0x13, 0xf4, 0xd8, 0xce, 0xe4, 0xe9, 0xe4, + 0xd6, 0xc5, 0xb3, 0x00, 0xec, 0xe3, 0xe9, 0xaf, 0xfc, 0xaa, 0x1b, 0x1d, + 0x05, 0xf6, 0xfa, 0xfe, 0x13, 0xf3, 0x1a, 0xd6, 0x11, 0xfa, 0x16, 0xfa, + 0x15, 0xf9, 0xfe, 0x05, 0xde, 0xdb, 0x02, 0x01, 0x02, 0xd6, 0x01, 0x06, + 0xff, 0xff, 0x09, 0xcd, 0x1e, 0x22, 0xf7, 0xf9, 0x1a, 0x09, 0x08, 0x02, + 0x0b, 0xfd, 0xe5, 0x0d, 0x13, 0xff, 0x12, 0xb4, 0x02, 0xfc, 0xf0, 0xff, + 0xff, 0x20, 0x0e, 0x12, 0xfb, 0x17, 0xfb, 0xf7, 0xfe, 0x0c, 0x12, 0xf3, + 0xfc, 0xf7, 0x0a, 0x0a, 0x04, 0x10, 0x07, 0x0c, 0x08, 0x04, 0x02, 0x09, + 0x02, 0x0d, 0x07, 0xfd, 0xf9, 0xe6, 0xf8, 0xff, 0x0b, 0xf6, 0x0e, 0x0a, + 0x04, 0xec, 0x01, 0x14, 0xf7, 0x06, 0x06, 0xf2, 0xdd, 0xf7, 0xbc, 0xbf, + 0xdd, 0x04, 0xe4, 0xe8, 0xc3, 0x0b, 0xd5, 0xb2, 0xf9, 0xef, 0xea, 0xb1, + 0x01, 0xfd, 0x17, 0xfc, 0x19, 0x14, 0x0d, 0x13, 0x0f, 0x0e, 0x04, 0xdc, + 0x04, 0x16, 0x0d, 0xfa, 0x08, 0x05, 0x05, 0x0d, 0x03, 0x0a, 0x0e, 0x0c, + 0x12, 0xff, 0x04, 0x07, 0x08, 0x15, 0x07, 0x0a, 0xf7, 0x0f, 0xf3, 0xc6, + 0xdd, 0x0b, 0xa6, 0x99, 0x01, 0x17, 0xe2, 0x8f, 0x02, 0xb5, 0x02, 0xcc, + 0x0d, 0x15, 0x0c, 0x0b, 0x06, 0x11, 0xe7, 0xe4, 0x07, 0x11, 0x0f, 0x81, + 0x11, 0xe9, 0x0f, 0x29, 0x04, 0x07, 0x0c, 0x0b, 0xd3, 0x02, 0xef, 0xeb, + 0x09, 0x03, 0x02, 0xda, 0x0e, 0xde, 0x08, 0x0f, 0x06, 0xdb, 0xf4, 0x1c, + 0x0c, 0x00, 0xfb, 0xfe, 0x06, 0xe7, 0x19, 0xfb, 0x02, 0xfb, 0x02, 0x23, + 0xe7, 0xa8, 0xf6, 0x28, 0x08, 0xdf, 0xfc, 0xfa, 0x07, 0xb6, 0x14, 0xff, + 0xce, 0x06, 0xfe, 0x03, 0xb1, 0x85, 0x0f, 0x01, 0xfd, 0x00, 0xfc, 0xf6, + 0x01, 0xf0, 0xfd, 0xcc, 0xa9, 0xfc, 0xe5, 0xfa, 0x05, 0xe3, 0xed, 0x18, + 0x08, 0x1b, 0x03, 0x04, 0x0f, 0x06, 0x16, 0xee, 0x01, 0x04, 0x19, 0x0d, + 0xdc, 0xb6, 0x1e, 0xfe, 0x04, 0x10, 0x0b, 0x04, 0xef, 0xe8, 0xfe, 0xf7, + 0xee, 0x09, 0x06, 0x07, 0xc4, 0x90, 0x3f, 0x02, 0xfc, 0xcb, 0xd0, 0xcd, + 0xfe, 0xec, 0x07, 0x81, 0x8d, 0xb8, 0x87, 0x14, 0x04, 0xfb, 0xf0, 0x0e, + 0x0c, 0x14, 0x07, 0x0c, 0x0e, 0x10, 0x0d, 0xf9, 0x13, 0x03, 0x19, 0x10, + 0xbb, 0xd3, 0x14, 0xe7, 0x10, 0x35, 0x14, 0x05, 0xff, 0x1f, 0xba, 0x0f, + 0x02, 0x17, 0x1e, 0xfd, 0xb3, 0x97, 0x5c, 0xc1, 0xee, 0x85, 0xc6, 0xae, + 0xb6, 0x9c, 0xdc, 0xbf, 0x95, 0xb5, 0xa0, 0xca, 0xcb, 0xdd, 0xe2, 0x9d, + 0x17, 0x06, 0x07, 0x02, 0xf0, 0x03, 0xf9, 0x08, 0xfd, 0x09, 0x14, 0xb4, + 0xe2, 0xe1, 0xfc, 0xf2, 0x10, 0x20, 0x0c, 0x06, 0xee, 0x16, 0xe6, 0x08, + 0x14, 0x04, 0x1b, 0x12, 0xd6, 0xe3, 0x01, 0x8c, 0x0a, 0x0e, 0x12, 0x12, + 0xe5, 0x09, 0xd1, 0x17, 0x06, 0x0b, 0xfe, 0xf0, 0xb3, 0xb4, 0xf9, 0x12, + 0x23, 0x1f, 0x1a, 0x1e, 0xf9, 0x02, 0x1c, 0xd3, 0xef, 0x1e, 0x10, 0xe4, + 0xcc, 0xb6, 0x03, 0xe9, 0x0f, 0x03, 0x0e, 0x07, 0xb5, 0x0b, 0xe5, 0xf8, + 0xfe, 0xff, 0xe3, 0xe5, 0x9e, 0xb9, 0xed, 0xb1, 0x12, 0xf5, 0x15, 0x0a, + 0xe2, 0x01, 0xc7, 0x0a, 0xb8, 0x0c, 0xb3, 0xae, 0xe3, 0xc2, 0x05, 0x13, + 0xd7, 0xc5, 0xdf, 0xde, 0xd4, 0xce, 0x00, 0x81, 0x00, 0xd4, 0xd5, 0x0e, + 0x96, 0xf7, 0xc3, 0xc9, 0xca, 0xf8, 0x01, 0xff, 0x90, 0xae, 0x91, 0xc6, + 0xac, 0xf4, 0xdc, 0xc4, 0x0a, 0xb6, 0xed, 0x0a, 0x29, 0xc2, 0xe3, 0xe6, + 0x32, 0xb1, 0x25, 0xf5, 0x93, 0xf5, 0xd9, 0xc9, 0xf8, 0xb8, 0x08, 0x10, + 0x19, 0x04, 0x0c, 0x08, 0x09, 0xdf, 0x13, 0xfe, 0xeb, 0x0e, 0xfa, 0x06, + 0xf4, 0xd0, 0x2d, 0x1c, 0x28, 0xfb, 0x10, 0x0b, 0x0a, 0xf9, 0x0f, 0x1a, + 0xe4, 0x1b, 0xec, 0x02, 0xc4, 0xed, 0x2a, 0x17, 0x11, 0xf2, 0x0b, 0x06, + 0x07, 0xee, 0x05, 0x01, 0xc9, 0x0c, 0xeb, 0x21, 0x07, 0xf6, 0xf8, 0x0b, + 0xf9, 0xf4, 0xff, 0xfc, 0xfb, 0xda, 0x06, 0xf9, 0xfb, 0xed, 0xed, 0x03, + 0x1d, 0xd7, 0xc9, 0x12, 0x1f, 0x03, 0x05, 0xf0, 0x34, 0xc9, 0x0c, 0xf0, + 0xe3, 0x03, 0xe2, 0x0f, 0x03, 0xfa, 0x17, 0x07, 0x0a, 0xd7, 0xfb, 0xf0, + 0x16, 0xc9, 0x0a, 0x01, 0xc8, 0x01, 0xae, 0x38, 0xbe, 0x10, 0xe8, 0xcf, + 0x90, 0xb4, 0xd6, 0xdc, 0x8f, 0xec, 0xa6, 0xf6, 0xc8, 0xec, 0x8c, 0xfd, + 0xa3, 0xdb, 0xd0, 0x9e, 0xa6, 0xb5, 0xb4, 0xc6, 0x8d, 0xe6, 0xbf, 0xf5, + 0xb2, 0xb4, 0x95, 0xcd, 0x99, 0x2e, 0xd0, 0xcb, 0xa5, 0x81, 0xcd, 0xbb, + 0x94, 0xc9, 0xde, 0x0b, 0x95, 0xaf, 0x88, 0x2e, 0xeb, 0xf4, 0xf8, 0xc3, + 0xf5, 0x15, 0x07, 0x05, 0x01, 0x0c, 0xe2, 0xdb, 0x0b, 0x04, 0x17, 0xc1, + 0xfd, 0xf6, 0x1e, 0xed, 0xf9, 0x12, 0x05, 0x07, 0x08, 0x12, 0xf8, 0x81, + 0x10, 0x09, 0x15, 0x15, 0x03, 0xf5, 0x22, 0x08, 0xd1, 0xeb, 0xc3, 0xb8, + 0x11, 0xf5, 0xef, 0xc0, 0x06, 0xdb, 0xff, 0x09, 0x05, 0xfb, 0x0b, 0x0b, + 0x00, 0x1a, 0x0a, 0x05, 0x15, 0x18, 0x0b, 0xa4, 0x17, 0x0e, 0x2a, 0xe3, + 0x09, 0x0b, 0x20, 0x02, 0xfa, 0x09, 0xee, 0xf7, 0x10, 0x07, 0x00, 0x82, + 0x11, 0xfa, 0x13, 0xe2, 0x1a, 0x13, 0xfd, 0x08, 0xed, 0x08, 0xa1, 0xa5, + 0x18, 0x0c, 0x01, 0xc3, 0x08, 0xd4, 0x09, 0xf1, 0xc2, 0xca, 0x16, 0x00, + 0xf5, 0x04, 0xf4, 0x00, 0xb9, 0x04, 0x09, 0x90, 0xf9, 0x00, 0xee, 0xdd, + 0xeb, 0xfa, 0xf9, 0xe5, 0xdf, 0xfc, 0xf8, 0xf1, 0xce, 0x0c, 0xd8, 0x8c, + 0xfd, 0xf3, 0xfd, 0xdf, 0x00, 0x05, 0xf9, 0xf9, 0xe4, 0x10, 0xa8, 0xa3, + 0xbb, 0x0c, 0xfd, 0xbe, 0xff, 0xa6, 0xdf, 0xe8, 0x0e, 0x0c, 0x0f, 0x0d, + 0xfc, 0x22, 0xfa, 0xde, 0x07, 0x11, 0x09, 0x1c, 0x18, 0xe9, 0x0c, 0x1a, + 0x0e, 0xff, 0x05, 0x03, 0xec, 0x10, 0xd6, 0xba, 0x08, 0x06, 0x0b, 0x0c, + 0x0c, 0xd4, 0x03, 0x15, 0x08, 0x0e, 0x2e, 0xf3, 0x88, 0x05, 0xc9, 0xbb, + 0x07, 0x04, 0xdb, 0xf8, 0x0e, 0xe4, 0x01, 0xf8, 0x19, 0x0a, 0x10, 0x01, + 0xf5, 0x06, 0xc7, 0xaf, 0x03, 0x07, 0xfb, 0x22, 0x0a, 0xbb, 0x0e, 0x0e, + 0x0d, 0x08, 0xf8, 0xfd, 0xc6, 0x08, 0x9d, 0xa5, 0x07, 0xfd, 0xf4, 0x16, + 0x00, 0xa4, 0x06, 0x09, 0xf6, 0x00, 0xfd, 0xec, 0x9a, 0x00, 0xda, 0xcf, + 0xf0, 0xf9, 0xdc, 0xdc, 0x03, 0xce, 0x0e, 0xf9, 0x11, 0x0d, 0x17, 0x07, + 0x07, 0x05, 0xdc, 0xd0, 0x15, 0x06, 0xfe, 0x1d, 0x05, 0xd8, 0x0c, 0x09, + 0x04, 0xf3, 0xe3, 0xff, 0xb6, 0xe5, 0xba, 0xad, 0xb9, 0xf3, 0xea, 0xff, + 0xf4, 0x9e, 0xcb, 0x1b, 0xe4, 0xf7, 0xd5, 0xd4, 0xe8, 0x09, 0xbe, 0xbf, + 0xf5, 0x00, 0xf5, 0x81, 0x01, 0xbc, 0xd1, 0xd0, 0x8c, 0xa4, 0xe6, 0x98, + 0xf8, 0xfe, 0x0b, 0x04, 0xc3, 0xe4, 0x81, 0xec, 0xd2, 0x05, 0x08, 0xa6, + 0xdf, 0xe5, 0xee, 0xbe, 0xe2, 0x0e, 0x05, 0x0a, 0xfd, 0xf9, 0xec, 0x01, + 0xfa, 0x07, 0x03, 0xa2, 0xf8, 0xed, 0x0f, 0xf0, 0xfe, 0x0f, 0x07, 0x0b, + 0xfd, 0xfa, 0x00, 0xfc, 0x04, 0x04, 0x03, 0x02, 0xa9, 0xd0, 0x02, 0xa0, + 0xf9, 0x0f, 0xfd, 0xfb, 0xa3, 0xf7, 0xaa, 0xcc, 0xbf, 0xfe, 0xfd, 0xc1, + 0xd9, 0xde, 0xf1, 0xce, 0xed, 0x16, 0x05, 0x05, 0xe1, 0x00, 0xfe, 0xe3, + 0x02, 0x08, 0x06, 0xd2, 0xfa, 0xf6, 0x27, 0xfa, 0xfd, 0x09, 0x0d, 0x10, + 0x05, 0xfc, 0xff, 0x04, 0x09, 0x0c, 0x12, 0x08, 0xc5, 0xd6, 0x1e, 0xb1, + 0xd5, 0xce, 0xe5, 0xe1, 0xbf, 0xe9, 0xa0, 0xe9, 0xc8, 0xcb, 0xc4, 0xef, + 0xf0, 0xfd, 0xe5, 0xc1, 0xc7, 0x12, 0xee, 0xf9, 0xd1, 0xfa, 0xe5, 0xcb, + 0x0a, 0xea, 0x0d, 0xe2, 0x19, 0x0f, 0x31, 0x06, 0xf9, 0x1c, 0x07, 0x02, + 0x11, 0x10, 0xf9, 0xee, 0x1b, 0x06, 0x27, 0x14, 0x00, 0x06, 0x0a, 0xec, + 0xff, 0x0a, 0xf8, 0xde, 0xf9, 0x03, 0xf6, 0xe3, 0x06, 0xf6, 0x02, 0xd3, + 0x24, 0x14, 0x15, 0x0e, 0x0d, 0x08, 0xd3, 0xd6, 0x03, 0x09, 0x02, 0x09, + 0x0f, 0xe6, 0x12, 0x15, 0x14, 0x09, 0xef, 0x14, 0x1b, 0x05, 0xef, 0xf1, + 0x15, 0x00, 0x12, 0xf6, 0x0b, 0xf7, 0x07, 0x06, 0xfe, 0x0a, 0xd6, 0xec, + 0x02, 0x10, 0xec, 0xe4, 0xfb, 0x0b, 0xef, 0xe0, 0xfa, 0xe6, 0xee, 0xea, + 0x13, 0x04, 0xda, 0x09, 0x19, 0x03, 0xd0, 0xd0, 0x02, 0x01, 0x12, 0xf4, + 0x0a, 0xc9, 0xfc, 0xf5, 0x14, 0xd1, 0xcd, 0x1b, 0x26, 0xde, 0xe0, 0xf0, + 0x0e, 0xd2, 0x18, 0xf1, 0xf3, 0xde, 0xfa, 0x00, 0x86, 0xb4, 0xe1, 0xba, + 0xce, 0x9d, 0xfd, 0xfa, 0x81, 0xc0, 0xb4, 0xff, 0x96, 0xfd, 0x81, 0xcb, + 0xbd, 0xb3, 0xaf, 0xee, 0xef, 0xcb, 0xff, 0xfd, 0xc0, 0x9e, 0xff, 0x08, + 0xb3, 0xfe, 0xc0, 0xc2, 0x00, 0xc7, 0xc9, 0x05, 0x08, 0xf1, 0x06, 0x07, + 0x0c, 0xd2, 0x0a, 0x06, 0xfe, 0x09, 0x01, 0xd5, 0x10, 0xe4, 0xeb, 0x04, + 0x02, 0xd3, 0xfa, 0xec, 0x04, 0xb3, 0x0b, 0x0b, 0xf9, 0xf0, 0x0d, 0x02, + 0x05, 0xb8, 0xbd, 0x08, 0xfb, 0x81, 0xa5, 0xb3, 0x0b, 0x81, 0x07, 0xe1, + 0x01, 0xc7, 0x0a, 0xfe, 0xf4, 0xb4, 0xf7, 0x04, 0x09, 0xbf, 0xc7, 0xc9, + 0x04, 0xb0, 0x04, 0xcd, 0xec, 0xe8, 0xf2, 0x00, 0x09, 0x02, 0x06, 0x0f, + 0x0a, 0xef, 0x0d, 0x09, 0x0a, 0xda, 0x07, 0x08, 0x08, 0x04, 0x0b, 0xff, + 0x13, 0x0d, 0xed, 0x02, 0x0d, 0xf4, 0xc9, 0xcd, 0x13, 0x01, 0x0a, 0xc3, + 0x0e, 0xed, 0x10, 0x01, 0x09, 0x04, 0xf9, 0x04, 0x07, 0xe3, 0xcb, 0xd7, + 0x0c, 0xec, 0x06, 0xd4, 0xf8, 0xee, 0xfd, 0x18, 0x0b, 0x0f, 0xfa, 0x08, + 0x0f, 0x10, 0xfc, 0xff, 0x0f, 0xfb, 0x0b, 0xeb, 0x06, 0xff, 0x10, 0xfc, + 0x17, 0x08, 0x08, 0x12, 0x21, 0xfd, 0xd5, 0xd5, 0x14, 0x0c, 0x0f, 0xe3, + 0x10, 0xe6, 0x0d, 0x07, 0x00, 0x09, 0xe8, 0x06, 0xf9, 0x03, 0xd8, 0xeb, + 0x02, 0x00, 0x01, 0xef, 0xfe, 0xdd, 0xff, 0x04, 0x16, 0xbf, 0xc0, 0x0a, + 0x02, 0x9f, 0xcf, 0xb2, 0x06, 0x97, 0x09, 0x08, 0x0a, 0xaa, 0xf7, 0x0a, + 0xd5, 0xb6, 0x96, 0x0a, 0xcf, 0xab, 0x02, 0xfe, 0xe7, 0x94, 0xec, 0x24, + 0xc9, 0x11, 0xe2, 0x14, 0xae, 0xab, 0xd9, 0xaa, 0xf3, 0xf1, 0x01, 0x08, + 0xcc, 0xcc, 0xe3, 0xf5, 0xd5, 0x03, 0xea, 0xbf, 0x05, 0xeb, 0xe4, 0x03, + 0x00, 0xc3, 0xfc, 0xfb, 0x12, 0xda, 0xff, 0xc9, 0x11, 0xfd, 0x19, 0xcf, + 0x19, 0xfc, 0x97, 0x0c, 0x1a, 0xeb, 0xf9, 0xff, 0x1b, 0xef, 0x13, 0xf4, + 0x22, 0x03, 0x1c, 0xba, 0x09, 0xfd, 0xba, 0x08, 0xfa, 0xf7, 0x08, 0x05, + 0x10, 0xfc, 0xf8, 0xed, 0x05, 0x04, 0x0e, 0xb2, 0x06, 0x03, 0x9e, 0x08, + 0x0d, 0x01, 0xee, 0xf4, 0x05, 0x0d, 0x03, 0xb9, 0x0a, 0x00, 0x07, 0xea, + 0x12, 0xfe, 0xae, 0x11, 0x27, 0x0a, 0xe5, 0xfa, 0x13, 0xfe, 0x18, 0x81, + 0x0b, 0xf8, 0x12, 0xdc, 0x00, 0xfa, 0xe8, 0x0e, 0x01, 0x02, 0xfa, 0xfb, + 0x10, 0x05, 0x0b, 0xa7, 0x0c, 0xf4, 0x0a, 0xfb, 0xf7, 0xf9, 0x13, 0xfd, + 0x07, 0x06, 0x10, 0x08, 0xf0, 0xf3, 0x02, 0xf7, 0xfc, 0x0c, 0x0a, 0xda, + 0x35, 0x11, 0xba, 0x1f, 0x1a, 0xe9, 0x8f, 0xb9, 0x11, 0xfe, 0x1a, 0xcc, + 0x05, 0x9c, 0x02, 0x3b, 0xf3, 0xd6, 0xb8, 0x1a, 0x08, 0xa8, 0xe1, 0x0a, + 0x00, 0xc7, 0x0d, 0xae, 0x09, 0xdc, 0x0b, 0x31, 0xaa, 0xb2, 0x38, 0xbf, + 0x15, 0xe3, 0x0b, 0x0c, 0xfa, 0xc2, 0xff, 0x0e, 0xb5, 0x13, 0xf4, 0xb3, + 0xce, 0x9f, 0xe7, 0x05, 0x0c, 0x8c, 0xf7, 0xf1, 0x0e, 0x97, 0x13, 0xf4, + 0x9e, 0xec, 0xbe, 0x12, 0x9b, 0xd8, 0xe5, 0xf8, 0xd7, 0x0c, 0x01, 0x0f, + 0xe4, 0xfd, 0xf3, 0x03, 0xeb, 0x09, 0xff, 0x01, 0xc1, 0x89, 0x13, 0xe0, + 0x06, 0x2b, 0x15, 0x0e, 0xf4, 0x00, 0xfd, 0x05, 0xf6, 0x0b, 0x17, 0x81, + 0xdb, 0x8b, 0x0c, 0x09, 0x09, 0x13, 0x0a, 0x05, 0x1c, 0xfd, 0x17, 0x0d, + 0xfa, 0x0b, 0x0e, 0x06, 0xb8, 0xbc, 0x1c, 0x0a, 0x0c, 0x12, 0x04, 0x0c, + 0xfb, 0xf5, 0x06, 0x11, 0xe5, 0x07, 0x06, 0x14, 0x04, 0x1f, 0xf2, 0xb2, + 0xd4, 0x06, 0xfc, 0x02, 0xb6, 0x0f, 0xcf, 0xd3, 0x03, 0xfd, 0xfe, 0xf8, + 0x15, 0x0d, 0xd8, 0xea, 0xfa, 0x1a, 0x00, 0x05, 0xfb, 0x1d, 0xf5, 0xeb, + 0x12, 0x01, 0x0d, 0xd9, 0x0b, 0xff, 0xff, 0x0c, 0x1c, 0x1b, 0x10, 0x04, + 0x15, 0x03, 0x0f, 0x07, 0x0f, 0x06, 0x0f, 0x06, 0x8d, 0xc7, 0x81, 0xa0, + 0x9e, 0xca, 0xb7, 0xcb, 0xb6, 0xc5, 0xb1, 0xe4, 0xa0, 0x93, 0xa9, 0xa5, + 0x24, 0x03, 0xd8, 0xf7, 0xd8, 0x0f, 0xf7, 0xf4, 0xf7, 0x06, 0xfb, 0xf2, + 0x15, 0xfe, 0x10, 0xee, 0x18, 0xfc, 0x1c, 0x07, 0x06, 0x0b, 0xfc, 0x08, + 0x0d, 0x00, 0x0d, 0xfd, 0x0d, 0xfa, 0x0d, 0x10, 0x96, 0xa8, 0xdc, 0x8b, + 0x04, 0xda, 0x0a, 0xfe, 0xbc, 0x9c, 0xae, 0x01, 0x99, 0xff, 0xe7, 0xc1, + 0x0a, 0xf1, 0x1e, 0xec, 0xf5, 0x02, 0x07, 0x00, 0xf3, 0xe7, 0xf8, 0xfe, + 0x00, 0xf9, 0x01, 0x95, 0x08, 0xfb, 0x13, 0x03, 0x08, 0xfe, 0x05, 0x0d, + 0x10, 0xfa, 0x0b, 0x0f, 0x04, 0x09, 0x09, 0x00, 0x1b, 0x09, 0x33, 0xe5, + 0x31, 0x12, 0x2b, 0x1b, 0xf5, 0xf0, 0x09, 0xf7, 0x02, 0x2f, 0x0c, 0x18, + 0x11, 0xec, 0x0d, 0x0f, 0x29, 0x0d, 0x2c, 0x36, 0x04, 0xfe, 0x13, 0x00, + 0x07, 0x23, 0x21, 0x15, 0x04, 0xcd, 0xf8, 0x10, 0x75, 0x08, 0x32, 0x2d, + 0x15, 0xdc, 0x29, 0x38, 0x06, 0x37, 0x27, 0x08, 0x35, 0x21, 0xd5, 0xfd, + 0x23, 0x45, 0x1a, 0x16, 0x23, 0x31, 0x1b, 0xc0, 0x2a, 0x19, 0x3f, 0x1b, + 0x02, 0xf9, 0xee, 0x1c, 0x2a, 0x2d, 0x16, 0x32, 0x1e, 0x12, 0x16, 0xfc, + 0x2f, 0x11, 0x36, 0xec, 0xd3, 0xa9, 0xf7, 0x1b, 0x41, 0x07, 0x15, 0x25, + 0x33, 0xe6, 0x39, 0x3e, 0x08, 0x1d, 0x27, 0xde, 0x21, 0x2a, 0x04, 0xf1, + 0x19, 0x33, 0xd0, 0xd9, 0x43, 0x37, 0x03, 0x81, 0x29, 0xdd, 0x24, 0x00, + 0xf1, 0xe9, 0xfc, 0x30, 0x12, 0x20, 0x11, 0x1a, 0x3a, 0x19, 0x48, 0xe5, + 0x37, 0x1e, 0x2d, 0x08, 0xc7, 0xbd, 0x12, 0xff, 0x1f, 0x40, 0x2c, 0x34, + 0x26, 0x14, 0x0b, 0x30, 0x1f, 0x27, 0x3f, 0xec, 0xa9, 0xcf, 0x0a, 0x8c, + 0x0f, 0x11, 0x07, 0x09, 0xec, 0xf7, 0x8f, 0xfb, 0xfa, 0x04, 0x12, 0xd0, + 0xf9, 0x00, 0x24, 0xa0, 0x1e, 0x14, 0x16, 0x12, 0x04, 0x16, 0xb9, 0x03, + 0x18, 0x09, 0x0d, 0x1e, 0xe8, 0xf0, 0x04, 0xaa, 0x0f, 0xfc, 0x08, 0x0e, + 0xe2, 0xf7, 0xa5, 0x08, 0xf8, 0x13, 0xf2, 0x01, 0xb0, 0xcc, 0x17, 0x85, + 0x17, 0x15, 0x10, 0x05, 0xcc, 0x00, 0xc0, 0xf4, 0xfa, 0x03, 0x01, 0xdf, + 0x0b, 0xe4, 0x13, 0xd6, 0x07, 0x07, 0xf4, 0xfb, 0xef, 0x19, 0xda, 0xea, + 0x0d, 0xf8, 0xda, 0x2e, 0xd1, 0xf1, 0x0d, 0xb0, 0xfd, 0xec, 0xf8, 0xf0, + 0xbc, 0xf0, 0x9c, 0x10, 0xdf, 0xef, 0xde, 0x45, 0x90, 0x9b, 0x03, 0xa6, + 0x01, 0x14, 0x02, 0xfb, 0xa0, 0xfd, 0xba, 0xf8, 0xe5, 0xfe, 0xe6, 0xc9, + 0xc6, 0xce, 0xa8, 0xeb, 0xce, 0xb2, 0x0a, 0x16, 0x81, 0xb9, 0xe6, 0x29, + 0xb0, 0x02, 0xb0, 0x06, 0xa9, 0x18, 0xb8, 0xad, 0xf6, 0xfe, 0x06, 0x07, + 0xb3, 0xc6, 0x92, 0x1a, 0xdf, 0x09, 0x00, 0x4d, 0xf0, 0x03, 0x01, 0xd3, + 0x04, 0x07, 0x02, 0x02, 0xf5, 0x06, 0xf1, 0xe8, 0xfd, 0xff, 0x00, 0xd7, + 0x05, 0x07, 0x0a, 0x07, 0x0a, 0x11, 0x02, 0x03, 0x0b, 0x13, 0x00, 0xdc, + 0x02, 0x09, 0x0b, 0x00, 0xf5, 0x00, 0x1b, 0xfd, 0x0f, 0x14, 0x05, 0x04, + 0x08, 0x0e, 0x02, 0xf6, 0x05, 0x00, 0x02, 0x0a, 0x05, 0x08, 0xe5, 0xe6, + 0xe9, 0x03, 0xec, 0xe7, 0x06, 0x04, 0xf4, 0xe7, 0x02, 0xdd, 0x09, 0xaf, + 0x10, 0x0d, 0x0f, 0x17, 0x05, 0xff, 0xde, 0xd5, 0x15, 0x04, 0xfe, 0x08, + 0x0e, 0xdc, 0x07, 0x20, 0x10, 0x0b, 0x10, 0x07, 0xf4, 0x0b, 0xde, 0xea, + 0xf6, 0x0d, 0x02, 0xfa, 0xfe, 0xda, 0xf6, 0x28, 0x0d, 0x0d, 0x00, 0xda, + 0xe1, 0x01, 0xe1, 0xd8, 0xf7, 0x11, 0xd1, 0xf7, 0x06, 0xe7, 0x01, 0xf9, + 0xfb, 0xfa, 0xe0, 0xeb, 0xce, 0xfe, 0xba, 0xdd, 0xa4, 0xfa, 0xda, 0x0b, + 0xf4, 0xac, 0xb1, 0x17, 0xca, 0xf8, 0xb1, 0xcb, 0xb7, 0xb8, 0xf1, 0xe8, + 0x9d, 0xd8, 0xca, 0x13, 0xb9, 0xd9, 0x81, 0xff, 0xfb, 0xe7, 0x0a, 0x09, + 0x17, 0x0c, 0x01, 0x08, 0x13, 0xfb, 0x0b, 0xfa, 0x02, 0x08, 0x12, 0x06, + 0xcc, 0xd4, 0x09, 0x06, 0x06, 0x17, 0x06, 0x04, 0xfd, 0xe7, 0x00, 0xf6, + 0x05, 0x0a, 0x24, 0xd2, 0x02, 0x02, 0x1b, 0xee, 0x09, 0xfa, 0x06, 0x01, + 0x00, 0xe9, 0x09, 0x05, 0xd7, 0x0b, 0xf8, 0xf7, 0x03, 0xd8, 0x06, 0x12, + 0x06, 0x02, 0x06, 0x05, 0x0d, 0xe9, 0x0e, 0xf5, 0xfb, 0x02, 0x13, 0xf3, + 0xda, 0xb3, 0x22, 0x00, 0x1e, 0x1a, 0x10, 0x13, 0x03, 0xfc, 0x06, 0x0d, + 0xfb, 0x18, 0x20, 0xf8, 0xfe, 0xc0, 0x1a, 0x07, 0x0f, 0xe6, 0x05, 0x07, + 0xfb, 0xb0, 0x08, 0x13, 0x9f, 0x06, 0xde, 0x04, 0xd6, 0xc3, 0x18, 0x14, + 0x05, 0xeb, 0xfc, 0x03, 0xa8, 0xba, 0x0d, 0x0b, 0xb5, 0x03, 0xee, 0xfc, + 0x84, 0x99, 0x10, 0xd3, 0x17, 0xfc, 0x0d, 0x07, 0x81, 0xb8, 0xc7, 0x12, + 0xb6, 0x12, 0xe0, 0x8d, 0xf8, 0xad, 0xfd, 0x06, 0x01, 0xe8, 0x03, 0xff, + 0xf6, 0x8e, 0x1d, 0x0b, 0x8d, 0x03, 0xd8, 0xb1, 0xe3, 0xc7, 0x10, 0xf1, + 0x1d, 0xf5, 0x07, 0x0b, 0xfa, 0xc9, 0xf0, 0x07, 0xcb, 0x0c, 0xe3, 0xce, + 0xc9, 0xc7, 0x11, 0xeb, 0xdb, 0xd8, 0x01, 0x08, 0xc9, 0xe0, 0xdc, 0x00, + 0xdb, 0x13, 0xbd, 0xe2, 0xd7, 0xd4, 0x2b, 0xf1, 0x07, 0xf5, 0x0b, 0x0e, + 0x10, 0xcd, 0x02, 0x01, 0xcc, 0x0d, 0xf0, 0xfe, 0x1e, 0x23, 0xfa, 0xfe, + 0x00, 0xdf, 0xc6, 0xd3, 0x06, 0x11, 0xbb, 0x1d, 0xf1, 0xec, 0x05, 0xed, + 0xee, 0xfb, 0x14, 0xc8, 0xf1, 0xc0, 0xe4, 0xeb, 0xe5, 0xe5, 0xdf, 0x07, + 0xc4, 0xd9, 0xe0, 0xc7, 0x0c, 0xde, 0x1b, 0x13, 0x17, 0xf6, 0x0b, 0x09, + 0x05, 0xc7, 0x17, 0x03, 0xc9, 0x10, 0xd0, 0xf3, 0x11, 0x21, 0xf4, 0xdb, + 0xa2, 0x17, 0xb8, 0xae, 0x00, 0x2b, 0xbd, 0x10, 0x0c, 0xaf, 0x11, 0x15, + 0x00, 0x2a, 0xf8, 0xd5, 0xa2, 0x0c, 0xbd, 0xd6, 0xfe, 0x24, 0xb0, 0x04, + 0x18, 0xa9, 0x0a, 0x09, 0x81, 0xfb, 0x11, 0x8d, 0xce, 0xab, 0xe3, 0xe0, + 0xa3, 0xd2, 0xad, 0x0e, 0xa3, 0xc5, 0x9a, 0x19, 0x19, 0xa7, 0xe6, 0x1c, + 0x0e, 0xd1, 0xf4, 0xf6, 0x0d, 0xbc, 0x12, 0xc3, 0xf9, 0xf7, 0x08, 0x14, + 0x0e, 0xad, 0x9d, 0x15, 0x19, 0x8d, 0xb0, 0xc9, 0x1b, 0x9b, 0x17, 0x98, + 0xe6, 0xcb, 0x03, 0x31, 0x00, 0xcc, 0xc1, 0x08, 0xfb, 0xc5, 0xa7, 0xb3, + 0xfc, 0xde, 0x05, 0xbb, 0xf1, 0xb0, 0xfb, 0x1d, 0x1c, 0xea, 0xf6, 0x0c, + 0x1d, 0xcc, 0xf8, 0xe0, 0x1b, 0xe2, 0x0c, 0xf6, 0x06, 0xfc, 0x12, 0x20, + 0x04, 0xa5, 0x92, 0x10, 0x13, 0xb0, 0xb8, 0xf2, 0x16, 0x98, 0x09, 0xb3, + 0xe3, 0xea, 0xeb, 0x2f, 0xdc, 0xe7, 0xc2, 0x03, 0x07, 0xeb, 0xb7, 0xc6, + 0xf8, 0xf3, 0x07, 0xbb, 0xab, 0xcd, 0xaa, 0x1e, 0x0c, 0xea, 0xee, 0x21, + 0x13, 0xe4, 0xf6, 0xf3, 0x04, 0xf5, 0x18, 0xff, 0xfe, 0xdd, 0xfe, 0x23, + 0xd0, 0xa3, 0xa7, 0x14, 0x0a, 0x9a, 0xe4, 0xd0, 0xd4, 0xd3, 0x07, 0xe3, + 0x9b, 0xce, 0x8b, 0x30, 0xc0, 0xa4, 0xc6, 0x0b, 0x10, 0xd1, 0xd0, 0xeb, + 0xed, 0xee, 0xfe, 0xcd, 0x81, 0xc2, 0xb2, 0x2d, 0x9f, 0xc1, 0x06, 0x81, + 0x0e, 0x03, 0x0c, 0x04, 0x01, 0x05, 0xc2, 0x05, 0xf7, 0x0c, 0xff, 0x9f, + 0xde, 0x01, 0xfd, 0xab, 0x09, 0x0f, 0x03, 0x03, 0xfa, 0x02, 0xc6, 0x09, + 0xfe, 0x06, 0x11, 0x9c, 0x00, 0x02, 0x04, 0xbf, 0x03, 0x04, 0x0b, 0x06, + 0xf2, 0x07, 0xc2, 0x09, 0x06, 0x05, 0x01, 0xd3, 0xbf, 0xc2, 0xfd, 0xf0, + 0x08, 0xfb, 0x02, 0x07, 0xe8, 0xf1, 0xf3, 0x0d, 0xec, 0x07, 0xf6, 0xbf, + 0xfb, 0x0e, 0x01, 0xea, 0x08, 0x11, 0x0a, 0x0d, 0xdc, 0x0b, 0xf6, 0x07, + 0xfe, 0x08, 0x07, 0xa8, 0x10, 0x0e, 0x13, 0xdc, 0x01, 0x03, 0x03, 0x04, + 0xd5, 0x01, 0xd7, 0x08, 0x09, 0x05, 0x01, 0x1f, 0xf7, 0xcd, 0xea, 0x01, + 0x0b, 0xf7, 0x03, 0x08, 0xf8, 0xb6, 0x00, 0x01, 0xaa, 0x09, 0xfb, 0x00, + 0xfd, 0xb5, 0x04, 0x0c, 0x0d, 0xfa, 0x00, 0x06, 0xe3, 0xbb, 0x0d, 0xff, + 0xaf, 0x05, 0xf1, 0x01, 0xaa, 0xb3, 0x05, 0x00, 0x04, 0xf8, 0x02, 0x06, + 0xaf, 0xaf, 0xc7, 0x0a, 0xac, 0x06, 0xea, 0xdd, 0x21, 0xec, 0xcd, 0x16, + 0x1a, 0xd4, 0xf4, 0xfa, 0x0d, 0xc7, 0x1a, 0xfa, 0x0d, 0xe7, 0x09, 0x0b, + 0x06, 0xcd, 0xd6, 0x15, 0x0f, 0xd5, 0xcc, 0xc1, 0x11, 0xe1, 0x10, 0xfa, + 0x16, 0xdc, 0x12, 0x1d, 0x04, 0xb3, 0xfe, 0x04, 0x03, 0x93, 0xee, 0xf1, + 0x10, 0x87, 0x01, 0xeb, 0x09, 0xf9, 0x04, 0x10, 0x0f, 0xd5, 0xa3, 0x09, + 0x23, 0xb9, 0xc3, 0xb7, 0x0e, 0x9c, 0x0b, 0xbd, 0x11, 0xc7, 0x04, 0x0c, + 0x17, 0xd9, 0x08, 0x11, 0x0e, 0xd9, 0xc3, 0xc9, 0x08, 0xd8, 0x09, 0xdc, + 0x0c, 0xd7, 0x14, 0x09, 0x09, 0xe0, 0x01, 0x05, 0x09, 0xc8, 0xa4, 0xc7, + 0x05, 0xbc, 0x06, 0xa9, 0x0d, 0x9e, 0x07, 0x0a, 0xff, 0xe4, 0x84, 0x04, + 0x09, 0xe7, 0x9d, 0x8f, 0xfe, 0xbb, 0x07, 0xca, 0xfd, 0xae, 0x0c, 0xfc, + 0x0a, 0x03, 0x10, 0x01, 0xff, 0xeb, 0x93, 0x9c, 0x0f, 0xf5, 0x07, 0x0c, + 0x11, 0xa4, 0x0d, 0x19, 0x02, 0xfd, 0x0e, 0x02, 0x02, 0xe3, 0x89, 0x81, + 0xef, 0xe1, 0x00, 0xd6, 0x00, 0x8f, 0xf9, 0x12, 0xe9, 0xbc, 0x98, 0x03, + 0xf6, 0x9e, 0xb4, 0xb6, 0xcc, 0xa8, 0x02, 0xeb, 0xd3, 0xac, 0xa6, 0xf3, + 0xf7, 0xb5, 0xcc, 0x12, 0x0a, 0xa6, 0xb6, 0xce, 0xfe, 0xb3, 0x08, 0xd4, + 0xd4, 0xc1, 0xbd, 0x17, 0x02, 0xad, 0xd9, 0x0a, 0x10, 0xae, 0xdc, 0xef, + 0x08, 0x9c, 0x07, 0xd3, 0xf9, 0xd4, 0xf1, 0x0d, 0xc9, 0xcf, 0xf5, 0xf2, + 0xff, 0xbe, 0xfd, 0x01, 0x05, 0xce, 0x03, 0x11, 0xc2, 0xfe, 0xfe, 0xd2, + 0xdf, 0xc1, 0x06, 0xfa, 0xfa, 0xd6, 0x04, 0x07, 0xfe, 0xde, 0xf6, 0xff, + 0xc9, 0xf7, 0xfc, 0xe8, 0xf9, 0xc4, 0xf7, 0xff, 0x0d, 0x04, 0x00, 0x09, + 0x0c, 0xe0, 0x0c, 0x02, 0xf6, 0x03, 0x08, 0x06, 0x00, 0xb7, 0xeb, 0x11, + 0x09, 0x1a, 0x0a, 0x0e, 0x0f, 0xfc, 0x09, 0x05, 0x0a, 0x0d, 0x12, 0xf1, + 0xf9, 0x81, 0x0f, 0x00, 0x10, 0x0d, 0x0d, 0x13, 0x07, 0xe4, 0x0b, 0x1c, + 0xf8, 0x17, 0x14, 0xec, 0xf7, 0x8d, 0x19, 0x08, 0x1b, 0x00, 0x15, 0x18, + 0x05, 0xde, 0x0e, 0x0e, 0xf8, 0x1a, 0x11, 0xee, 0xf3, 0x0a, 0x16, 0xfd, + 0x0a, 0xfb, 0x0b, 0x0f, 0x00, 0x04, 0x01, 0x0c, 0xf8, 0x0b, 0x00, 0xf7, + 0xd0, 0xdc, 0x0f, 0x07, 0x07, 0xf4, 0xf4, 0xff, 0xfe, 0x01, 0x03, 0x9d, + 0x01, 0xfa, 0xd0, 0x00, 0xb9, 0xbe, 0xb7, 0x0d, 0xd8, 0xa7, 0x95, 0xa7, + 0xfc, 0x97, 0xfe, 0xfc, 0x81, 0xc0, 0xba, 0xfc, 0x03, 0x1c, 0x38, 0xf4, + 0x1a, 0x19, 0x19, 0x1b, 0x00, 0x1b, 0xff, 0x1a, 0x11, 0x15, 0x02, 0xf7, + 0xe4, 0xc4, 0x02, 0x00, 0x0a, 0xd0, 0xe6, 0xe7, 0xfc, 0xbe, 0x05, 0x95, + 0xb6, 0xf4, 0xb3, 0xf2, 0xbc, 0xcc, 0xc9, 0x06, 0xdd, 0xc5, 0xb5, 0xb9, + 0xe7, 0xc6, 0x00, 0xd2, 0xa0, 0xb7, 0xbc, 0x14, 0x10, 0x3c, 0x27, 0xe8, + 0x19, 0x14, 0x12, 0x19, 0x09, 0x21, 0xf6, 0x17, 0xfd, 0x18, 0x07, 0x0e, + 0xf9, 0x05, 0xe4, 0x0e, 0x07, 0xb1, 0xda, 0xd7, 0x0b, 0xfe, 0x03, 0xf7, + 0xcf, 0xd6, 0xca, 0x12, 0xc8, 0xec, 0xdc, 0x01, 0xef, 0xcc, 0xa1, 0xc7, + 0xf7, 0xd7, 0xff, 0xf1, 0xae, 0xbf, 0xcc, 0x0e, 0xd8, 0xda, 0x13, 0x26, + 0x04, 0x09, 0xff, 0x03, 0xea, 0xf6, 0x1c, 0xec, 0x0b, 0x07, 0x13, 0xfd, + 0xe4, 0xf4, 0x25, 0xfb, 0xfd, 0x15, 0x02, 0x03, 0xed, 0x11, 0xf1, 0x90, + 0x17, 0x06, 0x21, 0x1c, 0xf6, 0xf8, 0x47, 0xe0, 0xde, 0x0d, 0xf2, 0xea, + 0xde, 0x09, 0xed, 0x9c, 0x00, 0xe5, 0xf1, 0x2d, 0x85, 0xd4, 0x33, 0x81, + 0x16, 0x1d, 0x0b, 0x10, 0xd3, 0x0c, 0xaa, 0xe9, 0x12, 0x06, 0x1e, 0xae, + 0xcf, 0xef, 0x17, 0xd9, 0x13, 0x1e, 0x05, 0xfe, 0x0d, 0x1a, 0xf2, 0x8a, + 0x10, 0x0b, 0x2e, 0x0c, 0xd7, 0xe0, 0xfa, 0xfb, 0xb3, 0xe3, 0xae, 0xaf, + 0xdf, 0x0d, 0xf8, 0x8f, 0xf7, 0xc1, 0x9d, 0x13, 0xa7, 0xd5, 0x22, 0x9e, + 0x1b, 0x1e, 0x08, 0x02, 0xe2, 0x07, 0xec, 0xfb, 0x0c, 0x0d, 0x0f, 0xb4, + 0xdf, 0xd6, 0x0f, 0x09, 0x1a, 0x16, 0x03, 0x03, 0xfc, 0x19, 0x14, 0x82, + 0x14, 0x02, 0xff, 0x01, 0xbf, 0xfc, 0x9a, 0x17, 0xf0, 0xac, 0xa2, 0xa7, + 0x02, 0xb7, 0x12, 0x9c, 0xbe, 0xc4, 0xab, 0x08, 0xf0, 0xe0, 0x81, 0x2d, + 0x09, 0xe1, 0xdc, 0xf0, 0xeb, 0xd5, 0x1f, 0x98, 0xed, 0xd2, 0xe6, 0x2d, + 0x0b, 0x03, 0x53, 0x0f, 0x0d, 0x16, 0x10, 0x08, 0x0c, 0x0c, 0x09, 0xdb, + 0x11, 0x0f, 0x1e, 0x1a, 0x07, 0x04, 0x17, 0xf0, 0xc7, 0x02, 0x00, 0xea, + 0xd9, 0x09, 0xd5, 0x10, 0x05, 0xf0, 0xf9, 0x0a, 0xb0, 0xc4, 0x9f, 0xbd, + 0xde, 0xfd, 0xdf, 0xe9, 0x9f, 0xdb, 0xda, 0xd5, 0xdf, 0xca, 0xea, 0xb1, + 0x0c, 0x07, 0x45, 0xfc, 0x13, 0x28, 0x10, 0x03, 0x1c, 0x1c, 0xff, 0xde, + 0x1d, 0x0c, 0x27, 0x31, 0xed, 0xd4, 0x23, 0xdc, 0xd7, 0xcf, 0x05, 0xfc, + 0xc3, 0xfd, 0x9c, 0x0c, 0xcf, 0xf9, 0xb8, 0x27, 0xa3, 0xd3, 0xfd, 0xc9, + 0x05, 0x0a, 0x04, 0x00, 0xc9, 0xd7, 0xff, 0xfc, 0xe4, 0x00, 0xf5, 0xea, + 0x0f, 0x0d, 0x33, 0x16, 0x0f, 0x19, 0x0d, 0x04, 0x1d, 0x18, 0x07, 0xec, + 0x21, 0x06, 0x24, 0x1d, 0xdb, 0xe0, 0x2a, 0xd8, 0xe4, 0xca, 0xe4, 0xf3, + 0xed, 0xf9, 0x98, 0xed, 0xe2, 0xe6, 0xd1, 0x42, 0x12, 0x14, 0xf6, 0xf1, + 0xb8, 0x0e, 0xc1, 0xa0, 0x0a, 0x0d, 0xee, 0xe6, 0x0f, 0xc6, 0x11, 0xe6, + 0x22, 0x1f, 0x19, 0x05, 0xf6, 0x15, 0xdf, 0xdf, 0xfb, 0x15, 0xf3, 0x19, + 0x12, 0xec, 0x0b, 0x0e, 0x08, 0x01, 0x00, 0x0e, 0x0f, 0x12, 0xca, 0xc6, + 0xfc, 0x04, 0x0a, 0x05, 0x02, 0xdb, 0xfc, 0x11, 0x03, 0x1d, 0x93, 0xca, + 0xa9, 0x05, 0xc0, 0xb5, 0xce, 0xf2, 0xea, 0x0f, 0x09, 0xb9, 0xe5, 0xc9, + 0x22, 0x19, 0x16, 0xee, 0xf5, 0x0c, 0x0d, 0xec, 0x13, 0x0a, 0xf9, 0x12, + 0x0d, 0x14, 0x0c, 0xf6, 0x09, 0x03, 0x11, 0x01, 0xeb, 0xff, 0xc1, 0xa4, + 0x07, 0x00, 0xfe, 0xfe, 0x01, 0xb6, 0x04, 0x03, 0x8f, 0x97, 0xdf, 0xae, + 0x16, 0xba, 0xfe, 0x04, 0xc6, 0x90, 0xfe, 0xf8, 0x81, 0xfe, 0x96, 0x87, + 0x11, 0xfe, 0xe4, 0x05, 0x0b, 0x00, 0x0f, 0x10, 0xfd, 0xf2, 0x10, 0x10, + 0xfd, 0x06, 0xff, 0xc6, 0x04, 0xff, 0x1b, 0x0f, 0xf7, 0x00, 0x07, 0x09, + 0x10, 0x05, 0x06, 0x0e, 0x04, 0xf6, 0x06, 0x1c, 0x0e, 0xf9, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x2f, 0x43, + 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x00, 0x00, 0x00, 0x70, 0xf8, 0xff, 0xff, + 0x08, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0xb1, 0x93, 0xb9, 0x3a, 0x15, 0x93, 0xf8, 0x3a, 0x80, 0x56, 0xad, 0x3a, + 0x2f, 0x2c, 0xb4, 0x3a, 0x73, 0xdb, 0x97, 0x3a, 0xcf, 0xc9, 0xa2, 0x3a, + 0x3c, 0x68, 0xb3, 0x3a, 0x7b, 0x4f, 0x9d, 0x3a, 0x5c, 0x19, 0x5f, 0x3a, + 0xd5, 0x55, 0x67, 0x3a, 0x53, 0x13, 0x7d, 0x3a, 0x7a, 0x37, 0x9f, 0x3a, + 0xae, 0xdc, 0xb2, 0x3a, 0xc9, 0x9b, 0xa2, 0x3a, 0xbd, 0xc1, 0xa3, 0x3a, + 0xb3, 0xb3, 0x93, 0x3a, 0x1d, 0x0d, 0xa5, 0x3a, 0x7a, 0x4f, 0x9d, 0x3a, + 0x3b, 0x3c, 0x80, 0x3a, 0x87, 0xdf, 0x06, 0x3a, 0x8e, 0x2e, 0x87, 0x3a, + 0xc3, 0x83, 0xb3, 0x3a, 0xe8, 0xd4, 0x7b, 0x3a, 0x2e, 0x51, 0x77, 0x3a, + 0x2c, 0x10, 0x6e, 0x3a, 0xe1, 0x3f, 0xb7, 0x3a, 0xfd, 0xae, 0x83, 0x3a, + 0xa0, 0x4a, 0xa5, 0x3a, 0xba, 0x56, 0x4c, 0x3a, 0xa7, 0xb1, 0x90, 0x3a, + 0x3f, 0x35, 0x95, 0x3a, 0x91, 0x32, 0x88, 0x3a, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xfb, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, + 0x40, 0x04, 0x00, 0x00, 0xa2, 0xfc, 0xff, 0xff, 0xd4, 0xff, 0xff, 0xff, + 0x4c, 0xff, 0xff, 0xff, 0x66, 0xff, 0xff, 0xff, 0x96, 0xfc, 0xff, 0xff, + 0xf9, 0xf3, 0xff, 0xff, 0x06, 0xfe, 0xff, 0xff, 0x9b, 0xfe, 0xff, 0xff, + 0xe8, 0xfe, 0xff, 0xff, 0x59, 0x02, 0x00, 0x00, 0xf6, 0xff, 0xff, 0xff, + 0xc3, 0xfc, 0xff, 0xff, 0x62, 0x0b, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, + 0x3a, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x2f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x6f, + 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, + 0x46, 0x75, 0x73, 0x65, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, + 0x72, 0x6d, 0x56, 0x33, 0x3b, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x2f, + 0x62, 0x69, 0x61, 0x73, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, + 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, + 0x64, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x76, + 0x32, 0x64, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x00, 0x00, 0x00, + 0xf0, 0xfa, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x93, 0xc8, 0x52, 0x39, 0x5c, 0x36, 0x73, 0x39, + 0x26, 0x92, 0x02, 0x39, 0x39, 0xfd, 0x48, 0x39, 0x64, 0x2b, 0x46, 0x39, + 0x76, 0xae, 0x86, 0x39, 0x90, 0x52, 0xbc, 0x38, 0xd0, 0xc2, 0xe2, 0x38, + 0x2c, 0x13, 0xd6, 0x38, 0x55, 0x74, 0x41, 0x39, 0xee, 0xe5, 0xf0, 0x38, + 0x51, 0x0a, 0xb9, 0x39, 0x61, 0xfc, 0xef, 0x38, 0x01, 0xed, 0xc1, 0x38, + 0x1f, 0x36, 0x7a, 0x38, 0xac, 0x4c, 0x0e, 0x39, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xfc, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xe4, 0x1e, 0xab, 0xfc, + 0x1b, 0xa1, 0xfe, 0x0f, 0x9c, 0xf3, 0x22, 0x98, 0xf2, 0x1b, 0x81, 0x02, + 0x11, 0x8a, 0xf3, 0x11, 0xd2, 0xf3, 0x19, 0xa4, 0x02, 0x0d, 0xcb, 0xcf, + 0x20, 0x87, 0xd7, 0x16, 0xc0, 0xd3, 0x13, 0xc0, 0xbe, 0x23, 0x81, 0xb9, + 0x26, 0x90, 0xad, 0x1d, 0x84, 0xc7, 0x1d, 0xa3, 0xd2, 0x1f, 0xb1, 0xc1, + 0x19, 0xa5, 0xd4, 0x17, 0x33, 0xf5, 0xfc, 0xdc, 0x17, 0xaa, 0x81, 0xcc, + 0x29, 0x17, 0x0a, 0xf7, 0x0d, 0x32, 0xab, 0x8a, 0x87, 0x4a, 0xf7, 0x12, + 0xe4, 0xdd, 0x28, 0xba, 0xb6, 0x48, 0x09, 0x81, 0x39, 0x04, 0xf1, 0x26, + 0xfd, 0x02, 0x49, 0x0f, 0xb3, 0x25, 0x10, 0xba, 0xf8, 0xfe, 0xff, 0x42, + 0xf9, 0xf1, 0x20, 0x03, 0xfe, 0x06, 0x01, 0xff, 0xf3, 0x01, 0x18, 0x22, + 0x02, 0x22, 0x23, 0x01, 0x1f, 0x0c, 0x00, 0x19, 0x1d, 0xfd, 0x2d, 0x3f, + 0x00, 0x13, 0xf2, 0x00, 0x14, 0x20, 0xfb, 0x0e, 0x57, 0xe1, 0x81, 0x81, + 0x10, 0xf1, 0xc7, 0x1e, 0xf4, 0xe6, 0x15, 0xf5, 0xad, 0x14, 0x03, 0xcd, + 0x1b, 0xf7, 0xda, 0x16, 0xf9, 0x0b, 0xf8, 0xf8, 0xec, 0x0c, 0xfe, 0xf5, + 0x06, 0x03, 0x9f, 0x07, 0x48, 0xf3, 0x06, 0x57, 0xf7, 0xff, 0x50, 0xf7, + 0xfe, 0x6b, 0xfe, 0xfb, 0x7f, 0xf7, 0x01, 0x52, 0xfb, 0x00, 0x44, 0xf7, + 0x03, 0x68, 0x05, 0x00, 0x6b, 0xf3, 0x08, 0x3f, 0xff, 0x04, 0x58, 0xf7, + 0x05, 0x3c, 0x08, 0x02, 0x57, 0x03, 0x01, 0x63, 0xf0, 0x09, 0x57, 0x0c, + 0x04, 0x2f, 0x0d, 0xfe, 0x53, 0x0c, 0x04, 0x7f, 0x20, 0xe7, 0x1b, 0x23, + 0xc3, 0x2f, 0x3b, 0xb4, 0x19, 0x0a, 0x3c, 0xbb, 0x4a, 0x64, 0x81, 0x67, + 0xec, 0xfd, 0xe7, 0x37, 0x85, 0x13, 0x4f, 0x9d, 0x43, 0x19, 0xe9, 0x8b, + 0x32, 0xc2, 0xa5, 0x2b, 0xcf, 0xcc, 0x14, 0xf1, 0x81, 0x34, 0x9e, 0x97, + 0x2b, 0xc9, 0xa7, 0x1d, 0xdf, 0xa5, 0x24, 0xae, 0xcb, 0x25, 0xb9, 0xc8, + 0x05, 0xf6, 0x4a, 0xff, 0x05, 0x7f, 0x1a, 0xc4, 0x4a, 0x08, 0xfb, 0x64, + 0xed, 0x20, 0x68, 0xf4, 0x0a, 0x6d, 0x01, 0x00, 0x50, 0xe8, 0x0e, 0x59, + 0xfa, 0x01, 0x53, 0x01, 0x01, 0xde, 0x13, 0x81, 0x04, 0xf2, 0x0b, 0x05, + 0xed, 0x1c, 0xfe, 0x07, 0xf0, 0xfe, 0xeb, 0x34, 0xfb, 0xf6, 0x20, 0xfd, + 0x00, 0x1d, 0xf8, 0xf8, 0x28, 0x02, 0xfa, 0x22, 0xdf, 0x33, 0xb7, 0xcb, + 0x40, 0xba, 0xee, 0x1b, 0xf2, 0xe1, 0x41, 0x91, 0xc5, 0x58, 0x81, 0xc1, + 0x38, 0xab, 0x04, 0x04, 0xf5, 0xe6, 0x29, 0xbd, 0xd3, 0x2c, 0xc4, 0xa5, + 0x0f, 0x4e, 0xdf, 0xfe, 0x57, 0xfc, 0xf8, 0x21, 0xfc, 0x09, 0x63, 0xfc, + 0x00, 0x7f, 0x03, 0xfa, 0x66, 0x09, 0x08, 0x16, 0xf8, 0x09, 0x4f, 0x14, + 0x05, 0x4b, 0xfc, 0x00, 0xfb, 0xe8, 0x20, 0xef, 0xf1, 0x0c, 0xef, 0xfa, + 0x25, 0xce, 0xba, 0x73, 0xd3, 0xbd, 0x4e, 0xdc, 0xf0, 0x49, 0xb1, 0xe4, + 0x7f, 0xc6, 0xc1, 0x79, 0xdf, 0x05, 0x31, 0x82, 0x2f, 0xf9, 0xe1, 0x5c, + 0xa3, 0xd4, 0x00, 0x53, 0x81, 0x45, 0xb6, 0xfc, 0x37, 0xac, 0xff, 0x06, + 0x10, 0xdb, 0x22, 0xca, 0x04, 0x30, 0xb5, 0x04, 0x66, 0xfe, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, + 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x46, 0x75, 0x73, 0x65, + 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x56, 0x33, + 0x3b, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x2f, 0x62, 0x69, 0x61, 0x73, + 0x3b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x32, + 0x64, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, 0x64, 0x3b, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x2f, 0x43, + 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x31, 0x00, 0x00, 0x28, 0xfe, 0xff, 0xff, + 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x93, 0xc8, 0x52, 0x39, 0x5c, 0x36, 0x73, 0x39, 0x26, 0x92, 0x02, 0x39, + 0x39, 0xfd, 0x48, 0x39, 0x64, 0x2b, 0x46, 0x39, 0x76, 0xae, 0x86, 0x39, + 0x90, 0x52, 0xbc, 0x38, 0xd0, 0xc2, 0xe2, 0x38, 0x2c, 0x13, 0xd6, 0x38, + 0x55, 0x74, 0x41, 0x39, 0xee, 0xe5, 0xf0, 0x38, 0x51, 0x0a, 0xb9, 0x39, + 0x61, 0xfc, 0xef, 0x38, 0x01, 0xed, 0xc1, 0x38, 0x1f, 0x36, 0x7a, 0x38, + 0xac, 0x4c, 0x0e, 0x39, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x18, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x5f, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x6f, 0x6f, + 0x6c, 0x69, 0x6e, 0x67, 0x32, 0x64, 0x2f, 0x4d, 0x65, 0x61, 0x6e, 0x2f, + 0x72, 0x65, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, + 0x64, 0x69, 0x63, 0x65, 0x73, 0x00, 0x00, 0x00, 0x58, 0xff, 0xff, 0xff, + 0x14, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x31, 0x3a, + 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00}; +unsigned int g_magic_wand_model_data_len = 30880; diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand_model_data.h b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand_model_data.h new file mode 100644 index 000000000..9a7b9a814 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/magic_wand_model_data.h @@ -0,0 +1,24 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This is a standard TensorFlow Lite model file that has been converted into a +// C data array, so it can be easily compiled into a binary for devices that +// don't have a file system. It was created using the command: +// xxd -i magic_wand_model.tflite > magic_wand_model_data.cc + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MAGIC_WAND_MAGIC_WAND_MODEL_DATA_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MAGIC_WAND_MAGIC_WAND_MODEL_DATA_H_ + +extern const unsigned char g_magic_wand_model_data[]; +extern const int g_magic_wand_model_data_len; + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MAGIC_WAND_MAGIC_WAND_MODEL_DATA_H_ \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/rasterize_stroke.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/rasterize_stroke.cpp new file mode 100644 index 000000000..839a85db0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/rasterize_stroke.cpp @@ -0,0 +1,157 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "rasterize_stroke.h" + +namespace { +constexpr int kFixedPoint = 4096; + +int32_t MulFP(int32_t a, int32_t b) { return (a * b) / kFixedPoint; } + +int32_t DivFP(int32_t a, int32_t b) { + if (b == 0) { + b = 1; + } + return (a * kFixedPoint) / b; +} + +int32_t FloatToFP(float a) { return static_cast(a * kFixedPoint); } + +int32_t NormToCoordFP(int32_t a_fp, int32_t range_fp, int32_t half_size_fp) { + const int32_t norm_fp = DivFP(a_fp, range_fp); + return MulFP(norm_fp, half_size_fp) + half_size_fp; +} + +int32_t RoundFPToInt(int32_t a) { + return static_cast((a + (kFixedPoint / 2)) / kFixedPoint); +} + +int32_t Gate(int32_t a, int32_t min, int32_t max) { + if (a < min) { + return min; + } else if (a > max) { + return max; + } else { + return a; + } +} + +int32_t Abs(int32_t a) { + if (a > 0) { + return a; + } else { + return -a; + } +} + +} // namespace + +void RasterizeStroke(int8_t* stroke_points, int stroke_points_count, + float x_range, float y_range, int width, int height, + int8_t* out_buffer) { + constexpr int num_channels = 3; + const int buffer_byte_count = height * width * num_channels; + + for (int i = 0; i < buffer_byte_count; ++i) { + out_buffer[i] = -128; + } + + const int32_t width_fp = width * kFixedPoint; + const int32_t height_fp = height * kFixedPoint; + const int32_t half_width_fp = width_fp / 2; + const int32_t half_height_fp = height_fp / 2; + const int32_t x_range_fp = FloatToFP(x_range); + const int32_t y_range_fp = FloatToFP(y_range); + + const int t_inc_fp = kFixedPoint / stroke_points_count; + + const int one_half_fp = (kFixedPoint / 2); + + for (int point_index = 0; point_index < (stroke_points_count - 1); + ++point_index) { + const int8_t* start_point = &stroke_points[point_index * 2]; + const int32_t start_point_x_fp = (start_point[0] * kFixedPoint) / 128; + const int32_t start_point_y_fp = (start_point[1] * kFixedPoint) / 128; + + const int8_t* end_point = &stroke_points[(point_index + 1) * 2]; + const int32_t end_point_x_fp = (end_point[0] * kFixedPoint) / 128; + const int32_t end_point_y_fp = (end_point[1] * kFixedPoint) / 128; + + const int32_t start_x_fp = + NormToCoordFP(start_point_x_fp, x_range_fp, half_width_fp); + const int32_t start_y_fp = + NormToCoordFP(-start_point_y_fp, y_range_fp, half_height_fp); + const int32_t end_x_fp = + NormToCoordFP(end_point_x_fp, x_range_fp, half_width_fp); + const int32_t end_y_fp = + NormToCoordFP(-end_point_y_fp, y_range_fp, half_height_fp); + const int32_t delta_x_fp = end_x_fp - start_x_fp; + const int32_t delta_y_fp = end_y_fp - start_y_fp; + + const int32_t t_fp = point_index * t_inc_fp; + int32_t red_i32; + int32_t green_i32; + int32_t blue_i32; + if (t_fp < one_half_fp) { + const int32_t local_t_fp = DivFP(t_fp, one_half_fp); + const int32_t one_minus_t_fp = kFixedPoint - local_t_fp; + red_i32 = RoundFPToInt(one_minus_t_fp * 255) - 128; + green_i32 = RoundFPToInt(local_t_fp * 255) - 128; + blue_i32 = -128; + } else { + const int32_t local_t_fp = DivFP(t_fp - one_half_fp, one_half_fp); + const int32_t one_minus_t_fp = kFixedPoint - local_t_fp; + red_i32 = -128; + green_i32 = RoundFPToInt(one_minus_t_fp * 255) - 128; + blue_i32 = RoundFPToInt(local_t_fp * 255) - 128; + } + const int8_t red_i8 = Gate(red_i32, -128, 127); + const int8_t green_i8 = Gate(green_i32, -128, 127); + const int8_t blue_i8 = Gate(blue_i32, -128, 127); + + int line_length; + int32_t x_inc_fp; + int32_t y_inc_fp; + if (Abs(delta_x_fp) > Abs(delta_y_fp)) { + line_length = Abs(RoundFPToInt(delta_x_fp)); + if (delta_x_fp > 0) { + x_inc_fp = 1 * kFixedPoint; + y_inc_fp = DivFP(delta_y_fp, delta_x_fp); + } else { + x_inc_fp = -1 * kFixedPoint; + y_inc_fp = -DivFP(delta_y_fp, delta_x_fp); + } + } else { + line_length = Abs(RoundFPToInt(delta_y_fp)); + if (delta_y_fp > 0) { + y_inc_fp = 1 * kFixedPoint; + x_inc_fp = DivFP(delta_x_fp, delta_y_fp); + } else { + y_inc_fp = -1 * kFixedPoint; + x_inc_fp = -DivFP(delta_x_fp, delta_y_fp); + } + } + for (int i = 0; i < (line_length + 1); ++i) { + const int32_t x_fp = start_x_fp + (i * x_inc_fp); + const int32_t y_fp = start_y_fp + (i * y_inc_fp); + const int x = RoundFPToInt(x_fp); + const int y = RoundFPToInt(y_fp); + if ((x < 0) or (x >= width) or (y < 0) or (y >= height)) { + continue; + } + const int buffer_index = (y * width * num_channels) + (x * num_channels); + out_buffer[buffer_index + 0] = red_i8; + out_buffer[buffer_index + 1] = green_i8; + out_buffer[buffer_index + 2] = blue_i8; + } + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/rasterize_stroke.h b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/rasterize_stroke.h new file mode 100644 index 000000000..a9c118a32 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/rasterize_stroke.h @@ -0,0 +1,22 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MAGIC_WAND_RASTERIZE_STROKE_H +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MAGIC_WAND_RASTERIZE_STROKE_H + +#include + +void RasterizeStroke(int8_t* stroke_points, int stroke_points_count, + float x_range, float y_range, int width, int height, + int8_t* out_buffer); + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MAGIC_WAND_RASTERIZE_STROKE_H diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/train/train_magic_wand_model.ipynb b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/train/train_magic_wand_model.ipynb new file mode 100644 index 000000000..63379fdc6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/train/train_magic_wand_model.ipynb @@ -0,0 +1 @@ +{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Copy of Magic Wand Training","provenance":[{"file_id":"https://github.com/petewarden/magic_wand/blob/main/train/train_magic_wand_model.ipynb","timestamp":1638386707719}],"collapsed_sections":[]},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"code","metadata":{"id":"0g1pF6RfViPr","executionInfo":{"status":"ok","timestamp":1638745473565,"user_tz":480,"elapsed":179,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}}},"source":["SAVED_MODEL_FILENAME = \"saved_model\"\n","FLOAT_TFL_MODEL_FILENAME = \"float_model.tfl\"\n","QUANTIZED_TFL_MODEL_FILENAME = \"quantized_model.tfl\"\n","TFL_CC_MODEL_FILENAME = \"magic_wand_model_data.cc\""],"execution_count":1,"outputs":[]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"xvPo0OP0TFDq","executionInfo":{"status":"ok","timestamp":1638745477856,"user_tz":480,"elapsed":2072,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"2b44a027-1c9a-46aa-9660-57db546c8f75"},"source":["!curl -L https://github.com/petewarden/magic_wand_digit_data/archive/8170591863f9addca27b1a963263f7c7bed33f41.zip -o magic_wand_digit_data.zip\n","!unzip magic_wand_digit_data.zip\n","!rm -rf magic_wand_digit_data\n","!mv magic_wand_digit_data-* magic_wand_digit_data\n","!rm -rf magic_wand_digit_data.zip\n","!rm -rf sample_data\n","!mkdir -p checkpoints"],"execution_count":2,"outputs":[{"output_type":"stream","name":"stdout","text":[" % Total % Received % Xferd Average Speed Time Time Time Current\n"," Dload Upload Total Spent Left Speed\n","100 171 0 171 0 0 228 0 --:--:-- --:--:-- --:--:-- 228\n","100 238k 0 238k 0 0 250k 0 --:--:-- --:--:-- --:--:-- 1667k\n","Archive: magic_wand_digit_data.zip\n","8170591863f9addca27b1a963263f7c7bed33f41\n"," creating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/\n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/LICENSE \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_0.json \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_1.json \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_2.json \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_3.json \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_4.json \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_5.json \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_6.json \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_7.json \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_8.json \n"," inflating: magic_wand_digit_data-8170591863f9addca27b1a963263f7c7bed33f41/petewarden_9.json \n"]}]},{"cell_type":"code","metadata":{"id":"mWO58-igVFSd","executionInfo":{"status":"ok","timestamp":1638745496968,"user_tz":480,"elapsed":166,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}}},"source":["import glob\n","import json\n","\n","strokes = []\n","for filename in glob.glob(\"magic_wand_digit_data/*.json\"):\n"," with open(filename, \"r\") as file:\n"," file_contents = file.read()\n"," file_data = json.loads(file_contents)\n"," for stroke in file_data[\"strokes\"]:\n"," stroke[\"filename\"] = filename\n"," strokes.append(stroke)"],"execution_count":3,"outputs":[]},{"cell_type":"code","metadata":{"id":"xfLzrpyLVJ5S","executionInfo":{"status":"ok","timestamp":1638745501162,"user_tz":480,"elapsed":171,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}}},"source":["import matplotlib.pyplot as plt\n","\n","def plot_stroke(stroke):\n","\n"," x_array = []\n"," y_array = []\n"," for coords in stroke[\"strokePoints\"]:\n"," x_array.append(coords[\"x\"])\n"," y_array.append(coords[\"y\"])\n","\n"," fig = plt.figure(figsize=(12.8, 4.8))\n"," fig.suptitle(stroke[\"label\"])\n","\n"," ax = fig.add_subplot(131)\n"," ax.set_xlabel('x')\n"," ax.set_ylabel('y')\n"," ax.set_xlim(-0.4, 0.4)\n"," ax.set_ylim(-0.4, 0.4)\n"," ax.plot(x_array, y_array)\n","\n"," plt.show()"],"execution_count":4,"outputs":[]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/","height":391},"id":"dveZd2ZuW-jl","executionInfo":{"status":"ok","timestamp":1638746177871,"user_tz":480,"elapsed":466,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"ab8d5f8e-d753-49eb-fc06-607944f55e86"},"source":["import numpy as np\n","\n","shuffled_strokes = list(strokes)\n","np.random.shuffle(shuffled_strokes)\n","plot_stroke(shuffled_strokes[0])\n","print(f\"This stroke: {len(shuffled_strokes[0]['strokePoints'])}\")\n","func = lambda x: len(x[\"strokePoints\"])\n","values = list(map(func, strokes))\n","print(f\"All strokes: min {np.min(values)} max {np.max(values)} avg {np.average(values)}\")"],"execution_count":8,"outputs":[{"output_type":"display_data","data":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAAZkAAAFUCAYAAAD200GkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3deXhV9b3v8fc3CQlzICRASMIgRCmTIhGsQj0WnFuwilWs06ktta3Wc3tsj/fY2/bae0611rZPj/Yo1T51wqHcqtTZUquiMgSkDAokoISEIWEKc0KS7/0jW2/AkIRkr72y9/68noeHvfb+Ze3Pegj5ZK3fWmubuyMiIhKElLADiIhI4lLJiIhIYFQyIiISGJWMiIgERiUjIiKBUcmIiEhgVDIiIhIYlYyIiLSJmX3OzP5mZtVmVmpmX2nta1QyIiLSKjNLA54HXgCygNnA42Z2cotfpyv+RUSkNWY2BlgE9PJIcZjZa8Bid/9fx/s67cmIiEh7GTCmpQEqGRERaYt1QCXwAzPrYmbnA+cA3Vv6Ih0uExGRNjGzccB/0bj3UgxUATXufuNxv0YlIyIi7WFm7wKPuPuDxxujw2UiItImZjbOzLqaWXczuw3IBf7Y0teoZEREpK2uBbbSODczFTjP3Wta+gIdLhMRkcBoT0ZERAKjkhERkcCoZEREJDAqGRERCYxKRkREAqOSERGRwKhkREQkMCoZEREJjEpGREQCo5IREZHAqGRERCQwKhkREQmMSkZERAKjkhERkcCoZEREJDAqGRERCYxKRkREAqOSERGRwKhkREQkMCoZEREJTKglY2YXmtk6Mys1s9tbGHe5mbmZFcUyn4iIdExoJWNmqcD9wEXAKGCWmY1qZlwv4FZgcWwTiohIR4W5JzMRKHX3je5eCzwFzGhm3M+Au4HDsQwnIiIdlxbie+cBm5sslwOTmg4ws9OBAnd/0cx+cLwVmdlsYDZAjx49JowcOTKAuCLJZdmyZTvcPSfsHBLfwiyZFplZCvAr4IbWxrr7HGAOQFFRkRcXFwcbTiQJmNmmsDNI/AvzcFkFUNBkOT/y3Cd6AWOAv5vZx8CZwHxN/ouIxI8wS2YpUGhmw8wsHbgKmP/Ji+5e7e7Z7j7U3YcCi4Dp7q7dFBGROBFaybh7HXAz8CrwIfCMu68xszvNbHpYuUREJHpCnZNx95eAl4557sfHGftPscgkIiLRoyv+RUQkMCoZEREJjEpGREQCo5IREZHAqGRERCQwKhkREQmMSkZERAKjkhERkcCoZEREJDAqGRERCYxKRkREAqOSERGRwKhkREQkMCoZEREJjEpGREQCo5IREZHAqGRERCQwKhkREQmMSkZERAKjkhERkcCoZEREJDAqGRERCYxKRkREAhNqyZjZhWa2zsxKzez2Zl6/ycxWmdkKM1toZqPCyCkiIu2TFtYbm1kqcD9wHlAOLDWz+e7+QZNhc939gcj46cCvgAtjHlZiZlV5Nfe+vo7dB2pbHHfmSf343tRCemSE9i0sIm0Q5v/QiUCpu28EMLOngBnApyXj7nubjO8BeEwTSszsO3yEe19bz6PvfUxWjwzG5PU+7tiaIw08+NZG/vKPLfx0+mjOHz0wdkFF5ISEWTJ5wOYmy+XApGMHmdl3ge8D6cAXm1uRmc0GZgMMHjw46kElOO7OK6u38dO/rKFyXw3XTBrCbRecQma3Li1+3bJNu/j3P69m9mPLOG/UAO6cMZrczG4xSi0ibdXpJ/7d/X53Hw78G/Cj44yZ4+5F7l6Uk5MT24DSbpt3HeTrf1zKt59YTr8eGfz522fxs0vHtFowABOGZPHC9yZz+0Ujebukipn//R4799fEILWInIgwS6YCKGiynB957nieAi4NNJHExJH6Bh54cwPn/fpNFn+0ix9d8jnm33w24wf3PaH1dElN4aZzhvPMtz7Pjv01fHfuco7UNwSUWkTaI8ySWQoUmtkwM0sHrgLmNx1gZoVNFi8BSmKYTwKwbNMuvvxfC7nr5bVMKczh9e+fwzemnERaavu/Fcfl9+Hnl41l0cZd/MeLH0YxrYh0VGhzMu5eZ2Y3A68CqcAf3H2Nmd0JFLv7fOBmM5sGHAF2A9eHlVc6Zs/BWu5+ZR1PLiljUGZX5lw7IaoT9pedns+aLXt5eOFHjB7UmyuKClr/IhEJnLkn1glbRUVFXlxcHHYMiXB3nl+xhZ+98AF7Dh3h62cP5V+mnRzIqcd19Q1c94clFG/azTPf+jynFfSJ+nskEzNb5u5FYeeQ+NbpJ/4lfh0+Us//eHoF//L0CvKzujP/5rO545JRgV3bkpaawn1Xn07/Xhl867FiKvcdDuR9RKTtVDISiMq9h7lyziKeW7GFfz3vZP787bMYPSgz8PfN6pHOnGuLqD50hO88vpzaOp0IIBImlYxE3aryaqbf9w4l2/fxwDUTuGVqIakpFrP3HzWoN/fMPJXiTbv5339ZE7P3FZHP0j05JKpeWLmF2/70D/r1yGDeTWcxatDxr9wP0pdPHcSaLXt54M0NjB6UydWTdJGuSBhUMhIVDQ3ObxaU8NsFJRQN6csD104gu2dGqJl+cMEpfLh1Lz+Zv5pTBvZkwpCsUPOIJCMdLpOouPOFD/jtghJmTsjniW9OCr1gAFJTjN9eNZ68Pt347hPva35GJAQqGemwZ5Zu5o/vfszXzx7GPTPHkZGWGnakT2V278JPpo9m297DvPbBtrDjiCQdlYx0yPKy3fzoudVMKczm3y8eiVnsJvjb6guFOeT16cbcxWVhRxFJOioZabfKvYe56bFlDMzsyn/NGt+hW8MEKTXFmDWxgHc37OSjHQfCjiOSVDrnTwXp9Grq6vnW48vYd7iOOddNoE/39LAjteirRQWkpRhPLtHejEgsqWSkXX79egnvl+3h3q+eysiB4ZymfCL69+7KtM8NYN6ycmrq6sOOI5I0VDJywg7V1jN38Sa+NC6Xi8fmhh2nza6eNJhdB2p5ZbVOABCJFZWMnLAXVm5h7+E6rjlzSNhRTsjkEdkMzuquEwBEYkglIyds7pIyhuf0YNKw+Lq4MSXFmDVxMIs/2kVp5f6w44gkBZWMnJAPt+7l/bI9zJo4uFOertyaK4ry6ZKqEwBEYkUlIyfk929vJD0thZkT8sOO0i7ZPTM4f/RA5i0r5/ARnQAgEjSVjLTZ00vL+PPyCr5+9rBOf8pyS742cTDVh47w8uqtYUcRSXgqGWmT5WW7+V/PrWFKYTa3nX9y2HE65PPD+zEsuwdPLNIhM5GgqWSkVfFyZX9bmTXeAaB4027Wb98XdhyRhBbfPy0kcDV19dwUR1f2t9XMCQWkp6bodGaRgKlkpEV3vbyW5XF0ZX9bZfVI58IxA/m/y8s5VKsTAESCopKR46pvcOYtK+fS0wbF1ZX9bXX1pMHsO1zHCyu3hB1FJGGpZOS4VpbvYd/hOqZ+bkDYUQIxaVgWw3N6MFfXzIgERiUjx7WwZAcAZ4/IDjlJMBpPABjM+2V7+HDr3rDjiCSkUEvGzC40s3VmVmpmtzfz+vfN7AMzW2lmC8wsvm6WFecWlu5g9KDeZPVIjMn+5syckE96mk4AEAlKaCVjZqnA/cBFwChglpmNOmbY+0CRu48D5gG/iG3K5HWgpo7lZbuZXJiYezGf6NM9nUvG5vLs+xUcrK0LO45IwglzT2YiUOruG929FngKmNF0gLu/4e4HI4uLgPi8l0kcWvLRLo7UO5MT9FBZUzNOG8T+mjreL9sTdhSRhBNmyeQBm5ssl0eeO54bgZebe8HMZptZsZkVV1VVRTFi8lpYuoP0tBTOGBpfd1puj1Pz+wCwqqI65CQiiScuJv7N7BqgCLinudfdfY67F7l7UU5OTmzDJaiFJTs4Y2hfunZJDTtK4Pr2SKcgqxurylUyItEWZslUAAVNlvMjzx3FzKYBdwDT3b0mRtmSWuXew6zbvo/JI5KnsMfmZWpPRiQAYZbMUqDQzIaZWTpwFTC/6QAzGw88SGPBVIaQMSm9s6Hx1OUpCT7p39TYvD6U7TrInoO1YUcRSSihlYy71wE3A68CHwLPuPsaM7vTzKZHht0D9AT+ZGYrzGz+cVYnUfR2yQ6yeqQzKjdxbiPTmrF5mQCsrtD1MiLRlBbmm7v7S8BLxzz34yaPp8U8VJJzdxaW7OCs4f1ISYm/T75sr09KZmXFnoQ/bVskluJi4l9ip6RyP5X7apLi1OWmMrt3YXBWd1ZrXkYkqlQycpRPbiWTjL/Nj83PZKXOMBOJKpWMHGVh6Q6GZfcgv2/3sKPE3Ni8TMp3H2L3AU3+i0SLSkaOsm7bPk4r6BN2jFCMGdQ4L/OBbpYpEjUqGTmKu5OWRBP+TRUO6AlAaeX+kJOIJA6VjEhE/14Z9MpIU8mIRJFKRiTCzBjev6dKRiSKVDIiTRT270lplUpGJFpUMiJNjOjfk6p9NVQfPBJ2FJGEoJIRaWJE/8jkf9W+kJOIJAaVjHxGg4edIDyflozmZUSiQiUjR8nP6s767cn7W3x+3+6kp6WoZESiRCUjR5k8IpvVW6qT9qr31BRjeI7OMBOJFpWMHGVyYTbu//8zZZLRCJ1hJhI1Khk5yri8THp1Tfv0RpnJaEROT8p3H+JQbX3YUUTinkpGjpKWmsLnT+rH2yU7cE/OMwBG9O+JO2zQ3oxIh6lk5DOmFGZTsecQm3YeDDtKKHJ6ZQCwR9fKiHSYSkY+Y3JhDgBvlybnITNLzvuDigRCJSOfMbRfd/L6dGNhSVXYUUQkzqlk5DPMjMkjsnl3w07qk/nKTBHpMJWMNGtyYTb7DtexsnxP2FFEJI6pZKRZZw3vB5DUpzKLSMepZKRZ/XpmMHpQbxYm6eS/iESHSkaOa3JhNsvLdnOgpi7sKCISp0ItGTO70MzWmVmpmd3ezOtfMLPlZlZnZjPDyJjMJo/I5ki9s+SjXWFHEZE4FVrJmFkqcD9wETAKmGVmo44ZVgbcAMyNbToBOGNoFulpKTpkJiLtlhbie08ESt19I4CZPQXMAD74ZIC7fxx5rSGMgMmua5dUJg7N0uS/iLRbmIfL8oDNTZbLI8+dMDObbWbFZlZcVaULCKPp7BHZrNu+j8q9h8OOIiJxKCEm/t19jrsXuXtRTk5O2HESypTCbAAdMhORdgmzZCqAgibL+ZHnpBMZldubvt27qGREpF3CLJmlQKGZDTOzdOAqYH6IeaQZKSnGWSOyWZjEt/4XkfYLrWTcvQ64GXgV+BB4xt3XmNmdZjYdwMzOMLNy4ArgQTNbE1beZDZlRDaV+2oo0UcSi8gJCvPsMtz9JeClY577cZPHS2k8jCYhmhyZl3m7ZAcnD+gVchoRiScJMfEvwcrv252h/brz8qqtNOiuzCJyAlQy0ibfmHISxZt285sFJWFHEZE4opKRNvnapMFcMSGf3y4o4ZXV28KOIyJxQiUjbWJm/OzSMZxa0Id/fWYF67fvCzuSiMQBlYy0WdcuqTx4zQS6pacx+9Fiqg8eCTuSiHRyKhk5IQMzu/LANadTsecQ335iGfsOJ17R6HIgkehRycgJKxqaxd2Xj2PJR7u47HfvUrbzYNiRoqp8d+P29O+dEXISkfinkpF2uez0fB69cSJV+2uYfv9C3tuwM+xIUbOyvJpuXVIZntMz7CgicU8lI+121vBsnvvO2WT3zODahxczd3FZ2JGiYnVFNaMH9SY1xcKOIhL3VDLSIUOze/Dn75zF5MJs/v3ZVfx0/hrq6uP343/qG5w1W/YyJi8z7CgiCUElIx3Wu2sXHr7+DL45ZRh/fPdjrvvDEjbvis95mg1V+zl0pJ5x+SoZkWhQyUhUpKYYd1wyintmjmPF5j2c/+u3ePDNDRyJs72aleXVAIzVnoxIVIR6g0xJPFcUFXDWiGx+On8NP395Lc++X8F/fGUME4ZkRf29Dh+pp3z3oaOey0hLoSCre7vXubqimu7pqZykSX+RqFDJSNTl9enG768r4tU12/jp/DVc/t/vMXFYFteeOYQLRg8kPa3jO9C7D9Ry6e/eYdMxp0+PyevNC7dMafd6V5bv0aS/SBSpZCQwF4weyNkjsnli0SYeX7yJW558n+yeGcyaWMCsiYMZ1Kdbu9ZbV9/AzU8uZ+uew/zHV8bQq2uXT1/L7Nalha9sfb0fbN3L1ROHtHsdInI0lYwEqmdGGt86ZzjfnHISb5ZU8fh7m7jvjVLuf6OUc07OYUDvrp+OTU0xZk7IZ/zgvp8+5+48vPAjSpt8YFrFnkO8U7qTX8wcx1eLCoiW0qr9HD7SwNj83lFbp0iyU8lITKSkGOee0p9zT+nP5l0HeXJJGS+u2soHW/d+Omb/4TrmLinja5MG84MLRpLZrQtz3trIz19eS3bPDFKbHGX73tTCqBYMaNJfJAgqGYm5gqzu/PDCkfzwwpFHPb+/po57X1vHI+9+zKtrtnNlUQG/+3spl4zN5b6rx2MW7DzJ6opqeqSnclK2Jv1FokWnMEun0TMjjZ98eTTzb55MbmZX7nujlJMH9OKeK8YFXjDQuCczOi+TFE36i0SN9mSk0xmTl8mz3zmbV9dso2hIX7qnB/9teqS+gQ+37uWaMzXpLxJNKhnplFJTjIvH5sbs/Uq276emrkFX+otEmQ6XidA4HwPonmUiUaaSEQFWVuyhZ0Yaw/r1CDuKSEIJtWTM7EIzW2dmpWZ2ezOvZ5jZ05HXF5vZ0NinlGSwqmIvY/J6a9JfJMpCKxkzSwXuBy4CRgGzzGzUMcNuBHa7+wjg18DdsU0pyeCTSX9dHyMSfa2WjJndYmZ9WxvXDhOBUnff6O61wFPAjGPGzAAeiTyeB0y1WJzLKkll/fZ91NY1MDa/T9hRRBJOW/ZkBgBLzeyZyOGtaP2QzwM2N1kujzzX7Bh3rwOqgX7HrsjMZptZsZkVV1VVRSmeJItVutJfJDCtloy7/wgoBB4GbgBKzOw/zWx4wNnazN3nuHuRuxfl5OSEHUfizKqKanp1TWNIBz4iQESa16Y5GXd3YFvkTx3QF5hnZr/owHtXAE1vPpUfea7ZMWaWBmQCOzvwniKfsaqimjGDdKW/SBDaMidzq5ktA34BvAOMdfdvAxOAyzvw3kuBQjMbZmbpwFXA/GPGzAeujzyeCfwtUngiUVFb18Darft0EaZIQNpyxX8WcJm7b2r6pLs3mNmX2vvG7l5nZjcDrwKpwB/cfY2Z3QkUu/t8Gg/RPWZmpcAuGotIJGrWb99HbX0DY1UyIoFotWTc/SctvPZhR97c3V8CXjrmuR83eXwYuKIj7yHSklUVmvQXCZKu+JektrK8mt5d0xisSX+RQKhkJKmtrqhmbH5mTD5KQCQZqWQkadXU1bN2217G5ukiTJGgqGQkaa3ftp8j9a4zy0QCpJKRpLX4o8ZLrjTpLxIclYwkJXfnySVljB/chwJN+osERiUjSWnJR7vYUHWAqycODjuKSEJTyUhSemJxGb26pvGlcYPCjiKS0FQyknR2HajlldXbuPz0fLqlp4YdRyShqWQk6cxbtpna+gaunqRDZSJBU8lIUmmc8N9M0ZC+nDygV9hxRBKeSkaSynsbdvLRjgPaixGJEZWMJJUnlpSR2a0LF4/NDTuKSFJQyUjS2LG/htfWbGPmhHy6dtGEv0gsqGQkaTy/YgtH6p1ZujZGJGZUMpI01lRUM7B3V0b07xl2FJGkoZKRpFFatV8FIxJjKhlJCu7OhkqVjEisqWQkKWytPsyB2nqVjEiMqWQkKZRU7gdQyYjEmEpGkkKpSkYkFCoZSQqllfvp070L/Xqkhx1FJKmoZCQpbKjcT2H/nphZ2FFEkopKRpKCTl8WCUcoJWNmWWb2upmVRP7ue5xxr5jZHjN7IdYZJXHs3F/DrgO1DM9RyYjEWlh7MrcDC9y9EFgQWW7OPcC1MUslCUmT/iLhCatkZgCPRB4/Alza3CB3XwDsi1UoSUylVY0lU6jPjxGJubBKZoC7b4083gYM6MjKzGy2mRWbWXFVVVXH00lCWbZpN70y0sjt3TXsKCJJJy2oFZvZX4GBzbx0R9MFd3cz8468l7vPAeYAFBUVdWhdkliqDx3hpVVb+cr4fFJSdGaZSKwFVjLuPu14r5nZdjPLdfetZpYLVAaVQ5Lbs8vLOXykga/pkzBFQhHW4bL5wPWRx9cDz4eUQxKYuzN3SRnj8jMZk5cZdhyRpBRWydwFnGdmJcC0yDJmVmRmD30yyMzeBv4ETDWzcjO7IJS0EpeWbdrN+u37tRcjEqLADpe1xN13AlObeb4Y+EaT5SmxzCWJZe7iMnplpPHlUweFHUUkaemKf0lIew7W8sKqrVw6Po/u6aH8LiUiqGQkQc1bVk5tXQNX61CZSKhUMpJwPpnwHz+4D5/L7R12HJGkppKRhLP4o11srDrA1RO1FyMSNpWMJJw/vvMxvbqm8aVxmvAXCZtKRhLKis17eGXNNv757GF0S08NO45I0lPJSMJwd+5+eS39eqQz+wsnhR1HRFDJSAJ5q2QH723cyS1fHEHPDJ22LNIZqGQkITQ0OHe9vJaCrG5cPWlI2HFEJEIlIwnhLyu38OHWvdx2/imkp+nbWqSz0P9GiXu1dQ388rV1jMrtzZd1RplIp6KSSXK/f2sjSz/eFXaMDpm7eBObdx3i3y4aqc+MEelkVDJJ7q5X1vLmuvj9NNH6BmfOWxuZOCyLLxRmhx1HRI6hkpG49vd1lWypPsw/nzUUM+3FiHQ2KpkkVn3wCA3uxPPP5rmLy8jplcG0UQPCjiIizVDJJKn6BueWp94nLcU4L05/QG/Zc4g31lXy1aJ8uqTqW1mkM9IVa0nqnlfX8db6Kn5+2VjG5fcJO067PLV0Mw5cdYZuhCnSWenXvyRUW9fAnLc2cOlpg5gVp3cqrqtv4OmlZXyhMIeCrO5hxxGR41DJJKEGdxocThkYv5+18re1lWzfW6MPJRPp5HS4LIHtPXyE2Y8Ws/dQ3VHPN7iHlCh65i4pY0DvDKaO7B92FBFpgUomgXVJSWHzrkNU7DnEhCF96ds9/dPXhvbrwbkjc0JM136bdx3kzfVV3HLuCNI04S/SqalkEli39FQevHYCMx94l1Qzfve10xPivl5PLS3DgCvjdD5JJJnE/08cadGYvEzuvnwcSz7exfT7FrJsU3zfQmZ/TR1PLtnMuaf0J69Pt7DjiEgrQikZM8sys9fNrCTyd99mxpxmZu+Z2RozW2lmV4aRNRHMOC2Ph64rYu+hI1z+3+/xP/+8ij0Ha8OO1S6/f2sjuw7UcsvUwrCjiEgbhLUnczuwwN0LgQWR5WMdBK5z99HAhcBvzCw+L+joBKaNGsDr3z+Hb04ZxjPFm5l675ss3rgz7FgnpGpfDQ+9vZGLxw7ktAJ9K4jEg7BKZgbwSOTxI8Clxw5w9/XuXhJ5vAWoBOJzprqT6JGRxh2XjGL+zWeT2b0LNz2+jM27DoYdq83u+1sJh+sauO38U8KOIiJtFFbJDHD3rZHH24AW72tiZhOBdGBD0MGSwehBmfzh+jOob3BmP7aMQ7X1YUdqVdnOg8xdUsaVZxRwUk7PsOOISBsFVjJm9lczW93MnxlNx7m7A8e9cMPMcoHHgH9294bjjJltZsVmVlxVFb+3rY+lodk9+O2s8azdtpcfzPsH3smvnbn39XWkphi3ai5GJK4Edgqzu0873mtmtt3Mct19a6REKo8zrjfwInCHuy9q4b3mAHMAioqKOvdPy07kn07pzw8vGMndr6xlTF4mN50zPOxIzVpdUc3zK7bw3XOHM6B317DjiMgJCOtw2Xzg+sjj64Hnjx1gZunAs8Cj7j4vhtmSyk3nnMQl43K5+5W1PPd+Rafbo6mta+A/X/qQPt278K1OWoIicnxhlcxdwHlmVgJMiyxjZkVm9lBkzFeBLwA3mNmKyJ/TwombuMyMe2aO47SCPvzL0yu48ZHiTnMywK4DtVz78GLe3bCTH14wkt5du4QdSUROkHW231w7qqioyIuLi8OOEXfq6hv447sf86vX1+MOt04r5MbJw0L7nJb12/dx4yNL2b63hl9cPo5Lx+eFkiOZmdkydy8KO4fEN5WMHKVizyF+On8Nr3+wnbw+3bh60mCuPKOA7J4ZMcuw4MPt3PrUCrqlpzLn2gmMH/yZa3UlBlQyEg0qGWnWG2sreWjhRt4p3UmXVOPisblce+YQJgzpiwX0ec3uzpy3NnLXK2sZMyiTOddNIDdTt44Ji0pGokE3yJRmnTuyP+eO7E9p5X6eWLyJecvKeX7FFkYO7MU1Zw7h0vF59MyI3rdP+e6D/PLVdTy3YguXjMvllzNPpVt6atTWLyLh0J6MtMnB2jrmr9jCo+9t4oOte+mZkcZlp+dxzZlDOHlAr3ats6HBeaukiscXbWLB2koMuHXqyXxv6ojA9pak7bQnI9GgkpET4u4sL9vD44s28eLKrdTWN3DmSVlce+ZQzh89oE0nCuw+UMuflm3m8UVllO06SHbPDGZNLOCqiYN1Z+VORCUj0aCSkXbbub+GPy0r5/FFmyjffYi0FCMlpfU9kCP1DbjDxGFZXHvmEC4YPTAhPucm0ahkJBpUMtJh9Q3Om+srWfrxbtry7ZSRlsLFY3M5ZWD7DrNJbKhkJBo08S8dlppifHHkAL44ssX7nIpIEtIxChERCYxKRkREAqOSERGRwKhkREQkMCoZEREJjEpGREQCo5IREZHAqGRERCQwKhkREQmMSkZERAKjkhERkcCoZEREJDAqGRERCYxKRkREAqOSERGRwKhkREQkMKGUjJllmdnrZlYS+btvM2OGmNlyM1thZmvM7KYwsoqISPuFtSdzO7DA3QuBBZHlY20FPu/upwGTgNvNbFAMM4qISAeFVTIzgEcijx8BLj12gLvXuntNZDEDHdoTEYk7Yf3gHuDuWyOPtwHNfji8mRWY2UpgM3C3u285zrjZZlZsZsVVVVXBJBYRkROWFtSKzeyvwMBmXrqj6YK7u5l5c+tw983AuMhhsufMbJ67b29m3BxgDkBRUVGz6xIRkdgLrGTcfdrxXjOz7WaW6+5bzSwXqGxlXVvMbDUwBZgX5agiIhKQsA6XzQeujzy+HibW76wAAAWcSURBVHj+2AFmlm9m3SKP+wKTgXUxSygiIh0WVsncBZxnZiXAtMgyZlZkZg9FxnwOWGxm/wDeBH7p7qtCSSsiIu0S2OGylrj7TmBqM88XA9+IPH4dGBfjaCIiEkU6LVhERAKjkhERkcCoZEREJDAqGRERCYxKRkREAqOSERGRwKhkREQkMCoZEREJjEpGREQCo5IREZHAqGRERCQwKhkREQmMSkZERAKjkhERkcCoZEREJDAqGRERCYxKRkREAqOSERGRwKhkREQkMCoZEREJjEpGREQCo5IREZHAqGRERCQwKhkREQlMKCVjZllm9rqZlUT+7tvC2N5mVm5m98Uyo4iIdFxYezK3AwvcvRBYEFk+np8Bb8UklYiIRFVYJTMDeCTy+BHg0uYGmdkEYADwWoxyiYhIFKWF9L4D3H1r5PE2GovkKGaWAtwLXANMa2llZjYbmB1ZrDGz1VHM2hlkAzvCDhFFibY9kJjbdErYAST+BVYyZvZXYGAzL93RdMHd3cy8mXHfAV5y93Iza/G93H0OMCfyvsXuXtS+1J1Tom1Tom0PJO42hZ1B4l9gJePux937MLPtZpbr7lvNLBeobGbY54EpZvYdoCeQbmb73b2l+RsREelEwjpcNh+4Hrgr8vfzxw5w96998tjMbgCKVDAiIvElrIn/u4DzzKyExvmWuwDMrMjMHurguud0NFwnlGjblGjbA9omkWaZe3PTISIiIh2nK/5FRCQwKhkREQlM3JdMIt6ipi3bZGanmdl7ZrbGzFaa2ZVhZG2JmV1oZuvMrNTMPnPShpllmNnTkdcXm9nQ2Kc8MW3Ypu+b2QeRf5MFZjYkjJxt1dr2NBl3uZm5mSXUadoSvLgvGRLzFjVt2aaDwHXuPhq4EPiNmfWJYcYWmVkqcD9wETAKmGVmo44ZdiOw291HAL8G7o5tyhPTxm16n8YzIccB84BfxDZl27VxezCzXsCtwOLYJpREkAglk4i3qGl1m9x9vbuXRB5vofFao5yYJWzdRKDU3Te6ey3wFI3b1VTT7ZwHTLXWrrwNV6vb5O5vuPvByOIiID/GGU9EW/6NoPGXs7uBw7EMJ4khEUrmRG5Rc1ssg3VAq9vUlJlNBNKBDUEHOwF5wOYmy+WR55od4+51QDXQLybp2qct29TUjcDLgSbqmFa3x8xOBwrc/cVYBpPEEdbFmCcklreoiZUobNMn68kFHgOud/eG6KaU9jKza4Ai4Jyws7RX5JezXwE3hBxF4lhclEwi3qImCtuEmfUGXgTucPdFAUVtrwqgoMlyfuS55saUm1kakAnsjE28dmnLNmFm02j8ZeEcd6+JUbb2aG17egFjgL9HfjkbCMw3s+nurvuaSZskwuGyT25RAy3cosbdB7v7UBoPmT3ayW9R0+o2mVk68CyN2zIvhtnaailQaGbDIlmvonG7mmq6nTOBv3nnvjq41W0ys/HAg8B0d2/2l4NOpMXtcfdqd89296GR/zuLaNwuFYy0WSKUTJC3qAlLW7bpq8AXgBvMbEXkz2nhxP2syBzLzcCrwIfAM+6+xszuNLPpkWEPA/3MrBT4Pi2fGRi6Nm7TPTTuLf8p8m9ybLF2Gm3cHpEO0W1lREQkMImwJyMiIp2USkZERAKjkhERkcCoZEREJDAqGRERCYxKRkREAqOSERGRwKhkJGbM7IzI56x0NbMekc/CGRN2LhEJji7GlJgys/8DdAW6AeXu/vOQI4lIgFQyElORe2QtpfGzSc5y9/qQI4lIgHS4TGKtH4339upF4x6NiCQw7clITEVuGPkUMAzIdfebQ44kIgGKi8+TkcRgZtcBR9x9buTz5d81sy+6+9/CziYiwdCejIiIBEZzMiIiEhiVjIiIBEYlIyIigVHJiIhIYFQyIiISGJWMiIgERiUjIiKB+X8z34BsjWwClwAAAABJRU5ErkJggg==\n","text/plain":["
"]},"metadata":{"needs_background":"light"}},{"output_type":"stream","name":"stdout","text":["This stroke: 89\n","All strokes: min 32 max 145 avg 94.526\n"]}]},{"cell_type":"code","metadata":{"id":"3FVPj-eqjvoB","executionInfo":{"status":"ok","timestamp":1638746658017,"user_tz":480,"elapsed":192,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}}},"source":["import math\n","import numpy as np\n","import PIL\n","\n","FIXED_POINT = 4096\n","\n","def mul_fp(a, b):\n"," return (a * b) // FIXED_POINT\n","\n","def div_fp(a, b):\n"," if b == 0:\n"," b = 1\n"," return (a * FIXED_POINT) // b\n","\n","def float_to_fp(a):\n"," return math.floor(a * FIXED_POINT)\n","\n","def norm_to_coord_fp(a, range_fp, half_size_fp):\n"," a_fp = float_to_fp(a)\n"," norm_fp = div_fp(a_fp, range_fp)\n"," return mul_fp(norm_fp, half_size_fp) + half_size_fp\n","\n","def round_fp_to_int(a):\n"," return math.floor((a + (FIXED_POINT / 2)) / FIXED_POINT)\n","\n","def gate(a, min, max):\n"," if a < min:\n"," return min\n"," elif a > max:\n"," return max\n"," else:\n"," return a\n","\n","def rasterize_stroke(stroke_points, x_range, y_range, width, height):\n"," num_channels = 3\n"," buffer_byte_count = height * width * num_channels\n"," buffer = bytearray(buffer_byte_count)\n","\n"," width_fp = width * FIXED_POINT\n"," height_fp = height * FIXED_POINT\n"," half_width_fp = width_fp / 2\n"," half_height_fp = height_fp / 2\n"," x_range_fp = float_to_fp(x_range)\n"," y_range_fp = float_to_fp(y_range)\n","\n"," t_inc_fp = FIXED_POINT // len(stroke_points)\n","\n"," one_half_fp = (FIXED_POINT / 2)\n","\n"," for point_index in range(len(stroke_points) - 1):\n"," start_point = stroke_points[point_index]\n"," end_point = stroke_points[point_index + 1]\n"," start_x_fp = norm_to_coord_fp(start_point[\"x\"], x_range_fp, half_width_fp)\n"," start_y_fp = norm_to_coord_fp(-start_point[\"y\"], y_range_fp, half_height_fp)\n"," end_x_fp = norm_to_coord_fp(end_point[\"x\"], x_range_fp, half_width_fp)\n"," end_y_fp = norm_to_coord_fp(-end_point[\"y\"], y_range_fp, half_height_fp)\n"," delta_x_fp = end_x_fp - start_x_fp\n"," delta_y_fp = end_y_fp - start_y_fp\n","\n"," t_fp = point_index * t_inc_fp\n"," if t_fp < one_half_fp:\n"," local_t_fp = div_fp(t_fp, one_half_fp)\n"," one_minus_t_fp = FIXED_POINT - local_t_fp\n"," red = round_fp_to_int(one_minus_t_fp * 255)\n"," green = round_fp_to_int(local_t_fp * 255)\n"," blue = 0\n"," else:\n"," local_t_fp = div_fp(t_fp - one_half_fp, one_half_fp)\n"," one_minus_t_fp = FIXED_POINT - local_t_fp\n"," red = 0\n"," green = round_fp_to_int(one_minus_t_fp * 255)\n"," blue = round_fp_to_int(local_t_fp * 255)\n"," red = gate(red, 0, 255)\n"," green = gate(green, 0, 255)\n"," blue = gate(blue, 0, 255)\n","\n"," if abs(delta_x_fp) > abs(delta_y_fp):\n"," line_length = abs(round_fp_to_int(delta_x_fp))\n"," if delta_x_fp > 0:\n"," x_inc_fp = 1 * FIXED_POINT\n"," y_inc_fp = div_fp(delta_y_fp, delta_x_fp)\n"," else:\n"," x_inc_fp = -1 * FIXED_POINT\n"," y_inc_fp = -div_fp(delta_y_fp, delta_x_fp)\n"," else:\n"," line_length = abs(round_fp_to_int(delta_y_fp))\n"," if delta_y_fp > 0:\n"," y_inc_fp = 1 * FIXED_POINT\n"," x_inc_fp = div_fp(delta_x_fp, delta_y_fp)\n"," else:\n"," y_inc_fp = -1 * FIXED_POINT\n"," x_inc_fp = -div_fp(delta_x_fp, delta_y_fp)\n"," for i in range(line_length + 1):\n"," x_fp = start_x_fp + (i * x_inc_fp)\n"," y_fp = start_y_fp + (i * y_inc_fp)\n"," x = round_fp_to_int(x_fp)\n"," y = round_fp_to_int(y_fp)\n"," if (x < 0) or (x >= width) or (y < 0) or (y >= height):\n"," continue\n"," buffer_index = (y * width * num_channels) + (x * num_channels)\n"," buffer[buffer_index + 0] = red\n"," buffer[buffer_index + 1] = green\n"," buffer[buffer_index + 2] = blue\n"," \n"," np_buffer = np.frombuffer(buffer, dtype=np.uint8).reshape(height, width, num_channels)\n","\n"," return np_buffer"],"execution_count":9,"outputs":[]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/","height":529},"id":"sOaxOIjRskJg","executionInfo":{"status":"ok","timestamp":1638746717413,"user_tz":480,"elapsed":165,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"9f3e55ad-2c1e-4441-cdc8-fabc272e3b50"},"source":["raster = rasterize_stroke(shuffled_strokes[0][\"strokePoints\"], 0.5, 0.5, 32, 32)\n","img = PIL.Image.fromarray(raster).resize((512, 512), PIL.Image.NEAREST)\n","display(img)"],"execution_count":10,"outputs":[{"output_type":"display_data","data":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAIAAAB7GkOtAAAHHUlEQVR4nO3dIWydZRSA4ZatDUuLRJERDJjN4BDMgIYEiWdmKAwGi8FhhmEaTZgGAwYDZhgQJDSZwtECuWUJimRiITlp7/3v3fs8+tzc494c8397ewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAxf7SC8AueenX2fzp8Wz+cDWbf/jCbB4e98zSCwCwDAEAiBIAgCgBAIgSAIAoAQCIEgCAKAEAiBIAgCgBAIgSAIAoAQCIEgCAKAEAiBIAgKirSy8AS7rxYDa/Op/N//78bP7an7N5uAgXAECUAABECQBAlAAARAkAQJQAAEQJAECUAABECQBAlAAARAkAQJQAAEQJAECUAABECQBA1P7SC8D/ef3b2fz5wWz++9dm89vmyj+z+UdeAOExLgCAKAEAiBIAgCgBAIgSAIAoAQCIEgCAKAEAiBIAgCgBAIgSAIAoAQCIEgCAKAEAiBIAgChfB2erHa5m89/dWs8e2+rR3pXxL+A/LgCAKAEAiBIAgCgBAIgSAIAoAQCIEgCAKAEAiBIAgCgBAIgSAIAoAQCIEgCAKAEAiBIAgCjvAbBRb301m7//5nr2eGpcHX7f/69nZ/PX/p7Ns1NcAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUd4DYKMOV0tvELc6HP7AewBPMxcAQJQAAEQJAECUAABECQBAlAAARAkAQJQAAEQJAECUAABECQBAlAAARAkAQJQAAEQJAECU9wDYqOPTpTeIG78HwNPMBQAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAEOU9ADbq6Gw2/97ns/l7t2fzOd4D4DEuAIAoAQCIEgCAKAEAiBIAgCgBAIgSAIAoAQCIEgCAKAEAiBIAgCgBAIgSAIAoAQCIEgCAKO8BsFGfvT+bv3N3PXtknR8svQFbxAUAECUAAFECABAlAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAECUAAFECABC1v/QCcJk+/GQ2f3A+mz8+nc0fnc3mr5/M5t/5cja/9/PLs/lXfhn+AbvEBQAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAEOU9ACh5cGM2f/On9ezBVnABAEQJAECUAABECQBAlAAARAkAQJQAAEQJAECUAABECQBAlAAARAkAQJQAAEQJAECUAABEXV16AeACfnh1Nn/zx/XswU5yAQBECQBAlAAARAkAQJQAAEQJAECUAABECQBAlAAARAkAQJQAAEQJAECUAABECQBAlAAARHkPAHbZ+cHSG7DDXAAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAECUAAFHeA4BdtjpcegN2mAsAIEoAAKIEACBKAACiBAAgSgAAogQAIEoAAKIEACBKAACiBAAgSgAAogQAIEoAAKIEACDKewCwTb5+YzZ/65v17EGCCwAgSgAAogQAIEoAAKIEACBKAACiBAAgSgAAogQAIEoAAKIEACBKAACiBAAgSgAAogQAIMp7AGzW8R+z+dPn1rPHpky/739+sJ494AlcAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUd4D4GKu/zabP9nx7/tPnR3N5t++v5494AlcAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUQIAECUAAFECABAlAABRAgAQJQAAUd4D4GJOXpzNf/zRbP7obDb/waez+akv3p3Nr1br2QMugQsAIEoAAKIEACBKAACiBAAgSgAAogQAIEoAAKIEACBKAACiBAAgSgAAogQAIEoAAKIEACBqf+kF4FLdvTObPxx+r//2vdk8bDEXAECUAABECQBAlAAARAkAQJQAAEQJAECUAABECQBAlAAARAkAQJQAAEQJAECUAABECQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDQv3ZkRy9r0+kjAAAAAElFTkSuQmCC\n","text/plain":[""]},"metadata":{}}]},{"cell_type":"code","metadata":{"id":"o-FOVdFpgkdf","executionInfo":{"status":"ok","timestamp":1638746921132,"user_tz":480,"elapsed":150,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}}},"source":["from pathlib import Path\n","import shutil\n","\n","X_RANGE = 0.6\n","Y_RANGE = 0.6\n","\n","def ensure_empty_dir(dirname):\n"," dirpath = Path(dirname)\n"," if dirpath.exists() and dirpath.is_dir():\n"," shutil.rmtree(dirpath)\n"," dirpath.mkdir()\n","\n","def augment_points(points, move_range, scale_range, rotate_range):\n"," move_x = np.random.uniform(low=-move_range, high=move_range)\n"," move_y = np.random.uniform(low=-move_range, high=move_range)\n"," scale = np.random.uniform(low=1.0-scale_range, high=1.0+scale_range)\n"," rotate = np.random.uniform(low=-rotate_range, high=rotate_range)\n","\n"," x_axis_x = math.cos(rotate) * scale\n"," x_axis_y = math.sin(rotate) * scale\n","\n"," y_axis_x = -math.sin(rotate) * scale\n"," y_axis_y = math.cos(rotate) * scale\n","\n"," new_points = []\n"," for point in points:\n"," old_x = point[\"x\"]\n"," old_y = point[\"y\"]\n"," new_x = (x_axis_x * old_x) + (x_axis_y * old_y) + move_x\n"," new_y = (y_axis_x * old_x) + (y_axis_y * old_y) + move_y\n"," new_points.append({\"x\": new_x, \"y\": new_y})\n","\n"," return new_points\n","\n","def save_strokes_as_images(strokes, root_folder, width, height, augment_count):\n"," ensure_empty_dir(root_folder)\n"," labels = set()\n"," for stroke in strokes:\n"," labels.add(stroke[\"label\"].lower())\n"," for label in labels:\n"," label_path = Path(root_folder, label)\n"," ensure_empty_dir(label_path)\n","\n"," label_counts = {}\n"," for stroke in strokes:\n"," points = stroke[\"strokePoints\"]\n"," label = stroke[\"label\"].lower()\n"," if label == \"\":\n"," raise Exception(\"Missing label for %s:%d\" % (stroke[\"filename\"], stroke[\"index\"]))\n"," if label not in label_counts:\n"," label_counts[label] = 0\n"," label_count = label_counts[label]\n"," label_counts[label] += 1\n"," raster = rasterize_stroke(points, X_RANGE, Y_RANGE, width, height)\n"," image = PIL.Image.fromarray(raster)\n"," image.save(Path(root_folder, label, str(label_count) + \".png\"))\n"," for i in range(augment_count):\n"," # Note: no move augmentation as the stroke should be more or less\n"," # centered within the raster\n"," augmented_points = augment_points(points, 0.0, 0.1, 0.3)\n"," raster = rasterize_stroke(augmented_points, X_RANGE, Y_RANGE, width, height)\n"," image = PIL.Image.fromarray(raster)\n"," image.save(Path(root_folder, label, str(label_count) + \"_a\" + str(i) + \".png\"))\n"],"execution_count":11,"outputs":[]},{"cell_type":"code","metadata":{"id":"2cmmhBwW9d_p","executionInfo":{"status":"ok","timestamp":1638747505532,"user_tz":480,"elapsed":13446,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}}},"source":["IMAGE_WIDTH = 32\n","IMAGE_HEIGHT = 32\n","\n","shuffled_strokes = list(strokes)\n","np.random.shuffle(shuffled_strokes)\n","\n","test_percentage = 10\n","validation_percentage = 10\n","train_percentage = 100 - (test_percentage + validation_percentage)\n","\n","test_count = math.floor((len(shuffled_strokes) * test_percentage) / 100)\n","validation_count = math.floor((len(shuffled_strokes) * validation_percentage) / 100)\n","test_strokes = shuffled_strokes[0:test_count]\n","validation_strokes = shuffled_strokes[test_count:(test_count + validation_count)]\n","train_strokes = shuffled_strokes[(test_count + validation_count):]\n","\n","save_strokes_as_images(test_strokes, \"test\", IMAGE_WIDTH, IMAGE_HEIGHT, 10)\n","save_strokes_as_images(validation_strokes, \"validation\", IMAGE_WIDTH, IMAGE_HEIGHT, 0)\n","save_strokes_as_images(train_strokes, \"train\", IMAGE_WIDTH, IMAGE_HEIGHT, 10)"],"execution_count":12,"outputs":[]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"9-Ttfz7LlPil","executionInfo":{"status":"ok","timestamp":1638747530290,"user_tz":480,"elapsed":3475,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"2e9daa0f-acea-4c5e-c4c3-89a7060f388a"},"source":["\n","import tensorflow as tf\n","from tensorflow import keras\n","from tensorflow.keras.utils import image_dataset_from_directory\n","\n","validation_ds = image_dataset_from_directory(\n"," directory='validation',\n"," labels='inferred',\n"," label_mode='categorical',\n"," batch_size=32,\n"," image_size=(IMAGE_WIDTH, IMAGE_HEIGHT)).prefetch(buffer_size=32)\n","\n","train_ds = image_dataset_from_directory(\n"," directory='train',\n"," labels='inferred',\n"," label_mode='categorical',\n"," batch_size=32,\n"," image_size=(IMAGE_WIDTH, IMAGE_HEIGHT)).prefetch(buffer_size=32)\n"],"execution_count":13,"outputs":[{"output_type":"stream","name":"stdout","text":["Found 100 files belonging to 10 classes.\n","Found 8800 files belonging to 10 classes.\n"]}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/","height":591},"id":"Q_vUMVmQn400","executionInfo":{"status":"ok","timestamp":1638747597760,"user_tz":480,"elapsed":1017,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"07159ba4-ee1b-4364-8776-3726db2e0595"},"source":["import matplotlib.pyplot as plt\n","\n","plt.figure(figsize=(10, 10))\n","for images, labels in train_ds.take(1):\n"," for i in range(9):\n"," ax = plt.subplot(3, 3, i + 1)\n"," ax.set_title(f\"{np.argmax(labels[i])}\")\n"," plt.imshow(images[i].numpy().astype(\"uint8\"))\n"," plt.axis(\"off\")"],"execution_count":15,"outputs":[{"output_type":"display_data","data":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAAjgAAAI+CAYAAACxLHDrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAaBklEQVR4nO3df7CmZXkf8Otyz7IHWAhYY0JJLYbakGgi1djEGtSJRqKJTDUkJUXFtFgFNyoJUdNi1cqUqFgx8kODCqYkHX9RRg21GDKp4qiBph2NlaipJmWAiLJ2Wdhz2MW7f+xSd/d+dvcs+77v857rfD4zOwPf9xyeaxwf9svNdW6ytRYAAJU8bOwBAAAmTcEBAMpRcACAchQcAKAcBQcAKEfBAQDKUXAAgHIUnCnKzMdk5lJmXjP2LDCmzDwhM6/PzM2ZeWdmXpqZC2PPBWPJzE2ZeUtmLmfm1WPPU5GCM12XRcTNYw8Bc+DyiPhmRBwXESdHxNMi4txRJ4Jx3R4RF0bE+8YepCoFZ0oy84yI+E5E3Dj2LDAHHh0RH2ytLbXW7oyIT0TEY0eeCUbTWru2tXZdRHx77FmqUnCmIDOPjoh/FxG/MfYsMCcuiYgzMvOIzDw+Ip4dO0sOwFQoONPxpoh4b2vttrEHgTnxqdh5YrMlIm6LiFsi4rpRJwJKU3AmLDNPjohnRsTbx54F5kFmPix2ntZcGxFHRsQjIuLYiHjzmHMBtfkphsl7ekScEBF/k5kRERsjYl1m/lhr7QkjzgVjeXhEPCoiLm2tLUfEcmZeFTsXLF896mRAWU5wJu/3IuLE2PmTIidHxLsi4o8i4tQxh4KxtNa+FRFfj4hzMnMhM4+JiLMi4gvjTgbj2fUuLEbEutj5D8GLrk6YLAVnwlpr97XW7nzwV0RsjYil1tpdY88GI3p+RPx8RNwVEV+LiO0Rcd6oE8G4LoiIbRHx2oh4wa4/vmDUiYrJ1trYMwAATJQTHACgHAUHAChHwQEAylFwAIByFBwAoJz9/sx9ZvoRK0bTWsuxZ9ibd4IxeSdgT/t7J5zgAADlKDgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUoOABAOQoOAFCOggMAlKPgAADlKDgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUoOABAOQoOAFCOggMAlKPgAADlKDgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUoOABAOQtjD8A+/Ndn9dmpN8x+DgBYhZzgAADlKDgAQDkKDgBQjoIDAJRjyXge3HZ8n918xOzngGn7mU/32THf6bOPP3f6swClOcEBAMpRcACAchQcAKAcBQcAKMeS8azdfWyfbd8+kK2f/iwwa7f8ZJ/94sf77AX/sc+ueeHk5wHKcoIDAJSj4AAA5Sg4AEA5Cg4AUE621vb9Yea+P+ShuWdjn330tD478w+nP8uca63l2DPszTsxIy++qs8WdvTZe14y/VnmiHeinudd22cblvvs6C0r+7p3vuLQZ1pN9vdOOMEBAMpRcACAchQcAKAcBQcAKMdNxtO0tKHP1t/XZ24thj1d/Wt99rIrZj8HTNkNz+qzoeXhu//O9GepxgkOAFCOggMAlKPgAADlKDgAQDmWjCfkYQ/02Xdjex9eNbA8OXRDK6xyV57dZ0P/V19cWln2vKEQVrl7F9f12caB31A4aE5wAIByFBwAoBwFBwAoR8EBAMqxZDwh6wf2iZcXv9uHVwzcWnz2eyc/EMzQW8/vs6WBneBfv/RQnnJeH53/1j67+LcO5SEwW1uOHgg3z3yMipzgAADlKDgAQDkKDgBQjoIDAJRjyfgh2HhPn21dnP0cMIY3XdBnOwZuKD60heIBF7xpZQ+G1WR5w9gTlOUEBwAoR8EBAMpRcACAchQcAKAcS8YH8Mi/7bPtA7cWD7riZQPfPHCTMawiQzuRr7twBg++8HV9NrR4DPPqG3+/z47769nPsUY4wQEAylFwAIByFBwAoBwFBwAox5Lxbv7BV/ts28BC8Td/YIV/waGF4le886BmgnmzNE+3dm9YHnsCWDm3Fs+UExwAoBwFBwAoR8EBAMpRcACAciwZ72b9wELxs/9Ln614TditxRS0Y+DvGi+7os/edc6EH/z2V/XZ0o4JPwSowgkOAFCOggMAlKPgAADlKDgAQDmWjHfz5R8byAa+7jW/02dvvviuPtx+8SHPBPPmkvP67Owr+2zii8cLAwvFvz3wMsK8cpPxTDnBAQDKUXAAgHIUHACgHAUHACgnW2v7/jBz3x+yp6f9aZ897i+66C1HbOqyI+7rv3XTZROYaZVrreXYM+xtzb0TN/9kny0t9tnQ9cZDXzeUbd24sq97yXv6bI3xTqwiQ+/Ok26Z/RzF7e+dcIIDAJSj4AAA5Sg4AEA5Cg4AUI6bjCflvz29z/7R27vo1W+d/ijwkHzxcX3245Ndijz9Q3324RdO9BEAEeEEBwAoSMEBAMpRcACAchQcAKAcS8bTdMl5Y08Aw75+Qp/tWJr6Y4cuPP7Fj/XZx5879VFgupY3jD3BmucEBwAoR8EBAMpRcACAchQcAKAcS8awFi3s6LNHf2Pqj73ueX32zE9O/bEwe5aMR+cEBwAoR8EBAMpRcACAchQcAKAcS8awFi1O/9bilRq63Xho8fiPf276s8DEWDIenRMcAKAcBQcAKEfBAQDKUXAAgHIsGcNaNLRkvH3gbwfrB248nrClxT773JOn/liYnPe/qM9e/NaBL/yBqY/C9zjBAQDKUXAAgHIUHACgHAUHACjHkjGsRUdt7bPWRwvb+2zH+smOMnSTMawqW47us1e/pc/On/4ofI8THACgHAUHAChHwQEAylFwAIBysrWBzcIHP8zc94cwZa21HHuGva21d2JxW58tDFxuvPWoh/6Mk77cZ7f+6EP/61XmnYA97e+dcIIDAJSj4AAA5Sg4AEA5Cg4AUI4lY+aWhcr5dMzmPhtaPB7KFpf67BuPPvSZ1grvBOzJkjEAsKYoOABAOQoOAFCOggMAlGPJmLlloRL25J2APVkyBgDWFAUHAChHwQEAylFwAIByFBwAoBwFBwAoR8EBAMpRcACAchQcAKAcBQcAKEfBAQDKUXAAgHIUHACgHAUHAChHwQEAylFwAIByFBwAoBwFBwAoR8EBAMrJ1trYMwAATJQTHACgHAUHAChHwQEAylFwAIByFBwAoBwFBwAoR8EBAMpRcACAchQcAKAcBQcAKEfBAQDKUXAAgHIUHACgHAUHAChHwQEAylFwAIByFJwpyMxrMvOOzNySmV/JzLPHngnGlJmbMvOWzFzOzKvHngfGlpknZOb1mbk5M+/MzEszc2HsuSpRcKbjoog4obV2dEScFhEXZuYTR54JxnR7RFwYEe8bexCYE5dHxDcj4riIODkinhYR5446UTEKzhS01r7UWlt+8E93/TpxxJFgVK21a1tr10XEt8eeBebEoyPig621pdbanRHxiYh47MgzlaLgTElmXp6Z90XErRFxR0RcP/JIAMyPSyLijMw8IjOPj4hnx86Sw4QoOFPSWjs3Io6KiFMi4tqIWN7/dwCwhnwqdp7YbImI2yLiloi4btSJilFwpqi19kBr7aaI+KGIOGfseQAYX2Y+LHae1lwbEUdGxCMi4tiIePOYc1Wj4MzGQtjBAWCnh0fEoyLi0tbacmvt2xFxVUQ8Z9yxalFwJiwzH5mZZ2Tmxsxcl5mnRsSvRsSNY88GY8nMhcxcjIh1EbEuMxf9SCxrVWvtWxHx9Yg4Z9e7cUxEnBURXxh3sloUnMlrsfNfR90WEZsj4uKIeFVr7aOjTgXjuiAitkXEayPiBbv++IJRJ4JxPT8ifj4i7oqIr0XE9og4b9SJisnW2tgzAABMlBMcAKAcBQcAKEfBAQDKUXAAgHIUHACgnP3eQ5GZfsSK0bTWcuwZ9uadYEzeCdjT/t4JJzgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUoOABAOQoOAFCOggMAlKPgAADlKDgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUoOABAOQoOAFCOggMAlKPgAADlKDgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUoOABAOQoOAFCOggMAlKPgAADlKDgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUsjD1AZcuH9dmG+2c/B8yzs6/ss5e+u8/+7u19dvxABqvKmdf02eLSyrLLNk1+nkKc4AAA5Sg4AEA5Cg4AUI6CAwCUk621fX+Yue8P2cPv/nqfbT62z+49ss/uH1hGvuS8Q59ptWut5dgz7M07MXk/e2Of/ckzZj/HauCdWOWOvbvPnnVDn33gjD575SV9tn57n138Wwc/1yq2v3fCCQ4AUI6CAwCUo+AAAOUoOABAOW4ynpBXvHOyf71zL+uzoWXklS4tf+T0Q58JpmFoGR9K2vzwLnrPxv7Lzh763ne8qs9ee9Ehj1SZExwAoBwFBwAoR8EBAMpRcACActxkXNBzP9pnHztt9nMcKre21nPSl/vs2M199tl/Mv1ZViPvxOp26cv7bNPAD5Qckje8fiB744QfMj/cZAwArCkKDgBQjoIDAJSj4AAA5bjJeJX72Rv77GPPmP0csBJLi31moZiKLnllny0szeDBi7N4yOrgBAcAKEfBAQDKUXAAgHIUHACgHEvGc+qnPtdn67f32WFbpz8LTMq2w8eeAGZjaKH+Ve+YwYOHlowv/s0+O/9t059lZE5wAIByFBwAoBwFBwAoR8EBAMqxZDwpO9b12b1H9tn9h60o+/z29Sv73lO+uoLhYD5YMmat2DHW765Dm8xD1yqvAU5wAIByFBwAoBwFBwAoR8EBAMqxZHwAh9/XZ0O7vj/8vx/osq/+wy1TmGgvf/HYPhsa8An/Y/qzwG4OW+6zLRtmPweMYbQl43f/qz576SyuUJ4/TnAAgHIUHACgHAUHAChHwQEAyrFkfADbjljZ1412n/DjvtRnn//Hffbpn+mzU26a/Dywy/3rBm73jn4ZHyqaya3d739Rn+3YMYMHrw5OcACAchQcAKAcBQcAKEfBAQDKsWRc0daNfbZx6+znYO3YemSfLdw7+zlgTkz8JuMP/MrAQwYWis/6/Qk/ePVyggMAlKPgAADlKDgAQDkKDgBQjiXjiu4dWPh8xp/Mfg7WjsFrWy0Zs3a97alP6sNPLfbZ0LuzNPB1QwvF/+yDBz/YGuIEBwAoR8EBAMpRcACAchQcAKAcS8ar3Yd/qc9O+8js52BtG1wyhjXiK4/ps6WlLnr5n93cZZdtmsZARDjBAQAKUnAAgHIUHACgHAUHACjHkvE8eP+L+mz99pV97+n/abKzwEMxdPMqrBULA7cM/8QXu+iygW996bv67N0vO/SRcIIDABSk4AAA5Sg4AEA5Cg4AUI4l49393A199slnTfYZV57dZ2e9Z7LPgFnbfGyfPeKuPvvW909/FpimO36wz7YPLBmv0NBC8b8c+C3hvQO/dbB/TnAAgHIUHACgHAUHAChHwQEAyrFkvLvPPrnP/sV7++ykW/ts6Obhw+7vs5dcfvBzwbz7qxP7zEIxFQ3dWnzcnRN9xA6/M0+EExwAoBwFBwAoR8EBAMpRcACAcrK1tu8PM/f9IUxZay3HnmFv3gnG5J2YA/ds7LOjtk79sWde02dDy8gfOGPqo8yV/b0TTnAAgHIUHACgHAUHAChHwQEAyrFkzNyyUAl78k7MgW2LfXb40uzniIjnf6TPhi7Vr7x4bMkYAFhTFBwAoBwFBwAoR8EBAMqxZMzcslAJe/JOjG9hYIn38G19ds/R059lyHP+qM+u/4XZzzErlowBgDVFwQEAylFwAIByFBwAoJyB/9g6ADBkx/o+W7i7z467vc8WBy48HsqGlpYXdqwsWxrnUuW55AQHAChHwQEAylFwAIByFBwAoBw3GTO33NoKe/JOrG4/+r/6bMfAj/oMLR5/8ScmP08FbjIGANYUBQcAKEfBAQDKUXAAgHIsGTO3LFTCnrwTsCdLxgDAmqLgAADlKDgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUoOABAOQoOAFCOggMAlKPgAADlZGv+S/cAQC1OcACAchQcAKAcBQcAKEfBAQDKUXAAgHIUHACgHAUHAChHwQEAylFwAIByFBwAoBwFBwAoR8EBAMpRcACAchQcAKAcBQcAKEfBAQDKUXCmIDP/NDOXMnPrrl9/OfZMMKbM3JSZt2TmcmZePfY8MLbMvCYz78jMLZn5lcw8e+yZqlFwpmdTa23jrl8/MvYwMLLbI+LCiHjf2IPAnLgoIk5orR0dEadFxIWZ+cSRZypFwQGmrrV2bWvtuoj49tizwDxorX2ptbb84J/u+nXiiCOVo+BMz0WZ+a3M/ExmPn3sYQCYL5l5eWbeFxG3RsQdEXH9yCOVouBMx2si4ocj4viI+L2I+FhmauYA/H+ttXMj4qiIOCUiro2I5f1/BwdDwZmC1trnW2v3tNaWW2vvj4jPRMRzxp4LgPnSWnugtXZTRPxQRJwz9jyVKDiz0SIixx4CgLm1EHZwJkrBmbDMPCYzT83MxcxcyMwzI+KpEfGJsWeDsex6FxYjYl1ErHvw/Rh7LhhDZj4yM8/IzI2ZuS4zT42IX42IG8eerZJsrY09QymZ+f2xc1HspIh4IHYuj72utfbJUQeDEWXmGyLi9XvFb2ytvWH208C4dv0+8eGIeHzsPGj464j43dbalaMOVoyCAwCU419RAQDlKDgAQDkKDgBQjoIDAJSj4AAA5ez3HorM9CNWjKa1NneXI3onGJN3Ava0v3fCCQ4AUI6CAwCUo+AAAOUoOABAOQoOAFCOggMAlKPgAADlKDgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUoOABAOQoOAFCOggMAlKPgAADlKDgAQDkKDgBQjoIDAJSj4AAA5Sg4AEA5Cg4AUI6CAwCUo+AAAOUoOABAOQoOAFDOwtgDAGvHsXf32eaHz34OoD4nOABAOQoOAFCOggMAlKPgAADlWDIGZmbz9w39M9V3Zz4HUJ8THACgHAUHAChHwQEAylFwAIByLBkDs7Pl6IHwOzMfA6jPCQ4AUI6CAwCUo+AAAOUoOABAOZaMgenYfEyf3X/Y7OcA1iQnOABAOQoOAFCOggMAlKPgAADlZGtt3x9m7vtDZu7Ks/tscanPXnjN9GeZhdZajj3D3rwTh+hv/l4X/dKf/Z8u+8jpsxhm9fFOwJ729044wQEAylFwAIByFBwAoBwFBwAox03GB/CUm/rslE/32eHb+mxoAXj99j5b2LGy7CVX9NnQdt8LBzKYua+d2GeP+qsu2vAHM5gF5sC/fWOf3Xtknw1d+L3SbOvGlT3j+l/os2qc4AAA5Sg4AEA5Cg4AUI6CAwCUY8n4ALYd3me/89uzn2Nf5u5aU3jQ8oYVfdmG5SnPAXPiKZ/ps1NvmP5zn/nJ6T9jHjnBAQDKUXAAgHIUHACgHAUHACjHkvEBDC0ZA5Nz2P1jTwCzMYuF4p/+bJ/98ZOn/9x55AQHAChHwQEAylFwAIByFBwAoBxLxgeww/9C8NC4yRim6gn/vc8O2zr7OeaVExwAoBwFBwAoR8EBAMpRcACAcqzQHsAh3WR801P6bGhreeghQ1+3fX2fPf8/H/xcMEeedPPYE8D8e9wX++zPf3z2c6wmTnAAgHIUHACgHAUHAChHwQEAysnW2r4/zNz3hwX94B19duc9j+nDlS4FP/HPD32o3X3wl1c2y1m/P9nnjqS1lmPPsLe19k4cks/9VJ/99OdnP0ch3on5tG5Hnz2wfbEP7z9sstm9R67s67Zu7LOnfrrPVqH9vRNOcACAchQcAKAcBQcAKEfBAQDKcZPxbu45aiDcNrA99vgvTH2WQb/yoZV93aUv77NNl012FgAiIuKBod9JH7i/zw5fmvosg65/dp+tgR8CcIIDAJSj4AAA5Sg4AEA5Cg4AUI4l493ce/hA3zvqntkPcjAueWWfbXrH7OeAvS1vGHsCGM+67449wfcM3W5cbKF4iBMcAKAcBQcAKEfBAQDKUXAAgHIsGe9ucCnsWzMfY58uem2f7dg++zlgJYYWG4Hp+tDpffZPPzz7OeaAExwAoBwFBwAoR8EBAMpRcACAciwZz6s3XdBn67f12flvm/4s8FC4yZi17KgtfXbP0ZN9xh/88z775T+c7DNWMSc4AEA5Cg4AUI6CAwCUo+AAAOVYMp4HQwvFr7tw9nMAMBnrJ3zL/FUv7rMzr57sM4pxggMAlKPgAADlKDgAQDkKDgBQjiXjWXv9G/psx8yngOm756ixJ4DZeNtv9NmXr+2zx2/qs8PuX1n2a1cf9FhrnRMcAKAcBQcAKEfBAQDKUXAAgHIsGR/II/+2z4aWJ7cdsbK/3vb1ffbv/83BzQSrwfKGsSeA2fjN/zD2BAxwggMAlKPgAADlKDgAQDkKDgBQTrbW9v1h5r4/XCt+5NY++8uTVva9r35zn73lNYc2zxrSWsuxZ9ibd+IgfN93+uzcy/vson89/VmK8E7Anvb3TjjBAQDKUXAAgHIUHACgHAUHACjHTcYHcvL/7LMnX9Vnh2/rs+1Lk58HVov/e0yfXTT7MYC1yQkOAFCOggMAlKPgAADlKDgAQDluMmZuubUV9uSdgD25yRgAWFMUHACgHAUHAChHwQEAylFwAIByFBwAoBwFBwAoR8EBAMpRcACAchQcAKAcBQcAKEfBAQDKUXAAgHIUHACgHAUHAChHwQEAylFwAIByFBwAoBwFBwAoR8EBAMpRcACAchQcAKAcBQcAKEfBAQDKUXAAgHIUHACgHAUHAChHwQEAylFwAIBysrU29gwAABPlBAcAKEfBAQDKUXAAgHIUHACgHAUHAChHwQEAyvl/2VZxmSyeGCkAAAAASUVORK5CYII=\n","text/plain":["
"]},"metadata":{"needs_background":"light"}}]},{"cell_type":"code","metadata":{"id":"21qi3bLAo80t","executionInfo":{"status":"ok","timestamp":1638747856480,"user_tz":480,"elapsed":184,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}}},"source":["from keras import layers\n","\n","def make_model(input_shape, num_classes):\n"," inputs = keras.Input(shape=input_shape)\n","\n"," # Entry block\n"," x = layers.Rescaling(1.0 / 255)(inputs)\n"," x = layers.Conv2D(16, 3, strides=2, padding=\"same\")(x)\n"," x = layers.BatchNormalization()(x)\n"," x = layers.Activation(\"relu\")(x)\n"," x = layers.Dropout(0.5)(x)\n","\n"," x = layers.Conv2D(32, 3, strides=2, padding=\"same\")(x)\n"," x = layers.BatchNormalization()(x)\n"," x = layers.Activation(\"relu\")(x)\n"," x = layers.Dropout(0.5)(x)\n","\n"," x = layers.Conv2D(64, 3, strides=2, padding=\"same\")(x)\n"," x = layers.BatchNormalization()(x)\n"," x = layers.Activation(\"relu\")(x)\n"," x = layers.Dropout(0.5)(x)\n","\n"," x = layers.GlobalAveragePooling2D()(x)\n"," activation = \"softmax\"\n"," units = num_classes\n","\n"," x = layers.Dropout(0.5)(x)\n"," outputs = layers.Dense(units, activation=activation)(x)\n"," return keras.Model(inputs, outputs)"],"execution_count":16,"outputs":[]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/","height":1000},"id":"7DjpCkt0qZiy","executionInfo":{"status":"ok","timestamp":1638747862714,"user_tz":480,"elapsed":822,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"eb7158b8-b866-455f-e5fb-7dee1fa25e70"},"source":["model = make_model(input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, 3), num_classes=10)\n","keras.utils.plot_model(model, show_shapes=True)"],"execution_count":17,"outputs":[{"output_type":"execute_result","data":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAAq0AAAc0CAIAAADqb6jQAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nOzdeVxTV9o48HOBkIQQCLvIIpKIiELVSgewDLVOqZURREBwa62jg9oWWXxFUBQBUdAX+IBQx2UYR6wsSsGqqC+ljLUuPztipbG1EUUE1LCH1YRwf3/c6X3zIktYb+A+37+ac26ePPdcbJ7c5RwMx3EEAAAAAFpSozoBAAAAAFAG6gAAAACAvqAOAAAAAOgL6gAAAACAvjSoToCObt26lZSURHUWAACgWpydnUNDQ6nOgnbgfAAFnj9/fu7cOaqzoMDt27dv375NdRYT2Llz56qrq6nOYszB3wk93b59+9atW1RnQUdwPoAyeXl5VKcw3vz8/BAtd3y0YBgWEhKycuVKqhMZW/B3Qk/EcQfjD84HAAAAAPQFdQAAAABAX1AHAAAAAPQFdQAAAABAX1AHAAAAAPQFdQAAk9zly5d1dXW/+eYbqhMZZZs3b8Z+t3btWsWu4uLiiIiI8+fPW1tbExusW7dOcQN3d3cul6uurj579ux79+6Nb+L/kZCQYGtry2azORyOra1tVFSURCIhe2NiYuzs7HR0dJhMpkAg2LFjR1tbmypHvnDhQkJCglwuJzcuKCggD5ChoaGSHwHGH9QBAExyk3hNUX19/aKiokePHp08eZJs3Lt3b2pqamRkpI+Pz5MnT/h8voGBQVZW1qVLl8htrl27lpeXt2zZMqFQOH/+fCpyR99///2mTZuqqqpevXoVGxubkJDg6+tL9paUlHz++eeVlZX19fXx8fEpKSnKP1ZHSWRPT08Wi7V48eLm5maixcvLq7q6+vr160uXLlUyPqAGDsZdTk4OPUfe19fX19eX6iwmMIRQTk4O1Vn0q6Ojw9nZeeRxlPw7CQwMNDMz69V44MABGxubzs5OsoXP5585c0ZNTc3MzKy5uZlsLyoq8vLyGnm2w+bt7a2YJ/FlXFtbS7z08PDo7u4me4lJI6qqqlQ5Mo7jQUFBzs7OMplM8V3btm0zMDAYNDj8/4EqcD4AADA6Tp48KRaLKUzg8ePHUVFR+/btY7FYiu0uLi7BwcE1NTXbt2+nKrc35efnK+ZpZmaGECJP0V+8eFFdXZ3sJc6rd3R0qHJkhFB0dPT9+/dTUlKUiQZUBNQBAExmN27csLS0xDDsyJEjCKGMjAwOh6OlpVVYWPjRRx/p6OiYm5ufPXuW2Dg1NZXFYhkbG2/evNnU1JTFYrm4uNy5c4foDQoK0tTUnDJlCvHys88+43A4GIbV19cjhIKDg8PCwioqKjAMEwgECKErV67o6Ojs379/3HY2NTUVx3FPT883u+Li4mxsbE6cOFFcXNzne3EcT0pKmjVrFpPJ1NPTW758+a+//kp0DTxoCCG5XL5nzx5LS0s2m+3g4ECc8BsqkUjE4/GmTZvWZ29NTQ2bzZ4+fbqKR9bT03Nzc0tJScEn79WoyQfqAAAms3fffffmzZvky61bt4aEhHR2dnK53JycnIqKCmtr602bNslkMoRQUFDQ+vXrOzo6tm3bVllZee/eve7u7g8++OD58+cIodTUVMUpjdPT0/ft20e+TElJWbZsGZ/Px3H88ePHCCHilrGenp5x29lLly7NnDlTS0vrzS42m/2Pf/xDTU1t06ZN7e3tb24QHR0dERGxa9cusVh8/fr158+fu7q6vnr1Cg02aAihnTt3JiYmJicnv3jxYtmyZatXr/7xxx+VzFkmk9XU1Bw5cqS4uDgtLU1TU/PNbTo6OkpKSjZt2tRnr6pFnjdvXk1NzU8//aR8QEAtqAMAoCMXFxcdHR0jI6OAgID29vaqqiqyS0NDg/hZbGdnl5GR0drampmZOYyP8PDwkEgkUVFRo5f1QNrb258+fcrn8/vbwNnZOSQkpLKycufOnb26Ojs7k5KSVqxYsXbtWl1dXXt7+6NHj9bX1x87dkxxsz4HraurKyMjw9vb28fHh8fj7d69m8FgKD9iFhYW5ubm0dHRiYmJ/v7+fW4THx9vamoaFxenZExqI8+YMQMhVF5ePqSYgEJQBwBAa8SPOfKnbS8LFizQ0tIiz5CrMrFYjON4nycDSHFxcTNnzkxPT79x44Ziu1AobGtrW7BgAdni6OioqalJXhPpRXHQHj161NHRMWfOHKKLzWZPmTJF+RF7/vy5WCz+6quvTp06NW/evDdvsMjPz8/Nzb169SqXy1UyJrWRiUNAnEoBEwLUAQCAgTCZzLq6OqqzGFxXVxdCiMlkDrANi8XKzMzEMGzDhg2dnZ1kO/Gom7a2tuLGPB6vtbV10M8lrjLs3r2bfFb+2bNnSt52hxBiMBhGRkbu7u7Z2dlCoTA+Pl6xNzs7++DBg6WlpVZWVkoGpDwym81Gvx8OMCFAHQAA6JdMJmtubjY3N6c6kcERXz+K89j0ydnZOTQ0VCQSxcbGko08Hg8h1OtbX8kdNzIyQgglJycrPoh169atoeYvEAjU1dWFQiHZkpaWlpWVVVJSMnXq1KFGoyoyQkgqlaLfDweYEKAOAAD0q7S0FMdxJycn4qWGhkZ/VxAoZ2xsjGFYS0vLoFvGxsba2tqWlZWRLXPmzNHW1la8ue/OnTtSqfTtt98eNJqFhQWLxbp///6Qsm1oaFi9erVii0gkksvlFhYWCCEcx8PDw8vLywsKCnqdpVDZyCTiEJiYmAwpOKAQ1AEAgP+jp6enqampu7v7wYMHwcHBlpaW69evJ7oEAkFjY2NBQYFMJqurq3v27JniG/X19WtraysrK1tbW2UyWVFR0Xg+N6ilpWVtbV1dXT3olsTVAcVn6FksVlhYWH5+flZWlkQiKS8v37Jli6mpaWBgoDLRPv3007Nnz2ZkZEgkErlcXl1d/eLFC4RQQECAiYlJn/MWczica9eulZSUSCQSmUxWVlb2ySefcDic0NBQhNDDhw8TExOPHz/OYDAwBYcPHyberoKRScQhsLe3H3TogIqAOgCAyezIkSOOjo4IofDwcC8vr4yMjOTkZISQg4PDkydPjh8/HhYWhhBasmSJSCQi3tLV1WVvb89ms11dXW1sbL777jvyovvWrVsXLVq0atWqmTNnxsbGEud+nZ2diQcLt2zZYmxsbGdnt3Tp0sbGxvHfWQ8PD6FQSF74//rrrwUCQUVFhaOj4xdffKG4pZOTU69vr71798bHx8fExBgaGrq5uVlZWZWWlnI4HITQoIOWkpISEhKSkJBgYGBgamoaHBzc1NSEEJJKpWKxuLCw8M1UWSzWwoULN27caGZmxuVy/fz8rKysbt++TdxvOOjD9yoYmXT37l0zMzMHB4eBPwiokPGdvhDgOMwrDIYLjf28woGBgfr6+mP6EYMa9rzCIpFIQ0Pj9OnTY5ba0MjlcldX15MnT9Incn19PYvFOnz4sGIjzCus4uB8AADg/xj0VjvV0dnZefXqVZFIRNybJhAIYmJiYmJilF9Ab+zI5fKCgoLW1taAgAD6RI6Ojp47d25QUBBCCMfx2traGzduEPNKAZUFdQAAYKJqbGxcsmSJjY3Nhg0biJaIiAg/P7+AgABlbhgcU6WlpefPny8qKhp4SoPJFDkpKen+/fuXL19mMBgIocLCQjMzM1dXV8WVHoEKgjpAdanysvE9PT3JyckuLi6jHvn27duzZs1SU1PDMMzExGSoM52NhOJy9VOmTOm1pD0dREZGZmZmtrS0TJ8+/dy5c1SnM4ijR4+SJzazsrLI9v379wcFBR04cIDC3BBCixcvPnPmDLkcw6SPXFhY+Pr169LSUj09PaJl+fLl5AEiFqEAqkmD6gRAv3BVXahDJBJ9+umnP/zww1tvvTXqwZ2cnH755ZclS5ZcvXr10aNHxIPd48PHx8fHx0cgENTX1798+XLcPld1xMfH95oTZoJyd3d3d3enOgt68fLy8vLyojoLMBxwPkB1eXh4tLS0LFu2bKw/qLOzU/lf9j/99NPOnTu3bNkyd+7cMc1qfAxp3wEAYPKBOgAMbdn4t9566/z582vWrBl4AteJYkj7DgAAkw/UASqKwmXjVY2q7fv3339vZ2enq6vLYrHs7e2vXr2KENq4cSNxYwGfzycmqvv000+1tLR0dXUvXLiA+lmiPjExUUtLi8vlisXisLAwMzOzR48ejebYAQDAoMb/UUWg5PwBxNwsaWlpxMtdu3YhhL799tuWlhaxWOzq6srhcKRSKdEbGBjI4XAePnzY1dUlFAodHR25XG5VVRXRu2bNGhMTEzLyoUOHEEJ1dXXESx8fH2LZ+CH5wx/+8NZbbw3pLco/H/zhhx8ihJqamoiX47nvfD5fV1d3gNzy8vKio6MbGxsbGhqcnJzIB6N9fHzU1dVramrILVevXn3hwgXiv7dv385kMs+dO9fU1BQZGammpnb37l1y17Zt25aWlrZixYpffvllgI9GYz9/gCqA58jpCY47VeB8wAQzDsvGqywV2XdfX9+9e/fq6enp6+t7eno2NDQQy/Ft2bJFLpeTnyuRSO7evbt06VKkxBL1Bw8e/Pzzz8+fP29raztGaQMAQJ/geYGJatIsGz8MqrPvxHPSxMQ777//vo2Nzd///vfIyEgMw7KzswMCAohJ7Ee4RL0if39/f3//0dsD1YVhGNUpgPHm6+tLdQp0BHXApDVRlo0fC2O675cuXTp06JBQKCRWWyHbMQzbvHlzaGjot99++6c//emf//znmTNniC5yifrdu3eT25uamg7j04ODg52dnUe2B6qOmMw/JCSE6kTAuCKOOxh/UAdMThNo2fhRNxb7fv369X//+98hISFVVVXe3t4rVqz4+9//PnXq1LS0tB07dpCbrV+/PjIy8sSJExYWFjo6OtOmTSPaySXqg4ODR5iJs7PzypUrRxhExeXl5SGEJv1ugl6I4w7GH9QBk9MEWjZ+1I3Fvv/73/8mlp4rLy+XyWRbt261trZGb5y71tPT8/f3z87O5nK5mzZtItuHt0Q9AACMA7hPcPIYrWXjKUh9xMZu32Uy2atXr8glaC0tLRFCxcXFXV1dIpGIfECRtGXLltevX1+8eFFxAqgBlqgHAACKUf3AAh0p89xgWloa8dS7lpaWp6dneno6sfLHjBkzKioqjh07pqOjgxCaNm3ab7/9huN4YGAgg8EwMzPT0NDQ0dFZvnx5RUUFGa2hoWHRokUsFmv69OlffPHFf/3XfyGEBAIB8XDdvXv3pk2bxmaz33333ZcvXw6c2K1btxYuXEhe254yZYqLi8u//vUvZXZcmeeCbt++PXv2bDU1NSL4/v37x23fv/zySz6f39+/lPz8fCJgeHi4vr4+j8fz8/MjZnfg8/nkY4o4js+bNy8iIqLXfr1+/To8PNzS0lJDQ8PIyMjHx0coFCYkJLDZbISQhYWFMqvlInhuEExecNypguGqOon9JJabm+vv7z+6I7958+a8vLyGhoZRjDnq/Pz80BhcBVS1fffw8Dhy5Mj06dNHPTKGYTk5OZP+wvkY/Z0AFQfHnSpwXWDymEDLxo86yvedvKbw4MED4twDtfkAAICSoA4A/+vXX3/F+hcQEEB1gqorPDxcJBL99ttvn376aWxsLNXp0MLmzZvJP85ei0QXFxdHREQoLiS9bt06xQ3c3d25XK66uvrs2bPv3bs3von/R0JCgq2tLZvN5nA4tra2UVFREomE7I2JibGzs9PR0WEymQKBYMeOHW1tbaoc+cKFCwkJCYoVeUFBAXmADA0NlfwIQAGqL0zQkZLzCisvIiKCmFrHysoqLy9vFCOPrrG4/qci+75r1y41NTULCwtyIuGxgOD+AAWBgYH6+vpFRUWPHj3q6uoi2/fs2bNs2TKJREK85PP5BgYGCKGLFy8qvr2oqMjLy2t0Mx8SDw+Pw4cPi8Xi1tbW3NxcBoPxwQcfkL1ubm7p6ekNDQ0SiSQnJ4fBYCxZskTFI6ekpLi5uZHTgff09FRXV1+/fn3p0qXk9NsDgPsDqAJ1AAVGvQ6YKODf+QiNdR3Q0dHh7OxMeSjl6wAzM7NejQcOHLCxsens7CRb+Hz+mTNn1NTUzMzMmpubyXbK6wBvb2/FPImr47W1tcRLDw+P7u5uspe4KUTxdlQVjIzjeFBQkLOzs0wmU3zXtm3boA5QZXBdAADwH6O4CjMlCzo/fvw4Kipq3759LBZLsd3FxSU4OLimpmb79u3jnNIA8vPzFfM0MzNDCJGn6C9evEhMSk0gzqt3dHSocmSEUHR09P3791NSUpSJBlQE1AEATCo4jiclJRGrLunp6S1fvpxcyGBIqzCP7oLOV65c0dHR2b9//5jue2pqKo7jnp6eb3bFxcXZ2NicOHGiuLi4z/cOMG4Dr3yN+llUeqhEIhGPxyPnoOylpqaGzWYP7/7T8Yysp6fn5uaWkpKCw5NoEwi1pyPoCa4LgOFBSlwX2LNnj6am5unTp5ubmx88eDB//nxDQ0NyWoghrcI8igs6X7x4kcvlxsTEKLObw74uYG1tbWdn12szPp//9OlTHMdv3ryppqZmZWXV1taGv3FdYOBxG3jl6/4WlVaGVCqtrq5OS0tjMpn9zSHR3t7O5XKDgoKUjElt5IiICIRQWVkZ2QLXBVQcnA8AYPLo7OxMSkpasWLF2rVrdXV17e3tjx49Wl9ff+zYseEFHK0FnT08PCQSSVRU1PDSUEZ7e/vTp08HmAnK2dk5JCSksrJy586dvbqUHLc+V74edFHpgVlYWJibm0dHRycmJva3kmR8fLypqWlcXJySMamNPGPGDIRQeXn5kGICCkEdAMDkIRQK29raFixYQLY4Ojpqamq+Of/xMKj4YtZisRjHcWLqyf7ExcXNnDkzPT39xo0biu1DHTfFla9HuKj08+fPxWLxV199derUqXnz5r15U0V+fn5ubu7Vq1e5XK6SMamNTByCV69eDSkmoBDUAQBMHs3NzQghbW1txUYej9fa2joq8VV5Meuuri6EEJPJHGAbFouVmZmJYdiGDRs6OzvJ9pGMG7moNPms/LNnz5S87Q4hxGAwjIyM3N3ds7OzhUJhfHy8Ym92dvbBgwdLS0utrKyUDEh5ZGKqbOJwgAkB6gAAJg8ej4cQ6vXtNVqrMKv4YtbE18+gM0s6OzuHhoaKRCLF6Z5GMm7kotKKF1xv3bo11PwFAoG6urpQKCRb0tLSsrKySkpKpk6dOtRoVEVGCEmlUvT74QATAtQBAEwec+bM0dbW/vHHH8mWO3fuSKXSt99+m3g5klWYVXwxa2NjYwzDWlpaBt0yNjbW1ta2rKyMbBl03AYwvEWlGxoaVq9erdgiEonkcrmFhQVCCMfx8PDw8vLygoKCXmcpVDYyiTgEJiYmQwoOKAR1AACTB4vFCgsLy8/Pz8rKkkgk5eXlW7ZsMTU1DQwMJDYY6irMo7Wgc1FR0Vg/N6ilpWVtbV1dXT3olsTVAcVn6Acdt4Gj9beodEBAgImJSZ/zFnM4nGvXrpWUlEgkEplMVlZW9sknn3A4nNDQUITQw4cPExMTjx8/zmAwFOf2Pnz4MPF2FYxMIg6Bvb39oEMHVATUAQBMKnv37o2Pj4+JiTE0NHRzc7OysiotLeVwOETv1q1bFy1atGrVqpkzZ8bGxhInb52dnZ8/f44Q2rJli7GxsZ2d3dKlSxsbGxFCXV1d9vb2bDbb1dXVxsbmu+++Iy/ADzXUOPDw8BAKheSF/6+//logEFRUVDg6On7xxReKWzo5OfX69hpg3DIyMpKTkxFCDg4OT548OX78eFhYGEJoyZIlIpEIIZSSkhISEpKQkGBgYGBqahocHNzU1IQQkkqlYrG4sLDwzVRZLNbChQs3btxoZmbG5XL9/PysrKxu375N3G+ID/bwvQpGJt29e9fMzMzBwWHgDwIqZPwfVQQwfwAYHjS+6wsQE/iP28eRhj1/gEgk0tDQ6O9Z+fEnl8tdXV1PnjxJn8j19fUsFuvw4cOKjTB/gIqD8wEAgH5RvqDzwDo7O69evSoSiYh70wQCQUxMTExMjPIL6I0duVxeUFDQ2to66gt1qnLk6OjouXPnBgUFIYRwHK+trb1x48bjx49HNU0wyqAOAABMVI2NjUuWLLGxsdmwYQPREhER4efnFxAQoMwNg2OqtLT0/PnzRUVFA09pMJkiJyUl3b9///LlywwGAyFUWFhoZmbm6up66dKl0c0TjC6oAwAAfYiMjMzMzGxpaZk+ffq5c+eoTqcPR48eJU9sZmVlke379+8PCgo6cOAAhbkhhBYvXnzmzBlyCYZJH7mwsPD169elpaV6enpEy/Lly8kDRCw8AVSTBtUJAABUUXx8fK/5YSYQd3d3d3d3qrOgFy8vLy8vL6qzAMMB5wMAAAAA+oI6AAAAAKAvqAMAAAAA+oI6AAAAAKAvuE+QMrm5uVSnMN6ICUdpuOOjaBgL2Ew48HdCT9XV1Sq7itXkhuGDTTMJRl1ubq6/vz/VWQAAgGrx9fXNy8ujOgvagToAAFrDMCwnJ2flypVUJwIAoAbcHwAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF9QBAAAAAH1BHQAAAADQF4bjONU5AADGT2Bg4KNHj8iX9+7dmz59up6eHvFSXV391KlT5ubmFGUHABhvGlQnAAAYVyYmJseOHVNsefDgAfnf1tbWUAQAQCtwXQAAelm9enV/XZqamuvXrx/HXAAA1IPrAgDQzpw5cx4+fNjnv/1Hjx7Z2NiMf0oAAKrA+QAAaOfjjz9WV1fv1Yhh2FtvvQVFAAB0A3UAALSzatUquVzeq1FdXf2TTz6hJB8AAIXgugAAdOTi4nLnzp2enh6yBcOw58+fm5mZUZgVAGD8wfkAAOho3bp1GIaRL9XU1N59910oAgCgIagDAKAjPz8/xZcYhn388cdUJQMAoBDUAQDQkaGh4eLFi8m7BTEM8/b2pjYlAAAloA4AgKbWrl1L3B6krq7+4YcfGhgYUJ0RAIACUAcAQFMrVqzQ1NRECOE4vnbtWqrTAQBQA+oAAGiKw+H8+c9/RghpamouW7aM6nQAANSAOgAA+lqzZg1CyNvbm8PhUJ0LAIAaMH+ACsnNzfX396c6CwAAGFu+vr55eXlUZwH+A9YbVDk5OTlUp6AS/P39g4ODnZ2dqU5ERY3W+GRlZQUEBGhoqOj/CpKTkxFCISEhVCcCRg1xTIHqgPMBKoQ4HwBHhIBhWE5OzsqVK6lOREWN1vh0dXWxWKxRSWksEPMcwG/HyQSOqaqB+wMAoDVVLgIAAOMA6gAAAACAvqAOAAAAAOgL6gAAAACAvqAOAAAAAOgL6gAAaOTy5cu6urrffPMN1YmMleLi4oiIiPPnz1tbW2MYhmHYunXrFDdwd3fncrnq6uqzZ8++d+8eJUkmJCTY2tqy2WwOh2NraxsVFSWRSMjemJgYOzs7HR0dJpMpEAh27NjR1tamypEvXLiQkJAgl8uVDAVUDdQBANDI5H4qde/evampqZGRkT4+Pk+ePOHz+QYGBllZWZcuXSK3uXbtWl5e3rJly4RC4fz58ynJ8/vvv9+0aVNVVdWrV69iY2MTEhJ8fX3J3pKSks8//7yysrK+vj4+Pj4lJaXXItGqFtnT05PFYi1evLi5uVnJaEC14EBlEDMIUZ2FqkAI5eTkUJ2F6lLx8eno6HB2dh55HF9fX19fX2W2PHDggI2NTWdnJ9nC5/PPnDmjpqZmZmbW3NxMthcVFXl5eY08t2Hz9vZWzJP4Mq6trSVeenh4dHd3k73EFBFVVVWqHBnH8aCgIGdnZ5lMNmgo5Y8pGB9wPgAAMPpOnjwpFovH7eMeP34cFRW1b9++XtMhuLi4BAcH19TUbN++fdySGVR+fr5inmZmZggh8hT9xYsX1dXVyV5DQ0OEUEdHhypHRghFR0ffv38/JSVFmWhApUAdAABd3Lhxw9LSEsOwI0eOIIQyMjI4HI6WllZhYeFHH32ko6Njbm5+9uxZYuPU1FQWi2VsbLx582ZTU1MWi+Xi4nLnzh2iNygoSFNTc8qUKcTLzz77jMPhYBhWX1+PEAoODg4LC6uoqMAwTCAQIISuXLmio6Ozf//+Mdq11NRUHMc9PT3f7IqLi7OxsTlx4kRxcXGf78VxPCkpadasWUwmU09Pb/ny5b/++ivRNfAQIYTkcvmePXssLS3ZbLaDg8PwJgUXiUQ8Hm/atGl99tbU1LDZ7OnTp6t4ZD09PTc3t5SUFHxSX3uanCg+HwEUwHUBRUi1z3tTbnjj8/z5c4RQWloa8XLXrl0IoW+//balpUUsFru6unI4HKlUSvQGBgZyOJyHDx92dXUJhUJHR0cul0ueRl6zZo2JiQkZ+dChQwihuro64qWPjw+fzyd7L168yOVyY2JihpqwkueQra2t7ezsejXy+fynT5/iOH7z5k01NTUrK6u2tjb8jesCe/bs0dTUPH36dHNz84MHD+bPn29oaPjy5Uuid+Ah2r59O5PJPHfuXFNTU2RkpJqa2t27d5XcNalUWl1dnZaWxmQyT58+3ec27e3tXC43KChIyZjURo6IiEAIlZWVDRwErguoGjgfAADdubi46OjoGBkZBQQEtLe3V1VVkV0aGhrED2U7O7uMjIzW1tbMzMxhfISHh4dEIomKihq9rP9Xe3v706dP+Xx+fxs4OzuHhIRUVlbu3LmzV1dnZ2dSUtKKFSvWrl2rq6trb29/9OjR+vr6Y8eOKW7W5y/VCKYAACAASURBVBB1dXVlZGR4e3v7+PjweLzdu3czGAzlx8fCwsLc3Dw6OjoxMbG/hUbj4+NNTU3j4uKUjElt5BkzZiCEysvLhxQTUA7qAADAf2hqaiKEZDJZn70LFizQ0tIiz5mrDrFYjOO4lpbWANvExcXNnDkzPT39xo0biu1CobCtrW3BggVki6Ojo6amJnkFpBfFIXr06FFHR8ecOXOILjabPWXKFOXH5/nz52Kx+Kuvvjp16tS8efPevJ0iPz8/Nzf36tWrXC5XyZjURiYOwatXr4YUE1AO6gAAgLKYTGZdXR3VWfTW1dWFEGIymQNsw2KxMjMzMQzbsGFDZ2cn2U486qatra24MY/Ha21tHfRz29vbEUK7d+/Gfvfs2TMlb7tDCDEYDCMjI3d39+zsbKFQGB8fr9ibnZ198ODB0tJSKysrJQNSHpnNZqPfDweYQKAOAAAoRSaTNTc3m5ubU51Ib8TXz6Dz2Dg7O4eGhopEotjYWLKRx+MhhHp96yu5m0ZGRgih5ORkxUutt27dGmr+AoFAXV1dKBSSLWlpaVlZWSUlJVOnTh1qNKoiI4SkUin6/XCACQTqAACAUkpLS3Ecd3JyIl5qaGj0dwVhnBkbG2MY1tLSMuiWsbGxtra2ZWVlZMucOXO0tbV//PFHsuXOnTtSqfTtt98eNJqFhQWLxbp///6Qsm1oaFi9erVii0gkksvlFhYWCCEcx8PDw8vLywsKCnqdpVDZyCTiEJiYmAwpOKAc1AEAgH719PQ0NTV1d3c/ePAgODjY0tJy/fr1RJdAIGhsbCwoKJDJZHV1dc+ePVN8o76+fm1tbWVlZWtrq0wmKyoqGrvnBrW0tKytraurqwfdkrg6oPgMPYvFCgsLy8/Pz8rKkkgk5eXlW7ZsMTU1DQwMVCbap59+evbs2YyMDIlEIpfLq6urX7x4gRAKCAgwMTHpc95iDodz7dq1kpISiUQik8nKyso++eQTDocTGhqKEHr48GFiYuLx48cZDAam4PDhw8TbVTAyiTgE9vb2gw4dUClQBwBAF0eOHHF0dEQIhYeHe3l5ZWRkJCcnI4QcHByePHly/PjxsLAwhNCSJUtEIhHxlq6uLnt7ezab7erqamNj891335GX4bdu3bpo0aJVq1bNnDkzNjaWOBvs7OxMPJq4ZcsWY2NjOzu7pUuXNjY2jvWueXh4CIVC8sL/119/LRAIKioqHB0dv/jiC8UtnZycen177d27Nz4+PiYmxtDQ0M3NzcrKqrS0lMPhIIQGHaKUlJSQkJCEhAQDAwNTU9Pg4OCmpiaEkFQqFYvFhYWFb6bKYrEWLly4ceNGMzMzLpfr5+dnZWV1+/Zt4n5DfLCH71UwMunu3btmZmYODg4DfxBQOeP/qCLoD8wfoAjB/AEDGofxCQwM1NfXH9OPGJSSz5qLRCINDY3+npUff3K53NXV9eTJk/SJXF9fz2KxDh8+POiWMH+AqoHzAQCAfk2UReQEAkFMTExMTIzyC+iNHblcXlBQ0NraGhAQQJ/I0dHRc+fODQoKGt3EwDiAOgAM5PDhw8RNWEePHiVaVGfhWsW1ZQksFmv69OkbNmx4+vTp+OSgyuNDNxEREX5+fgEBAcrcMDimSktLz58/X1RUNPCUBpMpclJS0v379y9fvsxgMEY3MTAOoA4AA9m+ffvNmzcVW3CVmTycXFtWV1cXx3G5XF5VVRUTE5OTk+Pk5NTQ0DAOOajy+IxQZGRkZmZmS0vL9OnTz507R3U6Stm/f39QUNCBAweoTWPx4sVnzpwhF1+Y9JELCwtfv35dWlqqp6c36omBcaBBdQJggvHw8KD891af1NTUjI2N161b9/PPPycmJhYXF/c3o+qYUtnxGar4+Phes8RMCO7u7u7u7lRnQS9eXl5eXl5UZwGGD84HgPGD43heXl6vmdtHHbHA3cuXL8f0U8bC+IwPAAAogjpggklMTNTS0uJyuWKxOCwszMzM7NGjR/0tfvqvf/3rnXfe0dLS0tHRsbe3l0gkRPvp06cXLFjAYrE4HI6VlRUxvdr3339vZ2enq6vLYrHs7e2vXr365qcPaeFahJBcLo+Pj585cyabzTY0NJw+fXp8fPzKlSvHdIiIB7reeustxTRgfAAAoE9QB0wwO3bsCA0NbWtri4+Pnz59upOTE47jO3fuTExMTE5OfvHixbJly1avXv3jjz+2t7d7enr6+vo2NjaKRCIbGxti1s+UlJSPP/7Y19e3tra2uro6MjLy0aNHCKFXr175+/tXVlbW1tZqa2uvWbPmzU9/9913FS+Hb926NSQkpLOzk8vl5uTkVFRUWFtbb9q0iZxmLiEhYc+ePYcOHWpsbLx27VpXVxePxyNmch0Lzc3Np06dSk9P9/DweO+998h2GB8AAOgXlQ8tgv9LyfkDiAXROzs7iZednZ1aWloBAQHEy46ODiaTuXXr1p9//hkhdPHiRcX3SqVSHo+3aNEisqW7uzslJaXXRxAXholl3Iif119++SXR1ecC9mQy6enpCKHHjx8TLx0dHd955x0y7F//+lc1NbXXr18rMxpIuefje602i2FYXFwcuTw8TvvxmejgWfPJB46pqoH7BCe8/hY/tba2NjY2Xrt27bZt29avX0+sLfbgwYPm5uYPP/yQfLu6uvq2bdt6xSQe/hnGs+O9Fq7t6upisVhkr1wuZzAYirO6jgpdXV1i1bgdO3YcOnRIV1dX8eGlSTw+w1jSZsIhpqrNzc2lOhEwaqqrq1VwtSpao7oQAf9reOcDfvjhhzcPK3G94Oeff/7zn/+soaGBYZi/v39HR0dJSQlC6OjRo2+GvXjxopubm6GhoaamJoZhCKEXL17gQ/y9e/z4cYTQL7/8QrwMDw9XU1MrKCjo6Oi4e/eugYGBj4+PkqOBlD4fQDw3iOO4RCKZMmUKl8utqqoiN5jE4wPABAXnA1QK3B8w4Q2w+Ons2bO/+eab2tra8PDwnJycw4cPE4uN1tfX9wpSVVXl7e09ZcqUO3futLS0JCQkjEpu0dHR77///vr163V0dFasWLFy5Urii3CMcLncgwcPtra2bt26lWycxOMD1wXAROTr6zsq/3zAaIE6YMLrb/HT2trahw8fIoSMjIwOHDgwf/78hw8fWllZ6evrX7t2rdfG5eXlMpls69at1tbWLBaL+L07ckKhsKKioq6uTiaTVVVVZWRkjPVMIx9//PEf/vCHixcvkmeSYXwAAGAAUAdMeP0tflpbW7t58+Zff/1VKpWWlZU9e/bMycmJyWRGRkZev349KCiopqamp6entbX14cOHlpaWCKHi4uKuri6RSHTnzp1Rye3zzz+3tLQczynfMQxLTU3FMCwoKIhY+Q3GBwAABkL1KSLwv5S5PyAhIYFY4NXCwoJcXe3169fh4eGWlpYaGhpGRkY+Pj5CobCystLFxUVPT09dXX3q1Km7du3q7u4mtj9y5Ii9vT2LxWKxWPPmzUtPT8dxPDw8XF9fn8fj+fn5EY+/8/n84OBgExMThBCHw1mxYkVaWhox86iWlpanp2d6ejoxG/mMGTMqKiqOHTumo6ODEJo2bdpvv/2G43hJSYmBgQH5x8ZgMGbNmnX+/HllRgMNdt77hx9+sLGxISJPnTp18+bNZNf69esRQjwe78CBA7Qdn8kBrgtMPnBMVQ2Gww1HKiM3N9ff338yHZGMjAyRSESs4I4QkkqlO3fuzMjIaGpqIqqZAWAYlpOTM7kn1YHxGZSfnx9CKC8vj+pEwKiBY6pq4LlBMFZevnwZFBSkeGFeU1PT0tJSJpPJZLJBv+cmPRgfAIAqgPsDwFhhs9kMBuPkyZOvXr2SyWS1tbUnTpzYs2dPQEAAcXqc5mB8AACqAOoAMFZ0dXWvXbv2888/29jYsNlsOzu7zMzMgwcPnjp1iurUVAKMz1goLi6OiIg4f/68tbU1hmEYhq1bt05xA3d3dy6Xq66uPnv27Hv37lGSZEJCgq2tLZvN5nA4tra2UVFR5NoWCKGYmBg7OzsdHR0mkykQCHbs2KH8naSURL5w4UJCQsIwptUCqoLqGxTA/1JyHiGaQPS4D27YaDI+Q7qnbM+ePcuWLZNIJMRLPp9P3IbZa/booqIiLy+vUU50KDw8PA4fPiwWi1tbW3NzcxkMxgcffED2urm5paenNzQ0SCSSnJwcBoOxZMkSFY+ckpLi5ubW1NSkTCi4T1DVwPkAAEAfOjs7XVxcVC3UAA4ePJidnZ2bm8vlcsnG1NRUNTW1wMDAlpaWsU5AeZqamp999pmRkZG2trafn9/y5cv/53/+58WLF0SvtrZ2YGCgvr4+l8tduXKlt7f3lStXiHkqVTbytm3b3nrrraVLl3Z3dw99PADFoA4AAPTh5MmTYrFY1UL15/Hjx1FRUfv27VNcrwEh5OLiEhwcXFNTs3379jFNYEjy8/MV8zQzM0MIkafoL168qLjGhKGhIUKoo6NDlSMjhKKjo+/fv5+SkqJMNKBSoA4AYNLCcTwpKWnWrFlMJlNPT2/58uW//vor0RUUFKSpqUnMdoAQ+uyzzzgcDoZhxJzKwcHBYWFhFRUVGIYJBILU1FQWi2VsbLx582ZTU1MWi+Xi4kJOpjSkUAihK1eu6Ojo7N+/fxT3NDU1FcdxT0/PN7vi4uJsbGxOnDhRXFw81FHKyMjgcDhaWlqFhYUfffSRjo6Oubn52bNnyffK5fI9e/ZYWlqy2WwHBwfi0t5QiUQiHo83bdq0PntramrYbPb06dNVPLKenp6bmxuxOOcwAgIqUXtZAiiC+wMUIXpc/x42ZcZnz549mpqap0+fbm5ufvDgwfz58w0NDV++fEn0rlmzxsTEhNz40KFDCKG6ujripY+PD5/PJ3sDAwM5HM7Dhw+7urqEQqGjo6Piek5DCnXx4kUulxsTE6PMbip5Ldna2trOzq5XI5/Pf/r0KY7jN2/eVFNTs7Kyamtrw9+4P2DgUSJWivr2229bWlrEYrGrqyuHwyEXtt6+fTuTyTx37lxTU1NkZKSamtrdu3eV2S8cx6VSaXV1dVpaGpPJJOcE66W9vZ3L5QYFBSkZk9rIERERCKGysrKBg8D9AaoGzgcAMDl1dnYmJSWtWLFi7dq1urq69vb2R48era+vP3bs2PACamhoED+a7ezsMjIyWltbMzMzhxHHw8NDIpFERUUNL403tbe3P336lM/n97eBs7NzSEhIZWXlzp07e3UpOUouLi46OjpGRkYBAQHt7e1VVVUIoa6uroyMDG9vbx8fHx6Pt3v3bgaDofyYWFhYmJubR0dHJyYm+vv797lNfHy8qalpXFyckjGpjTxjxgyEUHl5+ZBiAspBHQDA5CQUCtva2hYsWEC2ODo6ampqjsriCAsWLNDS0iLPn1NLLBbjOE5M4dyfuLi4mTNnpqen37hxQ7F9qKOkqamJEJLJZAihR48edXR0zJkzh+his9lTpkxRfkyeP38uFou/+uqrU6dOzZs3781bKPLz83Nzc69evap456MqRyYOwatXr4YUE1AO6gAAJqfm5maEkLa2tmIjj8drbW0dlfhMJrOurm5UQo1QV1cXQojJZA6wDYvFyszMxDBsw4YNnZ2dZPtIRqm9vR0htHv3bux3z549U/K2O4QQg8EwMjJyd3fPzs4WCoXx8fGKvdnZ2QcPHiwtLbWyslIyIOWRiUkwicMBJhCoAwCYnHg8HkKo1/dZc3Ozubn5yIPLZLLRCjVyxNfPoPPYODs7h4aGikSi2NhYsnEko2RkZIQQSk5OVrzUeuvWraHmLxAI1NXVhUIh2ZKWlpaVlVVSUjJ16tShRqMqMkJIKpWi3w8HmECgDgBgcpozZ462tvaPP/5Itty5c0cqlb799tvESw0NDeL89jCUlpbiOO7k5DTyUCNnbGyMYZgyMwTExsba2tqWlZWRLYOO0gAsLCxYLJbiChHKaGhoWL16tWKLSCSSy+UWFhYIIRzHw8PDy8vLCwoKep2lUNnIJOIQECtwggkE6gAAJicWixUWFpafn5+VlSWRSMrLy7ds2WJqahoYGEhsIBAIGhsbCwoKZDJZXV3ds2fPFN+ur69fW1tbWVnZ2tpKfMf39PQ0NTV1d3c/ePAgODjY0tKSWN95qKGKiopG97lBLS0ta2vr6urqQbckrg4oPkM/6CgNHO3TTz89e/ZsRkaGRCKRy+XV1dXE1DoBAQEmJiZ9zlvM4XCuXbtWUlIikUhkMllZWdknn3zC4XBCQ0MRQg8fPkxMTDx+/DiDwcAUHD58mHi7CkYmEYfA3t5+0KEDKgXqAAAmrb1798bHx8fExBgaGrq5uVlZWZWWlnI4HKJ369atixYtWrVq1cyZM2NjY4nTuc7OzsQEc1u2bDE2Nrazs1u6dGljYyNCqKury97ens1mu7q62tjYfPfdd+Ql+aGGGnUeHh5CoZC88P/1118LBIKKigpHR8cvvvhCcUsnJ6de314DjFJGRgaxKrSDg8OTJ0+OHz8eFhaGEFqyZIlIJEIIpaSkhISEJCQkGBgYmJqaBgcHNzU1IYSkUqlYLC4sLHwzVRaLtXDhwo0bN5qZmXG5XD8/Pysrq9u3bxP3G+KDPXyvgpFJd+/eNTMzc3BwGPiDgMoZ/0cVQX9g/gBFCOYPGNA4jw8xH+24fRxJyWfNRSKRhoZGf8/Kjz+5XO7q6nry5En6RK6vr2exWIcPHx50S5g/QNXA+QAAgFJUeUE5gUAQExMTExOj/AJ6Y0culxcUFLS2tgYEBNAncnR09Ny5c4OCgkY3MTAOoA4AAEwGERERfn5+AQEBlC8pVFpaev78+aKiooGnNJhMkZOSku7fv3/58mUGgzG6iYFxAHUAAGAQkZGRmZmZLS0t06dPP3fuHNXp9Gv//v1BQUEHDhygNo3FixefOXOGXHBh0kcuLCx8/fp1aWmpnp7eqCcGxoEG1QkAAFRdfHx8rxljVJa7u7u7uzvVWdCLl5eXl5cX1VmA4YPzAQAAAAB9QR0AAAAA0BfUAQAAAAB9QR0AAAAA0BfcJ6hy/Pz8qE5BVSQnJ+fl5VGdheqiw/jcvn0bwT+KyeX27dvkyhRAFWD4YJNNgnFz69atpKQkqrMA9FJUVDRv3ryxeBQNgP4Qaz9SnQX4D6gDAKA1DMNycnJWrlxJdSIAAGrA/QEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANAX1AEAAAAAfUEdAAAAANCXBtUJAADGVXNzM47jii3t7e1NTU3kS21tbQaDMe55AQCogfX6PwIAYHJ7//33v/vuu/561dXVa2pqTExMxjMlAACF4LoAAPSyatUqDMP67FJTU/vjH/8IRQAAtAJ1AAD04uvrq6HR9wVBDMM+/vjjcc4HAEAtqAMAoBc9PT13d3d1dfU3u9TU1Ly9vcc/JQAAhaAOAIB21q5d29PT06tRQ0PDw8NDV1eXkpQAAFSBOgAA2vH09GQymb0a5XL52rVrKckHAEAhqAMAoB0tLS1vb+9eDwey2eylS5dSlRIAgCpQBwBAR6tXr5bJZORLBoPh6+vLZrMpTAkAQAmoAwCgow8//FDxVgCZTLZ69WoK8wEAUAXqAADoiMFgBAQEaGpqEi95PN7ixYupTQkAQAmoAwCgqVWrVkmlUoQQg8FYu3Ztf5MKAAAmN5hXGACa6unpmTp16qtXrxBCN27cWLhwIdUZAQAoAOcDAKApNTW1devWIYRMTU1dXFyoTgcAQA04E6iKbt269fz5c6qzAJOfoaEhQugPf/hDXl4e1bkAWli5ciXVKYDe4LqAKvLz8zt37hzVWQAAwCiDbxwVBNcFVJSvry9OG76+vrTa3wHk5OQghMbzE/Py8sbz40gIoZycHEo+GlCC+NsGKgjqAABozdfXl+oUAABUgjoAAAAAoC+oAwAAAAD6gjoAAAAAoC+oAwAAAAD6gjoAAAAAoC+oAwCY8C5fvqyrq/vNN99Qncj4KS4ujoiIOH/+vLW1NYZhGIYRcyOS3N3duVyuurr67Nmz7927R0mSCQkJtra2bDabw+HY2tpGRUVJJBKyNyYmxs7OTkdHh8lkCgSCHTt2tLW1qXLkCxcuJCQkyOVyJUOBiQLqAAAmPJxmc7Ps3bs3NTU1MjLSx8fnyZMnfD7fwMAgKyvr0qVL5DbXrl3Ly8tbtmyZUCicP38+JXl+//33mzZtqqqqevXqVWxsbEJCguJTmiUlJZ9//nllZWV9fX18fHxKSoqfn58qR/b09GSxWIsXL25ublYyGpgYqJ5bAvSBbvPq0G1/BzD+8wgNSUdHh7Oz86iEQsOdR+jAgQM2NjadnZ1kC5/PP3PmjJqampmZWXNzM9leVFTk5eU1CrkOl7e3t2KexJdxbW0t8dLDw6O7u5vsJSbcraqqUuXIOI4HBQU5OzvLZDJloilS8b9tOoPzAQAAZZ08eVIsFlOYwOPHj6Oiovbt28disRTbXVxcgoODa2pqtm/fTlVub8rPz1fM08zMDCFEnqK/ePGiuro62Uus9dDR0aHKkRFC0dHR9+/fT0lJUSYamBCgDgBgYrtx44alpSWGYUeOHEEIZWRkcDgcLS2twsLCjz76SEdHx9zc/OzZs8TGqampLBbL2Nh48+bNpqamLBbLxcXlzp07RG9QUJCmpuaUKVOIl5999hmHw8EwrL6+HiEUHBwcFhZWUVGBYZhAIEAIXblyRUdHZ//+/eO2s6mpqTiOe3p6vtkVFxdnY2Nz4sSJ4uLiPt+L43hSUtKsWbOYTKaent7y5ct//fVXomvgQUMIyeXyPXv2WFpastlsBweH4U2RKxKJeDzetGnT+uytqalhs9nTp09X8ch6enpubm4pKSk4za5GTWYUn48AfaHbeXK67e8AhnfulFidMi0tjXi5a9cuhNC3337b0tIiFotdXV05HI5UKiV6AwMDORzOw4cPu7q6hEKho6Mjl8slTxqvWbPGxMSEjHzo0CGEUF1dHfHSx8eHz+eTvRcvXuRyuTExMcPYUzSs6wLW1tZ2dna9Gvl8/tOnT3Ecv3nzppqampWVVVtbG/7GdYE9e/ZoamqePn26ubn5wYMH8+fPNzQ0fPnyJdE78KBt376dyWSeO3euqakpMjJSTU3t7t27SuYslUqrq6vT0tKYTObp06f73Ka9vZ3L5QYFBQ1hLKiLHBERgRAqKysbUky4LqCy4HwAAJOTi4uLjo6OkZFRQEBAe3t7VVUV2aWhoUH8LLazs8vIyGhtbc3MzBzGR3h4eEgkkqioqNHLeiDt7e1Pnz7l8/n9beDs7BwSElJZWblz585eXZ2dnUlJSStWrFi7dq2urq69vf3Ro0fr6+uPHTumuFmfg9bV1ZWRkeHt7e3j48Pj8Xbv3s1gMJQfMQsLC3Nz8+jo6MTERH9//z63iY+PNzU1jYuLUzImtZFnzJiBECovLx9STKCyoA4AYJLT1NRECMlksj57FyxYoKWlRZ4hV2VisRjHcS0trQG2iYuLmzlzZnp6+o0bNxTbhUJhW1vbggULyBZHR0dNTU3ymkgvioP26NGjjo6OOXPmEF1sNnvKlCnKj9jz58/FYvFXX3116tSpefPmvXmDRX5+fm5u7tWrV7lcrpIxqY1MHIJXr14NKSZQWVAHAEB3TCazrq6O6iwG19XVhRBiMpkDbMNisTIzMzEM27BhQ2dnJ9lOPOqmra2tuDGPx2ttbR30c9vb2xFCu3fvxn737NkzJW+7QwgxGAwjIyN3d/fs7GyhUBgfH6/Ym52dffDgwdLSUisrKyUDUh6ZzWaj3w8HmASgDgCA1mQyWXNzs7m5OdWJDI74+hl0HhtnZ+fQ0FCRSBQbG0s28ng8hFCvb30ld9zIyAghlJycrHhJ9datW0PNXyAQqKurC4VCsiUtLS0rK6ukpGTq1KlDjUZVZISQVCpFvx8OMAlAHQAArZWWluI47uTkRLzU0NDo7woC5YyNjTEMa2lpGXTL2NhYW1vbsrIysmXOnDna2to//vgj2XLnzh2pVPr2228PGs3CwoLFYt2/f39I2TY0NKxevVqxRSQSyeVyCwsLhBCO4+Hh4eXl5QUFBb3OUqhsZBJxCExMTIYUHKgsqAMAoJ2enp6mpqbu7u4HDx4EBwdbWlquX7+e6BIIBI2NjQUFBTKZrK6u7tmzZ4pv1NfXr62traysbG1tlclkRUVF4/ncoJaWlrW1dXV19aBbElcHFJ+hZ7FYYWFh+fn5WVlZEomkvLx8y5YtpqamgYGBykT79NNPz549m5GRIZFI5HJ5dXX1ixcvEEIBAQEmJiZ9zlvM4XCuXbtWUlIikUhkMllZWdknn3zC4XBCQ0MRQg8fPkxMTDx+/DiDwcAUHD58mHi7CkYmEYfA3t5+0KEDEwLUAQBMbEeOHHF0dEQIhYeHe3l5ZWRkJCcnI4QcHByePHly/PjxsLAwhNCSJUtEIhHxlq6uLnt7ezab7erqamNj891335EX3bdu3bpo0aJVq1bNnDkzNjaWOPfr7OxMPJq4ZcsWY2NjOzu7pUuXNjY2jv/Oenh4CIVC8sL/119/LRAIKioqHB0dv/jiC8UtnZycen177d27Nz4+PiYmxtDQ0M3NzcrKqrS0lMPhIIQGHbSUlJSQkJCEhAQDAwNTU9Pg4OCmpiaEkFQqFYvFhYWFb6bKYrEWLly4ceNGMzMzLpfr5+dnZWV16pxo+gAAIABJREFU+/Zt4n5DfLCH71UwMunu3btmZmYODg4DfxCYMMb/UUUwKLo9T0+3/R3AODxjHRgYqK+vP6YfoQw0rPkDRCKRhoZGf8/Kjz+5XO7q6nry5En6RK6vr2exWIcPHx7qG2H+AJUF5wMAoJ2Ju2ScQCCIiYmJiYlRfgG9sSOXywsKClpbWwMCAugTOTo6eu7cuUFBQaObGKAQ1AFgCJRfz3Tjxo1cLhfDsKHeXTWoR48effHFF7Nnz+ZyuRoaGrq6ujY2Nh4eHsO4f3uoBth9xQVwCZqamsbGxu+9996hQ4eIc8hgVERERPj5+QUEBChzw+CYKi0tPX/+fFFR0cBTGkymyElJSffv3798+TKDwRjdxACVqD4hAfqgsufJ3dzc0tPTGxoaJBJJTk4Og8FYsmRJfxsT07MrM/mo8vt74sQJBoPxxz/+8cqVK01NTV1dXRUVFdnZ2S4uLn/729+GsCfDMuju8/l8XV1dHMeJG/G+++679evXYxhmamqq5DS0Y33uNCIigpghx8rKKi8vb+w+aFBouOsNEq5evRoeHj6K+YBBFRQUxMfHK65kOCRwXUBlaVBahIAJRltbOzAwkLgNe+XKlefPn8/NzX3+/Hmvx4rGyO3btwMDA93c3K5evaqh8Z8/XWtra2trax6PR94EN3aU330Mw3g83nvvvffee+95eHj4+/t7eHj89ttvurq6Y53kwOLj43vNCTNBubu7u7u7U50FvXh5eXl5eVGdBRh9cF0ADMGQ1jPFMGx0Pz0uLk4ulx84cIAsAkgffvjh559/Prof96bhLefq6+u7fv16sVh89OjRsc0PAACGDuqAie306dMLFixgsVgcDsfKyoqYQA0f7vqqs2bNwjBMTU3t7bffJr7eduzYoaury2Kx/vGPf7z56b3WM8Vx/NChQzNnzmQymbq6uv/1X/81insqlUq//fZbAwODd955Z+Atqdr9ARBP5xcVFQ1hhwEAYHxQfF0C9EXJ6+XEE88HDhxoaGhobGz829/+tmbNGnwE66t2d3dbWVlZWloqXgIMCQnpNaMq4c31THft2oVh2H//9383NTV1dHSkp6ej0bs/4LfffkMIOTk5DRqNqt3HFe4P6EUikSCELCwsBk2ePtdQ0cjuDwATDn3+ticcOCqqSJnvRalUyuPxFi1aRLZ0d3enpKR0dHRoa2sHBASQ7f/v//0/hBC5SDzxRdjZ2Um8JL6tHz9+TLwkaovc3FziZXt7u6WlZUtLy5sJ7Nq1y8bGRiKREC87Ojq0tLQ++OADcoPRvU+QmBH2T3/608CbUbX7hP7qABzHiTsGBk4ep9P/K6EOoBv6/G1POHCf4ET14MGD5ubmDz/8kGxRV1fftm3bjz/+OOz1VRFCGzdujI6OTklJ8fPzQwhlZWUtX75cR0en17uI9UyvXbtGrmf6+PHjjo6OxYsXj94u/h/ETOmDXowfyfKyaAS7P7D29nYcx9+M0x/i0ye95OTkvLw8qrMA40SZCaEBJeD+gImKONVMrKKmaCTrqxJv/Otf/3rz5k3iZ/SXX3755oQhfa5nSvwjJ1ZmGwtWVlYsFou4OjAAqnZ/YETatra2Sm4PAADjBs4HTFTEcqL19fW92keyviohKCgoJSUlOTl5y5YtFhYWfD5fsTctLe3q1aslJSW9vmtZLBZC6PXr10PcD2UxmcwPP/ywsLDwhx9+WLhwYa/exsbGHTt2nDhxgqrdH9iVK1cQQh999JGS29PhVzKGYSEhIStXrqQ6ETBOcnNz/f39qc4C9AHOB0xUVlZW+vr6165d69U+kvVVCebm5itXrjx37lxUVFRwcDDZjg+4numcOXPU1NT+9a9/DWtvlBIdHc1kMkNDQ8llZkg///wz8TAhVbs/gJcvXyYnJ5ubm2/YsEH5dwEAwPiAOmCiYjKZkZGR169fDwoKqqmp6enpaW1tffjw4UjWVyWFhYV1d3c3NTW9//77ZOPA65kaGRn5+PicO3fu5MmTEonkwYMHx44dG91dnjt37pkzZ37++WdXV9fLly+3tLTIZLKnT58eP378L3/5CzHRKVW7T8JxvK2traenB8fxurq6nJychQsXqqurFxQUKH9/AAAAjB9K71IEfVN+nt0jR47Y29uzWCwWizVv3rz09HQcx3t6eg4dOjRjxgwGg6Gnp+ft7f3o0SNi+/T0dGJe8RkzZlRUVBw7doz4cpo2bdpvv/2mGHnRokUnTpxQbCkvL+/zT+jQoUPEBq2trRs3bjQwMNDW1n733Xf37NmDEDI3N//pp59Ga39xHK+qqtq+fbu9vb22tra6ujqPx5s3b95f/vKXH374gdiAkt2/cOGCg4ODlpaWpqammpoa+n1KwXfeeScmJqahoUHJvaPPPdUInhegGfr8bU84GD7YYtVg/BG3i9PhIjGBbvs7AOIaKh3+VWIYlpOTA/cH0Ad9/rYnHLguAAAAANAX1AEAAFVXXFwcERGhuLjzunXrFDdwd3fncrnq6uqzZ8++d+8eVXkihHp6epKTk11cXN7skslk8fHxAoFAU1OTx+PNmTOnsrJygka+cOFCQkKCXC5X/lOAyoI6AACg0vbu3ZuamhoZGenj4/PkyRM+n29gYJCVlXXp0iVym2vXruXl5S1btkwoFM6fP5+qVEUi0R//+MfQ0NA+J7zy9/f/5z//eebMmY6Ojl9++YXP57e1tU3QyJ6eniwWa/HixcSMHWBCg/kDAKCXzs7OxYsX37x5U6VC9efgwYPZ2dk//fQTMUEFITU1dd26dYGBgUKhkPKlnEk//fRTTEzMli1biOkje/VmZ2cXFBT89NNP9vb2CCFTU9PCwsIJHXnbtm1PnjxZunTp9evX31wCFEwgcD4AAHo5efKkWCxWtVB9evz4cVRU1L59+xSLAISQi4tLcHBwTU3N9u3bx+7Th+qtt946f/78mjVrmEzmm71ffvnl/PnziS/USRM5Ojr6/v37KSkpw/hooDqgDgBg4sH7X1s5KChIU1NzypQpxMvPPvuMw+FgGEZMPRkcHBwWFlZRUYFhmEAgSE1NZbFYxsbGmzdvNjU1ZbFYLi4u5FoMQwqFELpy5YqOjs7+/ftHazdTU1NxHPf09HyzKy4uzsbG5sSJE8XFxUMdooGXn0YIyeXyPXv2WFpastlsBwcH4oG3kZBKpbdv3547d+4I46haZD09PTc3t5SUFHgKYEKDOgCAiSc6OjoiImLXrl1isfj69evPnz93dXV99eoVQig1NVXxYbz09PR9+/aRL1NSUpYtW8bn83Ecf/z4cVBQ0Pr16zs6OrZt21ZZWXnv3r3u7u4PPvjg+fPnQw2FECLuGuvp6Rmt3bx06dLMmTOJKR96YbPZ//jHP9TU1DZt2tTe3v7mBgMM0datW0NCQjo7O7lcbk5OTkVFhbW19aZNm8jlpnbu3JmYmJicnPzixYtly5atXr1acYbKYaitrZVKpf/+978XLVpE1FuzZs0iZvsYSVhViDxv3ryampqffvpphB8HKAR1AAATTGdnZ1JS0ooVK9auXaurq2tvb3/06NH6+vphT+CooaFB/G62s7PLyMhobW3NzMwcRhwPDw+JRBIVFTW8NHppb29/+vRpr/UdFDk7O4eEhFRWVu7cubNXl5JD5OLioqOjY2RkFBAQ0N7eXlVVhRDq6urKyMjw9vb28fHh8Xi7d+9mMBjDGxAScW+dkZHR/v37hULhq1evli9f/vnnn3/11VcjCasKkWfMmIEQ6m+WLTAhQB0AwAQz1LWVh2TBggVaWlrkKXQKicViHMf7PBlAiouLmzlzZnp6+o0bNxTbR7L89KNHjzo6OubMmUN0sdnsKVOmjHBAiKvvs2fPdnFx0dfX19XV3bdvn66u7sjn3qY8MnGAiBMtYIKCOgCACWaEaysPislk1tXVjUqokejq6kK/fxv1h8ViZWZmYhi2YcMGxdWnRjJExFWG3bt3k0tIPHv2rM9n6pRnamqK/u/qoJqamtOmTauoqBhJWFWIzGaz0e8HC0xQUAcAMMGMfG3lAchkstEKNULEF8ygM9U4OzuHhoaKRKLY2FiycSRDZGRkhBBKTk5WnID91q1bw9gFkra29owZMx4+fKjY2N3dPfKHHimPLJVK0e8HC0xQUAcAMMEMurayhoYGecvbUJWWluI47uTkNPJQI2RsbIxhWEtLy6BbxsbG2tralpWVkS0jWX7awsKCxWLdv39/eGn3x9/fv6ys7MmTJ8TLjo6OZ8+eDe9hP5WKTBwgExOTkX8coArUAQBMMIOurSwQCBobGwsK/j97dx7X1JnvD/w5kISELQRFoCgoS92wLtVOiVqHYUpvZUAQENw66Iw/qrURsY7iCgi4DnCxYMdbh9YdFS+0V+l4nTvU+io6tyJoqbWAsrkhKIIkbMn5/XFeZnJZA4GchPN5/+VZ8j3Pec4x+XKW55vT3t7+9OnTyspKzY/b2to+fPiwoqKiqamJ+Y1XqVTPnz/v6Oi4detWVFSUs7NzRETEAELl5eUN4nuD5ubmrq6uNTU12nRIZmamqamp5pwBl58WCoUrVqw4depURkZGY2OjUqmsqal59OgRISQ8PNze3n5g4xZHR0e7uLhERERUVVXV19dv2rRJoVCon3A0xsgM5gANStoBrNFTXUPoj37V4R0GuLa/vdCyNmsvtZVpmq6vr/f29hYKhePGjfv44483btxICHF3d6+qqqJpurCw0MXFRSQSzZkz5/Hjx5GRkXw+38nJicfjWVtbBwYGlpeXDyzUxYsXraysEhIStNlTokXdYZlMxufz5XI5M3n+/Hnm9YGRI0euXbu208obN25csGCBNl3UZ/np1tbWTZs2OTs783g8Ozu74ODgkpISmqaDgoIIITt27Oi2tQUFBbNnz2ZuqxNCHBwcpFLpt99+q16hurp68eLFEonEzMzsrbfeysvLUy8yxsgMPz8/JycnlUrVbXxNqDtssHBUDBHXfhe5tr+90P93ZWRkpK2trT63yNAmDygtLeXxeMeOHdNPk/qkVCrnzp175MgRRGbU1dUJhcIDBw5oszLyAIOF+wIAXGewVePc3d3j4+Pj4+O1r5ozdJRKZU5OTlNTU3h4OCIzYmNjp02bJpPJhiI46A3yAAAwXDExMaGhoeHh4do8MDik8vPzs7Oz8/Lyeh/SgCORCSHJyclFRUUXL17k8/mDHhz0CXkAAHdt2bIlMzPzxYsX48aNO3fuHNvN6V5iYqJMJtu9eze7zfDx8Tlx4oS62gLHI+fm5ra2tubn50skkkEPDnqGYpEA3JWUlJSUlMR2K/rm6+vr6+vLdivgXxYsWLBgwQK2WwGDA9cDAAAAuAt5AAAAAHchDwAAAOAu5AEAAADchTwAAACAuyiaptluA3QWGhpqsC9xAQAMGH5xDBDyAENUUFBQXV3NdiuAE8LCwqKiory8vNhuCHDCokWL2G4CdIY8AIDTKIrKysrCtzMAZ+H5AAAAAO5CHgAAAMBdyAMAAAC4C3kAAAAAdyEPAAAA4C7kAQAAANyFPAAAAIC7kAcAAABwF/IAAAAA7kIeAAAAwF3IAwAAALgLeQAAAAB3IQ8AAADgLuQBAAAA3IU8AAAAgLuQBwAAAHAX8gAAAADuQh4AAADAXcgDAAAAuAt5AAAAAHchDwAAAOAu5AEAAADchTwAAACAu5AHAAAAcBfyAAAAAO5CHgAAAMBdyAMAAAC4C3kAAAAAdyEPAAAA4C7kAQAAANyFPAAAAIC7kAcAAABwF4/tBgCAXp06daqpqUlzzuXLlxsaGtSTQUFBdnZ2em8XALCDomma7TYAgP5ERER8+eWXfD6fmWS+ASiKIoQolUpLS8va2lozMzM2mwgAeoT7AgDcsnjxYkJI+ysdHR0dHR3Mv01NTUNDQ5EEAHAKrgcAcEtHR4e9vf2zZ8+6Xfr3v//9N7/5jZ6bBAAswvUAAG7h8XiLFy9W3xfQNHLkyHnz5um/SQDAIuQBAJyzePHi9vb2TjP5fP7y5ctNTU1ZaRIAsAX3BQA4h6ZpZ2fnmpqaTvP/+c9/zpo1i5UmAQBbcD0AgHMoilq2bFmnWwNjxoyZOXMmW00CALYgDwDgok63Bvh8fkREBPP2IABwCu4LAHDUhAkT7t69q5788ccfJ0+ezGJ7AIAVuB4AwFHLly9X3xqYNGkSkgAAbkIeAMBRy5Yt6+joIITw+fzf//73bDcHANiB+wIA3DVz5swbN25QFFVRUeHs7Mx2cwCABbgeAMBdH3zwASHkV7/6FZIAAM5iv95gcnJyQUEB260A4KKWlhaKolpbW0NDQ9luCwBHnT17lt0GsH89oKCg4Nq1a2y3AgzOuXPnug50A4NLKBTa29uPHj2a7Yb0pqam5ty5c2y3Qh9wznONgZzb7D8fwPwhwnpCBIaGoqisrKxFixax3ZBhrqyszN3dne1W9ObMmTNhYWGsf1PpAc55rjGQc5v96wEAwCIDTwIAYKghDwAAAOAu5AEAAADchTwAAACAu5AHAAAAcBfyAAAYhi5evCgWi7/++mu2GzJULl++HBMTk52d7erqSlEURVHLly/XXMHX19fKysrU1HTy5MmFhYVstZMQolKpUlJSpFJp10Xt7e1JSUnu7u4CgcDGxsbT07OiosJII3/11Vd79+5VKpXab8VAIA8AgGGI9XexhtTOnTvT0tK2bNkSHBx87949Nze3ESNGHD9+/MKFC+p1Ll26dPbsWX9//5KSkhkzZrDV1NLS0nfeeSc6Oloul3ddGhYWdvTo0RMnTsjl8jt37ri5ub18+dJIIwcEBAiFQh8fn4aGBi03ZCDYH08QAGDQ+fn5vXjxQg8bUigUPj4+33//vR62xdizZ8/p06eLi4uFQqF6Zlpa2vLlyyMjI0tKSsRisd4a07vi4uL4+PjVq1c3Nzd3zcxOnz6dk5NTXFw8ZcoUQoijo2Nubq5RR163bt29e/fmz59/5coVHs9ofl5xPQAAYOCOHDlSW1urt82VlZVt3749Li5OMwkghEil0qioqAcPHnzyySd6a0yfpk6dmp2dvXTpUjMzs65LDx06NGPGDOYHddhEjo2NLSoqSk1NHcCm2YI8AACGm6tXrzo7O1MU9emnnxJCMjIyLCwszM3Nc3Nz33//fWtr69GjR586dYpZOS0tTSgUjho16sMPP3R0dBQKhVKp9Pr168xSmUwmEAgcHByYyY8++sjCwoKiqLq6OkJIVFTUhg0bysvLKYpiRmT65ptvrK2tExMTh2jX0tLSaJoOCAjouighIeH111///PPPL1++3O1naZpOTk6eOHGimZmZRCIJDAz8+eefmUW9dxEhRKlU7tixw9nZWSQSvfHGG1lZWTruSFtb27Vr16ZNm6ZjHEOLLJFI5s2bl5qaakR3ppAHAMBwM2fOHM0L9WvWrFm/fr1CobCyssrKyiovL3d1dV21alV7ezshRCaTRUREyOXydevWVVRUFBYWdnR0vPvuu9XV1YSQtLQ0zYF+09PT4+Li1JOpqan+/v5ubm40TZeVlRFCmMfEVCrVEO3ahQsXxo8fb25u3nWRSCT64osvTExMVq1a1dzc3HWF2NjYmJiYrVu31tbWXrlypbq6eu7cuU+ePCF9dREhZPPmzfv27UtJSXn06JG/v/+SJUt++OEHXXbk4cOHbW1tN27c8Pb2ZtKviRMnpqen6/7zyXrk6dOnP3jwoLi4WMfN6Q3yAADgCqlUam1tbWdnFx4e3tzcXFVVpV7E4/GYP5QnTZqUkZHR1NSUmZk5gE34+fk1NjZu37598Fr9L83Nzffv33dzc+tpBS8vr/Xr11dUVGzevLnTIoVCkZycvHDhwmXLlonF4ilTpnz22Wd1dXWHDx/WXK3bLmppacnIyAgKCgoODraxsdm2bRufzx9Y/6gxz9bZ2dklJiaWlJQ8efIkMDBw7dq1J0+e1CWsIUT28PAghNy+fVvHzekN8gAA4ByBQEAIUf+x28nMmTPNzc3V18wNR21tLU3T3V4MUEtISBg/fnx6evrVq1c155eUlLx8+XLmzJnqObNmzRIIBOo7IJ1odtHdu3flcrmnpyezSCQSOTg46Ng/zN33yZMnS6VSW1tbsVgcFxcnFos75SXGGJk5QMyFFqOAPAAAoDMzM7OnT5+y3YrOWlpayKtfo54IhcLMzEyKolauXKlQKNTzmZfZLC0tNVe2sbFpamrqc7vMXYZt27ZRr1RWVnb7Tp32HB0dCSHMYxYMgUDg4uJSXl6uS1hDiCwSicirg2UUkAcAAPwf7e3tDQ0No0ePZrshnTE/MH2OVOPl5RUdHV1aWrpr1y71TBsbG0JIp199LXfTzs6OEJKSkkJrKCgoGMAuqFlaWnp4ePz000+aMzs6OnR/6ZH1yG1tbeTVwTIKyAMAAP6P/Px8mqbffvttZpLH4/V0B0HPRo0aRVGUNuMi7Nq1a8KECTdv3lTP8fT0tLS01Hy47/r1621tbW+++Waf0caMGSMUCouKigbW7J6EhYXdvHnz3r17zKRcLq+srBzYy34GFZk5QPb29rpvTj+QBwAAEJVK9fz5846Ojlu3bkVFRTk7O0dERDCL3N3dnz17lpOT097e/vTp08rKSs0P2traPnz4sKKioqmpqb29PS8vb+jeGzQ3N3d1da2pqelzTebugKmpqeacDRs2nD9//vjx442Njbdv3169erWjo2NkZKQ20VasWHHq1KmMjIzGxkalUllTU/Po0SNCSHh4uL29/cDGLY6OjnZxcYmIiKiqqqqvr9+0aZNCoVA/4WiMkRnMARqUtENPaLaFhISEhISw3QowOISQrKwstlsB7GNeVe/XRw4ePMi88W9ubh4QEJCens48uuXh4VFeXn748GFra2tCiIuLyy+//ELTdGRkJJ/Pd3Jy4vF41tbWgYGB5eXl6mj19fXe3t5CoXDcuHEff/zxxo0bCSHu7u5VVVU0TRcWFrq4uIhEojlz5jx+/PjixYtWVlYJCQkD2FNtznmZTMbn8+VyOTN5/vx55vWBkSNHrl27ttPKGzduXLBggXpSpVLt37/fw8ODz+dLJJKgoKC7d+8yi/rsotbW1k2bNjk7O/N4PDs7u+Dg4JKSEpqmg4KCCCE7duzotrUFBQWzZ89mbqsTQhwcHKRS6bfffqteobq6evHixRKJxMzM7K233srLy1MvMsbIDD8/PycnJ5VK1W18TQM4t4cC+y1AHgDdQh4ADD18V0ZGRtra2g7pJrShzTlfWlrK4/GOHTumnyb1SalUzp0798iRI4jMqKurEwqFBw4c0GZlA8kDcF8AAKDvh+8MhLu7e3x8fHx8vPZVc4aOUqnMyclpamoKDw9HZEZsbOy0adNkMtlQBB8iyAMAAIxJTExMaGhoeHi4fgop9SI/Pz87OzsvL6/3IQ04EpkQkpycXFRUdPHiRT6fP+jBh45x5AGzZs0yNTUdivGiCSErVqwQCoUURRnR6569OHDgAPNQ8WeffcbMGdxC7IZT1l2z8jqDx+ONHDnyt7/97fnz5wdrK72fHgZe/Z07J4MutmzZkpmZ+eLFi3Hjxp07d47t5mglMTFRJpPt3r2b3Wb4+PicOHFCXXyB45Fzc3NbW1vz8/MlEsmgBx9SxpEH/O///q+3t/cQBc/MzDSoCl06+uSTTzqVQKUHtdzF4EbThbryulgsZu5yPX36NCsr68GDB8HBwbrXQWH0fnoYePV37pwMukhKSmptbaVp+v79+yEhIWw3R1u+vr579uxhuxXwLwsWLIiJidF8R8NYGEcewKAoqr8fUSgUUql0KBpjRJhC7P7+/gP7eKc+1DHakJJIJD4+Pv/+7/9OCDlz5kyf6w/i6ZGWlmZiYhIZGcn6pdrecedkAAAtGVMeMIA7Lv0qDT6APIML9FxeXXdjx44lr0ZR7d0gnh6GWf190BndyQAAfTKmPKCsrGzChAkWFhYikWju3LmaVTS+++67SZMmicVioVA4ZcqUv/3tb6S70uCEkGPHjs2cOVMoFFpYWIwdO1Y97qaJicmFCxfef/99sVjs6Oj417/+VZsm9Vm0m+654Pe+ffvMzc2trKxqa2s3bNjg5OS0evVqCwsLExOTN998097ens/nW1hYzJgxY+7cucx4XjY2Nn/605963+tOOhViLysro7r47//+by37sFO03newz84ZIrdu3SKEzJs3Tz1HP6eHLtXfcTIAAGtYeVtRk5bjB/j4+Li6ut6/f7+9vf3HH3/81a9+JRQKmQEuaJo+e/ZsbGzss2fP6uvr33777REjRjDzg4ODmdLgjJSUFELI7t276+vrnz179pe//GXp0qU0TW/dupUQ8ve//72hoeHZs2fz5883MzNrbm7Wpv3qz7548aK2tnbu3LkWFhZtbW3M0h07dggEgmPHjjU0NNy6dWvGjBkjR458/Pix5mfXrVt38ODBhQsX3rlzZ+fOnYSQ69evNzc319XV/du//Rsh5MKFC0+fPm1ubmbeRSkqKup9r0tLSwkhhw4dYiaZMuoHDx5kFm3evJnZtUePHkkkEqlUqlQqte9DzWha7mBPndM7ot34AZrPB8jl8ry8PBcXF19f35cvX6rXGerTw83N7f79+zRNf//99yYmJmPHjmW2npeXpzmKC06GgZ0MBvKOtR5oec7DsGEg5zb7LdA+D5g6dap6kvmb75NPPum6ZlJSEnlVoFPza6utrc3Gxsbb21u9ZkdHR2pqKv3qG0qhUDDzjx49Sgj58ccftWl/p8+mp6cTQsrKymialsvllpaW4eHh6pX/+c9/EkLi4+O7/SxN08xXf1NTEzP55ZdfEkJu376t+fHTp0/3vte9fPVrCgoKEgqFP//8c+/Revnq7+8OanZOn7TPAzqltlOmTPnyyy+ZJ7+03zVdTg91HkDT9IYNGwghzMhumnkAToYBnwwG8l2pB8gDuMYoNJVvAAAgAElEQVRAzm3eQK4hGIApU6aIxWImG+iEeYyg66ggt27damhoeO+999RzTE1N161b11OEgVUW0Sza3d+C3z1F6+jo6LNhPe11T86cOfOf//mfe/fuHT9+/ICj6VLRfBCJxWLmaYCOjo4nT55cunRJJpMlJSVdvXp15MiRnVYe6tMjISHhv/7rv9LT08PCwjTn42TopL8nA0ce3wkLC+t05gAMNWPNAwghfD5f/SVy4cKF/fv3l5SUNDY29vTN0tjYSF4V39QPXQp+a0Obve5WfX39xx9/PGvWLOaP1wFHG+od7C8ej+fk5LRixQqlUrlq1ardu3f/+c9/Jvo9PZj6LnPmzFm5cuXevXvV83Ey6GiwXgQ1ZGFhYVFRUV5eXmw3BPSkoKAgNTWV7VYYbR7Q0dHx7NkzZ2dnQkhVVVVQUNDChQv/+te/vvbaawcPHtR8fkrttddeI4TU1dXprZG6FPzuk5Z73a1169Y1NDT8z//8j/pV14FFG9Id1AVT6YspE67/04Op/n7gwIFdu3YxpyjByaCzRYsWDUocQxYWFubl5cWFPQU1Q8gDjOl9AU3/+Mc/VCoVMzzL7du329vb16xZ4+rqygz91u1Hxo4da2tre+nSJb01UpeC333Scq+7unDhwokTJ7Zv3z558mRmzsaNGwcWbUh3UBc3btwghDBXuVk5PQa3+nufcDIAwIAZUx7Q1tb24sWLjo6OwsJCmUzGFIEmhDB/cl2+fLmlpaW0tFTzfqRmaXATE5MtW7ZcuXJFJpM9ePBApVI1NTUxfzIOEV0Kfvepl73uRWNj44cffjht2jSmYHZLS8sPP/xQVFSkZR92ukQ8pDvYLwqFgqny+fDhw8zMzG3bto0cOXL9+vWEpdNjcKu/9wknAwAMHNsPKmr7vkBmZqa3t/eoUaN4PN6IESMWL15cWVmpXrpp0yZbW1sbG5vQ0FDmbWY3N7eqqqpOpcFpmv7000+nTJkiFAqFQuH06dPT09P37t0rEonIq8Lbx48fZ0aHHj16dJ+vDPRZtLuXgt/q7Y4ZM4apIpqamspEGzt27Hfffbdnzx6xWEwIsbe3P3HixOnTp+3t7QkhEonk1KlTPe11VFQUs5qFhcXChQs7FWI/cOBA13Ng/vz5Wvbhtm3bNKP1voN9dk7vSF/PTqsrr2syMzPz8PBYs2YNUxt+qE+Pwar+jpOhFwbyTLUe9HnOwzBjIOc2RbM9QnhoaCgh5OzZs+w2AwwNRVFZWVm4VwpnzpwJCwtj/ZtKD3DOc42BnNvGdF8AAAAABhfygN78/PPPXQdeVQsPD2e7gQDAUZcvX46JiTHwytcMlUqVkpLSbU2v9vb2pKQkd3d3gUBgY2Pj6elZUVFhpJG/+uqrvXv3aj9uh+FAHtCbCRMm9HJP5fTp02w3EAC4aOfOnWlpaVu2bDHwyteEkNLS0nfeeSc6Oloul3ddGhYWdvTo0RMnTsjl8jt37ri5ub18+dJIIwcEBAiFQh8fH22KnBkUYx0/AABgsCgUCh8fn++//96gQvVkz549p0+fLi4uFgqF6plpaWnLly+PjIwsKSlhHik1BMXFxfHx8atXr2bKWHRaevr06ZycnOLiYmbAD0dHx9zcXKOOvG7dunv37s2fP//KlSs8ntH8vOJ6AABw3SDWUx7q0sxlZWXbt2+Pi4vTTAKIoVa+njp1anZ29tKlS83MzLouPXTo0IwZM5gf1GETOTY2tqioyBBGB9Ie8gAAGA7onqsey2QygUDAvOVICPnoo48sLCwoimKGj+xUTzktLU0oFI4aNerDDz90dHQUCoVSqVQ9iEK/QhFCvvnmG2tr68TExMHazbS0NJqmAwICui7SpfJ1n4WhlUrljh07nJ2dRSLRG2+8ofswz21tbdeuXZs2bZqOcQwtskQimTdvHlOibNAbMESQBwDAcBAbGxsTE7N169ba2torV65UV1fPnTv3yZMnhJC0tDTNl/HS09Pj4uLUk6mpqf7+/kwdxbKyMplMFhERIZfL161bV1FRUVhY2NHR8e677zLFFfsViryqz6RSqQZrNy9cuDB+/HhmMIZORCLRF198YWJismrVqubm5q4r9NJFa9asWb9+vUKhsLKyysrKKi8vd3V1XbVqlXq0qM2bN+/bty8lJeXRo0f+/v5LlizRHDtyAB4+fNjW1nbjxg1vb28m35o4cWJ6erruP5+sR54+ffqDBw+Ki4t13JzeIA8AAKOnUCiSk5MXLly4bNkysVg8ZcqUzz77rK6u7vDhwwMLyOPxmL+bJ02alJGR0dTUlJmZOYA4fn5+jY2N27dvH1gzOmlubr5//37X4bPUvLy81q9fX1FRwYwRqUnLLpJKpdbW1nZ2duHh4c3NzVVVVYSQlpaWjIyMoKCg4OBgGxubbdu28fn8gXWIGvNsnZ2dXWJiYklJyZMnTwIDA9euXXvy5EldwhpCZA8PD0LI7du3ddyc3iAPAACjp3tZ517MnDnT3NxcfQmdRbW1tTRNd3sxQC0hIWH8+PHp6elXr17VnK9LYei7d+/K5XJPT09mkUgkcnBw0LFDmLvvkydPlkqltra2YrE4Li5OLBYPOHUznMjMAWIutBgF5AEAYPSGuuqxmZnZ06dPByWULlpaWsirX6OeMLUtKIpauXKlQqFQz9eli5i7DNu2bVOPnlJZWdntO3Xac3R0JP+3wqdAIHBxcSkvL9clrCFEZsYIZw6WUUAeAABGb0irHre3txtCNW3y6gemz5FqmMrXpaWlu3btUs/UpYvs7OwIISkpKZoDqBQUFAxgF9QsLS09PDw6lfLq6OjQ/aVH1iO3tbWRVwfLKCAPAACj12fVYx6P16lAovby8/Npmn777bd1D6WjUaNGURT14sWLPtcc3MrXY8aMEQqFRUVFA2t2T8LCwm7evHnv3j1mUi6XV1ZWDuxlP4OKzBwgpsSXUUAeAABGr8+qx+7u7s+ePcvJyWlvb3/69GllZaXmx7vWU1apVM+fP+/o6Lh161ZUVJSzszNT5by/ofLy8gbxvUFzc3NXV9eamhptOmQQK18LhcIVK1acOnUqIyOjsbFRqVTW1NQ8evSIEBIeHm5vbz+wcYujo6OZ8vFVVVX19fWbNm1SKBTqJxyNMTKDOUCDknboyeCWLxwALesOA9cQ1GAFmqa1rs3aS9Vjmqbr6+u9vb2FQuG4ceM+/vjjjRs3EkLc3d2Z+tSdKlBHRkby+XwnJycej2dtbR0YGFheXj6wUBcvXrSyskpISNBmT7U552UyGZ/Pl8vlzORgVb7uszB0a2vrpk2bnJ2deTyenZ1dcHBwSUkJTdNBQUGEkB07dnTb2oKCgtmzZzO31QkhDg4OUqn022+/Va9QXV29ePFiiURiZmb21ltv5eXlqRcZY2SGn5+fk5OTSqXqNr4mA6k7zH4LkAdAt5AHAEP/35WRkZG2trb63CJDm3O+tLSUx+MdO3ZMP03qk1KpnDt37pEjRxCZUVdXJxQKDxw4oM3KBpIH4L4AAEBnBls1zt3dPT4+Pj4+XvuqOUNHqVTm5OQ0NTUNevFVY4zMiI2NnTZtmkwmG4rgQwR5AACAMYmJiQkNDQ0PD9fmgcEhlZ+fn52dnZeX1/uQBhyJTAhJTk4uKiq6ePEin88f9OBDB3kAAMC/bNmyJTMz88WLF+PGjTt37hzbzeleYmKiTCbbvXs3u83w8fE5ceKEutoCxyPn5ua2trbm5+dLJJJBDz6kjKYwIgCAHiQlJSUlJbHdir75+vr6+vqy3Qr4lwULFixYsIDtVgwErgcAAABwF/IAAAAA7kIeAAAAwF3IAwAAALjLIJ4TrKmpOXPmDNutAIOjYyETGB6Y04AjXxE45znFUA432wMZ0SEhIWz3AQAAADvY/hGmKZqm2e4EAGANRVFZWVmLFi1iuyEAwA48HwAAAMBdyAMAAAC4C3kAAAAAdyEPAAAA4C7kAQAAANyFPAAAAIC7kAcAAABwF/IAAAAA7kIeAAAAwF3IAwAAALgLeQAAAAB3IQ8AAADgLuQBAAAA3IU8AAAAgLuQBwAAAHAX8gAAAADuQh4AAADAXcgDAAAAuAt5AAAAAHchDwAAAOAu5AEAAADchTwAAACAu5AHAAAAcBfyAAAAAO5CHgAAAMBdyAMAAAC4C3kAAAAAdyEPAAAA4C7kAQAAANyFPAAAAIC7kAcAAABwF/IAAAAA7kIeAAAAwF0UTdNstwEA9CcyMvLu3bvqycLCwnHjxkkkEmbS1NT0yy+/HD16NEutAwB947HdAADQK3t7+8OHD2vOuXXrlvrfrq6uSAIAOAX3BQC4ZcmSJT0tEggEERERemwLALAP9wUAOMfT0/Onn37q9v/+3bt3X3/9df03CQDYgusBAJzzwQcfmJqadppJUdTUqVORBABwDfIAAM5ZvHixUqnsNNPU1PT3v/89K+0BABbhvgAAF0ml0uvXr6tUKvUciqKqq6udnJxYbBUA6B+uBwBw0fLlyymKUk+amJjMmTMHSQAAByEPAOCi0NBQzUmKoj744AO2GgMALEIeAMBFI0eO9PHxUT8tSFFUUFAQu00CAFYgDwDgqGXLljGPB5mamr733nsjRoxgu0UAwALkAQActXDhQoFAQAihaXrZsmVsNwcA2IE8AICjLCwsfve73xFCBAKBv78/280BAHYgDwDgrqVLlxJCgoKCLCws2G4LALAD4wfoyZkzZ8LCwthuBQCAcQgJCTl79izbreAE1BvUq6ysLLabYKAKCgpSU1PRP/2SkpJCCFm/fr0uQY4fPx4eHs7jGe5XAc4NDmLObdAPw/3PPywtWrSI7SYYrtTUVPRPvzB/LenYaQEBAUKhcJBaNFRwbnANrgToE54PAOA0w08CAGBIIQ8AAADgLuQBAAAA3IU8AAAAgLuQBwAAAHAX8gAAbrl48aJYLP7666/ZbshQuXz5ckxMTHZ2tqurK0VRFEUtX75ccwVfX18rKytTU9PJkycXFhay1U5CiEqlSklJkUqlXRe1t7cnJSW5u7sLBAIbGxtPT8+KigojjfzVV1/t3btXqVRqvxXQJ+QBANwyvIcO27lzZ1pa2pYtW4KDg+/du+fm5jZixIjjx49fuHBBvc6lS5fOnj3r7+9fUlIyY8YMtppaWlr6zjvvREdHy+XyrkvDwsKOHj164sQJuVx+584dNze3ly9fGmlk5t1UHx+fhoYGLTcE+oTxAwC4xc/P78WLF3rYkEKh8PHx+f777/WwLcaePXtOnz5dXFys+TJkWlra8uXLIyMjS0pKxGKx3hrTu+Li4vj4+NWrVzc3N3fNzE6fPp2Tk1NcXDxlyhRCiKOjY25urlFHXrdu3b179+bPn3/lyhVDHrSKm3A9AACGxJEjR2pra/W2ubKysu3bt8fFxXUaEUEqlUZFRT148OCTTz7RW2P6NHXq1Ozs7KVLl5qZmXVdeujQoRkzZjA/qMMmcmxsbFFRUWpq6gA2DUMKeQAAh1y9etXZ2ZmiqE8//ZQQkpGRYWFhYW5unpub+/7771tbW48ePfrUqVPMymlpaUKhcNSoUR9++KGjo6NQKJRKpdevX2eWymQygUDg4ODATH700UcWFhYURdXV1RFCoqKiNmzYUF5eTlGUu7s7IeSbb76xtrZOTEwcol1LS0ujaTogIKDrooSEhNdff/3zzz+/fPlyt5+laTo5OXnixIlmZmYSiSQwMPDnn39mFvXeRYQQpVK5Y8cOZ2dnkUj0xhtv6D7+cVtb27Vr16ZNm6ZjHEOLLJFI5s2bl5qaOrzvTBkj5AEAHDJnzhzNC/Vr1qxZv369QqGwsrLKysoqLy93dXVdtWpVe3s7IUQmk0VERMjl8nXr1lVUVBQWFnZ0dLz77rvV1dWEkLS0NM2xftPT0+Pi4tSTqamp/v7+bm5uNE2XlZURQpjHxFQq1RDt2oULF8aPH29ubt51kUgk+uKLL0xMTFatWtXc3Nx1hdjY2JiYmK1bt9bW1l65cqW6unru3LlPnjwhfXURIWTz5s379u1LSUl59OiRv7//kiVLfvjhB1125OHDh21tbTdu3PD29mbSr4kTJ6anp+v+88l65OnTpz948KC4uFjHzcHgQh4AAEQqlVpbW9vZ2YWHhzc3N1dVVakX8Xg85g/lSZMmZWRkNDU1ZWZmDmATfn5+jY2N27dvH7xW/0tzc/P9+/fd3Nx6WsHLy2v9+vUVFRWbN2/utEihUCQnJy9cuHDZsmVisXjKlCmfffZZXV3d4cOHNVfrtotaWloyMjKCgoKCg4NtbGy2bdvG5/MH1j9qzLN1dnZ2iYmJJSUlT548CQwMXLt27cmTJ3UJawiRPTw8CCG3b9/WcXMwuJAHAMC/CAQCQoj6j91OZs6caW5urr5mbjhqa2tpmu72YoBaQkLC+PHj09PTr169qjm/pKTk5cuXM2fOVM+ZNWuWQCBQ3wHpRLOL7t69K5fLPT09mUUikcjBwUHH/mHuvk+ePFkqldra2orF4ri4OLFY3CkvMcbIzAFiLrSA4UAeAAD9YGZm9vTpU7Zb0VlLSwt59WvUE6FQmJmZSVHUypUrFQqFej7zMpulpaXmyjY2Nk1NTX1ul7nLsG3bNuqVysrKbt+p056joyMhhHnMgiEQCFxcXMrLy3UJawiRRSIReXWwwHAgDwAAbbW3tzc0NIwePZrthnTG/MD0OVKNl5dXdHR0aWnprl271DNtbGwIIZ1+9bXcTTs7O0JISkoKraGgoGAAu6BmaWnp4eHx008/ac7s6OjQ/aVH1iO3tbWRVwcLDAfyAADQVn5+Pk3Tb7/9NjPJ4/F6uoOgZ6NGjaIoSptxEXbt2jVhwoSbN2+q53h6elpaWmo+3Hf9+vW2trY333yzz2hjxowRCoVFRUUDa3ZPwsLCbt68ee/ePWZSLpdXVlYO7GU/g4rMHCB7e3vdNweDCHkAAPRGpVI9f/68o6Pj1q1bUVFRzs7OERERzCJ3d/dnz57l5OS0t7c/ffq0srJS84O2trYPHz6sqKhoampqb2/Py8sbuvcGzc3NXV1da2pq+lyTuTtgamqqOWfDhg3nz58/fvx4Y2Pj7du3V69e7ejoGBkZqU20FStWnDp1KiMjo7GxUalU1tTUPHr0iBASHh5ub28/sHGLo6OjXVxcIiIiqqqq6uvrN23apFAo1E84GmNkBnOABiXtgMFEg14wbxWz3QrDhf4ZgJCQkJCQkH595ODBg8wb/+bm5gEBAenp6cyjWx4eHuXl5YcPH7a2tiaEuLi4/PLLLzRNR0ZG8vl8JycnHo9nbW0dGBhYXl6ujlZfX+/t7S0UCseNG/fxxx9v3LiREOLu7l5VVUXTdGFhoYuLi0gkmjNnzuPHjy9evGhlZZWQkNDf3dTy3JDJZHw+Xy6XM5Pnz59nXh8YOXLk2rVrO628cePGBQsWqCdVKtX+/fs9PDz4fL5EIgkKCrp79y6zqM8uam1t3bRpk7OzM4/Hs7OzCw4OLikpoWk6KCiIELJjx45uW1tQUDB79mzmtjohxMHBQSqVfvvtt+oVqqurFy9eLJFIzMzM3nrrrby8PPUiY4zM8PPzc3JyUqlU3cbXNIBzGwYM37x6gt+53qF/BkAP35WRkZG2trZDuok+aXlulJaW8ni8Y8eO6aFJ2lAqlXPnzj1y5AgiM+rq6oRC4YEDB7RZGXmAPuG+AAD0xljKxLm7u8fHx8fHx2tfNWfoKJXKnJycpqam8PBwRGbExsZOmzZNJpMNRXDQBfKAYWUoSsoabJnakydPUhTVbf1T7XGqx4a9mJiY0NDQ8PBw/RRS6kV+fn52dnZeXl7vQxpwJDIhJDk5uaio6OLFi3w+f9CDg46QBwwr9BAM3D0UMQfFyZMn3dzcCgoKmGFrB4ZTPdZfW7ZsyczMfPHixbhx486dO8d2c7SSmJgok8l2797NbjN8fHxOnDihLr7A8ci5ubmtra35+fkSiWTQg8MgYPe2BHcM0f1vuVzu5eVl+DH71N/+qaurGzdu3PHjxwkh27dv1/6Dw6bHaM7cQ8WzIxzEkXPbQOB6gHEbitKuei4XOzBnzpzx8/MLCAgQCoXMo2FafpCzPQYA0C3kAYblu+++mzRpklgsFgqFU6ZM+dvf/qZedOzYsZkzZwqFQgsLi7Fjx+7atatTaddOJWUnTpxIUZSJicmbb77JDHT6pz/9iYn8xRdf9LSt3mMS3Sq0DqKTJ08uXLjQysrK19e3oqLiu+++67oOegwAoG8sX4/gDC2vbZ49ezY2NvbZs2f19fVvv/32iBEjmPkpKSmEkN27d9fX1z979uwvf/nL0qVLaZoODg5mSrsymIKwBw8epGm6o6Nj7Nixzs7OHR0d6hXWr1+vHgO1p231EpOm6R07dggEgmPHjjU0NNy6dWvGjBkjR458/Pgxs3Tr1q2EkL///e8vXryora2dO3euhYVFW1vbYPUPo7Ky0s7OjtmvY8eOEUL+8Ic/dFpn2PcYzZlrp7gvwEEcObcNBK4HGJaQkJCdO3dKJBJbW9uAgID6+vqnT5+2t7fHxcV5e3tv3rzZ1tZWIpH84Q9/mDVrVu+hTE1N161bV1VVdf78eWaOXC7Pzs5euXJlL9vqPaYuFVoH0cmTJ3/3u98xQ8IFBASYmZmdPXtWs3IMegwAQEs8thsAPWJesFEqlbdu3WpoaHjvvffUi5hfrD4j/PGPf4yNjU1NTQ0NDSWEHD9+PDAwkBkNradt9R5Qlwqtg+jkyZNJSUnMv62trX19fb/++uvc3Fz1e8/c6bGampozZ85oubKRYsr2DPvdBE01NTUGWM5quEIeYFguXLiwf//+kpKSxsZG9Y9BY2MjeVUVrV8sLS3/3//7f/v37//nP//51ltvHTp0SPPtr2631TtdKrQOlh9//PH27dv+/v6d5h89elSdB3Cnx65duxYWFjYooQwcR3YT1EJCQthuAlfgvoABqaqqCgoKcnBwuH79+osXL/bu3cvMf+2118j/re2tPWbQ9ZSUlCtXrowZM4YZcb2XbfVOlwqtg+XEiROLFy/WvLn17NkzkUh06dKlx48fM+twp8e4cA8VzwdwEJIAfUIeYEBu377d3t6+Zs0aV1dXoVBIURQzf+zYsba2tpcuXRpAzNGjRy9atOjcuXPbt2+Piorqc1u906VC66Cgafr06dMfffSR5kyJRBIaGqpUKk+ePMnMQY8BAGgJeYABcXZ2JoRcvny5paWltLRUfQvZzMxsy5YtV65ckclkDx48UKlUTU1NP/30E+lS2rXbsBs2bOjo6Hj+/PlvfvObPrfVe0xdKrQOiu+//97a2nr27Nmd5q9evZoQcvToUWYSPQYAoC22L/9whZbXNjdt2mRra2tjYxMaGsq8gO7m5sZUcf3000+nTJkiFAqFQuH06dPT09Pp/1vaddu2bZolZTXDent7f/7551puq/eYulRo1bF//vCHP1hYWPB4vKlTpxYWFqrn79q1S10L1cnJiemZYd9jNGfercJ9AQ7iyLltICh6uIyFbuDOnDkTFhaG3u4J+mcAmJcazp49y3ZDhhbODQ7iyLltIHBfAAAAgLuQBwAAAHAX8gAAGFYuX74cExOTnZ3t6upKURRFUcuXL9dcwdfX18rKytTUdPLkyYWFhWy1kxCiUqlSUlKkUmnXRe3t7UlJSe7u7gKBwMbGxtPTs6Kiwkgjf/XVV3v37u1z0C1gC/IAABg+du7cmZaWtmXLluDg4Hv37rm5uY0YMeL48eMXLlxQr3Pp0qWzZ8/6+/uXlJTMmDGDraaWlpa+88470dHRTFGrTsLCwo4ePXrixAm5XH7nzh03N7eXL18aaWSmLqiPjw8zrBYYGownCAA9UigUPj4+33//vUGF6smePXtOnz5dXFwsFArVM9PS0pYvXx4ZGVlSUiIWi4du6/1SXFwcHx+/evXq5ubmro9Anj59Oicnp7i4eMqUKYQQR0fH3Nxco468bt26e/fuzZ8//8qVKzwefncMC64HAECPjhw5Ultba2ihulVWVrZ9+/a4uDjNJIAQIpVKo6KiHjx48Mknnwzd1vtr6tSp2dnZS5cuNTMz67r00KFDM2bMYH5Qh03k2NjYoqKi1NTUAWwahhTyAIBhjqbp5OTkiRMnmpmZSSSSwMDAn3/+mVkkk8kEAgEz4AEh5KOPPrKwsKAoihmSOSoqasOGDeXl5RRFubu7p6WlCYXCUaNGffjhh46OjkKhUCqVqsdT6lcoQsg333xjbW2dmJg4WLuZlpZG03RAQEDXRQkJCa+//vrnn39++fLl/nZRRkaGhYWFubl5bm7u+++/b21tPXr06FOnTqk/q1Qqd+zY4ezsLBKJ3njjDWa0A120tbVdu3Zt2rRpOsYxtMgSiWTevHmpqal4BdTQIA8AGOZiY2NjYmK2bt1aW1t75cqV6urquXPnPnnyhBCSlpa2aNEi9Zrp6elxcXHqydTUVH9/fzc3N5qmy8rKZDJZRESEXC5ft25dRUVFYWFhR0fHu+++W11d3d9Q5FWpRpVKNVi7eeHChfHjxzPjMnUiEom++OILExOTVatWNTc3d12hly5as2bN+vXrFQqFlZVVVlZWeXm5q6vrqlWr1ANHbt68ed++fSkpKY8ePfL391+yZInmMNID8PDhw7a2ths3bnh7ezP51sSJE5lRsHQJawiRp0+f/uDBg+LiYh03B4MLeQDAcKZQKJKTkxcuXLhs2TKxWDxlypTPPvusrq7u8OHDAwvI4/GYv5snTZqUkZHR1NSUmZk5gDh+fn6NjY3bt28fWDM6aW5uvn//vrooVFdeXl7r16+vqKjYvHlzp0VadpFUKrW2trazswsPD29ubq6qqiKEtLS0ZGRkBAUFBQcH29jYbNu2jc/nD6xD1Jhn6+zs7BITE0tKSp48eRIYGLh27Vp1+Qzjjezh4UEIuX37to6bg8GFPABgOLYBp2QAACAASURBVCspKXn58uXMmTPVc2bNmiUQCDTrIwzYzJkzzc3N1ZfQWVRbW0vTdLcXA9QSEhLGjx+fnp5+9epVzfn97SKBQEAIYa4H3L17Vy6Xe3p6MotEIpGDg4OOHcLcfZ88ebJUKrW1tRWLxXFxcWKxeMCpm+FEZg4Qc6EFDAfyAIDhjHlTy9LSUnOmjY1Np1LIA2ZmZvb06dNBCaWLlpYW8urXqCdCoTAzM5OiqJUrVyoUCvV8XbqIucuwbds26pXKyspu36nTHlMsQ7NqtkAgcHFxKS8v1yWsIUQWiUTk1cECw4E8AGA4s7GxIYR0+klraGgYPXq07sHb29sHK5SOmB+YPkeq8fLyio6OLi0t3bVrl3qmLl1kZ2dHCElJSdGs2lJQUDCAXVCztLT08PBgymOqdXR06P7SI+uR29rayKuDBYYDeQDAcObp6Wlpaan55Nr169fb2trefPNNZpLH4/VUf7lP+fn5NE2//fbbuofS0ahRoyiKevHiRZ9r7tq1a8KECTdv3lTP6bOLejFmzBihUFhUVDSwZvckLCzs5s2b9+7dYyblcnllZeXAXvYzqMjMAbK3t9d9czCIkAcADGdCoXDDhg3nz58/fvx4Y2Pj7du3V69e7ejoGBkZyazg7u7+7NmznJyc9vb2p0+fVlZWan7c1tb24cOHFRUVTU1NzG+8SqV6/vx5R0fHrVu3oqKinJ2dIyIiBhAqLy9vEN8bNDc3d3V1ramp0aZDMjMzTU1NNef03kW9R1uxYsWpU6cyMjIaGxuVSmVNTc2jR48IIeHh4fb29gMbtzg6OtrFxSUiIqKqqqq+vn7Tpk0KhUL9hKMxRmYwB2hQ0g4YTPopbwyood479M8AaFmjXaVS7d+/38PDg8/nSySSoKCgu3fvqpfW19d7e3sLhcJx48Z9/PHHGzduJIS4u7tXVVXRNF1YWOji4iISiebMmfP48ePIyEg+n+/k5MTj8aytrQMDA8vLywcW6uLFi1ZWVgkJCX22X8tzQyaT8fl8uVzOTJ4/f555fWDkyJFr167ttPLGjRsXLFigTRelp6czT7d5eHiUl5cfPnzY2tqaEOLi4vLLL7/QNN3a2rpp0yZnZ2cej2dnZxccHFxSUkLTdFBQECFkx44d3ba2oKBg9uzZzG11QoiDg4NUKv3222/VK1RXVy9evFgikZiZmb311lt5eXnqRcYYmeHn5+fk5KRSqbqNr0nLcxsGBb559QS/c71D/wyA/r8rIyMjbW1t9blFWutzo7S0lMfjHTt2TA9N0oZSqZw7d+6RI0cQmVFXVycUCg8cOKDNysgD9An3BQCgHwy2apy7u3t8fHx8fLz2VXOGjlKpzMnJaWpqCg8PR2RGbGzstGnTZDLZUAQHXSAPAIBhIiYmJjQ0NDw8XJsHBodUfn5+dnZ2Xl5e70MacCQyISQ5ObmoqOjixYt8Pn/Qg4OOkAcAgFa2bNmSmZn54sWLcePGnTt3ju3mdC8xMVEmk+3evZvdZvj4+Jw4cUJdbYHjkXNzc1tbW/Pz8yUSyaAHB92h/iMAaCUpKSkpKYntVvTN19fX19eX7VbAvyxYsGDBggVstwJ6hOsBAAAA3IU8AAAAgLuQBwAAAHAX8gAAAADuwnOCehUaGsp2EwwUM+Ao+qdfrl27RjjQaTg3OOjatWvquhUw1CiaptluAycUFBQkJyez3QqAzvLy8qZPnz4Ub4sB6IIpDsl2KzgBeQAAp1EUlZWVtWjRIrYbAgDswPMBAAAA3IU8AAAAgLuQBwAAAHAX8gAAAADuQh4AAADAXcgDAAAAuAt5AAAAAHchDwAAAOAu5AEAAADchTwAAACAu5AHAAAAcBfyAAAAAO5CHgAAAMBdyAMAAAC4C3kAAAAAdyEPAAAA4C7kAQAAANyFPAAAAIC7kAcAAABwF/IAAAAA7kIeAAAAwF3IAwAAALgLeQAAAAB3IQ8AAADgLuQBAAAA3IU8AAAAgLuQBwAAAHAX8gAAAADuQh4AAADAXcgDAAAAuAt5AAAAAHchDwAAAOAuHtsNAAC9amhooGlac05zc/Pz58/Vk5aWlnw+X+/tAgB2UJ2+EQBgePvNb37zj3/8o6elpqamDx48sLe312eTAIBFuC8AwC2LFy+mKKrbRSYmJu+88w6SAABOQR4AwC0hISE8Xvc3BCmK+uCDD/TcHgBgF/IAAG6RSCS+vr6mpqZdF5mYmAQFBem/SQDAIuQBAJyzbNkylUrVaSaPx/Pz8xOLxaw0CQDYgjwAgHMCAgLMzMw6zVQqlcuWLWOlPQDAIuQBAJxjbm4eFBTU6eVAkUg0f/58tpoEAGxBHgDARUuWLGlvb1dP8vn8kJAQkUjEYpMAgBXIAwC46L333tN8FKC9vX3JkiUstgcA2II8AICL+Hx+eHi4QCBgJm1sbHx8fNhtEgCwAnkAAEctXry4ra2NEMLn85ctW9bToAIAMLxhXGEAjlKpVK+99tqTJ08IIVevXp09ezbbLQIAFuB6AABHmZiYLF++nBDi6OgolUrZbg4AsANXAg1RQUFBdXU1262A4W/kyJGEkF/96ldnz55luy3ACYsWLWK7CdAZ7gsYotDQ0HPnzrHdCgCAQYZfHAOE+wIGKiQkhOYeQkhWVhbbrWBTVlYWIUSfWzx79qw+N6eGY801zLkNBgh5AACnhYSEsN0EAGAT8gAAAADuQh4AAADAXcgDAAAAuAt5AAAAAHchDwAAAOAu5AEARu/ixYtisfjrr79muyFD5fLlyzExMdnZ2a6urhRFURTFjISo5uvra2VlZWpqOnny5MLCQrbaSQhRqVQpKSndjs/Y3t6elJTk7u4uEAhsbGw8PT0rKiqMNPJXX321d+9epVKp/VbAYCEPADB69LAem2Xnzp1paWlbtmwJDg6+d++em5vbiBEjjh8/fuHCBfU6ly5dOnv2rL+/f0lJyYwZM9hqamlp6TvvvBMdHS2Xy7suDQsLO3r06IkTJ+Ry+Z07d9zc3F6+fGmkkQMCAoRCoY+PT0NDg5YbAoOFcYUBjJ6fn9+LFy/0sCGFQuHj4/P999/rYVuMPXv2nD59uri4WCgUqmempaUtX748MjKypKRELBbrrTG9Ky4ujo+PX716dXNzc9fM7PTp0zk5OcXFxVOmTCGEODo65ubmGnXkdevW3bt3b/78+VeuXEGxSqOG6wEAoK0jR47U1tbqbXNlZWXbt2+Pi4vTTAIIIVKpNCoq6sGDB5988oneGtOnqVOnZmdnL1261MzMrOvSQ4cOzZgxg/lBHTaRY2Nji4qKUlNTB7BpMBzIAwCM29WrV52dnSmK+vTTTwkhGRkZFhYW5ubmubm577//vrW19ejRo0+dOsWsnJaWJhQKR40a9eGHHzo6OgqFQqlUev36dWapTCYTCAQODg7M5EcffWRhYUFRVF1dHSEkKipqw4YN5eXlFEW5u7sTQr755htra+vExMQh2rW0tDSapgMCArouSkhIeP311z///PPLly93+1mappOTkydOnGhmZiaRSAIDA3/++WdmUe9dRAhRKpU7duxwdnYWiURvvPGG7gPitrW1Xbt2bdq0aTrGMbTIEolk3rx5qampw/vO1LCHPADAuM2ZM0fzQv2aNWvWr1+vUCisrKyysrLKy8tdXV1XrVrV3t5OCJHJZBEREXK5fN26dRUVFYWFhR0dHe+++y5T3zItLU2zHFx6enpcXJx6MjU11d/f383NjabpsrIyQgjzmJhKpRqiXbtw4cL48ePNzc27LhKJRF988YWJicmqVauam5u7rhAbGxsTE7N169ba2torV65UV1fPnTv3yZMnpK8uIoRs3rx53759KSkpjx498vf3X7JkyQ8//KDLjjx8+LCtre3GjRve3t5M+jVx4sT09HTdfz5Zjzx9+vQHDx4UFxfruDlgEfIAgOFJKpVaW1vb2dmFh4c3NzdXVVWpF/F4POYP5UmTJmVkZDQ1NWVmZg5gE35+fo2Njdu3bx+8Vv9Lc3Pz/fv33dzcelrBy8tr/fr1FRUVmzdv7rRIoVAkJycvXLhw2bJlYrF4ypQpn332WV1d3eHDhzVX67aLWlpaMjIygoKCgoODbWxstm3bxufzB9Y/asyzdXZ2domJiSUlJU+ePAkMDFy7du3Jkyd1CWsIkT08PAght2/f1nFzwCLkAQDDnEAgIISo/9jtZObMmebm5upr5oajtraWpuluLwaoJSQkjB8/Pj09/erVq5rzS0pKXr58OXPmTPWcWbNmCQQC9R2QTjS76O7du3K53NPTk1kkEokcHBx07B/m7vvkyZOlUqmtra1YLI6LixOLxZ3yEmOMzBwg5kILGCnkAQBcZ2Zm9vTpU7Zb0VlLSwt59WvUE6FQmJmZSVHUypUrFQqFej7zMpulpaXmyjY2Nk1NTX1ul7nLsG3bNuqVysrKbt+p056joyMhhHnMgiEQCFxcXMrLy3UJawiRRSIReXWwwEghDwDgtPb29oaGhtGjR7PdkM6YH5g+R6rx8vKKjo4uLS3dtWuXeqaNjQ0hpNOvvpa7aWdnRwhJSUmhNRQUFAxgF9QsLS09PDx++uknzZkdHR26v/TIeuS2tjby6mCBkUIeAMBp+fn5NE2//fbbzCSPx+vpDoKejRo1iqIobcZF2LVr14QJE27evKme4+npaWlpqflw3/Xr19va2t58880+o40ZM0YoFBYVFQ2s2T0JCwu7efPmvXv3mEm5XF5ZWTmwl/0MKjJzgOzt7XXfHLAFeQAA56hUqufPn3d0dNy6dSsqKsrZ2TkiIoJZ5O7u/uzZs5ycnPb29qdPn1ZWVmp+0NbW9uHDhxUVFU1NTe3t7Xl5eUP33qC5ubmrq2tNTU2fazJ3B0xNTTXnbNiw4fz588ePH29sbLx9+/bq1asdHR0jIyO1ibZixYpTp05lZGQ0NjYqlcqamppHjx4RQsLDw+3t7Qc2bnF0dLSLi0tERERVVVV9ff2mTZsUCoX6CUdjjMxgDtCgpB3AGhoMT0hISEhICNutYAEhJCsri+1WsIl5Vb1fHzl48CDzxr+5uXlAQEB6ejrz6JaHh0d5efnhw4etra0JIS4uLr/88gtN05GRkXw+38nJicfjWVtbBwYGlpeXq6PV19d7e3sLhcJx48Z9/PHHGzduJIS4u7tXVVXRNF1YWOji4iISiebMmfP48eOLFy9aWVklJCQMYE+1OdYymYzP58vlcmby/PnzzOsDI0eOXLt2baeVN27cuGDBAvWkSqXav3+/h4cHn8+XSCRBQUF3795lFvXZRa2trZs2bXJ2dubxeHZ2dsHBwSUlJTRNBwUFEUJ27NjRbWsLCgpmz57N3FYnhDg4OEil0m+//Va9QnV19eLFiyUSiZmZ2VtvvZWXl6deZIyRGX5+fk5OTiqVqtv4mgZwboN+4KgYIuQBnKWH78rIyEhbW9sh3YQ2tDnWpaWlPB7v2LFj+mlSn5RK5dy5c48cOYLIjLq6OqFQeODAAW1WRh5gsHBfAIBzjKVMnLu7e3x8fHx8vPZVc4aOUqnMyclpamoKDw9HZEZsbOy0adNkMtlQBAe9QR4wTPzxj3+0srKiKGrQn28yKJqVZxkCgWDUqFG//vWv9+/f//z5c7YbCIMsJiYmNDQ0PDxcP4WUepGfn5+dnZ2Xl9f7kAYciUwISU5OLioqunjxIp/PH/TgoE/IA4aJzz///D/+4z/YbsWQU1eeFYvFNE2rVKra2tozZ86MGzdu06ZNkydP1nH812Fvy5YtmZmZL168GDdu3Llz59hujlYSExNlMtnu3bvZbYaPj8+JEyfUxRc4Hjk3N7e1tTU/P18ikQx6cNAz5AEw5BQKhVQqHYrIFEXZ2Nj8+te/zszMPHPmzJMnT/RWgbdfhq4H+ispKam1tZWm6fv374eEhLDdHG35+vru2bOH7VbAvyxYsCAmJkbzHQ0wXsgDhg+KothuQvf0U6w2JCQkIiKitrb2s88+G+pt9Zeey/UCAGgPeYARo2l6//7948ePNzMzE4vFzCtejH379pmbm1tZWdXW1m7YsMHJyYl5aaqnSqy9l6MlvVZx7W+x2qHDvASfl5fH2R4AAOg3Ft9VgJ5o+d7g1q1bKYr685///Pz5c7lcnp6eTgi5efOmeikhZN26dQcPHly4cOGdO3d27NghEAiOHTvW0NBw69atGTNmjBw58vHjx8z6kZGRFhYWP/30U0tLS0lJyaxZs6ysrJi3xmma7v2zS5cutbe3Vzds//79hJCnT58yk8HBwUyx2j4R7d4bVD8f0EljYyMhZMyYMcbbA9x5t0rLYw3DBnfObaOD6wHGSqFQpKSk/Pa3v42OjraxsRGJRLa2tl1X27Nnz9q1a7Ozs11cXPqsxNpTOVotq7iyjnljotOo8pzqAQCA/uKx3QAYoLKyMrlc7uPjo+X6/a3EqlmOtr+fZUtzczNN08zYcF0ZUQ+EhoYORVhDk5KScvbsWbZbAXqizRDRwApcDzBWzH8qpjaaNgZQiVVdjlaXKq769MsvvxBCJkyY0O1SLvQAAEB/4XqAsRIKhYSQ1tZWLdfvbyVWzXK0ulRx1advvvmGEPL+++93u9SIeoALfyVTFLV+/fpFixax3RDQkzNnzoSFhbHdCugGrgcYK09PTxMTk2+//Vb79ftViVWzHG2fnzWEYrWPHz9OSUkZPXr0ypUru11h2PcAAMAAIA8wVkwZtHPnzh05cqSxsfHWrVu9P7OmTSXWnsrR9vnZfhWrHZTdp2n65cuXTJWzp0+fZmVlzZ4929TUNCcnp6fnA4ZZDwAADA5W31aA7mn53mBTU9Mf//jHESNGWFpazpkzZ8eOHYSQ0aNHFxcX7927VyQSEULGjBmjLtfWSyVWuq9ytL1/tl/FanvZI9LXu2RfffXVG2+8YW5uLhAITExMyKshBd966634+Pj6+nr1mkbaA9x5t6rPYw3DDHfObaND0TTNVgoCPWEeF9fzTeIPP/zw7Nmz9fX1+txoJxRFZWVlsXXP2BB6gLmHyoX/lewea9A/7pzbRgf3BeBfjKUc7dBBDwAA1yAPAABDd/ny5ZiYGM2q08uXL9dcwdfX18rKytTUdPLkyYWFhWy1kxCiUqlSUlK6LSvV3t6elJTk7u4uEAhsbGw8PT0rKiqMNPJXX321d+9e5M3DA/IAIMQ4y9EOLvSAwdq5c2daWtqWLVvUVadHjBhx/PjxCxcuqNe5dOnS2bNn/f39S0pKZsyYwVZTS0tL33nnnejoaLlc3nVpWFjY0aNHT5w4IZfL79y54+bm9vLlSyONHBAQIBQKfXx8mKE1wLix/HwCdEfL5wSHH8L5Z8f08CyVXC738vJiPZSWx3r37t2vv/66QqFQz3Fzcztx4oSJiYmTk1NDQ4N6fl5e3oIFCwbWmEFRVFS0cOHC48ePT5s2berUqZ2Wnjp1iqKoW7duDafIMpnMy8urvb1dm23hOUGDhesBANwyiEWQh7qecllZ2fbt2+Pi4phRs9SkUmlUVNSDBw8++eSTodt6f02dOjU7O3vp0qVmZmZdlx46dGjGjBlTpkwZTpFjY2OLiopSU1MHsGkwHMgDAIwPPUhFkHuvttzfesrffPONtbV1YmLiYO1mWloaTdMBAQFdFyUkJLz++uuff/755cuX+9tFGRkZFhYW5ubmubm577//vrW19ejRo0+dOqX+rFKp3LFjh7Ozs0gkeuONN5g/ZHXR1tZ27dq1adOm6RjH0CJLJJJ58+alpqbSeAvAmCEPADA+sbGxMTExW7dura2tvXLlSnV19dy5c588eUIISUtL03wZLz09PS4uTj2Zmprq7+/PFEEuKyuTyWQRERFyuXzdunUVFRWFhYUdHR3vvvtudXV1f0ORV29bqFSqwdrNCxcujB8/3tzcvOsikUj0xRdfmJiYrFq1qrm5uesKvXTRmjVr1q9fr1AorKyssrKyysvLXV1dV61apR7iafPmzfv27UtJSXn06JG/v/+SJUs0h5IcgIcPH7a1td24ccPb25vJtyZOnJienq77zyfrkadPn/7gwYPi4mIdNwcsQh4AYGQGvQhyT9WW+8vPz6+xsXH79u0Da0Ynzc3N9+/fd3Nz62kFLy+v9evXV1RUbN68udMiLbtIKpVaW1vb2dmFh4c3NzdXVVURQlpaWjIyMoKCgoKDg21sbLZt28bn8wfWIWrMs3V2dnaJiYklJSVPnjwJDAxcu3btyZMndQlrCJE9PDwIIbdv39Zxc8Ai5AEARmZIiyBrVltmV21tLU3T3V4MUEtISBg/fnx6evrVq1c15/e3iwQCASGEuR5w9+5duVzu6enJLBKJRA4ODjp2CHP3ffLkyVKp1NbWViwWx8XFicXiAaduhhOZOUDMhRYwUsgDAIzMUBdBVldbZldLSwt59WvUE6FQmJmZSVHUypUrFQqFer4uXcTcZdi2bRv1SmVlZbfv1GnP0dGREMI8V8EQCAQuLi7l5eW6hDWEyMzo3czBAiOFPADAyAxpEWTNasvsYn5g+hypxsvLKzo6urS0dNeuXeqZunSRnZ0dISQlJUXzxaqCgoIB7IKapaWlh4fHTz/9pDmzo6NDLBbrEtYQIre1tZFXBwuMFPIAACMzpEWQNast6xhKR6NGjaIo6sWLF32uuWvXrgkTJty8eVM9p781pjWNGTNGKBQWFRUNrNk9CQsLu3nz5r1795hJuVxeWVk5sJf9DCoyc4Ds7e113xywBXkAgJEZ9CLIPVVb/v/s3XtcE1feP/AzkJCEkHARROQOURHFW7UV1LrUXVzl8YKI4q3V2pZabUS8ICoWEVHURR4sbOvlx7qiAgrFropatdS6tW67SkV8ahEvgDdABMJNIMzvj3k1m40IEUgmOJ/3X82ZOWfOHKfJl5k55/uqTeXk5HTjvEFTU1M3N7fS0lJtBiQlJcXY2Fi9pMMc0+20tmjRoiNHjiQnJ9fU1CiVytLS0kePHhFCgoODbW1tO7ducVhYmLOz88KFC4uLi58+fRoeHt7Q0KB6w7Entsxg/oG6JewA1uh11SLQDtYT5Cwt11zrxiTI7WdbfqWmTp06JZFIYmJitDlTbf6t5XI5n8+vr69nPmZlZTHTB6ytrZctW6ax8+rVq9XXE2xniJKSkpi32/r161dUVLRnzx6pVEoIcXZ2/u2332iafv78eXh4uJOTE4/Hs7GxCQwMLCgooGk6ICCAELJx48Y2e3v58uUxY8Ywj9UJIX369PHx8fnuu+9UO5SUlMyZM8fS0lIgELz55ps5OTmqTT2xZYa/v7+9vX1ra2ub7avDeoIGC/8qhghxAGfp/7syJCTEyspKn0dkaPNvXVhYyOPxDh48qJ8udUipVI4bN27//v1omVFRUSEUCnfu3KnNzogDDBaeCwBwncFmjZPJZNHR0dHR0dpnzdEdpVKZnZ2tUCiCg4PRMiMqKmrYsGFyuVwXjYPeIA4AAMMVERERFBQUHByszQuDOpWbm5uZmZmTk9P+kgYcaZkQEh8fn5eXd+rUKT6f3+2Ngz4hDgDgrh6RbXnLli1yuXzr1q3sdmPChAmHDh1SZVvgeMvHjx9//vx5bm6upaVltzcOesZjuwMAwJrY2NjY2Fi2e9ExPz8/Pz8/tnsB/zFt2rRp06ax3QvoHrgfAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3EXRNM12H0BTUFCQwU7iAgDoNPziGCDEAYbo8uXLJSUlbPcCOGH27NmhoaHe3t5sdwQ4YdasWWx3ATQhDgDgNIqi0tPT8e0MwFl4PwAAAIC7EAcAAABwF+IAAAAA7kIcAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLsQBwAAAHAX4gAAAADuQhwAAADAXYgDAAAAuAtxAAAAAHchDgAAAOAuxAEAAADchTgAAACAuxAHAAAAcBfiAAAAAO5CHAAAAMBdiAMAAAC4C3EAAAAAdyEOAAAA4C7EAQAAANyFOAAAAIC7EAcAAABwF+IAAAAA7kIcAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3MVjuwMAoFdHjhxRKBTqJefOnauqqlJ9DAgIsLGx0Xu/AIAdFE3TbPcBAPRn4cKFBw4c4PP5zEfmG4CiKEKIUqk0MzMrKysTCARsdhEA9AjPBQC4Zc6cOYSQ5t+1tLS0tLQw/21sbBwUFIQgAIBTcD8AgFtaWlpsbW0rKyvb3Hr+/Pl33nlHz10CABbhfgAAt/B4vDlz5qieC6iztrYeP368/rsEACxCHADAOXPmzGlubtYo5PP5CxYsMDY2ZqVLAMAWPBcA4Byapp2cnEpLSzXK//Wvf40aNYqVLgEAW3A/AIBzKIqaP3++xqMBR0fHkSNHstUlAGAL4gAALtJ4NMDn8xcuXMjMHgQATsFzAQCO8vDwuHXrlurjjRs3Bg0axGJ/AIAVuB8AwFELFixQPRrw9PREEADATYgDADhq/vz5LS0thBA+n//ee++x3R0AYAeeCwBw18iRI//9739TFHXv3j0nJye2uwMALMD9AADuevfddwkhb731FoIAAM5CvkF2xMfHX758me1eANc1NjZSFPX8+fOgoCC2+wJAjh49ynYXuAj3A9hx+fLlH3/8ke1e9Aw//vgjxopRWlp67NixbmxQKBTa2to6ODh0Y5vd4tixYy8ucwSvsW6/tkF7eD+AHcyfXwh+tYGxUsnIyJg9e3b3/j97+/ZtmUzWjQ12C4qi0tPTZ82axXZHQE90cW2DlnA/AIDTDDAIAAB9QhwAAADAXYgDAAAAuAtxAAAAAHchDgAAAOAuxAEAr7lTp06Zm5v/4x//YLsjunLu3LmIiIjMzEw3NzeKoiiKWrBggfoOfn5+EonE2Nh40KBBV69eZaufhJDW1tZdu3b5+Pi8uKm5uTk2NlYmk5mYmFhYpiS+QAAAIABJREFUWAwePPjevXs9tOWvv/46Li5OqVRqfxRgEeIAgNfc6z0X67PPPktMTFy3bl1gYOCdO3fc3d179eqVmpp68uRJ1T5nz549evTolClTCgoKRowYwVZXCwsL33777bCwsPr6+he3zp49++9///uhQ4fq6+v/7//+z93dvba2toe2PHXqVKFQOGHChKqqKi0PBCzCeoIArzl/f//q6mo9HKihoWHChAk//PCDHo7F2LZtW1pa2i+//CIUClWFiYmJCxYsCAkJKSgoMDc311tn2vfLL79ER0cvWbKkrq7uxcgsLS0tOzv7l19+8fLyIoTY2dkdP368R7e8fPnyO3fuTJ48+eLFizwefmgMGu4HAED32L9/f1lZmd4Od/v27cjIyE2bNqkHAYQQHx+f0NDQBw8erFq1Sm+d6dDQoUMzMzPnzZsnEAhe3PrXv/51xIgRzA/qa9NyVFRUXl5eQkJCJw4N+oQ4AOB1dunSJScnJ4qiPv/8c0JIcnKyWCw2NTU9fvz4pEmTpFKpg4PDkSNHmJ0TExOFQmHv3r0//vhjOzs7oVDo4+Nz5coVZqtcLjcxMenTpw/zcenSpWKxmKKoiooKQkhoaOjKlSuLioooimLWJjp9+rRUKt2yZYuOTi0xMZGm6alTp764KSYmpn///vv27Tt37lybdWmajo+PHzhwoEAgsLS0nD59+q+//spsan+ICCFKpXLjxo1OTk4ikWjIkCHp6eldPJGmpqYff/xx2LBhXWzH0Fq2tLQcP358QkLC6/1k6jWAOADgdTZ27Fj1G/WffPLJihUrGhoaJBJJenp6UVGRm5vbhx9+2NzcTAiRy+ULFy6sr69fvnz5vXv3rl692tLS8qc//amkpIQQkpiYqL7Qb1JS0qZNm1QfExISpkyZ4u7uTtP07du3CSHMa2Ktra06OrWTJ08OGDDA1NT0xU0ikehvf/ubkZHRhx9+WFdX9+IOUVFRERER69evLysru3jxYklJybhx4548eUI6GiJCyNq1a7dv375r165Hjx5NmTJl7ty5P//8c1dO5OHDh01NTf/+9799fX2Z8GvgwIFJSUld//lkveXhw4c/ePDgl19+6eLhQKcQBwBwkY+Pj1QqtbGxCQ4OrqurKy4uVm3i8XjMH8qenp7JyckKhSIlJaUTh/D396+pqYmMjOy+Xv9HXV3d3bt33d3dX7aDt7f3ihUr7t27t3btWo1NDQ0N8fHxM2bMmD9/vrm5uZeX1xdffFFRUbFnzx713docosbGxuTk5ICAgMDAQAsLiw0bNvD5/M6Njwrzbp2Njc2WLVsKCgqePHkyffr0ZcuWHT58uCvNGkLL/fr1I4Tk5+d38XCgU4gDADjNxMSEEKL6Y1fDyJEjTU1NVffMDUdZWRlN023eDFCJiYkZMGBAUlLSpUuX1MsLCgpqa2tHjhypKhk1apSJiYnqCYgG9SG6detWfX394MGDmU0ikahPnz5dHB/m6fugQYN8fHysrKzMzc03bdpkbm6uEZf0xJaZfyDmRgsYLMQBANAegUBQXl7Odi80NTY2kt9/jV5GKBSmpKRQFPX+++83NDSoypnJbGZmZuo7W1hYKBSKDo/LPGXYsGED9bv79++3OadOe3Z2doQQ5jULhomJibOzc1FRUVeaNYSWRSIR+f0fCwwW4gAAeKnm5uaqqioHBwe2O6KJ+YHpcKUab2/vsLCwwsLCzZs3qwotLCwIIRq/+lqepo2NDSFk165dtJrLly934hRUzMzM+vXrd/PmTfXClpaWrk96ZL3lpqYm8vs/FhgsxAEA8FK5ubk0TY8ePZr5yOPxXvYEQc969+5NUZQ26yJs3rzZw8Pj2rVrqpLBgwebmZmpv9x35cqVpqamN954o8PWHB0dhUJhXl5e57r9MrNnz7527dqdO3eYj/X19ffv3+/cZD+Dapn5B7K1te364UB3EAcAwH9pbW199uxZS0vL9evXQ0NDnZycFi5cyGySyWSVlZXZ2dnNzc3l5eX3799Xr2hlZfXw4cN79+4pFIrm5uacnBzdzRs0NTV1c3MrLS3tcE/m6YCxsbF6ycqVK7OyslJTU2tqavLz85csWWJnZxcSEqJNa4sWLTpy5EhycnJNTY1SqSwtLX306BEhJDg42NbWtnPrFoeFhTk7Oy9cuLC4uPjp06fh4eENDQ2qNxx7YssM5h+oW8IO0CEa2DBz5syZM2ey3YueAWOlwkxVf6Uqu3fvZmb8m5qaTp06NSkpiXl1q1+/fkVFRXv27JFKpYQQZ2fn3377jabpkJAQPp9vb2/P4/GkUun06dOLiopUrT19+tTX11coFLq6un766aerV68mhMhksuLiYpqmr1696uzsLBKJxo4d+/jx41OnTkkkkpiYmE6cKSEkPT29/X3kcjmfz6+vr2c+ZmVlMdMHrK2tly1bprHz6tWrp02bpvrY2tq6Y8eOfv368fl8S0vLgICAW7duMZs6HKLnz5+Hh4c7OTnxeDwbG5vAwMCCggKapgMCAgghGzdubLO3ly9fHjNmDPNYnRDSp08fHx+f7777TrVDSUnJnDlzLC0tBQLBm2++mZOTo9rUE1tm+Pv729vbt7a2ttm+uk5c29BdMO7swG+b9jBWKnr4rgwJCbGystLpIbShTRxQWFjI4/EOHjyony51SKlUjhs3bv/+/WiZUVFRIRQKd+7cqc3OiANYhOcCAPBfekqaOJlMFh0dHR0drX3WHN1RKpXZ2dkKhSI4OBgtM6KiooYNGyaXy3XROHQjxAEA0FNFREQEBQUFBwfrJ5FSO3JzczMzM3Nyctpf0oAjLRNC4uPj8/LyTp06xefzu71x6F6IA+C/REdHe3p6SqVSgUAgk8nWrFnzsj+2PvjgA4lEQlHUK7073U4u825x69atTz/9dNCgQRKJhMfjmZub9+/f39/fv4szu7TRztBlZma6ublRakxMTHr37v2HP/xhx44dz54903XftLRu3bqUlJTq6mpXV9djx46x3R2tbNmyRS6Xb926ld1uTJgw4dChQ6rkCxxv+fjx48+fP8/NzbW0tOz2xqH7sf1ggqMM9pn3+PHjk5KSnj59WlNTk56ezufz//znP79sZyb5yrVr17Rs/LfffhszZgwhZOjQodp3Sfux2rdvH5/Pf/vtt0+fPv3s2bPGxsaioqK0tDQfH58vv/xS+yN2TodD5+7ubm5uTtM080L+t99+u3DhQoqi7OzsfvrpJ20OwZ1nqESL9wPgdcKda9sAIS00/BczM7OQkBBmktWsWbMyMzMzMjJKSkocHR272HL7ucy77scffwwJCRk/fvyZM2dU+c7d3Nzc3NwsLCwKCwu7/YgatB86iqIsLCz+8Ic//OEPf/D39589e7a/v/9vv/3W9dVdAABeFZ4LwH85ceKE+kxra2trQsjLlk2lKEr7ltvPZd51MTExSqVy69atqiBAZeLEicuWLdPFQdW90tCpzJw5c+HChWVlZV988YVu+wcA0BbEAYbu4MGDI0eOFAqFYrHYxcWFWR6V7mz29IEDB1IUZWRk9MYbbzA/UWvWrDE3NxcKhX/7299ePPqDBw9EIpGrqyvzkabpHTt2DBgwQCAQmJubM9PHDUFTU9P58+d79er15ptvtr8nW0PXDmaVnpycnFc4YQCA7sLuYwnO0vKZ965duwghW7duffr0aWVl5Zdffjlv3jyapjdu3GhiYnLw4MGqqqrr16+PGDHC2tr68ePHTK3169cTQs6fP19dXV1WVjZu3DixWNzU1ETTdEtLi4uLi5OTU0tLi+ooK1as0FgvnVFXVyeRSORyuapk/fr1FEX95S9/efbsWX19fVJSEnmV9wMYb731Vre/H/Dbb78RQkaPHt1ha2wNHa32foCGmpoaQoijo2OHnefOM1SC9wM4hjvXtgHC/QDD1dzcvGnTJl9f37Vr11pZWVlaWi5evHjUqFFdyZ5ubGy8fPny4uLirKwsZrf6+vrMzMz333//xQ7Exsba2dnFxMQwHxsaGnbt2vXHP/4xLCzMwsJCJBJZWVnpeAy0xfyUamSQexFbQ9c+ZtqFNsnuAAC6HeIAw3X9+vWqqqqJEyeqSpifoq5kTyeEfPDBB+bm5gkJCczH1NTU6dOnMyunqsvKysrIyDhz5oxEImFKbt++XV9fP2HChG46v+7ERAAdPoxna+jax7w4+WI7L0NxACFk9uzZbPcC9Gf27NlaXv/Q7TBfwHAxf+MyOVLVdSV7OlPxo48+2rFjx7/+9a8333zzr3/964szxdPS0uLj43Nzc/v27asqZFKGMHlXDY2Li4tQKGSeDrSDraFrH9NtDw8PLfdn7qC+3mbPnh0aGurt7c12R0BPLl++rIqwQc8QBxgu5oekoqJCo7wr2dMZcrk8ISFh165dS5YscXR0ZLKzqOzevfvMmTMXLlzQ+L0UCoWEkOfPn7/ieeiDQCCYOHHi8ePH//nPfzJLFKirrKxcs2bNvn372Bq69p0+fZoQMmnSJC33nzVrlvaN91CzZ8/29vbmwpmCCuIAtuC5gOFycXGxsrI6e/asRnlXsqczHBwcZs2adezYscjIyNDQUFU5TdPh4eH5+fnZ2dkv/pINHjzYyMjou+++69TZ6FxUVJRAIAgLC2toaNDYdOPGDWYyIVtD147Hjx/v2rXLwcGhzfcMAAB0DXGA4RIIBOvWrbt48aJcLn/w4EFra6tCobh582ZXsqerrFy5sqWl5dmzZ++8846q8ObNm9u3b9+7dy+fz1d/dLdz505CCJNi9dixY/v376+pqbl+/brG63XsGjZs2KFDh27cuDFu3LhTp05VV1c3NzffvXt37969ixcvZhY5Z2voVGiarq2tZdKwlpeXp6enjxkzxtjYODs7W/v3AwAAuhOrsxW4S/u1cj///HMvLy+hUCgUCocPH56UlER3LXu6iq+v7759+9RL8vPz27xIduzYweygUCg++OCDXr16mZmZjR07duPGjYQQBweHX375pcMT6TCXedfHiqbp4uLiVatWeXl5mZmZGRsbW1hYDB8+fPHixf/85z+ZHVgZuq+//nrIkCGmpqYmJiZGRkbk9yUF33zzzejo6KdPn2p5dtyZW0Uwb5BjuHNtGyCK1sEKr9ChoKAgQsjRo0fZ7kgPgLFSycjImD17Nhf+n6UoKj09He8HcAd3rm0DhOcCAAAA3IU4ALrBr7/+2s7M4ODgYLY7CNx17ty5iIgI9dTPCxYsUN/Bz89PIpEYGxsPGjTo6tWrbPXz8OHDo0aNkkgkzs7OixYtevz4sR7qxsXFeXh4iEQisVjs4eERGRnJTFdmtJNK++uvv46Li1Mqldp3EgwXy88luMpg8w4bIIyVCneeoZJuej9g48aNU6ZMqampYT66u7v36tWLEHLixAn13XJycqZNm9b1w3VaWloaISQuLq6qquratWtubm7Dhg1rbm7WdV1/f/+dO3eWlZUpFIqMjAw+n/+nP/1JtbX9VNoJCQnjx49/9uzZq55sm7hzbRsg3A8AgP9oaGjw8fExtKY6Z9u2bWlpaRkZGeoLOyYmJhoZGYWEhFRXV7PYNw1ffvll3759V69ebW5uPmzYsLCwsLy8vJctc9mNdU1MTJYuXWpjY2NmZhYUFDR9+vRvvvnm0aNHzFYmlbaVlZVEIpk1a1ZAQMDp06dLSkqYrcuXLx86dOjkyZNbWlo6d9ZgIBAHAMB/7N+/v6yszNCa6oTbt29HRkZu2rSJWf9KxcfHJzQ09MGDB6tWrWKrby8qKSmxs7Ojfk/k7ejoSAi5f/++rutmZWWpj4+9vT0hRHXzv8NU2lFRUXl5eVj/p6dDHADwuqFfnltZLpebmJj06dOH+bh06VKxWExRFLNsZWho6MqVK4uKiiiKkslkiYmJQqGwd+/eH3/8sZ2dnVAo9PHxUf2h+UpNEUJOnz4tlUq3bNmin0FITEykaXrq1KkvboqJienfv/++ffvOnTvXZt12BrD95NSEEKVSuXHjRicnJ5FINGTIEC0XgXZzc1OPmZgH/G5ubrquq6GwsNDCwsLZ2bnNrS+m0ra0tBw/fnxCQgKN9/x7NHYfS3AWnnlrD2OlouUz1PZzK8+bN8/W1la1844dOwgh5eXlzMfAwEB3d3fV1pCQELFYfPPmzcbGxoKCAuZltOLi4k40deLECYlEEh0drc2Zki6/H+Dm5ubp6alR6O7ufvfuXZqmf/jhByMjIxcXl9raWvqF9wM6nZyapulVq1YJBIJjx449e/Zs3bp1RkZGP/30U4e9zc3N5fP5iYmJNTU1N27cGDhw4MSJE7U8067UZTQ1NZWWlu7evVsgEBw8eLDNfdpMpU3TdEREBHn15OMvwvsBLML9AIDXipa5lbXH4/GYv4w9PT2Tk5MVCkVKSkon2vH396+pqYmMjOxcN15JXV3d3bt3NbI/qPP29l6xYsW9e/fWrl2rsakryakbGxuTk5MDAgICAwMtLCw2bNjA5/O1Ga7x48eHh4fL5XKpVDp48GCFQrFv3z4tT7YrdRmOjo4ODg5RUVHbt29/Wd6/l6XS7tevHyHkZetoQY+AOADgtfKquZVfyciRI01NTVU3yQ1WWVkZTdPM6pAvExMTM2DAgKSkpEuXLqmXdyU59a1bt+rr6wcPHsxsEolEffr00Wa41q9fv2fPnvPnz9fW1t65c8fHx8fb21v1Rp7u6jJKSkrKysoOHz584MCB4cOHv/hWRzuptJlBfvLkifaHA0ODOADgtdLF3ModEggE5eXl3dKU7jQ2NhJCBAJBO/sIhcKUlBSKot5//3313FRdGcC6ujpCyIYNG1SLZ9y/f1/9xbo2PXr0KC4u7qOPPnrnnXfEYrGrq+vevXsfPnzIPGfRXV0VPp9vY2Pj5+eXlpZWUFAQGxurvjUtLW3btm25ubkuLi4v1hWJROT3AYceCnEAwGul67mV29Hc3NxdTekU8+PU4So33t7eYWFhhYWFmzdvVhV2ZQBtbGwIIbt27VJ/+Hr58uX2axUWFiqVSibPOEMqlVpZWRUUFHR4xK7UfZFMJjM2Nlavu3v37tTU1AsXLqgfQl1TUxP5fcChh0IcAPBa6TC3Mo/HY25id0Jubi5N06NHj+56UzrVu3dviqK0WSFg8+bNHh4e165dU5V0JTm1o6OjUCjMy8t7pd4yEYZq1j4hRKFQVFZWMjMAdVf36dOnc+fOVS9hogqmLq1dKm1mkG1tbTs8HBgsxAEAr5UOcyvLZLLKysrs7Ozm5uby8nKNieZWVlYPHz68d++eQqFgfuNbW1ufPXvW0tJy/fr10NBQJyenhQsXdqKpnJwcvc0bNDU1dXNzKy0t7XBP5umA+iz5riSnFgqFixYtOnLkSHJyck1NjVKpLC0tZX6kg4ODbW1t21y32NXV1dfXd+/evRcvXmxoaCgpKWGOtXjxYmYHHdUVi8Vnz569cOFCTU1Nc3PztWvX3nvvPbFYHBYWRrROpc0MspeXV4eDA4aLlVkKgLlw2sNYqWg5t6qd3Mo0TT99+tTX11coFLq6un766aerV68mhMhkMmY24NWrV52dnUUi0dixYx8/fhwSEsLn8+3t7Xk8nlQqnT59elFRUeeaOnXqlEQiiYmJ0eZMSZfnDcrlcj6fX19fz3zMyspipg9YW1svW7ZMY+fVq1erzxvsSnLq58+fh4eHOzk58Xg8GxubwMDAgoICmqYDAgIIIRs3bmyztxUVFaGhoTKZTCAQmJmZjRkz5quvvlJt1V3dqVOnurq6mpmZCQQCd3f34ODg/Px8ZlOHWcgZ/v7+9vb2ra2tbbavPcwbZBHGnR34bdMexkpF/9+VzLKy+jwio+txQGFhIY/He9lseP1TKpXjxo3bv39/D6rboYqKCqFQuHPnzq43hTiARXguAADt6aE55WQyWXR0dHR0tGqVXBYplcrs7GyFQtGJ3Jts1dVGVFTUsGHD5HK5LhoHvUEcAACvp4iIiKCgoODgYNZTCuXm5mZmZubk5LS/pIFB1e1QfHx8Xl7eqVOn+Hx+tzcO+oQ4AADatm7dupSUlOrqaldX12PHjrHdnc7YsmWLXC7funUru92YMGHCoUOHVLkYekTd9h0/fvz58+e5ubmWlpbd3jjoGY/tDgCAgYqNjdVYUqYn8vPz8/PzY7sXr5tp06ZNmzaN7V5A98D9AAAAAO5CHAAAAMBdiAMAAAC4C3EAAAAAd+E9QdaUlpZmZGSw3YsegFm4FGNFCGEy1nBkKDpMzwOvE/xzs4iiaZrtPnBRUFBQD52IBQCgI/g9YgXiAABOoygqPT191qxZbHcEANiB9wMAAAC4C3EAAAAAdyEOAAAA4C7EAQAAANyFOAAAAIC7EAcAAABwF+IAAAAA7kIcAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLsQBwAAAHAX4gAAAADuQhwAAADAXYgDAAAAuAtxAAAAAHchDgAAAOAuxAEAAADchTgAAACAuxAHAAAAcBfiAAAAAO5CHAAAAMBdiAMAAAC4C3EAAAAAdyEOAAAA4C7EAQAAANyFOAAAAIC7EAcAAABwF+IAAAAA7kIcAAAAwF2IAwAAALiLomma7T4AgP6EhITcunVL9fHq1auurq6WlpbMR2Nj4wMHDjg4OLDUOwDQNx7bHQAAvbK1td2zZ496yfXr11X/7ebmhiAAgFPwXACAW+bOnfuyTSYmJgsXLtRjXwCAfXguAMA5gwcPvnnzZpv/79+6dat///767xIAsAX3AwA459133zU2NtYopChq6NChCAIAuAZxAADnzJkzR6lUahQaGxu/9957rPQHAFiE5wIAXOTj43PlypXW1lZVCUVRJSUl9vb2LPYKAPQP9wMAuGjBggUURak+GhkZjR07FkEAAAchDgDgoqCgIPWPFEW9++67bHUGAFiEOACAi6ytrSdMmKB6W5CiqICAAHa7BACsQBwAwFHz589nXg8yNjaeOHFir1692O4RALAAcQAAR82YMcPExIQQQtP0/Pnz2e4OALADcQAAR4nF4v/5n/8hhJiYmEyZMoXt7gAAOxAHAHDXvHnzCCEBAQFisZjtvgAAS2i2zZw5k+0xAAAAYAfbP8K0QeQbHD169IoVK9juBbw+Zs+eHRoa6u3tzXZHeoDU1NTg4GAezyC+Crrd5cuXExIS0tPT2e6IzuGa74mY65PtXhjAeoLMPOajR4+y2w14nVAUlZ6ePmvWLLY70gM0NjYKhUK2e6ErGRkZs2fPZv1bTg9wzfdEBnJ94v0AAE57jYMAANAG4gAAAADuQhwAAADAXYgDAAAAuAtxAAAAAHchDgAA+C+nTp0yNzf/xz/+wXZHdOXcuXMRERGZmZlubm4URVEUtWDBAvUd/Pz8JBKJsbHxoEGDrl69ylY/Dx8+PGrUKIlE4uzsvGjRosePH+uhblxcnIeHh0gkEovFHh4ekZGRNTU1qq3R0dGenp5SqVQgEMhksjVr1tTW1jKbvv7667i4OKVSqX0nDQTiAACA/8L6PC6d+uyzzxITE9etWxcYGHjnzh13d/devXqlpqaePHlStc/Zs2ePHj06ZcqUgoKCESNGsNLP9PT0efPmBQUFlZaWHj9+/OLFi5MmTWppadF13e+///7DDz8sLi5+8uTJ5s2b4+Li1Be7u3DhwrJly+7du1dRUREbG5uQkKBK4T116lShUDhhwoSqqqpOnC+b2F3GiKbpmTNnzpw5k+1ewGuFEJKens52L4B9zApCbPfiperr6729vbulKS2v+a1bt/bv37+hoUFV4u7ufujQISMjI3t7+6qqKlV5Tk7OtGnTuqVvnePr69u3b9/W1lbm4+eff04IuXTpkq7rBgQEqI8P8zP/8OFD5qO/v39LS4tqK7NgQ3FxsapELpd7e3s3NzdrcywDuT5xPwAAgB379+8vKyvT2+Fu374dGRm5adMmjUUjfHx8QkNDHzx4sGrVKr11pkMlJSV2dnYURTEfHR0dCSH379/Xdd2srCz18bG3tyeEqG7+nzhxwtjYWLXV2tqaEFJfX68qiYqKysvLM4RVArWHOAAA4D8uXbrk5OREURTzR2RycrJYLDY1NT1+/PikSZOkUqmDg8ORI0eYnRMTE4VCYe/evT/++GM7OzuhUOjj43PlyhVmq1wuNzEx6dOnD/Nx6dKlYrGYoqiKigpCSGho6MqVK4uKiiiKkslkhJDTp09LpdItW7bo6NQSExNpmp46deqLm2JiYvr3779v375z5861WZem6fj4+IEDBwoEAktLy+nTp//666/MpvaHiBCiVCo3btzo5OQkEomGDBmi5TLPbm5u6kES84Dfzc1N13U1FBYWWlhYODs7t7n1wYMHIpHI1dVVVWJpaTl+/PiEhAS6Bz1dYvl+BJ4LgA4QPBcAmqY7e9+1pKSEELJ7927m4/r16wkh58+fr66uLisrGzdunFgsbmpqYraGhISIxeKbN282NjYWFBQw76apbhTPmzfP1tZW1fKOHTsIIeXl5czHwMBAd3d31dYTJ05IJJLo6OhOnKk217ybm5unp6dGobu7+927d2ma/uGHH4yMjFxcXGpra+kXngts3LjRxMTk4MGDVVVV169fHzFihLW19ePHj5mt7Q/RqlWrBALBsWPHnj17tm7dOiMjo59++qnDM8rNzeXz+YmJiTU1NTdu3Bg4cODEiRO1HI2u1GU0NTWVlpbu3r1bIBAcPHiwzX3q6uokEolcLtcoj4iIIIRcu3atw6PguQAAQI/h4+MjlUptbGyCg4Pr6uqKi4tVm3g8HvOHsqenZ3JyskKhSElJ6cQh/P39a2pqIiMju6/X/1FXV3f37l13d/eX7eDt7b1ixYp79+6tXbtWY1NDQ0N8fPyMGTPmz59vbm7u5eX1xRdfVFRU7NmzR323NoeosbExOTk5ICAgMDDQwsJiw4YZI2ctAAAgAElEQVQNfD5fm/EZP358eHi4XC6XSqWDBw9WKBT79u3T8mS7Upfh6Ojo4OAQFRW1ffv22bNnt7lPbGysnZ1dTEyMRnm/fv0IIfn5+a90RBYhDgAAeAUmJiaEkObm5ja3jhw50tTUVHXP3HCUlZXRNG1qatrOPjExMQMGDEhKSrp06ZJ6eUFBQW1t7ciRI1Ulo0aNMjExUT0B0aA+RLdu3aqvrx88eDCzSSQS9enTR5vxWb9+/Z49e86fP19bW3vnzh0fHx9vb2/mVo1O6zJKSkrKysoOHz584MCB4cOHv/gaR1ZWVkZGxpkzZyQSicYmZpCfPHmi/eHYhTgAAKA7CQSC8vJytnuhqbGxkRAiEAja2UcoFKakpFAU9f777zc0NKjKmYlwZmZm6jtbWFgoFIoOj1tXV0cI2bBhA/W7+/fvq79Y16ZHjx7FxcV99NFH77zzjlgsdnV13bt378OHD5kHK7qrq8Ln821sbPz8/NLS0goKCmJjY9W3pqWlbdu2LTc318XF5cW6IpGI/D7gPQLiAACAbtPc3FxVVeXg4MB2RzQxP04drnLj7e0dFhZWWFi4efNmVaGFhQUhRONXX8vTtLGxIYTs2rVL/YH05cuX269VWFioVCr79u2rKpFKpVZWVgUFBR0esSt1XySTyYyNjdXr7t69OzU19cKFC+qHUNfU1ER+H/AeAXEAAEC3yc3NpWl69OjRzEcej/eyJwh61rt3b4qiqqurO9xz8+bNHh4e165dU5UMHjzYzMzs559/VpVcuXKlqanpjTfe6LA1R0dHoVCYl5f3Sr1lIoxHjx6pShQKRWVlJTMDUHd1nz59OnfuXPUSJqpg6tI0HR4enp+fn52drXF3RB0zyLa2th0ezkAgDgAA6JLW1tZnz561tLRcv349NDTUyclp4cKFzCaZTFZZWZmdnd3c3FxeXq4xhd3Kyurhw4f37t1TKBTNzc05OTm6mzdoamrq5uZWWlra4Z7M0wH1WfJCoXDlypVZWVmpqak1NTX5+flLliyxs7MLCQnRprVFixYdOXIkOTm5pqZGqVSWlpYyP9LBwcG2trZtrlvs6urq6+u7d+/eixcvNjQ0lJSUMMdavHgxs4OO6orF4rNnz164cKGmpqa5ufnatWvvvfeeWCwOCwsjhNy8eXP79u179+7l8/mUmp07d6o3wgyyl5dXh4NjKFiZpaAO8wah2xHMGwSapjs1L2v37t3MjH9TU9OpU6cmJSUxr33169evqKhoz549UqmUEOLs7Pzbb7/RNB0SEsLn8+3t7Xk8nlQqnT59elFRkaq1p0+f+vr6CoVCV1fXTz/9dPXq1YQQmUzGTCy8evWqs7OzSCQaO3bs48ePT506JZFIYmJiOnGm2lzzcrmcz+fX19czH7OyspjpA9bW1suWLdPYefXq1erzBltbW3fs2NGvXz8+n29paRkQEHDr1i1mU4dD9Pz58/DwcCcnJx6PZ2NjExgYWFBQQNN0QEAAIWTjxo1t9raioiI0NFQmkwkEAjMzszFjxnz11VeqrbqrO3XqVFdXVzMzM4FA4O7uHhwcnJ+fz2x62RSAHTt2qLfg7+9vb2+vWs2wHQYyb5D9HiAOgG6HOAAYevieDQkJsbKy0ukhtKHNNV9YWMjj8V42G17/lErluHHj9u/f34PqdqiiokIoFO7cuVObnQ0kDsBzAQCALukpKeZkMll0dHR0dLRqlVwWKZXK7OxshUIRHBzcU+pqIyoqatiwYXK5XBeN60jPiANGjRplbGw8bNgwXTS+aNEioVBIUVQPmubRjp07dzIvBH3xxRdMSfcmUdVzStbW1tZdu3b5+Ph0b7PqGVcZPB7P2tr6j3/8Y1ZWVncdpf1Ly8Czvr5mFxIwIiIigoKCgoODtXlhUKdyc3MzMzNzcnLaX9LAoOp2KD4+Pi8v79SpU3w+v9sb152eEQf89NNPvr6+Omo8JSXFoLJrdNGqVat++OEH9RK6W5e57t7W2ldYWPj222+HhYV1ONv4VakyrpqbmzN3xsrLy9PT0x88eBAYGKjl+ucdav/SMvCsr6/ThaQ769atS0lJqa6udnV1PXbsGNvd0cqWLVvkcvnWrVvZ7caECRMOHTqkSr7QI+q27/jx48+fP8/NzbW0tOz2xnWqZ8QBDFXyKO01NDR0+5+SPY6/v391dfWUKVM6V11jDLvYmvZ++eWXtWvXLlmyREf3gTRYWlpOmDDhf//3fwkhGRkZHe7fjZdWYmKikZFRSEgI63+ita+HXkg6FRsb+/z5c5qm7969q56l3sD5+flt27aN7V68bqZNmxYREaE+z6Kn6ElxQCfutLxSWs9OxBlcoOfUqCpDhw7NzMycN29e+yugdS9mdTBm9bT2deOlZZhZX7sdWxcSALSvJ8UBt2/f9vDwEIvFIpFo3Lhx6itgf//9956enubm5kKh0MvL68yZM6SttJ6EkIMHD44cOVIoFIrFYhcXF9WaWUZGRidPnpw0aZK5ubmdnd3/+3//T5sudZhwk355ss7t27ebmppKJJKysrKVK1fa29svWbJELBYbGRm98cYbtra2fD5fLBaPGDFi3LhxzFocFhYWa9asaf+sNWgkUb19+zb1gm+++UbLMdRorf0T7HBwDND169cJIePHj1eV6OfS6krWV1xIANAlrMxSUKflvMEJEya4ubndvXu3ubn5xo0bb731llAoZCan0jR99OjRqKioysrKp0+fjh49ulevXky5RlrPXbt2EUK2bt369OnTysrKL7/8ct68ebRa0syqqqrKysrJkycLBIK6ujpt+t9+wk1tknUuX7589+7dM2bM+L//+7/PPvuMEHLlypW6urqKioo///nPhJCTJ0+Wl5fX1dUx76Dm5eW1f9aFhYWEkL/+9a/MR/UkqoWFhWvXrmVO7dGjR5aWlj4+PkqlUvsx1EjJ2pVspFp66623hg4d+kpViHbzBtXfD6ivr8/JyXF2dvbz82PyrjJ0fWl1Y9ZXXEgvMpB5WXqg5TUPBsVArk/2e6B9HKD+Y8D83bZq1aoX92QSQjDJtdS/epqamiwsLHx9fVV7trS0JCQk0L9/yzQ0NDDlf//73wkhN27c0Kb/GnWTkpIIIbdv36Zpur6+3szMLDg4WLXzv/71L0KIKr+4Rl2appmvb4VCwXw8cOAAIUS1igVTPS0trf2zbufrW11AQIBQKPz111/bb62dr+9XPUH1wdGeTuMAjbDYy8vrwIEDzBPfF+ni0lLFATRNr1y5khDCrOiiHgfgQur0hWQg37N6gDigJzKQ65PXmXsIBsDLy8vc3JyJBjQwrxG8OKP3+vXrVVVVEydOVJUYGxsvX778ZS10blVw9YSbr5qs82WttbS0dNixl531y2RkZHz11VdxcXEDBgzodGtdyUZqIMzNzZm3AVpaWp48eXL27Fm5XB4bG3vp0iVra2uNnXV9acXExJw4cSIpKUkj3zkuJA2veiFp8+Lna6DD5D1gaAzkn6ynxgGEED6fr/oiOHny5I4dOwoKCphFodvcv6amhvyeOEs/upKsUxvanHWbnj59+umnn44aNYr5A7TTren6BPWJx+PZ29svWrRIqVR++OGHW7du/ctf/kL0e2kx67qPHTv2/fffj4uLU5XjQuoijbjqdZWQkJCQkMB2L6Dn6UnvCapraWmprKx0cnIihBQXFwcEBPTp0+fKlSvV1dXqX6DqmByRFRUVeutkV5J1dkjLs27T8uXLq6qq1FOJdK41nZ4gW5jsIDdv3iRsXFrdnvW1Q1y4kNi+7aoPBM8FeqDuWqqki3pqHPDtt9+2trYyS6zk5+c3Nzd/8sknbm5uzPJtbVZxcXGxsrI6e/as3jrZlWSdHdLyrF908uTJQ4cORUZGDho0iClZvXp151rT6Qmy5d///jchhLnLzcql1b1ZXzuECwmA43pSHNDU1FRdXd3S0nL16lW5XO7s7Mwk92TuCpw7d66xsbGwsFD9maJ6Wk8jI6N169ZdvHhRLpc/ePCgtbVVoVAwf/bpSFeSdXaonbNuR01Nzccffzxs2LC1a9cSQhobG3/++ee8vDwtx1DjNq9OT1BvGhoamMxgDx8+TElJ2bBhg7W19YoVKwhLl1b3Zn3tEC4kAK5j+76ItvMFUlJSfH19e/fuzePxevXqNWfOnPv376u2hoeHW1lZWVhYBAUFMTOS3d3di4uLNdJ60jT9+eefe3l5CYVCoVA4fPjwpKSkuLg4kUhEfk+amZqayqwK6eDg0OGUgQ4TbraTrFN1XEdHRyYDWEJCAtOai4vL999/v23bNnNzc0KIra3toUOH0tLSbG1tCSGWlpZHjhx52VmHhoYyu4nF4hkzZmgkUdXIk82YPHmylmO4YcMG9dbaP8EOB6d9ly9fHjNmjJ2dHdPJPn36+Pj4fPfddx1WpLW4R6rKuKpOIBD069fvk08+YXLCMnR3aXVX1ldcSO0wkPex9aDDax4MkIFcnxTN9irfQUFBhJCjR4+y2w14nVAUlZ6ePmvWLLY7AizLyMiYPXs2699yeoBrvicykOuzJz0XAAAAgO6FOKA9v/7664uLp6roKH01F2BgAQAMBOKA9nh4eLTzTCUtLY3tDvZUGFgAFp07dy4iIiIzM9PNzY0JvhcsWKC+g5+fn0QiMTY2HjRo0NWrV9nq5+HDh0eNGiWRSJydnRctWvT48WM91I2Li/Pw8BCJRGKx2MPDIzIyklkghBEdHe3p6SmVSgUCgUwmW7NmTW1tLbPp66+/jouL034NLsOBOAAAgEM+++yzxMTEdevWBQYG3rlzx93dvVevXqmpqSdPnlTtc/bs2aNHj06ZMqWgoICZnq1/6enp8+bNCwoKKi0tPX78+MWLFydNmqRaE1N3db///vsPP/ywuLj4yZMnmzdvjouLU88ofeHChWXLlt27d6+ioiI2NjYhIYF5xY0QMnXqVKFQOGHCBG0SlhoUxAEAAJ3X0NDg4+NjaE29zLZt29LS0jIyMiQSiaowMTHRyMgoJCSkurpap0d/JV9++WXfvn1Xr15tbm4+bNiwsLCwvLw8Lee1dqWuiYnJ0qVLbWxszMzMgoKCpk+f/s033zx69IjZamZmFhISYmVlJZFIZs2aFRAQcPr0aSZZBiFk+fLlQ4cOnTx5spYxh4FAHAAA0Hn79+8vKysztKbadPv27cjIyE2bNgmFQvVyHx+f0NDQBw8erFq1SndHf1UlJSV2dnaqpagcHR0JIffv39d13aysLPXxsbe3J4Sobv6fOHFCfW0PJgtJfX29qiQqKiovL69nLfCMOAAAuI6m6fj4+IEDBwoEAktLy+nTp//666/MJrlcbmJiwqx2QAhZunSpWCymKIpZRjo0NHTlypVFRUUURclkssTERKFQ2Lt3748//tjOzk4oFPr4+Kj+DH2lpgghp0+flkqlW7Zs6a7TTExMpGl66tSpL26KiYnp37//vn37zp0796pDlJycLBaLTU1Njx8/PmnSJKlU6uDgcOTIEVVdpVK5ceNGJycnkUg0ZMgQLRfTdXNzU4+KmAf8bm5uuq6robCw0MLCwtnZuc2tDx48EIlErq6uqhJLS8vx48cz6UY7cTh2dNtKBJ2l5TpCANojWFMFaJrWep2WjRs3mpiYHDx4sKqq6vr16yNGjLC2tmaWh6Jpet68eba2tqqdd+zYQQgpLy9nPmrkUw4JCRGLxTdv3mxsbCwoKGBeVVOtTPVKTZ04cUIikaiSL7dPm2vezc3N09NTo1CV+fqHH34wMjJycXGpra2l/zvzNd3REDGJoc+fP19dXV1WVjZu3DixWNzU1MRsXbVqlUAgOHbs2LNnz9atW2dkZPTTTz91eEa5ubl8Pj8xMbGmpubGjRsDBw6cOHGiNkPRxbqMpqam0tLS3bt3CwQCZnmuF9XV1UkkErlcrlEeERFBCLl27VqHRzGQdYRwPwAAOK2hoSE+Pn7GjBnz5883Nzf38vL64osvKioq9uzZ07kGeTwe83ezp6dncnKyQqFISUnpRDv+/v41NTWRkZGd64aGurq6u3fvvriMpoq3t/eKFSvu3bvHrBWtTssh8vHxkUqlNjY2wcHBdXV1xcXFhJDGxsbk5OSAgIDAwEALC4sNGzbw+XxtBmT8+PHh4eFyuVwqlQ4ePFihUOzbt0/Lk+1KXYajo6ODg0NUVNT27dtflq8yNjbWzs4uJiZGo7xfv36EkPz8/Fc6IosQBwAApxUUFNTW1o4cOVJVMmrUKBMTEy1fK2vfyJEjTU1NVbfQWVRWVkbTNLNC88vExMQMGDAgKSnp0qVL6uWvOkQmJiaEECaLxK1bt+rr6wcPHsxsEolEffr00WZA1q9fv2fPnvPnz9fW1t65c8fHx8fb21v1Rp7u6jJKSkrKysoOHz584MCB4cOHv/jeRlZWVkZGxpkzZ9TfuGQwg/zkyRPtD8cuxAEAwGnMLC8zMzP1QgsLC408yJ0mEAjKy8u7pamuaGxsZDrTzj5MjiuKot5///2GhgZVeVeGqK6ujhCyYcMG1UJh9+/fV3+xrk2PHj2Ki4v76KOP3nnnHbFY7Orqunfv3ocPHzJPUnRXV4XP59vY2Pj5+aWlpRUUFMTGxqpvTUtL27ZtW25urouLy4t1mXwfzID3CIgDAIDTLCwsCCEaP2lVVVUODg5db7y5ubm7muoi5sepw1VuvL29w8LCCgsLN2/erCrsyhDZ2NgQQnbt2qX+QPry5cvt1yosLFQqlX379lWVSKVSKyurgoKCDo/YlbovkslkxsbG6nV3796dmpp64cIF9UOoa2pqIr8PeI+AOAAAOG3w4MFmZmY///yzquTKlStNTU1vvPEG85HH42kkStZebm4uTdOjR4/uelNd1Lt3b4qitFkhYPPmzR4eHteuXVOVdDhE7XB0dBQKhXl5ea/UWybCUM3aJ4QoFIrKykpmBqDu6j59+nTu3LnqJUxUwdSlaTo8PDw/Pz87O1vj7og6ZpCZdJ09AuIAAOA0oVC4cuXKrKys1NTUmpqa/Pz8JUuW2NnZhYSEMDvIZLLKysrs7Ozm5uby8nKNaehWVlYPHz68d++eQqFgfuNbW1ufPXvW0tJy/fr10NBQJyenhQsXdqKpnJycbpw3aGpq6ubmVlpaqs2ApKSkqM+S73CI2m9t0aJFR44cSU5OrqmpUSqVpaWlzI90cHCwra1tm+sWu7q6+vr67t279+LFiw0NDSUlJcyxFi9ezOygo7pisfjs2bMXLlyoqalpbm6+du3ae++9JxaLw8LCCCE3b97cvn373r17+Xy+ekoUjTTczCB7eXl1ODiGgpVZCuowbxC6HcG8QaBpWut5Wa2trTt27OjXrx+fz7e0tAwICLh165Zq69OnT319fYVCoaur66effrp69WpCiEwmY2YDXr161dnZWSQSjR079vHjxyEhIXw+397ensfjSaXS6dOnFxUVda6pU6dOSSSSmJgYbc5Um2teLpfz+fz6+nrmY1ZWFjN9wNraetmyZRo7r169Wn3eYDtDlJSUxLwZ169fv6Kioj179kilUkKIs7Pzb7/9RtP08+fPw8PDnZyceDyejY1NYGBgQUEBTdMBAQGEkI0bN7bZ24qKitDQUJlMJhAIzMzMxowZ89VXX6m26q7u1KlTXV1dzczMBAKBu7t7cHBwfn4+s+llUwB27Nih3oK/v7+9vX1ra2ub7aszkHmD7PcAcQB0O8QBwND/9yyz6Kw+j8jQ5povLCzk8Xgvmw2vf0qlcty4cfv37+9BdTtUUVEhFAp37typzc4GEgfguQAAQHcy2IxzMpksOjo6OjpatUoui5RKZXZ2tkKh6ESecbbqaiMqKmrYsGFyuVwXjesI4gAAAK6IiIgICgoKDg5mPaVQbm5uZmZmTk5O+0saGFTdDsXHx+fl5Z06dYrP53d747qDOAAAoHusW7cuJSWlurra1dX12LFjbHenbVu2bJHL5Vu3bmW3GxMmTDh06JAq20KPqNu+48ePP3/+PDc319LSstsb1yke2x0AAHhNxMbGaiw4Y5j8/Pz8/PzY7sXrZtq0adOmTWO7F52B+wEAAADchTgAAACAuxAHAAAAcBfiAAAAAO4yiPcEf/zxx6CgILZ7Aa+VXbt2HT16lO1eAMuYFV458vWCa77H0WaZZz2gaJpmtwfx8fEd5p4CAB3JyckZPny4LqZRAYA2WI/e2I8DAIBFFEWlp6fPmjWL7Y4AADvwfgAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLsQBwAAAHAX4gAAAADuQhwAAADAXYgDAAAAuAtxAAAAAHchDgAAAOAuxAEAAADchTgAAACAuxAHAAAAcBfiAAAAAO5CHAAAAMBdiAMAAAC4C3EAAAAAdyEOAAAA4C7EAQAAANyFOAAAAIC7EAcAAABwF+IAAAAA7kIcAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLsQBwAAAHAX4gAAAADuQhwAAADAXYgDAAAAuIvHdgcAQK+qqqpomlYvqaure/bsmeqjmZkZn8/Xe78AgB2UxjcCALze3nnnnW+//fZlW42NjR88eGBra6vPLgEAi/BcAIBb5syZQ1FUm5uMjIzefvttBAEAnII4AIBbZs6cyeO1/UCQoqh3331Xz/0BAHYhDgDgFktLSz8/P2Nj4xc3GRkZBQQE6L9LAMAixAEAnDN//vzW1laNQh6P5+/vb25uzkqXAIAtiAMAOGfq1KkCgUCjUKlUzp8/n5X+AACLEAcAcI6pqWlAQIDG5ECRSDR58mS2ugQAbEEcAMBFc+fObW5uVn3k8/kzZ84UiUQsdgkAWIE4AICLJk6cqP4qQHNz89y5c1nsDwCwBXEAABfx+fzg4GATExPmo4WFxYQJE9jtEgCwAnEAAEfNmTOnqamJEMLn8+fPn/+yRQUA4PWGdYUBOKq1tbVv375PnjwhhFy6dGnMmDFs9wgAWID7AQAcZWRktGDBAkKInZ2dj48P290BAHbgTqCelJaW/vDDD2z3AuC/WFtbE0Leeuuto0ePst0XgP/i6Ojo7e3Ndi84Ac8F9CQjI2P27Nls9wIAoGeYOXMmwlP9wP0AvULUpQtMjIWxfSVBQUGEkKNHjx47dmzmzJlsd0dXcG30UMz1CfqB9wMAOO01DgIAQBuIAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLsQBwCAtk6dOmVubv6Pf/yD7Y7oyrlz5yIiIjIzM93c3CiKoiiKWXJRxc/PTyKRGBsbDxo06OrVq2z18/Dhw6NGjZJIJM7OzosWLXr8+LEe6sbFxXl4eIhEIrFY7OHhERkZWVNTo9oaHR3t6ekplUoFAoFMJluzZk1tbS2z6euvv46Li1Mqldp3EvQJcQAAaOv1noj/2WefJSYmrlu3LjAw8M6dO+7u7r169UpNTT158qRqn7Nnzx49enTKlCkFBQUjRoxgpZ/p6enz5s0LCgoqLS09fvz4xYsXJ02a1NLSouu633///YcfflhcXPzkyZPNmzfHxcWpTzq9cOHCsmXL7t27V1FRERsbm5CQoFoDYOrUqUKhcMKECVVVVZ04X9A1xAEAoC1/f//q6uopU6bo+kANDQ16Tnmwbdu2tLS0jIwMiUSiKkxMTDQyMgoJCamurtZnZ9r35Zdf9u3bd/Xq1ebm5sOGDQsLC8vLy7ty5Yqu65qYmCxdutTGxsbMzCwoKGj69OnffPPNo0ePmK1mZmYhISFWVlYSiWTWrFkBAQGnT58uKSlhti5fvnzo0KGTJ0/WMuYAfUIcAAAGZ//+/WVlZXo73O3btyMjIzdt2iQUCtXLfXx8QkNDHzx4sGrVKr11pkMlJSV2dnYURTEfHR0dCSH379/Xdd2srCz18bG3tyeEqG7+nzhxwtjYWLWVSV1RX1+vKomKisrLy0tISNDmWKBPiAMAQCuXLl1ycnKiKOrzzz8nhCQnJ4vFYlNT0+PHj0+aNEkqlTo4OBw5coTZOTExUSgU9u7d++OPP7azsxMKhT4+Pqq/O+VyuYmJSZ8+fZiPS5cuFYvFFEVVVFQQQkJDQ1euXFlUVERRlEwmI4ScPn1aKpVu2bJFR6eWmJhI0/TUqVNf3BQTE9O/f/99+/adO3euzbo0TcfHxw8cOFAgEFhaWk6fPv3XX39lNrU/RIQQpVK5ceNGJycnkUg0ZMiQ9PR0bXrr5uamHiQxD/jd3Nx0XVdDYWGhhYWFs7Nzm1sfPHggEolcXV1VJZaWluPHj09ISHi9ny71SDToBfN/ONu9eD1hbDth5syZM2fOfNVazG3e3bt3Mx/Xr19PCDl//nx1dXVZWdm4cePEYnFTUxOzNSQkRCwW37x5s7GxsaCggHk3rbi4mNk6b948W1tbVcs7duwghJSXlzMfAwMD3d3dVVtPnDghkUiio6NftcNaXhtubm6enp4ahe7u7nfv3qVp+ocffjAyMnJxcamtraVpOicnZ9q0aardNm7caGJicvDgwaqqquvXr48YMcLa2vrx48fM1vaHaNWqVQKB4NixY8+ePVu3bp2RkdFPP/3UYW9zc3P5fH5iYmJNTc2NGzcGDhw4ceJErYaja3UZTU1NpaWlu3fvFggEBw8ebHOfuro6iUQil8s1yiMiIggh165d6/Aonbs+oXNwPwAAusTHx0cqldrY2AQHB9fV1RUXF6s28Xg85g9lT0/P5ORkhUKRkpLSiUP4+/vX1NRERkZ2X6//o66u7u7du+7u7i/bwdvbe8WKFffu3Vu7dq3GpoaGhvj4+BkzZsyfP9/c3NzLy+uLL76oqKjYs2eP+m5tDlFjY2NycnJAQEBgYKCFhcWGDRv4fL424zN+/Pjw8HC5XC6VSgcPHqxQKPbt26flyXalLsPR0dHBwSEqKmr79u0vy6EaGxtrZ2cXExOjUd6vXz9CSH5+/gKottkAACAASURBVCsdEXQNcQAAdA8TExNCSHNzc5tbR44caWpqqrpnbjjKyspomjY1NW1nn5iYmAEDBiQlJV26dEm9vKCgoLa2duTIkaqSUaNGmZiYvOzNO/UhunXrVn19/eDBg5lNIpGoT58+2ozP+vXr9+zZc/78+dra2jt37vj4+Hh7e6veyNNdXUZJSUlZWdnhw4cPHDgwfPjwF1/jyMrKysjIOHPmjPoblwxmkJ88eaL94UAPEAcAgJ4IBILy8nK2e6GpsbGRECIQCNrZRygUpqSkUBT1/vvvNzQ0qMqZiXBmZmbqO1tYWCgUig6PW1dXRwjZsGED9bv79++rv1jXpkePHsXFxX300UfvvPOOWCx2dXXdu3fvw4cPmQcruqurwufzbWxs/Pz80tLSCgoKYmNj1bempaVt27YtNzfXxcXlxboikYj8PuBgOBAHAIA+NDc3V1VVOTg4sN0RTcyPU4er3Hh7e4eFhRUWFm7evFlVaGFhQQjR+NXX8jRtbGwIIbt27VJ/Unv58uX2axUWFiqVyr59+6pKpFKplZVVQUFBh0fsSt0XyWQyY2Nj9bq7d+9OTU29cOGC+iHUNTU1kd8HHAwH4gAA0Ifc3FyapkePHs185PF4L3uCoGe9e/emKEqbFQI2b97s4eFx7do1VcngwYPNzMx+/vlnVcmVK1eampreeOONDltzdHQUCoV5eXmv1FsmwlDN2ieEKBSKyspKZgag7uo+ffp07ty56iVMVMHUpWk6PDw8Pz8/Oztb4+6IOmaQbW1tOzwc6BPiAADQldbW1mfPnrW0tFy/fj00NNTJyWnhwoXMJplMVllZmZ2d3dzcXF5erjGF3crK6uHDh/fu3VMoFM3NzTk5ObqbN2hqaurm5lZaWtrhnszTAfVZ8kKhcOXKlVlZWampqTU1Nfn5+UuWLLGzswsJCdGmtUWLFh05ciQ5ObmmpkapVJaWljI/0sHBwba2tm2uW+zq6urr67t3796LFy82NDSUlJQwx1q8eDGzg47qisXis2fPXrhwoaamprm5+dq1a++9955YLA4LCyOE3Lx5c/v27Xv37uXz+ZSanTt3qjfCDLKXl1eHgwP6hDgAALTy+eefjxo1ihASHh4+bdq05OTkXbt2EUKGDBly586dvXv3rly5khDy5z//ubCwkKnS2Njo5eUlEonGjRvXv3//b7/9VvUY/pNPPvH19Z0zZ86AAQM2b97M3CtWvbO2ZMmS3r17e3p6Tp48ubKyUten5u/vX1BQoHrw/9VXX8lksqKiolGjRn366afqe44ePZr55VP57LPPYmNjo6Ojra2tx48f7+LikpubKxaLCSEdDlFCQsKKFSvi4uJ69eplZ2cXGhr67NkzQkhTU1NZWdnx48df7CpFUUePHg0ODl68eLGlpaWnp2dxcXFmZua4ceOYHXRUVygUjhkz5oMPPrC3t5dIJEFBQS4uLj/++CPzniOt3ZIAP/30k729/ZAhQ7TZGfSHjcmKXIQ57rqDse0EPczPZlaZ1ekhOqTltVFYWMjj8V42G17/lErluHHj9u/f34PqdqiiokIoFO7cuVObnbF+gD7hfgAA6EpPSTEnk8mio6Ojo6NVq+SySKlUZmdnKxSK4ODgnlJXG1FRUcOGDZPL5bpoHLoCccBrRRdpYfWcara1tXXXrl26zjFz+PBhiqK6eJTXYLRBJSIiIigoKDg4mPWUQrm5uZmZmTk5Oe0vaWBQdTsUHx+fl5d36tQpPp/f7Y1DFyEOeK3QOli4WxdtvkxhYeHbb78dFhbW4SzqLjp8+LC7u/vly5dv377d6UZ6+mjr1Lp161JSUqqrq11dXY8dO8Z2d7SyZcsWuVy+detWdrsxYcKEQ4cOqZIv9Ii67Tt+/Pjz589zc3MtLS27vXHoBuw+luAOHT3Drq+v9/b2Nvw2tZGXlzdjxozU1NRhw4YNHTpU+4qvOrYVFRWurq6pqamEkMjISO0rvk6jzZHnr3h3pIfiyPVpIHA/oGfTRXpWPad8VRk6dGhmZua8efPaX9mt6zIyMvz9/adOnSoUCplXw7Ss+DqNNgAAA3GAYfn+++89PT3Nzc2FQqGXl9eZM2dUmw4ePDhy5EihUCgWi11cXDZv3qyRnlUjLezAgQMpijIyMnrjjTeY2+xr1qxhWv7b3/72/9m787gojvR/4NXAMDMMMxyKiNyHiohndCMYl6AbjGFFERC8Eq+EGM2IqFFEDCKiqAu8MJBE9Mdmvbg0YFSMq4YYo+ZYJSJuDKIoeCEIDKfA0L8/+pXZ+SLHcAw92J/3X+nqrurqmonz0N1VT3vn6rhN0rMsqxriyJEjc+bMEYvFHh4eRUVFP/zww8vHYLQBgCtYvh/BGSren0xPTw8PD3/+/Hl5efmkSZMGDBjAlDOzkHfs2FFeXv78+fMvv/xywYIF9EvpWZXTwjY3N9vY2FhZWTU3NysOWLNmjWId0/bO1UGbdM+yrKro9ddfV99zgfv375uYmDBjcvDgQULIsmXLWh3DhdHmyH1XPBfopzjy/dQQuB+gWXx9fT/99FMjIyNjY2MvL6/y8vJnz541NTVt3brV3d1948aNxsbGRkZGy5YtY1Z06YC2tvbq1asfPHhw/PhxpqSuru7YsWNLly7t4Fwdt9mTLKsa4siRI3//+9+ZJeG8vLz4fH56erpy5hiMNgBwig7bHYB2MRNs5HL5jRs3Kisrp0+frtjF/Op02sLy5cvDw8Pj4uL8/PwIIYcOHZo9e7ZEIungXB032JMsqxriyJEjigxpEonEw8Pjm2++ycrKUsyZ5s5oX716lenqK4xZyPaVv8xXz9WrVxWpKEDdcD9As5w6derNN980MTHh8/mffPIJUyiTycifmc26RF9f/4MPPrh8+fLPP/9MCPn888+VF/Fo81wd60mWVU1w8+bNvLy8mTNnKtY/Z2bq/+tf/1Icg9EGAE7B/QAN8uDBA29v7zlz5vy///f/hgwZsnfvXuYHg0niWVZW1o02pVJpXFxcbGzsihUrLC0t7e3tOz5Xx3qSZVUTHD58eN68eUeOHFGUVFRUmJubnz179smTJ8zMae6M9qRJk9LT03ulKY2Vlpbm7+//yl/mqwe3cPoS7gdokLy8vKampo8++sjOzk4gEFAUxZTb2NgYGxufPXu2G21aWFjMnTs3IyMjLCwsKCio03N1rCdZVllH03RKSsrKlSuVC42MjPz8/ORyuSI4wGgDAKcgDtAgVlZWhJBz5841NDQUFBQoHgPz+fxNmzZdvHhRKpU+fPiwpaWlurr61q1b5KX0rG02u3bt2ubm5oqKiqlTp3Z6ro7b7EmWVdZdvnxZIpFMnjy5VfmKFSuI0qMBjDYAcAvbExa4QsX5Sxs2bDA2NjY0NPTz82Mmkdvb2z948ICm6c8++2zUqFECgUAgEIwbNy4hIYGm6WvXrllbWwuFwjfeeGPz5s3MnW09PT0vLy/lZt3d3ffv36/iuTpus6WlZffu3UOHDuXxeEZGRt7e3rdv32YaTEhIYFYmHzp0aGFh4b59+5i35Kytrf/4449Or/3KlSuTJ082MzNjvpmDBw92dXX9/vvve2Vsly1bJhKJdHR0xowZc+3aNUX5tm3bFGc0NzdnRpXmwGhzZF4W5g32Uxz5fmoIin5V1jPXcMxzSoy2OmBsu4F5/vrKPzjHd6Of4sj3U0PguQAAAAB3IQ6AvvD7779T7VNTvnOArjp37lxISMixY8fs7OyYL+eiRYuUD/Dw8BCLxdra2iNHjrx27Rpb/Txy5MjEiRPFYrG1tfWSJUuePHnSB3Wjo6MdHR2FQqFIJHJ0dAwLC2Mm2TIiIiKcnJwkEgmfz3dwcPjkk09qamqYXSdOnIiOju50wQxgDbuPJbgDzynVB2PbDRx5/tql78aWLVtmzpwpk8mYTXt7+wEDBhBCTp48qXxYdnb2rFmzermjXZGSkkIIiY6OrqysvH79up2d3dixY5uamtRd19PTc8+ePaWlpdXV1WlpaTwe76233lLsdXNzS0hIKC8vl8lkqampPB7v7bffVuyNi4tzc3OrqKhQ8Ro58v3UELgfAABqUV9f7+rqqmlNtWfnzp0pKSlpaWlisVhRGB8fr6WlFRgYWFVVpdazd8mXX345ZMiQ9evXGxgYjB07Njg4ODc3t71VJnuxrq6u7sqVK01MTPT19f38/GbPnv3vf//78ePHzF59ff3AwEBjY2OxWDx37lxvb+8zZ84w+TIIIatXrx4zZsw777zT3NzcvasG9UEcAABq0YspldWdnfnOnTthYWFbt24VCATK5a6urkFBQQ8fPly3bp36zt5VxcXFZmZmilUoLC0tCSH3799Xd93jx48rj4+5uTkhRHHz/+TJk0zaDsbAgQMJIUzuTUZ4eHhubm5cXJwq54K+hDgAANpFt5/4WCqV6urqMhMdCSErV64UiUQURTFLMbZKqRwfHy8QCAYNGvThhx+amZkJBAJXV1fFn6FdaooQcubMGYlEsn379t66zPj4eJqmvby8Xt4VGRk5bNiw/fv3nzt3rqtD1GluaLlcvmXLFisrK6FQOHr0aOYpRqfs7OyUoyLmAb+dnZ2667ZSUFBgaGhobW3d5t6HDx8KhUJbW1tFiZGRkZubW1xcHI3pG5qG3ccS3IFn2OqDse0GFZ+/dpz4eMGCBaampoqDd+/eTQh59uwZs9kqpXJgYKBIJLp161ZDQ0N+fj7zqhqzNkZXmzp58qRYLI6IiOi0/yp+N+zs7JycnFoV2tvb37t3j6bpy5cva2lp2djY1NTU0C+9H9CT3NDr1q3j8/kZGRkVFRWbNm3S0tL65ZdfOu1tTk4Oj8eLj4+XyWQ3b94cMWLE9OnTO63V87qMxsbGkpKSvXv38vn8gwcPtnlMbW2tWCyWSqWtykNCQggh169f7/QseD+gL+F+AAC0TcXEx6rT0dFh/m52cnJKTEysrq5OTk7uRjuenp4ymSwsLKx73Wiltrb23r17imQQL3NxcVmzZk1RUdHGjRtb7epJbuiGhobExERvb28fHx9DQ8PNmzfzeDxVBsTNzW3Dhg1SqVQikTg7O1dXV+/fv1/Fi+1JXYalpaWFhUV4ePiuXbv8/f3bPCYqKsrMzCwyMrJV+dChQwkheXl5XTojqBviAABoW1cTH3fJhAkT9PT0FLfQWVRaWkrTNLM4Y3siIyOHDx+ekJBw6dIl5fKe5Ia+fft2XV2ds7Mzs0soFA4ePFiVAQkNDd23b9/58+dramru3r3r6urq4uKieCNPfXUZxcXFpaWlR44c+eqrr8aNG/fyexvHjx9PS0v79ttvld+4ZDCD/PTpU9VPB30AcQAAtE3diY/5fP6zZ896pameaGhoYDrTwTECgSA5OZmiqKVLl9bX1yvKezJEtbW1hJDNmzcrFtK4f/++8ot1bXr8+HF0dPQHH3wwdepUkUhka2ublJT06NEj5kmK+uoq8Hg8ExMTDw+PlJSU/Pz8qKgo5b0pKSk7d+7MycmxsbF5ua5QKCR/DjhoDsQBANA2tSY+bmpq0pCM1cyPU6er3Li4uAQHBxcUFGzbtk1R2JMhMjExIYTExsYqP6m9cuVKx7UKCgrkcjmTHZshkUiMjY3z8/M7PWNP6r7MwcFBW1tbue7evXsPHTp04cIF5VMoa2xsJH8OOGgOxAEA0LZOEx/r6Oi0l3exUzk5OTRNT5o0qedN9dCgQYMoilJlhYBt27Y5Ojpev35dUdKT3NCWlpYCgSA3N7dLvWUiDMWsfUJIdXX18+fPmRmA6qtbXl4+f/585RImqmDq0jS9YcOGvLy8zMzMVndHlDGDbGpq2unpoC8hDgCAtnWa+NjBweH58+eZmZlNTU3Pnj1rNQ395ZTKLS0tFRUVzc3NN27cCAoKsrKyWrx4cTeays7O7sV5g3p6enZ2diUlJaoMSHJysvIs+Z7khhYIBEuWLDl69GhiYqJMJpPL5SUlJcyPdEBAgKmpaZvrFtva2rq7uyclJV28eLG+vr64uJg517Jly5gD1FRXJBKdPXv2woULMpmsqanp+vXr7733nkgkCg4OJoTcunVr165dSUlJPB5PecnwPXv2KDfCDPKoUaM6HRzoU6zMUuAgzG1TH4xtN6g4L6uDxMc0TZeXl7u7uwsEAltb248//nj9+vWEEAcHB2Y2oHJK5SdPngQGBvJ4PHNzcx0dHYlEMnv27MLCwu41dfr0abFYHBkZ2Wn/VfxuSKVSHo9XV1fHbB4/fpyZPjBw4MBVq1a1Onj9+vXK8wZ7khv6xYsXGzZssLKy0tHRMTEx8fHxyc/Pp2na29ubELJly5Y2e1tWVhYUFOTg4MDn8/X19SdPnvz1118r9qqvrpeXl62trb6+Pp/Pt7e3DwgIyMvLY3a1NwVg9+7dyi14enqam5u3tLS02b4yzBvsS/jXs4/gt0p9MLbd0Pf/zjKLzvblGWmVvxsFBQU6OjrtzYbve3K5fMqUKQcOHOhHdTtVVlYmEAj27NmjysGIA/oSngsAQB/R2IxzDg4OERERERERilVyWSSXyzMzM6urq7uRh5OtuqoIDw8fO3asVCpVR+PQE4gDAABISEiIn59fQEAA6ymFcnJyjh07lp2d3fGSBhpVt1MxMTG5ubmnT5/m8Xi93jj0EOIAAFC7TZs2JScnV1VV2draZmRksN2dtm3fvl0qle7YsYPdbkybNu3w4cOKbAv9om7HsrKyXrx4kZOTY2Rk1OuNQ8/psN0BAHj1RUVFtVpwRjN5eHh4eHiw3YtXzaxZs2bNmsV2L6BduB8AAADAXYgDAAAAuAtxAAAAAHchDgAAAOAuxAEAAADchfkCfYqiKLa78MrC2HYDRwaNI5f5ivH19WW7C1xB0TTNdh84oaSk5PLly2z3AqA1f3//oKAgFxcXtjsC8H9YWlria9k3EAcAcBpFUampqXPnzmW7IwDADrwfAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLsQBwAAAHAX4gAAAADuQhwAAADAXYgDAAAAuAtxAAAAAHchDgAAAOAuxAEAAADchTgAAACAuxAHAAAAcBfiAAAAAO5CHAAAAMBdiAMAAAC4C3EAAAAAdyEOAAAA4C7EAQAAANyFOAAAAIC7EAcAAABwF+IAAAAA7kIcAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLsQBwAAAHAX4gAAAADu0mG7AwDQp44ePVpdXa1ccu7cucrKSsWmt7e3iYlJn/cLANhB0TTNdh8AoO8sXrz4q6++4vF4zCbzLwBFUYQQuVyur69fWlrK5/PZ7CIA9CE8FwDglnnz5hFCmv7U3Nzc3NzM/Le2trafnx+CAABOwf0AAG5pbm42NTV9/vx5m3vPnz8/derUPu4SALAI9wMAuEVHR2fevHmK5wLKBg4c6Obm1vddAgAWIQ4A4Jx58+Y1NTW1KuTxeIsWLdLW1malSwDAFjwXAOAcmqatrKxKSkpalf/8888TJ05kpUsAwBbcDwDgHIqiFi5c2OrRgKWl5YQJE9jqEgCwBXEAABe1ejTA4/EWL17MzB4EAE7BcwEAjnJ0dLx9+7Zi8+bNmyNHjmSxPwDACtwPAOCoRYsWKR4NODk5IQgA4CbEAQActXDhwubmZkIIj8d777332O4OALADzwUAuGvChAn/+c9/KIoqKiqysrJiuzsAwALcDwDgrnfffZcQ8vrrryMIAOAs5BvURDExMVeuXGG7F/Dqa2hooCjqxYsXfn5+bPcFOCE9PZ3tLkBruB+gia5cuXL16lW2e9HPZGRkvLwwDqeUlJRkZGR0qYpAIDA1NbWwsFBTl9QEn3V/1I3vJ/QNvB+giZg/zhA4dwlFUampqXPnzmW7I6xJS0vz9/fv6v/Rd+7ccXBwUFOX1ASfdX/Uve8n9AHcDwDgtH4XBABA70IcAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAJx2+vRpAwODb775hu2OqMu5c+dCQkKOHTtmZ2dHURRFUYsWLVI+wMPDQywWa2trjxw58tq1a2z188iRIxMnThSLxdbW1kuWLHny5Ekf1I2OjnZ0dBQKhSKRyNHRMSwsTCaTKfZGREQ4OTlJJBI+n+/g4PDJJ5/U1NQwu06cOBEdHS2Xy1XvJGgsxAEAnPZqz+P69NNP4+PjN23a5OPjc/fuXXt7+wEDBhw6dOjUqVOKY86ePZuenj5z5sz8/Pzx48ez0s/U1NQFCxb4+fmVlJRkZWVdvHhxxowZTPYHtdb94Ycf3n///QcPHjx9+nTbtm3R0dG+vr6KvRcuXFi1alVRUVFZWVlUVFRcXJxivSkvLy+BQDBt2rTKyspuXC9oFho0j6+vr6+vL9u96GcIIampqWz3gk2pqama/H90XV2di4tLrzSl4me9Y8eOYcOG1dfXK0rs7e0PHz6spaVlbm5eWVmpKM/Ozp41a1av9K173N3dhwwZ0tLSwmx+9tlnhJBLly6pu663t7fy+DA/848ePWI2PT09m5ubFXuZBRsePHigKJFKpS4uLk1NTaqcS8O/n1yG+wEA0BcOHDhQWlraZ6e7c+dOWFjY1q1bBQKBcrmrq2tQUNDDhw/XrVvXZ53pVHFxsZmZGUVRzKalpSUh5P79++que/z4ceXxMTc3J4Qobv6fPHlSW1tbsXfgwIGEkLq6OkVJeHh4bm5uXFycKucCjYU4AIC7Ll26ZGVlRVEU80dkYmKiSCTS09PLysqaMWOGRCKxsLA4evQoc3B8fLxAIBg0aNCHH35oZmYmEAhcXV1/+uknZq9UKtXV1R08eDCzuXLlSpFIRFFUWVkZISQoKGjt2rWFhYUURTErF505c0YikWzfvl1NlxYfH0/TtJeX18u7IiMjhw0btn///nPnzrVZl6bpmJiYESNG8Pl8IyOj2bNn//7778yujoeIECKXy7ds2WJlZSUUCkePHs38EdwpOzs75SCJecBvZ2en7rqtFBQUGBoaWltbt7n34cOHQqHQ1tZWUWJkZOTm5hYXF0e/0k+XXn0s34+AtuC5QDcQPBfo1n3X4uJiQsjevXuZzdDQUELI+fPnq6qqSktLp0yZIhKJGhsbmb2BgYEikejWrVsNDQ35+fnMu2mKG8ULFiwwNTVVtLx7925CyLNnz5hNHx8fe3t7xd6TJ0+KxeKIiIhuXKkqn7WdnZ2Tk1OrQnt7+3v37tE0ffnyZS0tLRsbm5qaGvql5wJbtmzR1dU9ePBgZWXljRs3xo8fP3DgwCdPnjB7Ox6idevW8fn8jIyMioqKTZs2aWlp/fLLL51eUU5ODo/Hi4+Pl8lkN2/eHDFixPTp01UcjZ7UZTQ2NpaUlOzdu5fP5x88eLDNY2pra8VisVQqbVUeEhJCCLl+/XqnZ8FzAY2F+wEA0Jqrq6tEIjExMQkICKitrX3w4IFil46ODvOHspOTU2JiYnV1dXJycjdO4enpKZPJwsLCeq/X/1NbW3vv3j17e/v2DnBxcVmzZk1RUdHGjRtb7aqvr4+JiZkzZ87ChQsNDAxGjRr1xRdflJWV7du3T/mwNoeooaEhMTHR29vbx8fH0NBw8+bNPB5PlfFxc3PbsGGDVCqVSCTOzs7V1dX79+9X8WJ7UpdhaWlpYWERHh6+a9cuf3//No+JiooyMzOLjIxsVT506FBCSF5eXpfOCBoFcQAAtEtXV5cQ0tTU1ObeCRMm6OnpKe6Za47S0lKapvX09Do4JjIycvjw4QkJCZcuXVIuz8/Pr6mpmTBhgqJk4sSJurq6iicgrSgP0e3bt+vq6pydnZldQqFw8ODBqoxPaGjovn37zp8/X1NTc/fuXVdXVxcXF+ZWjVrrMoqLi0tLS48cOfLVV1+NGzfu5dc4jh8/npaW9u2334rF4la7mEF++vSp6qcDTYM4AAC6j8/nP3v2jO1etNbQ0EAI4fP5HRwjEAiSk5Mpilq6dGl9fb2inJkIp6+vr3ywoaFhdXV1p+etra0lhGzevJn60/3795VfrGvT48ePo6OjP/jgg6lTp4pEIltb26SkpEePHjEPVtRXV4HH45mYmHh4eKSkpOTn50dFRSnvTUlJ2blzZ05Ojo2Nzct1hUIh+XPAoZ9CHAAA3dTU1FRZWWlhYcF2R1pjfpw6XeXGxcUlODi4oKBg27ZtikJDQ0NCSKtffRUv08TEhBASGxur/PD1ypUrHdcqKCiQy+VDhgxRlEgkEmNj4/z8/E7P2JO6L3NwcNDW1lauu3fv3kOHDl24cEH5FMoaGxvJnwMO/RTiAADoppycHJqmJ02axGzq6Oi09wShjw0aNIiiqKqqqk6P3LZtm6Oj4/Xr1xUlzs7O+vr6v/76q6Lkp59+amxsfO211zptzdLSUiAQ5Obmdqm3TITx+PFjRUl1dfXz58+ZGYDqq1teXj5//nzlEiaqYOrSNL1hw4a8vLzMzMxWd0eUMYNsamra6elAYyEOAIAuaGlpqaioaG5uvnHjRlBQkJWV1eLFi5ldDg4Oz58/z8zMbGpqevbsWasp7MbGxo8ePSoqKqqurm5qasrOzlbfvEE9PT07O7uSkpJOj2SeDijPkhcIBGvXrj1+/PihQ4dkMlleXt6KFSvMzMwCAwNVaW3JkiVHjx5NTEyUyWRyubykpIT5kQ4ICDA1NW1z3WJbW1t3d/ekpKSLFy/W19cXFxcz51q2bBlzgJrqikSis2fPXrhwQSaTNTU1Xb9+/b333hOJRMHBwYSQW7du7dq1KykpicfjUUr27Nmj3AgzyKNGjep0cEBzsTJLATqGeYPdQDBvsOvzsvbu3cvM+NfT0/Py8kpISGBe+xo6dGhhYeG+ffskEgkhxNra+o8//qBpOjAwkMfjmZub6+joSCSS2bNnFxYWKlorLy93d3cXCAS2trYff/zx+vXrCSEODg7M7JO8IgAAIABJREFUxMJr165ZW1sLhcI33njjyZMnp0+fFovFkZGR3bhSVT5rqVTK4/Hq6uqYzePHjzPTBwYOHLhq1apWB69fv1553mBLS8vu3buHDh3K4/GMjIy8vb1v377N7Op0iF68eLFhwwYrKysdHR0TExMfH5/8/Hyapr29vQkhW7ZsabO3ZWVlQUFBDg4OfD5fX19/8uTJX3/9tWKv+up6eXnZ2trq6+vz+Xx7e/uAgIC8vDxmV3tTAHbv3q3cgqenp7m5uWI1ww5g3qDGwqeiiRAHdAPigD74dzYwMNDY2Fitp1CFKp91QUGBjo5Oe7Ph+55cLp8yZcqBAwf6Ud1OlZWVCQSCPXv2qHIw4gCNhecCANAF/SXFnIODQ0REREREhGKVXBbJ5fLMzMzq6uqAgID+UlcV4eHhY8eOlUql6mgc+gziAAB4NYWEhPj5+QUEBKjywqBa5eTkHDt2LDs7u+MlDTSqbqdiYmJyc3NPnz7N4/F6vXHoS4gDXhHLly8Xi8UURXX1XWXN1NLSEhsb6+rq2ottKmegZ+jq6g4aNOjNN9/cvXt3RUVFL57rlbRp06bk5OSqqipbW9uMjAy2u6OS7du3S6XSHTt2sNuNadOmHT58WJF8oV/U7VhWVtaLFy9ycnKMjIx6vXHoY4gDXhH79+9PSkpiuxe9o6Cg4K9//WtwcHCnC7B0iSIDvYGBAU3TLS0tpaWlaWlptra2GzZsGDlypPJUMXhZVFTUixcvaJq+d++ecpZ6Defh4bFz5062e/GqmTVrVkhIiPI8C+i/EAeA2tXX16v+l/1vv/22cePGFStWjB07Vq29oijK0NDwzTffTE5OTktLe/r0qaenJ+s3kF/WpdEDAOgqxAGvDkUCck3TpcTzY8aMOXbs2IIFCzpeFLZ3+fr6Ll68uLS09Isvvuizk6qoS6MHANBViAP6MZqmd+/ePXz4cD6fb2BgwEzXZuzatUtPT08sFpeWlq5du9bc3JyZAN1eVvWOU8uTDjOydzXxvGZiFsPJzs4mGD0A4BQW5yxCe1RcPyA0NJSiqH/84x8VFRV1dXUJCQlEKRE4kyV99erVe/funTNnzn//+9+Os6p3nFq+47pdSjyvotdff33MmDGqH09UWz9A8X5AKzKZjBBiaWnJbPbH0ePO/GwVP2vQKNz5fvY7uB/QX9XX18fGxv7tb38LDg42NDQUCoXGxsYvH7Zz585Vq1YdO3bM2tq606zq7aWWVzEje7/GzLZolV0GowcArzwdtjsA3XTnzp26urpp06apeHxXs6orp5bvat3+qLa2lqZpZo3Yl/Wj0dPY10R6l7+/v7+/P9u9AHgVIA7or5j0HkyeU1V0I6u6IrV8TzKy9xd//PEHIcTR0bHNvf1o9Ji7r682f3//oKAgFxcXtjsCXXDlypW4uDi2ewFtQBzQXwkEAkLIixcvVDy+q1nVlVPL9yQje39x5swZQsiMGTPa3NuPRm/u3LnqaFaj+Pv7u7i4cOFKXzGIAzQT3g/or5ydnbW0tL7//nvVj+9SVnXl1PKd1tWcxPPd8+TJk9jYWAsLi6VLl7Z5AEYPAF5ViAP6KyalaUZGxoEDB2Qy2Y0bNzp+70yVrOrtpZbvtG6XEs/3/lh0EU3TNTU1TKbUZ8+epaamTp48WVtbOzMzs733AzB6APDKYnW2ArRNxXmD1dXVy5cvHzBggL6+/htvvLFlyxZCiIWFxW+//RYdHS0UCgkhlpaWitSrHWRVpztLLd9x3S4lnu/4oq5cuTJ58mQzMzPm+zl48GBXV9fvv/++09Egnc0lO3HixOjRo/X09HR1dbW0tMifSwr+5S9/iYiIKC8vVxzZT0ePO/OyOv2sQQNx5/vZ71A0TbMRfkBH/Pz8CCHp6el9edIPP/wwPT29vLy8L0/aiyiKSk1NZeuZsSaMXlpamr+/Pxf+j2b3s4bu4c73s9/BcwH4n/6SWl4zYfQAoD9CHAB95/fff6faFxAQwHYH4RV07ty5kJAQ5azTixYtUj7Aw8NDLBZra2uPHDny2rVrbPXzyJEjzDKU1tbWS5YsefLkSR/UjY6OdnR0FAqFIpHI0dExLCyMWViTERER4eTkJJFI+Hy+g4PDJ598UlNTw+w6ceJEdHQ0Yt9XBMvPJaAtKr4f0ItCQkJ0dXUJITY2Nunp6X156t5C2HtmrCGjx53nr6p/1lu2bJk5c6ZMJmM27e3tBwwYQAg5efKk8mHZ2dmzZs3q/Y6qLCUlhRASHR1dWVl5/fp1Ozu7sWPHNjU1qbuup6fnnj17SktLq6ur09LSeDzeW2+9pdjr5uaWkJBQXl4uk8lSU1N5PN7bb7+t2BsXF+fm5lZRUaHiNXLn+9nv4FPRRH0fB7wCWIwDNEQf/DtbV1fn4uLCelMqftY7duwYNmxYfX29osTe3v7w4cNaWlrm5uaVlZWKctbjAHd39yFDhjBzWGia/uyzzwghly5dUnddb29v5fFh3kx69OgRs+np6dnc3KzYy7yQociaQdO0VCp1cXFRMeZAHKCx8FwAAFTVi0mQ1Z1P+c6dO2FhYVu3bmVW3FJwdXUNCgp6+PDhunXr1Hf2riouLjYzM1OsCW1paUkIaTWDVB11jx8/rjw+5ubmhBDFzf+TJ09qa2sr9g4cOJAQUldXpygJDw/Pzc3F6kD9HeIAAG6heykJcsfZlruaT/nMmTMSiWT79u29dZnx8fE0TXt5eb28KzIyctiwYfv37z937lxXhygxMVEkEunp6WVlZc2YMUMikVhYWBw9elRRVy6Xb9myxcrKSigUjh49WsVlnu3s7JSjIuYBv52dnbrrtlJQUGBoaGhtbd3m3ocPHwqFQltbW0WJkZGRm5tbXFwcjVkA/Rq7tyOgTXgu0A0EzwVUu+/ai0mQO8623KWmTp48KRaLIyIiVLlSVT5rOzs7JyenVoX29vb37t2jafry5ctaWlo2NjY1NTX0S88FOh4iJif1+fPnq6qqSktLp0yZIhKJGhsbmb3r1q3j8/kZGRkVFRWbNm3S0tL65ZdfOr2inJwcHo8XHx8vk8lu3rw5YsSI6dOnqzIUPazLaGxsLCkp2bt3L5/PVyyY0Uptba1YLJZKpa3KQ0JCiFK68w7guYDGwv0AAA7p9STI7WVb7ipPT0+ZTBYWFta9brRSW1t77949e3v79g5wcXFZs2ZNUVHRxo0bW+1ScYhcXV0lEomJiUlAQEBtbe2DBw8IIQ0NDYmJid7e3j4+PoaGhps3b+bxeKoMiJub24YNG6RSqUQicXZ2rq6u3r9/v4oX25O6DEtLSwsLi/Dw8F27drWXxTEqKsrMzCwyMrJV+dChQwkheXl5XTojaBTEAQAcotYkyMrZltlVWlpK07Senl4Hx0RGRg4fPjwhIeHSpUvK5V0dImaqCLPk8+3bt+vq6pydnZldQqFw8ODBqgxIaGjovn37zp8/X1NTc/fuXVdXVxcXl+Li4k4r9rAuo7i4uLS09MiRI1999dW4ceNefm/j+PHjaWlp3377rVgsbrWLGeSnT5+qfjrQNIgDADhE3UmQFdmW2dXQ0MB0poNjBAJBcnIyRVFLly6tr69XlPdkiGprawkhmzdvVqyKcf/+feUX69r0+PHj6OjoDz74YOrUqSKRyNbWNikp6dGjR8yTFPXVVeDxeCYmJh4eHikpKfn5+VFRUcp7U1JSdu7cmZOTY2Nj83JdZgVuZsChn0IcAMAhak2CrJxtmV3Mj1Onq9y4uLgEBwcXFBRs27ZNUdiTITIxMSGExMbGKj98vXLlSse1CgoK5HL5kCFDFCUSicTY2Dg/P7/TM/ak7sscHBy0tbWV6+7du/fQoUMXLlxQPoWyxsZG8ueAQz+FOACAQ9SaBFk523IPm+qhQYMGURRVVVXV6ZHbtm1zdHS8fv26oqSrOaaVWVpaCgSC3NzcLvWWiTAeP36sKKmurn7+/DkzA1B9dcvLy+fPn69cwkQVTF2apjds2JCXl5eZmdnq7ogyZpBNTU07PR1oLMQBABzS60mQ28u23NWmsrOze3HeoJ6enp2dXUlJiSoDkpycrDxLXpUc0x20tmTJkqNHjyYmJspkMrlcXlJSwvxIBwQEmJqatrlusa2trbu7e1JS0sWLF+vr64uLi5lzLVu2jDlATXVFItHZs2cvXLggk8mampquX7/+3nvviUSi4OBgQsitW7d27dqVlJTE4/GU1//es2ePciPMII8aNarTwQHNxcosBegY5g12A8G8QdXmZfViEuSOsy13qanTp0+LxeLIyEhVrlSVz1oqlfJ4vLq6Ombz+PHjzPSBgQMHrlq1qtXB69evV5432MEQJSQkMG/GDR06tLCwcN++fRKJhBBibW39xx9/0DT94sWLDRs2WFlZ6ejomJiY+Pj45Ofn0zTt7e1NCNmyZUubvS0rKwsKCnJwcODz+fr6+pMnT/76668Ve9VX18vLy9bWVl9fn8/n29vbBwQE5OXlMbvamwKwe/du5RY8PT3Nzc0Vqxl2APMGNRY+FU2EOKAbEAf0/b+zgYGBxsbGfXlGhiqfdUFBgY6OTnuz4fueXC6fMmXKgQMH+lHdTpWVlQkEgj179qhyMOIAjYXnAgDQfRqbcc7BwSEiIiIiIkKxSi6L5HJ5ZmZmdXV1N5JqslVXFeHh4WPHjpVKpepoHPoM4gAAeDWFhIT4+fkFBASo8sKgWuXk5Bw7diw7O7vjJQ00qm6nYmJicnNzT58+zePxer1x6EuIAwCgOzZt2pScnFxVVWVra5uRkcF2d9q2fft2qVS6Y8cOdrsxbdq0w4cPK7It9Iu6HcvKynrx4kVOTo6RkVGvNw59TIftDgBAvxQVFdVqwRnN5OHh4eHhwXYvXjWzZs2aNWsW272A3oH7AQAAANyFOAAAAIC7EAcAAABwF+IAAAAA7sJ7ghqqpKQkLS2N7V70M50mdHm1MZfPka8Nxz/r/ggfmcaiaJpmuw/Qmp+fn8ZOxAIA6Db84mggxAEAnEZRVGpq6ty5c9nuCACwA+8HAAAAcBfiAAAAAO5CHAAAAMBdiAMAAAC4C3EAAAAAdyEOAAAA4C7EAQAAANyFOAAAAIC7EAcAAABwF+IAAAAA7kIcAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLsQBwAAAHAX4gAAAADuQhwAAADAXYgDAAAAuAtxAAAAAHchDgAAAOAuxAEAAADchTgAAACAuxAHAAAAcBfiAAAAAO5CHAAAAMBdiAMAAAC4C3EAAAAAdyEOAAAA4C7EAQAAANyFOAAAAIC7EAcAAABwF0XTNNt9AIC+ExgYePv2bcXmtWvXbG1tjYyMmE1tbe2vvvrKwsKCpd4BQF/TYbsDANCnTE1N9+3bp1xy48YNxX/b2dkhCADgFDwXAOCW+fPnt7dLV1d38eLFfdgXAGAfngsAcI6zs/OtW7fa/H//9u3bw4YN6/suAQBbcD8AgHPeffddbW3tVoUURY0ZMwZBAADXIA4A4Jx58+bJ5fJWhdra2u+99x4r/QEAFuG5AAAXubq6/vTTTy0tLYoSiqKKi4vNzc1Z7BUA9D3cDwDgokWLFlEUpdjU0tJ64403EAQAcBDiAAAu8vPzU96kKOrdd99lqzMAwCLEAQBcNHDgwGnTpineFqQoytvbm90uAQArEAcAcNTChQuZ14O0tbWnT58+YMAAtnsEACxAHADAUXPmzNHV1SWE0DS9cOFCtrsDAOxAHADAUSKR6O9//zshRFdXd+bMmWx3BwDYgTgAgLsWLFhACPH29haJRGz3BQDYgfUDNJGfn19GRgbbvQAA6GX4xdFAyDeooSZNmrRmzRq2e9EPxMbGEkIwVoSQK1euxMXFpaamdqnWoUOHAgICdHT60z8F/v7+QUFBLi4ubHcEuoD5frLdC2gD7gdoImZud3p6Otsd6QcwVgppaWn+/v5d/T+6oaFBIBCoqUtqQlFUamrq3Llz2e4IdEH3vp/QB/B+AACn9bsgAAB6F+IAAAAA7kIcAAAAwF2IAwAAALgLcQAAAAB3IQ4A4LTTp08bGBh88803bHdEXc6dOxcSEnLs2DE7OzuKoiiKWrRokfIBHh4eYrFYW1t75MiR165dY6ufR44cmThxolgstra2XrJkyZMnT/qgbnR0tKOjo1AoFIlEjo6OYWFhMplMsTciIsLJyUkikfD5fAcHh08++aSmpobZdeLEiejoaLlcrnonQWMhDgDgtFd7Htenn34aHx+/adMmHx+fu3fv2tvbDxgw4NChQ6dOnVIcc/bs2fT09JkzZ+bn548fP56Vfqampi5YsMDPz6+kpCQrK+vixYszZsxobm5Wd90ffvjh/ffff/DgwdOnT7dt2xYdHe3r66vYe+HChVWrVhUVFZWVlUVFRcXFxSnSVXt5eQkEgmnTplVWVnbjekGjIA4A4DRPT8+qqqo+yC9QX1/v6uqq7rMo27lzZ0pKSlpamlgsVhTGx8draWkFBgZWVVX1ZWc69uWXXw4ZMmT9+vUGBgZjx44NDg7Ozc396aef1F1XV1d35cqVJiYm+vr6fn5+s2fP/ve///348WNmr76+fmBgoLGxsVgsnjt3rre395kzZ4qLi5m9q1evHjNmzDvvvKNizAEaC3EAAPSFAwcOlJaW9tnp7ty5ExYWtnXr1lYLJLi6ugYFBT18+HDdunV91plOFRcXm5mZURTFbFpaWhJC7t+/r+66x48fVx4fc3NzQoji5v/Jkye1tbUVewcOHEgIqaurU5SEh4fn5uZilcD+DnEAAHddunTJysqKoqjPPvuMEJKYmCgSifT09LKysmbMmCGRSCwsLI4ePcocHB8fLxAIBg0a9OGHH5qZmQkEAldXV8XfnVKpVFdXd/DgwczmypUrRSIRRVFlZWWEkKCgoLVr1xYWFlIU5eDgQAg5c+aMRCLZvn27mi4tPj6epmkvL6+Xd0VGRg4bNmz//v3nzp1rsy5N0zExMSNGjODz+UZGRrNnz/7999+ZXR0PESFELpdv2bLFyspKKBSOHj1axWWe7ezslIMk5gG/nZ2duuu2UlBQYGhoaG1t3ebehw8fCoVCW1tbRYmRkZGbm1tcXNyr/XTp1UeD5vH19fX19WW7F/0DxkqB+cnpai3mNu/evXuZzdDQUELI+fPnq6qqSktLp0yZIhKJGhsbmb2BgYEikejWrVsNDQ35+fnMu2kPHjxg9i5YsMDU1FTR8u7duwkhz549YzZ9fHzs7e0Ve0+ePCkWiyMiIrpxpYSQ1NTUjo+xs7NzcnJqVWhvb3/v3j2api9fvqylpWVjY1NTU0PTdHZ29qxZsxSHbdmyRVdX9+DBg5WVlTdu3Bg/fvzAgQOfPHnC7O14iNatW8fn8zMyMioqKjZt2qSlpfXLL790ekU5OTk8Hi8+Pl4mk928eXPEiBHTp09XcTR6UpfR2NhYUlKyd+9ePp9/8ODBNo+pra0Vi8VSqbRVeUhICCHk+vXrnZ6le99P6AO4HwAArbm6ukokEhMTk4CAgNra2gcPHih26ejoMH8oOzk5JSYmVldXJycnd+MUnp6eMpksLCys93r9P7W1tffu3bO3t2/vABcXlzVr1hQVFW3cuLHVrvr6+piYmDlz5ixcuNDAwGDUqFFffPFFWVnZvn37lA9rc4gaGhoSExO9vb19fHwMDQ03b97M4/FUGR83N7cNGzZIpVKJROLs7FxdXb1//34VL7YndRmWlpYWFhbh4eG7du3y9/dv85ioqCgzM7PIyMhW5UOHDiWE5OXldemMoFEQBwBAu3R1dQkhTU1Nbe6dMGGCnp6e4p655igtLaVpWk9Pr4NjIiMjhw8fnpCQcOnSJeXy/Pz8mpqaCRMmKEomTpyoq6vb3pt3ykN0+/bturo6Z2dnZpdQKBw8eLAq4xMaGrpv377z58/X1NTcvXvX1dXVxcVF8Uae+uoyiouLS0tLjxw58tVXX40bN+7l1ziOHz+elpb27bffKr9xyWAG+enTp6qfDjQN4gAA6D4+n//s2TO2e9FaQ0MDIYTP53dwjEAgSE5Opihq6dKl9fX1inJmIpy+vr7ywYaGhtXV1Z2et7a2lhCyefNm6k/3799XfrGuTY8fP46Ojv7ggw+mTp0qEolsbW2TkpIePXrEPFhRX10FHo9nYmLi4eGRkpKSn58fFRWlvDclJWXnzp05OTk2NjYv1xUKheTPAYd+CnEAAHRTU1NTZWWlhYUF2x1pjflx6nSVGxcXl+Dg4IKCgm3btikKDQ0NCSGtfvVVvEwTExNCSGxsrPLD1ytXrnRcq6CgQC6XDxkyRFEikUiMjY3z8/M7PWNP6r7MwcFBW1tbue7evXsPHTp04cIF5VMoa2xsJH8OOPRTiAMAoJtycnJomp40aRKzqaOj094ThD42aNAgiqJUWSFg27Ztjo6O169fV5Q4Ozvr6+v/+uuvipKffvqpsbHxtdde67Q1S0tLgUCQm5vbpd4yEYZi1j4hpLq6+vnz58wMQPXVLS8vnz9/vnIJE1UwdWma3rBhQ15eXmZmZqu7I8qYQTY1Ne30dKCxEAcAQBe0tLRUVFQ0NzffuHEjKCjIyspq8eLFzC4HB4fnz59nZmY2NTU9e/as1RR2Y2PjR48eFRUVVVdXNzU1ZWdnq2/eoJ6enp2dXUlJSadHMk8HlGfJCwSCtWvXHj9+/NChQzKZLC8vb8WKFWZmZoGBgaq0tmTJkqNHjyYmJspkMrlcXlJSwvxIBwQEmJqatrlusa2trbu7e1JS0sWLF+vr64uLi5lzLVu2jDlATXVFItHZs2cvXLggk8mampquX7/+3nvviUSi4OBgQsitW7d27dqVlJTE4/EoJXv27FFuhBnkUaNGdTo4oLEQBwBw12effTZx4kRCyIYNG2bNmpWYmBgbG0sIGT169N27d5OSktauXUsIefvttwsKCpgqDQ0No0aNEgqFU6ZMGTZs2Hfffad4DP/RRx+5u7vPmzdv+PDh27ZtY+4VK95ZW7FixaBBg5ycnN55553nz5+r+9I8PT3z8/MVD/6//vprBweHwsLCiRMnfvzxx8pHTpo0ifnlU/j000+joqIiIiIGDhzo5uZmY2OTk5MjEokIIZ0OUVxc3Jo1a6KjowcMGGBmZhYUFFRRUUEIaWxsLC0tzcrKermrFEWlp6cHBAQsW7bMyMjIycnpwYMHx44dmzJlCnOAmuoKBILJkycvX77c3NxcLBb7+fnZ2NhcvXqVec+RVm1JgF9++cXc3Hz06NGqHAwaio3JitAJzIlXHcZKoQ/mZzOrzKr1FKogKqwfUFBQoKOj095s+L4nl8unTJly4MCBflS3U2VlZQKBYM+ePaocjPUDNBbuBwBAF/SXFHMODg4RERERERGKVXJZJJfLMzMzq6urAwIC+ktdVYSHh48dO1YqlaqjcegziAOgCzrIQ9rK8uXLxWIxRVEqvjOless9cfv27Y8//njkyJFisVhHR8fAwGDYsGGenp6dvtHdcx1coHJKXIauru6gQYPefPPN3bt3M3eVoRtCQkL8/PwCAgJYTymUk5Nz7Nix7Ozsjpc00Ki6nYqJicnNzT19+jSPx+v1xqFPsX1DAtqgsfe63dzcEhISysvLZTJZamoqj8d7++232zuYWXRdlQVHu9qyMtXHav/+/Twe769//euZM2cqKioaGhoKCwtTUlJcXV2//PJLVVroiU4v0N7e3sDAgKZp5kW87777bvHixRRFmZmZqbIwLa3++64hISHMmjk2Njbp6enqO1GniArPBRS+/fbbDRs2qLU/HJSZmRkVFdXc3Kx6FTwX0Fj4VDSRxsYBnp6eyv/nz507lxCiWF6+lS7FAV1qWZmKY3XlyhVtbe2pU6c2NTW12nXmzBnF6vrq0+kFKuIAZenp6VpaWoMGDaqsrOz0FNz5d7ZLcQBoCO58P/sdPBeALug0D6kyRSLUXm+5GyIjI+Vy+Y4dO3R0dFrtmj59+qpVq3rrRO3p3gX6+vouXry4tLT0iy++UG//AICrEAf0bwcPHpwwYYJAIBCJRDY2NsyyaHR3s6aOGDGCoigtLa3XXnuN+Yn65JNPDAwMBALBP//5z5fP3ioPKU3Tu3fvHj58OJ/PNzAwWL9+fbev6+UMpz3R2Nh4/vz5AQMG/OUvf+n4SLaGrgPM7Pzs7OwuXDAAgOpYvh8BbVHxXjczj3nHjh3l5eXPnz//8ssvFyxYQPcga2pzc7ONjY2VlZXyHew1a9a0WieV8XIe0tDQUIqi/vGPf1RUVNTV1SUkJBCVnwt03HIHVBmrP/74gxAyadKkTltja+jodp4L0DQtk8kIIZaWlp12njv3XQmeC/RD3Pl+9jv4VDSRKr9tjY2NhoaG7u7uipLm5ua4uLi6ujp9ff2AgABF+c8//0wIUSR6Z37M6uvrmU3m1/rOnTvMJhNbpKWlMZu1tbVWVlZVVVUvdyA0NHTYsGEymYzZrKur09PTe+uttxQHdOn9gA5a7pgqY8WsEfu3v/2t48PYGjpGe3EATdMURRkaGnbceZpL/84iDuiPuPP97HdaPyuF/uLGjRuVlZXTp09XlGhra69evfrXX3/tdtZUQsjy5cvDw8Pj4uL8/PwIIYcOHZo9e7ZEImlVi8lDevbsWUUe0jt37tTV1U2bNq2H1/Vyyz3HrI7e6cP4niScJT0Yuo7V1tbSNP1yO+1JS0tT8ch+rQ+mekLvwkemsRAH9FfM7WImN5qynmRNZSp+8MEHu3fv/vnnn//yl798/vnnGRkZrY5JSUmJiYnJyclRTkHGLDPO5FvrtjZb7jkbGxuBQMA8HegAW0PXMabbjo6OKh7v7++v4pH9WlxcXFxcHNu9AHgV4D3B/or5ISkrK2tV3pOsqQypVMrj8WJjYy9evGhpaWlvb6+8t708pAKBgBDy4sWLLl5H5y33HJ/Pnz6bKYanAAAgAElEQVR9ellZ2Y8//vjy3ufPny9fvpywN3QdO3PmDCFkxowZKh7P9i3GvkDwXKAfYp4LgAZCHNBf2djYGBsbnz17tlV5T7KmMiwsLObOnZuRkREWFhYUFKQopzvMQ+rs7KylpfX9999341o6brlXhIeH8/n84OBgReIZhZs3bzKTCdkaug48efIkNjbWwsJi6dKlqtcCAFAd4oD+is/nb9q06eLFi1Kp9OHDhy0tLdXV1bdu3epJ1lSFtWvXNjc3V1RUTJ06VVHYcR5SExMTHx+fjIyMAwcOyGSyGzdu7Nu3T8XTqZjhtCfGjh17+PDhmzdvTpky5fTp01VVVU1NTffu3UtKSlq2bBmzMCpbQ6dA03RNTU1LSwtN08+ePUtNTZ08ebK2tnZmZqbq7wcAAHQNqzeKoG2qryf42WefjRo1SiAQCASCcePGJSQk0DTd0tKye/fuoUOH8ng8IyMjb2/v27dvM8cnJCQwK40PHTq0sLBw3759zA+MtbX1H3/8odyyu7v7/v37lUvy8vLa/Art3r2bOaC6unr58uUDBgzQ19d/4403tmzZQgixsLD47bffOr6KTlvulbGiafrBgwfr1q0bNWqUvr6+tra2oaHhuHHjli1b9uOPPzIHsDJ0J06cGD16tJ6enq6urpaWFiGEmSDwl7/8JSIiory8XMWr48772ATPBfoh7nw/+x2KVi3JNPQl5oXz9PR0tjvSD2CsFNLS0vz9/bnwfzRFUampqczazNBfcOf72e/guQAAAAB3IQ4Atfv999+p9qkpMzoAAKgCcQConaOjYwePplJSUtjuILzKzp07FxIScuzYMTs7Oyb0XLRokfIBHh4eYrFYW1t75MiR165dY6ufCg0NDY6Ojps3b+6buk1NTVFRUQ4ODrq6uoaGhs7OzkVFRZ22fOLEiejoaLlc3o1OgqZBHAAAr6xPP/00Pj5+06ZNPj4+d+/etbe3HzBgwKFDh06dOqU45uzZs+np6TNnzszPzx8/fjyLvWWEhobevn27z+r6+/v/61//Onz4cF1d3X//+197e/uamppOW/by8hIIBNOmTWNW34J+DXEAAKiqvr7e1dVV05pqz86dO1NSUtLS0pSXcI6Pj9fS0goMDKyqqlLr2bvn8uXLN2/e7LO6KSkpmZmZ6enpr7/+uo6OjpmZWVZWlrOzsyotr169esyYMe+8805zc3P3OgwaAnEAAKjqwIEDpaWlmtZUm+7cuRMWFrZ161ZmpUsFV1fXoKCghw8frlu3Tn1n7576+vr169d3b73k7tX9/PPPx48fP2rUqO61HB4enpubiwWe+zvEAQDcQtN0TEzMiBEj+Hy+kZHR7Nmzf//9d2aXVCrV1dUdPHgws7ly5UqRSERRFLN8dVBQ0Nq1awsLCymKcnBwiI+PFwgEgwYN+vDDD83MzAQCgaurqyInU5eaIoScOXNGIpFs3769ty4zPj6epmkvL6+Xd0VGRg4bNmz//v3nzp3r6hAlJiaKRCI9Pb2srKwZM2ZIJBILCwsmtSZDLpdv2bLFyspKKBSOHj26S4vphoaGrly5sntJOrpRt7Gx8erVq2PHju12y0ZGRm5ubnFxcZgN2K8hDgDglvDw8JCQkNDQ0NLS0osXLxYXF0+ZMuXp06eEkPj4eOVJ+QkJCVu3blVsxsXFzZw5097enqbpO3fuSKXSxYsX19XVrV69uqio6Nq1a83NzW+99VZxcXFXmyKEMG+ctbS09NZlnjp1avjw4czST60IhcJ//vOfWlpa77//fm1t7csHdDBEH3300Zo1a+rr68VicWpqamFhoZ2d3fvvv69IO7lx48Zdu3bFxsY+fvx45syZ8+fPV16pugM//vhjYWHh/Pnzu3Gx3av76NGjxsbG//znP+7u7kwkN2LECGYtMtVbHjdu3MOHD3/77bdudBs0BOIAAA6pr6+PiYmZM2fOwoULDQwMRo0a9cUXX5SVlam+CHQrOjo6zN/NTk5OiYmJ1dXVycnJ3WjH09NTJpOFhYV1rxut1NbW3rt3r1WeJ2UuLi5r1qwpKirauHFjq10qDpGrq6tEIjExMQkICKitrX3w4AEhpKGhITEx0dvb28fHx9DQcPPmzTweT5UBqa+vDwoKSkxM7MbFdrsu8z6giYnJ9u3b8/Pznz59Onv27FWrVh05ckT1locOHUoIaW/FTOgXEAcAcEh+fn5NTc2ECRMUJRMnTtTV1VXcz++JCRMm6OnpKW6hs6i0tJSm6TZvBihERkYOHz48ISHh0qVLyuVdHSJdXV1CCHM/4Pbt23V1dYr37IRC4eDBg1UZkE2bNn3wwQfm5uadHtmLdfl8PiFk5MiRrq6uxsbGBgYGW7duNTAwUEQ8qrTMDDJzswT6KcQBABzCzPJqlfPQ0NCwVbblbuPz+c+ePeuVpnqioaGB/Pk71x6BQJCcnExR1NKlS5WzUPZkiJinDJs3b1Ysk3X//v26urqOa126dCkvL49Jft1VPalrZmZG/m/ucl1dXWtr68LCQtVbFgqF5M8Bh34KcQAAhxgaGhJCWv2kVVZWWlhY9Lzxpqam3mqqh5gfp05XuXFxcQkODi4oKNi2bZuisCdDxLxMFxsbq7xS1pUrVzqudeDAgfPnz2tpaTGhA9PI9u3bKYrq9N2CntTV19cfOnTorVu3lAubm5sNDAxUb7mxsZH8OeDQTyEOAOAQZ2dnfX195X/Hf/rpp8bGxtdee43Z1NHRUbzy1lU5OTk0TU+aNKnnTfXQoEGDKIpSZYWAbdu2OTo6Xr9+XVHS6RB1wNLSUiAQ5Obmdqm3ycnJynEDc0MlNDSUpmnlxxO9XpcQ4u/vf/369bt37zKbdXV19+/fZ6YRqtgyM8impqZdumTQKIgDADhEIBCsXbv2+PHjhw4dkslkeXl5K1asMDMzCwwMZA5wcHB4/vx5ZmZmU1PTs2fP7t+/r1zd2Nj40aNHRUVF1dXVzG98S0tLRUVFc3PzjRs3goKCrKysFi9e3I2msrOze3HeoJ6enp2dXUlJiSoDkpycrK2trVzS8RB13NqSJUuOHj2amJgok8nkcnlJScnjx48JIQEBAaampt1bt1h9dYODg62trRcvXvzgwYPy8vINGzbU19e//O5kB5hB7ngFAtBwiAMAuOXTTz+NioqKiIgYOHCgm5ubjY1NTk6OSCRi9n700Ufu7u7z5s0bPnz4tm3bmPu9Li4uzGzAFStWDBo0yMnJ6Z133nn+/DkhpKGhYdSoUUKhcMqUKcOGDfvuu+8UT+W72lTv8vT0zM/PVzz4//rrrx0cHAoLCydOnPjxxx8rHzlp0qTg4GAVhygxMTE2NpYQMnr06Lt37yYlJa1du5YQ8vbbbxcUFBBC4uLi1qxZEx0dPWDAADMzs6CgoIqKCkJIY2NjaWlpVlZWN65FfXWNjIx++OEHCwuLsWPHmpub//zzz6dOnep0RQFlv/zyi7m5+ejRo7vRN9AUHSSAAbb4+vr6+vqy3Yv+AWOlwCxZ05dnDAwMNDY27sszMgghqampHR9TUFCgo6Nz8ODBvulSp+Ry+ZQpUw4cONCP6naqrKxMIBDs2bNHlYP7/vsJKsL9AADoPo3NOOfg4BAREREREdFm1pw+JpfLMzMzq6uru5Flm626qggPDx87dqxUKlVH49BnEAcAwKspJCTEz88vICCA9ZRCOTk5x44dy87O7nhJA42q26mYmJjc3NzTp0/zeLxebxz6EuIAAOiOTZs2JScnV1VV2draZmRksN2dtm3fvl0qle7YsYPdbkybNu3w4cOKbAv9om7HsrKyXrx4kZOTY2Rk1OuNQx/TYbsDANAvRUVFRUVFsd2Lznl4eHh4eLDdi1fNrFmzZs2axXYvoHfgfgAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLvwnqCGunr1qp+fH9u96AeuXr1KCMFYkT9XeOXIUMTGxqanp7PdC+gCVZZ5BlZQNE2z3QdoLSYmptMcZQC9Ijs7e9y4ceqYWgbwMkRvGghxAACnURSVmpo6d+5ctjsCAOzA+wEAAADchTgAAACAuxAHAAAAcBfiAAAAAO5CHAAAAMBdiAMAAAC4C3EAAAAAdyEOAAAA4C7EAQAAANyFOAAAAIC7EAcAAABwF+IAAAAA7kIcAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAAA3IU4AAAAgLsQBwAAAHAX4gAAAADuQhwAAADAXYgDAAAAuAtxAAAAAHchDgAAAOAuxAEAAADchTgAAACAuxAHAAAAcBfiAAAAAO5CHAAAAMBdiAMAAAC4C3EAAAAAdyEOAAAA4C4dtjsAAH2qsrKSpmnlktra2oqKCsWmvr4+j8fr834BADuoVv8iAMCrberUqd999117e7W1tR8+fGhqatqXXQIAFuG5AAC3zJs3j6KoNndpaWn99a9/RRAAwCmIAwC4xdfXV0en7QeCFEW9++67fdwfAGAX4gAAbjEyMvLw8NDW1n55l5aWlre3d993CQBYhDgAgHMWLlzY0tLSqlBHR8fT09PAwICVLgEAWxAHAHCOl5cXn89vVSiXyxcuXMhKfwCARYgDADhHT0/P29u71eRAoVD4zjvvsNUlAGAL4gAALpo/f35TU5Nik8fj+fr6CoVCFrsEAKxAHADARdOnT1d+FaCpqWn+/Pks9gcA2II4AICLeDxeQECArq4us2loaDht2jR2uwQArEAcAMBR8+bNa2xsJITweLyFCxe2t6gAALzasK4wAEe1tLQMGTLk6dOnhJBLly5NnjyZ7R4BAAtwPwCAo7S0tBYtWkQIMTMzc3V1Zbs7AMAO9u8EXrlypbi4mO1eAHDRwIEDCSGvv/56eno6230B4Ki5c+ey3AOabb6+viwPAQAAAEvY/hGm2b8fQAjx9fXFnyPQiyiKSk1NZT/K7g8yMjJe4Vg8LS3N39+f5sBbUPjO90fM95PtXuD9AABue4WDAABQBeIAAAAA7kIcAAAAwF2IAwAAALgLcQAAAAB3IQ4AAADgLsQBAAD/x+nTpw0MDL755hu2O6Iu586dCwkJOXbsmJ2dHUVRFEUxK0sqeHh4iMVibW3tkSNHXrt2ja1+KjQ0NDg6Om7evLlv6jY1NUVFRTk4OOjq6hoaGjo7OxcVFXXa8okTJ6Kjo+VyeTc6yS7EAQAA/8ervd7Ap59+Gh8fv2nTJh8fn7t379rb2w8YMODQoUOnTp1SHHP27Nn09PSZM2fm5+ePHz+exd4yQkNDb9++3Wd1/f39//Wvfx0+fLiuru6///2vvb19TU1Npy17eXkJBIJp06ZVVlZ2r6tsQRwAAPB/eHp6VlVVzZw5U90nqq+v7+PMDjt37kxJSUlLSxOLxYrC+Ph4LS2twMDAqqqqvuyMii5fvnzz5s0+q5uSkpKZmZmenv7666/r6OiYmZllZWU5Ozur0vLq1avHjBnzzjvvNDc3d6/DrEAcAADAjgMHDpSWlvbZ6e7cuRMWFrZ161aBQKBc7urqGhQU9PDhw3Xr1vVZZ1RUX1+/fv36uLi4Pqv7+eefjx8/ftSoUd1rOTw8PDc3t3sdZgviAACA/7l06ZKVlRVFUZ999hkhJDExUSQS6enpZWVlzZgxQyKRWFhYHD16lDk4Pj5eIBAMGjToww8/NDMzEwgErq6uP/30E7NXKpXq6uoOHjyY2Vy5cqVIJKIoqqysjBASFBS0du3awsJCiqIcHBwIIWfOnJFIJNu3b1fTpcXHx9M07eXl9fKuyMjIYcOG7d+//9y5c23WpWk6JiZmxIgRfD7fyMho9uzZv//+O7Or4yEihMjl8i1btlhZWQmFwtGjR6empqre59DQ0JUrV5qYmHTlQrtft7Gx8erVq2PHju12y0ZGRm5ubnFxcf3o6RLiAACA/3njjTcuX76s2Pzoo4/WrFlTX18vFotTU1MLCwvt7Ozef//9pqYmQohUKl28eHFdXd3q1auLioquXbvW3Nz81ltvMTlU4+PjlRf8T0hI2Lp1q2IzLi5u5syZ9vb2NE3fuXOHEMK8YtbS0qKmSzt16tTw4cP19PRe3iUUCv/5z39qaWm9//77tbW1Lx8QHh4eEhISGhpaWlp68eLF4uLiKVOmPH36lHQ2RISQjRs37tq1KzY29vHjxzNnzpw/f/6vv/6qSod//PHHwsLC+fPnd+Niu1f30aNHjY2N//nPf9zd3ZnAbsSIEQkJCco/6p22PG7cuIcPH/7222/d6DYrEAcAAHTO1dVVIpGYmJgEBATU1tY+ePBAsUtHR4f5Q9nJySkxMbG6ujo5Obkbp/D09JTJZGFhYb3X6/+pra29d++evb19ewe4uLisWbOmqKho48aNrXbV19fHxMTMmTNn4cKFBgYGo0aN+uKLL8rKyvbt26d8WJtD1NDQkJiY6O3t7ePjY2houHnzZh6Pp8r41NfXBwUFJSYmduNiu12XeR/QxMRk+/bt+fn5T58+nT179qpVq44cOaJ6y0OHDiWE5OXldaPnrEAcAADQBbq6uoQQxR+7rUyYMEFPT09xz1xzlJaW0jTd5s0AhcjIyOHDhyckJFy6dEm5PD8/v6amZsKECYqSiRP/P3t3HhfFle4N/DQ00M3WgCwSEJRFEAHRyESY8DqME2L0oqIgaEwGMxpcETCJsqgsgusFLgbixDAkcWNRA5kgxquRG43rRImICQMooGgERBbpRmio94/62LcvIt00dBdt/b5/pavqnHrqWOl+qOU8ntra2pI7IP1ID1FlZaVQKJQ8Z8fn88eOHSvP+MTExHz44YdWVlYytxzBtjo6OoSQyZMne3t7m5iYCASChIQEgUAgyXjk6ZkeZPpiiVpAHgAAMJJ0dHSampqYjqK/rq4u8vx37mV4PF5OTg6Hw/nggw9EIpFkOf0inL6+vvTGRkZGHR0dMvdL32WIi4vjPFdXVycUCgdvdeHChfLy8hUrVsjsf2TbWlpaEkLoBzho2tratra2NTU18vfM5/PJ8wFXC8gDAABGTE9PT2trq7W1NdOB9Ef/OMmc5cbLyysqKqqqqiopKUmy0MjIiBDS71dfzsOkH6ZLS0ujpFy6dGnwVtnZ2WfPntXQ0KBTB7qT5ORkDocj89mC4bTV19d3dHS8ffu29EKxWCwQCOTvubu7mzwfcLWAPAAAYMSUlpZSFDVjxgz6I5fLfdkdBBUzNzfncDjyzBCQlJTk7Ox848YNyRJXV1d9fX3pn7orV650d3e//vrrMnsbN24cj8crKysbUrQ5OTnSeQN9fSU2NpaiKOnbEyPelhASHBx848aNO3fu0B+FQmFdXR39GqGcPdODbGFhMaRDZhDyAACAYenr63vy5IlYLL5582ZERISNjU1oaCi9ysHBoaWlpbCwsKenp6mpqa6uTrqhiYnJgwcPamtrOzo6enp6SkpKlPfeoK6urp2d3f3792VuSd8d0NTUlF6ycePGEydOHDp0qL29vby8fPXq1ZaWlmFhYfL0tnz58qNHj2ZlZbW3t/f29t6/f//hw4eEkJCQEAsLC8XmLVZe26ioKFtb29DQ0Pr6+sePH2/atEkkEr347OQg6EEefAaCUQV5AADA//r00089PT0JIZs2bZo/f35WVlZaWhohxN3d/c6dOwcOHNi4cSMhZPbs2VVVVXSTrq4uNzc3Pp/v4+MzceLEc+fOSW7Dr1mzxtfXd8mSJU5OTklJSfS1Yi8vL/rFwtWrV5ubm7u4uMyZM6elpUXZhzZ37tyKigrJjf9vvvnGwcGhpqbG09Nz/fr10lvOmDEjKipKesm2bdtSUlISExNNTU1nzpw5fvz40tJSPT09QojMIUpPT4+MjNy1a9eYMWMsLS0jIiKePHlCCOnu7m5sbCwqKlLgWJTX1tjY+Pz589bW1h4eHlZWVlevXi0uLpY5o4C0a9euWVlZubu7KxAbMyimBQYGBgYGMh0FvFIIIXl5eUxHAcyjp6xR6i7CwsJMTEyUugt5yHPOV1VVcbncgwcPqiYkmXp7e318fLKzs9WorUzNzc08Hm/v3r3ybKyC81MeuB4AADAs6lJizsHBITExMTExccCqOSrW29tbWFjY0dEREhKiLm3lER8f7+HhER4erozOlUQ98gBPT09NTc0hXZmR3/Lly3k8HofDUaPXPAaxd+9e+oGg/fv300tGtoiqykqyJiYmuri4GBoa6ujoODg4fPLJJyP45SVdcZXG5XJNTU3/8pe/nDhxYqT2MvipNcqrvr4yJxJIi46ODgoKCgkJYbykUGlp6fHjx0tKSgaf0mBUtZUpNTW1rKzs5MmTWlpaI9658qhHHnDt2jVfX18ldZ6TkzMKq2so7KOPPpKeFZWMdBHVke1tED/88MO6detqa2ubm5tTUlLS09ODgoJGqnNJxVWBQEBfGWtqasrLy2toaFi0aNGQ5j8fxOCn1iiv+vrKnEhKFRMTk5OT09bWNmHChGPHjjEdjlySk5PDw8N37NjBbBizZs06fPiwpPiCWrQdXFFR0bNnz0pLS42NjUe8c6VSjzyAxuFwhtpE9WU9R6FhFlHtN4YqK8mqr69P33k1MDBYvHhxQEDAqVOn6KerlMHY2HjWrFn/9V//RQjJz8+Xuf0InlqjvOqrhJqeSEqVkpLy7NkziqLu3r0bGBjIdDjy8vPz27lzJ9NRvGrmz58fHR0t/Z6FulCnPECBKy1DKuupQJ7BBioujSrx3XffSf8fZWpqSgiROQ3ZMI0fP548nz1tcCN4ao3mqq8jiKkTCQAGp055QHV1tbOzs56eHv1+jvQM2OfPn3dxcREIBDwez83N7fvvvycDlfUkhBw8eHD69Ok8Hk9PT2/8+PGSObM0NDSKi4vfeecdgUBgaWn5j3/8Q56QZBbcpF5erHP37t26uroGBgaNjY0bN260srJavXq1np6ehobG66+/bmFhoaWlpaenN23aNB8fH3ouDiMjo08++WTwo+6nXxHV6upqzgv++7//W84x7Nfb4Acoc3CGpKGhgc/nT5gwQbHmcrp58yYhZObMmZIlqjm1hlP1FScSAAwLI28pSJPzvcFZs2bZ2dndvXu3p6fn1q1bb7zxBo/H+/e//02vLSgoiI+Pb2lpefz48YwZM8aMGUMvX7RoEV3Wk0a/5Lpjx47Hjx+3tLT8/e9/f/fddymKio2NJYScPXu2tbW1paVlzpw5Ojo6nZ2d8sQvadvW1tbY2Ojj46Onp9fd3U2v3bp1q7a29sGDB1tbW2/evDlt2jRTU9Pff/9duu2GDRv27du3cOHCX3/9ddu2bYSQK1eudHZ2Njc3z549mxBSXFzc1NTU2dlJP4NaVlY2+FHT7+x+9tln9Ef6Wvq+ffvoVZs3b6YP7eHDh8bGxt7e3r29vfKPoXRvch7gywZHfp2dnQYGBuHh4XJuT+R7b1D6+QChUFhSUmJra+vn5/f06VPJNso+tezt7e/evUtR1MWLFzU0NMaPH0/vvaSkZP78+ZLNcCIpdiKNkveyVEDOcx5GlVFyfjIfgfx5wJQpUyQf6b/bPvrooxe3TElJIc+La0l/9XR3dxsZGfn6+kq2FIvF6enp1PNvGZFIRC//+uuvCSG3bt2SJ/5+bTMzMwkh1dXVFEUJhUJ9ff2QkBDJxlevXiWEJCYmDtiWoij667ujo4P++NVXXxFCysvLpZvn5uYOftSDfH1LCwgI4PF4v/322+C9DfL1PdQDlB6cIYmNjZ04cWJ7e7uc28ufB/RLi93c3L766iv6ju+LlHFqSfIAiqLo2VfWrVtH/d88ACeSwifSKPmeVQHkAepolJyfXEWuIYwCbm5uAoGAzgb6oR8jePGN3ps3b7a2tr799tuSJZqamhs2bHhZD4rNCi5dcHOoxTpf1ptYLJYZ2MuO+mXy8/O/+eabXbt2OTk5KdzbcKqRyu/EiRP5+fmnT582MDAYUkN5CAQC+mkAsVj86NGj06dPh4eHp6SkXLhwgX4iQZqyT63t27d/9913mZmZwcHB0stxIvUz1BNpBN80Gc3S0tIKCgqYjgKGQJ5pnlVAnZ4P6EdLS0vyRVBcXPynP/3JzMxMR0dH+santPb2dvK8cJZqDKdYpzzkOeoBPX78eP369Z6envQfoAr3puwDJITk5ubu3LmztLSUfoJPebhcrpWV1fLly/fu3VtZWSl5q0qVp5Yyqr7Kgw0nEgC8jLpeDxCLxS0tLTY2NoSQ+vr6gICAhQsX/uMf/3jttdf27ds34LfPa6+9Rv5vYWllG06xTpnkPOoBbdiwobW19YcffpA8kK9Yb0o9QELIvn37vv/++x9++KHfL4RS0dVB6MKjqj+16Kqve/fuTUpKok9vghNp2NjwVzKHw4mMjFy8eDHTgcAQ5Ofn97v4xwh1vR5w7ty5vr4+eoqV8vLynp6eNWvW2NnZ0dO3Ddhk/PjxJiYmp0+fVlmQwynWKZOcR/2i4uLiw4cPb9myZfLkyfSSjz/+WLHelHeAFEVt2rSpvLy8sLBQlUkAIeTnn38mhNBXuRk5tUa26qtMr/aJBAAyqVMe0N3d3dbWJhaLr1+/Hh4eTpeGJITQfzadOXOmq6urqqpK+p6idFlPDQ2NmJiYH3/8MTw8vKGhoa+vr6Ojg/6zT0mGU6xTpkGOehDt7e2rVq3y8PCgy2h2dXX961//Kisrk3MM+92RVd4B3r59e/fu3QcOHNDS0pJ+M23v3r3D7PlFIpGor6+PoqgHDx7k5OTExcWZmppGRkYShk6tka36KtOrfSIBgGxMP6go7/sCOTk5vr6+5ubmXC53zJgxS5Ysqaurk6zdtGmTiYmJkZFRUFAQ/Uayvb19fX399evXbW1t+Xz+m2++Sb+D9Omnn7q5ufF4PB6PN3Xq1MzMzF27dtHFQB0dHWtqag4dOkTPCmltbS3zlYHMzEx6kmq67eeff25oaEgIsbW1pd9p7Ovr27Nnj6Ojo5aWlrv4CX4AACAASURBVLGxcUBAQGVlJd1Wst9x48bRFcDS09Pp3saPH3/+/PmdO3cKBAJCiIWFxeHDh3Nzcy0sLAghxsbGR48efdlRR0RE0Jvp6ektXLhw37599Ayaurq68+bNG/B3dM6cOXKOYVxcnHRvgx+gzMEZRHl5+YCn6549e2SeKpQcz06fOHHixZcFdHR0HB0d16xZU19fL9lSeaeWJAZTU1P6HQFpH3/8sfR7gziRFDuRRsnz2Cog85yHUWiUnJ8ciulZvulHedlwAw9UhsPh5OXl4V4p0PdfGf+WUwGc8+polJyf6nRfAAAAAEYW8oDB/Pbbby9OniqhpPLVbICBBWDQmTNnoqOjR3nla2ldXV3Ozs5xcXGqadvT05OSkuLg4KCtrW1kZOTq6lpbWyuz52+//XbXrl3yz70xeqjre4Oq4ezszPgVm1cSBhaAKdu2bbtx48bhw4cNDAwWLVrk4ODQ2tp66NChkJCQuXPn0tucPn361KlT+/fvLywsZDZaWmxsbGVlpcraBgcH3759+/Dhw6+//npTU9OqVauePn0qs+d58+bdvXt31qxZhYWFqpyoZvhwPQAAQHEjWIFaBXXSd+7cmZubm5+fLz075yivfH3x4sVbt26prG1ubm5hYWFBQcEbb7zB5XItLS2LiopcXV3l6XnDhg1TpkyZM2eOZO5OtYA8AABAcSNYT1nZpZmrq6u3bNmSkJDA4/Gkl4/mytcikejjjz9OT09XWdvPPvts2rRp9HxiCvQcHx9fVlamWMBMQR4AAGxHvbzqcXh4uLa2Nv2WIyFk7dq1enp6HA6Hnj6yXz3ljIwMHo9nbm6+atUqS0tLHo/n7e0tmURhSF0RQk6dOmVoaJicnDxSh5mRkUFR1Lx5815cNZzK1zILQ/f29m7dutXGxobP57u7u9Mvy8kpNjZ27dq1ZmZmQzlQxdt2d3dfvnzZw8ND4Z6NjY1nzpxJlxkbWrjMQR4AAGwXHx8fHR0dGxvb2Nj4448/3rt3z8fH59GjR4SQjIwM6ZfxMjMzExISJB/T09P9/f3pOorV1dXh4eGhoaFCoXDDhg21tbXXr18Xi8VvvfUWXVxxSF2R5/WZ+vr6Ruowi4uLnZyc6MkY+uHz+V9++aWGhsbKlSs7Oztf3GCQIVqzZk1kZKRIJDIwMMjLy6upqbGzs1u5cqVktqjNmzfv3r07LS3t4cOH/v7+S5culZ47chA//fRTTU3N0qVLFThYxdo+ePCgu7v7559/9vX1pTO5SZMmZWZmSv+oy+x56tSpDQ0Nv/zyiwJhMwJ5AACwmkgkSk1NXbhw4bJlywQCgZub2/79+5ubmz///HPFOuRyufTfzS4uLllZWR0dHTk5OQr0M3fu3Pb29i1btigWRj+dnZ137959cfosCS8vr8jIyNraWnqOSGlyDpG3t7ehoaGZmVlISEhnZ2d9fT0hpKurKysrKyAgYNGiRUZGRnFxcVpaWvIMiEgkioiIyMrKUuBgFW5LPw9oZmaWnJxcUVHx6NGjBQsWrFu37siRI/L37OjoSAh52WRooxDyAABgteGXdR7E9OnTdXV1JZfQGdTY2EhR1IAXAyS2b9/u5OSUmZl54cIF6eXDKQxdWVkpFAolz9nx+fyxY8fKMyAxMTEffvihlZWVzC1HsK2Ojg4hZPLkyd7e3iYmJgKBICEhQSAQSDIeeXqmB5m+WKIWkAcAAKspu+qxjo5OU1PTiHQ1HF1dXeT579zLKKPyNX2XIS4uTjJBSF1dnVAoHLzVhQsXysvLV6xYIbP/kW1raWlJ/m/tUG1tbVtb25qaGvl7puf5pgdcLSAPAABWU2rV456enhEsoDwc9I+TzFlu6MrXVVVVSUlJkoXDGSL6Ybq0tDTpCe0vXbo0eKvs7OyzZ89qaGjQqQPdSXJyMofDkflswXDa6uvrOzo69isSJhaL6Qodcvbc3d1Nng+4WkAeAACsJrPqMZfL7VcgUX6lpaUURc2YMWP4XQ2Tubk5h8ORZ4aAka18PW7cOB6PV1ZWNqRoc3JypPMG+oJKbGwsRVHStydGvC0hJDg4+MaNG3fu3KE/CoXCuro6+jVCOXumB5ku06UWkAcAAKvJrHrs4ODQ0tJSWFjY09PT1NRUV1cn3fzFesp9fX1PnjwRi8U3b96MiIiwsbGhK6QPtauSkpIRfG9QV1fXzs7u/v378gzICFa+5vF4y5cvP3r0aFZWVnt7e29v7/379x8+fEgICQkJsbCwUGzeYuW1jYqKoova19fXP378eNOmTSKR6MVnJwdBD/LgMxCMKsgDAIDttm3blpKSkpiYaGpqOnPmzPHjx5eWlurp6dFr16xZ4+vru2TJEicnp6SkJPp6r5eXF/024OrVq83NzV1cXObMmdPS0kII6erqcnNz4/P5Pj4+EydOPHfunOSu/FC7Gllz586tqKiQ3Pj/5ptvHBwcampqPD09169fL73ljBkzoqKi5ByirKystLQ0Qoi7u/udO3cOHDiwceNGQsjs2bOrqqoIIenp6ZGRkbt27RozZoylpWVERMSTJ08IId3d3Y2NjUVFRQoci/LaGhsbnz9/3tra2sPDw8rK6urVq8XFxTJnFJB27do1Kysrd3d3BWJjxsiULx6GwMDAwMBApqOAVwpBLXagKIqJ+u5hYWEmJiaq3CNNnnO+qqqKy+UePHhQNSHJ1Nvb6+Pjk52drUZtZWpububxeHv37pVnY9WfnwPC9QAAgJE0aivOOTg4JCYmJiYmDlg1R8V6e3sLCws7OjoUqC/KVFt5xMfHe3h4hIeHK6NzJUEeAADAFtHR0UFBQSEhIYyXFCotLT1+/HhJScngUxqMqrYypaamlpWVnTx5UktLa8Q7Vx7kAQAAIyMmJiYnJ6etrW3ChAnHjh1jOpyBJScnh4eH79ixg9kwZs2adfjwYUm1BbVoO7iioqJnz56VlpYaGxuPeOdKxWU6AACAV0RKSkpKSgrTUcjm5+fn5+fHdBSvmvnz58+fP5/pKBSB6wEAAADshTwAAACAvZAHAAAAsBfyAAAAAPZCHgAAAMBiTE9kRAUGBjI9BgAAAMxg+keY4lAUxewQXLp0iZ5bGwBULzg4OCIiwsvLi+lAAFhq8eLFzAbAfB4AAAzicDh5eXmMfxMBAFPwfAAAAAB7IQ8AAABgL+QBAAAA7IU8AAAAgL2QBwAAALAX8gAAAAD2Qh4AAADAXsgDAAAA2At5AAAAAHshDwAAAGAv5AEAAADshTwAAACAvZAHAAAAsBfyAAAAAPZCHgAAAMBeyAMAAADYC3kAAAAAeyEPAAAAYC/kAQAAAOyFPAAAAIC9kAcAAACwF/IAAAAA9kIeAAAAwF7IAwAAANgLeQAAAAB7IQ8AAABgL+QBAAAA7IU8AAAAgL2QBwAAALAX8gAAAAD2Qh4AAADAXsgDAAAA2IvLdAAAoFJHjx7t6OiQXnLmzJnW1lbJx4CAADMzM5XHBQDM4FAUxXQMAKA6oaGhX331lZaWFv2R/gbgcDiEkN7eXn19/cbGRh0dHSZDBAAVwn0BAHZZsmQJIaTnObFYLBaL6f/W1NQMCgpCEgDAKrgeAMAuYrHYwsKipaVlwLVnz57985//rOKQAIBBuB4AwC5cLnfJkiWS+wLSTE1NZ86cqfqQAIBByAMAWGfJkiU9PT39Fmppab333nuampqMhAQATMF9AQDWoSjKxsbm/v37/ZZfvXrV09OTkZAAgCm4HgDAOhwOZ9myZf1uDYwbN2769OlMhQQATEEeAMBG/W4NaGlphYaG0m8PAgCr4L4AAEs5OztXVlZKPt66dWvy5MkMxgMAjMD1AACWeu+99yS3BlxcXJAEALAT8gAAllq2bJlYLCaEaGlp/fWvf2U6HABgBu4LALDX9OnTf/75Zw6HU1tba2Njw3Q4AMAAXA8AYK/333+fEPLGG28gCQBgLdQbVJFLly6lpqYyHQXA/9HV1cXhcJ49exYUFMR0LAD/h5eXV1RUFNNRsAKuB6jIvXv3jh07xnQUr6b79+9jbIfq8uXLly9f5vF4FhYW1tbWTIejLDg31NTly5cvXbrEdBRsgesBKlVQUMB0CK+g/Pz84OBgjO2Q0BcACgoKqqurHRwcmA5HWXBuqClcoFIlXA8AYLVXOAkAAHkgDwAAAGAv5AEAAADshTwAAACAvZAHAAAAsBfyAACQ18mTJwUCwT//+U+mA1GWM2fOREdHHz9+3M7OjsPhcDic9957T3oDPz8/AwMDTU3NyZMnX79+nak4Jbq6upydnePi4lTTtqenJyUlxcHBQVtb28jIyNXVtba2VmbP33777a5du3p7exUIElQAeQAAyOvVnoZ827ZtGRkZMTExixYtunPnjr29/ZgxYw4dOlRcXCzZ5vTp0wUFBf7+/hUVFdOmTWMwWlpsbKx00Uhltw0ODv76668PHz4sFAp//fVXe3v7p0+fyux53rx5PB5v1qxZra2tioUKSoU8AADkNXfu3La2Nn9/f2XvSCQSeXt7K3sv0nbu3Jmbm5ufn29gYCBZmJGRoaGhERYW1tbWpspg5HTx4sVbt26prG1ubm5hYWFBQcEbb7zB5XItLS2LiopcXV3l6XnDhg1TpkyZM2cOXdoKRhXkAQAw6mRnZzc2Nqpsd9XV1Vu2bElISODxeNLLvb29IyIiGhoaPvroI5UFIyeRSPTxxx+np6errO1nn302bdo0Nzc3xXqOj48vKytTLGBQKuQBACCXCxcu2NjYcDicTz/9lBCSlZWlp6enq6tbVFT0zjvvGBoaWltbHz16lN44IyODx+OZm5uvWrXK0tKSx+N5e3tfuXKFXhseHq6trT127Fj649q1a/X09DgcTnNzMyEkIiJi48aNNTU1HA6Hnubo1KlThoaGycnJSjq0jIwMiqLmzZv34qrt27dPnDjxiy++OHPmzIBtKYpKTU2dNGmSjo6OsbHxggULfvvtN3rV4ENECOnt7d26dauNjQ2fz3d3d8/Ly5M/5tjY2LVr15qZmQ3lQBVv293dffnyZQ8PD4V7NjY2njlzZnp6+qt9d0kdIQ8AALm8+eabFy9elHxcs2ZNZGSkSCQyMDDIy8urqamxs7NbuXJlT08PISQ8PDw0NFQoFG7YsKG2tvb69etisfitt966d+8eISQjI2Px4sWSrjIzMxMSEiQf09PT/f397e3tKYqqrq4mhNCPmPX19Snp0IqLi52cnHR1dV9cxefzv/zySw0NjZUrV3Z2dr64QXx8fHR0dGxsbGNj448//njv3j0fH59Hjx4RWUNECNm8efPu3bvT0tIePnzo7++/dOnSf/3rX/IE/NNPP9XU1CxdulSBg1Ws7YMHD7q7u3/++WdfX186sZs0aVJmZqb0j7rMnqdOndrQ0PDLL78oEDYoD/IAABgWb29vQ0NDMzOzkJCQzs7O+vp6ySoul0v/oezi4pKVldXR0ZGTk6PALubOndve3r5ly5aRi/p/dXZ23r17197e/mUbeHl5RUZG1tbWbt68ud8qkUiUmpq6cOHCZcuWCQQCNze3/fv3Nzc3f/7559KbDThEXV1dWVlZAQEBixYtMjIyiouL09LSkmd8RCJRREREVlaWAgercFv6eUAzM7Pk5OSKiopHjx4tWLBg3bp1R44ckb9nR0dHQkh5ebkCkYPyIA8AgJGhra1NCJH8sdvP9OnTdXV1JdfMR4/GxkaKoga8GCCxfft2JyenzMzMCxcuSC+vqKh4+vTp9OnTJUs8PT21tbUld0D6kR6iyspKoVAoec6Oz+ePHTtWnvGJiYn58MMPraysZG45gm11dHQIIZMnT/b29jYxMREIBAkJCQKBQJLxyNMzPcj0xRIYPZAHAICK6OjoNDU1MR1Ff11dXeT579zL8Hi8nJwcDofzwQcfiEQiyXL6RTh9fX3pjY2MjDo6OmTul77LEBcXx3murq5OKBQO3urChQvl5eUrVqyQ2f/ItrW0tCSE0A9w0LS1tW1tbWtqauTvmc/nk+cDDqMH8gAAUIWenp7W1lZra2umA+mP/nGSOcuNl5dXVFRUVVVVUlKSZKGRkREhpN+vvpyHST9Ml5aWRkm5dOnS4K2ys7PPnj2roaFBpw50J8nJyRwOR+azBcNpq6+v7+joePv2bemFYrFYIBDI33N3dzd5PuAweiAPAABVKC0tpShqxowZ9Ecul/uyOwgqZm5uzuFw5JkhICkpydnZ+caNG5Ilrq6u+vr60j91V65c6e7ufv3112X2Nm7cOB6PV1ZWNqRoc3JypPMG+vpKbGwsRVHStydGvC0hJDg4+MaNG3fu3KE/CoXCuro6+jVCOXumB9nCwmJIhwzKhjwAAJSlr6/vyZMnYrH45s2bERERNjY2oaGh9CoHB4eWlpbCwsKenp6mpqa6ujrphiYmJg8ePKitre3o6Ojp6SkpKVHee4O6urp2dnb379+XuSV9d0BTU1N6ycaNG0+cOHHo0KH29vby8vLVq1dbWlqGhYXJ09vy5cuPHj2alZXV3t7e29t7//79hw8fEkJCQkIsLCwUm7dYeW2joqJsbW1DQ0Pr6+sfP368adMmkUj04rOTg6AHefAZCED1kAcAgFw+/fRTT09PQsimTZvmz5+flZWVlpZGCHF3d79z586BAwc2btxICJk9e3ZVVRXdpKury83Njc/n+/j4TJw48dy5c5Lb8GvWrPH19V2yZImTk1NSUhJ9rdjLy4t+sXD16tXm5uYuLi5z5sxpaWlR9qHNnTu3oqJCcuP/m2++cXBwqKmp8fT0XL9+vfSWM2bMiIqKkl6ybdu2lJSUxMREU1PTmTNnjh8/vrS0VE9PjxAic4jS09MjIyN37do1ZswYS0vLiIiIJ0+eEEK6u7sbGxuLiooUOBbltTU2Nj5//ry1tbWHh4eVldXVq1eLi4tlzigg7dq1a1ZWVu7u7grEBkpEgUrQM4QwHcWrCWOrgMDAwMDAQKXuIiwszMTERKm7kEnOc6OqqorL5R48eFAFIcmjt7fXx8cnOztbjdrK1NzczOPx9u7dK8/GKjg/QQLXAwBAWdSlxJyDg0NiYmJiYuKAVXNUrLe3t7CwsKOjIyQkRF3ayiM+Pt7DwyM8PFwZncNwIA8AACDR0dFBQUEhISGMlxQqLS09fvx4SUnJ4FMajKq2MqWmppaVlZ08eVJLS2vEO4dhQh7wSlFGeXiVlZxPTEx0cXExNDTU0dFxcHD45JNPlPfH2ZEjRzgczjAr2qn1aCtbTExMTk5OW1vbhAkTjh07xnQ4cklOTg4PD9+xYwezYcyaNevw4cOS4gtq0XZwRUVFz549Ky0tNTY2HvHOYfi4TAcAI4lSQgEPZfQ5oB9++GHdunUhISFaWlolJSXLli0rLy8vKSlRxr6OHDlib29/6dKl6upqupKNAtR6tJUtJSUlJSWF6SiGzM/Pz8/Pj+koXjXz58+fP38+01HAS+F6gHrrV6Z9RMrDK6NPeejr69NPlhkYGCxevDggIODUqVP00+Mj6/Hjx7dv36YL23z99dfyN3yVRhsAgIY8QL0po0y7iku/S3z33XfSb2abmpoSQmROs6qA/Pz8uXPnzps3j8fj0Y+Iy9nwVRptAAAa8oDR5fz58y4uLgKBgMfjubm5ff/995JVBw8enD59Oo/H09PTGz9+fFJSUr8y7f3Kw0+aNInD4WhoaLz++uv0r+knn3xC9/zll1++bF+D90mGV219SBoaGvh8/oQJExQfzZc4cuTIwoULDQwM/Pz8amtrz58//+I2bBttAGAvBt9ZZBU532MuKCiIj49vaWl5/PjxjBkzxowZQy+nZyPZsWPH48ePW1pa/v73v7/77rsURS1atIgu006jr6Lv27ePoiixWDx+/HgbGxuxWCzZIDIyUjKf+cv2NUifFEVt3bpVW1v74MGDra2tN2/enDZtmqmp6e+//06vjY2NJYScPXu2ra2tsbHRx8dHT0+vu7t7qMPV2dlpYGAQHh4uz8ZDmj+grq7OzMyMHpODBw8SQv72t7/124YNo82S97Mxt4SaYsn5OUrg/xAVUeD7iH7MqrGxsbu728jIyNfXV7JKLBanp6dTsn5F6N+z/Px8+mNnZ6eNjU1bW9sg+xq8T6FQqK+vHxISIll79epVQkhiYiL9kf5lEolE9MfMzExCSHV19ZAOnO5n4sSJ7e3t8mw8pLHdsWPH8uXL6f9ua2vT0dExNDQUCoWSDVgy2iz5nkUeoKZYcn6OErgvMHrRL9r29vbevHmztbX17bfflqzS1NTcsGGDzB5WrFghEAjS09Ppj4cOHVqwYIGhoeEg+xq8w+FUW5ffiRMn8vPzv//+ewMDgyE1lAd9U4D+b0NDQz8/v/b2dumJVNkz2seOHeO86oKDgwkhTEcBQ6Yu75q+GvDe4OhSXFy8Z8+eioqK9vZ2yRd6e3s7eV7hdEj09fU//PDDPXv2XL169Q9/+MNnn30m/X/XgPsa3HCqrcspNzc3NTW1tLT0tddeG6k+JW7dulVeXv7i0/hff/21ZA419oz2jBkzIiMjR6SrUevSpUvp6en0VQFQI/TVNVAN5AGjSH19fUBAwMKFC//xj3+89tpr+/bt++STTwgh9C9ic3OzAn2Gh4enp6enpaWtXr163Lhx9vb2g+9rcMOpti6Pffv2ff/99z/88EO/H7+Rcvjw4SVLlhw5ckSy5MmTJ1ZWVqdPn/7999/pGVTYM9rW1taLFy8eka5Gs/T0dDYc5iumoKCA6RBYBPcFRpHy8vKenp41a9bY2dnxeDwOh0MvHz9+vImJyenTpxXok/6uP3bs2JYtWyIiImTua3DDqbY+OIqiNm3aVF5eXlhYqKQkgKKo3NzctWvXSi80NjYOCgrq7e2VJAdsGG0AAAnkAaOIjY0NIeTMmTNdXV1VVVWS28A6OjoxMTE//vhjeHh4Q0NDX19fR0fH7du3yQtl2gfsduPGjWKx+MmTJ3/+859l7mvwPodTbX1wt2/f3r1794EDB7S0tKRvE+7du3eYPUtcvHjR0NDwj3/8Y7/lq1evJlITCrFhtAEA/hfTDyqyhZzPLW/atMnExMTIyCgoKIh+idze3r6+vp6iqE8//dTNzY3H4/F4vKlTp2ZmZlIUdf36dVtbWz6f/+abb8bFxdFXtnV1defNmyfdra+v7xdffCHnvgbvs6+vb8+ePY6OjlpaWsbGxgEBAZWVlXSHmZmZdIUSR0fHmpqazz//nH5KztbW9t///vfgB15eXj7g+blnz54RGdu//e1venp6XC53ypQp169flyxPSkqytLSk92VlZUWP6is/2hRrnsfG+wJqiiXn5yjBoV6V+cxHufz8/ODgYIy2MmBsFRAUFERYcBcW54aaYsn5OUrgvgAAAAB7IQ8AVfjtt98GeVdY8s4eALPOnDkTHR19/PhxOzs7+uR87733pDfw8/MzMDDQ1NScPHny9evXmYpToqury9nZOS4uTjVte3p6UlJSHBwctLW1jYyMXF1da2trZfb87bff7tq1S+aEGcAU5AGgCs7OzoPcncrNzWU6QACybdu2jIyMmJiYRYsW3blzx97efsyYMYcOHSouLpZsc/r06YKCAn9//4qKimnTpjEYLS02NrayslJlbYODg7/++uvDhw8LhcJff/3V3t7+6dOnMnuma3rNmjWLnhIDRhvkAQCgFP1KKo+Srl5m586dubm5+fn50rNYZmRkaGhohIWFtbW1KXXvirl48eKtW7dU1jY3N7ewsLCgoOCNN97gcrmWlpZFRUWurq7y9Lxhw4YpU6bMmTNHLBYrFjAoD/IAAFCKESyprOzqzNXV1Vu2bElISODxeNLLvb29IyIiGhoaPvroI+XtXTEikejjjz+WzGOtgrafffbZtGnT3NzcFOs5Pj6+rKxMsYBBqZAHAMBLUS8vfBweHq6trU2/6EgIWbt2rZ6eHofDoadi7FdSOSMjg8fjmZubr1q1ytLSksfjeXt7S+ZRGFJXhJBTp04ZGhomJyeP1GFmZGRQFDVv3rwXV23fvn3ixIlffPHFmTNnhjpEMmtD9/b2bt261cbGhs/nu7u7D2n+49jY2LVr15qZmQ3lQBVv293dffnyZQ8PD4V7NjY2njlzJl2ya2jhgpIhDwCAl4qPj4+Ojo6NjW1sbPzxxx/v3bvn4+Pz6NEjQkhGRob0fL2ZmZkJCQmSj+np6f7+/nQpxerq6vDw8NDQUKFQuGHDhtra2uvXr4vF4rfeeouurzikrsjzEk19fX0jdZjFxcVOTk70fAz98Pn8L7/8UkNDY+XKlZ2dnS9uMMgQrVmzJjIyUiQSGRgY5OXl1dTU2NnZrVy5UjJh1ObNm3fv3p2Wlvbw4UN/f/+lS5dKTx85iJ9++qmmpmbp0qUKHKxibR88eNDd3f3zzz/7+vrSmdykSZPoeTXk73nq1KkNDQ2//PKLAmGD8iAPAICBiUSi1NTUhQsXLlu2TCAQuLm57d+/v7m5+fPPP1esQy6XS//d7OLikpWV1dHRkZOTo0A/c+fObW9v37Jli2Jh9NPZ2Xn37l1JMYgXeXl5RUZG1tbWbt68ud8qOYfI29vb0NDQzMwsJCSks7Ozvr6eENLV1ZWVlRUQELBo0SIjI6O4uDgtLS15BkQkEkVERGRlZSlwsAq3pZ8HNDMzS05OrqioePTo0YIFC9atWyeZkFuenh0dHQkhL5s0DJiCPAAABjbUwsdDMn36dF1dXckldAY1NjZSFDXgxQCJ7du3Ozk5ZWZmXrhwQXr5cGpDV1ZWCoVCyXN2fD5/7Nix8gxITEzMhx9+aGVlJXPLEWyro6NDCJk8ebK3t7eJiYlAIEhISBAIBJKMR56e6UGmL5bA6IE8AAAGpuzCxzo6Ok1NTSPS1XB0dXWR579zL8Pj8XJycjgczgcffCASiSTLhzNE9F2GuLg4yUQadXV1QqFw8FYXLlwoj35nxgAAIABJREFULy9fsWKFzP5Hti09/bZ0HU5tbW1bW9uamhr5e+bz+eT5gMPogTwAAAam1MLHPT09I1hDeTjoHyeZs9x4eXlFRUVVVVUlJSVJFg5niOiH6dLS0qTn0rh06dLgrbKzs8+ePauhoUGnDnQnycnJHA5H5rMFw2mrr6/v6OhIF9ySEIvFAoFA/p67u7vJ8wGH0QN5AAAMTGbhYy6X+7K6izKVlpZSFDVjxozhdzVM5ubmHA5HnhkCkpKSnJ2db9y4IVkynNrQ48aN4/F4ZWVlQ4o2JydHOm+gL6jExsZSFCV9e2LE2xJCgoODb9y4cefOHfqjUCisq6ujXyOUs2d6kC0sLIZ0yKBsyAMAYGAyCx87ODi0tLQUFhb29PQ0NTXV1dVJN3+xpHJfX9+TJ0/EYvHNmzcjIiJsbGxCQ0MV6KqkpGQE3xvU1dW1s7O7f/++PAOSk5OjqakpvUTh2tA8Hm/58uVHjx7Nyspqb2/v7e29f//+w4cPCSEhISEWFhaKzVusvLZRUVG2trahoaH19fWPHz/etGmTSCR68dnJQdCDPPgMBKB6yAMA4KW2bduWkpKSmJhoamo6c+bM8ePHl5aW6unp0WvXrFnj6+u7ZMkSJyenpKQk+nqvl5cX/Tbg6tWrzc3NXVxc5syZ09LSQgjp6upyc3Pj8/k+Pj4TJ048d+6c5K78ULsaWXPnzq2oqJDc+P/mm28cHBxqamo8PT3Xr18vveWMGTOioqLkHKKsrKy0tDRCiLu7+507dw4cOLBx40ZCyOzZs6uqqggh6enpkZGRu3btGjNmjKWlZURExJMnTwgh3d3djY2NRUVFChyL8toaGxufP3/e2traw8PDysrq6tWrxcXFMmcUkHbt2jUrKyt3d3cFYgMlGlqZYlAU6qArD8ZWAaqv7x4WFmZiYqLKPVJynxtVVVVcLvfgwYMqCEkevb29Pj4+2dnZatRWpubmZh6Pt3fvXnk2Vv35yWa4HgAAKjJqK845ODgkJiYmJiYOWDVHxXp7ewsLCzs6OhSow8lUW3nEx8d7eHiEh4cro3MYDuQBAAAkOjo6KCgoJCSE8ZJCpaWlx48fLykpGXxKg1HVVqbU1NSysrKTJ09qaWmNeOcwTMgDAEDpYmJicnJy2traJkyYcOzYMabDGVhycnJ4ePiOHTuYDWPWrFmHDx+WVFtQi7aDKyoqevbsWWlpqbGx8Yh3DsPHZToAAHj1paSkpKSkMB2FbH5+fn5+fkxH8aqZP3/+/PnzmY4CXgrXAwAAANgLeQAAAAB7IQ8AAABgL+QBAAAA7IXnBFUqPz+f6RBeQXRpFoztkNAzvL7yg4ZzQ03dv39/NNSgYgkORVFMx8AK+fn5wcHBTEcBAKAeAgMDCwoKmI6CFZAHALAah8PJy8tbvHgx04EAADPwfAAAAAB7IQ8AAABgL+QBAAAA7IU8AAAAgL2QBwAAALAX8gAAAAD2Qh4AAADAXsgDAAAA2At5AAAAAHshDwAAAGAv5AEAAADshTwAAACAvZAHAAAAsBfyAAAAAPZCHgAAAMBeyAMAAADYC3kAAAAAeyEPAAAAYC/kAQAAAOyFPAAAAIC9kAcAAACwF/IAAAAA9kIeAAAAwF7IAwAAANgLeQAAAAB7IQ8AAABgL+QBAAAA7IU8AAAAgL2QBwAAALAX8gAAAAD2Qh4AAADAXsgDAAAA2At5AAAAAHtxKIpiOgYAUJ2wsLDKykrJx+vXr0+YMMHY2Jj+qKmp+dVXX1lbWzMUHQCoGpfpAABApSwsLD7//HPpJTdv3pT8t52dHZIAAFbBfQEAdlm6dOnLVmlra4eGhqowFgBgHu4LALCOq6vr7du3B/x/v7KycuLEiaoPCQCYgusBAKzz/vvva2pq9lvI4XCmTJmCJACAbZAHALDOkiVLent7+y3U1NT861//ykg8AMAg3BcAYCNvb+8rV6709fVJlnA4nHv37llZWTEYFQCoHq4HALDRe++9x+FwJB81NDTefPNNJAEALIQ8AICNgoKCpD9yOJz333+fqWAAgEHIAwDYyNTUdNasWZKnBTkcTkBAALMhAQAjkAcAsNSyZcvox4M0NTXffvvtMWPGMB0RADAAeQAASy1cuFBbW5sQQlHUsmXLmA4HAJiBPACApfT09P7jP/6DEKKtre3v7890OADADOQBAOz17rvvEkICAgL09PSYjgUAmIH5A0ajoKCgY8eOMR0FAMAIwy/OKIR6g6PUjBkzIiMjmY5CnQQHB0dERHh5eTEdCGMuXbqUnp6el5c3pFaHDh0KCQnhctXpqwD/1uqIPj+ZjgIGgOsBoxH9bndBQQHTgagTDoeTl5e3ePFipgNhTH5+fnBw8FD/j+7q6uLxeEoKSUnwb62OFDs/QQXwfAAAq6ldEgAAIwt5AAAAAHshDwAAAGAv5AEAAADshTwAAACAvZAHALDayZMnBQLBP//5T6YDUZYzZ85ER0cfP37czs6Ow+FwOJz33ntPegM/Pz8DAwNNTc3Jkydfv36dqTglurq6nJ2d4+LiVNO2p6cnJSXFwcFBW1vbyMjI1dW1trZWZs/ffvvtrl27ent7FQgSRhvkAQCs9mq/x7Vt27aMjIyYmJhFixbduXPH3t5+zJgxhw4dKi4ulmxz+vTpgoICf3//ioqKadOmMRgtLTY2trKyUmVtg4ODv/7668OHDwuFwl9//dXe3v7p06cye543bx6Px5s1a1Zra6tiocLogTwAgNXmzp3b1tamgvoCIpHI29tb2XuRtnPnztzc3Pz8fAMDA8nCjIwMDQ2NsLCwtrY2VQYjp4sXL966dUtlbXNzcwsLCwsKCt544w0ul2tpaVlUVOTq6ipPzxs2bJgyZcqcOXPEYrFiAcMogTwAAFQhOzu7sbFRZburrq7esmVLQkJCvwkSvL29IyIiGhoaPvroI5UFIyeRSPTxxx8rNumeYm0/++yzadOmubm5KdZzfHx8WVkZZglUd8gDANjrwoULNjY2HA7n008/JYRkZWXp6enp6uoWFRW98847hoaG1tbWR48epTfOyMjg8Xjm5uarVq2ytLTk8Xje3t5Xrlyh14aHh2tra48dO5b+uHbtWj09PQ6H09zcTAiJiIjYuHFjTU0Nh8NxcHAghJw6dcrQ0DA5OVlJh5aRkUFR1Lx5815ctX379okTJ37xxRdnzpwZsC1FUampqZMmTdLR0TE2Nl6wYMFvv/1Grxp8iAghvb29W7dutbGx4fP57u7uQ5rmOTY2du3atWZmZkM5UMXbdnd3X7582cPDQ+GejY2NZ86cmZ6e/mrfXXrlIQ8AYK8333zz4sWLko9r1qyJjIwUiUQGBgZ5eXk1NTV2dnYrV67s6ekhhISHh4eGhgqFwg0bNtTW1l6/fl0sFr/11lv37t0jhGRkZEhP9JuZmZmQkCD5mJ6e7u/vb29vT1FUdXU1IYR+xKyvr09Jh1ZcXOzk5KSrq/viKj6f/+WXX2poaKxcubKzs/PFDeLj46Ojo2NjYxsbG3/88cd79+75+Pg8evSIyBoiQsjmzZt3796dlpb28OFDf3//pUuX/utf/5In4J9++qmmpmbp0qUKHKxibR88eNDd3f3zzz/7+vrSid2kSZMyMzOlf9Rl9jx16tSGhoZffvlFgbBhlEAeAAD9eXt7GxoampmZhYSEdHZ21tfXS1ZxuVz6D2UXF5esrKyOjo6cnBwFdjF37tz29vYtW7aMXNT/q7Oz8+7du/b29i/bwMvLKzIysra2dvPmzf1WiUSi1NTUhQsXLlu2TCAQuLm57d+/v7m5+fPPP5febMAh6urqysrKCggIWLRokZGRUVxcnJaWljzjIxKJIiIisrKyFDhYhdvSzwOamZklJydXVFQ8evRowYIF69atO3LkiPw9Ozo6EkLKy8sViBxGCeQBAPBS2trahBDJH7v9TJ8+XVdXV3LNfPRobGykKGrAiwES27dvd3JyyszMvHDhgvTyioqKp0+fTp8+XbLE09NTW1tbcgekH+khqqysFAqFkufs+Hz+2LFj5RmfmJiYDz/80MrKSuaWI9hWR0eHEDJ58mRvb28TExOBQJCQkCAQCCQZjzw904NMXywBNYU8AAAUp6Oj09TUxHQU/XV1dZHnv3Mvw+PxcnJyOBzOBx98IBKJJMvpF+H09fWlNzYyMuro6JC5X/ouQ1xcHOe5uro6oVA4eKsLFy6Ul5evWLFCZv8j29bS0pIQQj/AQdPW1ra1ta2pqZG/Zz6fT54POKgp5AEAoKCenp7W1lZra2umA+mP/nGSOcuNl5dXVFRUVVVVUlKSZKGRkREhpN+vvpyHST9Ml5aWRkm5dOnS4K2ys7PPnj2roaFBpw50J8nJyRwOR+azBcNpq6+v7+joePv2bemFYrFYIBDI33N3dzd5PuCgppAHAICCSktLKYqaMWMG/ZHL5b7sDoKKmZubczgceWYISEpKcnZ2vnHjhmSJq6urvr6+9E/dlStXuru7X3/9dZm9jRs3jsfjlZWVDSnanJwc6byBvr4SGxtLUZT07YkRb0sICQ4OvnHjxp07d+iPQqGwrq6Ofo1Qzp7pQbawsBjSIcOogjwAAIagr6/vyZMnYrH45s2bERERNjY2oaGh9CoHB4eWlpbCwsKenp6mpqa6ujrphiYmJg8ePKitre3o6Ojp6SkpKVHee4O6urp2dnb379+XuSV9d0BTU1N6ycaNG0+cOHHo0KH29vby8vLVq1dbWlqGhYXJ09vy5cuPHj2alZXV3t7e29t7//79hw8fEkJCQkIsLCwUm7dYeW2joqJsbW1DQ0Pr6+sfP368adMmkUj04rOTg6AHefAZCGCUQx4AwF6ffvqpp6cnIWTTpk3z58/PyspKS0sjhLi7u9+5c+fAgQMbN24khMyePbuqqopu0tXV5ebmxufzfXx8Jk6ceO7cOclt+DVr1vj6+i5ZssTJySkpKYm+Vuzl5UW/WLh69Wpzc3MXF5c5c+a0tLQo+9Dmzp1bUVEhufH/zTffODg41NTUeHp6rl+/XnrLGTNmREVFSS/Ztm1bSkpKYmKiqanpzJkzx48fX1paqqenRwiROUTp6emRkZG7du0aM2aMpaVlRETEkydPCCHd3d2NjY1FRUUKHIvy2hobG58/f97a2trDw8PKyurq1avFxcUyZxSQdu3aNSsrK3d3dwVig9GCgtEnMDAwMDCQ6SjUDCEkLy+P6SiYRE9Zo9RdhIWFmZiYKHUX8pDn37qqqorL5R48eFA1IcnU29vr4+OTnZ2tRm1lam5u5vF4e/fulWdjFZyfoBhcDwCAIVCXEnMODg6JiYmJiYkDVs1Rsd7e3sLCwo6OjpCQEHVpK4/4+HgPD4/w8HBldA4qgzzgFbFixQoDAwMOhzPUZ5RGm8TERBcXF0NDQx0dHQcHh08++WSkvselK8/StLW1zc3N//SnP+3Zs4e+eAuvkujo6KCgoJCQEMZLCpWWlh4/frykpGTwKQ1GVVuZUlNTy8rKTp48qaWlNeKdg0oxfUECBqDYfQF6kvMbN24oIySVmTlzZmZm5uPHj9vb2/Py8rS0tGbPni1PQyLffQF7e3uBQEBRFP2827lz50JDQzkcjqWl5bVr14YbPaOUfd01OjqanjNn/PjxBQUFytuRTHL+W9O+//77TZs2KTUeFiosLExJSRGLxfI3wX2BUQvXA0DphlRwVl9fn74JbWBgsHjx4oCAgFOnTtEPmo0sDodjZGT0pz/9KScnJz8//9GjR3QF3hHf0TCpvlzvy6SkpDx79oyiqLt37wYGBjIdjrz8/Px27tzJdBSvmvnz50dHR0u/ZwHqC3nAq4PD4TAdwsCGVHD2u+++k/5yMTU1JYTInJFtmAIDA0NDQxsbG/fv36/UHSlAxeV6AYBtkAeoMYqi9uzZ4+TkpKOjIxAIPv74Y8mq3bt36+rqGhgYNDY2bty40crKqrKyknp5NdXBS8qSQSuxDrXg7JA0NDTw+fwJEyYoPEpyol+CLykpIa/Q6AEAyMbkTQl4CTmfD4iNjeVwOP/5n//55MkToVCYmZlJpJ4PiI2NJYRs2LBh3759Cxcu/PXXX7du3aqtrX3w4MHW1tabN29OmzbN1NT0999/p7cPCwvT09O7fft2V1dXRUWFp6engYFBfX09vXbwtu+++66FhYUksD179hBCmpqa6I+LFi2iC84OVWdnp4GBQXh4uDwbkyE+H9BPe3s7IWTcuHH0R3UcPfbcf5Xz3xpGFfacn2oH1wPUlUgkSktL+8tf/hIVFWVkZMTn801MTF7cbOfOnevWrTt+/Litra3MaqovKykrZyXWEZeSkmJpabl9+3al7oVGv23Rb1Z5tR49AAB5cJkOABRUXV0tFApnzZol5/ZDraYqXVJ2qG1HxIkTJ/Lz80+fPm1gYKC8vUh0dnZSFGVoaDjgWjUavfz8fGV0O9rILN4Dow3+yUYt5AHqip7Wmy4CJg8FqqlKSsoOpxKrYnJzc1NTU0tLS1977TUl7aKff//734QQZ2fnAdeq0egFBwcro9vRJj09PT09nekoAF4FyAPUFY/HI4Q8e/ZMzu2HWk1VuqTscCqxKmDfvn3ff//9Dz/80O+3U6lOnTpFCHnnnXcGXKtGo0dRlDK6HVU4HE5eXt7ixYuZDgSGID8/nyVJqtrB8wHqytXVVUND43/+53/k335I1VSlS8rKbDtSBWcpitq0aVN5eXlhYaEqk4Dff/89LS3N2tr6gw8+GHADtRg9AAAFIA9QV2ZmZosWLTp27Fh2dnZ7e/vNmzcHf+5MnmqqLyspK7PtkArODhLk7du3d+/efeDAAS0tLekJgPfu3avwQL2IoqinT5/29fVRFNXU1JSXl/fHP/5RU1OzsLDwZc8HqMXoAQAogsF3FeBl5HxvsKOjY8WKFWPGjNHX13/zzTe3bt1KCLG2tv7ll1927dpFV30dN26cpORaX1/fnj17HB0dtbS0jI2NAwIC6NfiaWFhYVpaWlZWVlwu19DQcMGCBTU1NZK1g7d9/Pixr68vj8ebMGHC+vXr6ZkMHBwc6Bfnrl+/bmtry+fz33zzTcnLcgMqLy8f8Czds2ePzNEgst4l+/bbb93d3XV1dbW1tTU0NMjzKQX/8Ic/JCYmPn78WLKlmo4ee97LkvlvDaMQe85PtcOhWHA3Ue0EBQURQgoKClS501WrVhUUFDx+/FiVOx1BzN4zHg2jR99/ZcP/0Xg+QB2x5/xUO7gvAP9LXUrKjk4YPQBQR8gDQHV+++03zsspqUQ6AAAMAnkAEEJITExMTk5OW1vbhAkTjh07pqS9ODs7D3KPKjc3V0n7VTbVjB4o5syZM9HR0cePH7ezs6Mzzvfee096Az8/PwMDA01NzcmTJ1+/fp2pOCW6urqcnZ3j4uJU07anpyclJcXBwUFbW9vIyMjV1bW2tlZmz99+++2uXbtwDezVgDwACFHbkrKjBEZv1Nq2bVtGRkZMTMyiRYvu3Lljb28/ZsyYQ4cOFRcXS7Y5ffp0QUGBv79/RUXFtGnTGIyWFhsbW1lZqbK2wcHBX3/99eHDh4VC4a+//mpvb//06VOZPc+bN4/H482aNYueJgvUGvIAAJCXSCTy9vYebV29zM6dO3Nzc/Pz86Wnps7IyNDQ0AgLC2tra1Pq3hVz8eLFW7duqaxtbm5uYWFhQUHBG2+8weVyLS0ti4qKXF1d5el5w4YNU6ZMmTNnjlgsVixgGCWQBwCAvLKzsxsbG0dbVwOqrq7esmVLQkICPfOmhLe3d0RERENDw0cffaS8vStGJBJ9/PHHis2XrFjbzz77bNq0aW5ubor1HB8fX1ZWhgme1R3yAAB2oSgqNTWVLo1obGy8YMECuh4SISQ8PFxbW3vs2LH0x7Vr1+rp6XE4nObmZkJIRETExo0ba2pqOByOg4NDRkYGj8czNzdftWqVpaUlj8fz9vaWFE8aUleEkFOnThkaGiYnJ4/UYWZkZFAUNW/evBdXbd++feLEiV988cWZM2eGOkRZWVl6enq6urpFRUXvvPOOoaGhtbX10aNHJW17e3u3bt1qY2PD5/Pd3d3pl+blFBsbu3btWvmLhgyzbXd39+XLlz08PBTu2djYeObMmenp6XgbUK0hDwBgl/j4+Ojo6NjY2MbGxh9//PHevXs+Pj6PHj0ihGRkZEi/lJ+ZmZmQkCD5mJ6e7u/vb29vT1FUdXV1eHh4aGioUCjcsGFDbW3t9evXxWLxW2+9de/evaF2RZ6/ddnX1zdSh1lcXOzk5KSrq/viKj6f/+WXX2poaKxcubKzs/PFDQYZojVr1kRGRopEIgMDg7y8vJqaGjs7u5UrV0qmety8efPu3bvT0tIePnzo7++/dOlS6SmlB/HTTz/V1NQsXbpUgYNVrO2DBw+6u7t//vlnX19fOpObNGlSZmam9I+6zJ6nTp3a0NDwyy+/KBA2jBLIAwBYRCQSpaamLly4cNmyZQKBwM3Nbf/+/c3NzYNPSj0ILpdL/93s4uKSlZXV0dGRk5OjQD9z585tb2/fsmWLYmH009nZeffuXXt7+5dt4OXlFRkZWVtbu3nz5n6r5Bwib29vQ0NDMzOzkJCQzs7O+vp6QkhXV1dWVlZAQMCiRYuMjIzi4uK0tLTkGRCRSBQREZGVlaXAwSrcln4e0MzMLDk5uaKi4tGjRwsWLFi3bt2RI0fk79nR0ZEQ8rKZQEEtIA8AYJGKioqnT59Onz5dssTT01NbW1tyPX84pk+frqurK7mEzqDGxkaKoga8GCCxfft2JyenzMzMCxcuSC8f6hBpa2sTQujrAZWVlUKhUPKcHZ/PHzt2rDwDEhMT8+GHH1pZWcnccgTb6ujoEEImT57s7e1tYmIiEAgSEhIEAoEk45GnZ3qQ6YsloKaQBwCwCP2WV79ajkZGRv3KIitMR0enqalpRLoajq6uLvL8d+5leDxeTk4Oh8P54IMPRCKRZPlwhoi+yxAXFyeZHauurk4oFA7e6sKFC+Xl5StWrJDZ/8i2tbS0JITQT2zQtLW1bW1ta2pq5O+ZrsRBDzioKeQBACxiZGRECOn3k9ba2mptbT38znt6ekaqq2Gif5xkznLj5eUVFRVVVVWVlJQkWTicIaIfpktLS5OeIOvSpUuDt8rOzj579qyGhgadOtCdJCcnczgcmc8WDKetvr6+o6Pj7du3pReKxWKBQCB/z93d3eT5gIOaQh4AwCKurq76+vrS3+NXrlzp7u5+/fXX6Y9cLlfh6salpaUURc2YMWP4XQ2Tubk5h8ORZ4aApKQkZ2fnGzduSJbIHKJBjBs3jsfjlZWVDSnanJwc6byBvqASGxtLUZT07YkRb0sICQ4OvnHjxp07d+iPQqGwrq6Ofo1Qzp7pQbawsBjSIcOogjwAgEV4PN7GjRtPnDhx6NCh9vb28vLy1atXW1pahoWF0Rs4ODi0tLQUFhb29PQ0NTXV1dVJNzcxMXnw4EFtbW1HRwf9G9/X1/fkyROxWHzz5s2IiAgbG5vQ0FAFuiopKRnB9wZ1dXXt7Ozu378vz4Dk5ORoampKLxl8iAbvbfny5UePHs3Kympvb+/t7b1///7Dhw8JISEhIRYWForNW6y8tlFRUba2tqGhofX19Y8fP960aZNIJHrx2clB0IM8+AwEMMohDwBgl23btqWkpCQmJpqams6cOXP8+PGlpaV6enr02jVr1vj6+i5ZssTJySkpKYm+3uvl5UW/Dbh69Wpzc3MXF5c5c+a0tLQQQrq6utzc3Ph8vo+Pz8SJE8+dOye5Kz/UrkbW3LlzKyoqJDf+v/nmGwcHh5qaGk9Pz/Xr10tvOWPGjKioKDmHKCsrKy0tjRDi7u5+586dAwcObNy4kRAye/bsqqoqQkh6enpkZOSuXbvGjBljaWkZERHx5MkTQkh3d3djY2NRUZECx6K8tsbGxufPn7e2tvbw8LCysrp69WpxcbHMGQWkXbt2zcrKyt3dXYHYYLQYpO4LMCUwMDAwMJDpKNQMISQvL4/pKJhET1mjyj2GhYWZmJioco80ef6tq6qquFzuwYMHVROSTL29vT4+PtnZ2WrUVqbm5mYej7d37155Nlb9+QlywvUAAFDcqK045+DgkJiYmJiYOGDVHBXr7e0tLCzs6OhQoLg2U23lER8f7+HhER4erozOQWWQBwDAqyk6OjooKCgkJITxkkKlpaXHjx8vKSkZfEqDUdVWptTU1LKyspMnT2ppaY1456BKyAMAQBExMTE5OTltbW0TJkw4duwY0+EMLDk5OTw8fMeOHcyGMWvWrMOHD0uqLahF28EVFRU9e/astLTU2Nh4xDsHFeMyHQAAqKWUlJSUlBSmo5DNz8/Pz8+P6SheNfPnz58/fz7TUcDIwPUAAAAA9kIeAAAAwF7IAwAAANgLeQAAAAB74TnBUery5ctBQUFMR6Fm0tLSCgoKmI6CMfQMryw5bVj+b62O5JnmGRjBoSiK6Rigv9TUVJk1ygBGRElJydSpU5XxahnAi5C9jULIAwBYjcPh5OXlLV68mOlAAIAZeD4AAACAvZAHAAAAsBfyAAAAAPZCHgAAAMBeyAMAAADYC3kAAAAAeyEPAAAAYC/kAQAAAOyFPAAAAIC9kAcAAACwF/IAAAAA9kIeAAAAwF7IAwAAANgLeQAAAAB7IQ8AAABgL+QBAAAA7IU8AAAAgL2QBwAAALAX8gAAAAD2Qh4AAADAXsgDAAAA2At5AAAAAHshDwAAAGAv5AEAAADshTwAAACAvZAHAAAAsBfyAAAAAPZCHgAAAMBeyAMAAADYC3kAAAAAeyEPAAAAYC/kAQAAAOzFZToAAFCp1tZWiqKkl3R2dj558kTyUV9fX0tLS+VxAQAzOP2+EQDg1fbnP//53LlzL1urqanZ0NBgYWGhypAAgEG4LwDALkuWLOFwOAOu0tDQ+H//7/8hCQBgFeSe8kvyAAAgAElEQVQBAOwSGBjI5Q58Q5DD4bz//vsqjgcAmIU8AIBdjI2N/fz8NDU1X1yloaEREBCg+pAAgEHIAwBYZ9myZX19ff0WcrncuXPnCgQCRkICAKYgDwBgnXnz5uno6PRb2Nvbu2zZMkbiAQAGIQ8AYB1dXd2AgIB+Lwfy+fw5c+YwFRIAMAV5AAAbLV26tKenR/JRS0srMDCQz+czGBIAMAJ5AAAbvf3229KPAvT09CxdupTBeACAKcgDANhIS0srJCREW1ub/mhkZDRr1ixmQwIARiAPAGCpJUuWdHd3E0K0tLSWLVv2skkFAODVhnmF4f+zd+9xTVxp48DPQEhCAgmIgCwICgjITWqlFSo/dNmyVQpeAEGru9TVUrXFALrIReUiKNUCi5L6UVm69QpoC7aI64uVVuq1CopoLaCgeCGgyC3BcJnfH/PpvHm5JCGEBJjn+xczc+bMmcNAnsycOQ+gqL6+vj/96U+NjY0IobKysvfee0/dLQIAqAHcDwCAojQ0NFavXo0QMjExcXd3V3dzAADq8X/uBDY0NFy+fFldTQEAqNjkyZMRQu+++25+fr662wIAUJGpU6e6ubn97zIuITc3V30NAwAAAMCoCwgIkPzoH2RkEIwYAGNfXl5eUFAQXKsjd+rUqYCAAHW3YkIJDAxECE34WyzwNzhOEdenJBgfAAClQRAAAMVBHAAAAABQF8QBAAAAAHVBHAAAAABQF8QBAAAAAHVBHAAAAABQF8QBAACgfmfPnuVyud9//726GzJaSkpKoqOjT58+bWlpiWEYhmHEdJYkb29vXV1dTU1NBweHW7duqaudpK6uLjs7u7i4ONXs293dnZKSYm1tTafT9fT0HB0d6+rqZNZ85syZ1NTU3t5eBRpJgjgAAADUb2K/iL9jx47MzMyYmBh/f/+HDx9aWVkZGBgcPXq0qKiILHP+/Pn8/HxfX9+qqqrZs2ersbWE2NjYBw8eqGzfoKCgb7755tixY0Kh8P79+1ZWVh0dHTJr9vPzYzKZXl5er1+/VqypCOIAAAAYC3x8fFpbW319fUf7QCKRSMXpJHbv3n3y5Mm8vDxdXV1yZWZmpoaGRmhoaGtrqyobI6fLly/fvXtXZfuePHmyoKAgPz//3XffpdFoJiYmhYWFjo6O8tS8adOmWbNmLVq0qKenR7EGQxwAAAAUkp2dLRAIVHa4mpqabdu2JSQkMJlMyfXu7u48Hu/p06ebN29WWWPkJBKJtmzZkpGRobJ9v/rqq9mzZzs5OSlWc3x8fEVFhWINRhAHAACA2pWVlZmbm2MYtn//foQQn89ns9ksFquwsHDhwoUcDsfMzOzEiRNE4czMTCaTaWRk9Omnn5qYmDCZTHd392vXrhFbw8LC6HT6lClTiMWNGzey2WwMw5qbmxFCPB4vMjKytrYWwzBra2uE0Llz5zgcTnJy8iidWmZmJo7jfn5+Azft3LnTxsbm8OHDJSUlg+6L43haWtrMmTMZDIa+vv6SJUt+++03YpP0LkII9fb2bt++3dzcXFtb29nZeVjZc2JjYzdu3GhoaDicE1V8X7FYfPXqVRcXF4Vr1tfX9/T0zMjIUOzpEsQBAACgZvPmzZPM9bphw4bw8HCRSKSrq5ubm1tbW2tpablu3bru7m6EUFhYWEhIiFAo3LRpU11d3a1bt3p6et5///0nT54ghDIzM5cvX05WlZWVlZCQQC5mZGT4+vpaWVnhOF5TU4MQIoaY9fX1jdKpFRUV2draslisgZu0tbW//vprDQ2NdevWdXZ2DiwQHx8fHR0dGxsrEAh+/vnnJ0+eeHh4NDY2IlldhBDaunXrF198kZ6e/vz5c19f35UrV/7666/yNPiXX36pra1duXKlAier2L7Pnj0Ti8U3b95csGABEdjNnDkzKytL8kNdZs1vvfXW06dPb9++rUCzIQ4AAIAxyt3dncPhGBoaBgcHd3Z2Pn78mNxEo9GIL8r29vZ8Pr+9vT0nJ0eBQ/j4+LS1tW3btk15rf5fnZ2djx49srKyGqqAm5tbeHh4XV3d1q1b+20SiURpaWnLli1btWoVl8t1cnI6cOBAc3PzwYMHJYsN2kVdXV18Pn/p0qX+/v56enpxcXFaWlry9I9IJOLxeHw+X4GTVXhfYjygoaFhcnJyVVVVY2PjkiVLPvvss+PHj8tf84wZMxBClZWVCrQc4gAAABjr6HQ6Qoj8stvPnDlzWCwWec987BAIBDiOD3ozgLRz505bW9usrKyysjLJ9VVVVR0dHXPmzCHXuLq60ul08glIP5Jd9ODBA6FQSI6z09bWnjJlijz9ExMT88knn5iamsosqcR9GQwGQsjBwcHd3X3SpElcLjchIYHL5ZIRjzw1E51M3CwZLogDAABg3GMwGE1NTepuRX9dXV3oj8+5oTCZzJycHAzD1qxZIxKJyPXEi3A6OjqShfX09Nrb22Uel3jKEBcXh/2hvr5eKBRK36usrKyysnLt2rUy61fuviYmJgghYgAHgU6nW1hY1NbWyl+ztrY2+qPDhwviAAAAGN+6u7tfv35tZmam7ob0R3w4yZzlxs3NLSIiorq6OikpiVypp6eHEOr3qS/naRKD6dLT03EJV65ckb5Xdnb2hQsXNDQ0iNCBqCQ5ORnDMJljC0ayr46OzowZM+7duye5sqenh8vlyl+zWCxGf3T4cEEcAAAA41tpaSmO43PnziUWaTTaUE8QVMzIyAjDMHlmCEhKSrKzsysvLyfXODo66ujoSH7UXbt2TSwWv/322zJrmzp1KpPJrKioGFZrc3JyJOMG4v5KbGwsjuOSjyeUvi9CKCgoqLy8/OHDh8SiUCisr68nXiOUs2aik42NjYd1ygSIAwAAYPzp6+traWnp6em5c+cOj8czNzcPCQkhNllbW7969aqgoKC7u7upqam+vl5yx0mTJj179qyurq69vb27u7u4uHj03htksViWlpYNDQ0ySxJPBzQ1NSXXREZGfvvtt0ePHm1ra6usrFy/fr2JiUloaKg8tX388ccnTpzg8/ltbW29vb0NDQ3Pnz9HCAUHBxsbGys2b/Ho7RsREWFhYRESEvL48eOXL19GRUWJRKKBYyelIDpZ+gwEQ4E4AAAA1Gz//v2urq4IoaioqMWLF/P5/PT0dISQs7Pzw4cPDx06FBkZiRD64IMPqquriV26urqcnJy0tbU9PDxsbGwuXrxIPobfsGHDggULVqxYYWtrm5SURNwrdnNzI14sXL9+vZGRkb29/aJFi169ejXap+bj41NVVUU++P/uu++sra1ra2tdXV0///xzyZJz586NiIiQXLNjx46UlJTExMTJkyd7enpOmzattLSUzWYjhGR2UUZGRnh4eGpqqoGBgYmJCY/Ha2lpQQiJxWKBQFBYWKjAuYzevvr6+pcuXTIzM3NxcTE1Nb1+/XpRUZHMGQUk3bhxw9TU1NnZWYG2IckbDsRMCzgAYx5cq2DMCggICAgIGNVDhIaGTpo0aVQPIZOcf4PV1dU0Gu3IkSMqaJI8ent7PTw8srOzx9G+MjU3NzOZzL1798pTeOD1CfcDAABg/BlhijmVsba2TkxMTExMHDRrjor19vYWFBS0t7cHBwePl33lER8f7+LiEhYWptjuSo4D9u7dSwwMOXDggMzCrq6umpqaw7r1MdxDAHkM7FIlpkBNTEy0t7fncDgMBsPa2vqf//znUP8O1q5dq6uri2HYcEf3yPT7779//vnnDg4OHA6HTqcbGhra2dktW7bsu+++Iwqo/bo9fvw4hmEqzv6iMMnUsRiGaWlpmZqafvTRR/fv3x955eq6GvudFIZhdDrdyMho/vz5e/bsIW4pA8VER0cHBgYGBwerPaVQaWnp6dOni4uLpU9pMKb2lSktLa2iouLs2bNaWloKViF5c0Ap91qJZzNfffWVPIW9vLxmzZo1qocA8ujXpT/88AOHwzlz5szIa/b09MzKynr58mVbW1tubq6WltYHH3wwVGFievDy8nKZ1cp/rebk5NDp9Hnz5p07d66lpaWrq6u2tvb777/38fEJDQ0li6n3uvXx8SHmXKuurh5utepiZWXF5XJxHO/o6Dhz5oy5ubmOjs5vv/028prVeDWSJ0WMwrt48WJISAiGYSYmJjdu3JDzKKP9XCA6OpqYM2fatGn5+fmjdyDphvt58d///jcqKmr02kNNBQUFKSkpPT098u8yFp8LYBim7iaA/pSYAlVHR4d4lqmrq7t8+fKlS5eeO3eOGK+kAlevXl27dq27u/vFixf/+te/6unpMRgMS0vLDz/8MDMzcyQ1K/G6ffny5b1794hJ4L/55htlVasybDbb19f3X//6V0dHx759+5Rev1quRgzD9PT05s+fn5OTk5eX19jYSDRj5G0YuZSUlDdv3uA4/ujRo4CAAHU3R17e3t67d+9WdysmmsWLF0dHR0u+Z6EAJcQBOI7n5+f3m/NZforfyhhXRthL40i/M/3hhx8kr9HJkycjhIaa2EvpQWFycnJvb++uXbtoNFq/TZaWliN5tKTE6zYvL8/Hx8fPz4/JZBLDqZRVswIUvlDfeecdhJDCKdtHyUiuRlJAQEBISIhAIIBnkWBCUiQO6O3tTUlJsbW11dbWnjx58vTp01NSUiQzXEnCh04cSaipqbGzs2Oz2cQLMJJTTF+6dMne3p7L5TKZTCcnp//+978KtHbQSmbOnIlhmIaGxttvv038F/jnP/9JlPn666/REDkrv/jiCxaLpaurKxAIIiMjTU1NHzx4MFQjpfeSAjkxpScbldnVMn8RpGGlQJV5pv08ffpUW1t7+vTpZKv27Nlja2vLYDC4XO6WLVtk9oP8xGJxSUnJpEmTyPlV5KfK6/b48ePLli3T1dX19vauq6u7dOkSuWkcXag9PT1IYgbZ8Xg1SkG8ml9cXCyzJADjj+RDAjmf9yQnJ2tqahYWFgqFwps3bxobG8+fP5/c2u/Z3vbt2+l0+pEjR16/fn3nzp3Zs2dPnjz5xYsXxFYvLy9LS8tHjx51d3ffvXv33XffZTKZv//+O7E1Pz8/Pj7+1atXL1++nDt3roGBwaCHkG7QSnp6eqZNm2Zubi75WCU8PJych3Lz5s0MBuPUqVMtLS0xMTEaGhrE08HY2FiE0KZNm/bt27ds2bL79+8P1UjpvTRU/dKFhoay2ex79+51dXVVVVW5urrq6uo+fvxYnq6WvrVflxJ3Svft20csEmd94cKF1tZWgUDg4eHBZrPFYrE8Zyqps7NTV1c3LCyMXBMbG4th2JdfftnS0iIUCrOyspDyxgf8/vvvCKG5c+fKrA1X33VbX19vaGhIXIdHjhxBCP3jH/8gt47lC5V8lE4gGr9lyxZ5OnBsXo0DT4rU1taGEJo6deqgVfWjgvcGxwJ4d3ecGnh9KhIHuLq6vvPOO+TiJ598oqGhQTyvwv/v37BQKNTR0QkODiYLX79+HSGUmJhILPYbb3Xnzh2E0ObNmwceNCUlBf2RvUrhcYKSlRBzUOTl5RGbOjs7zc3NW1tbcRwXiUQsFotstlAoZDAYGzZswP/4HyQSiWTWL6WXpNQvXWhoqOQ/qRs3biCEEhIScFldLfMXIc9/XvKsiU/rmpoaYlH69SApNjbWxsamra2NPHEWi/X++++TBZQ7TpCYkfQvf/mLzNpw9V23u3bt+vjjj4mfW1tbGQwGh8MRCoVkgTF7oUqOEzx16pSxsbGRkVFDQ4PMDhybV2O/kxqIGDEw6KZ+IA4AY9nA67P/Q1N5dHV1MZlMcrG3t1dLS2vQcQrDTRzp5OTE5XKJ/6r9EI9jR/jKrGQla9eujY+Pz8jICAwMRAgdPXp0yZIlHA4HjSBnpWT9UnpJ4fr7kUw2Kr2rh/uLkK5fClQ5r4dvv/02Ly/v/Pnzurq6xJqamhqhUOjl5aVAG+RBZCojMo9JysvLi4qKqqurQwjZ2dn99NNPRkZGkgVUed0eP36c+FRGCHE4HG9v7++//76wsJB8z3gsX6itra0Yhmlqak6ZMmXRokU7duwgUqOOx6tRus7OThzHiW6Xx9WrV4nf1wRGTGQ74U9z4rl69Wq/R6WKjA9YtGjRzZs3CwsLRSLRr7/+WlBQ8OGHHw4aByiQOFJLS4v8ky4qKpo/f76hoSGDwfjnP/+pQFOlVKKjo/PJJ59cvnyZ+C7y1VdfkZMwDCtn5VD1S+klxXJiDopMNiq9q0eSwVMmea6HkydP7t69u7S0dNq0aeRK4v8IkT5rNFhYWDAYjJqamn7rly9f/ujRIwsLC2Nj4/v37/cLApAKr9u7d+9WVlb6+vqSVwLxlrzkWwNj+UIlvjr39PQ0NDT8+9//trCwkKcDx+bVKB3xjMnOzm7kLQRgrFHkfkB8fPzNmzdDQkI6OjpMTEyWL18+VI6K4SaO7OnpefXqlbm5OULo8ePHS5cuXbZs2b///e8//elP+/btUyAUkF5JWFhYRkZGenr6+vXrp06dSrzAjSRyVvJ4PIXrl9JL8tcvnWSyUeldPZIMnjLJvB727dv33//+98cff+z3r5/43vbmzZuRt2FQTCbzL3/5S1FR0cD4VzqVXbfHjh1bsWLF8ePHyTUtLS2mpqbnz59/8eLFlClTiJXj7kIdj1ejdOfOnUMILVy4UM7yc+fOzc/Pl7/+8SgvLy8oKGjCn+bEM/AWjiJxQFVVVW1tbVNT08B3sfoZbuLIixcv9vX1zZ49GyFUWVnZ3d29YcMGS0tLpOgbZdIrMTMzW758eW5u7rNnz3bs2EGulz9npZT6pfSSYjkxB5JMNiq9q0eSwVMmKWeK4/jWrVtbWloKCgoGbnV0dNTQ0Pjpp5/Wr18/8mYMKiEh4fz581u2bPnxxx/lf9NPNdctjuMnT548evSo5Ep9ff3AwMBvvvnm+PHjZM6VcXehjserUYoXL16kp6ebmZmtWbNm5C0EYKxR5LnAZ599Zm5uLs9k0fIkjhSLxa2trT09Pbdu3QoLCyNyLyKEiG9XJSUlXV1d1dXVij07lFlJZGRkT09PS0vLn//8Z8lmD5WzUv76pfSS/PUPNFSyUeldPZIMnjJJOdN79+598cUXhw4d0tLSkpyxde/evQghQ0NDf3//U6dOZWdnt7W13blzR+nzK7z99ttHjhy5efPm/Pnzz5079/z5856envr6+iNHjkjJtKaa6/by5cscDue9997rt56IivpNKDS+LtTxeDWScBzv6Ojo6+vDcbypqSk3N/e9997T1NQsKCiQf3wAAOOJ5KBBOcd//vjjjwYGBmQNWlpaM2fOPH36NI7jX375pbGxMUKIzWYvW7YMx/G+vr49e/bMmDFDS0tLX19/6dKlDx48IKvKyclZsGCBkZERjUYzMDBYsWJFfX09uTUqKmrSpEl6enqBgYHE28NWVlY8Hq/fIaQbtBLyXTscxxcsWHD48OF+e7158yYqKsrc3JxGoxEfV1VVVampqUQGz6lTp5Lps4aqX0ovDVW/zHMJDQ0l5nKn0WgcDmfJkiW1tbXkVuldLWVrv9/avn37iDvSLBbLz88vKyuLmBN7xowZtbW1Bw8eJP4bWlhYEG/KSTnTysrKQa+6PXv2EIdub29fu3atgYGBjo7OvHnztm/fjhAyMzO7ffu29K4Y1ljlR48e8Xg8BwcHNpvNZDKnT5/u4eGxdevWn3/+edAekNmZI79u//GPf7DZbBqNNmvWrFu3bpH7JiUlmZiYEL1kamqalZVFbho7F+ovv/xiY2NDlDcxMQkMDBzY5+Puajxz5oyzszOLxaLT6RoaGuiPKQXfeeedxMTEly9fynmx4fC+ABjblPPeYFZWFo/HIxffvHkTHh7OYDAkX3YCo9FLYyHZ6EBquR7gf5CyTLA/57FwOhAHgLFMCe8NvnjxIiwsTPKRIZ1ONzc37+7u7u7uJr6FgNHrpbGWbBSuh3Ftgv36JtjpAKAawx4foK2traWllZ2d3djY2N3d/ezZs8OHD2/fvj04OFj1D89+++03bGijlOlZHgr00pg9F+nG1PUAhmuC/fom2OkAUklJSXR0tGRu6NWrV0sW8Pb21tXV1dTUdHBwuHXrlrra2d3dnZKSYm1tTafT9fT0HB0diXlK+unq6rKzs4uLiyMWz5w5k5qaqs7veJI3B+S8z/Pzzz//5S9/4XA4mpqaXC7X3d09Kyuru7tbyTcvxjml99IYSTY6kFquB7gnqSwT7M95LJwOPBdQru3bt/v6+pIzP1pZWRFDQH744QfJYsXFxYsXL1ZBe6RYunSpra3t1atXiTDUz8+vsrJyYDHiVaDY2FhyTUZGhqenZ0tLiwoaqZzxAQCoHVyrYMxSQRwgFArd3NzUW5Vq/gZ37dplY2MjOUO2lZXVsWPHNDQ0TE1NX79+Ta5Xexxw4sQJDMPu3Lkjvdgvv/zi7e3dLw7AcTwsLMzNzU0FMevA61MJeYcBAACoUnZ2tkAgGGtVKV1NTc22bdsSEhIk54pGCLm7u/N4vKdPn27evFldbRvoq6++mj17tpOTk5QyIpFoy5YtGRkZAzfFx8dXVFQMumm0QRwAAABqgA+dfDksLIxOp5MTSm7cuJHNZmMY1tzcjBDi8XiRkZG1tbUYhllbW0vPSD6sqhBC586d43A4Q00Rq2KZmZk4jvv5+Q3ctHPnThsbm8OHD5eUlAy6r5TulSd79XDzwovF4qtXr7q4uEgvFhsbu3HjxkEnU9fX1/f09MzIyMBxXObhlEzy5gDcawXjBVyrYMyS87mA9OTLH330kbGxMVl4z549CKGmpiZi0d/f38rKitwqPSP5sKr64YcfdHV1ydyPUqjgb9DS0tLe3r7fSisrq0ePHuE4fvnyZQ0NjWnTpnV0dOADngtI717p2asVyAv/6NEjhJCLi8v8+fOnTJnCYDDs7Oz2799PTEhFKCsr8/Pzw3GcSArT77kAjuPR0dFIvoSrIwHPBQAAQP1EIlFaWtqyZctWrVrF5XKdnJwOHDjQ3Nys8JSaNBqN+O5rb2/P5/Pb29tzcnIUqMfHx6etrW3btm2KNUOJOjs7Hz16RGbTGMjNzS08PLyurm7r1q39NsnZve7u7hwOx9DQMDg4uLOz8/Hjxwihrq4uPp+/dOlSf39/PT29uLg4LS0tmZ1JTGFpaGiYnJxcVVXV2Ni4ZMmSzz77jMweIhKJeDwen8+XUsmMGTMQQkNNeDV6IA4AAABVU27y5X4kM5KPXwKBAMdxYvrIoezcudPW1jYrK6usrExy/XC7VzJ7tWLpvBkMBkLIwcHB3d190qRJXC43ISGBy+WSkUdMTMwnn3xCJOYeCnGyjY2N0o+ldBAHAACAqo1q8mUkkZF8/Orq6kJ/fL4Ohclk5uTkYBi2Zs0akUhErh9J9yqWF56YDpwYdUGg0+kWFha1tbUIobKyssrKyrVr10qvhJjqijhxVYI4AAAAVG1Uky9LZiQfv4gPRZmz67i5uUVERFRXVyclJZErR9K9ZLptySfoV65ckb6Xjo7OjBkz7t27J7myp6eHy+UihLKzsy9cuKChoUEEFsQhkpOTMQyTTLwpFovJE1cliAMAAEDVZCZfptFoxG1qBUhmJB9hVWpkZGSEYVhra6vMkklJSXZ2duXl5eSakeS2VjjddlBQUHl5+cOHD4lFoVBYX19PvEaYk5MjGVVIjhOUfHhBnCyRZ0uVIA4AAABVk5l82dra+tWrVwUFBd3d3U1NTfX19ZK7T5o06dmzZ3V1de3t7cRn/FAZyYdbVXFx8Rh5b5DFYllaWjY0NMgsSTwd0NTUlFyjcG5rKem2g4ODjY2Nh5q3OCIigsg//vjx45cvX0ZFRYlEooFjGKUgTlb6DASjAeIAAABQgx07dqSkpCQmJk6ePNnT03PatGmlpaVsNpvYumHDhgULFqxYscLW1jYpKYm4V+zm5vbkyROE0Pr1642MjOzt7RctWvTq1SuEUFdXl5OTk7a2toeHh42NzcWLF8kn68Otauzw8fGpqqoiH/x/99131tbWtbW1rq6un3/+uWTJuXPnEpP1kqR0L5/PT09PRwg5Ozs/fPjw0KFDkZGRCKEPPviguroaIZSRkREeHp6ammpgYGBiYsLj8VpaWhBCYrFYIBAUFhYO2lp9ff1Lly6ZmZm5uLiYmppev369qKhI5owCkm7cuGFqaurs7Cz/LsohebMC3skG4wVcq2DMUn1+AbVkJFfB32B1dTWNRjty5MioHkV+vb29Hh4e2dnZo1F5c3Mzk8ncu3fvaFQuCeYPAACACWisZSRXCmtr68TExMTEROLtfPXq7e0tKChob28fpeyv8fHxLi4uYWFho1G5dBAHAAAAGKOio6MDAwODg4PlGTA4qkpLS0+fPl1cXCx9SgPFpKWlVVRUnD17VktLS+mVywRxAAAAjGMxMTE5OTmtra3Tp08/deqUupujfMnJyWFhYbt27VJvM7y8vI4dO0ZmalCiwsLCN2/elJaW6uvrK71yedDUclQAAABKkZKSkpKSou5WjC5vb28iV++EtHjx4sWLF6uxAXA/AAAAAKAuiAMAAAAA6oI4AAAAAKAuiAMAAAAA6oI4AAAAAKCuQd4XwDBM9e0AQAFwrYIxiyIXJ0VOc4IJCAiQXMRwHCcXGhoaLl++rPImAQDUJigoiMfjubm5qbshAAAVmTp1quSf/P+JAwAAVINhWG5u7vLly9XdEACAesD4AAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviANow6CgAACAASURBVAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqAviAAAAAIC6IA4AAAAAqIum7gYAAFTqxIkT7e3tkmtKSkpev35NLi5dutTQ0FDl7QIAqAeG47i62wAAUJ2QkJD//Oc/WlpaxCLxHwDDMIRQb2+vjo6OQCBgMBjqbCIAQIXguQAA1LJixQqEUPcfenp6enp6iJ81NTUDAwMhCACAUuB+AADU0tPTY2xs/OrVq0G3Xrhw4c9//rOKmwQAUCO4HwAAtdBotBUrVpDPBSRNnjzZ09NT9U0CAKgRxAEAUM6KFSu6u7v7rdTS0lq9erWmpqZamgQAUBd4LgAA5eA4bm5u3tDQ0G/99evXXV1d1dIkAIC6wP0AACgHw7BVq1b1ezQwderUOXPmqKtJAAB1gTgAACrq92hAS0srJCSEeHsQAEAp8FwAAIqys7N78OABuXj37l0HBwc1tgcAoBZwPwAAilq9ejX5aMDe3h6CAACoCeIAAChq1apVPT09CCEtLa2///3v6m4OAEA94LkAANQ1Z86cmzdvYhhWV1dnbm6u7uYAANQA7gcAQF1/+9vfEELvvvsuBAEAUBbkG5xo0tLSrly5ou5WgPGhq6sLw7A3b94EBgaquy1g3MjPz1d3E4Aywf2AiebKlStXr15VdyvGmVOnTg2cVIcKmEymsbGxmZlZQ0PDqVOn1N0cVaDs71opqHOdUAqMD5hoiC92ELAPC4Zhubm5y5cvV3dD1KCmpsba2jovLy8oKIgK/w2o/LseOepcJ5QC9wMAoDRra2t1NwEAoE4QBwAAAADUBXEAAAAAQF0QBwAAAADUBXEAAAAAQF0QBwAAFHT27Fkul/v999+ruyGjpaSkJDo6+vTp05aWlhiGYRi2evVqyQLe3t66urqampoODg63bt1SVzu7u7tTUlKsra3pdLqenp6jo2NdXd3AYl1dXXZ2dnFxccTimTNnUlNTe3t7VdpWMPZAHAAAUNDEfn9sx44dmZmZMTEx/v7+Dx8+tLKyMjAwOHr0aFFREVnm/Pnz+fn5vr6+VVVVs2fPVldTg4KCvvnmm2PHjgmFwvv371tZWXV0dAwsFhsbK5lh0s/Pj8lkenl5vX79WoWNBWMOxAEAAAX5+Pi0trb6+vqO9oFEIpG7u/toH0XS7t27T548mZeXp6urS67MzMzU0NAIDQ1tbW1VZWOkO3nyZEFBQX5+/rvvvkuj0UxMTAoLCx0dHfsVu3z58t27d/ut3LRp06xZsxYtWkRknALUBHEAAGCsy87OFggEKjtcTU3Ntm3bEhISmEym5Hp3d3cej/f06dPNmzerrDEyffXVV7Nnz3ZycpJSRiQSbdmyJSMjY+Cm+Pj4ioqKQTcBioA4AACgiLKyMnNzcwzD9u/fjxDi8/lsNpvFYhUWFi5cuJDD4ZiZmZ04cYIonJmZyWQyjYyMPv30UxMTEyaT6e7ufu3aNWJrWFgYnU6fMmUKsbhx40Y2m41hWHNzM0KIx+NFRkbW1tZiGEbMenTu3DkOh5OcnDxKp5aZmYnjuJ+f38BNO3futLGxOXz4cElJyaD74jielpY2c+ZMBoOhr6+/ZMmS3377jdgkvYsQQr29vdu3bzc3N9fW1nZ2ds7NzZXZVLFYfPXqVRcXF+nFYmNjN27caGhoOHCTvr6+p6dnRkbGxH7KA6SAOAAAoIh58+ZdvnyZXNywYUN4eLhIJNLV1c3Nza2trbW0tFy3bl13dzdCKCwsLCQkRCgUbtq0qa6u7tatWz09Pe+///6TJ08QQpmZmZIT/WZlZSUkJJCLGRkZvr6+VlZWOI7X1NQghIihbX19faN0akVFRba2tiwWa+AmbW3tr7/+WkNDY926dZ2dnQMLxMfHR0dHx8bGCgSCn3/++cmTJx4eHo2NjUhWFyGEtm7d+sUXX6Snpz9//tzX13flypW//vqr9KY+e/ZMLBbfvHlzwYIFRIA1c+bMrKwsyQ/1X375pba2duXKlUNV8tZbbz19+vT27dvydA6YeCAOAAAok7u7O4fDMTQ0DA4O7uzsfPz4MbmJRqMRX5Tt7e35fH57e3tOTo4Ch/Dx8Wlra9u2bZvyWv2/Ojs7Hz16ZGVlNVQBNze38PDwurq6rVu39tskEonS0tKWLVu2atUqLpfr5OR04MCB5ubmgwcPShYbtIu6urr4fP7SpUv9/f319PTi4uK0tLRk9g8xHtDQ0DA5ObmqqqqxsXHJkiWfffbZ8ePHySbxeDw+ny+lkhkzZiCEKisrpR8LTFQQBwAARgWdTkcIkV92+5kzZw6LxSLvmY8dAoEAx/FBbwaQdu7caWtrm5WVVVZWJrm+qqqqo6Njzpw55BpXV1c6nU4+AelHsosePHggFArJ8X3a2tpTpkyR2T8MBgMh5ODg4O7uPmnSJC6Xm5CQwOVyycgjJibmk08+MTU1lVIJcbLETQtAQRAHAADUg8FgNDU1qbsV/XV1daE/Pl+HwmQyc3JyMAxbs2aNSCQi1xMv4Ono6EgW1tPTa29vl3lc4ilDXFwc9of6+nqhUCh9LxMTE4QQMZCCQKfTLSwsamtrEUJlZWWVlZVr166VXom2tjb648QBBUEcAABQg+7u7tevX5uZmam7If0RH4oyZ9dxc3OLiIiorq5OSkoiV+rp6SGE+n3qy3maxCC+9PR0XMKVK1ek76WjozNjxox79+5Jruzp6eFyuQih7OzsCxcuaGhoEIEFcYjk5GQMwyRHHojFYvLEAQVBHAAAUIPS0lIcx+fOnUss0mi0oZ4gqJiRkRGGYfLMEJCUlGRnZ1deXk6ucXR01NHRkfyIvXbtmlgsfvvtt2XWNnXqVCaTWVFRMdwGBwUFlZeXP3z4kFgUCoX19fXEa4Q5OTmSUQVx9yU2NhbHccmHF8TJGhsbD/fQYGKAOAAAoCJ9fX0tLS09PT137tzh8Xjm5uYhISHEJmtr61evXhUUFHR3dzc1NdXX10vuOGnSpGfPntXV1bW3t3d3dxcXF4/ee4MsFsvS0rKhoUFmSeLpgKampuSayMjIb7/99ujRo21tbZWVlevXrzcxMQkNDZWnto8//vjEiRN8Pr+tra23t7ehoeH58+cIoeDgYGNj46HmLY6IiLCwsAgJCXn8+PHLly+joqJEItHAMYxSECcrfQYCMIFBHAAAUMT+/ftdXV0RQlFRUYsXL+bz+enp6QghZ2fnhw8fHjp0KDIyEiH0wQcfVFdXE7t0dXU5OTlpa2t7eHjY2NhcvHiRfAy/YcOGBQsWrFixwtbWNikpibhH7ebmRrxYuH79eiMjI3t7+0WLFr169Wq0T83Hx6eqqop88P/dd99ZW1vX1ta6urp+/vnnkiXnzp0bEREhuWbHjh0pKSmJiYmTJ0/29PScNm1aaWkpm81GCMnsooyMjPDw8NTUVAMDAxMTEx6P19LSghASi8UCgaCwsHDQ1urr61+6dMnMzMzFxcXU1PT69etFRUUyZxSQdOPGDVNTU2dnZ/l3ARMKDiaWgICAgIAAdbdinEEI5ebmqrsV6kRMWTOqhwgNDZ00adKoHkIe8vyuq6uraTTakSNHVNMkmXp7ez08PLKzs0ej8ubmZiaTuXfvXnkKq+A6AaoH9wMAACoyXlLbWVtbJyYmJiYmDpqtR8V6e3sLCgra29uDg4NHo/74+HgXF5ewsLDRqByMCxAHAABAf9HR0YGBgcHBwWpPKVRaWnr69Oni4mLpUxooJi0traKi4uzZs1paWkqvHIwXEAcAtHbtWl1dXQzDFBirPKakpqba2dlpa2uz2Ww7O7tt27a1tbUppWbJDPQEOp1uZGQ0f/78PXv2EA9xgRQxMTE5OTmtra3Tp08/deqUupsjl+Tk5LCwsF27dqm3GV5eXseOHSOTLyhRYWHhmzdvSktL9fX1lV45GEcgDgDo8OHDhw4dUncrlODSpUvr1q17/PhxY2NjUlJSampqQECAUmomM9BzuVwcx/v6+gQCQV5e3vTp06OiohwcHGTOA09xKSkpb968wXH80aNHyvqlqIC3t/fu3bvV3YrRsnjx4ujoaMn3HQA1QRwAxrRhJZ6n0+lEUjUdHZ3AwMAlS5b8z//8D/HmlXJhGKanpzd//vycnJy8vLzGxkYfHx+130AeaFi9BwCgJogDAEIIYRim7iYMbliJ57/99lvJhPHEnOqjPdQrICAgJCREIBAcOHBgVA+kgGH1HgCAmiAOoCgcx/fs2WNra8tgMLhc7pYtW8hNX3zxBYvF0tXVFQgEkZGRpqamDx48wIfOqi49tTySmpF9uInnh6W6ulpPT8/CwkLhXpITMRlOcXExmkC9BwCgCjW+swhGg5zzB8TGxmIY9uWXX7a0tAiFwqysLIRQeXk5uRUhtGnTpn379i1btuz+/fvbt2+n0+lHjhx5/fr1nTt3Zs+ePXny5BcvXhDlQ0ND2Wz2vXv3urq6qqqqXF1ddXV1Hz9+TGyVvu9HH31kbGxMNmzPnj0IoaamJmLR39+fSDwvP7FY3NDQsG/fPgaDIecr4Ei++QPI8QH9EKMRp06dSiyOx96jznvhcv6uwaCoc51QCvxGJxp54gChUMhisd5//31yzYkTJwbGASKRiCyvo6MTHBxMlr9+/TpCKDExkVgMDQ2V/IC8ceMGQighIUGefZUeBxDTpBsYGPzrX/8Si8Xy7DLCOADHcWLEAPHzeOw96vx/hzhgJKhznVAKTVX3HcAYUlNTIxQKvby85Cw/3Kzqkqnlh7vvyD158uT169fl5eXR0dEHDx788ccfjYyMRulYhM7OThzHORzOoFvHUe+N2WEiyhUUFBQUFKTuVgAwVkAcQEVEWhEiCak8FMiqTqaWH0lGdsVoaWkZGhp6e3tPnz7dxsYmJSUlIyNjlI5F+P333xFCdnZ2g24dR71HfNub2IKCgng8npubm7obMi5duXJltP+agOpBHEBFxKD6N2/eyFl+uFnVJVPLjyQj+whZW1trampWVVWN9oHOnTuHEFq4cOGgW8dR7y1fvnw0qh1TgoKC3NzcqHCmowTigIkH3hegIkdHRw0NjZ9++kn+8sPKqi6ZWl7mvspKPP/y5cuVK1dKrqmuru7t7Z06derIK5fixYsX6enpZmZma9asGbTAuOg9AABlQRxARYaGhv7+/qdOncrOzm5ra7tz587BgwellJcnq/pQqeVl7jusxPNSGslms8+fP//jjz+2tbV1d3eXl5f//e9/Z7PZ/dLCjhCO4x0dHX19fTiONzU15ebmvvfee5qamgUFBUONDxgXvQcAoC61jlIEyifne4Pt7e1r1641MDDQ0dGZN2/e9u3bEUJmZma3b99OTU0lsr9PnTqVfO+ur69vz549M2bM0NLS0tfXX7p0KfFaPCE0NFRLS8vU1JRGo3E4nCVLltTW1pJbpe/78uXLBQsWMJnM6dOnf/7558RMBtbW1sSLc7du3bKwsNDW1p43bx75stxQ/Pz8pk+frqOjw2AwrKysgoODKysr5ek0JGsM+ZkzZ5ydnVksFp1O19DQQH9MKfjOO+8kJia+fPmSLDlOe48648Bl/q6BFNS5TigFw3FcXSEIGA2BgYEIofz8fFUe9NNPP83Pz3/58qUqD6pEGIbl5uaq65nxWOi9vLy8oKAgKvw3UO/veryjznVCKfBcACjHeEktPzZB7wEA1AXiADA+/Pbbb9jQgoOD1d1AMAGVlJRER0dLZp1evXq1ZAFvb29dXV1NTU0HB4dbt26pq53d3d0pKSnW1tZ0Ol1PT8/R0bGurm5gsa6uLjs7u7i4OGLxzJkzqampEIMCiAPASKkmtbydnZ2U51snT54cpeOONtX0HlDAjh07MjMzY2JiyKzTBgYGR48eLSoqIsucP38+Pz/f19e3qqpq9uzZ6mpqUFDQN998c+zYMaFQeP/+fSsrq0HTa8XGxj548IBc9PPzYzKZXl5exDQVgLIgDgAjNU5Ty48R1Ok9JSZBVkE+5d27d588eTIvL09XV5dcmZmZqaGhERoaOqZyTJ88ebKgoCA/P//dd9+l0WgmJiaFhYWOjo79il2+fPnu3bv9Vm7atGnWrFmLFi3q6elRVXvBmANxAABAFZSYBHm08ynX1NRs27YtISFBMo01Qsjd3Z3H4z19+nTz5s2jd/Th+uqrr2bPnu3k5CSljEgk2rJly6BTAMXHx1dUVMDsQFQGcQAAQF64kpIgS8+2PNx8yufOneNwOMnJyco6zczMTBzH/fz8Bm7auXOnjY3N4cOHS0pKhttFfD6fzWazWKzCwsKFCxdyOBwzMzMixReht7d3+/bt5ubm2trazs7O8kzzLBaLr1696uLiIr1YbGzsxo0bB51KXF9f39PTMyMjA94CoK7RfjERqJic8wcASYjy75TL+V64EpMgS8+2PKyqfvjhB11dXTIHo3Ty/K4tLS3t7e37rbSysnr06BGO45cvX9bQ0Jg2bVpHRweO48XFxYsXLyaLSe8iIhflhQsXWltbBQKBh4cHm80ms2Ju3ryZwWCcOnWqpaUlJiZGQ0Pjxo0b0pv66NEjhJCLi8v8+fOnTJnCYDDs7Oz2799PTHVFKCsr8/Pzw3GcSFoRGxvbr5Lo6GgkkW5UCpg/YEKC+wEAALmIRKK0tLRly5atWrWKy+U6OTkdOHCgublZ+mSUUtBoNOJ7s729PZ/Pb29vz8nJUaAeHx+ftra2bdu2KdaMfjo7Ox89emRlZTVUATc3t/Dw8Lq6uq1bt/bbJGcXubu7czgcQ0PD4ODgzs7Ox48fI4S6urr4fP7SpUv9/f319PTi4uK0tLRkdggxHtDQ0DA5ObmqqqqxsXHJkiWfffbZ8ePHySbxeDw+ny+lkhkzZiCEKisrpR8LTFQQBwAA5DKqSZAlsy2rl0AgwHGcxWJJKbNz505bW9usrKyysjLJ9cPtIjqdjhAipnx+8OCBUCgkx/dpa2tPmTJFZocwGAyEkIODg7u7+6RJk7hcbkJCApfLJSOPmJiYTz75xNTUVEolxMk2NjZKPxaYqCAOAADIZbSTIJPZltWrq6sL/fH5OhQmk5mTk4Nh2Jo1a0QiEbl+JF3U2dmJEIqLiyNnxaivrxcKhdL3MjExQQgRIycIdDrdwsKitrYWIVRWVlZZWbl27VrplRAzYRMnDigI4gAAgFxGNQmyZLZl9SI+FGXOruPm5hYREVFdXZ2UlESuHEkXEYP40tPTJR/cXrlyRfpeOjo6M2bMuHfvnuTKnp4eLpeLEMrOzr5w4YKGhgYRWBCHSE5OxjBMMomlWCwmTxxQEMQBAAC5jGoSZMlsyyOsaoSMjIwwDJNnhoCkpCQ7O7vy8nJyzXBzTEuaOnUqk8msqKgYboODgoLKy8sfPnxILAqFwvr6euI1wpycHMmoQnKcoOTDC+JkjY2Nh3toMDFAHAAAkIvSkyAPlW15uFUVFxcr8b1BFotlaWnZ0NAgT4fk5ORoampKrpGZY1pKbR9//PGJEyf4fH5bW1tvb29DQ8Pz588RQsHBwcbGxkPNWxwREWFhYRESEvL48eOXL19GRUWJRKKBYxilIE5W+gwEYAKDOAAAIK8dO3akpKQkJiZOnjzZ09Nz2rRppaWlbDab2Lphw4YFCxasWLHC1tY2KSmJuM/s5ub25MkThND69euNjIzs7e0XLVr06tUrhFBXV5eTk5O2traHh4eNjc3FixfJp/LDrUq5fHx8qqqqyAf/3333nbW1dW1traur6+effy5Zcu7cuREREXJ2EZ/PT09PRwg5Ozs/fPjw0KFDkZGRCKEPPviguroaIZSRkREeHp6ammpgYGBiYsLj8VpaWhBCYrFYIBAUFhYO2lp9ff1Lly6ZmZm5uLiYmppev369qKhI5owCkm7cuGFqaurs7Cz/LmBCUd0rikAlYP4ABSCYP0Dl74WHhoZOmjRJlUckyPO7rq6uptFoR44cUU2TZOrt7fXw8MjOzh6Nypubm5lM5t69e+UpDPMHTEhwPwAAoB5jNtOdtbV1YmJiYmLioNl6VKy3t7egoKC9vX2UkmrGx8e7uLiEhYWNRuVgXIA4AAAA+ouOjg4MDAwODlZ7SqHS0tLTp08XFxdLn9JAMWlpaRUVFWfPntXS0lJ65WC8gDgAAKBq4yLbcnJyclhY2K5du9TbDC8vr2PHjpHZFpSosLDwzZs3paWl+vr6Sq8cjCM0dTcAAEA5KSkpKSkp6m6FbN7e3t7e3upuxWhZvHjx4sWL1d0KoH5wPwAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCcYITUENDQ15enrpbMc7ITOgysRGnT5HLhuK/65GArpuQMBzH1d0GoEyBgYFj9kUsAMAEAJ8aEwzEAQBQGoZhubm5y5cvV3dDAADqAeMDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAAAAAOrCcBxXdxsAAKoTGhr64MEDcvHWrVvTp0/X19cnFjU1Nf/zn/+YmZmpqXUAAFWjqbsBAACVMjY2PnjwoOSaO3fukD9bWlpCEAAApcBzAQCoZeXKlUNtotPpISEhKmwLAED94LkAAJTj6Oh47969Qf/2Hzx4YGNjo/omAQDUBe4HAEA5f/vb3zQ1NfutxDBs1qxZEAQAQDUQBwBAOStWrOjt7e23UlNT8+9//7ta2gMAUCN4LgAAFbm7u1+7dq2vr49cg2HYkydPTE1N1dgqAIDqwf0AAKho9erVGIaRixoaGvPmzYMgAAAKgjgAACoKDAyUXMQw7G9/+5u6GgMAUCOIAwCgosmTJ3t5eZGjBTEMW7p0qXqbBABQC4gDAKCoVatWEcODNDU1//rXvxoYGKi7RQAANYA4AACKWrZsGZ1ORwjhOL5q1Sp1NwcAoB4QBwBAUWw2+8MPP0QI0el0X19fdTcHAKAeEAcAQF0fffQRQmjp0qVsNlvdbQEAqAfMHwBkyMvLCwoKUncrAACKCAgIyM/PV3crwJgG+QaBXHJzc9XdhBEJCgri8Xhubm7qbohypKenI4TCw8NHXtXRo0eDg4NptLH4r+DKlSsZGRnj/dpTI+I6AUC6sfjHD8ag5cuXq7sJIxIUFOTm5jbez4JEfMNTyun4+fkxmcyR1zNKMjIyJsxvTfXgTgCQB4wPAIDSxnIQAABQAYgDAAAAAOqCOAAAAACgLogDAAAAAOqCOAAAAACgLogDAKCKs2fPcrnc77//Xt0NGS0lJSXR0dGnT5+2tLTEMAzDsNWrV0sW8Pb21tXV1dTUdHBwuHXrlrra2d3dnZKSYm1tTafT9fT0HB0d6+rqBhbr6uqys7OLi4sjFs+cOZOamtrb26vStgIKgDgAAKqY2JOG7dixIzMzMyYmxt/f/+HDh1ZWVgYGBkePHi0qKiLLnD9/Pj8/39fXt6qqavbs2epqalBQ0DfffHPs2DGhUHj//n0rK6uOjo6BxWJjYx88eEAuEm94enl5vX79WoWNBRMfxAEAUIWPj09ra6sKUgmIRCJ3d/fRPoqk3bt3nzx5Mi8vT1dXl1yZmZmpoaERGhra2tqqysZId/LkyYKCgvz8/HfffZdGo5mYmBQWFjo6OvYrdvny5bt37/ZbuWnTplmzZi1atKinp0dV7QUTH8QBAAAly87OFggEKjtcTU3Ntm3bEhIS+s2F4O7uzuPxnj59unnzZpU1Rqavvvpq9uzZTk5OUsqIRKItW7ZkZGQM3BQfH19RUTHoJgAUA3EAAJRQVlZmbm6OYdj+/fsRQnw+n81ms1iswsLChQsXcjgcMzOzEydOEIUzMzOZTKaRkdGnn35qYmLCZDLd3d2vXbtGbA0LC6PT6VOmTCEWN27cyGazMQxrbm5GCPF4vMjIyNraWgzDrK2tEULnzp3jcDjJycmjdGqZmZk4jvv5+Q3ctHPnThsbm8OHD5eUlAy6L47jaWlpM2fOZDAY+vr6S5Ys+e2334hN0rsIIdTb27t9+3Zzc3NtbW1nZ2d55j8Wi8VXr151cXGRXiw2Nnbjxo2GhoYDN+nr63t6emZkZEzspzxAlSAOAIAS5s2bd/nyZXJxw4YN4eHhIpFIV1c3Nze3trbW0tJy3bp13d3dCKGwsLCQkBChULhp06a6urpbt2719PS8//77T548QQhlZmZKzvWblZWVkJBALmZkZPj6+lpZWeE4XlNTgxAihrb19fWN0qkVFRXZ2tqyWKyBm7S1tb/++msNDY1169Z1dnYOLBAfHx8dHR0bGysQCH7++ecnT554eHg0NjYiWV2EENq6desXX3yRnp7+/PlzX1/flStX/vrrr9Kb+uzZM7FYfPPmzQULFhAB1syZM7OysiQ/1H/55Zfa2tqVK1cOVclbb7319OnT27dvy9M5AMgEcQAAlObu7s7hcAwNDYODgzs7Ox8/fkxuotFoxBdle3t7Pp/f3t6ek5OjwCF8fHza2tq2bdumvFb/r87OzkePHllZWQ1VwM3NLTw8vK6ubuvWrf02iUSitLS0ZcuWrVq1isvlOjk5HThwoLm5+eDBg5LFBu2irq4uPp+/dOlSf39/PT29uLg4LS0tmf1DjAc0NDRMTk6uqqpqbGxcsmTJZ599dvz4cbJJPB6Pz+dLqWTGjBkIocrKSunHAkBOEAcAABBCiE6nI4TIL7v9zJkzh8VikffM094QCwAAEfhJREFUxw6BQIDj+KA3A0g7d+60tbXNysoqKyuTXF9VVdXR0TFnzhxyjaurK51OJ5+A9CPZRQ8ePBAKheT4Pm1t7SlTpsjsHwaDgRBycHBwd3efNGkSl8tNSEjgcrlk5BETE/PJJ5+YmppKqYQ4WeKmBQAjB3EAAEAuDAajqalJ3a3or6urC/3x+ToUJpOZk5ODYdiaNWtEIhG5nngBT0dHR7Kwnp5ee3u7zOMSTxni4uKwP9TX1wuFQul7mZiYIISIgRQEOp1uYWFRW1uLECorK6usrFy7dq30SrS1tdEfJw7AyEEcAACQrbu7+/Xr12ZmZupuSH/Eh6LM2XXc3NwiIiKqq6uTkpLIlXp6egihfp/6cp4mMYgvPT0dl3DlyhXpe+no6MyYMePevXuSK3t6erhcLkIoOzv7woULGhoaRGBBHCI5ORnDMMmRB2KxmDxxAEYO4gAAgGylpaU4js+dO5dYpNFoQz1BUDEjIyMMw+SZISApKcnOzq68vJxc4+joqKOjI/kRe+3aNbFY/Pbbb8usberUqUwms6KiYrgNDgoKKi8vf/jwIbEoFArr6+uJ1whzcnIkowri7ktsbCyO45IPL4iTNTY2Hu6hARgUxAEAgMH19fW1tLT09PTcuXOHx+OZm5uHhIQQm6ytrV+9elVQUNDd3d3U1FRfXy+546RJk549e1ZXV9fe3t7d3V1cXDx67w2yWCxLS8uGhgaZJYmnA5qampJrIiMjv/3226NHj7a1tVVWVq5fv97ExCQ0NFSe2j7++OMTJ07w+fy2trbe3t6Ghobnz58jhIKDg42NjYeatzgiIsLCwiIkJOTx48cvX76MiooSiUQDxzBKQZys9BkIAJAfxAEAUML+/ftdXV0RQlFRUYsXL+bz+enp6QghZ2fnhw8fHjp0KDIyEiH0wQcfVFdXE7t0dXU5OTlpa2t7eHjY2NhcvHiRfAy/YcOGBQsWrFixwtbWNikpibhH7ebmRrxYuH79eiMjI3t7+0WLFr169Wq0T83Hx6eqqop88P/dd99ZW1vX1ta6urp+/vnnkiXnzp0bEREhuWbHjh0pKSmJiYmTJ0/29PScNm1aaWkpm81GCMnsooyMjPDw8NTUVAMDAxMTEx6P19LSghASi8UCgaCwsHDQ1urr61+6dMnMzMzFxcXU1PT69etFRUUyZxSQdOPGDVNTU2dnZ/l3AUAaHACpiNlR1N2KkUII5ebmqrsVShMQEBAQEDCqhwgNDZ00adKoHkImOa+96upqGo125MgRFTRJHr29vR4eHtnZ2aNReXNzM5PJ3Lt3rzyFVXCdgAkA7gcAAAY3XlLbWVtbJyYmJiYmDpqtR8V6e3sLCgra29uDg4NHo/74+HgXF5ewsLDRqBxQE8QBQPnWrl2rq6uLYZgCo6jURTJZLYFOpxsZGc2fP3/Pnj3E/V4wZkVHRwcGBgYHB6s9pVBpaenp06eLi4ulT2mgmLS0tIqKirNnz2ppaSm9ckBZEAcA5Tt8+PChQ4fU3YrhIZPVcrlcHMf7+voEAkFeXt706dOjoqIcHBxkThk7kcTExOTk5LS2tk6fPv3UqVPqbo5ckpOTw8LCdu3apd5meHl5HTt2jEy+oESFhYVv3rwpLS3V19dXeuWAymjqbgAAYxGGYXp6evPnz58/f76Pj09QUJCPj8/vv/9OvOc94aWkpKSkpKi7FcPm7e3t7e2t7laMlsWLFy9evFjdrQATENwPAKMCwzB1N0FpAgICQkJCBALBgQMH1N0WAABQMogDgHLgOL5nzx5bW1sGg8Hlcrds2SK5ddAMrTLzuv7000/vvPMOi8XicDhOTk5tbW1DVTXaiPfmi4uLJ8bpAADA/1L3CwtgrJPz3a3Y2FgMw7788suWlhahUJiVlYUQKi8vJ7Zu3ryZwWCcOnWqpaUlJiZGQ0Pjxo0bxF4IoQsXLrS2tgoEAg8PDzabLRaLcRzv6OjgcDipqakikejFixfLli1ramqSUpV0SL73BsnxAf0Qn9lTp04dI6dDkffBJsY7q2pEkesEjBD8jQEZ5PlfLBQKWSzW+++/T64hvgcTcYBIJGKxWMHBwWRhBoOxYcMG/I8PTpFIRGwiooeamhocx+/evYsQ+uGHHyQPJKUq6UYYB+A4TowYGCOnQ5H/7xAHjBBFrhMwQjBOEChBTU2NUCj08vIadKv8GVol87paWloaGRmtWrVq06ZNISEh06ZNG1ZVytXZ2YnjOIfDGTun09DQkJeXp4RzG8OItD0T/jRHT0NDwxhMDQXGHHUHImCsk+c72dmzZxFCkhOoSd4P+OWXXwZeeHPnzsUHfIEm3ja8f/8+sXj37t0PP/yQRqNhGBYUFCQUCqVUJR0a2f0AYq54b2/vMXI6AQEBCv/JA0qB+wFAJhgnCJSAyWQihN68eTPoVsUytCKEHBwcvv/++2fPnkVFReXm5u7du1fhqkbo3LlzCKGFCxeiMXM6VPj/Ds8FRgjiRSAPiAOAEjg6OmpoaPz000+DblUsQ+uzZ8+INO2Ghoa7du2aPXv2vXv3FE72OhIvXrxIT083MzNbs2YNGv+nAwAAkiAOAEpgaGjo7+9/6tSp7Ozstra2O3fuHDx4kNwqJUOrFM+ePfv0009/++03sVhcXl5eX18/d+5cxaoaFhzHOzo6+vr6cBxvamrKzc197733NDU1CwoKiPEB4+t0AABABnXfuAJjnZz3Ztvb29euXWtgYKCjozNv3rzt27cjhMzMzG7fvo3j+Js3b6KioszNzWk0GhE0VFVVZWVlEXOwz5gxo7a29uDBg8QHrYWFxe+//15XV+fu7q6vr6+pqfmnP/0pNja2p6dnqKpkNg/JGh9w5swZZ2dnFotFp9M1NDTQH1MKvvPOO4mJiS9fvpQsrPbTocg4cHguMEIUuU7ACGE4jqstBgHjQV5eXlBQ0Hi/TjAMy83NXb58ubobohyBgYEIofz8fHU3ZHRNjGtPjShynYARgucCAAAAAHVBHAAAAABQF8QBAIAJoqSkJDo6+vTp05aWlhiGYRi2evVqyQLe3t66urqampoODg7EnBDq0tfXl56e7u7uPnBTWVnZe++9x2KxTExMoqKiyNdxz5w5k5qa2tvbq9qWgokP4gAAwESwY8eOzMzMmJgYf3//hw8fWllZGRgYHD16tKioiCxz/vz5/Px8X1/fqqqq2bNnq6up1dXV/+///b+IiAihUNhvU1VVlbe3t5eXV1NT07fffvvvf/97/fr1xCY/Pz8mk+nl5fX69WuVNxlMZBAHAAAGIRKJBv22qt6qhrJ79+6TJ0/m5eXp6uqSKzMzMzU0NEJDQ1tbW0f16MNy+/btrVu3rl+/3sXFZeDWpKSkKVOmJCQksNlsNze3qKior7/+mpxqetOmTbNmzVq0aFFPT49qWw0mMogDAACDyM7OFggEY62qQdXU1Gzbti0hIYGY15Lk7u7O4/GePn26efPm0Tv6cM2aNev06dMfffQRg8Hot6mnp6eoqMjT0xPDMGLNwoULcRwvLCwky8THx1dUVGRkZKiuxWCigzgAgAkLx/G0tLSZM2cyGAx9ff0lS5aQ3yzDwsLodPqUKVOIxY0bN7LZbAzDmpubEUI8Hi8yMrK2thbDMGtr68zMTCaTaWRk9Omnn5qYmDCZTHd392vXrilQFULo3LlzHA4nOTlZWaeZmZmJ47ifn9/ATTt37rSxsTl8+HBJSclwu4jP57PZbBaLVVhYuHDhQg6HY2ZmRiTOIPT29m7fvt3c3FxbW9vZ2ZmY7WAkHj582NHRYW5uTq6xsrJCCN25c4dco6+v7+npmZGRAa9TAmWBOACACSs+Pj46Ojo2NlYgEPz8889Pnjzx8PBobGxECGVmZkrOppCVlZWQkEAuZmRk+Pr6WllZ4TheU1MTFhYWEhIiFAo3bdpUV1d369atnp6e999//8mTJ8OtCiFEjHTr6+tT1mkWFRXZ2toSkzj1o62t/fXXX2toaKxbt66zs3NgASldtGHDhvDwcJFIpKurm5ubW1tba2lpuW7dOiKBJEJo69atX3zxRXp6+vPnz319fVeuXPnrr7+O5ERevHiBEJJ8tMFkMrW1tYn2kN56662nT5/evn17JMcCgARxAAATk0gkSktLW7Zs2apVq7hcrpOT04EDB5qbmyWnfB4WGo1GfG+2t7fn8/nt7e05OTkK1OPj49PW1rZt2zbFmtFPZ2fno0ePiO/Ng3JzcwsPD6+rq9u6dWu/TXJ2kbu7O4fDMTQ0DA4O7uzsfPz4MUKoq6uLz+cvXbrU399fT08vLi5OS0tLsQ4hEa8GaGpqSq7U0tISiUSSa2bMmIEQqqysHMmxACBBHADAxFRVVdXR0TFnzhxyjaurK51OJ+/nj8ScOXNYLBZ5C12NBAIBjuOD3gwg7dy509bWNisrq6ysTHL9cLuITqcjhIj7AQ8ePBAKhY6OjsQmbW3tKVOmjLBDiPEN/cYAisVibW1tyTXEyfa7SQCAwiAOAGBiIt4u09HRkVypp6fX3t6ulPoZDEZTU5NSqhqJrq4uojFSyjCZzJycHAzD1qxZI/ndeiRdRDxliIuLw/5QX18/8D3AYSHGWLS1tZFrhEJhV1eXiYmJZDEiLCBOHICRgzgAgIlJT08PIdTvI+3169dmZmYjr7y7u1tZVY0Q8aEoc3YdNze3iIiI6urqpKQkcuVIusjQ0BAhlJ6eLpmv5cqVKwqcAmn69Om6urr19fXkGmJEhbOzs2QxsViM/jhxAEYO4gAAJiZHR0cdHR3JkWvXrl0Ti8Vvv/02sUij0cghb8NVWlqK4/jcuXNHXtUIGRkZYRgmzwwBSUlJdnZ25eXl5BqZXSTF1KlTmUxmRUWFYs0eFI1GW7Ro0c8//0wOoiwuLsYwrN+rEMTJGhsbK/HQgMogDgBgYmIymZGRkf+/vbsHSeeP4wD+/cEdWZCgFCWCYihNQVNDD0MELg2XhHCjTRLU0XJEQQ9I2WDYVEMQDhURldiiq07nFFE0VAgR0gM9kVYkdd5vECR+9M/Dv3bWvV+b+OXj+74e+tF7+AaDwbW1tVQqdXh4ODg4aDAY3G53boDVar2/vw+FQm9vbzc3Nx9/hhJC9Hr9xcXF2dlZOp3Ofcdns9mHh4f39/eDg4ORkRGTyeRyuYooFYlESnjdYE1NTVNTUzKZlDMhgUDg41l4Bafo62oDAwMbGxtLS0upVEoUxWQyeXl5SQhhWbahoaG4+xZPTExcX19PTU09Pz8LguDz+VwuV3Nz88cxuY1taWkpoj7AJ75zkWP4iX7HGvCEkM3NTaVTlIzMdeWz2azP57PZbDRN63Q6h8NxfHycf/bu7q67u1uj0VgsluHhYZ7nCSFWq/X8/FySpL29PbPZXF1d3dnZeXV15Xa7aZo2Go0URWm12r6+vkQiUVypcDhcW1s7MzNTML/MfY/jOJqmX15ecg+DwWDu8oG6urqhoaF/BvM8zzCMnClaXFzMnZFns9kSicTy8rJWqyWEmM3mk5MTSZIymczo6KjJZKIoqr6+vr+//+joSJIkh8NBCJmcnPw0rSAIHR0d+UP+jY2N7e3tsVgsPyAWi7W1tVVVVRkMBp7nX19f/6nQ29trNBqz2WzBmZG5n4DK/fjPdyg39AEV6Ps/391ut16v/85XlGTve6enpxRFra6ufkMkOURR7OrqWllZKUfx29tbjUYzPz8vZzD6AJADxwUAQJaKXenOarV6PB6Px/P09KR0FiKKYigUSqfTLMuWo/709HRrayvHceUoDuqEPgAAfryxsTGn08myrOJLCkWj0Z2dnUgk8vUtDYrj9/v39/fD4TBN0yUvDqqFPgAAChgfHw8EAo+PjxaLZXt7W+k4n5udneU4bm5uTtkYPT096+vr+dUWSmh3dzeTyUSjUZ1OV/LioGaU0gEAoNJ5vV6v16t0isLsdrvdblc6RbkwDMMwjNIp4BfC/wEAAADqhT4AAABAvdAHAAAAqBf6AAAAAPXCeYIgi9PpVDrC/7WwsLC1taV0itKIx+PkV7wpX8vdQPfXb2b5xOPx/BoQAP/ljyRJSmeAiiYIgt/vVzoFABQjt9Ci0imgoqEPAAAAUC+cHwAAAKBe6AMAAADUC30AAACAeqEPAAAAUK+/SEPUCTMyGBQAAAAASUVORK5CYII=\n","text/plain":[""]},"metadata":{},"execution_count":17}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"287Am2coqkQC","executionInfo":{"status":"ok","timestamp":1638748150465,"user_tz":480,"elapsed":277815,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"85c947d2-d4d2-47ea-c278-5487002ddf45"},"source":["epochs = 30\n","\n","callbacks = [\n"," keras.callbacks.ModelCheckpoint(\"checkpoints/save_at_{epoch}.h5\"),\n","]\n","model.compile(\n"," optimizer=keras.optimizers.Adam(1e-3),\n"," loss=\"binary_crossentropy\",\n"," metrics=[\"accuracy\"],\n",")\n","model.fit(\n"," train_ds, epochs=epochs, callbacks=callbacks, validation_data=validation_ds,\n",")"],"execution_count":18,"outputs":[{"output_type":"stream","name":"stdout","text":["Epoch 1/30\n","275/275 [==============================] - 9s 29ms/step - loss: 0.3763 - accuracy: 0.1932 - val_loss: 0.3480 - val_accuracy: 0.0800\n","Epoch 2/30\n","275/275 [==============================] - 8s 28ms/step - loss: 0.2665 - accuracy: 0.4103 - val_loss: 0.2391 - val_accuracy: 0.5800\n","Epoch 3/30\n","275/275 [==============================] - 8s 27ms/step - loss: 0.2268 - accuracy: 0.5433 - val_loss: 0.1719 - val_accuracy: 0.8400\n","Epoch 4/30\n","275/275 [==============================] - 7s 27ms/step - loss: 0.1998 - accuracy: 0.6261 - val_loss: 0.1379 - val_accuracy: 0.9000\n","Epoch 5/30\n","275/275 [==============================] - 7s 27ms/step - loss: 0.1794 - accuracy: 0.6794 - val_loss: 0.1251 - val_accuracy: 0.9300\n","Epoch 6/30\n","275/275 [==============================] - 8s 27ms/step - loss: 0.1657 - accuracy: 0.7163 - val_loss: 0.1016 - val_accuracy: 0.9200\n","Epoch 7/30\n","275/275 [==============================] - 7s 27ms/step - loss: 0.1532 - accuracy: 0.7484 - val_loss: 0.0936 - val_accuracy: 0.9600\n","Epoch 8/30\n","275/275 [==============================] - 8s 27ms/step - loss: 0.1436 - accuracy: 0.7665 - val_loss: 0.0766 - val_accuracy: 0.9700\n","Epoch 9/30\n","275/275 [==============================] - 8s 29ms/step - loss: 0.1361 - accuracy: 0.7812 - val_loss: 0.0657 - val_accuracy: 0.9800\n","Epoch 10/30\n","275/275 [==============================] - 9s 32ms/step - loss: 0.1270 - accuracy: 0.8081 - val_loss: 0.0548 - val_accuracy: 0.9700\n","Epoch 11/30\n","275/275 [==============================] - 8s 30ms/step - loss: 0.1230 - accuracy: 0.8209 - val_loss: 0.0554 - val_accuracy: 0.9900\n","Epoch 12/30\n","275/275 [==============================] - 8s 29ms/step - loss: 0.1163 - accuracy: 0.8323 - val_loss: 0.0468 - val_accuracy: 0.9700\n","Epoch 13/30\n","275/275 [==============================] - 8s 30ms/step - loss: 0.1110 - accuracy: 0.8399 - val_loss: 0.0465 - val_accuracy: 0.9900\n","Epoch 14/30\n","275/275 [==============================] - 8s 29ms/step - loss: 0.1089 - accuracy: 0.8405 - val_loss: 0.0511 - val_accuracy: 0.9800\n","Epoch 15/30\n","275/275 [==============================] - 8s 29ms/step - loss: 0.1047 - accuracy: 0.8505 - val_loss: 0.0376 - val_accuracy: 0.9800\n","Epoch 16/30\n","275/275 [==============================] - 8s 28ms/step - loss: 0.1047 - accuracy: 0.8523 - val_loss: 0.0360 - val_accuracy: 0.9800\n","Epoch 17/30\n","275/275 [==============================] - 8s 29ms/step - loss: 0.0993 - accuracy: 0.8637 - val_loss: 0.0337 - val_accuracy: 0.9800\n","Epoch 18/30\n","275/275 [==============================] - 8s 30ms/step - loss: 0.0972 - accuracy: 0.8669 - val_loss: 0.0301 - val_accuracy: 0.9900\n","Epoch 19/30\n","275/275 [==============================] - 8s 28ms/step - loss: 0.0963 - accuracy: 0.8686 - val_loss: 0.0334 - val_accuracy: 0.9800\n","Epoch 20/30\n","275/275 [==============================] - 8s 29ms/step - loss: 0.0929 - accuracy: 0.8790 - val_loss: 0.0333 - val_accuracy: 0.9800\n","Epoch 21/30\n","275/275 [==============================] - 9s 31ms/step - loss: 0.0913 - accuracy: 0.8805 - val_loss: 0.0323 - val_accuracy: 0.9700\n","Epoch 22/30\n","275/275 [==============================] - 9s 30ms/step - loss: 0.0912 - accuracy: 0.8773 - val_loss: 0.0335 - val_accuracy: 0.9800\n","Epoch 23/30\n","275/275 [==============================] - 8s 30ms/step - loss: 0.0863 - accuracy: 0.8865 - val_loss: 0.0326 - val_accuracy: 0.9800\n","Epoch 24/30\n","275/275 [==============================] - 8s 28ms/step - loss: 0.0850 - accuracy: 0.8884 - val_loss: 0.0216 - val_accuracy: 0.9900\n","Epoch 25/30\n","275/275 [==============================] - 8s 28ms/step - loss: 0.0842 - accuracy: 0.8940 - val_loss: 0.0212 - val_accuracy: 0.9800\n","Epoch 26/30\n","275/275 [==============================] - 8s 27ms/step - loss: 0.0835 - accuracy: 0.8914 - val_loss: 0.0194 - val_accuracy: 0.9900\n","Epoch 27/30\n","275/275 [==============================] - 8s 28ms/step - loss: 0.0818 - accuracy: 0.8917 - val_loss: 0.0214 - val_accuracy: 0.9700\n","Epoch 28/30\n","275/275 [==============================] - 8s 28ms/step - loss: 0.0811 - accuracy: 0.8917 - val_loss: 0.0214 - val_accuracy: 0.9700\n","Epoch 29/30\n","275/275 [==============================] - 8s 28ms/step - loss: 0.0794 - accuracy: 0.8950 - val_loss: 0.0201 - val_accuracy: 0.9800\n","Epoch 30/30\n","275/275 [==============================] - 8s 28ms/step - loss: 0.0790 - accuracy: 0.8947 - val_loss: 0.0267 - val_accuracy: 0.9700\n"]},{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":18}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"ocE3kudZq24U","executionInfo":{"status":"ok","timestamp":1638748338964,"user_tz":480,"elapsed":367,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"cc43a234-3bd4-460d-ef82-806889fc9d38"},"source":["def predict_image(model, filename):\n"," img = keras.preprocessing.image.load_img(filename, target_size=(IMAGE_WIDTH, IMAGE_HEIGHT))\n"," img_array = keras.preprocessing.image.img_to_array(img)\n"," img_array = tf.expand_dims(img_array, 0) # Create batch axis\n"," predictions = model.predict(img_array).flatten()\n"," predicted_label_index = np.argmax(predictions)\n"," predicted_score = predictions[predicted_label_index]\n"," return (predicted_label_index, predicted_score)\n"," \n","index, score = predict_image(model, \"test/7/2.png\")\n","\n","print(index, score)\n"],"execution_count":19,"outputs":[{"output_type":"stream","name":"stdout","text":["7 0.9931043\n"]}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/","height":83},"id":"MYyLaqOYtxTH","executionInfo":{"status":"ok","timestamp":1638748404260,"user_tz":480,"elapsed":54380,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"8c6b1cfc-e51a-461b-d8d6-4064a7f30e61"},"source":["from IPython.display import Image, display\n","\n","SCORE_THRESHOLD = 0.75\n","\n","correct_count = 0\n","wrong_count = 0\n","discarded_count = 0\n","for label_dir in glob.glob(\"test/*\"):\n"," label = int(label_dir.replace(\"test/\", \"\"))\n"," for filename in glob.glob(label_dir + \"/*.png\"):\n"," index, score = predict_image(model, filename)\n"," if score < SCORE_THRESHOLD:\n"," discarded_count += 1\n"," continue\n"," if index == label:\n"," correct_count += 1\n"," else:\n"," wrong_count += 1\n"," print(\"%d expected, %d found with score %f\" % (label, index, score))\n"," display(Image(filename=filename))\n","\n","correct_percentage = (correct_count / (correct_count + wrong_count)) * 100\n","print(\"%.1f%% correct (N=%d, %d unknown)\" % (correct_percentage, (correct_count + wrong_count), discarded_count))"],"execution_count":20,"outputs":[{"output_type":"stream","name":"stdout","text":["9 expected, 7 found with score 0.807747\n"]},{"output_type":"display_data","data":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAA8ElEQVR4nGNgGAWjYBTQHDCSocfoLMMvNoav3AxfeBheixFQzEKS0f4bGN4LMvz6xXDOGCrC+Y3hOxc+LUwkWfCblYHtF8MJS4TILzYCWkiwIH0GA/dXhj2uKIJ/f3MQbwJhkDgPlf+dg+EjH34tpAURzxdU/jshBv5P+LWQnIoq2hmE3jGIv2SIb5di+MXGoPiAVBOIBjfViFFFWhChmP6blUy9RIET5kQqJM4HKrdRuIdsGdh+UdUCtl8MvEip5Rcbg9F5Ii0grqiIWMHA+puhkoGBgYFhgz+Dy0YiTScRTM5hWBpFG6NHwSgYBRQBAJY6MnCXjHpLAAAAAElFTkSuQmCC\n","text/plain":[""]},"metadata":{}},{"output_type":"stream","name":"stdout","text":["99.9% correct (N=1027, 73 unknown)\n"]}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"d26wGJn0t20g","executionInfo":{"status":"ok","timestamp":1638748436167,"user_tz":480,"elapsed":2605,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"5d525abe-97bc-4a71-c757-79d8db945d4f"},"source":["model.save(SAVED_MODEL_FILENAME)"],"execution_count":21,"outputs":[{"output_type":"stream","name":"stdout","text":["INFO:tensorflow:Assets written to: saved_model/assets\n"]}]},{"cell_type":"code","metadata":{"id":"ki3E7lM_Kr0C"},"source":["#!curl -L https://storage.googleapis.com/download.tensorflow.org/models/tflite/micro/magic_wand_saved_model_2021_01_02.tgz -o saved_model.tgz\n","#!tar -xzf saved_model.tgz"],"execution_count":null,"outputs":[]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"t-hU8aU24gbL","executionInfo":{"status":"ok","timestamp":1638748457118,"user_tz":480,"elapsed":3003,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"8b57dc82-3d72-4bd1-988b-b3a8b85cb101"},"source":["converter = tf.lite.TFLiteConverter.from_saved_model(SAVED_MODEL_FILENAME)\n","model_no_quant_tflite = converter.convert()\n","\n","# Save the model to disk\n","open(FLOAT_TFL_MODEL_FILENAME, \"wb\").write(model_no_quant_tflite)\n","\n","def representative_dataset():\n"," for filename in glob.glob(\"test/*/*.png\"):\n"," img = keras.preprocessing.image.load_img(filename, target_size=(IMAGE_WIDTH, IMAGE_HEIGHT))\n"," img_array = keras.preprocessing.image.img_to_array(img)\n"," img_array = tf.expand_dims(img_array, 0) # Create batch axis for images, labels in train_ds.take(1):\n"," yield([img_array])\n","# Set the optimization flag.\n","converter.optimizations = [tf.lite.Optimize.DEFAULT]\n","# Enforce integer only quantization\n","converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]\n","converter.inference_input_type = tf.int8\n","converter.inference_output_type = tf.int8\n","# Provide a representative dataset to ensure we quantize correctly.\n","converter.representative_dataset = representative_dataset\n","model_tflite = converter.convert()\n","\n","# Save the model to disk\n","open(QUANTIZED_TFL_MODEL_FILENAME, \"wb\").write(model_tflite)"],"execution_count":22,"outputs":[{"output_type":"stream","name":"stderr","text":["WARNING:absl:Buffer deduplication procedure will be skipped when flatbuffer library is not properly loaded\n","WARNING:absl:Buffer deduplication procedure will be skipped when flatbuffer library is not properly loaded\n"]},{"output_type":"execute_result","data":{"text/plain":["30880"]},"metadata":{},"execution_count":22}]},{"cell_type":"code","metadata":{"id":"w5QZTfwRLFAi","executionInfo":{"status":"ok","timestamp":1638748759830,"user_tz":480,"elapsed":192,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}}},"source":["def predict_tflite(tflite_model, filename):\n"," img = keras.preprocessing.image.load_img(filename, target_size=(IMAGE_WIDTH, IMAGE_HEIGHT))\n"," img_array = keras.preprocessing.image.img_to_array(img)\n"," img_array = tf.expand_dims(img_array, 0)\n","\n"," # Initialize the TFLite interpreter\n"," interpreter = tf.lite.Interpreter(model_content=tflite_model)\n"," interpreter.allocate_tensors()\n","\n"," input_details = interpreter.get_input_details()[0]\n"," output_details = interpreter.get_output_details()[0]\n","\n"," # If required, quantize the input layer (from float to integer)\n"," input_scale, input_zero_point = input_details[\"quantization\"]\n"," if (input_scale, input_zero_point) != (0.0, 0):\n"," img_array = np.multiply(img_array, 1.0 / input_scale) + input_zero_point\n"," img_array = img_array.astype(input_details[\"dtype\"])\n"," \n"," # Invoke the interpreter\n"," interpreter.set_tensor(input_details[\"index\"], img_array)\n"," interpreter.invoke()\n"," pred = interpreter.get_tensor(output_details[\"index\"])[0]\n"," \n"," # If required, dequantized the output layer (from integer to float)\n"," output_scale, output_zero_point = output_details[\"quantization\"]\n"," if (output_scale, output_zero_point) != (0.0, 0):\n"," pred = pred.astype(np.float32)\n"," pred = np.multiply((pred - output_zero_point), output_scale)\n"," \n"," predicted_label_index = np.argmax(pred)\n"," predicted_score = pred[predicted_label_index]\n"," return (predicted_label_index, predicted_score)"],"execution_count":27,"outputs":[]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"vtee_WxPMgup","executionInfo":{"status":"ok","timestamp":1638748762171,"user_tz":480,"elapsed":137,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"0008362b-c68d-408b-efec-b64136898b4a"},"source":["predict_tflite(model_no_quant_tflite, \"test/7/2.png\")"],"execution_count":28,"outputs":[{"output_type":"execute_result","data":{"text/plain":["(7, 0.9931043)"]},"metadata":{},"execution_count":28}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"0rp0LirfN9vB","executionInfo":{"status":"ok","timestamp":1638748770247,"user_tz":480,"elapsed":165,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"c63b8114-3f8a-45d2-d72b-585a058cb875"},"source":["predict_tflite(model_tflite, \"test/7/2.png\")"],"execution_count":29,"outputs":[{"output_type":"execute_result","data":{"text/plain":["(7, 0.9921875)"]},"metadata":{},"execution_count":29}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/","height":83},"id":"jdNgTO19PRqO","executionInfo":{"status":"ok","timestamp":1638748783929,"user_tz":480,"elapsed":3912,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"8e6c5f8a-9236-4446-ff31-d5f95e170cee"},"source":["from IPython.display import Image, display\n","\n","correct_count = 0\n","wrong_count = 0\n","discarded_count = 0\n","for label_dir in glob.glob(\"test/*\"):\n"," label = int(label_dir.replace(\"test/\", \"\"))\n"," for filename in glob.glob(label_dir + \"/*.png\"):\n"," index, score = predict_tflite(model_tflite, filename)\n"," if score < 0.75:\n"," discarded_count += 1\n"," continue\n"," if index == label:\n"," correct_count += 1\n"," else:\n"," wrong_count += 1\n"," print(\"%d expected, %d found with score %f\" % (label, index, score))\n"," display(Image(filename=filename))\n","\n","correct_percentage = (correct_count / (correct_count + wrong_count)) * 100\n","\n","print(\"%.1f%% correct (N=%d, %d unknown)\" % (correct_percentage, (correct_count + wrong_count), discarded_count))"],"execution_count":30,"outputs":[{"output_type":"stream","name":"stdout","text":["9 expected, 7 found with score 0.816406\n"]},{"output_type":"display_data","data":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAA8ElEQVR4nGNgGAWjYBTQHDCSocfoLMMvNoav3AxfeBheixFQzEKS0f4bGN4LMvz6xXDOGCrC+Y3hOxc+LUwkWfCblYHtF8MJS4TILzYCWkiwIH0GA/dXhj2uKIJ/f3MQbwJhkDgPlf+dg+EjH34tpAURzxdU/jshBv5P+LWQnIoq2hmE3jGIv2SIb5di+MXGoPiAVBOIBjfViFFFWhChmP6blUy9RIET5kQqJM4HKrdRuIdsGdh+UdUCtl8MvEip5Rcbg9F5Ii0grqiIWMHA+puhkoGBgYFhgz+Dy0YiTScRTM5hWBpFG6NHwSgYBRQBAJY6MnCXjHpLAAAAAElFTkSuQmCC\n","text/plain":[""]},"metadata":{}},{"output_type":"stream","name":"stdout","text":["99.9% correct (N=1027, 73 unknown)\n"]}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/","height":173},"id":"NTjGMU8BPpoz","executionInfo":{"status":"ok","timestamp":1638748792684,"user_tz":480,"elapsed":135,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"ea56df39-9336-495c-e214-e39f9fcef78e"},"source":["import os\n","import pandas as pd\n","\n","def get_dir_size(dir):\n"," size = 0\n"," for f in os.scandir(dir):\n"," if f.is_file():\n"," size += f.stat().st_size\n"," elif f.is_dir():\n"," size += get_dir_size(f.path)\n"," return size\n","\n","# Calculate size\n","size_tf = get_dir_size(SAVED_MODEL_FILENAME)\n","size_no_quant_tflite = os.path.getsize(FLOAT_TFL_MODEL_FILENAME)\n","size_tflite = os.path.getsize(QUANTIZED_TFL_MODEL_FILENAME)\n","\n","# Compare size\n","pd.DataFrame.from_records(\n"," [[\"TensorFlow\", f\"{size_tf} bytes\", \"\"],\n"," [\"TensorFlow Lite\", f\"{size_no_quant_tflite} bytes \", f\"(reduced by {size_tf - size_no_quant_tflite} bytes)\"],\n"," [\"TensorFlow Lite Quantized\", f\"{size_tflite} bytes\", f\"(reduced by {size_no_quant_tflite - size_tflite} bytes)\"]],\n"," columns = [\"Model\", \"Size\", \"\"], index=\"Model\")\n"],"execution_count":31,"outputs":[{"output_type":"execute_result","data":{"text/html":["
\n","\n","\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
Size
Model
TensorFlow668171 bytes
TensorFlow Lite100096 bytes(reduced by 568075 bytes)
TensorFlow Lite Quantized30880 bytes(reduced by 69216 bytes)
\n","
"],"text/plain":[" Size \n","Model \n","TensorFlow 668171 bytes \n","TensorFlow Lite 100096 bytes (reduced by 568075 bytes)\n","TensorFlow Lite Quantized 30880 bytes (reduced by 69216 bytes)"]},"metadata":{},"execution_count":31}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"mrvnEJLfR8KU","executionInfo":{"status":"ok","timestamp":1638748913062,"user_tz":480,"elapsed":12258,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"fa3461ec-a27f-45c5-f6d0-555d339415cf"},"source":["# Install xxd if it is not available\n","!apt-get update && apt-get -qq install xxd\n","# Convert to a C source file, i.e, a TensorFlow Lite for Microcontrollers model\n","!xxd -i {QUANTIZED_TFL_MODEL_FILENAME} > {TFL_CC_MODEL_FILENAME}\n","# Update variable names\n","REPLACE_TEXT = QUANTIZED_TFL_MODEL_FILENAME.replace('/', '_').replace('.', '_')\n","!sed -i 's/'{REPLACE_TEXT}'/g_magic_wand_model_data/g' {TFL_CC_MODEL_FILENAME}"],"execution_count":32,"outputs":[{"output_type":"stream","name":"stdout","text":["\r0% [Working]\r \rGet:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]\n","Ign:2 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease\n","Get:3 https://cloud.r-project.org/bin/linux/ubuntu bionic-cran40/ InRelease [3,626 B]\n","Ign:4 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 InRelease\n","Hit:5 http://archive.ubuntu.com/ubuntu bionic InRelease\n","Get:6 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 Release [696 B]\n","Hit:7 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 Release\n","Get:8 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 Release.gpg [836 B]\n","Get:9 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic InRelease [15.9 kB]\n","Get:10 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]\n","Get:11 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [1,444 kB]\n","Hit:12 http://ppa.launchpad.net/cran/libgit2/ubuntu bionic InRelease\n","Get:13 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [2,461 kB]\n","Get:14 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]\n","Get:15 http://security.ubuntu.com/ubuntu bionic-security/restricted amd64 Packages [691 kB]\n","Hit:16 http://ppa.launchpad.net/deadsnakes/ppa/ubuntu bionic InRelease\n","Get:17 http://ppa.launchpad.net/graphics-drivers/ppa/ubuntu bionic InRelease [21.3 kB]\n","Get:19 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 Packages [829 kB]\n","Get:20 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic/main Sources [1,814 kB]\n","Get:21 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [2,898 kB]\n","Get:22 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic/main amd64 Packages [931 kB]\n","Get:23 http://archive.ubuntu.com/ubuntu bionic-updates/restricted amd64 Packages [725 kB]\n","Get:24 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [2,225 kB]\n","Get:25 http://ppa.launchpad.net/graphics-drivers/ppa/ubuntu bionic/main amd64 Packages [44.7 kB]\n","Fetched 14.4 MB in 4s (3,767 kB/s)\n","Reading package lists... Done\n","Selecting previously unselected package xxd.\n","(Reading database ... 155222 files and directories currently installed.)\n","Preparing to unpack .../xxd_2%3a8.0.1453-1ubuntu1.7_amd64.deb ...\n","Unpacking xxd (2:8.0.1453-1ubuntu1.7) ...\n","Setting up xxd (2:8.0.1453-1ubuntu1.7) ...\n","Processing triggers for man-db (2.8.3-2ubuntu0.1) ...\n"]}]},{"cell_type":"code","metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"oazLUtBqWzdJ","executionInfo":{"status":"ok","timestamp":1638748916580,"user_tz":480,"elapsed":339,"user":{"displayName":"David Davis","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"03716636181783186066"}},"outputId":"b6b57fbb-02e9-4972-8bb2-bedc856f0eaa"},"source":["# Print the C source file\n","!tail {TFL_CC_MODEL_FILENAME}"],"execution_count":33,"outputs":[{"output_type":"stream","name":"stdout","text":[" 0x75, 0x6c, 0x74, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x31, 0x3a,\n"," 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\n"," 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,\n"," 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,\n"," 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,\n"," 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00,\n"," 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,\n"," 0x04, 0x00, 0x00, 0x00\n","};\n","unsigned int g_magic_wand_model_data_len = 30880;\n"]}]},{"cell_type":"code","metadata":{"id":"VqN2F42PW-uv"},"source":[""],"execution_count":null,"outputs":[]}]} \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/website/index.html b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/website/index.html new file mode 100644 index 000000000..12e0e284a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/magic_wand/website/index.html @@ -0,0 +1,474 @@ + + + + Magic Wand Gesture Recorder + + + + + +
+
+ To get started recording magic wand gestures: +
    +
  • Upload the Magic Wand Capture sketch to an Arduino Nano BLE Sense board
  • +
  • Connect to the board using the Bluetooth button below.
  • +
  • Wave the wand to make gestures. They'll be recorded and displayed on the right.
  • +
  • Review the gestures, add labels by clicking on the '?', and remove mistakes.
  • +
  • Download the gestures as a JSON data file, ready for model training.
  • +
+
+
+ Download Data + +
Click button to connect to the board
+
+
+ +
+
+ +
+ +
+
+
+ + + diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/README.md b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/README.md new file mode 100644 index 000000000..b7a1b468a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/README.md @@ -0,0 +1,84 @@ + + +# Micro Speech Example + +This example shows how to run a 20 kB model that can recognize 2 keywords, +"yes" and "no", from speech data. + +The application listens to its surroundings with a microphone and indicates +when it has detected a word by lighting an LED or displaying data on a +screen, depending on the capabilities of the device. + +![Animation on Arduino](../../docs/animation_on_arduino.gif) + +The code has a small footprint (for example, around 166 kilobytes on a Cortex +M4) and only uses about 54 kilobytes of additional RAM for working memory. + +## Table of contents + +* [Table of contents](#table-of-contents) +* [Deploy to Arduino](#deploy-to-arduino) + * [Install the Arduino_TensorFlowLite library](#install-the-arduino_tensorflowlite-library) + * [Load and run the example](#load-and-run-the-example) + + +## Deploy to Arduino + +The following instructions will help you build and deploy this example to +[Arduino](https://www.arduino.cc/) devices. + +The example has been tested with the following devices: + +- [Arduino Nano 33 BLE Sense](https://store.arduino.cc/usa/nano-33-ble-sense-with-headers) + +The Arduino Nano 33 BLE Sense is currently the only Arduino with a built-in +microphone. If you're using a different Arduino board and attaching your own +microphone, you'll need to implement your own `audio_provider.cpp` code. It also has a +set of LEDs, which are used to indicate that a word has been recognized. + +### Install the Arduino_TensorFlowLite library + +This example application is included as part of the official TensorFlow Lite Micro +Arduino library. +To install the TensorFlow Lite Micro for Arduino library, see the +[how to install](../../README.md#how-to-install) instructions. + +### Load and run the example + +Once the library has been added, go to `File -> Examples`. You should see an +entry within the list named `Arduino_TensorFlowLite`. Select +it and click `micro_speech` to load the example. + +Use the Arduino IDE to build and upload the example. Once it is running, you +should see the built-in LED on your device flashing. The built-in LED will flash on/off for each inference cycle. Saying the word "yes" will +cause the green LED to remain on for 3 seconds. The current model has fairly low +accuracy, so you may have to repeat "yes" a few times. Saying the word "no" will cause the red LED to light up. The blue LED will be lit for certain "unknown" sounds. + +Word recognition should occur at a distance of approximately 1.5 feet in a low-noise environment. + +The program also outputs inference results to the serial port, which appear as +follows: + +``` +Heard yes (201) @4056ms +Heard no (205) @6448ms +Heard unknown (201) @13696ms +Heard yes (205) @15000ms +``` + +The number after each detected word is its score. By default, the program only +considers matches as valid if their score is over 200, so all of the scores you +see will be at least 200. + +When the program is run, it waits several seconds for a USB-serial connection to be +available. If there is no connection available, it will not output data. To see +the serial output in the Arduino desktop IDE, do the following: + +1. Open the Arduino IDE +1. Connect the Arduino board to your computer via USB +1. Press the reset button on the Arduino board +1. Within 5 seconds, go to `Tools -> Serial Monitor` in the Arduino IDE. You may + have to try several times, since the board will take a moment to connect. + +If you don't see any output, repeat the process again. + diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_audio_provider.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_audio_provider.cpp new file mode 100644 index 000000000..2c5594c9b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_audio_provider.cpp @@ -0,0 +1,194 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#if defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) +#define ARDUINO_EXCLUDE_CODE +#endif // defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) + +#ifndef ARDUINO_EXCLUDE_CODE + +#include +#include + +#include "PDM.h" +#include "audio_provider.h" +#include "micro_features_micro_model_settings.h" +#include "test_over_serial/test_over_serial.h" + +using namespace test_over_serial; + +namespace { +bool g_is_audio_initialized = false; +// An internal buffer able to fit 16x our sample size +constexpr int kAudioCaptureBufferSize = DEFAULT_PDM_BUFFER_SIZE * 16; +int16_t g_audio_capture_buffer[kAudioCaptureBufferSize]; +// A buffer that holds our output +int16_t g_audio_output_buffer[kMaxAudioSampleSize]; +// Mark as volatile so we can check in a while loop to see if +// any samples have arrived yet. +volatile int32_t g_latest_audio_timestamp = 0; +// error reporter +tflite::ErrorReporter* g_error_reporter; +// test_over_serial sample index +uint32_t g_test_sample_index; +// test_over_serial silence insertion flag +bool g_test_insert_silence = true; +} // namespace + +void CaptureSamples() { + // This is how many bytes of new data we have each time this is called + const int number_of_samples = DEFAULT_PDM_BUFFER_SIZE / 2; + // Calculate what timestamp the last audio sample represents + const int32_t time_in_ms = + g_latest_audio_timestamp + + (number_of_samples / (kAudioSampleFrequency / 1000)); + // Determine the index, in the history of all samples, of the last sample + const int32_t start_sample_offset = + g_latest_audio_timestamp * (kAudioSampleFrequency / 1000); + // Determine the index of this sample in our ring buffer + const int capture_index = start_sample_offset % kAudioCaptureBufferSize; + // Read the data to the correct place in our buffer + int num_read = + PDM.read(g_audio_capture_buffer + capture_index, DEFAULT_PDM_BUFFER_SIZE); + if (num_read != DEFAULT_PDM_BUFFER_SIZE) { + TF_LITE_REPORT_ERROR(g_error_reporter, "### short read (%d/%d) @%dms", + num_read, DEFAULT_PDM_BUFFER_SIZE, time_in_ms); + while (true) { + // NORETURN + } + } + // This is how we let the outside world know that new audio data has arrived. + g_latest_audio_timestamp = time_in_ms; +} + +TfLiteStatus InitAudioRecording(tflite::ErrorReporter* error_reporter) { + if (!g_is_audio_initialized) { + g_error_reporter = error_reporter; + // Hook up the callback that will be called with each sample + PDM.onReceive(CaptureSamples); + // Start listening for audio: MONO @ 16KHz + PDM.begin(1, kAudioSampleFrequency); + // gain: -20db (min) + 6.5db (13) + 3.2db (builtin) = -10.3db + PDM.setGain(13); + // Block until we have our first audio sample + while (!g_latest_audio_timestamp) { + } + g_is_audio_initialized = true; + } + + return kTfLiteOk; +} + +TfLiteStatus GetAudioSamples(tflite::ErrorReporter* error_reporter, + int start_ms, int duration_ms, + int* audio_samples_size, int16_t** audio_samples) { + // This next part should only be called when the main thread notices that the + // latest audio sample data timestamp has changed, so that there's new data + // in the capture ring buffer. The ring buffer will eventually wrap around and + // overwrite the data, but the assumption is that the main thread is checking + // often enough and the buffer is large enough that this call will be made + // before that happens. + + // Determine the index, in the history of all samples, of the first + // sample we want + const int start_offset = start_ms * (kAudioSampleFrequency / 1000); + // Determine how many samples we want in total + const int duration_sample_count = + duration_ms * (kAudioSampleFrequency / 1000); + for (int i = 0; i < duration_sample_count; ++i) { + // For each sample, transform its index in the history of all samples into + // its index in g_audio_capture_buffer + const int capture_index = (start_offset + i) % kAudioCaptureBufferSize; + // Write the sample to the output buffer + g_audio_output_buffer[i] = g_audio_capture_buffer[capture_index]; + } + + // Set pointers to provide access to the audio + *audio_samples_size = duration_sample_count; + *audio_samples = g_audio_output_buffer; + + return kTfLiteOk; +} + +namespace { + +void InsertSilence(const size_t len, int16_t value) { + for (size_t i = 0; i < len; i++) { + const size_t index = (g_test_sample_index + i) % kAudioCaptureBufferSize; + g_audio_capture_buffer[index] = value; + } + g_test_sample_index += len; +} + +int32_t ProcessTestInput(TestOverSerial& test) { + constexpr size_t samples_16ms = ((kAudioSampleFrequency / 1000) * 16); + + InputHandler handler = [](const InputBuffer* const input) { + if (0 == input->offset) { + // don't insert silence + g_test_insert_silence = false; + } + + for (size_t i = 0; i < input->length; i++) { + const size_t index = (g_test_sample_index + i) % kAudioCaptureBufferSize; + g_audio_capture_buffer[index] = input->data.int16[i]; + } + g_test_sample_index += input->length; + + if (input->total == (input->offset + input->length)) { + // allow silence insertion again + g_test_insert_silence = true; + } + return true; + }; + + test.ProcessInput(&handler); + + if (g_test_insert_silence) { + // add 16ms of silence just like the PDM interface + InsertSilence(samples_16ms, 0); + } + + // Round the timestamp to a multiple of 64ms, + // This emulates the PDM interface during inference processing. + g_latest_audio_timestamp = (g_test_sample_index / (samples_16ms * 4)) * 64; + return g_latest_audio_timestamp; +} + +} // namespace + +int32_t LatestAudioTimestamp() { + TestOverSerial& test = TestOverSerial::Instance(kAUDIO_PCM_16KHZ_MONO_S16); + if (!test.IsTestMode()) { + // check serial port for test mode command + test.ProcessInput(nullptr); + } + if (test.IsTestMode()) { + if (g_is_audio_initialized) { + // stop capture from hardware + PDM.end(); + g_is_audio_initialized = false; + g_test_sample_index = + g_latest_audio_timestamp * (kAudioSampleFrequency / 1000); + } + return ProcessTestInput(test); + } else { + // CaptureSamples() updated the timestamp + return g_latest_audio_timestamp; + } + // NOTREACHED +} + +#endif // ARDUINO_EXCLUDE_CODE diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_command_responder.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_command_responder.cpp new file mode 100644 index 000000000..7fedc6964 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_command_responder.cpp @@ -0,0 +1,89 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#if defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) +#define ARDUINO_EXCLUDE_CODE +#endif // defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) + +#ifndef ARDUINO_EXCLUDE_CODE + +#include "Arduino.h" +#include "command_responder.h" + +// Toggles the built-in LED every inference, and lights a colored LED depending +// on which word was detected. +void RespondToCommand(tflite::ErrorReporter* error_reporter, + int32_t current_time, const char* found_command, + uint8_t score, bool is_new_command) { + static bool is_initialized = false; + if (!is_initialized) { + pinMode(LED_BUILTIN, OUTPUT); + // Pins for the built-in RGB LEDs on the Arduino Nano 33 BLE Sense + pinMode(LEDR, OUTPUT); + pinMode(LEDG, OUTPUT); + pinMode(LEDB, OUTPUT); + // Ensure the LED is off by default. + // Note: The RGB LEDs on the Arduino Nano 33 BLE + // Sense are on when the pin is LOW, off when HIGH. + digitalWrite(LEDR, HIGH); + digitalWrite(LEDG, HIGH); + digitalWrite(LEDB, HIGH); + is_initialized = true; + } + static int32_t last_command_time = 0; + static int count = 0; + + if (is_new_command) { + TF_LITE_REPORT_ERROR(error_reporter, "Heard %s (%d) @%dms", found_command, + score, current_time); + // If we hear a command, light up the appropriate LED + digitalWrite(LEDR, HIGH); + digitalWrite(LEDG, HIGH); + digitalWrite(LEDB, HIGH); + + if (found_command[0] == 'y') { + digitalWrite(LEDG, LOW); // Green for yes + } else if (found_command[0] == 'n') { + digitalWrite(LEDR, LOW); // Red for no + } else if (found_command[0] == 'u') { + digitalWrite(LEDB, LOW); // Blue for unknown + } else { + // silence + } + + last_command_time = current_time; + } + + // If last_command_time is non-zero but was >3 seconds ago, zero it + // and switch off the LED. + if (last_command_time != 0) { + if (last_command_time < (current_time - 3000)) { + last_command_time = 0; + digitalWrite(LEDR, HIGH); + digitalWrite(LEDG, HIGH); + digitalWrite(LEDB, HIGH); + } + } + + // Otherwise, toggle the LED every time an inference is performed. + ++count; + if (count & 1) { + digitalWrite(LED_BUILTIN, HIGH); + } else { + digitalWrite(LED_BUILTIN, LOW); + } +} + +#endif // ARDUINO_EXCLUDE_CODE diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_main.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_main.cpp new file mode 100644 index 000000000..c70a2bcea --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/arduino_main.cpp @@ -0,0 +1,20 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "main_functions.h" + +// Arduino automatically calls the setup() and loop() functions in a sketch, so +// where other systems need their own main routine in this file, it can be left +// empty. diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/audio_provider.h b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/audio_provider.h new file mode 100644 index 000000000..88988ba1f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/audio_provider.h @@ -0,0 +1,49 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_AUDIO_PROVIDER_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_AUDIO_PROVIDER_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" + +// This is an abstraction around an audio source like a microphone, and is +// expected to return 16-bit PCM sample data for a given point in time. The +// sample data itself should be used as quickly as possible by the caller, since +// to allow memory optimizations there are no guarantees that the samples won't +// be overwritten by new data in the future. In practice, implementations should +// ensure that there's a reasonable time allowed for clients to access the data +// before any reuse. +// The reference implementation can have no platform-specific dependencies, so +// it just returns an array filled with zeros. For real applications, you should +// ensure there's a specialized implementation that accesses hardware APIs. +TfLiteStatus GetAudioSamples(tflite::ErrorReporter* error_reporter, + int start_ms, int duration_ms, + int* audio_samples_size, int16_t** audio_samples); + +// Returns the time that audio data was last captured in milliseconds. There's +// no contract about what time zero represents, the accuracy, or the granularity +// of the result. Subsequent calls will generally not return a lower value, but +// even that's not guaranteed if there's an overflow wraparound. +// The reference implementation of this function just returns a constantly +// incrementing value for each call, since it would need a non-portable platform +// call to access time information. For real applications, you'll need to write +// your own platform-specific implementation. +int32_t LatestAudioTimestamp(); + +// Starts audio capture +TfLiteStatus InitAudioRecording(tflite::ErrorReporter* error_reporter); + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_AUDIO_PROVIDER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/command_responder.h b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/command_responder.h new file mode 100644 index 000000000..ac3f448ee --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/command_responder.h @@ -0,0 +1,32 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Provides an interface to take an action based on an audio command. + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_COMMAND_RESPONDER_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_COMMAND_RESPONDER_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" + +// Called every time the results of an audio recognition run are available. The +// human-readable name of any recognized command is in the `found_command` +// argument, `score` has the numerical confidence, and `is_new_command` is set +// if the previous command was different to this one. +void RespondToCommand(tflite::ErrorReporter* error_reporter, + int32_t current_time, const char* found_command, + uint8_t score, bool is_new_command); + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_COMMAND_RESPONDER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/feature_provider.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/feature_provider.cpp new file mode 100644 index 000000000..a9142f7d4 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/feature_provider.cpp @@ -0,0 +1,127 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "feature_provider.h" + +#include "audio_provider.h" +#include "micro_features_micro_features_generator.h" +#include "micro_features_micro_model_settings.h" + +FeatureProvider::FeatureProvider(int feature_size, int8_t* feature_data) + : feature_size_(feature_size), + feature_data_(feature_data), + is_first_run_(true) { + // Initialize the feature data to default values. + for (int n = 0; n < feature_size_; ++n) { + feature_data_[n] = 0; + } +} + +FeatureProvider::~FeatureProvider() {} + +TfLiteStatus FeatureProvider::PopulateFeatureData( + tflite::ErrorReporter* error_reporter, int32_t last_time_in_ms, + int32_t time_in_ms, int* how_many_new_slices) { + if (feature_size_ != kFeatureElementCount) { + TF_LITE_REPORT_ERROR(error_reporter, + "Requested feature_data_ size %d doesn't match %d", + feature_size_, kFeatureElementCount); + return kTfLiteError; + } + + // Quantize the time into steps as long as each window stride, so we can + // figure out which audio data we need to fetch. + const int last_step = (last_time_in_ms / kFeatureSliceStrideMs); + // Number of new 20ms slices from which we can take 30ms samples + int slices_needed = + ((((time_in_ms - last_time_in_ms) - kFeatureSliceDurationMs) * + kFeatureSliceStrideMs) / + kFeatureSliceStrideMs + + kFeatureSliceStrideMs) / + kFeatureSliceStrideMs; + // If this is the first call, make sure we don't use any cached information. + if (is_first_run_) { + TfLiteStatus init_status = InitializeMicroFeatures(error_reporter); + if (init_status != kTfLiteOk) { + return init_status; + } + is_first_run_ = false; + return kTfLiteOk; + } + if (slices_needed > kFeatureSliceCount) { + slices_needed = kFeatureSliceCount; + } + if (slices_needed == 0) { + return kTfLiteOk; + } + *how_many_new_slices = slices_needed; + + const int slices_to_keep = kFeatureSliceCount - slices_needed; + const int slices_to_drop = kFeatureSliceCount - slices_to_keep; + // If we can avoid recalculating some slices, just move the existing data + // up in the spectrogram, to perform something like this: + // last time = 80ms current time = 120ms + // +-----------+ +-----------+ + // | data@20ms | --> | data@60ms | + // +-----------+ -- +-----------+ + // | data@40ms | -- --> | data@80ms | + // +-----------+ -- -- +-----------+ + // | data@60ms | -- -- | | + // +-----------+ -- +-----------+ + // | data@80ms | -- | | + // +-----------+ +-----------+ + if (slices_to_keep > 0) { + for (int dest_slice = 0; dest_slice < slices_to_keep; ++dest_slice) { + int8_t* dest_slice_data = + feature_data_ + (dest_slice * kFeatureSliceSize); + const int src_slice = dest_slice + slices_to_drop; + const int8_t* src_slice_data = + feature_data_ + (src_slice * kFeatureSliceSize); + for (int i = 0; i < kFeatureSliceSize; ++i) { + dest_slice_data[i] = src_slice_data[i]; + } + } + } + // Any slices that need to be filled in with feature data have their + // appropriate audio data pulled, and features calculated for that slice. + if (slices_needed > 0) { + for (int new_slice = slices_to_keep; new_slice < kFeatureSliceCount; + ++new_slice) { + const int new_step = last_step + (new_slice - slices_to_keep); + const int32_t slice_start_ms = (new_step * kFeatureSliceStrideMs); + int16_t* audio_samples = nullptr; + int audio_samples_size = 0; + GetAudioSamples(error_reporter, slice_start_ms, kFeatureSliceDurationMs, + &audio_samples_size, &audio_samples); + constexpr int wanted = + kFeatureSliceDurationMs * (kAudioSampleFrequency / 1000); + if (audio_samples_size != wanted) { + TF_LITE_REPORT_ERROR(error_reporter, + "Audio data size %d too small, want %d", + audio_samples_size, wanted); + return kTfLiteError; + } + int8_t* new_slice_data = feature_data_ + (new_slice * kFeatureSliceSize); + size_t num_samples_read; + TfLiteStatus generate_status = GenerateMicroFeatures( + error_reporter, audio_samples, audio_samples_size, kFeatureSliceSize, + new_slice_data, &num_samples_read); + if (generate_status != kTfLiteOk) { + return generate_status; + } + } + } + return kTfLiteOk; +} diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/feature_provider.h b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/feature_provider.h new file mode 100644 index 000000000..d086e013d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/feature_provider.h @@ -0,0 +1,52 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_FEATURE_PROVIDER_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_FEATURE_PROVIDER_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" + +// Binds itself to an area of memory intended to hold the input features for an +// audio-recognition neural network model, and fills that data area with the +// features representing the current audio input, for example from a microphone. +// The audio features themselves are a two-dimensional array, made up of +// horizontal slices representing the frequencies at one point in time, stacked +// on top of each other to form a spectrogram showing how those frequencies +// changed over time. +class FeatureProvider { + public: + // Create the provider, and bind it to an area of memory. This memory should + // remain accessible for the lifetime of the provider object, since subsequent + // calls will fill it with feature data. The provider does no memory + // management of this data. + FeatureProvider(int feature_size, int8_t* feature_data); + ~FeatureProvider(); + + // Fills the feature data with information from audio inputs, and returns how + // many feature slices were updated. + TfLiteStatus PopulateFeatureData(tflite::ErrorReporter* error_reporter, + int32_t last_time_in_ms, int32_t time_in_ms, + int* how_many_new_slices); + + private: + int feature_size_; + int8_t* feature_data_; + // Make sure we don't try to use cached information if this is the first call + // into the provider. + bool is_first_run_; +}; + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_FEATURE_PROVIDER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/main_functions.h b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/main_functions.h new file mode 100644 index 000000000..0ac067710 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/main_functions.h @@ -0,0 +1,37 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MAIN_FUNCTIONS_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MAIN_FUNCTIONS_H_ + +// Expose a C friendly interface for main functions. +#ifdef __cplusplus +extern "C" { +#endif + +// Initializes all data needed for the example. The name is important, and needs +// to be setup() for Arduino compatibility. +void setup(); + +// Runs one iteration of data gathering and inference. This should be called +// repeatedly from the application code. The name needs to be loop() for Arduino +// compatibility. +void loop(); + +#ifdef __cplusplus +} +#endif + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MAIN_FUNCTIONS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_features_generator.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_features_generator.cpp new file mode 100644 index 000000000..2776b2fc8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_features_generator.cpp @@ -0,0 +1,116 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "micro_features_micro_features_generator.h" + +#include +#include + +#include "micro_features_micro_model_settings.h" +#include "tensorflow/lite/experimental/microfrontend/lib/frontend.h" +#include "tensorflow/lite/experimental/microfrontend/lib/frontend_util.h" + +// Configure FFT to output 16 bit fixed point. +#define FIXED_POINT 16 + +namespace { + +FrontendState g_micro_features_state; +bool g_is_first_time = true; + +} // namespace + +TfLiteStatus InitializeMicroFeatures(tflite::ErrorReporter* error_reporter) { + FrontendConfig config; + config.window.size_ms = kFeatureSliceDurationMs; + config.window.step_size_ms = kFeatureSliceStrideMs; + config.noise_reduction.smoothing_bits = 10; + config.filterbank.num_channels = kFeatureSliceSize; + config.filterbank.lower_band_limit = 125.0; + config.filterbank.upper_band_limit = 7500.0; + config.noise_reduction.smoothing_bits = 10; + config.noise_reduction.even_smoothing = 0.025; + config.noise_reduction.odd_smoothing = 0.06; + config.noise_reduction.min_signal_remaining = 0.05; + config.pcan_gain_control.enable_pcan = 1; + config.pcan_gain_control.strength = 0.95; + config.pcan_gain_control.offset = 80.0; + config.pcan_gain_control.gain_bits = 21; + config.log_scale.enable_log = 1; + config.log_scale.scale_shift = 6; + if (!FrontendPopulateState(&config, &g_micro_features_state, + kAudioSampleFrequency)) { + TF_LITE_REPORT_ERROR(error_reporter, "FrontendPopulateState() failed"); + return kTfLiteError; + } + g_is_first_time = true; + return kTfLiteOk; +} + +// This is not exposed in any header, and is only used for testing, to ensure +// that the state is correctly set up before generating results. +void SetMicroFeaturesNoiseEstimates(const uint32_t* estimate_presets) { + for (int i = 0; i < g_micro_features_state.filterbank.num_channels; ++i) { + g_micro_features_state.noise_reduction.estimate[i] = estimate_presets[i]; + } +} + +TfLiteStatus GenerateMicroFeatures(tflite::ErrorReporter* error_reporter, + const int16_t* input, int input_size, + int output_size, int8_t* output, + size_t* num_samples_read) { + const int16_t* frontend_input; + if (g_is_first_time) { + frontend_input = input; + g_is_first_time = false; + } else { + frontend_input = input; + } + FrontendOutput frontend_output = FrontendProcessSamples( + &g_micro_features_state, frontend_input, input_size, num_samples_read); + + for (size_t i = 0; i < frontend_output.size; ++i) { + // These scaling values are derived from those used in input_data.py in the + // training pipeline. + // The feature pipeline outputs 16-bit signed integers in roughly a 0 to 670 + // range. In training, these are then arbitrarily divided by 25.6 to get + // float values in the rough range of 0.0 to 26.0. This scaling is performed + // for historical reasons, to match up with the output of other feature + // generators. + // The process is then further complicated when we quantize the model. This + // means we have to scale the 0.0 to 26.0 real values to the -128 to 127 + // signed integer numbers. + // All this means that to get matching values from our integer feature + // output into the tensor input, we have to perform: + // input = (((feature / 25.6) / 26.0) * 256) - 128 + // To simplify this and perform it in 32-bit integer math, we rearrange to: + // input = (feature * 256) / (25.6 * 26.0) - 128 + constexpr int32_t value_scale = 256; + constexpr int32_t value_div = static_cast((25.6f * 26.0f) + 0.5f); + int32_t value = + ((frontend_output.values[i] * value_scale) + (value_div / 2)) / + value_div; + value -= 128; + if (value < -128) { + value = -128; + } + if (value > 127) { + value = 127; + } + output[i] = value; + } + + return kTfLiteOk; +} diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_features_generator.h b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_features_generator.h new file mode 100644 index 000000000..293042393 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_features_generator.h @@ -0,0 +1,32 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_FEATURES_GENERATOR_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_FEATURES_GENERATOR_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" + +// Sets up any resources needed for the feature generation pipeline. +TfLiteStatus InitializeMicroFeatures(tflite::ErrorReporter* error_reporter); + +// Converts audio sample data into a more compact form that's appropriate for +// feeding into a neural network. +TfLiteStatus GenerateMicroFeatures(tflite::ErrorReporter* error_reporter, + const int16_t* input, int input_size, + int output_size, int8_t* output, + size_t* num_samples_read); + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_FEATURES_GENERATOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_model_settings.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_model_settings.cpp new file mode 100644 index 000000000..f772cef9b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_model_settings.cpp @@ -0,0 +1,23 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "micro_features_micro_model_settings.h" + +const char* kCategoryLabels[kCategoryCount] = { + "silence", + "unknown", + "yes", + "no", +}; diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_model_settings.h b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_model_settings.h new file mode 100644 index 000000000..e542213e8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_micro_model_settings.h @@ -0,0 +1,43 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_MODEL_SETTINGS_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_MODEL_SETTINGS_H_ + +// Keeping these as constant expressions allow us to allocate fixed-sized arrays +// on the stack for our working memory. + +// The size of the input time series data we pass to the FFT to produce the +// frequency information. This has to be a power of two, and since we're dealing +// with 30ms of 16KHz inputs, which means 480 samples, this is the next value. +constexpr int kMaxAudioSampleSize = 512; +constexpr int kAudioSampleFrequency = 16000; + +// The following values are derived from values used during model training. +// If you change the way you preprocess the input, update all these constants. +constexpr int kFeatureSliceSize = 40; +constexpr int kFeatureSliceCount = 49; +constexpr int kFeatureElementCount = (kFeatureSliceSize * kFeatureSliceCount); +constexpr int kFeatureSliceStrideMs = 20; +constexpr int kFeatureSliceDurationMs = 30; + +// Variables for the model's output categories. +constexpr int kSilenceIndex = 0; +constexpr int kUnknownIndex = 1; +// If you modify the output categories, you need to update the following values. +constexpr int kCategoryCount = 4; +extern const char* kCategoryLabels[kCategoryCount]; + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_MODEL_SETTINGS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_model.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_model.cpp new file mode 100644 index 000000000..428616ec5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_model.cpp @@ -0,0 +1,1596 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This is a standard TensorFlow Lite FlatBuffer model file that has been +// converted into a C data array, so it can be easily compiled into a binary +// for devices that don't have a file system. It was created using the command: +// xxd -i model.tflite > model.cc + +#include "micro_features_model.h" + +// We need to keep the data array aligned on some architectures. +#ifdef __has_attribute +#define HAVE_ATTRIBUTE(x) __has_attribute(x) +#else +#define HAVE_ATTRIBUTE(x) 0 +#endif +#if HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) +#define DATA_ALIGN_ATTRIBUTE __attribute__((aligned(4))) +#else +#define DATA_ALIGN_ATTRIBUTE +#endif + +const unsigned char g_model[] DATA_ALIGN_ATTRIBUTE = { + 0x20, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x94, 0x48, 0x00, 0x00, 0x34, 0x42, 0x00, 0x00, + 0x1c, 0x42, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x6d, 0x69, 0x6e, 0x5f, + 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xd4, 0x41, 0x00, 0x00, + 0xb4, 0x41, 0x00, 0x00, 0x24, 0x03, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00, + 0xec, 0x02, 0x00, 0x00, 0xe4, 0x02, 0x00, 0x00, 0xc4, 0x02, 0x00, 0x00, + 0xbc, 0x02, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x16, 0xbd, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x35, 0x2e, + 0x30, 0x00, 0x00, 0x00, 0x94, 0xba, 0xff, 0xff, 0x98, 0xba, 0xff, 0xff, + 0x32, 0xbd, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, + 0xfa, 0xee, 0x28, 0xc4, 0xee, 0xfe, 0xcf, 0x0f, 0x1e, 0xf7, 0x1f, 0x06, + 0x0d, 0xed, 0xe9, 0x83, 0x5c, 0xc9, 0x18, 0xe3, 0xf9, 0x14, 0x28, 0x2a, + 0x09, 0xf2, 0x18, 0x34, 0x62, 0xea, 0xef, 0xd6, 0x36, 0xb7, 0x1e, 0xf7, + 0x3b, 0x22, 0x28, 0x39, 0xc2, 0x9d, 0xf1, 0x07, 0x5e, 0x0b, 0x1e, 0x2c, + 0x07, 0xdd, 0xfd, 0xc3, 0xd8, 0x4a, 0xf3, 0x28, 0xa7, 0x16, 0xd5, 0xf1, + 0xc3, 0x05, 0xfd, 0x27, 0xcc, 0xba, 0x1e, 0xcb, 0xd7, 0x3d, 0xd4, 0x29, + 0x00, 0xfd, 0x28, 0x44, 0xfb, 0xf2, 0xf3, 0xb6, 0x4f, 0xcf, 0x09, 0xf0, + 0xfa, 0x45, 0x41, 0x49, 0x05, 0xc5, 0x17, 0x5d, 0x64, 0x00, 0xf8, 0xee, + 0x48, 0x17, 0xf4, 0xe9, 0x2e, 0x4b, 0x2e, 0x3f, 0xdf, 0xee, 0xe4, 0x08, + 0x38, 0xf1, 0x16, 0x13, 0x2f, 0x2a, 0xed, 0xc2, 0xbf, 0x36, 0xf4, 0x02, + 0xcf, 0xaa, 0xd2, 0xfa, 0xac, 0x13, 0xf6, 0xe8, 0xb5, 0x68, 0x12, 0xb6, + 0xce, 0x0e, 0xdf, 0x58, 0xe4, 0x49, 0x14, 0x15, 0x03, 0xed, 0xfa, 0xd4, + 0x40, 0xa7, 0xf6, 0xca, 0xfb, 0x00, 0x4d, 0x5e, 0xe4, 0x55, 0x1d, 0x30, + 0x45, 0xe2, 0xfc, 0x01, 0x48, 0x81, 0xe9, 0xf1, 0x1e, 0xfc, 0x21, 0x32, + 0xed, 0x4b, 0xed, 0xfa, 0x2f, 0xd2, 0xfa, 0xfb, 0x4d, 0xa7, 0xed, 0xc7, + 0x92, 0xdf, 0xe6, 0xdb, 0xf8, 0x1f, 0xd9, 0xfa, 0x91, 0xf5, 0xe5, 0xc5, + 0x8c, 0x17, 0x0f, 0xb9, 0xd2, 0xc7, 0xfe, 0x68, 0xd3, 0x51, 0x2e, 0x49, + 0x1f, 0xbd, 0x01, 0xeb, 0x31, 0x17, 0xf0, 0xef, 0xff, 0xb8, 0x5d, 0x62, + 0x02, 0x0f, 0x1f, 0x78, 0x6a, 0xb0, 0xf9, 0xfe, 0x4f, 0xcc, 0xd3, 0xff, + 0x0a, 0x96, 0x1e, 0x2c, 0xed, 0xbc, 0xf4, 0x0b, 0x42, 0xc8, 0xf1, 0xea, + 0x6e, 0x58, 0xec, 0xc4, 0x99, 0xae, 0xdc, 0xd7, 0x12, 0x87, 0xd8, 0x06, + 0xa2, 0xc2, 0xe6, 0xa2, 0x81, 0x24, 0xe9, 0xac, 0xce, 0xb6, 0x15, 0x6b, + 0xba, 0x00, 0x19, 0x58, 0x29, 0xb6, 0xfe, 0x01, 0x25, 0x96, 0xd2, 0xec, + 0x0e, 0x9c, 0x60, 0x5f, 0xe9, 0xf4, 0xf5, 0x69, 0x6b, 0xb5, 0xe1, 0xf6, + 0x5e, 0xb7, 0xb1, 0xe5, 0x11, 0x9b, 0x18, 0x10, 0xe3, 0xe1, 0xe0, 0x0d, + 0x4f, 0xa5, 0xde, 0xe5, 0x6f, 0xe2, 0xfb, 0x99, 0x82, 0xa5, 0xc9, 0xb6, + 0x1f, 0x46, 0xf3, 0x04, 0xc6, 0xca, 0xd6, 0x97, 0x90, 0x1d, 0xc0, 0x95, + 0xf0, 0x19, 0x30, 0x77, 0xc2, 0x3c, 0xfa, 0x24, 0x02, 0x4d, 0x06, 0x07, + 0x15, 0x02, 0xb0, 0xe7, 0x27, 0x22, 0x67, 0x4d, 0xf1, 0xc2, 0xf4, 0x64, + 0x38, 0x40, 0xdf, 0xf6, 0x3a, 0x43, 0xb8, 0xe1, 0x0d, 0x15, 0x11, 0xfe, + 0xf5, 0xec, 0xf9, 0xe5, 0x22, 0x36, 0xe4, 0xfd, 0x6d, 0xbf, 0x0d, 0x8e, + 0xb7, 0x15, 0xbf, 0x9f, 0x16, 0xad, 0x0a, 0x02, 0x8e, 0x14, 0xda, 0x9b, + 0x8e, 0xc3, 0xa6, 0xca, 0xf5, 0x7f, 0x51, 0x56, 0xc1, 0xb3, 0xd9, 0x35, + 0xf8, 0x7f, 0x04, 0x0a, 0x03, 0x3f, 0xbe, 0xee, 0x19, 0x68, 0x78, 0x50, + 0xf9, 0xa7, 0xf7, 0x7f, 0x1d, 0x76, 0xdb, 0xe8, 0x33, 0xb9, 0xd7, 0xe7, + 0xe8, 0x69, 0x15, 0xf7, 0xf5, 0xb2, 0xfe, 0xe8, 0xf3, 0x5b, 0xe2, 0x06, + 0x6e, 0x09, 0x36, 0xb7, 0xcc, 0x38, 0xbf, 0x8a, 0x28, 0x14, 0x2e, 0x18, + 0xa7, 0x26, 0xcb, 0xb2, 0x95, 0x37, 0xac, 0xcd, 0xd7, 0x51, 0x67, 0x44, + 0xcd, 0x31, 0xde, 0x04, 0xe9, 0x6a, 0x00, 0x13, 0x0a, 0x0c, 0xdd, 0x16, + 0xe0, 0x24, 0x7e, 0x49, 0xf1, 0xb5, 0x04, 0x52, 0x01, 0x50, 0xdd, 0xf5, + 0x26, 0xc9, 0xf4, 0xf8, 0xd6, 0x31, 0x1b, 0xd0, 0xef, 0x03, 0x0a, 0xc0, + 0xd4, 0x4f, 0xe2, 0xfd, 0x72, 0xf4, 0x5a, 0xc9, 0xd7, 0x31, 0xc0, 0x8e, + 0x17, 0x5e, 0x57, 0x00, 0xb4, 0x3a, 0xc8, 0xd2, 0x92, 0x32, 0xcb, 0xd8, + 0xc3, 0xa6, 0x63, 0x26, 0xcf, 0xbc, 0xe8, 0x57, 0x9b, 0xe9, 0xf7, 0x1c, + 0xea, 0x12, 0xf1, 0xf7, 0xdb, 0xb9, 0x7f, 0x16, 0xf6, 0xe0, 0x08, 0x70, + 0xa2, 0xed, 0xcc, 0xf1, 0x1e, 0x10, 0x04, 0xf7, 0xa9, 0xb7, 0x34, 0xaa, + 0x0a, 0xdb, 0x2a, 0xa6, 0xb6, 0x10, 0xea, 0xf8, 0x5e, 0x06, 0x72, 0xdd, + 0xd0, 0xb9, 0xd6, 0xa0, 0x10, 0x9f, 0x5a, 0x17, 0xb1, 0xe7, 0xc0, 0x01, + 0x9d, 0x01, 0xe0, 0xe0, 0xaf, 0x9c, 0x46, 0xd8, 0xaf, 0xe8, 0xce, 0x02, + 0x8a, 0xbb, 0xe4, 0xf6, 0xf3, 0x36, 0x07, 0xca, 0xcb, 0x87, 0x6e, 0xcc, + 0xd6, 0x9e, 0x0a, 0x2a, 0x81, 0xd7, 0xcf, 0xc0, 0x04, 0xeb, 0x24, 0xcc, + 0xc9, 0x95, 0x33, 0x81, 0xf7, 0xad, 0x1c, 0x9c, 0xa4, 0xd6, 0xf9, 0xe6, + 0x3d, 0x84, 0x7f, 0xcc, 0xd4, 0xb0, 0xf4, 0xa2, 0xe9, 0x3c, 0x36, 0xee, + 0xd5, 0xcf, 0xcd, 0x2d, 0x28, 0xbd, 0xff, 0xff, 0xc2, 0xbf, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x31, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0xbd, 0xff, 0xff, 0x4c, 0xbd, 0xff, 0xff, 0xe6, 0xbf, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8a, 0xfe, 0xff, 0xff, + 0xa9, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0xd0, 0x00, 0x00, 0x00, + 0x52, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4f, 0xfb, 0xff, 0xff, + 0x4a, 0xfd, 0xff, 0xff, 0x12, 0xc0, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x80, 0x3e, 0x00, 0x00, 0xff, 0xf9, 0xfd, 0x0a, 0x07, 0x08, 0x07, 0x03, + 0x07, 0xf2, 0xd1, 0x09, 0xf0, 0xe9, 0x28, 0x09, 0xdf, 0x05, 0xfa, 0xf0, + 0xe8, 0xe3, 0x13, 0x0e, 0x08, 0xef, 0xd3, 0xee, 0x0f, 0xe8, 0xeb, 0x14, + 0xf7, 0xed, 0xfd, 0x1f, 0xe8, 0xd5, 0xeb, 0xfc, 0x0e, 0xf4, 0xf7, 0x07, + 0x05, 0xea, 0xf6, 0x1f, 0xf8, 0xdb, 0xdc, 0x0b, 0x03, 0xdd, 0xd8, 0xf3, + 0x0f, 0x19, 0xe1, 0x09, 0xfc, 0xe4, 0x02, 0x04, 0xf1, 0x04, 0xeb, 0xf3, + 0x1e, 0x06, 0xfd, 0x11, 0xfc, 0xfa, 0xf6, 0x1f, 0x0f, 0x02, 0xf5, 0xf7, + 0xff, 0x24, 0xdf, 0xf7, 0xf8, 0xf3, 0xf6, 0xe9, 0xef, 0x03, 0xdd, 0xf2, + 0x28, 0xe1, 0xf2, 0x22, 0xf4, 0x09, 0xf7, 0xf9, 0xf0, 0xd4, 0xf9, 0xee, + 0xff, 0x14, 0xda, 0xf3, 0x11, 0xe2, 0xf6, 0x0c, 0xf2, 0xeb, 0xf8, 0xe8, + 0xe3, 0x08, 0x02, 0x17, 0xf4, 0x0b, 0x0c, 0x27, 0xe6, 0x02, 0x03, 0xf9, + 0x14, 0x18, 0xf6, 0xeb, 0x1f, 0x0c, 0xf1, 0xee, 0xfc, 0x08, 0xf0, 0xfe, + 0xfd, 0xee, 0x17, 0xfd, 0x1c, 0xef, 0xfd, 0xde, 0x04, 0x05, 0xf0, 0x31, + 0xfa, 0x0b, 0xdc, 0x0d, 0xed, 0xf5, 0xfa, 0xf4, 0x08, 0x0c, 0xd7, 0x1e, + 0x15, 0x03, 0xf5, 0x02, 0xf4, 0xfb, 0xed, 0x01, 0xfe, 0xd6, 0x1f, 0xfd, + 0xfd, 0x0e, 0xfa, 0x06, 0xf1, 0xf9, 0xe2, 0x16, 0xe9, 0xf1, 0x03, 0x0d, + 0x0d, 0xdf, 0xf9, 0x1a, 0x0e, 0xf6, 0xfc, 0x0a, 0x19, 0xe2, 0xe0, 0x09, + 0x15, 0xf0, 0xf1, 0x06, 0xf1, 0xe1, 0xef, 0x1a, 0x08, 0xe8, 0xfd, 0x12, + 0x14, 0x06, 0xf1, 0xfc, 0xea, 0xfb, 0xf7, 0xea, 0x1d, 0x09, 0xfa, 0xf6, + 0x08, 0xf2, 0xe7, 0xf8, 0xfc, 0x16, 0xf5, 0x0e, 0x08, 0xf9, 0x0a, 0x03, + 0x26, 0xd8, 0x02, 0xf5, 0xf6, 0xf6, 0xef, 0x1f, 0xe4, 0xe2, 0xfb, 0x02, + 0x1b, 0xe6, 0xde, 0x00, 0xf2, 0xed, 0xfb, 0x18, 0xe4, 0x16, 0x1a, 0x1d, + 0xf1, 0xf6, 0xea, 0x16, 0x05, 0xde, 0xfb, 0x18, 0xf5, 0xe4, 0xfe, 0xe2, + 0x1b, 0x1c, 0x0c, 0xe8, 0x02, 0xee, 0xfb, 0x07, 0x24, 0xf2, 0xe9, 0xfa, + 0x0d, 0x05, 0xf1, 0x03, 0xfe, 0xf6, 0x19, 0x06, 0xff, 0xf9, 0x04, 0xfb, + 0x15, 0xef, 0xf1, 0xf8, 0xe9, 0xe1, 0x10, 0x04, 0xfc, 0xe6, 0x1f, 0xed, + 0x0b, 0xef, 0x00, 0x1e, 0xe6, 0x16, 0xf3, 0x09, 0xfd, 0x08, 0x08, 0x06, + 0x06, 0x23, 0xdf, 0xfc, 0x08, 0xf4, 0xea, 0x0c, 0xf2, 0xe6, 0x18, 0xf5, + 0x02, 0xf9, 0x50, 0x09, 0x01, 0xda, 0x0b, 0x05, 0x12, 0x18, 0xef, 0x04, + 0x0e, 0xd9, 0xff, 0xdc, 0xf6, 0x16, 0xf9, 0xf4, 0xec, 0xff, 0xea, 0xe6, + 0xfa, 0x0a, 0xed, 0xef, 0x02, 0xf0, 0x25, 0x21, 0xf1, 0x26, 0xf5, 0xed, + 0x09, 0xea, 0xea, 0x24, 0xfa, 0x11, 0xfc, 0xdf, 0xf3, 0x0a, 0x28, 0x0c, + 0x19, 0xff, 0xf5, 0xd6, 0x0e, 0xe2, 0x2a, 0x06, 0xfa, 0x03, 0xf9, 0xe6, + 0xef, 0x23, 0xf9, 0xfa, 0xe6, 0xfe, 0xfc, 0x03, 0x06, 0x1a, 0xf9, 0x08, + 0xe0, 0xe5, 0xff, 0x05, 0x01, 0xe7, 0x12, 0x02, 0x1d, 0x05, 0x03, 0x05, + 0x0b, 0xee, 0xed, 0xfc, 0x0f, 0xf3, 0x02, 0xe0, 0x15, 0xdf, 0x02, 0xed, + 0x10, 0x26, 0xef, 0x0d, 0x06, 0xee, 0xef, 0xf6, 0xeb, 0x11, 0x09, 0xf4, + 0xf7, 0x06, 0x0f, 0x01, 0x2a, 0x0b, 0x01, 0xdd, 0xfc, 0xf4, 0xf1, 0x17, + 0x03, 0x04, 0x07, 0xfc, 0x22, 0xfc, 0xde, 0xfe, 0x0b, 0x03, 0xf3, 0xfb, + 0x0c, 0x25, 0x04, 0x19, 0x04, 0x03, 0x01, 0xfa, 0xfb, 0xf7, 0xf6, 0x0e, + 0x15, 0x0e, 0x09, 0xff, 0x06, 0xfa, 0xfb, 0x1e, 0xfb, 0x05, 0x22, 0xf9, + 0xfe, 0xf7, 0x1d, 0xed, 0xdf, 0x18, 0x09, 0xeb, 0xef, 0x04, 0x12, 0xea, + 0xdf, 0xfb, 0xda, 0xf6, 0xdf, 0x17, 0xef, 0xef, 0xe1, 0x1a, 0xd9, 0xe2, + 0xe2, 0xfc, 0x05, 0x11, 0xf6, 0xee, 0xe8, 0xf2, 0xe1, 0x08, 0x26, 0x04, + 0xed, 0x03, 0xe0, 0xfb, 0xee, 0x0c, 0xee, 0xf6, 0x04, 0x2d, 0xf2, 0xd3, + 0xf4, 0xe0, 0xf8, 0x0c, 0xfe, 0x11, 0x0b, 0xd7, 0xfd, 0x18, 0x07, 0x0d, + 0x07, 0x08, 0xf4, 0xc6, 0x0a, 0x0a, 0x1f, 0x0c, 0xf4, 0x1d, 0x02, 0x0b, + 0x09, 0x0e, 0x21, 0xff, 0x17, 0x0b, 0x0d, 0xf2, 0xed, 0xd7, 0x0a, 0xf8, + 0x03, 0x06, 0xfa, 0xe5, 0xfd, 0x03, 0x14, 0x0f, 0xe9, 0x1a, 0xf4, 0xda, + 0x01, 0xe6, 0x09, 0x06, 0x11, 0x0d, 0xfd, 0xeb, 0x16, 0x23, 0xfa, 0x00, + 0x0b, 0x17, 0xf7, 0xda, 0xd7, 0x1b, 0xfa, 0x01, 0x03, 0x05, 0xfe, 0xd6, + 0x02, 0xee, 0xee, 0x02, 0xf3, 0x06, 0xed, 0x03, 0xec, 0x01, 0xf2, 0x0f, + 0x05, 0x17, 0x0b, 0xfb, 0x0f, 0x05, 0x03, 0x13, 0xff, 0x06, 0x02, 0xf5, + 0xf4, 0x18, 0x2b, 0xf0, 0x00, 0x17, 0xfc, 0xfd, 0x05, 0x0b, 0x0e, 0x14, + 0xe1, 0x24, 0x08, 0x24, 0xe6, 0xeb, 0x21, 0x12, 0xfb, 0x12, 0xe7, 0xf4, + 0xe8, 0x0e, 0x18, 0xee, 0xf5, 0xf3, 0xd9, 0xf3, 0xdb, 0xec, 0x0c, 0x1e, + 0xcf, 0x14, 0xdb, 0xe3, 0xdc, 0x02, 0x0c, 0xfb, 0xdb, 0x1b, 0xd0, 0xfe, + 0xf9, 0xfe, 0x2a, 0xf5, 0x00, 0x0b, 0xcd, 0xe0, 0xe2, 0x0e, 0x04, 0xf8, + 0xda, 0x1c, 0xe5, 0x0f, 0xe8, 0xf4, 0xf7, 0x15, 0x06, 0xf8, 0x02, 0xf7, + 0x0f, 0xfb, 0x17, 0xf9, 0xda, 0x01, 0xda, 0xd1, 0xf6, 0x02, 0xfd, 0x16, + 0xf1, 0xe4, 0xfa, 0x07, 0xee, 0x0a, 0xf3, 0xfd, 0xf2, 0x23, 0xf0, 0xe1, + 0x0a, 0x1a, 0x12, 0x1f, 0xef, 0x27, 0x09, 0xf1, 0x0c, 0x13, 0x23, 0xfd, + 0xf5, 0x03, 0xfe, 0x09, 0xfd, 0x16, 0xf8, 0x07, 0x08, 0x25, 0x08, 0xf8, + 0xf6, 0x0a, 0xf1, 0xf5, 0x07, 0x09, 0x05, 0xcc, 0xf8, 0x08, 0x13, 0xf9, + 0x1d, 0x11, 0x0f, 0xdc, 0xee, 0xf3, 0x27, 0xf9, 0xf9, 0x22, 0xfa, 0x0d, + 0xe2, 0x13, 0xfb, 0x11, 0x03, 0x1e, 0xff, 0xfb, 0xed, 0xf1, 0x0e, 0x0b, + 0x0f, 0x00, 0x06, 0xe0, 0x15, 0xf3, 0x13, 0xfc, 0x18, 0xf9, 0xff, 0x09, + 0xfa, 0x1f, 0x12, 0xe5, 0xe2, 0x06, 0xf9, 0xf4, 0x07, 0x15, 0x0b, 0x04, + 0xdb, 0x0d, 0xeb, 0xf3, 0xe6, 0x06, 0xe5, 0xee, 0xd8, 0x22, 0xd8, 0x10, + 0xea, 0xf9, 0x1c, 0xf7, 0xd3, 0x11, 0xc3, 0xf8, 0xde, 0x05, 0x00, 0xe6, + 0x07, 0xfd, 0xd3, 0x03, 0xea, 0xe0, 0x13, 0x14, 0xcf, 0xeb, 0xcd, 0xd3, + 0xde, 0xf5, 0xf0, 0x0c, 0x0c, 0xfa, 0xeb, 0xd3, 0xfb, 0xfd, 0x08, 0xf9, + 0xf4, 0x10, 0xfa, 0xd3, 0xf4, 0x11, 0x11, 0xf8, 0xef, 0xf8, 0xf8, 0xf1, + 0xfc, 0xe1, 0xf7, 0x12, 0x04, 0xf4, 0xfb, 0xed, 0xef, 0x0c, 0xfd, 0x1c, + 0xfe, 0x0e, 0xfd, 0xe2, 0xfe, 0x0a, 0x02, 0xfe, 0xe6, 0x1f, 0xef, 0xe5, + 0xe6, 0xf8, 0x16, 0x27, 0xe8, 0x20, 0x05, 0xe3, 0xf1, 0xef, 0xee, 0xed, + 0x0d, 0x11, 0x16, 0xfb, 0xf3, 0xff, 0x14, 0x01, 0xff, 0x15, 0x10, 0x02, + 0xe5, 0x28, 0x29, 0x13, 0x13, 0x16, 0xe6, 0x00, 0xd2, 0x26, 0xfd, 0x03, + 0x04, 0x05, 0x07, 0x06, 0xf1, 0x0e, 0x05, 0x0d, 0xe2, 0x0f, 0x02, 0xe1, + 0x07, 0xf7, 0x1c, 0xfa, 0x14, 0x30, 0xf7, 0xee, 0x00, 0xfa, 0x3d, 0x06, + 0x1c, 0x04, 0x06, 0x07, 0x05, 0x1a, 0x10, 0xf6, 0xee, 0x0a, 0xeb, 0x04, + 0xeb, 0xdf, 0x1d, 0x09, 0xd5, 0xe8, 0xd6, 0xf4, 0xf0, 0x0f, 0x1d, 0xea, + 0xf2, 0xf8, 0xa6, 0x0b, 0xdc, 0x09, 0x08, 0x24, 0xee, 0x24, 0xaa, 0xe4, + 0xcb, 0x15, 0xef, 0xe7, 0xe9, 0x0c, 0xcf, 0x06, 0xe3, 0x12, 0x11, 0x00, + 0x07, 0x14, 0xd7, 0xde, 0xf6, 0x0f, 0x0b, 0x04, 0xfb, 0x0d, 0xf8, 0x0d, + 0xf6, 0x1b, 0xf1, 0x21, 0xdd, 0xfc, 0xf4, 0xe9, 0xf8, 0xe8, 0xf7, 0x06, + 0x03, 0x1e, 0xce, 0xe1, 0xea, 0xf6, 0x05, 0xf9, 0x16, 0x15, 0x04, 0xe0, + 0x14, 0xf7, 0x1e, 0x1c, 0x0a, 0x27, 0xef, 0xf3, 0x0f, 0xf3, 0xee, 0x04, + 0xf8, 0xf1, 0x07, 0xe3, 0x05, 0x0b, 0x00, 0x1c, 0x15, 0x27, 0x07, 0xf7, + 0xfa, 0x0b, 0xfa, 0xfa, 0x17, 0x13, 0xe1, 0xf5, 0xfb, 0x0c, 0x21, 0x2f, + 0xd7, 0xfb, 0xf5, 0xfd, 0xd3, 0xf4, 0x07, 0x0e, 0xfd, 0x0b, 0xfc, 0xfa, + 0xf5, 0x0e, 0x02, 0xfa, 0xfa, 0x19, 0xfd, 0xfa, 0xfc, 0x13, 0x24, 0x0c, + 0xe4, 0x31, 0xf8, 0x12, 0xf4, 0x04, 0x18, 0x29, 0x27, 0x19, 0xfc, 0x08, + 0x11, 0xe3, 0x07, 0xfe, 0x26, 0x40, 0x05, 0x02, 0x04, 0x02, 0x0f, 0xee, + 0xf4, 0x27, 0xea, 0xf4, 0xf5, 0x11, 0x26, 0x0b, 0xe7, 0x05, 0xd2, 0xf6, + 0xea, 0xfa, 0x0b, 0xf9, 0xfa, 0x16, 0xba, 0x00, 0xfb, 0x0d, 0x0b, 0xf9, + 0xe6, 0xf6, 0xc5, 0xf8, 0xf6, 0x01, 0x0f, 0xed, 0xed, 0x13, 0xcd, 0x0d, + 0xda, 0x06, 0x17, 0xee, 0x07, 0x1d, 0xb8, 0xfa, 0xe2, 0xea, 0xf2, 0xee, + 0x04, 0x00, 0xdc, 0xd0, 0xfb, 0xf5, 0xec, 0xfe, 0xf1, 0x0d, 0xf0, 0xdb, + 0xf9, 0x0d, 0x03, 0x03, 0x0e, 0x0a, 0xda, 0xd6, 0x01, 0xf2, 0x06, 0x14, + 0x1c, 0x1f, 0xe8, 0xe8, 0x0e, 0xfd, 0x0c, 0xf5, 0xf3, 0x3d, 0xf3, 0x05, + 0x10, 0xfa, 0x1b, 0x18, 0x08, 0x36, 0x09, 0xf1, 0xeb, 0xf9, 0x22, 0x01, + 0xf3, 0xf7, 0xff, 0xf0, 0x0c, 0xe9, 0x01, 0x29, 0x21, 0x15, 0x03, 0xee, + 0xe9, 0x1a, 0xf7, 0x15, 0x06, 0x25, 0xfa, 0xf0, 0xe4, 0xf1, 0x1f, 0x01, + 0xdc, 0x2d, 0xce, 0xe9, 0xea, 0x0b, 0x06, 0x2c, 0x0a, 0x30, 0xe7, 0x09, + 0xf4, 0xf0, 0x10, 0x29, 0xf9, 0x3d, 0xe7, 0xdc, 0xe4, 0xf7, 0x3b, 0x27, + 0x23, 0x3a, 0x0a, 0x06, 0x0e, 0xfd, 0x2c, 0x07, 0x2b, 0x1c, 0xfa, 0x00, + 0xf9, 0x11, 0xea, 0x14, 0xeb, 0xfc, 0x18, 0x03, 0xf1, 0x16, 0x12, 0x04, + 0xcf, 0x12, 0xdd, 0xe4, 0x0e, 0xf0, 0x09, 0xe8, 0xf3, 0xfb, 0xa8, 0xf9, + 0xee, 0xfb, 0x1e, 0x1d, 0xfd, 0x05, 0xab, 0xe5, 0xff, 0x01, 0xfe, 0x04, + 0xf9, 0x02, 0xb9, 0xdc, 0xdf, 0x05, 0xf1, 0xef, 0xf1, 0x1e, 0xc7, 0xee, + 0xf7, 0x1e, 0x00, 0x00, 0xf8, 0x10, 0xec, 0xe8, 0x04, 0x0f, 0xf6, 0xff, + 0x04, 0x09, 0xe0, 0x0a, 0x0e, 0xe4, 0xf0, 0xf1, 0x16, 0x2b, 0xd3, 0xe1, + 0x0a, 0xef, 0xf9, 0xfe, 0x0b, 0x22, 0xf5, 0x01, 0x0a, 0xf8, 0x02, 0x00, + 0x17, 0x19, 0xf3, 0x05, 0x21, 0xfa, 0xee, 0xee, 0x12, 0xf2, 0xfa, 0xf5, + 0x05, 0x12, 0xee, 0xe4, 0x28, 0xfa, 0xf1, 0x03, 0x15, 0x16, 0x18, 0xfd, + 0x0f, 0x21, 0x04, 0xf4, 0xe5, 0x0c, 0x06, 0x13, 0xde, 0x36, 0xe8, 0xfb, + 0xe7, 0xfd, 0xf6, 0x12, 0x0e, 0x1d, 0xea, 0xf8, 0xd4, 0xe8, 0x19, 0x07, + 0xe5, 0x1c, 0xf7, 0x0c, 0xef, 0x05, 0x0f, 0x09, 0xdd, 0x1a, 0xea, 0xd7, + 0xf9, 0xf9, 0x12, 0x17, 0x2e, 0x10, 0x08, 0xfe, 0x14, 0xf5, 0x1d, 0xfa, + 0x06, 0x33, 0xed, 0xfe, 0xf7, 0x11, 0xf0, 0x15, 0xe2, 0x24, 0xf6, 0x0a, + 0xe2, 0xfc, 0x23, 0x12, 0xdd, 0x11, 0xfd, 0xe5, 0x08, 0xff, 0x15, 0xf6, + 0xf1, 0x1b, 0xae, 0xfe, 0xe6, 0x15, 0x2c, 0x2d, 0x15, 0x15, 0xc5, 0xf8, + 0xea, 0xe7, 0x07, 0x04, 0xfe, 0x28, 0xa1, 0xf2, 0xe1, 0xf9, 0xf8, 0xff, + 0xf4, 0x22, 0xb4, 0xdb, 0x03, 0x20, 0xe6, 0xf3, 0x0e, 0x19, 0xe3, 0x0a, + 0xfa, 0xee, 0xf3, 0xe5, 0xd8, 0xf9, 0xf1, 0xde, 0x06, 0x05, 0xf2, 0xf5, + 0xe7, 0x16, 0xd8, 0xfe, 0x07, 0xea, 0xee, 0x0e, 0xfa, 0xff, 0xdb, 0xe7, + 0x03, 0xed, 0x01, 0xfd, 0x09, 0x1a, 0xfa, 0xe6, 0x05, 0x10, 0xe9, 0x01, + 0x1f, 0x13, 0xf7, 0xf6, 0xfb, 0x13, 0xff, 0xdb, 0xed, 0xfe, 0x0a, 0x10, + 0x09, 0x29, 0xf5, 0x04, 0xf5, 0x26, 0x0d, 0x0c, 0xf9, 0x16, 0xfa, 0x02, + 0xf4, 0x2e, 0xde, 0xf5, 0xe1, 0x1d, 0xfb, 0x02, 0x0b, 0x23, 0x07, 0xea, + 0xd9, 0x0a, 0xf3, 0x0a, 0x0f, 0x1e, 0xe7, 0xf1, 0xd7, 0x0b, 0xf6, 0xff, + 0x0d, 0x24, 0xcc, 0x0a, 0xee, 0xda, 0x14, 0x12, 0x11, 0x29, 0xf4, 0x1a, + 0xef, 0x0b, 0xfa, 0xec, 0x0c, 0x1b, 0xf4, 0xff, 0xf5, 0xef, 0x0f, 0x10, + 0xd4, 0x04, 0xf9, 0xf8, 0xec, 0xf9, 0x21, 0x05, 0xd3, 0x27, 0xf3, 0x17, + 0xff, 0xf6, 0x15, 0xf9, 0xed, 0x0a, 0xac, 0x02, 0xfd, 0xfb, 0x04, 0x29, + 0x06, 0x03, 0xb8, 0xe6, 0xd5, 0x17, 0x09, 0x1b, 0xf6, 0x1b, 0xab, 0xdc, + 0xdf, 0xfd, 0x06, 0x09, 0x09, 0x37, 0xbb, 0xed, 0x19, 0xd7, 0xe2, 0xdd, + 0x05, 0x01, 0xec, 0xfb, 0xe4, 0x0e, 0xeb, 0xf0, 0x03, 0x17, 0x04, 0xeb, + 0x09, 0xee, 0xeb, 0xe7, 0x0c, 0x16, 0xcb, 0x0e, 0x17, 0xd8, 0xe1, 0xf8, + 0x2b, 0x19, 0xde, 0xeb, 0x10, 0xf2, 0xff, 0xf8, 0xee, 0x0e, 0xe7, 0xf0, + 0x15, 0x08, 0xf8, 0xdf, 0x06, 0x0d, 0xf9, 0x14, 0xfa, 0x0b, 0x04, 0xfd, + 0x15, 0x23, 0x20, 0xff, 0xfd, 0x1d, 0x0c, 0xf1, 0xfe, 0x15, 0x0a, 0x02, + 0xed, 0xfe, 0xfb, 0x04, 0xfb, 0x1e, 0xdd, 0x05, 0xe0, 0x16, 0xf9, 0xf6, + 0xfd, 0x32, 0xdc, 0xf2, 0xd3, 0x08, 0xf4, 0xec, 0x17, 0x25, 0xe2, 0xf0, + 0xee, 0xf1, 0x0d, 0xfe, 0x13, 0x2d, 0x01, 0x11, 0xd4, 0xe4, 0x07, 0xfb, + 0x32, 0x11, 0x14, 0x07, 0xd7, 0x02, 0x10, 0xeb, 0x2b, 0x1d, 0x01, 0xfc, + 0xf3, 0xf0, 0x13, 0x1a, 0xdb, 0x20, 0x00, 0xf0, 0xf0, 0x05, 0x16, 0x03, + 0xd4, 0xe3, 0xc2, 0xf0, 0x06, 0x02, 0x1e, 0x0a, 0xec, 0x1f, 0xab, 0xea, + 0xfa, 0xe3, 0x20, 0x22, 0x03, 0x1b, 0xb3, 0x0e, 0xe3, 0xf3, 0x1d, 0x27, + 0xe3, 0x10, 0xa7, 0xda, 0xf3, 0x00, 0x0a, 0x0a, 0x04, 0xfb, 0xb2, 0x0f, + 0x0c, 0xf5, 0x07, 0xff, 0x13, 0x1e, 0xdb, 0xf6, 0xf9, 0xef, 0xe8, 0xe7, + 0xfb, 0x18, 0xeb, 0xec, 0x09, 0xda, 0xf1, 0xf0, 0x0b, 0x04, 0xe1, 0xfa, + 0x1c, 0x25, 0xee, 0x01, 0x0b, 0x29, 0xd7, 0x0c, 0x04, 0x0b, 0xef, 0xfd, + 0x1c, 0xfc, 0xf1, 0xfb, 0x0b, 0x0f, 0xdf, 0xed, 0x17, 0x38, 0x0c, 0xd7, + 0xff, 0xfd, 0x01, 0xfc, 0xfb, 0xfb, 0x18, 0x1a, 0x18, 0xe3, 0xf9, 0xf4, + 0xfa, 0x20, 0x06, 0x09, 0x11, 0x08, 0x1d, 0xf8, 0xfa, 0x1d, 0xf5, 0x1c, + 0xf5, 0xfe, 0x03, 0x07, 0xe4, 0x33, 0xc8, 0x0c, 0xe1, 0x13, 0xff, 0xe5, + 0x10, 0x2c, 0xd3, 0xf0, 0xed, 0x04, 0x07, 0x01, 0xf1, 0x16, 0xe0, 0x13, + 0xfa, 0x11, 0x07, 0xfa, 0x19, 0x16, 0x01, 0x00, 0x07, 0x26, 0x00, 0xec, + 0x1d, 0x23, 0x05, 0xf4, 0x07, 0x17, 0x2c, 0x1d, 0xee, 0xf0, 0x0c, 0x09, + 0xe3, 0x1a, 0x24, 0x0b, 0xf3, 0x1e, 0xce, 0xfe, 0xfe, 0x12, 0x21, 0x1a, + 0xf6, 0x23, 0xc3, 0x03, 0xf4, 0x10, 0x1a, 0x2a, 0xf4, 0x08, 0xbf, 0xff, + 0x04, 0xf4, 0x0b, 0x1d, 0x1a, 0xf8, 0xcc, 0x00, 0xf7, 0x13, 0xf4, 0xfd, + 0xf4, 0x19, 0xbd, 0xef, 0x0c, 0x0d, 0x02, 0xfc, 0x12, 0x13, 0xe9, 0xe7, + 0xf5, 0xfa, 0xfa, 0xf6, 0x1a, 0x2e, 0xce, 0xd4, 0x01, 0x12, 0xfd, 0xfc, + 0x26, 0x10, 0xcc, 0xe7, 0xee, 0x13, 0xee, 0xff, 0xef, 0xea, 0x00, 0x0e, + 0x1a, 0x17, 0x04, 0x0c, 0x04, 0x0c, 0xe6, 0xf3, 0xf6, 0xdb, 0xdd, 0x04, + 0xf4, 0x22, 0x11, 0x16, 0xf3, 0x07, 0xec, 0xf8, 0xf2, 0x07, 0x03, 0x02, + 0xf5, 0x0a, 0xf6, 0x02, 0x1d, 0x1b, 0x11, 0x06, 0xf8, 0x06, 0x02, 0xea, + 0xf3, 0x1d, 0xce, 0x00, 0xed, 0xf9, 0xef, 0xf6, 0xec, 0x22, 0xc7, 0xf0, + 0xed, 0xdb, 0xe0, 0x02, 0x11, 0x07, 0xe8, 0xf0, 0xd1, 0xed, 0xff, 0xfd, + 0x0c, 0x2e, 0xd4, 0xed, 0xec, 0x0e, 0xf1, 0x07, 0x01, 0x0e, 0x0e, 0xfe, + 0xda, 0x0b, 0x0a, 0x0a, 0x1f, 0x2e, 0x13, 0x07, 0x00, 0x07, 0x14, 0x21, + 0xe9, 0xfc, 0xf0, 0x1e, 0xd7, 0xea, 0x34, 0x07, 0xc6, 0x0c, 0xd4, 0xec, + 0xfd, 0x06, 0x24, 0x0a, 0xf3, 0x15, 0xaf, 0xff, 0xe9, 0xf1, 0x0d, 0x3e, + 0xe9, 0x18, 0xba, 0x13, 0xed, 0xd7, 0x0b, 0x31, 0x05, 0x0e, 0xaf, 0x13, + 0xd6, 0x0e, 0x10, 0x02, 0x02, 0x14, 0xcb, 0xd5, 0xf9, 0x0c, 0xf9, 0x0e, + 0x1f, 0x24, 0xd5, 0xeb, 0xff, 0xf1, 0xf5, 0x0c, 0x08, 0x07, 0xf4, 0xd7, + 0x06, 0x10, 0xe8, 0xef, 0xfc, 0x2f, 0xee, 0xf1, 0x18, 0xf8, 0xf4, 0x02, + 0x11, 0x21, 0xd3, 0x12, 0x14, 0xe4, 0xf4, 0x02, 0x05, 0x24, 0xca, 0xf2, + 0xf3, 0xeb, 0xe7, 0xf8, 0x16, 0x1a, 0xeb, 0x0d, 0x05, 0x16, 0xf1, 0xec, + 0x11, 0x1c, 0x09, 0x1e, 0xe0, 0xe6, 0xfa, 0x0e, 0x0d, 0x2a, 0xea, 0x2e, + 0xed, 0xf9, 0xf7, 0x16, 0x09, 0x05, 0xdd, 0xd6, 0x02, 0xeb, 0xf5, 0xf3, + 0xe4, 0x3b, 0xed, 0x04, 0xe0, 0x0e, 0xfd, 0x09, 0xfd, 0x35, 0xdc, 0x18, + 0xf3, 0x04, 0xfa, 0x05, 0x15, 0x34, 0xe5, 0xe1, 0xe4, 0xf4, 0xe0, 0xf9, + 0x08, 0x32, 0x04, 0x08, 0xf4, 0x0f, 0xff, 0x08, 0x09, 0x2f, 0x06, 0x02, + 0xfd, 0x05, 0x0c, 0x24, 0xe3, 0x1e, 0xf5, 0x0c, 0xdd, 0xf8, 0x18, 0x20, + 0xd8, 0x14, 0xef, 0xf4, 0x17, 0x08, 0x25, 0x14, 0x04, 0x06, 0xb0, 0xf5, + 0xf5, 0x09, 0x0f, 0x3e, 0xff, 0x28, 0xb3, 0xf5, 0x19, 0xd8, 0x14, 0x21, + 0xd9, 0xf7, 0xb7, 0xe5, 0xfe, 0xe7, 0x07, 0x1e, 0x04, 0x15, 0xc5, 0xf9, + 0x14, 0x20, 0xeb, 0x01, 0x01, 0x18, 0xce, 0x00, 0xe6, 0xe2, 0xf7, 0xfb, + 0xf3, 0x0d, 0xd3, 0xf3, 0x04, 0xf8, 0xf0, 0x03, 0xf1, 0x25, 0xb5, 0xef, + 0x05, 0xe0, 0x01, 0xf6, 0x04, 0x16, 0xd1, 0x01, 0x0a, 0x21, 0x01, 0x05, + 0x0e, 0x01, 0xf0, 0x0a, 0xf3, 0x00, 0x03, 0xf8, 0xfa, 0x03, 0x0b, 0xde, + 0xfe, 0xff, 0xfb, 0xea, 0x09, 0x02, 0xf5, 0xe8, 0xe7, 0x08, 0x00, 0xf5, + 0xf8, 0x0f, 0x13, 0xfa, 0xeb, 0xe8, 0xfb, 0x1f, 0x08, 0x16, 0xe6, 0xfa, + 0xe1, 0x00, 0x03, 0xdd, 0xf1, 0x26, 0xe5, 0x1d, 0xd9, 0xff, 0xf2, 0xf8, + 0xff, 0x33, 0xea, 0xe5, 0x03, 0x0c, 0x07, 0xf9, 0xf8, 0x0f, 0xe1, 0x1e, + 0xdd, 0x0f, 0x00, 0xf1, 0x06, 0x21, 0x09, 0x05, 0xf3, 0xec, 0xe6, 0x04, + 0x07, 0x32, 0xf1, 0xf9, 0xf2, 0x01, 0x18, 0x1f, 0xd2, 0xe2, 0x0a, 0xf4, + 0xca, 0xfc, 0x28, 0x16, 0xc2, 0x10, 0xf2, 0xfc, 0x08, 0xe9, 0x2a, 0x0f, + 0xfa, 0xf5, 0xa9, 0x07, 0xec, 0xe9, 0x19, 0x43, 0x0b, 0x1c, 0xa6, 0xe9, + 0xf4, 0x16, 0x0d, 0x2b, 0xfc, 0x11, 0x9a, 0xe1, 0xf1, 0x1c, 0xf5, 0x0f, + 0xe4, 0x18, 0xc0, 0xd9, 0x14, 0x26, 0xe6, 0xf8, 0x0a, 0x17, 0xec, 0xfb, + 0xe1, 0x22, 0xdf, 0xf2, 0xfe, 0x1e, 0xd4, 0xeb, 0xd7, 0x0e, 0x08, 0xf6, + 0xef, 0xfc, 0xe6, 0xd4, 0xf7, 0x0b, 0xfb, 0xf5, 0x01, 0x25, 0xd7, 0xfb, + 0x0d, 0xfe, 0xff, 0xf3, 0x1d, 0x32, 0xfe, 0xee, 0x12, 0xf2, 0x0c, 0xec, + 0x02, 0x10, 0xef, 0x01, 0xf2, 0x0b, 0xf3, 0xf7, 0xfa, 0x25, 0xfb, 0x0d, + 0x11, 0x15, 0x04, 0xfc, 0x0c, 0x21, 0x12, 0x29, 0x00, 0xfa, 0xf6, 0xf5, + 0x06, 0x22, 0xea, 0xe2, 0xee, 0x00, 0xfd, 0xf0, 0x0b, 0x1d, 0xd3, 0xe4, + 0xe4, 0x0a, 0xfc, 0xe8, 0xea, 0x2c, 0xed, 0xed, 0xef, 0xe8, 0xf2, 0x05, + 0xfd, 0x15, 0xd8, 0xda, 0xca, 0xee, 0xfa, 0x00, 0xfe, 0x0e, 0xf2, 0xf0, + 0x0e, 0xf5, 0x04, 0x03, 0x1d, 0x2b, 0xee, 0x05, 0x0f, 0x10, 0x13, 0x35, + 0xe2, 0x04, 0x10, 0xdf, 0xcf, 0xeb, 0x40, 0x26, 0xe4, 0x03, 0xf3, 0xf9, + 0xf5, 0x14, 0x24, 0x2a, 0xdf, 0xfe, 0xab, 0xe5, 0xfe, 0x1c, 0x27, 0x35, + 0xdb, 0xff, 0xac, 0x01, 0xf6, 0xfc, 0x19, 0x1a, 0x11, 0x1f, 0xa8, 0xf5, + 0x02, 0x0f, 0x1a, 0x1f, 0xf7, 0xf2, 0xa2, 0x00, 0x15, 0x22, 0xe4, 0x13, + 0x00, 0x09, 0xd9, 0xd5, 0x02, 0x19, 0xfd, 0xf8, 0xe7, 0xff, 0xfb, 0xe0, + 0xef, 0xf7, 0xee, 0xf3, 0xf3, 0x19, 0xb0, 0xdf, 0x00, 0x0f, 0x08, 0xf3, + 0x15, 0x17, 0xec, 0x0f, 0x11, 0x14, 0x02, 0x08, 0x10, 0x17, 0xe6, 0x08, + 0xf7, 0x00, 0xed, 0xf7, 0x29, 0x07, 0x10, 0x05, 0x05, 0xe7, 0xed, 0xf4, + 0xf9, 0x15, 0xf9, 0xf0, 0x08, 0x00, 0x03, 0x09, 0x21, 0x28, 0xf6, 0x0e, + 0xfb, 0xf3, 0x03, 0xf7, 0x0f, 0x0c, 0xf0, 0xf5, 0xe3, 0xd8, 0xf8, 0xf2, + 0x09, 0x1c, 0xe7, 0xfb, 0xe4, 0xf6, 0xfa, 0xf8, 0xf1, 0x42, 0xf6, 0xda, + 0xdd, 0xd7, 0xfa, 0xff, 0x2f, 0x2c, 0xda, 0x0a, 0xde, 0xec, 0xf1, 0x14, + 0xfb, 0x1d, 0xeb, 0xee, 0xf2, 0xeb, 0xf3, 0xed, 0x0e, 0x35, 0xf0, 0x06, + 0x19, 0x04, 0x2f, 0x23, 0xe2, 0x07, 0x13, 0x0f, 0xe9, 0xf0, 0x22, 0x2e, + 0xd9, 0x1a, 0xcb, 0xed, 0xfd, 0x04, 0x27, 0x1e, 0xf6, 0x07, 0x96, 0xd6, + 0xd8, 0x11, 0x18, 0x56, 0xd2, 0xfb, 0x92, 0xfc, 0x0b, 0x0a, 0x17, 0x2c, + 0xe5, 0x04, 0xa2, 0xf8, 0xe2, 0x04, 0x1a, 0x0d, 0xeb, 0x11, 0xa2, 0xe5, + 0xe5, 0xf8, 0x02, 0xf7, 0x17, 0x03, 0xca, 0xe9, 0x0c, 0x1f, 0xfe, 0xf5, + 0x18, 0x12, 0xdd, 0x08, 0x15, 0xff, 0xfc, 0xf6, 0xe1, 0x1d, 0xe2, 0xe1, + 0xfe, 0xfc, 0x03, 0xff, 0xf2, 0x23, 0xd2, 0x01, 0x13, 0xdd, 0xf3, 0xf4, + 0xf2, 0x07, 0xef, 0x03, 0x15, 0x21, 0xd8, 0xf8, 0x09, 0xf3, 0xe8, 0xea, + 0xe8, 0xf2, 0x08, 0xf0, 0x04, 0x1a, 0xf2, 0x19, 0xfb, 0x1b, 0x15, 0xfc, + 0x1d, 0x30, 0xe5, 0x1e, 0x09, 0xe8, 0xe9, 0x09, 0xf7, 0x2a, 0xe1, 0x0e, + 0x00, 0x21, 0xf3, 0xff, 0xfb, 0x01, 0xdf, 0xf2, 0xfe, 0xf4, 0xfc, 0xf0, + 0x0b, 0x0b, 0xdd, 0xe4, 0xd2, 0x14, 0xf7, 0xfe, 0x0b, 0x39, 0x01, 0xe6, + 0xe4, 0x27, 0xfa, 0xe4, 0x04, 0x2c, 0xe2, 0x04, 0xf5, 0x07, 0xf2, 0x03, + 0xf0, 0x10, 0xf5, 0xf6, 0xfc, 0x16, 0x22, 0x1b, 0xf8, 0x11, 0xe4, 0x09, + 0xf6, 0xf0, 0x41, 0x1e, 0xcf, 0x04, 0xea, 0xee, 0x0e, 0xf6, 0x1b, 0x2f, + 0xc7, 0xf1, 0xba, 0xef, 0x0f, 0x16, 0x1e, 0x39, 0x05, 0x1e, 0x90, 0xe6, + 0x0d, 0xfa, 0x22, 0x3f, 0xe3, 0x23, 0xa5, 0xe3, 0xe9, 0x0f, 0x05, 0x27, + 0x02, 0x11, 0x99, 0x05, 0xfa, 0x05, 0x03, 0x01, 0xff, 0x26, 0xd3, 0xf7, + 0xf7, 0xf9, 0x05, 0xf4, 0xef, 0x23, 0xd2, 0xdd, 0x05, 0x08, 0xfa, 0xff, + 0x03, 0x04, 0xbd, 0xd7, 0x14, 0x06, 0xef, 0x06, 0xe5, 0x05, 0xea, 0xea, + 0x02, 0xfd, 0x0d, 0x00, 0x08, 0xff, 0xe7, 0xfb, 0xfe, 0x13, 0xfe, 0xec, + 0xf9, 0x02, 0xf3, 0xff, 0xff, 0x08, 0x04, 0xed, 0x19, 0x1d, 0xfa, 0x0a, + 0x0d, 0xf2, 0x0f, 0xec, 0x25, 0x1c, 0xec, 0x0b, 0x01, 0xff, 0x01, 0xf6, + 0x08, 0x09, 0xe8, 0xe2, 0xec, 0x23, 0xe5, 0xe9, 0xf0, 0x2e, 0xbd, 0xe1, + 0xef, 0x14, 0xe9, 0xf6, 0xf5, 0x1d, 0xdc, 0xe3, 0xd7, 0xfc, 0xf9, 0xf2, + 0xfe, 0x24, 0xf2, 0x05, 0xd5, 0xed, 0xe9, 0xf9, 0xfa, 0x2d, 0xf0, 0xfe, + 0xee, 0xf2, 0xe8, 0xf7, 0x06, 0x14, 0x01, 0x10, 0x06, 0xf3, 0x0e, 0x0e, + 0xc2, 0x1d, 0xf2, 0x1c, 0xed, 0xe3, 0x53, 0x21, 0xb8, 0x0c, 0xde, 0x03, + 0x15, 0xeb, 0x46, 0x39, 0xdf, 0xf6, 0xa3, 0xee, 0xf6, 0xe0, 0x33, 0x50, + 0xdd, 0x27, 0x9f, 0x07, 0x13, 0xe2, 0x1f, 0x35, 0xed, 0x1f, 0xb7, 0x07, + 0x11, 0xed, 0x17, 0x28, 0xf4, 0x20, 0xc1, 0xec, 0xef, 0x16, 0x02, 0xfa, + 0xe0, 0x1b, 0xf7, 0xdb, 0xfd, 0x0a, 0xe7, 0xfb, 0xe7, 0x25, 0xe2, 0xe7, + 0xf8, 0xf0, 0xee, 0xe9, 0x02, 0x06, 0xc9, 0xe4, 0x14, 0xe3, 0xe2, 0xf7, + 0xf8, 0xfd, 0xdd, 0xe2, 0x08, 0x0a, 0xe4, 0x05, 0xf5, 0x16, 0xe7, 0x01, + 0x00, 0x1c, 0xe7, 0xf0, 0xf6, 0x19, 0xfe, 0x0c, 0xf2, 0x06, 0x03, 0xe8, + 0x0b, 0xfe, 0xe3, 0x19, 0x08, 0x1a, 0x10, 0xfd, 0x00, 0x21, 0xf0, 0xeb, + 0x18, 0x02, 0xf3, 0x04, 0xf0, 0x18, 0xdb, 0x05, 0x01, 0xde, 0xed, 0xe9, + 0x23, 0x15, 0xaf, 0xe6, 0xf1, 0x0a, 0xe6, 0xea, 0x01, 0x18, 0xd8, 0xfd, + 0xf1, 0xe6, 0xec, 0xf5, 0x0e, 0x1e, 0xcc, 0xfc, 0xe7, 0x00, 0xe9, 0x11, + 0x00, 0x30, 0xf9, 0x14, 0xf4, 0x19, 0xdd, 0xf7, 0xf7, 0x2f, 0xf4, 0xf2, + 0xff, 0x27, 0x15, 0x1c, 0xbc, 0x2f, 0xe9, 0x14, 0xf5, 0xe8, 0x44, 0x30, + 0xe8, 0x1d, 0xe4, 0x18, 0x11, 0x00, 0x0c, 0x2b, 0xf3, 0x29, 0x96, 0xe0, + 0x06, 0xee, 0x3e, 0x55, 0xdc, 0x13, 0x98, 0xdf, 0xf0, 0xfe, 0x17, 0x33, + 0xe8, 0x09, 0xa3, 0x07, 0xef, 0x0e, 0x1d, 0x37, 0xdd, 0xfe, 0xb5, 0x00, + 0xf7, 0xe0, 0xea, 0xfd, 0xfd, 0x19, 0xbc, 0xfd, 0x15, 0xfe, 0x01, 0xf3, + 0xd5, 0x20, 0xbf, 0xe3, 0x15, 0x0e, 0xf0, 0xf6, 0xf2, 0x14, 0xcc, 0xf0, + 0xf7, 0x04, 0xf2, 0xff, 0x0b, 0x02, 0xd2, 0xd8, 0xfa, 0xfc, 0xe5, 0x02, + 0x00, 0xfb, 0xf0, 0xdc, 0x1e, 0x10, 0x02, 0x01, 0x00, 0x18, 0xe9, 0xdb, + 0x1e, 0xf6, 0xfc, 0x03, 0xef, 0x0a, 0x00, 0x16, 0x00, 0x0f, 0xf4, 0x16, + 0xfa, 0x0b, 0xe2, 0xfa, 0xe0, 0x07, 0xfb, 0x02, 0x21, 0x0e, 0xdd, 0x0b, + 0xea, 0xf0, 0xeb, 0xfb, 0x19, 0x09, 0xd4, 0xf2, 0xef, 0x0b, 0x00, 0xeb, + 0x1a, 0x2f, 0xea, 0x06, 0x03, 0xf6, 0xf8, 0xfb, 0xfe, 0x1d, 0xea, 0xdd, + 0xed, 0xfd, 0xfb, 0xe7, 0xfe, 0x18, 0xf4, 0xfc, 0x0b, 0xf6, 0xfc, 0x0b, + 0xfb, 0x28, 0x07, 0xff, 0x07, 0x1e, 0x03, 0x21, 0xcf, 0x22, 0x05, 0xe6, + 0xea, 0xe7, 0x43, 0x2e, 0xe7, 0x14, 0xfb, 0x0a, 0x1e, 0xfe, 0x2c, 0x24, + 0xd5, 0xfd, 0x9e, 0xd1, 0xf2, 0x1c, 0x32, 0x51, 0x01, 0xf3, 0xac, 0xe1, + 0xf4, 0xe5, 0x1c, 0x37, 0xf1, 0x0f, 0xa7, 0xdb, 0x00, 0xf6, 0x0f, 0x18, + 0xe1, 0x10, 0xc9, 0xc5, 0xe8, 0xeb, 0xf2, 0xfd, 0xf6, 0x02, 0xc2, 0xff, + 0x00, 0x19, 0x03, 0x0f, 0x02, 0x22, 0xd4, 0xe7, 0x07, 0x0f, 0xe5, 0x1a, + 0x09, 0x0b, 0xdc, 0xd2, 0x00, 0x05, 0xee, 0xf8, 0xdc, 0x14, 0xd0, 0x0a, + 0x0a, 0xfa, 0xeb, 0x04, 0xf3, 0x06, 0xde, 0x05, 0xfb, 0xfd, 0xe3, 0xec, + 0xfd, 0x14, 0xd7, 0x11, 0x0e, 0xe6, 0x06, 0xec, 0xde, 0x22, 0xd7, 0x00, + 0x03, 0xf5, 0xf5, 0x0d, 0x01, 0x05, 0xea, 0x0b, 0x16, 0x04, 0xff, 0x13, + 0xf3, 0x12, 0xd2, 0xdf, 0x0b, 0xe4, 0x06, 0xf6, 0x08, 0x2d, 0xd3, 0xd6, + 0xe7, 0x0a, 0xec, 0xff, 0xfe, 0x01, 0xdf, 0xf4, 0xdf, 0x1c, 0xfe, 0xf9, + 0xf7, 0x13, 0xca, 0xff, 0x03, 0x06, 0xe9, 0xf7, 0x06, 0x08, 0xd7, 0xf3, + 0xed, 0x08, 0xe3, 0xfd, 0x0c, 0x11, 0x15, 0xfb, 0x15, 0x08, 0x28, 0x40, + 0xe7, 0x0d, 0x08, 0xec, 0xe8, 0x16, 0x67, 0x46, 0xc8, 0x16, 0xf1, 0x02, + 0x24, 0x00, 0x3a, 0x43, 0xd6, 0x12, 0xae, 0xe7, 0xf4, 0xf8, 0x3a, 0x65, + 0xe4, 0x0c, 0xb2, 0xef, 0x1f, 0xe8, 0x29, 0x59, 0xf8, 0x11, 0xc4, 0xe1, + 0xfe, 0xfa, 0x27, 0x43, 0xc9, 0x1e, 0xbb, 0xfb, 0xf3, 0x13, 0x15, 0x0d, + 0xf1, 0x13, 0xcd, 0xf0, 0x07, 0x19, 0x07, 0x00, 0xd8, 0xeb, 0xbf, 0xf0, + 0xfc, 0xf6, 0xef, 0x16, 0x01, 0x02, 0xc1, 0xdf, 0xfd, 0xe9, 0x06, 0x06, + 0xf1, 0x08, 0xd7, 0xcc, 0xfb, 0x0e, 0xfc, 0x14, 0xf2, 0x1a, 0xe2, 0x0d, + 0xeb, 0x09, 0x07, 0x10, 0xe6, 0x13, 0xeb, 0xf5, 0x15, 0x14, 0xeb, 0xfe, + 0xf9, 0x17, 0xd2, 0xe3, 0x1e, 0xf5, 0x04, 0x0a, 0xf1, 0x0e, 0xde, 0xe7, + 0x01, 0x20, 0x0c, 0xfc, 0xdc, 0xf9, 0xe5, 0xe9, 0xff, 0x1d, 0x0a, 0xfe, + 0xec, 0x25, 0xaf, 0xd2, 0x01, 0x16, 0xfc, 0x17, 0xe8, 0x1e, 0xcd, 0xd9, + 0xe2, 0xf1, 0xeb, 0x08, 0xff, 0x33, 0xe5, 0xfb, 0xeb, 0x04, 0xfe, 0xf7, + 0xfd, 0x1f, 0xee, 0xff, 0xed, 0xf8, 0xe0, 0xff, 0xfd, 0x2b, 0x0a, 0xf5, + 0x15, 0x1d, 0xf3, 0x3f, 0x16, 0xf6, 0xf2, 0xee, 0xf4, 0xef, 0xf0, 0x56, + 0x0a, 0x1a, 0xbc, 0xfc, 0x2f, 0xfb, 0xf0, 0x56, 0x1e, 0x0e, 0xc6, 0xe8, + 0x06, 0x0b, 0x11, 0x62, 0x3e, 0xf9, 0xb8, 0xc9, 0xed, 0xeb, 0x02, 0x63, + 0x2c, 0xfd, 0xc5, 0xe9, 0x00, 0x17, 0x0f, 0x37, 0xfe, 0x20, 0xcc, 0xe0, + 0xe0, 0x0e, 0xe6, 0x20, 0x0a, 0xfd, 0xdf, 0xee, 0x0b, 0x02, 0xee, 0x1f, + 0xfb, 0x06, 0xd2, 0xed, 0xfe, 0xeb, 0xfc, 0x12, 0xfd, 0x14, 0x00, 0xd8, + 0x08, 0xf6, 0xec, 0x17, 0xf9, 0x10, 0x00, 0xd9, 0x18, 0xf1, 0xee, 0x0f, + 0xf4, 0x03, 0xee, 0xeb, 0xf0, 0xef, 0xf2, 0x06, 0x04, 0x00, 0xf4, 0x0f, + 0x09, 0x06, 0xf7, 0x0b, 0xfd, 0x01, 0x03, 0x03, 0xf4, 0xf6, 0xdd, 0x14, + 0x1c, 0xef, 0xf1, 0xdd, 0xf7, 0x13, 0xd9, 0x15, 0xef, 0x02, 0xd2, 0xe7, + 0x05, 0x05, 0xe2, 0x09, 0xf2, 0x11, 0xf5, 0xba, 0xf0, 0x04, 0xe0, 0x01, + 0x06, 0x10, 0xe6, 0xef, 0xfc, 0x12, 0xf9, 0xf4, 0x1b, 0x2f, 0xe3, 0x0f, + 0xd7, 0xf6, 0x0b, 0x11, 0xf7, 0x0c, 0x00, 0x06, 0x18, 0xef, 0x06, 0x03, + 0x0a, 0x09, 0xf6, 0x1a, 0x0d, 0xed, 0xfe, 0x2c, 0x43, 0xf4, 0xe5, 0xde, + 0xf5, 0x02, 0x25, 0x5a, 0x49, 0xd4, 0xe6, 0x24, 0x1e, 0xf7, 0x0e, 0x5c, + 0x5d, 0xf0, 0xf9, 0xe4, 0x1c, 0xeb, 0x28, 0x7f, 0x5b, 0xec, 0xfa, 0xdb, + 0x0c, 0xf5, 0x20, 0x49, 0x51, 0xe1, 0xed, 0xe6, 0x0e, 0x26, 0x28, 0x33, + 0x35, 0x05, 0xe1, 0xe4, 0x1f, 0xfc, 0xf9, 0x39, 0x18, 0x04, 0xed, 0xed, + 0x01, 0xe7, 0xe6, 0x08, 0x09, 0x03, 0xe7, 0xf9, 0x0e, 0x06, 0xec, 0x08, + 0x12, 0x1a, 0xda, 0xef, 0xdf, 0xf9, 0xe2, 0x1e, 0x1c, 0x00, 0x12, 0xd7, + 0x01, 0xf7, 0x21, 0x17, 0x13, 0x19, 0xde, 0xe0, 0xec, 0x16, 0x01, 0x1b, + 0x06, 0x0c, 0xf0, 0xe8, 0x18, 0x03, 0x06, 0x0e, 0x09, 0xfa, 0x03, 0xf3, + 0xdd, 0x01, 0xfb, 0x0a, 0x2a, 0xf4, 0xf6, 0xda, 0xe9, 0xfe, 0xe9, 0x12, + 0x19, 0xe9, 0x05, 0xdf, 0x00, 0xeb, 0xf2, 0x10, 0x0c, 0xe1, 0xcd, 0xcb, + 0xf2, 0x1f, 0xd9, 0x0c, 0xfa, 0xfb, 0xe8, 0xde, 0x00, 0xfc, 0xe5, 0x00, + 0x11, 0x02, 0xe6, 0x17, 0x14, 0x00, 0xf2, 0xfd, 0x00, 0xe1, 0x10, 0x24, + 0x12, 0xec, 0xed, 0x1e, 0x09, 0x18, 0x03, 0x0c, 0x04, 0xf4, 0x15, 0x0f, + 0x10, 0x18, 0xd6, 0x29, 0x10, 0x04, 0x1c, 0xef, 0x0f, 0x0c, 0xc7, 0x04, + 0xfe, 0xeb, 0xff, 0xf5, 0xe3, 0x15, 0xfe, 0xcb, 0x10, 0xff, 0x12, 0xfb, + 0xe4, 0xeb, 0xf9, 0x00, 0x02, 0xf1, 0x14, 0x13, 0x01, 0x02, 0xf9, 0x01, + 0x06, 0x0c, 0xf5, 0x0a, 0x1e, 0x01, 0x19, 0x0e, 0x05, 0xf5, 0x0a, 0xff, + 0xff, 0xf2, 0xfb, 0xdb, 0xf8, 0x06, 0x17, 0xf2, 0xf7, 0x0d, 0x0e, 0xf4, + 0xfa, 0xf7, 0x14, 0xdb, 0xe0, 0xfd, 0x08, 0x16, 0xf7, 0x16, 0xfc, 0x09, + 0x27, 0x07, 0x09, 0xfb, 0x0a, 0xfc, 0x0c, 0xe4, 0xdb, 0xee, 0xff, 0x10, + 0xf3, 0x09, 0xfa, 0xf4, 0x23, 0xf3, 0xf4, 0x19, 0xff, 0xfa, 0xff, 0x19, + 0x0f, 0x11, 0xed, 0xec, 0xf8, 0x0f, 0x10, 0xf3, 0xff, 0x0b, 0xf7, 0x06, + 0x0b, 0x0e, 0x07, 0xe4, 0x18, 0x0a, 0x08, 0x0e, 0x02, 0x0a, 0x05, 0x19, + 0x02, 0xf3, 0xfe, 0xfe, 0x0b, 0x0f, 0xfc, 0xfa, 0x05, 0xf9, 0xe2, 0xf9, + 0x1b, 0xf7, 0x0f, 0x07, 0xfc, 0x12, 0xfe, 0x01, 0xfd, 0xf0, 0x04, 0xf4, + 0xfd, 0x07, 0xf2, 0x04, 0x04, 0x07, 0xef, 0x0c, 0xed, 0x0e, 0xf6, 0xef, + 0x08, 0x07, 0x04, 0xe9, 0xf3, 0x20, 0xda, 0x15, 0xf8, 0xff, 0xec, 0xe0, + 0xf6, 0xff, 0xe9, 0x08, 0x01, 0x10, 0xf0, 0xfc, 0xe9, 0x08, 0xe8, 0xf5, + 0xf8, 0xe5, 0x17, 0xe6, 0x03, 0xfc, 0x09, 0xf5, 0xdd, 0xf2, 0xff, 0x05, + 0xf6, 0xf8, 0xf5, 0x07, 0xfc, 0xf1, 0x04, 0xf3, 0x13, 0xe1, 0x0f, 0xf2, + 0x0a, 0xf9, 0xfd, 0x1c, 0xe0, 0x11, 0x1b, 0xe6, 0xef, 0x05, 0x05, 0x0c, + 0x23, 0x10, 0x09, 0xfe, 0xf7, 0x1a, 0xf1, 0xfc, 0x11, 0x1d, 0xff, 0x03, + 0x03, 0xe6, 0x07, 0x11, 0x0c, 0x0d, 0x16, 0x05, 0x05, 0x25, 0xf3, 0x10, + 0x10, 0x06, 0x09, 0xe8, 0x1a, 0xf0, 0xee, 0x09, 0xff, 0x24, 0xf7, 0xfb, + 0xe6, 0x06, 0xfa, 0x08, 0x03, 0x00, 0xf2, 0x04, 0xf0, 0xeb, 0x14, 0x1c, + 0x03, 0x21, 0x14, 0x1d, 0xfe, 0x03, 0xf6, 0x02, 0x09, 0xff, 0x00, 0x13, + 0xef, 0x10, 0x1e, 0x0b, 0x1d, 0x1c, 0xf1, 0xf6, 0xe7, 0xfd, 0x14, 0x01, + 0xff, 0x13, 0xf7, 0xfc, 0x00, 0x21, 0xe3, 0xeb, 0x07, 0x0e, 0x09, 0xf1, + 0xf8, 0xfd, 0x03, 0xee, 0x19, 0xfd, 0xff, 0xfb, 0xff, 0xea, 0xfb, 0x07, + 0xf0, 0x0a, 0x04, 0x04, 0x0b, 0x12, 0xfe, 0x0b, 0xe0, 0xff, 0xf6, 0xe5, + 0xfc, 0x11, 0xed, 0xfd, 0x15, 0x03, 0xdd, 0xdb, 0x04, 0xfe, 0xff, 0x0e, + 0xff, 0xfa, 0xfb, 0xe5, 0xef, 0xf6, 0xfe, 0x22, 0x0f, 0xe8, 0xfe, 0xf4, + 0xfd, 0xd9, 0x03, 0x0a, 0xdf, 0xcf, 0xf1, 0x14, 0x05, 0xfd, 0xfb, 0xf3, + 0xfb, 0xfb, 0x0f, 0xf8, 0x05, 0x09, 0x03, 0xf7, 0x05, 0x05, 0x13, 0xfb, + 0xeb, 0x23, 0xe7, 0x18, 0xfb, 0x00, 0xfe, 0xdd, 0xe9, 0xea, 0xd3, 0xe8, + 0x1a, 0xef, 0x01, 0xf1, 0x09, 0x1d, 0xd8, 0xfc, 0xda, 0x19, 0x03, 0xec, + 0xe5, 0xf3, 0xed, 0x0a, 0xf4, 0x13, 0x0b, 0xf7, 0x0c, 0x00, 0xf9, 0xea, + 0xe3, 0xfe, 0xff, 0x0d, 0x0a, 0x1b, 0xd7, 0x17, 0xeb, 0xe9, 0x00, 0x0e, + 0xee, 0x24, 0xef, 0x09, 0x07, 0xf0, 0xf5, 0x07, 0xf5, 0xf5, 0x10, 0x17, + 0x06, 0xf7, 0xfc, 0x02, 0xfb, 0xf9, 0xe7, 0x0a, 0x26, 0xf3, 0x01, 0x01, + 0x09, 0x0b, 0x02, 0x27, 0xf8, 0xee, 0xfd, 0x1c, 0xf8, 0xf2, 0x0f, 0xfc, + 0x0d, 0xe0, 0xea, 0x02, 0x0b, 0x00, 0xe0, 0x08, 0xfe, 0x10, 0x04, 0xfe, + 0xeb, 0x13, 0x01, 0x0c, 0x0e, 0xed, 0x09, 0x01, 0x0c, 0xe3, 0x10, 0xdf, + 0xd1, 0x14, 0xf3, 0xef, 0x09, 0xf0, 0xee, 0xe5, 0x11, 0xf4, 0xf6, 0x00, + 0xe8, 0x20, 0x0a, 0xfc, 0xea, 0xf7, 0x02, 0x16, 0xe7, 0xf3, 0x0d, 0xe4, + 0x04, 0xe6, 0xef, 0xf8, 0x0f, 0x23, 0x02, 0xe0, 0x01, 0x01, 0x01, 0x05, + 0xf5, 0x0d, 0xf5, 0xf5, 0xe1, 0xff, 0x04, 0x00, 0xf4, 0x0d, 0xee, 0xf1, + 0xef, 0xf7, 0x0b, 0xff, 0x1b, 0xec, 0x05, 0xe7, 0xf3, 0x13, 0x12, 0xf2, + 0xf3, 0xfc, 0xea, 0x06, 0xfe, 0x13, 0x12, 0xdb, 0x11, 0xe2, 0xfc, 0x0d, + 0x1c, 0xe8, 0x1d, 0xfc, 0xf2, 0xe2, 0x13, 0x1d, 0xda, 0xf6, 0x1c, 0x18, + 0x1e, 0xf4, 0xfa, 0x03, 0xdc, 0x0f, 0xff, 0xff, 0x18, 0x0b, 0xed, 0xf1, + 0xf8, 0x02, 0xf4, 0x10, 0xf9, 0xeb, 0x0b, 0x0e, 0x0f, 0x01, 0x02, 0x1b, + 0x06, 0x10, 0x00, 0xe7, 0x23, 0x0d, 0xf6, 0x11, 0x08, 0xf5, 0x0f, 0x05, + 0x13, 0xf7, 0x01, 0x01, 0x0c, 0xf6, 0xf9, 0xf0, 0x29, 0x01, 0xe9, 0x11, + 0x02, 0xfa, 0xeb, 0x16, 0x0e, 0x10, 0x09, 0x0e, 0x1c, 0x0a, 0xe3, 0xd3, + 0x01, 0xe3, 0x00, 0x06, 0xe2, 0xe9, 0x19, 0xef, 0x12, 0xf3, 0xfc, 0x02, + 0x0b, 0x0c, 0x0d, 0xed, 0xfd, 0xf6, 0xf9, 0xe9, 0xf2, 0x28, 0xfe, 0x03, + 0xec, 0x03, 0x00, 0xf8, 0xde, 0x0d, 0x25, 0x07, 0x1a, 0xe7, 0xfd, 0x29, + 0xd8, 0xf7, 0xfb, 0xde, 0x0c, 0x08, 0x06, 0x22, 0xee, 0x1d, 0x05, 0x07, + 0xf0, 0xfb, 0xfe, 0x07, 0xf1, 0x04, 0xe9, 0x01, 0xfc, 0xf1, 0x00, 0xeb, + 0xe3, 0x08, 0xec, 0xfe, 0x04, 0xeb, 0xfc, 0x01, 0xf6, 0x0e, 0xdf, 0xf8, + 0x12, 0xe3, 0x16, 0xdc, 0x21, 0x0a, 0xe6, 0x06, 0xe5, 0x10, 0x07, 0xf7, + 0x1e, 0xde, 0xe3, 0x07, 0x16, 0xed, 0x23, 0xf2, 0x12, 0x0d, 0xe9, 0xf9, + 0xe8, 0xfe, 0x0e, 0x02, 0x18, 0x0a, 0xea, 0xec, 0xfb, 0xfe, 0x0c, 0x1b, + 0x19, 0x20, 0xfa, 0x07, 0xe5, 0x0c, 0x04, 0x27, 0xdb, 0xe6, 0xfe, 0x0d, + 0x0a, 0x0a, 0xfe, 0x39, 0xdd, 0xde, 0x05, 0xec, 0x09, 0x05, 0x0a, 0x2c, + 0xf4, 0x02, 0x1f, 0xd3, 0x24, 0xee, 0x0f, 0x3c, 0xf5, 0xfd, 0xf8, 0xf8, + 0x12, 0xf5, 0xf3, 0x19, 0xf9, 0xda, 0xf6, 0x0a, 0x0a, 0xf4, 0x09, 0x0f, + 0xfc, 0x00, 0x01, 0x01, 0xf3, 0xf8, 0x05, 0xf3, 0x0c, 0x19, 0x0e, 0xfd, + 0xfa, 0xe1, 0xfc, 0x0c, 0x03, 0xfb, 0x1b, 0x06, 0xcc, 0xe4, 0x08, 0xf9, + 0x10, 0xe9, 0x06, 0x00, 0x17, 0xe8, 0x0d, 0x12, 0xca, 0xf5, 0x23, 0xe4, + 0x21, 0xf6, 0x19, 0x33, 0xdd, 0xfa, 0x0c, 0x01, 0x14, 0x07, 0x00, 0x34, + 0xda, 0x05, 0x07, 0x01, 0x07, 0xe4, 0x06, 0x24, 0x02, 0xff, 0xf0, 0x09, + 0xfc, 0xf4, 0x03, 0x06, 0xee, 0x08, 0xe2, 0x1d, 0xfa, 0x0c, 0xfc, 0x02, + 0x03, 0xe5, 0xf0, 0xe2, 0x0a, 0x18, 0x12, 0x0c, 0x1e, 0x20, 0xed, 0x20, + 0xe4, 0x01, 0x2a, 0x09, 0x0d, 0x0e, 0xd0, 0xf4, 0xdd, 0xfd, 0x2b, 0xf2, + 0x08, 0x0c, 0xf8, 0xf7, 0xfc, 0xf9, 0x15, 0xef, 0x19, 0x1c, 0x01, 0xff, + 0xe2, 0x01, 0xf3, 0x30, 0x0e, 0xfb, 0x15, 0xe8, 0x1c, 0x00, 0xfa, 0x16, + 0xef, 0xea, 0xfb, 0x05, 0xf0, 0x0e, 0x02, 0x13, 0xf4, 0x01, 0x03, 0xe5, + 0x29, 0x07, 0x09, 0x24, 0xf9, 0xe3, 0xf8, 0xde, 0x2d, 0xf4, 0xf5, 0x40, + 0xed, 0xdf, 0x07, 0xef, 0x0f, 0x0a, 0x0b, 0x32, 0x0d, 0xe8, 0x00, 0xe6, + 0xf6, 0xfc, 0xfd, 0x19, 0x11, 0x09, 0xf3, 0x03, 0xea, 0xf1, 0xfb, 0x02, + 0xfd, 0x06, 0xff, 0xfe, 0x09, 0xec, 0x06, 0x0c, 0x15, 0xf9, 0x06, 0xd7, + 0xe3, 0xf7, 0xed, 0x01, 0x03, 0xfd, 0x14, 0x01, 0x0e, 0xe0, 0x37, 0x0d, + 0xd2, 0x18, 0x2f, 0xea, 0x12, 0x0d, 0x05, 0x3a, 0xd5, 0x07, 0x1e, 0xf2, + 0x21, 0x11, 0xf9, 0x36, 0xd3, 0xf5, 0x12, 0xf6, 0xfb, 0xf6, 0x06, 0x0f, + 0xde, 0xf9, 0x06, 0x09, 0xdf, 0xff, 0x0b, 0xf3, 0xf5, 0x01, 0xf1, 0xea, + 0xf2, 0x02, 0x12, 0xfc, 0x0e, 0xee, 0xf8, 0xeb, 0x00, 0xef, 0x21, 0x0f, + 0x09, 0xef, 0xeb, 0x1e, 0xef, 0xf2, 0x26, 0xf9, 0x17, 0xf1, 0xf1, 0xf0, + 0x0c, 0x10, 0x1d, 0xff, 0x1d, 0x06, 0x03, 0xf6, 0xfb, 0x14, 0x1b, 0x03, + 0x22, 0xfd, 0xec, 0x03, 0xfa, 0xf8, 0x01, 0x2b, 0x1e, 0x1b, 0x09, 0x09, + 0x07, 0xff, 0xf0, 0x20, 0xee, 0x14, 0xfb, 0xf6, 0xf8, 0x11, 0xd9, 0x29, + 0xf4, 0xfa, 0x07, 0xef, 0x20, 0xf9, 0xf2, 0x30, 0xee, 0xf0, 0xf3, 0xd6, + 0x0d, 0xfe, 0x03, 0x36, 0xf5, 0xd7, 0x01, 0xe6, 0x04, 0xf0, 0x05, 0x1f, + 0x0f, 0xdd, 0xff, 0xf8, 0x1f, 0xf2, 0x04, 0x37, 0xfa, 0x00, 0xfd, 0xf8, + 0x10, 0xe1, 0xfb, 0x0d, 0xed, 0xf6, 0xe2, 0xfe, 0x08, 0xfe, 0x07, 0x08, + 0x08, 0x11, 0x0a, 0xf0, 0xf8, 0xf5, 0x04, 0xea, 0x08, 0x12, 0x06, 0x0d, + 0x0f, 0x10, 0x40, 0x28, 0xc0, 0xfb, 0x3f, 0x08, 0x1d, 0x09, 0x1b, 0x3d, + 0xee, 0xf4, 0x29, 0x13, 0x20, 0xfc, 0x11, 0x4c, 0xdb, 0x02, 0x15, 0x05, + 0xec, 0xeb, 0x0a, 0x22, 0xe7, 0x00, 0x02, 0x01, 0xd4, 0xea, 0x0a, 0xf3, + 0xe3, 0xf8, 0xf5, 0xfa, 0x01, 0x0d, 0x19, 0x06, 0x24, 0x13, 0x02, 0xf5, + 0xf1, 0xf1, 0x1b, 0x0f, 0x19, 0x04, 0xe3, 0xf9, 0xe7, 0x02, 0x29, 0xfc, + 0x29, 0xec, 0xe9, 0x04, 0xdc, 0x22, 0x1d, 0xfd, 0x1f, 0x01, 0xec, 0xe8, + 0xf5, 0x14, 0x1b, 0x19, 0x06, 0x0e, 0x02, 0x0d, 0xf9, 0x06, 0xfc, 0x15, + 0x07, 0xfa, 0x0c, 0xe1, 0x18, 0x1a, 0xe8, 0x1b, 0xe9, 0xef, 0x0a, 0x18, + 0xfc, 0x05, 0xf9, 0x14, 0xdc, 0x04, 0x01, 0xff, 0x07, 0xfd, 0xf0, 0x2c, + 0xf2, 0xec, 0x0e, 0xe7, 0x1a, 0x05, 0xe8, 0x35, 0x13, 0x09, 0xf9, 0x07, + 0xfe, 0xfa, 0x0d, 0x40, 0x0c, 0xea, 0xf4, 0x04, 0x01, 0x11, 0xfc, 0x23, + 0xeb, 0xf4, 0xe9, 0x04, 0xeb, 0xe7, 0x07, 0x09, 0xfb, 0xf1, 0xf6, 0xfd, + 0x02, 0xfa, 0x02, 0xff, 0x00, 0xff, 0xf1, 0xf1, 0x1a, 0xe9, 0x10, 0xe3, + 0x0b, 0x0c, 0x08, 0x04, 0x1b, 0x0a, 0x2b, 0x10, 0xe1, 0x01, 0x1f, 0x06, + 0x04, 0xec, 0x19, 0x49, 0xee, 0xf8, 0x22, 0x0c, 0x20, 0x02, 0x07, 0x31, + 0xe7, 0xff, 0x0f, 0xf0, 0xfd, 0xea, 0x13, 0x26, 0xce, 0xfa, 0xff, 0xee, + 0xe9, 0xfe, 0x15, 0x08, 0x04, 0x05, 0x0d, 0xfa, 0xdd, 0xf8, 0x07, 0x0b, + 0x33, 0xef, 0xec, 0xf9, 0xd9, 0xe6, 0x1d, 0x10, 0x41, 0xf6, 0xdf, 0x11, + 0xe3, 0x14, 0x1d, 0xfb, 0x2b, 0x15, 0xdc, 0x09, 0xf6, 0x05, 0x16, 0x00, + 0x1c, 0x27, 0xe4, 0xfc, 0xf7, 0x16, 0x08, 0x08, 0x2f, 0xdd, 0xf8, 0xfa, + 0xe9, 0x0e, 0x0b, 0x0b, 0x02, 0x12, 0x02, 0xfd, 0x19, 0x03, 0xeb, 0x11, + 0xf4, 0x09, 0x09, 0x15, 0x12, 0x0d, 0xef, 0x1c, 0xe4, 0xfe, 0x17, 0x0c, + 0x09, 0x04, 0xea, 0x2f, 0xf2, 0x1e, 0x02, 0xfb, 0xfe, 0xe3, 0x00, 0x2e, + 0x04, 0xf9, 0x0c, 0x05, 0x27, 0x0c, 0x07, 0x2d, 0xf7, 0x0b, 0xfb, 0xf9, + 0x1c, 0xdf, 0x11, 0x36, 0x05, 0xf2, 0x02, 0xf8, 0x0b, 0x07, 0x05, 0xfb, + 0xfc, 0x0e, 0x13, 0xfa, 0xfb, 0x09, 0xf5, 0xfd, 0x06, 0x15, 0xf9, 0x03, + 0x18, 0xfd, 0x1a, 0x0a, 0x03, 0xe2, 0xfb, 0x00, 0x1e, 0xfe, 0x4f, 0x27, + 0xe1, 0xf7, 0x31, 0xf0, 0x1b, 0xec, 0x07, 0x5f, 0xe2, 0xf8, 0x40, 0x05, + 0x17, 0x24, 0x0c, 0x3c, 0xf3, 0x10, 0x13, 0xf8, 0x0b, 0xf3, 0xf9, 0x36, + 0xe1, 0xf3, 0xf4, 0xe8, 0xef, 0xf8, 0xfc, 0xeb, 0xe3, 0xfb, 0xf0, 0xee, + 0xdb, 0x06, 0x0c, 0x11, 0x1e, 0x10, 0xe2, 0xe9, 0xeb, 0x0d, 0x34, 0x0f, + 0x43, 0xd9, 0xef, 0x08, 0xec, 0x05, 0x1d, 0x02, 0x33, 0xef, 0xf4, 0xf7, + 0xe6, 0xf9, 0x22, 0x07, 0x04, 0x06, 0xe9, 0x02, 0xf0, 0xfc, 0x24, 0x20, + 0x24, 0x17, 0xe6, 0x0f, 0x05, 0xf6, 0xfc, 0x1f, 0xf2, 0x01, 0x0d, 0xe7, + 0xff, 0x1d, 0xf0, 0xfa, 0xd0, 0x00, 0xff, 0x0e, 0x23, 0xf9, 0xf3, 0x11, + 0xde, 0x0d, 0x05, 0x04, 0x0b, 0x0b, 0xfb, 0x26, 0x0d, 0x0d, 0xff, 0xe8, + 0x16, 0xe8, 0x0b, 0x3c, 0x18, 0xe4, 0x04, 0xff, 0xfa, 0xf3, 0xff, 0x40, + 0xee, 0x06, 0xfc, 0x0d, 0x00, 0xf7, 0x13, 0x3f, 0xf7, 0x13, 0x06, 0x08, + 0xf9, 0x13, 0xf2, 0x19, 0xfd, 0xf9, 0xf3, 0xe6, 0xfc, 0x07, 0xf6, 0xfd, + 0x0a, 0x22, 0x00, 0x01, 0x19, 0xff, 0xe7, 0xff, 0x08, 0xfd, 0x03, 0xfd, + 0x1f, 0xe7, 0x28, 0x08, 0xde, 0xf3, 0x43, 0xf6, 0x0c, 0xfe, 0x1e, 0x52, + 0xf2, 0x04, 0x17, 0xf2, 0x08, 0x0d, 0x04, 0x38, 0xde, 0x0c, 0x10, 0xef, + 0xdf, 0x0f, 0x01, 0x24, 0xde, 0xe1, 0x0d, 0xfd, 0xd4, 0xf6, 0x12, 0x0e, + 0xed, 0x01, 0xf0, 0xf3, 0xfd, 0xff, 0x18, 0xf3, 0x36, 0xda, 0xf6, 0xef, + 0xe8, 0xef, 0x37, 0x27, 0x4e, 0xf8, 0xf4, 0xff, 0xe5, 0xf3, 0x32, 0x0b, + 0x36, 0x08, 0xe9, 0xf6, 0xe2, 0x13, 0x21, 0xfe, 0x12, 0xed, 0xdd, 0xfb, + 0xf8, 0x05, 0x0f, 0x03, 0x1c, 0x04, 0xfc, 0xf2, 0x23, 0x0e, 0x03, 0xfc, + 0xf9, 0x18, 0xf7, 0x01, 0x1b, 0x03, 0xf5, 0xfd, 0xde, 0xf3, 0x19, 0xfc, + 0x11, 0x02, 0xe7, 0x13, 0xde, 0xd8, 0xf2, 0x05, 0x28, 0x02, 0x02, 0x27, + 0x07, 0x08, 0xff, 0x07, 0x27, 0x0e, 0x19, 0x40, 0xfb, 0x02, 0x0c, 0xf6, + 0x0d, 0x07, 0x0f, 0x47, 0xf8, 0x05, 0x0e, 0xfd, 0x03, 0x1e, 0x07, 0x32, + 0xe7, 0xf6, 0x24, 0x01, 0x01, 0x02, 0x0a, 0xff, 0xf6, 0x26, 0x15, 0xf0, + 0x04, 0x13, 0x03, 0xfa, 0xfe, 0xf6, 0xf1, 0x09, 0x2a, 0xe6, 0xea, 0xf6, + 0x17, 0x13, 0xeb, 0xff, 0x15, 0xeb, 0x23, 0x06, 0xc8, 0xf6, 0x33, 0xeb, + 0xf4, 0xe7, 0x12, 0x2a, 0xe3, 0xe6, 0x32, 0xfa, 0x16, 0x15, 0x17, 0x40, + 0xf1, 0x08, 0x1a, 0xf3, 0xf6, 0x0c, 0x0c, 0x11, 0xd0, 0x22, 0x02, 0xee, + 0xea, 0xf4, 0xf8, 0xf9, 0x13, 0x10, 0x17, 0xf5, 0xf1, 0x0a, 0x0e, 0xfd, + 0x32, 0xda, 0xf1, 0xe2, 0xdb, 0xf2, 0x34, 0x1f, 0x53, 0xfc, 0xe4, 0xf2, + 0xf6, 0xf2, 0x1d, 0x04, 0x4a, 0xec, 0xee, 0x06, 0xdf, 0x01, 0x1a, 0x04, + 0x27, 0xfc, 0xe6, 0xfd, 0xd9, 0xfd, 0x0e, 0x00, 0x0c, 0x16, 0xf3, 0x03, + 0xf7, 0xfc, 0x0e, 0x0f, 0x09, 0x06, 0x06, 0x04, 0x08, 0x02, 0xed, 0xf5, + 0xe4, 0xe6, 0x07, 0x06, 0x03, 0x18, 0xea, 0x13, 0xe2, 0xfa, 0x10, 0xf2, + 0x02, 0xec, 0x03, 0x3c, 0xf6, 0xf6, 0x0a, 0x10, 0x09, 0xf8, 0x15, 0x24, + 0xfd, 0x0d, 0x09, 0x01, 0x00, 0xff, 0x00, 0x1a, 0xf0, 0xee, 0x08, 0x03, + 0x1d, 0x05, 0x16, 0x46, 0xe6, 0xf8, 0x08, 0x00, 0x09, 0x09, 0xff, 0x01, + 0xfc, 0x20, 0xfc, 0xec, 0x05, 0x1b, 0x03, 0xf1, 0x12, 0xe4, 0xfa, 0x24, + 0x1c, 0xf5, 0xf2, 0x05, 0x11, 0xe7, 0xfa, 0x02, 0x20, 0xea, 0x31, 0x10, + 0xcf, 0xd8, 0x33, 0xee, 0xff, 0x09, 0x20, 0x3f, 0xe2, 0x0a, 0x29, 0xee, + 0x3a, 0xf2, 0x1e, 0x39, 0x02, 0x1e, 0xfe, 0xf2, 0xef, 0xe2, 0x0d, 0x0f, + 0xf1, 0x19, 0x02, 0xe7, 0xec, 0xff, 0xfe, 0xe4, 0xfe, 0xfb, 0x02, 0xf6, + 0xf1, 0xf4, 0x07, 0x1a, 0x2a, 0xf9, 0x06, 0xf9, 0xda, 0xf4, 0x22, 0x02, + 0x4f, 0x0a, 0xf3, 0xfc, 0xf3, 0xf6, 0x25, 0x0a, 0x28, 0x01, 0xf7, 0x09, + 0xe6, 0x05, 0x28, 0xf7, 0x1e, 0xf2, 0xee, 0x13, 0xee, 0x05, 0x0f, 0x0a, + 0x09, 0xe8, 0xe8, 0x0e, 0x05, 0x12, 0x0f, 0x15, 0x02, 0xec, 0xf8, 0x02, + 0xf7, 0x05, 0xf8, 0xff, 0xdc, 0x00, 0x01, 0x00, 0x12, 0x17, 0xec, 0x19, + 0xfa, 0x09, 0xfa, 0xf3, 0x1d, 0x0b, 0x07, 0x25, 0xea, 0x0c, 0xf5, 0xfa, + 0x04, 0xf7, 0xfe, 0x33, 0xfe, 0x14, 0xef, 0x04, 0xf0, 0x00, 0x00, 0x3a, + 0xea, 0xfa, 0x10, 0x01, 0xe4, 0x00, 0xff, 0x23, 0xe9, 0x26, 0x15, 0x10, + 0x04, 0x14, 0x0d, 0x08, 0xf8, 0xfd, 0x10, 0xfb, 0x00, 0x21, 0x06, 0xfa, + 0x0f, 0x08, 0xf1, 0x09, 0x28, 0xf0, 0xd8, 0x0d, 0x08, 0x09, 0x02, 0xfb, + 0x12, 0x03, 0x0e, 0xfb, 0xce, 0xf0, 0x39, 0xe5, 0x09, 0xf6, 0x1f, 0x35, + 0xdd, 0x1c, 0x25, 0xef, 0x17, 0x0c, 0xf6, 0x3e, 0xf0, 0x21, 0x08, 0xff, + 0xd7, 0xfc, 0xfd, 0x1f, 0xe5, 0x18, 0x12, 0xe9, 0xf5, 0xe9, 0x12, 0xf6, + 0x02, 0x13, 0xf4, 0x0a, 0xfd, 0x03, 0x09, 0x08, 0x2f, 0x07, 0xee, 0xfd, + 0xd7, 0x00, 0x2b, 0x29, 0x3b, 0xdb, 0xde, 0xf1, 0xe1, 0xf7, 0x47, 0x12, + 0x35, 0x0c, 0xe4, 0x09, 0xef, 0x17, 0x2b, 0xea, 0x2d, 0xf8, 0xe8, 0x18, + 0xef, 0x03, 0x11, 0x0a, 0x10, 0xff, 0xe8, 0x07, 0x0c, 0x07, 0x03, 0x18, + 0x05, 0x08, 0xf8, 0xf8, 0x06, 0x18, 0xe9, 0xf9, 0xe0, 0x0f, 0x0d, 0x18, + 0x04, 0x01, 0xf0, 0x1c, 0xf6, 0x14, 0xfd, 0x12, 0x0c, 0x0c, 0x02, 0x34, + 0xf6, 0xe6, 0xfd, 0xf9, 0xf9, 0xfd, 0x00, 0x2a, 0xfc, 0xf9, 0xff, 0x0a, + 0xfe, 0x1b, 0xf5, 0x34, 0xdc, 0xf9, 0x15, 0x13, 0xe7, 0x1b, 0xf7, 0x25, + 0xfd, 0x09, 0x08, 0x0a, 0xf0, 0x17, 0x0f, 0x04, 0xf4, 0xe9, 0x06, 0x07, + 0xf5, 0x02, 0xfc, 0xf5, 0x09, 0xee, 0xf1, 0x07, 0x38, 0x03, 0x05, 0x0f, + 0x16, 0x0f, 0xed, 0xff, 0x21, 0xf8, 0x34, 0x07, 0xd1, 0xf9, 0x27, 0x00, + 0x0c, 0x21, 0x18, 0x42, 0xe6, 0x02, 0x1a, 0xf1, 0x2f, 0xf1, 0x0e, 0x3b, + 0xee, 0xf8, 0x08, 0xea, 0xfe, 0xf9, 0x03, 0x18, 0xf5, 0xf8, 0x0d, 0xeb, + 0x01, 0x10, 0x09, 0x02, 0x15, 0xfb, 0xf1, 0x0b, 0xf2, 0x06, 0x08, 0x09, + 0x2f, 0x19, 0x02, 0xfe, 0xe4, 0x06, 0x1f, 0x17, 0x49, 0xf2, 0xe2, 0x02, + 0xef, 0x04, 0x26, 0x16, 0x3f, 0x08, 0xf1, 0x0a, 0xfd, 0xf9, 0x28, 0x01, + 0x15, 0x0b, 0xf9, 0x10, 0xdc, 0x02, 0x20, 0xf7, 0x16, 0xe6, 0x09, 0x03, + 0xf1, 0xf5, 0x12, 0x1c, 0xfb, 0x2a, 0x08, 0xfa, 0x0a, 0x16, 0xf6, 0x15, + 0xf0, 0x06, 0x11, 0xfd, 0x0e, 0xf9, 0xf6, 0x12, 0xed, 0xf3, 0xfd, 0x1f, + 0x0b, 0xfa, 0x08, 0x30, 0xf8, 0xff, 0x0b, 0xeb, 0x10, 0xff, 0x07, 0x22, + 0x0d, 0x07, 0x09, 0x03, 0xf6, 0xf8, 0xfc, 0x26, 0xf8, 0xee, 0x11, 0x02, + 0x03, 0x0a, 0xef, 0x38, 0xfe, 0x13, 0x1b, 0x09, 0xfe, 0x06, 0x05, 0xf3, + 0x04, 0xdf, 0xfc, 0x00, 0xe7, 0x15, 0xec, 0xf1, 0xf8, 0xfc, 0xed, 0x05, + 0x0e, 0xf3, 0x15, 0x09, 0x01, 0x0d, 0xfd, 0x00, 0x24, 0xe2, 0x31, 0x13, + 0xd5, 0x1b, 0x2b, 0xe8, 0x03, 0x08, 0x1d, 0x33, 0xdc, 0xfd, 0x24, 0xe4, + 0x20, 0xfa, 0x07, 0x33, 0x01, 0x12, 0x06, 0xf5, 0xef, 0xf7, 0xfa, 0x13, + 0x01, 0xec, 0xee, 0xe0, 0xfd, 0x0d, 0xff, 0x09, 0xf6, 0x00, 0xed, 0x07, + 0xea, 0x0e, 0xff, 0x0e, 0x26, 0xfc, 0xf0, 0xe7, 0xe7, 0xfe, 0x30, 0xff, + 0x24, 0x04, 0x06, 0xf4, 0xf5, 0xf8, 0x23, 0x0e, 0x3d, 0xf2, 0xfd, 0x04, + 0xe8, 0xfb, 0x23, 0xfe, 0x33, 0xe1, 0x01, 0xfd, 0xdc, 0xfb, 0x0e, 0xfa, + 0x22, 0xfb, 0x11, 0xfa, 0xff, 0x08, 0x21, 0x30, 0x13, 0x03, 0xf2, 0x03, + 0xf8, 0x0f, 0xec, 0x0d, 0xef, 0x0f, 0x10, 0x10, 0x0f, 0xf6, 0xf9, 0x1e, + 0xf7, 0xe5, 0x08, 0xfa, 0x09, 0xff, 0x00, 0x15, 0x02, 0x00, 0x08, 0xfe, + 0xfb, 0x0e, 0x15, 0x28, 0xfa, 0xfb, 0x13, 0x06, 0xfb, 0x05, 0xf6, 0x11, + 0xf6, 0x0b, 0x06, 0x15, 0xe1, 0x00, 0xe9, 0x0f, 0xe1, 0x1d, 0x18, 0xfd, + 0x0b, 0x0f, 0xff, 0xf2, 0xf5, 0xfd, 0x14, 0xff, 0xf4, 0xfe, 0xe2, 0xf8, + 0x14, 0x0b, 0xeb, 0x07, 0x35, 0xe2, 0xeb, 0x0b, 0x04, 0x22, 0xfe, 0x0e, + 0x1d, 0xf2, 0x24, 0x11, 0xcc, 0xec, 0x25, 0xf7, 0xff, 0xf9, 0x06, 0x29, + 0xe4, 0x07, 0x1c, 0xdb, 0xf8, 0x1d, 0xfa, 0x44, 0xf2, 0x01, 0x0f, 0xe6, + 0x11, 0x03, 0xee, 0x17, 0x06, 0xe0, 0x0c, 0xd8, 0xe9, 0xfd, 0x11, 0xfe, + 0x07, 0xdd, 0xea, 0xff, 0xde, 0xdd, 0x0a, 0x09, 0x30, 0xf2, 0x01, 0xe4, + 0xe0, 0xeb, 0x2d, 0x12, 0x2d, 0xeb, 0xfc, 0xf0, 0xe8, 0xf9, 0x1f, 0x08, + 0x3f, 0xeb, 0x0e, 0x13, 0xf9, 0x0c, 0x1c, 0x02, 0x25, 0xec, 0xf6, 0x05, + 0xf3, 0xf4, 0x18, 0x08, 0x12, 0xe9, 0xfb, 0xfd, 0xf9, 0x08, 0x13, 0x1c, + 0x08, 0xec, 0xfe, 0x02, 0xf1, 0x19, 0xf3, 0x1d, 0xf1, 0x07, 0x11, 0x12, + 0xfa, 0xf2, 0xf6, 0x0d, 0xff, 0x17, 0x0a, 0xfb, 0x1f, 0xf8, 0x11, 0x24, + 0xf6, 0xfc, 0xfe, 0x07, 0xed, 0x05, 0x1c, 0x21, 0xfe, 0xfe, 0x16, 0x0d, + 0x08, 0x0f, 0x09, 0x33, 0xf4, 0x1f, 0x14, 0x0c, 0xfe, 0xf5, 0xeb, 0x2a, + 0xee, 0xf3, 0x12, 0x19, 0xec, 0x01, 0x06, 0xf7, 0x05, 0x22, 0x0b, 0xeb, + 0xeb, 0x06, 0xe1, 0xf5, 0x0d, 0xee, 0xfb, 0x0a, 0x31, 0xff, 0xe3, 0xea, + 0x18, 0x09, 0xe3, 0x07, 0x1a, 0xf8, 0x15, 0xfc, 0xcc, 0xf2, 0x2a, 0xe5, + 0x01, 0xea, 0x10, 0x1f, 0xd9, 0x02, 0x13, 0xf6, 0x16, 0x01, 0x0e, 0x3c, + 0x02, 0x17, 0x04, 0xf1, 0xf7, 0x02, 0x07, 0x0c, 0x02, 0x1f, 0xf4, 0xe6, + 0xf0, 0xe9, 0x05, 0xf4, 0xfd, 0xe4, 0xf7, 0xe9, 0xfc, 0xef, 0x06, 0x02, + 0x26, 0xf1, 0xf1, 0xeb, 0xe9, 0xe6, 0x30, 0x1c, 0x38, 0x0f, 0x03, 0xf1, + 0x10, 0x04, 0x30, 0x19, 0x1f, 0xfb, 0xfc, 0x05, 0xe2, 0xfe, 0x18, 0xf2, + 0x1c, 0xf2, 0xf5, 0x0e, 0xf2, 0x05, 0x1d, 0x28, 0x12, 0xf0, 0xf0, 0x0f, + 0x0a, 0x03, 0x1a, 0x1a, 0xf3, 0x08, 0x13, 0xef, 0xf5, 0x1c, 0x06, 0x00, + 0xee, 0x12, 0x1d, 0x03, 0x18, 0x06, 0x0a, 0x0e, 0xf0, 0xeb, 0xfa, 0x0d, + 0x08, 0xff, 0x06, 0x24, 0x0f, 0x03, 0x0a, 0x0f, 0x0e, 0xff, 0x08, 0x33, + 0xfc, 0x00, 0x0e, 0xfb, 0xfb, 0x05, 0x07, 0x19, 0xe8, 0xe7, 0x12, 0x11, + 0x15, 0xf7, 0x0c, 0x1a, 0xf6, 0x28, 0x08, 0xeb, 0xf2, 0x25, 0xee, 0x01, + 0x03, 0xec, 0xed, 0xfa, 0xf0, 0xf2, 0xef, 0xf1, 0x02, 0x23, 0xef, 0x01, + 0x41, 0xfa, 0xf4, 0xf4, 0x15, 0xf5, 0xf5, 0xf9, 0x28, 0xde, 0x20, 0xf6, + 0xc7, 0xde, 0x21, 0xe4, 0xfe, 0xec, 0x0d, 0x2c, 0xee, 0x24, 0x10, 0xf0, + 0x1d, 0x12, 0x0e, 0x2b, 0x06, 0xf8, 0xfd, 0x01, 0x08, 0xef, 0xfd, 0x0f, + 0xeb, 0xed, 0xe1, 0xdf, 0xf1, 0xe5, 0x16, 0xe3, 0x08, 0xfc, 0xf6, 0xf6, + 0xd8, 0xf0, 0x23, 0xfc, 0x2b, 0xf5, 0xff, 0xe7, 0xf4, 0xe9, 0x29, 0x09, + 0x2b, 0x0c, 0xff, 0x08, 0x0b, 0xed, 0x29, 0x14, 0x3c, 0xf5, 0xeb, 0x18, + 0xf6, 0x10, 0x22, 0xf9, 0x17, 0x23, 0x02, 0x0c, 0xf6, 0xfa, 0x2f, 0xfe, + 0x1e, 0xeb, 0xfd, 0x03, 0xf0, 0x07, 0x1c, 0x09, 0xfa, 0xe1, 0x0d, 0x0f, + 0x18, 0x03, 0xfe, 0xf0, 0xec, 0x0b, 0x10, 0x02, 0x14, 0x06, 0xef, 0xf7, + 0xea, 0x0b, 0x05, 0xfe, 0x1f, 0x06, 0x0e, 0x07, 0x00, 0xe1, 0x01, 0x01, + 0x07, 0x05, 0x09, 0xf7, 0xef, 0x15, 0xf7, 0x12, 0x05, 0x03, 0x04, 0x1d, + 0x04, 0x10, 0x12, 0x06, 0x05, 0x00, 0x08, 0x18, 0xd6, 0xf2, 0xfa, 0x07, + 0xf8, 0x12, 0x07, 0xfd, 0xdd, 0x00, 0x04, 0xfb, 0xf8, 0x09, 0xf3, 0x09, + 0xfb, 0xf0, 0xe8, 0x09, 0x27, 0xf5, 0xf8, 0x06, 0x01, 0x02, 0x0e, 0xf6, + 0x1f, 0xfa, 0x29, 0xf8, 0xd6, 0x01, 0x22, 0xf8, 0x1d, 0xe3, 0x1a, 0x39, + 0x0a, 0x0d, 0x19, 0xf5, 0x12, 0xfb, 0x1d, 0x2a, 0x03, 0xf6, 0x0c, 0xf2, + 0xfd, 0xec, 0x18, 0x13, 0xfe, 0x1a, 0xe8, 0xdd, 0x01, 0xf8, 0x30, 0x01, + 0xf8, 0xfe, 0xe4, 0xe7, 0xff, 0xeb, 0x23, 0xfa, 0x2c, 0xf0, 0xfc, 0xe7, + 0x0a, 0xf8, 0x18, 0x10, 0x23, 0x01, 0xfa, 0xe8, 0xf1, 0xfa, 0x1d, 0x0e, + 0x17, 0xe7, 0xe4, 0xf5, 0xf9, 0x0c, 0x17, 0x0c, 0x13, 0xe8, 0xe1, 0x17, + 0x19, 0x05, 0x0b, 0x0f, 0x23, 0xed, 0xff, 0xfe, 0xe0, 0x14, 0x16, 0x00, + 0x0d, 0x1c, 0x0b, 0xf5, 0xfb, 0x18, 0xee, 0xff, 0xff, 0xf3, 0x18, 0x0c, + 0x05, 0xfa, 0xf6, 0xfe, 0xfe, 0xf8, 0xf8, 0x09, 0xef, 0xf8, 0x0e, 0xf0, + 0x00, 0xf8, 0x0c, 0xf8, 0xf6, 0x07, 0x16, 0x11, 0xf8, 0xea, 0xff, 0xff, + 0x01, 0x20, 0x07, 0x08, 0xfd, 0x1c, 0xfc, 0x06, 0xed, 0x0d, 0x08, 0x15, + 0xf0, 0x25, 0x01, 0x1b, 0x00, 0x02, 0xfe, 0x01, 0x05, 0x01, 0xfd, 0xf1, + 0xe5, 0x0c, 0xe4, 0xe1, 0xf0, 0xfa, 0xee, 0x0e, 0x35, 0xee, 0x15, 0xef, + 0x0a, 0xf9, 0x01, 0xf5, 0x1f, 0x05, 0x1f, 0x0d, 0xe1, 0xf4, 0xff, 0xf5, + 0x23, 0x02, 0x18, 0x30, 0xfc, 0xf0, 0x0d, 0x04, 0x0d, 0x06, 0x29, 0x1d, + 0xf9, 0x08, 0x06, 0xe5, 0x13, 0xfd, 0x0d, 0x26, 0xef, 0x09, 0xdc, 0xf2, + 0x05, 0xdf, 0x0c, 0xf6, 0xf3, 0xd9, 0xf8, 0x08, 0xef, 0xeb, 0x0f, 0xf9, + 0x3a, 0x03, 0xff, 0xe0, 0xf7, 0xf0, 0x15, 0x12, 0x41, 0x0b, 0xf1, 0x04, + 0x04, 0xe2, 0x0e, 0x0b, 0x2c, 0x03, 0xea, 0x02, 0xfb, 0xe7, 0x08, 0xe9, + 0x22, 0xf3, 0xf2, 0x1c, 0xfa, 0xf3, 0x11, 0x04, 0x1f, 0xf5, 0x02, 0x0f, + 0x1a, 0x1f, 0x24, 0x0b, 0x06, 0x1f, 0xf3, 0x06, 0x00, 0x02, 0xe8, 0xf6, + 0xf4, 0xe8, 0x07, 0x2e, 0xfb, 0xf8, 0x10, 0x09, 0xf0, 0x0e, 0xff, 0xfe, + 0x1c, 0x14, 0x17, 0x06, 0xe2, 0xf1, 0xfa, 0x01, 0x11, 0x13, 0x12, 0x29, + 0xf1, 0x0f, 0x1f, 0xfa, 0xfd, 0xfd, 0x02, 0x07, 0x0e, 0xfb, 0x0e, 0x04, + 0x01, 0x01, 0xed, 0xfe, 0xde, 0xfd, 0x08, 0xef, 0xf6, 0x0a, 0xff, 0x0f, + 0xe7, 0xf2, 0x0f, 0x02, 0xea, 0x10, 0xf9, 0xec, 0xfd, 0x09, 0xea, 0x1f, + 0x46, 0xdd, 0xe2, 0xf7, 0x08, 0xf5, 0xf7, 0xe9, 0x33, 0xfb, 0x2f, 0xf6, + 0xb5, 0x1d, 0x15, 0xeb, 0x11, 0xf7, 0x2a, 0x2e, 0x08, 0x1d, 0xf4, 0xfb, + 0x15, 0xfa, 0x22, 0x34, 0xff, 0x06, 0xf6, 0xfd, 0xfa, 0xf9, 0x03, 0xf5, + 0xf4, 0xf4, 0xd5, 0xea, 0x01, 0x08, 0x22, 0xf1, 0xf2, 0x06, 0xd1, 0xe5, + 0x0c, 0xef, 0x12, 0x03, 0x08, 0x02, 0xf7, 0x05, 0x1b, 0x07, 0x39, 0x34, + 0x21, 0xe2, 0xe3, 0x0b, 0x0c, 0xf6, 0x29, 0xf7, 0x24, 0x0a, 0xfc, 0xff, + 0x1a, 0xfd, 0x05, 0xff, 0xff, 0x0e, 0x0a, 0x1a, 0x09, 0xfb, 0x15, 0x04, + 0x03, 0xf7, 0xfe, 0x00, 0xfc, 0xfb, 0x11, 0xfa, 0x1d, 0x0e, 0x06, 0xed, + 0xfc, 0x23, 0xd8, 0xf2, 0x04, 0xe5, 0x0f, 0x16, 0x29, 0xfe, 0xf5, 0xec, + 0xe2, 0x0e, 0xeb, 0x09, 0x1d, 0x11, 0x05, 0x11, 0xe4, 0x29, 0x12, 0x02, + 0x12, 0x19, 0x0e, 0x1a, 0xee, 0xf9, 0x05, 0x09, 0xf5, 0xfd, 0x05, 0x04, + 0xe4, 0xf1, 0x17, 0x01, 0xf2, 0xfe, 0x0b, 0xf4, 0x0d, 0x04, 0x06, 0xfe, + 0xff, 0xec, 0xe9, 0x00, 0xff, 0x03, 0x03, 0xfd, 0xf1, 0x15, 0xfc, 0xf3, + 0xff, 0xfe, 0x09, 0xee, 0x3c, 0x01, 0xec, 0x02, 0xf0, 0xf6, 0x20, 0xeb, + 0x16, 0x07, 0x32, 0xf3, 0xce, 0xf0, 0x02, 0xd4, 0x11, 0xe6, 0x28, 0x0e, + 0xe3, 0x21, 0xee, 0xce, 0x1e, 0xd9, 0x23, 0x26, 0x06, 0xfa, 0xf9, 0xf1, + 0x01, 0xe6, 0x0b, 0x07, 0xdc, 0x21, 0xbc, 0xe3, 0xef, 0xf8, 0x12, 0xfc, + 0xe6, 0xfe, 0xf5, 0xd4, 0x15, 0x0a, 0x00, 0x13, 0xfc, 0xec, 0xf3, 0xd6, + 0x1a, 0xe3, 0x21, 0x36, 0x2a, 0x03, 0xe9, 0xe3, 0xff, 0x00, 0x13, 0x1c, + 0x0e, 0x20, 0xe5, 0xf5, 0x24, 0x0b, 0x20, 0x14, 0x13, 0xf8, 0x04, 0x1b, + 0x2f, 0x0a, 0x15, 0x00, 0xf4, 0x1a, 0x11, 0x0d, 0x03, 0x18, 0x0f, 0x18, + 0x04, 0x1f, 0xfb, 0xf2, 0x1f, 0x15, 0x03, 0xfb, 0x0b, 0x17, 0xfb, 0x0b, + 0x1b, 0x1f, 0xf4, 0x07, 0xf9, 0xf9, 0xf8, 0xf4, 0x14, 0x0f, 0xf6, 0xfe, + 0xdd, 0x0b, 0xff, 0x01, 0x18, 0x04, 0x1b, 0x0a, 0xed, 0xe7, 0xf9, 0x16, + 0x02, 0x01, 0x00, 0xf7, 0xf1, 0x07, 0xf0, 0x06, 0xf8, 0x0b, 0x02, 0xf3, + 0xff, 0x20, 0xfd, 0x01, 0x04, 0xf5, 0xd9, 0xf4, 0xf4, 0xf2, 0xe8, 0xff, + 0x04, 0x00, 0xf0, 0xe2, 0xfe, 0xed, 0x1b, 0xef, 0x20, 0xfa, 0xfb, 0xf4, + 0x02, 0x18, 0x07, 0xfb, 0xef, 0xe4, 0x08, 0x0d, 0xe1, 0x0e, 0x25, 0xc6, + 0xfd, 0x0c, 0x1c, 0x0b, 0xf0, 0x01, 0x1c, 0xd4, 0x11, 0xf5, 0x1b, 0x09, + 0xfb, 0xda, 0x13, 0xe3, 0xf9, 0x10, 0x14, 0xf0, 0xf0, 0xfd, 0x1f, 0xcf, + 0xf4, 0xe4, 0xfb, 0x0e, 0x0a, 0x11, 0xed, 0xdc, 0xfc, 0xe6, 0xf7, 0xfc, + 0x13, 0xe1, 0x0b, 0xe4, 0x04, 0x11, 0xee, 0x21, 0x14, 0xe1, 0x07, 0xe4, + 0xfb, 0x08, 0x03, 0x2b, 0x27, 0xf6, 0x0d, 0x02, 0x1b, 0x09, 0x09, 0xf8, + 0x14, 0x19, 0x0f, 0x0b, 0x01, 0x10, 0x09, 0x12, 0x03, 0xf5, 0x18, 0xf3, + 0xfb, 0xf5, 0x02, 0x0e, 0x0d, 0x00, 0x07, 0xfc, 0x18, 0x25, 0x0b, 0xf0, + 0xf9, 0xe6, 0x08, 0x01, 0x24, 0x14, 0xfa, 0xed, 0xe5, 0x1f, 0x09, 0xfe, + 0x08, 0xee, 0x1a, 0x1a, 0x05, 0x00, 0xff, 0x0c, 0xfe, 0xf9, 0x11, 0x11, + 0xea, 0xfe, 0x08, 0xf9, 0xf0, 0xe4, 0x01, 0x0d, 0xf1, 0x00, 0x0b, 0xea, + 0x19, 0xea, 0xf3, 0xf8, 0x08, 0x12, 0x1c, 0x1f, 0xfb, 0xef, 0xf0, 0xf2, + 0x14, 0xe1, 0x03, 0xfa, 0xf9, 0xda, 0xe9, 0xfc, 0xf3, 0xff, 0x12, 0x04, + 0xf7, 0xfc, 0x17, 0x0f, 0xfc, 0x29, 0x03, 0xe5, 0xf2, 0xee, 0x1e, 0xfa, + 0x04, 0xed, 0x25, 0xf4, 0xe1, 0x15, 0x10, 0x1e, 0xef, 0x1c, 0x04, 0xde, + 0xe5, 0x08, 0x21, 0xfd, 0xfd, 0xea, 0x03, 0xca, 0xda, 0x26, 0x00, 0x0a, + 0xfd, 0x05, 0xf0, 0xd4, 0xe1, 0x1a, 0xe4, 0xf5, 0x07, 0xe7, 0xfa, 0xdf, + 0xd4, 0x03, 0xf0, 0x10, 0x15, 0x0c, 0xf4, 0xed, 0xe3, 0xfb, 0x0f, 0x1e, + 0x16, 0x09, 0x00, 0xec, 0xea, 0x13, 0x16, 0x0b, 0x01, 0xfb, 0xff, 0x00, + 0xfb, 0x07, 0x13, 0x08, 0xf4, 0xe4, 0x12, 0x00, 0xfb, 0xfa, 0xfc, 0x08, + 0xeb, 0x19, 0x02, 0x1c, 0xe8, 0x26, 0xf3, 0x10, 0x09, 0x0f, 0x19, 0x02, + 0xfb, 0xec, 0xf7, 0xe2, 0xfb, 0xfa, 0x11, 0xf3, 0x0b, 0x08, 0xff, 0xd9, + 0xf8, 0x12, 0x18, 0x06, 0x07, 0x22, 0xff, 0x19, 0xf5, 0x0b, 0x0a, 0x13, + 0xf2, 0xfa, 0x02, 0x21, 0xeb, 0x11, 0x17, 0x17, 0xec, 0xe1, 0x0e, 0xf7, + 0xe8, 0xd8, 0x0e, 0x01, 0xf1, 0xed, 0xed, 0xf0, 0x09, 0xf7, 0xe7, 0xfd, + 0xf0, 0xf9, 0xdb, 0xee, 0xdc, 0xfb, 0xf8, 0x0a, 0xf5, 0x0b, 0xd4, 0xd7, + 0x08, 0x06, 0x18, 0x06, 0x0c, 0x13, 0xfd, 0x09, 0x13, 0x26, 0x12, 0xf4, + 0xef, 0x00, 0xf5, 0x28, 0x18, 0xfe, 0x04, 0x0e, 0x21, 0x1a, 0x0a, 0x1e, + 0x09, 0xf0, 0x0d, 0x0f, 0xec, 0xf3, 0x17, 0x22, 0x00, 0xec, 0x0e, 0x01, + 0xe9, 0x08, 0x09, 0xf2, 0xf2, 0x08, 0xf0, 0x0b, 0xd9, 0x09, 0x14, 0xf5, + 0xf6, 0x04, 0x19, 0xf4, 0x11, 0xe9, 0xf2, 0x0d, 0x20, 0x17, 0x0a, 0x05, + 0x0c, 0x04, 0x01, 0xfd, 0xf4, 0xfb, 0x1b, 0x0c, 0xf2, 0x0b, 0xff, 0xfe, + 0x01, 0xd8, 0xfa, 0x0e, 0xf5, 0x14, 0xf9, 0x01, 0x04, 0xf8, 0xfa, 0x02, + 0xe8, 0xf9, 0xf9, 0xea, 0xf1, 0x07, 0xff, 0x1e, 0x01, 0x0b, 0xf7, 0x0a, + 0xf7, 0x0c, 0xfd, 0xec, 0xf3, 0x05, 0xf8, 0xda, 0x0b, 0x15, 0xf6, 0xee, + 0xf9, 0x10, 0xfa, 0xfe, 0x08, 0xf0, 0xe6, 0xec, 0x05, 0xff, 0x15, 0x19, + 0x1f, 0x11, 0xfc, 0x09, 0x08, 0x01, 0x06, 0xfe, 0x04, 0x08, 0xfb, 0xfb, + 0x08, 0xf4, 0xf6, 0x28, 0x10, 0xf9, 0x28, 0x0b, 0xf8, 0x0d, 0x01, 0x00, + 0xff, 0x02, 0x05, 0x08, 0xea, 0xe9, 0xf4, 0xf6, 0x01, 0xea, 0xdf, 0x1f, + 0xfe, 0x0a, 0xf9, 0xf7, 0x0c, 0x1b, 0x06, 0xed, 0xf6, 0xf2, 0x03, 0x03, + 0xfd, 0x04, 0xf5, 0x10, 0x0a, 0x0b, 0xf4, 0xf8, 0xf1, 0xe7, 0x05, 0xfe, + 0xe7, 0x0b, 0xf1, 0xec, 0xf4, 0xec, 0x06, 0xee, 0xde, 0x05, 0x1b, 0xfe, + 0x13, 0xf3, 0xd9, 0xea, 0x04, 0x10, 0x05, 0xed, 0x15, 0x02, 0x0b, 0x10, + 0xfa, 0x02, 0x05, 0x0b, 0x02, 0x07, 0xfc, 0xf5, 0x15, 0x14, 0x05, 0xf7, + 0x0c, 0xfe, 0xf6, 0xf4, 0xfa, 0x06, 0xfc, 0x13, 0xdc, 0xe4, 0x09, 0xfa, + 0x02, 0x23, 0xec, 0x06, 0x11, 0x13, 0xf8, 0xfa, 0x27, 0x28, 0x0b, 0x23, + 0xec, 0xf1, 0x09, 0x17, 0x0f, 0x13, 0xff, 0xf2, 0xfc, 0x0a, 0xf5, 0x0d, + 0x03, 0x26, 0x01, 0x0f, 0xfe, 0xf1, 0xfb, 0xe6, 0xf0, 0x02, 0xf2, 0xff, + 0x02, 0x11, 0xff, 0xfd, 0x1c, 0x02, 0x0b, 0xf6, 0x14, 0x0c, 0x0b, 0x21, + 0x28, 0xf0, 0x11, 0x05, 0x06, 0xed, 0xf9, 0x0a, 0xf2, 0xef, 0xf8, 0xf1, + 0xfe, 0x0d, 0xf9, 0xf7, 0xea, 0x00, 0x08, 0xdb, 0x02, 0x0f, 0xfe, 0x04, + 0xef, 0x20, 0x16, 0x01, 0xe8, 0xed, 0xe4, 0x22, 0xf6, 0x19, 0x00, 0x04, + 0x01, 0x13, 0xeb, 0x0d, 0xec, 0x01, 0x08, 0x05, 0x0c, 0x0e, 0xfe, 0x02, + 0x12, 0xf7, 0x27, 0xf9, 0xfd, 0x18, 0xfe, 0x24, 0xf7, 0x13, 0xed, 0x1e, + 0x09, 0xff, 0xd8, 0xf4, 0x12, 0xf8, 0x04, 0x0c, 0x1c, 0x11, 0xfd, 0x17, + 0x1d, 0x01, 0x13, 0xee, 0x11, 0xf3, 0xf8, 0x06, 0xf6, 0x16, 0xfe, 0x15, + 0x16, 0xdc, 0x1f, 0x00, 0x25, 0xee, 0xff, 0xf7, 0xf6, 0x02, 0xdd, 0x15, + 0xf1, 0x14, 0x08, 0xe8, 0xe5, 0x21, 0xea, 0xf0, 0x1a, 0x07, 0xea, 0x08, + 0xea, 0xe4, 0x1e, 0x00, 0x13, 0x17, 0xec, 0x11, 0xd6, 0x11, 0x18, 0x17, + 0x04, 0x15, 0x03, 0x3a, 0xd6, 0x02, 0x07, 0x04, 0xe6, 0xe5, 0xfe, 0x0e, + 0xff, 0xed, 0xfc, 0xfb, 0xff, 0x1c, 0x06, 0x0a, 0xfb, 0xf9, 0xea, 0x1a, + 0x21, 0xf5, 0x04, 0x06, 0x0a, 0xe3, 0x16, 0xea, 0x04, 0xe2, 0xf9, 0xf9, + 0xe6, 0xfb, 0x0f, 0xfc, 0x06, 0xfb, 0x10, 0x07, 0x07, 0x13, 0x07, 0xfc, + 0x16, 0xef, 0x07, 0xdc, 0x12, 0x1f, 0x08, 0xf4, 0xe9, 0x14, 0x06, 0xf7, + 0xf1, 0x0c, 0x01, 0x0c, 0xe6, 0x04, 0xf3, 0xf2, 0xe5, 0xf3, 0xef, 0x1d, + 0xf6, 0x20, 0x07, 0xfe, 0xf4, 0x05, 0xee, 0x10, 0xfd, 0x0e, 0x0b, 0x02, + 0x0d, 0xd8, 0x07, 0xfb, 0x26, 0x0a, 0x1c, 0x21, 0x06, 0x1f, 0xf4, 0x06, + 0x37, 0x18, 0xfa, 0x16, 0x1e, 0x24, 0xfb, 0xf0, 0x12, 0xf9, 0x02, 0x09, + 0x17, 0x16, 0xf3, 0xf9, 0x17, 0xf2, 0x02, 0x0a, 0x2d, 0xe7, 0xe3, 0x25, + 0xf0, 0xf9, 0x0f, 0xdd, 0x15, 0xe6, 0x04, 0xfc, 0xf1, 0x17, 0x0a, 0xea, + 0x24, 0x07, 0xf1, 0x11, 0x13, 0x29, 0xf4, 0xc5, 0xfb, 0x07, 0xef, 0x13, + 0x0b, 0xe1, 0xf1, 0xeb, 0xf8, 0x1b, 0x09, 0x08, 0x1f, 0x15, 0xf2, 0x05, + 0x02, 0xdd, 0x09, 0x0f, 0x16, 0x10, 0x01, 0x30, 0xf2, 0xe0, 0x27, 0xfe, + 0xf1, 0x0e, 0x0e, 0x07, 0xe6, 0x07, 0x0b, 0x18, 0xfe, 0x0f, 0x01, 0x07, + 0xf4, 0x07, 0x10, 0xe7, 0xfb, 0xf3, 0xf7, 0x0b, 0xf9, 0x15, 0x18, 0x25, + 0x0c, 0x14, 0x02, 0x08, 0x0a, 0x0f, 0x10, 0xec, 0xee, 0x1a, 0x03, 0x14, + 0x0f, 0xfa, 0x25, 0xff, 0x18, 0x0d, 0x0b, 0xea, 0x1f, 0x28, 0x10, 0x0c, + 0xe7, 0xee, 0xf7, 0xfa, 0x03, 0x15, 0x0c, 0x1d, 0x01, 0x00, 0x12, 0xee, + 0x01, 0xf1, 0xf8, 0x0b, 0xf3, 0xfd, 0x04, 0xf8, 0x02, 0x1e, 0x0e, 0xf3, + 0x02, 0x10, 0xfd, 0x07, 0x0b, 0x09, 0x03, 0x10, 0x3e, 0x08, 0x0e, 0x0c, + 0xf4, 0xe7, 0xfd, 0x1c, 0x27, 0x1a, 0xed, 0xe1, 0x08, 0xdc, 0xd9, 0xf1, + 0x1e, 0x07, 0x12, 0xf1, 0x10, 0xfb, 0xc8, 0x08, 0x0f, 0x03, 0x1d, 0xdc, + 0x23, 0x04, 0xf9, 0x0a, 0xff, 0x08, 0x0e, 0xc9, 0x39, 0x0a, 0x01, 0x07, + 0xec, 0xe0, 0x05, 0xe8, 0x14, 0xd8, 0xe1, 0xfa, 0xd6, 0xf8, 0xed, 0xdb, + 0xff, 0x1d, 0xf5, 0x17, 0x0f, 0x1c, 0xdc, 0xed, 0xff, 0xff, 0x04, 0x13, + 0xf5, 0xe7, 0xd2, 0x12, 0xdb, 0xe1, 0x13, 0x11, 0x23, 0x0e, 0xf9, 0x31, + 0xdc, 0xef, 0x07, 0x0a, 0x20, 0xf2, 0xf9, 0x13, 0xff, 0x1c, 0x2a, 0xdf, + 0xdb, 0xe7, 0x11, 0xf2, 0xfd, 0xfb, 0x28, 0x00, 0x15, 0x03, 0x02, 0x20, + 0x07, 0xf7, 0x19, 0x13, 0x13, 0xf6, 0x09, 0xfe, 0xfd, 0x20, 0x14, 0xf5, + 0xf5, 0xfc, 0x14, 0x0e, 0x17, 0xfe, 0x15, 0x04, 0xf9, 0xf6, 0x1d, 0xf6, + 0x1b, 0xe4, 0xee, 0xfd, 0x00, 0xe9, 0xee, 0xce, 0x0f, 0x20, 0x05, 0x02, + 0x0d, 0x06, 0x05, 0xf8, 0xef, 0xdf, 0x16, 0x17, 0xe6, 0xf1, 0x10, 0xf3, + 0x06, 0x04, 0xdb, 0xfb, 0xe7, 0xf8, 0x02, 0x11, 0xff, 0x0d, 0x0a, 0xfa, + 0x27, 0x0a, 0xfc, 0xe8, 0x11, 0x17, 0xf0, 0x0d, 0x0d, 0xee, 0xdf, 0xdd, + 0xf1, 0x15, 0xd6, 0xf7, 0x00, 0xef, 0x2e, 0xe6, 0x24, 0xfd, 0xd5, 0x04, + 0xf0, 0x08, 0x08, 0xed, 0x22, 0x07, 0xe1, 0x09, 0xd0, 0x0b, 0x18, 0xe6, + 0x3f, 0x0a, 0xe5, 0xe2, 0xf9, 0x08, 0x02, 0xd6, 0x13, 0x15, 0xbd, 0x00, + 0x0e, 0xf8, 0xe2, 0xca, 0xec, 0x0e, 0xe6, 0xef, 0x15, 0x11, 0xcb, 0xdf, + 0xf9, 0x03, 0x22, 0x10, 0xfb, 0xf9, 0xe5, 0x08, 0xe1, 0x11, 0x10, 0xfc, + 0xfa, 0x00, 0xf8, 0x30, 0xe5, 0x08, 0x14, 0xe8, 0x12, 0xe2, 0x04, 0x19, + 0x0b, 0xfa, 0x33, 0xf3, 0xec, 0xfe, 0xf8, 0x25, 0xf8, 0x21, 0x28, 0xef, + 0x00, 0xde, 0xff, 0x2b, 0x03, 0xfc, 0x10, 0x0c, 0xcf, 0xfd, 0x19, 0x0a, + 0x0c, 0xf2, 0xf7, 0x0c, 0xfd, 0x02, 0x1c, 0xdf, 0x26, 0x0d, 0xf0, 0x0b, + 0xce, 0x15, 0xfb, 0xec, 0x27, 0xf6, 0xf9, 0xe5, 0xe2, 0xfb, 0xfd, 0xd8, + 0x28, 0xec, 0xe9, 0xf2, 0xca, 0x09, 0x02, 0x06, 0x0c, 0xfa, 0x05, 0x01, + 0xd5, 0x0a, 0x02, 0xfb, 0x04, 0x17, 0xdd, 0xfe, 0xeb, 0xf1, 0x09, 0x10, + 0x12, 0xff, 0x00, 0xe0, 0x26, 0xf7, 0xed, 0xf4, 0x00, 0xf2, 0xfa, 0x07, + 0x02, 0xf5, 0x06, 0xe8, 0x03, 0xfd, 0xdc, 0xf2, 0xc2, 0xff, 0x0b, 0xd6, + 0x25, 0x04, 0xe9, 0xf0, 0xd9, 0x08, 0x09, 0xc5, 0x23, 0x12, 0xf6, 0x13, + 0x11, 0xf3, 0x18, 0xf0, 0x34, 0xfe, 0xfe, 0xed, 0xea, 0x02, 0x17, 0xdc, + 0x1b, 0x1b, 0xea, 0xfe, 0xea, 0xfe, 0xf2, 0xc4, 0xfd, 0x04, 0xe9, 0x0d, + 0x0d, 0x09, 0xca, 0xd4, 0xe1, 0x04, 0x1e, 0xff, 0x0f, 0xef, 0xd6, 0x0f, + 0xd5, 0xf8, 0x26, 0xd6, 0x33, 0xe8, 0xf5, 0x3b, 0xf1, 0xe8, 0x39, 0xe8, + 0x08, 0xe5, 0x01, 0x02, 0x04, 0xf6, 0x19, 0x0a, 0xd0, 0xeb, 0x0b, 0x15, + 0xf7, 0x0e, 0x23, 0xf6, 0xf4, 0xd8, 0xf4, 0x17, 0x23, 0x25, 0x14, 0x01, + 0xd7, 0xfd, 0xf9, 0x1f, 0x1b, 0x11, 0x0a, 0x18, 0xf5, 0xf5, 0x0f, 0xe0, + 0x2e, 0x01, 0xe5, 0xdb, 0xe2, 0xf2, 0x14, 0xfa, 0x2a, 0x00, 0xe2, 0xea, + 0xfd, 0x0e, 0xfc, 0xc1, 0x35, 0x08, 0xf6, 0xf9, 0xec, 0x00, 0x06, 0x00, + 0x0b, 0xf6, 0x01, 0xfe, 0xea, 0x0b, 0x08, 0x05, 0xe4, 0xea, 0xd7, 0xfd, + 0xee, 0xf3, 0x0c, 0x0c, 0x0d, 0x02, 0xfd, 0xee, 0x17, 0x10, 0x13, 0xfd, + 0x07, 0x03, 0xf8, 0x0c, 0xd4, 0xed, 0xfe, 0x07, 0xf4, 0xee, 0xf4, 0x03, + 0xc2, 0x18, 0x2c, 0xd1, 0x33, 0xd8, 0xdb, 0xfa, 0xed, 0x10, 0x1c, 0xe3, + 0x37, 0x0a, 0xea, 0xfe, 0xf6, 0xef, 0x20, 0xed, 0x32, 0xf7, 0xf5, 0xf3, + 0xca, 0xfd, 0x0a, 0xcf, 0x0d, 0x10, 0xde, 0x07, 0x18, 0x10, 0xf0, 0xd6, + 0x0c, 0x04, 0xeb, 0x1a, 0xf9, 0x08, 0xc4, 0xcb, 0xe4, 0x0b, 0x19, 0xfc, + 0x29, 0xf6, 0xec, 0x07, 0xf3, 0xed, 0x2b, 0xe9, 0xfa, 0x02, 0xec, 0x2b, + 0xf0, 0xf2, 0x2d, 0xe8, 0xed, 0x00, 0x12, 0x13, 0xed, 0x1a, 0x3d, 0xf0, + 0x05, 0x04, 0xfc, 0x13, 0x10, 0x01, 0x40, 0xf2, 0x06, 0x02, 0xf9, 0x22, + 0x24, 0xff, 0x18, 0x00, 0xeb, 0xe8, 0x14, 0xf9, 0x25, 0xe0, 0xff, 0x03, + 0xe5, 0xfd, 0x08, 0xea, 0x2e, 0x0b, 0x05, 0xe7, 0xde, 0xe4, 0xf5, 0xea, + 0x3a, 0xf4, 0xf4, 0xe7, 0xed, 0xec, 0xf8, 0xee, 0x30, 0x0a, 0xdb, 0x05, + 0xf7, 0x16, 0xff, 0xf7, 0xfa, 0x1f, 0xef, 0xe4, 0xce, 0xf8, 0x13, 0x04, + 0xf9, 0x01, 0xe1, 0x03, 0xf9, 0xf9, 0x08, 0x04, 0xfa, 0xe4, 0xe7, 0xf7, + 0x28, 0xfd, 0xfd, 0x00, 0xfc, 0xfb, 0xef, 0x0a, 0xec, 0x0c, 0x0a, 0xd2, + 0x05, 0xfb, 0xcd, 0xfb, 0x9d, 0xea, 0x1c, 0xe5, 0x25, 0xe8, 0xea, 0x0b, + 0xf0, 0xf3, 0x0d, 0xab, 0x49, 0x0e, 0xeb, 0x00, 0xe2, 0x03, 0x29, 0xe0, + 0x3d, 0x06, 0xf7, 0xf8, 0xcf, 0x0c, 0x1a, 0xd6, 0x1f, 0xef, 0xfd, 0xff, + 0xef, 0x0c, 0xdb, 0xe0, 0x20, 0x06, 0xdf, 0x1a, 0xe7, 0xfc, 0xb2, 0xd1, + 0xdf, 0x13, 0x07, 0x1f, 0x0c, 0xf7, 0xde, 0x0a, 0xdb, 0xdf, 0x1a, 0xf5, + 0x29, 0x0d, 0xeb, 0x2c, 0xcf, 0x0e, 0x26, 0xfe, 0xef, 0x04, 0xf5, 0x14, + 0x09, 0x13, 0x34, 0xff, 0xfe, 0x0e, 0x06, 0x0e, 0x10, 0xf9, 0x2a, 0x0b, + 0xe6, 0xfe, 0xf1, 0x1a, 0x36, 0x29, 0x29, 0x05, 0x05, 0xd8, 0x14, 0x12, + 0x26, 0x0b, 0x18, 0xff, 0xd7, 0xdf, 0x0f, 0xed, 0x31, 0xf7, 0xfc, 0xec, + 0x0b, 0xef, 0x0c, 0xd2, 0x30, 0xf9, 0x04, 0xfe, 0xef, 0xe4, 0xfb, 0xd1, + 0x32, 0xe5, 0xee, 0xf0, 0x0c, 0xe6, 0x13, 0xed, 0x1e, 0x0b, 0xe4, 0xe0, + 0xfa, 0xf4, 0x14, 0xf4, 0x18, 0xf7, 0xd9, 0xf6, 0xed, 0xea, 0xfc, 0x06, + 0xfc, 0xf5, 0xed, 0xeb, 0x05, 0x03, 0x1b, 0x0b, 0xff, 0x0b, 0xef, 0x01, + 0xf1, 0x16, 0x05, 0x00, 0xee, 0x0a, 0xdb, 0x10, 0xb4, 0x14, 0x0f, 0xe1, + 0x1c, 0xfd, 0xf0, 0xf8, 0xc3, 0x11, 0x17, 0xba, 0x47, 0x15, 0xe6, 0x01, + 0xea, 0xf1, 0x0c, 0x08, 0x4a, 0x15, 0xf0, 0xf7, 0xea, 0x00, 0xf5, 0xd4, + 0xf1, 0xff, 0xe0, 0x0c, 0xf4, 0x17, 0xd8, 0xea, 0x03, 0xff, 0xd5, 0x18, + 0xfb, 0x07, 0xc7, 0xc9, 0xdd, 0xf3, 0x15, 0x0d, 0x22, 0xea, 0xdb, 0x0a, + 0xd6, 0x09, 0x1d, 0xe5, 0x2d, 0x04, 0xfc, 0x35, 0xc6, 0x0e, 0x33, 0xf1, + 0xd7, 0xea, 0x01, 0x1b, 0x0e, 0x01, 0x2a, 0xff, 0xef, 0xf1, 0xf7, 0x0f, + 0xff, 0x00, 0x3b, 0xe8, 0x0a, 0xff, 0xf4, 0x0d, 0x1f, 0x04, 0x17, 0xf7, + 0xdf, 0xec, 0x12, 0x26, 0x36, 0x07, 0x0c, 0x06, 0xe7, 0xd6, 0x13, 0xe3, + 0x30, 0x09, 0x00, 0xf5, 0xe0, 0xf3, 0x11, 0xe2, 0x38, 0x0d, 0xf6, 0x05, + 0xec, 0x05, 0x00, 0xe5, 0x24, 0xef, 0xfe, 0xf8, 0x00, 0xd8, 0x18, 0xf1, + 0x26, 0x0b, 0xf2, 0xfc, 0xe0, 0xe4, 0x06, 0x0b, 0x1a, 0x05, 0xc6, 0xf6, + 0xe8, 0xde, 0xfe, 0x0c, 0x03, 0x09, 0xfe, 0xe2, 0x18, 0x1b, 0xfb, 0xf7, + 0x06, 0xf1, 0xfe, 0xf6, 0xef, 0x1b, 0x07, 0x0d, 0x01, 0x0a, 0xed, 0xf0, + 0xad, 0x1a, 0x17, 0xd6, 0x37, 0xfd, 0xd8, 0xec, 0xca, 0xf1, 0x15, 0xc4, + 0x33, 0xf1, 0xed, 0xf0, 0xe9, 0x15, 0x0d, 0xf2, 0x36, 0xde, 0xfd, 0x0e, + 0xfb, 0x10, 0x0f, 0xf6, 0xf9, 0x0c, 0xea, 0xf0, 0xe5, 0x0b, 0xee, 0xc1, + 0x10, 0xf4, 0xe8, 0x1f, 0xee, 0x00, 0xd0, 0xe4, 0xe7, 0x13, 0x07, 0x27, + 0x12, 0xea, 0xea, 0x0f, 0xea, 0xf4, 0x14, 0xee, 0xfe, 0x09, 0xfb, 0x31, + 0xdb, 0x1b, 0x1c, 0xe7, 0xef, 0xf5, 0xf7, 0x1a, 0x06, 0x01, 0x2c, 0xed, + 0xfb, 0x04, 0xfa, 0x07, 0x19, 0xec, 0x2b, 0x0d, 0xfc, 0xd8, 0xfc, 0x0f, + 0x1f, 0xfc, 0x2d, 0xf3, 0xc9, 0xda, 0x0a, 0xfe, 0x29, 0x00, 0xfa, 0x09, + 0xe8, 0xf6, 0x21, 0xf3, 0x4a, 0x1a, 0xf8, 0x00, 0xe7, 0xf0, 0x21, 0x01, + 0x22, 0xf3, 0x00, 0xe9, 0x06, 0xe3, 0x15, 0xd7, 0x3d, 0x0c, 0x07, 0xf1, + 0xf3, 0xec, 0x17, 0xdf, 0x29, 0x1b, 0xfd, 0xfe, 0xeb, 0xed, 0x17, 0xf6, + 0x23, 0x0a, 0xea, 0xee, 0xf9, 0xf3, 0x0f, 0x0c, 0xf8, 0xf5, 0xed, 0xe8, + 0x1c, 0x14, 0x07, 0x17, 0x0b, 0x0d, 0xed, 0xf7, 0xed, 0x10, 0x07, 0xd5, + 0xf2, 0x09, 0xd6, 0xf7, 0xb5, 0xf6, 0x19, 0xc9, 0x25, 0x15, 0xe8, 0xf5, + 0xc4, 0xf9, 0x2a, 0xb0, 0x39, 0x0e, 0x02, 0x11, 0xf0, 0xf7, 0x1d, 0xeb, + 0x39, 0x10, 0x02, 0x15, 0xe0, 0x08, 0x01, 0xee, 0x1c, 0x1e, 0x08, 0x04, + 0xf2, 0x02, 0xe8, 0xda, 0xfa, 0xfb, 0xe0, 0xfe, 0x05, 0x02, 0xd3, 0xca, + 0xf4, 0xec, 0x10, 0x16, 0x05, 0x0d, 0xd7, 0x09, 0xdc, 0xf6, 0x1e, 0xf8, + 0x10, 0xed, 0xf7, 0x27, 0xf5, 0x08, 0x28, 0xee, 0xec, 0xe0, 0xf8, 0x17, + 0xfb, 0x23, 0x2e, 0xf1, 0xfa, 0xf5, 0xfc, 0x1a, 0x10, 0xf7, 0x32, 0xfb, + 0xfb, 0xe8, 0xf1, 0x03, 0x24, 0xeb, 0x25, 0xf9, 0xca, 0xf1, 0xfe, 0x01, + 0x2e, 0x07, 0x18, 0x03, 0xe5, 0xea, 0x10, 0xfa, 0x3b, 0x07, 0x0f, 0x11, + 0x04, 0xf7, 0x1d, 0xf1, 0x24, 0xd9, 0x08, 0xef, 0x02, 0xdd, 0x07, 0xc8, + 0x2c, 0x0d, 0x06, 0xec, 0x17, 0xda, 0x21, 0xdf, 0x34, 0xd9, 0xfb, 0xf2, + 0xf4, 0xec, 0x0e, 0x0a, 0x0f, 0x0f, 0xdb, 0xf0, 0xfb, 0xe6, 0x0f, 0x00, + 0x04, 0xf9, 0x01, 0x05, 0x05, 0xfe, 0x08, 0xf3, 0x0e, 0xf2, 0xfb, 0x01, + 0xfd, 0x18, 0x1d, 0xf6, 0xee, 0x06, 0xcf, 0xfc, 0xae, 0x27, 0x21, 0xd2, + 0x33, 0x03, 0xe0, 0xe0, 0xc9, 0xfb, 0x3a, 0xbd, 0x4d, 0x04, 0xe8, 0xf5, + 0xe6, 0xeb, 0x19, 0xf2, 0x4b, 0x1d, 0xfc, 0xf7, 0xd9, 0xff, 0xfe, 0xea, + 0x0f, 0x04, 0x0e, 0x00, 0xed, 0x19, 0xe9, 0xe9, 0xff, 0x11, 0xef, 0x14, + 0x01, 0x17, 0xbc, 0xb5, 0xef, 0x0c, 0x22, 0x27, 0x0f, 0x01, 0xd4, 0x03, + 0xce, 0x01, 0x25, 0xff, 0xf9, 0xf0, 0x0a, 0x1c, 0xe5, 0x0f, 0x1c, 0xee, + 0xf4, 0xf1, 0xf4, 0x0c, 0x00, 0x08, 0x1c, 0xf4, 0xd5, 0xf1, 0xfc, 0x1f, + 0x11, 0x00, 0x18, 0x03, 0xf7, 0xe4, 0xff, 0x07, 0x09, 0x1a, 0x18, 0xff, + 0xea, 0xec, 0xfd, 0x13, 0x2b, 0xf8, 0x0c, 0xfa, 0xdf, 0xf6, 0x11, 0xda, + 0x2a, 0xdc, 0xfc, 0xff, 0xff, 0xec, 0x12, 0xe1, 0x37, 0xfd, 0xeb, 0xfe, + 0xea, 0xd1, 0x12, 0xfa, 0x28, 0x1a, 0x0d, 0xf0, 0xf7, 0xe0, 0x0c, 0xeb, + 0x35, 0x14, 0xeb, 0x00, 0xeb, 0xe7, 0x1b, 0xfc, 0x09, 0x00, 0xf2, 0x04, + 0xf9, 0xe5, 0x1a, 0x0e, 0x08, 0x12, 0xf8, 0xfe, 0x09, 0x0f, 0x0d, 0xea, + 0x03, 0xe1, 0xfe, 0xf2, 0xec, 0x0d, 0x02, 0xdb, 0x04, 0x1d, 0xd4, 0x01, + 0xca, 0x13, 0x29, 0xca, 0x28, 0x04, 0xe2, 0xf1, 0xdb, 0x0b, 0x2c, 0xcd, + 0x44, 0x00, 0xe7, 0xf4, 0xd0, 0x12, 0x15, 0xff, 0x42, 0x11, 0x05, 0xfd, + 0xd9, 0x11, 0x1c, 0xf4, 0x15, 0xec, 0xf2, 0x24, 0xd6, 0x1d, 0xec, 0xda, + 0xf5, 0xec, 0xe5, 0x22, 0xf2, 0x0b, 0xbd, 0xd0, 0xeb, 0x05, 0x07, 0x1b, + 0x01, 0xed, 0xf5, 0x02, 0xcf, 0x08, 0x15, 0xfd, 0x1c, 0xe5, 0x04, 0x19, + 0xc7, 0x25, 0x22, 0xf3, 0xde, 0xfb, 0xfb, 0x20, 0xf6, 0xeb, 0x25, 0xfe, + 0xf5, 0x08, 0xf5, 0x17, 0x0e, 0x04, 0x1c, 0xf9, 0xee, 0xec, 0xe1, 0x06, + 0x12, 0xff, 0x2a, 0x13, 0xed, 0xfe, 0x05, 0x18, 0x25, 0x20, 0x09, 0x13, + 0xea, 0xd7, 0x05, 0x06, 0x33, 0x25, 0xff, 0x0a, 0xf0, 0xea, 0x17, 0xe1, + 0x30, 0xfa, 0x0d, 0x0a, 0x04, 0x00, 0x0e, 0xe9, 0x16, 0x20, 0x0d, 0x02, + 0xe8, 0xed, 0x07, 0xe8, 0x3c, 0xf1, 0xd9, 0xfa, 0xe1, 0xed, 0x18, 0xfc, + 0xf0, 0x09, 0xe3, 0x05, 0xfe, 0xd1, 0x0b, 0x0e, 0xf5, 0x25, 0xfd, 0xfb, + 0x30, 0x1e, 0x08, 0xfc, 0x0c, 0x21, 0xea, 0xfc, 0xe5, 0x1e, 0x16, 0xf5, + 0xf4, 0xfc, 0xf0, 0xea, 0xc4, 0x21, 0x27, 0xe9, 0x2b, 0xdb, 0xdb, 0xec, + 0xe5, 0xfe, 0x37, 0xe2, 0x46, 0x25, 0xfa, 0xec, 0xe4, 0xf3, 0x19, 0xf2, + 0x4c, 0x06, 0x00, 0xfb, 0xeb, 0x10, 0x10, 0xf7, 0x2a, 0xf8, 0xe9, 0x18, + 0xee, 0x21, 0xe8, 0xd5, 0xf4, 0x0a, 0xed, 0x24, 0xfe, 0xf9, 0xb2, 0xbc, + 0xf3, 0x1d, 0x00, 0x2f, 0x07, 0x08, 0xe1, 0xf1, 0xed, 0x27, 0x27, 0xfe, + 0x22, 0xfd, 0x02, 0x20, 0xd8, 0x05, 0x25, 0xec, 0xf1, 0xff, 0x0a, 0x0f, + 0xe6, 0xfe, 0x46, 0xfd, 0xe1, 0xca, 0xf7, 0x22, 0x03, 0x08, 0x21, 0xf5, + 0x0f, 0xf7, 0xfb, 0x0c, 0xfb, 0x14, 0x2d, 0x03, 0xe5, 0xe4, 0x09, 0x0b, + 0x1a, 0xe6, 0x01, 0x28, 0xe9, 0xd6, 0x0b, 0xf7, 0x2c, 0xfb, 0x11, 0xee, + 0x0b, 0xed, 0x17, 0xf0, 0x3c, 0xf5, 0x08, 0xfa, 0xf8, 0xcd, 0x17, 0xfa, + 0x39, 0xea, 0x11, 0xf5, 0xed, 0xee, 0x0a, 0xec, 0x41, 0xd6, 0xe7, 0xf9, + 0xfa, 0xc8, 0x15, 0xf7, 0x08, 0x0e, 0xe3, 0x08, 0xe8, 0xec, 0xfd, 0xfe, + 0xf1, 0x00, 0xe9, 0xf4, 0x09, 0x26, 0x02, 0x16, 0xf0, 0x01, 0xef, 0x01, + 0xff, 0x03, 0x22, 0xdb, 0xfc, 0xf5, 0xde, 0xe5, 0xc4, 0x01, 0x28, 0xd4, + 0x38, 0x08, 0xd0, 0xec, 0xd5, 0x04, 0x2f, 0xce, 0x4e, 0xeb, 0xf9, 0xe7, + 0xdf, 0xf0, 0x1b, 0xf5, 0x42, 0xf1, 0xf6, 0x09, 0xd5, 0x0a, 0x0d, 0x08, + 0x04, 0x05, 0xe2, 0x0e, 0xd7, 0x19, 0xdb, 0xda, 0xe1, 0x25, 0xde, 0x15, + 0x0e, 0x14, 0xbd, 0xb0, 0xe3, 0xe5, 0x24, 0x1e, 0xf8, 0x0d, 0xd8, 0xf7, + 0xf2, 0xff, 0x18, 0xf5, 0x07, 0xf0, 0x02, 0x25, 0xd5, 0x1e, 0x2e, 0xdf, + 0xe7, 0x05, 0xef, 0x11, 0xe8, 0xe7, 0x47, 0xf4, 0xe1, 0xde, 0x09, 0x36, + 0x1a, 0x11, 0x11, 0xf5, 0x12, 0xe5, 0xe7, 0x18, 0x01, 0x17, 0x2a, 0x03, + 0x05, 0xea, 0x09, 0x0b, 0x12, 0x04, 0x17, 0xf0, 0xee, 0xd7, 0x11, 0xed, + 0x3c, 0x17, 0x16, 0xff, 0x02, 0xdc, 0x21, 0xf3, 0x2e, 0xe5, 0x13, 0xef, + 0xec, 0xe2, 0x10, 0xd0, 0x2e, 0xee, 0xff, 0x01, 0xe0, 0xe5, 0x0b, 0xda, + 0x1f, 0xf8, 0xf6, 0xfb, 0x07, 0xdb, 0x05, 0xf6, 0x0c, 0xf3, 0xf0, 0x10, + 0xf9, 0xf5, 0xf2, 0x0d, 0x10, 0xf7, 0xf6, 0xff, 0x2b, 0x0d, 0x06, 0x1e, + 0xf3, 0x0c, 0xe9, 0x01, 0xf2, 0x23, 0xfe, 0xe9, 0xdd, 0x12, 0xdd, 0xf7, + 0xbb, 0x22, 0x1b, 0xd4, 0x38, 0x29, 0xd4, 0xcf, 0xf5, 0xf9, 0x27, 0xdd, + 0x47, 0x00, 0xf2, 0xe5, 0x09, 0xfc, 0x0e, 0xf9, 0x34, 0x0a, 0x02, 0xfd, + 0xec, 0x25, 0x1d, 0x03, 0x15, 0x09, 0xf1, 0x1b, 0xd0, 0x17, 0xda, 0xda, + 0xe7, 0x07, 0xe3, 0x15, 0xf1, 0x02, 0xb9, 0xce, 0xe6, 0x0c, 0x10, 0x31, + 0xfe, 0xf7, 0xd9, 0xfa, 0xed, 0xed, 0x33, 0xf4, 0x19, 0xe7, 0xfe, 0x3f, + 0xe5, 0x06, 0x2e, 0xe6, 0xf2, 0xdc, 0xf5, 0x18, 0xe6, 0x01, 0x2f, 0xee, + 0xe7, 0xe4, 0xfe, 0x2c, 0x03, 0xf7, 0x20, 0x05, 0x07, 0xe2, 0x06, 0x1e, + 0x05, 0xed, 0x2f, 0x03, 0xea, 0xf8, 0x0e, 0x0c, 0x1f, 0xff, 0x20, 0xf4, + 0xe8, 0xe1, 0x1c, 0xec, 0x22, 0x1e, 0x05, 0xfd, 0xf5, 0xca, 0x30, 0xe9, + 0x30, 0xe4, 0x14, 0xff, 0xf2, 0xdc, 0x17, 0xf8, 0x26, 0xe1, 0x0b, 0x01, + 0x11, 0xc2, 0x02, 0xf1, 0x36, 0x10, 0x02, 0x05, 0xed, 0xf1, 0x15, 0xfa, + 0x17, 0xf8, 0xf7, 0xf1, 0xe8, 0xd3, 0xfd, 0x08, 0xfb, 0x27, 0xf5, 0xf5, + 0x13, 0x06, 0x0b, 0xf0, 0x01, 0xf9, 0xd7, 0x0e, 0xec, 0x12, 0xfe, 0xfd, + 0xee, 0x25, 0xd8, 0xf1, 0xb2, 0x09, 0x1c, 0xbf, 0x34, 0xea, 0xc8, 0xea, + 0xdb, 0x0e, 0x24, 0xde, 0x47, 0xfe, 0xdc, 0xe0, 0xf3, 0x06, 0x20, 0xfe, + 0x2b, 0xf6, 0x18, 0x14, 0xcd, 0x19, 0x16, 0xfe, 0x1a, 0x15, 0xf8, 0x11, + 0xf4, 0x22, 0xd7, 0xcc, 0xdd, 0x15, 0xdc, 0x14, 0xf9, 0x02, 0xbb, 0xca, + 0xe3, 0xf3, 0x0d, 0x1e, 0x2a, 0x0c, 0xe4, 0x05, 0xe0, 0x18, 0x2a, 0x07, + 0x20, 0xed, 0xf6, 0x17, 0xcf, 0xf4, 0x2a, 0xd6, 0xfb, 0xce, 0x03, 0x37, + 0xe2, 0xfd, 0x1d, 0xfb, 0xe5, 0xe0, 0x05, 0x29, 0xef, 0x16, 0x23, 0xf7, + 0x01, 0xf4, 0x0c, 0x14, 0xff, 0xee, 0x31, 0xf9, 0x12, 0xf9, 0x14, 0xf6, + 0x0c, 0xf6, 0x0b, 0x0f, 0xd8, 0xdc, 0xfe, 0x0f, 0x37, 0xfa, 0x01, 0x09, + 0x04, 0xd1, 0x0b, 0x0c, 0x29, 0xf3, 0x0a, 0xf9, 0xed, 0xc2, 0x18, 0xf4, + 0x25, 0x18, 0x0f, 0x08, 0xf7, 0xed, 0x1f, 0xf7, 0x4f, 0x0e, 0xf0, 0xe4, + 0x00, 0xeb, 0xfa, 0x1a, 0x0c, 0x03, 0xe9, 0xfc, 0xf0, 0xcc, 0x06, 0x05, + 0xf2, 0x12, 0x04, 0xe2, 0x16, 0x0a, 0x0a, 0xf3, 0x0b, 0xf3, 0xdc, 0xfd, + 0x10, 0xfc, 0x0e, 0xe2, 0xe0, 0xfe, 0xf0, 0xff, 0xb1, 0x06, 0x1b, 0xe4, + 0x30, 0x13, 0xc6, 0xc3, 0xfa, 0x0c, 0x1e, 0xd9, 0x57, 0x11, 0xe1, 0xd6, + 0xfa, 0xee, 0x1d, 0xf7, 0x37, 0xea, 0xf0, 0x05, 0xef, 0x24, 0x1e, 0xf1, + 0x10, 0xe8, 0xeb, 0x19, 0xd1, 0x18, 0xf5, 0xc8, 0xf8, 0xec, 0xf5, 0x1f, + 0xf2, 0xff, 0xb3, 0xd2, 0xe6, 0x0e, 0x06, 0x2e, 0x07, 0x17, 0xe0, 0xf5, + 0x02, 0xf9, 0x20, 0x07, 0x16, 0x08, 0xe8, 0x1d, 0xd3, 0x08, 0x34, 0xda, + 0xf2, 0xce, 0xfb, 0x1f, 0xe1, 0x00, 0x2d, 0xdb, 0xdf, 0xcc, 0x05, 0xfb, + 0xf7, 0x00, 0x33, 0xf9, 0x0b, 0x01, 0x13, 0x28, 0xf8, 0x07, 0x24, 0xf8, + 0x0f, 0x03, 0x0d, 0xe9, 0x06, 0xfe, 0x18, 0xf9, 0xed, 0xf5, 0x0c, 0xe0, + 0x2c, 0x0e, 0xf9, 0x06, 0xfb, 0xce, 0x27, 0xe8, 0x29, 0x19, 0xf9, 0x01, + 0x0e, 0xc8, 0x25, 0xed, 0x30, 0xeb, 0x01, 0xfe, 0x10, 0xdc, 0x1e, 0x00, + 0x1e, 0x10, 0xf9, 0x00, 0xfc, 0xc8, 0x0e, 0x04, 0x13, 0x04, 0xf0, 0x02, + 0xfe, 0xd8, 0x0f, 0x1b, 0xf7, 0xe1, 0xf8, 0xde, 0x12, 0xe2, 0xef, 0x0a, + 0x02, 0xe0, 0xdd, 0xf1, 0x0e, 0x2a, 0x25, 0x15, 0xeb, 0x02, 0xf4, 0xf0, + 0xbf, 0xfc, 0x27, 0xdc, 0x42, 0x0f, 0xe9, 0xbf, 0xe8, 0x20, 0x33, 0xc9, + 0x3f, 0x10, 0xec, 0xf3, 0x03, 0x02, 0x2c, 0x04, 0x38, 0x06, 0x0a, 0xf9, + 0xe5, 0x1c, 0x3f, 0x0f, 0x0c, 0x25, 0xe2, 0x06, 0xe6, 0x03, 0xf4, 0xd7, + 0xfe, 0xf6, 0xe7, 0x2f, 0xfa, 0x03, 0xb6, 0xcb, 0xf1, 0x11, 0x0a, 0x2c, + 0xfc, 0x1e, 0xe0, 0xff, 0xc2, 0xdd, 0x1d, 0xf3, 0x10, 0xfa, 0x07, 0x1e, + 0xf6, 0x20, 0x07, 0xe6, 0xf1, 0x0a, 0xe8, 0x27, 0xf1, 0xf5, 0x24, 0xed, + 0xfd, 0xee, 0x13, 0x15, 0xe9, 0xe2, 0x22, 0xe5, 0xf9, 0xdd, 0x1d, 0x32, + 0x04, 0xfa, 0x25, 0x00, 0xee, 0xfd, 0x0b, 0x0e, 0x23, 0xfa, 0x0f, 0x01, + 0xf8, 0xf0, 0x15, 0xe4, 0x21, 0xf7, 0x10, 0xf9, 0xe7, 0xc3, 0x19, 0xe1, + 0x34, 0xff, 0xed, 0xf4, 0xef, 0xd7, 0x21, 0x01, 0x31, 0xee, 0xf7, 0xf2, + 0xf3, 0xe5, 0x0a, 0xee, 0x2e, 0x1e, 0xf2, 0x0c, 0x07, 0xc2, 0x08, 0x0a, + 0x14, 0x14, 0x00, 0xfc, 0xf9, 0xd6, 0xfb, 0xf8, 0xe5, 0xf1, 0xfa, 0xe0, + 0x15, 0x21, 0xef, 0x06, 0xf9, 0x00, 0xf5, 0xf4, 0x0b, 0x0b, 0x18, 0x02, + 0xf5, 0x04, 0xdb, 0xfd, 0xcc, 0x32, 0x1d, 0xc9, 0x3b, 0x12, 0xd9, 0xaf, + 0xcf, 0x0f, 0x26, 0xde, 0x35, 0xe4, 0xdb, 0xd3, 0x22, 0x11, 0x2e, 0xfb, + 0x36, 0xfa, 0xfd, 0x02, 0xeb, 0x0f, 0x37, 0x0b, 0x14, 0x1d, 0xdd, 0x18, + 0xe0, 0x10, 0xe0, 0xdf, 0x14, 0xf9, 0xf0, 0x19, 0xf7, 0xfb, 0xc4, 0xe5, + 0xe7, 0x11, 0x01, 0x31, 0x1a, 0xf7, 0xd8, 0xf1, 0xe9, 0xf3, 0x21, 0xf9, + 0xfe, 0xe4, 0xe9, 0x02, 0xd0, 0x06, 0x14, 0xd7, 0xfc, 0xec, 0x06, 0x10, + 0xfc, 0xf0, 0x1c, 0xe7, 0xec, 0xe3, 0x03, 0x21, 0xe4, 0x04, 0x12, 0xf0, + 0xf3, 0xed, 0x16, 0x36, 0x02, 0xfd, 0x13, 0x11, 0xdf, 0xeb, 0x19, 0x07, + 0x10, 0x0c, 0xf9, 0x08, 0xf8, 0xf4, 0x1d, 0xfd, 0x1d, 0x16, 0xf4, 0x0a, + 0x08, 0xec, 0x0c, 0x09, 0x3d, 0xe0, 0x0b, 0xee, 0x10, 0xd1, 0x1e, 0x15, + 0x43, 0xeb, 0xfa, 0xf3, 0x05, 0xc7, 0xf2, 0xd9, 0x25, 0x20, 0xee, 0xe9, + 0xfd, 0xce, 0x16, 0x0c, 0x27, 0x06, 0x0a, 0x06, 0xf9, 0xd6, 0x0b, 0x05, + 0xe8, 0x02, 0xe8, 0xd2, 0x10, 0x01, 0xf2, 0x15, 0x09, 0x04, 0xd3, 0xe2, + 0xfe, 0xf0, 0x32, 0x1b, 0xd9, 0xf5, 0xea, 0xcc, 0xcb, 0x10, 0x1c, 0xf1, + 0x3b, 0x02, 0xd4, 0xbf, 0xca, 0xfe, 0x12, 0xdb, 0x3b, 0xf8, 0xd5, 0xe7, + 0x13, 0x10, 0x1a, 0xf4, 0x38, 0x09, 0x08, 0xee, 0xf4, 0xf4, 0x3c, 0xf7, + 0x15, 0x04, 0xe4, 0xfa, 0xf4, 0x04, 0xee, 0xf4, 0x07, 0xf8, 0xe9, 0x3b, + 0xe2, 0x1f, 0xd5, 0xed, 0xe6, 0xfd, 0x18, 0x49, 0x21, 0x06, 0xd8, 0xde, + 0xfa, 0xf0, 0x1b, 0xfe, 0xde, 0x08, 0xf7, 0x14, 0xc7, 0x0f, 0x1d, 0xcf, + 0x00, 0xea, 0xff, 0x1b, 0xd5, 0x08, 0x0d, 0xd9, 0xf1, 0xf4, 0x16, 0x23, + 0xd8, 0x0c, 0x29, 0xdc, 0xf1, 0xf2, 0x21, 0x49, 0xfc, 0xe2, 0x08, 0x01, + 0xf0, 0xf8, 0x17, 0xf9, 0x0f, 0xf5, 0xfa, 0x1a, 0xef, 0xec, 0x09, 0xeb, + 0x1a, 0x0c, 0x17, 0x09, 0x11, 0xe9, 0x1a, 0xf7, 0x29, 0xf9, 0xfd, 0x07, + 0x01, 0xdd, 0x0a, 0xec, 0x22, 0x15, 0x03, 0xfd, 0xe2, 0xd2, 0x15, 0xec, + 0x4d, 0xd7, 0xfc, 0xf6, 0x0b, 0xcc, 0x0e, 0x04, 0x03, 0xf7, 0xfb, 0xfb, + 0x0d, 0xeb, 0x19, 0x07, 0xf4, 0xf4, 0xe5, 0xde, 0x22, 0x07, 0xea, 0xf7, + 0xeb, 0x23, 0xc8, 0xee, 0x03, 0x04, 0x0f, 0x19, 0xc3, 0xf8, 0x06, 0xd0, + 0xf7, 0xfe, 0x0e, 0xe7, 0x0a, 0x02, 0xb0, 0xb8, 0x00, 0xfb, 0x18, 0x0f, + 0x22, 0xf7, 0xe9, 0xdc, 0x09, 0x15, 0x23, 0x0d, 0x22, 0x13, 0xe2, 0xed, + 0xeb, 0x18, 0x20, 0x0b, 0x12, 0xfc, 0x02, 0xf1, 0xdb, 0x0e, 0xe1, 0x04, + 0xdb, 0x0f, 0xf3, 0x1a, 0x06, 0xef, 0xdb, 0xdc, 0xdd, 0xfb, 0x00, 0x2a, + 0x20, 0xfd, 0xc1, 0xe3, 0xef, 0x01, 0x14, 0xf2, 0x14, 0x00, 0x0f, 0x28, + 0xd9, 0xff, 0xf4, 0xdc, 0x09, 0xfa, 0x1c, 0x08, 0xd1, 0x03, 0x0a, 0xf4, + 0xe4, 0xdb, 0x20, 0x30, 0xea, 0x06, 0x11, 0xe2, 0x26, 0xf7, 0x16, 0x22, + 0xf9, 0x07, 0x02, 0xf5, 0xf6, 0xfb, 0x1d, 0x0c, 0x16, 0x0a, 0x07, 0xf9, + 0x11, 0xde, 0x20, 0x08, 0x19, 0x04, 0x0a, 0x0b, 0x0c, 0xf7, 0xf4, 0xfc, + 0x41, 0xf1, 0xf8, 0x16, 0x09, 0xdc, 0x0e, 0x1a, 0x2b, 0x1f, 0xe7, 0xfe, + 0x01, 0xe0, 0xfd, 0xe2, 0x34, 0xec, 0xf3, 0xf5, 0x03, 0xec, 0x0b, 0xfb, + 0x04, 0xf6, 0xdd, 0xfd, 0x06, 0x14, 0x0d, 0xfa, 0xfc, 0xf1, 0x0a, 0xca, + 0x01, 0xec, 0x0e, 0x0e, 0xec, 0xd7, 0xee, 0xd4, 0xf2, 0xfe, 0x16, 0xfa, + 0xbd, 0x0d, 0xef, 0xcb, 0xc4, 0xee, 0xed, 0x13, 0x10, 0x19, 0xf8, 0xb1, + 0xf1, 0xe3, 0x00, 0xf3, 0x0c, 0xf6, 0xde, 0xc6, 0x15, 0x27, 0x14, 0x29, + 0x15, 0xf6, 0xf4, 0xf5, 0xe7, 0x00, 0x0b, 0x2f, 0x0c, 0xef, 0x03, 0x0f, + 0xfd, 0x08, 0xf3, 0xf9, 0xf9, 0x05, 0x0d, 0x34, 0x15, 0x1b, 0xc8, 0xd1, + 0xf2, 0x1b, 0x0a, 0x22, 0x12, 0x11, 0xe9, 0xf4, 0xe1, 0x2a, 0x20, 0x03, + 0xf2, 0xf8, 0x14, 0x0b, 0xd0, 0xf4, 0x0e, 0xbf, 0xc6, 0xd8, 0x04, 0x05, + 0xf8, 0xf4, 0x04, 0xc9, 0xea, 0xfd, 0xf7, 0xfa, 0xe3, 0x1b, 0x11, 0xde, + 0x0c, 0x11, 0x25, 0x29, 0xe5, 0x02, 0xef, 0xef, 0x02, 0xfa, 0x1a, 0x21, + 0x19, 0x09, 0x08, 0x05, 0x04, 0xe5, 0xfa, 0xed, 0x2d, 0x26, 0xfa, 0x17, + 0xf6, 0xe8, 0x12, 0x12, 0x31, 0xfc, 0x0d, 0x00, 0xf7, 0xeb, 0x19, 0xf1, + 0x2a, 0x06, 0x14, 0xec, 0x08, 0xd3, 0x21, 0x07, 0x32, 0xe3, 0x02, 0x0b, + 0xfb, 0xd8, 0x27, 0x07, 0x05, 0xe6, 0xf5, 0xf5, 0x0a, 0xf7, 0x2c, 0x2a, + 0xd8, 0x1b, 0xda, 0xf7, 0xea, 0xf6, 0xf9, 0x0e, 0xf8, 0x0c, 0x05, 0xc7, + 0xd6, 0x06, 0x12, 0xe3, 0xe1, 0xe1, 0xd8, 0xdb, 0xc6, 0xf8, 0xe6, 0xfa, + 0x0c, 0x07, 0xf8, 0xe7, 0xe1, 0x0f, 0x00, 0xf3, 0x03, 0xf0, 0xde, 0xcc, + 0xf5, 0xfc, 0xef, 0x1e, 0x16, 0x13, 0xfb, 0xf4, 0x03, 0xe9, 0xfc, 0xfa, + 0x15, 0xe8, 0x15, 0x09, 0xf1, 0x0d, 0xdb, 0x0a, 0xe8, 0x09, 0xf5, 0x1a, + 0x04, 0xf8, 0xd8, 0xd4, 0x04, 0xee, 0x25, 0x29, 0x09, 0xfe, 0xf3, 0xf5, + 0xd4, 0x0a, 0x15, 0x19, 0xf5, 0x12, 0xfe, 0x04, 0xe7, 0x01, 0xeb, 0xde, + 0xbe, 0xfe, 0x09, 0x12, 0xdf, 0x13, 0xe0, 0xef, 0xc7, 0xff, 0x03, 0x08, + 0xfe, 0xf2, 0x19, 0xe0, 0xe4, 0x0c, 0x22, 0x1e, 0x05, 0xf7, 0x16, 0xf2, + 0xf9, 0x06, 0x17, 0xf6, 0x0c, 0x1e, 0x23, 0x08, 0xfe, 0xdc, 0xfd, 0x17, + 0x11, 0xdf, 0xf5, 0x0f, 0x01, 0x03, 0x08, 0xee, 0x1b, 0x02, 0x0b, 0x1b, + 0x0c, 0x16, 0x1a, 0x00, 0x0f, 0x26, 0x14, 0xf8, 0xf4, 0xf3, 0x19, 0x16, + 0x22, 0x0a, 0xd0, 0xf9, 0xf1, 0x05, 0x2b, 0x1e, 0x1e, 0xef, 0xf5, 0x06, + 0x05, 0xe7, 0x3f, 0x2a, 0x06, 0xf0, 0x15, 0x14, 0x13, 0x20, 0x1b, 0xde, + 0x10, 0x05, 0x33, 0xf8, 0x08, 0x04, 0x17, 0x0d, 0x0f, 0xf6, 0x01, 0xed, + 0x28, 0x25, 0x1c, 0x13, 0xfb, 0xea, 0xfb, 0xf3, 0x1c, 0xf9, 0x1f, 0xf0, + 0xfb, 0x17, 0xf8, 0xff, 0x10, 0xf7, 0x0b, 0x24, 0x04, 0x00, 0x0d, 0x0c, + 0xf7, 0x0a, 0x16, 0x13, 0xf8, 0x05, 0x0a, 0xf1, 0xf5, 0xee, 0xf8, 0x14, + 0x0e, 0xed, 0xfe, 0x1b, 0xfe, 0x17, 0x13, 0x10, 0x12, 0x21, 0x1c, 0xfa, + 0xe5, 0x0b, 0x08, 0x0c, 0x10, 0x1b, 0x03, 0xef, 0x0d, 0x05, 0x0a, 0xf0, + 0x04, 0x11, 0x15, 0x00, 0xfd, 0xef, 0x02, 0x18, 0xf4, 0x09, 0xfa, 0xf6, + 0x02, 0xf7, 0xfd, 0x13, 0xef, 0x13, 0xf7, 0xf9, 0x17, 0x0f, 0xfa, 0xf8, + 0x15, 0xff, 0x04, 0xef, 0xf0, 0x15, 0xfa, 0xfe, 0xf0, 0xf4, 0xed, 0x06, + 0x1c, 0x02, 0xfb, 0xf7, 0x05, 0xfb, 0x0c, 0xef, 0xf4, 0xf0, 0xf6, 0xec, + 0x17, 0xf3, 0xf5, 0xef, 0x02, 0xfd, 0xe5, 0x21, 0x0c, 0xf1, 0x1e, 0x08, + 0xf1, 0x0b, 0xf7, 0x09, 0x1d, 0xf2, 0xf9, 0xf2, 0xfb, 0x0e, 0xed, 0xf8, + 0xfa, 0xdd, 0xf0, 0xfd, 0xdb, 0x1a, 0xf4, 0xef, 0x0c, 0x06, 0x0f, 0xdf, + 0xe2, 0x06, 0x06, 0xee, 0xfa, 0x0d, 0x17, 0xfc, 0xf9, 0x15, 0x1a, 0xe4, + 0xfb, 0x0c, 0x1a, 0xfc, 0x1b, 0x04, 0x07, 0x20, 0xff, 0x09, 0x0f, 0xf2, + 0x26, 0x19, 0x1f, 0x0d, 0x02, 0x16, 0x03, 0x03, 0xfd, 0x05, 0x01, 0x1b, + 0x0a, 0x11, 0xfa, 0x21, 0x13, 0xfb, 0x0c, 0x05, 0xf3, 0xdd, 0xe4, 0xdc, + 0x22, 0x1b, 0x15, 0x14, 0x0e, 0xe8, 0x00, 0xf7, 0xf8, 0xf4, 0x0b, 0x0b, + 0xfd, 0x21, 0xe3, 0x0f, 0xe1, 0x22, 0x01, 0x21, 0x0b, 0x1f, 0x09, 0x10, + 0xe2, 0x18, 0x11, 0x0e, 0xed, 0x01, 0x14, 0x12, 0xfd, 0x11, 0xf6, 0xe9, + 0x20, 0xe1, 0xf5, 0x1b, 0x27, 0x22, 0xfa, 0xf7, 0xfe, 0x13, 0xf6, 0xdc, + 0x06, 0x0d, 0xf4, 0x05, 0x20, 0x0d, 0x0b, 0xe4, 0x15, 0x28, 0x0c, 0x00, + 0xf5, 0x07, 0x0c, 0x0a, 0x06, 0x0e, 0xf3, 0xfb, 0xfe, 0x04, 0x08, 0xf4, + 0xef, 0x03, 0xe4, 0xeb, 0x06, 0xee, 0xed, 0xdb, 0xeb, 0x1d, 0xf4, 0xfa, + 0x0c, 0xfc, 0xfe, 0x11, 0xf7, 0xf8, 0xf5, 0xef, 0xe7, 0xfc, 0x1b, 0xdc, + 0x17, 0xfd, 0xfe, 0x00, 0xea, 0xf4, 0xf1, 0xf7, 0x0f, 0x21, 0x04, 0xfd, + 0x0d, 0x0c, 0x0a, 0x14, 0xfd, 0x19, 0x09, 0x01, 0xfd, 0xe2, 0x0c, 0x0c, + 0xe0, 0x25, 0xfb, 0xff, 0x0d, 0x18, 0xf6, 0x0b, 0x19, 0x12, 0x10, 0x09, + 0x0b, 0x06, 0x12, 0x1c, 0x10, 0x03, 0x13, 0x0a, 0x05, 0x0f, 0x09, 0x01, + 0x21, 0xe4, 0x01, 0x26, 0xf9, 0xf4, 0x05, 0x19, 0x00, 0xff, 0x0b, 0xff, + 0x16, 0x09, 0xe7, 0xee, 0xed, 0xf5, 0x0f, 0x2f, 0xee, 0x19, 0x03, 0x0a, + 0x10, 0xee, 0xf7, 0x2e, 0xf4, 0x08, 0xf7, 0xee, 0x07, 0x00, 0xfc, 0x0e, + 0xf0, 0x12, 0x08, 0x05, 0xed, 0x11, 0xfc, 0xfb, 0xf7, 0x25, 0xf1, 0x05, + 0x0c, 0xf9, 0xfa, 0x03, 0x0c, 0x16, 0x04, 0x25, 0xf8, 0xe7, 0xfc, 0x11, + 0x0d, 0x19, 0xd8, 0xfa, 0x0b, 0x06, 0xfd, 0xef, 0x13, 0xf6, 0xff, 0x0e, + 0xf9, 0x04, 0xf1, 0xdc, 0xfb, 0xe1, 0xf6, 0x0b, 0x15, 0x07, 0xf7, 0x02, + 0x0e, 0xf1, 0xfd, 0xe3, 0xeb, 0x07, 0xf1, 0xef, 0x03, 0xfe, 0xf8, 0x07, + 0x10, 0xf7, 0x00, 0xf9, 0xf2, 0x0e, 0xf9, 0xf2, 0x1d, 0xf5, 0xd8, 0xff, + 0xe6, 0x18, 0x2a, 0x1b, 0x03, 0x16, 0xfe, 0xf4, 0xf5, 0xfd, 0x04, 0x01, + 0xfe, 0xfe, 0x07, 0xfc, 0x0e, 0xfa, 0x15, 0xeb, 0x02, 0x15, 0xea, 0xfd, + 0x04, 0xe5, 0xfe, 0xed, 0xfe, 0x1a, 0x09, 0x2a, 0x1b, 0xdf, 0xfb, 0xf8, + 0xf1, 0x04, 0x1a, 0x34, 0x07, 0xf9, 0x0d, 0xf5, 0xef, 0xec, 0x10, 0x1a, + 0x0b, 0x0f, 0x13, 0xfe, 0x10, 0x22, 0x1e, 0x02, 0xe6, 0xf7, 0x11, 0xfa, + 0x11, 0xfc, 0x1b, 0x21, 0x12, 0xf4, 0x18, 0x16, 0x29, 0xe4, 0x0c, 0x2e, + 0x12, 0x07, 0x20, 0xf6, 0x1d, 0xf4, 0x12, 0x33, 0xf4, 0xee, 0xfe, 0x05, + 0x06, 0xfb, 0x13, 0x0c, 0x0e, 0xf0, 0x00, 0xf8, 0xee, 0xf3, 0x17, 0x00, + 0xf7, 0xfb, 0xfc, 0x0f, 0xf4, 0xd5, 0x0a, 0xed, 0xeb, 0xf5, 0xe9, 0xef, + 0xd8, 0xf0, 0xf8, 0xe2, 0x19, 0xf7, 0xf8, 0x0a, 0x0b, 0x09, 0xfa, 0xe7, + 0x0f, 0xfc, 0xe8, 0x02, 0x00, 0x1a, 0xfe, 0xfd, 0x1b, 0xe6, 0xef, 0x0f, + 0xe3, 0x10, 0xf1, 0xe2, 0x0b, 0x0e, 0x06, 0x29, 0x00, 0x01, 0xf3, 0x00, + 0x11, 0x04, 0xf2, 0xf7, 0xea, 0xf8, 0xe0, 0x09, 0x0e, 0x13, 0xf4, 0x00, + 0x09, 0xfa, 0xf5, 0x0c, 0xff, 0x18, 0x08, 0x0d, 0xfa, 0xde, 0xfa, 0x03, + 0xf2, 0xf3, 0x1b, 0xeb, 0x06, 0xea, 0xfb, 0xff, 0x0d, 0xf5, 0x10, 0x17, + 0xf8, 0xe8, 0xf1, 0xf1, 0xf5, 0x00, 0x03, 0x0a, 0x09, 0x0a, 0xf3, 0xfb, + 0x33, 0x26, 0xe7, 0x17, 0xe3, 0xfa, 0x1f, 0x24, 0xfc, 0x07, 0x02, 0xe2, + 0xeb, 0x08, 0x2c, 0xf8, 0x02, 0x1f, 0x04, 0xeb, 0x0b, 0x04, 0x17, 0xf7, + 0xff, 0x1c, 0xed, 0x00, 0x3f, 0xd5, 0x17, 0x1d, 0xfe, 0x03, 0xf1, 0x1c, + 0x17, 0xec, 0x0e, 0x54, 0xee, 0xf5, 0x25, 0xfa, 0x08, 0xee, 0x13, 0x32, + 0x0e, 0xd8, 0x09, 0x0f, 0xee, 0xe5, 0x06, 0x10, 0xf4, 0xfb, 0xe4, 0xfb, + 0x09, 0xde, 0x13, 0xff, 0x02, 0xf9, 0xec, 0x0a, 0x00, 0xe9, 0xfd, 0xdc, + 0x06, 0x04, 0xdb, 0x06, 0x01, 0xf8, 0x09, 0xe2, 0x0c, 0x14, 0xda, 0xfe, + 0x20, 0xe3, 0x09, 0xda, 0x14, 0x12, 0xe1, 0x05, 0xff, 0xf3, 0x00, 0x08, + 0xfb, 0xf1, 0xfd, 0xf3, 0x04, 0xfa, 0x08, 0xff, 0x01, 0x1d, 0x0b, 0xfd, + 0x0a, 0xf4, 0xfb, 0xfc, 0xf9, 0x19, 0xed, 0xfc, 0xf2, 0x06, 0xe7, 0x02, + 0xf6, 0x0c, 0xfc, 0xfb, 0x01, 0x0c, 0xeb, 0x1b, 0xff, 0xff, 0x08, 0x1d, + 0xf7, 0xe8, 0xfc, 0xf4, 0x0c, 0xfa, 0xf1, 0xee, 0xed, 0xdd, 0xfc, 0x06, + 0x05, 0xdc, 0x1a, 0xfc, 0xf9, 0x07, 0xdf, 0x1b, 0x14, 0x0c, 0xfc, 0x01, + 0x16, 0xe1, 0xed, 0x09, 0x34, 0xee, 0xe4, 0x1c, 0x1b, 0xfc, 0x3b, 0x03, + 0x15, 0xf2, 0xeb, 0x14, 0x00, 0xdd, 0x24, 0x04, 0xf1, 0xed, 0xfd, 0xe6, + 0x32, 0xf9, 0x24, 0x04, 0x0e, 0x22, 0x03, 0x14, 0x2f, 0xf5, 0x1a, 0x37, + 0xf4, 0x18, 0x03, 0x0f, 0x4b, 0xe6, 0x0d, 0x5c, 0xf7, 0x1f, 0x1c, 0xe6, + 0x23, 0x0c, 0x15, 0x4e, 0xe0, 0x05, 0x1c, 0xec, 0xff, 0x04, 0x13, 0x15, + 0xee, 0x07, 0xec, 0x0c, 0xdd, 0xf8, 0x0e, 0x03, 0x0c, 0x1f, 0xe8, 0x0e, + 0xf5, 0xec, 0xfc, 0xe2, 0xe8, 0xfb, 0xf6, 0x00, 0xe5, 0xea, 0xf3, 0xd3, + 0xf5, 0xfd, 0xd2, 0xfd, 0x1b, 0xed, 0x09, 0xd1, 0x23, 0xfa, 0xd4, 0xf7, + 0xe9, 0xf0, 0x0a, 0xd6, 0x14, 0x03, 0xe6, 0x10, 0xf4, 0x18, 0xfe, 0xe1, + 0x0b, 0x25, 0xf5, 0xfc, 0xe9, 0xf2, 0xe9, 0xf4, 0x0d, 0xf5, 0x00, 0xf9, + 0x17, 0x02, 0xfd, 0x03, 0x04, 0xf8, 0xf5, 0x14, 0xe3, 0xd3, 0xeb, 0xe7, + 0x09, 0xf3, 0x14, 0x17, 0xee, 0xe6, 0xf6, 0xff, 0x11, 0x26, 0xf4, 0xf7, + 0x02, 0xfa, 0x05, 0x08, 0x16, 0xff, 0x0d, 0xf7, 0xf1, 0xf7, 0xe6, 0xfb, + 0x04, 0x04, 0x07, 0x02, 0x04, 0x09, 0xf5, 0xfc, 0x5f, 0xd6, 0xe7, 0x2a, + 0x23, 0xf4, 0x1b, 0x06, 0x01, 0xea, 0xe7, 0x05, 0x25, 0xe3, 0x25, 0x07, + 0xea, 0xfb, 0xfb, 0x09, 0x25, 0xde, 0x37, 0x04, 0x07, 0xe5, 0xff, 0x14, + 0x2f, 0x0a, 0x30, 0x23, 0x04, 0xf0, 0x23, 0xfe, 0x1c, 0xd2, 0x2b, 0x55, + 0x01, 0xe5, 0x26, 0xfe, 0x14, 0xed, 0x24, 0x46, 0xe6, 0xee, 0x0f, 0xfd, + 0xed, 0xef, 0x0e, 0x1e, 0x05, 0x0a, 0x12, 0xff, 0xe4, 0xf5, 0x0c, 0xed, + 0xfd, 0xea, 0x0d, 0x13, 0x1a, 0xe5, 0xfc, 0xc2, 0xef, 0x0a, 0xe2, 0x0f, + 0xfe, 0xff, 0x0c, 0xf0, 0xff, 0xdf, 0xea, 0x00, 0xf6, 0xe1, 0x04, 0xd8, + 0x26, 0x20, 0xdc, 0xf4, 0x19, 0x06, 0xe8, 0xd2, 0x10, 0x04, 0xf1, 0x02, + 0x0c, 0x06, 0xf0, 0xf0, 0x04, 0x1f, 0xf4, 0xf5, 0xed, 0xf1, 0xfa, 0xf1, + 0x04, 0x02, 0xf8, 0xfb, 0x04, 0xf1, 0xe5, 0xe4, 0x0a, 0xf0, 0xfe, 0xef, + 0x1c, 0xe3, 0xeb, 0xf3, 0x00, 0x17, 0x01, 0x13, 0x19, 0xda, 0xf8, 0x06, + 0xde, 0x11, 0xea, 0xf7, 0xf4, 0xef, 0x03, 0x04, 0x0b, 0xe8, 0x08, 0x0e, + 0xe2, 0xee, 0xde, 0x06, 0x0e, 0x29, 0xfb, 0xfa, 0x00, 0x02, 0xec, 0x1b, + 0x52, 0xff, 0xde, 0x3a, 0x2f, 0x13, 0x30, 0xe9, 0xff, 0xf6, 0xe7, 0x15, + 0x1d, 0xd9, 0x3c, 0x0f, 0xe6, 0x14, 0xee, 0x13, 0x1f, 0xe7, 0x33, 0x08, + 0xfc, 0x06, 0x0c, 0x08, 0x19, 0xd9, 0x2b, 0x1f, 0x07, 0x10, 0x24, 0x16, + 0x29, 0xfc, 0x31, 0x4d, 0xf0, 0xd9, 0x3f, 0xf2, 0x20, 0xe2, 0x25, 0x49, + 0xe5, 0xec, 0x0a, 0xf5, 0xf2, 0xd9, 0x22, 0x1f, 0xed, 0x22, 0x02, 0x0a, + 0x16, 0x08, 0xf7, 0xfb, 0x0e, 0xfb, 0xfb, 0x1d, 0xf3, 0x1c, 0xf6, 0xe1, + 0xcf, 0x19, 0xf4, 0x0f, 0xee, 0xf9, 0x04, 0xd1, 0xf9, 0xe2, 0xda, 0xf1, + 0x24, 0xf5, 0x07, 0xdf, 0x1d, 0xf9, 0xdb, 0x18, 0x0b, 0xea, 0x08, 0xca, + 0xf2, 0xfa, 0xec, 0x04, 0x0e, 0x17, 0xed, 0xf1, 0x06, 0x15, 0xfc, 0xfd, + 0x08, 0xfa, 0xe3, 0xe4, 0x0a, 0xfc, 0xee, 0x08, 0xf5, 0x09, 0xef, 0xee, + 0x06, 0xef, 0xe1, 0x19, 0x07, 0xe8, 0xe6, 0xdf, 0xea, 0x0d, 0xf1, 0x16, + 0xee, 0xed, 0xf8, 0x09, 0xfa, 0xfb, 0x0c, 0xf8, 0xeb, 0xda, 0x00, 0xfc, + 0x04, 0xfe, 0xf5, 0xff, 0xf6, 0xe1, 0x0c, 0x0a, 0x13, 0x0d, 0xf6, 0xf5, + 0x15, 0x07, 0xca, 0xec, 0x50, 0x0e, 0xd0, 0x26, 0x4c, 0xf8, 0x23, 0xeb, + 0xff, 0x08, 0xe3, 0x11, 0x2c, 0xf9, 0x2a, 0xf1, 0xe9, 0x0b, 0xe9, 0x0f, + 0x15, 0xec, 0x33, 0x11, 0x0c, 0x0d, 0x01, 0x01, 0x32, 0xe3, 0x41, 0x27, + 0x11, 0x02, 0x2e, 0x07, 0x09, 0xe3, 0x22, 0x4d, 0xf1, 0x05, 0x27, 0x03, + 0x25, 0xf5, 0x2c, 0x3b, 0xf4, 0x00, 0x16, 0x0b, 0xec, 0xfe, 0x17, 0x0d, + 0xff, 0xe7, 0xfe, 0x24, 0x06, 0xee, 0xf0, 0xe9, 0xfa, 0x1c, 0xf2, 0x19, + 0x08, 0xfa, 0xff, 0xd2, 0x01, 0x02, 0xea, 0x05, 0xf2, 0xf4, 0x0b, 0xd2, + 0xf9, 0x0d, 0xcd, 0x0d, 0x12, 0xf2, 0x0e, 0xe1, 0x1f, 0x00, 0xe7, 0x14, + 0x04, 0xff, 0x09, 0xdb, 0xfc, 0xd9, 0x06, 0xf9, 0xeb, 0x01, 0xef, 0xfa, + 0xfb, 0xf5, 0xfc, 0xfb, 0x14, 0xe2, 0xf9, 0xf5, 0x02, 0xfd, 0xfc, 0x01, + 0xf7, 0xf3, 0x00, 0xec, 0xe7, 0xf2, 0x00, 0xf1, 0x11, 0xec, 0xf0, 0xe9, + 0x11, 0x0a, 0x07, 0x04, 0x01, 0xee, 0xfb, 0xf2, 0x14, 0x01, 0x12, 0xf0, + 0xf2, 0xf1, 0xf0, 0xfb, 0x08, 0x03, 0xf8, 0x01, 0xe8, 0xf9, 0x17, 0x26, + 0x0f, 0xea, 0xf7, 0xf8, 0x1e, 0xfe, 0xf2, 0xf8, 0x3f, 0x00, 0xd4, 0x1c, + 0x53, 0xfe, 0x1e, 0x0f, 0xef, 0xdd, 0xed, 0x10, 0x19, 0xe7, 0x34, 0x0e, + 0xde, 0xdf, 0xfa, 0x0e, 0x29, 0xe3, 0x16, 0x09, 0x06, 0x12, 0xeb, 0xf9, + 0x32, 0xe0, 0x1a, 0x1d, 0xf3, 0xed, 0x10, 0x07, 0x31, 0xf2, 0x12, 0x52, + 0xeb, 0xf7, 0x1e, 0xf7, 0x1a, 0xdc, 0x3e, 0x33, 0xe3, 0xfb, 0x1f, 0x0b, + 0x08, 0xfe, 0x13, 0x1a, 0xf4, 0xf8, 0xfe, 0x08, 0xfc, 0xe9, 0xfe, 0xeb, + 0xe6, 0xf6, 0x02, 0x18, 0x02, 0xe8, 0xfb, 0xf3, 0x01, 0x08, 0xd7, 0x13, + 0x04, 0xe6, 0x02, 0xe6, 0xd7, 0x01, 0xd4, 0xf0, 0x0e, 0x05, 0x18, 0xe5, + 0x08, 0xe5, 0xd2, 0x16, 0x12, 0xfe, 0x0e, 0xd3, 0xfc, 0x1f, 0xe9, 0xf8, + 0x11, 0x06, 0xf3, 0xd5, 0xf8, 0xff, 0xf0, 0x04, 0x0a, 0xd9, 0xf8, 0xfd, + 0xf5, 0x12, 0xff, 0x06, 0x1b, 0xe6, 0xfe, 0xfe, 0xde, 0xee, 0xf6, 0x18, + 0xf1, 0xf8, 0x06, 0xf3, 0x02, 0xea, 0x04, 0x14, 0xfc, 0xee, 0xe6, 0x09, + 0xf9, 0xee, 0xe3, 0xe7, 0xfc, 0xd9, 0xef, 0xfc, 0x0a, 0x0c, 0x03, 0xf6, + 0xe2, 0x11, 0x0f, 0x19, 0x18, 0x10, 0xef, 0xe5, 0x22, 0xf5, 0xe5, 0xe9, + 0x4b, 0xf7, 0xdb, 0x0c, 0x4f, 0xde, 0x22, 0x16, 0x09, 0x16, 0xd1, 0xf8, + 0x19, 0xe0, 0x24, 0xfe, 0xb8, 0xfb, 0xe5, 0x12, 0x1c, 0xe3, 0x22, 0x09, + 0x05, 0x29, 0xf7, 0x10, 0x31, 0xe1, 0x33, 0x3f, 0xfd, 0xed, 0x04, 0x03, + 0x2e, 0xed, 0x30, 0x36, 0xee, 0x16, 0x2f, 0xf5, 0x1b, 0xdc, 0x3a, 0x56, + 0xe5, 0xef, 0x26, 0xff, 0x03, 0xd7, 0x31, 0x16, 0xef, 0xf1, 0x08, 0x13, + 0x01, 0x02, 0x03, 0xf1, 0xf2, 0x08, 0xff, 0x05, 0x12, 0xf2, 0xee, 0xda, + 0xed, 0xec, 0xea, 0xf7, 0x0c, 0xf1, 0x09, 0xe6, 0xe6, 0x00, 0xcc, 0x10, + 0x0d, 0x0d, 0x20, 0xf4, 0x18, 0x23, 0xec, 0xf9, 0x00, 0xe4, 0x07, 0xd4, + 0xfb, 0x16, 0xd2, 0x01, 0xe6, 0x01, 0x06, 0xf0, 0xfe, 0x03, 0xf3, 0x09, + 0x01, 0x0d, 0x05, 0xf7, 0xd4, 0x02, 0xfb, 0xfb, 0x08, 0xf0, 0x1f, 0xf3, + 0xfe, 0xeb, 0x02, 0x0e, 0x1b, 0x0f, 0x04, 0xf5, 0xf0, 0x1f, 0x14, 0xf7, + 0x06, 0xdc, 0xf9, 0xe9, 0x01, 0xff, 0x08, 0xf2, 0x06, 0xff, 0xff, 0xf3, + 0x05, 0x1a, 0xfc, 0xfa, 0xeb, 0xfb, 0xfa, 0x12, 0x20, 0xf6, 0xe0, 0xe8, + 0x1c, 0xfa, 0xd6, 0x0d, 0x2c, 0x04, 0xe1, 0x09, 0x3b, 0xd3, 0x2a, 0xee, + 0xf7, 0xed, 0xf1, 0xf7, 0x0d, 0xf0, 0x32, 0x0f, 0xc9, 0x0e, 0x00, 0x10, + 0x24, 0xfb, 0x31, 0xf0, 0xf4, 0xdd, 0xf5, 0x04, 0x25, 0xc7, 0x27, 0x25, + 0x16, 0x11, 0x2e, 0x09, 0x30, 0xd1, 0x2c, 0x34, 0xe6, 0xf0, 0x21, 0xf5, + 0x21, 0xc8, 0x40, 0x39, 0xde, 0xf0, 0x12, 0xf3, 0x10, 0xe8, 0x1f, 0x18, + 0xfa, 0xea, 0x07, 0x11, 0xdf, 0xed, 0xfa, 0xf0, 0x07, 0xef, 0xf3, 0x05, + 0x10, 0xe5, 0xf3, 0xe9, 0xe9, 0xe8, 0xd6, 0x01, 0xf9, 0x05, 0x0b, 0xee, + 0xf9, 0x12, 0xe3, 0x05, 0xfd, 0xe6, 0x16, 0xe2, 0x1b, 0x12, 0xc5, 0x00, + 0xfd, 0x02, 0x04, 0xd2, 0xff, 0xec, 0xf6, 0xfd, 0x00, 0xe4, 0xf7, 0xf3, + 0xeb, 0xfa, 0xf8, 0x0d, 0x03, 0xfa, 0xfe, 0xe4, 0xdb, 0xe3, 0x06, 0xff, + 0xf4, 0xf2, 0x1b, 0xf1, 0xf7, 0x02, 0x01, 0x04, 0x13, 0xe5, 0x0c, 0x05, + 0xf7, 0x0a, 0x03, 0x03, 0x0b, 0x03, 0xee, 0xf7, 0x21, 0x20, 0xff, 0xf3, + 0x09, 0xe5, 0xff, 0xec, 0x17, 0x00, 0x06, 0x14, 0xeb, 0xf2, 0x18, 0x16, + 0x1f, 0xec, 0xee, 0xe1, 0x1e, 0x03, 0xfa, 0xfe, 0x28, 0x03, 0xc9, 0x0c, + 0x3f, 0xd8, 0x30, 0x16, 0x03, 0xf8, 0xe9, 0xfb, 0x28, 0xe1, 0x36, 0x0a, + 0xdf, 0xe5, 0xeb, 0x08, 0x1c, 0xcd, 0x29, 0xf2, 0xfc, 0x0a, 0xed, 0x01, + 0x29, 0xf1, 0x20, 0x13, 0x04, 0xec, 0x17, 0x0a, 0x35, 0xc3, 0x1a, 0x46, + 0xe0, 0xd7, 0x3c, 0x09, 0x28, 0xd1, 0x22, 0x20, 0xd5, 0xfa, 0x28, 0xfa, + 0xff, 0xea, 0x1d, 0x23, 0xe0, 0x07, 0x07, 0x0f, 0xf1, 0xf1, 0x08, 0xf0, + 0xf8, 0xff, 0x05, 0x1b, 0x05, 0xfa, 0xf0, 0xfb, 0xe3, 0xe4, 0xcc, 0x1a, + 0xf9, 0x09, 0x06, 0xee, 0xf4, 0x03, 0xd0, 0x14, 0xf4, 0xff, 0x1d, 0xe8, + 0x11, 0xf4, 0xd1, 0xf4, 0x04, 0x0b, 0xfb, 0xdc, 0x0a, 0x0c, 0xeb, 0xed, + 0x06, 0xf3, 0x04, 0xdd, 0xdf, 0xf9, 0xea, 0xfc, 0xf5, 0xf2, 0xfb, 0xea, + 0xe3, 0x03, 0xee, 0x0e, 0xff, 0xdb, 0x1e, 0x04, 0xf7, 0x1a, 0x04, 0x0c, + 0x0d, 0xda, 0x04, 0xe9, 0xff, 0x04, 0x00, 0x0c, 0xf9, 0xe4, 0xfb, 0xf6, + 0x14, 0xde, 0x1b, 0x00, 0x0b, 0xfe, 0x06, 0xf8, 0x0f, 0xdc, 0x01, 0xef, + 0xef, 0x0d, 0xf8, 0xf1, 0x0f, 0xf9, 0xf9, 0xdf, 0x0d, 0xe4, 0xd9, 0xf9, + 0x2b, 0xee, 0xe8, 0x09, 0x40, 0xf9, 0x2f, 0x0a, 0xfa, 0xe8, 0xe9, 0x01, + 0x0e, 0xe7, 0x23, 0x0a, 0xd0, 0x19, 0xd3, 0x0e, 0x04, 0xda, 0x2b, 0x0f, + 0xe7, 0xe6, 0xf3, 0xfb, 0x2c, 0xd3, 0x36, 0x19, 0x0e, 0xfe, 0x03, 0x1a, + 0x2e, 0xd0, 0x23, 0x32, 0xf1, 0xe1, 0x2a, 0x09, 0x1b, 0xf6, 0x29, 0x3e, + 0xce, 0x15, 0x0a, 0xe8, 0xec, 0xdf, 0x44, 0x28, 0xd9, 0xfd, 0xfa, 0x09, + 0xff, 0xe7, 0x08, 0xec, 0xf4, 0xef, 0x01, 0x19, 0x11, 0xf3, 0xeb, 0xeb, + 0xed, 0x1a, 0xdd, 0x15, 0x0f, 0x07, 0xfe, 0xeb, 0xff, 0xd6, 0xd5, 0x04, + 0xf5, 0x07, 0x10, 0xe6, 0x0c, 0xe4, 0xda, 0x0c, 0x08, 0xee, 0x06, 0xd8, + 0xf8, 0xf1, 0xe0, 0x01, 0x08, 0xfe, 0xf9, 0xf3, 0xdf, 0x03, 0xe6, 0xf4, + 0x0a, 0xff, 0xf2, 0xe0, 0xd9, 0xeb, 0x01, 0x10, 0x02, 0xfc, 0x0d, 0x14, + 0xea, 0xf8, 0x03, 0x18, 0xf3, 0x09, 0xfc, 0x0c, 0x0b, 0x1f, 0xf5, 0x05, + 0xf7, 0xf9, 0x00, 0xfd, 0x04, 0xfc, 0x16, 0x07, 0x00, 0xdf, 0xf9, 0xfa, + 0x0c, 0xfb, 0xf4, 0xf7, 0xf0, 0xeb, 0x07, 0x17, 0x20, 0xfb, 0xf0, 0xec, + 0x04, 0x00, 0xf8, 0xf2, 0x2d, 0xf9, 0xd9, 0x0b, 0x55, 0xec, 0x33, 0x26, + 0xf8, 0x0a, 0xf2, 0x0b, 0x25, 0xdf, 0x29, 0x05, 0xd1, 0x14, 0xe2, 0xf2, + 0x12, 0xdd, 0x28, 0xfc, 0xec, 0x08, 0xfd, 0x02, 0x3a, 0xe6, 0x29, 0x25, + 0x0d, 0x10, 0x09, 0x0a, 0x32, 0xf5, 0x17, 0x2d, 0xea, 0xfb, 0x35, 0xfc, + 0x28, 0xd0, 0x29, 0x2f, 0xcb, 0x06, 0x0f, 0x04, 0xf2, 0xf3, 0x34, 0x1c, + 0xf4, 0x08, 0x05, 0xfc, 0xfd, 0xed, 0x0f, 0xf8, 0xe9, 0xf0, 0x09, 0x16, + 0xfe, 0x02, 0xff, 0xd4, 0xea, 0x0a, 0xeb, 0x0c, 0xf8, 0xf4, 0x09, 0xf4, + 0xf2, 0x07, 0xd9, 0x0b, 0xfd, 0xe4, 0x1a, 0xef, 0x14, 0x08, 0xd8, 0xfc, + 0xf5, 0xe1, 0x03, 0xcf, 0xf1, 0x11, 0xdb, 0x15, 0x07, 0x10, 0xf8, 0xfc, + 0xe2, 0xf1, 0xf5, 0xde, 0xff, 0xe7, 0x01, 0xea, 0xee, 0xe9, 0x02, 0x0a, + 0x18, 0xec, 0xfe, 0xf9, 0x09, 0xf3, 0x0e, 0x02, 0xf1, 0xfc, 0xf9, 0x16, + 0x05, 0x07, 0x09, 0x0d, 0x0e, 0xf7, 0x04, 0xed, 0x04, 0xdb, 0x04, 0x04, + 0xf6, 0xdc, 0xee, 0xec, 0xf5, 0xfe, 0xf4, 0x02, 0xe4, 0x0b, 0xe0, 0x17, + 0x0a, 0xe0, 0xf7, 0xdc, 0x11, 0xd6, 0xfe, 0xfa, 0x35, 0xde, 0xe6, 0x06, + 0x44, 0xf9, 0x35, 0x0a, 0xfb, 0xff, 0xec, 0xfb, 0x16, 0xd9, 0x23, 0x0f, + 0xd4, 0xef, 0xdf, 0x06, 0x0b, 0xd9, 0x25, 0xff, 0xf8, 0xeb, 0xf4, 0x0a, + 0x20, 0xe5, 0x22, 0x1c, 0xeb, 0xf4, 0x0d, 0x0c, 0x19, 0xe1, 0x1e, 0x31, + 0xe9, 0xfb, 0x20, 0xf0, 0x23, 0xfe, 0x35, 0x28, 0xb4, 0x06, 0x28, 0xe7, + 0xfb, 0xe9, 0x2a, 0x1a, 0xef, 0x15, 0x0c, 0xed, 0xf1, 0x04, 0x0e, 0x0a, + 0xff, 0x16, 0x01, 0x04, 0x17, 0xea, 0xec, 0xdc, 0xf4, 0xf7, 0x04, 0x16, + 0x1f, 0x0a, 0x11, 0xef, 0x12, 0xdf, 0xd9, 0x0c, 0xf5, 0x10, 0x02, 0xf3, + 0x10, 0x03, 0xd3, 0xf5, 0x0b, 0x02, 0x00, 0xcb, 0xf6, 0x23, 0xf6, 0xf1, + 0x1f, 0xf9, 0xfc, 0xf0, 0xf6, 0xfe, 0xfa, 0xf8, 0xf9, 0xf4, 0xfb, 0x0a, + 0xd6, 0x29, 0x09, 0x02, 0x00, 0xfc, 0xfc, 0xee, 0xf5, 0x05, 0xfb, 0x1e, + 0xf1, 0xf1, 0xf3, 0x02, 0xec, 0x1c, 0x0c, 0x0e, 0x0b, 0x04, 0xf6, 0xe7, + 0x14, 0x08, 0x27, 0x01, 0xfe, 0xe5, 0xe7, 0x01, 0x1b, 0xf0, 0xf6, 0xff, + 0xf4, 0xe7, 0xee, 0x18, 0x0d, 0x08, 0xf8, 0xd6, 0x07, 0xf4, 0x08, 0xff, + 0x1d, 0x13, 0xe7, 0x0b, 0x42, 0xef, 0x28, 0x00, 0xf9, 0xf0, 0xf3, 0x00, + 0x15, 0xfd, 0x1a, 0x22, 0xc1, 0xf5, 0xe0, 0xf8, 0x09, 0xe6, 0x0e, 0x05, + 0xf9, 0xf6, 0x01, 0x01, 0x13, 0xdc, 0x1f, 0x0d, 0xfb, 0x04, 0x08, 0x0b, + 0x15, 0xdb, 0x28, 0x34, 0xed, 0x0b, 0x3a, 0xed, 0x16, 0xe3, 0x39, 0x32, + 0xc4, 0x0b, 0x20, 0xe7, 0xf7, 0x02, 0x35, 0x24, 0xfc, 0xe8, 0x1c, 0xf8, + 0xf1, 0xfa, 0x0c, 0x1d, 0xf2, 0x05, 0xff, 0x12, 0x0f, 0x01, 0xec, 0xea, + 0xf0, 0x03, 0xe7, 0x15, 0xfd, 0x05, 0x08, 0xe0, 0x1b, 0xf8, 0xe1, 0x1e, + 0xed, 0xdc, 0x11, 0xeb, 0xfd, 0x1a, 0xeb, 0x09, 0xf9, 0xf3, 0x00, 0xe8, + 0xe6, 0x08, 0xf7, 0xde, 0x1e, 0x00, 0x00, 0x00, 0xe4, 0x09, 0xf2, 0xf8, + 0xe7, 0xf2, 0x0d, 0xfa, 0xe2, 0x0f, 0x04, 0x08, 0xf2, 0x13, 0xf8, 0xf9, + 0xf1, 0xff, 0x03, 0x11, 0x12, 0xe9, 0xf4, 0x13, 0x07, 0x0c, 0x13, 0x2b, + 0xf7, 0xdd, 0xf9, 0xe9, 0xfa, 0xdb, 0x1d, 0xf6, 0xf6, 0xf9, 0xe4, 0xf6, + 0x0d, 0xeb, 0x0d, 0x08, 0xe7, 0xe7, 0xf2, 0x03, 0x1d, 0xd9, 0xd8, 0xe4, + 0xf7, 0xea, 0xdc, 0xdc, 0x26, 0x02, 0xee, 0xfa, 0x38, 0xfc, 0x1a, 0xef, + 0xda, 0xf1, 0xdf, 0x0b, 0x1a, 0xe0, 0x16, 0x16, 0xdc, 0x04, 0xfa, 0xf7, + 0xee, 0x02, 0x25, 0x02, 0xf5, 0xfb, 0x08, 0xf6, 0x11, 0xf5, 0x12, 0x08, + 0xf4, 0xe3, 0x1b, 0xf5, 0x3a, 0xdc, 0x20, 0x2e, 0xe0, 0xf5, 0x30, 0xe4, + 0x09, 0xf8, 0x3c, 0x45, 0xd3, 0x08, 0x23, 0xd8, 0x09, 0xe4, 0x35, 0x30, + 0xe4, 0xfe, 0x07, 0xf6, 0x05, 0x01, 0x05, 0xff, 0xf6, 0x0d, 0x02, 0xfd, + 0x03, 0x05, 0x0d, 0x00, 0xf5, 0xd6, 0xcf, 0x19, 0x06, 0xee, 0x0d, 0xf2, + 0x01, 0x18, 0xef, 0x12, 0x04, 0x02, 0x21, 0xd9, 0x02, 0x0d, 0xeb, 0xe9, + 0x13, 0x08, 0x15, 0xf0, 0xee, 0x03, 0xec, 0x06, 0x17, 0xed, 0x00, 0x1a, + 0xee, 0xf2, 0xfc, 0x09, 0xec, 0xf8, 0xf8, 0x18, 0xf4, 0x13, 0x04, 0xf6, + 0x02, 0xf0, 0xfc, 0xfe, 0xe3, 0x01, 0x0a, 0x1c, 0x1b, 0xec, 0x0e, 0x01, + 0xfb, 0x08, 0x11, 0xf5, 0x00, 0x14, 0xe6, 0x12, 0x07, 0xf4, 0x15, 0x07, + 0xfc, 0xfb, 0xf5, 0xf1, 0x01, 0x21, 0x01, 0xe9, 0xe8, 0xef, 0xdb, 0xdf, + 0x1f, 0x0a, 0xdd, 0xd1, 0x16, 0x04, 0xfd, 0xe1, 0x24, 0xf0, 0xec, 0xf4, + 0x38, 0xe1, 0x16, 0xfd, 0xe0, 0xec, 0xe7, 0x0c, 0x2a, 0x04, 0x0c, 0x17, + 0xdc, 0xe8, 0xf2, 0x03, 0xec, 0xfd, 0x19, 0xfe, 0xf3, 0xf0, 0xf3, 0xfb, + 0x18, 0xdf, 0x1c, 0x00, 0x09, 0xf4, 0x18, 0x0b, 0x1f, 0xf6, 0x34, 0x22, + 0xf4, 0x22, 0x45, 0xeb, 0x23, 0xcf, 0x32, 0x34, 0xf2, 0xf9, 0x29, 0xd4, + 0xf7, 0x0b, 0x38, 0x2a, 0x09, 0xe6, 0x05, 0x01, 0x0b, 0xfe, 0x17, 0xfb, + 0x00, 0xeb, 0x08, 0xfd, 0x0c, 0x02, 0x1d, 0xea, 0xfa, 0x0b, 0xeb, 0x09, + 0xfe, 0xfe, 0x10, 0xe0, 0xf6, 0x06, 0xf0, 0x15, 0xf3, 0x09, 0x11, 0xe4, + 0xf9, 0x07, 0xe1, 0xed, 0x17, 0x05, 0x0c, 0xe1, 0xdb, 0xf2, 0xf8, 0xea, + 0x22, 0xe9, 0x02, 0x00, 0xfd, 0xe7, 0xf2, 0xf8, 0xf9, 0xfc, 0xfa, 0xe8, + 0xe8, 0xeb, 0xe9, 0x0d, 0x04, 0xf8, 0xf8, 0xf7, 0xf8, 0x0d, 0x03, 0x0c, + 0x13, 0xf2, 0x0f, 0xf9, 0xe6, 0xfd, 0x0f, 0x19, 0x08, 0xf7, 0xfa, 0x01, + 0xf3, 0x12, 0x1e, 0x05, 0x0a, 0x09, 0xfd, 0x0b, 0x07, 0x08, 0x02, 0xfc, + 0xd6, 0xe8, 0x14, 0x01, 0x13, 0x19, 0xef, 0xda, 0x0e, 0x0a, 0x07, 0xef, + 0x34, 0xe0, 0x05, 0x1e, 0x4e, 0xe9, 0x19, 0xff, 0xe1, 0x04, 0xfb, 0x0e, + 0x11, 0x05, 0x1f, 0x15, 0xd4, 0xec, 0xf9, 0xe7, 0xf9, 0xfc, 0x25, 0xff, + 0x06, 0xf2, 0x01, 0xf6, 0x2a, 0x17, 0x24, 0x11, 0xf3, 0x1a, 0x1f, 0xfb, + 0x32, 0xeb, 0x33, 0x2f, 0x00, 0x08, 0x2c, 0xf0, 0x26, 0xf4, 0x25, 0x36, + 0xd9, 0xf1, 0x1a, 0xd5, 0xec, 0xf9, 0x32, 0x27, 0xfc, 0xf4, 0xf0, 0xe3, + 0xfa, 0x0c, 0x16, 0x17, 0xfa, 0xf9, 0xe5, 0x1f, 0x1f, 0xfa, 0xff, 0xfd, + 0x0d, 0x02, 0xe9, 0x0e, 0xf0, 0x12, 0x09, 0xda, 0x02, 0xea, 0xe5, 0x0a, + 0xff, 0x03, 0x13, 0xf0, 0x0a, 0xf9, 0xe9, 0xff, 0x10, 0xfc, 0x1a, 0xf3, + 0xf7, 0x0f, 0xf4, 0xfa, 0xf4, 0x05, 0x10, 0x0a, 0xdd, 0x09, 0xf7, 0xf0, + 0xe5, 0x07, 0x07, 0xfa, 0x02, 0xd7, 0xf8, 0xf7, 0x01, 0xfb, 0x0e, 0xf8, + 0x07, 0x0f, 0xfe, 0x03, 0x12, 0x05, 0x09, 0x13, 0xf8, 0xdc, 0xfd, 0x27, + 0x0f, 0xec, 0xf7, 0x07, 0x00, 0xfc, 0x12, 0xf8, 0xfb, 0xea, 0xe4, 0xe9, + 0xe9, 0xe0, 0xff, 0xdc, 0xd6, 0xeb, 0xf2, 0xf7, 0x0d, 0x1b, 0xe9, 0xc4, + 0x06, 0x00, 0xfd, 0x04, 0x46, 0xf9, 0xe9, 0x13, 0x2d, 0x0c, 0x1f, 0xf8, + 0xd3, 0x0c, 0x14, 0x11, 0x05, 0xe5, 0x27, 0x08, 0xc5, 0xef, 0xdf, 0xdd, + 0x04, 0xf8, 0x11, 0x10, 0xf0, 0xe7, 0xfb, 0x03, 0x3c, 0xe7, 0x14, 0x0c, + 0xf4, 0xf6, 0x1b, 0x0a, 0x23, 0xf2, 0x2d, 0x1a, 0x08, 0xff, 0x32, 0xe7, + 0x1a, 0x05, 0x2b, 0x34, 0xf1, 0x0a, 0x00, 0xe8, 0x02, 0xdf, 0x2c, 0x2a, + 0x03, 0xe6, 0xfc, 0xef, 0xfc, 0xe4, 0x03, 0x01, 0x03, 0xee, 0xe9, 0x15, + 0x05, 0x03, 0x13, 0x11, 0x0e, 0xee, 0xf5, 0x22, 0x1b, 0x0e, 0xfd, 0xf3, + 0x0a, 0x02, 0xdd, 0x20, 0xeb, 0x06, 0xf8, 0xe2, 0x06, 0x0e, 0xde, 0x0d, + 0xf9, 0x16, 0x1c, 0x0c, 0xe0, 0xf0, 0xec, 0x0c, 0x0f, 0xf2, 0x27, 0x1d, + 0xde, 0xe6, 0xf0, 0xf9, 0xf0, 0x02, 0x0a, 0x07, 0x06, 0xf9, 0x0f, 0xfa, + 0xf0, 0xee, 0xf1, 0xf7, 0xff, 0x02, 0x0b, 0x0d, 0x1b, 0xee, 0xf6, 0x05, + 0xff, 0x1c, 0x17, 0x04, 0x05, 0x17, 0x00, 0xff, 0x0d, 0xf3, 0x23, 0x10, + 0xfd, 0x05, 0xfb, 0xea, 0x03, 0x10, 0x07, 0xd7, 0xf7, 0xff, 0xf3, 0xf1, + 0x17, 0xed, 0xd3, 0xcb, 0x14, 0x1c, 0xf5, 0x03, 0x47, 0xf6, 0xf7, 0xf2, + 0x3e, 0xf2, 0x22, 0xf4, 0xed, 0xfc, 0xee, 0x0b, 0xf4, 0xf1, 0x25, 0x10, + 0xd0, 0xf6, 0x00, 0xef, 0x10, 0xfc, 0x15, 0xe5, 0xdb, 0xf3, 0xea, 0x10, + 0x22, 0xf2, 0x2b, 0x11, 0xf9, 0x0a, 0xfc, 0xf5, 0x53, 0x16, 0x25, 0x43, + 0xe0, 0x0e, 0x13, 0xfc, 0x2d, 0xe2, 0x55, 0x65, 0xf4, 0x08, 0x01, 0xdf, + 0x0a, 0x00, 0x49, 0x1c, 0xfe, 0xdf, 0xef, 0xf2, 0xf9, 0xf6, 0xfd, 0xff, + 0xf3, 0x02, 0xf6, 0x14, 0x0b, 0xe8, 0x09, 0xfc, 0xfc, 0xe2, 0xe5, 0x11, + 0x03, 0x09, 0xfb, 0x06, 0x10, 0x1a, 0xf3, 0x0d, 0xfa, 0x0a, 0xd5, 0xf5, + 0x1a, 0x11, 0xf2, 0xfc, 0x1f, 0xfe, 0x0e, 0xe4, 0xef, 0xd7, 0xee, 0x06, + 0x1e, 0x04, 0x12, 0x28, 0xf7, 0x0e, 0x06, 0xf8, 0xee, 0xf0, 0x1a, 0x01, + 0xf7, 0xfd, 0x03, 0x11, 0x19, 0x10, 0x04, 0xfb, 0xd7, 0xfa, 0x16, 0x06, + 0x07, 0x23, 0xfa, 0x14, 0x11, 0xf1, 0x12, 0x10, 0x04, 0xe1, 0xee, 0xf7, + 0x21, 0x0e, 0x0a, 0x0a, 0xf8, 0x07, 0x0a, 0xee, 0x03, 0x1f, 0xfa, 0xc4, + 0xec, 0x12, 0x01, 0x1e, 0xfd, 0xf1, 0xe8, 0xcc, 0xf4, 0x17, 0xff, 0xdd, + 0x45, 0x10, 0xee, 0xfa, 0x3d, 0xe7, 0x27, 0xdd, 0xd7, 0xf9, 0xf4, 0xf6, + 0x06, 0xf8, 0x1e, 0x13, 0xe7, 0xe2, 0xf1, 0xe3, 0xf3, 0xf7, 0x18, 0x12, + 0xe4, 0x0a, 0xdb, 0xff, 0xff, 0xfe, 0x20, 0x09, 0x00, 0xf7, 0x23, 0xf6, + 0x2d, 0x14, 0x26, 0x28, 0xe5, 0xff, 0x0f, 0xe3, 0x1d, 0xe8, 0x56, 0x43, + 0xe7, 0xfb, 0xf9, 0xe6, 0xe9, 0xe2, 0x19, 0x19, 0x08, 0xfa, 0xf3, 0xe5, + 0x23, 0x07, 0x0f, 0xf8, 0xf8, 0xf3, 0xfc, 0x11, 0x2a, 0x05, 0xf4, 0xf1, + 0xfa, 0xfb, 0xf1, 0x1e, 0x13, 0x0f, 0xf9, 0xf5, 0xfa, 0x09, 0xf9, 0x03, + 0xf0, 0xf0, 0xe7, 0xec, 0xf1, 0x0c, 0xe6, 0xee, 0xf6, 0x20, 0x0f, 0xe9, + 0x00, 0xf4, 0xfe, 0xf0, 0x13, 0x0a, 0x17, 0x13, 0xee, 0x13, 0xfb, 0xff, + 0xf8, 0xfd, 0xf4, 0xe2, 0xe8, 0x06, 0xfc, 0x14, 0x03, 0x17, 0x00, 0x03, + 0xe6, 0xfd, 0xf2, 0x12, 0x12, 0x20, 0xeb, 0x10, 0x02, 0xf7, 0x13, 0x0d, + 0x11, 0xfd, 0xde, 0xf5, 0x07, 0xf3, 0x04, 0xff, 0x06, 0x05, 0xfb, 0xea, + 0xf0, 0x0a, 0x00, 0xb5, 0xe8, 0x1a, 0x03, 0xfe, 0x0d, 0x1a, 0xe7, 0xc0, + 0xd6, 0xdc, 0xf6, 0xf8, 0x39, 0xf5, 0xd5, 0xf8, 0x22, 0xfa, 0x22, 0x05, + 0xd0, 0xf4, 0x2d, 0xfc, 0x00, 0x0a, 0x1b, 0xfc, 0xe6, 0x09, 0x14, 0xfa, + 0x00, 0x1d, 0x1a, 0xfd, 0xf3, 0x18, 0xfc, 0xeb, 0x15, 0xf5, 0x0e, 0x0a, + 0xf3, 0xf1, 0x1b, 0x05, 0x14, 0x03, 0x2d, 0x27, 0xfb, 0x18, 0x22, 0xef, + 0xf6, 0x06, 0x28, 0x2b, 0xde, 0xec, 0xef, 0xe8, 0xd3, 0xfe, 0x17, 0x12, + 0x01, 0x13, 0x05, 0xf7, 0x00, 0xde, 0xf3, 0xe5, 0x03, 0xfb, 0x07, 0x0b, + 0xfd, 0xdc, 0xdf, 0x03, 0x0c, 0x00, 0xfa, 0x06, 0x0e, 0x02, 0x05, 0xfa, + 0xfd, 0xed, 0x09, 0x0c, 0xfd, 0xfb, 0x0c, 0xf0, 0xe4, 0x04, 0xd6, 0xf3, + 0x09, 0x0a, 0xf9, 0xf8, 0xe2, 0xef, 0xdf, 0xf0, 0xf8, 0x03, 0x0f, 0x20, + 0xf4, 0xe3, 0xf8, 0x02, 0xe2, 0xe5, 0x25, 0x0f, 0xeb, 0xf8, 0xe9, 0xfd, + 0x04, 0x0c, 0x0c, 0xfe, 0x01, 0x08, 0xfc, 0xfc, 0x1b, 0x01, 0xe5, 0x13, + 0xf9, 0xe8, 0x07, 0x20, 0xfe, 0x06, 0xec, 0xfe, 0x09, 0xef, 0x14, 0x04, + 0x0b, 0xf5, 0xe7, 0xff, 0x0a, 0x02, 0x09, 0xe9, 0xc4, 0x16, 0x0d, 0xe7, + 0x15, 0x14, 0xf1, 0xd0, 0xec, 0xe7, 0xf0, 0xf0, 0x33, 0x05, 0xda, 0xf2, + 0x0b, 0x08, 0x38, 0x01, 0x07, 0xfd, 0xd8, 0x06, 0xd9, 0xf0, 0x16, 0x1f, + 0xff, 0xf7, 0xe0, 0xd8, 0xf3, 0xf7, 0x12, 0x08, 0x0e, 0x05, 0xf6, 0x03, + 0xef, 0x1b, 0x12, 0xf4, 0xe8, 0x0f, 0x02, 0xfd, 0xf2, 0x16, 0x26, 0x22, + 0xe0, 0x07, 0xf7, 0xe6, 0xeb, 0x16, 0x22, 0x1a, 0x0b, 0x01, 0xf5, 0xea, + 0xd2, 0x22, 0x0f, 0x13, 0x15, 0x08, 0xf0, 0xfb, 0xed, 0x11, 0xf3, 0xe9, + 0xff, 0xde, 0x0a, 0x18, 0x0f, 0x02, 0xfb, 0xf9, 0xfb, 0xe8, 0x12, 0x18, + 0x01, 0xf4, 0xf6, 0xf8, 0xf0, 0x1f, 0x24, 0x15, 0xf5, 0x00, 0x1c, 0xf9, + 0x01, 0x0a, 0x11, 0xd5, 0x01, 0x12, 0x02, 0xec, 0xfd, 0x07, 0xf2, 0xea, + 0xf9, 0xff, 0xf7, 0xfb, 0x15, 0xec, 0xe5, 0x01, 0xeb, 0x05, 0xf9, 0x10, + 0xfe, 0x28, 0xe5, 0x0a, 0xeb, 0x1b, 0x0e, 0xf9, 0xde, 0x02, 0x15, 0x0a, + 0xff, 0xfe, 0x11, 0x24, 0x03, 0xf8, 0x00, 0x08, 0xfd, 0x0e, 0xeb, 0xf3, + 0xf6, 0xf7, 0x14, 0x0e, 0xfc, 0xf5, 0xde, 0xf5, 0x9e, 0xfe, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xab, 0x01, 0x00, 0x00, + 0xfa, 0xfd, 0xff, 0xff, 0xa2, 0xff, 0xff, 0xff, 0xba, 0x00, 0x00, 0x00, + 0x24, 0xfc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x54, 0x4f, 0x43, 0x4f, + 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x24, 0xfb, 0xff, 0xff, + 0x68, 0x01, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xce, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1a, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, + 0x07, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xc4, 0xfc, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x10, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x07, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x1a, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x07, 0x00, 0x14, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x31, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x34, 0x04, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00, + 0x4c, 0x03, 0x00, 0x00, 0xdc, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0xfc, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x44, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf4, 0xfb, 0xff, 0xff, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x5f, 0x73, 0x6f, 0x66, 0x74, 0x6d, 0x61, 0x78, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x1a, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0c, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0xb4, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x11, 0x1e, 0x23, 0x3a, 0x9e, 0xa1, 0x15, 0x39, + 0x23, 0x69, 0x45, 0x3a, 0x09, 0xe4, 0xe4, 0x39, 0x65, 0xd7, 0x13, 0x3a, + 0xe0, 0xb2, 0xfd, 0x39, 0x1b, 0xc1, 0x53, 0x3a, 0xc2, 0x50, 0x2d, 0x3a, + 0x12, 0x00, 0x00, 0x00, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x77, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x3a, 0xfd, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x54, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2c, 0xfd, 0xff, 0xff, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xb5, 0xfa, 0xfa, 0x39, 0x1f, 0x00, 0x00, 0x00, 0x66, 0x69, 0x6e, 0x61, + 0x6c, 0x5f, 0x66, 0x63, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, + 0x2f, 0x72, 0x65, 0x61, 0x64, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, + 0x6f, 0x73, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xa0, 0x0f, 0x00, 0x00, 0xa2, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x58, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x74, 0xfe, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf2, 0xdd, 0xbb, 0x3d, + 0x01, 0x00, 0x00, 0x00, 0x32, 0xa3, 0x25, 0x41, 0x01, 0x00, 0x00, 0x00, + 0xf6, 0xa0, 0x50, 0xc1, 0x05, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x5f, + 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0e, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, + 0x2c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, + 0x32, 0x2f, 0x73, 0x68, 0x61, 0x70, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x4a, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x5c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x50, 0xd0, 0x3d, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcf, 0x41, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68, + 0x61, 0x70, 0x65, 0x5f, 0x32, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xc2, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x58, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x94, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x50, 0x50, 0xd0, 0x3d, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xcf, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, + 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xa8, 0x07, 0x00, 0x00, 0x2e, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x60, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x3a, 0x6a, 0xac, 0x3d, 0x01, 0x00, 0x00, 0x00, + 0xd0, 0xbd, 0xab, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x52, 0x65, 0x6c, 0x75, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, + 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x96, 0x08, 0x29, 0x38, 0x0b, 0x00, 0x00, 0x00, + 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x18, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x9a, 0xbb, 0x84, 0x38, 0x83, 0x84, 0x73, 0x37, 0x5b, 0xa3, 0xa0, 0x38, + 0x16, 0x41, 0x3a, 0x38, 0xc7, 0x9a, 0x70, 0x38, 0xed, 0x70, 0x4e, 0x38, + 0x54, 0x4f, 0xac, 0x38, 0xfd, 0x07, 0x8d, 0x38, 0x0b, 0x00, 0x00, 0x00, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x19, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0a, 0x00, 0x0e, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x03, 0x00, 0x00, 0x00}; +const int g_model_len = 18712; diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_model.h b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_model.h new file mode 100644 index 000000000..deec2d646 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_features_model.h @@ -0,0 +1,27 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This is a standard TensorFlow Lite FlatBuffer model file that has been +// converted into a C data array, so it can be easily compiled into a binary +// for devices that don't have a file system. It was created using the command: +// xxd -i model.tflite > model.cc + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MODEL_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MODEL_H_ + +extern const unsigned char g_model[]; +extern const int g_model_len; + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MODEL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_speech.ino b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_speech.ino new file mode 100644 index 000000000..b995289b6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/micro_speech.ino @@ -0,0 +1,216 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "audio_provider.h" +#include "command_responder.h" +#include "feature_provider.h" +#include "main_functions.h" +#include "micro_features_micro_model_settings.h" +#include "micro_features_model.h" +#include "recognize_commands.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_interpreter.h" +#include "tensorflow/lite/micro/micro_mutable_op_resolver.h" +#include "tensorflow/lite/micro/system_setup.h" +#include "tensorflow/lite/schema/schema_generated.h" + +#undef PROFILE_MICRO_SPEECH + +// Globals, used for compatibility with Arduino-style sketches. +namespace { +tflite::ErrorReporter* error_reporter = nullptr; +const tflite::Model* model = nullptr; +tflite::MicroInterpreter* interpreter = nullptr; +TfLiteTensor* model_input = nullptr; +FeatureProvider* feature_provider = nullptr; +RecognizeCommands* recognizer = nullptr; +int32_t previous_time = 0; + +// Create an area of memory to use for input, output, and intermediate arrays. +// The size of this will depend on the model you're using, and may need to be +// determined by experimentation. +constexpr int kTensorArenaSize = 10 * 1024; +uint8_t tensor_arena[kTensorArenaSize]; +int8_t feature_buffer[kFeatureElementCount]; +int8_t* model_input_buffer = nullptr; +} // namespace + +// The name of this function is important for Arduino compatibility. +void setup() { + tflite::InitializeTarget(); + + // Set up logging. Google style is to avoid globals or statics because of + // lifetime uncertainty, but since this has a trivial destructor it's okay. + // NOLINTNEXTLINE(runtime-global-variables) + static tflite::MicroErrorReporter micro_error_reporter; + error_reporter = µ_error_reporter; + + // Map the model into a usable data structure. This doesn't involve any + // copying or parsing, it's a very lightweight operation. + model = tflite::GetModel(g_model); + if (model->version() != TFLITE_SCHEMA_VERSION) { + TF_LITE_REPORT_ERROR(error_reporter, + "Model provided is schema version %d not equal " + "to supported version %d.", + model->version(), TFLITE_SCHEMA_VERSION); + return; + } + + // Pull in only the operation implementations we need. + // This relies on a complete list of all the ops needed by this graph. + // An easier approach is to just use the AllOpsResolver, but this will + // incur some penalty in code space for op implementations that are not + // needed by this graph. + // + // tflite::AllOpsResolver resolver; + // NOLINTNEXTLINE(runtime-global-variables) + static tflite::MicroMutableOpResolver<4> micro_op_resolver(error_reporter); + if (micro_op_resolver.AddDepthwiseConv2D() != kTfLiteOk) { + return; + } + if (micro_op_resolver.AddFullyConnected() != kTfLiteOk) { + return; + } + if (micro_op_resolver.AddSoftmax() != kTfLiteOk) { + return; + } + if (micro_op_resolver.AddReshape() != kTfLiteOk) { + return; + } + + // Build an interpreter to run the model with. + static tflite::MicroInterpreter static_interpreter( + model, micro_op_resolver, tensor_arena, kTensorArenaSize, error_reporter); + interpreter = &static_interpreter; + + // Allocate memory from the tensor_arena for the model's tensors. + TfLiteStatus allocate_status = interpreter->AllocateTensors(); + if (allocate_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed"); + return; + } + + // Get information about the memory area to use for the model's input. + model_input = interpreter->input(0); + if ((model_input->dims->size != 2) || (model_input->dims->data[0] != 1) || + (model_input->dims->data[1] != + (kFeatureSliceCount * kFeatureSliceSize)) || + (model_input->type != kTfLiteInt8)) { + TF_LITE_REPORT_ERROR(error_reporter, + "Bad input tensor parameters in model"); + return; + } + model_input_buffer = model_input->data.int8; + + // Prepare to access the audio spectrograms from a microphone or other source + // that will provide the inputs to the neural network. + // NOLINTNEXTLINE(runtime-global-variables) + static FeatureProvider static_feature_provider(kFeatureElementCount, + feature_buffer); + feature_provider = &static_feature_provider; + + static RecognizeCommands static_recognizer(error_reporter); + recognizer = &static_recognizer; + + previous_time = 0; + + // start the audio + TfLiteStatus init_status = InitAudioRecording(error_reporter); + if (init_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "Unable to initialize audio"); + return; + } + + TF_LITE_REPORT_ERROR(error_reporter, "Initialization complete"); +} + +// The name of this function is important for Arduino compatibility. +void loop() { +#ifdef PROFILE_MICRO_SPEECH + const uint32_t prof_start = millis(); + static uint32_t prof_count = 0; + static uint32_t prof_sum = 0; + static uint32_t prof_min = std::numeric_limits::max(); + static uint32_t prof_max = 0; +#endif // PROFILE_MICRO_SPEECH + + // Fetch the spectrogram for the current time. + const int32_t current_time = LatestAudioTimestamp(); + int how_many_new_slices = 0; + TfLiteStatus feature_status = feature_provider->PopulateFeatureData( + error_reporter, previous_time, current_time, &how_many_new_slices); + if (feature_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "Feature generation failed"); + return; + } + previous_time += how_many_new_slices * kFeatureSliceStrideMs; + // If no new audio samples have been received since last time, don't bother + // running the network model. + if (how_many_new_slices == 0) { + return; + } + + // Copy feature buffer to input tensor + for (int i = 0; i < kFeatureElementCount; i++) { + model_input_buffer[i] = feature_buffer[i]; + } + + // Run the model on the spectrogram input and make sure it succeeds. + TfLiteStatus invoke_status = interpreter->Invoke(); + if (invoke_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed"); + return; + } + + // Obtain a pointer to the output tensor + TfLiteTensor* output = interpreter->output(0); + // Determine whether a command was recognized based on the output of inference + const char* found_command = nullptr; + uint8_t score = 0; + bool is_new_command = false; + TfLiteStatus process_status = recognizer->ProcessLatestResults( + output, current_time, &found_command, &score, &is_new_command); + if (process_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, + "RecognizeCommands::ProcessLatestResults() failed"); + return; + } + // Do something based on the recognized command. The default implementation + // just prints to the error console, but you should replace this with your + // own function for a real application. + RespondToCommand(error_reporter, current_time, found_command, score, + is_new_command); + +#ifdef PROFILE_MICRO_SPEECH + const uint32_t prof_end = millis(); + if (++prof_count > 10) { + uint32_t elapsed = prof_end - prof_start; + prof_sum += elapsed; + if (elapsed < prof_min) { + prof_min = elapsed; + } + if (elapsed > prof_max) { + prof_max = elapsed; + } + if (prof_count % 300 == 0) { + TF_LITE_REPORT_ERROR(error_reporter, + "## time: min %dms max %dms avg %dms", prof_min, + prof_max, prof_sum / prof_count); + } + } +#endif // PROFILE_MICRO_SPEECH +} diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/recognize_commands.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/recognize_commands.cpp new file mode 100644 index 000000000..552cf58d3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/recognize_commands.cpp @@ -0,0 +1,159 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "recognize_commands.h" + +#include + +#undef DEBUG_MICRO_SPEECH + +RecognizeCommands::RecognizeCommands(tflite::ErrorReporter* error_reporter, + int32_t average_window_duration_ms, + uint8_t detection_threshold, + int32_t suppression_ms, + int32_t minimum_count) + : error_reporter_(error_reporter), + average_window_duration_ms_(average_window_duration_ms), + detection_threshold_(detection_threshold), + suppression_ms_(suppression_ms), + minimum_count_(minimum_count), + previous_results_(error_reporter) { + previous_top_label_ = kCategoryLabels[0]; // silence + previous_top_label_time_ = std::numeric_limits::min(); +} + +TfLiteStatus RecognizeCommands::ProcessLatestResults( + const TfLiteTensor* latest_results, const int32_t current_time_ms, + const char** found_command, uint8_t* score, bool* is_new_command) { + if ((latest_results->dims->size != 2) || + (latest_results->dims->data[0] != 1) || + (latest_results->dims->data[1] != kCategoryCount)) { + TF_LITE_REPORT_ERROR( + error_reporter_, + "The results for recognition should contain %d elements, but there are " + "%d in an %d-dimensional shape", + kCategoryCount, latest_results->dims->data[1], + latest_results->dims->size); + return kTfLiteError; + } + + if (latest_results->type != kTfLiteInt8) { + TF_LITE_REPORT_ERROR( + error_reporter_, + "The results for recognition should be int8_t elements, but are %d", + latest_results->type); + return kTfLiteError; + } + + if ((!previous_results_.empty()) && + (current_time_ms < previous_results_.front().time_)) { + TF_LITE_REPORT_ERROR( + error_reporter_, + "Results must be fed in increasing time order, but received a " + "timestamp of %d that was earlier than the previous one of %d", + current_time_ms, previous_results_.front().time_); + return kTfLiteError; + } + + // Prune any earlier results that are too old for the averaging window. + const int64_t time_limit = current_time_ms - average_window_duration_ms_; + while ((!previous_results_.empty()) && + previous_results_.front().time_ < time_limit) { + previous_results_.pop_front(); + } + + // Add the latest results to the head of the queue. + previous_results_.push_back({current_time_ms, latest_results->data.int8}); + + // If there are too few results, assume the result will be unreliable and + // bail. + const int64_t how_many_results = previous_results_.size(); + const int64_t earliest_time = previous_results_.front().time_; + const int64_t samples_duration = current_time_ms - earliest_time; + if ((how_many_results < minimum_count_) || + (samples_duration < (average_window_duration_ms_ / 4))) { + *found_command = previous_top_label_; + *score = 0; + *is_new_command = false; + return kTfLiteOk; + } + + // Calculate the average score across all the results in the window. + int32_t average_scores[kCategoryCount]; + for (int offset = 0; offset < previous_results_.size(); ++offset) { + PreviousResultsQueue::Result previous_result = + previous_results_.from_front(offset); + const int8_t* scores = previous_result.scores; + for (int i = 0; i < kCategoryCount; ++i) { + if (offset == 0) { + average_scores[i] = scores[i] + 128; + } else { + average_scores[i] += scores[i] + 128; + } + } + } + for (int i = 0; i < kCategoryCount; ++i) { + average_scores[i] /= how_many_results; + } + + // Find the current highest scoring category. + int current_top_index = 0; + int32_t current_top_score = 0; + for (int i = 0; i < kCategoryCount; ++i) { + if (average_scores[i] > current_top_score) { + current_top_score = average_scores[i]; + current_top_index = i; + } + } + const char* current_top_label = kCategoryLabels[current_top_index]; + + // If we've recently had another label trigger, assume one that occurs too + // soon afterwards is a bad result. + int64_t time_since_last_top; + if ((previous_top_label_ == kCategoryLabels[0]) || + (previous_top_label_time_ == std::numeric_limits::min())) { + time_since_last_top = std::numeric_limits::max(); + } else { + time_since_last_top = current_time_ms - previous_top_label_time_; + } + if ((current_top_score > detection_threshold_) && + ((current_top_label != previous_top_label_) || + (time_since_last_top > suppression_ms_))) { +#ifdef DEBUG_MICRO_SPEECH + TF_LITE_REPORT_ERROR( + error_reporter_, "Scores: s %d u %d y %d n %d %s -> %s", + average_scores[0], average_scores[1], average_scores[2], + average_scores[3], previous_top_label_, current_top_label); +#endif // DEBUG_MICRO_SPEECH + previous_top_label_ = current_top_label; + previous_top_label_time_ = current_time_ms; + *is_new_command = true; + } else { +#ifdef DEBUG_MICRO_SPEECH + if (current_top_label != previous_top_label_) { + TF_LITE_REPORT_ERROR( + error_reporter_, "#Scores: s %d u %d y %d n %d %s -> %s", + average_scores[0], average_scores[1], average_scores[2], + average_scores[3], previous_top_label_, current_top_label); + previous_top_label_ = current_top_label; + } +#endif // DEBUG_MICRO_SPEECH + *is_new_command = false; + } + *found_command = current_top_label; + *score = current_top_score; + + return kTfLiteOk; +} diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/recognize_commands.h b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/recognize_commands.h new file mode 100644 index 000000000..fa29d7dde --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/micro_speech/recognize_commands.h @@ -0,0 +1,159 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_RECOGNIZE_COMMANDS_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_RECOGNIZE_COMMANDS_H_ + +#include + +#include "micro_features_micro_model_settings.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" + +// Partial implementation of std::dequeue, just providing the functionality +// that's needed to keep a record of previous neural network results over a +// short time period, so they can be averaged together to produce a more +// accurate overall prediction. This doesn't use any dynamic memory allocation +// so it's a better fit for microcontroller applications, but this does mean +// there are hard limits on the number of results it can store. +class PreviousResultsQueue { + public: + PreviousResultsQueue(tflite::ErrorReporter* error_reporter) + : error_reporter_(error_reporter), front_index_(0), size_(0) {} + + // Data structure that holds an inference result, and the time when it + // was recorded. + struct Result { + Result() : time_(0), scores() {} + Result(int32_t time, int8_t* input_scores) : time_(time) { + for (int i = 0; i < kCategoryCount; ++i) { + scores[i] = input_scores[i]; + } + } + int32_t time_; + int8_t scores[kCategoryCount]; + }; + + int size() { return size_; } + bool empty() { return size_ == 0; } + Result& front() { return results_[front_index_]; } + Result& back() { + int back_index = front_index_ + (size_ - 1); + if (back_index >= kMaxResults) { + back_index -= kMaxResults; + } + return results_[back_index]; + } + + void push_back(const Result& entry) { + if (size() >= kMaxResults) { + TF_LITE_REPORT_ERROR( + error_reporter_, + "Couldn't push_back latest result, too many already!"); + return; + } + size_ += 1; + back() = entry; + } + + Result pop_front() { + if (size() <= 0) { + TF_LITE_REPORT_ERROR(error_reporter_, + "Couldn't pop_front result, none present!"); + return Result(); + } + Result result = front(); + front_index_ += 1; + if (front_index_ >= kMaxResults) { + front_index_ = 0; + } + size_ -= 1; + return result; + } + + // Most of the functions are duplicates of dequeue containers, but this + // is a helper that makes it easy to iterate through the contents of the + // queue. + Result& from_front(int offset) { + if ((offset < 0) || (offset >= size_)) { + TF_LITE_REPORT_ERROR(error_reporter_, + "Attempt to read beyond the end of the queue!"); + offset = size_ - 1; + } + int index = front_index_ + offset; + if (index >= kMaxResults) { + index -= kMaxResults; + } + return results_[index]; + } + + private: + tflite::ErrorReporter* error_reporter_; + static constexpr int kMaxResults = 50; + Result results_[kMaxResults]; + + int front_index_; + int size_; +}; + +// This class is designed to apply a very primitive decoding model on top of the +// instantaneous results from running an audio recognition model on a single +// window of samples. It applies smoothing over time so that noisy individual +// label scores are averaged, increasing the confidence that apparent matches +// are real. +// To use it, you should create a class object with the configuration you +// want, and then feed results from running a TensorFlow model into the +// processing method. The timestamp for each subsequent call should be +// increasing from the previous, since the class is designed to process a stream +// of data over time. +class RecognizeCommands { + public: + // labels should be a list of the strings associated with each one-hot score. + // The window duration controls the smoothing. Longer durations will give a + // higher confidence that the results are correct, but may miss some commands. + // The detection threshold has a similar effect, with high values increasing + // the precision at the cost of recall. The minimum count controls how many + // results need to be in the averaging window before it's seen as a reliable + // average. This prevents erroneous results when the averaging window is + // initially being populated for example. The suppression argument disables + // further recognitions for a set time after one has been triggered, which can + // help reduce spurious recognitions. + explicit RecognizeCommands(tflite::ErrorReporter* error_reporter, + int32_t average_window_duration_ms = 1000, + uint8_t detection_threshold = 200, + int32_t suppression_ms = 1500, + int32_t minimum_count = 3); + + // Call this with the results of running a model on sample data. + TfLiteStatus ProcessLatestResults(const TfLiteTensor* latest_results, + const int32_t current_time_ms, + const char** found_command, uint8_t* score, + bool* is_new_command); + + private: + // Configuration + tflite::ErrorReporter* error_reporter_; + int32_t average_window_duration_ms_; + uint8_t detection_threshold_; + int32_t suppression_ms_; + int32_t minimum_count_; + + // Working variables + PreviousResultsQueue previous_results_; + const char* previous_top_label_; + int32_t previous_top_label_time_; +}; + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_MICRO_SPEECH_RECOGNIZE_COMMANDS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/README.md b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/README.md new file mode 100644 index 000000000..cfde53712 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/README.md @@ -0,0 +1,69 @@ +# Person detection example + +This example shows how you can use [Tensorflow Lite Micro](https://www.tensorflow.org/lite/microcontrollers) to run a 300.5 kilobyte neural +network to recognize people in images. + +## Table of contents + + * [Deploy to Arduino](#deploy-to-arduino) + * [Install the Arduino_TensorFlowLite library](#install-the-arduino_tensorflowlite-library) + * [Load and run the example](#load-and-run-the-example) + * [Training your own model](#training-your-own-model) + + +## Deploy to Arduino + +The following instructions will help you build and deploy this example to +[Arduino](https://www.arduino.cc/) devices. + +The example has been tested with the following devices: + +- [Tiny Machine Learning Kit](https://store.arduino.cc/products/arduino-tiny-machine-learning-kit) + +The Arduino Tiny Machine Learning Kit uses the OV7675 camera attachment. The OV7675 is currently not supported, and the code will simply generate a blank image (support coming _**soon**_). If you're using a different Arduino board and attaching your own +camera, you'll need to implement your own `arduino_image_provider.cpp` code. It also has a +set of LEDs, which are used to indicate whether a person has been recognized. + +### Install the Arduino_TensorFlowLite library + +This example application is included as part of the official TensorFlow Lite Micro +Arduino library. +To install the TensorFlow Lite Micro for Arduino library, see the +[how to install](../../README.md#how-to-install) instructions. + +### Load and run the example + +Once the library has been added, go to `File -> Examples`. You should see an +entry within the list named `Arduino_TensorFlowLite`. Select +it and click `person_detection` to load the example. + +Use the Arduino IDE to build and upload the example. Once it is running, you +should see the built-in LED on your device flashing. The built-in LED will flash on/off for each inference cycle. The green LED will be lit if a person is predicted, +The blue LED will be lit if the prediction is not-a-person. + +The program also outputs inference results to the serial port, which appear as +follows: + +``` +Cropping image and quantizing +Image cropped and quantized +Person score: 39.6% No person score: 60.93% +``` + +When the program is run, it waits several seconds for a USB-serial connection to be +available. If there is no connection available, it will not output data. To see +the serial output in the Arduino desktop IDE, do the following: + +1. Open the Arduino IDE +1. Connect the Arduino board to your computer via USB +1. Press the reset button on the Arduino board +1. Within 5 seconds, go to `Tools -> Serial Monitor` in the Arduino IDE. You may + have to try several times, since the board will take a moment to connect. + +If you don't see any output, repeat the process again. + +## Training your own model + +You can train your own model with some easy-to-use scripts. See +[training_a_model.md](https://github.com/tensorflow/tflite-micro/blob/main/tensorflow/lite/micro/examples/person_detection/training_a_model.md) for instructions. + diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_detection_responder.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_detection_responder.cpp new file mode 100644 index 000000000..7de122422 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_detection_responder.cpp @@ -0,0 +1,76 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#if defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) +#define ARDUINO_EXCLUDE_CODE +#endif // defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) + +#ifndef ARDUINO_EXCLUDE_CODE + +#include + +#include "Arduino.h" +#include "detection_responder.h" + +// Flash the yellow (builtin) LED after each inference +void RespondToDetection(tflite::ErrorReporter* error_reporter, + float person_score, float no_person_score) { + static bool is_initialized = false; + if (!is_initialized) { + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, HIGH); + // Pins for the built-in RGB LEDs on the Arduino Nano 33 BLE Sense + pinMode(LEDR, OUTPUT); + pinMode(LEDG, OUTPUT); + pinMode(LEDB, OUTPUT); + // Switch the LEDs off + digitalWrite(LEDG, HIGH); + digitalWrite(LEDB, HIGH); + digitalWrite(LEDR, HIGH); + is_initialized = true; + } + + // Note: The RGB LEDs on the Arduino Nano 33 BLE + // Sense are on when the pin is LOW, off when HIGH. + + // Switch on the green LED when a person is detected, + // the blue when no person is detected + if (person_score > no_person_score) { + digitalWrite(LEDG, LOW); + digitalWrite(LEDB, HIGH); + } else { + digitalWrite(LEDG, HIGH); + digitalWrite(LEDB, LOW); + } + + // Flash the yellow LED after every inference. + // The builtin LED is on when the pin is HIGH + digitalWrite(LED_BUILTIN, LOW); + delay(100); + digitalWrite(LED_BUILTIN, HIGH); + + float person_score_frac, person_score_int; + float no_person_score_frac, no_person_score_int; + person_score_frac = std::modf(person_score * 100, &person_score_int); + no_person_score_frac = std::modf(no_person_score * 100, &no_person_score_int); + TF_LITE_REPORT_ERROR(error_reporter, + "Person score: %d.%d%% No person score: %d.%d%%", + static_cast(person_score_int), + static_cast(person_score_frac * 100), + static_cast(no_person_score_int), + static_cast(no_person_score_frac * 100)); +} + +#endif // ARDUINO_EXCLUDE_CODE diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_image_provider.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_image_provider.cpp new file mode 100644 index 000000000..515f55e4c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_image_provider.cpp @@ -0,0 +1,199 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include "image_provider.h" +#include "model_settings.h" +#include "tensorflow/lite/micro/micro_utils.h" +#include "test_over_serial/test_over_serial.h" + +using namespace test_over_serial; + +#if defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) +#define ARDUINO_EXCLUDE_CODE +#endif // defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) + +#ifndef ARDUINO_EXCLUDE_CODE + +#include "Arduino.h" + +namespace { + +constexpr size_t kQQVGA_width = 160; // pixels +constexpr size_t kQQVGA_height = 120; // pixels + +uint8_t image_buffer[kQQVGA_height * kQQVGA_width]; +constexpr size_t kImageBufferLength = + std::extent::value; + +// Get the camera module ready +TfLiteStatus InitCamera(tflite::ErrorReporter* error_reporter) { + // This function kept for future implementation + TF_LITE_REPORT_ERROR( + error_reporter, + "OV7675 not yet supported. Blank image will be substituted."); + return kTfLiteOk; +} + +// Begin the capture and wait for it to finish +TfLiteStatus PerformCapture(tflite::ErrorReporter* error_reporter) { + // This function kept for future implementation + TF_LITE_REPORT_ERROR(error_reporter, "Starting capture"); + delay(50); + TF_LITE_REPORT_ERROR(error_reporter, "Image captured"); + return kTfLiteOk; +} + +// Read data from the camera module into a local buffer +TfLiteStatus ReadData(tflite::ErrorReporter* error_reporter) { + // This function kept for future implementation + // until OV7675 supported, just fill with zeros (black image) + std::fill_n(image_buffer, kImageBufferLength, 0); + return kTfLiteOk; +} + +// Decode the image, crop it, and convert it to grayscale +TfLiteStatus CropAndQuantizeImage(tflite::ErrorReporter* error_reporter, + size_t image_width, size_t image_height, + const TfLiteTensor* tensor) { + TF_LITE_REPORT_ERROR(error_reporter, "Cropping image and quantizing"); + + // cropping parameters + const size_t vert_top = (image_height - kNumRows) / 2; + const size_t vert_bottom = vert_top + kNumRows - 1; + const size_t horz_left = (image_width - kNumCols) / 2; + const size_t horz_right = horz_left + kNumCols - 1; + + const uint8_t* p = image_buffer + (vert_top * image_width); + p += horz_left; + int8_t* image_data = tensor->data.int8; + for (size_t line = vert_top; line <= vert_bottom; line++) { + for (size_t row = horz_left; row <= horz_right; row++, p++) { + *image_data++ = tflite::FloatToQuantizedType( + p[0] / 255.0f, tensor->params.scale, tensor->params.zero_point); + } + // move to next line + p += ((image_width - 1) - horz_right) + horz_left; + } + + TF_LITE_REPORT_ERROR(error_reporter, "Image cropped and quantized"); + return kTfLiteOk; +} + +// Get an image from the camera module +TfLiteStatus GetCameraImage(tflite::ErrorReporter* error_reporter, + const TfLiteTensor* tensor) { + static bool g_is_camera_initialized = false; + if (!g_is_camera_initialized) { + TfLiteStatus init_status = InitCamera(error_reporter); + if (init_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "InitCamera failed"); + return init_status; + } + g_is_camera_initialized = true; + } + + TfLiteStatus capture_status = PerformCapture(error_reporter); + if (capture_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "PerformCapture failed"); + return capture_status; + } + + TfLiteStatus read_data_status = ReadData(error_reporter); + if (read_data_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "ReadData failed"); + return read_data_status; + } + + TfLiteStatus decode_status = + CropAndQuantizeImage(error_reporter, kQQVGA_width, kQQVGA_height, tensor); + if (decode_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "CropAndQuantizeImage failed"); + return decode_status; + } + + return kTfLiteOk; +} + +TfLiteStatus GetTestImage(tflite::ErrorReporter* error_reporter, + TestOverSerial& test, const TfLiteTensor* tensor) { + volatile bool done = false; + volatile bool aborted = false; + volatile size_t image_width = 0, image_height = 0; + + InputHandler handler = [&aborted, &done, &image_width, + &image_height](const InputBuffer* const input) { + if (0 == input->offset) { + if ((kQQVGA_height * kQQVGA_width) == input->total) { + image_width = kQQVGA_width; + image_height = kQQVGA_height; + } else if ((kNumCols * kNumRows) == input->total) { + image_width = kNumCols; + image_height = kNumRows; + } else { + // image dimensions are not supported, abort input processing + aborted = true; + return false; + } + } + + std::copy_n(input->data.uint8, input->length, &image_buffer[input->offset]); + if (input->total == (input->offset + input->length)) { + done = true; + } + return true; + }; + + while (!done) { + test.ProcessInput(&handler); + if (aborted) { + TF_LITE_REPORT_ERROR(error_reporter, "Input processing aborted"); + return kTfLiteError; + } + // wait for a full image from serial port before processing + if (done) { + TfLiteStatus decode_status = CropAndQuantizeImage( + error_reporter, image_width, image_height, tensor); + if (decode_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "CropAndQuantizeImage failed"); + return decode_status; + } + } + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteStatus GetImage(tflite::ErrorReporter* error_reporter, + const TfLiteTensor* tensor) { + TestOverSerial& test = TestOverSerial::Instance(kIMAGE_GRAYSCALE); + if (!test.IsTestMode()) { + // check serial port for test mode command + test.ProcessInput(nullptr); + } + if (test.IsTestMode()) { + return GetTestImage(error_reporter, test, tensor); + } else { + // get an image from the camera + return GetCameraImage(error_reporter, tensor); + } + // NOTREACHED +} + +#endif // ARDUINO_EXCLUDE_CODE diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_main.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_main.cpp new file mode 100644 index 000000000..c70a2bcea --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/arduino_main.cpp @@ -0,0 +1,20 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "main_functions.h" + +// Arduino automatically calls the setup() and loop() functions in a sketch, so +// where other systems need their own main routine in this file, it can be left +// empty. diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/detection_responder.h b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/detection_responder.h new file mode 100644 index 000000000..1d9cabcb2 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/detection_responder.h @@ -0,0 +1,34 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Provides an interface to take an action based on the output from the person +// detection model. + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_DETECTION_RESPONDER_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_DETECTION_RESPONDER_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" + +// Called every time the results of a person detection run are available. The +// `person_score` has the numerical confidence that the captured image contains +// a person, and `no_person_score` has the numerical confidence that the image +// does not contain a person. Typically if person_score > no person score, the +// image is considered to contain a person. This threshold may be adjusted for +// particular applications. +void RespondToDetection(tflite::ErrorReporter* error_reporter, + float person_score, float no_person_score); + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_DETECTION_RESPONDER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/image_provider.h b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/image_provider.h new file mode 100644 index 000000000..3fc18bb31 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/image_provider.h @@ -0,0 +1,40 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_IMAGE_PROVIDER_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_IMAGE_PROVIDER_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" + +// This is an abstraction around an image source like a camera, and is +// expected to place 8-bit quantized sample data into the tensor. +// +// The assumption is that this will be +// called in a low duty-cycle fashion in a low-power application. In these +// cases, the imaging sensor need not be run in a streaming mode, but rather can +// be idled in a relatively low-power mode between calls to GetImage(). The +// assumption is that the overhead and time of bringing the low-power sensor out +// of this standby mode is commensurate with the expected duty cycle of the +// application. The underlying sensor may actually be put into a streaming +// configuration, but the tensor provided to GetImage should not be +// overwritten by the driver code until the next call to GetImage(); +// +// For real applications, you should +// ensure there's a specialized implementation that accesses hardware APIs. +TfLiteStatus GetImage(tflite::ErrorReporter* error_reporter, + const TfLiteTensor* tensor); + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_IMAGE_PROVIDER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/main_functions.h b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/main_functions.h new file mode 100644 index 000000000..2620097a8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/main_functions.h @@ -0,0 +1,37 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_MAIN_FUNCTIONS_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_MAIN_FUNCTIONS_H_ + +// Expose a C friendly interface for main functions. +#ifdef __cplusplus +extern "C" { +#endif + +// Initializes all data needed for the example. The name is important, and needs +// to be setup() for Arduino compatibility. +void setup(); + +// Runs one iteration of data gathering and inference. This should be called +// repeatedly from the application code. The name needs to be loop() for Arduino +// compatibility. +void loop(); + +#ifdef __cplusplus +} +#endif + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_MAIN_FUNCTIONS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/model_settings.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/model_settings.cpp new file mode 100644 index 000000000..2d4ad1e28 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/model_settings.cpp @@ -0,0 +1,21 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "model_settings.h" + +const char* kCategoryLabels[kCategoryCount] = { + "notperson", + "person", +}; diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/model_settings.h b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/model_settings.h new file mode 100644 index 000000000..f94d58ed6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/model_settings.h @@ -0,0 +1,35 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_MODEL_SETTINGS_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_MODEL_SETTINGS_H_ + +// Keeping these as constant expressions allow us to allocate fixed-sized arrays +// on the stack for our working memory. + +// All of these values are derived from the values used during model training, +// if you change your model you'll need to update these constants. +constexpr int kNumCols = 96; +constexpr int kNumRows = 96; +constexpr int kNumChannels = 1; + +constexpr int kMaxImageSize = kNumCols * kNumRows * kNumChannels; + +constexpr int kCategoryCount = 2; +constexpr int kPersonIndex = 1; +constexpr int kNotAPersonIndex = 0; +extern const char* kCategoryLabels[kCategoryCount]; + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_MODEL_SETTINGS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detect_model_data.cpp b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detect_model_data.cpp new file mode 100644 index 000000000..7e2c73fc1 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detect_model_data.cpp @@ -0,0 +1,23148 @@ + +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This is a TensorFlow Lite model file that has been converted into a C data +// array using the tensorflow.lite.util.convert_bytes_to_c_source() function. +// This form is useful for compiling into a binary for devices that don't have a +// file system. + +#include "person_detect_model_data.h" + +// Keep model aligned to 8 bytes to guarantee aligned 64-bit accesses. +alignas(8) const unsigned char g_person_detect_model_data[] = { + 0x1c, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x84, 0x95, 0x04, + 0x00, 0xec, 0x5b, 0x03, 0x00, 0xd4, 0x5b, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x5a, 0x00, 0x00, 0x00, 0xc4, 0x5b, 0x03, 0x00, 0xac, 0x5b, 0x03, 0x00, 0x94, + 0x5b, 0x03, 0x00, 0x84, 0x59, 0x03, 0x00, 0x74, 0x55, 0x03, 0x00, 0x64, 0x55, + 0x02, 0x00, 0x54, 0x51, 0x02, 0x00, 0x44, 0x48, 0x02, 0x00, 0x34, 0x44, 0x02, + 0x00, 0x24, 0x42, 0x02, 0x00, 0x94, 0x3d, 0x02, 0x00, 0x84, 0x3b, 0x02, 0x00, + 0x74, 0xfb, 0x01, 0x00, 0xe4, 0xf6, 0x01, 0x00, 0xd4, 0xb6, 0x01, 0x00, 0xc4, + 0xb4, 0x01, 0x00, 0xb4, 0x74, 0x01, 0x00, 0xa4, 0x72, 0x01, 0x00, 0x94, 0x70, + 0x01, 0x00, 0x84, 0x6e, 0x01, 0x00, 0x74, 0x2e, 0x01, 0x00, 0x64, 0xee, 0x00, + 0x00, 0x54, 0xec, 0x00, 0x00, 0xc4, 0xe7, 0x00, 0x00, 0xb4, 0xe5, 0x00, 0x00, + 0xa4, 0xc5, 0x00, 0x00, 0x94, 0xc4, 0x00, 0x00, 0x44, 0xc2, 0x00, 0x00, 0x34, + 0xb2, 0x00, 0x00, 0x24, 0xb1, 0x00, 0x00, 0x14, 0xa9, 0x00, 0x00, 0x84, 0xa8, + 0x00, 0x00, 0x54, 0xa7, 0x00, 0x00, 0x44, 0xa3, 0x00, 0x00, 0xb4, 0xa2, 0x00, + 0x00, 0x84, 0xa1, 0x00, 0x00, 0x34, 0xa1, 0x00, 0x00, 0x2c, 0xa1, 0x00, 0x00, + 0x24, 0xa1, 0x00, 0x00, 0x1c, 0xa1, 0x00, 0x00, 0x14, 0xa1, 0x00, 0x00, 0x0c, + 0xa1, 0x00, 0x00, 0x04, 0xa1, 0x00, 0x00, 0xfc, 0xa0, 0x00, 0x00, 0xf4, 0xa0, + 0x00, 0x00, 0xec, 0xa0, 0x00, 0x00, 0xe4, 0xa0, 0x00, 0x00, 0xdc, 0xa0, 0x00, + 0x00, 0x8c, 0xa0, 0x00, 0x00, 0x84, 0xa0, 0x00, 0x00, 0x7c, 0xa0, 0x00, 0x00, + 0x74, 0xa0, 0x00, 0x00, 0x6c, 0xa0, 0x00, 0x00, 0x64, 0xa0, 0x00, 0x00, 0x5c, + 0xa0, 0x00, 0x00, 0x4c, 0x9e, 0x00, 0x00, 0x1c, 0x9e, 0x00, 0x00, 0x14, 0x9e, + 0x00, 0x00, 0x74, 0x9d, 0x00, 0x00, 0xe4, 0x9c, 0x00, 0x00, 0x8c, 0x9c, 0x00, + 0x00, 0x7c, 0x9a, 0x00, 0x00, 0xec, 0x99, 0x00, 0x00, 0x5c, 0x99, 0x00, 0x00, + 0x54, 0x99, 0x00, 0x00, 0x4c, 0x99, 0x00, 0x00, 0x44, 0x99, 0x00, 0x00, 0x3c, + 0x99, 0x00, 0x00, 0xe4, 0x98, 0x00, 0x00, 0xd4, 0x18, 0x00, 0x00, 0xc4, 0x16, + 0x00, 0x00, 0x34, 0x12, 0x00, 0x00, 0xa4, 0x0d, 0x00, 0x00, 0x9c, 0x0d, 0x00, + 0x00, 0x94, 0x0d, 0x00, 0x00, 0x8c, 0x0d, 0x00, 0x00, 0x7c, 0x0c, 0x00, 0x00, + 0x2c, 0x0a, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x00, 0x14, 0x08, 0x00, 0x00, 0x84, + 0x03, 0x00, 0x00, 0x7c, 0x03, 0x00, 0x00, 0x4c, 0x03, 0x00, 0x00, 0x3c, 0x01, + 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x7c, 0xfc, 0xfb, 0xff, 0x80, 0xfc, 0xfb, 0xff, 0x84, 0xfc, 0xfb, 0xff, 0x88, + 0xfc, 0xfb, 0xff, 0x8c, 0xfc, 0xfb, 0xff, 0xba, 0xa4, 0xfc, 0xff, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x37, 0x0f, 0x00, 0x00, 0x5d, 0xe6, 0xff, + 0xff, 0x75, 0xdd, 0xff, 0xff, 0xee, 0xf7, 0xff, 0xff, 0xa4, 0xfa, 0xff, 0xff, + 0xc7, 0xf5, 0xff, 0xff, 0x0a, 0x0c, 0x00, 0x00, 0xdb, 0x16, 0x00, 0x00, 0x06, + 0x09, 0x00, 0x00, 0x81, 0x1b, 0x00, 0x00, 0xc1, 0x29, 0x00, 0x00, 0xd2, 0x18, + 0x00, 0x00, 0xd0, 0xf6, 0xff, 0xff, 0x93, 0x5c, 0x00, 0x00, 0xf3, 0xb9, 0xff, + 0xff, 0x0a, 0x28, 0x00, 0x00, 0xed, 0xe9, 0xff, 0xff, 0x86, 0xc9, 0xff, 0xff, + 0x28, 0x27, 0x00, 0x00, 0x77, 0x04, 0x00, 0x00, 0x7a, 0xd0, 0xff, 0xff, 0xad, + 0x58, 0x00, 0x00, 0x1c, 0x4b, 0x00, 0x00, 0xb0, 0x9b, 0xff, 0xff, 0xb5, 0xce, + 0xff, 0xff, 0xfc, 0x12, 0x00, 0x00, 0x3e, 0xfd, 0xff, 0xff, 0x4b, 0xf5, 0xff, + 0xff, 0xae, 0xcb, 0xff, 0xff, 0xc3, 0x39, 0x00, 0x00, 0x56, 0xd1, 0xff, 0xff, + 0x3d, 0x19, 0x00, 0x00, 0x4b, 0x18, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0xc6, + 0x6a, 0x00, 0x00, 0xca, 0xb0, 0xff, 0xff, 0xb4, 0x08, 0x00, 0x00, 0x3b, 0x4b, + 0x00, 0x00, 0xc9, 0xbe, 0xff, 0xff, 0xd4, 0x12, 0x00, 0x00, 0xe2, 0xf4, 0xff, + 0xff, 0x36, 0xff, 0xff, 0xff, 0xd0, 0xef, 0xff, 0xff, 0x08, 0xcc, 0xff, 0xff, + 0xa7, 0xd3, 0xff, 0xff, 0x9c, 0x08, 0x00, 0x00, 0x03, 0x1b, 0x00, 0x00, 0xaf, + 0xa2, 0xff, 0xff, 0x71, 0x13, 0x00, 0x00, 0x0c, 0x7b, 0x00, 0x00, 0xf2, 0x03, + 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x1e, 0x29, 0x00, 0x00, 0x0c, 0x04, 0x00, + 0x00, 0x92, 0x59, 0x00, 0x00, 0x27, 0xd4, 0xff, 0xff, 0x30, 0x0c, 0x00, 0x00, + 0xfa, 0xfb, 0xff, 0xff, 0x17, 0xca, 0xff, 0xff, 0x92, 0xd3, 0xff, 0xff, 0x6c, + 0x11, 0x00, 0x00, 0xc9, 0xff, 0xff, 0xff, 0x78, 0x00, 0x00, 0x00, 0x4f, 0x43, + 0x00, 0x00, 0xc6, 0xa5, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x6e, 0xcc, 0xff, 0xff, 0x69, 0x36, 0x00, 0x00, 0xfb, 0xee, 0xff, 0xff, + 0x24, 0x4c, 0x00, 0x00, 0xb3, 0x07, 0x00, 0x00, 0x96, 0x3f, 0x00, 0x00, 0xe1, + 0xd2, 0xff, 0xff, 0xf7, 0xfd, 0xff, 0xff, 0x01, 0x4f, 0x00, 0x00, 0x9b, 0xea, + 0xff, 0xff, 0xcc, 0xe4, 0xff, 0xff, 0xb2, 0x00, 0x00, 0x00, 0x52, 0xed, 0xff, + 0xff, 0xef, 0xad, 0xff, 0xff, 0xef, 0x34, 0x00, 0x00, 0x37, 0x0c, 0x00, 0x00, + 0xea, 0x47, 0x00, 0x00, 0xf8, 0xed, 0xff, 0xff, 0xa0, 0xef, 0xff, 0xff, 0xea, + 0x43, 0x00, 0x00, 0x17, 0xed, 0xff, 0xff, 0xab, 0xfd, 0xff, 0xff, 0x0b, 0xf8, + 0xff, 0xff, 0x37, 0x26, 0x00, 0x00, 0x33, 0xea, 0xff, 0xff, 0x0e, 0x1e, 0x00, + 0x00, 0xc4, 0x09, 0x00, 0x00, 0x6f, 0x1f, 0x00, 0x00, 0xfc, 0x69, 0xff, 0xff, + 0x9c, 0xd9, 0xff, 0xff, 0xc1, 0xf0, 0xff, 0xff, 0x89, 0x19, 0x00, 0x00, 0x9c, + 0x29, 0x00, 0x00, 0x10, 0xb7, 0xff, 0xff, 0x2f, 0xd9, 0xff, 0xff, 0x23, 0xe9, + 0xff, 0xff, 0xaf, 0x57, 0x00, 0x00, 0x05, 0x48, 0x00, 0x00, 0x30, 0xf7, 0xff, + 0xff, 0x1c, 0x12, 0x00, 0x00, 0xa7, 0xcc, 0xff, 0xff, 0xd0, 0xc6, 0xff, 0xff, + 0x9d, 0xea, 0xff, 0xff, 0x9a, 0xfc, 0xff, 0xff, 0xc1, 0xcc, 0xff, 0xff, 0x63, + 0xcf, 0xff, 0xff, 0xa8, 0x11, 0x00, 0x00, 0x1d, 0xfd, 0xff, 0xff, 0xfc, 0xfa, + 0xff, 0xff, 0x14, 0xe9, 0xff, 0xff, 0xb5, 0x37, 0x00, 0x00, 0x46, 0x21, 0x00, + 0x00, 0x3e, 0x02, 0x00, 0x00, 0x77, 0xd2, 0xff, 0xff, 0x0e, 0xe5, 0xff, 0xff, + 0xde, 0x24, 0x00, 0x00, 0xe9, 0x28, 0x00, 0x00, 0xdc, 0x6d, 0xff, 0xff, 0x59, + 0xb6, 0xff, 0xff, 0xb8, 0x0d, 0x00, 0x00, 0x89, 0xf5, 0xff, 0xff, 0xf5, 0x25, + 0x00, 0x00, 0xd6, 0x1e, 0x00, 0x00, 0x03, 0x32, 0x00, 0x00, 0x2f, 0x1f, 0x00, + 0x00, 0xe1, 0xfa, 0xff, 0xff, 0x59, 0xd8, 0xff, 0xff, 0x85, 0x3e, 0x00, 0x00, + 0xae, 0xea, 0xff, 0xff, 0x72, 0x3e, 0x00, 0x00, 0x87, 0xfd, 0xff, 0xff, 0x27, + 0x57, 0x00, 0x00, 0x0b, 0xf2, 0xff, 0xff, 0xc2, 0x1c, 0x00, 0x00, 0xd9, 0x20, + 0x00, 0x00, 0xf9, 0x2e, 0x00, 0x00, 0x84, 0xfd, 0xff, 0xff, 0x6b, 0x22, 0x00, + 0x00, 0x2b, 0x94, 0xff, 0xff, 0xdf, 0xfd, 0xff, 0xff, 0x80, 0xee, 0xff, 0xff, + 0x4d, 0xe6, 0xff, 0xff, 0x71, 0xd4, 0xff, 0xff, 0xd6, 0xd8, 0xff, 0xff, 0xdc, + 0x4d, 0x00, 0x00, 0xfc, 0xb8, 0xff, 0xff, 0xa6, 0x45, 0x00, 0x00, 0xa5, 0xf1, + 0xff, 0xff, 0x63, 0x31, 0x00, 0x00, 0x3c, 0xd8, 0xff, 0xff, 0x12, 0x29, 0x00, + 0x00, 0x34, 0xdb, 0xff, 0xff, 0xae, 0x57, 0x00, 0x00, 0x6c, 0xc9, 0xff, 0xff, + 0x1b, 0x2f, 0x00, 0x00, 0x44, 0x28, 0x00, 0x00, 0x34, 0xf3, 0xff, 0xff, 0xdd, + 0x1c, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0xaa, 0x02, 0x00, 0x00, 0x23, 0x41, + 0x00, 0x00, 0x97, 0x0e, 0x00, 0x00, 0xcf, 0x1b, 0x00, 0x00, 0x50, 0x17, 0x00, + 0x00, 0x67, 0x8b, 0xff, 0xff, 0x22, 0x0b, 0x00, 0x00, 0x56, 0xd1, 0xff, 0xff, + 0xfe, 0xe8, 0xff, 0xff, 0x8d, 0x31, 0x00, 0x00, 0xc9, 0xd1, 0xff, 0xff, 0x98, + 0x10, 0x00, 0x00, 0x9c, 0x44, 0x00, 0x00, 0x0f, 0x0b, 0x00, 0x00, 0xd4, 0x3e, + 0x00, 0x00, 0x64, 0x19, 0x00, 0x00, 0x0c, 0xe8, 0xff, 0xff, 0xcc, 0x04, 0x00, + 0x00, 0xcc, 0xb7, 0xff, 0xff, 0xea, 0x3d, 0x00, 0x00, 0x30, 0x19, 0x00, 0x00, + 0x70, 0x06, 0x00, 0x00, 0x14, 0x2f, 0x00, 0x00, 0xcb, 0xd4, 0xff, 0xff, 0xd2, + 0xee, 0xff, 0xff, 0x4e, 0x26, 0x00, 0x00, 0xd4, 0x23, 0x00, 0x00, 0xa0, 0x55, + 0x00, 0x00, 0x2e, 0x15, 0x00, 0x00, 0xd2, 0xa7, 0xfc, 0xff, 0x04, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0xbe, 0x0e, 0x00, 0x00, 0x95, 0xff, 0xff, 0xff, + 0x56, 0xb6, 0xfe, 0xff, 0xac, 0xc9, 0xff, 0xff, 0xd9, 0x50, 0x00, 0x00, 0xfa, + 0xff, 0xff, 0xff, 0xdf, 0x2c, 0x00, 0x00, 0x9a, 0xcb, 0xfd, 0xff, 0xd4, 0xff, + 0xfb, 0xff, 0x02, 0xa8, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, + 0x00, 0x5e, 0xac, 0x7e, 0x7f, 0xdc, 0xf2, 0xcc, 0x39, 0x8c, 0x81, 0x5e, 0xa5, + 0xa7, 0x7f, 0xbd, 0x37, 0x45, 0x1b, 0xf3, 0x74, 0x7f, 0x1e, 0xc4, 0xfb, 0x00, + 0xbe, 0xfc, 0xfa, 0x03, 0x22, 0x7f, 0x59, 0x38, 0xac, 0x75, 0xeb, 0x56, 0xa8, + 0x9e, 0x00, 0x9a, 0x99, 0xf4, 0xa2, 0x5f, 0x08, 0x7f, 0x44, 0xc9, 0x01, 0x36, + 0x0d, 0xde, 0xc2, 0xbf, 0xa4, 0x01, 0x7f, 0xf8, 0x1a, 0xd2, 0xec, 0x01, 0x41, + 0x41, 0x0f, 0x0c, 0xd8, 0x05, 0xd6, 0x4f, 0x81, 0x37, 0x2e, 0x63, 0x7f, 0x2e, + 0x1c, 0xd1, 0xab, 0xbe, 0x52, 0xb3, 0x7f, 0x7f, 0x14, 0xa3, 0xe0, 0xad, 0x7f, + 0xc1, 0x69, 0xc3, 0xc7, 0xf7, 0x71, 0xc6, 0xaf, 0x81, 0x25, 0x7f, 0x75, 0x18, + 0xc4, 0xcf, 0xdd, 0x4f, 0x1d, 0x9b, 0x04, 0xa4, 0xe9, 0x81, 0xb0, 0x31, 0x89, + 0x4f, 0x1f, 0x14, 0x4d, 0x78, 0x24, 0x81, 0x7f, 0xfb, 0x81, 0xf5, 0xe8, 0x4f, + 0xc5, 0x7f, 0x10, 0x26, 0x50, 0xce, 0xe5, 0xf4, 0x00, 0x0c, 0xac, 0xd6, 0x4f, + 0x50, 0x42, 0x7f, 0x0d, 0xe7, 0x35, 0x3c, 0xfd, 0x4b, 0xf1, 0xae, 0x18, 0xfb, + 0xc9, 0x1f, 0xe3, 0x52, 0x3d, 0x7f, 0xe8, 0x44, 0x7f, 0x3a, 0xd7, 0xe1, 0x3d, + 0x8b, 0xba, 0xc4, 0x57, 0x3b, 0x1d, 0x1b, 0x26, 0x8e, 0x45, 0x3b, 0xcd, 0x4d, + 0xcc, 0x14, 0xb0, 0x2e, 0x60, 0xed, 0xf8, 0xb0, 0xfe, 0xf9, 0x30, 0xfc, 0x22, + 0x7c, 0xc0, 0x15, 0x70, 0x70, 0x20, 0x7f, 0x9c, 0x4d, 0x06, 0x11, 0xc8, 0xb5, + 0xc7, 0xc1, 0x2a, 0xb8, 0x51, 0x1b, 0x4e, 0xbd, 0x9d, 0x5e, 0x30, 0xd3, 0x47, + 0xc5, 0x49, 0xe9, 0x20, 0xc7, 0x2c, 0xf0, 0x59, 0xdf, 0x47, 0x2e, 0xd5, 0x9e, + 0x9e, 0xa7, 0xd1, 0x81, 0xf9, 0xd7, 0x15, 0x9c, 0xa6, 0x6d, 0xfe, 0x7f, 0x79, + 0x7f, 0xd7, 0x7f, 0x4f, 0xdf, 0x7a, 0x00, 0xbf, 0x7f, 0xd6, 0x48, 0x93, 0x3d, + 0x5a, 0x7f, 0xca, 0x81, 0x42, 0xbc, 0xb6, 0x67, 0xb7, 0xae, 0x40, 0xc0, 0x7f, + 0x2f, 0x12, 0x3a, 0x7f, 0x22, 0x43, 0x42, 0xec, 0xc1, 0x21, 0x07, 0xf0, 0x18, + 0xc9, 0x11, 0x30, 0x21, 0xef, 0x26, 0x44, 0xdd, 0xc0, 0xaf, 0x9d, 0xa9, 0x20, + 0xb5, 0x00, 0xbd, 0x0d, 0x54, 0x45, 0x7f, 0x0d, 0x3b, 0x03, 0x1a, 0xaa, 0x21, + 0xc4, 0xec, 0x63, 0xf9, 0x09, 0x08, 0x0b, 0x20, 0x2e, 0xd4, 0x56, 0x73, 0x13, + 0xed, 0x76, 0x81, 0xd7, 0x4d, 0xfb, 0x14, 0xf4, 0xf7, 0x23, 0xc4, 0x99, 0xbc, + 0x1c, 0x14, 0x6a, 0x05, 0xe0, 0x8a, 0x5c, 0x8a, 0xf7, 0xb1, 0x30, 0xf4, 0xf3, + 0x08, 0x0b, 0xfb, 0x7f, 0xaf, 0x39, 0x78, 0x77, 0x25, 0xda, 0xbd, 0x9e, 0xcf, + 0x26, 0xf3, 0x1e, 0xd8, 0x08, 0x5c, 0xcc, 0x77, 0xaa, 0x07, 0xfa, 0x08, 0x14, + 0xce, 0x11, 0xa1, 0x71, 0xa8, 0x8c, 0x5a, 0xf2, 0xd5, 0x9f, 0x60, 0x54, 0xd5, + 0x21, 0xbe, 0x7f, 0xa4, 0xa3, 0x7f, 0x74, 0x81, 0x5c, 0x81, 0xd4, 0x15, 0x13, + 0x7f, 0x68, 0x19, 0x7f, 0xda, 0x68, 0xf9, 0x20, 0x64, 0x1e, 0xcd, 0xe3, 0x03, + 0x16, 0x4f, 0xbe, 0x45, 0xe8, 0xfd, 0x8d, 0xd9, 0xf3, 0xd1, 0xa0, 0x90, 0x81, + 0xfc, 0x81, 0x2c, 0x68, 0xca, 0x21, 0x0a, 0x17, 0xff, 0x81, 0xe5, 0x81, 0x39, + 0x04, 0x00, 0xc6, 0xb3, 0x7f, 0x2a, 0xd7, 0x1b, 0xd8, 0x35, 0xa4, 0x7f, 0x47, + 0x5c, 0xf7, 0x76, 0x67, 0x24, 0xef, 0x4e, 0x41, 0xab, 0xcc, 0xd2, 0x7f, 0x81, + 0x4f, 0x35, 0x7f, 0xb8, 0x99, 0xf9, 0x25, 0x98, 0x7f, 0x81, 0x6f, 0xf5, 0x7f, + 0xd5, 0xc3, 0xc9, 0xd7, 0x59, 0x92, 0x2b, 0xcd, 0x99, 0x94, 0x7f, 0x1e, 0xb1, + 0x40, 0xcc, 0x15, 0x8d, 0x77, 0x63, 0xba, 0x24, 0x2b, 0x28, 0x46, 0xd1, 0x7f, + 0xa2, 0xc3, 0xd2, 0xa1, 0x3b, 0x05, 0x26, 0xd1, 0x1c, 0x19, 0xe1, 0x04, 0x9a, + 0x15, 0x81, 0xb9, 0x41, 0x05, 0x9f, 0xe8, 0x49, 0x18, 0x1b, 0x05, 0x30, 0x71, + 0xe4, 0x17, 0x7f, 0x7f, 0x02, 0x6f, 0x64, 0xee, 0x30, 0xcd, 0x04, 0x27, 0x4b, + 0xeb, 0x7f, 0x7f, 0xf4, 0xca, 0xc5, 0x7f, 0xb9, 0x08, 0x84, 0x3c, 0x43, 0x8b, + 0x6f, 0x6b, 0x1c, 0x42, 0x28, 0x81, 0xeb, 0xae, 0xcf, 0x9f, 0x04, 0x00, 0x7f, + 0xf8, 0xc1, 0x0c, 0xd8, 0x1e, 0x49, 0x9a, 0x50, 0xaf, 0xed, 0x26, 0xb0, 0x49, + 0x45, 0x21, 0xe4, 0xf8, 0x7f, 0x7f, 0xd7, 0xd1, 0xa9, 0x41, 0x38, 0xc6, 0x38, + 0x7f, 0xfd, 0xf8, 0x7f, 0x12, 0xa8, 0xfb, 0xae, 0x7f, 0x07, 0x65, 0x81, 0x59, + 0x94, 0xff, 0xaf, 0xc0, 0x7f, 0xdf, 0xa3, 0x17, 0x05, 0x7f, 0x03, 0xe9, 0xb5, + 0x6c, 0xd5, 0x35, 0x15, 0xf7, 0x56, 0x7f, 0x54, 0xe8, 0x3b, 0x34, 0x06, 0xd6, + 0x81, 0x20, 0x18, 0x25, 0x7f, 0xc6, 0x4f, 0x5a, 0xd2, 0x1b, 0xf4, 0x56, 0xb4, + 0xa3, 0xee, 0x19, 0x89, 0x5c, 0x58, 0x25, 0x11, 0x27, 0x6e, 0x1a, 0x0f, 0x36, + 0x33, 0xee, 0x03, 0x7f, 0x28, 0xbc, 0x42, 0x01, 0xdd, 0x3f, 0x38, 0x05, 0x69, + 0xc8, 0xfa, 0xe0, 0xd3, 0xd1, 0xbb, 0x55, 0x81, 0x70, 0xc9, 0xab, 0x1a, 0x7f, + 0x6c, 0x51, 0x09, 0x00, 0xf5, 0x9e, 0x57, 0xab, 0x2a, 0x08, 0xcf, 0xb5, 0xe5, + 0x3b, 0x13, 0x7f, 0x04, 0x7f, 0x7f, 0x61, 0xfa, 0x7f, 0xb7, 0x31, 0x2d, 0x48, + 0x3f, 0xf0, 0xf1, 0x37, 0xde, 0x9a, 0xc1, 0xf0, 0x5f, 0x30, 0x2e, 0xd9, 0xb9, + 0x53, 0xe4, 0x02, 0x07, 0x09, 0xad, 0x3d, 0x01, 0x3c, 0x31, 0x12, 0xdf, 0x6d, + 0x2f, 0xd4, 0x54, 0x9b, 0x81, 0x81, 0xcd, 0x28, 0xa8, 0x01, 0x81, 0x7f, 0x03, + 0x5a, 0x12, 0x8e, 0x1e, 0x3f, 0x0d, 0x7f, 0x99, 0x2a, 0xa1, 0xe8, 0xac, 0xae, + 0x74, 0xf2, 0xb8, 0xb9, 0x31, 0xf0, 0xe9, 0x76, 0xfd, 0x15, 0xc4, 0x8f, 0x28, + 0x7f, 0x0a, 0xfa, 0xaf, 0xd5, 0x02, 0x56, 0x28, 0x6b, 0xeb, 0x6d, 0x0f, 0x03, + 0x7f, 0x1a, 0x7f, 0x7f, 0x06, 0xb7, 0xd0, 0xc7, 0xa0, 0xbd, 0xd2, 0xfa, 0x58, + 0x7f, 0x89, 0xbe, 0x81, 0x81, 0xeb, 0x82, 0x90, 0x8b, 0xf9, 0xe3, 0xca, 0xca, + 0x42, 0x6a, 0x50, 0xd8, 0x56, 0x45, 0x79, 0xe5, 0x0f, 0x7f, 0xea, 0xdb, 0x7f, + 0x2b, 0x7f, 0xf9, 0x9b, 0xb0, 0x29, 0x5e, 0xfa, 0x59, 0xff, 0x7f, 0x7f, 0xe3, + 0x7a, 0x04, 0xb1, 0x95, 0xe0, 0x60, 0xd8, 0xff, 0xe9, 0x47, 0x8f, 0x5b, 0xa2, + 0x01, 0x81, 0x53, 0xed, 0x51, 0x34, 0x57, 0x0d, 0xcd, 0x9b, 0x2e, 0x09, 0xa9, + 0x13, 0xa4, 0xa1, 0xa6, 0x40, 0x16, 0xdc, 0x61, 0xa0, 0xee, 0xb5, 0x76, 0x8b, + 0xbc, 0xeb, 0xda, 0x00, 0x31, 0x0c, 0x2f, 0xe3, 0x8d, 0x9e, 0x93, 0x16, 0x5f, + 0x86, 0x81, 0x02, 0xa7, 0xba, 0x6a, 0xb8, 0xc7, 0xc9, 0x87, 0xa6, 0xfd, 0xe0, + 0x73, 0xf0, 0xb1, 0x26, 0x2c, 0xef, 0x71, 0xe7, 0x3f, 0x09, 0x6b, 0x1b, 0xad, + 0x53, 0x1e, 0x25, 0xfc, 0x1d, 0x99, 0x1d, 0xcf, 0xbc, 0x15, 0x7f, 0x65, 0xdc, + 0x1b, 0xd2, 0x6e, 0xe0, 0x1e, 0x81, 0xad, 0x0c, 0xdf, 0xe0, 0x81, 0xf7, 0x43, + 0x7f, 0xab, 0x7e, 0xfc, 0x3a, 0xde, 0xfd, 0x10, 0xba, 0xdd, 0x5c, 0x6b, 0x5c, + 0xd3, 0x2e, 0x77, 0xfb, 0x5a, 0xd1, 0x6e, 0x3c, 0x3a, 0x4b, 0xe4, 0x0f, 0x4d, + 0xb0, 0xf3, 0x81, 0x11, 0x2c, 0xbc, 0xc4, 0x51, 0xaa, 0x7f, 0x40, 0x49, 0xbe, + 0xf9, 0x10, 0x64, 0x7f, 0x0a, 0x9f, 0x2b, 0xcb, 0x49, 0xd0, 0x81, 0x38, 0x89, + 0xdb, 0x9a, 0xf7, 0x3b, 0xe8, 0x24, 0x9c, 0x21, 0x8d, 0x60, 0xcf, 0xd2, 0xdd, + 0x10, 0x1e, 0xc0, 0xf5, 0x79, 0xad, 0x8e, 0xbe, 0xce, 0x36, 0x61, 0xae, 0xc2, + 0x1a, 0x32, 0xf2, 0x7f, 0xd1, 0xef, 0x8b, 0xca, 0x08, 0xef, 0x20, 0x2c, 0x4c, + 0xc0, 0xf6, 0x7f, 0x76, 0x56, 0xdf, 0x44, 0xcf, 0xec, 0x5d, 0xe0, 0x0b, 0xad, + 0x7f, 0x7f, 0xe8, 0x81, 0x42, 0x81, 0x2f, 0xfa, 0x0c, 0x32, 0x81, 0xc8, 0xca, + 0x3b, 0xfd, 0x3f, 0xa9, 0x1c, 0x0d, 0x16, 0xf7, 0xda, 0x7f, 0x67, 0x21, 0xe6, + 0x7f, 0x77, 0x7f, 0xb1, 0xd1, 0x69, 0x81, 0x54, 0x5a, 0xef, 0x34, 0xde, 0xc1, + 0x7f, 0xd3, 0x52, 0xdf, 0x66, 0xec, 0x41, 0x21, 0xe0, 0x04, 0xf6, 0x81, 0x81, + 0xfd, 0x48, 0x10, 0xf9, 0xbf, 0xb0, 0x81, 0x60, 0xc0, 0xdc, 0xa3, 0xc3, 0xec, + 0x6d, 0x0c, 0x1d, 0x05, 0x08, 0xbd, 0x7f, 0x0b, 0x8f, 0x06, 0x81, 0xea, 0xcf, + 0xac, 0x11, 0xc6, 0x7f, 0xe9, 0x1c, 0xd7, 0x7f, 0x81, 0x81, 0xd7, 0xdc, 0xf2, + 0x38, 0x13, 0x6a, 0x9f, 0xad, 0xb5, 0x83, 0x02, 0x7f, 0x64, 0x04, 0xfc, 0xff, + 0x92, 0xac, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x7f, + 0xf0, 0xff, 0xff, 0x8a, 0xf8, 0xff, 0xff, 0x87, 0xf6, 0xff, 0xff, 0x8e, 0xff, + 0xff, 0xff, 0x68, 0x11, 0x00, 0x00, 0x24, 0xea, 0xff, 0xff, 0x95, 0x27, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x58, 0xe5, 0xff, 0xff, 0x96, 0xef, 0xff, 0xff, + 0xe7, 0xf7, 0xff, 0xff, 0x63, 0x00, 0x00, 0x00, 0x4f, 0xf8, 0xff, 0xff, 0xac, + 0xff, 0xff, 0xff, 0x5d, 0x25, 0x00, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xc1, 0xff, + 0xff, 0xff, 0xe0, 0x07, 0x00, 0x00, 0x1b, 0x03, 0x00, 0x00, 0x9a, 0xfd, 0xff, + 0xff, 0xf8, 0x04, 0x00, 0x00, 0xe0, 0xfc, 0xff, 0xff, 0xa2, 0xfd, 0xff, 0xff, + 0xf5, 0xee, 0xff, 0xff, 0x02, 0xfb, 0xff, 0xff, 0x19, 0x20, 0x00, 0x00, 0xd6, + 0x26, 0x00, 0x00, 0xc9, 0xfc, 0xff, 0xff, 0x8e, 0x22, 0x00, 0x00, 0x21, 0xff, + 0xff, 0xff, 0xbf, 0x31, 0x00, 0x00, 0x6b, 0x27, 0x00, 0x00, 0xce, 0xe7, 0xff, + 0xff, 0x52, 0xfd, 0xff, 0xff, 0xfc, 0xfc, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, + 0x8e, 0x20, 0x00, 0x00, 0xd8, 0x04, 0x00, 0x00, 0x2f, 0xfc, 0xff, 0xff, 0xc2, + 0x29, 0x00, 0x00, 0x34, 0xf3, 0xff, 0xff, 0xfd, 0xec, 0xff, 0xff, 0x52, 0xf9, + 0xff, 0xff, 0x66, 0xeb, 0xff, 0xff, 0x90, 0x21, 0x00, 0x00, 0xef, 0x39, 0x00, + 0x00, 0xb4, 0x03, 0x00, 0x00, 0xe5, 0x01, 0x00, 0x00, 0x37, 0xfb, 0xff, 0xff, + 0xf5, 0xf8, 0xff, 0xff, 0xac, 0xf9, 0xff, 0xff, 0x05, 0xf5, 0xff, 0xff, 0x74, + 0xff, 0xff, 0xff, 0xd7, 0xf8, 0xff, 0xff, 0x3a, 0x1e, 0x00, 0x00, 0x43, 0x2e, + 0x00, 0x00, 0xf0, 0xf2, 0xff, 0xff, 0x1f, 0xfd, 0xff, 0xff, 0x4d, 0x1c, 0x00, + 0x00, 0xe9, 0xff, 0xff, 0xff, 0xb6, 0xfc, 0xff, 0xff, 0x45, 0x2c, 0x00, 0x00, + 0xf4, 0x08, 0x00, 0x00, 0xbe, 0xff, 0xff, 0xff, 0x92, 0x29, 0x00, 0x00, 0xf6, + 0x32, 0x00, 0x00, 0x01, 0xf7, 0xff, 0xff, 0xe3, 0xf6, 0xff, 0xff, 0xf2, 0xfd, + 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0x1a, 0xf4, 0xff, 0xff, 0x22, 0x00, 0x00, + 0x00, 0x32, 0xeb, 0xff, 0xff, 0xed, 0x22, 0x00, 0x00, 0x3c, 0xfc, 0xff, 0xff, + 0x95, 0x00, 0x00, 0x00, 0xcb, 0x0b, 0x00, 0x00, 0xc6, 0x32, 0x00, 0x00, 0xf8, + 0xf8, 0xff, 0xff, 0x28, 0x27, 0x00, 0x00, 0x1b, 0x05, 0x00, 0x00, 0xfb, 0xfe, + 0xff, 0xff, 0x05, 0xf9, 0xff, 0xff, 0xb3, 0x27, 0x00, 0x00, 0xb7, 0x2d, 0x00, + 0x00, 0x78, 0x0e, 0x00, 0x00, 0x0e, 0xf7, 0xff, 0xff, 0xe2, 0xf3, 0xff, 0xff, + 0xc4, 0xfe, 0xff, 0xff, 0x35, 0xff, 0xff, 0xff, 0x1b, 0xf6, 0xff, 0xff, 0xa4, + 0xfd, 0xff, 0xff, 0x1d, 0xfd, 0xff, 0xff, 0xe7, 0x28, 0x00, 0x00, 0x1e, 0xf6, + 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0x12, 0xf8, 0xff, 0xff, 0x04, 0xf8, 0xff, + 0xff, 0x51, 0xf8, 0xff, 0xff, 0xde, 0xff, 0xff, 0xff, 0x15, 0x07, 0x00, 0x00, + 0xa4, 0xfa, 0xff, 0xff, 0xb4, 0xf8, 0xff, 0xff, 0x8b, 0x2d, 0x00, 0x00, 0xd5, + 0x2f, 0x00, 0x00, 0x47, 0xf9, 0xff, 0xff, 0xbb, 0xf8, 0xff, 0xff, 0xda, 0x39, + 0x00, 0x00, 0xa0, 0x14, 0x00, 0x00, 0x2c, 0xfb, 0xff, 0xff, 0x20, 0x01, 0x00, + 0x00, 0xf5, 0xfc, 0xff, 0xff, 0x4b, 0x29, 0x00, 0x00, 0x80, 0xfd, 0xff, 0xff, + 0x4c, 0x22, 0x00, 0x00, 0xd7, 0x07, 0x00, 0x00, 0xb3, 0x28, 0x00, 0x00, 0x21, + 0xff, 0xff, 0xff, 0xf3, 0xf7, 0xff, 0xff, 0x17, 0xfe, 0xff, 0xff, 0xa3, 0xf4, + 0xff, 0xff, 0x4d, 0x38, 0x00, 0x00, 0x2a, 0xfd, 0xff, 0xff, 0x3b, 0x38, 0x00, + 0x00, 0x7a, 0xfc, 0xff, 0xff, 0x78, 0xfd, 0xff, 0xff, 0x5e, 0x01, 0x00, 0x00, + 0xb6, 0x43, 0x00, 0x00, 0x9e, 0xae, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00, 0x40, + 0x02, 0x00, 0x00, 0x47, 0xc3, 0xfe, 0xec, 0xfe, 0x7f, 0xd6, 0x81, 0x3d, 0x37, + 0x29, 0x0b, 0xb8, 0x1b, 0x0c, 0x3a, 0x13, 0xc8, 0xde, 0x81, 0xd3, 0x01, 0xf4, + 0xbc, 0x3c, 0xf7, 0x44, 0xac, 0x0b, 0xf6, 0x81, 0xc9, 0x30, 0x13, 0xe8, 0x31, + 0x0f, 0x2c, 0x8d, 0xc6, 0x7f, 0x28, 0x0d, 0xf9, 0xb9, 0xa3, 0x4d, 0x81, 0x0b, + 0xed, 0x7f, 0xfb, 0xe2, 0x7f, 0xbf, 0x91, 0x7f, 0xc9, 0xa9, 0x72, 0x30, 0xfb, + 0xe1, 0x42, 0x48, 0x81, 0x1f, 0x3c, 0x7f, 0x7c, 0xac, 0x93, 0x51, 0x7f, 0xdd, + 0x15, 0xf1, 0x13, 0x47, 0x7f, 0x34, 0x90, 0x63, 0xb4, 0xfd, 0x89, 0x7f, 0xb9, + 0x7f, 0x17, 0x31, 0xb5, 0x5f, 0xa1, 0x3d, 0x4c, 0x60, 0x9c, 0x38, 0x81, 0xe9, + 0xf7, 0x82, 0xb6, 0xfd, 0xcf, 0xed, 0x39, 0x81, 0x89, 0xba, 0x8a, 0x19, 0x27, + 0xe8, 0xde, 0x81, 0x44, 0x86, 0xb3, 0x5b, 0xa5, 0x81, 0x37, 0x8b, 0xd5, 0xab, + 0xac, 0x0c, 0xc4, 0x03, 0xfb, 0xea, 0xb8, 0xd5, 0xa4, 0xe3, 0xcd, 0xeb, 0xea, + 0xec, 0x24, 0xce, 0x10, 0xdc, 0xee, 0xdb, 0xe8, 0xe0, 0x35, 0x08, 0xcc, 0xea, + 0xf1, 0x3e, 0xf8, 0xc7, 0xf9, 0x9a, 0xfe, 0x4a, 0x30, 0xf9, 0xdd, 0x1a, 0xec, + 0x0b, 0xd9, 0xd0, 0xd7, 0xf9, 0xd0, 0xfb, 0x9e, 0xf0, 0xbb, 0xdf, 0xf5, 0x0a, + 0xdd, 0xfd, 0xdf, 0xd2, 0x07, 0xe0, 0xfe, 0x05, 0x96, 0x42, 0xf2, 0xec, 0xb9, + 0x3d, 0xf1, 0x66, 0x81, 0x18, 0x77, 0xf4, 0x89, 0x7f, 0xbe, 0x7f, 0x20, 0xf1, + 0x7f, 0xeb, 0xf5, 0x55, 0x81, 0x42, 0xbb, 0xdf, 0xba, 0x00, 0xef, 0x47, 0x03, + 0x8b, 0x81, 0xd6, 0xe0, 0xac, 0xab, 0x70, 0xa4, 0x81, 0xb3, 0x93, 0xa3, 0x75, + 0x7f, 0x4c, 0x24, 0x7f, 0x2d, 0x9b, 0x81, 0x7f, 0x8a, 0x4f, 0x02, 0x5f, 0xa6, + 0xfd, 0x4f, 0x8d, 0x81, 0xe0, 0xcf, 0xcd, 0x7f, 0xf6, 0x81, 0xca, 0xc7, 0x7f, + 0x0a, 0x6b, 0x5d, 0x2c, 0x28, 0x81, 0xbe, 0xa6, 0xdf, 0xba, 0x7f, 0x2c, 0x7e, + 0x7f, 0xf4, 0x7f, 0x94, 0x7f, 0x93, 0x81, 0x81, 0xb1, 0x81, 0x4c, 0x7f, 0x81, + 0x98, 0x7f, 0x81, 0xc2, 0x7f, 0x7f, 0x81, 0x6b, 0x82, 0xe3, 0x81, 0x7f, 0x22, + 0x3b, 0x7f, 0x89, 0x7f, 0x81, 0xab, 0xdb, 0x1e, 0x7f, 0x7f, 0x1b, 0x22, 0x65, + 0x4f, 0x81, 0x99, 0xaa, 0x81, 0x8b, 0x7f, 0x81, 0xef, 0x81, 0x81, 0x08, 0x23, + 0xf6, 0x7d, 0xab, 0xaf, 0xd9, 0x83, 0xc5, 0xfc, 0x0a, 0xf1, 0xea, 0x00, 0x3e, + 0xf3, 0x07, 0xdd, 0x16, 0x17, 0xd4, 0x54, 0x03, 0xfb, 0xec, 0x05, 0xde, 0xb3, + 0x32, 0x13, 0x9d, 0x34, 0xfc, 0xdc, 0x72, 0xdb, 0x7f, 0xc5, 0xfc, 0x1e, 0xf8, + 0xcd, 0xea, 0x02, 0xa3, 0xb8, 0xbf, 0xb4, 0x05, 0x0d, 0x11, 0x7f, 0x08, 0x13, + 0xcf, 0xf2, 0xf7, 0xcf, 0xef, 0xb7, 0x0f, 0xbe, 0xdf, 0x2c, 0xe1, 0x11, 0xad, + 0xb7, 0xf7, 0xbc, 0x58, 0x14, 0xeb, 0x02, 0xfe, 0x01, 0xfa, 0x12, 0xea, 0x07, + 0xf0, 0xd0, 0xf8, 0xfe, 0xe0, 0xee, 0x0c, 0x36, 0x16, 0xf1, 0x17, 0xc2, 0xea, + 0xd2, 0xfb, 0xdc, 0xe0, 0xef, 0x00, 0xc5, 0xd6, 0x32, 0x46, 0x77, 0x01, 0xcf, + 0x2f, 0x0f, 0xc0, 0xd8, 0xec, 0x8b, 0xe7, 0xdb, 0xaa, 0xb9, 0x0a, 0xe6, 0x1d, + 0x22, 0xa5, 0x36, 0xd8, 0xb0, 0x30, 0x8a, 0xf3, 0xf3, 0x14, 0x0e, 0x81, 0xea, + 0xf3, 0xd0, 0xfc, 0xb0, 0xd1, 0xed, 0xea, 0x21, 0x7f, 0x61, 0x01, 0xb2, 0x07, + 0xa0, 0x0e, 0xfd, 0x98, 0x08, 0xd3, 0xe9, 0x07, 0xf0, 0xf2, 0xb4, 0x33, 0xdc, + 0x96, 0xd9, 0x10, 0xcc, 0xd5, 0xb5, 0x02, 0x63, 0x56, 0x1d, 0x2a, 0x5a, 0xea, + 0x2d, 0xba, 0xbd, 0x1c, 0x0d, 0x1f, 0x1e, 0x3a, 0x3f, 0x2e, 0xe4, 0xfc, 0xe4, + 0xb9, 0xd2, 0xb4, 0xd0, 0xb2, 0xc9, 0xd8, 0x2b, 0xe6, 0xf6, 0xe7, 0x2e, 0xef, + 0xf5, 0x28, 0xf0, 0xfd, 0x0b, 0xec, 0xfd, 0x15, 0xcd, 0xee, 0xee, 0xf1, 0x0f, + 0xa1, 0x0b, 0xce, 0xea, 0xf6, 0x07, 0xea, 0xf8, 0xf0, 0x22, 0xfe, 0x0b, 0xe0, + 0x0f, 0x01, 0xf2, 0xed, 0x22, 0x1b, 0x48, 0xd7, 0xf9, 0x05, 0xf5, 0xd1, 0xe1, + 0xe2, 0xf0, 0xf2, 0xb1, 0xf3, 0xee, 0x0c, 0x4d, 0xf4, 0xe9, 0x2d, 0x1d, 0x0e, + 0xd2, 0x08, 0x1e, 0x2c, 0x11, 0x40, 0x28, 0xea, 0xb0, 0xfc, 0xff, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x8b, 0x31, 0x00, 0x00, 0xe5, 0x8e, 0x00, + 0x00, 0x3e, 0x18, 0x00, 0x00, 0xd4, 0x04, 0x00, 0x00, 0xda, 0x3d, 0x00, 0x00, + 0x9d, 0xf1, 0xff, 0xff, 0x5e, 0x56, 0x00, 0x00, 0xe2, 0x3c, 0x00, 0x00, 0xef, + 0xde, 0xff, 0xff, 0x58, 0x35, 0x00, 0x00, 0x4a, 0x14, 0x00, 0x00, 0x9f, 0xf0, + 0xff, 0xff, 0x0e, 0x10, 0x00, 0x00, 0x1f, 0xdc, 0xff, 0xff, 0xf1, 0x08, 0x00, + 0x00, 0x47, 0x32, 0x00, 0x00, 0x12, 0x43, 0x00, 0x00, 0x6d, 0x1c, 0x00, 0x00, + 0x44, 0x7d, 0xff, 0xff, 0x96, 0x0b, 0x00, 0x00, 0xd3, 0x11, 0x00, 0x00, 0x13, + 0x1b, 0x00, 0x00, 0xb4, 0xa8, 0xff, 0xff, 0x1e, 0x1c, 0x00, 0x00, 0x2b, 0xd2, + 0xff, 0xff, 0x4b, 0x8b, 0x00, 0x00, 0x20, 0x27, 0x00, 0x00, 0xcd, 0xff, 0xff, + 0xff, 0x50, 0xce, 0xff, 0xff, 0x02, 0x39, 0x00, 0x00, 0x08, 0x30, 0x00, 0x00, + 0x91, 0xf1, 0xff, 0xff, 0x61, 0x12, 0x00, 0x00, 0xa9, 0x50, 0x00, 0x00, 0x28, + 0x1a, 0x00, 0x00, 0x4a, 0x0d, 0x00, 0x00, 0x60, 0x3b, 0x00, 0x00, 0x07, 0x37, + 0x00, 0x00, 0x15, 0x63, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x00, 0xbe, 0x37, 0x00, + 0x00, 0xfd, 0x2d, 0x00, 0x00, 0x1a, 0x3c, 0x00, 0x00, 0x08, 0x4b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x0a, 0x70, 0x00, 0x00, 0xde, 0xec, 0x00, 0x00, 0x12, + 0xef, 0xff, 0xff, 0xa8, 0xa0, 0xff, 0xff, 0x5d, 0x4b, 0x00, 0x00, 0x62, 0x1f, + 0x00, 0x00, 0x27, 0xfe, 0xff, 0xff, 0x8b, 0x23, 0x00, 0x00, 0xc5, 0xfe, 0xff, + 0xff, 0xc4, 0x02, 0x00, 0x00, 0xfc, 0x6a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, + 0xf9, 0x44, 0x00, 0x00, 0x15, 0x65, 0x00, 0x00, 0xae, 0x0c, 0x00, 0x00, 0x0d, + 0x6d, 0x00, 0x00, 0x37, 0x14, 0x00, 0x00, 0x86, 0x39, 0x00, 0x00, 0xfd, 0x60, + 0x00, 0x00, 0xcc, 0x09, 0xfc, 0xff, 0xd0, 0x09, 0xfc, 0xff, 0xd4, 0x09, 0xfc, + 0xff, 0x02, 0xb2, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, + 0x57, 0xc3, 0x64, 0x7f, 0x09, 0x99, 0x87, 0xf8, 0x13, 0x56, 0x0d, 0xbb, 0xe5, + 0x1d, 0xec, 0x1c, 0x72, 0xd5, 0x92, 0xc5, 0xa9, 0x79, 0x1a, 0xb3, 0xfc, 0x07, + 0xed, 0x44, 0x0f, 0x7f, 0x67, 0x4b, 0xee, 0x81, 0xd9, 0xd1, 0x2f, 0x7b, 0x81, + 0x81, 0xb8, 0xa1, 0x81, 0x7f, 0xc1, 0xf0, 0xc3, 0x7f, 0xc8, 0xc6, 0x63, 0x24, + 0x25, 0x26, 0x81, 0x9d, 0x4d, 0x81, 0x57, 0x81, 0xba, 0x12, 0xe7, 0x55, 0xed, + 0x95, 0x5c, 0x22, 0xe0, 0x14, 0x38, 0x33, 0xf9, 0x73, 0xf8, 0x19, 0xaf, 0xb6, + 0x7f, 0x76, 0xa7, 0xd2, 0xca, 0xb2, 0x98, 0xad, 0x40, 0x23, 0x56, 0xdd, 0x59, + 0xd4, 0x23, 0x50, 0xf4, 0xf0, 0xcd, 0x40, 0x56, 0xb8, 0x81, 0xc0, 0x94, 0xd0, + 0xca, 0xb9, 0x2f, 0xf3, 0xf1, 0x0a, 0x3a, 0x7f, 0xbe, 0x6e, 0x7f, 0x73, 0xda, + 0x81, 0x58, 0x87, 0x49, 0x9f, 0xd5, 0x7f, 0x09, 0x5f, 0x1b, 0x16, 0x3e, 0xc1, + 0xb0, 0x26, 0xd9, 0x0c, 0x8c, 0x00, 0xde, 0x25, 0x2e, 0xe7, 0xb7, 0x7f, 0xd7, + 0x65, 0xef, 0x0f, 0x81, 0x8b, 0x9a, 0xf4, 0x5b, 0x0c, 0xd1, 0xaf, 0xdc, 0x05, + 0x10, 0xf8, 0xbf, 0x7d, 0xd9, 0xc6, 0xe2, 0xe2, 0xe5, 0x7f, 0xe3, 0x0d, 0xab, + 0x99, 0x28, 0x22, 0xce, 0x4c, 0xdf, 0x63, 0x0f, 0x9d, 0x7f, 0x7f, 0x19, 0x31, + 0xe7, 0xd4, 0x7f, 0xc5, 0x29, 0x88, 0xe5, 0x06, 0xd2, 0x4e, 0xc7, 0x3b, 0x2b, + 0xf5, 0x7f, 0xd6, 0x2d, 0x02, 0x8c, 0x50, 0xdc, 0xa3, 0xb2, 0x99, 0x32, 0x7f, + 0x56, 0xc7, 0x2a, 0x36, 0xcb, 0xfa, 0xba, 0x40, 0x3e, 0x05, 0x7f, 0xdc, 0x29, + 0x2c, 0xec, 0xfb, 0xc9, 0x7f, 0x08, 0x4a, 0x04, 0xdc, 0xa1, 0x50, 0xdb, 0xe7, + 0xf8, 0x91, 0xe9, 0xfc, 0x67, 0x3b, 0x99, 0x32, 0x69, 0x10, 0xeb, 0x17, 0xa6, + 0xae, 0xf2, 0x78, 0xf3, 0x5d, 0x08, 0x72, 0x35, 0x09, 0x16, 0x83, 0xa1, 0x41, + 0x44, 0x34, 0x55, 0x28, 0x23, 0xd8, 0x44, 0xb6, 0x2b, 0x65, 0xe3, 0xcd, 0x7f, + 0xeb, 0xf3, 0x25, 0xb2, 0x81, 0x7f, 0x15, 0xb4, 0xae, 0x9a, 0x1a, 0x0d, 0xca, + 0x81, 0x1f, 0x81, 0xb7, 0xf8, 0xb6, 0x78, 0x27, 0xa7, 0xab, 0xab, 0xae, 0xdc, + 0xfe, 0xaa, 0x1b, 0x34, 0xf9, 0x38, 0x97, 0x2c, 0x14, 0x37, 0x3e, 0xb8, 0x9a, + 0x4c, 0xc0, 0x7f, 0xdf, 0x9d, 0xca, 0x1d, 0x8f, 0xdd, 0x7f, 0x7f, 0x1a, 0xf2, + 0xef, 0x7f, 0x7f, 0xca, 0x4b, 0xea, 0xd7, 0xb1, 0xfd, 0x61, 0x74, 0x1c, 0xa6, + 0x7f, 0x1b, 0x81, 0x7f, 0xe4, 0x07, 0x7f, 0xee, 0x40, 0xbd, 0x28, 0xf4, 0xe2, + 0x7f, 0xcc, 0x64, 0x2f, 0xf3, 0x92, 0x9b, 0x8c, 0xf5, 0xa0, 0xdc, 0x0d, 0xc2, + 0x03, 0x22, 0x4f, 0x47, 0xbc, 0x17, 0x1d, 0x2e, 0xd5, 0x3a, 0xbd, 0xbd, 0x22, + 0x72, 0xf8, 0x25, 0xfe, 0x7e, 0x7f, 0x04, 0x10, 0xe0, 0x7f, 0x10, 0x46, 0xf1, + 0xad, 0x46, 0x7f, 0x35, 0xff, 0xde, 0xe7, 0xcf, 0xf5, 0x7f, 0x55, 0xf0, 0xbc, + 0xc2, 0xda, 0x7b, 0x51, 0x34, 0x0c, 0xb0, 0x1c, 0x0e, 0x08, 0x26, 0x79, 0x35, + 0x8b, 0x35, 0x0d, 0xe2, 0x6d, 0x14, 0x28, 0x81, 0xa9, 0x81, 0x41, 0x26, 0xf1, + 0x3a, 0xa9, 0x55, 0x81, 0x8f, 0xcc, 0x5f, 0x7f, 0x7f, 0xd2, 0x13, 0xd9, 0xbc, + 0x00, 0x86, 0xc6, 0x7f, 0x25, 0xf6, 0x9b, 0xc2, 0x43, 0x7f, 0xf2, 0x1f, 0x23, + 0x37, 0x53, 0x3f, 0x3e, 0x1a, 0xbb, 0x08, 0x61, 0xdc, 0xf9, 0x9a, 0x22, 0xcf, + 0x9d, 0x2d, 0x7f, 0x35, 0xac, 0xe8, 0xf6, 0x9b, 0x7f, 0x03, 0xdc, 0xe5, 0xfa, + 0xfe, 0x7f, 0x96, 0xc0, 0x81, 0xbf, 0x39, 0xae, 0x4b, 0x29, 0x3d, 0x1e, 0xf0, + 0xaf, 0xe6, 0xc3, 0x7f, 0x8f, 0x22, 0xf3, 0x92, 0x7f, 0xaf, 0x79, 0x83, 0x22, + 0x27, 0x20, 0x7f, 0xb1, 0xdb, 0x54, 0x1b, 0x0a, 0xd2, 0x7f, 0x7f, 0xd1, 0x22, + 0xff, 0x21, 0x29, 0xf1, 0xc6, 0x20, 0x3d, 0x7a, 0xc1, 0xd2, 0xb7, 0xca, 0x7f, + 0x14, 0x2b, 0x7f, 0xf7, 0xa8, 0x4c, 0x1f, 0x08, 0x08, 0x5d, 0x7f, 0xbd, 0x31, + 0x02, 0x32, 0xf6, 0xbf, 0xa5, 0x90, 0x7f, 0x11, 0x9e, 0xf6, 0x28, 0x2d, 0x3d, + 0xfe, 0xda, 0x31, 0x2f, 0x01, 0x15, 0x0b, 0xcc, 0x26, 0x54, 0xb2, 0xf5, 0xd8, + 0x9d, 0x3b, 0xfd, 0x81, 0xca, 0x28, 0x69, 0xef, 0x52, 0x41, 0xd3, 0xec, 0x23, + 0x7f, 0x30, 0x53, 0x81, 0x3d, 0x23, 0xe0, 0x7f, 0xc2, 0xe7, 0x54, 0x68, 0x2a, + 0xd2, 0x11, 0x1e, 0xcf, 0xe0, 0xcd, 0x38, 0x7f, 0x7f, 0x37, 0x7f, 0xf1, 0x75, + 0x57, 0xf9, 0x0c, 0xf3, 0x17, 0xfa, 0x6a, 0x22, 0x11, 0x7f, 0xe2, 0x08, 0x36, + 0x14, 0x5f, 0xbb, 0x0e, 0xf7, 0x78, 0x59, 0x33, 0x78, 0x6c, 0xf9, 0x64, 0x0e, + 0x02, 0xc2, 0x02, 0x7f, 0xe7, 0x82, 0x1f, 0x31, 0x2e, 0x7f, 0x7f, 0x69, 0x16, + 0x7f, 0x20, 0xb3, 0x02, 0x3c, 0xeb, 0x5c, 0xd3, 0x07, 0x81, 0x54, 0x9a, 0x20, + 0xd1, 0xa8, 0x81, 0xdf, 0x33, 0x09, 0xc5, 0xf5, 0x7c, 0xe9, 0xf7, 0x18, 0x13, + 0x7f, 0xf0, 0xd8, 0xcf, 0xc8, 0xcf, 0xcb, 0xf4, 0xd1, 0x1c, 0x35, 0xc9, 0x26, + 0xba, 0xae, 0x3f, 0x31, 0x45, 0xf2, 0x26, 0xf6, 0xca, 0x10, 0xca, 0x94, 0x03, + 0x22, 0xd3, 0x81, 0x29, 0x4b, 0x73, 0x65, 0xea, 0x26, 0x3b, 0x42, 0x78, 0x29, + 0x0f, 0xc6, 0x1e, 0x5c, 0x85, 0x39, 0x81, 0x05, 0x7f, 0x89, 0x28, 0x52, 0x2c, + 0xda, 0x18, 0xdc, 0x1a, 0x43, 0x07, 0x29, 0x5a, 0xee, 0xf4, 0x14, 0x7f, 0xed, + 0xff, 0xbf, 0xe7, 0xa2, 0x3e, 0x7f, 0xb6, 0x1a, 0xf8, 0x2d, 0xfc, 0x97, 0xd9, + 0x12, 0x3f, 0x63, 0xff, 0x2e, 0x81, 0x2b, 0x39, 0x43, 0xf5, 0xfa, 0x77, 0x44, + 0x4e, 0x12, 0x7f, 0x3c, 0x74, 0x15, 0xb7, 0xd2, 0x3a, 0x4a, 0x72, 0xf4, 0x04, + 0x81, 0xad, 0xd9, 0x5a, 0xd8, 0x7f, 0xc2, 0x95, 0xeb, 0x2d, 0xde, 0x52, 0x7f, + 0xe8, 0xa0, 0x01, 0x0e, 0x1c, 0x39, 0x57, 0x01, 0x49, 0x7f, 0xf0, 0xfc, 0x24, + 0x24, 0xfe, 0xe6, 0x8b, 0xd0, 0x02, 0xba, 0x60, 0x10, 0x23, 0xc0, 0xac, 0xa5, + 0xa5, 0x2e, 0x1d, 0x8a, 0x7f, 0xfb, 0xca, 0xf9, 0xe7, 0xec, 0x29, 0x12, 0x94, + 0xab, 0xb6, 0x39, 0x3f, 0xe2, 0x7f, 0xf4, 0x24, 0x48, 0x51, 0x7f, 0x6f, 0x9c, + 0x3a, 0x33, 0xc8, 0x03, 0xe3, 0xb0, 0xf5, 0xad, 0x1d, 0x4b, 0xec, 0xd6, 0x01, + 0xc0, 0x7f, 0xb0, 0x3e, 0xe6, 0xf0, 0xe6, 0x97, 0x7c, 0x8b, 0xb7, 0x1a, 0x81, + 0x37, 0x81, 0x29, 0x33, 0x33, 0xc0, 0x7f, 0x81, 0x96, 0x81, 0xc3, 0x92, 0x62, + 0x30, 0xba, 0xb1, 0xc6, 0x6f, 0xc9, 0x32, 0xc1, 0x7f, 0x0e, 0xe6, 0x25, 0xde, + 0x4c, 0xc8, 0xff, 0x16, 0x37, 0xd7, 0xe8, 0xf3, 0x7f, 0xfc, 0x3a, 0xf3, 0xe2, + 0x81, 0xff, 0xd4, 0x5f, 0xaf, 0xea, 0xe4, 0xe8, 0x52, 0x60, 0x1c, 0x9c, 0x81, + 0x30, 0x7f, 0xaa, 0xa5, 0xb4, 0x54, 0x1f, 0x5b, 0x7f, 0x1c, 0x0f, 0xfc, 0xab, + 0x9e, 0xb0, 0xc6, 0xc9, 0x81, 0x7f, 0x20, 0x8d, 0xd4, 0xa1, 0x93, 0xb2, 0xe9, + 0xf9, 0xe5, 0x34, 0x5a, 0x86, 0xaa, 0x8a, 0x81, 0x2d, 0x03, 0xc6, 0xc0, 0x26, + 0x0e, 0xd4, 0xe3, 0x4f, 0xf3, 0x4c, 0x60, 0xd2, 0x61, 0x1c, 0x1e, 0x7f, 0xdc, + 0xba, 0x25, 0xcb, 0x9a, 0x50, 0xbd, 0x7f, 0xaa, 0x81, 0xc1, 0xeb, 0xb9, 0x52, + 0xe5, 0x1d, 0xff, 0xdd, 0xba, 0xdc, 0x18, 0x5e, 0xd1, 0x9f, 0xac, 0x7f, 0xe9, + 0x7f, 0xf3, 0x7f, 0x2d, 0x7e, 0xed, 0xb5, 0x15, 0xda, 0x9d, 0x23, 0x56, 0x6b, + 0xa2, 0xcc, 0x2f, 0x81, 0x36, 0xb8, 0x07, 0x45, 0xaf, 0x01, 0x0d, 0x73, 0x2f, + 0x45, 0xf3, 0x19, 0xd8, 0x21, 0x4f, 0x31, 0xe4, 0x7f, 0xdb, 0xb9, 0xdf, 0xa5, + 0x0c, 0x10, 0xad, 0xa0, 0x5c, 0xd0, 0x6d, 0xc1, 0xe9, 0x20, 0xa4, 0x7f, 0x35, + 0xfe, 0xc3, 0x23, 0x7e, 0x43, 0x42, 0x13, 0x07, 0x21, 0xcc, 0x15, 0xac, 0x8e, + 0xca, 0xcc, 0x47, 0x5c, 0x7f, 0xc7, 0x2f, 0x81, 0x09, 0x37, 0xda, 0xee, 0x96, + 0x4a, 0x03, 0x93, 0xcf, 0xc4, 0xd7, 0xe2, 0x7f, 0xca, 0xba, 0x2d, 0x1a, 0xf6, + 0x1c, 0xec, 0xf7, 0xc9, 0x7f, 0x40, 0x48, 0x7f, 0x97, 0x74, 0x43, 0xda, 0x74, + 0x14, 0xe1, 0x3e, 0x96, 0x32, 0x25, 0xd9, 0x21, 0x7f, 0xba, 0x53, 0xd3, 0x76, + 0xd2, 0x14, 0xc2, 0xa9, 0xd5, 0x2c, 0xa3, 0x9d, 0x9e, 0x45, 0x87, 0x14, 0x0a, + 0xae, 0xdc, 0x1a, 0x1c, 0xe1, 0xbb, 0xc1, 0x83, 0x7f, 0x7f, 0xe6, 0xba, 0xcd, + 0x7f, 0x4b, 0x7f, 0xcc, 0x49, 0xd8, 0x36, 0x7f, 0x8e, 0xb6, 0xfc, 0xff, 0x04, + 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x81, 0xd9, 0xb1, 0x81, 0x51, 0x0d, + 0x56, 0x42, 0xa4, 0x72, 0xe6, 0xd3, 0x0e, 0x5e, 0xae, 0x23, 0xd1, 0x7f, 0x4a, + 0xe6, 0x0b, 0x0f, 0x24, 0xb8, 0x60, 0x38, 0xf1, 0x3c, 0xf2, 0xeb, 0xed, 0xf8, + 0xe3, 0x37, 0xd9, 0x14, 0x40, 0x35, 0xa9, 0x1c, 0x98, 0x2c, 0x7f, 0x7f, 0xbe, + 0x27, 0x22, 0x37, 0xe3, 0xdd, 0x54, 0xce, 0x9d, 0x11, 0xf6, 0xf4, 0x2b, 0xf3, + 0x40, 0x6d, 0x0b, 0xf5, 0x7f, 0xab, 0xac, 0x0b, 0xaf, 0x81, 0xf5, 0x6e, 0xf4, + 0xd1, 0xd0, 0x81, 0xdb, 0x44, 0x91, 0x99, 0x27, 0xbc, 0x46, 0xa7, 0xd6, 0x20, + 0x0c, 0xa1, 0x81, 0x2e, 0xba, 0xda, 0xc8, 0x2b, 0xd6, 0xa1, 0xdd, 0x15, 0x12, + 0xdf, 0x26, 0x4d, 0xe2, 0xe8, 0xeb, 0xe7, 0x08, 0xd4, 0xb5, 0xd2, 0xa0, 0x7f, + 0xb0, 0x4b, 0xe0, 0x95, 0xb9, 0xc3, 0xb6, 0xcf, 0xc3, 0xc5, 0xad, 0xeb, 0x12, + 0xd4, 0x2f, 0x0a, 0xb1, 0x5e, 0x5d, 0x7f, 0x1e, 0xbb, 0x49, 0xc0, 0x10, 0x7f, + 0xea, 0x8a, 0xa7, 0x4b, 0x47, 0x7f, 0x40, 0x7f, 0xa5, 0x46, 0xf6, 0xda, 0x27, + 0x2f, 0x3a, 0xdc, 0xb6, 0x7f, 0x59, 0x6e, 0xf0, 0x1b, 0x2b, 0x76, 0x1b, 0x72, + 0x8f, 0x77, 0x7f, 0xf3, 0xeb, 0x06, 0xb2, 0xdc, 0x22, 0x38, 0x40, 0x5e, 0x59, + 0x1e, 0x49, 0x6d, 0xe0, 0xe8, 0x09, 0x7f, 0x34, 0x7f, 0x7f, 0x3f, 0x52, 0x34, + 0x7f, 0x99, 0x39, 0xf0, 0xd0, 0x2b, 0xb6, 0x96, 0x87, 0x62, 0xd9, 0x91, 0x93, + 0x8a, 0x3d, 0x0a, 0x8b, 0xf9, 0x97, 0x7f, 0x7f, 0xb0, 0x04, 0x72, 0x4d, 0xb1, + 0x22, 0x7f, 0xae, 0x34, 0xf1, 0x3a, 0xd1, 0x81, 0xac, 0xa0, 0x27, 0x7f, 0x26, + 0x7f, 0xa1, 0xc0, 0xa7, 0x7f, 0x81, 0xc8, 0x81, 0x18, 0xad, 0xdc, 0x9d, 0x0c, + 0x51, 0xd5, 0xb4, 0xf0, 0xb0, 0xdf, 0x16, 0xf0, 0x87, 0x92, 0xf3, 0x1a, 0x7f, + 0x8c, 0x83, 0x55, 0x7c, 0x43, 0xe8, 0x9d, 0x07, 0xf3, 0x7f, 0x24, 0x81, 0xbb, + 0x19, 0x20, 0x2a, 0x1a, 0xa2, 0x61, 0xcb, 0xa2, 0x24, 0xde, 0xc2, 0x39, 0x16, + 0xa4, 0xa6, 0x57, 0xfe, 0x61, 0xd6, 0x46, 0xf0, 0xec, 0x7f, 0x24, 0xcf, 0xe1, + 0x4c, 0xe6, 0x0f, 0xfb, 0xeb, 0xc2, 0x60, 0x7c, 0x53, 0x55, 0xcd, 0x7f, 0xd9, + 0x06, 0xe5, 0xd4, 0xde, 0x1b, 0x0e, 0x38, 0x35, 0x22, 0x27, 0x17, 0x19, 0x29, + 0x59, 0xe0, 0xce, 0xf3, 0x81, 0x9f, 0xd6, 0x74, 0xf2, 0x65, 0xe4, 0x9a, 0x7f, + 0xd5, 0xd1, 0xc3, 0xb8, 0xe2, 0x50, 0x9e, 0x4b, 0x35, 0xfb, 0xab, 0x46, 0x0b, + 0xd1, 0xdc, 0xdb, 0x22, 0xc6, 0xbf, 0xce, 0xe7, 0x08, 0x51, 0xfa, 0xcf, 0x9a, + 0x99, 0xad, 0x30, 0x9c, 0xa9, 0x8b, 0xef, 0x9e, 0xec, 0x98, 0x7f, 0x7f, 0xd5, + 0x7f, 0x35, 0xb1, 0xdb, 0x22, 0xba, 0xe9, 0xc2, 0xf2, 0xdf, 0x89, 0x24, 0xe7, + 0x23, 0xfb, 0xdd, 0x23, 0xd3, 0x12, 0x94, 0x2a, 0x13, 0xd8, 0x8f, 0x81, 0xc8, + 0x3d, 0xca, 0xbc, 0x55, 0xd4, 0x71, 0xe2, 0xc3, 0x01, 0x34, 0xb2, 0xf4, 0x5c, + 0xa8, 0x13, 0xe8, 0x7c, 0x97, 0xe9, 0xeb, 0x9c, 0x7f, 0xb1, 0x32, 0x2b, 0x7f, + 0xcb, 0x1b, 0xb0, 0x7f, 0x24, 0x33, 0x49, 0x7f, 0x34, 0xe3, 0x13, 0xb8, 0x61, + 0xb8, 0x7f, 0x3a, 0x37, 0xd1, 0x27, 0x65, 0xeb, 0x0f, 0x0c, 0xc7, 0x5e, 0x6b, + 0xc6, 0x22, 0x03, 0x8a, 0xf3, 0x81, 0xc6, 0xeb, 0x14, 0xd7, 0x14, 0xf7, 0xb3, + 0xd3, 0x51, 0x0e, 0x41, 0x92, 0x03, 0x7f, 0x45, 0xd8, 0x8d, 0xe6, 0x18, 0x07, + 0x00, 0x69, 0xd1, 0x98, 0xa1, 0x8d, 0x23, 0xd1, 0xe7, 0x2e, 0xe3, 0x72, 0xe0, + 0xf2, 0xdf, 0x93, 0x21, 0xf6, 0xf6, 0x2d, 0x81, 0xf7, 0xe2, 0xfd, 0xa8, 0x14, + 0xad, 0xa6, 0x94, 0x99, 0xcc, 0xcd, 0x7f, 0xfe, 0x35, 0x89, 0x8e, 0x2b, 0x4c, + 0x2e, 0xdf, 0xb3, 0x36, 0x81, 0xbc, 0x32, 0xa4, 0x81, 0xa6, 0x7f, 0x47, 0x43, + 0x8e, 0x68, 0x7f, 0x26, 0x7f, 0xbb, 0x7f, 0x7f, 0xa1, 0xcb, 0x0f, 0x17, 0x7f, + 0x77, 0x4f, 0x57, 0xb2, 0xef, 0x0a, 0x28, 0xb6, 0x2f, 0x19, 0xf7, 0x89, 0x23, + 0xbd, 0xdc, 0x10, 0x26, 0x7f, 0x3e, 0x7f, 0x07, 0x7f, 0x47, 0x9b, 0x81, 0x68, + 0x1f, 0x7f, 0x10, 0x2f, 0x7f, 0x7f, 0xfc, 0x58, 0x81, 0xfa, 0x7f, 0xb6, 0x7f, + 0xcb, 0x8e, 0x40, 0xcb, 0x67, 0xd9, 0x7f, 0x9d, 0xfe, 0xbf, 0xd8, 0xa6, 0x7f, + 0x3e, 0x5f, 0xd2, 0xaf, 0x00, 0x7f, 0x81, 0xd6, 0x18, 0x07, 0x52, 0x2b, 0x79, + 0xeb, 0xaf, 0xcd, 0xb0, 0x4d, 0x4b, 0x4a, 0x6d, 0xe6, 0x7f, 0xaf, 0x5e, 0x9c, + 0xc6, 0x46, 0x38, 0x18, 0xd2, 0xc0, 0xff, 0x4a, 0xf3, 0xb7, 0xe1, 0xe5, 0x81, + 0x7f, 0xb4, 0xbb, 0x7f, 0x7f, 0x7f, 0xdc, 0x81, 0xdb, 0x4f, 0x3b, 0x09, 0x02, + 0xc1, 0x19, 0xfb, 0xff, 0x23, 0xdc, 0xa5, 0x00, 0x52, 0x7f, 0xfe, 0x9d, 0x4d, + 0xe9, 0xed, 0xe5, 0xd5, 0x05, 0x37, 0xd5, 0xeb, 0xdd, 0xe9, 0x22, 0x7f, 0x04, + 0x7f, 0xc5, 0x7f, 0x68, 0x5c, 0x81, 0xc8, 0x27, 0x29, 0x8f, 0xe8, 0x81, 0xa3, + 0x03, 0x35, 0x40, 0x61, 0x26, 0x0a, 0x4d, 0xcd, 0xf6, 0xac, 0x07, 0x0d, 0xf8, + 0x72, 0x03, 0x17, 0x34, 0x14, 0x01, 0xb7, 0x3c, 0xa9, 0xd4, 0x0b, 0xcd, 0xb3, + 0xfa, 0x86, 0x40, 0x7f, 0x16, 0x8b, 0x4f, 0x98, 0x42, 0xc0, 0x37, 0x03, 0xc4, + 0xc4, 0x94, 0x43, 0x02, 0xd2, 0x23, 0xf9, 0xf3, 0xde, 0xd1, 0x7f, 0xe8, 0x8b, + 0x81, 0x81, 0x05, 0x0a, 0x5b, 0x0c, 0x81, 0x43, 0xf7, 0x3c, 0x9a, 0xcc, 0x5b, + 0xfd, 0xf6, 0xc7, 0x98, 0x0b, 0x0e, 0xf0, 0x58, 0x77, 0x81, 0x98, 0xff, 0xa0, + 0xb4, 0x2d, 0x7a, 0xdd, 0xaf, 0xa5, 0x78, 0x2e, 0x7d, 0xc6, 0x7f, 0xb3, 0x22, + 0x43, 0xc3, 0x09, 0xb6, 0x8b, 0xe9, 0xe9, 0x37, 0x5d, 0x81, 0xcc, 0xde, 0x94, + 0xcb, 0x9c, 0x1f, 0xd8, 0xac, 0x81, 0x6e, 0xb3, 0xb5, 0xc7, 0x4e, 0xb3, 0x40, + 0x0e, 0xf2, 0xe9, 0x82, 0x16, 0xe8, 0x4b, 0x81, 0x7f, 0xdc, 0x40, 0xd4, 0xfb, + 0x7c, 0xbe, 0xeb, 0xec, 0x48, 0xe8, 0x7f, 0xaa, 0x3b, 0x2c, 0x1d, 0xbd, 0xc5, + 0xc1, 0xc4, 0x7f, 0xec, 0xfe, 0xda, 0x33, 0x81, 0x0f, 0x8c, 0xe7, 0x07, 0x13, + 0xb6, 0xf6, 0x33, 0x3b, 0x36, 0x81, 0xc5, 0x81, 0xf9, 0xf7, 0xcf, 0xb8, 0x07, + 0x1b, 0x25, 0x8c, 0xeb, 0x0a, 0x61, 0x24, 0xe7, 0xe5, 0x64, 0xd8, 0x8c, 0xb5, + 0x89, 0xad, 0x14, 0xa5, 0xa7, 0x5f, 0x9f, 0xec, 0x9d, 0xdb, 0x1f, 0xeb, 0x38, + 0x12, 0x50, 0x04, 0x05, 0x7f, 0xd5, 0x0d, 0xdf, 0xaf, 0x07, 0xaa, 0x88, 0xe9, + 0x22, 0x03, 0x42, 0xbb, 0x81, 0xb6, 0x5f, 0xb5, 0x74, 0x92, 0x7f, 0x4b, 0x89, + 0xe2, 0x95, 0x9e, 0x85, 0xfd, 0x11, 0x32, 0xb3, 0x58, 0x2e, 0xe0, 0xc8, 0xa2, + 0x1a, 0x6f, 0x81, 0x97, 0x7f, 0x97, 0xc6, 0x28, 0x41, 0x5a, 0x7f, 0xdc, 0xec, + 0x98, 0xba, 0x7f, 0x00, 0x1b, 0xa0, 0x6e, 0xc7, 0xc6, 0xd2, 0x1c, 0x33, 0xcf, + 0x3b, 0xe3, 0x5b, 0x68, 0x04, 0xb6, 0x39, 0x4d, 0x3d, 0xb0, 0x8c, 0x51, 0x26, + 0x5e, 0xd6, 0x9d, 0xeb, 0x1a, 0x05, 0xf7, 0xbe, 0xc8, 0x7f, 0x67, 0x7f, 0xc1, + 0x70, 0x3d, 0xf9, 0xb8, 0x6e, 0xbc, 0x37, 0xd4, 0xf9, 0xe2, 0x7f, 0x23, 0x33, + 0xe7, 0x9a, 0xf9, 0x7f, 0x7f, 0x7f, 0x61, 0x7f, 0xa7, 0xc2, 0xcc, 0x81, 0x01, + 0x7f, 0xd7, 0xa5, 0x6a, 0x81, 0xca, 0x88, 0x81, 0x4d, 0x59, 0x75, 0xb6, 0xc3, + 0xfd, 0x0c, 0x17, 0xcc, 0x7f, 0xab, 0xb6, 0x01, 0x89, 0x09, 0x22, 0x70, 0xf5, + 0xc1, 0xba, 0xf8, 0xfb, 0xd6, 0xfc, 0x65, 0x8c, 0x32, 0x63, 0xfd, 0xf1, 0xce, + 0x15, 0xbe, 0x13, 0x25, 0x73, 0xa2, 0xbf, 0xe6, 0xbe, 0xbb, 0x81, 0x2c, 0x53, + 0xe7, 0xa1, 0x48, 0x8d, 0xeb, 0xf5, 0x7f, 0x05, 0x13, 0x2f, 0x23, 0x02, 0xbd, + 0xf1, 0xff, 0xf5, 0xec, 0x4c, 0xd4, 0xe9, 0xca, 0xd4, 0x30, 0xf1, 0xb0, 0xe9, + 0x29, 0x7f, 0x42, 0x02, 0x30, 0x5b, 0x61, 0xa1, 0xed, 0x32, 0x31, 0x33, 0x0d, + 0x00, 0xda, 0xae, 0x91, 0x1f, 0x8e, 0x01, 0x2e, 0x46, 0x55, 0x36, 0x1c, 0x17, + 0x1e, 0xe2, 0x7f, 0xa1, 0x0f, 0xff, 0x6d, 0x81, 0x19, 0x28, 0xf6, 0xb1, 0xe9, + 0x0b, 0xb0, 0x4c, 0xb7, 0xa9, 0x3b, 0xe7, 0x84, 0x98, 0xc7, 0x26, 0xda, 0xa6, + 0x95, 0x27, 0xb7, 0x07, 0x20, 0xde, 0x4a, 0x7f, 0x7f, 0xcc, 0xf6, 0x01, 0x32, + 0xea, 0x31, 0x74, 0x93, 0x9e, 0xf0, 0x81, 0x81, 0xee, 0xf6, 0xfe, 0xae, 0xd6, + 0x55, 0x81, 0x1a, 0xbb, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0xcc, 0x1b, 0x00, 0x00, 0x82, 0x1f, 0x00, 0x00, 0xeb, 0x2d, 0x00, 0x00, + 0x9a, 0x2d, 0x00, 0x00, 0xff, 0x26, 0x00, 0x00, 0x2f, 0x35, 0x00, 0x00, 0x95, + 0xd4, 0xff, 0xff, 0xef, 0x14, 0x00, 0x00, 0xf3, 0x2f, 0x00, 0x00, 0xad, 0xe7, + 0xff, 0xff, 0x14, 0xd3, 0xff, 0xff, 0xcf, 0x0b, 0x00, 0x00, 0xb5, 0x19, 0x00, + 0x00, 0x22, 0x01, 0x00, 0x00, 0x2c, 0x18, 0x00, 0x00, 0xe6, 0xea, 0xff, 0xff, + 0xbf, 0x0a, 0x00, 0x00, 0x03, 0x0e, 0x00, 0x00, 0x15, 0xcc, 0xff, 0xff, 0xf9, + 0xf0, 0xff, 0xff, 0xfc, 0xea, 0xff, 0xff, 0x04, 0xe3, 0xff, 0xff, 0x68, 0x9d, + 0xff, 0xff, 0x8a, 0xdd, 0xff, 0xff, 0x7f, 0x15, 0x00, 0x00, 0x14, 0xee, 0xff, + 0xff, 0x7e, 0x12, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0xe3, 0x42, 0x00, 0x00, + 0xb2, 0xee, 0xff, 0xff, 0x2a, 0xed, 0xff, 0xff, 0x67, 0x1a, 0x00, 0x00, 0xbf, + 0xff, 0xff, 0xff, 0xdd, 0x3a, 0x00, 0x00, 0xff, 0xc9, 0xff, 0xff, 0x0a, 0xf7, + 0xff, 0xff, 0x89, 0xdb, 0xff, 0xff, 0x97, 0xf0, 0xff, 0xff, 0x30, 0x16, 0x00, + 0x00, 0x15, 0xfd, 0xff, 0xff, 0x52, 0x18, 0x00, 0x00, 0xbb, 0xf5, 0xff, 0xff, + 0xf4, 0xff, 0xff, 0xff, 0xb8, 0x23, 0x00, 0x00, 0x58, 0x2d, 0x00, 0x00, 0xc3, + 0xfe, 0xff, 0xff, 0xe7, 0x34, 0x00, 0x00, 0x8d, 0xcf, 0xff, 0xff, 0x3c, 0x34, + 0x00, 0x00, 0x21, 0x52, 0x00, 0x00, 0x98, 0x26, 0x00, 0x00, 0xc3, 0xef, 0xff, + 0xff, 0x40, 0xf3, 0xff, 0xff, 0xd8, 0x1f, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, + 0x6e, 0xf8, 0xff, 0xff, 0x67, 0x13, 0x00, 0x00, 0x53, 0x17, 0x00, 0x00, 0xcd, + 0xb2, 0xff, 0xff, 0xaf, 0xe6, 0xff, 0xff, 0x6a, 0x1d, 0x00, 0x00, 0xda, 0x27, + 0x00, 0x00, 0xf1, 0x1c, 0x00, 0x00, 0x99, 0x15, 0x00, 0x00, 0x40, 0x08, 0x00, + 0x00, 0x75, 0xd8, 0xff, 0xff, 0x19, 0xdf, 0xff, 0xff, 0x49, 0xfa, 0xff, 0xff, + 0xc0, 0x26, 0x00, 0x00, 0x61, 0x26, 0x00, 0x00, 0xa6, 0x41, 0x00, 0x00, 0x1b, + 0xf3, 0xff, 0xff, 0x64, 0x05, 0x00, 0x00, 0x38, 0x17, 0x00, 0x00, 0x80, 0x3e, + 0x00, 0x00, 0x7e, 0xe7, 0xff, 0xff, 0xd2, 0xd5, 0xff, 0xff, 0xd6, 0xcd, 0xff, + 0xff, 0xe7, 0xde, 0xff, 0xff, 0xad, 0xf9, 0xff, 0xff, 0xc2, 0xe6, 0xff, 0xff, + 0xaf, 0xe5, 0xff, 0xff, 0x35, 0x43, 0x00, 0x00, 0xc1, 0x02, 0x00, 0x00, 0xcf, + 0xfe, 0xff, 0xff, 0x29, 0x1d, 0x00, 0x00, 0x7c, 0xef, 0xff, 0xff, 0x37, 0x0e, + 0x00, 0x00, 0x81, 0x13, 0x00, 0x00, 0x15, 0x31, 0x00, 0x00, 0xb6, 0x26, 0x00, + 0x00, 0x2b, 0x21, 0x00, 0x00, 0x1b, 0xf9, 0xff, 0xff, 0x1d, 0x03, 0x00, 0x00, + 0x71, 0xfd, 0xff, 0xff, 0xf0, 0x1e, 0x00, 0x00, 0x33, 0x21, 0x00, 0x00, 0x03, + 0xfd, 0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0x92, 0xea, 0xff, 0xff, 0x33, 0x08, + 0x00, 0x00, 0x3e, 0xe2, 0xff, 0xff, 0x7e, 0xe2, 0xff, 0xff, 0xc3, 0x12, 0x00, + 0x00, 0x3b, 0xda, 0xff, 0xff, 0x81, 0xf0, 0xff, 0xff, 0x5f, 0x28, 0x00, 0x00, + 0x6f, 0x2c, 0x00, 0x00, 0x8e, 0xf4, 0xff, 0xff, 0xe4, 0xd7, 0xff, 0xff, 0xa7, + 0x23, 0x00, 0x00, 0xe5, 0xe8, 0xff, 0xff, 0xc9, 0xee, 0xff, 0xff, 0xdf, 0x15, + 0x00, 0x00, 0x10, 0x2e, 0x00, 0x00, 0xf9, 0x14, 0x00, 0x00, 0x99, 0xc5, 0xff, + 0xff, 0x47, 0x17, 0x00, 0x00, 0x25, 0x1e, 0x00, 0x00, 0x31, 0x40, 0x00, 0x00, + 0x01, 0xfd, 0xff, 0xff, 0x9e, 0x0c, 0x00, 0x00, 0x50, 0x20, 0x00, 0x00, 0xba, + 0x50, 0x00, 0x00, 0x3e, 0xf3, 0xff, 0xff, 0x5b, 0xfe, 0xff, 0xff, 0x16, 0xe2, + 0xff, 0xff, 0x45, 0xfc, 0xff, 0xff, 0x26, 0xbd, 0xfc, 0xff, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x2f, 0xf6, 0xb9, 0xd7, 0x23, 0xf5, 0x3b, 0xe2, + 0x24, 0xbf, 0x2c, 0xf9, 0x38, 0x0f, 0x25, 0xc9, 0x00, 0x27, 0xe0, 0xd5, 0x10, + 0x9f, 0xf4, 0x11, 0xd1, 0x25, 0xf0, 0x28, 0x73, 0xc2, 0x11, 0xd8, 0xfc, 0x1f, + 0x3b, 0x1a, 0xed, 0x16, 0xf3, 0xcc, 0x01, 0xdd, 0xce, 0x45, 0x1d, 0xd9, 0x3a, + 0x3c, 0xfc, 0xa9, 0x3c, 0x31, 0xe4, 0xb8, 0xc3, 0x7f, 0xfd, 0x63, 0x00, 0x12, + 0xdf, 0xfd, 0x56, 0xe6, 0x38, 0xf7, 0x0d, 0x27, 0xee, 0xef, 0x1a, 0xe2, 0xc2, + 0xf7, 0x06, 0x01, 0xe1, 0xa3, 0x6a, 0x00, 0xc4, 0x02, 0x24, 0x34, 0xfc, 0xeb, + 0xd5, 0x10, 0xcf, 0xc8, 0x10, 0xeb, 0x49, 0xf9, 0x04, 0x14, 0xf7, 0xc7, 0xff, + 0x23, 0x4b, 0x3c, 0x4f, 0x0c, 0x21, 0x22, 0xb5, 0xf6, 0xd4, 0xd4, 0xde, 0x02, + 0xe6, 0x39, 0x16, 0xfe, 0x73, 0xb6, 0x04, 0x16, 0x12, 0xee, 0xf4, 0x66, 0xe3, + 0x00, 0x0c, 0xd6, 0xbf, 0x2e, 0xd9, 0x02, 0xd9, 0xc6, 0x35, 0x25, 0xdb, 0x3e, + 0x04, 0xc1, 0x17, 0xe5, 0x40, 0x9c, 0x0e, 0xf6, 0xc8, 0xa8, 0x00, 0x54, 0x4a, + 0x2d, 0xd2, 0xb7, 0xb5, 0xfe, 0xe2, 0x4c, 0x30, 0x34, 0xfe, 0xfc, 0x05, 0x32, + 0x46, 0x19, 0xca, 0xe6, 0x77, 0x17, 0x81, 0x62, 0xf0, 0xc7, 0x04, 0x4a, 0x51, + 0x18, 0x0f, 0x07, 0xa3, 0x1b, 0xe3, 0xc0, 0x63, 0x03, 0x01, 0x33, 0x14, 0x17, + 0x35, 0x2e, 0x78, 0x2f, 0x03, 0xdd, 0xf6, 0x53, 0x1c, 0x11, 0x59, 0x23, 0x14, + 0xdc, 0xd7, 0x04, 0xcb, 0x3c, 0x46, 0x0c, 0x2c, 0xa5, 0xf5, 0xf1, 0xef, 0xd8, + 0x4a, 0xcd, 0x3f, 0xb5, 0x37, 0x46, 0xef, 0x56, 0x07, 0x39, 0x19, 0xe7, 0x64, + 0xf1, 0x37, 0x28, 0xe5, 0x24, 0x18, 0x36, 0xe3, 0xc9, 0x64, 0x4c, 0x25, 0x76, + 0xd8, 0x00, 0xfd, 0x83, 0xfd, 0x4c, 0x0c, 0x3a, 0xe9, 0xc3, 0x17, 0x6c, 0xeb, + 0xe0, 0x48, 0x36, 0x07, 0xd7, 0xe2, 0x15, 0xd5, 0xf9, 0xff, 0x05, 0x0a, 0xee, + 0xae, 0x15, 0x09, 0x34, 0xb7, 0x0f, 0xc5, 0xbb, 0xf9, 0xca, 0xbe, 0x13, 0xa9, + 0xa8, 0xd5, 0x60, 0x81, 0xfb, 0x0c, 0x33, 0xf4, 0xd9, 0xf8, 0x31, 0xff, 0x23, + 0x13, 0x13, 0xda, 0x95, 0xfa, 0xe7, 0x4c, 0xc5, 0xe7, 0x5e, 0xf3, 0xc6, 0x1f, + 0x3e, 0xbd, 0x32, 0xe7, 0xe6, 0x35, 0xd5, 0x02, 0x42, 0x3d, 0x05, 0x08, 0xde, + 0xc0, 0x2d, 0x31, 0x94, 0xf4, 0x2c, 0x05, 0xd2, 0xf3, 0xd2, 0xf9, 0xc5, 0x13, + 0x63, 0x22, 0x1e, 0xfa, 0xea, 0x12, 0xc4, 0xb4, 0x22, 0xdf, 0xf0, 0xf9, 0x0d, + 0xfb, 0x35, 0xdd, 0xe9, 0xe4, 0xdb, 0x46, 0xe1, 0x91, 0x1b, 0x2b, 0x10, 0xc4, + 0xc6, 0x16, 0xff, 0xfe, 0xe2, 0x12, 0xfa, 0xbf, 0x18, 0x0d, 0xe0, 0xf1, 0xc6, + 0x1a, 0x49, 0x14, 0xf2, 0x04, 0xf3, 0xe1, 0x1a, 0xbd, 0x0e, 0x5b, 0xa7, 0x41, + 0x2a, 0xed, 0xf0, 0x00, 0x35, 0xe8, 0x1c, 0xe5, 0x2a, 0x35, 0x0b, 0x73, 0x23, + 0xe6, 0x00, 0x0d, 0xf8, 0x09, 0x1e, 0xe4, 0x26, 0x0e, 0x2b, 0xc3, 0x3e, 0x08, + 0x17, 0x15, 0xb7, 0xd5, 0xfe, 0xb7, 0xd1, 0x1a, 0x0e, 0xbd, 0x56, 0x13, 0xcd, + 0x2b, 0x19, 0x06, 0xca, 0xd2, 0x31, 0xcf, 0x0c, 0x3a, 0x0b, 0x19, 0x44, 0xe3, + 0x10, 0xe1, 0x15, 0x18, 0x00, 0x0c, 0x1c, 0x0d, 0xe9, 0x05, 0xdb, 0x3e, 0x40, + 0xeb, 0xb1, 0x08, 0x72, 0xe5, 0x31, 0x56, 0xd7, 0xde, 0xfb, 0x31, 0x00, 0x55, + 0x10, 0xc3, 0x12, 0xfa, 0xf1, 0x15, 0x7b, 0xef, 0xdd, 0x04, 0x20, 0xc7, 0x15, + 0x13, 0xf9, 0x35, 0x0b, 0xe8, 0x2a, 0xff, 0xf8, 0x7f, 0xdd, 0x47, 0xf7, 0xd1, + 0x19, 0x02, 0xfb, 0x02, 0x55, 0xd5, 0x15, 0xe5, 0x43, 0x21, 0xbf, 0x0b, 0xd8, + 0x14, 0x28, 0x0a, 0xd9, 0x12, 0x36, 0x40, 0xf4, 0xfc, 0x22, 0xf2, 0x25, 0x7f, + 0x06, 0x23, 0x01, 0x39, 0xfb, 0xeb, 0xfb, 0xff, 0xdd, 0x1f, 0xee, 0xcd, 0xd0, + 0x10, 0x07, 0xed, 0x17, 0x3e, 0x09, 0xdf, 0x1a, 0xfa, 0x07, 0x36, 0xd5, 0x31, + 0xdf, 0xf3, 0x06, 0xe7, 0x00, 0x1b, 0x10, 0x13, 0x01, 0xee, 0xf5, 0xdc, 0xe9, + 0xe6, 0x24, 0x13, 0x03, 0x00, 0x07, 0xde, 0xe7, 0xdc, 0x02, 0x32, 0xeb, 0xf7, + 0xcf, 0x06, 0xc1, 0xde, 0xba, 0xf4, 0x07, 0x2a, 0x06, 0xf2, 0xeb, 0xce, 0x1e, + 0xe7, 0xcf, 0xfa, 0x01, 0xce, 0xdb, 0x08, 0x24, 0x42, 0xe2, 0x1b, 0x0e, 0xd8, + 0xe8, 0xde, 0xeb, 0xa9, 0xe9, 0xe5, 0x1b, 0x33, 0xe7, 0xe7, 0xde, 0x30, 0x33, + 0x6f, 0xfd, 0xc5, 0x1c, 0xe7, 0x0a, 0xf3, 0xdb, 0xf0, 0x11, 0xf4, 0x07, 0x30, + 0xe8, 0x00, 0x04, 0xc8, 0x13, 0x3e, 0x0a, 0x52, 0x2a, 0xba, 0x31, 0x13, 0xee, + 0x1e, 0x07, 0x1e, 0x10, 0xe8, 0xe6, 0xf8, 0xe6, 0xd5, 0x2a, 0x06, 0x0b, 0xc5, + 0xdb, 0xff, 0x45, 0xf8, 0x0d, 0x25, 0x26, 0x1b, 0xe4, 0xc6, 0x1c, 0xe5, 0x07, + 0xfc, 0x12, 0x70, 0xfe, 0xd3, 0x1c, 0x00, 0xc5, 0xcf, 0xbd, 0x11, 0x01, 0x1e, + 0xe7, 0xe5, 0x25, 0x06, 0x02, 0xfc, 0xbc, 0x01, 0x4b, 0xc3, 0xe8, 0xf1, 0xa9, + 0x54, 0x1d, 0x03, 0x32, 0xaf, 0xd1, 0x0e, 0xdd, 0xf6, 0x37, 0xe9, 0x81, 0x0b, + 0x41, 0x29, 0x92, 0x0a, 0x56, 0x0d, 0xd2, 0xe0, 0x08, 0xfb, 0xf6, 0xa3, 0xf3, + 0x1f, 0xe6, 0xd9, 0xcb, 0x28, 0x4d, 0x34, 0x43, 0x75, 0xdd, 0x1f, 0x47, 0xf8, + 0xea, 0xfd, 0xd7, 0x0e, 0xf8, 0xd8, 0x09, 0xf8, 0x3c, 0x03, 0xee, 0x1c, 0xe1, + 0x2b, 0xdd, 0x06, 0xdc, 0x07, 0xc9, 0xc4, 0xc1, 0xe0, 0xca, 0x2c, 0xe3, 0x30, + 0xfc, 0x2e, 0xe6, 0xf3, 0xff, 0x0f, 0x78, 0x18, 0x60, 0x15, 0x06, 0xf5, 0xbf, + 0x01, 0x00, 0xf0, 0x39, 0x01, 0xfd, 0xcb, 0x03, 0xff, 0xbb, 0xca, 0x09, 0xe9, + 0xe7, 0x81, 0xf5, 0x28, 0xb2, 0x4d, 0x05, 0xc4, 0xe0, 0x27, 0x14, 0x02, 0x0e, + 0x30, 0xf4, 0xee, 0x13, 0xd4, 0x58, 0x0f, 0x07, 0x16, 0x13, 0x48, 0x05, 0x17, + 0xc1, 0x13, 0xf0, 0xdf, 0x00, 0xcd, 0xe6, 0xf3, 0x0c, 0x05, 0x00, 0x2c, 0x0d, + 0xfe, 0x0a, 0x25, 0x03, 0xf8, 0x09, 0xf9, 0x2d, 0x08, 0xf8, 0x00, 0xf4, 0x20, + 0x0c, 0xf3, 0x34, 0x16, 0x0e, 0xee, 0xe7, 0x0a, 0xce, 0xeb, 0x0d, 0xe6, 0xff, + 0x52, 0xe3, 0xdb, 0xff, 0x17, 0x9d, 0x32, 0xd5, 0xe2, 0x0e, 0xd3, 0xec, 0x2a, + 0x4d, 0xf8, 0xe7, 0x47, 0x12, 0x1e, 0x20, 0x01, 0xfe, 0x01, 0xdf, 0x1a, 0xf4, + 0xfe, 0xea, 0xfa, 0xbd, 0x24, 0x3c, 0x0a, 0x2b, 0xef, 0xe8, 0x31, 0x1c, 0xe8, + 0xf9, 0xec, 0xf6, 0x07, 0xf1, 0x1e, 0xdb, 0x0c, 0x35, 0x0f, 0x0b, 0xf6, 0x01, + 0x76, 0x22, 0x1a, 0xc8, 0x07, 0x0f, 0x07, 0xd7, 0x12, 0x1f, 0x1f, 0x04, 0xef, + 0xfa, 0xf7, 0x22, 0x1d, 0x3e, 0x1b, 0x98, 0x0e, 0x0b, 0xf8, 0x0e, 0x1a, 0x06, + 0xff, 0xf8, 0xbf, 0x3f, 0x0f, 0xd3, 0x49, 0xff, 0xdf, 0x7f, 0xd8, 0xcd, 0xe7, + 0x1d, 0xd8, 0x26, 0x2a, 0xdb, 0xed, 0x14, 0x5f, 0xe3, 0xdd, 0x20, 0xe8, 0x0d, + 0xfe, 0x45, 0xfc, 0x39, 0xf8, 0x07, 0xda, 0xfc, 0xff, 0xd9, 0xf0, 0x38, 0x1b, + 0xed, 0x08, 0xf6, 0x05, 0xfc, 0x23, 0xeb, 0xfc, 0x31, 0x19, 0xe3, 0x5c, 0x42, + 0x11, 0xa9, 0x58, 0xcd, 0x1e, 0x20, 0x16, 0xc5, 0x23, 0xe6, 0xf3, 0x06, 0xfd, + 0xea, 0x0a, 0x07, 0x29, 0xe9, 0xee, 0xc4, 0x1d, 0x0f, 0x30, 0x3f, 0xc9, 0x0f, + 0x18, 0xd6, 0x3d, 0x06, 0x0c, 0x10, 0xbf, 0xdd, 0xfa, 0xf6, 0xdd, 0x1f, 0x1a, + 0x0f, 0xd4, 0xe0, 0x2a, 0x26, 0x19, 0x36, 0x0e, 0xec, 0x07, 0xf5, 0x33, 0x28, + 0xc3, 0xae, 0x1e, 0xe5, 0xeb, 0x29, 0xfb, 0x11, 0xeb, 0x34, 0x06, 0x06, 0x1e, + 0x7f, 0x11, 0xfb, 0xe6, 0xf8, 0x0d, 0x0f, 0x34, 0x30, 0x10, 0xc0, 0x0f, 0xf0, + 0x22, 0x65, 0x29, 0xed, 0x1c, 0xbd, 0x21, 0x15, 0x09, 0xde, 0x1c, 0x20, 0xdc, + 0xff, 0x12, 0x22, 0x0b, 0x38, 0x34, 0xf4, 0xc6, 0x37, 0xff, 0x18, 0x49, 0x11, + 0x08, 0xc9, 0x24, 0x12, 0x11, 0x51, 0x09, 0x25, 0xfd, 0xff, 0xd6, 0xff, 0xde, + 0x1b, 0x2d, 0xcc, 0xef, 0xd6, 0xef, 0xfb, 0x18, 0x30, 0x05, 0x35, 0xf3, 0xe7, + 0x2e, 0xfd, 0x08, 0xee, 0x22, 0xda, 0x0e, 0x1e, 0x5c, 0x2a, 0xda, 0x09, 0x04, + 0x07, 0x2f, 0xdb, 0xfd, 0x31, 0xf6, 0x04, 0x24, 0x02, 0xea, 0x1b, 0xed, 0x4f, + 0xfd, 0xd3, 0x1a, 0xf6, 0xd4, 0x04, 0x0c, 0x38, 0x0d, 0xdf, 0xdb, 0x26, 0x04, + 0x26, 0xdb, 0x4c, 0x22, 0x1b, 0xfc, 0xda, 0x19, 0x09, 0x28, 0x17, 0x1f, 0x58, + 0xe5, 0xe1, 0xda, 0x7f, 0xdc, 0x04, 0x16, 0x1d, 0x5b, 0x0b, 0x0f, 0xea, 0xdd, + 0xe1, 0xbc, 0xfa, 0x0e, 0x1c, 0xf8, 0x11, 0x1c, 0xcb, 0x2c, 0xad, 0x3c, 0x23, + 0x06, 0x2d, 0x42, 0xbc, 0xfe, 0xf9, 0x06, 0x5e, 0xee, 0xe2, 0xe6, 0xce, 0x12, + 0x24, 0xec, 0x53, 0xd7, 0x17, 0xd7, 0xdb, 0xe0, 0x04, 0x43, 0xeb, 0x1a, 0xff, + 0x65, 0xd0, 0x00, 0x3c, 0x58, 0xe3, 0xc6, 0xbe, 0x24, 0xc9, 0xde, 0xe3, 0xfa, + 0x1a, 0x38, 0xe8, 0x0f, 0xd8, 0x33, 0xf7, 0x3f, 0x32, 0x19, 0xbe, 0x11, 0xf0, + 0x19, 0x0e, 0x15, 0xed, 0x23, 0xc8, 0x08, 0xc9, 0xec, 0x0b, 0x1a, 0xd1, 0xb9, + 0x15, 0xdf, 0x23, 0x1e, 0x11, 0xf1, 0xf7, 0x35, 0x23, 0x28, 0xff, 0xcf, 0xf6, + 0x2d, 0xc8, 0xeb, 0x2b, 0xd9, 0x45, 0xcf, 0x14, 0x33, 0x69, 0x0d, 0x16, 0xcb, + 0x25, 0x33, 0x40, 0x20, 0xbd, 0x26, 0x19, 0x2d, 0x2a, 0x0e, 0x20, 0xc7, 0xd4, + 0xda, 0x03, 0xd0, 0xfe, 0x13, 0xfa, 0xb9, 0xf2, 0x29, 0x1d, 0x25, 0x04, 0xe8, + 0xd0, 0xf4, 0x21, 0x1b, 0x20, 0x03, 0x60, 0xfc, 0x10, 0xee, 0x6a, 0xf8, 0xfd, + 0x2a, 0xe8, 0xf8, 0xef, 0xf6, 0xbe, 0x28, 0xf9, 0xec, 0xff, 0xd3, 0x0e, 0xca, + 0xf6, 0x00, 0xe2, 0xda, 0x5a, 0xe1, 0x08, 0x15, 0x65, 0xe9, 0xfc, 0x19, 0x19, + 0x20, 0xf2, 0xf6, 0xdf, 0xf6, 0x2a, 0x10, 0xfa, 0x0f, 0xee, 0x08, 0xef, 0x1e, + 0xf5, 0xd5, 0xec, 0x00, 0xf6, 0x2b, 0xcc, 0xea, 0xb5, 0x77, 0x81, 0xfc, 0xc1, + 0xdb, 0xe2, 0xfd, 0xcf, 0x66, 0x53, 0xc2, 0x1b, 0xe0, 0x02, 0x1b, 0x02, 0xe2, + 0x01, 0xee, 0x09, 0x08, 0xc6, 0xfc, 0x0a, 0x16, 0xe6, 0xe9, 0x11, 0x05, 0x34, + 0x0a, 0xfe, 0x11, 0x17, 0x1f, 0xd9, 0xd6, 0xf9, 0x04, 0x21, 0xd8, 0x1a, 0x1f, + 0xfd, 0x13, 0xf6, 0x21, 0x07, 0xeb, 0x06, 0xeb, 0xc8, 0xa4, 0x2a, 0xae, 0x4d, + 0xb9, 0x3f, 0x60, 0x9e, 0x19, 0xe7, 0x11, 0x73, 0xff, 0xec, 0x3c, 0xe4, 0x33, + 0x4f, 0x02, 0xd1, 0xf5, 0xd0, 0xe9, 0x97, 0xb2, 0xa3, 0x46, 0xf9, 0x02, 0xe1, + 0x2a, 0xd0, 0x16, 0xe3, 0x08, 0xf3, 0xf1, 0x32, 0xfe, 0xd4, 0xf3, 0x3a, 0xc8, + 0x20, 0x85, 0xd2, 0x19, 0x73, 0x40, 0x5e, 0xcc, 0xdd, 0x07, 0xa5, 0xba, 0xcf, + 0x60, 0xfe, 0xe7, 0x1e, 0x01, 0xf5, 0xd1, 0x1c, 0x3a, 0xd0, 0x18, 0x19, 0xbe, + 0x1a, 0x2b, 0x7f, 0x4c, 0xef, 0x2f, 0x8b, 0x39, 0xf2, 0x30, 0xb5, 0x59, 0xf1, + 0x6f, 0x02, 0xcc, 0xd4, 0xdf, 0x2e, 0x05, 0xd5, 0x47, 0xd9, 0xec, 0xea, 0xaf, + 0xd2, 0x20, 0x5b, 0x49, 0xd7, 0x30, 0xc3, 0xad, 0xba, 0x05, 0x0b, 0xd9, 0xf4, + 0x3d, 0x72, 0xec, 0x30, 0xb5, 0x48, 0x2e, 0xc7, 0xe7, 0xde, 0xe2, 0xc4, 0x50, + 0xdc, 0x43, 0xf4, 0xe4, 0x2f, 0x14, 0x47, 0xca, 0x04, 0x33, 0x16, 0xf3, 0xae, + 0x0a, 0x66, 0x23, 0x35, 0x21, 0x37, 0xd8, 0x10, 0x12, 0xf5, 0x7f, 0x08, 0x58, + 0x6b, 0x3d, 0xb0, 0xd7, 0x08, 0x18, 0xf4, 0x00, 0x41, 0x29, 0x89, 0x07, 0xfd, + 0xe3, 0x1d, 0x15, 0xee, 0x09, 0x0e, 0x18, 0x07, 0x21, 0x01, 0xd2, 0x23, 0x3f, + 0x30, 0xc5, 0x1e, 0x51, 0x31, 0xbe, 0xd7, 0x5c, 0x1c, 0x11, 0x50, 0xcb, 0xd6, + 0x3c, 0xfc, 0xbd, 0x1a, 0x5d, 0xe9, 0xde, 0x2d, 0xed, 0xae, 0x09, 0x44, 0x4a, + 0x7b, 0x5f, 0x05, 0x22, 0x4c, 0x4f, 0x04, 0x36, 0xf8, 0x07, 0x17, 0xaf, 0xea, + 0x3d, 0xd3, 0x3c, 0xee, 0x21, 0xe4, 0x30, 0x59, 0xf3, 0xce, 0x3f, 0x03, 0x1e, + 0xc4, 0x05, 0x35, 0xd0, 0x12, 0x17, 0xfa, 0x22, 0xfa, 0xf0, 0x24, 0x24, 0xe3, + 0xe9, 0xf9, 0x2d, 0x6a, 0xf6, 0x2e, 0xe4, 0x3b, 0x25, 0xc5, 0xf6, 0x3a, 0xc6, + 0xf2, 0x29, 0xca, 0x2c, 0x7c, 0xf9, 0xeb, 0x00, 0xde, 0xd7, 0x27, 0xd3, 0x22, + 0x21, 0x73, 0x38, 0xec, 0x05, 0xfb, 0xdb, 0xfa, 0xf9, 0x3a, 0xa1, 0xf0, 0xdb, + 0x7f, 0xec, 0xe7, 0x12, 0x1a, 0x3a, 0xfb, 0xc7, 0x10, 0x0e, 0x11, 0x09, 0xf5, + 0xdf, 0xf7, 0xe5, 0xe9, 0x1b, 0x38, 0x12, 0x1e, 0xf3, 0xfa, 0xde, 0x17, 0x04, + 0x06, 0xe3, 0x1e, 0x03, 0xe7, 0xa9, 0xca, 0xb2, 0xdb, 0x0a, 0xde, 0x24, 0x11, + 0x02, 0x19, 0xd3, 0xf7, 0xef, 0xdc, 0x03, 0xfb, 0xe5, 0x22, 0x39, 0x13, 0x3a, + 0x04, 0xe7, 0xf3, 0x41, 0xed, 0xf2, 0xc1, 0x52, 0x03, 0xd4, 0xe9, 0xf9, 0xbb, + 0xc0, 0xee, 0x0f, 0xf0, 0xe1, 0xd4, 0xc4, 0x0e, 0x0d, 0x2b, 0x41, 0xc4, 0xea, + 0xf6, 0x3e, 0xe6, 0xfc, 0xdf, 0x35, 0x15, 0x08, 0x1d, 0x01, 0xd1, 0xe3, 0xf7, + 0xf6, 0xea, 0x1a, 0x1b, 0xfd, 0x1b, 0x08, 0x00, 0xcb, 0x05, 0x12, 0xfb, 0x43, + 0xe1, 0xff, 0x22, 0x0a, 0x02, 0x08, 0xf7, 0xea, 0x13, 0xf3, 0x1a, 0xd8, 0xe4, + 0x25, 0xed, 0x0d, 0x0f, 0xf6, 0x00, 0x0f, 0x12, 0xe1, 0xdd, 0x0c, 0xd3, 0x0b, + 0x03, 0xef, 0x1d, 0xdb, 0xe9, 0x16, 0xe4, 0x3c, 0x25, 0x02, 0xbe, 0x44, 0xe5, + 0x11, 0x39, 0x5b, 0x0c, 0xda, 0x1f, 0x11, 0xee, 0x2c, 0x2d, 0xea, 0x1b, 0x00, + 0x16, 0x1c, 0x0e, 0x07, 0x00, 0xe5, 0x15, 0x1b, 0xfb, 0x16, 0x13, 0xf3, 0x1a, + 0x0e, 0x0b, 0x2d, 0x15, 0xf4, 0xed, 0xfb, 0x22, 0x1f, 0x0a, 0x21, 0xfa, 0x03, + 0xcc, 0x21, 0x0a, 0x03, 0xf5, 0x42, 0xf0, 0xee, 0xfe, 0xf1, 0x0a, 0x7f, 0xdb, + 0x03, 0x14, 0x30, 0x2d, 0x1b, 0xf7, 0x02, 0x11, 0x1f, 0x0b, 0x01, 0x14, 0x3f, + 0xf1, 0x04, 0x08, 0x21, 0xf7, 0x03, 0xe7, 0xf1, 0x18, 0xf3, 0x11, 0x02, 0x41, + 0xee, 0x2b, 0xf3, 0xf1, 0x29, 0x10, 0xe2, 0x17, 0x04, 0xed, 0x2d, 0x02, 0xfb, + 0xc9, 0x09, 0xf9, 0xec, 0x0f, 0x16, 0xdf, 0xf4, 0x0e, 0x1a, 0x07, 0x28, 0x14, + 0x2b, 0xf5, 0x09, 0xe5, 0xfa, 0x0d, 0x31, 0x35, 0x4f, 0x11, 0xfd, 0x10, 0xf5, + 0x7f, 0xf8, 0xee, 0x36, 0xf8, 0x0f, 0xe0, 0xfc, 0xf8, 0x29, 0xe4, 0x0d, 0x02, + 0x10, 0x18, 0xeb, 0x08, 0x11, 0xe6, 0xfe, 0x0c, 0x0e, 0x01, 0x0f, 0xf6, 0xf0, + 0xf3, 0xed, 0xfa, 0xe6, 0x0e, 0x0f, 0xe7, 0xfd, 0xf4, 0x05, 0xfa, 0x05, 0xf5, + 0xe2, 0xed, 0xfe, 0x10, 0xf2, 0x0a, 0x00, 0xc4, 0x42, 0xec, 0xef, 0xfa, 0x1d, + 0xd4, 0x1f, 0xe6, 0xfd, 0x1d, 0xe9, 0xf0, 0x00, 0x0a, 0x02, 0x12, 0xec, 0x05, + 0xfb, 0x03, 0xf6, 0xf8, 0xea, 0x1e, 0x2a, 0x17, 0x15, 0xf5, 0x02, 0xfa, 0x1c, + 0xe8, 0x19, 0xf9, 0x23, 0xdc, 0xea, 0x00, 0x2e, 0x29, 0xee, 0xe8, 0xf8, 0x27, + 0xf4, 0xf6, 0x01, 0xbe, 0xe0, 0x0c, 0x21, 0x0f, 0x65, 0x24, 0xf6, 0xda, 0xf3, + 0x14, 0x39, 0xfa, 0x09, 0xe3, 0xe2, 0x1e, 0xdc, 0x75, 0xcf, 0x2e, 0x31, 0xeb, + 0xf2, 0xe0, 0x24, 0x55, 0xeb, 0xb4, 0xe7, 0x7f, 0xc0, 0x25, 0xea, 0xe5, 0xf9, + 0x23, 0xed, 0x47, 0xf7, 0x01, 0xd3, 0x48, 0xe1, 0x2d, 0xe3, 0xe0, 0xa2, 0xf6, + 0x3b, 0xee, 0xc8, 0x18, 0x08, 0x06, 0x28, 0x2d, 0x26, 0xc9, 0x06, 0xfd, 0x9a, + 0x11, 0x1d, 0xe1, 0x10, 0xd9, 0xdf, 0x1a, 0x0d, 0xf8, 0xe6, 0x04, 0x23, 0x26, + 0xe4, 0xee, 0x0a, 0x4b, 0xeb, 0x3c, 0xbf, 0xfe, 0xe7, 0x4a, 0xf7, 0xec, 0xe7, + 0x28, 0x2f, 0xfa, 0x09, 0xef, 0x06, 0xdf, 0x11, 0x40, 0xdb, 0xfe, 0x18, 0xee, + 0xdf, 0x34, 0x00, 0x09, 0x15, 0xf5, 0x57, 0xe8, 0x4d, 0xeb, 0xd5, 0x15, 0x39, + 0x45, 0x28, 0x14, 0x16, 0x13, 0xd8, 0xca, 0xea, 0x27, 0xe0, 0x21, 0x1d, 0xd3, + 0xf8, 0x26, 0x02, 0x38, 0xff, 0x43, 0xd6, 0x10, 0x42, 0xb5, 0xec, 0xfb, 0xca, + 0x37, 0xe3, 0x10, 0x23, 0x2b, 0xf6, 0x28, 0x47, 0x4c, 0xe0, 0xc9, 0x16, 0x28, + 0xf2, 0xeb, 0x28, 0x7d, 0x7f, 0xe3, 0xf2, 0xf3, 0x04, 0xe5, 0xf6, 0x19, 0x35, + 0xe1, 0x31, 0x4e, 0x00, 0xdc, 0x36, 0xd6, 0xa5, 0x27, 0x4f, 0xe7, 0x2a, 0x1c, + 0x1e, 0x05, 0xfb, 0x33, 0x11, 0x04, 0x30, 0xe4, 0xf4, 0xe6, 0x1e, 0xd6, 0xd7, + 0x12, 0x0b, 0x19, 0x4b, 0xe5, 0xda, 0x4c, 0x26, 0x20, 0x24, 0xe9, 0x0d, 0xdf, + 0xe1, 0x23, 0x33, 0x36, 0x16, 0xd0, 0xbe, 0x4b, 0x6a, 0x48, 0x49, 0xf1, 0x49, + 0xfa, 0xf5, 0x33, 0x21, 0x30, 0xe3, 0xef, 0xef, 0xe4, 0x45, 0xfe, 0xd7, 0x01, + 0x2f, 0x00, 0x10, 0xcf, 0xfe, 0x15, 0x36, 0x15, 0xe6, 0xec, 0x00, 0x28, 0x13, + 0x13, 0xe4, 0x3b, 0xd0, 0xdb, 0xdd, 0x19, 0x0c, 0xfc, 0x0a, 0x59, 0x26, 0xcb, + 0xc8, 0xf1, 0x0a, 0x19, 0x34, 0x06, 0x40, 0x1e, 0x4a, 0x0a, 0x12, 0x07, 0xce, + 0xb9, 0xb5, 0xc8, 0xee, 0x3d, 0x3b, 0x0f, 0x35, 0xc7, 0xf6, 0xda, 0xf2, 0x19, + 0x4b, 0xed, 0xf1, 0x1c, 0x92, 0xd6, 0xbc, 0xda, 0x22, 0x52, 0xf2, 0x57, 0xe0, + 0xea, 0x0d, 0xde, 0xff, 0xe2, 0x54, 0xef, 0xcb, 0xf1, 0xae, 0xee, 0xff, 0xc0, + 0xae, 0xe9, 0x6d, 0xd1, 0xf0, 0x35, 0xd8, 0xfc, 0x0d, 0x60, 0xe9, 0x3a, 0xec, + 0xd0, 0x2a, 0x1f, 0x19, 0x48, 0x33, 0xea, 0xb7, 0xde, 0xbd, 0x48, 0x8e, 0x13, + 0xff, 0x0a, 0x18, 0x17, 0xea, 0xfc, 0xda, 0xbc, 0x7f, 0xf1, 0x2e, 0xdf, 0xfd, + 0xe7, 0x26, 0xce, 0x1d, 0x02, 0x2a, 0xf9, 0xd3, 0x13, 0xfc, 0xe6, 0xd9, 0xb3, + 0xf5, 0x03, 0xfb, 0xd1, 0x34, 0xcc, 0xcf, 0xe8, 0x45, 0xd1, 0x0a, 0xdc, 0x0f, + 0xfa, 0x9d, 0xe7, 0xc2, 0x06, 0xe6, 0x58, 0x35, 0xd0, 0x24, 0xef, 0x04, 0xea, + 0x4b, 0x3c, 0x16, 0x09, 0xaf, 0x24, 0x0d, 0x23, 0x25, 0x1a, 0xf4, 0x2a, 0x39, + 0xcf, 0xd3, 0x0f, 0xaf, 0xe0, 0x1b, 0x39, 0x08, 0x08, 0xb7, 0x38, 0xb1, 0xfb, + 0x01, 0xd1, 0x35, 0x00, 0x17, 0xe8, 0xdc, 0xc7, 0x11, 0xd4, 0xff, 0x4a, 0xa9, + 0x54, 0xd5, 0xdd, 0x31, 0xfd, 0x23, 0xf9, 0xf3, 0xb2, 0xbb, 0x23, 0xe0, 0xef, + 0xfd, 0x02, 0x5a, 0xd4, 0xf6, 0x19, 0xdd, 0xe0, 0x0f, 0xaf, 0xe0, 0x0f, 0xb5, + 0x1c, 0x16, 0xcc, 0xda, 0x10, 0x78, 0xcc, 0x40, 0x0d, 0xd1, 0xe6, 0xf8, 0x51, + 0xef, 0x1f, 0x47, 0x54, 0xef, 0x45, 0xcd, 0xdd, 0x06, 0x36, 0x48, 0xf9, 0xd3, + 0xc5, 0x9d, 0xbb, 0xc7, 0xbd, 0xf2, 0xae, 0x1f, 0x43, 0x39, 0xf8, 0xf2, 0x0a, + 0xea, 0xd1, 0x04, 0x0b, 0xfe, 0xb8, 0xb3, 0x7f, 0x0f, 0x16, 0x1d, 0x5a, 0x00, + 0x12, 0xef, 0x01, 0x55, 0x2a, 0x23, 0xe4, 0xec, 0xf1, 0xb9, 0x5c, 0x08, 0x05, + 0xf8, 0x19, 0x1b, 0xc1, 0x11, 0x1a, 0xe7, 0xe4, 0xc4, 0x02, 0xeb, 0xcc, 0xea, + 0x0e, 0xe9, 0xb3, 0x0c, 0xf4, 0xdb, 0x58, 0xdc, 0x1d, 0xbf, 0x03, 0x19, 0x30, + 0x10, 0xea, 0xf4, 0xf2, 0xe8, 0x5f, 0xf3, 0xe9, 0x13, 0x11, 0xd2, 0x28, 0x34, + 0xeb, 0x2a, 0x04, 0xe0, 0x1f, 0xd8, 0xc6, 0x7f, 0xef, 0x2b, 0xe7, 0xca, 0x0a, + 0xee, 0x31, 0x31, 0xd1, 0x94, 0xf5, 0x11, 0xd6, 0x57, 0xf8, 0x33, 0x12, 0x23, + 0x0e, 0x1c, 0x07, 0x01, 0xeb, 0x16, 0xfb, 0x08, 0xf9, 0x1c, 0xe6, 0x0c, 0x14, + 0xdc, 0xe5, 0xd9, 0xfe, 0xcc, 0xf8, 0xfa, 0xfd, 0x28, 0x01, 0xc6, 0x50, 0xec, + 0x22, 0x61, 0xe2, 0xed, 0x1d, 0x63, 0x17, 0xac, 0x05, 0x5b, 0xbf, 0xc1, 0xe4, + 0xf2, 0xf9, 0xcf, 0xf1, 0xfc, 0x68, 0x0e, 0x31, 0x30, 0x01, 0xe9, 0x1f, 0x05, + 0xfc, 0x0a, 0x17, 0xc3, 0x54, 0xbb, 0x06, 0x5b, 0xec, 0xc3, 0x0d, 0x15, 0x38, + 0x16, 0xbd, 0xce, 0xda, 0xff, 0x30, 0xc9, 0xfa, 0xfb, 0x00, 0xf8, 0xe2, 0x4e, + 0xee, 0x01, 0x0f, 0x1c, 0x1c, 0x1a, 0x49, 0x3b, 0xdc, 0x2a, 0xc9, 0xcd, 0xef, + 0xeb, 0x20, 0x1e, 0xd3, 0xe7, 0xe1, 0x3a, 0x19, 0xe0, 0x05, 0x04, 0xf2, 0x09, + 0xf9, 0x5d, 0x11, 0x5a, 0x18, 0x14, 0xe6, 0xcf, 0x01, 0xfb, 0xfd, 0x27, 0x5d, + 0xfd, 0x27, 0xf8, 0x10, 0x07, 0x0a, 0x09, 0xf2, 0x29, 0x08, 0xda, 0x11, 0xf8, + 0xd2, 0x16, 0x26, 0xe3, 0xfe, 0x2a, 0x7a, 0xe1, 0x07, 0x54, 0x27, 0xf2, 0xce, + 0x38, 0x0f, 0x0d, 0x38, 0xe4, 0xce, 0x4a, 0x3d, 0xee, 0x10, 0x3a, 0xf8, 0x1d, + 0x1b, 0x2c, 0xea, 0x05, 0x2e, 0xef, 0x01, 0x0a, 0xec, 0xda, 0xee, 0x6c, 0xed, + 0xfd, 0x16, 0xf2, 0x2a, 0xe7, 0xce, 0x05, 0x39, 0xf1, 0xf3, 0x44, 0x7f, 0x04, + 0xeb, 0x0b, 0xfc, 0x14, 0x1d, 0x0a, 0x15, 0x21, 0x0c, 0x34, 0x16, 0x15, 0xf8, + 0x34, 0x0e, 0xda, 0xbf, 0xe7, 0x01, 0x04, 0xe2, 0x0e, 0xdd, 0x34, 0x07, 0x03, + 0x03, 0x09, 0xa6, 0x44, 0x1f, 0xc8, 0xfe, 0x06, 0x49, 0x22, 0x29, 0xe2, 0x32, + 0xeb, 0xd7, 0xf0, 0xe3, 0x2c, 0x46, 0xf2, 0xba, 0xd3, 0x1c, 0xc9, 0xe1, 0x47, + 0x01, 0xe6, 0x09, 0x7f, 0xa5, 0xd4, 0x48, 0xff, 0x7a, 0xf3, 0x33, 0xfb, 0x2b, + 0xfc, 0x4a, 0xef, 0xf0, 0x05, 0xd0, 0x27, 0x15, 0x2a, 0x0f, 0xe9, 0xf9, 0xed, + 0xff, 0xfc, 0xc7, 0xcb, 0x25, 0xdb, 0xe3, 0x63, 0x16, 0xe4, 0xab, 0x73, 0xd7, + 0x32, 0xff, 0x10, 0xf7, 0xfd, 0xcb, 0x26, 0xda, 0xeb, 0xfe, 0xf0, 0x26, 0xee, + 0x1c, 0x08, 0xbc, 0x48, 0x28, 0x10, 0x1f, 0x06, 0xf8, 0xfc, 0xe9, 0x3f, 0x17, + 0x14, 0xd5, 0xfd, 0xd2, 0xe3, 0x3f, 0x14, 0x30, 0x27, 0xcc, 0xda, 0xe1, 0x03, + 0xfe, 0x07, 0x20, 0x12, 0xd3, 0x07, 0x1d, 0xfb, 0x0c, 0xc5, 0xda, 0xf9, 0xa8, + 0xcd, 0xce, 0xef, 0x35, 0xef, 0xc8, 0x0a, 0x47, 0xc4, 0xc9, 0x09, 0x06, 0x4d, + 0x09, 0xf3, 0x11, 0xdf, 0xea, 0x0d, 0x0a, 0x0c, 0xc2, 0xd0, 0xcd, 0xec, 0xe7, + 0xf6, 0x3c, 0x04, 0xd9, 0x04, 0xea, 0xe4, 0x09, 0x20, 0x3b, 0xdb, 0xd6, 0x4e, + 0x9f, 0xb1, 0x23, 0xca, 0x81, 0x13, 0xc0, 0x21, 0xab, 0x10, 0x3a, 0x8d, 0xfb, + 0xd4, 0x07, 0xe1, 0x15, 0x26, 0x4f, 0xe1, 0x06, 0xce, 0x34, 0x1f, 0x0d, 0x53, + 0x0e, 0x23, 0x00, 0xf0, 0xb5, 0x09, 0x44, 0xfb, 0xf8, 0xef, 0xde, 0xc8, 0x08, + 0xea, 0x56, 0xf4, 0x47, 0x40, 0x19, 0x4f, 0xe2, 0x96, 0x27, 0xff, 0x03, 0xb2, + 0xf3, 0xc4, 0xdf, 0xdd, 0x06, 0xfc, 0xf7, 0xf7, 0x40, 0xaf, 0xc4, 0x10, 0x2b, + 0xfa, 0xdd, 0xf3, 0xe4, 0xc7, 0x20, 0xa3, 0xfb, 0xe2, 0x0a, 0xc3, 0x11, 0xd7, + 0xf5, 0xff, 0x38, 0xf2, 0x0d, 0xdc, 0x55, 0x2b, 0x2e, 0x34, 0xf8, 0x46, 0xc8, + 0xca, 0x20, 0x0c, 0x15, 0xdf, 0x30, 0x31, 0x0f, 0x25, 0x51, 0xf3, 0xde, 0xdc, + 0xea, 0xcf, 0xa0, 0x9a, 0xd0, 0x28, 0xfc, 0xee, 0xf4, 0x26, 0x0d, 0x09, 0x09, + 0x27, 0xef, 0x13, 0xbf, 0x1a, 0x0d, 0xd4, 0xfe, 0x18, 0xd2, 0x04, 0x4d, 0xde, + 0x21, 0x10, 0x08, 0xcf, 0xfc, 0x0b, 0x12, 0x29, 0xd9, 0xf4, 0xd6, 0xeb, 0x3b, + 0x1e, 0xf3, 0xf0, 0x5a, 0xd3, 0x10, 0x2c, 0x04, 0xfe, 0x20, 0x44, 0x05, 0x12, + 0x6f, 0xfd, 0x08, 0x5b, 0x1f, 0xf5, 0xc2, 0x0c, 0x3d, 0x2c, 0xfc, 0xf6, 0x0a, + 0x7f, 0x2a, 0xe7, 0x62, 0x3e, 0xf1, 0x0c, 0xec, 0x03, 0x18, 0x12, 0xc2, 0xf8, + 0x1d, 0x12, 0x02, 0x04, 0xd2, 0x44, 0x38, 0xd9, 0x17, 0x09, 0xb6, 0x46, 0x1d, + 0x17, 0x6a, 0xf1, 0xe6, 0xd5, 0x2d, 0x0e, 0xd3, 0xfe, 0xee, 0xe9, 0x1c, 0x11, + 0x3e, 0xb8, 0x1a, 0x29, 0x01, 0xcd, 0xb6, 0xfb, 0x1c, 0x05, 0xe6, 0xfd, 0xdd, + 0xd0, 0xea, 0x1e, 0xec, 0xfb, 0xeb, 0x00, 0xe1, 0x0d, 0x19, 0xbd, 0xfa, 0xf8, + 0x34, 0x7f, 0x0b, 0xf8, 0xf3, 0x01, 0x1f, 0xdf, 0xdf, 0xec, 0x02, 0x00, 0xf6, + 0xef, 0x1f, 0xe0, 0xe1, 0x00, 0xec, 0x44, 0x17, 0xda, 0xd6, 0xf3, 0xe9, 0x08, + 0xda, 0x3c, 0x1a, 0xbc, 0x1e, 0x06, 0x05, 0xe1, 0x06, 0xde, 0xe2, 0x23, 0xd4, + 0x28, 0xef, 0x18, 0x08, 0x0b, 0xdc, 0xd1, 0xf4, 0x11, 0xe9, 0xe9, 0xf8, 0xf0, + 0xca, 0x19, 0xeb, 0x07, 0x0e, 0x1e, 0xe6, 0x51, 0x13, 0xe2, 0x18, 0xfb, 0x24, + 0x27, 0x30, 0x13, 0x04, 0xf3, 0xe4, 0xd9, 0x08, 0x07, 0x13, 0x2e, 0xca, 0x4c, + 0x1d, 0xd8, 0x09, 0xcc, 0xbf, 0x02, 0xf2, 0xe6, 0xf6, 0x40, 0xd7, 0x05, 0xd0, + 0xec, 0xe0, 0xd7, 0xd2, 0x02, 0x19, 0x29, 0x32, 0xfd, 0xeb, 0x1c, 0x03, 0x3d, + 0xf1, 0xde, 0x1e, 0x1f, 0x0b, 0xdc, 0x1f, 0xea, 0xf3, 0x44, 0x2c, 0x45, 0xf8, + 0xf8, 0xed, 0xde, 0xc6, 0x0e, 0xdf, 0x17, 0x04, 0x05, 0x52, 0xa5, 0xe7, 0xd3, + 0x62, 0xcd, 0x28, 0x2e, 0x2e, 0xab, 0x12, 0x7f, 0x00, 0x1d, 0xab, 0xcc, 0xfa, + 0xde, 0x1f, 0x5e, 0x55, 0x0f, 0xdd, 0x37, 0x4a, 0xf1, 0x30, 0x29, 0x18, 0xda, + 0x09, 0x23, 0xdc, 0x25, 0xdf, 0x61, 0x09, 0x21, 0x4c, 0xa0, 0x2c, 0xbd, 0x16, + 0xef, 0x1f, 0xe2, 0xff, 0x51, 0x44, 0x08, 0x19, 0xe6, 0xb7, 0xd4, 0x29, 0x2c, + 0xf8, 0x21, 0xdd, 0x2e, 0x08, 0x03, 0x4a, 0xde, 0x05, 0x92, 0xe8, 0xe7, 0xe6, + 0x73, 0x07, 0x3a, 0xa3, 0x02, 0xcf, 0xea, 0x0f, 0x3c, 0x12, 0xd4, 0x00, 0x40, + 0x07, 0xfe, 0x3f, 0xd4, 0xbc, 0x21, 0xe8, 0xbc, 0xd3, 0x5f, 0xf3, 0x45, 0x1a, + 0x29, 0x07, 0xff, 0x1d, 0xb4, 0x2d, 0xfa, 0xfa, 0x27, 0xc9, 0xc0, 0x11, 0x42, + 0xcf, 0xb4, 0xcb, 0xf7, 0xce, 0x0f, 0x00, 0x11, 0x54, 0xc4, 0xd8, 0xc6, 0x04, + 0x10, 0x23, 0x33, 0xd5, 0xf9, 0xe4, 0xc5, 0x19, 0x22, 0xe6, 0xe3, 0x0f, 0x2b, + 0x05, 0x40, 0x23, 0x18, 0x28, 0xc2, 0x49, 0x10, 0xb1, 0xfd, 0xd9, 0xf3, 0x29, + 0x14, 0x21, 0xdb, 0xf7, 0x1d, 0x1c, 0x2f, 0x37, 0xe4, 0x12, 0xd2, 0x15, 0xe4, + 0xfc, 0x02, 0x3d, 0xad, 0xbc, 0xbd, 0xd9, 0xeb, 0x3b, 0xdb, 0xd0, 0x35, 0xf4, + 0xf7, 0x11, 0xee, 0x32, 0x3d, 0x59, 0x2d, 0x1c, 0xe7, 0x05, 0xdb, 0x15, 0x18, + 0x1f, 0xd2, 0xe0, 0x0c, 0x5a, 0xca, 0x08, 0xda, 0x20, 0xbe, 0xf3, 0xf3, 0xb5, + 0x56, 0x08, 0x07, 0xfd, 0x65, 0x16, 0xe9, 0x12, 0x2b, 0x07, 0xbc, 0xdd, 0xf1, + 0xdb, 0xdf, 0xea, 0xde, 0x4c, 0xfc, 0xc5, 0xfb, 0xbc, 0xf8, 0x08, 0x07, 0xde, + 0xea, 0x2c, 0x20, 0x2a, 0x0a, 0x2c, 0x0f, 0x0e, 0xc3, 0x01, 0x24, 0xcf, 0x81, + 0xc2, 0x48, 0xb6, 0xf3, 0xba, 0xda, 0xe0, 0xd2, 0xea, 0x0b, 0xdf, 0x4a, 0x42, + 0x1b, 0xd0, 0xd6, 0xd4, 0x2d, 0x1f, 0xd7, 0x8f, 0xcc, 0x41, 0xda, 0xfc, 0xe1, + 0x36, 0x15, 0xfe, 0x4e, 0xaa, 0x08, 0xe5, 0x0d, 0x8f, 0x11, 0xc3, 0xed, 0xfb, + 0xec, 0x37, 0xa9, 0x65, 0xc2, 0x0d, 0xe4, 0x1a, 0x1c, 0x45, 0x03, 0x08, 0xf4, + 0xf7, 0xbb, 0x23, 0xe4, 0xeb, 0x0e, 0xed, 0x29, 0xfd, 0xff, 0xe9, 0xd5, 0xe8, + 0xb5, 0x0b, 0x0a, 0xdb, 0xb1, 0x3b, 0x2d, 0xf5, 0x42, 0xc1, 0x12, 0x84, 0x10, + 0xe9, 0xe9, 0xe7, 0x3c, 0xa3, 0xd0, 0xe2, 0x11, 0xbc, 0x94, 0x4d, 0xba, 0x00, + 0x0e, 0x53, 0xe8, 0xef, 0xf0, 0xd9, 0xf9, 0xcf, 0xf3, 0xed, 0x5e, 0xe4, 0xf1, + 0x14, 0x2a, 0xfd, 0x0d, 0xea, 0xee, 0x1a, 0xcb, 0xea, 0x2b, 0xa8, 0x48, 0x3e, + 0xf0, 0x0c, 0x18, 0xec, 0x1e, 0xaa, 0x16, 0xb9, 0x75, 0x61, 0x7f, 0xcb, 0xfd, + 0x40, 0x14, 0x3b, 0x41, 0xd5, 0xf7, 0x2b, 0x27, 0x00, 0x10, 0x3b, 0x0a, 0xb9, + 0x31, 0x03, 0x1f, 0xf5, 0x55, 0x12, 0x13, 0x4b, 0x04, 0x0c, 0x25, 0x07, 0xf5, + 0x96, 0x1f, 0x5f, 0xe4, 0x43, 0x11, 0x32, 0xe1, 0xe7, 0x39, 0xfb, 0x1b, 0x0c, + 0x36, 0xfe, 0x0b, 0x08, 0xff, 0x3e, 0x03, 0x1e, 0xe7, 0x0a, 0xf0, 0xe1, 0x34, + 0x18, 0x0e, 0xe1, 0x02, 0xe5, 0xbf, 0xe3, 0x13, 0x05, 0x0e, 0xeb, 0x7f, 0x06, + 0xce, 0x0c, 0x14, 0xcd, 0x09, 0x2f, 0xde, 0x1c, 0x00, 0x09, 0x4b, 0x17, 0x45, + 0xe8, 0x32, 0x28, 0xf5, 0xc4, 0x17, 0xeb, 0xe1, 0xda, 0xdf, 0x03, 0x18, 0x0a, + 0x07, 0x24, 0x21, 0x0d, 0xd4, 0x11, 0xdb, 0x0b, 0xf4, 0xba, 0x10, 0xd0, 0xf6, + 0xd4, 0x0f, 0xec, 0x1f, 0x0b, 0x27, 0xe4, 0x4f, 0xee, 0x4e, 0x3b, 0x32, 0x11, + 0xe0, 0xe8, 0xb8, 0x11, 0xdd, 0x22, 0x27, 0x1d, 0xeb, 0xef, 0xec, 0xe8, 0x21, + 0xee, 0xff, 0xd6, 0xb9, 0xf6, 0x08, 0xc9, 0x30, 0xef, 0x06, 0xb6, 0x9b, 0xe3, + 0x05, 0x21, 0xfd, 0x01, 0x4f, 0xe6, 0xe5, 0xf2, 0x1d, 0xbd, 0xfe, 0xa4, 0x41, + 0x1f, 0xdf, 0xd3, 0xdd, 0xb7, 0x1c, 0xd8, 0xfc, 0xdd, 0xee, 0xfb, 0xd5, 0xc8, + 0xb8, 0x96, 0xdd, 0xb8, 0x11, 0x02, 0xe7, 0xee, 0xbb, 0xd6, 0x19, 0xda, 0xde, + 0x07, 0x19, 0x16, 0x27, 0x0e, 0xfd, 0x17, 0xa9, 0xc4, 0xd2, 0xec, 0xd2, 0x04, + 0xa0, 0xe2, 0x08, 0xb1, 0x08, 0xab, 0xd5, 0x0a, 0xf4, 0xe5, 0xea, 0xcf, 0x06, + 0x1f, 0x8f, 0xd4, 0x0b, 0x02, 0xf5, 0x47, 0xca, 0x05, 0xf3, 0xf2, 0x10, 0x1c, + 0xfb, 0xea, 0x1c, 0xfc, 0x02, 0x08, 0xc5, 0x81, 0xa1, 0xc3, 0x59, 0xb2, 0x59, + 0xfe, 0x29, 0xd2, 0xbf, 0x1f, 0xce, 0xb2, 0x08, 0x27, 0xf1, 0x0a, 0x11, 0xc4, + 0x13, 0xa3, 0x19, 0xfe, 0xee, 0xe5, 0xe5, 0x0f, 0xec, 0x28, 0xe3, 0x1d, 0xc0, + 0xeb, 0xf6, 0xe1, 0x31, 0x0c, 0xd3, 0xea, 0xf6, 0xf6, 0xdc, 0x12, 0x48, 0xd4, + 0xdf, 0xf1, 0x6b, 0xdf, 0xd6, 0xfb, 0x04, 0x4d, 0xec, 0x09, 0x1c, 0xa7, 0xf0, + 0x6d, 0x09, 0xdd, 0x1f, 0x1b, 0xe1, 0xe2, 0xf2, 0xf6, 0xe2, 0xef, 0xeb, 0xfc, + 0xd6, 0xfb, 0x2d, 0xe8, 0x19, 0x0e, 0x0d, 0x07, 0x35, 0xdd, 0xab, 0x29, 0x49, + 0x25, 0xdd, 0xee, 0xed, 0x1a, 0x3c, 0xe0, 0x22, 0x11, 0xde, 0x20, 0x0d, 0x2f, + 0xcc, 0x45, 0x12, 0xf2, 0xd3, 0x40, 0xde, 0xb8, 0xe5, 0x13, 0x17, 0xd5, 0xf3, + 0xd9, 0xe7, 0xe7, 0xeb, 0x03, 0x03, 0x32, 0xf6, 0xd1, 0xf6, 0xe8, 0x22, 0xd7, + 0x1d, 0x06, 0x2b, 0x2a, 0x28, 0x33, 0xe1, 0xdf, 0x21, 0x2c, 0x10, 0xd0, 0xcf, + 0x7f, 0xc9, 0x31, 0x35, 0x21, 0x1b, 0x01, 0x17, 0x3b, 0x09, 0xce, 0x2f, 0xc3, + 0x1a, 0xbb, 0xf6, 0xed, 0x33, 0x0f, 0xec, 0xfa, 0xf4, 0x42, 0xe3, 0xf9, 0x17, + 0x0b, 0x21, 0xdd, 0x57, 0x06, 0xff, 0x2b, 0xec, 0xce, 0x0b, 0x1a, 0x00, 0x1d, + 0xd3, 0xdb, 0x03, 0x12, 0x2f, 0x0f, 0xf2, 0x0b, 0xbe, 0xd7, 0xd7, 0xbd, 0x33, + 0xda, 0x1a, 0xf5, 0xbb, 0x02, 0x66, 0xfd, 0xf6, 0x53, 0x3d, 0x16, 0xcf, 0xfb, + 0x02, 0x4e, 0xf9, 0x51, 0x0b, 0xfa, 0xa4, 0x1b, 0xfe, 0xe6, 0x9a, 0x4f, 0x1f, + 0xf8, 0x0e, 0xd9, 0x7f, 0xbd, 0xfb, 0xd9, 0x05, 0xbd, 0x36, 0x20, 0x12, 0xc6, + 0xec, 0xd4, 0x14, 0xc7, 0x5e, 0xae, 0xe1, 0x31, 0xf4, 0x37, 0x1d, 0xca, 0x13, + 0x0e, 0xbb, 0xda, 0x19, 0x27, 0xf2, 0x01, 0xf4, 0x02, 0x41, 0xeb, 0x0d, 0x02, + 0x11, 0x0c, 0xf9, 0xcd, 0x13, 0x08, 0x19, 0xf2, 0x01, 0x5a, 0x34, 0x06, 0xcf, + 0xff, 0xa1, 0xf9, 0xd6, 0x21, 0xea, 0x25, 0xd6, 0x0e, 0xd0, 0x11, 0x08, 0xc2, + 0xfb, 0xc6, 0xf4, 0x74, 0x7f, 0x17, 0x3a, 0x0e, 0xf9, 0x0b, 0xcd, 0xe0, 0xe3, + 0x17, 0xf4, 0xfa, 0x2d, 0xe0, 0xec, 0xd7, 0x06, 0xe6, 0xff, 0xf8, 0xd6, 0xdd, + 0xfe, 0xea, 0xfb, 0xff, 0xda, 0xfc, 0x2b, 0x63, 0xeb, 0xec, 0xce, 0x61, 0xf9, + 0xdc, 0xf9, 0xfc, 0xe8, 0x01, 0xe0, 0x73, 0x29, 0x08, 0x75, 0xf0, 0x12, 0x6f, + 0x38, 0x07, 0x22, 0x07, 0x20, 0xdc, 0xe2, 0x2e, 0xea, 0xe2, 0x01, 0x2e, 0xde, + 0xff, 0x29, 0x13, 0x11, 0x27, 0xec, 0x08, 0xfc, 0x21, 0x2a, 0x1d, 0x5d, 0xe0, + 0x78, 0x35, 0x07, 0xc8, 0x2f, 0xd9, 0xf6, 0xfb, 0x0b, 0x3a, 0xf8, 0xf8, 0xe1, + 0xfa, 0xce, 0xef, 0x40, 0xcf, 0x3c, 0xeb, 0x67, 0x2e, 0xff, 0x01, 0x1d, 0xdf, + 0xfe, 0xfd, 0x07, 0x0b, 0xfe, 0x27, 0x0d, 0x70, 0x08, 0xfd, 0xf3, 0xf7, 0xfa, + 0xc7, 0xde, 0x0e, 0x53, 0xfc, 0x12, 0x0f, 0xe3, 0xe6, 0x01, 0xe6, 0x12, 0xb3, + 0xad, 0x25, 0x4c, 0xc2, 0x20, 0x1a, 0x28, 0xba, 0x12, 0x31, 0x44, 0x1a, 0x41, + 0x3a, 0x13, 0x06, 0xeb, 0xfd, 0xf4, 0x37, 0x78, 0x0e, 0x31, 0x4b, 0x02, 0xf7, + 0x08, 0x2e, 0x3e, 0xed, 0x03, 0xd3, 0x0f, 0xcf, 0x3a, 0xeb, 0xfb, 0x96, 0xe9, + 0xdb, 0x0f, 0x53, 0x00, 0x2f, 0xec, 0xda, 0x0d, 0x52, 0xf6, 0x6f, 0xd7, 0x3c, + 0x14, 0xa5, 0xe9, 0x81, 0xcd, 0x36, 0x18, 0xee, 0xcb, 0xda, 0xd6, 0xf1, 0xec, + 0x17, 0x27, 0xeb, 0xff, 0x21, 0x1c, 0x0b, 0x7c, 0x34, 0x1c, 0xe7, 0x03, 0x0f, + 0x00, 0xe9, 0x00, 0x19, 0x3e, 0x01, 0xa2, 0xc3, 0x74, 0xe8, 0x31, 0xed, 0xf1, + 0x09, 0xeb, 0xdd, 0xe5, 0x42, 0x52, 0xff, 0xf4, 0xdf, 0xf0, 0xf3, 0x62, 0x01, + 0xfc, 0x12, 0x2c, 0xde, 0xf8, 0xe2, 0x19, 0x1c, 0x1d, 0x15, 0x34, 0x1d, 0xf1, + 0xf0, 0x09, 0x1c, 0xd8, 0x1e, 0xee, 0xfa, 0x30, 0xdf, 0xec, 0x0c, 0x03, 0x1f, + 0x28, 0x20, 0x0a, 0x09, 0xff, 0xf3, 0x43, 0x68, 0xe7, 0x21, 0xe8, 0xfd, 0x7f, + 0xc0, 0xd2, 0xf0, 0x1f, 0xf9, 0x1b, 0x04, 0x25, 0x3b, 0x4a, 0xfc, 0xb2, 0x2c, + 0xf0, 0xcb, 0x42, 0xf7, 0xc6, 0x31, 0x21, 0x35, 0x2b, 0x0a, 0xfa, 0xd3, 0xe6, + 0x35, 0xd2, 0x0f, 0xdc, 0x97, 0x02, 0xc5, 0x19, 0x51, 0xd5, 0xdb, 0xd9, 0xbe, + 0xcc, 0xd8, 0xdd, 0xc8, 0x3b, 0xe6, 0x0b, 0xee, 0xf1, 0x28, 0xc7, 0xdd, 0xec, + 0x11, 0xf2, 0x0d, 0xa5, 0xd9, 0x03, 0x1f, 0xbc, 0xe1, 0x19, 0x3d, 0xf7, 0x00, + 0x60, 0xf4, 0xe9, 0x22, 0x13, 0xd2, 0x02, 0x1a, 0xf3, 0xfe, 0xea, 0xb3, 0xc5, + 0x06, 0xf7, 0xb8, 0x45, 0xc5, 0x27, 0x00, 0x0d, 0xfb, 0x03, 0x3d, 0xd2, 0xf4, + 0x22, 0xcd, 0x23, 0xf7, 0x29, 0x06, 0x9d, 0x26, 0xfd, 0x0f, 0x1a, 0x30, 0x14, + 0x3e, 0xcc, 0xee, 0xe2, 0xba, 0x0d, 0x07, 0x02, 0x68, 0x30, 0xf8, 0x24, 0xe7, + 0x06, 0xdd, 0xed, 0xf2, 0xf2, 0x7f, 0x0f, 0x1c, 0xec, 0x3a, 0xfa, 0x01, 0x18, + 0x03, 0x1e, 0xf4, 0x01, 0xde, 0xfd, 0xe1, 0xf4, 0x08, 0x0a, 0x09, 0xf9, 0x19, + 0x23, 0xff, 0x2e, 0x00, 0xf3, 0xee, 0xf3, 0xf9, 0x03, 0xe4, 0x23, 0xfe, 0x29, + 0x0c, 0x12, 0xec, 0x21, 0x04, 0x03, 0x0c, 0x20, 0x08, 0x23, 0x1e, 0x40, 0xee, + 0x1e, 0x14, 0x08, 0x08, 0x03, 0x0a, 0xfe, 0xdf, 0x00, 0x19, 0xff, 0xf3, 0x04, + 0x0a, 0xf2, 0x01, 0x1e, 0x19, 0x0a, 0x23, 0x09, 0x21, 0xee, 0xff, 0x00, 0x01, + 0x03, 0xfa, 0x1a, 0xfd, 0xf3, 0x0c, 0xee, 0x14, 0x08, 0x0e, 0x03, 0x15, 0xf3, + 0xfe, 0xe9, 0x01, 0xd7, 0x03, 0x03, 0xf0, 0x2c, 0x3a, 0x03, 0x03, 0x04, 0x0b, + 0xe4, 0x05, 0xeb, 0x34, 0xff, 0x00, 0x25, 0x21, 0xdb, 0xd4, 0x0b, 0xd8, 0x06, + 0xec, 0xfe, 0x05, 0x04, 0x04, 0x1c, 0xf2, 0xd9, 0xfb, 0x09, 0xc1, 0xaa, 0x13, + 0x1c, 0x54, 0x8d, 0xcb, 0xd9, 0xc4, 0x1e, 0xc4, 0x21, 0x1f, 0xd4, 0xd7, 0x00, + 0x1a, 0xef, 0xfc, 0x0f, 0x4e, 0x02, 0x10, 0xe8, 0xcf, 0xb2, 0xdd, 0x21, 0x2f, + 0xf4, 0xbe, 0xe3, 0xfb, 0xea, 0xdf, 0x98, 0x03, 0xf0, 0x7f, 0x7c, 0x57, 0x15, + 0xfb, 0x0e, 0xda, 0xd0, 0x5a, 0x20, 0xf6, 0x3a, 0xfb, 0x4a, 0xec, 0xf5, 0xee, + 0x0c, 0xf8, 0xeb, 0xc8, 0xed, 0x03, 0xee, 0x27, 0x28, 0x08, 0xe9, 0xfd, 0x6b, + 0xcf, 0xf3, 0x48, 0x06, 0xba, 0xc5, 0x9d, 0xf3, 0xc6, 0x19, 0xd7, 0xa5, 0x27, + 0x40, 0x27, 0x2b, 0x16, 0x2c, 0xc5, 0x11, 0xe6, 0x23, 0x13, 0xf7, 0xe9, 0x21, + 0x77, 0xab, 0xcd, 0xed, 0x44, 0xfa, 0xeb, 0xca, 0x04, 0xf3, 0xdb, 0xb4, 0xd2, + 0xd5, 0xe0, 0xf4, 0xd4, 0xfa, 0xa4, 0x1c, 0xd7, 0xd1, 0x88, 0xd2, 0x14, 0xcf, + 0x10, 0x0c, 0x05, 0x3d, 0x26, 0x0b, 0x1e, 0xd9, 0xcf, 0x0e, 0xca, 0x01, 0x36, + 0xfe, 0x22, 0xd5, 0x37, 0xd6, 0xd0, 0xbf, 0x19, 0xc9, 0xc9, 0xde, 0x08, 0xb8, + 0x07, 0xf6, 0x2e, 0xdd, 0x10, 0x2e, 0xf8, 0x0e, 0xcb, 0x93, 0xbb, 0xbf, 0x2a, + 0x1d, 0x50, 0x01, 0x0a, 0xdc, 0x2c, 0xed, 0x08, 0xcc, 0x87, 0x5d, 0x1d, 0xee, + 0xed, 0xd0, 0xfb, 0x7f, 0xd5, 0x47, 0x24, 0xa5, 0xd3, 0xe7, 0x02, 0x25, 0xd3, + 0x17, 0xe2, 0xf5, 0xf5, 0xe6, 0xf3, 0x40, 0xca, 0x18, 0xda, 0x4c, 0x01, 0xdf, + 0x67, 0xf2, 0xdf, 0x18, 0x39, 0xf6, 0x12, 0xa3, 0x21, 0xcd, 0x21, 0x62, 0x55, + 0x07, 0x7b, 0xde, 0xea, 0x08, 0xe3, 0xce, 0x00, 0xfe, 0xf6, 0xc4, 0x4f, 0xf3, + 0x39, 0xff, 0xea, 0x31, 0x7e, 0x24, 0xf3, 0xc2, 0x47, 0xaf, 0x10, 0x09, 0x34, + 0xd0, 0xc9, 0xf0, 0x4e, 0xf1, 0x06, 0x1d, 0x58, 0x07, 0x4b, 0x01, 0x0b, 0xd1, + 0x25, 0xe8, 0x0a, 0x40, 0xc4, 0x2f, 0xfd, 0xf9, 0xe5, 0xcf, 0xea, 0x09, 0x00, + 0x1e, 0x07, 0xdd, 0x50, 0x0c, 0xfa, 0xd8, 0x64, 0xe7, 0xdd, 0x0d, 0x1b, 0x06, + 0xcb, 0x7f, 0xf4, 0x18, 0x11, 0x15, 0xe8, 0xdf, 0xeb, 0x03, 0xe0, 0x30, 0x0d, + 0x00, 0xba, 0xe9, 0xe1, 0xb5, 0x05, 0xfb, 0xce, 0xea, 0x3d, 0xc7, 0xd0, 0xd7, + 0x26, 0xde, 0xcc, 0xfb, 0x32, 0xed, 0xdb, 0xec, 0x16, 0x0e, 0x4e, 0x27, 0xfe, + 0x1a, 0x25, 0x15, 0x24, 0xde, 0x0c, 0x20, 0xe3, 0x38, 0xde, 0x0d, 0xf2, 0x22, + 0xd9, 0x2d, 0x47, 0xb7, 0x08, 0xf7, 0xcc, 0x12, 0x13, 0xd6, 0x3a, 0x1b, 0xc4, + 0xaa, 0x06, 0xf7, 0xf2, 0xf0, 0x14, 0xeb, 0x0a, 0xfe, 0x2b, 0xf1, 0x0a, 0x07, + 0x1c, 0xf1, 0xf4, 0x36, 0xba, 0xe2, 0x5c, 0x1a, 0x36, 0xd7, 0xf8, 0xfd, 0x35, + 0xf2, 0xf1, 0x2f, 0x08, 0x07, 0xde, 0x00, 0x39, 0x08, 0xe0, 0xe5, 0x1b, 0xc8, + 0xe9, 0x40, 0xc1, 0xe8, 0x17, 0x18, 0x07, 0x28, 0xd0, 0xc5, 0xd7, 0xf0, 0xc3, + 0x0a, 0xb7, 0xe3, 0x49, 0x2c, 0x15, 0xdb, 0xd8, 0xed, 0x11, 0xc4, 0x96, 0xf5, + 0x19, 0x22, 0x23, 0x05, 0xd7, 0xfa, 0x5e, 0xd6, 0xcc, 0xb0, 0xf5, 0xd4, 0xc0, + 0xff, 0x06, 0x5c, 0xef, 0x0d, 0xe2, 0x29, 0x0b, 0xc1, 0xe1, 0x0d, 0x2d, 0xe6, + 0x04, 0xd3, 0xd8, 0xc0, 0x2c, 0x0b, 0x43, 0x15, 0x09, 0x1b, 0xd5, 0x29, 0xde, + 0xf4, 0x0f, 0x01, 0xf1, 0x04, 0xfb, 0x05, 0x0f, 0xad, 0x26, 0xe7, 0xf1, 0x34, + 0x08, 0xfc, 0xf8, 0x1c, 0xcb, 0xf9, 0x3d, 0x04, 0xf0, 0xf1, 0xd4, 0x02, 0x42, + 0x3b, 0x31, 0x39, 0x1d, 0xe3, 0x30, 0xfc, 0x1f, 0xd5, 0xfd, 0x36, 0x34, 0x00, + 0x3a, 0x0f, 0x0c, 0xd8, 0x53, 0x0a, 0xef, 0x11, 0x1c, 0x7f, 0xaf, 0xd0, 0xfe, + 0x06, 0x05, 0x66, 0xd2, 0xe3, 0xe0, 0xe0, 0x2b, 0xf1, 0xe0, 0xe1, 0x45, 0x56, + 0x12, 0xde, 0xf8, 0x1a, 0xfc, 0x07, 0xcd, 0x0e, 0x03, 0x16, 0x70, 0x2e, 0x30, + 0x35, 0xac, 0x8e, 0x10, 0x14, 0xdd, 0x35, 0x4f, 0x16, 0xfa, 0xeb, 0x0c, 0xf3, + 0xe2, 0x26, 0xbd, 0xfc, 0xd6, 0x2b, 0x92, 0x4d, 0xfa, 0xfa, 0x03, 0xf9, 0xd6, + 0xf2, 0x3a, 0xcc, 0xcc, 0xe0, 0xe9, 0xe7, 0x0f, 0x04, 0xfa, 0xd9, 0xea, 0xe2, + 0xd9, 0x0d, 0xf4, 0xbb, 0xfd, 0x17, 0xfa, 0x29, 0xee, 0xf1, 0x7f, 0xc5, 0xd0, + 0x04, 0x08, 0xeb, 0x14, 0x18, 0xe2, 0x01, 0xca, 0xfc, 0xe2, 0xfc, 0x47, 0x4b, + 0x1c, 0x46, 0xcc, 0x19, 0x08, 0xb8, 0xe4, 0xff, 0x28, 0x3c, 0xfc, 0x25, 0xfe, + 0xc9, 0x03, 0xd9, 0x27, 0xe8, 0x0c, 0x14, 0xda, 0xf7, 0x20, 0xf3, 0x0a, 0x2e, + 0x1d, 0x28, 0xeb, 0x1c, 0x03, 0x18, 0xde, 0xec, 0x42, 0x67, 0x09, 0x16, 0x43, + 0xc6, 0xfe, 0xeb, 0x0e, 0x01, 0xce, 0xe6, 0xe5, 0x01, 0x46, 0x05, 0xef, 0x0c, + 0xe2, 0xe5, 0xe1, 0x9a, 0x27, 0xe8, 0xdf, 0xe6, 0x35, 0xc1, 0x10, 0xf7, 0xcd, + 0x2e, 0x00, 0xda, 0xfd, 0xd8, 0xf8, 0xea, 0x7f, 0xb8, 0xdf, 0xd9, 0xa9, 0x2e, + 0x03, 0xfa, 0xfb, 0xf3, 0x20, 0x1a, 0x64, 0xe2, 0x2c, 0xf7, 0xf7, 0xf8, 0xef, + 0x65, 0xee, 0xe3, 0xc9, 0xf3, 0xf4, 0xdb, 0xf6, 0x65, 0xe3, 0x1d, 0xb0, 0xc7, + 0xdf, 0x00, 0xc7, 0xf8, 0xde, 0x2d, 0xe9, 0x08, 0x3b, 0xde, 0x38, 0x54, 0x06, + 0x22, 0x10, 0xf3, 0x62, 0x0e, 0x43, 0x20, 0x22, 0xe7, 0xd2, 0xfa, 0x3c, 0xe0, + 0xef, 0xe4, 0x39, 0x42, 0x2b, 0xe5, 0x31, 0xf4, 0xe9, 0xfa, 0xcf, 0x37, 0x0c, + 0xf7, 0x18, 0x11, 0xc2, 0x15, 0x3e, 0x24, 0x25, 0x2a, 0xef, 0xf3, 0xe0, 0xd4, + 0x44, 0xff, 0xf8, 0xc4, 0x20, 0xff, 0x0f, 0x07, 0x68, 0xf7, 0x1c, 0x16, 0xa4, + 0x22, 0x0f, 0xda, 0xf4, 0x42, 0xea, 0xee, 0x79, 0x4c, 0x07, 0x1f, 0xe1, 0xd8, + 0x03, 0xfb, 0xf2, 0xf7, 0x05, 0xea, 0x40, 0xf4, 0x1c, 0x3d, 0x1b, 0x11, 0x12, + 0x13, 0x20, 0x47, 0x34, 0x40, 0x19, 0xdf, 0xd1, 0xe1, 0x3e, 0x07, 0x1e, 0x34, + 0xf3, 0x2b, 0x0d, 0xd8, 0x22, 0xea, 0x11, 0x23, 0x03, 0x19, 0xda, 0xf6, 0xf9, + 0x38, 0xcd, 0x06, 0x48, 0xe6, 0x37, 0x46, 0x1a, 0x1b, 0x01, 0x28, 0xf9, 0xed, + 0xfd, 0xea, 0xf2, 0x30, 0x01, 0xe7, 0x0a, 0x0a, 0x22, 0x32, 0xe4, 0x47, 0xdd, + 0x02, 0x23, 0x29, 0x58, 0x22, 0x22, 0xcf, 0xd8, 0x55, 0x44, 0xc2, 0x07, 0x20, + 0xe1, 0x3c, 0xf0, 0x79, 0x13, 0x06, 0x04, 0xfd, 0x01, 0xf3, 0xf0, 0x13, 0xf3, + 0xdb, 0x10, 0xee, 0x29, 0xf7, 0x2e, 0x42, 0x1a, 0xdb, 0xea, 0xeb, 0x02, 0xed, + 0x02, 0xe5, 0x51, 0x0e, 0xf0, 0x12, 0x7f, 0xd8, 0x14, 0xef, 0x45, 0xf7, 0xe9, + 0xce, 0x23, 0x16, 0x16, 0x43, 0x00, 0xec, 0xf2, 0xda, 0xcc, 0x4b, 0xf3, 0x3b, + 0xd5, 0xe8, 0x32, 0xe5, 0x39, 0xe0, 0xc1, 0x56, 0xdb, 0x11, 0xf1, 0xe8, 0x35, + 0x07, 0x1a, 0xd6, 0x25, 0xa4, 0x30, 0xf2, 0xf4, 0xc7, 0x19, 0x69, 0x54, 0xfc, + 0xa8, 0x23, 0xfd, 0xee, 0x07, 0x01, 0xd0, 0xaf, 0x28, 0xfd, 0xdf, 0x20, 0x81, + 0x19, 0x36, 0x03, 0xf2, 0x0f, 0x0d, 0x28, 0xce, 0xc4, 0xc1, 0xc6, 0x26, 0xc9, + 0xe8, 0xa0, 0xe4, 0x8e, 0xd2, 0x24, 0xda, 0xf7, 0xfd, 0xa3, 0xf8, 0xfc, 0xb0, + 0x08, 0x2b, 0x2c, 0x0d, 0x19, 0x17, 0x1b, 0xa3, 0x77, 0x76, 0xfc, 0xdd, 0x2e, + 0x0e, 0xf3, 0xc0, 0x6c, 0x1f, 0xd5, 0x06, 0xb9, 0xe5, 0xd7, 0x00, 0x03, 0xc7, + 0xbd, 0x13, 0x3e, 0xe0, 0x34, 0x0a, 0x36, 0xed, 0x2c, 0xd0, 0xe4, 0xa3, 0x16, + 0xdd, 0xc0, 0x1f, 0xfa, 0xbc, 0xb2, 0x14, 0xf3, 0xea, 0xf7, 0xd6, 0xe9, 0xe6, + 0xf6, 0x23, 0x2d, 0x00, 0xb8, 0xeb, 0x40, 0x17, 0x12, 0x77, 0xd1, 0xc4, 0x01, + 0x11, 0x46, 0xd1, 0x52, 0x36, 0x4c, 0xef, 0x05, 0xe0, 0x29, 0xc1, 0x6b, 0x14, + 0x04, 0x1d, 0x07, 0x2a, 0x41, 0x04, 0x15, 0x1e, 0x25, 0x04, 0x0d, 0x41, 0xe0, + 0xf6, 0xfc, 0xf5, 0xe6, 0xe7, 0x07, 0x37, 0x30, 0x30, 0x27, 0x47, 0xe7, 0xec, + 0x33, 0x00, 0x22, 0x08, 0x02, 0x1c, 0x26, 0x6a, 0xf9, 0x1c, 0xb8, 0xc9, 0xda, + 0xe0, 0xfc, 0xfa, 0x1c, 0xeb, 0x31, 0xf3, 0xc6, 0x22, 0x1b, 0xf6, 0x04, 0xd0, + 0x10, 0xe7, 0x36, 0x0f, 0x7f, 0x08, 0x1d, 0x03, 0xde, 0xc1, 0x30, 0x30, 0x1e, + 0x08, 0xbd, 0xcc, 0x29, 0xe2, 0x06, 0x21, 0xe3, 0xd7, 0x59, 0xe9, 0xcd, 0xf0, + 0x17, 0x07, 0x31, 0xc3, 0xbb, 0xcf, 0xfa, 0x14, 0xe1, 0x67, 0xea, 0x15, 0x0b, + 0x08, 0x23, 0x37, 0x33, 0xdb, 0x29, 0xc0, 0x0e, 0x1f, 0xef, 0xfd, 0x0c, 0x59, + 0x13, 0x1d, 0x71, 0xfa, 0x1b, 0x02, 0xe3, 0xe7, 0xde, 0xcf, 0x54, 0xff, 0x2b, + 0xdd, 0x33, 0x3d, 0xd6, 0xed, 0xb0, 0xd8, 0xe3, 0x0b, 0x0c, 0xfe, 0x3c, 0x0a, + 0x10, 0xf7, 0xd5, 0x48, 0x20, 0xc4, 0xdf, 0x04, 0xe6, 0x12, 0x20, 0x01, 0x38, + 0xfe, 0xd8, 0xea, 0x57, 0xde, 0x9a, 0x45, 0xe4, 0x16, 0x1f, 0x59, 0x17, 0x23, + 0xda, 0x0c, 0xfb, 0xe1, 0x33, 0xe5, 0xcd, 0xd7, 0x17, 0xe6, 0xe1, 0xc5, 0xff, + 0x9a, 0xd3, 0xc8, 0xe6, 0xf5, 0xdf, 0xd5, 0xd5, 0xfc, 0x19, 0xe3, 0x27, 0xb5, + 0xf5, 0xed, 0x27, 0xff, 0xe0, 0xd7, 0x34, 0x0f, 0xe2, 0xd2, 0xfa, 0x08, 0x00, + 0x57, 0xcf, 0xe7, 0xf4, 0x20, 0x09, 0x0f, 0x7f, 0x07, 0x42, 0xda, 0xfc, 0xf9, + 0x0a, 0xdf, 0xda, 0xf7, 0x23, 0xd3, 0x2a, 0x04, 0x04, 0x0b, 0xc2, 0x0e, 0x0d, + 0xf4, 0x13, 0x06, 0xf4, 0x25, 0xe6, 0xf5, 0xed, 0xd3, 0x0e, 0xa7, 0xee, 0xed, + 0x1b, 0x05, 0x3f, 0x4c, 0x1c, 0xd0, 0x34, 0xb3, 0x3a, 0xf8, 0xf4, 0x45, 0x3f, + 0x24, 0xc4, 0xaa, 0xf1, 0xc1, 0x16, 0x0d, 0xf0, 0x5d, 0x2d, 0x2d, 0xeb, 0xfc, + 0xe8, 0xf1, 0x18, 0x0e, 0x22, 0x28, 0xd1, 0xb4, 0x3c, 0x0b, 0xfc, 0x18, 0x11, + 0xe0, 0xfc, 0xe2, 0x3e, 0x01, 0x43, 0xdf, 0x02, 0x72, 0x05, 0x20, 0xec, 0xd3, + 0xc3, 0xfa, 0x35, 0xe5, 0xf7, 0xf7, 0xd9, 0xde, 0xf2, 0xf0, 0xc3, 0xfb, 0xfa, + 0xb7, 0x04, 0x01, 0xc2, 0x55, 0xb4, 0xfa, 0x04, 0xf0, 0x02, 0xa5, 0x2d, 0xe6, + 0x37, 0xb7, 0x16, 0xb1, 0xca, 0x1e, 0xc9, 0xd0, 0x47, 0x1b, 0x2e, 0x52, 0x2f, + 0xbf, 0xd7, 0x06, 0xa3, 0xde, 0x33, 0xef, 0xa4, 0x01, 0x5f, 0xd8, 0xe9, 0xb3, + 0x3d, 0xf8, 0x35, 0x2e, 0xf7, 0x13, 0x27, 0xde, 0xd2, 0x70, 0x1b, 0xd0, 0x12, + 0xfb, 0xac, 0xf0, 0xed, 0xd9, 0xc2, 0xe7, 0x15, 0x05, 0xc8, 0x0e, 0x81, 0x08, + 0x07, 0x12, 0xbc, 0xcb, 0x4a, 0x00, 0xee, 0xd5, 0xdd, 0xd8, 0x2b, 0x2b, 0x0c, + 0x39, 0xc7, 0xf7, 0xc2, 0x30, 0xd1, 0x1c, 0x0c, 0x20, 0x30, 0x0d, 0x26, 0x3e, + 0x2a, 0x28, 0xcf, 0x0e, 0x01, 0x7f, 0xe2, 0xf5, 0xc3, 0x28, 0x05, 0x20, 0x08, + 0xf2, 0x10, 0x04, 0xf7, 0xed, 0xd8, 0x43, 0xf3, 0xf7, 0xd4, 0x2b, 0x26, 0xdd, + 0xe1, 0x51, 0xf2, 0x3f, 0x39, 0xaa, 0xf6, 0x24, 0xd6, 0x2c, 0x15, 0xde, 0xf4, + 0xf9, 0xf6, 0x17, 0xdd, 0x1d, 0xe7, 0xf8, 0x02, 0xd2, 0xbd, 0xe4, 0x13, 0x0c, + 0x42, 0x12, 0x1e, 0x09, 0xfb, 0x40, 0x3c, 0x1f, 0xe2, 0xdc, 0x09, 0x1c, 0x12, + 0x4d, 0x3e, 0x16, 0x37, 0x0a, 0x37, 0x15, 0xf0, 0x24, 0xd1, 0xbb, 0xe7, 0x07, + 0xe3, 0xd8, 0xc9, 0x4f, 0xc1, 0x04, 0x05, 0xd4, 0x1d, 0xae, 0xc1, 0xcc, 0x15, + 0x0d, 0x07, 0x0e, 0x13, 0xcf, 0x0b, 0x07, 0x01, 0x0e, 0xf7, 0xc4, 0x1a, 0x36, + 0xea, 0x15, 0xed, 0xe3, 0x15, 0x7f, 0x2d, 0x2d, 0xf6, 0x10, 0xdd, 0xe4, 0xdf, + 0xf8, 0xf2, 0xe7, 0x06, 0x5d, 0xff, 0xc0, 0x04, 0x06, 0xdb, 0x2e, 0xf5, 0xc1, + 0x52, 0xd1, 0x04, 0xe1, 0x28, 0xdb, 0x15, 0x03, 0x17, 0xda, 0x10, 0xe6, 0x35, + 0xe6, 0xcc, 0xea, 0x33, 0x46, 0x04, 0xc9, 0xd0, 0x4c, 0xf4, 0xfc, 0x64, 0x30, + 0xe0, 0x48, 0xc0, 0x17, 0xd0, 0x1c, 0xdb, 0xfa, 0xe4, 0xf4, 0x1d, 0xe1, 0xb4, + 0x17, 0x13, 0xe0, 0xff, 0xf6, 0xc2, 0x24, 0xea, 0x61, 0x34, 0xf7, 0xfe, 0x1f, + 0xf3, 0xfd, 0xb0, 0x3a, 0xe1, 0xeb, 0x6c, 0x1d, 0x17, 0xf3, 0xec, 0x17, 0xda, + 0xf0, 0x21, 0xf4, 0x00, 0xe5, 0x3d, 0xe3, 0x16, 0x03, 0x07, 0xd3, 0xec, 0x11, + 0x26, 0xde, 0xe1, 0xbb, 0xd8, 0x04, 0x2a, 0x24, 0x11, 0xeb, 0x3c, 0x25, 0x1f, + 0xf3, 0x10, 0xed, 0x2e, 0x3f, 0xff, 0xa3, 0xdf, 0x3a, 0x49, 0xe4, 0xdd, 0x1f, + 0xf1, 0xc8, 0x60, 0xec, 0xe7, 0xe9, 0x36, 0xe9, 0x08, 0xf9, 0xcf, 0xeb, 0x03, + 0x04, 0x17, 0x38, 0xdb, 0xe1, 0x10, 0x11, 0xdf, 0xfe, 0xe9, 0x2f, 0xe0, 0xed, + 0xfc, 0xc0, 0xfd, 0xff, 0xea, 0xdd, 0xd9, 0xdb, 0x25, 0xf9, 0x2a, 0x2f, 0xe7, + 0x1f, 0x31, 0xec, 0xef, 0x71, 0x16, 0x54, 0xe5, 0x03, 0x1d, 0xf8, 0x22, 0xf8, + 0x0e, 0x00, 0x18, 0xf4, 0x03, 0x05, 0x0c, 0x02, 0x29, 0xfb, 0xe3, 0xe3, 0x27, + 0x1c, 0x30, 0x15, 0x35, 0xe6, 0x1d, 0x42, 0xf9, 0xe3, 0xfe, 0xeb, 0xec, 0x19, + 0xb7, 0xf9, 0x02, 0x1c, 0xd3, 0xff, 0xf5, 0xf3, 0x17, 0x0a, 0xfd, 0x08, 0x7f, + 0xf9, 0xfd, 0x06, 0x30, 0xdd, 0x1e, 0xf0, 0x0c, 0x1e, 0x3b, 0xff, 0xf2, 0x2a, + 0xfe, 0x15, 0xde, 0xcf, 0x2c, 0xf9, 0x0d, 0xff, 0x02, 0x01, 0xeb, 0xe9, 0x19, + 0xfe, 0x39, 0x31, 0x03, 0xe1, 0x00, 0x15, 0xea, 0xda, 0x00, 0xca, 0xf7, 0x3f, + 0xfc, 0xfe, 0x13, 0x03, 0xf2, 0xe5, 0x3e, 0x14, 0x44, 0xdf, 0x07, 0x38, 0x05, + 0xda, 0xe0, 0x15, 0x3b, 0x1b, 0x02, 0xe0, 0x06, 0x7f, 0x46, 0x29, 0xf3, 0x0f, + 0xeb, 0x14, 0xf6, 0x0f, 0x07, 0x1a, 0xd8, 0x09, 0xff, 0xee, 0xd4, 0x1e, 0x41, + 0xeb, 0xdf, 0xdb, 0x01, 0xae, 0x1c, 0x35, 0xe0, 0xea, 0xe4, 0xcd, 0xfe, 0x08, + 0xeb, 0xfa, 0x2f, 0x00, 0x09, 0x24, 0x0b, 0x02, 0x15, 0xed, 0x5d, 0xe6, 0x00, + 0x11, 0xfa, 0x34, 0x12, 0xd6, 0xca, 0xc3, 0xd2, 0x31, 0xde, 0xce, 0x29, 0x15, + 0xdc, 0xd0, 0xfc, 0xc8, 0x3b, 0x0f, 0xf9, 0xd5, 0xe4, 0x06, 0xc8, 0x31, 0xfd, + 0x13, 0xf3, 0xf6, 0x1e, 0xf9, 0xec, 0x39, 0xbd, 0x77, 0xdf, 0xde, 0xd3, 0xb6, + 0x51, 0xf0, 0xb0, 0x07, 0xf0, 0xde, 0x11, 0xb8, 0xda, 0x24, 0xe6, 0x23, 0xd4, + 0xec, 0x21, 0x56, 0xb5, 0xbc, 0x13, 0x2c, 0x21, 0x06, 0x03, 0x06, 0xf8, 0x2b, + 0x14, 0x31, 0xc5, 0x65, 0x40, 0xbc, 0xe9, 0x9b, 0x18, 0xe6, 0x0d, 0xf8, 0xf2, + 0x07, 0xf4, 0xea, 0x01, 0x26, 0x46, 0xe4, 0x1b, 0xfb, 0x0e, 0xd0, 0x43, 0x40, + 0xe1, 0xe8, 0x33, 0xc5, 0x44, 0xe9, 0x81, 0xf5, 0xe3, 0xe2, 0x08, 0x0a, 0x40, + 0x14, 0x2c, 0xd6, 0xd9, 0xed, 0xee, 0x54, 0x02, 0xcf, 0xfe, 0x1a, 0xcf, 0xf5, + 0x1d, 0x26, 0xfe, 0xca, 0x30, 0xc5, 0xd8, 0x33, 0x9c, 0xed, 0x1f, 0xf2, 0xdf, + 0xd4, 0x63, 0xdf, 0x20, 0xbf, 0xf8, 0x3c, 0x27, 0xd1, 0xde, 0x00, 0x32, 0xdf, + 0xc2, 0xb4, 0x09, 0xdd, 0x03, 0x0f, 0x0c, 0x08, 0x9c, 0xd2, 0xe0, 0x5a, 0xf8, + 0xb3, 0xe6, 0x15, 0x14, 0xf0, 0x0f, 0x29, 0x11, 0xd8, 0x15, 0x32, 0xda, 0x04, + 0xba, 0xe4, 0xee, 0x44, 0xf2, 0xae, 0x22, 0x25, 0xe0, 0xc2, 0xe7, 0x54, 0xfd, + 0x2d, 0x93, 0x30, 0x1c, 0xf3, 0x49, 0x37, 0xbe, 0x1a, 0xb9, 0x68, 0xec, 0x06, + 0x0b, 0x33, 0xb7, 0xc4, 0xd0, 0x1a, 0xf4, 0x09, 0x13, 0x0c, 0x27, 0xe5, 0x07, + 0xae, 0xf4, 0x20, 0xea, 0xf1, 0xfc, 0xd4, 0x03, 0x3b, 0x35, 0xc4, 0xdd, 0xc4, + 0xf4, 0xea, 0x2f, 0xfb, 0x85, 0x66, 0x02, 0xce, 0x1c, 0xf1, 0xa5, 0x2b, 0xe6, + 0xf8, 0xd7, 0xde, 0xd7, 0xc6, 0x02, 0x81, 0x22, 0x3b, 0xd7, 0x9c, 0x37, 0x20, + 0xe2, 0xee, 0xfe, 0xee, 0x21, 0x0a, 0xe6, 0x0e, 0x18, 0xf7, 0x50, 0x11, 0xe7, + 0x45, 0xa7, 0xd6, 0x07, 0xe8, 0x1b, 0xe1, 0x38, 0xac, 0x04, 0xf6, 0xba, 0x01, + 0xec, 0xec, 0xea, 0xfd, 0xfc, 0x00, 0x51, 0x32, 0xf9, 0xa5, 0xc8, 0xe5, 0xd4, + 0x05, 0x31, 0x04, 0x1e, 0xe0, 0xf0, 0xeb, 0x0e, 0x55, 0xf5, 0x3c, 0x13, 0xe3, + 0x43, 0x1b, 0xb0, 0x30, 0xec, 0x58, 0xda, 0x3f, 0x01, 0x06, 0xc5, 0x1e, 0x58, + 0x27, 0xcb, 0x13, 0x22, 0x67, 0x25, 0xf6, 0x03, 0x0e, 0xeb, 0xcb, 0x10, 0x2f, + 0xdd, 0x0a, 0x06, 0xf8, 0x0e, 0x01, 0x32, 0xf2, 0xdc, 0xf3, 0xc2, 0x4e, 0xfd, + 0xae, 0xc7, 0x5a, 0x13, 0xfb, 0xc4, 0xd0, 0x35, 0x41, 0x15, 0xf6, 0xdf, 0xef, + 0x17, 0x52, 0xc8, 0xdc, 0xf9, 0xc7, 0x51, 0xf8, 0xc2, 0xd2, 0x45, 0x49, 0xde, + 0xe4, 0x58, 0xad, 0x08, 0x0d, 0x26, 0xf4, 0xc8, 0xd3, 0xe6, 0xb3, 0xf7, 0xfa, + 0x16, 0x0f, 0xcf, 0xdf, 0xf5, 0x0e, 0x0f, 0xe4, 0x14, 0xeb, 0x2c, 0x81, 0xfd, + 0xef, 0xf9, 0x4a, 0xf9, 0xfa, 0x01, 0x9a, 0xe2, 0xa3, 0x5b, 0x14, 0x63, 0xe2, + 0xd9, 0xe0, 0xe8, 0xfc, 0x00, 0xf5, 0xdf, 0x07, 0x65, 0xd4, 0x14, 0x10, 0x21, + 0xd9, 0x00, 0xa9, 0x14, 0x2d, 0x05, 0x13, 0xdb, 0x05, 0x27, 0x39, 0xe2, 0x17, + 0xcd, 0xf3, 0xf5, 0xeb, 0xc2, 0xd0, 0xe3, 0x1d, 0xd8, 0x06, 0xfd, 0xc9, 0xcb, + 0x4c, 0xf7, 0xd6, 0xff, 0x0c, 0x28, 0x02, 0x08, 0xbc, 0x31, 0xdb, 0x37, 0xe3, + 0xf7, 0x81, 0x2e, 0xd1, 0xc7, 0x00, 0x41, 0xd2, 0xc4, 0x13, 0x12, 0x04, 0x0e, + 0x19, 0xee, 0xd6, 0x3c, 0x4d, 0xe4, 0xe2, 0x1f, 0x28, 0x04, 0xd7, 0x3d, 0xf5, + 0xcb, 0xeb, 0xb1, 0x1e, 0xbb, 0x17, 0xee, 0x36, 0x2c, 0xf8, 0x15, 0x09, 0xfd, + 0x33, 0xc4, 0xc2, 0xf2, 0xd5, 0xf9, 0xbe, 0x0c, 0xbc, 0x50, 0xb9, 0xed, 0xc4, + 0xd6, 0xdd, 0xed, 0x13, 0x06, 0xfe, 0x1d, 0x0d, 0xf5, 0xa3, 0x0d, 0xd3, 0x6b, + 0xe6, 0xff, 0x65, 0x29, 0xb4, 0x0e, 0xf0, 0xec, 0xe1, 0x1b, 0xee, 0xe4, 0xeb, + 0xf5, 0xec, 0x7b, 0x24, 0x2b, 0x26, 0x06, 0xc8, 0x27, 0x04, 0xfe, 0x2d, 0x12, + 0xa1, 0xe0, 0xe2, 0x18, 0x43, 0x24, 0x57, 0x1f, 0x0a, 0x1c, 0xfc, 0x1b, 0xe5, + 0xdd, 0x1d, 0xe0, 0xf5, 0x16, 0xe0, 0xf0, 0xef, 0xb0, 0x26, 0xdd, 0x17, 0xcf, + 0xe7, 0x0e, 0x11, 0xf7, 0xdf, 0x34, 0x21, 0xfd, 0xbc, 0xd4, 0x07, 0x0b, 0x10, + 0x3a, 0xbb, 0xdb, 0xdc, 0x31, 0x56, 0xfb, 0xf8, 0xff, 0x60, 0x04, 0xb5, 0x7f, + 0xdf, 0xfd, 0x06, 0x2c, 0xd8, 0xea, 0x16, 0xbd, 0xe1, 0x2a, 0x0c, 0xd4, 0xf6, + 0x44, 0x05, 0xd4, 0x19, 0xe1, 0xb8, 0xe8, 0x04, 0x06, 0xd6, 0xcc, 0x53, 0xdb, + 0xef, 0xfe, 0xd1, 0xf0, 0xe5, 0xfa, 0xc1, 0xc1, 0x1a, 0xbf, 0xea, 0x07, 0x08, + 0x52, 0x0d, 0xb8, 0x0d, 0x07, 0x26, 0x4e, 0xe0, 0x02, 0x06, 0x08, 0xe8, 0xfe, + 0xc3, 0xea, 0x50, 0x21, 0x05, 0xe5, 0x10, 0xc3, 0x1c, 0xfd, 0xf9, 0x06, 0x1e, + 0xdb, 0x49, 0x22, 0x1c, 0x07, 0xfd, 0xfe, 0x14, 0xea, 0x0e, 0xdf, 0xfb, 0xed, + 0x12, 0xef, 0x0b, 0x79, 0x1c, 0x2d, 0xc7, 0x11, 0x06, 0x1b, 0x0c, 0xf6, 0x07, + 0x21, 0x0d, 0x0f, 0xf6, 0x39, 0xc0, 0x1c, 0x23, 0xfa, 0xe3, 0x1a, 0x1f, 0x1c, + 0x01, 0xcc, 0xd6, 0x3a, 0x12, 0x3d, 0x97, 0x1e, 0x0d, 0x34, 0x16, 0x39, 0x33, + 0x23, 0xe1, 0xd4, 0x2b, 0x11, 0xfd, 0x1e, 0xd2, 0x2c, 0x9f, 0x01, 0x65, 0x10, + 0xca, 0x1f, 0xca, 0xfb, 0xce, 0x06, 0xbe, 0x29, 0x28, 0xea, 0x7f, 0x06, 0xa3, + 0x15, 0xdc, 0x18, 0x1e, 0xe4, 0x61, 0x0c, 0x0d, 0xeb, 0xcf, 0xf9, 0xb4, 0xe1, + 0x12, 0xb3, 0xff, 0x14, 0xe4, 0xc2, 0xe7, 0x02, 0xe7, 0x03, 0x0e, 0x34, 0x7c, + 0x46, 0x3c, 0x3f, 0x05, 0x06, 0x87, 0xba, 0xdf, 0xdb, 0x28, 0x01, 0x1b, 0xdf, + 0xf9, 0xf1, 0xba, 0x0d, 0xe3, 0xe2, 0xc2, 0xf3, 0x0a, 0xf7, 0xd2, 0x39, 0xea, + 0xb4, 0x11, 0x3b, 0xcb, 0x3d, 0xe9, 0xcd, 0xad, 0xcd, 0xac, 0x46, 0xf3, 0x5c, + 0x14, 0x56, 0xd0, 0xcb, 0xee, 0xc3, 0x12, 0x4c, 0x9d, 0xfa, 0xde, 0x03, 0x30, + 0xe7, 0xd0, 0x00, 0x2c, 0x2f, 0x3d, 0xe9, 0x15, 0x51, 0x18, 0x17, 0xe4, 0xf9, + 0x7f, 0x22, 0xd7, 0xfa, 0x1e, 0x10, 0xfc, 0xea, 0x64, 0x4b, 0xff, 0x2e, 0x12, + 0xda, 0xd0, 0xdb, 0x0a, 0x2c, 0x7a, 0xf3, 0x2d, 0x99, 0xab, 0x23, 0x22, 0x16, + 0x45, 0xcb, 0x1d, 0x0b, 0xfe, 0x0f, 0x00, 0x1c, 0xe2, 0xd1, 0xf4, 0xac, 0x73, + 0xec, 0x01, 0x27, 0xf8, 0x50, 0x3b, 0xd5, 0xdb, 0xef, 0x15, 0xfd, 0x19, 0x14, + 0xe4, 0x49, 0xe4, 0x2f, 0xf2, 0x10, 0x0f, 0x0e, 0x01, 0x23, 0x51, 0x1e, 0x23, + 0x46, 0x14, 0xde, 0xf9, 0x23, 0x2f, 0x03, 0xf4, 0x12, 0x18, 0x63, 0xdb, 0xf7, + 0xf7, 0x07, 0xb7, 0xed, 0x2d, 0xbd, 0xea, 0xdb, 0xdd, 0x2f, 0xfe, 0xe8, 0xff, + 0xf5, 0xf3, 0x08, 0xe7, 0x2d, 0x2e, 0xe9, 0x07, 0xdd, 0xca, 0x1d, 0x4b, 0xf8, + 0xd6, 0x0e, 0x6e, 0xce, 0xc3, 0x17, 0x18, 0xe7, 0xf5, 0xde, 0xf9, 0xcd, 0x31, + 0x78, 0xfd, 0x1b, 0x7c, 0x32, 0x40, 0x43, 0x05, 0xdd, 0x03, 0xf6, 0xe7, 0x0a, + 0xc9, 0x27, 0x26, 0xe8, 0x12, 0xd7, 0xf2, 0xc9, 0x07, 0xf6, 0xe1, 0xea, 0xf3, + 0xfd, 0xd9, 0x05, 0xd8, 0x2a, 0x17, 0x18, 0xe6, 0x1b, 0x25, 0x11, 0x12, 0x35, + 0xe1, 0x32, 0x06, 0xfb, 0x12, 0x2b, 0x3b, 0x14, 0xed, 0xd4, 0xe8, 0x09, 0x02, + 0x10, 0x7f, 0xe2, 0xf8, 0xbd, 0xe4, 0xe7, 0xc3, 0xeb, 0xff, 0x13, 0x04, 0xf8, + 0xdd, 0x11, 0xba, 0x27, 0xf4, 0xc7, 0x00, 0xd8, 0x5b, 0x24, 0x60, 0x44, 0xd7, + 0xfe, 0xc8, 0xce, 0x41, 0xe4, 0x27, 0xd5, 0x1b, 0x36, 0xca, 0xe8, 0x4f, 0xdf, + 0x22, 0x15, 0x18, 0x2e, 0x01, 0x06, 0x27, 0xed, 0xe8, 0xff, 0x29, 0x08, 0xd3, + 0x2b, 0xfe, 0xf1, 0xee, 0xfc, 0xe3, 0x15, 0xb6, 0xe8, 0x6d, 0x05, 0xf3, 0x1b, + 0x4f, 0x4f, 0x0c, 0x0b, 0x6c, 0x1c, 0xda, 0xfa, 0xd4, 0xf9, 0x0e, 0x11, 0xf8, + 0xf1, 0x25, 0x32, 0xfc, 0xfc, 0xef, 0x13, 0xf7, 0xf4, 0x23, 0x40, 0xde, 0x2b, + 0x3e, 0x19, 0xe4, 0xf1, 0x2d, 0xf3, 0xf3, 0x0e, 0x2a, 0x3c, 0x1e, 0x20, 0x09, + 0x12, 0x7a, 0x1d, 0x0d, 0x1f, 0x15, 0x35, 0x0e, 0xfd, 0x1e, 0xf0, 0xff, 0x0e, + 0xde, 0x1f, 0x19, 0xe5, 0x20, 0x1d, 0xee, 0xe5, 0x7f, 0x0b, 0x0e, 0xfa, 0xea, + 0xfd, 0xe9, 0xdf, 0x02, 0xe1, 0xec, 0x01, 0x12, 0x00, 0xe7, 0x11, 0x35, 0xf2, + 0xe2, 0xf9, 0xfb, 0xec, 0x08, 0xd9, 0x0f, 0xea, 0xf4, 0xf0, 0xee, 0x02, 0xf3, + 0xf1, 0x38, 0x1d, 0x1c, 0x37, 0xdf, 0x0b, 0xe2, 0x16, 0xf9, 0xfd, 0x09, 0xe8, + 0xed, 0xef, 0x00, 0x0d, 0x17, 0xf7, 0xeb, 0x0c, 0xf2, 0x12, 0xf3, 0xef, 0x39, + 0xfa, 0xd9, 0x02, 0xdf, 0x0a, 0xe5, 0xf2, 0x1c, 0xf7, 0x0e, 0x19, 0x05, 0x21, + 0x04, 0xf9, 0x24, 0xd9, 0xdf, 0xfc, 0xfa, 0x02, 0x34, 0x16, 0x34, 0x21, 0xff, + 0xd7, 0xf2, 0x1f, 0xf1, 0xec, 0x0d, 0xfe, 0xfd, 0xfe, 0x2a, 0x2f, 0xf7, 0x33, + 0xef, 0x4b, 0xce, 0x36, 0xef, 0xd4, 0xee, 0xf5, 0x5c, 0xee, 0x1a, 0xd5, 0xe9, + 0xe0, 0x51, 0xe4, 0xcb, 0x09, 0x43, 0xd4, 0xfb, 0x12, 0x27, 0xe5, 0x17, 0x21, + 0x05, 0x7f, 0x1e, 0x0c, 0xfe, 0xf0, 0xea, 0xda, 0xe9, 0x47, 0xfc, 0x07, 0x0d, + 0xed, 0xdb, 0xd2, 0xdb, 0xfa, 0xe5, 0x13, 0x08, 0x09, 0xf8, 0x15, 0x15, 0x16, + 0xe7, 0xe7, 0x46, 0x24, 0x18, 0xf2, 0x2d, 0xf8, 0xfc, 0x11, 0x02, 0x2c, 0x13, + 0xce, 0xe5, 0xef, 0x1a, 0x49, 0x21, 0xcd, 0xe7, 0xe9, 0xf6, 0x17, 0x2f, 0xfc, + 0xc3, 0x20, 0xf0, 0x07, 0x06, 0xf3, 0x12, 0x0f, 0x1c, 0xf3, 0xd9, 0xfc, 0xf7, + 0x0b, 0xfd, 0xf9, 0x00, 0x0f, 0x1e, 0xf4, 0xd2, 0xdb, 0x0d, 0xdc, 0x07, 0xee, + 0xf6, 0xe8, 0x22, 0xff, 0x30, 0xd3, 0x19, 0x27, 0x2c, 0xfa, 0xfa, 0x4a, 0xf3, + 0x2a, 0xe8, 0xd6, 0x39, 0xe9, 0x04, 0x0b, 0x1b, 0x34, 0xec, 0xf7, 0x3d, 0xa3, + 0x08, 0x5b, 0x26, 0xdc, 0xc2, 0x48, 0xdd, 0x2f, 0x2d, 0xf6, 0x60, 0x02, 0x37, + 0x59, 0xa4, 0x3a, 0x06, 0x02, 0x36, 0xff, 0x16, 0x1e, 0xf2, 0x68, 0x0b, 0x01, + 0x0e, 0xe8, 0xea, 0x30, 0x6a, 0x4d, 0x37, 0x38, 0xfb, 0xdb, 0xf4, 0x2a, 0x0d, + 0xfb, 0x14, 0xef, 0xe7, 0xce, 0x00, 0xeb, 0x0b, 0x05, 0xb8, 0x10, 0xcb, 0x2c, + 0xf5, 0xbf, 0x2f, 0x27, 0x65, 0x6d, 0x0b, 0x9f, 0x27, 0x4b, 0xfe, 0xe3, 0xee, + 0x24, 0xdd, 0x6a, 0xf1, 0xf3, 0xd5, 0x9d, 0x14, 0xdc, 0xf7, 0xfe, 0x15, 0xca, + 0xaa, 0x52, 0xf5, 0x16, 0xdb, 0xdb, 0x47, 0x10, 0x30, 0xcb, 0x0c, 0xf4, 0x00, + 0x0c, 0xf4, 0xb6, 0x7f, 0xc8, 0xe8, 0xe9, 0x23, 0x37, 0x00, 0x09, 0xf0, 0x0b, + 0xf6, 0xe6, 0xf3, 0x30, 0xe7, 0x37, 0x56, 0x45, 0xd3, 0x10, 0xc1, 0xfc, 0xbb, + 0x8c, 0x32, 0x0d, 0x11, 0xb7, 0x6d, 0xdd, 0x18, 0x5b, 0x46, 0x14, 0xc5, 0x17, + 0x2e, 0xf3, 0x2b, 0x02, 0x45, 0xdb, 0x3c, 0x03, 0xbe, 0xf0, 0x3a, 0x7d, 0x37, + 0xdd, 0xb1, 0xb5, 0x2c, 0x06, 0x3c, 0xb6, 0x66, 0xaf, 0x5d, 0x09, 0xdb, 0xf4, + 0xfb, 0x1f, 0xe7, 0xe7, 0x01, 0x21, 0xe9, 0x34, 0xfd, 0x3d, 0xc6, 0xef, 0xe7, + 0x0a, 0x3d, 0x20, 0x54, 0xdf, 0x0b, 0x07, 0x34, 0x96, 0x01, 0x65, 0x24, 0x63, + 0x28, 0x7f, 0x4e, 0x0b, 0x0e, 0xcb, 0x20, 0x46, 0xc5, 0xa7, 0x55, 0x02, 0xc1, + 0x18, 0x0c, 0xda, 0xe3, 0x3b, 0xbd, 0x3a, 0x22, 0x47, 0x10, 0xe5, 0x21, 0xdf, + 0x3b, 0xdd, 0x0f, 0x0e, 0x05, 0xc6, 0x9b, 0x06, 0x66, 0xf0, 0x3a, 0xd6, 0x20, + 0xba, 0xf3, 0x0a, 0xd1, 0xe6, 0x40, 0xe1, 0xe7, 0xf4, 0x1d, 0x05, 0xf1, 0x2c, + 0xef, 0xd0, 0xe1, 0x18, 0x11, 0x1c, 0x5e, 0x27, 0xfd, 0xff, 0xfb, 0xe9, 0xfb, + 0xf1, 0x1a, 0x40, 0x0d, 0x1d, 0x30, 0x3a, 0xdd, 0xde, 0xd2, 0x13, 0xdf, 0x35, + 0xfe, 0xe8, 0xeb, 0x1c, 0x02, 0x24, 0x10, 0x25, 0x00, 0x0a, 0x0d, 0x04, 0xf7, + 0xfb, 0xfd, 0xee, 0xc9, 0x14, 0xd1, 0x27, 0xd4, 0xdd, 0x21, 0xbd, 0xc6, 0x53, + 0xfd, 0xf2, 0x0d, 0xef, 0x0a, 0xf2, 0xe7, 0x0a, 0x1e, 0x1c, 0xe5, 0xff, 0xf5, + 0xed, 0xd9, 0xf8, 0x1e, 0xe2, 0xfd, 0x04, 0xfd, 0xe3, 0x14, 0xe6, 0x1a, 0x7f, + 0x05, 0x2a, 0xf0, 0xf8, 0xf2, 0x07, 0xfa, 0x11, 0xe4, 0xf8, 0xed, 0xe7, 0xfe, + 0xfc, 0xf9, 0xcf, 0x08, 0xe2, 0xf6, 0xea, 0xec, 0x07, 0x13, 0x0f, 0x25, 0x06, + 0xee, 0xdf, 0xf2, 0x19, 0x1e, 0xd5, 0x18, 0x0b, 0xe5, 0xf5, 0x11, 0xfc, 0x0e, + 0x19, 0xf4, 0xf7, 0xf5, 0xf5, 0x0c, 0x00, 0xf5, 0xfe, 0xfd, 0x04, 0xdf, 0xf0, + 0x0f, 0x43, 0xf2, 0xf9, 0x0a, 0xe1, 0x29, 0xea, 0xdf, 0x63, 0xf5, 0x21, 0xc6, + 0xf2, 0xf5, 0x2c, 0xd1, 0x3b, 0x2e, 0xee, 0x12, 0xc1, 0xe8, 0x0b, 0x05, 0x0a, + 0x1d, 0xbf, 0x57, 0xb8, 0xc4, 0xb4, 0xcc, 0x2c, 0x36, 0xda, 0x2a, 0x9e, 0x46, + 0x05, 0x18, 0xe3, 0x0d, 0x18, 0x03, 0x0f, 0xe6, 0x05, 0xe3, 0xd9, 0xd0, 0x2a, + 0xf6, 0x4c, 0x45, 0xe3, 0x25, 0xec, 0xfa, 0x18, 0xef, 0xfb, 0x9f, 0x10, 0xf5, + 0xfc, 0xd6, 0x08, 0x1e, 0x1b, 0xdf, 0x5a, 0x29, 0xf6, 0xe8, 0xfd, 0x3a, 0xfd, + 0x13, 0x0d, 0xfa, 0xa6, 0xf4, 0x32, 0x5a, 0xd4, 0xfa, 0xf9, 0xbe, 0xa4, 0x17, + 0xae, 0xa6, 0xe7, 0x0c, 0xe7, 0x02, 0x75, 0x05, 0x13, 0xc6, 0x48, 0x42, 0xb6, + 0xf0, 0x10, 0xd3, 0x81, 0xd5, 0xd4, 0xc7, 0x09, 0xea, 0x02, 0x6a, 0xd7, 0xdd, + 0xff, 0x2f, 0x17, 0x00, 0x34, 0xfd, 0xfc, 0x0b, 0xf5, 0x1d, 0xf0, 0x7e, 0xf6, + 0xfc, 0xa9, 0xf6, 0x1e, 0x39, 0x3e, 0x05, 0xd6, 0xfe, 0xf1, 0x62, 0x56, 0xba, + 0x79, 0x58, 0x11, 0x07, 0x05, 0x08, 0x14, 0xd8, 0x24, 0xe0, 0xe6, 0x2c, 0x5f, + 0x18, 0x26, 0x3a, 0x24, 0x0f, 0x4c, 0x5e, 0x5a, 0xb0, 0x31, 0x32, 0x24, 0xb8, + 0x11, 0xba, 0x12, 0x26, 0xc2, 0x3a, 0x11, 0x36, 0xea, 0xfd, 0x21, 0xca, 0xe6, + 0x14, 0x0b, 0xe7, 0x37, 0x4d, 0x05, 0x00, 0xea, 0xbb, 0xd5, 0xfc, 0xdb, 0x27, + 0x24, 0xbc, 0xf5, 0xfd, 0x12, 0xef, 0x0b, 0x59, 0xff, 0xdf, 0x03, 0xf0, 0x14, + 0x9e, 0x08, 0x1e, 0xcf, 0xf4, 0x10, 0xdf, 0xd0, 0xc2, 0x8d, 0x29, 0x2e, 0x1b, + 0xf1, 0xdb, 0xee, 0x46, 0xf3, 0x0f, 0xfc, 0xf4, 0xe7, 0xe6, 0x11, 0x9a, 0x2c, + 0xd1, 0xf3, 0xe3, 0xd3, 0x29, 0x16, 0x05, 0x00, 0xed, 0x75, 0xbb, 0x50, 0x4c, + 0x31, 0x2b, 0x67, 0xd7, 0xd8, 0xd0, 0xe5, 0x0e, 0x00, 0x08, 0xea, 0x7f, 0xb1, + 0xc8, 0x0f, 0xfa, 0xf0, 0x12, 0x2b, 0xfe, 0x7f, 0xe1, 0x29, 0x0a, 0x2f, 0x18, + 0xe1, 0xf3, 0xd3, 0x0f, 0x12, 0x08, 0x1d, 0xf4, 0x10, 0x1c, 0xfd, 0x16, 0xc9, + 0x11, 0xa5, 0x1f, 0xce, 0xbd, 0x11, 0xc4, 0xec, 0xeb, 0x09, 0x09, 0x24, 0xdd, + 0x72, 0xf2, 0xf2, 0x30, 0xea, 0x5a, 0x17, 0x17, 0x18, 0x61, 0xd3, 0x21, 0xe0, + 0xe8, 0xd0, 0x47, 0xf1, 0x2b, 0xb4, 0x2d, 0xf2, 0xf0, 0xcf, 0xcc, 0x34, 0xe2, + 0xf7, 0xf8, 0xdc, 0xc5, 0xe7, 0xd1, 0xed, 0x27, 0x2c, 0xa2, 0x0a, 0x6c, 0x51, + 0x0f, 0x48, 0x1b, 0x15, 0x06, 0xc6, 0xce, 0x0f, 0x1b, 0xdb, 0x1c, 0x49, 0x07, + 0xde, 0x16, 0xfb, 0x21, 0x29, 0xec, 0xf1, 0x2c, 0x4c, 0x18, 0xef, 0xe4, 0x01, + 0xdf, 0xfa, 0x29, 0x1b, 0x43, 0x12, 0xde, 0xd0, 0x06, 0x49, 0x42, 0x2a, 0x21, + 0x14, 0x01, 0x19, 0xf5, 0xf6, 0xe1, 0x1f, 0xc2, 0xfa, 0xcd, 0xe0, 0xf1, 0x3e, + 0xe4, 0x4f, 0x56, 0xcb, 0xc2, 0x0d, 0x79, 0x2d, 0x04, 0x32, 0xf3, 0x0d, 0xe2, + 0xb3, 0xf2, 0xab, 0x29, 0x06, 0xe8, 0x0a, 0xdf, 0xc3, 0x10, 0x1d, 0x26, 0xb1, + 0x17, 0x08, 0x13, 0xfc, 0x03, 0x30, 0x33, 0x2e, 0x0a, 0x24, 0xcf, 0x05, 0x36, + 0x00, 0xea, 0x04, 0xcf, 0x44, 0x21, 0x06, 0x6e, 0xd2, 0xd3, 0xe2, 0xc3, 0x2c, + 0x3c, 0x20, 0x0e, 0x26, 0xb2, 0xbd, 0xf4, 0xfa, 0xe7, 0xc8, 0xbe, 0x15, 0xf1, + 0xc0, 0x3e, 0xe4, 0x0f, 0x6d, 0xdf, 0x1a, 0xe7, 0x0a, 0x3f, 0x22, 0x43, 0x3d, + 0xd1, 0x02, 0x4d, 0xf5, 0xcb, 0x7f, 0x32, 0x43, 0x0e, 0xeb, 0xd6, 0xf1, 0xb5, + 0xf6, 0x2b, 0x02, 0x10, 0x14, 0xef, 0x01, 0xf7, 0x62, 0xec, 0x07, 0x05, 0x62, + 0xad, 0x1c, 0xee, 0xea, 0x2e, 0xed, 0x1e, 0xfa, 0x37, 0xfc, 0x40, 0x0c, 0xfb, + 0x26, 0xf5, 0x0e, 0xa6, 0x07, 0x5a, 0x19, 0x0e, 0xd7, 0x42, 0xd0, 0xe4, 0xe3, + 0x31, 0xc0, 0x21, 0xe4, 0x29, 0xac, 0xdc, 0xf8, 0xee, 0xbe, 0xd7, 0x37, 0xdc, + 0x47, 0xed, 0xfe, 0x20, 0xcc, 0xc6, 0x7f, 0x09, 0xed, 0x08, 0xcb, 0x16, 0xf7, + 0xdf, 0xd8, 0xfa, 0x21, 0x28, 0x3f, 0xc1, 0x95, 0x02, 0xcd, 0xd9, 0xf7, 0xa8, + 0xe6, 0xb9, 0x01, 0xce, 0xe2, 0x06, 0x19, 0x14, 0x31, 0x45, 0x23, 0xe1, 0xd1, + 0x0b, 0xec, 0xed, 0xeb, 0xbe, 0xc6, 0xba, 0xd1, 0xf3, 0xfe, 0x08, 0xf6, 0x3b, + 0x1a, 0xcc, 0xa5, 0xc6, 0x0e, 0x38, 0xd1, 0x00, 0xd5, 0xd6, 0x0e, 0x13, 0xd2, + 0x20, 0x4a, 0xad, 0x1b, 0xb9, 0x4d, 0xe7, 0x0d, 0xf7, 0x13, 0x67, 0xb4, 0xf8, + 0xf3, 0x39, 0x48, 0xf4, 0xf9, 0xe2, 0xe1, 0x22, 0x42, 0x2f, 0x11, 0x37, 0xc8, + 0x01, 0x17, 0xd1, 0xc6, 0x00, 0xc8, 0x29, 0x00, 0x2c, 0xa5, 0xce, 0xd7, 0x66, + 0x2b, 0x00, 0xb7, 0xf8, 0x03, 0x2f, 0x3b, 0x16, 0xf7, 0xf9, 0xf8, 0x49, 0x17, + 0x19, 0xda, 0x08, 0xf3, 0x04, 0xf6, 0x28, 0x15, 0x16, 0x03, 0x0a, 0xf3, 0x04, + 0x30, 0x51, 0x2f, 0xfa, 0xe0, 0xfa, 0x31, 0x10, 0xde, 0xea, 0xe8, 0x1e, 0x27, + 0x6d, 0xde, 0x11, 0x0f, 0x2e, 0xef, 0xd7, 0x2a, 0x0b, 0x5b, 0x18, 0x3f, 0xfb, + 0xd9, 0x49, 0x1d, 0x10, 0xeb, 0x0a, 0x38, 0xfe, 0x34, 0x27, 0x30, 0x20, 0x07, + 0xf5, 0x29, 0x0c, 0x18, 0x23, 0x1d, 0xd7, 0xec, 0x07, 0xff, 0x05, 0xfc, 0x10, + 0xec, 0x56, 0xfd, 0xd8, 0xef, 0xe8, 0x56, 0x29, 0x4c, 0xed, 0x11, 0xcb, 0x04, + 0xdf, 0x1f, 0x32, 0xec, 0xf9, 0xe4, 0xc8, 0x0b, 0xf8, 0x23, 0xed, 0x16, 0xf1, + 0x19, 0x17, 0xe3, 0xeb, 0x0e, 0xf3, 0x18, 0xd3, 0x04, 0x19, 0xed, 0xd3, 0x32, + 0x37, 0x0b, 0xba, 0x7f, 0x3d, 0x3e, 0x3c, 0x2d, 0x70, 0xd6, 0x04, 0x07, 0xfb, + 0xf5, 0xe8, 0x24, 0x4c, 0x60, 0x27, 0xe2, 0xd5, 0xe5, 0xf5, 0xcd, 0x15, 0xc4, + 0xd9, 0xeb, 0x08, 0x0f, 0xe5, 0xc2, 0xf1, 0x36, 0xd3, 0x0e, 0x2b, 0xe0, 0xdb, + 0xed, 0xd2, 0x4b, 0xc7, 0x02, 0xce, 0xfa, 0x55, 0x0f, 0x14, 0xf2, 0xf7, 0x1b, + 0x51, 0xeb, 0x31, 0x9f, 0x3e, 0xcb, 0xed, 0xa2, 0xfb, 0x16, 0xea, 0x33, 0xf3, + 0xd2, 0xf9, 0x4c, 0xdf, 0x28, 0x06, 0x47, 0xa5, 0x1e, 0x17, 0x30, 0xd7, 0x07, + 0x07, 0x02, 0xf0, 0xdf, 0x33, 0xf4, 0x1c, 0x2d, 0xe3, 0xd7, 0x06, 0xed, 0x12, + 0x01, 0xee, 0xc4, 0xba, 0xbf, 0xe2, 0xc6, 0x19, 0x04, 0x0c, 0x47, 0xf3, 0xf5, + 0xe0, 0x7f, 0xd7, 0x2a, 0x0d, 0xee, 0xb7, 0xe5, 0xd3, 0xc2, 0x1b, 0x0b, 0x0e, + 0x05, 0xc7, 0x30, 0x42, 0x02, 0x5b, 0x03, 0xd0, 0xe0, 0xd0, 0xf9, 0xe5, 0xf8, + 0xe1, 0x0f, 0x3e, 0xfa, 0x08, 0x0c, 0xe6, 0x03, 0xdd, 0x11, 0x1e, 0x0b, 0x11, + 0x41, 0x10, 0x15, 0xa3, 0xfb, 0xf3, 0xe1, 0xc3, 0x05, 0x23, 0xef, 0x17, 0x17, + 0x0b, 0x12, 0x19, 0xf3, 0x2f, 0xda, 0xec, 0xed, 0xf5, 0xc7, 0xe8, 0x4d, 0x0b, + 0x6d, 0x07, 0xf8, 0x00, 0x1c, 0x2c, 0xf7, 0x1a, 0xff, 0xdc, 0xf0, 0x42, 0x00, + 0xee, 0xd0, 0xeb, 0xfe, 0x13, 0xee, 0x4a, 0xf1, 0xe0, 0x07, 0x25, 0xda, 0xd8, + 0x12, 0xf0, 0xff, 0xe2, 0xdc, 0x22, 0xb3, 0x7f, 0x18, 0x05, 0xec, 0xe5, 0xe9, + 0xd8, 0xcd, 0x13, 0xd3, 0x0d, 0x01, 0xd7, 0x52, 0xfa, 0xc0, 0xf1, 0xf1, 0xe3, + 0xef, 0x03, 0x19, 0x09, 0xd9, 0xfc, 0x0b, 0xce, 0xdb, 0x21, 0x2e, 0x10, 0xf1, + 0xe8, 0xd8, 0xf3, 0x1a, 0x41, 0xd2, 0x0c, 0xeb, 0x21, 0x39, 0x14, 0x00, 0xfa, + 0xf2, 0x3a, 0x0d, 0xf9, 0x02, 0xb3, 0x04, 0x47, 0xfc, 0xd5, 0x2b, 0xe0, 0x1a, + 0xd2, 0x25, 0xf9, 0xcc, 0x1f, 0x07, 0xe5, 0x28, 0xe4, 0xfb, 0x06, 0x0e, 0x03, + 0x08, 0xfb, 0xf8, 0xed, 0x01, 0xc5, 0xea, 0x1f, 0x03, 0x19, 0x00, 0x11, 0x62, + 0x23, 0x4e, 0xff, 0x06, 0xc2, 0x36, 0x0f, 0xef, 0xee, 0x24, 0x49, 0xf4, 0xef, + 0xd3, 0x05, 0xd2, 0x10, 0x06, 0xdb, 0x3e, 0x1b, 0x03, 0x01, 0xfe, 0x13, 0x0c, + 0x01, 0x7a, 0x23, 0xf5, 0x60, 0x34, 0xc2, 0xfa, 0xfa, 0x0c, 0x44, 0x02, 0x2d, + 0xe0, 0x14, 0xe8, 0x2d, 0xd8, 0xee, 0xde, 0x1e, 0x06, 0xf4, 0xf5, 0xef, 0xf5, + 0xee, 0xfc, 0xf4, 0xde, 0xb7, 0xed, 0x2d, 0x11, 0x0f, 0x31, 0x02, 0xb8, 0xb7, + 0x7f, 0xe6, 0x2b, 0xec, 0x44, 0x0f, 0x01, 0xe8, 0x12, 0xf8, 0x0a, 0xcb, 0x3a, + 0x04, 0x03, 0x13, 0xeb, 0xf2, 0x1f, 0x35, 0xf6, 0xfa, 0x0f, 0x37, 0x26, 0xd2, + 0xf3, 0x24, 0xeb, 0x03, 0xfa, 0x14, 0xeb, 0x22, 0x38, 0xe7, 0xed, 0xd3, 0xe0, + 0xfa, 0x07, 0x22, 0x11, 0xdb, 0x0c, 0xf4, 0x22, 0xec, 0x32, 0x06, 0xfd, 0xe4, + 0x42, 0x01, 0xfa, 0x25, 0x1a, 0x0c, 0x04, 0x19, 0x33, 0xdf, 0x01, 0xe3, 0xd4, + 0xe1, 0x1b, 0x2c, 0x18, 0xdf, 0xbc, 0xcc, 0x06, 0xdf, 0x7c, 0x12, 0x18, 0xd6, + 0xc7, 0xee, 0xd0, 0x0e, 0xea, 0x06, 0xb1, 0xda, 0x1a, 0xf9, 0x94, 0xe6, 0xfe, + 0x05, 0xd0, 0xe3, 0xcc, 0xbb, 0xf2, 0xca, 0xe6, 0x27, 0xf8, 0xd7, 0x04, 0xe2, + 0xbc, 0x7f, 0xe3, 0xfe, 0x5a, 0xea, 0xc6, 0xc3, 0xe4, 0xc3, 0xf0, 0x16, 0xe5, + 0xf2, 0x19, 0xeb, 0x0c, 0x06, 0xaf, 0xf3, 0x06, 0x16, 0xe5, 0xf9, 0xd2, 0x08, + 0x10, 0x0b, 0x18, 0x03, 0xec, 0xd7, 0x27, 0xe0, 0xc6, 0xea, 0x40, 0x08, 0x3e, + 0x46, 0xa8, 0xff, 0x4b, 0x65, 0x70, 0xfc, 0x3d, 0x03, 0x04, 0x67, 0x08, 0x19, + 0xdc, 0xe1, 0xeb, 0x11, 0x12, 0xf2, 0x32, 0xf1, 0xfb, 0xdb, 0x0c, 0xd2, 0x16, + 0x85, 0xcf, 0xef, 0x2b, 0x09, 0xdf, 0x75, 0xce, 0x14, 0x73, 0xeb, 0xe8, 0x47, + 0xee, 0x2b, 0x11, 0xab, 0x3b, 0xef, 0x37, 0xed, 0x10, 0x06, 0xb2, 0xdd, 0xa3, + 0xb6, 0x3f, 0xfc, 0x34, 0x5e, 0x3d, 0xe9, 0x43, 0xf9, 0x03, 0x21, 0xee, 0xd0, + 0xfb, 0xf5, 0x23, 0x06, 0x45, 0xfc, 0xff, 0xc9, 0x25, 0xa2, 0x6d, 0xfb, 0xdc, + 0x11, 0x25, 0x07, 0x18, 0x58, 0x2e, 0x1d, 0xfa, 0x00, 0xe2, 0x28, 0xf8, 0xdb, + 0xc4, 0x12, 0xeb, 0xbf, 0xed, 0xc8, 0xf3, 0xdf, 0xa9, 0xc0, 0xf1, 0x10, 0xce, + 0x01, 0xc5, 0x0c, 0xd2, 0x0f, 0xf9, 0xb8, 0x1f, 0x3d, 0x52, 0x1c, 0x4a, 0xee, + 0x12, 0xe4, 0xef, 0xd7, 0xe0, 0x23, 0xd7, 0x47, 0x05, 0xf6, 0xc3, 0xfd, 0xfc, + 0xf7, 0x7f, 0xfa, 0x1d, 0xe6, 0x04, 0xdd, 0x02, 0xe2, 0x81, 0xca, 0x0f, 0xd0, + 0x2a, 0xca, 0xe7, 0x21, 0xf9, 0x1a, 0x57, 0x1d, 0x1b, 0xf8, 0x2f, 0x2d, 0xba, + 0xc8, 0xc7, 0xf1, 0x22, 0x20, 0x10, 0x30, 0x3e, 0xfd, 0x33, 0x16, 0x13, 0xcf, + 0xe6, 0x21, 0x1b, 0xe3, 0xf0, 0x07, 0x5c, 0xfe, 0x3a, 0x3d, 0x20, 0xbc, 0x44, + 0xf8, 0x09, 0xe8, 0xf8, 0xf5, 0x3b, 0x12, 0xea, 0x1c, 0xf2, 0x13, 0x5a, 0xf0, + 0xfb, 0x18, 0x13, 0xc8, 0x21, 0x31, 0xe7, 0x4b, 0x25, 0xb7, 0x5b, 0x52, 0x18, + 0x2a, 0xd9, 0x17, 0x17, 0x29, 0x33, 0x19, 0x0f, 0x0c, 0xd3, 0x27, 0xf3, 0x27, + 0xf7, 0xe7, 0xdb, 0x18, 0x05, 0x04, 0x17, 0x36, 0x28, 0xf0, 0xe8, 0xcc, 0xef, + 0x22, 0x44, 0xe4, 0x4c, 0x15, 0xfe, 0x02, 0x4b, 0xd9, 0x33, 0x1f, 0xe8, 0xd2, + 0x26, 0x29, 0x22, 0xfe, 0x7f, 0x0e, 0x32, 0xfc, 0x15, 0xf5, 0x1c, 0x10, 0x4b, + 0x04, 0x10, 0x3a, 0xed, 0x24, 0x31, 0xf6, 0x1a, 0x15, 0x48, 0x59, 0x0f, 0x01, + 0x08, 0xed, 0x33, 0x0a, 0x1f, 0x15, 0xfd, 0xe4, 0xde, 0xed, 0xfe, 0x12, 0x14, + 0x0b, 0x18, 0x09, 0x47, 0x11, 0x0a, 0xd9, 0x01, 0xb6, 0xf9, 0x10, 0x23, 0x00, + 0x70, 0x01, 0xfc, 0xe6, 0xec, 0xf7, 0xad, 0x19, 0x47, 0x3d, 0x27, 0x06, 0xe6, + 0xf7, 0x02, 0x1a, 0x16, 0xd4, 0x36, 0x03, 0xcf, 0xe7, 0x4a, 0x0f, 0xd5, 0x0d, + 0x02, 0x25, 0x96, 0x3f, 0x0b, 0xe6, 0xcd, 0x2f, 0x40, 0xce, 0x02, 0xdf, 0xe6, + 0xc0, 0x0e, 0x1e, 0x3e, 0x10, 0x39, 0xed, 0xef, 0x32, 0xed, 0xb3, 0xe2, 0xfa, + 0xd0, 0xf9, 0x0b, 0xf8, 0xfc, 0x07, 0x65, 0x18, 0x0a, 0x49, 0x38, 0x00, 0xe8, + 0x34, 0xe4, 0x06, 0x0d, 0xab, 0xa7, 0xd2, 0x14, 0xfd, 0xdd, 0x06, 0x10, 0x2b, + 0xd2, 0x52, 0x7f, 0xfc, 0xeb, 0xdf, 0x29, 0xc1, 0xf0, 0xdb, 0x05, 0xe2, 0xdc, + 0x24, 0x0e, 0xe3, 0x16, 0x3d, 0xf3, 0xee, 0x0e, 0xf8, 0xea, 0xd1, 0xea, 0x26, + 0x74, 0x1a, 0x3d, 0x1c, 0xd4, 0xb0, 0xf4, 0x09, 0xf5, 0xe7, 0x03, 0xf6, 0xcb, + 0xe5, 0xe6, 0xbf, 0x1d, 0xd1, 0xfd, 0x08, 0xd9, 0x3b, 0xfb, 0xff, 0x1a, 0x00, + 0x0a, 0x00, 0x7a, 0x3b, 0xf1, 0x3a, 0x01, 0xa7, 0xf7, 0x08, 0x22, 0xff, 0xf9, + 0x00, 0xe5, 0x13, 0xf0, 0x35, 0x07, 0x18, 0x50, 0x81, 0x0d, 0x45, 0x08, 0xb0, + 0x2b, 0xdc, 0xc0, 0x34, 0x03, 0x04, 0x6e, 0x38, 0x9d, 0xf5, 0x1a, 0x3c, 0xf0, + 0x26, 0x36, 0x15, 0xf2, 0x0d, 0xd6, 0xf9, 0x39, 0x2d, 0x04, 0xe9, 0xea, 0x14, + 0x15, 0xd2, 0x3b, 0x14, 0x69, 0xee, 0x1b, 0xe4, 0x23, 0x4f, 0x1f, 0xd6, 0x36, + 0xf1, 0xee, 0xc7, 0x2c, 0xda, 0xc1, 0x03, 0xd5, 0xb3, 0x15, 0x19, 0x59, 0xed, + 0x51, 0x05, 0x0b, 0xf7, 0xf9, 0x05, 0x08, 0xe4, 0x14, 0x31, 0x06, 0x22, 0x10, + 0x14, 0x44, 0xc1, 0xdc, 0x1a, 0xc0, 0x0a, 0x0a, 0x06, 0x19, 0xfb, 0x08, 0x08, + 0x05, 0x34, 0xfb, 0xe8, 0xfb, 0x06, 0x20, 0xee, 0x3a, 0x0f, 0x10, 0xed, 0x2b, + 0x14, 0x00, 0xd7, 0xfb, 0xfb, 0xd8, 0x04, 0xe2, 0xfc, 0xfb, 0xff, 0xeb, 0xf3, + 0x13, 0x1b, 0xfa, 0x09, 0x18, 0xb3, 0xf5, 0xf0, 0x14, 0x04, 0xff, 0xea, 0xef, + 0x03, 0xf2, 0x1c, 0xfa, 0xfb, 0x23, 0xce, 0xf6, 0xfd, 0x18, 0xe5, 0x25, 0xf5, + 0xee, 0x11, 0x05, 0xf8, 0x20, 0x04, 0x07, 0xef, 0x02, 0x22, 0xed, 0x04, 0x13, + 0xfb, 0x0a, 0xee, 0x07, 0xf4, 0x09, 0x18, 0xf6, 0xe9, 0x03, 0x05, 0xfc, 0xe5, + 0xd3, 0x04, 0x26, 0x02, 0x13, 0x25, 0x1e, 0xf8, 0x0d, 0xf9, 0x29, 0xea, 0xeb, + 0xf2, 0x33, 0xd2, 0xeb, 0x0e, 0x15, 0xee, 0x08, 0x0f, 0x3d, 0x1b, 0x7f, 0x03, + 0x05, 0xee, 0x23, 0xfa, 0xfb, 0x17, 0x06, 0x1f, 0x23, 0x06, 0x0e, 0xf5, 0x1a, + 0xfd, 0xfe, 0x08, 0x0c, 0xfc, 0x17, 0x19, 0x0f, 0xed, 0x06, 0x07, 0xde, 0x27, + 0xec, 0x00, 0xe8, 0x2d, 0x12, 0x13, 0xfd, 0x12, 0x09, 0xf2, 0x04, 0xd4, 0x0c, + 0xf9, 0x19, 0xca, 0xe8, 0x1f, 0xe7, 0x21, 0xe7, 0x09, 0x05, 0xf5, 0x1d, 0x00, + 0xfd, 0xec, 0x01, 0xe6, 0xf3, 0xf6, 0x26, 0xb6, 0xe9, 0xec, 0xf9, 0xee, 0xf1, + 0xe6, 0x01, 0xda, 0xda, 0xfd, 0xf6, 0xdb, 0x09, 0xf2, 0x0a, 0x1d, 0xef, 0xf6, + 0xdc, 0x27, 0x00, 0x09, 0xb8, 0xb7, 0xf5, 0xba, 0xdf, 0x18, 0xfd, 0xba, 0x0f, + 0x42, 0xdb, 0xff, 0xf9, 0xfc, 0x3a, 0x57, 0x06, 0x00, 0xfb, 0x1d, 0x81, 0x13, + 0x50, 0x32, 0x2c, 0x43, 0x09, 0x02, 0x17, 0x19, 0x0c, 0x1d, 0x28, 0xe9, 0xb2, + 0x32, 0xfb, 0xf4, 0x19, 0xfe, 0xd5, 0xe9, 0x20, 0xbd, 0x07, 0xd0, 0xbc, 0xa9, + 0x06, 0x03, 0xc2, 0xe2, 0xca, 0x27, 0xdb, 0xe5, 0x23, 0x3d, 0x13, 0xf6, 0xec, + 0xc6, 0x06, 0x0e, 0x21, 0x24, 0xef, 0xed, 0xad, 0x35, 0xc7, 0x1c, 0x15, 0x12, + 0x9e, 0xb8, 0xf0, 0xfb, 0x07, 0xe7, 0x07, 0x21, 0xfd, 0x10, 0x23, 0x15, 0x10, + 0x02, 0x28, 0xf2, 0xb0, 0x0d, 0xe1, 0xa9, 0xe7, 0xf9, 0x60, 0x28, 0x77, 0xb4, + 0xfe, 0xf5, 0x16, 0xf9, 0xed, 0xba, 0xd2, 0x46, 0x00, 0xfc, 0xef, 0x71, 0xca, + 0xe9, 0x0d, 0xf3, 0x1f, 0xed, 0x1a, 0x8c, 0xcc, 0x13, 0x2c, 0xb4, 0x4b, 0x0d, + 0xca, 0x3c, 0x38, 0xf2, 0xe3, 0x3b, 0x05, 0xf4, 0x1b, 0xd6, 0xef, 0xd5, 0x22, + 0x40, 0x0b, 0xf2, 0xeb, 0x24, 0xde, 0xc9, 0x0a, 0x22, 0xe8, 0xf6, 0x1a, 0x48, + 0x07, 0xfd, 0xe0, 0x33, 0x44, 0xd9, 0x3e, 0x10, 0xf8, 0x81, 0x0f, 0xc8, 0x09, + 0xe2, 0x1b, 0x97, 0xe5, 0xe1, 0x6a, 0xea, 0xce, 0x21, 0xed, 0xef, 0xd7, 0x08, + 0xf5, 0x46, 0xf5, 0x26, 0x17, 0xd2, 0xf2, 0x11, 0xfd, 0xec, 0x23, 0xfb, 0x3b, + 0xa3, 0x51, 0x03, 0x0a, 0x02, 0x05, 0x02, 0xe2, 0xd9, 0x31, 0x77, 0x20, 0x47, + 0xe5, 0xfa, 0x00, 0xfa, 0x21, 0xd8, 0x67, 0x27, 0x2f, 0x06, 0x5c, 0x02, 0x03, + 0x9d, 0x3f, 0x19, 0xd8, 0xde, 0x04, 0x37, 0xcb, 0x14, 0x15, 0x33, 0x08, 0x20, + 0x29, 0x4e, 0xc9, 0xe5, 0xf3, 0x5c, 0xba, 0x1e, 0xf9, 0xd9, 0x00, 0xed, 0x29, + 0x27, 0xb2, 0xe2, 0xc1, 0x43, 0x14, 0xf2, 0xcf, 0x00, 0xf6, 0x37, 0x47, 0x28, + 0x06, 0x17, 0x03, 0x0b, 0x22, 0x48, 0x11, 0xb2, 0x44, 0x1f, 0x3e, 0xe4, 0x9f, + 0x69, 0xf5, 0xfb, 0xe7, 0x3a, 0xce, 0x0b, 0xdc, 0xd5, 0x2c, 0xda, 0xbd, 0x50, + 0x1b, 0xb1, 0x50, 0x01, 0xc6, 0x03, 0x01, 0x14, 0x55, 0x27, 0x37, 0xc7, 0x0b, + 0x2c, 0xb1, 0xdb, 0x0e, 0xb9, 0x1c, 0x25, 0x8e, 0x00, 0xf2, 0x10, 0xdc, 0x1b, + 0x40, 0x03, 0x04, 0xd6, 0xff, 0xec, 0x26, 0x09, 0xbd, 0xca, 0xf2, 0xee, 0xeb, + 0x1c, 0xe8, 0xab, 0x81, 0x07, 0x20, 0x15, 0x39, 0xb8, 0x0a, 0xe5, 0xdb, 0xf3, + 0x03, 0xe6, 0x06, 0x07, 0xfc, 0xdf, 0x30, 0x1a, 0x32, 0x0b, 0xd2, 0x22, 0xe0, + 0x9d, 0xae, 0x21, 0x33, 0xc7, 0x7d, 0x38, 0x13, 0xc2, 0xdc, 0x27, 0x09, 0xb5, + 0xfe, 0xfe, 0x1a, 0x29, 0x0c, 0xe0, 0xf7, 0x79, 0xf9, 0x04, 0x30, 0xec, 0x5a, + 0xb5, 0x3a, 0x28, 0xf0, 0xe1, 0x2d, 0xba, 0x1a, 0x3d, 0xdd, 0x50, 0x5d, 0xb9, + 0xd7, 0x57, 0x1e, 0x07, 0xbc, 0x4b, 0xdc, 0xe3, 0xb1, 0xf0, 0xd9, 0xf4, 0x1b, + 0x69, 0xe9, 0xdf, 0xf4, 0xe0, 0xe1, 0xd2, 0xcf, 0xec, 0x01, 0xfa, 0xde, 0x5a, + 0xdd, 0xdf, 0x54, 0xcb, 0xf6, 0x81, 0x46, 0xef, 0x39, 0x0e, 0x1a, 0xe3, 0x0c, + 0x2e, 0x09, 0xe3, 0xd7, 0x04, 0xa0, 0xe7, 0xe1, 0x32, 0xfa, 0x02, 0x00, 0x0d, + 0xef, 0xaa, 0x20, 0xf3, 0xfd, 0xe5, 0xf2, 0xe6, 0x48, 0xc0, 0xfc, 0xf4, 0x34, + 0xfd, 0xd0, 0x28, 0x12, 0xf5, 0x32, 0x13, 0x35, 0xf0, 0xd3, 0xd5, 0x0a, 0xdb, + 0x19, 0x36, 0x4a, 0x50, 0x58, 0xcf, 0x37, 0x1f, 0x3e, 0xda, 0x32, 0xef, 0xcb, + 0x4d, 0xce, 0xfc, 0x2f, 0x19, 0xf1, 0xfe, 0xdb, 0x1d, 0x28, 0x1f, 0xfb, 0x4d, + 0xdd, 0xde, 0xc2, 0x3a, 0x0b, 0xf5, 0xb3, 0xe0, 0x68, 0x33, 0x09, 0xd7, 0x11, + 0xeb, 0x3e, 0xb6, 0x39, 0x2c, 0x1d, 0xfe, 0xd5, 0x30, 0xde, 0xe1, 0xc3, 0x0e, + 0xec, 0x1c, 0x64, 0x32, 0xf4, 0x41, 0x2f, 0xee, 0xcb, 0xfe, 0x31, 0x2e, 0xd1, + 0x9e, 0x89, 0xb2, 0x2d, 0x13, 0x17, 0x24, 0xf9, 0xdf, 0xec, 0x0b, 0x3a, 0x6f, + 0x2c, 0xd1, 0x0f, 0xf7, 0x00, 0xea, 0xc7, 0xf3, 0xe6, 0x6c, 0x2d, 0xb9, 0xc6, + 0x26, 0x7f, 0x25, 0x91, 0x07, 0xce, 0xf1, 0xa8, 0xed, 0x7c, 0x09, 0xc6, 0x01, + 0x4b, 0x0c, 0xdc, 0xd4, 0x69, 0x15, 0x0b, 0xdf, 0xf9, 0x2b, 0x0d, 0x62, 0x0a, + 0xc7, 0xf6, 0x28, 0x14, 0xaa, 0xef, 0xb6, 0xef, 0x26, 0xc0, 0xa4, 0x2b, 0xf3, + 0x15, 0xf2, 0x37, 0x1e, 0xdb, 0xc3, 0x34, 0xb6, 0x34, 0x38, 0xf6, 0xe5, 0xf6, + 0x26, 0xd2, 0xe4, 0x1b, 0x4b, 0x3a, 0xb5, 0x15, 0x2b, 0xeb, 0xb6, 0xba, 0x31, + 0xc4, 0x36, 0xfa, 0xdd, 0xec, 0x60, 0xdd, 0x7f, 0xb5, 0x2e, 0xe8, 0x6c, 0xfc, + 0x23, 0x0d, 0x07, 0xd2, 0x14, 0x62, 0xd2, 0x12, 0x36, 0x03, 0x10, 0xb7, 0xd4, + 0xe7, 0xa9, 0x3b, 0x25, 0xb2, 0xce, 0xd1, 0x9b, 0xc0, 0xe5, 0xdb, 0x1d, 0x24, + 0xb3, 0x5b, 0xec, 0x2b, 0x1e, 0x59, 0x35, 0x54, 0xef, 0xef, 0x20, 0x06, 0x70, + 0x20, 0xc7, 0xc5, 0xb7, 0xee, 0x3b, 0xe5, 0x1d, 0x46, 0xe6, 0xde, 0xfb, 0xf5, + 0xb5, 0x19, 0x34, 0x07, 0xe5, 0xfa, 0x18, 0xfa, 0x13, 0xa9, 0x33, 0xb6, 0xfa, + 0x08, 0xdd, 0x0d, 0x22, 0x8e, 0x57, 0xcd, 0x07, 0xd9, 0xec, 0x48, 0xe0, 0xd5, + 0x04, 0xf8, 0xc6, 0xd2, 0xd7, 0xf8, 0x08, 0xf1, 0x48, 0xac, 0x3e, 0x1f, 0x1d, + 0xe7, 0xc9, 0xc5, 0xd9, 0x38, 0x4a, 0xc6, 0x2d, 0x35, 0x3e, 0x1a, 0x1b, 0xf6, + 0x2d, 0xd1, 0x08, 0xe3, 0xa9, 0xc3, 0x2a, 0x6a, 0x17, 0xfd, 0xd9, 0xdb, 0x23, + 0xda, 0xde, 0x1d, 0x1d, 0x06, 0xf5, 0xaa, 0x85, 0xf3, 0x07, 0x30, 0xfb, 0x04, + 0xde, 0xe3, 0x51, 0xea, 0x0d, 0xfc, 0x17, 0x1e, 0x18, 0xd0, 0xdc, 0x28, 0x00, + 0x16, 0x1d, 0x51, 0x81, 0xd4, 0xc6, 0x22, 0xe0, 0x01, 0x02, 0x15, 0x0f, 0x4a, + 0x1e, 0x1e, 0xc4, 0x10, 0x03, 0xf8, 0x19, 0x0d, 0xbd, 0x16, 0x02, 0x1b, 0xf1, + 0x4a, 0xe5, 0x97, 0x39, 0x15, 0xcf, 0x25, 0xb8, 0xfa, 0xf0, 0x2c, 0x19, 0x17, + 0xd4, 0x03, 0x1c, 0x33, 0xde, 0xf3, 0xdc, 0xe9, 0x0c, 0xe3, 0xeb, 0xd2, 0x22, + 0x98, 0x2b, 0xf4, 0xea, 0xd7, 0x11, 0x15, 0xee, 0xd8, 0xf9, 0x0f, 0xfd, 0xd9, + 0xfc, 0xed, 0xed, 0x3d, 0xe2, 0xdf, 0xef, 0x2e, 0x24, 0xf8, 0x1d, 0xd6, 0x37, + 0x52, 0xd0, 0xa6, 0xea, 0x25, 0x07, 0x7f, 0x47, 0x1c, 0xff, 0x1f, 0x05, 0xfa, + 0x4b, 0x1e, 0x44, 0xee, 0x0e, 0x0e, 0xf5, 0xec, 0x1d, 0x10, 0x28, 0xe0, 0x28, + 0xe5, 0xe5, 0x38, 0x02, 0x1b, 0xb0, 0x10, 0xd8, 0x15, 0x2b, 0x00, 0xfb, 0xe2, + 0x26, 0x3d, 0x35, 0xeb, 0x13, 0x3a, 0x13, 0x02, 0x25, 0x39, 0x33, 0xe7, 0x06, + 0x1f, 0xdf, 0x06, 0x2e, 0xf8, 0x25, 0xe5, 0x33, 0xd5, 0xea, 0x17, 0x44, 0xb5, + 0xe3, 0xe6, 0xec, 0x67, 0xeb, 0xcd, 0xcf, 0x05, 0x45, 0x15, 0xec, 0xf8, 0x20, + 0xf9, 0x0f, 0x55, 0xe1, 0xc3, 0x2b, 0xef, 0xc0, 0x0f, 0xf4, 0x84, 0x0b, 0x04, + 0x09, 0xeb, 0xcc, 0xff, 0x40, 0xea, 0x03, 0x5f, 0xeb, 0xee, 0x44, 0xfa, 0xc3, + 0xef, 0x42, 0x09, 0xb4, 0xde, 0xde, 0x30, 0x46, 0x13, 0x45, 0xf7, 0x0a, 0x26, + 0xfc, 0xba, 0x26, 0xfb, 0x3e, 0x11, 0x1e, 0xfd, 0xc5, 0x54, 0xc1, 0xec, 0x37, + 0x08, 0x51, 0xf5, 0x5c, 0xcb, 0x1b, 0xb6, 0x6f, 0x02, 0x1b, 0xdf, 0x2e, 0xf5, + 0x1d, 0x18, 0xe7, 0x23, 0x0c, 0xd0, 0xb8, 0x04, 0xf5, 0x0d, 0x0a, 0x03, 0x3d, + 0x18, 0xc2, 0x3e, 0x2a, 0x10, 0xf1, 0x1c, 0x43, 0xdb, 0x2f, 0x18, 0x07, 0xfd, + 0x1a, 0xf6, 0x01, 0xf1, 0x03, 0xda, 0x1c, 0x69, 0x36, 0x01, 0x05, 0x2a, 0xf3, + 0x34, 0x0f, 0x1f, 0x07, 0x47, 0x40, 0xc3, 0x55, 0x08, 0x14, 0x44, 0x27, 0xeb, + 0x09, 0x05, 0x22, 0x0d, 0x5a, 0x66, 0x2d, 0x04, 0xa5, 0x23, 0x13, 0xf0, 0xe6, + 0xc0, 0x02, 0x7f, 0x1c, 0x54, 0x5a, 0x51, 0xd8, 0xdb, 0xf3, 0x01, 0x26, 0xe9, + 0xe6, 0xc6, 0x18, 0x20, 0x2a, 0x13, 0xfe, 0x48, 0x22, 0xf4, 0x4b, 0x07, 0x27, + 0xec, 0xd7, 0x0f, 0x4c, 0xd9, 0xff, 0xe1, 0x58, 0xcc, 0xbd, 0x04, 0x57, 0x1d, + 0x58, 0x17, 0xf2, 0xea, 0xc8, 0x41, 0x1b, 0x69, 0x41, 0x3a, 0x2c, 0x35, 0x3a, + 0xef, 0xe2, 0xeb, 0x07, 0xc2, 0x46, 0xf3, 0x06, 0x27, 0x0d, 0xfe, 0xc9, 0x0b, + 0x03, 0xff, 0x02, 0x03, 0xf1, 0xc7, 0x10, 0xe9, 0xc7, 0xe1, 0x03, 0x55, 0x7f, + 0xe1, 0xc3, 0x1b, 0x15, 0x05, 0xa2, 0x06, 0xe1, 0xf1, 0xf4, 0xcf, 0x40, 0x07, + 0x10, 0x44, 0x13, 0xf1, 0x51, 0xfd, 0x12, 0xfd, 0x24, 0xe2, 0xdb, 0x06, 0x34, + 0xd2, 0x2c, 0xd0, 0x1b, 0xc6, 0x1a, 0x0f, 0xce, 0x07, 0xf8, 0xe3, 0x28, 0xd8, + 0x11, 0x59, 0xf1, 0x02, 0x19, 0x2a, 0xec, 0xd5, 0xff, 0x59, 0xd3, 0x01, 0x19, + 0xf9, 0xfa, 0x15, 0xdc, 0x2a, 0x27, 0xc9, 0x00, 0xdc, 0x1c, 0x06, 0xfc, 0xec, + 0x37, 0x0b, 0xcd, 0xe8, 0xf3, 0xf1, 0x24, 0xcc, 0x32, 0x04, 0x05, 0x01, 0x0e, + 0x24, 0x03, 0xf1, 0x4a, 0xe9, 0x0e, 0x2c, 0x47, 0xee, 0x94, 0x25, 0x03, 0xfc, + 0xde, 0xfb, 0xbc, 0x20, 0xd2, 0xfb, 0x27, 0xdb, 0xf7, 0xfe, 0x0b, 0x11, 0x04, + 0x2b, 0xf4, 0x35, 0xef, 0x39, 0x0a, 0x0d, 0xcf, 0x0c, 0x06, 0x34, 0xe1, 0x1a, + 0x01, 0x0d, 0x7f, 0x1d, 0x08, 0x0a, 0x46, 0xf8, 0xdd, 0x1c, 0x2c, 0xda, 0x37, + 0x08, 0x40, 0xdd, 0x06, 0x21, 0xc6, 0xeb, 0x09, 0x07, 0x26, 0x4f, 0x34, 0x28, + 0x2e, 0x17, 0xe2, 0x3b, 0xed, 0xd6, 0xbc, 0xf1, 0x44, 0x1b, 0xe8, 0xe7, 0x0e, + 0xeb, 0xe1, 0x24, 0x12, 0x11, 0xed, 0x32, 0xcc, 0xec, 0x12, 0x19, 0xfc, 0x18, + 0x01, 0x2d, 0xe5, 0x12, 0xb0, 0x0d, 0xf5, 0xe3, 0xf7, 0x35, 0xe6, 0xf1, 0xf3, + 0x26, 0x02, 0xf0, 0x02, 0x33, 0x55, 0xe6, 0x28, 0x3a, 0x0b, 0xf8, 0x0f, 0xf9, + 0x1d, 0xce, 0xfd, 0xe1, 0xda, 0xfb, 0x16, 0x04, 0x3a, 0xc8, 0x1b, 0x26, 0x0d, + 0x3e, 0xd8, 0x1c, 0x34, 0x0c, 0xf3, 0x0d, 0x5d, 0xf0, 0xfa, 0x05, 0x13, 0xec, + 0x0f, 0x05, 0x1c, 0xed, 0xeb, 0x0c, 0xef, 0xfd, 0x10, 0x22, 0xfb, 0xee, 0x1e, + 0x3c, 0xfa, 0x32, 0x32, 0x04, 0xea, 0x18, 0xf3, 0x08, 0x07, 0x08, 0x2c, 0x44, + 0x40, 0x10, 0x20, 0x13, 0x7f, 0x1a, 0xf6, 0x11, 0x45, 0x16, 0xda, 0x0f, 0x12, + 0xf4, 0x09, 0x0c, 0xf6, 0x12, 0xfb, 0xed, 0x18, 0x1d, 0x01, 0xe5, 0x1d, 0xe9, + 0xf9, 0xeb, 0xfe, 0x00, 0x00, 0x06, 0x14, 0x11, 0xf1, 0x05, 0x14, 0x05, 0xfb, + 0x03, 0xf4, 0x0e, 0xf5, 0xf9, 0xf7, 0xf8, 0xfc, 0xf0, 0x05, 0x0a, 0xe5, 0x1f, + 0x03, 0xf3, 0xf9, 0x1b, 0xe1, 0x07, 0x28, 0x07, 0xca, 0x09, 0xed, 0x09, 0xf8, + 0xf8, 0xf7, 0xfa, 0x09, 0x1e, 0x09, 0x21, 0xf7, 0xfb, 0x21, 0xf1, 0x0c, 0xf8, + 0xf7, 0x04, 0x0f, 0x00, 0xe4, 0xee, 0xfd, 0xf0, 0xee, 0xf2, 0x04, 0x2b, 0x30, + 0xf3, 0x01, 0x0a, 0xe9, 0xfe, 0x1d, 0x00, 0xf5, 0x05, 0x10, 0xda, 0x12, 0x3a, + 0x13, 0x00, 0xf8, 0x07, 0xfe, 0x03, 0xd6, 0xf6, 0x0a, 0xfa, 0x51, 0xfc, 0x1c, + 0xcb, 0xfa, 0xec, 0xe0, 0x1c, 0x1e, 0xe0, 0x00, 0xfb, 0x37, 0x5c, 0x0b, 0xc5, + 0xf7, 0xe5, 0x20, 0xe5, 0x1a, 0x56, 0x2e, 0xf7, 0xd0, 0x71, 0x7f, 0xc4, 0x38, + 0x1a, 0xd0, 0xc6, 0x5f, 0x2c, 0xc5, 0x26, 0x1b, 0x24, 0xfd, 0xe3, 0x00, 0x40, + 0xe3, 0x20, 0x10, 0x25, 0xec, 0xfc, 0x07, 0xaf, 0xfd, 0x20, 0x9e, 0x0a, 0x4a, + 0xa2, 0xc4, 0x68, 0xdf, 0x28, 0xf3, 0x15, 0x0a, 0xc3, 0x44, 0xc3, 0xe0, 0xce, + 0xb9, 0x2c, 0x2a, 0xeb, 0x1b, 0x75, 0x56, 0x1d, 0xf6, 0xbd, 0x36, 0xa9, 0x08, + 0x67, 0x1a, 0xff, 0x1e, 0xdd, 0x05, 0xb3, 0xfd, 0xc2, 0x0c, 0xe3, 0xe5, 0xe3, + 0xda, 0xdc, 0xd6, 0x13, 0x62, 0x00, 0x31, 0xc6, 0x0c, 0x8e, 0xfa, 0x5c, 0xec, + 0xd8, 0x40, 0xbd, 0xdc, 0xbf, 0x0e, 0xc8, 0x3f, 0xc7, 0x15, 0x10, 0x55, 0xe2, + 0xf7, 0xc3, 0x39, 0x42, 0x1f, 0x08, 0x0f, 0x40, 0xf4, 0xd3, 0x07, 0x15, 0xd4, + 0x5c, 0xfe, 0xe9, 0xda, 0x59, 0x1f, 0xdd, 0x35, 0x5a, 0x9f, 0x04, 0x32, 0xe0, + 0x13, 0xcb, 0xe6, 0xe6, 0xb5, 0x1b, 0x12, 0xcb, 0xdc, 0xc7, 0x1d, 0x0f, 0xf6, + 0x48, 0xe8, 0x16, 0xdb, 0xfe, 0x1a, 0xe7, 0x0f, 0x27, 0xf5, 0x3c, 0xe6, 0xd8, + 0x0f, 0x06, 0x49, 0x09, 0xe8, 0x21, 0xf8, 0x17, 0x06, 0x22, 0x14, 0x50, 0x06, + 0x67, 0xe1, 0xc5, 0xa6, 0xca, 0x04, 0xf4, 0x22, 0xf5, 0xd9, 0xff, 0xf3, 0x67, + 0xef, 0x48, 0xf5, 0x57, 0xcd, 0xb1, 0xf7, 0x09, 0xfb, 0x30, 0x24, 0x10, 0x0a, + 0x3d, 0x0f, 0x15, 0x24, 0x35, 0x0e, 0x10, 0xeb, 0x48, 0xf8, 0x1b, 0xcd, 0x14, + 0xd2, 0x2d, 0x01, 0xe9, 0x51, 0x07, 0xe4, 0x46, 0xff, 0x2d, 0x7f, 0xeb, 0x18, + 0x1b, 0x4f, 0x0e, 0x27, 0x03, 0xdb, 0x42, 0xc1, 0x3c, 0x3b, 0x05, 0xd7, 0x29, + 0x16, 0xec, 0x5a, 0xa4, 0x04, 0xa0, 0x04, 0x1d, 0x1a, 0x08, 0x4a, 0x3b, 0x0d, + 0xf5, 0xf2, 0xdd, 0xd1, 0x34, 0xe9, 0x18, 0xf5, 0x0c, 0xfe, 0x39, 0xd4, 0x41, + 0xeb, 0x09, 0xdb, 0x02, 0x29, 0x35, 0xe9, 0x07, 0xe3, 0xfb, 0xe3, 0xef, 0x0d, + 0xd4, 0x33, 0xfa, 0x1b, 0xe1, 0x13, 0xfc, 0xf8, 0x0b, 0x00, 0xff, 0xee, 0xc8, + 0xdc, 0x31, 0x31, 0x41, 0xe5, 0xff, 0xef, 0x14, 0x4f, 0xee, 0x01, 0xe7, 0xf9, + 0xe7, 0xf1, 0xef, 0x16, 0xfa, 0x00, 0x07, 0xee, 0xf0, 0x1d, 0xd3, 0x1d, 0x04, + 0xf7, 0x7f, 0xbc, 0xf7, 0xd6, 0xfb, 0xd5, 0xe7, 0x31, 0x12, 0xf4, 0x13, 0xe1, + 0xea, 0xfc, 0xdf, 0x15, 0x45, 0xcf, 0xe3, 0x06, 0xed, 0x07, 0xf4, 0x04, 0x1b, + 0xe3, 0xf3, 0x1d, 0x11, 0xf1, 0xf6, 0xf6, 0xfb, 0x24, 0x32, 0x45, 0xf1, 0xeb, + 0xeb, 0x19, 0x26, 0xc0, 0x10, 0x12, 0x04, 0x26, 0x55, 0xe6, 0x25, 0xe1, 0x04, + 0x0e, 0xf1, 0x45, 0x00, 0xda, 0xc1, 0xbb, 0x65, 0x0e, 0x20, 0x18, 0xe3, 0xde, + 0xf3, 0x1b, 0xd1, 0x11, 0xc8, 0xe0, 0xed, 0x04, 0xda, 0xfc, 0x07, 0xe2, 0xe2, + 0xd5, 0xeb, 0xbb, 0xe0, 0xfc, 0x12, 0xf7, 0x1d, 0x16, 0x3d, 0xe9, 0x10, 0x53, + 0x03, 0x02, 0xe7, 0xd4, 0xfc, 0x7f, 0x39, 0x24, 0x2f, 0x22, 0xd8, 0x16, 0xf1, + 0xec, 0xfe, 0x20, 0xf4, 0xdd, 0x0c, 0x04, 0x07, 0x02, 0xb8, 0x0d, 0x03, 0x58, + 0x24, 0x21, 0xd1, 0x28, 0x35, 0xfd, 0x15, 0x05, 0x08, 0xdd, 0x10, 0x0a, 0xdb, + 0x58, 0x06, 0x31, 0x07, 0xfe, 0x22, 0xd4, 0x4b, 0xfe, 0x04, 0xf6, 0x06, 0x15, + 0x3f, 0x24, 0x0b, 0x12, 0x0e, 0x11, 0x10, 0x05, 0xee, 0x14, 0x06, 0xfc, 0xda, + 0x21, 0x22, 0x48, 0xec, 0xff, 0xb5, 0xee, 0xc3, 0xec, 0xbe, 0x0f, 0xfa, 0x23, + 0x11, 0x2f, 0x04, 0xf0, 0x23, 0x0c, 0x14, 0x5e, 0xe2, 0x02, 0xd9, 0x2c, 0xf4, + 0xe7, 0xdd, 0xef, 0xf3, 0x0f, 0x40, 0x35, 0x26, 0x0a, 0xe6, 0x81, 0x23, 0x18, + 0x4d, 0x18, 0x48, 0x0c, 0xf7, 0xf9, 0x2a, 0x5c, 0x17, 0x4d, 0xff, 0xe7, 0xfa, + 0x47, 0xeb, 0xda, 0x0b, 0x09, 0xe2, 0x22, 0x0b, 0xfb, 0x41, 0x20, 0xe1, 0xee, + 0x14, 0x18, 0x1a, 0x4b, 0x3b, 0x1b, 0xf0, 0x13, 0xfb, 0xf0, 0x10, 0x11, 0x13, + 0xee, 0xea, 0x0e, 0x08, 0xde, 0x0f, 0xe9, 0xfa, 0x0e, 0x27, 0xfc, 0xf5, 0x4a, + 0x36, 0x1f, 0x5b, 0x20, 0xf8, 0x10, 0x4f, 0xb4, 0x17, 0x19, 0x26, 0xdf, 0xf3, + 0x0c, 0x6d, 0x24, 0x2b, 0xf4, 0xed, 0x0f, 0x12, 0xe8, 0x0e, 0x1d, 0x12, 0xf8, + 0x08, 0xf1, 0x12, 0x14, 0x58, 0xd5, 0xf4, 0x05, 0x0a, 0xfe, 0xfe, 0x3a, 0x0c, + 0x2d, 0x09, 0xbb, 0x0f, 0x5c, 0x05, 0x33, 0x25, 0x3f, 0x22, 0xe9, 0xef, 0x0b, + 0xf3, 0xf9, 0xf6, 0x01, 0x01, 0xc6, 0x2b, 0x49, 0xac, 0x4e, 0x05, 0x2e, 0x09, + 0x28, 0xb4, 0x26, 0xfe, 0x3a, 0x28, 0xfa, 0xf5, 0x0e, 0x35, 0x11, 0x6a, 0x52, + 0x12, 0x8e, 0x02, 0x3e, 0xec, 0x3f, 0x31, 0x31, 0x3a, 0x9e, 0xe6, 0x5c, 0x00, + 0xbb, 0x00, 0xd7, 0xda, 0x41, 0x19, 0xaa, 0xd9, 0xcd, 0xe7, 0x08, 0xb2, 0xe0, + 0x09, 0x25, 0x46, 0x5d, 0x05, 0x36, 0x20, 0xdb, 0xf6, 0x24, 0xe4, 0x1f, 0x21, + 0x00, 0x26, 0x22, 0x28, 0x52, 0x13, 0x14, 0xe7, 0xe0, 0x17, 0x33, 0xe8, 0x0c, + 0x5d, 0x33, 0xdc, 0xb6, 0x10, 0x0f, 0xb0, 0xe3, 0xae, 0xf6, 0x39, 0xa9, 0x52, + 0x25, 0xf8, 0xc9, 0xf2, 0x2f, 0xf1, 0xe8, 0x44, 0x2e, 0x08, 0xda, 0x35, 0x46, + 0x0f, 0x02, 0x7f, 0xfe, 0xba, 0x04, 0xe8, 0x74, 0x00, 0xe1, 0xe8, 0x2f, 0xee, + 0xe2, 0x27, 0x59, 0x3b, 0x38, 0x33, 0x02, 0x01, 0x0f, 0xb6, 0x11, 0x18, 0x05, + 0x0c, 0xfb, 0x53, 0xeb, 0x0f, 0x18, 0x2b, 0xda, 0x14, 0xe3, 0x5a, 0x0d, 0xff, + 0xef, 0xff, 0xf3, 0x13, 0xdb, 0x28, 0x08, 0xdf, 0xe8, 0xf2, 0xc9, 0xfc, 0x42, + 0xd5, 0x10, 0x09, 0xe0, 0x4b, 0x3b, 0xdc, 0x13, 0xe4, 0xd6, 0x32, 0x45, 0x08, + 0xfb, 0x36, 0xcb, 0x04, 0x59, 0xf6, 0x17, 0xd2, 0x07, 0x46, 0x25, 0xd6, 0xe9, + 0xdb, 0xfc, 0xfd, 0xe2, 0xf3, 0xe6, 0xde, 0xf5, 0xae, 0x04, 0x13, 0xda, 0x55, + 0xd9, 0x4a, 0xde, 0x0f, 0x07, 0x0d, 0xa5, 0xc6, 0xe9, 0xd4, 0xbb, 0xda, 0xf3, + 0x45, 0x81, 0x18, 0xaf, 0xfc, 0x08, 0xfd, 0xb0, 0xe5, 0xcb, 0xda, 0x01, 0x01, + 0xf8, 0x59, 0xf0, 0x02, 0x17, 0x39, 0x0a, 0xdb, 0xac, 0x06, 0x16, 0xdc, 0xf4, + 0xf7, 0xf8, 0x1d, 0x10, 0xc2, 0x0b, 0xcc, 0x21, 0xdb, 0xc9, 0xde, 0x02, 0x11, + 0x57, 0x0c, 0x31, 0xec, 0x29, 0x40, 0x27, 0xe3, 0xe9, 0xed, 0x1e, 0xc0, 0x43, + 0xcf, 0xc0, 0x37, 0x3c, 0xbf, 0xfb, 0xd4, 0x1d, 0xef, 0xd1, 0x64, 0xe8, 0xf3, + 0x18, 0xf4, 0xee, 0x05, 0xeb, 0x03, 0xe0, 0xfb, 0xc2, 0xe7, 0xab, 0x24, 0xc5, + 0xf8, 0x7f, 0x2a, 0x00, 0xc4, 0xe9, 0xf0, 0x04, 0xfc, 0x1c, 0xf1, 0x05, 0xff, + 0xc7, 0x35, 0x15, 0xcd, 0xea, 0xfb, 0x0a, 0xb8, 0x6c, 0x2c, 0x0a, 0x10, 0xde, + 0xf3, 0xfa, 0x9a, 0x33, 0xda, 0x08, 0x24, 0xda, 0x0d, 0x18, 0x4e, 0x11, 0xf2, + 0xfe, 0x1c, 0xe6, 0xd2, 0xe3, 0xf1, 0x3a, 0xdc, 0x01, 0x2f, 0xe2, 0xf1, 0xdb, + 0xfa, 0x28, 0xbc, 0xef, 0x5e, 0xed, 0x05, 0xcf, 0xe9, 0xf2, 0xcb, 0xfa, 0x3a, + 0x2f, 0xf8, 0x28, 0xfa, 0xdf, 0xe9, 0xd7, 0x29, 0x07, 0x02, 0xf0, 0x3a, 0xf0, + 0xd3, 0x08, 0x15, 0x0d, 0x2d, 0xe4, 0x2a, 0x30, 0xe3, 0xc1, 0x1d, 0x2f, 0x17, + 0x14, 0xf9, 0x31, 0x11, 0xff, 0xfd, 0xc9, 0x1b, 0x1c, 0x0e, 0x55, 0xf3, 0xe2, + 0x16, 0xd7, 0xc7, 0xd8, 0x2f, 0xfc, 0xe1, 0x1f, 0x03, 0xcc, 0x32, 0x33, 0x30, + 0xeb, 0xe3, 0xbf, 0x13, 0xf9, 0x06, 0xe7, 0x03, 0x0e, 0xee, 0xf9, 0x3d, 0x51, + 0x05, 0xef, 0x22, 0xef, 0x02, 0xf4, 0x17, 0xdc, 0xbb, 0xf0, 0x0b, 0xcd, 0x48, + 0xf2, 0xd4, 0x32, 0x01, 0xef, 0xd6, 0x15, 0x12, 0x1c, 0xff, 0x2c, 0xf9, 0xca, + 0xd4, 0x15, 0x08, 0xdc, 0x03, 0x0a, 0xf0, 0xe1, 0x1b, 0xf4, 0xd4, 0xbd, 0xed, + 0xdc, 0xff, 0xeb, 0xce, 0x09, 0x25, 0xef, 0x31, 0xee, 0xee, 0x81, 0xfd, 0xf1, + 0xfb, 0xf7, 0x50, 0xaf, 0xd7, 0xcd, 0xec, 0xe3, 0x0a, 0x0c, 0x0c, 0xd7, 0x18, + 0x02, 0x18, 0xf2, 0xe2, 0x0d, 0x21, 0xd1, 0x0b, 0x00, 0x0c, 0x14, 0x41, 0xf3, + 0x14, 0xbc, 0x26, 0xe4, 0x26, 0x37, 0xfc, 0x0a, 0xe3, 0xd4, 0x06, 0x2a, 0xe3, + 0x27, 0x0a, 0xd4, 0xf6, 0xfd, 0xf1, 0xe8, 0x5b, 0xfa, 0xd2, 0xc6, 0x42, 0xdd, + 0x07, 0xe8, 0xed, 0x09, 0x32, 0x5b, 0xf8, 0xfb, 0x2a, 0x0d, 0x3f, 0xd4, 0x16, + 0xd4, 0x23, 0x06, 0xd3, 0x2c, 0xbb, 0x24, 0xd2, 0x14, 0x09, 0xed, 0x01, 0x5d, + 0x7f, 0xbb, 0xfb, 0xd5, 0x14, 0x2d, 0xfe, 0x13, 0xbe, 0x0c, 0xe5, 0x1a, 0x05, + 0x24, 0xd9, 0xbc, 0xef, 0x05, 0xfc, 0x16, 0x32, 0x31, 0x14, 0xd6, 0x33, 0xfc, + 0xe6, 0xe1, 0x1c, 0xe3, 0xef, 0xd8, 0xa7, 0xce, 0xd8, 0x11, 0xca, 0xf8, 0xf8, + 0xdd, 0x1b, 0xf5, 0x51, 0x08, 0x34, 0x09, 0xfb, 0xb7, 0x2f, 0xbf, 0x3e, 0xf2, + 0xda, 0x4a, 0xdc, 0xe2, 0x14, 0xf5, 0x7f, 0x37, 0x42, 0xd3, 0x10, 0xeb, 0xe0, + 0xf8, 0xd8, 0x10, 0xf4, 0xee, 0x48, 0x32, 0x0a, 0xcb, 0x1b, 0xc0, 0xf9, 0x19, + 0x01, 0x1c, 0xd1, 0x04, 0xe9, 0xd6, 0xb9, 0x5a, 0xe8, 0x0a, 0xe1, 0x25, 0x21, + 0x0d, 0xc6, 0xf8, 0xfa, 0xcc, 0x36, 0xe9, 0x22, 0x69, 0x2d, 0xec, 0x4d, 0x36, + 0xc1, 0xee, 0xcb, 0xe1, 0x4b, 0xfe, 0xd5, 0x31, 0xe0, 0xf9, 0x1d, 0xf3, 0xab, + 0x2b, 0x24, 0x4b, 0x15, 0x66, 0xd9, 0x29, 0x14, 0x40, 0x6d, 0xa1, 0xe4, 0xca, + 0x21, 0xb7, 0x07, 0xfb, 0xff, 0xc0, 0x2b, 0xf8, 0xe9, 0xfe, 0xe2, 0xe8, 0xad, + 0x23, 0xc0, 0x3e, 0x17, 0x09, 0xbc, 0x30, 0xcf, 0xd0, 0xf4, 0xd8, 0x1c, 0x5d, + 0xf6, 0x3c, 0x0f, 0xd9, 0x1c, 0x24, 0x0d, 0xd0, 0xc1, 0xd4, 0xd7, 0x00, 0xfd, + 0xe3, 0xa1, 0xde, 0xe1, 0x11, 0x0d, 0x36, 0x29, 0x48, 0x27, 0xf6, 0x3e, 0xf1, + 0x2b, 0x2b, 0x21, 0xc3, 0xe6, 0xf8, 0x10, 0xe3, 0xd8, 0x02, 0xf2, 0x45, 0x4f, + 0xd8, 0xfc, 0xf4, 0x6b, 0xf7, 0xfe, 0xac, 0x18, 0xe8, 0x12, 0xfd, 0x14, 0x1f, + 0x2a, 0xd1, 0x26, 0x56, 0xb8, 0xae, 0x0f, 0x36, 0xac, 0x16, 0xd7, 0x06, 0x0d, + 0x1d, 0x3f, 0xfa, 0x18, 0x40, 0x01, 0x7f, 0xfe, 0x35, 0xed, 0xc8, 0xcc, 0x04, + 0x3a, 0x2f, 0xdd, 0x32, 0x2c, 0xfb, 0x17, 0xf0, 0x0c, 0x17, 0x0e, 0x11, 0xd6, + 0xa7, 0x75, 0xd0, 0xf6, 0x23, 0xd8, 0x46, 0x01, 0x10, 0x06, 0xd1, 0x38, 0xc9, + 0xb7, 0xb0, 0xea, 0xf8, 0xe9, 0x10, 0x55, 0xcd, 0x17, 0x3c, 0x99, 0x0e, 0x81, + 0x27, 0xd5, 0xd3, 0x05, 0x2f, 0x2d, 0xab, 0xfa, 0x41, 0xc5, 0x7a, 0x44, 0xe9, + 0xca, 0xd8, 0xce, 0x0e, 0xc1, 0x23, 0x29, 0xdb, 0xda, 0x32, 0x09, 0x2a, 0xcd, + 0x2b, 0x61, 0xf4, 0x09, 0xf2, 0xe8, 0x18, 0x29, 0x03, 0x47, 0xee, 0xe5, 0xab, + 0xd3, 0xe6, 0x3a, 0x23, 0xe0, 0xb0, 0xcd, 0x2d, 0xce, 0xfd, 0x25, 0x95, 0x24, + 0x46, 0x27, 0x20, 0x49, 0x97, 0xb6, 0xe1, 0x2f, 0x8c, 0xf1, 0x11, 0x08, 0x1a, + 0xa8, 0x0f, 0x2d, 0x11, 0x20, 0x3a, 0xfd, 0x20, 0xfd, 0x20, 0xcc, 0x20, 0x31, + 0x5f, 0x1b, 0x47, 0x24, 0xd8, 0xf1, 0xc5, 0xb3, 0xe5, 0x25, 0xd5, 0x4f, 0x42, + 0x01, 0xbd, 0x27, 0x09, 0xac, 0x37, 0x3f, 0xd4, 0x50, 0xcc, 0xb6, 0x38, 0x1e, + 0xe6, 0x0d, 0x19, 0x0f, 0xd0, 0x1d, 0x0f, 0xf2, 0xa3, 0xf9, 0xe9, 0x07, 0xf4, + 0x09, 0x0c, 0xf6, 0xe8, 0x48, 0x18, 0xdd, 0x47, 0xaa, 0x17, 0x02, 0x00, 0x06, + 0x4b, 0xec, 0x2e, 0xf0, 0xe4, 0x28, 0xea, 0x31, 0x54, 0xa3, 0xe9, 0xb8, 0xee, + 0x2e, 0xa5, 0x9f, 0x00, 0xfa, 0xd0, 0x06, 0x13, 0x0f, 0x24, 0x16, 0x19, 0x58, + 0x1e, 0x07, 0x2e, 0x2f, 0xef, 0xfb, 0xcf, 0xeb, 0x3b, 0xa5, 0xf4, 0xcd, 0xb4, + 0x4e, 0x08, 0x7f, 0x06, 0xee, 0x2d, 0xcc, 0x04, 0x69, 0xe7, 0xe2, 0x1f, 0x00, + 0xe7, 0x00, 0xe5, 0xdb, 0xfb, 0x19, 0xb8, 0x00, 0x42, 0xd2, 0x3d, 0xb0, 0xd0, + 0x1a, 0x07, 0x24, 0xe9, 0xfc, 0x20, 0xec, 0x1a, 0xb8, 0x28, 0xc5, 0x24, 0x14, + 0xc9, 0x9e, 0x11, 0x00, 0xdf, 0xbd, 0x1d, 0xea, 0x19, 0xd5, 0xb0, 0x52, 0xf2, + 0xf3, 0x1d, 0xbe, 0xe9, 0xad, 0x3b, 0xe2, 0xff, 0xaa, 0xd6, 0xf1, 0xfe, 0x1f, + 0xda, 0xfa, 0x0f, 0x06, 0xb1, 0xf8, 0x20, 0x22, 0x67, 0x12, 0xea, 0xda, 0xa1, + 0xc3, 0xd6, 0x25, 0x57, 0xcb, 0xea, 0x1c, 0xf4, 0xcb, 0xb9, 0x44, 0xf7, 0x1f, + 0x3b, 0xe6, 0xb9, 0x9e, 0xd4, 0xd3, 0x2d, 0x4e, 0xe6, 0x09, 0xd8, 0x04, 0x58, + 0xf8, 0xc3, 0x9b, 0xe8, 0x14, 0xec, 0x41, 0xec, 0x01, 0xfe, 0x03, 0x19, 0xcd, + 0xc1, 0x90, 0x0b, 0xef, 0xda, 0x1d, 0xfa, 0x3d, 0xf5, 0x09, 0x11, 0xaa, 0x1d, + 0xe4, 0x10, 0x05, 0x14, 0xff, 0x1d, 0xe7, 0x36, 0x69, 0xee, 0x01, 0xfc, 0xd9, + 0x48, 0xe0, 0x06, 0x40, 0xfa, 0xcb, 0xf8, 0x65, 0x53, 0xfb, 0x0b, 0x7f, 0x53, + 0x2b, 0xed, 0x89, 0x50, 0x07, 0x03, 0x06, 0xf3, 0x12, 0x1c, 0xca, 0x1f, 0x72, + 0xd0, 0xce, 0x1e, 0x99, 0x20, 0x10, 0xbd, 0xf0, 0xd1, 0x48, 0xe1, 0x2b, 0xb6, + 0x38, 0xd0, 0x06, 0x05, 0xf6, 0x04, 0x19, 0x53, 0x1b, 0xbf, 0xaa, 0xd0, 0x06, + 0x26, 0xc4, 0x57, 0x46, 0xff, 0x0f, 0xa3, 0xfb, 0xf1, 0x0c, 0x2b, 0x33, 0xdc, + 0x10, 0x0f, 0x0e, 0xbd, 0x05, 0xbf, 0x2f, 0xe7, 0x2b, 0x0a, 0x00, 0x15, 0xfc, + 0xb1, 0x22, 0x01, 0x1e, 0x17, 0x08, 0x53, 0xfa, 0xcd, 0xf4, 0x39, 0xf7, 0xd6, + 0xe9, 0xd4, 0x01, 0xce, 0xcd, 0x27, 0x48, 0x91, 0xff, 0xd7, 0xaf, 0xbc, 0x32, + 0xb2, 0x26, 0xd4, 0xf6, 0x33, 0xc5, 0x29, 0x0d, 0xc3, 0x5a, 0xfd, 0x7c, 0x24, + 0xfc, 0xf8, 0xc3, 0x31, 0xba, 0xb5, 0x3d, 0xc7, 0xf0, 0x3f, 0xbf, 0x51, 0x17, + 0xd9, 0x79, 0xce, 0x17, 0xba, 0x29, 0xc4, 0x94, 0x33, 0xf9, 0xe9, 0xcb, 0x21, + 0xf7, 0x2e, 0x1e, 0xab, 0xeb, 0xc3, 0xfa, 0x0c, 0x0a, 0xc6, 0x81, 0x40, 0x00, + 0xfb, 0x0a, 0x0c, 0x01, 0xe3, 0x81, 0x00, 0x7e, 0xee, 0x48, 0x23, 0xd7, 0xde, + 0x42, 0x5e, 0xea, 0x11, 0xca, 0x47, 0xe9, 0x02, 0xf7, 0xd2, 0x28, 0x03, 0xf7, + 0xfa, 0x13, 0xc1, 0x2a, 0xdf, 0x01, 0xe7, 0xc8, 0x0b, 0xf6, 0xce, 0x42, 0x38, + 0x0c, 0x23, 0xc8, 0xd8, 0xed, 0x10, 0x22, 0xea, 0xfc, 0x28, 0xf9, 0xc7, 0x00, + 0xd6, 0xeb, 0x7a, 0x31, 0x33, 0xf2, 0xf6, 0xf4, 0x0c, 0x98, 0xe9, 0xd3, 0x2a, + 0xdf, 0x09, 0x1a, 0xf9, 0xf8, 0xfd, 0xe0, 0x1d, 0xec, 0x41, 0x28, 0x72, 0xf9, + 0xa4, 0xe1, 0xbf, 0xf1, 0xd7, 0xde, 0xf3, 0x05, 0x43, 0xf2, 0xcf, 0xc3, 0x1a, + 0xef, 0x05, 0x20, 0xef, 0xff, 0xeb, 0xfb, 0x16, 0x30, 0xc9, 0xe4, 0xcc, 0x1f, + 0xf4, 0xfb, 0xc3, 0x19, 0xf4, 0xa5, 0x32, 0x11, 0x07, 0x13, 0xec, 0x23, 0x50, + 0x0d, 0x02, 0xe1, 0xb0, 0x5c, 0xf8, 0x20, 0xd2, 0x44, 0x2e, 0xd0, 0x19, 0xc8, + 0xf8, 0xe1, 0x0f, 0xed, 0xed, 0xd3, 0x3d, 0xe5, 0x63, 0x4d, 0x3a, 0x32, 0xdb, + 0x31, 0x08, 0x3b, 0x56, 0x2c, 0xc2, 0x05, 0x2f, 0xfe, 0x16, 0xff, 0x17, 0x10, + 0xa0, 0xb7, 0x2a, 0x49, 0xb2, 0xf7, 0x0b, 0xbf, 0x33, 0xf8, 0xb9, 0x46, 0xfd, + 0x1a, 0x27, 0xd4, 0x12, 0x12, 0xe7, 0x25, 0x23, 0xf1, 0x1c, 0xda, 0x23, 0x47, + 0x22, 0xf4, 0x13, 0xda, 0x2d, 0xdc, 0xf1, 0xea, 0xda, 0x21, 0x35, 0xfc, 0x24, + 0xf2, 0xe3, 0x20, 0x0d, 0x39, 0xe8, 0x18, 0xe8, 0x7f, 0xde, 0xd8, 0x11, 0x33, + 0xcb, 0x20, 0xf4, 0x6f, 0x4a, 0xfe, 0x05, 0xf9, 0x2b, 0xff, 0x04, 0xe2, 0x28, + 0xec, 0x32, 0xdc, 0xf2, 0x07, 0x09, 0x43, 0xec, 0x11, 0xef, 0xdf, 0x11, 0xf0, + 0xfa, 0x10, 0xeb, 0xdb, 0x13, 0xc7, 0x19, 0xea, 0xd8, 0x06, 0x32, 0x19, 0x14, + 0x3c, 0x28, 0x09, 0xe4, 0x5b, 0x41, 0x1f, 0xfb, 0x57, 0x61, 0x57, 0x2d, 0x13, + 0xbd, 0x25, 0x38, 0x1b, 0x27, 0x2e, 0x34, 0x11, 0xbe, 0xda, 0x2a, 0x2a, 0xbe, + 0x0c, 0x02, 0x43, 0xe5, 0x1b, 0xf7, 0x08, 0xd8, 0x69, 0xd4, 0x27, 0x19, 0x4b, + 0xc6, 0x04, 0xc0, 0xf2, 0xe9, 0x3a, 0x25, 0xda, 0xc7, 0xf1, 0xd3, 0xae, 0x9e, + 0xc5, 0x2a, 0xea, 0x07, 0xd2, 0x04, 0xb9, 0x05, 0x5e, 0xda, 0x47, 0x81, 0xf6, + 0xf8, 0x01, 0x0a, 0x08, 0xe8, 0x11, 0xcb, 0xe2, 0xd7, 0xbe, 0x02, 0xb5, 0x2e, + 0x15, 0xf4, 0xce, 0xd6, 0x26, 0xf5, 0x28, 0x28, 0x39, 0xcb, 0xf1, 0x2f, 0xac, + 0xcc, 0x91, 0xed, 0x15, 0x0f, 0xd3, 0xd0, 0xed, 0xb8, 0x05, 0x0d, 0x47, 0xe9, + 0x18, 0x03, 0x1e, 0xdf, 0x18, 0xe0, 0xcf, 0xda, 0x5e, 0x99, 0x29, 0xc1, 0x3e, + 0xed, 0xf9, 0x4b, 0x9e, 0x06, 0xf6, 0x68, 0x27, 0xf2, 0xe2, 0xca, 0xf6, 0xc8, + 0xe6, 0xd7, 0xe7, 0xf7, 0xc3, 0xdd, 0x07, 0xf7, 0x17, 0xdb, 0xff, 0x05, 0x09, + 0x02, 0x01, 0xec, 0x0d, 0x01, 0x1d, 0xdf, 0x18, 0xb8, 0x15, 0xff, 0x35, 0xcf, + 0x06, 0x5f, 0x26, 0x1c, 0xdf, 0x05, 0xeb, 0x16, 0x42, 0x4d, 0xf8, 0x1f, 0xcd, + 0x20, 0xc4, 0xd5, 0x11, 0xf6, 0xea, 0x00, 0x23, 0x0b, 0xee, 0x37, 0x12, 0xe2, + 0xf2, 0x41, 0xea, 0x04, 0x0d, 0xd6, 0xd1, 0xd8, 0x18, 0xd5, 0xf1, 0x0f, 0xc1, + 0x01, 0x4a, 0x29, 0xeb, 0xd0, 0xfe, 0x00, 0x27, 0xf8, 0x11, 0x6d, 0x18, 0x5f, + 0x55, 0x47, 0x01, 0xe3, 0xf9, 0x09, 0xee, 0xdd, 0xdc, 0x2a, 0xbc, 0xaf, 0xd5, + 0xe1, 0xbd, 0x12, 0xe8, 0x0e, 0xf7, 0xec, 0xf7, 0xf3, 0x20, 0x1e, 0xc1, 0x19, + 0xfe, 0xe3, 0x1b, 0xff, 0xc1, 0xdc, 0xc3, 0xf0, 0xf7, 0x0b, 0x01, 0x35, 0x7f, + 0xeb, 0x2c, 0x3c, 0x0c, 0x0e, 0x43, 0xd6, 0xf2, 0xec, 0xf1, 0x10, 0xc7, 0xf1, + 0x13, 0x5a, 0x28, 0x0b, 0x0a, 0xf8, 0xe7, 0x2f, 0x02, 0x00, 0xf5, 0x0c, 0xeb, + 0x1b, 0xf8, 0x11, 0xfc, 0xfd, 0x12, 0x06, 0x0c, 0xdc, 0xcf, 0xbc, 0xeb, 0xde, + 0x41, 0x0a, 0xd7, 0x2a, 0xe4, 0x1b, 0x2d, 0x00, 0x0f, 0x39, 0xea, 0xf0, 0x02, + 0xe7, 0xdc, 0x1a, 0x2b, 0xf1, 0xe1, 0x3e, 0x05, 0x17, 0x00, 0x05, 0xe5, 0xef, + 0x32, 0x47, 0xe1, 0x17, 0x2e, 0x08, 0xe3, 0x25, 0x49, 0xfb, 0xff, 0x04, 0xf8, + 0x2b, 0x1e, 0x08, 0x46, 0x3e, 0xeb, 0x0b, 0xeb, 0x5b, 0x1d, 0x65, 0x39, 0xec, + 0x07, 0xb4, 0x15, 0xf9, 0xf5, 0x22, 0xfc, 0xcd, 0x79, 0x02, 0xed, 0xf7, 0x26, + 0xf3, 0xce, 0xc8, 0x21, 0x0e, 0x1e, 0xf1, 0x0f, 0x10, 0x1c, 0x1f, 0xf0, 0x11, + 0x2f, 0xda, 0xfc, 0xfb, 0xf8, 0x13, 0xd2, 0xca, 0xf2, 0x4b, 0xf0, 0x07, 0x31, + 0x7f, 0x05, 0x15, 0xe2, 0x1f, 0x04, 0x4f, 0x1e, 0x1b, 0x07, 0xd9, 0x4c, 0x48, + 0x3d, 0xf9, 0xfa, 0x05, 0xea, 0xe6, 0x14, 0x2b, 0xff, 0xef, 0x29, 0x04, 0xff, + 0xeb, 0x0d, 0x04, 0xeb, 0x16, 0x09, 0x06, 0xd3, 0xec, 0xfd, 0xdc, 0x3b, 0xd7, + 0x31, 0x10, 0x22, 0x7f, 0x3e, 0xc5, 0x24, 0x10, 0x14, 0x49, 0xfa, 0xf0, 0xcb, + 0xcc, 0xcb, 0x2a, 0xe0, 0x18, 0x18, 0xdc, 0xf5, 0xff, 0xed, 0xb0, 0x50, 0xf9, + 0x1a, 0xb7, 0xb4, 0x18, 0xd7, 0x0a, 0x35, 0xfc, 0x06, 0xc7, 0x0f, 0x62, 0xf6, + 0xdf, 0x06, 0xcc, 0x23, 0xbc, 0x45, 0x23, 0x14, 0x2a, 0xe7, 0x3e, 0xe0, 0x09, + 0xf3, 0xf0, 0x10, 0x00, 0xf3, 0x33, 0x3d, 0x37, 0x1d, 0xba, 0x1f, 0xf8, 0xf1, + 0x38, 0x01, 0xd3, 0x9f, 0x19, 0xc8, 0x1f, 0xe0, 0xc3, 0x12, 0xf6, 0x20, 0x57, + 0x24, 0x18, 0x01, 0xf0, 0x08, 0xd0, 0xed, 0x40, 0x0c, 0xdd, 0x17, 0x39, 0x2a, + 0xff, 0x85, 0xfa, 0x22, 0xf7, 0x09, 0xec, 0x02, 0x0f, 0x16, 0xb7, 0xc0, 0xc4, + 0xbd, 0xf0, 0xc4, 0x07, 0xc4, 0xea, 0x00, 0x13, 0xff, 0xd2, 0xf0, 0xf4, 0x0b, + 0xe3, 0xf6, 0xea, 0x0f, 0x36, 0xc2, 0xf9, 0xa8, 0xe1, 0xee, 0xd9, 0x1e, 0x0c, + 0xea, 0xd0, 0x1f, 0xd6, 0xf9, 0x18, 0x46, 0xdb, 0x22, 0xf2, 0xf5, 0x06, 0xda, + 0x39, 0x41, 0xfc, 0x48, 0xe8, 0xf9, 0xf7, 0x48, 0x27, 0x1e, 0x33, 0x0e, 0xd3, + 0xc5, 0xd3, 0x17, 0x7f, 0x05, 0x01, 0x2b, 0x21, 0xef, 0xef, 0x27, 0xf3, 0x12, + 0xfa, 0x01, 0x06, 0x0b, 0x26, 0x08, 0x25, 0x12, 0xf3, 0xf2, 0xc5, 0x0e, 0x07, + 0xd9, 0x07, 0x00, 0x25, 0xeb, 0x1e, 0x0c, 0x18, 0x1e, 0x03, 0xc6, 0x29, 0x20, + 0xfc, 0x04, 0xf0, 0xfa, 0xfe, 0x07, 0xf6, 0x1a, 0x18, 0x51, 0xf0, 0x17, 0xb8, + 0xfc, 0x03, 0x18, 0xe6, 0x0f, 0x36, 0xb9, 0xef, 0x1f, 0x3e, 0x34, 0x01, 0xe2, + 0x4e, 0x0d, 0xf4, 0x21, 0xfb, 0x2c, 0x0b, 0x28, 0x53, 0xef, 0xf7, 0x7b, 0x25, + 0xdb, 0xc9, 0xea, 0xe1, 0xf2, 0x45, 0x4a, 0xe8, 0x0a, 0xdc, 0x5b, 0xb3, 0xb8, + 0x9e, 0xb0, 0xe3, 0xf9, 0x5c, 0xc4, 0x05, 0xf4, 0xf5, 0x09, 0x0d, 0x24, 0xb0, + 0x42, 0x25, 0x22, 0xca, 0x3f, 0xd7, 0xfb, 0x81, 0x23, 0xd2, 0xea, 0x26, 0xf1, + 0xfc, 0x1c, 0x02, 0x0e, 0x4d, 0x06, 0xff, 0xc8, 0x78, 0xb6, 0xdf, 0xb7, 0x11, + 0xf3, 0x15, 0xf9, 0xf9, 0xe8, 0xec, 0x00, 0x67, 0xea, 0xd8, 0xc7, 0xfe, 0xb8, + 0x08, 0xd5, 0xed, 0x5a, 0xd7, 0x30, 0xe5, 0x0c, 0x14, 0x5f, 0xee, 0x23, 0x2b, + 0x32, 0x6c, 0xe8, 0x11, 0x30, 0xc4, 0x32, 0xdb, 0xfe, 0xd9, 0xd5, 0x51, 0xd9, + 0xda, 0x1d, 0x49, 0xdc, 0xe1, 0x04, 0xe1, 0x24, 0x16, 0xbd, 0xe6, 0x1d, 0xf0, + 0x34, 0x20, 0x0b, 0xfa, 0xf2, 0xc7, 0xcd, 0xd2, 0x36, 0x3e, 0xfa, 0x58, 0xf6, + 0xd0, 0x00, 0x0c, 0xde, 0x06, 0x40, 0x14, 0x96, 0x3b, 0xe9, 0x31, 0xe5, 0x34, + 0x0c, 0xf8, 0xf8, 0x63, 0x44, 0x0d, 0x1e, 0x4c, 0xf8, 0x0d, 0xfe, 0xe2, 0xe4, + 0x07, 0x2f, 0x09, 0x41, 0x16, 0xd8, 0x0d, 0x01, 0x36, 0x17, 0xe3, 0x28, 0xd7, + 0xf8, 0x5b, 0xde, 0x33, 0xf5, 0x2e, 0xea, 0x17, 0x07, 0x0f, 0x27, 0xfe, 0x31, + 0xe7, 0xea, 0x4a, 0xfa, 0xfa, 0x32, 0x0c, 0x06, 0xf4, 0x22, 0xfd, 0x5e, 0x3c, + 0x0f, 0x12, 0xfb, 0x1c, 0x23, 0x03, 0xdf, 0xe7, 0x1a, 0x0f, 0xfd, 0xff, 0xd9, + 0x20, 0xdd, 0x30, 0x12, 0xf7, 0xcc, 0xc8, 0x34, 0xfe, 0x19, 0xf6, 0x33, 0x0f, + 0x3d, 0x09, 0x50, 0x53, 0xcc, 0x03, 0x03, 0xd2, 0x10, 0x32, 0x00, 0xeb, 0x02, + 0xf4, 0x25, 0xd1, 0xf3, 0xf1, 0x45, 0xfe, 0xf6, 0x04, 0xee, 0x05, 0xfb, 0x0c, + 0xfb, 0x3d, 0xe8, 0xd9, 0xff, 0x7f, 0xdc, 0xd9, 0xe2, 0x42, 0x02, 0x1a, 0x17, + 0xe8, 0xff, 0x2e, 0x01, 0xfb, 0x0e, 0xfa, 0xff, 0xf4, 0x29, 0x2c, 0x20, 0xf1, + 0xd8, 0xfe, 0x05, 0xf9, 0xf6, 0xcf, 0x15, 0x0f, 0x0d, 0xd3, 0xdc, 0x25, 0x02, + 0xfa, 0xa1, 0xd1, 0xb7, 0xf6, 0x04, 0xe6, 0x19, 0x4d, 0x10, 0x1d, 0xc7, 0xe9, + 0x1d, 0x03, 0x18, 0xf5, 0x0a, 0x09, 0x09, 0x02, 0x12, 0x03, 0xc1, 0xf6, 0x1a, + 0xe0, 0x1b, 0x11, 0xd4, 0xc2, 0xf9, 0xf5, 0x54, 0xeb, 0x52, 0xeb, 0x0e, 0x19, + 0x1f, 0x06, 0xf6, 0x19, 0xf4, 0xf9, 0x1d, 0x10, 0x07, 0x18, 0xfa, 0xe1, 0x7f, + 0x0f, 0xf3, 0xf9, 0x2f, 0x10, 0xd7, 0xf9, 0xe7, 0x1c, 0xed, 0x0b, 0xd2, 0xce, + 0x24, 0x11, 0x50, 0xf3, 0x01, 0x36, 0xec, 0x08, 0xf2, 0x13, 0xc4, 0xfb, 0xdc, + 0x30, 0xf4, 0x0e, 0x14, 0xfa, 0xe6, 0x1f, 0xf5, 0xf4, 0x0a, 0xe6, 0x29, 0xea, + 0x1f, 0x36, 0xd2, 0xd9, 0x0a, 0xfb, 0xe8, 0xfd, 0x2a, 0x20, 0xed, 0xe1, 0x07, + 0x1b, 0xf6, 0xe9, 0xfc, 0x60, 0x01, 0x14, 0xde, 0x04, 0xb5, 0x13, 0x00, 0x1c, + 0x29, 0x27, 0xf9, 0x2c, 0x12, 0x33, 0xee, 0x26, 0xcb, 0x18, 0x01, 0xe6, 0xeb, + 0x27, 0xc1, 0x24, 0x03, 0xb9, 0x12, 0x0a, 0xe4, 0x3a, 0x12, 0x48, 0xeb, 0x22, + 0xef, 0xd6, 0xd1, 0x0d, 0xb7, 0x05, 0x72, 0xfa, 0xf4, 0xf4, 0x28, 0xb3, 0xce, + 0xdc, 0xf1, 0xb9, 0x05, 0x06, 0xd5, 0xfe, 0xf2, 0xaa, 0x23, 0xff, 0x1e, 0x18, + 0xf8, 0x25, 0xd3, 0xf4, 0x06, 0xf1, 0xff, 0x17, 0x0a, 0xef, 0xdc, 0xef, 0x11, + 0xf3, 0xf0, 0xae, 0x11, 0x47, 0xf4, 0xbc, 0xf3, 0xe2, 0x0b, 0xbd, 0xbd, 0x39, + 0xbb, 0x2b, 0x81, 0xe6, 0x04, 0xaa, 0xd1, 0x1b, 0xd2, 0x1f, 0x36, 0xc0, 0xd4, + 0xe0, 0x32, 0xf7, 0xb3, 0xba, 0x17, 0xa5, 0x02, 0xe9, 0x36, 0xf0, 0xcf, 0x2b, + 0xe3, 0x13, 0x05, 0x30, 0x20, 0x14, 0xe6, 0x13, 0x1d, 0xda, 0xfd, 0x58, 0x14, + 0x21, 0x48, 0xc8, 0x13, 0xe8, 0xd4, 0xcd, 0x0a, 0xf3, 0xce, 0xf2, 0xde, 0xff, + 0xe7, 0x03, 0x01, 0x06, 0xff, 0x14, 0xf2, 0x1d, 0xb2, 0xc5, 0x02, 0xd3, 0xf2, + 0x37, 0xc9, 0xf7, 0xfa, 0x36, 0x3d, 0xd5, 0x0c, 0xed, 0xe0, 0xdc, 0x13, 0x16, + 0xf1, 0x0e, 0xd5, 0xd3, 0x03, 0x47, 0x2e, 0xc1, 0x35, 0xe4, 0xd8, 0x1b, 0x04, + 0xce, 0x1c, 0x4e, 0xcd, 0xf3, 0xf8, 0xf5, 0x19, 0x3f, 0xfa, 0x00, 0xda, 0x1b, + 0xe9, 0x36, 0xfe, 0x1e, 0x17, 0x30, 0xf0, 0x0c, 0x3f, 0x10, 0x23, 0xe1, 0x01, + 0xbf, 0xf3, 0x15, 0x1c, 0x0e, 0xf4, 0xf2, 0x51, 0xfe, 0xf0, 0x46, 0x2e, 0x17, + 0xf6, 0x23, 0x05, 0xf8, 0xed, 0xfe, 0xd5, 0xf5, 0xd9, 0xed, 0xce, 0x33, 0x7f, + 0x03, 0x0f, 0xfd, 0x2b, 0x13, 0x0c, 0xff, 0x1b, 0xf9, 0xf3, 0x2d, 0x01, 0x32, + 0xfe, 0xfe, 0xee, 0x06, 0x1c, 0x20, 0x22, 0xeb, 0x24, 0xcd, 0x37, 0x02, 0x3d, + 0x1b, 0x20, 0x20, 0xfa, 0xb2, 0xf0, 0x32, 0xb9, 0xda, 0xf3, 0xdd, 0xf3, 0x19, + 0xe3, 0x0f, 0x17, 0x17, 0xe0, 0xe6, 0xd5, 0x14, 0x38, 0x24, 0xdf, 0x05, 0xce, + 0x28, 0xc7, 0xfa, 0x39, 0x57, 0x34, 0x08, 0xbc, 0x21, 0xcd, 0xf8, 0x1d, 0xee, + 0x21, 0x1a, 0x21, 0x0d, 0xea, 0x3a, 0xda, 0x43, 0xda, 0xf2, 0xe6, 0xf8, 0xd2, + 0xe1, 0x1a, 0xd6, 0xf6, 0xc4, 0x21, 0x3f, 0xd9, 0x1f, 0x02, 0x01, 0xe5, 0xf1, + 0x55, 0x0f, 0xd7, 0x24, 0x18, 0x1c, 0xff, 0xed, 0x0b, 0xef, 0xe2, 0xc8, 0x11, + 0xec, 0xd3, 0x1a, 0x01, 0x7f, 0x64, 0xee, 0x29, 0xde, 0x33, 0x2b, 0xb1, 0x06, + 0x18, 0x21, 0xf0, 0x01, 0x04, 0x1c, 0xc1, 0x07, 0x17, 0x3f, 0x17, 0xce, 0xe3, + 0xce, 0xf9, 0x26, 0x06, 0xdf, 0x21, 0xd4, 0x0c, 0xdd, 0x08, 0x05, 0x2b, 0xf9, + 0x15, 0xd0, 0xdb, 0xde, 0xc6, 0x00, 0xcb, 0xd5, 0x08, 0x1d, 0x09, 0xc9, 0x1f, + 0xdd, 0x1c, 0x57, 0xc6, 0xc9, 0xe7, 0x3b, 0xe7, 0xdb, 0xf8, 0x28, 0xfd, 0xdd, + 0xae, 0xe6, 0xf9, 0x0b, 0x37, 0xe5, 0x1a, 0x06, 0x00, 0x04, 0xd5, 0x18, 0xf4, + 0x1b, 0xc7, 0xd4, 0x06, 0xcc, 0x14, 0x1c, 0x13, 0xd3, 0xc0, 0xe4, 0xc9, 0x5e, + 0xfb, 0xe6, 0xbc, 0xf2, 0x13, 0x15, 0xf2, 0x0f, 0xfd, 0x00, 0xfe, 0xc9, 0xd7, + 0xf3, 0x3f, 0x24, 0x2a, 0xdb, 0xdc, 0xd7, 0xd7, 0x2f, 0xf5, 0xd8, 0xfe, 0x12, + 0x06, 0xdb, 0xf3, 0x08, 0x00, 0xe0, 0xd4, 0xf2, 0xf9, 0xf6, 0xbd, 0xf9, 0x0f, + 0x13, 0xef, 0xfb, 0xfd, 0x47, 0x7f, 0xdc, 0xe6, 0x3a, 0x05, 0xdc, 0xe3, 0xf1, + 0x0f, 0xe9, 0xdc, 0x37, 0x04, 0xd2, 0xe5, 0x0b, 0xe0, 0xf9, 0xc3, 0x19, 0xe9, + 0xe9, 0x02, 0xdc, 0x01, 0xd3, 0xad, 0xea, 0xed, 0xd8, 0x2f, 0x1b, 0xfa, 0x08, + 0x0b, 0x0c, 0xff, 0xc3, 0x0d, 0xf2, 0xe6, 0x22, 0x30, 0x27, 0x10, 0x40, 0x3e, + 0xed, 0xe3, 0xff, 0x44, 0x14, 0x15, 0x1d, 0xff, 0x5e, 0xf6, 0xf0, 0x06, 0x00, + 0x23, 0xe7, 0xe4, 0xcc, 0xf1, 0xa5, 0xd1, 0xde, 0x18, 0x12, 0x1f, 0x0b, 0xf9, + 0xbd, 0xe5, 0xfd, 0xd3, 0xba, 0x29, 0x01, 0xc7, 0x22, 0x6d, 0x39, 0x3d, 0x06, + 0xcc, 0xd2, 0xc6, 0xe9, 0xfd, 0x0e, 0xcf, 0x08, 0x0a, 0x0e, 0xe3, 0xea, 0xd3, + 0xdb, 0x18, 0xc9, 0x3c, 0xfc, 0x08, 0x38, 0xf4, 0x04, 0x14, 0xea, 0x0d, 0x12, + 0xfd, 0x5a, 0xed, 0x44, 0x7f, 0x34, 0x42, 0xb8, 0xd2, 0xf4, 0xc7, 0x0d, 0xc5, + 0x01, 0x17, 0xf4, 0xec, 0xc9, 0x44, 0xad, 0x6f, 0x39, 0x1a, 0xd6, 0xfa, 0xfa, + 0x17, 0xd5, 0x31, 0xf9, 0x1a, 0xdf, 0x25, 0x2b, 0xea, 0xd1, 0x08, 0xe8, 0x13, + 0xd8, 0xef, 0x6d, 0xcd, 0x40, 0xd6, 0x51, 0xe3, 0x55, 0x19, 0x21, 0xde, 0x1d, + 0x57, 0x21, 0x34, 0xd8, 0x3f, 0x46, 0x44, 0x97, 0x1f, 0xe7, 0x09, 0x19, 0x35, + 0x17, 0x1d, 0x3c, 0x5b, 0x23, 0xbb, 0x60, 0x13, 0xc6, 0xeb, 0x6b, 0x1d, 0xe2, + 0x7f, 0x4b, 0xd8, 0xd2, 0xeb, 0x1e, 0xd1, 0x39, 0x10, 0x27, 0x42, 0xfa, 0x1f, + 0xdd, 0xf1, 0xf1, 0xd5, 0xcf, 0x32, 0xe2, 0xf0, 0x31, 0xfd, 0x3d, 0xb8, 0x0f, + 0x32, 0x5e, 0x2e, 0x2e, 0x75, 0x40, 0x08, 0x1c, 0x48, 0x50, 0xe2, 0xf1, 0xe2, + 0xc2, 0x25, 0xf5, 0x21, 0x68, 0xfa, 0xd3, 0x17, 0xeb, 0xdb, 0x0a, 0x0a, 0x0c, + 0x27, 0xed, 0x0e, 0xd6, 0x40, 0x3c, 0x39, 0x0d, 0xb2, 0xed, 0x18, 0xd9, 0xf6, + 0x06, 0x4b, 0x2b, 0xcc, 0x05, 0xdd, 0xd0, 0x35, 0x23, 0x02, 0x4f, 0x4e, 0x05, + 0xdd, 0xe8, 0x18, 0xf5, 0x03, 0x07, 0xdb, 0xe9, 0xe8, 0x46, 0x24, 0x27, 0x1d, + 0xfb, 0xbe, 0xff, 0xfb, 0xab, 0x55, 0xd1, 0x40, 0x06, 0xf7, 0x09, 0x32, 0xf0, + 0x08, 0xe6, 0xeb, 0x53, 0xe6, 0xf0, 0x67, 0x0f, 0x05, 0x11, 0xd6, 0xe1, 0xbf, + 0xd4, 0x24, 0xe9, 0x25, 0xfe, 0xed, 0xce, 0x00, 0x16, 0x21, 0xf8, 0x10, 0x71, + 0xcb, 0xeb, 0xdc, 0xf1, 0xef, 0xfd, 0x06, 0xe2, 0x24, 0xd4, 0xe9, 0xf4, 0x23, + 0x10, 0xff, 0xf8, 0x28, 0xf5, 0xee, 0xf0, 0xe2, 0xe6, 0xe1, 0xab, 0xcf, 0x39, + 0x2a, 0xad, 0xe2, 0xd9, 0xbf, 0xf4, 0x62, 0xa9, 0xcf, 0x2a, 0x24, 0x1c, 0x0d, + 0xd7, 0x1a, 0xd0, 0xa2, 0xfb, 0x14, 0x08, 0xe0, 0xda, 0xd7, 0xf4, 0xd6, 0xec, + 0x16, 0xf1, 0xf7, 0xcd, 0x2e, 0xf4, 0x81, 0xd3, 0x31, 0x89, 0x9d, 0xae, 0x04, + 0xe6, 0x5e, 0x17, 0xd3, 0xf0, 0xd2, 0x2e, 0x19, 0x06, 0x0e, 0xf1, 0x13, 0x14, + 0xf4, 0xda, 0xc4, 0xf6, 0xa9, 0xba, 0x3b, 0xdf, 0xf3, 0xbb, 0x11, 0xee, 0xf4, + 0x20, 0xef, 0x04, 0x1a, 0x02, 0x06, 0x32, 0x06, 0x0e, 0x12, 0xba, 0x14, 0x14, + 0x39, 0xf2, 0xcc, 0x05, 0xf3, 0x03, 0xd6, 0xfc, 0x03, 0xf2, 0x36, 0xee, 0xfe, + 0x2f, 0x42, 0xe1, 0x35, 0xc8, 0x10, 0xed, 0xe6, 0x1b, 0xf0, 0xcc, 0x05, 0x77, + 0xf8, 0x13, 0x0e, 0xc3, 0xcc, 0x19, 0x6c, 0x7f, 0xd9, 0xdd, 0xdc, 0xf9, 0xc8, + 0xf0, 0x08, 0xce, 0xd1, 0x4f, 0xee, 0x4c, 0xf7, 0x22, 0x22, 0xfb, 0x0d, 0x5d, + 0xcb, 0xfc, 0x16, 0xf7, 0xef, 0xfd, 0xe4, 0xf6, 0xe2, 0x27, 0x9d, 0xe0, 0xc4, + 0xec, 0xf9, 0xe7, 0xef, 0xf8, 0xf2, 0x21, 0x10, 0xf9, 0x02, 0x34, 0x15, 0x33, + 0xe2, 0xe9, 0xf5, 0xa7, 0x61, 0x27, 0xcd, 0x16, 0x0a, 0xcf, 0xed, 0xb9, 0xf0, + 0xed, 0x05, 0xf0, 0xb1, 0xf5, 0xb4, 0x00, 0x1e, 0xe9, 0xa4, 0xd5, 0x2c, 0x0d, + 0x3d, 0xd3, 0xc5, 0xd5, 0x0f, 0xd1, 0xea, 0xc0, 0x01, 0xea, 0xbb, 0xf3, 0xee, + 0xd7, 0x0c, 0x0e, 0xf1, 0xa8, 0x05, 0x17, 0xe9, 0x17, 0xfa, 0xfb, 0xfb, 0x1d, + 0xdd, 0xc3, 0x0f, 0x02, 0xe8, 0x1a, 0x0c, 0xdf, 0x48, 0x4c, 0x41, 0xca, 0x27, + 0x12, 0xd2, 0x93, 0xf6, 0xd5, 0xd7, 0xf0, 0x4c, 0x51, 0xeb, 0xf3, 0x56, 0x1b, + 0xa9, 0x39, 0x03, 0x04, 0x7f, 0xd8, 0x26, 0x0e, 0x23, 0xdc, 0x06, 0xeb, 0xce, + 0xb8, 0x2f, 0xe3, 0xec, 0x37, 0x07, 0x26, 0x23, 0x4f, 0x32, 0x09, 0xd4, 0x2f, + 0xff, 0xa4, 0x7d, 0x19, 0x32, 0x67, 0x07, 0xe3, 0x00, 0xab, 0xde, 0xc9, 0xf3, + 0xe5, 0x0f, 0xee, 0xbe, 0x29, 0xf1, 0xd8, 0x1b, 0xcb, 0x12, 0xe2, 0xf8, 0xe2, + 0xe8, 0x20, 0x26, 0xda, 0x63, 0x0c, 0xd6, 0x28, 0xff, 0xc1, 0x49, 0x5f, 0x20, + 0xde, 0xed, 0xf7, 0xee, 0x02, 0x3c, 0x10, 0x22, 0x06, 0x1a, 0xe4, 0xe9, 0x0d, + 0xf6, 0xe8, 0xff, 0xef, 0xe7, 0x00, 0x2b, 0xf3, 0x33, 0xfb, 0x16, 0xd8, 0x52, + 0xfe, 0x2e, 0x07, 0x01, 0x25, 0x06, 0x20, 0x35, 0x25, 0x02, 0x2e, 0x0f, 0xfe, + 0x2f, 0xdb, 0x45, 0x0e, 0x43, 0x2e, 0xe5, 0x02, 0xe5, 0x01, 0x1f, 0xe7, 0x18, + 0xf4, 0x22, 0x06, 0x1d, 0x18, 0xf7, 0x2d, 0xe3, 0xbb, 0xc9, 0x12, 0xce, 0x10, + 0x1e, 0x67, 0xf2, 0x9d, 0xfa, 0x09, 0xd3, 0xca, 0x38, 0x56, 0xed, 0x3f, 0x0e, + 0xb3, 0x71, 0x34, 0xe0, 0xbb, 0xde, 0xd8, 0xad, 0x20, 0x3b, 0x23, 0x2a, 0x01, + 0xdd, 0xc4, 0xcd, 0xec, 0xec, 0x01, 0x37, 0xfe, 0x06, 0xb6, 0xbe, 0x3e, 0xd9, + 0xfb, 0x09, 0xc9, 0x58, 0x2e, 0xf2, 0x29, 0x7c, 0x3d, 0xe1, 0xa0, 0x26, 0xdc, + 0xf5, 0x34, 0xa1, 0x1f, 0x19, 0xb1, 0xe0, 0x1f, 0x7c, 0xfa, 0xde, 0xf2, 0x0d, + 0x10, 0xdb, 0x30, 0xf5, 0x0e, 0x9d, 0xdf, 0xfd, 0xed, 0x52, 0x20, 0x06, 0x0a, + 0xe3, 0xc9, 0x24, 0xe9, 0x0d, 0x52, 0xe1, 0xdf, 0x37, 0x48, 0xb3, 0xa4, 0x23, + 0xac, 0x37, 0x09, 0xd4, 0x24, 0xfa, 0x28, 0x7f, 0xcb, 0x0e, 0x17, 0x29, 0x0c, + 0xc4, 0xcf, 0xfa, 0xdb, 0xb5, 0xe9, 0xb8, 0x0e, 0x15, 0xb1, 0xfd, 0xe1, 0xd8, + 0x0b, 0xf3, 0x20, 0xe9, 0xff, 0xcc, 0x1f, 0xc4, 0xde, 0x08, 0x22, 0x38, 0xe0, + 0x00, 0xf4, 0x1a, 0x36, 0xaa, 0x34, 0x1d, 0x29, 0xcf, 0x2f, 0xea, 0x05, 0x30, + 0x4e, 0x03, 0xdf, 0x07, 0xc9, 0xba, 0x52, 0xf3, 0x39, 0x1f, 0xfa, 0xc2, 0x47, + 0xba, 0xc5, 0xef, 0xf9, 0xf9, 0x2c, 0xfd, 0xf4, 0xf9, 0xe2, 0x24, 0xf8, 0x15, + 0x10, 0xf5, 0x4d, 0xf5, 0x08, 0x3c, 0xe9, 0xf9, 0xc2, 0x0f, 0xba, 0x3f, 0xe3, + 0x81, 0x37, 0xf5, 0x21, 0xb9, 0x3d, 0x10, 0x0a, 0xb9, 0x08, 0x11, 0xf8, 0x15, + 0x12, 0x4b, 0x27, 0xe1, 0xe4, 0xdd, 0xe1, 0x30, 0xd9, 0x76, 0xfd, 0xf2, 0x0f, + 0x09, 0xf5, 0xef, 0x27, 0xfc, 0x90, 0x0a, 0xf5, 0x12, 0xd0, 0x39, 0xf4, 0x0b, + 0xfa, 0x11, 0x06, 0xfa, 0x0b, 0x51, 0x38, 0xe3, 0x36, 0xdd, 0x9c, 0xe8, 0xff, + 0x22, 0x28, 0xaf, 0x26, 0x11, 0xd0, 0xc6, 0xf1, 0x0d, 0xeb, 0x25, 0xce, 0xac, + 0x33, 0x0b, 0xd3, 0x0f, 0xc0, 0xd8, 0xe5, 0x47, 0xcd, 0xb4, 0x59, 0xa6, 0x5b, + 0xff, 0xdb, 0xf8, 0xed, 0xb7, 0x24, 0x37, 0x07, 0x96, 0xee, 0x7f, 0xb8, 0xe6, + 0x1e, 0xa0, 0xc6, 0x3f, 0xc2, 0x48, 0x8c, 0x33, 0x23, 0xe3, 0xea, 0xc5, 0xf1, + 0xf0, 0x28, 0x07, 0x3b, 0x2c, 0xbc, 0x10, 0xc3, 0x3a, 0xf5, 0xdf, 0x35, 0x17, + 0x92, 0x58, 0xc3, 0xf7, 0x50, 0xdf, 0xc0, 0xaf, 0x02, 0xfd, 0x1b, 0xed, 0x05, + 0x3c, 0xf3, 0x08, 0x19, 0x67, 0xd3, 0xe9, 0x39, 0xbf, 0xc1, 0xc2, 0x24, 0xe1, + 0xbc, 0xb0, 0x17, 0xd6, 0xe1, 0x3d, 0x26, 0xc6, 0x34, 0x23, 0xcd, 0xf5, 0xfd, + 0x0c, 0x0f, 0x33, 0x03, 0x09, 0xeb, 0xb3, 0x08, 0x12, 0xfc, 0xfa, 0x00, 0xe9, + 0x39, 0xc3, 0xf3, 0xf3, 0xfe, 0xb7, 0x19, 0x25, 0x17, 0xee, 0xe4, 0xe9, 0xdd, + 0xd4, 0xd0, 0xd4, 0x1c, 0xd8, 0x22, 0x36, 0x1e, 0x1e, 0x7f, 0x2e, 0x18, 0x29, + 0x2e, 0x14, 0x41, 0xed, 0xed, 0x3c, 0x01, 0xd1, 0x1b, 0x14, 0xc5, 0x30, 0xdb, + 0xf9, 0x22, 0xc5, 0x14, 0x10, 0x0f, 0x31, 0x03, 0x3e, 0xca, 0xe3, 0xff, 0x1e, + 0xf7, 0xe7, 0x2d, 0x33, 0x24, 0x17, 0xe6, 0x11, 0x0f, 0xd4, 0xd1, 0x21, 0x0c, + 0x18, 0xfa, 0x1a, 0x52, 0x24, 0x18, 0x49, 0xf6, 0x1e, 0xf4, 0xe7, 0x18, 0x25, + 0x38, 0xf7, 0xf2, 0xdd, 0x44, 0x46, 0x62, 0x51, 0xd5, 0x3d, 0x12, 0x14, 0x19, + 0x1e, 0x5a, 0x03, 0xe5, 0x18, 0x03, 0x11, 0x11, 0x17, 0xe8, 0xfa, 0x1c, 0x3a, + 0xfc, 0x05, 0x2a, 0xf5, 0x06, 0xf4, 0xd2, 0x28, 0x1f, 0xe8, 0xd3, 0x16, 0x21, + 0x32, 0xfa, 0x07, 0x54, 0xfc, 0x00, 0xe4, 0x53, 0x17, 0xf1, 0xf3, 0xf6, 0x25, + 0x17, 0x25, 0x4c, 0xfa, 0x1a, 0x07, 0x0e, 0xca, 0xe1, 0xea, 0x08, 0xde, 0xc8, + 0xdf, 0xc9, 0x13, 0x0a, 0x26, 0x02, 0x23, 0xf9, 0x1c, 0xff, 0xcb, 0xa1, 0xfc, + 0x29, 0xdd, 0x06, 0xcf, 0x49, 0x23, 0x5e, 0x29, 0xfd, 0x7a, 0xf3, 0x03, 0x0f, + 0x1f, 0xe1, 0xe7, 0xb5, 0x26, 0x31, 0xc4, 0x2f, 0x97, 0xbf, 0x20, 0x1d, 0x18, + 0x23, 0xf7, 0x09, 0x15, 0x11, 0x81, 0x2f, 0x3e, 0x66, 0xf4, 0xe9, 0xc3, 0xfb, + 0xe9, 0x49, 0xcb, 0xce, 0x0a, 0xf9, 0xa4, 0xf3, 0xc8, 0x44, 0x14, 0xec, 0x21, + 0x06, 0xff, 0xa9, 0xea, 0x16, 0xfb, 0xd0, 0x17, 0x14, 0xc8, 0x36, 0x1b, 0xbd, + 0xe3, 0x2e, 0xe7, 0xf4, 0x0c, 0x2b, 0x05, 0xa9, 0xcf, 0x45, 0xf0, 0x9e, 0x13, + 0x19, 0x60, 0xbc, 0xea, 0x1a, 0x5a, 0xd9, 0x41, 0x72, 0x31, 0x02, 0x67, 0xfd, + 0x1e, 0xdf, 0x15, 0x2c, 0x41, 0x0f, 0x08, 0x14, 0x10, 0xdb, 0xfc, 0xda, 0x50, + 0x0f, 0x19, 0x02, 0x08, 0xf9, 0x31, 0x04, 0xce, 0xb8, 0x23, 0xc6, 0x08, 0x07, + 0x26, 0xfd, 0xee, 0x05, 0xf9, 0xd2, 0xeb, 0x1e, 0xbd, 0x01, 0xe4, 0xa2, 0xcd, + 0xd4, 0xd3, 0xe8, 0x70, 0xec, 0x0e, 0x06, 0xd8, 0xd5, 0xcb, 0x02, 0x1f, 0xc8, + 0xfc, 0xc1, 0x16, 0x0e, 0x18, 0x2e, 0x05, 0xf2, 0xf4, 0xec, 0xfe, 0x3a, 0xfb, + 0x02, 0x0b, 0xfa, 0x36, 0x92, 0x01, 0x20, 0xef, 0xed, 0xec, 0x23, 0x3b, 0x11, + 0x1f, 0xd3, 0xfa, 0x11, 0xa6, 0xe2, 0x9b, 0xda, 0x28, 0xf0, 0x08, 0xa9, 0x73, + 0xf4, 0xd7, 0xd3, 0xbf, 0xe6, 0xef, 0x33, 0xad, 0xc9, 0x1f, 0x25, 0x19, 0x3f, + 0x0d, 0x25, 0xe2, 0xee, 0x13, 0xf8, 0x2f, 0xbf, 0x04, 0x09, 0x7f, 0xf1, 0x2a, + 0xfa, 0xd2, 0x2a, 0x20, 0x04, 0x47, 0xfe, 0x10, 0x09, 0xae, 0x17, 0x41, 0xd6, + 0x46, 0x2f, 0xea, 0x16, 0x34, 0x12, 0xea, 0x0d, 0x4c, 0x27, 0xf6, 0x05, 0x87, + 0x2b, 0x01, 0x10, 0xe8, 0x1a, 0xdc, 0x0d, 0xf8, 0x03, 0xee, 0x26, 0x44, 0x18, + 0xce, 0x14, 0xf1, 0x35, 0x1c, 0x11, 0xe8, 0x31, 0xfa, 0xdc, 0x03, 0x05, 0x33, + 0x01, 0xd0, 0x03, 0x21, 0xc7, 0x26, 0x2f, 0x1a, 0x0e, 0x23, 0x2b, 0xee, 0x39, + 0x1c, 0xe9, 0xda, 0x55, 0x10, 0x01, 0x09, 0x13, 0x09, 0xf6, 0x25, 0x08, 0x0e, + 0x27, 0x19, 0xbd, 0x06, 0x12, 0x30, 0xee, 0xe7, 0x38, 0x05, 0x27, 0x20, 0x0f, + 0x41, 0xd1, 0x08, 0x33, 0x51, 0x51, 0x17, 0x0f, 0x2b, 0x3f, 0x0b, 0xcb, 0x01, + 0xeb, 0x28, 0x1c, 0xde, 0xf7, 0x4b, 0x14, 0x01, 0x10, 0x45, 0x0e, 0xe6, 0x0f, + 0x00, 0xf1, 0xf3, 0xff, 0x13, 0x16, 0x06, 0x29, 0xc4, 0xdf, 0x4d, 0x5f, 0xe7, + 0x0e, 0xf9, 0xff, 0xeb, 0x19, 0x27, 0x59, 0xe6, 0x0c, 0x04, 0x7f, 0x13, 0xe0, + 0x09, 0x28, 0x23, 0x61, 0xf6, 0xe7, 0x16, 0xc8, 0x36, 0x19, 0x43, 0x02, 0xfe, + 0xb9, 0xe2, 0x05, 0xe8, 0xf5, 0x26, 0x05, 0xcd, 0x31, 0x28, 0xfc, 0x21, 0x18, + 0xfc, 0xd1, 0x23, 0xe7, 0x14, 0xc8, 0x25, 0xea, 0xd3, 0xf6, 0xee, 0x24, 0x1f, + 0x0d, 0xe8, 0xb8, 0x01, 0x30, 0xe1, 0xe6, 0x0c, 0x0a, 0x03, 0x3d, 0x3d, 0x15, + 0x3d, 0xf9, 0x19, 0xff, 0xc4, 0xf2, 0x13, 0xea, 0xe6, 0x3a, 0xf9, 0x29, 0xdb, + 0x5a, 0xe6, 0xdc, 0x18, 0xff, 0xe2, 0x44, 0x15, 0x1d, 0xf6, 0xf6, 0x24, 0xcf, + 0xf1, 0x08, 0xe0, 0x54, 0x0d, 0x1b, 0x3a, 0xf9, 0x04, 0xd5, 0x35, 0xfd, 0x3a, + 0x5b, 0xd4, 0xf7, 0x51, 0xe4, 0xd8, 0x1c, 0xf6, 0x11, 0xdf, 0xd9, 0x07, 0xd1, + 0xfe, 0xff, 0x04, 0xff, 0xfd, 0x02, 0xff, 0x0f, 0x7f, 0xe9, 0xe6, 0x1b, 0x0c, + 0x0b, 0x35, 0xf9, 0x12, 0x66, 0xe8, 0x2e, 0xe8, 0x6a, 0x15, 0x09, 0xfb, 0xfc, + 0xd7, 0xec, 0xf3, 0x05, 0x0b, 0xfb, 0x4a, 0x0c, 0x32, 0xe7, 0x10, 0xe7, 0x01, + 0xe3, 0xca, 0x0c, 0xd6, 0xf1, 0xed, 0x37, 0x13, 0xea, 0xff, 0x01, 0xbd, 0x1b, + 0x00, 0x15, 0xf3, 0xf4, 0xee, 0xff, 0x17, 0xf7, 0x34, 0x01, 0xff, 0x2a, 0x0c, + 0x1f, 0x10, 0xe0, 0xfc, 0x16, 0xfe, 0x06, 0xee, 0x08, 0xe2, 0xcd, 0x06, 0xf2, + 0xf6, 0xe4, 0xea, 0xeb, 0xd6, 0xbe, 0x1f, 0x16, 0xe4, 0xf0, 0xce, 0xfd, 0x05, + 0x0b, 0x0c, 0x03, 0xf3, 0x03, 0x18, 0x06, 0xf6, 0xe2, 0x1e, 0x00, 0x07, 0xe5, + 0x13, 0xf7, 0xea, 0x18, 0xf8, 0x27, 0xcf, 0xd3, 0xda, 0xe4, 0x0b, 0x20, 0xd4, + 0x03, 0x33, 0xf5, 0x18, 0x16, 0x7f, 0xe2, 0xf9, 0x18, 0xcb, 0x2e, 0xe4, 0x05, + 0xed, 0x19, 0xf7, 0x15, 0x14, 0xea, 0x34, 0xe8, 0x19, 0xf6, 0x09, 0x0a, 0xfb, + 0xbd, 0xfe, 0xeb, 0x01, 0x03, 0x44, 0x1a, 0x11, 0xc7, 0xb3, 0xf6, 0x19, 0x35, + 0xf7, 0x07, 0xeb, 0x20, 0x1f, 0x12, 0xf4, 0xf7, 0xdf, 0x12, 0xff, 0xda, 0x2d, + 0xfb, 0xc2, 0xbc, 0x2d, 0x07, 0x33, 0xdd, 0xfa, 0xf8, 0x33, 0xef, 0x10, 0x2b, + 0xe4, 0x1b, 0xc5, 0x65, 0xb2, 0x4a, 0x06, 0x0f, 0xb7, 0x6a, 0x56, 0x55, 0xe2, + 0xf7, 0xbd, 0x16, 0xdd, 0x10, 0xf2, 0xd3, 0xe9, 0x55, 0x53, 0x03, 0x7f, 0xc0, + 0xe1, 0xf6, 0xf8, 0x22, 0x13, 0x06, 0x4d, 0xdc, 0x1a, 0xe9, 0xfa, 0x37, 0xf0, + 0xaa, 0xc3, 0xe9, 0x08, 0xd3, 0x27, 0xcc, 0x06, 0x1e, 0xd9, 0xef, 0xf3, 0x15, + 0xdc, 0x18, 0x27, 0x32, 0xdd, 0x03, 0xfb, 0xed, 0x0e, 0x19, 0xc3, 0xd6, 0xed, + 0xca, 0xf7, 0xb1, 0x08, 0xf2, 0x04, 0xf8, 0xd4, 0x1b, 0xe4, 0x15, 0x5b, 0xd0, + 0xab, 0xd1, 0x41, 0xe4, 0x12, 0xcb, 0xc9, 0x0d, 0xf4, 0xf6, 0xc2, 0x0f, 0xcc, + 0xdd, 0x9e, 0x02, 0x2b, 0xdd, 0x1d, 0xf6, 0xf8, 0xec, 0xcb, 0xea, 0xef, 0xf3, + 0x0d, 0x2b, 0x1b, 0x0f, 0xfe, 0xfd, 0xe9, 0x55, 0x32, 0x49, 0xca, 0x04, 0x29, + 0xe9, 0x3f, 0xca, 0x09, 0x59, 0x05, 0xd7, 0xf5, 0x14, 0xe0, 0xfd, 0x7f, 0x02, + 0xd6, 0x08, 0xf0, 0xd8, 0xfc, 0xae, 0xea, 0xce, 0xeb, 0x04, 0xfa, 0x55, 0xe0, + 0x19, 0x0b, 0xd3, 0xc7, 0xaf, 0x0a, 0xf3, 0xcc, 0xff, 0x2e, 0x0d, 0x16, 0x10, + 0x00, 0xe0, 0xb5, 0xe4, 0xae, 0xba, 0x20, 0x02, 0xe6, 0x19, 0xd9, 0xfd, 0xd6, + 0xf8, 0x02, 0x32, 0xeb, 0xfa, 0xc4, 0xe4, 0xaf, 0x17, 0xcd, 0xfe, 0x02, 0x1d, + 0x11, 0xd8, 0x53, 0x28, 0x6a, 0x44, 0x10, 0xfa, 0xde, 0xee, 0xef, 0x2d, 0x30, + 0xc8, 0xa9, 0x49, 0xdc, 0x14, 0xf9, 0xee, 0xff, 0xf1, 0x3e, 0xf5, 0xec, 0x51, + 0xf6, 0xea, 0xde, 0xc4, 0x28, 0xb0, 0x33, 0x2e, 0x4a, 0xf3, 0x08, 0x01, 0x36, + 0x10, 0x42, 0x01, 0x09, 0xf7, 0xfd, 0x73, 0xbb, 0x33, 0xd0, 0xbf, 0x0e, 0x30, + 0x08, 0xf5, 0xf6, 0x64, 0xd4, 0x1d, 0xc0, 0x3b, 0x13, 0xbb, 0x1b, 0xe7, 0x70, + 0xec, 0x36, 0x20, 0xb3, 0xc1, 0x50, 0x09, 0xb9, 0xf9, 0x4f, 0x72, 0x62, 0x76, + 0x1c, 0x09, 0x22, 0x3c, 0xf1, 0x11, 0xb4, 0x26, 0xe5, 0x26, 0xff, 0xbd, 0x09, + 0xb1, 0x06, 0xe8, 0x31, 0x43, 0xed, 0xf4, 0x33, 0xae, 0xc8, 0x40, 0x46, 0xde, + 0xa9, 0x1e, 0x07, 0xc2, 0x7e, 0xe0, 0x33, 0x5b, 0xa9, 0xee, 0xd7, 0xd5, 0x12, + 0xa8, 0xb4, 0x96, 0xbb, 0xd7, 0xff, 0x2d, 0xbe, 0xae, 0xd4, 0x82, 0xdd, 0x14, + 0xf7, 0xd8, 0x50, 0x00, 0x35, 0x27, 0xbc, 0xd6, 0xef, 0x0f, 0x04, 0x97, 0x1d, + 0x13, 0x09, 0xfd, 0xf8, 0xc4, 0xd6, 0xee, 0x09, 0xbc, 0x12, 0x19, 0x16, 0xdf, + 0x9a, 0xcd, 0x01, 0xfc, 0x0c, 0x9f, 0x34, 0xbe, 0x5a, 0xa0, 0x1b, 0x2a, 0xfd, + 0xd3, 0x2b, 0x3b, 0xb3, 0x7f, 0x05, 0xc6, 0xec, 0x33, 0x00, 0xb2, 0xf9, 0xe6, + 0x38, 0xf9, 0xcd, 0xe7, 0x6c, 0x74, 0xd7, 0xcc, 0x76, 0x27, 0x19, 0x0a, 0x0f, + 0x54, 0x1f, 0xc4, 0xb4, 0x09, 0xbf, 0xd0, 0x5b, 0x54, 0x07, 0x1a, 0x11, 0xd9, + 0x15, 0x23, 0x17, 0xc2, 0x1f, 0x20, 0xdd, 0xf3, 0xe5, 0xdb, 0xf2, 0xbf, 0x06, + 0xdc, 0xbe, 0xe4, 0xe8, 0x3a, 0xab, 0xbd, 0xf4, 0x67, 0x1b, 0x4a, 0xc7, 0x17, + 0xd9, 0xc2, 0x4d, 0xa9, 0xd6, 0xd8, 0x03, 0xfb, 0xf0, 0xdf, 0xea, 0x1e, 0xb6, + 0xdd, 0xd3, 0xd0, 0xa6, 0x00, 0xca, 0x12, 0xfe, 0x13, 0xf8, 0x0b, 0x17, 0xf1, + 0x31, 0xe1, 0x46, 0xe7, 0x09, 0xc4, 0xec, 0xc1, 0xc9, 0x4a, 0xf0, 0x0e, 0x31, + 0xcf, 0xe1, 0x45, 0xc0, 0x37, 0x53, 0x1d, 0xc5, 0x0e, 0x32, 0xe6, 0xff, 0x1e, + 0x81, 0x02, 0x34, 0xba, 0xff, 0xf9, 0x1c, 0x30, 0xb2, 0x40, 0x59, 0x0c, 0x09, + 0x26, 0xa5, 0xee, 0x0f, 0xfc, 0x13, 0xb5, 0x12, 0xfb, 0x2a, 0xdd, 0xf7, 0x42, + 0xe4, 0xe3, 0xd0, 0xe8, 0xda, 0xd3, 0xda, 0x08, 0xe5, 0xbf, 0x3a, 0xdf, 0xc2, + 0x06, 0xe7, 0xc6, 0x2f, 0x00, 0xe8, 0xef, 0xec, 0xd7, 0xf0, 0xae, 0x4e, 0xdd, + 0x0d, 0xe2, 0xb2, 0xc2, 0xdf, 0x5c, 0x16, 0xc0, 0x59, 0xfc, 0xbe, 0xdc, 0x16, + 0x64, 0xf1, 0xef, 0x1c, 0xf6, 0x08, 0xc6, 0x16, 0x7f, 0xe4, 0x5b, 0x0b, 0xf9, + 0xf0, 0xeb, 0xd5, 0xf6, 0x2d, 0x05, 0x19, 0xf1, 0x10, 0xb3, 0xe9, 0xd2, 0xed, + 0xfd, 0x20, 0x07, 0xe5, 0x38, 0xf3, 0x0b, 0x64, 0xbf, 0xf5, 0xf8, 0xc5, 0x08, + 0x25, 0xeb, 0xfb, 0x6a, 0xc9, 0xbb, 0xe9, 0x30, 0xeb, 0x39, 0xc3, 0xff, 0x13, + 0xe8, 0x11, 0xe5, 0x39, 0xc1, 0x64, 0xc9, 0x0d, 0x32, 0x07, 0xd1, 0xdd, 0x00, + 0x39, 0xf0, 0x00, 0x1f, 0x13, 0x27, 0xe3, 0x02, 0x4a, 0xbe, 0x12, 0xfc, 0xfd, + 0x15, 0xf1, 0xe1, 0x11, 0x26, 0x3c, 0xe1, 0x10, 0x4b, 0x6a, 0xf0, 0xc8, 0xe8, + 0x47, 0xfa, 0x31, 0x1c, 0xcd, 0xd5, 0xce, 0x59, 0xe5, 0xf3, 0xd5, 0x35, 0xcf, + 0xd9, 0xe4, 0xfd, 0xc1, 0xd2, 0xbf, 0x4e, 0xe9, 0x0f, 0xe5, 0xcc, 0x10, 0xe2, + 0xab, 0x17, 0xd9, 0xfa, 0xd4, 0x4d, 0x19, 0x04, 0x02, 0x03, 0xad, 0xf5, 0x3b, + 0xd8, 0xed, 0x4c, 0xc4, 0xe5, 0xd7, 0x0b, 0xec, 0xeb, 0x28, 0x4b, 0xed, 0xcf, + 0x45, 0xca, 0xc3, 0x04, 0x1e, 0x39, 0x25, 0xc0, 0x39, 0xfb, 0x21, 0x20, 0x05, + 0x1e, 0x35, 0xfd, 0xcc, 0x2f, 0xdd, 0x15, 0x44, 0xfb, 0xf5, 0xe5, 0xbe, 0x0f, + 0xe1, 0x23, 0x19, 0xdd, 0x11, 0x20, 0xd9, 0xe3, 0x08, 0xfb, 0x0f, 0x07, 0x2a, + 0x15, 0xf2, 0x13, 0xbd, 0x2b, 0xf3, 0x19, 0xf5, 0x81, 0xe5, 0x16, 0xd1, 0x3d, + 0xbf, 0x09, 0x1c, 0x16, 0xfe, 0xd6, 0xd8, 0x3f, 0x2c, 0xff, 0x16, 0xf8, 0xfa, + 0x5a, 0xe0, 0x05, 0xb9, 0x00, 0xcb, 0xb1, 0xf1, 0x1e, 0xcf, 0x3b, 0xf7, 0xb9, + 0xe6, 0xfb, 0x0c, 0xef, 0x24, 0x19, 0xd3, 0xd8, 0xbf, 0x36, 0x5b, 0x04, 0xf6, + 0xc8, 0xdf, 0x19, 0x06, 0xd5, 0x1c, 0x08, 0x0d, 0xe7, 0xdd, 0xea, 0xbf, 0xec, + 0xea, 0x70, 0xe3, 0xcd, 0xba, 0x26, 0xe5, 0x08, 0x7f, 0xd1, 0x0d, 0x09, 0x12, + 0x0a, 0xc1, 0xed, 0xf8, 0xfd, 0xf5, 0x33, 0x01, 0x0f, 0xde, 0xcc, 0xf6, 0xb5, + 0x2c, 0xea, 0xfa, 0xe3, 0x07, 0x0e, 0x4e, 0x28, 0x04, 0xd2, 0xda, 0xfe, 0xdf, + 0x21, 0xdd, 0xe7, 0x4a, 0x00, 0xcb, 0x99, 0x10, 0x28, 0xed, 0x0e, 0xee, 0xef, + 0x0a, 0xeb, 0xd9, 0x50, 0xf8, 0xcb, 0x3f, 0x01, 0xfe, 0x0c, 0xd6, 0x00, 0x16, + 0x30, 0x0b, 0xeb, 0xf3, 0x20, 0x12, 0x07, 0x50, 0x1e, 0x05, 0xc0, 0x20, 0xdf, + 0xdb, 0x23, 0xce, 0xe5, 0xeb, 0x25, 0xdf, 0xe9, 0xe9, 0xcc, 0xf3, 0x2e, 0x1d, + 0xf1, 0x1b, 0x04, 0x4a, 0x41, 0x73, 0xa9, 0x65, 0x01, 0x2d, 0xbb, 0xee, 0x0f, + 0xd4, 0xb7, 0x4c, 0xb2, 0x34, 0xeb, 0x05, 0xa4, 0xc1, 0x10, 0xd3, 0xe2, 0x9e, + 0x90, 0x27, 0x29, 0xf9, 0xc5, 0x2b, 0xee, 0xc2, 0xe6, 0xff, 0xe6, 0x35, 0xfe, + 0xcf, 0x3a, 0xe0, 0xea, 0x37, 0xd9, 0x06, 0xf4, 0xbe, 0x42, 0x42, 0xe0, 0xe4, + 0xe7, 0x3f, 0x35, 0x4c, 0x0c, 0xe4, 0xb3, 0xaf, 0x1f, 0xbc, 0xcb, 0x4d, 0x05, + 0x10, 0xf9, 0xf4, 0x7f, 0x1b, 0x0e, 0x26, 0xef, 0x16, 0x02, 0xfb, 0x2a, 0x12, + 0x48, 0x1d, 0x07, 0xde, 0x95, 0xda, 0x37, 0x3f, 0xdd, 0x1f, 0x2a, 0x0e, 0xfe, + 0xd9, 0xf6, 0xd3, 0x00, 0x13, 0xf2, 0xd6, 0x43, 0x0a, 0x0c, 0xbf, 0xcf, 0x3f, + 0xf5, 0xe6, 0xfb, 0xec, 0x01, 0xf5, 0xd2, 0x18, 0x1c, 0x44, 0xcf, 0xfd, 0x31, + 0xcc, 0x3f, 0x12, 0x10, 0x1e, 0x04, 0xa2, 0x4f, 0xcd, 0x12, 0x10, 0xb6, 0xc8, + 0x40, 0x1b, 0x25, 0x17, 0xb9, 0xff, 0xdd, 0x0c, 0xfc, 0xe1, 0x1b, 0x0f, 0xd7, + 0xd7, 0x3b, 0xfe, 0x02, 0xbc, 0xda, 0xdf, 0xaf, 0xd7, 0xd8, 0xe8, 0x44, 0xd1, + 0x7b, 0xee, 0x27, 0xca, 0xd1, 0x10, 0xce, 0x8f, 0x3f, 0xcc, 0x36, 0x0f, 0x23, + 0xf1, 0xff, 0x0e, 0xd3, 0xc3, 0x1f, 0xfe, 0x35, 0x09, 0x64, 0xbd, 0xf9, 0x0c, + 0x49, 0xcc, 0x0e, 0x26, 0x07, 0x1e, 0xd8, 0x10, 0xd8, 0xef, 0x2f, 0xda, 0x40, + 0x02, 0xa9, 0xf9, 0xd2, 0xf7, 0xf8, 0xf5, 0x1c, 0x4f, 0x0b, 0x0e, 0x2b, 0x26, + 0xf3, 0x78, 0x4b, 0x35, 0x2d, 0xf7, 0x3b, 0xe1, 0x48, 0x8c, 0x00, 0x12, 0x01, + 0x81, 0xf9, 0xe9, 0x2e, 0x2d, 0xe5, 0x40, 0x15, 0x55, 0x12, 0xe0, 0x17, 0x0b, + 0x28, 0xd3, 0xab, 0xf7, 0x04, 0xaf, 0x67, 0x02, 0x69, 0xef, 0x25, 0x10, 0xfa, + 0xec, 0xcb, 0x2a, 0x03, 0x1b, 0xef, 0xe7, 0x0d, 0x04, 0x55, 0xfc, 0x2b, 0x20, + 0xbc, 0xaa, 0x2e, 0xde, 0xd5, 0x59, 0x1e, 0x19, 0xd8, 0x04, 0xdd, 0xeb, 0x54, + 0x01, 0x04, 0x4a, 0x1c, 0xe1, 0x15, 0x27, 0x35, 0xdd, 0xc1, 0xe3, 0x2e, 0x04, + 0x2d, 0x0e, 0xd2, 0xfa, 0xd0, 0x38, 0xf0, 0xd7, 0xaf, 0x4c, 0xf5, 0x08, 0x14, + 0x03, 0x2a, 0xcf, 0x07, 0x1a, 0x08, 0xf9, 0xc1, 0x13, 0xb4, 0xde, 0x27, 0x7f, + 0xc9, 0x34, 0x37, 0x24, 0xe6, 0x3c, 0xd8, 0xaf, 0x06, 0x0c, 0x19, 0xbe, 0x2a, + 0xf4, 0xbe, 0x54, 0x17, 0xdf, 0xfe, 0x33, 0xda, 0x53, 0x0e, 0x4b, 0xe8, 0xf0, + 0xaf, 0x1a, 0x0b, 0x00, 0xc8, 0xcd, 0x56, 0x10, 0xe6, 0x51, 0x1b, 0x4c, 0xe8, + 0xd6, 0x14, 0xd8, 0x31, 0x18, 0xd0, 0x07, 0xde, 0xe5, 0xea, 0x11, 0xdb, 0xe3, + 0x5d, 0x26, 0x5f, 0x09, 0xc5, 0x28, 0x31, 0x15, 0x0e, 0x59, 0x09, 0xf6, 0x5a, + 0xee, 0xab, 0x26, 0x29, 0x3b, 0x31, 0xd7, 0x21, 0xea, 0x1c, 0x52, 0xe5, 0x25, + 0x18, 0xc1, 0xe0, 0xf0, 0x18, 0x30, 0xf8, 0xdb, 0xd2, 0x34, 0x08, 0x29, 0xff, + 0xe0, 0xec, 0x0c, 0x44, 0xf3, 0xde, 0xec, 0x16, 0xbd, 0x06, 0xf3, 0x0f, 0x04, + 0xe4, 0x15, 0x28, 0xf2, 0xea, 0x3a, 0xb9, 0x16, 0xf7, 0x49, 0x10, 0x01, 0xca, + 0x44, 0x14, 0xe9, 0x2e, 0x17, 0xea, 0x37, 0xdb, 0x05, 0x30, 0x06, 0x7f, 0xfe, + 0xff, 0x24, 0xfb, 0xeb, 0x2c, 0x2a, 0xe5, 0x20, 0xf9, 0xf4, 0xe9, 0x09, 0xf4, + 0xdc, 0xe0, 0x36, 0xed, 0xef, 0xfe, 0x08, 0xfb, 0x58, 0xe5, 0xee, 0x11, 0xb6, + 0x17, 0x49, 0xfa, 0xfd, 0x27, 0xc5, 0x01, 0xdb, 0xa4, 0xef, 0x1a, 0xe5, 0x21, + 0x39, 0x0b, 0xf9, 0xf1, 0x2e, 0xf6, 0x10, 0x2e, 0x08, 0xf9, 0x22, 0xd7, 0xc4, + 0x16, 0x0f, 0xfb, 0xf7, 0x2c, 0x0c, 0x09, 0xdc, 0xdf, 0xff, 0xe9, 0xe2, 0xf9, + 0x09, 0x13, 0x10, 0xc9, 0xe5, 0x25, 0x0a, 0xd0, 0x26, 0xfd, 0xff, 0xee, 0xef, + 0x0d, 0x29, 0x10, 0xec, 0x0d, 0xc8, 0xfb, 0x09, 0xed, 0xfe, 0xe6, 0xfc, 0x20, + 0xf4, 0xfb, 0x09, 0xce, 0x08, 0xf9, 0xdc, 0xe7, 0x6b, 0xe1, 0xf0, 0x02, 0x03, + 0xa8, 0x25, 0x22, 0x13, 0x63, 0x1f, 0x65, 0xf3, 0xf6, 0xff, 0x15, 0x08, 0xdb, + 0x09, 0xed, 0x78, 0xf4, 0x03, 0x11, 0x12, 0xec, 0xfe, 0xea, 0xe8, 0xe6, 0x09, + 0x7f, 0x39, 0xfc, 0x00, 0x0c, 0xf0, 0x0f, 0x20, 0xff, 0x05, 0x09, 0xe4, 0x08, + 0xf2, 0x0b, 0x02, 0xde, 0x1a, 0x32, 0xf3, 0x10, 0x0f, 0xde, 0xdb, 0xd7, 0xf3, + 0x2a, 0xf4, 0x29, 0x34, 0x1d, 0xe2, 0x2c, 0xd4, 0xf5, 0x14, 0x09, 0x0f, 0x35, + 0x00, 0xba, 0x04, 0x0c, 0x0d, 0xe0, 0x41, 0x01, 0xe0, 0x55, 0x58, 0x1d, 0xf3, + 0x4f, 0xfb, 0xdc, 0xfc, 0xf5, 0x41, 0x0f, 0x0f, 0x2e, 0xeb, 0x2a, 0xff, 0x22, + 0xb9, 0xe3, 0xe8, 0xfa, 0xe6, 0x26, 0xee, 0x3a, 0x17, 0x2b, 0xf4, 0x21, 0x07, + 0x28, 0xb9, 0x28, 0x81, 0xad, 0xf8, 0xf2, 0xc5, 0xb2, 0x1c, 0x36, 0x4f, 0xe2, + 0x41, 0x2e, 0xd3, 0xc6, 0xf3, 0x6a, 0xc0, 0x02, 0x96, 0x09, 0xd5, 0x04, 0xb4, + 0x3f, 0xe8, 0x17, 0x09, 0x23, 0xff, 0xf0, 0xf9, 0xe0, 0x04, 0x0e, 0x2d, 0xc8, + 0x23, 0x56, 0xd5, 0x15, 0x09, 0xe0, 0xcb, 0xc5, 0x36, 0x4d, 0xcb, 0xcd, 0x0f, + 0x3f, 0xfa, 0x69, 0x0d, 0x5f, 0x29, 0x27, 0xf2, 0xae, 0x38, 0xeb, 0x1f, 0x34, + 0xde, 0x3e, 0x24, 0x13, 0xf5, 0xf0, 0x06, 0xb5, 0xe8, 0xf6, 0xf4, 0x18, 0xbd, + 0x12, 0xe9, 0x22, 0x22, 0xf2, 0xcf, 0x2b, 0xe0, 0x74, 0x06, 0xd5, 0xc9, 0xea, + 0xe6, 0xbf, 0xfe, 0xec, 0xf7, 0xf5, 0xe6, 0xcb, 0x03, 0xfe, 0xfc, 0x67, 0xfd, + 0xae, 0x2b, 0x25, 0xd2, 0x64, 0x0d, 0xc3, 0x0e, 0x4d, 0x15, 0xf7, 0xcc, 0xea, + 0x0b, 0x16, 0x12, 0x1c, 0xec, 0xa2, 0x5f, 0x4b, 0x3b, 0x3c, 0xdf, 0x32, 0xe6, + 0xd8, 0xfe, 0x3b, 0xdf, 0x1d, 0x14, 0x60, 0x5b, 0x09, 0xd1, 0xb2, 0xf2, 0xbf, + 0x39, 0x2e, 0xf4, 0xe4, 0xf7, 0x28, 0x22, 0xf5, 0x01, 0xc0, 0x40, 0xc6, 0xe4, + 0xa3, 0x59, 0xd0, 0x07, 0xb9, 0xd6, 0x09, 0x05, 0xe8, 0xf7, 0x7f, 0x97, 0x18, + 0x28, 0x3c, 0xfe, 0x32, 0x54, 0x49, 0xec, 0xf9, 0x3f, 0x03, 0x0d, 0xbf, 0x0a, + 0xe3, 0xf9, 0xc8, 0xe0, 0xe9, 0xe9, 0xd2, 0x2d, 0xd8, 0x9b, 0x15, 0xeb, 0x29, + 0x78, 0x4d, 0x20, 0xc0, 0x07, 0x0c, 0x2c, 0xc5, 0xe7, 0xf1, 0xfc, 0x2d, 0x2f, + 0x02, 0xff, 0xfe, 0x39, 0x2c, 0x0d, 0xfa, 0x03, 0x00, 0x1b, 0x15, 0x49, 0x03, + 0xf6, 0x1f, 0x17, 0xee, 0x4b, 0x13, 0x9e, 0xe7, 0x04, 0xfe, 0x1e, 0x30, 0xf2, + 0x1c, 0xe0, 0xf3, 0xea, 0x63, 0xfa, 0x2a, 0x26, 0xec, 0xfb, 0xec, 0xfa, 0xcc, + 0xde, 0xb8, 0xf4, 0x16, 0xc1, 0x27, 0xf0, 0xf3, 0x12, 0x1a, 0x4d, 0xd2, 0x26, + 0x23, 0x1c, 0x08, 0x43, 0x08, 0x7f, 0xf5, 0xc7, 0xc6, 0xeb, 0xd9, 0x2b, 0x3a, + 0xe7, 0xfe, 0x10, 0xf6, 0xda, 0xfa, 0x07, 0xdf, 0x1c, 0x15, 0x13, 0xfe, 0x19, + 0xfe, 0x20, 0xf0, 0xd6, 0xf0, 0x02, 0xfa, 0x0f, 0x50, 0xe9, 0xf7, 0x1f, 0xeb, + 0xf7, 0x4c, 0x17, 0x23, 0x03, 0x10, 0x32, 0x26, 0xf8, 0xd5, 0x1e, 0x12, 0xf8, + 0xcd, 0xe9, 0xef, 0xe9, 0xe8, 0xf7, 0x12, 0xf6, 0xcd, 0x01, 0x04, 0x32, 0x1b, + 0x23, 0x00, 0x0a, 0x44, 0xee, 0xd7, 0x50, 0xff, 0xf3, 0x31, 0xe6, 0xe4, 0xde, + 0xf8, 0xd5, 0xe0, 0x10, 0xfe, 0x11, 0xfd, 0xe9, 0xe4, 0x53, 0x07, 0x0d, 0xea, + 0x2f, 0xd5, 0x09, 0xf4, 0x01, 0x03, 0x2d, 0xc1, 0x12, 0x1c, 0xf8, 0xf7, 0xe7, + 0x1c, 0xf7, 0xf1, 0x10, 0x00, 0x25, 0xb9, 0xee, 0xf0, 0x15, 0xec, 0xea, 0x42, + 0x18, 0xa7, 0x09, 0x37, 0x0c, 0xc7, 0x0f, 0xd6, 0xd7, 0x08, 0x79, 0x6e, 0xd7, + 0xf9, 0x25, 0x0c, 0xcb, 0x41, 0xdb, 0xe0, 0x73, 0x12, 0x0a, 0xd7, 0xd0, 0xc9, + 0x25, 0x39, 0x0f, 0x07, 0x21, 0xd4, 0xc9, 0xaf, 0x20, 0x07, 0xfc, 0xcc, 0xed, + 0x2f, 0xde, 0xf0, 0x66, 0x0f, 0x3b, 0x1d, 0xb0, 0xf4, 0x89, 0x33, 0xeb, 0x43, + 0x1e, 0xfe, 0xd0, 0x3c, 0x73, 0x26, 0xe9, 0x0e, 0x25, 0xf0, 0x25, 0xfa, 0xf2, + 0xd8, 0x7d, 0xf3, 0x1f, 0x06, 0x03, 0xf7, 0xc3, 0x1c, 0xfa, 0x47, 0x53, 0xd4, + 0x01, 0xb1, 0xd7, 0x30, 0x11, 0xd6, 0xcd, 0x39, 0x08, 0xa0, 0xe9, 0x3d, 0xf5, + 0xe6, 0xa9, 0x08, 0x3e, 0x2b, 0x0d, 0x30, 0x67, 0xac, 0x4e, 0x47, 0xfb, 0xd5, + 0xf3, 0xdb, 0x93, 0xff, 0x42, 0xd9, 0xfa, 0x2e, 0x01, 0x1f, 0x81, 0x1d, 0x06, + 0x51, 0xca, 0x51, 0xe4, 0x30, 0xe7, 0x1d, 0xf1, 0x13, 0x3b, 0xda, 0x20, 0x13, + 0x3d, 0x36, 0x30, 0xf8, 0xe6, 0xf2, 0x0d, 0x1b, 0x0b, 0x3a, 0xf9, 0xc9, 0x23, + 0x7f, 0x2d, 0xbb, 0xed, 0x04, 0xe5, 0x06, 0x2e, 0x19, 0x42, 0xc6, 0x40, 0xed, + 0x0b, 0xf9, 0x05, 0x07, 0xf7, 0x05, 0x08, 0x38, 0xcb, 0xed, 0xf0, 0xe2, 0xfc, + 0xb1, 0x59, 0xef, 0x20, 0x03, 0xde, 0x21, 0xf8, 0x3d, 0xe8, 0x15, 0xdd, 0x15, + 0x2a, 0xe8, 0xd8, 0x4a, 0x1d, 0x10, 0x28, 0xed, 0x0f, 0xcc, 0x04, 0x39, 0x40, + 0xd0, 0x04, 0xf0, 0xee, 0x0f, 0x04, 0x18, 0xe7, 0xc4, 0x16, 0x0b, 0xe5, 0x14, + 0x62, 0x13, 0x22, 0xec, 0x62, 0xd0, 0xfd, 0x1d, 0x78, 0xf1, 0xf7, 0xde, 0x3d, + 0xfc, 0xd8, 0x1f, 0xeb, 0x51, 0x07, 0xf8, 0x55, 0xf2, 0x42, 0xc7, 0xcb, 0xd4, + 0xf1, 0x02, 0xec, 0x28, 0xf9, 0xc7, 0x6d, 0xca, 0x23, 0xee, 0xd7, 0x0a, 0x38, + 0x0c, 0x08, 0xe2, 0xea, 0x08, 0xde, 0xfc, 0x26, 0x09, 0xea, 0x24, 0x1d, 0xe9, + 0x26, 0x15, 0x03, 0xf6, 0xfe, 0xf7, 0x01, 0x03, 0xde, 0x04, 0xea, 0xec, 0xe7, + 0x2f, 0xf7, 0x37, 0x02, 0x15, 0xc5, 0xe7, 0xd4, 0x30, 0x5c, 0xae, 0xf9, 0xef, + 0xf1, 0xb8, 0x02, 0x1b, 0xa5, 0x0f, 0xe4, 0xf8, 0xdf, 0xfd, 0xd4, 0x2f, 0xba, + 0x32, 0xa7, 0xdb, 0xf7, 0xca, 0x11, 0xb8, 0xd9, 0xe8, 0x16, 0xf2, 0xfa, 0x08, + 0xda, 0xfd, 0xf4, 0xb7, 0x40, 0xbf, 0xcb, 0x0b, 0x34, 0xf5, 0xcd, 0xf7, 0x9e, + 0x16, 0x07, 0x07, 0x0e, 0xf0, 0xc6, 0x27, 0x26, 0x33, 0x01, 0xd3, 0xc0, 0xaf, + 0xdf, 0xe0, 0x15, 0x04, 0x0b, 0xbe, 0xc0, 0xce, 0xc6, 0x1f, 0xdc, 0xd3, 0x0b, + 0xfa, 0xa9, 0x03, 0xf4, 0x4e, 0x0f, 0xb7, 0xed, 0x0a, 0xf6, 0x71, 0x81, 0x05, + 0xe5, 0xf0, 0x06, 0xd9, 0x06, 0x35, 0x1a, 0xaf, 0x05, 0x49, 0x08, 0xf1, 0xe5, + 0xdf, 0xf6, 0xb7, 0x56, 0xfd, 0xe4, 0x05, 0xe3, 0xc4, 0x30, 0xf0, 0x2a, 0xfc, + 0x1a, 0x8d, 0xb1, 0x16, 0x9b, 0x00, 0x48, 0xe2, 0x15, 0xf9, 0x04, 0xe8, 0xc8, + 0x30, 0xce, 0xe9, 0xf3, 0x03, 0x3f, 0xd1, 0x99, 0x15, 0x05, 0x77, 0x28, 0xc7, + 0xd4, 0xc0, 0x5a, 0xed, 0x07, 0xdf, 0xe3, 0xf2, 0xf0, 0xca, 0x74, 0x18, 0xc6, + 0x0d, 0xd1, 0xee, 0x93, 0x0f, 0x2a, 0x6a, 0xc3, 0x02, 0x1c, 0xff, 0xd3, 0x0b, + 0xc0, 0xa0, 0x35, 0x05, 0x37, 0xf2, 0x4a, 0x21, 0xe3, 0xbb, 0xb9, 0xcd, 0x1b, + 0x1f, 0xcb, 0x44, 0x14, 0xc5, 0x2d, 0x07, 0x09, 0xfc, 0x03, 0x10, 0xfd, 0xe9, + 0xe4, 0x17, 0xe7, 0xa8, 0x87, 0xe5, 0xee, 0x30, 0xe9, 0x05, 0x07, 0xca, 0x02, + 0x04, 0x25, 0x08, 0x49, 0xcc, 0xfd, 0xf2, 0x51, 0xe9, 0xdc, 0xbf, 0x31, 0xd2, + 0xf1, 0xf7, 0x29, 0x4f, 0xb4, 0x31, 0x5b, 0xcd, 0xf5, 0x50, 0x20, 0x5f, 0xe6, + 0x01, 0x13, 0x03, 0x03, 0xd2, 0x22, 0x7f, 0x43, 0x8b, 0x2a, 0xe0, 0xed, 0xd2, + 0x1d, 0xe2, 0xec, 0xdb, 0x05, 0x06, 0x66, 0xfe, 0x27, 0x03, 0xf4, 0xf2, 0x09, + 0x16, 0xca, 0xfa, 0xde, 0x05, 0xc9, 0xef, 0x07, 0x1f, 0x12, 0xe8, 0x41, 0x01, + 0x0a, 0xdd, 0xb2, 0xf3, 0xe7, 0x0e, 0x16, 0xfa, 0x0f, 0xdf, 0x2e, 0x31, 0xcd, + 0xf7, 0xbb, 0x03, 0x14, 0x1f, 0xed, 0x36, 0x34, 0xf4, 0xba, 0x7f, 0xd2, 0xba, + 0x16, 0x0b, 0x05, 0xf2, 0x1d, 0x36, 0xfc, 0xff, 0xee, 0xf5, 0x0f, 0x1a, 0xeb, + 0x0a, 0xfa, 0xe7, 0x27, 0x17, 0xf8, 0xec, 0x27, 0x15, 0x2d, 0xea, 0x06, 0xd8, + 0xdb, 0xad, 0xfb, 0xe4, 0x14, 0xeb, 0x08, 0x21, 0x01, 0xd4, 0x05, 0x0b, 0x3f, + 0xd7, 0xc7, 0x20, 0x0a, 0xf7, 0xd6, 0x0b, 0x67, 0xc1, 0x03, 0x05, 0x20, 0x0a, + 0xb5, 0xe0, 0x2d, 0xc1, 0xf6, 0xd2, 0xfb, 0xf0, 0x2e, 0xfd, 0x0d, 0x0d, 0x07, + 0x1e, 0xf4, 0x07, 0x3f, 0xfa, 0x09, 0x27, 0x0d, 0x17, 0xfa, 0xfe, 0x05, 0xfd, + 0x17, 0x0d, 0xf9, 0x15, 0x20, 0xe9, 0x25, 0x03, 0xf3, 0xdc, 0x0a, 0x03, 0xf5, + 0x2a, 0xef, 0x0a, 0x05, 0x0a, 0xdc, 0x02, 0x1a, 0xe9, 0x04, 0xe1, 0xf6, 0xf3, + 0xee, 0x03, 0x09, 0x07, 0xce, 0x1d, 0xed, 0x1c, 0x01, 0x22, 0x22, 0x03, 0x03, + 0x07, 0x17, 0x7f, 0x16, 0x1b, 0xf7, 0x08, 0xe5, 0x05, 0xf6, 0xed, 0x1c, 0xf7, + 0x02, 0xe9, 0xec, 0xed, 0x27, 0xfd, 0x00, 0xe1, 0xf7, 0xed, 0x07, 0x05, 0x0d, + 0x1a, 0x24, 0x04, 0xef, 0x21, 0x16, 0xf9, 0x0b, 0x05, 0xf8, 0x25, 0xf0, 0x01, + 0xec, 0x0f, 0xeb, 0x06, 0x0e, 0x03, 0xf7, 0xee, 0xf2, 0x04, 0x45, 0xe7, 0x0e, + 0xee, 0x1a, 0xf5, 0x11, 0x14, 0x0c, 0xfe, 0xfa, 0x0f, 0xf4, 0x12, 0xf7, 0x0a, + 0xfc, 0xf9, 0x00, 0xff, 0xec, 0xe8, 0x09, 0xee, 0xf6, 0x12, 0xea, 0xf4, 0x01, + 0x17, 0xfd, 0xe0, 0x15, 0x13, 0x37, 0x5c, 0xfb, 0xea, 0xae, 0xe3, 0xeb, 0xfe, + 0x95, 0xee, 0x54, 0xf1, 0x14, 0xe2, 0x2f, 0xd9, 0xf8, 0xc5, 0xea, 0xb0, 0xbb, + 0xac, 0x10, 0xfc, 0xd6, 0xfa, 0x2b, 0xff, 0xdd, 0xdb, 0x28, 0x05, 0xbd, 0xc5, + 0x48, 0x0c, 0x08, 0x10, 0xe5, 0xf6, 0x7f, 0xfe, 0x03, 0x1d, 0xed, 0x02, 0x02, + 0x06, 0x16, 0x34, 0x01, 0x35, 0x9e, 0x03, 0x12, 0xd3, 0x3d, 0x0d, 0x0f, 0x3f, + 0xee, 0x30, 0x4b, 0x1e, 0xfa, 0x1a, 0xe7, 0xea, 0x05, 0x50, 0x0b, 0x5e, 0x78, + 0xfb, 0x2f, 0xbf, 0x17, 0xf7, 0xf2, 0x50, 0xf6, 0x24, 0x52, 0xf3, 0xe5, 0x76, + 0x43, 0x37, 0xec, 0x3e, 0xea, 0xf2, 0x2e, 0x21, 0xef, 0x0f, 0xcf, 0x2c, 0x11, + 0xf1, 0x1c, 0xf4, 0xff, 0x1f, 0x57, 0xe7, 0x07, 0xbe, 0x05, 0x70, 0xdf, 0x22, + 0xef, 0x63, 0x41, 0x69, 0xae, 0x07, 0x2d, 0x4e, 0xd6, 0x08, 0xe8, 0xfb, 0x29, + 0x24, 0x11, 0x16, 0xe9, 0x20, 0x2f, 0xf4, 0x12, 0x24, 0xef, 0x02, 0xf5, 0xe6, + 0x2f, 0xef, 0x07, 0xb4, 0xd0, 0xf2, 0x2f, 0xf9, 0x28, 0x00, 0xec, 0xa0, 0x39, + 0xd9, 0x23, 0x06, 0x11, 0xda, 0x1c, 0xea, 0x07, 0x32, 0x0d, 0x1f, 0x0b, 0x20, + 0xee, 0x0d, 0x76, 0x1d, 0xb1, 0xed, 0xde, 0x02, 0x28, 0xeb, 0x53, 0x11, 0xe9, + 0x26, 0xde, 0xf5, 0x3c, 0x1f, 0x21, 0xb4, 0xf3, 0xe3, 0x06, 0xfc, 0xe0, 0x4b, + 0xcf, 0x2f, 0x49, 0xfe, 0xf9, 0x03, 0xab, 0x1f, 0x62, 0xa0, 0x1e, 0x20, 0xfb, + 0x27, 0xd4, 0xda, 0x01, 0x2b, 0x14, 0x0e, 0x09, 0x45, 0xbb, 0x33, 0x16, 0xf8, + 0x16, 0x3e, 0xfa, 0x15, 0x0c, 0xfd, 0x10, 0x21, 0x19, 0x16, 0xed, 0x2e, 0x5e, + 0x7f, 0x10, 0x53, 0xca, 0x4b, 0x22, 0x49, 0x06, 0x32, 0xc3, 0x2a, 0x1f, 0x26, + 0xef, 0x37, 0x13, 0x16, 0x16, 0xd1, 0x40, 0x04, 0x23, 0xe6, 0x41, 0xe2, 0x33, + 0xcf, 0x24, 0x03, 0x0b, 0x18, 0xf1, 0xfa, 0xfa, 0xb5, 0x32, 0x0c, 0x1b, 0x07, + 0x28, 0xea, 0xb8, 0x81, 0xfa, 0x06, 0x34, 0x16, 0x26, 0x02, 0x1b, 0x04, 0xfe, + 0x16, 0x18, 0xe2, 0x0b, 0xf4, 0xbf, 0xfc, 0xff, 0xdf, 0x24, 0xc9, 0xf4, 0xfa, + 0x0b, 0xfb, 0xcf, 0x02, 0x08, 0xda, 0x0f, 0x15, 0x03, 0xf8, 0xdd, 0x18, 0x02, + 0xf5, 0x1b, 0x25, 0x0c, 0x39, 0x1b, 0xda, 0xef, 0xe9, 0x0c, 0x08, 0xec, 0xd2, + 0xf8, 0xe5, 0xe1, 0x1c, 0xed, 0xe4, 0x0d, 0xc4, 0x10, 0xec, 0x22, 0x23, 0x1c, + 0xbc, 0x0d, 0xf0, 0x05, 0xe7, 0xf7, 0xe3, 0x56, 0xde, 0x1d, 0xf6, 0x01, 0xe8, + 0xf7, 0xf7, 0x0e, 0x22, 0xef, 0x02, 0x0f, 0xe1, 0x1e, 0xda, 0xd7, 0xee, 0xe6, + 0x03, 0x2b, 0xd0, 0x17, 0xf0, 0x2b, 0xea, 0x04, 0x08, 0xf7, 0xdd, 0x14, 0x0d, + 0x1d, 0xd0, 0x1e, 0xdc, 0xf2, 0xbe, 0x20, 0xeb, 0x1c, 0x23, 0x0c, 0x1c, 0x37, + 0x02, 0x04, 0x3a, 0x05, 0x01, 0xc3, 0x43, 0xf9, 0xc6, 0x10, 0x54, 0x2c, 0xf4, + 0xd2, 0xfc, 0x04, 0x06, 0x11, 0xb5, 0xe6, 0x00, 0x10, 0xf9, 0x0d, 0x25, 0x17, + 0x08, 0xf7, 0x32, 0x57, 0xbd, 0xf1, 0x42, 0xfc, 0xe7, 0x00, 0xf4, 0x17, 0x1a, + 0xe0, 0x30, 0xf9, 0x15, 0x2a, 0x45, 0x24, 0x21, 0xfa, 0xed, 0xef, 0xe6, 0x11, + 0xf0, 0x69, 0x39, 0x23, 0x12, 0xc8, 0xf8, 0x08, 0xfd, 0xd9, 0xf3, 0x08, 0x01, + 0x0f, 0x22, 0xd4, 0xf2, 0x3a, 0xe2, 0xec, 0xf2, 0xf8, 0x62, 0xe5, 0x68, 0x23, + 0x01, 0x50, 0xef, 0xe2, 0xd2, 0x1d, 0xee, 0x19, 0x0c, 0x01, 0x01, 0x07, 0xdd, + 0xdd, 0xfc, 0x10, 0x06, 0x26, 0xf5, 0xe9, 0x0d, 0xc6, 0x08, 0xf1, 0x02, 0xfe, + 0x1e, 0xf7, 0x2f, 0xd7, 0xee, 0xe7, 0xff, 0x02, 0x0c, 0x04, 0xfa, 0x2b, 0xd1, + 0x0b, 0xf2, 0xfe, 0x06, 0x19, 0xf9, 0x02, 0x7f, 0x0f, 0x03, 0xf9, 0xdd, 0xf4, + 0x4f, 0xfc, 0x31, 0xf0, 0x37, 0xdd, 0x1c, 0x5d, 0x0e, 0x3a, 0xe4, 0xa5, 0xe2, + 0xfd, 0xe4, 0xc4, 0x7f, 0x19, 0x26, 0xf7, 0x20, 0xca, 0xfa, 0x02, 0x46, 0x5a, + 0xe2, 0x00, 0x1b, 0xff, 0x36, 0x2d, 0x12, 0x0c, 0xd1, 0xf5, 0x32, 0xc7, 0x01, + 0xf4, 0xd7, 0x66, 0x14, 0xd9, 0x08, 0xdf, 0xf1, 0xd8, 0xdc, 0x01, 0x36, 0x25, + 0xff, 0x3f, 0xf8, 0xf5, 0xae, 0xdc, 0x1c, 0xd9, 0x0a, 0x7d, 0xde, 0xe6, 0x1d, + 0x27, 0x1c, 0x27, 0x02, 0xea, 0x98, 0xdb, 0xdb, 0x08, 0xdd, 0xf2, 0x10, 0xe8, + 0xfc, 0x26, 0x11, 0x14, 0xf7, 0x3e, 0x07, 0x07, 0x3c, 0x27, 0xff, 0xfa, 0x24, + 0xe0, 0x45, 0x05, 0x2e, 0xce, 0x01, 0xfd, 0x56, 0xed, 0xe9, 0x4e, 0x2f, 0xfe, + 0x0d, 0xe1, 0xe6, 0x1b, 0x06, 0xea, 0x3b, 0x15, 0xea, 0xa9, 0x00, 0x05, 0x15, + 0xde, 0x82, 0x36, 0xdb, 0x11, 0xbe, 0xe1, 0x2b, 0x09, 0x28, 0x46, 0x5d, 0xde, + 0x36, 0x27, 0xfc, 0x50, 0xd0, 0x33, 0x0d, 0x10, 0x3b, 0xfd, 0xe3, 0xdf, 0x01, + 0xf6, 0xbc, 0x48, 0x2e, 0xfe, 0x1b, 0x2f, 0x20, 0xed, 0xf8, 0xfb, 0x8e, 0xf5, + 0xc3, 0x2e, 0x48, 0x68, 0xef, 0x3b, 0x40, 0xf1, 0xe8, 0xaf, 0x23, 0xeb, 0x16, + 0x37, 0x44, 0x93, 0x12, 0x07, 0x1c, 0x9a, 0xfb, 0xf5, 0xff, 0x78, 0x15, 0x18, + 0xf9, 0x42, 0xbc, 0xe2, 0x07, 0x2b, 0xc8, 0xdd, 0xa1, 0xbe, 0xc4, 0x0a, 0x1d, + 0xd6, 0xc1, 0xe9, 0xa4, 0xf3, 0x15, 0x3b, 0xe3, 0xf7, 0x0a, 0x1a, 0xee, 0xd8, + 0xe3, 0x6a, 0xf7, 0xd2, 0xf6, 0xdf, 0xf3, 0xdd, 0xd4, 0x9d, 0x22, 0x0b, 0xc2, + 0x16, 0x42, 0x58, 0x23, 0xf0, 0x03, 0xee, 0x1d, 0x1b, 0xf4, 0x18, 0xea, 0x2b, + 0xc2, 0x62, 0x2a, 0x9a, 0xfb, 0x2d, 0x28, 0xcf, 0x9f, 0xdb, 0xfa, 0xe9, 0xd5, + 0xcf, 0xef, 0xda, 0x0b, 0x9f, 0x7f, 0xec, 0x10, 0xca, 0x4d, 0xc4, 0x05, 0x09, + 0x33, 0x2b, 0x0f, 0x08, 0x0f, 0x27, 0x33, 0x0e, 0xec, 0xf3, 0x20, 0x19, 0xdf, + 0x31, 0xda, 0x10, 0x06, 0xf1, 0xcc, 0x08, 0xd9, 0x0a, 0x01, 0x14, 0x31, 0x0b, + 0x26, 0x14, 0x03, 0xf6, 0xcd, 0xd2, 0x0e, 0x1a, 0x39, 0x1a, 0x2c, 0xab, 0x1f, + 0xfb, 0x2f, 0x37, 0x25, 0x2c, 0xe8, 0x07, 0xec, 0x4d, 0xdf, 0x1c, 0x09, 0x0c, + 0x09, 0x06, 0xe4, 0xf2, 0x27, 0x05, 0x08, 0x1a, 0xfe, 0x06, 0x29, 0xce, 0x5e, + 0x21, 0xe6, 0xf9, 0xf6, 0x00, 0x49, 0x20, 0x14, 0xeb, 0xe6, 0x70, 0xd7, 0x32, + 0x77, 0xb3, 0xef, 0x07, 0xc4, 0x0b, 0x12, 0x05, 0x06, 0xc3, 0xdd, 0x45, 0x00, + 0xcf, 0x00, 0x22, 0x3d, 0xd0, 0xe1, 0xf7, 0xde, 0xe7, 0xe2, 0x03, 0x7f, 0xdf, + 0x13, 0x4b, 0x76, 0xe7, 0x23, 0x16, 0x5a, 0x21, 0xf8, 0xeb, 0xcc, 0xdf, 0xbc, + 0x1d, 0x0f, 0x28, 0x25, 0x33, 0x29, 0x1e, 0x15, 0xf7, 0x07, 0x19, 0x36, 0x40, + 0xbe, 0x56, 0x25, 0x41, 0xe4, 0xe4, 0xd1, 0x6f, 0xea, 0x04, 0x32, 0x41, 0x7f, + 0x1a, 0x3b, 0xe3, 0x43, 0x15, 0x02, 0x2f, 0x3e, 0x64, 0x63, 0xbc, 0xff, 0xc2, + 0x0b, 0x05, 0x31, 0x05, 0x11, 0x38, 0x22, 0x78, 0xff, 0xf6, 0x38, 0xb2, 0x19, + 0x00, 0x54, 0x10, 0x31, 0xde, 0x49, 0x19, 0x37, 0x2b, 0x41, 0xe2, 0x08, 0x1a, + 0x39, 0x0a, 0x20, 0xd4, 0x04, 0x35, 0x22, 0x06, 0x21, 0x57, 0x41, 0x66, 0xb6, + 0xfd, 0x0e, 0x3f, 0xd1, 0x58, 0x1e, 0x2d, 0x2f, 0x68, 0x14, 0xfd, 0x18, 0x9e, + 0xe5, 0x36, 0xf9, 0x15, 0xe4, 0x22, 0x13, 0x4b, 0xdd, 0x3c, 0x4f, 0xf0, 0xfa, + 0x03, 0x03, 0x19, 0xe5, 0x0d, 0x05, 0x1c, 0x58, 0xfa, 0x2c, 0x35, 0x07, 0x22, + 0x2f, 0x3a, 0x22, 0xe9, 0xf2, 0x37, 0x11, 0x3e, 0x23, 0x50, 0x23, 0x1b, 0x45, + 0x1d, 0xed, 0xce, 0x1b, 0xef, 0x28, 0x3e, 0xe5, 0x34, 0x17, 0xbf, 0x92, 0x4f, + 0xfb, 0xd7, 0xd0, 0x07, 0xeb, 0xf1, 0x2e, 0xce, 0xf3, 0xd2, 0xfa, 0x14, 0x33, + 0x02, 0x07, 0xee, 0xc7, 0xda, 0xd8, 0xd9, 0x0e, 0xf3, 0xdf, 0xfe, 0xf1, 0x19, + 0x0d, 0x1f, 0x0f, 0xe1, 0x5a, 0x74, 0x1b, 0xd3, 0xe1, 0xd2, 0x24, 0x43, 0x73, + 0x33, 0xdd, 0xd6, 0x25, 0xce, 0xec, 0x30, 0x05, 0x0f, 0xe1, 0xef, 0xd5, 0xea, + 0xbf, 0x02, 0xe0, 0xea, 0xf7, 0x0c, 0x66, 0xc9, 0x7f, 0x51, 0xf2, 0xc8, 0x02, + 0xec, 0x0e, 0x73, 0x0c, 0x02, 0x0a, 0xec, 0xd8, 0xd0, 0xeb, 0xe5, 0xe7, 0xdc, + 0x13, 0x00, 0xf9, 0xef, 0xc2, 0x5e, 0xd9, 0x17, 0x0e, 0xf0, 0x0a, 0x2d, 0x13, + 0xd8, 0x01, 0x26, 0xbb, 0x21, 0x2d, 0xec, 0x32, 0x08, 0x15, 0x10, 0x1c, 0x38, + 0xd8, 0xf7, 0x39, 0xe3, 0x1c, 0x2a, 0x1c, 0x21, 0x79, 0xd9, 0xeb, 0x43, 0xfa, + 0x20, 0xca, 0xec, 0x21, 0xd2, 0xea, 0xfa, 0x10, 0xdd, 0x3a, 0xf8, 0x14, 0xd3, + 0xdd, 0xc4, 0xda, 0xce, 0x02, 0x16, 0x05, 0x0c, 0x04, 0xd8, 0x0c, 0xf7, 0x16, + 0xe1, 0x45, 0x17, 0xe7, 0xb9, 0xeb, 0xfa, 0x11, 0x0b, 0x15, 0x9f, 0x49, 0xec, + 0x14, 0xe4, 0xde, 0xc0, 0xd3, 0x0b, 0xb7, 0x08, 0x12, 0xfe, 0x26, 0x17, 0x29, + 0x48, 0xe4, 0x0a, 0x22, 0x51, 0x21, 0x16, 0x12, 0xf0, 0x0e, 0xd6, 0xf2, 0x32, + 0x1b, 0x0c, 0xf4, 0x31, 0x12, 0x4b, 0xf0, 0x06, 0x0e, 0x03, 0xfe, 0x81, 0xcb, + 0x0d, 0x1d, 0xe9, 0x17, 0xff, 0xf5, 0x27, 0x05, 0x75, 0x01, 0xf7, 0x07, 0x15, + 0xec, 0xb4, 0xba, 0xf4, 0xe4, 0x04, 0x16, 0x09, 0x47, 0x30, 0xe9, 0xa5, 0x43, + 0x0e, 0x93, 0x05, 0xfa, 0xe8, 0x09, 0xfa, 0x53, 0xc5, 0x11, 0x0e, 0xf5, 0xb4, + 0xd3, 0x4e, 0xf8, 0x02, 0xd7, 0x10, 0xdd, 0xbb, 0xa7, 0xdd, 0x26, 0xd1, 0xdc, + 0xfc, 0x11, 0x3a, 0x13, 0x27, 0x10, 0x05, 0xaa, 0x13, 0x00, 0xe1, 0x25, 0xea, + 0xf7, 0xed, 0x0a, 0xa3, 0x0b, 0xe8, 0xec, 0x16, 0xfa, 0x12, 0xf8, 0xdc, 0xed, + 0x14, 0x23, 0xd1, 0x0a, 0x10, 0x03, 0xed, 0xf5, 0x26, 0xef, 0x08, 0x13, 0xb9, + 0xf6, 0x7f, 0x05, 0x25, 0xf9, 0xe0, 0x4a, 0x06, 0x68, 0x18, 0xf6, 0xef, 0xf6, + 0xf9, 0x0c, 0xee, 0x0d, 0xf1, 0xe9, 0x05, 0xb5, 0x12, 0xe4, 0xee, 0xde, 0x10, + 0x10, 0xfc, 0x23, 0xea, 0x1c, 0x3b, 0x10, 0xf9, 0x3c, 0x17, 0x09, 0xf4, 0x4b, + 0xbd, 0x12, 0xf7, 0xf7, 0x0b, 0xfb, 0xdf, 0xf9, 0xf8, 0xfb, 0x30, 0x1c, 0xff, + 0x19, 0x54, 0x15, 0xf6, 0x09, 0x27, 0x04, 0x1e, 0xef, 0x14, 0xe5, 0x07, 0xfd, + 0x13, 0x40, 0xcf, 0x67, 0xec, 0xe4, 0x21, 0xe1, 0x05, 0x02, 0xfd, 0xf9, 0x07, + 0xf9, 0xe5, 0x20, 0xeb, 0xf7, 0xe1, 0x31, 0xe2, 0x27, 0xe0, 0xe3, 0xf4, 0xea, + 0x0a, 0xe7, 0xd4, 0xc8, 0x14, 0x1c, 0x07, 0x1a, 0x44, 0xed, 0xe1, 0x1b, 0x19, + 0x19, 0x10, 0xe3, 0xe5, 0xe7, 0xe7, 0xd9, 0xe2, 0xf9, 0x3b, 0x0b, 0x37, 0xf2, + 0x5f, 0xfe, 0x2c, 0xed, 0xf5, 0xfa, 0xf1, 0xf0, 0x26, 0x13, 0xfc, 0x20, 0xec, + 0x27, 0xd8, 0xf7, 0xf7, 0xd0, 0xe5, 0xfd, 0xe5, 0xee, 0xe0, 0xf8, 0xf9, 0xfa, + 0x16, 0x2f, 0x33, 0xf2, 0x1d, 0x7f, 0xc5, 0xe7, 0xfd, 0xdc, 0x21, 0x03, 0xf6, + 0x0b, 0x06, 0x1b, 0xe5, 0x2a, 0xda, 0x4e, 0xe9, 0x39, 0xd0, 0x0f, 0x76, 0xfe, + 0x10, 0x20, 0xcc, 0xff, 0xf9, 0x0f, 0x0c, 0x14, 0x19, 0xfb, 0x23, 0xd1, 0xcf, + 0xed, 0xfd, 0xf6, 0xd9, 0xfe, 0x12, 0x0c, 0xd3, 0x25, 0xf2, 0x1a, 0x2a, 0x10, + 0xfa, 0x23, 0xd2, 0xe8, 0xe4, 0x0c, 0xff, 0x12, 0xfb, 0x1a, 0x0f, 0x05, 0xf9, + 0xf9, 0x2c, 0x14, 0x03, 0xca, 0x39, 0x19, 0x21, 0xef, 0x07, 0x1b, 0x38, 0x09, + 0xe6, 0xff, 0x38, 0xfc, 0x4f, 0x52, 0x17, 0x03, 0xd4, 0xb5, 0xfd, 0xbd, 0x46, + 0x6a, 0xef, 0x19, 0x04, 0x38, 0xf4, 0x38, 0xfb, 0x52, 0x51, 0x00, 0xb5, 0x22, + 0x07, 0x18, 0xe7, 0x17, 0x20, 0xf0, 0x03, 0xe5, 0x05, 0x4f, 0x2a, 0x12, 0x35, + 0x4b, 0x21, 0x11, 0xd7, 0x39, 0x0d, 0xe8, 0x01, 0x7f, 0xe3, 0x57, 0xe8, 0xe4, + 0xd4, 0xe5, 0xe9, 0xfb, 0x21, 0xe5, 0xf3, 0x1a, 0xb3, 0xde, 0xfe, 0x11, 0xe2, + 0xd6, 0xf5, 0x08, 0xed, 0x43, 0x31, 0xe8, 0x40, 0x44, 0x1f, 0xde, 0x0d, 0x0b, + 0x68, 0xd7, 0xf1, 0xb8, 0x2a, 0xe9, 0xdd, 0x4d, 0x23, 0x07, 0x33, 0x26, 0xe0, + 0x05, 0x16, 0xec, 0xf5, 0xc0, 0x0b, 0xfd, 0xff, 0xca, 0x01, 0xfd, 0xfe, 0xe9, + 0x18, 0xbd, 0x08, 0xf2, 0x1a, 0xfe, 0x3f, 0xd1, 0xf6, 0xcf, 0x1d, 0xfc, 0xe8, + 0x2a, 0x23, 0xa6, 0x02, 0x3a, 0xe9, 0xd9, 0xd6, 0xdc, 0x18, 0x0a, 0x1f, 0xbe, + 0xfd, 0xef, 0xf6, 0x15, 0x18, 0x15, 0xf8, 0x0e, 0x23, 0x2b, 0x1d, 0xda, 0xf0, + 0x26, 0xf9, 0xef, 0x2c, 0x25, 0x0c, 0xeb, 0x13, 0x53, 0xf5, 0x09, 0x1a, 0x5f, + 0xbc, 0xe9, 0x3a, 0xca, 0xf6, 0xfa, 0x03, 0xd9, 0xc1, 0x2d, 0x03, 0xf3, 0xfc, + 0x26, 0x2f, 0x07, 0x22, 0x20, 0x0e, 0xd5, 0xed, 0xcf, 0xfb, 0x17, 0xfa, 0x2c, + 0xe9, 0x5e, 0x18, 0xba, 0x3c, 0xd9, 0xff, 0x21, 0x1c, 0xff, 0x18, 0x13, 0x1c, + 0xc7, 0xe7, 0xa4, 0x19, 0x1a, 0x0b, 0x46, 0xdf, 0x17, 0xcf, 0xa3, 0xd0, 0x78, + 0xca, 0xfb, 0xc8, 0xcc, 0x01, 0xf8, 0xfa, 0x41, 0x0b, 0x38, 0xfe, 0x34, 0xf6, + 0xb1, 0x29, 0x1e, 0xd5, 0x0b, 0xff, 0xc4, 0x01, 0x3d, 0xf9, 0x2b, 0xf2, 0x04, + 0x7f, 0xde, 0xfd, 0xf7, 0xc2, 0x3c, 0x34, 0x22, 0x1b, 0x20, 0x10, 0x35, 0x06, + 0x0b, 0x00, 0xd0, 0xe3, 0x0f, 0x41, 0x59, 0xbe, 0x20, 0x45, 0xf9, 0xe3, 0xe8, + 0xec, 0xee, 0xd8, 0x1d, 0x04, 0xeb, 0x48, 0xf9, 0xdc, 0xe9, 0x08, 0xbf, 0xe7, + 0x22, 0xe7, 0x37, 0x0b, 0xcd, 0xd1, 0x05, 0xd4, 0x28, 0x33, 0xc3, 0xed, 0x2c, + 0x01, 0xfe, 0x42, 0xf5, 0xc1, 0x4a, 0x3a, 0x03, 0x05, 0xd0, 0xe5, 0xf2, 0xfb, + 0x0a, 0xd2, 0x30, 0x09, 0xf8, 0xff, 0x1f, 0x25, 0xe5, 0xf4, 0x10, 0x26, 0x1b, + 0x4c, 0x07, 0x00, 0xf2, 0xe6, 0xe5, 0xe4, 0x09, 0xdf, 0x16, 0x4d, 0xf4, 0x35, + 0x81, 0x0e, 0x18, 0x24, 0x06, 0xf6, 0xe4, 0xf6, 0xe8, 0xee, 0x79, 0x0b, 0x16, + 0xf7, 0xdc, 0xe5, 0x2d, 0x28, 0xeb, 0x2b, 0xfa, 0x0a, 0x21, 0xff, 0xf4, 0x00, + 0x1a, 0x36, 0x1e, 0x17, 0xda, 0xcd, 0xed, 0xc9, 0x43, 0xe5, 0x08, 0x0e, 0x33, + 0xf6, 0xdf, 0xdb, 0x1e, 0xc8, 0x11, 0xe3, 0x00, 0xfe, 0x21, 0xf7, 0x1b, 0xe5, + 0xd0, 0x08, 0xe0, 0x1a, 0x1a, 0x2e, 0xf7, 0xb5, 0x16, 0x2f, 0x28, 0x1f, 0xdf, + 0xe3, 0xcf, 0x34, 0xf8, 0xe0, 0xf7, 0x2b, 0xeb, 0x11, 0xd0, 0x1c, 0xe8, 0x03, + 0x03, 0xe5, 0x06, 0x54, 0xbf, 0xcf, 0xea, 0x3a, 0xe0, 0xff, 0xcf, 0x2c, 0x02, + 0xd4, 0xf4, 0xf9, 0xcf, 0x7f, 0xf2, 0x0d, 0x23, 0x2e, 0xe0, 0xc6, 0x38, 0xe7, + 0xe8, 0x1c, 0xbd, 0x30, 0xeb, 0x10, 0x10, 0xe8, 0x24, 0x0b, 0xf1, 0xfd, 0x23, + 0x07, 0x0e, 0xe4, 0x12, 0xcd, 0x50, 0x33, 0xfe, 0xf6, 0x0a, 0x03, 0x38, 0x00, + 0xf2, 0xec, 0x0b, 0xe2, 0xdd, 0xf2, 0x38, 0xd6, 0xdc, 0xf8, 0x40, 0x39, 0xe0, + 0x12, 0x03, 0x04, 0xe6, 0x0c, 0x00, 0xd1, 0x1a, 0xff, 0xd3, 0x40, 0x05, 0x50, + 0xf7, 0x0f, 0xfe, 0xcc, 0xee, 0xf0, 0x1d, 0x16, 0x2b, 0xec, 0xf4, 0xf4, 0xf8, + 0x25, 0xee, 0x09, 0xd3, 0x2f, 0x02, 0x07, 0xde, 0xa7, 0xeb, 0xd3, 0x3a, 0xdf, + 0x2d, 0x2f, 0xf0, 0x49, 0xfe, 0x0c, 0x81, 0xf8, 0xb3, 0xe8, 0xfb, 0x18, 0x24, + 0xd0, 0xc1, 0xef, 0x44, 0x9d, 0x0c, 0x15, 0xc4, 0xc0, 0xe1, 0xd6, 0x09, 0x1f, + 0x04, 0x0b, 0x0e, 0x19, 0xab, 0xac, 0x32, 0x10, 0x11, 0xb7, 0x02, 0xfe, 0x70, + 0x48, 0xe7, 0xcb, 0xd3, 0x9f, 0x2a, 0x28, 0x69, 0xe6, 0x97, 0xfe, 0xab, 0x14, + 0x3e, 0xd6, 0x26, 0xd1, 0x44, 0xf3, 0x0c, 0xf7, 0x18, 0xec, 0xcc, 0xe4, 0xf3, + 0xbe, 0x26, 0x1a, 0xa6, 0x0a, 0xdd, 0xa2, 0x87, 0x07, 0x43, 0x50, 0xd8, 0x46, + 0xa9, 0xf7, 0x36, 0xb1, 0xb4, 0x23, 0x14, 0x10, 0x4a, 0x2a, 0xfc, 0x35, 0xef, + 0xd5, 0x1e, 0x36, 0x40, 0x1c, 0xac, 0x23, 0x37, 0x03, 0xaa, 0xc0, 0xb5, 0x2b, + 0x3f, 0x54, 0x62, 0x0a, 0xaa, 0x92, 0xf0, 0x1a, 0xe9, 0x02, 0x31, 0xdc, 0x13, + 0x2e, 0xee, 0x15, 0x13, 0x13, 0x07, 0x3c, 0xcc, 0x05, 0x37, 0x5a, 0x02, 0x32, + 0x0f, 0x1d, 0x3a, 0x39, 0x0f, 0x2c, 0x0b, 0x3f, 0x6e, 0x51, 0xfc, 0x44, 0xcc, + 0xf9, 0xed, 0x23, 0xbf, 0x63, 0x0d, 0xd9, 0xdf, 0x16, 0x43, 0x0f, 0xbc, 0xf8, + 0xc1, 0x29, 0x26, 0xff, 0xb3, 0x11, 0xdd, 0x3d, 0x12, 0x2d, 0x0b, 0x7f, 0xfb, + 0x05, 0x01, 0xd6, 0x38, 0xea, 0xff, 0xf6, 0x37, 0xcd, 0x29, 0xa9, 0xde, 0x1a, + 0xce, 0xf7, 0x1f, 0xfb, 0x26, 0x17, 0x16, 0x45, 0x22, 0xde, 0x21, 0x0f, 0xeb, + 0xe3, 0x05, 0x0b, 0xee, 0x2b, 0x37, 0x2e, 0xd9, 0x7c, 0xf4, 0x18, 0x15, 0x1a, + 0xd1, 0xf9, 0xe1, 0x58, 0x1f, 0x20, 0x0f, 0x35, 0x17, 0x0f, 0xde, 0x52, 0x03, + 0xf9, 0xf6, 0xfa, 0x3a, 0x07, 0x22, 0x52, 0xc2, 0x21, 0x1a, 0x1d, 0xb0, 0xe5, + 0xfd, 0x0a, 0x1f, 0xc0, 0x3e, 0x4d, 0x53, 0x08, 0xf8, 0xd1, 0xf2, 0x0d, 0xf8, + 0x18, 0x2d, 0x21, 0xe8, 0x56, 0xe9, 0x06, 0x03, 0x1d, 0x16, 0x0e, 0x16, 0xf4, + 0x0d, 0xe6, 0xfc, 0x3a, 0x0d, 0x25, 0x19, 0x20, 0x03, 0x29, 0x13, 0x2a, 0xf3, + 0x4d, 0xc3, 0xc9, 0x10, 0x1e, 0x15, 0xcc, 0x56, 0x24, 0xb7, 0xea, 0xf8, 0x00, + 0x72, 0xe9, 0x0a, 0x51, 0x00, 0xc6, 0xda, 0x18, 0x1e, 0x15, 0xab, 0xf7, 0xe4, + 0xa4, 0xfb, 0x2d, 0x4f, 0x03, 0x9b, 0x17, 0x04, 0x3e, 0xc1, 0xcc, 0xe7, 0x0f, + 0x92, 0xfe, 0x22, 0x07, 0x20, 0xe7, 0xcf, 0xe2, 0xdf, 0xfa, 0x18, 0xda, 0x0e, + 0xe0, 0xe0, 0xe6, 0xb4, 0x2e, 0x38, 0x35, 0x28, 0x23, 0xd6, 0x02, 0x1d, 0xfc, + 0xed, 0x83, 0xe6, 0xfd, 0x1a, 0xad, 0xb4, 0xf9, 0x0a, 0x1a, 0xcb, 0x16, 0xd1, + 0x11, 0xc9, 0x24, 0xef, 0x0c, 0xfd, 0xf5, 0x00, 0x17, 0x02, 0x11, 0x14, 0x28, + 0x0a, 0x91, 0xf2, 0x2d, 0xf2, 0xf7, 0x3f, 0x25, 0xee, 0xe7, 0xd3, 0xf8, 0xdd, + 0x25, 0x20, 0x11, 0x7f, 0x42, 0xb3, 0x08, 0xe4, 0x2f, 0xda, 0xf7, 0xf3, 0x92, + 0x1f, 0x1c, 0x12, 0xae, 0xdc, 0xc3, 0xe1, 0x17, 0xef, 0xf5, 0x05, 0xcd, 0x15, + 0xf2, 0xf5, 0x21, 0xff, 0x26, 0xc2, 0x1b, 0xce, 0xfa, 0x03, 0xea, 0x02, 0xfc, + 0xe1, 0xca, 0xda, 0x1a, 0x02, 0x61, 0x20, 0xeb, 0xc7, 0xe2, 0x84, 0xfc, 0x00, + 0x1b, 0xca, 0xa8, 0xd0, 0x29, 0xef, 0x20, 0xcf, 0x2b, 0xfe, 0x40, 0x17, 0xff, + 0xf8, 0xf1, 0x29, 0x91, 0x07, 0xa8, 0xfe, 0xc0, 0xff, 0xff, 0x07, 0xfc, 0xd5, + 0xe2, 0x00, 0xed, 0xd7, 0x09, 0x29, 0xbc, 0x07, 0x68, 0xb1, 0xc3, 0x81, 0x10, + 0xf1, 0x00, 0x1d, 0xf8, 0xd1, 0x0d, 0xf5, 0xe8, 0xf1, 0xe3, 0xd4, 0x47, 0xf7, + 0xec, 0xe0, 0xe7, 0xde, 0x24, 0xf4, 0x61, 0xe3, 0xfe, 0xcb, 0x26, 0xe9, 0xb7, + 0x03, 0xd7, 0xb5, 0xe9, 0x2b, 0xec, 0xef, 0x17, 0xde, 0x29, 0xcf, 0x08, 0xf1, + 0xe5, 0xd0, 0xa9, 0x00, 0x1f, 0xee, 0x1e, 0xe9, 0x4f, 0x03, 0x18, 0xe0, 0x20, + 0xfc, 0x13, 0x6b, 0x0a, 0x01, 0xb8, 0xd3, 0x13, 0xf4, 0x09, 0x1e, 0x33, 0x44, + 0xec, 0x02, 0xff, 0x50, 0x5b, 0x00, 0xc7, 0x34, 0xea, 0xe1, 0x1e, 0x45, 0xde, + 0xf2, 0x29, 0xd1, 0xe2, 0x14, 0xd4, 0x36, 0x61, 0x7f, 0x12, 0x49, 0xdd, 0xec, + 0xe9, 0xf8, 0xc2, 0xf9, 0xc7, 0x05, 0x1d, 0xf9, 0xe2, 0x20, 0x04, 0xf4, 0xe2, + 0xe9, 0x2f, 0xeb, 0x0b, 0xef, 0x1f, 0xc0, 0xb8, 0xe8, 0xdd, 0xf9, 0xf3, 0xb4, + 0x39, 0x41, 0x18, 0xf8, 0xf0, 0xf3, 0x45, 0xd1, 0xc8, 0xd6, 0x3d, 0xf3, 0xee, + 0xec, 0x00, 0x2f, 0x03, 0xf7, 0x1d, 0x20, 0xf5, 0xe8, 0xfd, 0x24, 0xe2, 0x17, + 0xf3, 0x07, 0xee, 0xed, 0xd8, 0x2b, 0x3d, 0x18, 0x08, 0xf5, 0x24, 0x0e, 0xf7, + 0xed, 0x35, 0x22, 0x0e, 0x30, 0xf4, 0xc6, 0xb9, 0x21, 0xfc, 0x09, 0x06, 0x10, + 0xed, 0xfc, 0x38, 0x2b, 0x21, 0x96, 0x05, 0xdb, 0x09, 0xbe, 0x2e, 0xba, 0x52, + 0xfc, 0x3d, 0xd4, 0xd0, 0x04, 0x27, 0xae, 0x9d, 0x13, 0x57, 0x34, 0x0c, 0x11, + 0xe6, 0x3f, 0x1f, 0xb8, 0x2c, 0xf8, 0x2e, 0xe8, 0xe6, 0x06, 0x32, 0xe6, 0x23, + 0xc6, 0x29, 0x11, 0xcd, 0x06, 0xe6, 0xf8, 0x1a, 0x2f, 0x0e, 0x18, 0xc0, 0x11, + 0xeb, 0xdb, 0xec, 0x7f, 0xfe, 0xe4, 0xfe, 0xe0, 0xf2, 0xc8, 0x1b, 0x19, 0x0d, + 0xe3, 0xcb, 0xdd, 0xc8, 0xd9, 0xde, 0x09, 0xb5, 0xfc, 0x03, 0xef, 0xe9, 0xf0, + 0x3e, 0xfc, 0x12, 0xe9, 0xdf, 0xe7, 0xe8, 0xf9, 0xfd, 0xea, 0xff, 0x25, 0x03, + 0xd3, 0xd8, 0x14, 0x28, 0x0b, 0x31, 0x52, 0xd9, 0xfd, 0x0a, 0xe0, 0xe0, 0x02, + 0xec, 0xc5, 0x12, 0xf0, 0x17, 0xc8, 0x2a, 0xf0, 0x34, 0xd0, 0x1e, 0xea, 0xd5, + 0x47, 0x34, 0x29, 0xd0, 0xeb, 0xd4, 0x04, 0x0c, 0x38, 0x0d, 0xc7, 0x10, 0xd1, + 0x1d, 0x05, 0xdc, 0xe8, 0xeb, 0x0e, 0xe6, 0x17, 0xf3, 0x30, 0x26, 0xee, 0xf9, + 0x50, 0x25, 0xc7, 0x2e, 0x11, 0xd5, 0xbe, 0xfa, 0xca, 0xe5, 0xec, 0xa8, 0x05, + 0x00, 0x01, 0xd9, 0xb2, 0x1e, 0x37, 0xee, 0x81, 0x22, 0x0a, 0xb5, 0x26, 0x2e, + 0xbf, 0x56, 0x26, 0xfb, 0xe9, 0xbf, 0xee, 0xff, 0x21, 0x02, 0x18, 0xfc, 0x52, + 0xe8, 0x20, 0x28, 0xf7, 0xfe, 0xfe, 0xf2, 0x0c, 0x3f, 0xfe, 0xf8, 0x30, 0xfd, + 0x1f, 0xdc, 0xfb, 0x20, 0x77, 0x3e, 0xca, 0x3d, 0x2e, 0xf7, 0xca, 0xef, 0xfc, + 0x04, 0xec, 0xf6, 0xf4, 0x55, 0x11, 0xfd, 0xef, 0x0e, 0xed, 0xd4, 0x01, 0x09, + 0xf6, 0xe5, 0x01, 0x20, 0x04, 0x1a, 0xf2, 0xdf, 0x00, 0x44, 0x9e, 0xfc, 0x0a, + 0xe6, 0xff, 0xe8, 0xc8, 0x28, 0x5d, 0x26, 0x04, 0xeb, 0xd5, 0xf9, 0x04, 0xf9, + 0xb4, 0xd1, 0x14, 0x1d, 0x38, 0xf4, 0xf0, 0x33, 0x2e, 0x19, 0xd7, 0xe8, 0x13, + 0xe7, 0x15, 0x2f, 0x07, 0x00, 0x10, 0x00, 0x6f, 0x31, 0x31, 0x13, 0x3d, 0x28, + 0xda, 0x2d, 0xf0, 0x14, 0x2d, 0x13, 0x81, 0xd6, 0xe7, 0x2a, 0x1e, 0x34, 0x2b, + 0x0f, 0xc1, 0x1c, 0xcb, 0x21, 0xb7, 0x2f, 0x28, 0xe1, 0x3f, 0x23, 0xf6, 0x3b, + 0x20, 0xad, 0x41, 0xe4, 0xe4, 0x11, 0x3c, 0x27, 0x4c, 0x3a, 0x26, 0x23, 0x1f, + 0xec, 0x35, 0xe6, 0x1f, 0xf5, 0x3e, 0xfa, 0x07, 0x38, 0x28, 0x20, 0x03, 0x14, + 0x31, 0xfa, 0x4b, 0xf5, 0x1a, 0x47, 0x07, 0x32, 0xdc, 0x3d, 0x11, 0xd2, 0x05, + 0xf9, 0xd8, 0x08, 0x41, 0x33, 0x01, 0x11, 0x2b, 0x1c, 0x0a, 0x0b, 0xe7, 0x03, + 0x0a, 0xdc, 0x39, 0x39, 0x10, 0x24, 0xe5, 0x34, 0xfe, 0xf8, 0xe9, 0xec, 0xd9, + 0xd6, 0x07, 0x1b, 0x30, 0x3b, 0xf6, 0xcc, 0x53, 0xd1, 0xf6, 0x09, 0x1e, 0x20, + 0xee, 0x13, 0x14, 0xe8, 0xa4, 0x63, 0xc6, 0x1f, 0x0f, 0x0f, 0xd0, 0xe1, 0x5a, + 0x13, 0x0c, 0xb3, 0x1a, 0x21, 0x37, 0xc3, 0x58, 0xbf, 0x43, 0xcc, 0x09, 0xe9, + 0xc0, 0x63, 0xd6, 0xe0, 0xd9, 0x03, 0xbd, 0x10, 0x19, 0xe9, 0xc1, 0x13, 0xbc, + 0xd0, 0x51, 0x0a, 0xa9, 0x39, 0x0b, 0xca, 0x3c, 0xdf, 0xd2, 0x12, 0xbf, 0xcc, + 0x15, 0xe5, 0x1d, 0x08, 0xcb, 0xe5, 0x0e, 0xcb, 0x3c, 0xf2, 0xb1, 0x3b, 0xcc, + 0xb2, 0x0e, 0x12, 0x35, 0xfa, 0xff, 0xc8, 0x2d, 0xed, 0xfa, 0x3b, 0x04, 0xfc, + 0x09, 0xfd, 0xf4, 0xff, 0xf6, 0xe4, 0x02, 0xd4, 0x00, 0x92, 0x26, 0x17, 0xd2, + 0xe2, 0xad, 0x27, 0xef, 0xd9, 0x06, 0x64, 0xfe, 0x2d, 0x18, 0x2e, 0xe1, 0xb7, + 0x45, 0x30, 0x43, 0xde, 0xdc, 0xff, 0xaf, 0x18, 0xdb, 0xc9, 0xee, 0xf2, 0xd3, + 0x3c, 0x13, 0x06, 0x00, 0xf7, 0x13, 0x08, 0xdc, 0xf9, 0xf9, 0xfd, 0x2a, 0xf9, + 0xdb, 0xc5, 0x05, 0x23, 0x1c, 0x7f, 0x31, 0xe3, 0xdd, 0x51, 0xe8, 0x05, 0xf5, + 0x51, 0xbf, 0xa1, 0x2a, 0x46, 0xdf, 0x73, 0xec, 0xdb, 0xd6, 0xc7, 0x1a, 0xc8, + 0xfa, 0xcc, 0x08, 0xbe, 0x05, 0xe6, 0xf8, 0x04, 0x2e, 0x43, 0x08, 0x0f, 0x90, + 0x12, 0xe1, 0x25, 0xbb, 0xdd, 0xd8, 0x16, 0x3e, 0xda, 0x5f, 0x12, 0x19, 0xe5, + 0xf0, 0xf7, 0x2b, 0x02, 0x1e, 0xf4, 0xef, 0xaf, 0x2e, 0xcf, 0x49, 0xc2, 0xdc, + 0xea, 0x1f, 0xc1, 0xee, 0x09, 0x08, 0xf9, 0x36, 0x2a, 0xf0, 0x0d, 0x2b, 0xf0, + 0x11, 0x28, 0x28, 0x2a, 0x36, 0xda, 0xb5, 0x7f, 0xe7, 0xdd, 0x32, 0x03, 0x06, + 0xfe, 0x07, 0xfc, 0xf6, 0x4a, 0xfc, 0xe9, 0x04, 0x0f, 0xff, 0x0d, 0x4f, 0x1b, + 0x07, 0xf7, 0x1f, 0x04, 0xcf, 0xdc, 0x15, 0x0b, 0x2d, 0x47, 0x18, 0xf6, 0xb9, + 0xb4, 0xc4, 0xd8, 0x0c, 0x76, 0xe0, 0x06, 0xa8, 0xf5, 0xe0, 0x17, 0x1e, 0x07, + 0xe2, 0x5a, 0xec, 0xd7, 0x03, 0xdf, 0xf5, 0x01, 0x04, 0xeb, 0x05, 0xea, 0xdf, + 0x42, 0xe6, 0xe4, 0xce, 0x09, 0xfa, 0x38, 0x53, 0x02, 0xda, 0x16, 0xe7, 0x19, + 0x41, 0x14, 0xf2, 0xf9, 0xf6, 0x17, 0x03, 0x2d, 0x24, 0x20, 0x6b, 0xf3, 0x55, + 0x23, 0xf5, 0xe2, 0x0e, 0x4c, 0xe0, 0x0f, 0xd2, 0x7f, 0xba, 0x1e, 0xd3, 0x1a, + 0xd8, 0x3b, 0x18, 0x01, 0x0b, 0xe6, 0xfd, 0x20, 0xde, 0x14, 0xe0, 0x15, 0xf8, + 0x0c, 0xfd, 0xd1, 0x0c, 0x3c, 0x04, 0x09, 0x1f, 0xfa, 0xc3, 0x2e, 0x06, 0xf2, + 0xf5, 0x0d, 0xa2, 0x19, 0x37, 0xe7, 0xe3, 0xcb, 0xfd, 0x18, 0xdf, 0xf9, 0x02, + 0xf0, 0x0c, 0x2e, 0xd7, 0xff, 0xf5, 0x0c, 0xfa, 0xf5, 0x2b, 0x17, 0xe8, 0xb4, + 0xfd, 0xe4, 0x25, 0x2e, 0x0b, 0x31, 0x27, 0x1c, 0x03, 0x04, 0x06, 0xdb, 0xd1, + 0xff, 0x23, 0x15, 0x21, 0x43, 0xab, 0x20, 0xfb, 0x24, 0x02, 0xf6, 0x28, 0x03, + 0xfc, 0xcd, 0x2f, 0xed, 0x34, 0x21, 0x2f, 0x3c, 0xfa, 0xf9, 0x1b, 0xd3, 0xe6, + 0x13, 0x4d, 0xe2, 0x1d, 0x7a, 0x01, 0xc6, 0xd7, 0x14, 0xdf, 0x57, 0x4f, 0xdc, + 0xd1, 0xaf, 0x97, 0xc7, 0x52, 0xa2, 0x4d, 0x38, 0x6f, 0xe4, 0xe2, 0x60, 0x4b, + 0xcb, 0xf8, 0xd5, 0xbd, 0x33, 0x1d, 0xfa, 0x6a, 0x14, 0xf8, 0xed, 0x1e, 0x57, + 0x5f, 0xdb, 0xcf, 0xc5, 0xbf, 0xf2, 0xe4, 0x3c, 0xc5, 0xf2, 0x12, 0xee, 0x15, + 0x0e, 0x44, 0x3c, 0xde, 0x20, 0x23, 0x21, 0x48, 0xd5, 0x32, 0x5d, 0x07, 0xf7, + 0xe3, 0x26, 0x7f, 0xe2, 0xe3, 0xe7, 0xcd, 0x27, 0x5f, 0xe4, 0x37, 0x49, 0x21, + 0x2c, 0xd7, 0x39, 0xd5, 0x39, 0x2f, 0x00, 0xad, 0x24, 0x2f, 0xfb, 0xef, 0xf7, + 0x24, 0x2f, 0xe8, 0x02, 0x17, 0xb8, 0xdd, 0xf5, 0x41, 0x8f, 0x06, 0x34, 0x65, + 0xfe, 0xf5, 0x8b, 0x5b, 0x22, 0xfa, 0x24, 0x13, 0x0d, 0xdf, 0xec, 0x5f, 0xd9, + 0xca, 0x0e, 0xd0, 0xf1, 0x0e, 0xeb, 0x4b, 0xc4, 0xcf, 0xda, 0xce, 0xea, 0xec, + 0xd9, 0x1c, 0xc6, 0xc8, 0xf3, 0x05, 0xbd, 0x04, 0xf9, 0xea, 0x06, 0xd8, 0x26, + 0xaa, 0x08, 0x31, 0xc3, 0xe1, 0xef, 0xec, 0xfe, 0x55, 0x1e, 0x15, 0x03, 0xfe, + 0x06, 0x15, 0xf1, 0xdd, 0x0e, 0xe2, 0xf3, 0x9e, 0xb7, 0x30, 0x2a, 0x9c, 0x47, + 0xfb, 0xe6, 0xdb, 0xff, 0xcb, 0x2e, 0xce, 0x0a, 0xfd, 0x05, 0xde, 0xb3, 0xd8, + 0xe4, 0x34, 0x34, 0xed, 0x10, 0xb7, 0xf3, 0x37, 0xcf, 0xd4, 0xb5, 0xdc, 0xf4, + 0xe7, 0xca, 0xff, 0xcb, 0x2e, 0x31, 0xff, 0x25, 0xf7, 0x29, 0xb9, 0xc4, 0xf5, + 0x2f, 0x0d, 0x16, 0x04, 0xe0, 0x11, 0x10, 0x17, 0x08, 0x1e, 0xed, 0xef, 0x0e, + 0xf0, 0x06, 0xdf, 0xc6, 0xcf, 0xfa, 0xff, 0x08, 0x2d, 0xca, 0xe1, 0x15, 0xc5, + 0xa9, 0xfb, 0xea, 0xf8, 0xa8, 0x08, 0xf3, 0xdd, 0xc0, 0x7f, 0x34, 0x20, 0x01, + 0x19, 0xde, 0xd3, 0x96, 0x11, 0x27, 0xea, 0xd5, 0xfc, 0x02, 0xcb, 0xac, 0x16, + 0xbe, 0x62, 0xe5, 0x3e, 0xf6, 0xdd, 0x1a, 0xd5, 0x24, 0xd8, 0x37, 0xf9, 0xe1, + 0xcc, 0x8e, 0xe8, 0x4e, 0x04, 0x1b, 0xe3, 0xe0, 0xdf, 0x08, 0xe6, 0x6c, 0x02, + 0x97, 0xf2, 0x1c, 0x2d, 0xed, 0xc1, 0xc9, 0x29, 0x1b, 0x0f, 0xfb, 0x15, 0xb3, + 0xf1, 0xd4, 0xcd, 0x7a, 0xce, 0x01, 0xf9, 0x56, 0x02, 0xf6, 0x06, 0xe4, 0x46, + 0x71, 0xf4, 0xb4, 0x5b, 0x14, 0x2b, 0x34, 0x10, 0x17, 0xd1, 0xea, 0x1a, 0xe9, + 0xe5, 0xbe, 0xc0, 0xf4, 0xb0, 0xb1, 0x3a, 0x8d, 0x47, 0xc0, 0xfb, 0x20, 0xdf, + 0xff, 0xf0, 0xf7, 0x15, 0x64, 0x2a, 0xe2, 0x42, 0x49, 0xf2, 0xcf, 0xfa, 0x1f, + 0x22, 0x00, 0x2d, 0x03, 0x2d, 0xbb, 0xfc, 0x7f, 0x31, 0x15, 0xdf, 0xd3, 0x0b, + 0xfb, 0xf4, 0x1e, 0x20, 0xc4, 0xdd, 0x0c, 0xef, 0xe4, 0xc4, 0xfd, 0x14, 0x2e, + 0xe1, 0xd0, 0xec, 0x03, 0x01, 0xf0, 0x31, 0x2b, 0x13, 0xd7, 0x1f, 0xf7, 0x08, + 0x24, 0x35, 0xe8, 0x18, 0x00, 0xfc, 0x0d, 0xf6, 0x15, 0xf8, 0x24, 0x1b, 0xc0, + 0xd2, 0xf8, 0x0e, 0xee, 0xd1, 0xee, 0x0d, 0xd0, 0xfb, 0x42, 0xfd, 0x42, 0x39, + 0x18, 0x26, 0xbb, 0x09, 0x02, 0x2c, 0x2c, 0x37, 0x01, 0x31, 0xe5, 0xe9, 0x16, + 0xdb, 0x1f, 0x02, 0x31, 0x04, 0xec, 0x3d, 0x1a, 0xe3, 0x21, 0xf8, 0x0a, 0x1b, + 0xf3, 0x7f, 0x0e, 0x3c, 0x3b, 0x0f, 0x0e, 0x15, 0x12, 0x35, 0xee, 0x17, 0x09, + 0xf3, 0x36, 0x2f, 0xdd, 0x06, 0x40, 0x0c, 0x2f, 0x08, 0x23, 0xe8, 0xe1, 0x10, + 0x49, 0xeb, 0x03, 0x03, 0xd5, 0x10, 0x44, 0xf0, 0x5d, 0xf8, 0xf3, 0x00, 0xda, + 0x4a, 0xe4, 0x2a, 0xf4, 0xdb, 0x0d, 0x49, 0xee, 0x1b, 0x12, 0xf4, 0xed, 0x0d, + 0x12, 0xf9, 0xec, 0xbe, 0x05, 0xf4, 0x19, 0x49, 0xf7, 0x07, 0xb6, 0xfa, 0xc2, + 0x06, 0xd0, 0xa0, 0x0d, 0x45, 0x03, 0x8e, 0x34, 0x40, 0xe3, 0xc7, 0x19, 0x17, + 0xfc, 0xa3, 0x15, 0xea, 0xf1, 0x9f, 0xe4, 0xaa, 0x11, 0xbc, 0x30, 0xdb, 0xad, + 0x7f, 0x41, 0xf5, 0x34, 0x3e, 0xec, 0xfd, 0xf0, 0xfe, 0xa0, 0x13, 0x28, 0xf6, + 0xdf, 0xc4, 0xfd, 0xe8, 0x2a, 0xc0, 0xed, 0x54, 0x93, 0x4e, 0xfd, 0xd4, 0xec, + 0xf3, 0x24, 0xd1, 0x39, 0xd3, 0xd1, 0xe6, 0xd5, 0xe6, 0xd9, 0xef, 0xb6, 0xd3, + 0x2a, 0x04, 0xd8, 0x33, 0xd6, 0xc9, 0xd3, 0xb6, 0xdc, 0xbb, 0x19, 0x16, 0xfe, + 0xfa, 0xe1, 0x09, 0x9b, 0xb0, 0xa0, 0x44, 0x17, 0xfc, 0xd1, 0xcf, 0xd6, 0xdb, + 0x51, 0x0e, 0xec, 0x37, 0xc3, 0xe0, 0x0d, 0xbb, 0xda, 0xfa, 0xe2, 0xf0, 0xcf, + 0x2c, 0xa2, 0x25, 0xf8, 0xc1, 0xde, 0x42, 0x27, 0x09, 0xd7, 0x27, 0x9a, 0x53, + 0xf5, 0x14, 0x43, 0x69, 0x6f, 0x14, 0x23, 0x0d, 0xda, 0x4b, 0xf4, 0xf2, 0x0b, + 0x4c, 0x7f, 0x19, 0x36, 0x33, 0x1b, 0xca, 0xe9, 0x1e, 0x0c, 0x04, 0x48, 0x04, + 0xdb, 0xe1, 0xf2, 0xf2, 0x1f, 0xf4, 0x24, 0xec, 0x29, 0xf2, 0x16, 0x0f, 0xfb, + 0xdf, 0xb9, 0xe1, 0x41, 0xfa, 0x2c, 0x0d, 0xe7, 0xdf, 0xd4, 0xb9, 0xf4, 0x37, + 0x16, 0x25, 0xf8, 0xfd, 0xc9, 0x29, 0x02, 0x2a, 0xea, 0x40, 0xf1, 0x04, 0x1b, + 0x12, 0x02, 0x5b, 0xbb, 0xd4, 0x23, 0x0c, 0xd4, 0xe5, 0xd0, 0x02, 0x13, 0xec, + 0x0d, 0x0e, 0xeb, 0x01, 0x1c, 0x41, 0x04, 0xfa, 0x21, 0x1e, 0xf3, 0x14, 0x1b, + 0xc8, 0x15, 0xf2, 0xe1, 0xd8, 0xf2, 0xfa, 0x21, 0xe8, 0xd5, 0x5e, 0xfa, 0x02, + 0x00, 0xeb, 0x13, 0xdb, 0xa7, 0xf3, 0x16, 0x26, 0x18, 0xf5, 0x29, 0x0b, 0xd2, + 0x18, 0x1f, 0x3c, 0x18, 0x2f, 0x1c, 0x0b, 0x00, 0x25, 0xed, 0xb2, 0xe0, 0x47, + 0x3a, 0x05, 0x55, 0x12, 0xe4, 0x08, 0x7f, 0xe7, 0xbc, 0x53, 0xc3, 0xab, 0x2a, + 0x37, 0x05, 0x03, 0x1e, 0xed, 0xdf, 0xbf, 0x0d, 0x2b, 0xea, 0xd2, 0xee, 0xde, + 0x01, 0xbb, 0x07, 0xf6, 0x22, 0x2e, 0x69, 0x08, 0x30, 0xf6, 0xe6, 0x0e, 0xe9, + 0xc0, 0xf5, 0xf7, 0xf5, 0x09, 0x0d, 0x26, 0xf6, 0xbf, 0xd6, 0xa7, 0x00, 0x07, + 0x0f, 0x32, 0xb5, 0x17, 0x98, 0x22, 0x1c, 0x0b, 0x51, 0x32, 0xf3, 0xdb, 0x13, + 0x41, 0x94, 0x1a, 0x0a, 0x1e, 0x25, 0xf5, 0x19, 0x6f, 0x3d, 0x00, 0x3b, 0x19, + 0x33, 0xc7, 0xc3, 0xff, 0xee, 0xe8, 0x20, 0xc6, 0xe8, 0xf3, 0xe2, 0xfe, 0xf1, + 0xd9, 0xfd, 0x37, 0x22, 0xfc, 0xea, 0xf4, 0xfe, 0x75, 0xef, 0x16, 0xef, 0x4e, + 0x2f, 0xfe, 0xd0, 0xca, 0x09, 0xfa, 0xee, 0x01, 0x1e, 0x1b, 0xfe, 0x13, 0x0a, + 0x12, 0x07, 0x01, 0xf7, 0x03, 0xee, 0x31, 0x41, 0xa8, 0x09, 0xef, 0x3b, 0x13, + 0x05, 0xfc, 0x09, 0x20, 0x30, 0x18, 0xf3, 0x19, 0xf9, 0x42, 0x30, 0x74, 0xdb, + 0x07, 0xc7, 0xb7, 0xef, 0xde, 0xee, 0x18, 0xd2, 0xb3, 0xb9, 0x01, 0x04, 0x11, + 0xff, 0xb9, 0xc3, 0x01, 0xd4, 0x24, 0xd2, 0xcc, 0x1a, 0x4a, 0xd2, 0xe4, 0x2d, + 0xa8, 0xad, 0xa9, 0xe7, 0xaf, 0x2d, 0xe0, 0x69, 0x07, 0xfc, 0xb7, 0x40, 0xe2, + 0xe8, 0xf3, 0xb1, 0xfd, 0x1c, 0xfd, 0x51, 0x03, 0xe1, 0xeb, 0xf1, 0x9f, 0xca, + 0xe1, 0x46, 0xd6, 0xce, 0xe5, 0x27, 0x34, 0xdf, 0x4a, 0xeb, 0x09, 0x09, 0xb3, + 0xdc, 0xf5, 0xb2, 0xd9, 0x44, 0x34, 0x0c, 0xf0, 0xf2, 0xcf, 0xe7, 0xc1, 0x90, + 0xbf, 0x0a, 0x10, 0xc0, 0x23, 0xf7, 0x67, 0xbd, 0xca, 0x28, 0xd7, 0x14, 0xc3, + 0x54, 0xea, 0xb6, 0x7f, 0xd3, 0xc8, 0xd3, 0x10, 0xe4, 0xe5, 0x3a, 0x43, 0x0b, + 0xdb, 0xc8, 0xb5, 0xec, 0x53, 0x34, 0x26, 0xc9, 0x1d, 0xcc, 0xc7, 0xf0, 0x1c, + 0x25, 0x0a, 0x27, 0xe1, 0x08, 0xec, 0xd4, 0x15, 0xb4, 0x49, 0xe5, 0x60, 0x6c, + 0xf9, 0xd0, 0xa3, 0x41, 0xea, 0x2a, 0xf3, 0xfa, 0x29, 0xc0, 0x06, 0xe3, 0xe3, + 0x39, 0x29, 0xd8, 0x61, 0x16, 0xf4, 0x27, 0x42, 0x07, 0xb8, 0x15, 0x27, 0xd2, + 0xe9, 0xc2, 0x7f, 0x07, 0xe1, 0x6d, 0x2a, 0xec, 0x35, 0xf3, 0x09, 0xf3, 0x3d, + 0xf1, 0xeb, 0x34, 0x01, 0x07, 0xf4, 0xfd, 0x00, 0xd8, 0x1f, 0x1d, 0xfd, 0xe5, + 0x07, 0xe5, 0xfc, 0xfe, 0x24, 0x3f, 0xe3, 0x3e, 0x19, 0x09, 0x4a, 0xe3, 0xe7, + 0x6d, 0xdd, 0x17, 0xee, 0x16, 0x38, 0x13, 0xea, 0xb1, 0xf5, 0xf4, 0xd2, 0x0d, + 0x10, 0x01, 0xdb, 0x11, 0xfb, 0xef, 0xd3, 0x27, 0xe9, 0x22, 0x31, 0xe6, 0x47, + 0x14, 0x24, 0xc8, 0x14, 0xd1, 0xeb, 0x04, 0x11, 0x0d, 0xee, 0xf6, 0xe2, 0x14, + 0xdf, 0xfe, 0xdd, 0x0a, 0xf8, 0xf6, 0x27, 0x75, 0xe1, 0xa7, 0xde, 0x5c, 0x0f, + 0xcc, 0xd7, 0xe9, 0xf9, 0xcd, 0x0d, 0x91, 0xef, 0xf1, 0xf2, 0x7f, 0xd7, 0xd4, + 0x12, 0xf5, 0x0e, 0xd4, 0xdb, 0x3f, 0x4c, 0xcd, 0x10, 0xf9, 0x4d, 0x05, 0xe9, + 0x3d, 0x1b, 0x4e, 0xdc, 0x13, 0x33, 0x0a, 0x16, 0xf0, 0xeb, 0xa6, 0xe0, 0xdf, + 0x12, 0x08, 0xd6, 0x12, 0x00, 0x1b, 0x1b, 0xf6, 0x06, 0x38, 0xf5, 0xd2, 0x57, + 0xf5, 0xfa, 0x0b, 0xf3, 0x2f, 0x14, 0xfe, 0x26, 0xf2, 0xd3, 0xe5, 0x1e, 0xfb, + 0xdb, 0xea, 0xbe, 0x0b, 0x52, 0x0f, 0x16, 0xec, 0xef, 0x04, 0x0f, 0x34, 0x08, + 0xfa, 0x20, 0xc4, 0x01, 0x41, 0x18, 0xdf, 0xd0, 0xd0, 0x07, 0xf0, 0xf0, 0x11, + 0xf6, 0xc8, 0xee, 0x28, 0x14, 0xc6, 0xbf, 0xf6, 0xf4, 0x0f, 0x29, 0xf5, 0x1b, + 0x09, 0x09, 0x01, 0xe1, 0xf4, 0xc0, 0xe2, 0xe2, 0x13, 0x1a, 0xf8, 0x07, 0x07, + 0x08, 0xf2, 0xd0, 0xea, 0x0d, 0x4c, 0x01, 0xa6, 0x48, 0x04, 0x0a, 0x14, 0x90, + 0xfe, 0x0f, 0x2b, 0xa6, 0x7f, 0x84, 0x2d, 0x37, 0x07, 0xb2, 0xeb, 0x63, 0x0b, + 0xc9, 0xa5, 0xef, 0x35, 0x0c, 0xe3, 0x13, 0xf6, 0x20, 0xe5, 0xec, 0x09, 0x21, + 0x6b, 0xe2, 0x02, 0xc2, 0xd3, 0xe5, 0x13, 0xe6, 0x4a, 0x19, 0x9c, 0x24, 0x3b, + 0xba, 0xcb, 0xda, 0x00, 0x55, 0xee, 0x35, 0xad, 0xf2, 0x9a, 0x75, 0xe8, 0xf0, + 0x03, 0x0b, 0x17, 0xed, 0xd5, 0x18, 0xc9, 0xfe, 0xe0, 0xf6, 0xbd, 0xe8, 0xb8, + 0x53, 0xd8, 0xe8, 0x1f, 0x16, 0xd2, 0xdd, 0x1f, 0x50, 0x37, 0xf7, 0x54, 0x23, + 0x17, 0xd4, 0xd7, 0xd7, 0xf7, 0xd3, 0xd9, 0x08, 0x37, 0x21, 0xcf, 0xf5, 0x17, + 0xe3, 0xd9, 0xb6, 0xe5, 0x25, 0xd0, 0xee, 0x27, 0xd3, 0x46, 0x8b, 0x12, 0x21, + 0x26, 0x74, 0xaa, 0x10, 0x02, 0xff, 0x46, 0x31, 0x16, 0x30, 0xb2, 0x0b, 0x3e, + 0xc4, 0x30, 0x61, 0xfe, 0xf8, 0x4c, 0xb8, 0xfc, 0xee, 0x19, 0xf0, 0xcd, 0x1b, + 0x26, 0x35, 0x38, 0x0c, 0xe7, 0xf0, 0xfd, 0xec, 0xe5, 0x3d, 0xf0, 0x08, 0xd1, + 0x16, 0x16, 0x14, 0xce, 0x08, 0xfa, 0x25, 0xfb, 0xe6, 0x26, 0xd2, 0xfa, 0xff, + 0x04, 0xf4, 0x19, 0x0b, 0x01, 0x07, 0x17, 0xf4, 0x08, 0xdc, 0xc5, 0x08, 0xe0, + 0x4f, 0x24, 0xe6, 0xd5, 0x16, 0x19, 0xf9, 0xe8, 0xc6, 0xc9, 0xeb, 0x21, 0x06, + 0x2d, 0x15, 0xf2, 0x1a, 0xfa, 0xff, 0x0a, 0xf2, 0xfa, 0xeb, 0xa8, 0x03, 0xbe, + 0xd8, 0xf4, 0xf1, 0xfa, 0x35, 0x33, 0x46, 0xc1, 0xf7, 0x2b, 0xc3, 0xcb, 0xf6, + 0xd7, 0xf5, 0xf5, 0x34, 0x06, 0xde, 0x1c, 0x2c, 0xd7, 0xbf, 0xe8, 0xca, 0x22, + 0xff, 0x58, 0x14, 0xe0, 0xd9, 0xef, 0xd4, 0x33, 0x13, 0xff, 0x08, 0x19, 0xd7, + 0x81, 0x01, 0xf8, 0xea, 0xfb, 0x2b, 0x05, 0x16, 0x1b, 0x0e, 0xd8, 0xdf, 0x0f, + 0x1a, 0xfe, 0x15, 0x03, 0x2c, 0x07, 0x1c, 0xf4, 0xe5, 0xe0, 0xd9, 0x03, 0x03, + 0xff, 0xc4, 0x2f, 0x49, 0x12, 0xde, 0xd7, 0xc9, 0xf5, 0xfb, 0xfd, 0x23, 0x1e, + 0xf1, 0x20, 0xd7, 0xd1, 0x34, 0x1e, 0x29, 0xf3, 0x16, 0xf7, 0x34, 0x21, 0xd4, + 0x0c, 0xe0, 0xf8, 0xec, 0x2c, 0x06, 0xd0, 0x2d, 0x22, 0x09, 0x33, 0x64, 0xf2, + 0x32, 0xef, 0x1f, 0xea, 0xfd, 0xaf, 0xfd, 0xf7, 0xf0, 0x02, 0x2e, 0xfa, 0xcd, + 0xf0, 0xec, 0xea, 0xf8, 0xe7, 0x07, 0xe7, 0xe1, 0xde, 0xfb, 0x04, 0xe6, 0x00, + 0x00, 0xe9, 0x2a, 0x51, 0xdd, 0x2d, 0xf9, 0xfe, 0xdf, 0xed, 0xf3, 0x12, 0xba, + 0x81, 0x1f, 0x07, 0xe2, 0xe2, 0x08, 0xff, 0x00, 0x20, 0xe3, 0x28, 0xf9, 0xee, + 0xf2, 0x01, 0xfa, 0x3c, 0x1a, 0x11, 0xec, 0xff, 0x25, 0x1e, 0x29, 0xfb, 0x17, + 0xcb, 0xcd, 0x40, 0xf2, 0x03, 0xeb, 0xdf, 0xce, 0x07, 0x0f, 0x2d, 0xec, 0xe2, + 0x03, 0x17, 0x10, 0xf8, 0x16, 0xf3, 0xf2, 0x0a, 0xd4, 0xee, 0x3f, 0xfd, 0x1e, + 0x10, 0x46, 0xe7, 0xe5, 0xd5, 0xba, 0xed, 0xff, 0xf6, 0x58, 0x13, 0xda, 0x35, + 0xba, 0xe2, 0x1b, 0x25, 0xe7, 0xf1, 0xcc, 0xb3, 0x1e, 0x44, 0xed, 0x0e, 0xcc, + 0xe7, 0xe5, 0xeb, 0x36, 0xcb, 0x57, 0x0b, 0xc7, 0x32, 0x1d, 0x3c, 0x18, 0xd1, + 0xfd, 0x06, 0xdf, 0x07, 0xcf, 0xe0, 0x02, 0x1d, 0xed, 0x2e, 0xbf, 0x0d, 0xff, + 0x07, 0xc7, 0xf5, 0xe6, 0xd0, 0xf5, 0x00, 0xf8, 0x17, 0xfe, 0xfd, 0xe8, 0x3a, + 0xe7, 0x2b, 0x18, 0x4f, 0xf8, 0x2e, 0xfb, 0x2d, 0xa1, 0x01, 0xe9, 0x81, 0xe2, + 0xbb, 0x00, 0xcf, 0xf3, 0xc8, 0xf9, 0x57, 0xc9, 0x16, 0xd2, 0x22, 0xe9, 0x06, + 0xf2, 0x14, 0x15, 0x4a, 0xe9, 0xf4, 0x09, 0xef, 0x1a, 0x97, 0x20, 0xdf, 0xde, + 0x21, 0xfc, 0x0a, 0xdb, 0xd9, 0x02, 0xe9, 0xf5, 0xf9, 0xf4, 0x0f, 0x2b, 0x25, + 0x39, 0x0a, 0x36, 0x20, 0xf0, 0xef, 0x27, 0xfd, 0xeb, 0x5d, 0x08, 0xe1, 0xfe, + 0x46, 0xea, 0x50, 0x11, 0x0f, 0x23, 0xf2, 0xd1, 0x2d, 0x0c, 0x32, 0xed, 0x0b, + 0xd6, 0x25, 0xbc, 0x7f, 0x0e, 0xe6, 0xfc, 0x17, 0x47, 0xe7, 0x13, 0x3e, 0x15, + 0x1a, 0x13, 0xde, 0x12, 0x1d, 0x31, 0xee, 0xe9, 0x36, 0xe8, 0x24, 0xe7, 0x15, + 0x03, 0x03, 0x48, 0x24, 0xe3, 0xeb, 0x08, 0x09, 0xf9, 0x20, 0x17, 0xe5, 0xf7, + 0xec, 0xf7, 0x3b, 0x17, 0xaf, 0xfd, 0x02, 0x77, 0x22, 0x14, 0xe2, 0xe8, 0x1b, + 0xf0, 0xe4, 0x21, 0xb1, 0xcc, 0xfe, 0xec, 0xac, 0xc4, 0xc7, 0xc9, 0x03, 0xf8, + 0xde, 0xd9, 0xf3, 0xc3, 0xea, 0xed, 0xfb, 0x0c, 0x35, 0x22, 0x00, 0x64, 0x3b, + 0x09, 0x0b, 0x4e, 0x16, 0x22, 0x06, 0xf7, 0x6d, 0x09, 0xab, 0xed, 0xf6, 0x00, + 0x11, 0xb4, 0x0c, 0xf6, 0xf1, 0x26, 0xb2, 0x2b, 0x05, 0x04, 0x01, 0xa3, 0xd6, + 0x0c, 0x57, 0xe5, 0x07, 0x32, 0xf2, 0xf1, 0x00, 0xed, 0x24, 0xc1, 0xed, 0x12, + 0x45, 0xce, 0x35, 0xfd, 0xec, 0x2f, 0xd0, 0xed, 0xe8, 0xe5, 0x21, 0x0e, 0x0d, + 0x6c, 0x68, 0xcb, 0xdd, 0x20, 0x23, 0x30, 0xea, 0x20, 0x18, 0x1a, 0xee, 0xf1, + 0xaf, 0xef, 0xfb, 0xe2, 0xa3, 0xc0, 0xee, 0xf2, 0x7f, 0x82, 0x28, 0x36, 0x2e, + 0xf7, 0x12, 0x07, 0xc3, 0xee, 0xe2, 0x16, 0xea, 0x2f, 0x0a, 0xfc, 0x0b, 0xef, + 0x11, 0xb6, 0xcb, 0x18, 0xdc, 0x0c, 0x30, 0x3c, 0x0b, 0x39, 0x41, 0xe3, 0xe3, + 0x08, 0xff, 0x4c, 0xbb, 0xaf, 0x09, 0x6a, 0x0a, 0xd0, 0xe6, 0x1a, 0x1b, 0xea, + 0x29, 0x27, 0xdc, 0xe2, 0xc0, 0x1e, 0xff, 0xcf, 0x2c, 0x37, 0x3b, 0x05, 0xe8, + 0xb9, 0x33, 0xd0, 0x00, 0xdb, 0x20, 0xc7, 0x41, 0xc3, 0x0a, 0xf0, 0x20, 0x54, + 0x01, 0x0b, 0xd6, 0xef, 0x07, 0x18, 0x42, 0xcf, 0x26, 0x5b, 0xce, 0xf2, 0xea, + 0xfb, 0x0a, 0x2d, 0xf8, 0x02, 0xe2, 0xcd, 0xd2, 0x36, 0x02, 0x10, 0x27, 0x1b, + 0xca, 0x33, 0x34, 0xdb, 0xf5, 0x33, 0xdd, 0x1a, 0x0e, 0x3c, 0xd5, 0xd9, 0x16, + 0x15, 0x15, 0x0c, 0xe4, 0x15, 0x1d, 0x21, 0x20, 0x02, 0xf0, 0xe2, 0x3f, 0xd2, + 0x28, 0x16, 0xf7, 0x3d, 0xca, 0xca, 0x1e, 0xc9, 0xdf, 0x2d, 0xe4, 0x21, 0xe8, + 0xbe, 0x21, 0x2d, 0x06, 0xe5, 0xfc, 0x11, 0xf9, 0xfb, 0x2c, 0xeb, 0x39, 0x33, + 0x07, 0x06, 0x08, 0xc0, 0xee, 0xe9, 0xe5, 0x81, 0xf7, 0x04, 0x1c, 0x39, 0xff, + 0xf2, 0x13, 0x13, 0xf7, 0xc6, 0x46, 0xdc, 0xad, 0x04, 0xf7, 0x0b, 0x09, 0x04, + 0xde, 0x20, 0xdc, 0x00, 0xe3, 0x16, 0xd4, 0xde, 0xbf, 0xba, 0xe5, 0x62, 0xe7, + 0xf6, 0xde, 0xde, 0xd9, 0x30, 0xee, 0xf8, 0x00, 0x01, 0xdf, 0x05, 0xdf, 0xef, + 0x31, 0xec, 0xda, 0x1c, 0xf0, 0x00, 0x1b, 0xbf, 0xdc, 0xc1, 0x19, 0xe4, 0x2e, + 0xef, 0x15, 0x03, 0xd8, 0x1d, 0xdd, 0x02, 0x2b, 0x2b, 0xf1, 0xf8, 0x3d, 0x1d, + 0xfe, 0x1f, 0xce, 0x37, 0x35, 0xd6, 0x0f, 0xfb, 0x20, 0xb3, 0xe3, 0x33, 0xf7, + 0xc9, 0xd3, 0x0e, 0xe8, 0x07, 0x1a, 0xea, 0x04, 0xf4, 0xf7, 0x0c, 0x13, 0x4c, + 0x04, 0xe2, 0xd5, 0x0e, 0xbb, 0x1f, 0xde, 0xfb, 0x9e, 0x99, 0x12, 0x8c, 0xeb, + 0x43, 0xe3, 0xf8, 0x09, 0xe0, 0x1a, 0xe1, 0xdc, 0x16, 0x0d, 0x15, 0x09, 0x0b, + 0xbc, 0xf5, 0xfe, 0x23, 0x2f, 0xe6, 0x27, 0xed, 0xe1, 0x21, 0xd5, 0x44, 0xf1, + 0xe3, 0xed, 0xff, 0xb1, 0xeb, 0xf6, 0xe0, 0x13, 0xfe, 0x41, 0x08, 0xf9, 0x12, + 0xfb, 0x1a, 0xf7, 0x3c, 0x01, 0xdf, 0x7f, 0x12, 0xe2, 0x76, 0x24, 0x19, 0xf0, + 0xd3, 0x5e, 0xe8, 0xeb, 0x13, 0xda, 0x07, 0x17, 0xe6, 0x0a, 0x05, 0xf6, 0x17, + 0xd5, 0xcf, 0xe5, 0x0e, 0xc6, 0x3e, 0xd9, 0x00, 0xb1, 0x16, 0xec, 0xce, 0x23, + 0x6e, 0xdd, 0xdc, 0x3c, 0xd9, 0xd8, 0x13, 0xde, 0xf8, 0x19, 0xf8, 0x63, 0xca, + 0x11, 0xa3, 0xf3, 0x86, 0x0c, 0x31, 0x12, 0x16, 0x9f, 0xe1, 0xf0, 0xb9, 0x04, + 0xa3, 0xea, 0x01, 0x12, 0x19, 0x38, 0xd1, 0x2e, 0x44, 0x01, 0xfa, 0xb8, 0xcd, + 0xf1, 0x02, 0xd8, 0x66, 0xeb, 0x45, 0xea, 0xca, 0xf1, 0xb7, 0xe9, 0xf2, 0xe4, + 0xc5, 0x08, 0x02, 0xf9, 0x14, 0xfe, 0x11, 0x33, 0x2e, 0xe1, 0x21, 0x34, 0x13, + 0x2a, 0xf0, 0x24, 0xcc, 0xb9, 0x36, 0xd1, 0xbf, 0xbf, 0xcf, 0x59, 0xc7, 0x81, + 0x13, 0xa2, 0xfb, 0x0d, 0xf3, 0xdc, 0x0d, 0xc7, 0xf5, 0xd8, 0xbe, 0x05, 0xd5, + 0xe6, 0x23, 0x76, 0xda, 0xf3, 0x19, 0x26, 0xfb, 0x34, 0xd9, 0x13, 0x40, 0x0d, + 0x9f, 0x41, 0x7b, 0xfb, 0x04, 0x1b, 0xcc, 0x32, 0x21, 0x1c, 0x15, 0x1b, 0xee, + 0x4e, 0xe5, 0x0c, 0x04, 0x46, 0xe4, 0xfd, 0xd8, 0xf1, 0xf3, 0xe8, 0x14, 0x21, + 0xed, 0xfc, 0x0f, 0x2e, 0xf3, 0xf1, 0xcc, 0xd5, 0xfa, 0xeb, 0xe6, 0x25, 0x7f, + 0x0f, 0x15, 0xf5, 0x1a, 0x24, 0x53, 0x1a, 0x5b, 0xee, 0xde, 0x00, 0x55, 0xf4, + 0xf9, 0xe1, 0xd9, 0x05, 0x27, 0xd3, 0x46, 0x22, 0x0a, 0x05, 0x39, 0xe0, 0x0c, + 0x2f, 0xdb, 0xfd, 0xfe, 0x13, 0xcf, 0xb3, 0xc1, 0x0c, 0xe3, 0x08, 0xde, 0xe5, + 0x24, 0xe7, 0xd3, 0x34, 0xfa, 0x0b, 0x10, 0x33, 0xe3, 0xd9, 0x01, 0x09, 0x14, + 0xed, 0x21, 0xdc, 0xf4, 0xc0, 0x1f, 0x54, 0xcc, 0x2b, 0x15, 0xf3, 0xf4, 0xc1, + 0x12, 0x14, 0xfd, 0xe0, 0xee, 0x08, 0x0c, 0xdc, 0xdf, 0xe0, 0x03, 0x04, 0x0e, + 0xe9, 0xd7, 0xfd, 0xfc, 0xee, 0x00, 0xf3, 0xfc, 0xfb, 0xf6, 0x07, 0xee, 0x16, + 0xf4, 0xfa, 0xfc, 0xff, 0xf2, 0xda, 0x03, 0x03, 0x05, 0xdf, 0xfa, 0xef, 0x66, + 0x26, 0xb2, 0x14, 0x0a, 0x13, 0x05, 0xff, 0x0b, 0x3e, 0x19, 0x1a, 0x13, 0x0f, + 0x4a, 0x18, 0x0d, 0x33, 0x0e, 0x04, 0x01, 0x42, 0x3b, 0x35, 0x1d, 0xeb, 0x18, + 0x16, 0x1f, 0x0d, 0x0b, 0x36, 0x16, 0x21, 0x15, 0x19, 0xcd, 0x13, 0x23, 0xf8, + 0x14, 0x02, 0x19, 0x3e, 0x1e, 0x10, 0x2a, 0x0d, 0x41, 0xfa, 0x0c, 0x00, 0x07, + 0x21, 0x19, 0x2f, 0x18, 0x04, 0x24, 0xf4, 0x06, 0x11, 0x1e, 0x02, 0x25, 0x3b, + 0x16, 0x08, 0x0c, 0xfc, 0xd6, 0x07, 0xe8, 0x1e, 0xea, 0x08, 0x10, 0xf6, 0x10, + 0x7f, 0x1a, 0x01, 0x1b, 0x2f, 0xf9, 0x26, 0xf6, 0x13, 0xe7, 0xe6, 0xef, 0x33, + 0xfa, 0x22, 0xe3, 0x19, 0xf9, 0x14, 0x20, 0x11, 0x24, 0xee, 0xf9, 0xfa, 0xeb, + 0xec, 0xf6, 0xf8, 0x23, 0xdc, 0x05, 0x15, 0x0c, 0xf3, 0xfd, 0xde, 0x3c, 0xfb, + 0xe0, 0xf3, 0x2c, 0x1e, 0x08, 0xf7, 0x0e, 0xe9, 0xeb, 0x06, 0x3c, 0x11, 0xf3, + 0x39, 0xf7, 0xf2, 0x16, 0xe8, 0xdc, 0xe5, 0x18, 0x3b, 0xbc, 0x07, 0x24, 0x06, + 0xed, 0xe6, 0xcb, 0x12, 0x06, 0xef, 0x25, 0x1e, 0x0b, 0x1f, 0xb3, 0x08, 0x50, + 0x1b, 0x14, 0x02, 0x1e, 0x11, 0x8b, 0x13, 0xf2, 0x18, 0xbe, 0xba, 0xda, 0x20, + 0x3f, 0xdc, 0x38, 0xe7, 0xea, 0x2a, 0x69, 0xd3, 0x26, 0x07, 0x11, 0x04, 0xd2, + 0x10, 0xdd, 0xe8, 0x3c, 0x0c, 0x0c, 0xec, 0xe7, 0x19, 0x02, 0xbe, 0xbc, 0xf8, + 0xed, 0xe7, 0xfd, 0xf4, 0xdb, 0x33, 0x18, 0x00, 0xda, 0xd6, 0x7f, 0x3c, 0x17, + 0xb1, 0xcb, 0x67, 0x2f, 0xc0, 0x28, 0x48, 0xaf, 0xe2, 0x1e, 0xf7, 0xe7, 0xdd, + 0x1f, 0xdf, 0x27, 0x09, 0x09, 0xf8, 0xd0, 0x3e, 0x19, 0x32, 0x13, 0xd5, 0xe7, + 0xdb, 0x1b, 0x28, 0x95, 0x17, 0xf1, 0xcf, 0xb5, 0x20, 0x00, 0xf5, 0xf6, 0xd3, + 0x3f, 0xdc, 0xe1, 0x0d, 0xfb, 0x32, 0xe0, 0x09, 0x1e, 0xe2, 0x31, 0xdd, 0x02, + 0x1c, 0xc7, 0x0b, 0xf2, 0xdb, 0x48, 0xf4, 0x20, 0xf0, 0x14, 0x3a, 0x1b, 0xcd, + 0xd4, 0xf5, 0xf0, 0xc1, 0x81, 0xef, 0xf1, 0xd8, 0xf3, 0xac, 0xce, 0x01, 0xa9, + 0x39, 0x24, 0xea, 0xe0, 0x13, 0xf1, 0x3d, 0xc0, 0xe2, 0xd8, 0xce, 0x2d, 0x21, + 0xe9, 0xde, 0xc0, 0x70, 0xd3, 0xd8, 0x03, 0xf6, 0xc2, 0x24, 0x04, 0xd1, 0x07, + 0x1b, 0x06, 0xfb, 0x06, 0xfb, 0x15, 0xb9, 0x1d, 0xd4, 0xd3, 0xce, 0x0a, 0x0e, + 0x0b, 0x35, 0xc5, 0x1a, 0x11, 0xd7, 0xf4, 0xfd, 0xfe, 0xe1, 0xec, 0x2b, 0x26, + 0xac, 0x76, 0x25, 0x40, 0xe4, 0x03, 0xa9, 0xb6, 0xf6, 0xf1, 0x07, 0x2e, 0x1f, + 0xf2, 0xf7, 0x28, 0x07, 0xf2, 0x37, 0xd6, 0xef, 0xf2, 0x21, 0xe8, 0xe9, 0xed, + 0x3e, 0xfb, 0x2b, 0x01, 0xf2, 0x06, 0xe3, 0xb2, 0xed, 0x08, 0xe1, 0xee, 0xd8, + 0x0d, 0xe8, 0xd9, 0x17, 0x3c, 0xfd, 0xd4, 0xb2, 0x24, 0x27, 0x18, 0x18, 0xf6, + 0xdf, 0xf4, 0xd9, 0xf7, 0xfa, 0x18, 0x66, 0x13, 0x22, 0xf9, 0xd8, 0xcc, 0x3b, + 0x22, 0xc8, 0x03, 0xe1, 0x71, 0x4a, 0x09, 0xf5, 0x12, 0x03, 0x0d, 0x26, 0x0d, + 0xea, 0xf5, 0xcc, 0xe4, 0xf4, 0x22, 0xab, 0x08, 0x1b, 0x5d, 0xbf, 0x6b, 0xe4, + 0xfb, 0x21, 0xde, 0xe2, 0x53, 0x24, 0x33, 0x06, 0x11, 0xc8, 0x0c, 0x0f, 0x12, + 0x05, 0xfd, 0xe3, 0xf5, 0x1e, 0xdd, 0x41, 0x07, 0xd0, 0xe1, 0xcd, 0xbf, 0x17, + 0x24, 0x2e, 0xe8, 0x20, 0x08, 0x01, 0xb9, 0x4b, 0xd1, 0x2e, 0xf8, 0xf5, 0x2a, + 0xf6, 0xfd, 0x1d, 0x10, 0xc0, 0xd9, 0xda, 0x1d, 0x2d, 0x18, 0x28, 0xfb, 0x5d, + 0x32, 0xbc, 0xf7, 0x41, 0x03, 0xe6, 0xdc, 0x3a, 0x1d, 0x14, 0xb2, 0x04, 0x7f, + 0xec, 0xf1, 0x26, 0xea, 0x2b, 0xe4, 0xed, 0x13, 0x0e, 0xe0, 0x04, 0x08, 0x0a, + 0x1a, 0xf7, 0xf4, 0x2c, 0xcc, 0x27, 0x3c, 0xe8, 0x37, 0xbb, 0x2f, 0x35, 0x18, + 0x32, 0x11, 0x41, 0xa4, 0xe4, 0xff, 0xeb, 0xea, 0xfc, 0xde, 0x00, 0xda, 0xc1, + 0x4a, 0xd4, 0xd7, 0xc4, 0x33, 0xcf, 0x27, 0x20, 0xcb, 0x34, 0x06, 0x08, 0xca, + 0xcb, 0x47, 0xdc, 0xea, 0x28, 0xd0, 0xdd, 0xe1, 0x24, 0xd6, 0x04, 0xbf, 0x0a, + 0x30, 0x23, 0x00, 0xdb, 0x14, 0xf9, 0xf3, 0xf3, 0x52, 0xdd, 0xd5, 0xc7, 0xa9, + 0x19, 0xc8, 0xff, 0x19, 0x20, 0xdc, 0x43, 0xf4, 0xd2, 0x0b, 0xcf, 0x20, 0xd0, + 0x22, 0x3b, 0x17, 0x31, 0xa6, 0x7f, 0xe0, 0x57, 0x08, 0x61, 0x1a, 0x25, 0xe7, + 0x27, 0x27, 0x20, 0x0d, 0xc0, 0x0e, 0xe2, 0x2e, 0xf0, 0x06, 0xf1, 0x0f, 0xe5, + 0x09, 0x11, 0xd9, 0xdd, 0x25, 0x96, 0x27, 0xde, 0x03, 0x1f, 0xff, 0x1d, 0xfa, + 0xe6, 0x02, 0x35, 0xf9, 0xfa, 0x43, 0x29, 0x33, 0xf8, 0xf1, 0xc1, 0x3e, 0xe6, + 0x26, 0x2a, 0x1b, 0xd4, 0x1c, 0x2d, 0x00, 0x8f, 0xe5, 0xdb, 0x14, 0xfc, 0x96, + 0x41, 0xf7, 0x04, 0x16, 0x1a, 0xc3, 0xfb, 0xec, 0x4b, 0x01, 0xa3, 0x07, 0xe3, + 0xca, 0x15, 0xa4, 0x2f, 0x01, 0x25, 0x7f, 0xee, 0xe6, 0x21, 0x53, 0xde, 0x35, + 0x01, 0x08, 0x13, 0x05, 0xd2, 0x3f, 0xd5, 0xf8, 0x2b, 0x18, 0xaf, 0xe5, 0xd0, + 0xfc, 0x66, 0xf2, 0xd8, 0xfc, 0x14, 0xbf, 0x0c, 0xe6, 0x53, 0x17, 0x26, 0x24, + 0x46, 0x2b, 0xe5, 0x14, 0xf5, 0xde, 0x1a, 0xdf, 0xe2, 0xf9, 0x46, 0x22, 0x02, + 0xf2, 0xc7, 0xa6, 0xcb, 0xbc, 0xf9, 0xe9, 0x4c, 0xc6, 0x33, 0xe7, 0xab, 0xd8, + 0x07, 0x09, 0x4f, 0x0c, 0x1e, 0xe6, 0xd2, 0x2c, 0xca, 0xf1, 0x41, 0xca, 0xf8, + 0x17, 0xf6, 0x31, 0x34, 0x01, 0xdd, 0x2a, 0xed, 0xf1, 0xb9, 0xe1, 0xfe, 0x26, + 0x42, 0x2d, 0x1b, 0x3f, 0xf7, 0x14, 0xec, 0x08, 0xf1, 0xea, 0x12, 0xcc, 0xd3, + 0x24, 0xf9, 0xc0, 0xe0, 0xea, 0xfb, 0x26, 0xfb, 0x1c, 0x20, 0x1b, 0xc4, 0x37, + 0xfc, 0x1e, 0x15, 0xfb, 0x09, 0x2d, 0x14, 0x0d, 0x3d, 0x1e, 0x03, 0xf2, 0xf2, + 0xd4, 0xf4, 0x35, 0xf7, 0x0f, 0xf2, 0xe7, 0x35, 0x21, 0xf2, 0xc6, 0x0a, 0x31, + 0xee, 0xf4, 0x2d, 0x0a, 0x14, 0x15, 0x0a, 0x1d, 0x01, 0x14, 0xf6, 0xfb, 0x2a, + 0x2e, 0x3d, 0x30, 0x03, 0x0c, 0x2a, 0x2d, 0x04, 0xf0, 0x1e, 0x0f, 0xee, 0x05, + 0x3e, 0xe5, 0x4d, 0xfe, 0xe1, 0xea, 0x2c, 0x47, 0xe8, 0x4d, 0x7f, 0xd4, 0x2d, + 0xae, 0xe6, 0x00, 0x0a, 0x28, 0xf2, 0xe9, 0x34, 0x0b, 0xd8, 0x59, 0x2b, 0xfe, + 0x23, 0x14, 0x3c, 0x01, 0x28, 0xe2, 0xfd, 0x0c, 0x21, 0xef, 0x21, 0xc3, 0x35, + 0x2e, 0x32, 0xe5, 0x0d, 0xf7, 0xf2, 0x3c, 0xfd, 0x68, 0xc8, 0x23, 0x19, 0x73, + 0x06, 0xe2, 0x23, 0x24, 0x2f, 0xf2, 0xff, 0x1d, 0x0b, 0x24, 0x31, 0x1b, 0x1a, + 0x14, 0x07, 0xe8, 0xeb, 0x34, 0x00, 0xf7, 0x2b, 0xea, 0x12, 0x35, 0x58, 0xc8, + 0xfe, 0xf5, 0x24, 0xfa, 0x23, 0x15, 0x0d, 0xde, 0xfe, 0x52, 0xf5, 0xfd, 0x21, + 0x32, 0x11, 0x18, 0xd2, 0x0b, 0x0d, 0x3a, 0xd2, 0xba, 0xb1, 0x04, 0xe7, 0x02, + 0x29, 0x64, 0xa5, 0x2d, 0x4e, 0x0f, 0x99, 0xfe, 0x0f, 0xc2, 0x00, 0xdd, 0xec, + 0xf6, 0xab, 0x15, 0x0a, 0xd1, 0xe3, 0x4d, 0xe5, 0xda, 0x16, 0x0c, 0x12, 0xe9, + 0x93, 0x29, 0xe4, 0xf1, 0x09, 0x55, 0xfb, 0xe3, 0x07, 0x10, 0xea, 0xcf, 0x28, + 0xde, 0x00, 0x41, 0xeb, 0x26, 0xd4, 0xcb, 0xfc, 0x35, 0xe7, 0xb8, 0xce, 0xeb, + 0xd0, 0xf8, 0x01, 0x00, 0x07, 0xfe, 0xc4, 0xea, 0x39, 0x07, 0x21, 0x28, 0x24, + 0x0d, 0xe9, 0xb9, 0xfc, 0x23, 0x0e, 0xe2, 0x5f, 0x11, 0x21, 0xc7, 0xee, 0xcd, + 0x36, 0x03, 0xf9, 0xe7, 0xf5, 0xee, 0xec, 0xf9, 0x7f, 0xcf, 0xfc, 0xed, 0xff, + 0xea, 0x0a, 0xd9, 0x01, 0x28, 0xda, 0xff, 0x0a, 0xff, 0xdc, 0xcf, 0x2e, 0x03, + 0x40, 0x01, 0x1c, 0x16, 0xdb, 0xd8, 0xe1, 0x1a, 0x23, 0x1d, 0xf0, 0xf3, 0xe3, + 0x7f, 0x33, 0xea, 0xed, 0xfd, 0x05, 0x2f, 0xe7, 0x09, 0x09, 0xf1, 0xe0, 0x1c, + 0xf7, 0x27, 0xf3, 0xb3, 0x70, 0xd2, 0xee, 0x1c, 0x4b, 0xdd, 0x3d, 0x05, 0xd0, + 0xf1, 0xe6, 0xe2, 0x0c, 0x03, 0xd3, 0xe7, 0x09, 0x17, 0xfd, 0x0f, 0x22, 0x07, + 0x22, 0xbf, 0x40, 0x0d, 0xe7, 0x3b, 0x39, 0x1d, 0xf8, 0xc5, 0xcd, 0xb0, 0xf6, + 0x30, 0xc2, 0x12, 0x2d, 0xf7, 0xd8, 0xf9, 0xd8, 0xdc, 0x01, 0xee, 0xd4, 0xd7, + 0xdc, 0xff, 0xe8, 0x05, 0xf2, 0xe1, 0x0a, 0xf4, 0x64, 0x1f, 0xf1, 0xf3, 0xd4, + 0x2a, 0xda, 0x29, 0xde, 0x04, 0x40, 0x15, 0x0b, 0x2a, 0xf8, 0xea, 0x02, 0x9a, + 0xf6, 0x22, 0x01, 0x12, 0xc4, 0x1d, 0x2d, 0x41, 0x1c, 0xcd, 0x77, 0xaf, 0xeb, + 0xee, 0xf0, 0x04, 0xf5, 0x20, 0x35, 0x12, 0xe8, 0x7f, 0xf6, 0x1e, 0xc4, 0xca, + 0x1e, 0x15, 0x4c, 0xd1, 0xf2, 0xea, 0x73, 0x00, 0xe7, 0xfd, 0x07, 0x1b, 0xea, + 0xb2, 0xdf, 0xf9, 0x0d, 0xd6, 0x3e, 0xa3, 0xc8, 0x0b, 0x20, 0xe7, 0xfa, 0xf7, + 0x0a, 0x22, 0x69, 0xc4, 0xc7, 0xd2, 0x22, 0xc0, 0xcc, 0x29, 0xad, 0xef, 0xe7, + 0x35, 0x27, 0x3b, 0x1a, 0x07, 0xd2, 0x0d, 0xd3, 0xc9, 0x1d, 0x31, 0x02, 0x0d, + 0x22, 0x31, 0x06, 0xfd, 0x14, 0x2c, 0x0c, 0x20, 0x93, 0xf0, 0xaa, 0xe8, 0xfb, + 0x01, 0x07, 0x2a, 0x1c, 0x1a, 0x06, 0xec, 0xff, 0xe5, 0x4a, 0x14, 0xba, 0x08, + 0xbd, 0x79, 0xd2, 0xf9, 0x0a, 0x24, 0x14, 0x12, 0xe1, 0xa9, 0x24, 0xc9, 0xdc, + 0xe3, 0x27, 0x28, 0x20, 0x18, 0x34, 0x25, 0x27, 0xb7, 0x93, 0x12, 0xf7, 0x06, + 0x15, 0xf0, 0x20, 0x30, 0x00, 0xf2, 0x6c, 0xd9, 0xfd, 0x14, 0x3c, 0x03, 0xf6, + 0x09, 0xe3, 0xfc, 0xe5, 0xd3, 0x02, 0xde, 0xc4, 0xe3, 0xe2, 0x2b, 0x27, 0x38, + 0xe1, 0xe8, 0x16, 0x26, 0xd8, 0xd0, 0xdf, 0xcd, 0xc9, 0x1e, 0xc4, 0x33, 0xf8, + 0x58, 0xd4, 0x2e, 0x2e, 0xfd, 0xd2, 0x02, 0x41, 0xd6, 0x09, 0xf0, 0x0c, 0x5e, + 0xf0, 0xf4, 0xed, 0xea, 0xf8, 0x41, 0x09, 0xe6, 0xd0, 0xfe, 0xf4, 0xda, 0x32, + 0xda, 0x3d, 0xe6, 0xfc, 0x36, 0x37, 0xea, 0x12, 0xf7, 0x0b, 0x33, 0x08, 0x1b, + 0x01, 0x2a, 0xe1, 0xda, 0xf5, 0x1d, 0x11, 0x11, 0xfe, 0xff, 0xef, 0xcf, 0x3d, + 0x7f, 0xe3, 0xf1, 0xdc, 0x06, 0xe0, 0x1d, 0xe2, 0x09, 0x23, 0x18, 0xf0, 0x2e, + 0x0e, 0xfb, 0xfd, 0x0b, 0x29, 0xf1, 0xf2, 0x18, 0xf2, 0x09, 0xf3, 0x09, 0x20, + 0x3f, 0xd2, 0xce, 0x29, 0x54, 0xe3, 0x31, 0xd2, 0x1a, 0x1d, 0x0b, 0x17, 0x0e, + 0xd2, 0xe9, 0x08, 0x39, 0x16, 0xde, 0x09, 0x1d, 0x22, 0x0c, 0xd0, 0x17, 0xf1, + 0xea, 0x19, 0x3d, 0x60, 0x16, 0x45, 0x23, 0x0b, 0xc9, 0xce, 0xdc, 0xce, 0xf7, + 0x1b, 0xe4, 0x15, 0xf3, 0x02, 0x11, 0x04, 0x5b, 0x2a, 0x0d, 0x52, 0x55, 0xf4, + 0xc4, 0x26, 0x07, 0xef, 0x2d, 0x7a, 0x0b, 0x31, 0x6f, 0x15, 0xf3, 0xf0, 0x38, + 0x28, 0xfa, 0x26, 0xd3, 0x08, 0xf0, 0xe1, 0x02, 0xe5, 0x23, 0x0e, 0xfc, 0xdf, + 0xfa, 0x23, 0xff, 0x7e, 0x04, 0x2c, 0x08, 0xe8, 0xe9, 0x11, 0x51, 0x61, 0x1e, + 0x24, 0x21, 0x57, 0xcf, 0x29, 0xfc, 0x1c, 0xdb, 0x23, 0x3f, 0x25, 0xf5, 0x07, + 0xfd, 0xf7, 0xeb, 0x0e, 0xf8, 0x0e, 0x20, 0xe9, 0xf6, 0x04, 0x25, 0xe5, 0x1a, + 0xe8, 0x23, 0x60, 0xe6, 0x32, 0xf0, 0xec, 0xf8, 0xec, 0x7f, 0x00, 0x20, 0x6b, + 0xd7, 0xf6, 0x6f, 0x10, 0x05, 0x3d, 0xec, 0xf0, 0x24, 0x21, 0xdb, 0xe0, 0xcd, + 0x38, 0x15, 0x31, 0x46, 0xd3, 0xf4, 0x0f, 0x12, 0x00, 0x1e, 0x12, 0x17, 0xdd, + 0xfa, 0x10, 0xf0, 0xfb, 0x28, 0xda, 0x1b, 0xfb, 0x27, 0x01, 0x04, 0xe4, 0xcc, + 0xec, 0x0b, 0x18, 0x26, 0xe0, 0x48, 0xe5, 0xcd, 0x16, 0x12, 0x0c, 0x24, 0xea, + 0x1a, 0xee, 0x25, 0x38, 0x1a, 0x0e, 0x29, 0x0c, 0x26, 0x02, 0x28, 0xf4, 0x06, + 0x3a, 0x11, 0xf4, 0xfb, 0x00, 0x08, 0x02, 0x15, 0xe4, 0xf0, 0xf9, 0x0b, 0xfc, + 0x36, 0x33, 0x0f, 0x04, 0xf9, 0x20, 0x19, 0x01, 0x5a, 0x10, 0x25, 0x43, 0x11, + 0x08, 0xe3, 0x22, 0x2e, 0xf2, 0x26, 0xfc, 0xd6, 0x34, 0x16, 0x00, 0x2e, 0x19, + 0xdb, 0x01, 0x21, 0xf1, 0xdf, 0x1d, 0x16, 0xfa, 0x26, 0xce, 0xe9, 0xe3, 0xd6, + 0x22, 0x35, 0x06, 0xf4, 0x1d, 0x06, 0x2c, 0xfd, 0x1e, 0x52, 0x0e, 0x0f, 0x19, + 0x7f, 0xfc, 0xe5, 0x07, 0x20, 0xe3, 0x22, 0x01, 0x03, 0x1c, 0x0a, 0x2a, 0x0d, + 0x32, 0x26, 0x01, 0xdd, 0xf1, 0xb2, 0xfb, 0x05, 0xc6, 0xf4, 0xc9, 0x03, 0x0c, + 0xf5, 0xf0, 0xdc, 0xf2, 0xf6, 0xef, 0x0d, 0xb7, 0xf0, 0x11, 0xc2, 0x36, 0xd2, + 0x15, 0xd9, 0xd2, 0x7f, 0xdf, 0xd2, 0x1d, 0xec, 0x18, 0x01, 0xc3, 0x0a, 0xfe, + 0xfc, 0xda, 0x17, 0x37, 0xeb, 0x56, 0xd7, 0x0f, 0xa8, 0xfb, 0xb4, 0x35, 0xde, + 0x38, 0x2a, 0xa3, 0xf1, 0xd7, 0xe5, 0x2b, 0x0b, 0x02, 0xcd, 0x2a, 0x42, 0xd5, + 0xf0, 0xed, 0xfc, 0x10, 0x2c, 0x0f, 0x0a, 0x18, 0xe0, 0x45, 0x27, 0xde, 0xfd, + 0xe6, 0xdf, 0xf1, 0xfd, 0xea, 0xaf, 0x26, 0xfe, 0x0f, 0x09, 0x4c, 0xbc, 0x33, + 0x0f, 0xf6, 0x13, 0xec, 0x2e, 0xf3, 0xf8, 0xe7, 0xf9, 0xea, 0x04, 0x42, 0x10, + 0x09, 0xdf, 0xdf, 0xfe, 0xfb, 0xac, 0xe9, 0xb3, 0xc9, 0x18, 0xe9, 0x07, 0xf4, + 0xdd, 0xeb, 0x0a, 0xf3, 0x1f, 0xde, 0xad, 0xf5, 0x19, 0x60, 0x1a, 0xdc, 0xb6, + 0xe1, 0x14, 0xf2, 0xba, 0x3c, 0x0c, 0x20, 0x0f, 0x38, 0xe5, 0xe5, 0xe9, 0x34, + 0xfa, 0xbf, 0x48, 0xa3, 0xc3, 0x0a, 0x28, 0x13, 0xfe, 0x17, 0xf6, 0x3a, 0x59, + 0x34, 0xf1, 0x0a, 0x1e, 0xe8, 0x9d, 0xf8, 0x1c, 0xdb, 0xdb, 0x50, 0xc6, 0xdd, + 0x31, 0xcc, 0xc4, 0x0d, 0xb1, 0xb3, 0x48, 0x1b, 0x35, 0xca, 0x30, 0xce, 0xd1, + 0x81, 0x64, 0x95, 0x4f, 0x31, 0xd1, 0xe5, 0xe1, 0xf2, 0x05, 0xda, 0xc1, 0x20, + 0xf6, 0xa4, 0x02, 0x12, 0xe5, 0xa1, 0xd0, 0xf6, 0x2f, 0x23, 0xdc, 0x28, 0x35, + 0x4c, 0x28, 0xe0, 0x05, 0x07, 0xc7, 0x18, 0xc3, 0x01, 0xc4, 0xf3, 0xdc, 0xec, + 0x2d, 0x02, 0x12, 0x0e, 0x18, 0xe0, 0x08, 0xe1, 0x0b, 0xcf, 0x0d, 0xe1, 0xb5, + 0x34, 0xbb, 0xf3, 0x07, 0x2f, 0x11, 0xfc, 0xfc, 0x42, 0xf2, 0x15, 0x3a, 0x55, + 0xf2, 0xf2, 0xd9, 0xfb, 0xcc, 0xdc, 0x35, 0x13, 0x11, 0x0a, 0x03, 0xe9, 0xf7, + 0xf9, 0x5c, 0xe3, 0xee, 0xd4, 0x19, 0x34, 0xec, 0x49, 0x16, 0x29, 0x0e, 0xd7, + 0xe0, 0xcf, 0xef, 0x21, 0xfc, 0xf2, 0x11, 0x0c, 0xf5, 0x14, 0x1b, 0x17, 0xbd, + 0x08, 0x2c, 0xfa, 0xf3, 0x41, 0xc2, 0x00, 0xef, 0xd7, 0x25, 0xf6, 0x03, 0x00, + 0xd6, 0x10, 0xfc, 0x59, 0x08, 0xeb, 0x32, 0xbf, 0x1a, 0xb9, 0x22, 0x40, 0x2f, + 0x6a, 0x1f, 0xff, 0x11, 0xf8, 0xe9, 0xf0, 0xd9, 0xcd, 0x00, 0xdd, 0xe1, 0xcd, + 0x58, 0x06, 0xd2, 0xf2, 0xa8, 0xf3, 0x06, 0x21, 0x18, 0x1a, 0x06, 0x14, 0xe0, + 0xf5, 0x2c, 0x1f, 0x24, 0x0f, 0xc5, 0xf9, 0x05, 0x28, 0xcd, 0x06, 0xe0, 0xc3, + 0x22, 0x16, 0x16, 0x0f, 0x32, 0x2d, 0xfe, 0x1a, 0xf8, 0xf7, 0x29, 0x28, 0xd7, + 0x19, 0xeb, 0x4b, 0xe6, 0x07, 0x19, 0xd9, 0xf6, 0x05, 0x03, 0x08, 0xc3, 0xea, + 0xfb, 0x2d, 0xb6, 0xe8, 0x02, 0x31, 0xcd, 0xdf, 0x7f, 0xf3, 0xfc, 0x17, 0x04, + 0x12, 0x3c, 0xf3, 0x6b, 0x05, 0x02, 0xeb, 0x4a, 0xf8, 0x33, 0xe8, 0x23, 0x3b, + 0x07, 0x35, 0x4a, 0xf3, 0x81, 0xf7, 0x21, 0x0e, 0x49, 0x1b, 0x05, 0x30, 0xb7, + 0x37, 0x21, 0xf1, 0xee, 0x16, 0x2b, 0x10, 0x0c, 0x0c, 0xdc, 0x30, 0x02, 0xe9, + 0x29, 0xcc, 0x2d, 0xea, 0xfd, 0x21, 0x02, 0x15, 0x2a, 0x10, 0xff, 0xf4, 0x0b, + 0x10, 0xf8, 0x21, 0x35, 0xfc, 0x0c, 0xef, 0xed, 0x18, 0xfb, 0x02, 0x22, 0x02, + 0x2e, 0xda, 0x35, 0x00, 0x11, 0xe1, 0x26, 0x09, 0x4b, 0x12, 0x00, 0x03, 0x13, + 0x1d, 0x2c, 0x25, 0x36, 0xf5, 0x0f, 0xf6, 0xfe, 0x05, 0x0e, 0x31, 0x06, 0xe4, + 0x0f, 0xe9, 0x2a, 0x1e, 0x09, 0x35, 0x07, 0xfb, 0xd1, 0xd3, 0x04, 0x2a, 0xfc, + 0xfc, 0x28, 0xfd, 0x20, 0x34, 0x27, 0x03, 0xef, 0x1e, 0x2b, 0x0c, 0xfc, 0x13, + 0x2f, 0xdc, 0xfc, 0x0a, 0xe0, 0x1b, 0x6d, 0x08, 0xfe, 0x35, 0xd3, 0xec, 0xd8, + 0xf2, 0xd7, 0x07, 0x1e, 0xd5, 0x06, 0xf4, 0xe8, 0xec, 0x0e, 0xf9, 0xdc, 0xec, + 0x0c, 0xf8, 0xfc, 0x64, 0x2c, 0xd0, 0xf8, 0x1a, 0x2b, 0xcf, 0xaf, 0x1d, 0x3c, + 0x04, 0x22, 0x0b, 0x2a, 0xe4, 0x3d, 0x09, 0xf8, 0xcf, 0xde, 0xf9, 0xb8, 0xae, + 0xc9, 0xea, 0xd7, 0xd4, 0x1a, 0xec, 0x40, 0x20, 0xe4, 0xdc, 0x22, 0xda, 0x0a, + 0xe4, 0x5b, 0xaf, 0xd6, 0xf2, 0x1f, 0x1a, 0x1a, 0x04, 0xf0, 0xf2, 0x0f, 0x1f, + 0xfe, 0x22, 0x4d, 0xea, 0xcb, 0xec, 0xfe, 0xef, 0x3a, 0xf2, 0x2c, 0x26, 0xd5, + 0xfc, 0x7f, 0x79, 0xd4, 0xb3, 0xf9, 0x0b, 0x05, 0x32, 0xdf, 0xd5, 0xce, 0xbe, + 0x12, 0xe1, 0xfc, 0xfe, 0xf2, 0xe8, 0x2f, 0x24, 0xfa, 0xf3, 0xfd, 0x1a, 0xc8, + 0xfe, 0xea, 0x18, 0x09, 0x12, 0xca, 0xe7, 0x62, 0xf8, 0xe6, 0xfc, 0xf6, 0xce, + 0xe6, 0x16, 0xf4, 0x7b, 0x20, 0x08, 0xf4, 0xf3, 0xf3, 0xdf, 0xfa, 0xfa, 0x22, + 0x01, 0x30, 0x42, 0x2d, 0x0f, 0x3c, 0xe7, 0xdf, 0x1b, 0xfb, 0xe7, 0x05, 0x2b, + 0xd2, 0xe2, 0x07, 0xd2, 0x0b, 0x0d, 0x16, 0x3f, 0x9a, 0x14, 0x0b, 0xf6, 0xd4, + 0xfa, 0xfc, 0xc8, 0x47, 0x1f, 0xe1, 0x7f, 0x3e, 0xd5, 0x02, 0xec, 0x19, 0xf6, + 0x23, 0x13, 0x1c, 0xf7, 0xea, 0xe9, 0x19, 0x1b, 0x57, 0xe0, 0xe8, 0x16, 0x2e, + 0x10, 0x0a, 0x1e, 0x24, 0x1d, 0x1f, 0x23, 0xe4, 0x26, 0x20, 0x2f, 0xf9, 0x3f, + 0xe2, 0xe2, 0xca, 0x2e, 0xfe, 0xfe, 0xfe, 0x07, 0xbb, 0x07, 0x0f, 0x01, 0xf9, + 0x62, 0xf0, 0x09, 0x19, 0xfd, 0xee, 0x16, 0xfa, 0x26, 0x28, 0x01, 0x24, 0x05, + 0x10, 0x4a, 0xeb, 0xf2, 0xf1, 0x02, 0x17, 0xfc, 0xf8, 0xfe, 0x05, 0xe7, 0xff, + 0x31, 0x32, 0x03, 0xfc, 0x01, 0xfb, 0xfb, 0x19, 0x15, 0x21, 0x03, 0x11, 0x57, + 0x22, 0xf5, 0xde, 0xe3, 0xc1, 0x35, 0x06, 0x25, 0x37, 0x27, 0xe9, 0x81, 0x19, + 0xfc, 0xed, 0x16, 0xee, 0xe4, 0xd2, 0x5b, 0x36, 0xbc, 0xe1, 0xf3, 0x42, 0x0d, + 0x10, 0xf5, 0xf3, 0xf6, 0x06, 0x3a, 0xfc, 0xe1, 0x0e, 0xc4, 0xfc, 0xf9, 0x49, + 0xc0, 0x24, 0x09, 0x0a, 0x35, 0xfb, 0xb7, 0x2d, 0x20, 0xd0, 0xc6, 0xe0, 0xfd, + 0xc2, 0x28, 0x04, 0x07, 0xc3, 0xd8, 0xfa, 0x07, 0x32, 0x25, 0xbd, 0x26, 0xda, + 0x13, 0x2c, 0x1f, 0x06, 0x2d, 0x12, 0x07, 0x2d, 0xea, 0x04, 0xef, 0xc5, 0xb2, + 0xed, 0x03, 0xaa, 0xd7, 0x14, 0xf0, 0xf5, 0x0f, 0xde, 0x00, 0x19, 0x3a, 0xf1, + 0x1b, 0x20, 0x16, 0xf5, 0xc4, 0xe5, 0xb3, 0xd3, 0xb0, 0xf3, 0xec, 0x10, 0x0f, + 0xd4, 0x14, 0x13, 0xea, 0x19, 0xe6, 0x0d, 0xef, 0xe5, 0xf1, 0x14, 0xfd, 0x31, + 0xeb, 0xce, 0xaa, 0xb7, 0x0e, 0x1f, 0x02, 0xfc, 0x21, 0xbd, 0xf6, 0xf3, 0x0a, + 0xfb, 0x1d, 0xdb, 0xb8, 0xef, 0xd2, 0x28, 0xee, 0x0f, 0x29, 0xf1, 0x14, 0x23, + 0x0e, 0xf7, 0x4b, 0x2b, 0xfa, 0x1f, 0x0b, 0x21, 0x01, 0x11, 0xfc, 0x14, 0x3a, + 0x60, 0x16, 0xe5, 0xf4, 0x19, 0x06, 0x14, 0x55, 0x5d, 0xd5, 0xf7, 0xfe, 0x11, + 0x6a, 0xe9, 0x2a, 0xe8, 0x36, 0x67, 0x04, 0x24, 0xef, 0x13, 0x39, 0xe7, 0xf7, + 0xf6, 0xea, 0xf3, 0xfc, 0xfd, 0xe6, 0xf9, 0xe0, 0x53, 0x1d, 0xf2, 0x13, 0x25, + 0x69, 0xf0, 0x3c, 0x10, 0x3a, 0xf2, 0xff, 0x40, 0x1c, 0x17, 0x08, 0x28, 0x3a, + 0x18, 0x00, 0x27, 0xd6, 0xbf, 0xff, 0xb3, 0x23, 0xd0, 0xd3, 0xdb, 0x12, 0xff, + 0xf0, 0xe8, 0x21, 0xe7, 0xcd, 0x33, 0xff, 0x20, 0x06, 0x03, 0xef, 0x25, 0x52, + 0x01, 0xcb, 0x4a, 0x05, 0x0f, 0xd4, 0x09, 0xec, 0xfc, 0x36, 0x33, 0x05, 0xfc, + 0xcc, 0x2e, 0xe4, 0xe3, 0xc5, 0x39, 0xd1, 0x40, 0x7f, 0x23, 0xd3, 0xc5, 0xdd, + 0x12, 0x3e, 0x2b, 0xe3, 0xef, 0x56, 0xaa, 0xc7, 0x24, 0x06, 0xe6, 0xc3, 0xed, + 0xb1, 0xb2, 0x4a, 0x50, 0xf1, 0x2c, 0xd1, 0xdf, 0xc9, 0xf0, 0xdf, 0xe6, 0x02, + 0x03, 0x08, 0xe3, 0xd0, 0x40, 0xf0, 0xd6, 0x2d, 0x0c, 0xcc, 0xde, 0x49, 0x4a, + 0xd7, 0x1d, 0x81, 0x39, 0xdd, 0xb3, 0x33, 0xdd, 0xde, 0xc8, 0xd6, 0xda, 0xfe, + 0xfd, 0xcd, 0x1b, 0x12, 0x34, 0xfa, 0xf6, 0x17, 0x13, 0x0c, 0xfe, 0xba, 0xe4, + 0x08, 0x47, 0xee, 0xf7, 0xf1, 0xe0, 0x16, 0x9e, 0x13, 0x68, 0x39, 0xb1, 0x07, + 0xb5, 0x0e, 0xda, 0xc7, 0xcb, 0x0e, 0x11, 0xfa, 0x6b, 0x10, 0xf5, 0xd9, 0xfc, + 0xcf, 0xea, 0x08, 0xf7, 0xe6, 0xf7, 0x4f, 0xde, 0x1f, 0x19, 0x0c, 0xb9, 0x2a, + 0xf9, 0x1e, 0xe4, 0xf6, 0xc1, 0xb8, 0xea, 0x32, 0xd1, 0xff, 0x14, 0xd4, 0x67, + 0x10, 0x06, 0xe3, 0xd8, 0x5c, 0x1b, 0xd5, 0x0b, 0x65, 0xf6, 0x3b, 0x24, 0xd8, + 0x1b, 0xfc, 0x0b, 0xed, 0xde, 0x71, 0xb2, 0x3b, 0x46, 0x1e, 0xfa, 0xe3, 0x10, + 0x15, 0xf0, 0x3e, 0xfb, 0xb8, 0xf4, 0x07, 0xcd, 0x4e, 0x5c, 0xed, 0xc7, 0x38, + 0x02, 0x55, 0xfd, 0xe5, 0xae, 0xcb, 0xd6, 0xfb, 0xac, 0x6f, 0xf7, 0xcd, 0x14, + 0xea, 0x16, 0x03, 0x25, 0x15, 0x3e, 0xe0, 0x20, 0x17, 0xa8, 0xe9, 0xf1, 0x26, + 0xe3, 0x0d, 0x27, 0x02, 0xb8, 0x3d, 0x4b, 0xd6, 0xdc, 0x02, 0xe0, 0xd4, 0xfb, + 0xd2, 0x3b, 0x51, 0xd5, 0x28, 0xdd, 0x1e, 0xc5, 0xb6, 0x72, 0xed, 0x0b, 0x3a, + 0xba, 0x0c, 0xd1, 0x02, 0xdf, 0xf1, 0x02, 0xe1, 0xe4, 0xe4, 0xe4, 0xf3, 0x26, + 0xf7, 0x40, 0x09, 0x05, 0xe4, 0x23, 0x19, 0xc1, 0xf3, 0xc4, 0x0f, 0xc6, 0x21, + 0x0f, 0x39, 0x4b, 0x17, 0xce, 0x5f, 0xfd, 0x12, 0x0d, 0xd2, 0x7f, 0xf6, 0xfd, + 0x2a, 0xe2, 0x17, 0xc2, 0x41, 0x0d, 0x29, 0xed, 0x10, 0x38, 0xf0, 0xf8, 0xd2, + 0x15, 0x1c, 0x39, 0x4e, 0xed, 0x0d, 0xaa, 0xd5, 0xe2, 0x17, 0x7f, 0xa5, 0x14, + 0xde, 0x3b, 0x69, 0x06, 0x0a, 0xfc, 0xff, 0x2e, 0x12, 0x39, 0x05, 0xee, 0x6f, + 0xee, 0x26, 0x06, 0xbb, 0x01, 0xf5, 0xaa, 0x3c, 0xe7, 0xb9, 0x1b, 0xe7, 0x90, + 0xd2, 0x41, 0x37, 0x0e, 0x38, 0xf2, 0x2e, 0x16, 0xdb, 0x0f, 0x03, 0xc2, 0x05, + 0x12, 0xe1, 0xe0, 0x25, 0x23, 0xd7, 0xd6, 0xef, 0xf8, 0xf7, 0xf9, 0xb6, 0x0a, + 0x2a, 0x0c, 0x05, 0xe9, 0xd9, 0xdf, 0x25, 0x08, 0x2a, 0x24, 0x30, 0xdb, 0x2e, + 0xf4, 0x2a, 0x0a, 0xd0, 0xc5, 0x32, 0xd8, 0xf3, 0xef, 0x11, 0xf1, 0x25, 0xc8, + 0x2d, 0x02, 0x1f, 0xca, 0x12, 0x1f, 0x14, 0xe9, 0x26, 0xec, 0x0e, 0x09, 0x06, + 0x07, 0xf3, 0x18, 0x24, 0x1d, 0xfc, 0x1c, 0xf8, 0xe5, 0xd1, 0xde, 0xea, 0xa5, + 0x14, 0x34, 0xd1, 0x6a, 0x1a, 0xbf, 0xfe, 0xdf, 0xe7, 0xda, 0xf4, 0xe9, 0x03, + 0x04, 0x81, 0x1f, 0xdd, 0xdb, 0xf5, 0x19, 0xbe, 0xdd, 0x0a, 0x1b, 0xfa, 0xee, + 0xde, 0xef, 0x04, 0x16, 0x1e, 0xe6, 0xf2, 0xc9, 0xaf, 0xf6, 0xe7, 0x43, 0xe7, + 0xfe, 0x3b, 0x1b, 0x0a, 0x10, 0xce, 0x00, 0xf8, 0xf8, 0xc6, 0x24, 0x21, 0xce, + 0xe0, 0x02, 0xb6, 0xd2, 0xe0, 0xe6, 0xe8, 0xfd, 0x24, 0x21, 0x14, 0xe5, 0xf4, + 0x07, 0xfb, 0xd6, 0xda, 0x10, 0xe9, 0x0e, 0x4c, 0x0a, 0xee, 0x19, 0x0d, 0x03, + 0xcf, 0xe9, 0x0b, 0x0d, 0xd4, 0xd9, 0x06, 0xc6, 0xd1, 0x08, 0xef, 0xc2, 0xe6, + 0x24, 0xf0, 0x4a, 0xfa, 0x0d, 0x0c, 0xf4, 0x13, 0x38, 0xf0, 0x27, 0x28, 0xfb, + 0xdb, 0x34, 0xf2, 0xc5, 0x14, 0x0e, 0xfd, 0x44, 0xef, 0x17, 0xfd, 0xf6, 0x0b, + 0xc8, 0xe2, 0x09, 0xf9, 0x22, 0xde, 0xd4, 0x10, 0x27, 0xdc, 0x05, 0xea, 0xc8, + 0x08, 0x01, 0xfc, 0xfa, 0xef, 0x23, 0x71, 0xd6, 0xda, 0x15, 0x08, 0xeb, 0x22, + 0xcb, 0xf3, 0xea, 0x4f, 0xff, 0xf5, 0x5d, 0xc5, 0xfa, 0x15, 0x5b, 0x0b, 0x03, + 0xbe, 0xfe, 0x38, 0xeb, 0x04, 0xb7, 0x2a, 0xe9, 0x7f, 0xe5, 0x1d, 0xda, 0xb0, + 0x0a, 0x20, 0xb8, 0x51, 0x00, 0xd7, 0xce, 0x3a, 0xe0, 0xab, 0xe7, 0xd5, 0xed, + 0xd6, 0xf4, 0xef, 0xda, 0xbe, 0xe6, 0xde, 0xb9, 0xe8, 0x6b, 0x21, 0xd1, 0x12, + 0x2f, 0x0e, 0xd1, 0xc1, 0x19, 0x15, 0xe1, 0xc9, 0xea, 0x40, 0xdc, 0xcd, 0x09, + 0x0a, 0x7f, 0xfb, 0xed, 0xa5, 0x00, 0xe2, 0xe2, 0xe5, 0x8a, 0xb3, 0xf8, 0x3c, + 0x17, 0xfc, 0x25, 0xe1, 0x10, 0x05, 0x14, 0xf5, 0xa2, 0x31, 0xed, 0xff, 0x06, + 0xd0, 0x10, 0x0f, 0xc3, 0x20, 0x07, 0x1c, 0x1d, 0x36, 0x00, 0xaf, 0x18, 0x4e, + 0xdd, 0xd3, 0x51, 0x1a, 0x09, 0x06, 0x12, 0xf1, 0xa5, 0xc9, 0xf6, 0xdf, 0xfa, + 0xfc, 0xe7, 0x11, 0x2c, 0x03, 0xe4, 0x1f, 0x05, 0x27, 0x28, 0xf6, 0x27, 0x35, + 0xf4, 0x3d, 0x2a, 0x1b, 0xea, 0x25, 0x49, 0xe5, 0xa6, 0x0c, 0xc2, 0xd6, 0xe1, + 0x22, 0x0f, 0x38, 0x59, 0xfb, 0xda, 0xdf, 0x28, 0xde, 0xec, 0xf6, 0xd0, 0x25, + 0x1d, 0x47, 0xf9, 0xed, 0x5f, 0xb0, 0x5c, 0xc0, 0xeb, 0x18, 0x2c, 0x10, 0x39, + 0x1f, 0x5a, 0xe8, 0xbf, 0x10, 0xf3, 0xf1, 0xf9, 0x02, 0x1c, 0x17, 0xf9, 0xfa, + 0xf8, 0x37, 0xe5, 0xfb, 0xfd, 0xcb, 0x77, 0xfd, 0x52, 0x41, 0x62, 0xac, 0xbb, + 0x2c, 0x21, 0x3d, 0xea, 0xd4, 0xb8, 0x12, 0x05, 0x03, 0xcc, 0xf9, 0x0a, 0xfc, + 0xc7, 0x1e, 0xea, 0x6b, 0xf5, 0x0c, 0xf9, 0xcc, 0x0e, 0xbf, 0xea, 0x2a, 0x31, + 0x26, 0xe8, 0xf9, 0x52, 0xee, 0x0c, 0xf0, 0x7f, 0x28, 0x4f, 0x14, 0x67, 0x07, + 0xb4, 0x52, 0x05, 0xda, 0x22, 0xf0, 0x05, 0x0c, 0x2b, 0x6c, 0x19, 0x07, 0x23, + 0x2c, 0xde, 0xed, 0x26, 0xdc, 0x40, 0x42, 0xbf, 0xc2, 0x05, 0x53, 0xe1, 0xf5, + 0x18, 0xb0, 0xaf, 0x30, 0x0b, 0xf9, 0xbe, 0x03, 0xeb, 0xf6, 0x01, 0xf9, 0x09, + 0x2a, 0x11, 0xd6, 0xae, 0x27, 0x47, 0x12, 0xdc, 0x40, 0xdd, 0x04, 0x2d, 0xe5, + 0xcb, 0xca, 0x73, 0xa3, 0x3a, 0x06, 0xd7, 0xde, 0x3b, 0xeb, 0xed, 0x0e, 0x40, + 0xf8, 0xdf, 0x09, 0x19, 0xd9, 0x52, 0xd9, 0x25, 0xfa, 0xd9, 0x00, 0x29, 0xfa, + 0x0f, 0x24, 0xdf, 0xee, 0x7f, 0xd2, 0x2e, 0x34, 0x1f, 0xf1, 0xea, 0xb6, 0xe7, + 0xd4, 0x1e, 0xd6, 0xd3, 0xd4, 0xb9, 0xa8, 0xea, 0xba, 0xd6, 0xa2, 0x31, 0x3f, + 0x10, 0xf2, 0x23, 0x13, 0x31, 0xda, 0x23, 0x0b, 0x16, 0x4c, 0xe6, 0x04, 0x03, + 0x22, 0xf2, 0x2f, 0x25, 0xbb, 0xe8, 0x15, 0xef, 0xed, 0x07, 0x2b, 0xb4, 0xfa, + 0xe4, 0x23, 0x18, 0x25, 0x03, 0x3b, 0xb3, 0x68, 0xf3, 0x4e, 0xe9, 0xed, 0xf0, + 0x4a, 0xfb, 0x10, 0x0a, 0x1d, 0x20, 0xef, 0x1f, 0x06, 0xfa, 0xe8, 0xf7, 0x1e, + 0xb6, 0xd3, 0x0e, 0x02, 0xf9, 0x19, 0x2c, 0x2b, 0x1e, 0x10, 0x62, 0xc8, 0xc7, + 0xe8, 0xd8, 0xb9, 0x0a, 0xf3, 0x10, 0x16, 0x07, 0x1a, 0x15, 0xf0, 0x15, 0x24, + 0x37, 0xdb, 0xfc, 0x1c, 0x30, 0x07, 0x14, 0xec, 0x26, 0xee, 0xd4, 0xea, 0xd8, + 0xf9, 0x0d, 0x2c, 0x04, 0x12, 0x33, 0xda, 0xe0, 0xff, 0x3f, 0x42, 0xec, 0xe3, + 0x25, 0xd9, 0xf1, 0x22, 0xc9, 0xe8, 0xf1, 0x27, 0x7f, 0x34, 0xa1, 0x0d, 0x25, + 0xfd, 0xd8, 0xce, 0xfe, 0xcd, 0x9e, 0xc8, 0x36, 0xa6, 0xc7, 0xf3, 0xd5, 0xc5, + 0x20, 0x36, 0xea, 0xa7, 0x2e, 0x27, 0x3a, 0x33, 0xdd, 0xa0, 0xd4, 0xf3, 0xff, + 0xfd, 0x16, 0x0a, 0xf8, 0xb2, 0x06, 0xf5, 0xcb, 0x2d, 0x20, 0x03, 0x31, 0x0a, + 0xe9, 0xde, 0x4c, 0x17, 0xf7, 0xe0, 0xe8, 0xe3, 0xb9, 0xf2, 0xe9, 0xd5, 0xf0, + 0xe5, 0xdc, 0x0c, 0xd6, 0xb2, 0xbc, 0x7f, 0x44, 0x79, 0xca, 0xc9, 0xa6, 0x2a, + 0x36, 0xd0, 0xc0, 0x19, 0x4d, 0xf0, 0xf9, 0x04, 0x43, 0xf9, 0xf2, 0xd8, 0x49, + 0x55, 0xd2, 0xeb, 0xb5, 0xf6, 0xda, 0x10, 0xd7, 0xfc, 0x41, 0xbf, 0x1f, 0x34, + 0xf7, 0xf3, 0x1e, 0xfb, 0xf8, 0xf7, 0xf0, 0x0c, 0xde, 0xe7, 0x6b, 0xe8, 0xf4, + 0xee, 0xf0, 0xd5, 0xfd, 0x0d, 0x44, 0xe5, 0xd8, 0xf1, 0xfe, 0x07, 0xd1, 0xd7, + 0x15, 0x01, 0xf1, 0x50, 0xfc, 0x27, 0xe5, 0x51, 0xcc, 0x4c, 0xd9, 0xf1, 0x0b, + 0xcf, 0x14, 0xf9, 0xd7, 0xf7, 0xe2, 0xe7, 0x15, 0x22, 0xf3, 0xd2, 0xed, 0xe1, + 0x0b, 0x1c, 0xc9, 0x07, 0x23, 0x0e, 0xce, 0xf1, 0x26, 0x0d, 0xc8, 0x09, 0x27, + 0xef, 0x06, 0x1c, 0xee, 0xc4, 0xe4, 0x4c, 0xf2, 0x2d, 0xf9, 0xdc, 0x23, 0x34, + 0x06, 0xf6, 0xf1, 0x3e, 0x0e, 0xea, 0xeb, 0x54, 0x00, 0x18, 0x12, 0x0c, 0xe9, + 0x14, 0x0f, 0xef, 0x09, 0x02, 0x37, 0xd2, 0xf3, 0xe1, 0x2e, 0x15, 0x08, 0xa6, + 0x0e, 0x23, 0xe3, 0xf7, 0x13, 0xf7, 0xf0, 0x21, 0x45, 0xd2, 0xf7, 0x03, 0x17, + 0x1a, 0x3d, 0xe6, 0x24, 0x42, 0xd4, 0x09, 0x2f, 0xfe, 0x2a, 0xd2, 0x11, 0x2a, + 0x2f, 0xdb, 0xe0, 0xbc, 0x12, 0xe1, 0xd7, 0x57, 0x04, 0x11, 0x07, 0x2d, 0x2a, + 0x37, 0xce, 0xd8, 0x3a, 0xf1, 0xb9, 0x1b, 0x13, 0xe8, 0xba, 0xe7, 0x7f, 0x01, + 0xe9, 0xf6, 0xd3, 0xb8, 0x3b, 0xbf, 0x12, 0x0c, 0xdb, 0x2f, 0xf2, 0xdf, 0xa3, + 0x0a, 0x5a, 0x7c, 0x21, 0xdf, 0x0d, 0xca, 0x4d, 0xdf, 0x13, 0xd9, 0xd0, 0x14, + 0xf8, 0x14, 0x0c, 0xe5, 0x24, 0xfb, 0xaa, 0xee, 0x8f, 0x0e, 0xe4, 0x06, 0x05, + 0xbf, 0x25, 0x65, 0x33, 0xd8, 0xf1, 0xfd, 0x65, 0x0e, 0xdf, 0x26, 0xd5, 0xf4, + 0xdd, 0x05, 0xd4, 0x15, 0x0e, 0x25, 0xf3, 0xed, 0xce, 0xdf, 0x19, 0x20, 0x38, + 0x13, 0xda, 0x05, 0x1a, 0x00, 0xdb, 0x21, 0x14, 0xff, 0xf9, 0x16, 0x1c, 0x04, + 0xec, 0x07, 0xe9, 0xe5, 0x1d, 0x14, 0xf6, 0xff, 0x35, 0x3b, 0x24, 0x25, 0xea, + 0xee, 0xee, 0x2b, 0xd1, 0x35, 0xff, 0x15, 0x1e, 0x0b, 0xef, 0xfe, 0x34, 0xf8, + 0xf6, 0xe9, 0x0c, 0x19, 0xe9, 0x11, 0x20, 0xdb, 0xaa, 0xda, 0xee, 0x05, 0xba, + 0x19, 0xe8, 0x22, 0xe4, 0xd4, 0xfa, 0x02, 0xe8, 0xf2, 0x5d, 0xe8, 0xd3, 0x12, + 0xf3, 0x0d, 0x0a, 0x2e, 0xe8, 0xd3, 0xc6, 0x64, 0xd2, 0xd8, 0xb5, 0xf1, 0x07, + 0xf3, 0xd8, 0xe7, 0xf5, 0x08, 0x12, 0x04, 0xe0, 0xee, 0xf6, 0x0c, 0xe5, 0xea, + 0x19, 0x21, 0xbe, 0x7f, 0x00, 0xef, 0xbf, 0x09, 0xcd, 0xdf, 0x16, 0x00, 0xd6, + 0x0d, 0xe8, 0x2e, 0xf1, 0xdc, 0x17, 0x18, 0xe4, 0xf4, 0xf5, 0xf3, 0x2e, 0x2f, + 0x16, 0xe2, 0xdd, 0x4d, 0x27, 0xf3, 0xba, 0xfe, 0x2d, 0x31, 0x03, 0xfb, 0xc6, + 0x3c, 0x19, 0x4b, 0xe3, 0xbc, 0x08, 0xeb, 0x26, 0xd1, 0x03, 0x3a, 0x01, 0xf1, + 0xe6, 0xb6, 0x37, 0x26, 0x14, 0x3c, 0x2a, 0x4a, 0xe1, 0xe2, 0x2a, 0xf1, 0xff, + 0x34, 0xb8, 0xf9, 0xe6, 0xba, 0x2a, 0xf9, 0x0a, 0xe4, 0x6f, 0xf0, 0x4b, 0xcc, + 0x1f, 0xd2, 0xd1, 0xc6, 0x5e, 0xba, 0xe9, 0xd6, 0xc3, 0xf7, 0xf1, 0xf4, 0x0c, + 0xe7, 0xc8, 0xce, 0xe7, 0x2b, 0xdc, 0xfa, 0xe9, 0xd3, 0xf2, 0x02, 0x2f, 0x11, + 0x2a, 0x51, 0xba, 0x2b, 0xec, 0x49, 0x06, 0xfb, 0xbf, 0xf4, 0xe4, 0xa0, 0xdf, + 0xab, 0x81, 0xe9, 0x22, 0x0b, 0x1a, 0x78, 0x24, 0xf2, 0x0d, 0x0f, 0xe4, 0xe4, + 0xea, 0xdd, 0x1c, 0x13, 0xd2, 0xe2, 0x04, 0x10, 0x22, 0x14, 0xc6, 0xc3, 0xe3, + 0x2c, 0xef, 0x64, 0xbe, 0x03, 0x02, 0x0f, 0x01, 0x25, 0x3e, 0xf3, 0xf9, 0xdd, + 0x32, 0x1e, 0x3d, 0x1c, 0x1e, 0x10, 0x02, 0x3e, 0x1d, 0x3f, 0xa6, 0x28, 0x68, + 0x08, 0xeb, 0xfb, 0x56, 0xe6, 0xdf, 0x25, 0x46, 0xcf, 0xa5, 0xf4, 0xf6, 0x15, + 0x2f, 0x1b, 0xdc, 0x4a, 0x10, 0x28, 0xd9, 0xfd, 0xd7, 0xdb, 0x0f, 0xe7, 0xed, + 0xff, 0xdb, 0x14, 0x2b, 0xe8, 0xa2, 0x92, 0x35, 0x46, 0xda, 0xb7, 0x0e, 0xf2, + 0x16, 0x51, 0x16, 0xf2, 0xff, 0x06, 0x1f, 0x04, 0xf0, 0x0c, 0xd4, 0xfa, 0x08, + 0xbb, 0xed, 0x06, 0xfc, 0xd8, 0xfc, 0x26, 0xd9, 0x09, 0xf6, 0xe2, 0x7f, 0x11, + 0x73, 0xd9, 0x09, 0x43, 0xa9, 0xe2, 0xb6, 0xf4, 0xeb, 0x5a, 0x1a, 0xf3, 0x12, + 0xfe, 0xf8, 0x0f, 0x14, 0x14, 0xe9, 0x2e, 0xee, 0x2c, 0xe8, 0xff, 0x0c, 0xb0, + 0xe0, 0x18, 0xba, 0x1d, 0xe9, 0x12, 0xec, 0xeb, 0xe2, 0xe2, 0xe4, 0x27, 0x1b, + 0xd1, 0xc5, 0xe3, 0xeb, 0x1a, 0xf1, 0x06, 0xe2, 0xf6, 0xe2, 0x30, 0xf2, 0xdd, + 0x0b, 0xb5, 0x6e, 0x07, 0xdf, 0xbc, 0x5f, 0x0c, 0x4f, 0xc7, 0xbd, 0xf1, 0xe1, + 0x18, 0xdd, 0x67, 0x29, 0x3a, 0xf9, 0xce, 0x39, 0x06, 0xba, 0xf6, 0xdb, 0xf7, + 0x21, 0xa4, 0xf9, 0xd6, 0x25, 0xdb, 0x1c, 0xe6, 0x03, 0xd4, 0x00, 0x2b, 0x02, + 0x2d, 0x02, 0xd5, 0x43, 0xb0, 0x8f, 0x12, 0xf7, 0x18, 0x15, 0x2f, 0x25, 0x19, + 0xfe, 0x1a, 0x27, 0xf6, 0x04, 0x0d, 0xd7, 0xe1, 0xf7, 0x3d, 0x02, 0xde, 0x27, + 0xf6, 0x27, 0x25, 0x1a, 0x48, 0xf4, 0xfb, 0xe7, 0x52, 0xf2, 0x24, 0x4c, 0xea, + 0x10, 0x02, 0x48, 0x6d, 0xea, 0xda, 0x6c, 0xb6, 0xb7, 0x7f, 0x12, 0xef, 0x38, + 0xc6, 0xf7, 0xf4, 0xc6, 0x1b, 0x0b, 0x0c, 0x05, 0x12, 0xf1, 0xe5, 0x18, 0x2e, + 0x96, 0xec, 0x0f, 0xea, 0x3a, 0x33, 0xf6, 0xd9, 0x77, 0xd9, 0xf4, 0xd2, 0x03, + 0xf6, 0x5d, 0x05, 0xb2, 0x25, 0x18, 0xf4, 0xfc, 0xdb, 0x61, 0x12, 0x0d, 0xd7, + 0xcd, 0xe9, 0xdb, 0x19, 0xf7, 0x36, 0x02, 0x90, 0xdc, 0xfe, 0x21, 0x3e, 0xfb, + 0xf2, 0x35, 0xf4, 0xf9, 0xf0, 0x50, 0xe9, 0xd2, 0xee, 0x3c, 0xfd, 0x4d, 0x31, + 0x59, 0x02, 0x23, 0x45, 0x10, 0x02, 0xc1, 0x2b, 0xd4, 0xfd, 0x2d, 0x18, 0xc9, + 0x00, 0x38, 0xda, 0xd6, 0x02, 0x61, 0x0e, 0xe1, 0x1b, 0xde, 0xcc, 0xf7, 0xf6, + 0x82, 0x0b, 0x34, 0x03, 0xdf, 0xfd, 0xbc, 0xd4, 0xc7, 0xe6, 0xd0, 0xf5, 0x1c, + 0xfa, 0xf3, 0x1e, 0xda, 0x30, 0x17, 0x24, 0xa3, 0xe6, 0xe6, 0x4c, 0xd3, 0xa8, + 0x7f, 0x02, 0xf5, 0xc9, 0x33, 0xc6, 0x26, 0x82, 0x0c, 0x20, 0xf0, 0xdb, 0x40, + 0xe9, 0x18, 0x96, 0xb5, 0xcb, 0x3f, 0xfd, 0x00, 0x67, 0xea, 0x26, 0x53, 0xcf, + 0x0f, 0x1f, 0x11, 0x07, 0x08, 0xff, 0xc7, 0xfe, 0xec, 0x85, 0x45, 0xe8, 0x0f, + 0xe9, 0xf6, 0xf6, 0x42, 0x2b, 0x2a, 0x55, 0xde, 0x00, 0xf5, 0x4f, 0x00, 0x40, + 0x0b, 0x10, 0xf6, 0x97, 0x14, 0xc0, 0xe8, 0xcc, 0xf7, 0xf6, 0x11, 0x27, 0x07, + 0xda, 0xf0, 0x0f, 0xe9, 0xf9, 0x58, 0xc4, 0x1a, 0xde, 0x37, 0xa8, 0x03, 0x13, + 0xe9, 0xcd, 0x01, 0xd3, 0x12, 0xff, 0x0d, 0xc8, 0xf1, 0x7f, 0xf2, 0xf4, 0x0c, + 0x31, 0x17, 0xc9, 0xbb, 0x1c, 0x9f, 0xf8, 0x10, 0x23, 0xe5, 0xce, 0x00, 0xf6, + 0xf1, 0xff, 0x00, 0x00, 0xc4, 0x22, 0x1e, 0x0d, 0x37, 0xf8, 0x12, 0xfd, 0x1f, + 0xc0, 0x0b, 0xd6, 0xd9, 0xf7, 0x1d, 0x33, 0xcf, 0xfd, 0x37, 0x10, 0x10, 0x1e, + 0xd7, 0xeb, 0x10, 0x6a, 0x1e, 0x46, 0xf0, 0xfe, 0xc5, 0xe8, 0x4a, 0xf9, 0xe2, + 0xc4, 0xe9, 0x08, 0xf1, 0x35, 0xf2, 0xec, 0xd9, 0xfe, 0x10, 0xf3, 0x22, 0x13, + 0xec, 0xd1, 0xf1, 0x21, 0x18, 0xe0, 0x2d, 0xee, 0x06, 0x1b, 0x27, 0xec, 0x00, + 0xf4, 0xf2, 0xdb, 0xd2, 0x03, 0xc4, 0xf0, 0xe6, 0xc0, 0x74, 0xd5, 0x0b, 0x1e, + 0x31, 0x21, 0x04, 0x15, 0x18, 0x30, 0xc3, 0xe4, 0xbc, 0xcd, 0x39, 0x38, 0x2e, + 0xba, 0x0b, 0x2b, 0x11, 0x1a, 0x30, 0x54, 0x0b, 0x44, 0xd2, 0xf3, 0xfd, 0x43, + 0x48, 0xfd, 0x02, 0xc8, 0xd9, 0xc6, 0xda, 0xfb, 0x19, 0xd1, 0xd4, 0x0b, 0xee, + 0xd1, 0x22, 0x2c, 0x6f, 0x2f, 0xde, 0x34, 0xdc, 0x3f, 0xf5, 0x2a, 0xf5, 0xed, + 0xff, 0xd8, 0xa9, 0x08, 0xc8, 0x1b, 0xde, 0xca, 0xdd, 0xfc, 0xae, 0x78, 0x59, + 0xf7, 0xd0, 0xf4, 0xe9, 0x2c, 0x81, 0x05, 0xed, 0x1d, 0x14, 0xdc, 0x03, 0x5f, + 0x53, 0x04, 0x17, 0x09, 0x12, 0x34, 0xce, 0xe7, 0x26, 0x32, 0x1d, 0x10, 0xd2, + 0xd3, 0x0d, 0x2f, 0xec, 0xfe, 0x38, 0x1f, 0x1e, 0xfd, 0x69, 0x14, 0x45, 0xf9, + 0xef, 0xe4, 0x14, 0xfe, 0x09, 0xa8, 0x27, 0xdf, 0xce, 0xed, 0xe6, 0x09, 0xea, + 0xb8, 0xb4, 0xef, 0x6c, 0x49, 0x02, 0x17, 0x4f, 0xb0, 0xd7, 0x0a, 0x2c, 0x13, + 0xeb, 0x40, 0x77, 0x15, 0xf4, 0x9e, 0xad, 0xff, 0x31, 0x1a, 0x5f, 0xed, 0xee, + 0x34, 0xe0, 0xfc, 0xf2, 0x34, 0xa0, 0x27, 0xef, 0x07, 0x08, 0x18, 0x0c, 0x3f, + 0xa5, 0xe0, 0xda, 0xfd, 0x13, 0xd2, 0xf3, 0xc4, 0x25, 0xe2, 0x0d, 0x09, 0x15, + 0xa1, 0xef, 0xdf, 0xf4, 0x40, 0xde, 0x1d, 0x5f, 0xfe, 0x16, 0x31, 0xf6, 0x0f, + 0x64, 0xd8, 0xd4, 0xda, 0xd7, 0xce, 0x4b, 0xd2, 0xd5, 0xe0, 0xdd, 0x03, 0xd0, + 0x1f, 0x20, 0x3d, 0x04, 0x06, 0xeb, 0x7f, 0x39, 0xfe, 0x46, 0x7a, 0x03, 0x33, + 0x01, 0x12, 0xc2, 0xbe, 0xd3, 0xe2, 0xcf, 0xef, 0x13, 0x25, 0xf1, 0x04, 0xd2, + 0xe9, 0xc5, 0xd0, 0x00, 0x33, 0x00, 0x4e, 0x0d, 0x59, 0xbc, 0x07, 0xf3, 0xea, + 0xe0, 0x56, 0x40, 0xf9, 0x3f, 0x14, 0x28, 0x4a, 0xd2, 0x15, 0x15, 0x0c, 0x36, + 0x0c, 0x22, 0xe4, 0x2d, 0xff, 0x09, 0xdd, 0x20, 0xfd, 0x3d, 0x7f, 0xc0, 0x07, + 0x47, 0x1f, 0x40, 0x0e, 0x33, 0x0f, 0xe9, 0x2f, 0x01, 0xdd, 0xdd, 0xfb, 0xe0, + 0x47, 0xea, 0xf7, 0xc8, 0x1e, 0x0d, 0x27, 0xe8, 0xe0, 0x0d, 0x0a, 0x10, 0x66, + 0x08, 0x2d, 0x2e, 0x02, 0xee, 0x09, 0xee, 0x14, 0x52, 0x0e, 0xef, 0xfd, 0xd9, + 0xf2, 0x21, 0xea, 0xf0, 0xe7, 0x10, 0xeb, 0xc8, 0x05, 0xed, 0xfb, 0x16, 0xbd, + 0xfa, 0xdf, 0xe0, 0xe2, 0xf2, 0xa6, 0xfe, 0x23, 0xfb, 0xff, 0xd2, 0xd8, 0x07, + 0x73, 0x32, 0xc2, 0x1e, 0x30, 0x11, 0x0b, 0xa1, 0x0e, 0x04, 0x1a, 0x27, 0x1a, + 0xd6, 0xf5, 0x00, 0xf7, 0xf6, 0xed, 0x04, 0xf3, 0x1c, 0x3d, 0x14, 0xe4, 0xcd, + 0x0f, 0x9a, 0x0e, 0x0d, 0x15, 0xd9, 0x06, 0xe8, 0x07, 0xdf, 0x0c, 0xf4, 0x17, + 0x12, 0xe6, 0x18, 0x1e, 0xf0, 0xf4, 0x2c, 0x2f, 0xc3, 0xed, 0x1c, 0xef, 0x0f, + 0xca, 0x13, 0xfd, 0x0b, 0xfc, 0x12, 0x2f, 0x0a, 0x55, 0x09, 0x25, 0x36, 0xf9, + 0xf0, 0x02, 0xad, 0xd4, 0x17, 0x04, 0xda, 0x22, 0x7f, 0x11, 0xd7, 0x12, 0x1d, + 0xf8, 0xfa, 0xf5, 0x6a, 0x3c, 0xf7, 0xec, 0xe5, 0x0a, 0xd8, 0x0d, 0xd7, 0xea, + 0x04, 0x06, 0x19, 0x0f, 0x40, 0x28, 0x16, 0x07, 0xf7, 0xde, 0xf5, 0x1a, 0xc7, + 0xd9, 0x23, 0xfe, 0xc0, 0x22, 0xf5, 0xf8, 0xe8, 0x12, 0xdc, 0xdc, 0xf9, 0xf9, + 0x1d, 0xc8, 0x1a, 0x11, 0x07, 0xf4, 0x08, 0xf6, 0xf9, 0x10, 0xf2, 0x12, 0x00, + 0x41, 0xf9, 0x2e, 0xf1, 0xd2, 0xc3, 0xc5, 0xf6, 0xdc, 0x06, 0x09, 0x16, 0xf1, + 0x22, 0x22, 0x14, 0x11, 0xff, 0x01, 0x02, 0x16, 0x14, 0x12, 0xf1, 0xdd, 0x2e, + 0xf6, 0x1d, 0xf0, 0xef, 0x07, 0xe7, 0x48, 0x0b, 0x20, 0x1d, 0x11, 0x3a, 0x01, + 0xd4, 0xcb, 0xd3, 0xf0, 0x0b, 0x03, 0x2e, 0xd5, 0x42, 0x0c, 0xeb, 0x17, 0x09, + 0x0e, 0x07, 0xc7, 0x01, 0x2d, 0x02, 0x43, 0x9e, 0xeb, 0x1d, 0xf5, 0xca, 0xa5, + 0x7f, 0xbc, 0x2d, 0xf3, 0x35, 0xe5, 0x33, 0x08, 0xf8, 0xf9, 0x42, 0xcc, 0x10, + 0x35, 0xce, 0x54, 0x00, 0x30, 0xef, 0x9e, 0xf4, 0xfd, 0xe8, 0x49, 0xef, 0xa3, + 0x3a, 0x2d, 0xd4, 0xe3, 0x13, 0xdb, 0xe0, 0xcf, 0x15, 0xe7, 0xf3, 0xd7, 0x28, + 0xe1, 0xfb, 0x15, 0x03, 0xf6, 0xde, 0x3c, 0xe5, 0xd9, 0xbb, 0xf4, 0xec, 0xda, + 0x0f, 0x04, 0x3a, 0x16, 0xf0, 0x33, 0x07, 0xd7, 0x09, 0xde, 0x25, 0xf0, 0xdd, + 0x11, 0x94, 0x1b, 0xcf, 0xda, 0x31, 0xa7, 0x0a, 0xde, 0x09, 0x21, 0x17, 0x0a, + 0x0c, 0x19, 0xf3, 0x2a, 0xdb, 0xdb, 0xec, 0x0b, 0x2b, 0xf2, 0xd4, 0x2c, 0xa8, + 0xed, 0xeb, 0x38, 0xec, 0xd8, 0x3a, 0x5f, 0xcd, 0xec, 0x1b, 0xe6, 0x38, 0xeb, + 0x18, 0x1e, 0x83, 0xe6, 0xcd, 0x00, 0x63, 0x0b, 0x95, 0xcc, 0xf6, 0xd1, 0x2d, + 0xd5, 0x35, 0xea, 0x17, 0xf5, 0x01, 0xe5, 0x1c, 0x13, 0xef, 0xe2, 0x1d, 0x3a, + 0x0a, 0x06, 0x08, 0xd8, 0xf2, 0x44, 0xf7, 0x1e, 0x15, 0x42, 0x16, 0xe6, 0xe5, + 0xfc, 0xd5, 0xe6, 0x34, 0x10, 0x02, 0x1f, 0x19, 0xeb, 0xff, 0xc4, 0xe9, 0x01, + 0xe3, 0xda, 0xcb, 0xea, 0x04, 0xf7, 0xc7, 0x24, 0xf6, 0x19, 0x1f, 0x55, 0xdd, + 0x3e, 0x0d, 0x1b, 0xf7, 0xf1, 0xfc, 0xe7, 0x3a, 0x17, 0xff, 0xeb, 0xf3, 0x00, + 0xed, 0x0a, 0xd0, 0xd6, 0x0d, 0xb2, 0xdf, 0xf2, 0xe2, 0x11, 0x24, 0xd4, 0x23, + 0x08, 0x1d, 0xb9, 0x32, 0x2b, 0xde, 0x29, 0x1e, 0xff, 0x08, 0xf5, 0x1b, 0x00, + 0x36, 0x28, 0xe8, 0xd5, 0xfd, 0xce, 0x7f, 0xe7, 0x23, 0xf8, 0x59, 0x23, 0x3c, + 0xea, 0xcf, 0x2e, 0x03, 0x95, 0xdf, 0x16, 0xf3, 0xb2, 0xda, 0xda, 0x1e, 0x3b, + 0x4b, 0x08, 0xe5, 0xea, 0xbe, 0xe9, 0xe5, 0x0e, 0x25, 0x60, 0xf5, 0xab, 0xbc, + 0x0f, 0x22, 0x59, 0x0f, 0x0b, 0x02, 0xed, 0xdd, 0x01, 0x57, 0x09, 0x0d, 0xff, + 0x26, 0x1b, 0x35, 0xd8, 0x17, 0xfb, 0xd2, 0x1b, 0xc9, 0xff, 0x0b, 0x7f, 0xaf, + 0x07, 0x31, 0xd9, 0xef, 0x35, 0xbf, 0x05, 0x29, 0xea, 0xb6, 0xde, 0xac, 0xe4, + 0x05, 0xe5, 0x08, 0xfd, 0xe8, 0xf2, 0xb7, 0xad, 0xb4, 0xc7, 0xe8, 0xea, 0x1b, + 0x02, 0x31, 0xd8, 0x33, 0xbb, 0xe1, 0xbd, 0xfd, 0x8f, 0xd4, 0xeb, 0x46, 0x30, + 0xd0, 0x05, 0xbc, 0xfb, 0x0c, 0xf5, 0x58, 0xba, 0xd1, 0x53, 0x24, 0xf0, 0xca, + 0xc8, 0xe9, 0x46, 0x1d, 0xf2, 0x02, 0x0a, 0xeb, 0xd3, 0x19, 0x44, 0xfa, 0x07, + 0xef, 0xe1, 0x13, 0x33, 0xb5, 0x0b, 0xdc, 0x3f, 0x2d, 0xd0, 0x1c, 0xfd, 0x1c, + 0xcd, 0x15, 0x3d, 0xd7, 0xf9, 0x5e, 0x12, 0x15, 0xf8, 0xfc, 0x0a, 0xfc, 0x19, + 0xe0, 0xce, 0x28, 0xfc, 0xe7, 0xee, 0xec, 0xc7, 0xf5, 0xf0, 0x49, 0x23, 0xd8, + 0x03, 0x52, 0x66, 0x3a, 0xe9, 0x25, 0x3c, 0xf9, 0x14, 0xcb, 0xe8, 0x20, 0xe9, + 0x8f, 0xeb, 0xe1, 0x3a, 0xf1, 0xdb, 0x14, 0x15, 0x8c, 0x14, 0x58, 0x3e, 0x90, + 0x20, 0x22, 0xed, 0xef, 0x21, 0xce, 0x25, 0x29, 0xd2, 0x0c, 0xe8, 0x9a, 0xc8, + 0x39, 0x06, 0x2e, 0xf9, 0xea, 0xa3, 0xca, 0xdc, 0xd5, 0xfa, 0x20, 0x44, 0x27, + 0x02, 0x45, 0xdf, 0x1d, 0x15, 0x32, 0x1c, 0xe5, 0x2c, 0x3a, 0x55, 0xe6, 0x39, + 0xfe, 0x25, 0xf3, 0x26, 0x08, 0xec, 0xec, 0x00, 0xef, 0xfe, 0xee, 0xed, 0x26, + 0x36, 0xef, 0xb0, 0xf5, 0x1d, 0x18, 0x1b, 0x1c, 0xed, 0xf3, 0x1c, 0xe8, 0x01, + 0x21, 0x68, 0xd5, 0x45, 0xc7, 0xd7, 0x10, 0x3d, 0xcf, 0x09, 0x10, 0xee, 0x4b, + 0xfd, 0x45, 0xda, 0x19, 0xd1, 0x78, 0x08, 0xe9, 0xe0, 0x2a, 0xeb, 0xc8, 0x7f, + 0x36, 0x22, 0x27, 0xc2, 0xe9, 0xf7, 0x01, 0x0e, 0xec, 0x37, 0xfb, 0xd6, 0x5b, + 0x38, 0xec, 0x1c, 0xf8, 0x2b, 0xce, 0x29, 0x07, 0x32, 0xeb, 0x0c, 0xc4, 0xff, + 0xe4, 0xfe, 0xce, 0xf7, 0xf1, 0x01, 0xe0, 0x11, 0xdd, 0x1e, 0xde, 0x20, 0x1e, + 0xe6, 0x10, 0x11, 0x0e, 0x7f, 0x2f, 0xc3, 0x5d, 0x02, 0x13, 0xf5, 0x1e, 0x4e, + 0x45, 0xfe, 0x20, 0x26, 0xe3, 0x1d, 0x02, 0xfa, 0x1f, 0x14, 0x3d, 0xc6, 0xef, + 0x42, 0xf6, 0x20, 0x10, 0x18, 0x27, 0x0c, 0x15, 0x3b, 0x1c, 0x34, 0x46, 0x11, + 0xa3, 0x2c, 0x29, 0x06, 0x13, 0x0e, 0xdb, 0x16, 0x4c, 0x28, 0x4c, 0xd1, 0xe3, + 0x4e, 0x1a, 0xf1, 0xf7, 0x10, 0xf1, 0xf0, 0x14, 0xf4, 0x02, 0x1f, 0xec, 0x41, + 0x2e, 0x26, 0xf6, 0xea, 0x35, 0x15, 0xf2, 0xf2, 0xe3, 0xc3, 0xfc, 0x03, 0x21, + 0xe9, 0xf4, 0xda, 0x2e, 0xf2, 0x11, 0xd0, 0x33, 0x12, 0xd7, 0x41, 0x01, 0x14, + 0x15, 0xf0, 0x10, 0xeb, 0x1c, 0x05, 0x15, 0x03, 0xf6, 0xe2, 0xef, 0x62, 0x26, + 0x0b, 0xeb, 0x08, 0xff, 0x1b, 0xed, 0xcf, 0x15, 0xd0, 0xd2, 0xfa, 0xf8, 0xe6, + 0xff, 0x19, 0x1d, 0x01, 0xd3, 0x18, 0xfd, 0xfd, 0xcd, 0x04, 0xdb, 0xdd, 0x14, + 0x12, 0xe4, 0x6d, 0x7f, 0xc8, 0xfc, 0x1b, 0xe5, 0x0d, 0x18, 0x10, 0x34, 0x38, + 0xfb, 0x02, 0x12, 0x11, 0x12, 0x01, 0x33, 0x0d, 0xc3, 0x07, 0x18, 0x0b, 0xce, + 0x0a, 0x1f, 0x00, 0xfa, 0x3d, 0x40, 0x27, 0x30, 0x19, 0xed, 0xef, 0xfe, 0xfc, + 0xe7, 0xde, 0xe7, 0xff, 0xf9, 0xcf, 0xe2, 0xfa, 0x28, 0x35, 0xd5, 0x17, 0x17, + 0x17, 0x1b, 0x1c, 0x11, 0x07, 0x17, 0xf2, 0xf1, 0xfc, 0x0f, 0x16, 0xdb, 0x05, + 0xf4, 0xec, 0xe6, 0xdf, 0x47, 0xd7, 0xe8, 0x10, 0xd1, 0x4c, 0x40, 0x0b, 0xe4, + 0xe0, 0xd9, 0xe7, 0xff, 0x14, 0xfa, 0xe9, 0xdc, 0x1a, 0xdf, 0x17, 0x33, 0x0c, + 0x29, 0xa9, 0x53, 0x1c, 0xd6, 0xc4, 0x13, 0x74, 0xf8, 0xf8, 0x1d, 0xfd, 0x2f, + 0x09, 0xb0, 0x2d, 0x15, 0x1a, 0xcc, 0xcd, 0x2c, 0xdd, 0x19, 0x4d, 0xeb, 0x04, + 0x89, 0xe1, 0x28, 0xff, 0xf6, 0xf8, 0x1e, 0xd9, 0x00, 0x1f, 0xf3, 0xfb, 0xe3, + 0x56, 0x06, 0xfd, 0xe3, 0xfb, 0x0d, 0x1e, 0xc5, 0xdc, 0xe6, 0x09, 0x39, 0xdf, + 0x2f, 0x1e, 0xb8, 0x09, 0x36, 0xfb, 0x43, 0x41, 0xa4, 0xfa, 0xd9, 0xd7, 0x1c, + 0xda, 0x24, 0xcf, 0x14, 0x1a, 0xc3, 0xce, 0xb3, 0xc5, 0x9a, 0x8a, 0x04, 0xc5, + 0xdf, 0x6c, 0xef, 0x16, 0xe7, 0xe9, 0xfe, 0xd1, 0xee, 0xd4, 0x25, 0xf1, 0x0b, + 0xf3, 0xe5, 0xc2, 0xa7, 0xdd, 0xef, 0x44, 0x0d, 0x0d, 0xf5, 0xe0, 0x11, 0x20, + 0xc8, 0xbe, 0xf8, 0x1a, 0xe7, 0x49, 0x13, 0xd0, 0xe6, 0x03, 0x32, 0x4c, 0x81, + 0x06, 0xea, 0xcf, 0x17, 0x01, 0x44, 0xd8, 0x39, 0xf5, 0xcd, 0x52, 0x11, 0xfe, + 0x03, 0xd3, 0x0a, 0xe8, 0x18, 0xe2, 0x08, 0x18, 0xf8, 0x54, 0x26, 0xea, 0xc1, + 0xf8, 0xf5, 0xd4, 0xe1, 0x37, 0x66, 0x0c, 0x1c, 0xf4, 0x32, 0x0d, 0x6c, 0x12, + 0xf8, 0xe5, 0x11, 0xd7, 0x02, 0x5b, 0x0a, 0xe3, 0x23, 0x41, 0xa5, 0x57, 0x1b, + 0x47, 0xf3, 0xf9, 0x58, 0xe3, 0x3d, 0x24, 0x15, 0x1d, 0xfd, 0xb3, 0xc4, 0xfd, + 0xf4, 0xdf, 0x16, 0xf0, 0x38, 0xf7, 0x18, 0x19, 0x19, 0x63, 0x0e, 0x36, 0x40, + 0x2d, 0x17, 0xed, 0x30, 0x4c, 0x04, 0xf0, 0xb5, 0x42, 0x16, 0x04, 0x07, 0xfe, + 0x37, 0x70, 0x24, 0xe6, 0xfe, 0x7f, 0x03, 0xd4, 0x29, 0x41, 0x09, 0xe0, 0x0b, + 0x31, 0xda, 0x35, 0x02, 0xe9, 0xee, 0x0b, 0x02, 0xfb, 0x01, 0xfc, 0x12, 0x08, + 0xec, 0xdd, 0x40, 0xea, 0xea, 0xd4, 0x4a, 0xf7, 0xde, 0xf4, 0xe6, 0x23, 0x57, + 0x0a, 0x31, 0xe2, 0x09, 0x07, 0x2f, 0xe2, 0xca, 0x50, 0x12, 0x37, 0x19, 0x28, + 0xe2, 0x04, 0x7f, 0x4d, 0x3c, 0xad, 0x28, 0xf0, 0xea, 0xe0, 0xac, 0x01, 0x06, + 0x37, 0x5c, 0x08, 0xb8, 0xe9, 0x09, 0xd1, 0x35, 0x16, 0xdf, 0x22, 0xf9, 0x10, + 0x18, 0x22, 0x1b, 0xec, 0x00, 0xf6, 0xd4, 0x41, 0x16, 0x1f, 0xf9, 0xf9, 0x19, + 0x40, 0x45, 0x52, 0xf9, 0x1c, 0x17, 0xed, 0xd9, 0x2f, 0x1f, 0x71, 0x61, 0xca, + 0x0c, 0xfc, 0xf6, 0xf8, 0x29, 0x02, 0xd8, 0x16, 0xfa, 0xc5, 0x18, 0x28, 0x14, + 0x26, 0x03, 0xcd, 0xc0, 0x2e, 0x1b, 0x15, 0x31, 0xec, 0xf5, 0xda, 0x30, 0x0c, + 0x54, 0x5e, 0x18, 0x30, 0x1e, 0xeb, 0xe4, 0x08, 0x17, 0x29, 0x15, 0xfc, 0xdd, + 0xd8, 0x1b, 0x3e, 0xc8, 0x28, 0x31, 0x0e, 0xe6, 0x11, 0x06, 0x3a, 0xa8, 0xe6, + 0x1c, 0xe7, 0xd9, 0x66, 0x3d, 0x0b, 0xda, 0x30, 0x37, 0x0e, 0xc6, 0x22, 0xe6, + 0x1e, 0x28, 0xeb, 0xe9, 0x9a, 0x29, 0x37, 0x19, 0xec, 0xd4, 0xfd, 0xe5, 0xed, + 0xfb, 0x59, 0xde, 0x29, 0xce, 0x25, 0xfd, 0xe2, 0xea, 0x13, 0xde, 0xcd, 0xee, + 0x3d, 0x38, 0xef, 0x1f, 0x1b, 0x7f, 0xee, 0xef, 0x37, 0xca, 0x29, 0x0a, 0xff, + 0xe5, 0xec, 0x0c, 0xf7, 0xdb, 0x2a, 0x12, 0xd2, 0x29, 0x16, 0xbc, 0xef, 0x19, + 0xf9, 0x34, 0xee, 0x07, 0xec, 0xe4, 0xee, 0x42, 0xd6, 0xfa, 0x17, 0xd6, 0xdd, + 0xc7, 0x02, 0xdc, 0xe8, 0xcc, 0xd8, 0xe3, 0xd8, 0x0a, 0x0a, 0x20, 0x08, 0xeb, + 0x2d, 0xfe, 0x1f, 0xee, 0x05, 0xe2, 0x3a, 0xe7, 0xe9, 0xe4, 0xe2, 0xfd, 0xc3, + 0xbe, 0xec, 0xd6, 0xdc, 0xe1, 0xee, 0xee, 0x17, 0x16, 0x3e, 0xee, 0x32, 0xf4, + 0x02, 0xf8, 0x25, 0xdc, 0x05, 0xf5, 0x1b, 0xf0, 0xfe, 0xe7, 0x00, 0x15, 0xd9, + 0x0d, 0x05, 0xe6, 0xd7, 0x1f, 0x1d, 0x02, 0xe5, 0xcb, 0xeb, 0xd8, 0x13, 0xee, + 0x46, 0xe6, 0x10, 0xc1, 0xee, 0x11, 0xef, 0xec, 0xfe, 0x1a, 0xd6, 0x27, 0xf9, + 0xf9, 0x07, 0x06, 0xee, 0x30, 0x0c, 0x3a, 0x1b, 0x1a, 0x31, 0x0b, 0xf1, 0x20, + 0x10, 0x25, 0x2b, 0x15, 0xd3, 0xf7, 0x1e, 0x38, 0xe8, 0x7f, 0x04, 0x29, 0x18, + 0x0b, 0xe9, 0xf7, 0xea, 0x16, 0xe8, 0xe9, 0x06, 0xfa, 0xe1, 0x0b, 0xdd, 0xdb, + 0x02, 0x0e, 0xfc, 0x01, 0x50, 0xe6, 0x01, 0xca, 0xea, 0x08, 0x05, 0x38, 0x05, + 0xe0, 0x0e, 0x13, 0x1d, 0xd2, 0x02, 0xe8, 0x00, 0xf8, 0xe9, 0x13, 0x07, 0x0e, + 0x2e, 0x10, 0x4a, 0x0c, 0x07, 0x41, 0x18, 0x07, 0x34, 0x03, 0xf1, 0x27, 0xde, + 0xff, 0xc5, 0x16, 0xe7, 0xd8, 0x0b, 0xf9, 0xd2, 0x3a, 0x24, 0x21, 0x15, 0xf3, + 0xed, 0xf5, 0xf6, 0x2d, 0xe5, 0x4a, 0xc9, 0xe0, 0x0f, 0x20, 0xf2, 0x1a, 0x28, + 0x3c, 0x1a, 0xf6, 0xfa, 0x3a, 0xe4, 0x3f, 0x0d, 0x05, 0xde, 0xe9, 0x1e, 0x17, + 0x3a, 0x21, 0xbf, 0xbb, 0x0b, 0xed, 0xfc, 0x15, 0xe8, 0xfe, 0x81, 0x2b, 0xd8, + 0x2e, 0x14, 0x2f, 0xd9, 0xeb, 0x22, 0x0f, 0x0a, 0xf4, 0xf1, 0x01, 0x17, 0x0a, + 0x20, 0xe9, 0x29, 0xf7, 0xea, 0xfb, 0xf9, 0xfb, 0xd0, 0x48, 0xef, 0x05, 0xce, + 0xf5, 0xf8, 0xc7, 0x52, 0xd5, 0x07, 0xd3, 0xfc, 0xf4, 0xa8, 0x2d, 0x14, 0xdb, + 0x3b, 0xdd, 0xd1, 0xfb, 0x1e, 0xd3, 0x09, 0xc4, 0xce, 0x12, 0xcd, 0xce, 0xe2, + 0x07, 0x43, 0xfb, 0xf2, 0xd7, 0x1a, 0xe8, 0x1c, 0xf4, 0x16, 0x1a, 0xb7, 0xe8, + 0xec, 0xe7, 0xe6, 0x04, 0xfc, 0x3c, 0x3c, 0xf7, 0xc3, 0xec, 0x58, 0xe0, 0x24, + 0xdf, 0x1a, 0x40, 0x41, 0xfa, 0x25, 0xf5, 0x00, 0xc5, 0x3f, 0xfc, 0xd5, 0x24, + 0x1a, 0xfc, 0xf6, 0xd6, 0xb2, 0x10, 0x0c, 0xeb, 0x02, 0x01, 0x33, 0xd7, 0x06, + 0xe2, 0x13, 0xff, 0x11, 0x38, 0xc9, 0xd7, 0xd7, 0xeb, 0xf4, 0x15, 0xfa, 0xda, + 0x32, 0x3d, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xb5, + 0x79, 0x9c, 0x67, 0xe0, 0x3a, 0x57, 0xa7, 0x81, 0x58, 0x81, 0x7f, 0x5f, 0xe6, + 0xfe, 0xb2, 0xc5, 0xdb, 0x8a, 0x3c, 0xec, 0xc7, 0xaf, 0xa8, 0xf2, 0x09, 0x08, + 0x2f, 0xdd, 0x81, 0x7b, 0xb7, 0x0a, 0x0e, 0x24, 0x6b, 0x7f, 0xa3, 0x01, 0xdd, + 0x10, 0x04, 0x8c, 0x26, 0xe6, 0x4e, 0x81, 0x81, 0x39, 0x81, 0x04, 0x4f, 0xf1, + 0x46, 0x28, 0xc0, 0x6a, 0x9c, 0x3e, 0xb7, 0x2e, 0x77, 0x06, 0xfa, 0x46, 0x1d, + 0x63, 0x4c, 0xf2, 0xec, 0xd1, 0x91, 0x5c, 0x95, 0xfc, 0xff, 0x60, 0x95, 0xfc, + 0xff, 0x64, 0x95, 0xfc, 0xff, 0x68, 0x95, 0xfc, 0xff, 0x96, 0x3d, 0xfd, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0xf9, 0xf0, 0x0f, 0x05, + 0x06, 0x81, 0x04, 0xff, 0x74, 0xef, 0xfe, 0xf9, 0x81, 0x18, 0x16, 0x7f, 0xeb, + 0xf7, 0x04, 0x00, 0x12, 0xf5, 0xf7, 0x20, 0xec, 0x06, 0xf4, 0x7f, 0x5a, 0x7a, + 0xf7, 0x07, 0xfa, 0x2a, 0xef, 0x60, 0x0a, 0x7f, 0xee, 0x81, 0x55, 0x0a, 0xfa, + 0xfc, 0xbb, 0x0b, 0xfe, 0xdf, 0x19, 0xec, 0xfb, 0x1f, 0x04, 0x81, 0xef, 0x7f, + 0x3e, 0xea, 0xf8, 0xce, 0x31, 0x4d, 0x11, 0xfc, 0x81, 0x0b, 0x00, 0xfd, 0x15, + 0xf9, 0xf8, 0x01, 0x0d, 0x0f, 0x01, 0x03, 0xe6, 0x81, 0x03, 0x81, 0xdb, 0x0c, + 0xfa, 0x0a, 0x0d, 0xc9, 0xf8, 0x49, 0x5a, 0x15, 0xf1, 0xfd, 0x60, 0x81, 0xfd, + 0x04, 0xf1, 0x01, 0x07, 0xa2, 0x0b, 0x81, 0xf9, 0xb4, 0xc8, 0x07, 0x02, 0xaa, + 0x17, 0x7f, 0x02, 0x05, 0xd9, 0xd7, 0xf0, 0x7f, 0x23, 0xd8, 0x1d, 0x0d, 0x0a, + 0x09, 0xf1, 0xf5, 0xea, 0x7f, 0x00, 0x22, 0x3e, 0xfd, 0xff, 0x04, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x1f, 0xe2, 0xff, 0xff, 0xff, 0x2f, 0x00, 0x00, + 0xaf, 0xee, 0xff, 0xff, 0xdb, 0x16, 0x00, 0x00, 0x44, 0xff, 0xff, 0xff, 0x16, + 0x54, 0x00, 0x00, 0x34, 0x17, 0x00, 0x00, 0xd5, 0x0c, 0x00, 0x00, 0xf6, 0x22, + 0x00, 0x00, 0xcd, 0x20, 0x00, 0x00, 0xdf, 0x8f, 0x00, 0x00, 0x64, 0x25, 0x00, + 0x00, 0x83, 0x1d, 0x00, 0x00, 0x53, 0x42, 0x00, 0x00, 0xe6, 0x19, 0x00, 0x00, + 0x9f, 0x0d, 0x00, 0x00, 0x03, 0xde, 0xff, 0xff, 0x52, 0x23, 0x00, 0x00, 0x71, + 0x3f, 0x00, 0x00, 0x92, 0x19, 0x00, 0x00, 0xb0, 0xd9, 0xff, 0xff, 0xa0, 0x23, + 0x00, 0x00, 0xaf, 0x03, 0x00, 0x00, 0x30, 0xf9, 0xff, 0xff, 0x2b, 0x28, 0x00, + 0x00, 0xfc, 0x97, 0x00, 0x00, 0xcc, 0x09, 0x00, 0x00, 0xb9, 0x24, 0x00, 0x00, + 0x6b, 0xb9, 0xff, 0xff, 0x68, 0x56, 0x00, 0x00, 0x43, 0x2c, 0x00, 0x00, 0xce, + 0xef, 0xff, 0xff, 0xae, 0x3e, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x03, 0x34, 0xee, 0xd9, 0x38, 0x14, 0x0d, 0xc6, 0xdc, 0x0d, 0x1d, + 0xf3, 0x7f, 0x3a, 0x01, 0x13, 0x0f, 0x3c, 0xfd, 0x0d, 0xe3, 0xd9, 0xc3, 0xaf, + 0xad, 0xfc, 0x1a, 0xff, 0xf2, 0x7f, 0xe4, 0xdc, 0x0d, 0x74, 0x0d, 0x0a, 0xdb, + 0xdb, 0xd6, 0xac, 0xe4, 0x1f, 0xfc, 0x43, 0xff, 0x7f, 0xf9, 0x04, 0xf8, 0x48, + 0xf0, 0x85, 0x56, 0x81, 0xbc, 0xc9, 0xd4, 0x04, 0x31, 0xf8, 0x64, 0xe4, 0x16, + 0xec, 0x40, 0xed, 0xbe, 0xf2, 0x0c, 0x0b, 0x19, 0x0c, 0x38, 0x07, 0xc8, 0xe4, + 0x2d, 0x81, 0xe4, 0x77, 0xab, 0xf6, 0x2a, 0xe2, 0x27, 0xe8, 0x0a, 0xa3, 0x49, + 0xad, 0x7f, 0x1c, 0xf4, 0x39, 0x17, 0xa1, 0xa7, 0x1b, 0x0b, 0xef, 0x17, 0xd9, + 0xff, 0xf1, 0x02, 0x49, 0x2b, 0xe3, 0xcf, 0x2f, 0x7f, 0xa2, 0xff, 0xe4, 0x0f, + 0xe8, 0xe4, 0x01, 0x7f, 0xa3, 0xfa, 0xdd, 0xff, 0xce, 0x0d, 0xf6, 0xea, 0x0d, + 0xaa, 0xf6, 0xc2, 0x32, 0x02, 0xeb, 0x29, 0x1b, 0x7f, 0xe6, 0xee, 0x0c, 0xf3, + 0xc2, 0x25, 0x35, 0xde, 0xfc, 0xdc, 0xc9, 0x7f, 0x2b, 0xd7, 0x17, 0x20, 0x22, + 0x2b, 0x09, 0x59, 0xba, 0x38, 0x35, 0x16, 0x5d, 0x4d, 0x3c, 0xad, 0x95, 0x09, + 0xbd, 0x81, 0xe2, 0x22, 0xc8, 0x9f, 0x33, 0xec, 0xab, 0x70, 0x16, 0xeb, 0x24, + 0x20, 0xce, 0x2f, 0xc2, 0xb8, 0xe5, 0xf7, 0x14, 0x1e, 0x22, 0x81, 0x2f, 0xda, + 0x7f, 0xc3, 0xce, 0x5a, 0xcc, 0x70, 0xfa, 0x4d, 0x06, 0xa7, 0x8e, 0x06, 0xbc, + 0x1d, 0x35, 0x15, 0x0b, 0xd6, 0xed, 0x1f, 0xef, 0xc2, 0xca, 0xd1, 0xe1, 0xf7, + 0x23, 0xff, 0x81, 0xd2, 0x39, 0xe3, 0xee, 0x15, 0x06, 0xe2, 0xf6, 0x48, 0xc0, + 0x13, 0xeb, 0x81, 0xbd, 0x13, 0x37, 0xf5, 0x38, 0x29, 0xfc, 0x7f, 0xf4, 0xee, + 0x0a, 0x08, 0x1e, 0xac, 0x1f, 0xd0, 0x43, 0xe4, 0xd3, 0xf1, 0xfd, 0x2e, 0xe6, + 0xd4, 0x2f, 0x2b, 0x3e, 0x0a, 0x5a, 0x7f, 0x08, 0xd4, 0xe3, 0x18, 0x24, 0xb1, + 0x00, 0x11, 0x85, 0xed, 0xfc, 0x22, 0x3c, 0x0e, 0x19, 0xc7, 0x78, 0xfa, 0xbc, + 0x27, 0xfb, 0x2f, 0x81, 0x5f, 0x35, 0x0c, 0x1a, 0xe8, 0x96, 0xbd, 0x7f, 0x95, + 0x0e, 0x32, 0x62, 0xe7, 0xf6, 0xcf, 0xb3, 0xb3, 0xef, 0x55, 0xf5, 0xf2, 0xf2, + 0x24, 0xbf, 0x55, 0x79, 0xfe, 0xcc, 0xf4, 0x61, 0x58, 0x81, 0x69, 0x81, 0x11, + 0xb0, 0x4d, 0xee, 0x2d, 0x7f, 0x39, 0xdc, 0xde, 0xf7, 0x76, 0x52, 0xb6, 0xdf, + 0x7f, 0x0e, 0x68, 0x18, 0x1d, 0xe3, 0xc7, 0xb9, 0x25, 0xb6, 0x48, 0x15, 0x2b, + 0xe8, 0xc5, 0x0b, 0x11, 0x03, 0xe4, 0xc9, 0xf5, 0x19, 0xe1, 0x7f, 0x05, 0x25, + 0xd7, 0x3f, 0x08, 0x0b, 0x00, 0xba, 0x29, 0x7f, 0x1f, 0xe7, 0x18, 0xf3, 0x04, + 0x26, 0xf1, 0x1a, 0xe6, 0x11, 0x19, 0xe7, 0xfa, 0xf0, 0xa7, 0x0c, 0xf6, 0x7f, + 0xc3, 0x09, 0xec, 0xe0, 0x14, 0xe2, 0x23, 0xf0, 0x97, 0x04, 0x38, 0x10, 0x7f, + 0xd3, 0x08, 0x5d, 0xb5, 0x25, 0x20, 0x46, 0x95, 0x30, 0xa6, 0x09, 0xde, 0x64, + 0xcc, 0xf6, 0xa8, 0x03, 0xfe, 0x01, 0x10, 0xf1, 0x38, 0xfb, 0xeb, 0xfc, 0x7f, + 0x06, 0x00, 0x06, 0xf1, 0x1a, 0x3d, 0xf4, 0xf1, 0xec, 0xef, 0x7f, 0xdf, 0x2d, + 0x99, 0x12, 0xa9, 0x40, 0xef, 0x94, 0xf3, 0x0f, 0x7f, 0xe8, 0x29, 0x07, 0xf8, + 0xd9, 0xca, 0x23, 0x71, 0x36, 0x06, 0x0b, 0x2c, 0x1a, 0xdb, 0xf4, 0xec, 0x7f, + 0xe4, 0xdf, 0x03, 0xa3, 0xde, 0xb6, 0xa8, 0x08, 0x0f, 0xda, 0xfe, 0xc5, 0x1a, + 0xd2, 0xe4, 0x3a, 0xca, 0xf3, 0xfa, 0x81, 0xd0, 0xd3, 0xf2, 0x08, 0x10, 0xda, + 0x17, 0x02, 0x1a, 0x11, 0x81, 0x81, 0x76, 0xf9, 0xd7, 0xe3, 0xda, 0xbc, 0x51, + 0x3e, 0x65, 0xbe, 0x37, 0x71, 0x43, 0xca, 0xba, 0x40, 0xfd, 0xff, 0x04, 0x00, + 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x14, 0xfd, 0x8d, 0x2e, 0x0c, 0x0c, 0xff, + 0x1a, 0x0e, 0x00, 0x85, 0xbe, 0xff, 0x00, 0xf9, 0xf0, 0x11, 0xf9, 0x81, 0x90, + 0xf7, 0x01, 0x00, 0x01, 0xe0, 0xf0, 0xf2, 0x9f, 0xe1, 0xe9, 0x00, 0x22, 0x81, + 0x1b, 0x0c, 0x18, 0xfe, 0xcb, 0x13, 0x5e, 0xd9, 0xeb, 0x42, 0x3e, 0x0a, 0xec, + 0x00, 0x7f, 0x24, 0xf9, 0xdf, 0xcc, 0x81, 0xbc, 0x01, 0x66, 0xb4, 0x7f, 0xfe, + 0x81, 0x1c, 0x81, 0x7f, 0x63, 0x25, 0x3b, 0xc3, 0xa5, 0x78, 0x8f, 0x01, 0x03, + 0x0e, 0x41, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x7a, + 0xed, 0xff, 0xff, 0xc0, 0xef, 0xff, 0xff, 0x49, 0x1b, 0x00, 0x00, 0xc7, 0x21, + 0x00, 0x00, 0x4d, 0x74, 0x00, 0x00, 0x26, 0x7a, 0x00, 0x00, 0x85, 0xc4, 0xff, + 0xff, 0x41, 0x95, 0xff, 0xff, 0x1b, 0xf2, 0xff, 0xff, 0x05, 0x33, 0x00, 0x00, + 0xcb, 0xf5, 0xff, 0xff, 0x4d, 0x6c, 0x00, 0x00, 0xb1, 0x08, 0x00, 0x00, 0x01, + 0xd2, 0xff, 0xff, 0x47, 0x05, 0x00, 0x00, 0x59, 0x3e, 0x00, 0x00, 0x13, 0xd9, + 0xff, 0xff, 0x62, 0x2f, 0x00, 0x00, 0x79, 0xcd, 0xff, 0xff, 0x86, 0xd7, 0xff, + 0xff, 0x99, 0x0a, 0x00, 0x00, 0x7f, 0x21, 0x00, 0x00, 0x27, 0xf4, 0xff, 0xff, + 0xc2, 0xec, 0xff, 0xff, 0xc1, 0xf3, 0xff, 0xff, 0x04, 0xff, 0xff, 0xff, 0x0f, + 0xf5, 0xff, 0xff, 0x51, 0xed, 0xff, 0xff, 0x3c, 0x2a, 0x00, 0x00, 0xec, 0xe8, + 0xff, 0xff, 0x24, 0xc3, 0xff, 0xff, 0x99, 0x32, 0x00, 0x00, 0x9a, 0x41, 0xfd, + 0xff, 0x04, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x4f, 0x2a, 0xde, 0x21, + 0xa6, 0xcc, 0x33, 0x25, 0x47, 0xe7, 0x16, 0xe6, 0xc7, 0x59, 0xb9, 0x94, 0x7f, + 0x3d, 0xd7, 0x5e, 0x81, 0x9f, 0x61, 0x50, 0x6a, 0xb5, 0x40, 0xa7, 0xa3, 0x7f, + 0xa2, 0xac, 0x4f, 0x1a, 0xde, 0x32, 0xbb, 0xe6, 0x3d, 0x37, 0x2e, 0xd2, 0x37, + 0x88, 0xcc, 0x3a, 0xda, 0xe7, 0x4e, 0x52, 0xbd, 0x30, 0xa1, 0x98, 0x3d, 0x7f, + 0x53, 0xdb, 0x53, 0xb1, 0xb7, 0x3b, 0xa0, 0xc6, 0x69, 0x7f, 0x81, 0x7f, 0x83, + 0x81, 0x7f, 0x7f, 0x7f, 0x81, 0x7f, 0x81, 0x81, 0x69, 0x81, 0x81, 0x38, 0x40, + 0xc8, 0x43, 0xb5, 0xe8, 0x56, 0x2f, 0x3d, 0xd3, 0x4b, 0xa6, 0xb8, 0x4f, 0xbb, + 0xc4, 0x16, 0x20, 0xd6, 0x01, 0xe1, 0xe3, 0x18, 0x63, 0x1d, 0xf3, 0x41, 0xdf, + 0xeb, 0x04, 0xe9, 0x18, 0x1d, 0x4c, 0xa4, 0x23, 0xc5, 0xd1, 0x2d, 0x58, 0x2b, + 0xeb, 0x53, 0xc8, 0xc9, 0x07, 0xe0, 0xfd, 0x13, 0x26, 0xeb, 0x24, 0xf9, 0x01, + 0x1c, 0x12, 0x12, 0x00, 0x23, 0xf0, 0xe3, 0x0e, 0xf8, 0xfc, 0x0c, 0x9a, 0xfc, + 0xff, 0x3a, 0x42, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x9c, 0x79, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x7c, + 0xf5, 0xff, 0xff, 0xf1, 0x1c, 0x00, 0x00, 0xcc, 0x3d, 0x00, 0x00, 0xdb, 0x02, + 0x00, 0x00, 0xc2, 0xff, 0xff, 0xff, 0x66, 0x42, 0xfd, 0xff, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0xe7, 0xe7, 0xff, 0xff, 0xf6, 0xff, 0xff, 0xff, + 0x1c, 0xf5, 0xff, 0xff, 0x54, 0x38, 0x00, 0x00, 0xdf, 0xe2, 0xff, 0xff, 0xbe, + 0x0b, 0x00, 0x00, 0xbe, 0x02, 0x00, 0x00, 0xc9, 0xed, 0xff, 0xff, 0xa7, 0x31, + 0x00, 0x00, 0x86, 0x2a, 0x00, 0x00, 0x48, 0x2b, 0x00, 0x00, 0x9d, 0xf3, 0xff, + 0xff, 0x00, 0xec, 0xff, 0xff, 0x2f, 0xe0, 0xff, 0xff, 0x94, 0x39, 0x00, 0x00, + 0x83, 0xd9, 0xff, 0xff, 0x50, 0x06, 0x00, 0x00, 0xd1, 0xfc, 0xff, 0xff, 0x1f, + 0xfd, 0xff, 0xff, 0x33, 0x2b, 0x00, 0x00, 0xa6, 0xf8, 0xff, 0xff, 0x8e, 0xde, + 0xff, 0xff, 0x78, 0x1c, 0x00, 0x00, 0xcc, 0x24, 0x00, 0x00, 0xfd, 0xed, 0xff, + 0xff, 0x55, 0x06, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0xb6, 0xe8, 0xff, 0xff, + 0x06, 0xf2, 0xff, 0xff, 0x6b, 0xf5, 0xff, 0xff, 0x83, 0xfc, 0xff, 0xff, 0x6b, + 0xf6, 0xff, 0xff, 0x99, 0xf9, 0xff, 0xff, 0xdd, 0xf0, 0xff, 0xff, 0x68, 0x38, + 0x00, 0x00, 0x22, 0xf1, 0xff, 0xff, 0xe3, 0xeb, 0xff, 0xff, 0x2a, 0xf3, 0xff, + 0xff, 0xc1, 0x32, 0x00, 0x00, 0xe5, 0xe5, 0xff, 0xff, 0x26, 0x26, 0x00, 0x00, + 0xfb, 0x08, 0x00, 0x00, 0x31, 0xf9, 0xff, 0xff, 0x56, 0xe6, 0xff, 0xff, 0xd5, + 0xe0, 0xff, 0xff, 0x40, 0xe8, 0xff, 0xff, 0xdf, 0xf1, 0xff, 0xff, 0x76, 0xf5, + 0xff, 0xff, 0x2e, 0xe4, 0xff, 0xff, 0xec, 0xf1, 0xff, 0xff, 0x19, 0xf5, 0xff, + 0xff, 0x03, 0x2c, 0x00, 0x00, 0xb4, 0xec, 0xff, 0xff, 0x57, 0xe2, 0xff, 0xff, + 0x26, 0xe7, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xff, 0x2a, 0xf9, 0xff, 0xff, 0x91, + 0xf3, 0xff, 0xff, 0x2a, 0xec, 0xff, 0xff, 0xb1, 0xe3, 0xff, 0xff, 0xa0, 0xf7, + 0xff, 0xff, 0x0a, 0x28, 0x00, 0x00, 0xfb, 0xeb, 0xff, 0xff, 0xa2, 0xfb, 0xff, + 0xff, 0x62, 0x26, 0x00, 0x00, 0x82, 0xf0, 0xff, 0xff, 0x5e, 0x29, 0x00, 0x00, + 0xe7, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xf7, 0xff, 0xff, 0x40, + 0xfa, 0xff, 0xff, 0x70, 0x0a, 0x00, 0x00, 0xeb, 0xf5, 0xff, 0xff, 0x15, 0x2b, + 0x00, 0x00, 0xf0, 0xf2, 0xff, 0xff, 0x6f, 0x24, 0x00, 0x00, 0xd8, 0x11, 0x00, + 0x00, 0x79, 0x28, 0x00, 0x00, 0x1e, 0xf8, 0xff, 0xff, 0x76, 0xf9, 0xff, 0xff, + 0x12, 0xe8, 0xff, 0xff, 0xa4, 0x31, 0x00, 0x00, 0x2a, 0xfd, 0xff, 0xff, 0x89, + 0xea, 0xff, 0xff, 0xfe, 0xe3, 0xff, 0xff, 0xf5, 0x28, 0x00, 0x00, 0xf9, 0x1b, + 0x00, 0x00, 0xdd, 0xf8, 0xff, 0xff, 0xb1, 0x04, 0x00, 0x00, 0xb8, 0xf3, 0xff, + 0xff, 0x9f, 0x03, 0x00, 0x00, 0x92, 0xe7, 0xff, 0xff, 0x93, 0xfe, 0xff, 0xff, + 0xe6, 0x2d, 0x00, 0x00, 0xf7, 0x30, 0x00, 0x00, 0x6c, 0x36, 0x00, 0x00, 0x4a, + 0x0c, 0x00, 0x00, 0x4c, 0xf8, 0xff, 0xff, 0x12, 0xed, 0xff, 0xff, 0x67, 0xf8, + 0xff, 0xff, 0x29, 0x33, 0x00, 0x00, 0x08, 0xef, 0xff, 0xff, 0x72, 0x2b, 0x00, + 0x00, 0xed, 0xf4, 0xff, 0xff, 0x0b, 0x29, 0x00, 0x00, 0xf4, 0x2e, 0x00, 0x00, + 0x48, 0xfe, 0xff, 0xff, 0xd3, 0xf2, 0xff, 0xff, 0xde, 0xfd, 0xff, 0xff, 0xd9, + 0x08, 0x00, 0x00, 0x6e, 0x25, 0x00, 0x00, 0x9b, 0xf6, 0xff, 0xff, 0xf7, 0xea, + 0xff, 0xff, 0x82, 0x0a, 0x00, 0x00, 0x7d, 0x0e, 0x00, 0x00, 0x68, 0xee, 0xff, + 0xff, 0x0c, 0x27, 0x00, 0x00, 0xeb, 0x2e, 0x00, 0x00, 0xc9, 0xfe, 0xff, 0xff, + 0xda, 0x39, 0x00, 0x00, 0xd4, 0x32, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x1d, + 0xdf, 0xff, 0xff, 0xe8, 0xfb, 0xff, 0xff, 0x89, 0x07, 0x00, 0x00, 0xcd, 0x28, + 0x00, 0x00, 0x22, 0x1e, 0x00, 0x00, 0xe5, 0xf8, 0xff, 0xff, 0x48, 0x9c, 0xfc, + 0xff, 0x4c, 0x9c, 0xfc, 0xff, 0x50, 0x9c, 0xfc, 0xff, 0x54, 0x9c, 0xfc, 0xff, + 0x58, 0x9c, 0xfc, 0xff, 0x5c, 0x9c, 0xfc, 0xff, 0x8a, 0x44, 0xfd, 0xff, 0x04, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x62, 0xff, + 0xff, 0xff, 0xed, 0x4a, 0x00, 0x00, 0x94, 0xfe, 0xff, 0xff, 0x5d, 0x18, 0x00, + 0x00, 0x82, 0x2f, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x00, + 0x79, 0x01, 0x00, 0x00, 0x7d, 0x2c, 0x00, 0x00, 0xc2, 0x15, 0x00, 0x00, 0x74, + 0x36, 0x00, 0x00, 0x1a, 0x56, 0x00, 0x00, 0xa2, 0x11, 0x00, 0x00, 0x6c, 0x1d, + 0x00, 0x00, 0x29, 0x1e, 0x00, 0x00, 0xac, 0x9c, 0xfc, 0xff, 0xb0, 0x9c, 0xfc, + 0xff, 0xb4, 0x9c, 0xfc, 0xff, 0xb8, 0x9c, 0xfc, 0xff, 0xbc, 0x9c, 0xfc, 0xff, + 0xc0, 0x9c, 0xfc, 0xff, 0xc4, 0x9c, 0xfc, 0xff, 0xc8, 0x9c, 0xfc, 0xff, 0xcc, + 0x9c, 0xfc, 0xff, 0xd0, 0x9c, 0xfc, 0xff, 0xd4, 0x9c, 0xfc, 0xff, 0x02, 0x45, + 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x50, 0x27, 0x00, + 0x00, 0x6a, 0x04, 0x00, 0x00, 0x00, 0xcd, 0xff, 0xff, 0xb4, 0x89, 0xff, 0xff, + 0xcb, 0xa4, 0xff, 0xff, 0x2a, 0x40, 0x00, 0x00, 0x76, 0x19, 0x00, 0x00, 0xd1, + 0xbd, 0xff, 0xff, 0x57, 0x0b, 0x00, 0x00, 0x4e, 0x32, 0x00, 0x00, 0x17, 0x46, + 0x00, 0x00, 0x15, 0xed, 0xff, 0xff, 0x10, 0x4a, 0x00, 0x00, 0x2c, 0x21, 0x00, + 0x00, 0xd1, 0xd7, 0xff, 0xff, 0x07, 0xdc, 0xff, 0xff, 0x4e, 0x45, 0xfd, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x1b, 0x31, 0x3b, 0x4d, 0x2e, + 0xfe, 0xe7, 0xae, 0xcf, 0x14, 0x7f, 0xfc, 0xe6, 0x08, 0x36, 0xa9, 0x01, 0x7a, + 0xdf, 0xf7, 0xf8, 0x0b, 0xed, 0x0e, 0xfe, 0xfc, 0xd3, 0x81, 0xf5, 0xbc, 0x02, + 0xf4, 0xa4, 0x81, 0x9a, 0xfa, 0xcd, 0xf0, 0x46, 0xd4, 0xd4, 0xcd, 0xa8, 0x37, + 0xb3, 0xb8, 0x2e, 0xe1, 0x51, 0x4e, 0xfa, 0x1f, 0xf2, 0xc3, 0xd9, 0x7f, 0x3c, + 0x0f, 0x4e, 0xe4, 0x7f, 0x81, 0x81, 0xb8, 0x16, 0x0a, 0x06, 0xb1, 0xbe, 0xf5, + 0x2a, 0xd4, 0x2f, 0x25, 0xd5, 0xac, 0x57, 0x29, 0xd3, 0xa5, 0xf0, 0x8d, 0x19, + 0x07, 0x81, 0x1b, 0xbe, 0x01, 0xe1, 0xea, 0xf6, 0xcc, 0xe9, 0x31, 0x2a, 0x12, + 0xf1, 0x46, 0x7f, 0x7f, 0x7f, 0xe0, 0x61, 0xbb, 0xdd, 0x0a, 0xe8, 0x04, 0xb7, + 0x11, 0x0c, 0xcd, 0x0a, 0x7f, 0xf6, 0x1e, 0xfe, 0xa6, 0xa4, 0x01, 0x64, 0xc9, + 0x4a, 0xa8, 0x43, 0xba, 0xc3, 0x7f, 0x81, 0x63, 0xbb, 0x00, 0xc6, 0x81, 0x7f, + 0x9e, 0x81, 0x81, 0xf7, 0x7f, 0x81, 0x81, 0x7f, 0x1d, 0x7f, 0xed, 0x7f, 0x81, + 0xe3, 0x7f, 0x9f, 0x3c, 0x7f, 0x81, 0x7f, 0x49, 0x61, 0x9f, 0xa2, 0x00, 0x13, + 0xa9, 0x55, 0xa7, 0xcf, 0xfa, 0x7e, 0x81, 0xf9, 0x16, 0x07, 0xac, 0xe6, 0x42, + 0xfa, 0xf0, 0x13, 0xa0, 0xbb, 0x30, 0x81, 0xf9, 0x81, 0xe7, 0xfc, 0xe6, 0xc0, + 0xc1, 0x2c, 0x78, 0xdf, 0xca, 0x0b, 0x97, 0x0f, 0x1e, 0xe8, 0x0e, 0xc8, 0xf6, + 0xf6, 0x14, 0x99, 0x09, 0xd9, 0x19, 0xd9, 0x81, 0xce, 0x24, 0x16, 0xf6, 0x42, + 0x40, 0xd6, 0xd9, 0xe4, 0x2b, 0x06, 0x9b, 0xea, 0xf5, 0x19, 0x0d, 0xfd, 0x68, + 0xc6, 0xef, 0xed, 0xee, 0xf7, 0x08, 0xe4, 0x09, 0x3b, 0x11, 0xaa, 0xe4, 0x08, + 0xff, 0x08, 0xb8, 0xde, 0x58, 0xed, 0xe2, 0x06, 0x07, 0x15, 0x62, 0x08, 0x83, + 0xe5, 0x14, 0xc7, 0x26, 0x16, 0x12, 0xc4, 0xf2, 0xf8, 0xf5, 0x03, 0x17, 0xee, + 0x0c, 0x28, 0x01, 0x1e, 0x15, 0x17, 0xd5, 0xc6, 0xb6, 0x00, 0xcf, 0xae, 0xed, + 0xdb, 0xfc, 0xe2, 0x2d, 0xf9, 0xdb, 0xe3, 0x37, 0xe7, 0x10, 0x7a, 0x46, 0xfd, + 0xff, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, 0x1c, 0x00, 0x00, + 0x0e, 0xfe, 0xff, 0xff, 0x07, 0x01, 0x00, 0x00, 0x49, 0xf8, 0xff, 0xff, 0xd4, + 0x08, 0x00, 0x00, 0x93, 0x25, 0x00, 0x00, 0x1f, 0xe7, 0xff, 0xff, 0xa9, 0x1c, + 0x00, 0x00, 0xc2, 0x3a, 0x00, 0x00, 0xe4, 0x1b, 0x00, 0x00, 0x9f, 0x06, 0x00, + 0x00, 0x37, 0xf8, 0xff, 0xff, 0x90, 0x5b, 0x00, 0x00, 0x57, 0x08, 0x00, 0x00, + 0x72, 0xfb, 0xff, 0xff, 0xc9, 0x7e, 0x00, 0x00, 0x19, 0x07, 0x00, 0x00, 0x67, + 0xff, 0xff, 0xff, 0x74, 0xff, 0xff, 0xff, 0x37, 0xff, 0xff, 0xff, 0x96, 0x30, + 0x00, 0x00, 0xb3, 0xfc, 0xff, 0xff, 0x52, 0x5d, 0x00, 0x00, 0x32, 0x03, 0x00, + 0x00, 0xdb, 0x04, 0x00, 0x00, 0x3f, 0x05, 0x00, 0x00, 0xa4, 0xfe, 0xff, 0xff, + 0xc1, 0x36, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x24, 0x1b, 0x00, 0x00, 0x83, + 0x32, 0x00, 0x00, 0x09, 0xfa, 0xff, 0xff, 0x06, 0x47, 0xfd, 0xff, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x13, 0xe9, 0xd2, 0x14, 0x97, 0x41, 0xa4, + 0xeb, 0x07, 0x1d, 0x32, 0xfb, 0xf7, 0x0a, 0xe6, 0xfe, 0xbd, 0x6c, 0x2d, 0x1c, + 0xd1, 0x3a, 0x16, 0x2d, 0x1e, 0xf8, 0x7f, 0x13, 0x1b, 0xc3, 0x50, 0x2b, 0xf9, + 0x17, 0xfd, 0xe6, 0x16, 0xea, 0xe0, 0x98, 0xcd, 0x32, 0xeb, 0x3c, 0x10, 0xf8, + 0x1b, 0xef, 0xf1, 0x10, 0x35, 0x00, 0x0b, 0x13, 0x03, 0xb3, 0xdf, 0x05, 0x7f, + 0xdd, 0xae, 0x3d, 0x3b, 0xf7, 0x62, 0xbe, 0xf2, 0xba, 0x28, 0x10, 0xfb, 0x98, + 0xa5, 0x21, 0x31, 0x27, 0xec, 0xfd, 0xe4, 0x1c, 0x09, 0xe2, 0x44, 0x0d, 0x28, + 0x28, 0xf9, 0xd5, 0x43, 0xe8, 0xcc, 0x27, 0xbe, 0x81, 0xa7, 0xd8, 0x1d, 0xe1, + 0x00, 0xe9, 0x33, 0x5a, 0x59, 0xf8, 0x81, 0xa4, 0x12, 0x00, 0xa1, 0x01, 0x26, + 0x29, 0x37, 0x27, 0xe7, 0xfd, 0x12, 0xcc, 0xe1, 0xd7, 0x01, 0x5f, 0x1b, 0xf5, + 0x5c, 0x1c, 0xc2, 0xb4, 0xe3, 0xed, 0xee, 0x03, 0xdc, 0xbb, 0xdc, 0x71, 0xb4, + 0xb9, 0xf2, 0xf3, 0xba, 0xc9, 0x18, 0x25, 0xd3, 0xe0, 0x89, 0xdd, 0x30, 0xc3, + 0x7f, 0xfb, 0x3e, 0x58, 0xca, 0x55, 0xa7, 0xec, 0xcc, 0xf0, 0xfb, 0x01, 0xf4, + 0xb8, 0xe8, 0x09, 0x04, 0x39, 0x02, 0x81, 0xcc, 0xbe, 0xc9, 0x06, 0xd1, 0x11, + 0xbe, 0xde, 0xe4, 0xf7, 0x2f, 0xf2, 0x38, 0x04, 0xd2, 0x52, 0xf2, 0x07, 0x24, + 0xd5, 0xbf, 0x06, 0x14, 0xf7, 0x49, 0x08, 0xd8, 0xc9, 0xae, 0x1b, 0x6e, 0x40, + 0xca, 0x7f, 0x51, 0x1f, 0xf0, 0xf8, 0x2b, 0x2b, 0xff, 0xf9, 0x0a, 0xe4, 0x1e, + 0x14, 0xc6, 0xf9, 0x27, 0x42, 0x0e, 0x38, 0x14, 0x01, 0xde, 0xea, 0x3b, 0x35, + 0x60, 0xf5, 0x2d, 0xea, 0xab, 0x4e, 0x33, 0x73, 0x58, 0x6f, 0x02, 0x20, 0x7d, + 0x30, 0x1e, 0x0d, 0xd6, 0x1a, 0xe9, 0x60, 0xb7, 0x0f, 0x11, 0x8e, 0x26, 0x29, + 0x1f, 0x7f, 0x16, 0xe3, 0x23, 0x75, 0x11, 0x81, 0xf0, 0xc4, 0xef, 0x13, 0x0b, + 0x43, 0xaf, 0x20, 0x1a, 0x01, 0x49, 0xa6, 0xff, 0x0f, 0x24, 0xfe, 0x05, 0x2f, + 0x4b, 0xbb, 0xce, 0x4a, 0x12, 0x50, 0x22, 0xf4, 0xc5, 0x08, 0x0c, 0x1f, 0x2a, + 0x58, 0xfa, 0xf7, 0x30, 0x30, 0xde, 0x4a, 0xa8, 0xf3, 0x21, 0x59, 0x19, 0x1e, + 0xdb, 0x0c, 0x17, 0x03, 0xb5, 0x91, 0xdc, 0xed, 0x09, 0xbe, 0x81, 0xfb, 0xe6, + 0xcc, 0x2b, 0x76, 0x55, 0xca, 0xf0, 0xe6, 0xef, 0xee, 0x19, 0xc7, 0xba, 0xb4, + 0x28, 0x20, 0xd1, 0x7f, 0x0a, 0xf4, 0x10, 0xf9, 0xe4, 0x01, 0xfe, 0xdb, 0x1e, + 0x36, 0x28, 0xd4, 0x21, 0xef, 0xdc, 0x00, 0xe7, 0x3e, 0x52, 0x12, 0xa5, 0x29, + 0x09, 0xad, 0x87, 0x81, 0x10, 0x9f, 0x49, 0xca, 0x1c, 0xb0, 0xe4, 0x23, 0xbe, + 0xde, 0x28, 0x0e, 0x22, 0xcf, 0xe9, 0xaf, 0x10, 0xf7, 0xdf, 0x10, 0x0a, 0xf6, + 0x04, 0xe5, 0xfd, 0x00, 0xe5, 0xfe, 0x81, 0x09, 0xc6, 0x1f, 0x10, 0x15, 0xcf, + 0xe7, 0x05, 0xc2, 0xd2, 0x09, 0x04, 0x15, 0xf6, 0x37, 0x65, 0x18, 0xd5, 0x06, + 0x4a, 0xcf, 0x1d, 0xfe, 0x0b, 0xe0, 0xed, 0x02, 0x15, 0x09, 0x03, 0xd4, 0xd7, + 0xec, 0x53, 0xe0, 0x03, 0x21, 0x7f, 0xfa, 0xf9, 0xf8, 0xed, 0x1a, 0x11, 0xf6, + 0xeb, 0xfe, 0x46, 0x2a, 0x3a, 0xd3, 0x5b, 0x1b, 0x0d, 0x08, 0x3d, 0x14, 0x3a, + 0xdf, 0x14, 0x16, 0xea, 0x25, 0xf7, 0x14, 0xfa, 0x3a, 0xe7, 0x05, 0x0f, 0x0b, + 0xe1, 0xeb, 0x13, 0x1a, 0xf4, 0xe1, 0x0d, 0xe9, 0x0f, 0xde, 0x7f, 0xfd, 0xfc, + 0xe9, 0x0d, 0x0d, 0x03, 0xf9, 0xc0, 0x28, 0xdd, 0x07, 0x04, 0xe5, 0xf9, 0x0c, + 0xe8, 0x87, 0x07, 0x06, 0xe7, 0xb2, 0x10, 0x1c, 0x81, 0xf1, 0x12, 0xf9, 0x12, + 0xf6, 0x11, 0x70, 0x24, 0x2e, 0x55, 0xda, 0xe4, 0xe8, 0x9e, 0x00, 0xf1, 0x60, + 0x0f, 0x03, 0xb9, 0xa3, 0x2f, 0x29, 0x34, 0xe5, 0xf8, 0x0f, 0x22, 0xec, 0x31, + 0xec, 0xea, 0xf1, 0xf5, 0xfd, 0x05, 0x18, 0x65, 0xda, 0x2e, 0x14, 0x3d, 0xcc, + 0x4e, 0x1f, 0x1f, 0x7f, 0xba, 0xc6, 0xfb, 0x22, 0x23, 0x61, 0x48, 0x32, 0x73, + 0x81, 0xf5, 0xfc, 0x50, 0xdd, 0xd7, 0x05, 0xe4, 0x0a, 0xa0, 0xf5, 0xe7, 0xce, + 0x3b, 0xce, 0xaa, 0xc1, 0xda, 0xd1, 0x2d, 0x08, 0xcb, 0xea, 0xfd, 0x07, 0xfd, + 0x02, 0x06, 0xf4, 0xed, 0xfb, 0xcc, 0x7f, 0xf1, 0x29, 0x01, 0x2a, 0xd5, 0x2b, + 0x4b, 0x01, 0x2f, 0x01, 0xde, 0x12, 0xf7, 0xe6, 0x13, 0xea, 0x06, 0x1c, 0xe8, + 0x05, 0x0a, 0x13, 0xf7, 0xfa, 0x07, 0x0a, 0xf0, 0xf8, 0xcf, 0x0c, 0x57, 0x3d, + 0x29, 0x2c, 0x06, 0x13, 0x7f, 0xbd, 0xe2, 0xf8, 0x09, 0x19, 0xf6, 0x13, 0x44, + 0x24, 0xf5, 0xed, 0xc4, 0x3c, 0xa0, 0xff, 0x22, 0x50, 0x04, 0xf7, 0xf5, 0xf0, + 0x03, 0x07, 0xc1, 0x04, 0x12, 0x07, 0x17, 0x08, 0x09, 0xff, 0xf3, 0xfd, 0xeb, + 0xff, 0xf4, 0xf9, 0xd8, 0x7f, 0xdb, 0xed, 0xec, 0x3d, 0x32, 0xf9, 0xea, 0x0b, + 0xe4, 0xfa, 0x28, 0xb0, 0xb8, 0xeb, 0x08, 0x3d, 0xda, 0x41, 0x34, 0xcf, 0x27, + 0xf3, 0x21, 0x03, 0xba, 0x17, 0xe2, 0xc6, 0xa2, 0xe1, 0x4d, 0xdd, 0xd6, 0x81, + 0x17, 0xfd, 0xf5, 0xf0, 0x19, 0xe9, 0x58, 0xd3, 0x30, 0xfa, 0x31, 0xe1, 0xfe, + 0x35, 0x6e, 0xfd, 0x6d, 0x04, 0x9e, 0xec, 0x58, 0x2f, 0xa4, 0x1d, 0x81, 0x01, + 0x0b, 0xf1, 0x01, 0xfb, 0xff, 0x25, 0xed, 0xc6, 0xe4, 0x5c, 0xde, 0xfb, 0xd1, + 0x40, 0xea, 0x7f, 0x2a, 0xe3, 0x05, 0xd8, 0xf4, 0x07, 0xf9, 0x33, 0x60, 0xdf, + 0x16, 0x02, 0x05, 0xf0, 0xe8, 0xe0, 0x41, 0x14, 0x01, 0x06, 0xda, 0x08, 0x0c, + 0x01, 0x21, 0xef, 0xdd, 0x00, 0x20, 0xf4, 0x0a, 0xed, 0xde, 0x20, 0xf2, 0xdf, + 0xe7, 0x0b, 0xfd, 0x06, 0xf9, 0x04, 0xe5, 0xfa, 0xf6, 0x1d, 0x0b, 0xfc, 0x22, + 0x7f, 0x07, 0x71, 0x02, 0x03, 0x18, 0x02, 0xd6, 0x06, 0xe4, 0x02, 0x02, 0xfe, + 0x1f, 0xd1, 0xf9, 0x0f, 0xfe, 0xf2, 0xf2, 0x0a, 0xe0, 0xf9, 0x11, 0xfa, 0x34, + 0xf5, 0xe4, 0xbd, 0xf8, 0x0c, 0x7f, 0xeb, 0xe0, 0x2f, 0xc5, 0x14, 0xd2, 0xf9, + 0x11, 0x09, 0xd8, 0x14, 0x34, 0xf2, 0xf3, 0xfe, 0xe8, 0xff, 0xea, 0xf2, 0x3b, + 0x18, 0x0b, 0xdd, 0x0d, 0xfe, 0xd0, 0x03, 0x1c, 0xe3, 0x7f, 0x18, 0xcc, 0xd5, + 0x23, 0x25, 0x20, 0xb8, 0x0a, 0x36, 0xef, 0x2e, 0x2c, 0x03, 0xf8, 0x03, 0xff, + 0xf4, 0xd6, 0xf2, 0x1b, 0x7f, 0x39, 0x1f, 0xe1, 0x1a, 0x03, 0x17, 0x02, 0xd5, + 0xe2, 0xff, 0xdb, 0xbf, 0x1b, 0xff, 0x09, 0xdc, 0xf5, 0x65, 0xf4, 0x12, 0x02, + 0xe0, 0x3a, 0x0c, 0xee, 0xd2, 0xfe, 0xf7, 0x12, 0x1b, 0x01, 0xb8, 0xe0, 0xee, + 0xc6, 0x1c, 0x07, 0x06, 0x9d, 0xfd, 0xcc, 0x53, 0x1c, 0xff, 0x1a, 0xe4, 0x1c, + 0xf2, 0xf1, 0x48, 0x21, 0x1c, 0x7f, 0x20, 0xf0, 0xe2, 0x9c, 0x0b, 0x22, 0xda, + 0x13, 0x41, 0x3d, 0x1b, 0xfc, 0xf5, 0xf2, 0x19, 0x09, 0x7f, 0x15, 0x5a, 0xfc, + 0x20, 0x3b, 0x63, 0x1a, 0xf6, 0xe2, 0x00, 0xe8, 0xed, 0xd0, 0xf4, 0xbb, 0x03, + 0x41, 0x2c, 0x32, 0x39, 0xf8, 0x62, 0xf7, 0xfb, 0xda, 0x16, 0x21, 0xfe, 0x35, + 0x2b, 0x41, 0x13, 0xd1, 0x0f, 0x78, 0x50, 0xfe, 0x04, 0x2f, 0x1e, 0xe1, 0x09, + 0x31, 0x0d, 0xf2, 0xf5, 0x0b, 0xee, 0x08, 0xe8, 0xf8, 0x7f, 0x95, 0xb5, 0x00, + 0x29, 0x04, 0x12, 0x01, 0x20, 0x42, 0x81, 0x19, 0x09, 0xeb, 0xe6, 0xe6, 0xe1, + 0x1a, 0xca, 0xf8, 0x01, 0xf5, 0xc9, 0xec, 0xa8, 0xe7, 0xba, 0xd2, 0x27, 0x00, + 0x3f, 0x22, 0xba, 0x12, 0x4b, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x20, 0x01, + 0x00, 0x00, 0xb2, 0x3b, 0xbe, 0xc6, 0x7f, 0xe4, 0x20, 0x29, 0xa7, 0x18, 0xe5, + 0xfe, 0x3c, 0xcf, 0x64, 0x43, 0x27, 0xa0, 0xd5, 0x52, 0xbb, 0x59, 0xc8, 0x39, + 0xcc, 0x50, 0x68, 0x54, 0xaa, 0x81, 0x05, 0x15, 0xab, 0x52, 0x9e, 0x96, 0x1f, + 0xae, 0x36, 0x31, 0x81, 0xd7, 0xa7, 0xe6, 0x64, 0x81, 0x7f, 0x5a, 0x5c, 0x93, + 0xaa, 0x64, 0xb4, 0x7f, 0xb9, 0x5b, 0xac, 0x67, 0x7f, 0x52, 0x88, 0x96, 0xb5, + 0x41, 0xf3, 0x33, 0xe1, 0xbf, 0xb8, 0xc5, 0x19, 0x0e, 0xb8, 0xcc, 0xcf, 0xe2, + 0x47, 0xaf, 0x27, 0x28, 0x33, 0xc4, 0xc8, 0x2a, 0xf0, 0x36, 0xf7, 0x2b, 0xd4, + 0x35, 0x21, 0x07, 0xd1, 0xe5, 0xb1, 0x2c, 0xca, 0x70, 0xbc, 0xa3, 0x6a, 0xb9, + 0x50, 0x53, 0xaf, 0xc1, 0xad, 0xb4, 0x65, 0x23, 0x60, 0x63, 0x3d, 0x8e, 0x9e, + 0x66, 0xba, 0x58, 0xa4, 0x46, 0xa6, 0x5f, 0x73, 0x71, 0xaf, 0xcd, 0xaf, 0x43, + 0x81, 0x7f, 0x81, 0x81, 0xfe, 0x81, 0x7f, 0x7f, 0xa7, 0x81, 0x81, 0x81, 0x7f, + 0x2c, 0x7c, 0x7f, 0x7f, 0x81, 0x81, 0x7f, 0x81, 0x66, 0x81, 0x7f, 0x81, 0x7f, + 0x7d, 0x7f, 0x81, 0xa4, 0x81, 0x7f, 0xb5, 0x37, 0xba, 0xb4, 0xad, 0xb3, 0x47, + 0x4a, 0xe3, 0xb2, 0xc5, 0xaf, 0x3c, 0xfe, 0x2f, 0x2a, 0x36, 0xc8, 0xcf, 0x3a, + 0xc6, 0x0f, 0xc2, 0x41, 0xca, 0x3d, 0x1f, 0x21, 0xcc, 0xc2, 0xc1, 0x44, 0x04, + 0x45, 0xdc, 0xd5, 0x23, 0xc8, 0x38, 0x49, 0xfd, 0xc0, 0xd2, 0xa9, 0x47, 0x2e, + 0x11, 0x28, 0x23, 0xd1, 0xc6, 0x23, 0xef, 0xf9, 0xc9, 0x18, 0xd6, 0x2d, 0x1f, + 0x2f, 0xdf, 0xf8, 0xa8, 0x2e, 0xab, 0x3b, 0xbb, 0xc5, 0xdf, 0xbf, 0x59, 0x63, + 0xfc, 0xaa, 0xc6, 0x84, 0x46, 0x59, 0x10, 0x36, 0x39, 0xd8, 0xc2, 0x32, 0xcd, + 0xcc, 0xb2, 0x32, 0xcc, 0x31, 0x1b, 0x46, 0xd6, 0xd7, 0xcb, 0x46, 0xa7, 0x09, + 0xc8, 0xe3, 0xd8, 0xe8, 0x3b, 0x23, 0x0d, 0xd3, 0xe3, 0xd3, 0xfe, 0x30, 0x0b, + 0x13, 0x16, 0x03, 0x02, 0x13, 0xdd, 0xd5, 0xd6, 0x19, 0xf0, 0x0b, 0x04, 0x2d, + 0xed, 0xd0, 0x08, 0x1f, 0x3e, 0x4c, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0xac, 0x6f, 0x00, 0x00, 0x6b, 0x01, 0x00, 0x00, 0xc8, 0x6b, + 0x00, 0x00, 0x16, 0x57, 0x00, 0x00, 0x08, 0xef, 0xff, 0xff, 0xb3, 0x6a, 0x00, + 0x00, 0x5d, 0x04, 0x00, 0x00, 0xef, 0xfb, 0xff, 0xff, 0x67, 0x65, 0x00, 0x00, + 0x6a, 0xa4, 0x00, 0x00, 0xb1, 0x56, 0x00, 0x00, 0x6b, 0x6f, 0x00, 0x00, 0xde, + 0xf9, 0xff, 0xff, 0xa9, 0xff, 0xff, 0xff, 0xb7, 0xe7, 0xff, 0xff, 0xe4, 0xff, + 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x87, 0x91, 0x00, 0x00, 0x8e, 0x43, 0x00, + 0x00, 0x32, 0xff, 0xff, 0xff, 0xd6, 0x42, 0x00, 0x00, 0xe5, 0xfd, 0xff, 0xff, + 0xf1, 0xa7, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0xcf, 0x2b, 0x00, 0x00, 0x24, + 0xff, 0xff, 0xff, 0x0e, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x74, + 0x00, 0x00, 0x5c, 0x6c, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xdb, 0x03, 0x00, + 0x00, 0xca, 0x4c, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0xf7, 0xee, 0xf3, 0x35, 0xfa, 0xb2, 0xf7, 0x5f, 0x50, 0xfe, 0xd6, 0xfc, 0x11, + 0x20, 0xd5, 0x97, 0x20, 0x00, 0xe1, 0xf7, 0xb7, 0x33, 0xec, 0xf1, 0xd1, 0x13, + 0xfb, 0x4f, 0x7f, 0xa5, 0xfa, 0x8e, 0xe5, 0xe7, 0xfa, 0x34, 0x03, 0xf4, 0xee, + 0x21, 0x01, 0x95, 0x0f, 0x8b, 0x07, 0x03, 0xa3, 0xc8, 0xf1, 0xd3, 0x0e, 0xd7, + 0x1a, 0xeb, 0xe4, 0x0d, 0x28, 0xf5, 0xa1, 0x7f, 0x36, 0xfb, 0x10, 0x1d, 0x0e, + 0x7f, 0x0b, 0xf1, 0x39, 0x04, 0x1e, 0xdb, 0xb1, 0xf6, 0xd4, 0x13, 0xf3, 0x35, + 0xef, 0x0d, 0x2a, 0xb5, 0x0e, 0xc8, 0xf0, 0xdf, 0x25, 0x6e, 0xe2, 0xf7, 0x10, + 0x3c, 0xcf, 0x07, 0x0f, 0xe6, 0x45, 0xdd, 0x17, 0xef, 0x33, 0xcf, 0xe1, 0x34, + 0x08, 0x34, 0xf6, 0x0e, 0xfa, 0xfb, 0xfc, 0x7f, 0xf7, 0xe5, 0x1a, 0xea, 0x11, + 0x1b, 0xfb, 0x95, 0x17, 0xfe, 0xc7, 0xb3, 0xde, 0x22, 0xe7, 0xea, 0xdc, 0x53, + 0x2a, 0x12, 0xdb, 0x6c, 0x16, 0xbc, 0x01, 0x46, 0xef, 0xdc, 0x27, 0xf8, 0xbe, + 0x99, 0x43, 0xe8, 0x9a, 0xc0, 0x93, 0xc0, 0xfe, 0xf6, 0xc8, 0x7f, 0xfd, 0x07, + 0xd8, 0xe8, 0x20, 0x35, 0xe5, 0xd2, 0x71, 0xf5, 0xdf, 0xc7, 0xb0, 0x1d, 0x12, + 0xde, 0xef, 0x17, 0x01, 0x3a, 0x11, 0x6d, 0x04, 0x1b, 0x68, 0x7f, 0x1b, 0xce, + 0x1d, 0xef, 0xe8, 0xd5, 0xeb, 0x35, 0xda, 0x11, 0xb5, 0xfb, 0xf9, 0xe4, 0xe3, + 0x24, 0x17, 0x02, 0x20, 0xac, 0xf2, 0x48, 0x11, 0xe2, 0xfe, 0xbe, 0xd4, 0x81, + 0x67, 0xbd, 0x2d, 0xea, 0xe8, 0xec, 0xcf, 0xf7, 0xd9, 0x44, 0x95, 0xea, 0x01, + 0xd2, 0x08, 0xf5, 0x1a, 0xb5, 0x4d, 0xe1, 0x15, 0xe9, 0x01, 0xea, 0xaa, 0xda, + 0x1f, 0xd1, 0xf8, 0x11, 0xbd, 0x3b, 0x81, 0xdb, 0xf5, 0xfb, 0xe0, 0xf8, 0xe5, + 0x1e, 0xf7, 0xf7, 0x6d, 0x0d, 0xf3, 0xeb, 0x00, 0x7d, 0x2e, 0xf5, 0x20, 0xe6, + 0xcb, 0xf3, 0x09, 0x09, 0x13, 0x1f, 0xeb, 0xfb, 0xc0, 0x02, 0x27, 0x7f, 0xff, + 0x2b, 0x26, 0x27, 0xea, 0x30, 0x73, 0xbd, 0xfa, 0xc7, 0x16, 0xb0, 0x2c, 0xfd, + 0x20, 0xf0, 0xce, 0x1c, 0x16, 0xe7, 0xf2, 0xd9, 0x00, 0xf9, 0x19, 0xe4, 0xe5, + 0xf1, 0x11, 0x3b, 0xbd, 0xf0, 0x2e, 0x0c, 0x2c, 0xe3, 0xd5, 0x01, 0xf3, 0xfc, + 0xef, 0x7f, 0x08, 0x10, 0xf3, 0xff, 0xff, 0xf9, 0x20, 0xff, 0x09, 0x81, 0x51, + 0x0d, 0xc6, 0x32, 0xf5, 0x07, 0x12, 0xc4, 0xe4, 0xf4, 0x24, 0x22, 0x06, 0x1d, + 0xe8, 0x0b, 0xf3, 0xf5, 0x61, 0x00, 0x1b, 0x4f, 0x13, 0xd9, 0x0f, 0x16, 0x03, + 0x4f, 0xc6, 0x35, 0x5b, 0x38, 0xd7, 0x0d, 0xf9, 0xce, 0xd0, 0xad, 0x1b, 0xfb, + 0xf8, 0xd4, 0x0f, 0xf6, 0xfb, 0x13, 0x23, 0x3a, 0x52, 0x6a, 0x09, 0x81, 0xfe, + 0x36, 0x0d, 0xf8, 0x29, 0xc6, 0xec, 0xf8, 0xf6, 0x54, 0x31, 0x02, 0x09, 0x5d, + 0x7f, 0x1d, 0xed, 0xed, 0xcf, 0xe5, 0xb1, 0xe4, 0x40, 0x17, 0x90, 0xab, 0xa0, + 0xc9, 0x13, 0xd2, 0x3b, 0x13, 0x0a, 0x18, 0x55, 0xfc, 0x6b, 0x95, 0x2a, 0xfb, + 0xa0, 0x16, 0x0b, 0xa7, 0x01, 0x09, 0x1e, 0x0f, 0x22, 0x61, 0x24, 0x51, 0xdc, + 0x27, 0x38, 0xdc, 0xd8, 0xdf, 0xce, 0x56, 0xe3, 0xf1, 0x7f, 0x66, 0xbb, 0x31, + 0xf8, 0xba, 0xe9, 0x02, 0xbb, 0x45, 0x0c, 0x23, 0x32, 0xef, 0x0e, 0x1a, 0xd6, + 0x00, 0xf0, 0xd7, 0xb9, 0xe0, 0xd7, 0x07, 0xd6, 0xf9, 0x25, 0xee, 0xe8, 0x43, + 0x35, 0xe0, 0x7f, 0x4f, 0xde, 0xf0, 0xe3, 0xda, 0x32, 0xfe, 0xa4, 0x23, 0x0c, + 0xf7, 0xd2, 0x04, 0xf4, 0x0d, 0xe3, 0x10, 0xef, 0xd9, 0xe9, 0xc3, 0xf8, 0xe2, + 0xf5, 0xd1, 0xf9, 0xe7, 0x00, 0xdb, 0x09, 0xbd, 0x2d, 0x16, 0x0f, 0x05, 0xf4, + 0x7f, 0x04, 0xe4, 0x09, 0xf5, 0xf8, 0xda, 0x0f, 0xd9, 0xef, 0x10, 0x0c, 0x12, + 0xc4, 0xec, 0xa7, 0x16, 0xb6, 0x00, 0x3f, 0x6c, 0xf2, 0x11, 0xab, 0x81, 0x14, + 0xc3, 0x52, 0xa4, 0x09, 0x93, 0x36, 0x0b, 0xc8, 0xa9, 0xf4, 0xf0, 0xe3, 0xf4, + 0x00, 0x20, 0x11, 0xec, 0x71, 0x15, 0x0b, 0x28, 0x13, 0xfd, 0xc4, 0x11, 0x7f, + 0x0d, 0x14, 0xad, 0x98, 0xf5, 0xdc, 0x43, 0x0b, 0xb6, 0xf4, 0xe1, 0xe9, 0xb8, + 0xdf, 0x82, 0xb4, 0x17, 0xd9, 0xd6, 0x06, 0x28, 0xfa, 0x1d, 0x46, 0x98, 0x28, + 0x7f, 0x34, 0x47, 0x34, 0x06, 0x53, 0xfb, 0xeb, 0x25, 0x23, 0x51, 0xea, 0x16, + 0xc8, 0xf9, 0xfc, 0x14, 0xf5, 0x57, 0x1c, 0x46, 0x60, 0xda, 0x0f, 0x39, 0xc2, + 0x9a, 0xc3, 0xa9, 0x1d, 0xda, 0x68, 0xe6, 0xdc, 0xec, 0x08, 0xc6, 0x9a, 0x3d, + 0x07, 0x1c, 0xd7, 0xf0, 0xfc, 0x7f, 0x43, 0x54, 0x31, 0x09, 0x6e, 0x1d, 0xd3, + 0x5e, 0x22, 0xb7, 0xda, 0x46, 0x1a, 0x55, 0x14, 0xf4, 0x0a, 0x3f, 0xdf, 0xf6, + 0x24, 0xd7, 0x00, 0x01, 0x0a, 0x4a, 0xed, 0x81, 0x36, 0x27, 0x06, 0x5f, 0xf2, + 0x01, 0xf2, 0x0d, 0xac, 0xf0, 0xf2, 0x12, 0xe2, 0xeb, 0xcd, 0xb4, 0xdf, 0x36, + 0xc6, 0xd1, 0x47, 0xe2, 0xe3, 0xe7, 0xf6, 0x7f, 0x04, 0x0d, 0xef, 0x51, 0xe0, + 0x0c, 0xdf, 0x14, 0xf8, 0xad, 0xfc, 0x17, 0xf8, 0xbd, 0xe1, 0x49, 0xf1, 0x2a, + 0x07, 0xe4, 0xf7, 0xf3, 0x05, 0x07, 0xe7, 0x4c, 0x55, 0xef, 0x10, 0x21, 0x05, + 0x1f, 0xdf, 0xfa, 0x72, 0xf8, 0xd8, 0x33, 0xf3, 0xc4, 0x08, 0x19, 0x59, 0xe3, + 0xfb, 0x14, 0x33, 0xff, 0x7f, 0xe5, 0x1a, 0x08, 0xd3, 0xca, 0x3b, 0xdd, 0x0f, + 0x22, 0xd1, 0x28, 0x0f, 0x06, 0xf3, 0xd6, 0x14, 0x12, 0x3b, 0x24, 0x7f, 0xab, + 0xd6, 0xf2, 0xef, 0xd2, 0xb9, 0x41, 0x16, 0xfc, 0xd8, 0xfe, 0xfa, 0xe0, 0x11, + 0x30, 0x4c, 0x34, 0xff, 0xf8, 0x1d, 0x47, 0x7f, 0xe0, 0xee, 0xd6, 0x20, 0xe0, + 0xbb, 0xee, 0x3c, 0x15, 0xd8, 0xcd, 0x04, 0x17, 0x1b, 0xbd, 0x4c, 0x39, 0x47, + 0x50, 0xcb, 0xe2, 0xfa, 0xd0, 0x28, 0xf3, 0xb9, 0xcb, 0xd4, 0x1c, 0xe8, 0x7e, + 0x60, 0xcb, 0xc7, 0xd3, 0xdf, 0x3c, 0x06, 0xff, 0xaf, 0xcc, 0x02, 0x4a, 0xe4, + 0x1e, 0xd9, 0xe2, 0x81, 0x2e, 0xdf, 0x24, 0xeb, 0x50, 0xd3, 0x00, 0xb3, 0xd1, + 0xc5, 0x20, 0xda, 0x18, 0x13, 0x37, 0x7f, 0x1e, 0x12, 0x12, 0x14, 0xdf, 0x03, + 0xed, 0x31, 0xc1, 0xd4, 0x29, 0xc1, 0xdf, 0xeb, 0xd1, 0xea, 0x1b, 0x1a, 0x01, + 0xf4, 0x08, 0x03, 0xed, 0xf7, 0x23, 0xea, 0x16, 0xf8, 0xf8, 0xfb, 0x08, 0xc9, + 0xc7, 0xf8, 0x12, 0x25, 0x0b, 0x0f, 0xf5, 0x7f, 0x19, 0x1f, 0xd8, 0xaf, 0x19, + 0x06, 0x12, 0xff, 0x21, 0xe3, 0xfd, 0xee, 0xf8, 0xed, 0x00, 0xea, 0x30, 0x11, + 0xfb, 0x41, 0x41, 0x04, 0xf5, 0xad, 0xe3, 0xe4, 0x11, 0x33, 0x05, 0xd5, 0xfe, + 0x5a, 0x59, 0x1a, 0x0a, 0xdd, 0x72, 0x20, 0xbc, 0x07, 0xe3, 0xf5, 0xf6, 0xd7, + 0x2e, 0x7f, 0x0c, 0xba, 0xe6, 0xb0, 0x15, 0x32, 0x12, 0x8e, 0xee, 0xc4, 0x16, + 0x29, 0xf5, 0xc7, 0x3a, 0xd3, 0x7f, 0xfd, 0xea, 0x74, 0xbd, 0xbf, 0xe8, 0xcf, + 0x00, 0x1c, 0xff, 0xf9, 0xde, 0x7d, 0xfe, 0xfe, 0xfa, 0xdd, 0xee, 0xd4, 0xa6, + 0x24, 0xc6, 0xe9, 0x99, 0x81, 0xfa, 0x4d, 0xa9, 0x4e, 0x4f, 0xd7, 0x30, 0xe8, + 0xe4, 0x19, 0x00, 0x0f, 0x2a, 0x1e, 0x08, 0xa3, 0x05, 0xb9, 0x10, 0x59, 0x54, + 0xf2, 0xdc, 0xaf, 0xe0, 0x17, 0x7f, 0xba, 0xfd, 0x13, 0xe6, 0x2e, 0xdd, 0xce, + 0x13, 0xed, 0xd4, 0xef, 0x1a, 0xe8, 0xf4, 0x17, 0x3a, 0x01, 0x4c, 0xe8, 0xf7, + 0x77, 0xc0, 0x15, 0xbb, 0x04, 0x51, 0x06, 0xe6, 0xf1, 0xee, 0xfa, 0x18, 0x3e, + 0x24, 0xd3, 0x07, 0xcd, 0xd0, 0xf1, 0xf3, 0x21, 0xd9, 0x0f, 0xdf, 0x9e, 0x16, + 0xea, 0xde, 0x31, 0x32, 0xed, 0xf4, 0x03, 0x1a, 0xd2, 0x7f, 0xdc, 0x0b, 0xee, + 0x1c, 0x0c, 0x0d, 0x22, 0xdd, 0xbc, 0x96, 0x46, 0xde, 0xc5, 0x4c, 0x22, 0xbc, + 0x0e, 0x57, 0x1c, 0x23, 0x74, 0xf8, 0x81, 0x87, 0x22, 0x2a, 0x28, 0x31, 0xc8, + 0xdb, 0x12, 0x47, 0x13, 0xf1, 0x35, 0x37, 0xb7, 0xd6, 0xb7, 0x15, 0x01, 0xf2, + 0x0d, 0x60, 0xdf, 0x04, 0x06, 0x27, 0x77, 0x04, 0x5f, 0xf5, 0xcd, 0xea, 0xf3, + 0xb1, 0x56, 0xae, 0x81, 0xef, 0xeb, 0x12, 0x1a, 0x74, 0x4a, 0x25, 0x14, 0x8e, + 0x46, 0x22, 0x13, 0xfc, 0x23, 0xee, 0xf1, 0x0c, 0xd2, 0xf0, 0xfb, 0xf3, 0xeb, + 0xf4, 0x09, 0xdf, 0xcc, 0xdf, 0xf9, 0x2e, 0x03, 0x7f, 0x21, 0xf0, 0x1f, 0xfc, + 0x9a, 0x2f, 0xd9, 0x03, 0xfa, 0x0a, 0xbf, 0x56, 0x1b, 0x0e, 0xfd, 0xda, 0xf8, + 0x19, 0xb6, 0x36, 0xdc, 0xa4, 0xda, 0xe2, 0xf1, 0x33, 0xe8, 0xa1, 0x29, 0xe9, + 0xf8, 0xcd, 0x1e, 0x6a, 0x7f, 0x0a, 0xfe, 0xee, 0x35, 0xed, 0x51, 0x0a, 0xec, + 0xf2, 0xed, 0xfc, 0xf9, 0xe4, 0xff, 0x19, 0x1f, 0x12, 0xb0, 0x24, 0xfb, 0xe6, + 0xe4, 0x03, 0x24, 0xbc, 0x01, 0xf3, 0xdd, 0xea, 0x03, 0xd5, 0x1a, 0x0c, 0x10, + 0xd4, 0x4c, 0x02, 0x7f, 0xc3, 0x05, 0x21, 0xdd, 0x00, 0x1d, 0xc9, 0x01, 0x02, + 0x14, 0xfa, 0x21, 0x4c, 0xeb, 0xa4, 0xe0, 0x20, 0x81, 0x12, 0x45, 0x8f, 0x11, + 0xc2, 0xf0, 0xe9, 0x23, 0xb2, 0x01, 0x12, 0x45, 0xf6, 0x09, 0x82, 0x2b, 0xec, + 0x2e, 0x27, 0x8d, 0x2f, 0x93, 0xb8, 0x3c, 0xa5, 0x45, 0x41, 0xdc, 0x5f, 0x1a, + 0x1f, 0xd3, 0x7f, 0x66, 0xdd, 0xfe, 0xfa, 0x37, 0x3e, 0xdb, 0x04, 0xd7, 0xfa, + 0xdf, 0xc2, 0x99, 0x17, 0x0a, 0xba, 0x55, 0xdd, 0xe2, 0x6e, 0xc0, 0xce, 0xd5, + 0xbf, 0x13, 0xc3, 0xbb, 0x4f, 0xb3, 0xfb, 0xb8, 0xbc, 0x0b, 0x42, 0x2d, 0x53, + 0x23, 0x92, 0x0a, 0xc3, 0xe6, 0xb7, 0xaf, 0xf1, 0x25, 0x32, 0x0e, 0x81, 0x38, + 0xf1, 0x0c, 0xff, 0xd0, 0x46, 0x33, 0xc4, 0xf7, 0xb8, 0xb2, 0xfb, 0x0e, 0x0f, + 0xf2, 0xd7, 0x5e, 0xcc, 0x11, 0xc0, 0x1c, 0xeb, 0x09, 0x7f, 0xf8, 0xf6, 0xf3, + 0xff, 0x2c, 0x0d, 0xc7, 0xf3, 0x27, 0xd0, 0x11, 0x2e, 0x47, 0x4b, 0xba, 0xd7, + 0x05, 0xe5, 0xfd, 0x59, 0xe5, 0x1d, 0xdc, 0x19, 0xd0, 0x2d, 0xb9, 0xa4, 0xe1, + 0xc4, 0x97, 0x28, 0xee, 0x0f, 0xf1, 0x7f, 0xdb, 0x07, 0xf3, 0xdf, 0xc4, 0xcd, + 0x34, 0xfa, 0xce, 0xb3, 0xd8, 0x13, 0xe4, 0xad, 0xef, 0x7f, 0xe6, 0x1c, 0x44, + 0xea, 0xe2, 0x19, 0x71, 0x93, 0xd5, 0x5a, 0xe2, 0x82, 0xb5, 0xac, 0x8d, 0x09, + 0xef, 0xbf, 0xdd, 0xef, 0xfd, 0xd9, 0xe3, 0xcf, 0xfc, 0xe0, 0xf1, 0x42, 0xfa, + 0x4a, 0xe9, 0x0c, 0xf3, 0x14, 0x02, 0x7f, 0x07, 0xc0, 0xf6, 0x06, 0xdc, 0xd8, + 0x23, 0xef, 0xfb, 0x15, 0xd6, 0xe0, 0xd6, 0xf6, 0xdf, 0x24, 0xed, 0xe6, 0xd6, + 0x2a, 0x08, 0x2e, 0xed, 0xf9, 0x61, 0xbd, 0xf3, 0x03, 0x23, 0xf6, 0x0e, 0xb2, + 0xea, 0x81, 0xfb, 0xcc, 0xe1, 0xe8, 0x9c, 0xe4, 0xf5, 0xfc, 0xe3, 0xf7, 0x20, + 0xd8, 0xe2, 0x01, 0xa7, 0x2f, 0x8a, 0x15, 0xd4, 0x3f, 0x4c, 0x81, 0x8c, 0x97, + 0xd7, 0xdb, 0x3f, 0x52, 0x84, 0xee, 0xfa, 0xd4, 0x04, 0x14, 0x07, 0xca, 0xc7, + 0xec, 0xe9, 0xce, 0xd8, 0x3b, 0x04, 0xee, 0x92, 0xe9, 0x04, 0xd2, 0x40, 0x66, + 0xcd, 0xc8, 0xff, 0xe5, 0xf3, 0xad, 0xbf, 0x46, 0xc4, 0xf4, 0x47, 0xf6, 0x00, + 0x58, 0x7f, 0xd9, 0xe8, 0x25, 0xf2, 0x04, 0xe4, 0xc1, 0xc3, 0xff, 0x10, 0xe8, + 0x55, 0x07, 0x2b, 0xf6, 0x13, 0x3b, 0xf9, 0xe9, 0xfd, 0x21, 0xd4, 0x1d, 0xf8, + 0x04, 0xcd, 0xff, 0x7f, 0x1d, 0x14, 0x01, 0x14, 0x1f, 0x0c, 0x5d, 0x17, 0xa9, + 0x49, 0x08, 0xfa, 0x16, 0x03, 0x50, 0x19, 0x04, 0xdb, 0xde, 0x31, 0x2c, 0xe3, + 0xfd, 0x1c, 0x18, 0x00, 0xf2, 0x13, 0x2f, 0xf5, 0xef, 0xb4, 0xde, 0xdb, 0x81, + 0x14, 0xe9, 0xdf, 0xeb, 0xf2, 0xf7, 0xe4, 0xfe, 0xfc, 0xec, 0xf7, 0x04, 0xf5, + 0x27, 0xd2, 0x7f, 0x0d, 0x1c, 0x2e, 0x0d, 0xee, 0xda, 0xfc, 0xec, 0x12, 0xfc, + 0x22, 0xf2, 0xf1, 0xe1, 0xde, 0xdf, 0x0c, 0xe9, 0xce, 0xf5, 0xe6, 0xfe, 0xe8, + 0xc2, 0x0c, 0x15, 0xeb, 0x07, 0x09, 0xf5, 0xc2, 0x1d, 0x07, 0x21, 0x10, 0xee, + 0x29, 0xc1, 0x00, 0x62, 0xf3, 0xe5, 0xd1, 0x06, 0xf3, 0x13, 0x7f, 0x2a, 0x12, + 0x01, 0xe5, 0x00, 0xf0, 0xf5, 0x06, 0x09, 0xc3, 0xb9, 0xd5, 0x03, 0x0e, 0xf9, + 0x01, 0x39, 0x0d, 0x10, 0x05, 0x46, 0x7f, 0xc6, 0xee, 0x25, 0xe3, 0x4d, 0xeb, + 0xfd, 0xf4, 0x09, 0x28, 0xb0, 0xea, 0xb0, 0xdf, 0xd4, 0x03, 0x04, 0xed, 0xdf, + 0xe0, 0x01, 0x18, 0xdd, 0x08, 0xfa, 0x14, 0x08, 0xf4, 0xff, 0x1e, 0xc8, 0x7f, + 0x1c, 0xdc, 0x02, 0x1b, 0xbd, 0x46, 0xea, 0x10, 0x1a, 0x2d, 0x0b, 0x21, 0x08, + 0x1d, 0x10, 0xaf, 0xc3, 0x2c, 0xd8, 0xc2, 0x1d, 0x03, 0xcf, 0xe8, 0x17, 0x20, + 0x09, 0xe5, 0x26, 0x3d, 0x1a, 0xdc, 0xf4, 0xfd, 0xcc, 0xdc, 0xb1, 0xc9, 0x02, + 0xff, 0x12, 0xda, 0x36, 0xd2, 0xcc, 0x01, 0xfe, 0x20, 0x7f, 0x11, 0x21, 0x0a, + 0x6c, 0xef, 0x1b, 0xd9, 0x20, 0x19, 0x18, 0x05, 0x23, 0x0d, 0xbe, 0x3c, 0xf6, + 0xcc, 0xec, 0xc4, 0xd6, 0xd5, 0xd0, 0x81, 0xd2, 0xd4, 0x37, 0xca, 0x1d, 0xc3, + 0xd4, 0x0e, 0x23, 0xee, 0x4f, 0xd4, 0x09, 0xe1, 0x92, 0xfc, 0xf4, 0x0f, 0x18, + 0xfc, 0xf4, 0x07, 0x28, 0x3a, 0xfd, 0xee, 0xd9, 0xc8, 0x02, 0xb7, 0x05, 0x1a, + 0xd7, 0x2c, 0xb8, 0xd5, 0x52, 0x1c, 0xc7, 0x1a, 0xe0, 0x01, 0x81, 0xe1, 0xd9, + 0x3c, 0xdb, 0xde, 0x10, 0x2d, 0xd2, 0xed, 0x00, 0xfe, 0xf9, 0xec, 0xec, 0xf6, + 0xa6, 0x01, 0x1f, 0x11, 0x03, 0x81, 0xde, 0x4d, 0xe3, 0x18, 0x34, 0xe0, 0xe9, + 0x14, 0x0c, 0xfa, 0xdb, 0x0e, 0xe1, 0x0a, 0xf6, 0xe2, 0xb9, 0xb2, 0x45, 0x5b, + 0xa8, 0x98, 0x2a, 0x43, 0x81, 0x54, 0x84, 0xd9, 0x06, 0xdf, 0x05, 0xec, 0xc9, + 0xc6, 0xd8, 0xd0, 0x3f, 0x24, 0x5e, 0xeb, 0xf9, 0x01, 0x0c, 0xa4, 0xa1, 0x12, + 0xd3, 0xd6, 0x3f, 0x3b, 0x01, 0x03, 0xdd, 0xf6, 0xc7, 0xc0, 0xdf, 0x01, 0xf1, + 0xfe, 0xeb, 0x28, 0x1d, 0xf1, 0x07, 0x3c, 0xc6, 0x16, 0x5c, 0x7f, 0xe3, 0x1f, + 0x26, 0xf8, 0xd6, 0x33, 0xe7, 0x6f, 0xe7, 0x9a, 0xbb, 0xe8, 0xf6, 0x01, 0xcc, + 0xf8, 0x03, 0xcd, 0x1c, 0x16, 0xda, 0xe1, 0xed, 0x17, 0x27, 0xc3, 0x2b, 0x26, + 0xf8, 0x18, 0xf6, 0x02, 0xf5, 0xe6, 0xfa, 0x09, 0xf5, 0xeb, 0x26, 0x81, 0x27, + 0xf2, 0xe2, 0x00, 0x0f, 0xe6, 0xce, 0xef, 0xf0, 0xfb, 0x25, 0x18, 0xe0, 0xee, + 0xf1, 0x7f, 0x1e, 0x11, 0xd9, 0xd8, 0xfa, 0x15, 0xd3, 0x02, 0xee, 0xfc, 0xe8, + 0x2d, 0x06, 0x0f, 0x4f, 0x02, 0xe9, 0xf6, 0x04, 0x0d, 0xdd, 0xed, 0x05, 0xe3, + 0xe7, 0xca, 0x02, 0xfa, 0xe8, 0x22, 0x1b, 0x55, 0xf0, 0xc9, 0xe2, 0x0f, 0x0e, + 0xf1, 0xa2, 0xc1, 0xbd, 0xcf, 0x16, 0xc9, 0x7f, 0x24, 0xfc, 0xf1, 0xda, 0x18, + 0x10, 0x18, 0xfa, 0x11, 0x33, 0x03, 0xdc, 0xe6, 0xe1, 0x1b, 0xa2, 0xd5, 0x23, + 0xdb, 0xf6, 0xdf, 0xcf, 0x24, 0xff, 0xdf, 0x7f, 0x16, 0xd3, 0xf7, 0xf5, 0xd0, + 0xb0, 0x05, 0x0d, 0x0b, 0x15, 0xb2, 0xed, 0xd6, 0x54, 0xfd, 0xff, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x2f, 0xe7, 0xff, 0xff, 0x82, 0x23, 0x00, + 0x00, 0xe2, 0xff, 0xff, 0xff, 0x05, 0xfc, 0xff, 0xff, 0x10, 0xfe, 0xff, 0xff, + 0xcb, 0x05, 0x00, 0x00, 0x3c, 0x2d, 0x00, 0x00, 0x97, 0x48, 0x00, 0x00, 0xb1, + 0xfb, 0xff, 0xff, 0x0d, 0xfc, 0xff, 0xff, 0xc7, 0xfe, 0xff, 0xff, 0x9c, 0xfa, + 0xff, 0xff, 0x73, 0xff, 0xff, 0xff, 0x5d, 0xf4, 0xff, 0xff, 0xe8, 0xfb, 0xff, + 0xff, 0xe8, 0xfc, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, 0x68, 0x30, 0x00, 0x00, + 0x88, 0xfc, 0xff, 0xff, 0x88, 0x3f, 0x00, 0x00, 0x2f, 0x35, 0x00, 0x00, 0x29, + 0x2b, 0x00, 0x00, 0x37, 0xff, 0xff, 0xff, 0xf2, 0x27, 0x00, 0x00, 0xae, 0xf3, + 0xff, 0xff, 0x8c, 0xfd, 0xff, 0xff, 0xdf, 0x16, 0x00, 0x00, 0x5d, 0x42, 0x00, + 0x00, 0x87, 0xec, 0xff, 0xff, 0xb2, 0x29, 0x00, 0x00, 0x7d, 0x23, 0x00, 0x00, + 0x5e, 0xfb, 0xff, 0xff, 0x31, 0xfb, 0xff, 0xff, 0x11, 0x3d, 0x00, 0x00, 0x69, + 0x05, 0x00, 0x00, 0xd5, 0x41, 0x00, 0x00, 0x35, 0xff, 0xff, 0xff, 0xca, 0x0c, + 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x19, 0xe9, 0xff, + 0xff, 0xc0, 0xf7, 0xff, 0xff, 0x11, 0x07, 0x00, 0x00, 0x05, 0xfe, 0xff, 0xff, + 0x3c, 0x34, 0x00, 0x00, 0x48, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x58, + 0x4a, 0x00, 0x00, 0xe3, 0xf2, 0xff, 0xff, 0x61, 0xf7, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf2, 0xf4, 0xff, 0xff, 0xd6, 0xff, 0xff, 0xff, 0x66, 0xef, 0xff, + 0xff, 0x7b, 0x3c, 0x00, 0x00, 0xa2, 0x2e, 0x00, 0x00, 0xb3, 0x12, 0x00, 0x00, + 0x59, 0x1f, 0x00, 0x00, 0x3f, 0x33, 0x00, 0x00, 0x3c, 0xfe, 0xff, 0xff, 0x1c, + 0x15, 0x00, 0x00, 0x14, 0x34, 0x00, 0x00, 0x09, 0x26, 0x00, 0x00, 0x64, 0x20, + 0x00, 0x00, 0xe2, 0x55, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0xf3, 0x32, 0x0b, 0x24, 0xff, 0x39, 0x14, 0xfe, 0x1c, 0x2f, 0xe1, 0x1e, + 0x0b, 0xd4, 0xb6, 0xcf, 0x31, 0xf6, 0x7f, 0xec, 0x48, 0xd7, 0x4a, 0xdd, 0x34, + 0x48, 0xe2, 0xcb, 0x26, 0x1f, 0x01, 0xbb, 0xe2, 0x1a, 0x1e, 0xd3, 0xfd, 0xc7, + 0xa4, 0xe3, 0x10, 0x12, 0xdf, 0x45, 0xf6, 0xe0, 0x29, 0xe0, 0x71, 0xa6, 0x03, + 0x18, 0xb5, 0x21, 0xac, 0xf5, 0x12, 0x1e, 0x0e, 0x00, 0xf1, 0x0b, 0x0d, 0x25, + 0x7f, 0xe0, 0x2d, 0x0b, 0xc3, 0xf7, 0xd3, 0x48, 0x06, 0x07, 0xda, 0x09, 0xf3, + 0xc9, 0xba, 0x10, 0xcf, 0x00, 0xfc, 0x1c, 0x13, 0x1e, 0x08, 0x47, 0xe2, 0xd3, + 0xee, 0x11, 0x3a, 0xbd, 0x10, 0x43, 0xd7, 0x5d, 0x11, 0x15, 0xe7, 0x0d, 0x17, + 0xf9, 0x17, 0x23, 0x18, 0xf1, 0x1e, 0xfd, 0xe2, 0xcc, 0xf6, 0xf6, 0x1c, 0x01, + 0x26, 0xec, 0xf0, 0xec, 0xeb, 0xe2, 0x56, 0xf5, 0x21, 0x00, 0xf6, 0xc5, 0xf3, + 0x03, 0xf2, 0x19, 0xf4, 0x01, 0x0f, 0x31, 0xdc, 0xf4, 0x01, 0xdb, 0x3a, 0x81, + 0xd6, 0x17, 0x79, 0xec, 0xee, 0xfd, 0xe7, 0xe8, 0xfa, 0xf5, 0x06, 0xf7, 0x16, + 0x37, 0x04, 0xed, 0x1f, 0x21, 0xbd, 0x24, 0xf3, 0x44, 0xe6, 0x0d, 0x09, 0x24, + 0x01, 0xdc, 0x1a, 0x2a, 0xe3, 0xef, 0xee, 0x38, 0x10, 0x25, 0xed, 0x02, 0xe7, + 0x11, 0x08, 0xfd, 0xf1, 0x18, 0xf5, 0xe3, 0x26, 0x14, 0x2d, 0xf0, 0xe8, 0xfb, + 0x21, 0xff, 0x02, 0xf0, 0xf0, 0xfc, 0xe4, 0x07, 0x02, 0x1f, 0x17, 0xfd, 0x15, + 0x29, 0xd9, 0x1a, 0x16, 0x09, 0x09, 0x1f, 0x24, 0x19, 0xe8, 0x81, 0xed, 0xcd, + 0x29, 0x34, 0x12, 0xfb, 0x40, 0xd8, 0x11, 0x07, 0xd6, 0xf3, 0xfa, 0x06, 0xfe, + 0x3d, 0x2c, 0xdc, 0x1f, 0xee, 0xdc, 0x12, 0x38, 0x2f, 0x2a, 0xee, 0x02, 0xf5, + 0x05, 0x2e, 0x0d, 0x20, 0xf6, 0x0c, 0xe2, 0x20, 0x14, 0x00, 0xce, 0x12, 0xf3, + 0x1f, 0xd8, 0xc5, 0xce, 0x34, 0xfb, 0xe7, 0x0d, 0x1d, 0xa0, 0xe5, 0x4b, 0xf0, + 0x0c, 0x3c, 0xdf, 0x39, 0xfd, 0x28, 0x04, 0x0a, 0xff, 0x0b, 0x43, 0xf7, 0x40, + 0xe2, 0x17, 0x24, 0x48, 0xc6, 0x2f, 0xbd, 0x01, 0xdf, 0xe5, 0xee, 0x12, 0x52, + 0xc7, 0xab, 0x0b, 0x0d, 0x2b, 0x1a, 0xf2, 0x03, 0xd8, 0xe7, 0xfe, 0x27, 0xf4, + 0x2d, 0xfa, 0xc7, 0x25, 0x7f, 0xe7, 0x01, 0x2b, 0x9a, 0xfb, 0x5d, 0x32, 0xed, + 0xf9, 0xff, 0x7f, 0xf9, 0xf0, 0x2d, 0xd4, 0x07, 0xe5, 0x06, 0x15, 0x69, 0xf5, + 0xe1, 0xfe, 0x98, 0x95, 0x85, 0x75, 0xfc, 0xe9, 0x29, 0x7c, 0xe6, 0x0b, 0xd5, + 0x14, 0xfa, 0xd4, 0x12, 0x61, 0x39, 0xe9, 0x10, 0x24, 0x19, 0xcc, 0x1c, 0xf3, + 0xee, 0xa7, 0x59, 0xf1, 0x49, 0xe8, 0x15, 0xe5, 0x0a, 0x12, 0xca, 0x9f, 0x0a, + 0x0f, 0x23, 0x16, 0x24, 0xc3, 0x00, 0x17, 0xe4, 0xd0, 0xc4, 0x0f, 0x16, 0xf7, + 0xda, 0x13, 0xdf, 0x2e, 0xf4, 0x1e, 0xe7, 0xf3, 0x12, 0xe0, 0x27, 0xf4, 0xe8, + 0xff, 0x1c, 0x06, 0xf0, 0x04, 0x03, 0xf8, 0x7f, 0xe7, 0x51, 0xe3, 0xee, 0x08, + 0x20, 0xca, 0x05, 0xd1, 0xfd, 0xf0, 0xfa, 0xdb, 0xae, 0xca, 0x2a, 0x28, 0x0f, + 0x00, 0x92, 0x35, 0x2c, 0xe2, 0xfe, 0x02, 0xb0, 0x0d, 0x05, 0xce, 0xe7, 0xdb, + 0x02, 0xcf, 0xd9, 0xf1, 0xf9, 0x07, 0xf4, 0xe5, 0x1b, 0x40, 0xed, 0xd9, 0x21, + 0xce, 0xa6, 0xd3, 0x22, 0xf0, 0xf2, 0x1a, 0x40, 0xf7, 0x49, 0xdf, 0x17, 0xe3, + 0x28, 0x0a, 0x0f, 0xfa, 0xc6, 0xd0, 0x97, 0x12, 0x1d, 0xae, 0xd4, 0x37, 0x5e, + 0xa2, 0x03, 0x53, 0xc6, 0xdf, 0x9f, 0x3e, 0xe8, 0xb5, 0xf4, 0x14, 0x49, 0xf7, + 0x01, 0xe6, 0xec, 0xc4, 0x7f, 0x02, 0xee, 0x44, 0x4c, 0x2c, 0x25, 0xe5, 0xd2, + 0x20, 0x16, 0xeb, 0xee, 0xe1, 0xc3, 0x42, 0xde, 0x09, 0x27, 0xec, 0xf4, 0xf2, + 0xf0, 0x22, 0x13, 0x03, 0xfb, 0xd5, 0xca, 0x27, 0x28, 0xc9, 0x29, 0xf4, 0x06, + 0xf0, 0x11, 0xe4, 0xed, 0x01, 0x21, 0x06, 0xfe, 0xe4, 0xfa, 0x0c, 0x1f, 0xb6, + 0xf5, 0xda, 0x03, 0x02, 0x00, 0x05, 0xfc, 0xf4, 0x7f, 0x1e, 0xff, 0x0b, 0xfd, + 0xe4, 0xb8, 0xde, 0xbc, 0xe0, 0x4a, 0x2e, 0x01, 0xbf, 0x15, 0x20, 0x10, 0x20, + 0x11, 0x20, 0x1b, 0x28, 0xb9, 0x0b, 0xe9, 0xf1, 0xcf, 0x2c, 0x00, 0xdc, 0x4a, + 0x3e, 0x33, 0x0b, 0xdf, 0xa4, 0xe6, 0x14, 0xf4, 0xc4, 0xd1, 0xd4, 0x17, 0xec, + 0x16, 0x06, 0xda, 0xca, 0x7f, 0x15, 0xf9, 0xc8, 0xba, 0x33, 0xee, 0xae, 0xfc, + 0xe8, 0xbb, 0xfc, 0xe6, 0x24, 0x12, 0xe6, 0x05, 0xf5, 0xfb, 0x05, 0x0e, 0xc5, + 0x32, 0xe8, 0x04, 0xd1, 0x0a, 0xf2, 0xbc, 0x1b, 0x14, 0x15, 0xc5, 0xf9, 0xce, + 0xfd, 0x38, 0xfd, 0xeb, 0xe6, 0x7f, 0x23, 0x45, 0x08, 0xeb, 0xee, 0x3e, 0x26, + 0xf6, 0xd9, 0xbb, 0x0a, 0xa6, 0x1e, 0xd3, 0xea, 0x08, 0xf6, 0xcc, 0x0c, 0xe9, + 0x39, 0xea, 0x08, 0xe4, 0x04, 0x13, 0xfc, 0xf5, 0xe8, 0xe4, 0x05, 0xeb, 0x91, + 0xea, 0x19, 0x3c, 0xd0, 0xdd, 0xe0, 0x13, 0xfb, 0xf0, 0xe6, 0xc8, 0x3e, 0xef, + 0xeb, 0x13, 0x42, 0xc2, 0xf0, 0xdf, 0xe1, 0xe0, 0x0f, 0xf8, 0xfa, 0xc8, 0xc5, + 0xfb, 0x2a, 0x14, 0xee, 0x36, 0xdd, 0x0d, 0x01, 0xd2, 0xe5, 0xb1, 0x11, 0x09, + 0x59, 0x03, 0x16, 0xeb, 0x81, 0x24, 0xb4, 0xd6, 0x27, 0x02, 0x1d, 0x29, 0x66, + 0x0f, 0xa9, 0x35, 0x36, 0x99, 0x2a, 0x33, 0xfa, 0xce, 0xd7, 0xe1, 0xff, 0x06, + 0xfa, 0x2b, 0x05, 0xe9, 0xc4, 0xdf, 0x19, 0xee, 0xd1, 0xca, 0x0a, 0x44, 0x9e, + 0x09, 0xd4, 0x5d, 0x26, 0x26, 0xec, 0x6a, 0x32, 0x00, 0xf7, 0x59, 0xf9, 0x37, + 0xfb, 0xc9, 0x93, 0xe0, 0xf6, 0x03, 0xdd, 0x3f, 0x17, 0xf6, 0x10, 0xed, 0x00, + 0xcd, 0xf6, 0x90, 0xcb, 0x12, 0xe3, 0x3f, 0x01, 0x7f, 0x20, 0xfa, 0xfc, 0x15, + 0x02, 0x7d, 0xce, 0xe4, 0x04, 0x12, 0x04, 0x13, 0xcf, 0x1a, 0x21, 0xdf, 0x70, + 0xef, 0xf4, 0x12, 0xe1, 0x01, 0x29, 0x04, 0x37, 0xf1, 0x42, 0xf1, 0x9a, 0x0d, + 0x1e, 0x14, 0x05, 0x1d, 0x18, 0xde, 0x03, 0x06, 0xef, 0xed, 0xb3, 0xdf, 0x0d, + 0xec, 0x08, 0xb4, 0x01, 0x12, 0x0a, 0x48, 0xec, 0xd7, 0x7f, 0x04, 0x37, 0xde, + 0x4f, 0xd7, 0xd9, 0x21, 0xa5, 0x19, 0x0f, 0x0d, 0x16, 0xde, 0xe3, 0x3f, 0xcd, + 0x36, 0x2f, 0x34, 0x05, 0x4a, 0xb7, 0x22, 0x47, 0xf0, 0xeb, 0x07, 0x0a, 0x25, + 0xcc, 0x8d, 0xd5, 0xed, 0xc6, 0xce, 0xf1, 0xf9, 0x37, 0xbc, 0xed, 0x32, 0x08, + 0xbf, 0xe9, 0x0e, 0x9a, 0xe3, 0x0e, 0xe5, 0xe0, 0xd4, 0xca, 0xc8, 0xd5, 0xb2, + 0x3c, 0xd6, 0xe0, 0x0f, 0x19, 0x01, 0x02, 0xf1, 0xfc, 0xef, 0x22, 0xff, 0x1f, + 0xdf, 0x05, 0x23, 0x2a, 0xf2, 0x00, 0x48, 0xf9, 0x00, 0xf4, 0x69, 0x27, 0xef, + 0x00, 0x7f, 0x04, 0x2e, 0x2a, 0x2b, 0x0d, 0x35, 0xfa, 0xf1, 0x0b, 0xdd, 0x14, + 0x24, 0x17, 0x03, 0xfe, 0x27, 0x1f, 0x07, 0xe9, 0x13, 0xea, 0x5e, 0x05, 0xd5, + 0x04, 0xf1, 0x16, 0xf0, 0xf9, 0xd6, 0xe8, 0xe0, 0x00, 0x53, 0xec, 0xf7, 0x22, + 0xeb, 0xfd, 0x0a, 0xd3, 0x05, 0xf2, 0x43, 0x9c, 0xdf, 0xcc, 0x01, 0x00, 0x14, + 0xe4, 0xfa, 0xe3, 0x40, 0x0b, 0xa5, 0x05, 0xdb, 0x11, 0x26, 0x8b, 0x8f, 0x1d, + 0x6d, 0x01, 0xc9, 0xdb, 0xc0, 0x44, 0x19, 0x81, 0x14, 0xd1, 0x44, 0xfe, 0xcf, + 0x36, 0xed, 0xde, 0x19, 0xeb, 0xeb, 0xf8, 0x05, 0x3d, 0xf7, 0xd4, 0xcd, 0x3e, + 0x1b, 0x65, 0x72, 0x13, 0xd1, 0x59, 0x1a, 0x11, 0x28, 0x00, 0xd9, 0xd3, 0x12, + 0x08, 0x20, 0xd4, 0xf2, 0x17, 0x02, 0xf8, 0xf1, 0x06, 0x03, 0x36, 0xe4, 0xc5, + 0x16, 0x7d, 0xaf, 0x35, 0x2e, 0x19, 0xf2, 0x7f, 0x0e, 0x0e, 0xe4, 0xf8, 0xd9, + 0xf9, 0xf2, 0x0f, 0xfe, 0xc4, 0x41, 0x08, 0x07, 0xde, 0x42, 0xfe, 0xdd, 0x00, + 0x04, 0xfd, 0xe5, 0xda, 0x04, 0xea, 0x0b, 0x0f, 0x48, 0xf9, 0x07, 0x1c, 0x0e, + 0x16, 0xfc, 0xfb, 0x25, 0xf0, 0xcd, 0xfa, 0x03, 0x22, 0xec, 0x1b, 0xee, 0x20, + 0x13, 0xea, 0x00, 0xfc, 0xf8, 0x1d, 0x08, 0x1c, 0x7f, 0x37, 0x2f, 0x11, 0x03, + 0x36, 0xc8, 0xe2, 0xe8, 0x1b, 0x66, 0x12, 0x0c, 0x26, 0x91, 0x20, 0xe6, 0xff, + 0x2b, 0x5c, 0x02, 0xcb, 0x06, 0x28, 0x21, 0xfc, 0xee, 0x17, 0x18, 0xfd, 0xf6, + 0xde, 0x17, 0x44, 0x61, 0xfb, 0xf8, 0x20, 0xc2, 0x07, 0x1a, 0xfe, 0xe5, 0xd4, + 0x0b, 0x16, 0x29, 0x04, 0xec, 0x6b, 0x42, 0x1a, 0x22, 0x7f, 0x90, 0x00, 0xca, + 0x33, 0xd1, 0xa4, 0x09, 0xe9, 0x59, 0xbe, 0x01, 0x1b, 0xf3, 0x7d, 0x1a, 0xd2, + 0x2b, 0x0c, 0x04, 0x38, 0xca, 0x26, 0x38, 0x30, 0xc9, 0x2a, 0x7c, 0x12, 0xe5, + 0x02, 0x1e, 0x03, 0xe2, 0x07, 0xfd, 0xca, 0xf4, 0xd3, 0xc2, 0x4c, 0xeb, 0xca, + 0x47, 0x64, 0xe7, 0x0e, 0xfa, 0xc2, 0xf0, 0xfd, 0x9f, 0x3f, 0xca, 0x0c, 0xa7, + 0x47, 0x05, 0xee, 0x17, 0x0a, 0x0f, 0xf7, 0xcb, 0xfc, 0x3c, 0x58, 0x07, 0x18, + 0x36, 0xf6, 0x24, 0xeb, 0xf7, 0x17, 0xfc, 0xf4, 0xe9, 0xfb, 0x7f, 0x13, 0xf2, + 0xf9, 0xee, 0x06, 0xe6, 0xf9, 0xe9, 0xdb, 0xdb, 0x3a, 0xda, 0xd8, 0x0e, 0x0e, + 0x44, 0xd9, 0x10, 0x02, 0xfc, 0xfd, 0x2e, 0x15, 0xc2, 0x0e, 0x00, 0xf1, 0xdb, + 0xfe, 0x15, 0xfd, 0x0a, 0x00, 0xe7, 0x2d, 0x04, 0x19, 0xeb, 0xd1, 0xee, 0x28, + 0x22, 0xe3, 0xd9, 0xbc, 0xe1, 0x27, 0x05, 0xf4, 0x25, 0x2c, 0x0f, 0x31, 0x45, + 0x0d, 0x00, 0x13, 0xe6, 0x05, 0x0c, 0xe9, 0x16, 0xe3, 0xde, 0xaa, 0xfe, 0x76, + 0x1c, 0x26, 0xdb, 0x12, 0xf9, 0x18, 0xa3, 0x1d, 0x14, 0xdb, 0x0d, 0x03, 0xed, + 0x0c, 0x0a, 0x4c, 0x18, 0x2a, 0x38, 0x52, 0x33, 0xd3, 0xfe, 0xff, 0xd8, 0xfa, + 0xf2, 0x0f, 0x06, 0xee, 0x22, 0xee, 0x5b, 0x22, 0x07, 0xf8, 0x02, 0x63, 0x08, + 0xe0, 0x4e, 0xf6, 0xd7, 0x81, 0x59, 0xde, 0x08, 0x40, 0x0d, 0xd9, 0xf2, 0xf0, + 0x26, 0x81, 0x4c, 0x24, 0x34, 0xd1, 0x10, 0xd9, 0x13, 0x96, 0xda, 0xdb, 0x2e, + 0x07, 0xd4, 0xfd, 0x36, 0xcf, 0xcd, 0xd1, 0xd9, 0x06, 0xb7, 0xf1, 0x00, 0xeb, + 0x18, 0xd5, 0xdf, 0xf0, 0xd9, 0x3d, 0xd3, 0xaa, 0x10, 0x47, 0xf5, 0xfb, 0xde, + 0x59, 0xd3, 0x0c, 0x42, 0x1a, 0xf1, 0x28, 0xf7, 0x1e, 0xb8, 0xfc, 0xc0, 0xf0, + 0xea, 0xe2, 0x1e, 0xf4, 0xd4, 0xf2, 0x1b, 0xd6, 0xf5, 0xdd, 0xcf, 0x35, 0xd2, + 0xf8, 0x17, 0xf3, 0xd8, 0x3b, 0x25, 0x11, 0x0c, 0xb2, 0x2f, 0x07, 0xad, 0xff, + 0x28, 0xd2, 0x40, 0xf2, 0x99, 0xfe, 0xef, 0x22, 0xd5, 0x93, 0xca, 0x05, 0xe8, + 0xf9, 0x0d, 0x21, 0x0b, 0x0a, 0xdf, 0xde, 0xcc, 0x04, 0x81, 0x46, 0x25, 0x18, + 0x34, 0x0b, 0xfe, 0xe9, 0xec, 0xdd, 0xef, 0xe0, 0x3e, 0xf8, 0xcb, 0x1c, 0xe8, + 0xd0, 0xab, 0xcf, 0x29, 0xdd, 0x00, 0x12, 0x53, 0x03, 0x02, 0x1e, 0x14, 0x08, + 0x0a, 0x09, 0x75, 0x01, 0x21, 0x21, 0x34, 0x05, 0xce, 0x1e, 0xf8, 0xcf, 0x44, + 0x4c, 0x14, 0xed, 0xe0, 0x25, 0x26, 0x13, 0xfb, 0xd9, 0xf5, 0x0e, 0xf7, 0x47, + 0x3d, 0x27, 0x24, 0x3e, 0x07, 0x15, 0x27, 0x52, 0xfe, 0xfc, 0x0d, 0xee, 0xd1, + 0xea, 0xca, 0xc4, 0x4b, 0xee, 0xfb, 0x0f, 0x3a, 0x37, 0xa9, 0x0a, 0x55, 0x57, + 0xee, 0xec, 0x7f, 0x1e, 0x19, 0x32, 0x97, 0xdb, 0x1f, 0xb2, 0x3b, 0xe4, 0x7f, + 0x03, 0xe7, 0xec, 0xc4, 0xf6, 0xfc, 0x27, 0x51, 0x43, 0x02, 0xd0, 0xbb, 0x0b, + 0x2b, 0x9a, 0xf5, 0x44, 0xfe, 0xb5, 0x23, 0x35, 0xd2, 0x47, 0xca, 0x7b, 0xda, + 0xee, 0x0a, 0x35, 0x65, 0xb9, 0xb6, 0xdc, 0x41, 0xef, 0x1c, 0xed, 0x13, 0x50, + 0x03, 0xe8, 0x18, 0xef, 0xfe, 0x04, 0x16, 0xfc, 0x1f, 0x00, 0xf1, 0xbb, 0xf8, + 0x0f, 0x59, 0xc8, 0x09, 0xf0, 0x5a, 0x10, 0xbe, 0xf5, 0x16, 0x2c, 0xc7, 0x4d, + 0x15, 0x2b, 0xd6, 0xf2, 0x28, 0x38, 0xc9, 0x09, 0x27, 0xff, 0x26, 0xfa, 0xde, + 0x3c, 0x22, 0xf2, 0x07, 0xec, 0x0c, 0x43, 0x1a, 0x02, 0x1e, 0x3c, 0x03, 0xca, + 0xe3, 0xf2, 0xbe, 0xdc, 0x29, 0x0d, 0x81, 0x27, 0x02, 0x5b, 0x3d, 0xd6, 0xff, + 0x46, 0x47, 0xe8, 0x2b, 0xc3, 0xd7, 0xfd, 0xee, 0x5c, 0xe9, 0x3a, 0x12, 0x04, + 0xfb, 0xf1, 0x1b, 0x39, 0xf2, 0x20, 0xfe, 0xd7, 0xef, 0x0d, 0xf9, 0x13, 0xed, + 0x06, 0xf0, 0x31, 0xef, 0x0e, 0x0d, 0xdc, 0xe8, 0x12, 0x31, 0x02, 0xc5, 0xe7, + 0xda, 0x14, 0x10, 0xc5, 0xcb, 0xf3, 0xfb, 0xe3, 0x26, 0xf1, 0x03, 0xfe, 0x14, + 0xd0, 0xef, 0xe7, 0x7f, 0x0e, 0x03, 0x10, 0xd5, 0x01, 0xf6, 0xef, 0x02, 0x00, + 0x04, 0x36, 0xef, 0xd4, 0x0c, 0x16, 0x1f, 0xfe, 0xe7, 0xf2, 0xef, 0x0b, 0x07, + 0xef, 0xfa, 0xd9, 0x49, 0x11, 0x4c, 0xf3, 0x4e, 0x7f, 0xe9, 0xb6, 0xcc, 0xf8, + 0xe1, 0x19, 0xc1, 0x15, 0xbf, 0xc4, 0x14, 0xc0, 0x07, 0xcb, 0xbe, 0x70, 0xc2, + 0x3c, 0x12, 0xdd, 0x4f, 0x04, 0x06, 0xe1, 0xd2, 0x23, 0xdb, 0x22, 0xf9, 0xb4, + 0x00, 0x12, 0xd1, 0xae, 0x57, 0xf8, 0xf4, 0x37, 0x32, 0xea, 0xcd, 0xd6, 0xdd, + 0xd8, 0x1b, 0x0b, 0xbd, 0x41, 0x42, 0x35, 0xda, 0xd6, 0x10, 0x26, 0x22, 0xf5, + 0x0c, 0xe7, 0x02, 0x0a, 0xfc, 0xea, 0xfe, 0x56, 0xf8, 0x3b, 0xe6, 0x16, 0xbc, + 0x0c, 0x12, 0x08, 0x4a, 0xf7, 0x2e, 0xd5, 0x4c, 0x1c, 0xdc, 0xeb, 0x7f, 0xe7, + 0x1a, 0x05, 0x0b, 0xff, 0x0c, 0xf8, 0xab, 0x1b, 0xee, 0xcd, 0x00, 0x06, 0xd7, + 0x21, 0x1e, 0x50, 0xf0, 0x0f, 0x0b, 0xb7, 0x21, 0x12, 0xec, 0x0e, 0x19, 0x2e, + 0xf4, 0xd4, 0xe0, 0x4c, 0xfc, 0x26, 0xeb, 0xf0, 0x44, 0xb0, 0x43, 0xe3, 0xfc, + 0xf2, 0xf9, 0x19, 0xb7, 0xc9, 0x39, 0xd5, 0x1e, 0x06, 0x07, 0xeb, 0x02, 0xf3, + 0x1f, 0x81, 0x05, 0xb9, 0x30, 0xe4, 0xf2, 0xd3, 0x02, 0xdf, 0x10, 0x0e, 0xf9, + 0xf1, 0xd6, 0x05, 0x24, 0xe3, 0x03, 0xfa, 0xc7, 0x0f, 0xed, 0xff, 0xd0, 0xc3, + 0x05, 0x2b, 0xfa, 0x0b, 0xd4, 0x19, 0x4a, 0xe6, 0x4c, 0x16, 0xee, 0x14, 0xe9, + 0x0c, 0xae, 0xe9, 0xd8, 0xd1, 0xdc, 0xd4, 0x1a, 0xdf, 0xf5, 0xd5, 0x0e, 0xde, + 0xf6, 0xf7, 0xea, 0x05, 0x18, 0xef, 0xd5, 0x03, 0xce, 0xf3, 0x1b, 0xdb, 0x2d, + 0x10, 0x21, 0x3f, 0xf9, 0xdd, 0xd8, 0xe6, 0x0e, 0x12, 0x09, 0x07, 0xed, 0x0f, + 0x2c, 0x1b, 0x12, 0xee, 0x00, 0x05, 0x7f, 0xd6, 0x39, 0xd5, 0x4d, 0x38, 0x05, + 0xfe, 0x39, 0x21, 0x05, 0xfc, 0x48, 0x27, 0x04, 0xfc, 0xec, 0xf4, 0x0c, 0xce, + 0x26, 0xf6, 0xf8, 0xf7, 0x2b, 0x49, 0x18, 0x25, 0x1e, 0xff, 0xda, 0x2f, 0x56, + 0x0f, 0x2a, 0x4a, 0x24, 0xf0, 0xe4, 0x37, 0xe8, 0x0a, 0xa0, 0x21, 0xe5, 0x93, + 0xaa, 0x08, 0x0b, 0xa5, 0xff, 0xf1, 0x0f, 0xd4, 0x64, 0xe0, 0xd2, 0xbd, 0xf9, + 0x44, 0x43, 0xeb, 0xe5, 0x0e, 0x08, 0xdd, 0xe1, 0x2c, 0xee, 0x81, 0x45, 0xe6, + 0xdf, 0xd1, 0xa5, 0x65, 0xe1, 0x03, 0xeb, 0xfc, 0xf8, 0xe6, 0x0a, 0xed, 0xb5, + 0x20, 0xd5, 0xca, 0x3a, 0x2d, 0xf3, 0x1a, 0xf1, 0x3b, 0xd9, 0x9e, 0x0d, 0x4a, + 0xe3, 0xa9, 0xc8, 0x0c, 0x85, 0x25, 0xf0, 0x2b, 0xb5, 0xb7, 0xf3, 0xad, 0x2c, + 0x45, 0x57, 0xf8, 0x4a, 0xa0, 0xe3, 0x32, 0x22, 0xfc, 0x10, 0x03, 0x40, 0xe2, + 0xd4, 0xea, 0x05, 0xf2, 0x2f, 0x34, 0x81, 0xba, 0xbf, 0xef, 0xe8, 0x2b, 0x0e, + 0x3e, 0xb0, 0x44, 0x04, 0xa7, 0x2f, 0x20, 0x33, 0xfe, 0x3c, 0x41, 0x21, 0xbe, + 0xdc, 0xf9, 0x10, 0x15, 0xd8, 0x19, 0x47, 0xad, 0x2c, 0x0d, 0x2b, 0xf4, 0xfc, + 0x35, 0xbd, 0x2d, 0x0d, 0x36, 0x58, 0x22, 0x07, 0xee, 0x05, 0x7f, 0x15, 0xc5, + 0x17, 0x0c, 0xfd, 0xf6, 0xe3, 0x1d, 0x2f, 0xcc, 0x9a, 0x5a, 0x0d, 0x31, 0xc9, + 0x65, 0x0c, 0xdc, 0x2c, 0x3b, 0xe4, 0xfd, 0xe1, 0xa4, 0xf4, 0xfc, 0xeb, 0xc4, + 0xcc, 0xf3, 0x0c, 0x32, 0x33, 0x12, 0xf0, 0x27, 0xaf, 0xfa, 0xd6, 0xdd, 0x1b, + 0xcc, 0xcf, 0x41, 0x32, 0xef, 0xde, 0x18, 0x08, 0xe9, 0xc2, 0xaa, 0xbc, 0xf3, + 0xaa, 0x03, 0x2f, 0xf3, 0xc9, 0x81, 0xbb, 0x91, 0x19, 0x26, 0xfe, 0x07, 0xfc, + 0x17, 0xcb, 0xb3, 0x0d, 0xd6, 0x15, 0xa5, 0xf0, 0xc2, 0xbd, 0x34, 0x1e, 0xcf, + 0xf8, 0xdf, 0x19, 0xdc, 0xb4, 0xe8, 0xde, 0x8c, 0x10, 0xfa, 0x05, 0x3a, 0xe5, + 0xe5, 0x04, 0xce, 0x0e, 0xf2, 0xf5, 0x2d, 0x12, 0xf3, 0x00, 0x8a, 0x37, 0x15, + 0xd8, 0xa3, 0x35, 0x0a, 0x81, 0xbe, 0xfd, 0xfe, 0x2c, 0x35, 0xdd, 0xed, 0x32, + 0xb5, 0xed, 0x0d, 0x14, 0xe8, 0xd9, 0x3c, 0x31, 0x18, 0x09, 0xfe, 0x3a, 0x0b, + 0x1b, 0xfa, 0xe5, 0x22, 0x07, 0xcd, 0x38, 0xc6, 0xeb, 0x08, 0x7f, 0x0c, 0x5c, + 0xf5, 0x1a, 0xe5, 0xd2, 0xcf, 0xdb, 0x04, 0x5a, 0x0e, 0xe9, 0x35, 0x1b, 0xd1, + 0x23, 0xe6, 0xf8, 0xfc, 0xeb, 0x34, 0xdd, 0x49, 0xd6, 0x00, 0x47, 0xd4, 0x11, + 0x0b, 0xfa, 0x1d, 0x37, 0x18, 0xe8, 0x28, 0xeb, 0x47, 0xb3, 0xe4, 0x4c, 0x28, + 0xf9, 0x28, 0x3c, 0xea, 0xf9, 0xf2, 0xda, 0x1e, 0xc4, 0xfd, 0xc1, 0xd8, 0xf8, + 0xfd, 0x7f, 0xf1, 0x2d, 0xaf, 0xe2, 0x08, 0xe1, 0x33, 0x34, 0xe8, 0x1a, 0x3b, + 0xd5, 0xf7, 0xbd, 0x3b, 0x0e, 0x31, 0x03, 0x01, 0xbf, 0xe1, 0x51, 0x07, 0x08, + 0x49, 0xf8, 0x4b, 0xa5, 0x4b, 0x25, 0x27, 0xfe, 0xee, 0x07, 0xd7, 0xb5, 0xf3, + 0xd4, 0x51, 0xc3, 0x34, 0xd8, 0x29, 0xe4, 0x1a, 0xca, 0xbe, 0x1d, 0x14, 0x55, + 0x0f, 0xa0, 0xd0, 0xd7, 0x14, 0xa1, 0xc4, 0x61, 0xb4, 0xf0, 0xbd, 0xf3, 0xd6, + 0xf0, 0x81, 0x43, 0x2b, 0x20, 0xdf, 0xfc, 0x52, 0x2d, 0x35, 0xec, 0xd5, 0xe2, + 0x51, 0x4b, 0x29, 0xfc, 0x1c, 0xd7, 0x36, 0x12, 0xcc, 0x04, 0xee, 0xd5, 0xac, + 0x30, 0xd5, 0xe8, 0xfb, 0x18, 0xf1, 0xf2, 0x1a, 0xc2, 0x2b, 0x18, 0xae, 0xe0, + 0x9f, 0xcd, 0xbb, 0xec, 0x4d, 0x18, 0xc3, 0x7a, 0x3e, 0xba, 0x20, 0xf8, 0xe7, + 0xde, 0xd9, 0xbd, 0xe1, 0xc6, 0x73, 0x5b, 0x7e, 0xd5, 0x1e, 0xe9, 0xcd, 0xcd, + 0xd4, 0xc7, 0x00, 0x0e, 0x6a, 0xf7, 0x3d, 0xff, 0x11, 0x7f, 0x0e, 0x18, 0xcd, + 0x0b, 0x31, 0x3a, 0x49, 0x0a, 0xed, 0xdd, 0xf5, 0x1d, 0xbd, 0x3f, 0x29, 0x0b, + 0x0c, 0x07, 0xf6, 0x46, 0x15, 0xb6, 0xd2, 0x40, 0x4b, 0xc9, 0xee, 0x67, 0x40, + 0x44, 0x56, 0x4d, 0x0e, 0xda, 0xfc, 0xf3, 0xea, 0xf6, 0xfd, 0xff, 0x17, 0xf9, + 0xf9, 0x05, 0xd8, 0xf9, 0x05, 0x07, 0xee, 0xe0, 0x13, 0xf3, 0xc8, 0xf0, 0xab, + 0x0a, 0x41, 0x3d, 0xda, 0x9f, 0xf5, 0x04, 0x81, 0x14, 0x07, 0x09, 0xff, 0x24, + 0x0b, 0x0d, 0xee, 0xce, 0xf3, 0x0b, 0xfb, 0x02, 0x2d, 0xf0, 0x18, 0x1e, 0xf8, + 0xfb, 0xf4, 0xf5, 0x3c, 0x06, 0x15, 0xfd, 0xfb, 0xbe, 0x12, 0x01, 0x06, 0x10, + 0x0c, 0x29, 0xea, 0xf2, 0xf6, 0xfd, 0x1e, 0x2a, 0x15, 0xf7, 0xed, 0xbd, 0xd6, + 0x34, 0xe9, 0xfe, 0xc4, 0x43, 0x3a, 0xb2, 0x4f, 0xe7, 0xeb, 0x3d, 0xbc, 0x7f, + 0xe0, 0x33, 0x0e, 0x28, 0x27, 0xe5, 0xf0, 0x35, 0x19, 0xca, 0x10, 0xdc, 0xdc, + 0xb3, 0xf2, 0x06, 0x0a, 0xdf, 0x45, 0x31, 0x15, 0xf4, 0xb7, 0xf7, 0x10, 0xff, + 0xff, 0xd9, 0xe1, 0xe1, 0xd0, 0x0f, 0x03, 0x03, 0xfc, 0xfe, 0x0e, 0xc9, 0x17, + 0x21, 0xc9, 0xe4, 0xf8, 0x98, 0x08, 0xfe, 0x20, 0x5a, 0x1c, 0x3b, 0xfd, 0x00, + 0xe5, 0x27, 0x13, 0xc0, 0x45, 0x1f, 0xeb, 0xfb, 0xe2, 0x23, 0x0d, 0xd4, 0xeb, + 0xf4, 0x1a, 0x1b, 0x06, 0xe4, 0x1a, 0x2e, 0x4c, 0x1d, 0xea, 0x1e, 0xd8, 0x8f, + 0xfa, 0x3b, 0xdd, 0xe4, 0x2a, 0x0d, 0xf9, 0x02, 0xce, 0x07, 0x11, 0x18, 0xeb, + 0x1b, 0x21, 0xfd, 0x81, 0x09, 0x02, 0xf3, 0x0e, 0x19, 0xf0, 0x3d, 0xd0, 0xc9, + 0xfb, 0x72, 0x36, 0x24, 0x32, 0x15, 0x04, 0x12, 0x7f, 0x3a, 0x0d, 0x1a, 0x1d, + 0xe4, 0xf0, 0x07, 0x09, 0x0a, 0xff, 0x59, 0x18, 0xbf, 0xe9, 0x2b, 0xf2, 0xf0, + 0x29, 0x1e, 0xf1, 0x31, 0xc8, 0xe2, 0x4c, 0xf7, 0x6c, 0xf6, 0x51, 0x1c, 0xec, + 0x1b, 0x3a, 0x17, 0x08, 0xf7, 0x43, 0xec, 0xc4, 0xeb, 0x20, 0x2f, 0xe4, 0x26, + 0xf1, 0xfe, 0xd1, 0xfe, 0xe4, 0x69, 0xfb, 0x03, 0xd4, 0xf3, 0xbf, 0x44, 0xed, + 0x4c, 0xec, 0x10, 0x52, 0x0f, 0xc6, 0xf5, 0x24, 0x1c, 0xe7, 0xf3, 0xbc, 0x19, + 0x7f, 0xe4, 0x4c, 0x0d, 0x11, 0xf4, 0xeb, 0x14, 0xbb, 0x45, 0xe9, 0xce, 0x0d, + 0x0f, 0xc7, 0x1c, 0x12, 0xf0, 0x18, 0x06, 0x0f, 0xc2, 0xd6, 0xd0, 0xb9, 0x03, + 0x15, 0xe2, 0x18, 0x4f, 0x4d, 0x3b, 0x02, 0xd4, 0xe2, 0xfb, 0x2c, 0xe0, 0x1d, + 0x18, 0xc8, 0xf6, 0x29, 0x1c, 0xf1, 0xea, 0x20, 0x24, 0x8c, 0x1e, 0x05, 0x22, + 0x2a, 0x00, 0x11, 0xe4, 0x00, 0x17, 0x1d, 0xc5, 0x0e, 0x7f, 0xe6, 0xd0, 0xd4, + 0xee, 0x45, 0xd5, 0x26, 0xd7, 0xe4, 0xeb, 0x47, 0xf1, 0x6a, 0x1c, 0x26, 0x45, + 0x42, 0xeb, 0x06, 0x2e, 0xfc, 0xd5, 0xfa, 0xcb, 0x01, 0xf4, 0xc2, 0xe3, 0x0b, + 0x0a, 0xcd, 0x49, 0x01, 0x28, 0x19, 0xde, 0x86, 0xd8, 0x11, 0xfd, 0x1c, 0x25, + 0x2a, 0x1a, 0x05, 0x1c, 0xf5, 0x78, 0x34, 0x1e, 0xe7, 0x06, 0x1d, 0xe7, 0xcc, + 0xde, 0xfb, 0x02, 0xf2, 0x7f, 0x26, 0x08, 0xb7, 0xd6, 0xaa, 0x0c, 0xe8, 0x23, + 0x28, 0xfb, 0xef, 0x04, 0x0b, 0xd8, 0x02, 0xc1, 0xf0, 0x31, 0x2b, 0xe6, 0x1b, + 0xfe, 0x0c, 0x1a, 0xbe, 0xf9, 0x14, 0xef, 0xe2, 0xc8, 0xe0, 0xf2, 0x2a, 0x6d, + 0x0d, 0x15, 0xc3, 0xfe, 0x43, 0x2c, 0x12, 0xf4, 0x6a, 0x10, 0x1c, 0x28, 0xdf, + 0xf5, 0x15, 0xb1, 0xd7, 0x03, 0xea, 0xf3, 0x42, 0x9a, 0xec, 0xcb, 0x3e, 0xf3, + 0xc6, 0x69, 0x10, 0xf0, 0x14, 0xea, 0x17, 0x00, 0x6f, 0xe7, 0x81, 0xe9, 0x8b, + 0x0a, 0xd5, 0x62, 0x4c, 0x38, 0x57, 0x92, 0xb6, 0xeb, 0xe9, 0xe4, 0x63, 0xb3, + 0xfd, 0x00, 0x2e, 0x3f, 0x11, 0xee, 0xf3, 0x05, 0xdc, 0x88, 0x0c, 0x2c, 0x4c, + 0xd6, 0xf2, 0x06, 0x1c, 0xdc, 0x55, 0xeb, 0xfe, 0xb5, 0x0d, 0xa3, 0x07, 0x22, + 0xae, 0x3a, 0xd2, 0x79, 0x26, 0xf8, 0x3f, 0x26, 0x31, 0x2c, 0x29, 0x45, 0xfb, + 0x34, 0xfa, 0x6a, 0x38, 0xbc, 0xe0, 0x55, 0xfe, 0xf8, 0x21, 0xfb, 0xe9, 0xec, + 0x0b, 0xca, 0xd7, 0xbb, 0xff, 0x7f, 0xfc, 0x1b, 0xcf, 0xd5, 0x33, 0x54, 0xfc, + 0x0e, 0xd3, 0x25, 0xfc, 0x31, 0xc0, 0x4d, 0xe9, 0x09, 0x39, 0xc9, 0xe5, 0xf3, + 0xe3, 0x22, 0xf9, 0xf1, 0xb5, 0xff, 0x7f, 0xec, 0x46, 0x09, 0xfb, 0xdf, 0xc8, + 0xcf, 0x37, 0x35, 0x56, 0x17, 0xf2, 0xf9, 0xee, 0xe1, 0x04, 0xf6, 0xf9, 0xf0, + 0xc6, 0x1e, 0x04, 0xd9, 0x04, 0x31, 0x1d, 0xc3, 0x75, 0x58, 0x8a, 0x31, 0x2d, + 0x10, 0xa5, 0xd6, 0xee, 0x29, 0x8b, 0x39, 0xef, 0x24, 0x39, 0x01, 0x02, 0x44, + 0x21, 0xfa, 0xb2, 0x8a, 0x95, 0xe4, 0xde, 0xdd, 0xf4, 0xc8, 0xf1, 0x28, 0x23, + 0x64, 0xff, 0x3f, 0xcf, 0x81, 0x32, 0x01, 0x0f, 0xc6, 0xef, 0xc4, 0x0e, 0x01, + 0x3a, 0x29, 0xb0, 0xf4, 0xf9, 0x22, 0x16, 0xb9, 0x00, 0xd0, 0xf3, 0x1e, 0x57, + 0x03, 0x10, 0xea, 0x56, 0x22, 0xf1, 0x3d, 0x0a, 0x06, 0xd2, 0x9a, 0x67, 0x14, + 0xd6, 0x3e, 0xd7, 0xbf, 0xea, 0xf0, 0xd5, 0x32, 0xbe, 0x24, 0x01, 0x9e, 0x11, + 0xd0, 0x1e, 0x8e, 0xaa, 0xd1, 0xfa, 0xe8, 0xf4, 0x1d, 0x3b, 0x7f, 0x14, 0xe8, + 0xe0, 0xba, 0x06, 0xc1, 0xf7, 0x14, 0x98, 0x18, 0xa5, 0x0e, 0x48, 0x2f, 0xf5, + 0xc3, 0xca, 0xce, 0xf9, 0x3f, 0x28, 0xd5, 0x27, 0x2e, 0x19, 0xdd, 0x68, 0x1e, + 0x44, 0x03, 0x07, 0xe4, 0xe0, 0xf5, 0x40, 0xf7, 0x5f, 0xfc, 0xbf, 0x41, 0xf7, + 0x0a, 0x9e, 0x18, 0xda, 0xc8, 0x19, 0xdf, 0xfa, 0x2f, 0xe8, 0x07, 0xfa, 0xf0, + 0xee, 0xfa, 0xb9, 0x29, 0x06, 0xb1, 0xae, 0x08, 0x2f, 0xec, 0xf9, 0xfc, 0xdf, + 0xbe, 0x7f, 0xc3, 0x1b, 0x0f, 0x11, 0xd8, 0x32, 0xfd, 0xe8, 0xed, 0x0d, 0xbf, + 0xef, 0xee, 0x48, 0xf7, 0x02, 0xf8, 0xd9, 0xef, 0xf2, 0x2e, 0xee, 0x11, 0xea, + 0xfe, 0xd8, 0xf6, 0xc0, 0x30, 0xb4, 0x20, 0x12, 0x09, 0xf9, 0xcf, 0xe9, 0x09, + 0xca, 0xd6, 0x4e, 0x30, 0xf8, 0xea, 0xeb, 0x03, 0x81, 0xee, 0x34, 0xf6, 0xf8, + 0xf5, 0xda, 0x30, 0x05, 0x04, 0xf6, 0x11, 0x40, 0xee, 0xfc, 0x0a, 0xda, 0xea, + 0x13, 0x0d, 0x1e, 0x3e, 0x11, 0x2a, 0x0e, 0x09, 0x18, 0x31, 0xd9, 0xd1, 0x0a, + 0xe5, 0xd1, 0x53, 0x3a, 0xd5, 0xd5, 0x4c, 0x6d, 0x03, 0xde, 0x3a, 0xd3, 0x21, + 0x11, 0x81, 0x15, 0x40, 0x5b, 0xfc, 0x15, 0xb3, 0x14, 0x8e, 0x47, 0x3e, 0x8a, + 0xb0, 0x2a, 0x57, 0x40, 0xee, 0xc1, 0xf4, 0x2a, 0x0c, 0xef, 0xc0, 0xb6, 0x2e, + 0x74, 0x73, 0x1e, 0xf8, 0xe7, 0x1d, 0x8c, 0x6d, 0xf6, 0xec, 0x35, 0xc6, 0xf2, + 0xde, 0x0a, 0xc9, 0xcb, 0x07, 0x15, 0xe1, 0x1b, 0x47, 0x0f, 0xf0, 0xf1, 0xf9, + 0x0d, 0x1a, 0x41, 0x08, 0x58, 0x29, 0xf7, 0x0e, 0x1f, 0x50, 0xeb, 0xe7, 0x19, + 0x47, 0xf3, 0x3d, 0x0c, 0x21, 0xfd, 0x08, 0x09, 0xde, 0x7f, 0x15, 0xfd, 0xe5, + 0x29, 0x0c, 0x15, 0x02, 0xfa, 0xdd, 0xeb, 0x07, 0x26, 0x01, 0x16, 0x3e, 0x3d, + 0xda, 0xe0, 0xda, 0x1c, 0xde, 0xe1, 0x2b, 0xe7, 0xf8, 0x04, 0xc3, 0x21, 0xf7, + 0x6f, 0xd2, 0xf7, 0xd2, 0x55, 0xb7, 0xe6, 0x20, 0xf6, 0xf8, 0xd4, 0x3e, 0xe7, + 0x2e, 0x3b, 0xd7, 0xd8, 0xb3, 0x9e, 0xc1, 0xde, 0x37, 0x2f, 0xcb, 0xb9, 0x25, + 0xb1, 0xb7, 0xc9, 0x0a, 0xa2, 0x5f, 0x17, 0x82, 0xb1, 0xce, 0x19, 0x36, 0x26, + 0xba, 0x0c, 0x09, 0xea, 0xf1, 0xea, 0xda, 0x04, 0xf9, 0x18, 0xee, 0xb5, 0x9f, + 0xb4, 0xfc, 0xc9, 0x7f, 0x15, 0xe8, 0x05, 0xe4, 0x24, 0x22, 0xf0, 0xd7, 0xda, + 0x14, 0xde, 0x2b, 0x0e, 0x08, 0x9c, 0x4a, 0x03, 0xec, 0xea, 0xe4, 0xd1, 0x2f, + 0xc6, 0x4b, 0xd1, 0x7f, 0xf9, 0x0e, 0xe6, 0xd8, 0x2f, 0xe2, 0x7a, 0xb0, 0x2c, + 0xdf, 0xd2, 0xd2, 0xe3, 0x17, 0x21, 0xd4, 0x35, 0x1b, 0xf9, 0x26, 0xfb, 0x13, + 0x4e, 0xff, 0x01, 0x42, 0x07, 0xea, 0xc9, 0xe5, 0x34, 0x30, 0x20, 0xf6, 0xd2, + 0x13, 0x2c, 0xcb, 0x3d, 0xf8, 0x42, 0xcc, 0x1a, 0xf3, 0xeb, 0xe9, 0x37, 0x1c, + 0x17, 0x41, 0x03, 0xa7, 0x1a, 0x31, 0x35, 0xd2, 0xf7, 0xdb, 0xa2, 0x2b, 0x09, + 0xcd, 0xdc, 0x20, 0xfa, 0x0f, 0xed, 0x39, 0x11, 0x27, 0x12, 0xeb, 0x1b, 0x20, + 0xad, 0x19, 0xa5, 0x0c, 0xff, 0x64, 0xd3, 0xc7, 0xef, 0x1f, 0xe5, 0x44, 0xc1, + 0xdc, 0x10, 0x2e, 0xa8, 0x2e, 0xdf, 0xc7, 0xd2, 0xfb, 0x26, 0xc0, 0xe2, 0xf2, + 0x52, 0x28, 0xea, 0xfc, 0x8b, 0x3c, 0x29, 0x4b, 0x38, 0xaa, 0x7f, 0x0a, 0x3f, + 0x4b, 0xf3, 0xe0, 0xc9, 0xe4, 0x06, 0x16, 0xdf, 0xaa, 0xd1, 0xec, 0xf2, 0x28, + 0x23, 0x00, 0x1a, 0xeb, 0xe3, 0xb3, 0x3d, 0x49, 0x2a, 0xac, 0x1e, 0xea, 0x29, + 0xcb, 0xbe, 0x52, 0xe2, 0x07, 0xd8, 0xf1, 0x20, 0x32, 0xc4, 0x39, 0x12, 0x02, + 0xd5, 0xd2, 0xf3, 0xeb, 0xe9, 0x13, 0x3d, 0xec, 0x6c, 0x13, 0xf9, 0x10, 0x73, + 0xe0, 0xd9, 0xe0, 0xf7, 0x19, 0xec, 0xfd, 0xe7, 0x08, 0xca, 0x37, 0xe9, 0xfd, + 0xf5, 0x03, 0x23, 0x05, 0x7f, 0xd2, 0xf1, 0x02, 0xdd, 0xf8, 0xc4, 0xce, 0xd6, + 0xeb, 0xb1, 0x1e, 0x21, 0xfe, 0x1a, 0xfd, 0xd9, 0x0d, 0x0f, 0x7f, 0xcc, 0x51, + 0x0a, 0xfb, 0xf3, 0x21, 0xdf, 0x41, 0xf8, 0x04, 0x18, 0x08, 0x03, 0x05, 0x31, + 0x39, 0x1c, 0x74, 0xf5, 0x1a, 0x03, 0xe6, 0x35, 0x5c, 0x03, 0xee, 0x55, 0xbf, + 0xff, 0x3c, 0xe1, 0x1f, 0x0e, 0xf7, 0x2c, 0xec, 0x51, 0xbe, 0xc2, 0xee, 0xf3, + 0x15, 0x11, 0xeb, 0xf1, 0x37, 0x1d, 0x21, 0x7f, 0x01, 0x69, 0xe8, 0x0f, 0x20, + 0x1e, 0x57, 0x10, 0x54, 0xbf, 0xf8, 0xe4, 0x27, 0x22, 0x0e, 0xe2, 0xc7, 0x42, + 0x09, 0x07, 0xe7, 0x01, 0xbe, 0x10, 0x41, 0xdb, 0xdf, 0x39, 0xc9, 0x11, 0xde, + 0xd7, 0xf7, 0x0c, 0x1b, 0xd9, 0x1b, 0xe7, 0xde, 0xf9, 0xf6, 0xe8, 0x22, 0x3d, + 0xf8, 0x15, 0xfb, 0x79, 0xf3, 0x1c, 0xfc, 0x06, 0xcb, 0x09, 0x52, 0xfe, 0x2d, + 0x16, 0xf7, 0x09, 0xe5, 0x43, 0xe0, 0x48, 0xce, 0xed, 0x0e, 0xc1, 0xea, 0x32, + 0xc0, 0xe0, 0xd7, 0xf2, 0x77, 0x0d, 0x76, 0x18, 0xd6, 0xb5, 0x2a, 0xca, 0x61, + 0xe4, 0xe0, 0x01, 0xd9, 0xd1, 0xec, 0x19, 0xc4, 0x0d, 0x22, 0x00, 0xac, 0x25, + 0xb8, 0xe0, 0xea, 0x37, 0xc5, 0x07, 0xc5, 0xe0, 0xe1, 0x19, 0x7f, 0xaf, 0x23, + 0xf5, 0xed, 0xb7, 0x69, 0x26, 0xf1, 0x07, 0x32, 0xe8, 0x2d, 0xf1, 0x3e, 0x0b, + 0xdc, 0xf3, 0xff, 0x1b, 0x10, 0xee, 0x2f, 0x16, 0x2b, 0xc9, 0x37, 0xff, 0xec, + 0xcc, 0xcb, 0xf2, 0x23, 0xeb, 0x06, 0x1c, 0xc9, 0xf1, 0x33, 0xf2, 0x0a, 0x06, + 0xaf, 0xf6, 0x27, 0x09, 0x98, 0x06, 0xeb, 0xfa, 0x11, 0x02, 0xf6, 0x03, 0x24, + 0x66, 0xe1, 0x43, 0xcf, 0xdd, 0xf9, 0xd2, 0x1d, 0x49, 0xdc, 0xf9, 0x05, 0x7f, + 0xe6, 0x22, 0x0e, 0xe5, 0x10, 0xfa, 0xcc, 0x16, 0xda, 0x03, 0xcd, 0x05, 0x0a, + 0xdc, 0x0d, 0x1e, 0x0b, 0x00, 0x15, 0x08, 0x24, 0xf8, 0xfb, 0x2e, 0xac, 0x08, + 0xed, 0xd5, 0x4e, 0x2b, 0xd2, 0x20, 0x38, 0x31, 0x2b, 0xb9, 0xc9, 0xf1, 0x56, + 0xd2, 0xa7, 0xfd, 0x95, 0x55, 0x4d, 0xef, 0xe4, 0xce, 0xb3, 0xd6, 0xd2, 0x2b, + 0x19, 0xd2, 0xe8, 0x29, 0x1c, 0x05, 0xad, 0xd8, 0x81, 0x34, 0x2a, 0x39, 0x6e, + 0x7a, 0x30, 0x04, 0x05, 0xd5, 0x2c, 0xac, 0x0d, 0x1b, 0xb2, 0x06, 0x11, 0x06, + 0xc8, 0xe5, 0x3c, 0x29, 0x2c, 0xc9, 0xfb, 0x2d, 0x97, 0x2f, 0xc6, 0x40, 0x25, + 0x16, 0x2c, 0x1b, 0x1e, 0xd1, 0x1d, 0xdf, 0xf8, 0x6c, 0xd9, 0x16, 0x4a, 0x1c, + 0x1a, 0xea, 0xd5, 0xcb, 0xdd, 0x00, 0x04, 0xf0, 0xc0, 0x02, 0xfe, 0xf4, 0x2e, + 0x02, 0x46, 0xe0, 0xdf, 0xb2, 0x29, 0x17, 0xd4, 0xd7, 0x44, 0xdf, 0xfc, 0x07, + 0xee, 0x23, 0xff, 0x14, 0x1f, 0xdb, 0xb9, 0xa1, 0x04, 0xf1, 0x93, 0x01, 0xd9, + 0x82, 0x7f, 0xee, 0x65, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0xd8, 0x31, 0x7a, 0xbf, 0x55, 0x3c, 0x49, 0x68, 0xb3, 0xbd, 0x56, 0xe8, + 0xa8, 0xeb, 0x48, 0x81, 0xac, 0xd2, 0xdd, 0xbe, 0x4c, 0x93, 0x67, 0x4d, 0x48, + 0x95, 0x3b, 0x17, 0x3d, 0x7f, 0xe3, 0x22, 0x48, 0xe3, 0xbd, 0x52, 0xf6, 0x08, + 0x4e, 0xb2, 0x48, 0x36, 0xd1, 0x5b, 0x67, 0xab, 0xdd, 0xd9, 0x44, 0xdd, 0xe4, + 0x41, 0x29, 0xa9, 0x1b, 0x46, 0x81, 0x43, 0x60, 0x4a, 0x0f, 0x50, 0x61, 0x7f, + 0xcf, 0x5b, 0x7f, 0xb6, 0x74, 0x5b, 0x5e, 0x7f, 0x9b, 0x8e, 0x46, 0xb3, 0x91, + 0xe5, 0x7f, 0xca, 0xb0, 0x81, 0xc4, 0xbb, 0x73, 0xe7, 0x7f, 0x69, 0x6e, 0x81, + 0x5b, 0x32, 0x6f, 0x7e, 0xa6, 0x7f, 0x68, 0x97, 0xac, 0x61, 0xc6, 0xd1, 0x65, + 0xae, 0x66, 0xe8, 0x96, 0x7f, 0x72, 0x91, 0xb5, 0xd9, 0x4e, 0xb4, 0x43, 0x4c, + 0x7f, 0xd2, 0xe1, 0x5d, 0x12, 0x7f, 0x6b, 0x65, 0x27, 0x68, 0x74, 0xfa, 0xf6, + 0x35, 0x1f, 0xd8, 0x41, 0x13, 0x2c, 0x37, 0xf4, 0xb7, 0x0e, 0xc6, 0xd9, 0x1a, + 0x4b, 0x1a, 0xe9, 0xaf, 0xea, 0xd4, 0x3b, 0x52, 0x1b, 0x2c, 0x2b, 0xbd, 0x1c, + 0x2f, 0x2e, 0x18, 0xc1, 0x6d, 0x3a, 0xa3, 0xe3, 0x27, 0xc7, 0xca, 0x32, 0xd3, + 0x25, 0xdc, 0xad, 0x20, 0x17, 0xc9, 0xd4, 0xf8, 0x19, 0xea, 0x6b, 0x18, 0x40, + 0x0a, 0xd4, 0x23, 0x59, 0x51, 0x22, 0x2c, 0x20, 0x20, 0x29, 0x85, 0xaa, 0x60, + 0x73, 0x9e, 0x4d, 0x72, 0x5f, 0x6a, 0x86, 0xbe, 0x70, 0xc0, 0xb4, 0xa3, 0x5c, + 0xa7, 0x81, 0x25, 0x95, 0x81, 0x51, 0x99, 0x26, 0x5e, 0x7f, 0xb7, 0x48, 0x53, + 0x46, 0x6e, 0xbf, 0x35, 0x6c, 0xba, 0xa7, 0x7d, 0xbf, 0xc4, 0x51, 0x8d, 0x5e, + 0x7f, 0x97, 0x12, 0x6e, 0x87, 0xa1, 0x43, 0x59, 0xa7, 0x25, 0x59, 0xbe, 0x9a, + 0x60, 0x63, 0xb9, 0x0a, 0x5d, 0x4e, 0x46, 0x51, 0x69, 0x2e, 0x81, 0x7f, 0x7d, + 0x81, 0x7f, 0x7f, 0x7f, 0x64, 0x81, 0x81, 0x7f, 0x81, 0x81, 0x81, 0x69, 0x14, + 0x81, 0x27, 0x81, 0x91, 0x7f, 0x78, 0x1e, 0x7f, 0x5e, 0x91, 0x7f, 0x7f, 0x7f, + 0x58, 0x81, 0x77, 0x7f, 0x81, 0x81, 0x7f, 0x81, 0x9a, 0x7f, 0x81, 0x7f, 0x41, + 0x81, 0x63, 0x7f, 0x81, 0x81, 0x6a, 0x7f, 0x81, 0x78, 0x7f, 0x22, 0x81, 0x5b, + 0x7f, 0x48, 0x4c, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xd3, 0xcd, 0x40, 0x3d, 0xc6, + 0x4c, 0x1c, 0x3e, 0x20, 0xbe, 0xb5, 0x1a, 0xad, 0xb5, 0xda, 0x37, 0x4d, 0xda, + 0x07, 0xc3, 0xdd, 0x44, 0x7f, 0x0a, 0x3e, 0x19, 0xb3, 0x44, 0x45, 0x3c, 0xff, + 0xab, 0x4f, 0x3b, 0x91, 0xb1, 0x32, 0xba, 0xbc, 0x35, 0xc8, 0x2e, 0xab, 0xc9, + 0x46, 0x26, 0xbb, 0xcb, 0x3e, 0x39, 0xd5, 0x7f, 0x2c, 0xf4, 0xd5, 0x10, 0x2f, + 0x4f, 0x43, 0x3e, 0x43, 0x51, 0x33, 0x1f, 0xd4, 0xc5, 0x59, 0x16, 0xd0, 0x20, + 0x48, 0x18, 0x1b, 0xc6, 0xd8, 0x3c, 0xc2, 0xf8, 0xc6, 0x41, 0xfd, 0xc6, 0x2b, + 0xb9, 0xc5, 0x13, 0x95, 0xe2, 0x22, 0x32, 0x10, 0x1c, 0x3f, 0x1c, 0x09, 0xc3, + 0x12, 0x36, 0xf2, 0xcc, 0x4d, 0xaa, 0x81, 0x23, 0xbb, 0x28, 0x51, 0xc2, 0xbd, + 0xfe, 0xb7, 0xa6, 0x5c, 0x28, 0xcd, 0x3c, 0x24, 0xa7, 0xdd, 0x57, 0x25, 0xe8, + 0xbf, 0x23, 0x1c, 0x53, 0x18, 0x11, 0xc7, 0xaf, 0x57, 0x25, 0xb5, 0x2a, 0x35, + 0x2e, 0x02, 0xa9, 0xb4, 0x56, 0xaa, 0xaf, 0xa6, 0x2d, 0x2e, 0xb6, 0x43, 0xa7, + 0xd8, 0x1f, 0x65, 0xd6, 0x39, 0xf5, 0xf6, 0x36, 0x58, 0x25, 0xe9, 0xb1, 0x07, + 0x44, 0xb8, 0xae, 0x4c, 0xaa, 0xbe, 0x3e, 0xb4, 0x33, 0x40, 0xdd, 0xdb, 0xf1, + 0xc6, 0xb0, 0x7f, 0x39, 0xbf, 0x59, 0x40, 0xb8, 0x9e, 0x7f, 0x3e, 0x2d, 0xe4, + 0x3e, 0x4b, 0x61, 0x29, 0x19, 0xc7, 0xe3, 0x22, 0x0b, 0xeb, 0x12, 0x06, 0x1a, + 0x06, 0xca, 0xec, 0x1e, 0xea, 0xca, 0xc7, 0xf9, 0x30, 0xe7, 0x20, 0xc9, 0xfa, + 0x15, 0x28, 0x08, 0x20, 0xcc, 0x03, 0x23, 0x2e, 0x13, 0xfc, 0xe0, 0x06, 0x16, + 0xe1, 0xce, 0x2a, 0xe1, 0xdf, 0x2b, 0xf1, 0x14, 0xc8, 0x06, 0xf6, 0xf2, 0xe7, + 0xde, 0x44, 0x2b, 0xec, 0x38, 0x15, 0xcc, 0xda, 0x28, 0x1d, 0x0a, 0x07, 0x2e, + 0x26, 0x29, 0x14, 0x05, 0x22, 0x3a, 0x68, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0xd5, 0x4f, 0x00, 0x00, 0x93, 0xfe, 0xff, 0xff, 0x2a, + 0xf6, 0xff, 0xff, 0x5b, 0x51, 0x00, 0x00, 0x78, 0xfc, 0xff, 0xff, 0x1e, 0x01, + 0x00, 0x00, 0x43, 0xfe, 0xff, 0xff, 0xd9, 0xff, 0xff, 0xff, 0x2b, 0x3c, 0x00, + 0x00, 0xac, 0x31, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x43, 0x57, 0x00, 0x00, + 0xdf, 0x40, 0x00, 0x00, 0xe9, 0x56, 0x00, 0x00, 0x52, 0xe8, 0xff, 0xff, 0x43, + 0x14, 0x00, 0x00, 0xc8, 0x57, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x2f, 0x59, + 0x00, 0x00, 0xd4, 0x3f, 0x00, 0x00, 0x9f, 0xfe, 0xff, 0xff, 0x3c, 0xf5, 0xff, + 0xff, 0x2b, 0xf0, 0xff, 0xff, 0xac, 0xfb, 0xff, 0xff, 0x72, 0xea, 0xff, 0xff, + 0xeb, 0x65, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xc3, 0xff, 0xff, 0xff, 0x2a, + 0x01, 0x00, 0x00, 0x2b, 0x0f, 0x00, 0x00, 0x7f, 0x53, 0x00, 0x00, 0x43, 0x01, + 0x00, 0x00, 0x4f, 0xee, 0xff, 0xff, 0x26, 0x46, 0x00, 0x00, 0x18, 0x26, 0x00, + 0x00, 0x11, 0x02, 0x00, 0x00, 0xb7, 0x3c, 0x00, 0x00, 0xea, 0x34, 0x00, 0x00, + 0xcb, 0xfe, 0xff, 0xff, 0x20, 0x6c, 0x00, 0x00, 0x7a, 0xff, 0xff, 0xff, 0xdb, + 0xf7, 0xff, 0xff, 0xc3, 0x57, 0x00, 0x00, 0xde, 0xff, 0xff, 0xff, 0x46, 0xfd, + 0xff, 0xff, 0xd4, 0x40, 0x00, 0x00, 0xbf, 0x58, 0x00, 0x00, 0x62, 0x00, 0x00, + 0x00, 0x55, 0xf7, 0xff, 0xff, 0xe7, 0x65, 0x00, 0x00, 0x0b, 0xe4, 0xff, 0xff, + 0x36, 0x00, 0x00, 0x00, 0x95, 0x08, 0x00, 0x00, 0x4d, 0x56, 0x00, 0x00, 0x0c, + 0xf5, 0xff, 0xff, 0xac, 0xff, 0xff, 0xff, 0x58, 0xfb, 0xff, 0xff, 0xec, 0xf8, + 0xff, 0xff, 0x83, 0xf0, 0xff, 0xff, 0xa1, 0xe1, 0xff, 0xff, 0x43, 0xf8, 0xff, + 0xff, 0xfa, 0xff, 0xff, 0xff, 0x14, 0x02, 0x00, 0x00, 0x9f, 0x11, 0x00, 0x00, + 0x46, 0x69, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x35, + 0x0c, 0xc2, 0x04, 0x56, 0x1a, 0x14, 0x2f, 0x49, 0xe0, 0x11, 0x00, 0x14, 0xdf, + 0xfb, 0x14, 0x07, 0xed, 0x61, 0x4f, 0x08, 0x00, 0x29, 0xf1, 0xd7, 0x0d, 0x9d, + 0xb3, 0x0a, 0x36, 0x00, 0x81, 0x95, 0x0e, 0x01, 0x08, 0x18, 0xda, 0xeb, 0x46, + 0x21, 0x46, 0xc0, 0xe6, 0x35, 0x28, 0x2c, 0x00, 0x1d, 0xe5, 0xc1, 0xfa, 0x3f, + 0xd3, 0x0a, 0x12, 0x04, 0xf0, 0xd8, 0xe6, 0xce, 0x42, 0xfa, 0x0f, 0xe3, 0x04, + 0x7f, 0x1c, 0xea, 0xda, 0xbb, 0xde, 0xdb, 0xe1, 0x41, 0x33, 0xfd, 0x27, 0x42, + 0xd1, 0xc6, 0xe0, 0xe1, 0xed, 0x25, 0x0e, 0xf0, 0xfb, 0x13, 0x0c, 0x41, 0x15, + 0x4b, 0x20, 0x16, 0xae, 0x1a, 0xe9, 0xee, 0xf8, 0x17, 0xfc, 0x24, 0xb2, 0x0d, + 0xfd, 0x2a, 0x12, 0xbf, 0xf4, 0xe6, 0x41, 0xba, 0xe8, 0x4d, 0x0c, 0x61, 0xdd, + 0xff, 0xb4, 0xe5, 0xc5, 0x1f, 0xeb, 0xf8, 0xe1, 0xaf, 0x01, 0xf7, 0x15, 0xee, + 0xeb, 0xec, 0x08, 0xf5, 0xe4, 0xfe, 0xe1, 0xe8, 0xf2, 0x06, 0xd9, 0x11, 0xfa, + 0x17, 0x03, 0xea, 0x14, 0xef, 0x1b, 0xeb, 0x0b, 0xdb, 0xd0, 0x1b, 0x0d, 0x7f, + 0x13, 0x16, 0xf7, 0xcb, 0xe0, 0x16, 0x0d, 0xcb, 0xd6, 0x04, 0xdf, 0x31, 0x24, + 0xf8, 0x16, 0x51, 0xd1, 0xf5, 0x13, 0x09, 0xd7, 0xea, 0xf4, 0x10, 0x09, 0x12, + 0x21, 0x0d, 0xf7, 0xcd, 0xe8, 0xd6, 0x23, 0x1d, 0x2b, 0xd9, 0x01, 0x1d, 0x11, + 0xf3, 0x7f, 0x08, 0xf4, 0x06, 0x0d, 0x02, 0x09, 0xd8, 0xf1, 0x1b, 0x02, 0xe7, + 0x26, 0x14, 0xe3, 0xe3, 0xfd, 0x03, 0xf1, 0xf0, 0x1a, 0x25, 0xec, 0x07, 0xe7, + 0x1f, 0xf4, 0xd1, 0xb1, 0xea, 0x12, 0x06, 0x19, 0x30, 0xd5, 0x1e, 0xf5, 0xef, + 0x22, 0x09, 0xea, 0x1f, 0xff, 0xf4, 0xf7, 0x01, 0xf2, 0x1b, 0x0c, 0x16, 0x17, + 0x0e, 0xf7, 0xe2, 0xd4, 0x0e, 0xda, 0xd4, 0x1c, 0x01, 0x30, 0xe8, 0x14, 0xfb, + 0x1f, 0xc0, 0x2f, 0x2b, 0xf7, 0xd4, 0x4e, 0x81, 0x3d, 0x9f, 0x3d, 0x0f, 0x5c, + 0x0a, 0xdb, 0x28, 0xf6, 0xd3, 0x10, 0xd5, 0x03, 0x07, 0x8f, 0xba, 0x4b, 0x12, + 0xd6, 0xed, 0xdb, 0xfa, 0xe6, 0xea, 0xbf, 0x17, 0xd0, 0xde, 0x2a, 0x03, 0x10, + 0xeb, 0xea, 0x35, 0xeb, 0x1b, 0x08, 0x0a, 0x26, 0x23, 0xb9, 0x3c, 0x21, 0x0c, + 0xee, 0x00, 0x39, 0x09, 0x22, 0x92, 0xc8, 0xe7, 0xfe, 0x3d, 0xf7, 0x13, 0xf5, + 0xf1, 0x19, 0xfd, 0x16, 0xeb, 0x07, 0x0e, 0xdc, 0x24, 0x0f, 0xa6, 0x1d, 0xeb, + 0xd2, 0x39, 0x03, 0xd4, 0xf2, 0xdb, 0xdf, 0x1f, 0xd6, 0xf6, 0xf8, 0x0c, 0xb0, + 0xee, 0xfc, 0xee, 0xb3, 0xf3, 0xd4, 0xd4, 0xe5, 0xeb, 0x23, 0x19, 0xf4, 0x02, + 0xc4, 0x64, 0xee, 0x7f, 0x20, 0x0e, 0xf6, 0xfc, 0x0d, 0xde, 0x54, 0x13, 0x1c, + 0xf5, 0x05, 0x07, 0xe1, 0xf9, 0xfe, 0x1d, 0xeb, 0xb1, 0x31, 0xd3, 0x12, 0xbc, + 0x72, 0xe3, 0xd9, 0xbc, 0x2b, 0x04, 0x03, 0x69, 0x23, 0x38, 0xf5, 0xb1, 0x40, + 0x1b, 0x0c, 0xa8, 0xf9, 0xe6, 0xc6, 0xe6, 0x08, 0xe4, 0x74, 0x42, 0x1b, 0xcb, + 0xf0, 0x26, 0xf4, 0xed, 0x19, 0xf8, 0x0c, 0x12, 0x1d, 0xbf, 0xfa, 0x12, 0x50, + 0xeb, 0x22, 0x2e, 0x1e, 0x02, 0xeb, 0x7f, 0x91, 0xd6, 0xe6, 0xff, 0x15, 0x08, + 0xe2, 0xf7, 0x0a, 0x09, 0xfa, 0x12, 0x19, 0x02, 0xd3, 0xb4, 0xd9, 0xeb, 0xba, + 0x22, 0xe0, 0x05, 0x25, 0xec, 0xd9, 0xc4, 0xe7, 0xce, 0xea, 0xf0, 0x03, 0x42, + 0x58, 0x3a, 0xfb, 0xf9, 0x12, 0x2c, 0xdd, 0x4d, 0x5c, 0x2d, 0x32, 0xde, 0xe8, + 0x01, 0xfb, 0xcf, 0x14, 0xd1, 0xec, 0xe4, 0xf7, 0x23, 0xbc, 0xb4, 0xd6, 0xe7, + 0xef, 0x7f, 0xef, 0xa2, 0xc0, 0x2c, 0xe4, 0x07, 0xf7, 0x3e, 0xc0, 0x42, 0x3f, + 0x7b, 0xc6, 0xd4, 0x43, 0x15, 0x06, 0x30, 0xf4, 0x58, 0x16, 0x14, 0xd0, 0x28, + 0x16, 0xd1, 0x22, 0x0a, 0x1a, 0xfa, 0x08, 0xf0, 0x2c, 0x18, 0xee, 0xc7, 0xf5, + 0xe1, 0xfa, 0xfa, 0xfb, 0xfa, 0xbe, 0xe9, 0x0d, 0x15, 0xe7, 0xc6, 0xfc, 0xfd, + 0x09, 0xee, 0xe3, 0xf7, 0x2a, 0x1a, 0x03, 0x23, 0x19, 0x00, 0xea, 0x13, 0xec, + 0x3f, 0x10, 0xf6, 0x1f, 0x48, 0x7f, 0x10, 0x11, 0xf4, 0x21, 0x04, 0x0d, 0x13, + 0x04, 0xd8, 0xf5, 0x21, 0x2c, 0xb6, 0x28, 0x3a, 0xe9, 0xeb, 0x57, 0x2a, 0x59, + 0x28, 0x19, 0x29, 0xb5, 0x4c, 0xd1, 0xf8, 0xd5, 0xfa, 0x01, 0xff, 0xeb, 0x18, + 0x81, 0xfc, 0xe2, 0xfd, 0xea, 0xde, 0x16, 0x1c, 0xed, 0x5e, 0x27, 0x07, 0xd2, + 0x2e, 0xe4, 0x0e, 0x24, 0xf9, 0xc5, 0x3b, 0xde, 0xfc, 0x13, 0x37, 0x9f, 0xfc, + 0xe1, 0xee, 0x12, 0x0f, 0x07, 0x1a, 0xe1, 0xe7, 0xf8, 0x33, 0xda, 0x23, 0xb6, + 0xcd, 0xde, 0xdf, 0x01, 0x65, 0xab, 0x15, 0xf5, 0x26, 0xff, 0xe5, 0xbd, 0x1d, + 0x39, 0x23, 0x11, 0xd5, 0xb3, 0x27, 0xed, 0x17, 0x21, 0xd9, 0x22, 0xd5, 0x01, + 0x3c, 0xf8, 0xf7, 0x2a, 0x7f, 0xf7, 0xdd, 0xeb, 0x23, 0x0f, 0x0e, 0x45, 0xd2, + 0x25, 0x75, 0xe2, 0xb0, 0xe7, 0x04, 0x14, 0x1a, 0xe0, 0x95, 0xec, 0xef, 0xad, + 0xde, 0x4c, 0x03, 0x05, 0x3a, 0xce, 0x21, 0xdc, 0xbc, 0x4c, 0x9b, 0xf2, 0x23, + 0x02, 0x15, 0x17, 0xfd, 0xea, 0x0e, 0x0e, 0xc0, 0x54, 0xfb, 0x05, 0x02, 0xd2, + 0xdc, 0xf3, 0x25, 0xe1, 0x1e, 0x22, 0xf3, 0x04, 0x9d, 0xe7, 0xfd, 0x19, 0x05, + 0x37, 0x05, 0xd4, 0xc2, 0xc3, 0x1a, 0x40, 0xee, 0xe0, 0xfb, 0xdb, 0xe3, 0x11, + 0x4e, 0x2c, 0x26, 0x10, 0xdc, 0x2e, 0xfb, 0xed, 0x06, 0x17, 0xeb, 0xda, 0x11, + 0xd1, 0xef, 0x37, 0x10, 0x7f, 0x01, 0x12, 0x09, 0xde, 0xe0, 0x14, 0x04, 0x0d, + 0x21, 0xea, 0x2e, 0xb7, 0x1b, 0x00, 0xeb, 0xf0, 0xe7, 0x2c, 0x24, 0x79, 0x1f, + 0xf0, 0xe0, 0xdc, 0x18, 0xd3, 0xdd, 0x03, 0x1c, 0x05, 0xd7, 0xe9, 0x21, 0xd4, + 0xe0, 0x43, 0x2e, 0x0a, 0xf3, 0x09, 0x1a, 0x30, 0x65, 0xe8, 0x3c, 0x20, 0x1d, + 0x0f, 0xf2, 0xb7, 0xfc, 0xd5, 0x7f, 0xbb, 0xff, 0xa9, 0xe9, 0xd4, 0x3b, 0x36, + 0x18, 0x30, 0xd7, 0xe2, 0xfd, 0x01, 0x9d, 0x39, 0x08, 0xfb, 0xa9, 0x32, 0xb6, + 0xff, 0xe8, 0x2f, 0xb9, 0x58, 0x5c, 0x15, 0xd3, 0xb9, 0x02, 0x19, 0x81, 0xe9, + 0xc3, 0x18, 0x4e, 0xeb, 0x57, 0xbf, 0xb5, 0x2a, 0xdc, 0xc6, 0xe6, 0xff, 0xe6, + 0xed, 0x67, 0x30, 0xa6, 0x5f, 0xad, 0x09, 0xce, 0xd8, 0x17, 0xc7, 0x0e, 0x06, + 0xc2, 0xff, 0x0f, 0x1e, 0x01, 0xb0, 0x37, 0xff, 0xdd, 0x29, 0xec, 0xf2, 0x06, + 0xd4, 0x0c, 0xe1, 0xfb, 0xda, 0x24, 0xfd, 0x08, 0x5a, 0xfd, 0x14, 0xff, 0x0c, + 0xf4, 0xe7, 0xa4, 0xe4, 0x07, 0xed, 0xed, 0xbe, 0x2d, 0x2f, 0xad, 0xeb, 0x11, + 0xde, 0x0d, 0x2d, 0x58, 0x0d, 0xa2, 0x01, 0xf9, 0x06, 0xb7, 0xd6, 0xcf, 0x99, + 0xfd, 0x62, 0xfb, 0x38, 0xbe, 0x88, 0x35, 0x39, 0xf5, 0xf6, 0xec, 0xff, 0xfa, + 0xfb, 0xbd, 0x36, 0xba, 0x0d, 0x30, 0x50, 0x12, 0x28, 0x22, 0x81, 0x00, 0xd7, + 0xff, 0xfd, 0xf1, 0xb6, 0xf1, 0xb1, 0xf3, 0x38, 0xdb, 0x30, 0x48, 0x1b, 0x1a, + 0xd4, 0xd8, 0x22, 0xfb, 0x13, 0xdd, 0xec, 0xe6, 0xf0, 0xf6, 0x56, 0x08, 0xc8, + 0x0a, 0x1e, 0x4e, 0x1e, 0xac, 0x07, 0x02, 0x52, 0xf6, 0xd6, 0x59, 0xb5, 0x01, + 0xf0, 0x18, 0xcf, 0xfa, 0x1f, 0x22, 0x7f, 0x1b, 0xee, 0x79, 0x00, 0x00, 0x03, + 0xe8, 0xca, 0x14, 0xf7, 0xf4, 0xc5, 0xf7, 0x2e, 0x31, 0xd8, 0x03, 0xe9, 0x0c, + 0xf9, 0x1a, 0x32, 0x7c, 0xc5, 0xd7, 0x1c, 0xf7, 0x1c, 0xa8, 0x19, 0xbc, 0x0f, + 0x08, 0x3b, 0x0a, 0xa6, 0x2a, 0x0a, 0x0d, 0xd0, 0xb0, 0xf6, 0xfc, 0x14, 0xa7, + 0xe4, 0x1b, 0x34, 0x1d, 0x00, 0x06, 0x5f, 0xb6, 0x13, 0x38, 0xfc, 0x16, 0xed, + 0xff, 0xb3, 0x81, 0xf4, 0x2e, 0x2f, 0xc1, 0xeb, 0x03, 0x36, 0x2c, 0xd6, 0xf4, + 0x64, 0x5c, 0xe2, 0x48, 0xb6, 0xe3, 0x2d, 0xf9, 0xce, 0xe0, 0x11, 0x1f, 0x1f, + 0xaf, 0xe9, 0x1b, 0x43, 0xe3, 0x35, 0x4c, 0xf9, 0x68, 0xda, 0x24, 0xfa, 0x0b, + 0x50, 0xf9, 0xca, 0x16, 0xdd, 0x28, 0x0b, 0xf6, 0x49, 0x10, 0x0d, 0xdb, 0x0e, + 0x0c, 0x0c, 0xec, 0xfb, 0xfc, 0x0c, 0x1e, 0xef, 0xd7, 0xca, 0xb8, 0xea, 0x0b, + 0x0e, 0xc1, 0xed, 0xf5, 0xc6, 0xeb, 0x04, 0x7f, 0x01, 0xcb, 0x17, 0xff, 0xe1, + 0x7e, 0xfd, 0xed, 0x19, 0x0e, 0x17, 0x1c, 0x09, 0x2a, 0xe7, 0xe9, 0x10, 0xe5, + 0xe6, 0x25, 0xc7, 0xe6, 0xeb, 0xd0, 0xe4, 0xec, 0xdb, 0xd7, 0xf4, 0xfb, 0xd2, + 0x08, 0xfa, 0xf0, 0xe9, 0xf6, 0xd9, 0xf0, 0x12, 0xea, 0x1a, 0x11, 0x04, 0xef, + 0xed, 0x08, 0xfe, 0x00, 0xca, 0xe5, 0xd5, 0x1f, 0xef, 0x18, 0x7f, 0x2e, 0x13, + 0x10, 0x13, 0xf8, 0xf5, 0xed, 0x0c, 0xf6, 0xd8, 0xe7, 0x02, 0xd0, 0x12, 0xdd, + 0xf1, 0xda, 0xfc, 0xe8, 0xfa, 0xd4, 0xeb, 0xe8, 0xd8, 0xe3, 0xe2, 0x16, 0xed, + 0x2f, 0x07, 0x22, 0xfd, 0xfa, 0xf3, 0xee, 0xfb, 0xfe, 0xed, 0x47, 0xac, 0xe7, + 0xc6, 0x05, 0x01, 0xcc, 0x1e, 0x03, 0x09, 0x1a, 0x4a, 0xea, 0xef, 0xe5, 0xf4, + 0xe6, 0x19, 0x2c, 0x36, 0x07, 0x81, 0x34, 0xde, 0x1e, 0xfa, 0x2f, 0xe7, 0xfb, + 0xeb, 0x0d, 0x18, 0x1c, 0xee, 0xcf, 0xec, 0xe6, 0x20, 0xca, 0x12, 0xf3, 0xea, + 0x22, 0xe7, 0xee, 0xdb, 0x0e, 0xec, 0xfb, 0x0a, 0xf1, 0x0a, 0xdd, 0x3b, 0xe9, + 0xf2, 0x15, 0xf3, 0x29, 0xfd, 0xe7, 0x14, 0xf8, 0xfe, 0xe9, 0xd7, 0x1c, 0x7f, + 0xe6, 0xe1, 0xfa, 0xf3, 0x17, 0xff, 0xf5, 0xda, 0xe6, 0x21, 0xe9, 0x22, 0xd3, + 0xb4, 0x0f, 0xff, 0x04, 0x07, 0xff, 0xf0, 0xe3, 0xf1, 0x26, 0x45, 0xf0, 0xf9, + 0xf8, 0xe6, 0x0c, 0x26, 0xc4, 0xcb, 0xd5, 0xfe, 0xf3, 0x0b, 0xcd, 0xf7, 0xea, + 0xf2, 0x04, 0x15, 0xde, 0xf1, 0x1b, 0xfb, 0x26, 0x18, 0x12, 0xff, 0xfa, 0x10, + 0x38, 0x14, 0xf4, 0x0b, 0xc0, 0xe8, 0xf8, 0x30, 0xbd, 0x28, 0xc0, 0x3f, 0xde, + 0xe2, 0xec, 0x13, 0xde, 0x32, 0xd7, 0xf4, 0x1c, 0xd7, 0xf2, 0xf7, 0xf2, 0xdc, + 0xd5, 0xc1, 0xef, 0xaa, 0x3f, 0x0b, 0x13, 0x1b, 0xbb, 0x19, 0xd1, 0x04, 0xf5, + 0x7f, 0xd3, 0x03, 0x03, 0x3c, 0x1b, 0x12, 0x1e, 0x14, 0xcd, 0x0a, 0xd9, 0x31, + 0x3e, 0x47, 0xf1, 0xfe, 0x04, 0x04, 0xe2, 0x23, 0x00, 0xe8, 0x41, 0x08, 0xbf, + 0xa7, 0xf1, 0xe7, 0x12, 0xc9, 0x33, 0xe3, 0x0e, 0xeb, 0x98, 0xaa, 0xec, 0xf5, + 0x7f, 0x01, 0x01, 0xdc, 0xed, 0xee, 0x36, 0x20, 0xfd, 0xe4, 0xf6, 0x05, 0xed, + 0x14, 0xe2, 0xec, 0xe9, 0xec, 0xf4, 0x3b, 0xee, 0x22, 0x00, 0x1f, 0xe5, 0xed, + 0xe2, 0x03, 0x08, 0xdd, 0x00, 0x56, 0x28, 0xdc, 0x09, 0xc0, 0xef, 0xdd, 0xec, + 0xf8, 0xe2, 0xdb, 0x10, 0xf6, 0x05, 0xfe, 0x18, 0xdd, 0x1a, 0x02, 0xf8, 0x93, + 0xbc, 0x0e, 0x3e, 0x0d, 0xe4, 0xaa, 0x03, 0xdd, 0xe3, 0x44, 0xe4, 0x39, 0x07, + 0xdd, 0xe8, 0xfc, 0x33, 0x12, 0xfd, 0xf4, 0x2c, 0xda, 0xf7, 0x02, 0xe9, 0x1c, + 0x0c, 0x31, 0x22, 0x1d, 0x15, 0x30, 0xf1, 0xc6, 0xfc, 0xe7, 0x7f, 0xf3, 0x02, + 0xef, 0x1d, 0x31, 0xf9, 0xe2, 0xc3, 0xf9, 0x1f, 0x0f, 0x22, 0x12, 0xf5, 0x3a, + 0xe4, 0x07, 0x0b, 0xea, 0xdf, 0xe3, 0x1b, 0xe2, 0x24, 0x04, 0x74, 0x22, 0xb9, + 0x34, 0x18, 0xe2, 0xcd, 0xf4, 0x46, 0xd4, 0xf2, 0x1d, 0xf7, 0xe6, 0xea, 0x1a, + 0xfd, 0x17, 0xfb, 0x28, 0xee, 0xf7, 0x03, 0xfa, 0xea, 0x0b, 0xde, 0xef, 0xf1, + 0xdf, 0xf7, 0x0e, 0xff, 0x00, 0x0e, 0x1f, 0x02, 0x36, 0x1b, 0x7f, 0x14, 0xf3, + 0x1e, 0xf7, 0xd7, 0x26, 0xe5, 0xfc, 0xfb, 0xea, 0xce, 0xd8, 0xe9, 0x00, 0xc5, + 0x2e, 0xea, 0x30, 0xe3, 0xfc, 0xf9, 0xfc, 0xa2, 0xfa, 0xcb, 0x3f, 0xfa, 0x0f, + 0x08, 0xa1, 0x20, 0x05, 0x21, 0x81, 0x2d, 0xd4, 0x04, 0x82, 0xc1, 0xa9, 0xa6, + 0xbd, 0xfe, 0xcb, 0xf9, 0x01, 0x18, 0x2b, 0x17, 0x0a, 0xc1, 0xf2, 0x37, 0xdc, + 0xb3, 0xf0, 0xd2, 0x4a, 0x37, 0xfe, 0xa4, 0xc1, 0xe1, 0xc6, 0x36, 0xed, 0x04, + 0xdf, 0x18, 0x01, 0xc4, 0x13, 0xfd, 0x39, 0x1f, 0xb5, 0xe0, 0x44, 0x07, 0x9f, + 0xe2, 0x81, 0x60, 0xbe, 0xd5, 0x15, 0xd6, 0xb5, 0xf0, 0x3b, 0xbb, 0x00, 0x06, + 0x03, 0x57, 0x08, 0x13, 0x10, 0x1f, 0x2d, 0x09, 0x13, 0x17, 0xd8, 0xac, 0xd4, + 0x0f, 0xf8, 0x0a, 0xdf, 0xc0, 0x14, 0xc3, 0xf6, 0xcd, 0xfb, 0x25, 0xf2, 0x0f, + 0xf4, 0x03, 0xf2, 0xc0, 0xf0, 0xeb, 0x24, 0xf6, 0xf8, 0x2c, 0xdb, 0x16, 0xf9, + 0x23, 0x15, 0x36, 0x05, 0xbf, 0x06, 0x58, 0xb3, 0x05, 0x65, 0x28, 0x7f, 0xfa, + 0xe0, 0x1b, 0xe2, 0xf8, 0x35, 0x1d, 0x62, 0x29, 0xc8, 0x0f, 0x06, 0x06, 0xfa, + 0x22, 0x07, 0xb3, 0xe0, 0x1b, 0xcc, 0x14, 0xe3, 0xdd, 0xfa, 0xf6, 0x0a, 0xe8, + 0xe5, 0xec, 0xfa, 0x2a, 0x17, 0xd2, 0x47, 0x11, 0xf2, 0x13, 0xe8, 0x1d, 0x3c, + 0x7c, 0xc6, 0xbc, 0x0f, 0xfb, 0xec, 0xfd, 0x18, 0x81, 0xc9, 0xe9, 0x0e, 0xee, + 0x06, 0xf3, 0x1f, 0x25, 0xfc, 0x11, 0x74, 0x06, 0xe4, 0xd7, 0x04, 0x0b, 0x1e, + 0x0a, 0xfc, 0x55, 0xc9, 0xdc, 0x12, 0xe1, 0xfe, 0x19, 0xd2, 0xda, 0xd2, 0xa2, + 0xea, 0x34, 0x20, 0x0d, 0x42, 0x05, 0x0a, 0xc1, 0xb1, 0xce, 0x11, 0xb6, 0x02, + 0x01, 0x29, 0x1f, 0xd8, 0x40, 0xe3, 0x62, 0xc7, 0x14, 0x09, 0xd1, 0xef, 0x11, + 0x3d, 0xed, 0xc0, 0xc1, 0xe9, 0xe9, 0x13, 0x3f, 0x23, 0x81, 0x16, 0xd3, 0x0c, + 0xde, 0x40, 0xf2, 0x1e, 0x3e, 0x13, 0xfe, 0xd2, 0xeb, 0xdf, 0x10, 0xda, 0xdb, + 0x13, 0x03, 0x11, 0xad, 0xdf, 0xf6, 0x06, 0x56, 0x10, 0x10, 0xd7, 0xfa, 0xbe, + 0xf9, 0x12, 0xfb, 0x31, 0xe0, 0x0b, 0x30, 0xd9, 0xe9, 0x08, 0xea, 0x0d, 0xce, + 0x0f, 0x23, 0xf1, 0x03, 0xf8, 0xe8, 0xfe, 0xdf, 0xce, 0x29, 0xfb, 0xec, 0xcc, + 0x2c, 0xc0, 0xcd, 0xec, 0x13, 0x7f, 0xf4, 0x18, 0xd1, 0x0a, 0xc1, 0xfb, 0xfe, + 0x05, 0xe6, 0x0f, 0x0c, 0xfb, 0x0f, 0x30, 0x13, 0xe1, 0xd4, 0xf2, 0xea, 0xde, + 0xfe, 0x2c, 0xf9, 0xde, 0x18, 0x16, 0xf9, 0xea, 0xe1, 0x2e, 0x1e, 0xdc, 0xed, + 0x3c, 0x07, 0xfa, 0x06, 0x13, 0xfd, 0xcf, 0x04, 0xf3, 0x15, 0x0d, 0x81, 0xe5, + 0x08, 0xb8, 0xc8, 0xf6, 0xea, 0x14, 0xf7, 0xef, 0xea, 0x43, 0x19, 0xeb, 0x3d, + 0xf9, 0x1b, 0xb7, 0x0b, 0x14, 0x0e, 0xed, 0xd5, 0xf9, 0xb7, 0x10, 0xe5, 0x4b, + 0xee, 0xd2, 0x17, 0xf2, 0x14, 0x25, 0xfa, 0xd8, 0x05, 0x06, 0xd1, 0x17, 0xf8, + 0xf7, 0xc6, 0xc9, 0xbc, 0xfd, 0xe5, 0xf9, 0xd3, 0xd2, 0xcb, 0xd4, 0xce, 0x0a, + 0xc9, 0xd3, 0xfe, 0xb3, 0x5e, 0x0d, 0xf5, 0x0c, 0xcd, 0x1c, 0x7f, 0xe8, 0x9a, + 0x15, 0x63, 0x30, 0x08, 0x3b, 0x0a, 0x26, 0x9e, 0x26, 0x5c, 0x6e, 0xe5, 0x6a, + 0xcd, 0xdc, 0x04, 0xf0, 0xe9, 0xeb, 0xf8, 0x20, 0xbe, 0x2e, 0xdc, 0x11, 0x01, + 0xb0, 0xce, 0x2f, 0x1f, 0xe0, 0xf6, 0xa3, 0xf2, 0xb4, 0xe2, 0x1a, 0x32, 0x16, + 0xdf, 0x42, 0xe7, 0x07, 0xd6, 0x38, 0xda, 0xc7, 0xcd, 0xeb, 0xf5, 0xdc, 0xff, + 0xed, 0x2d, 0x15, 0x17, 0x17, 0x27, 0x02, 0x03, 0x2e, 0x04, 0xea, 0x2e, 0xf4, + 0x7f, 0xdd, 0x04, 0x1c, 0x5d, 0xce, 0xd0, 0x00, 0x1f, 0xf5, 0xf2, 0x16, 0x72, + 0x07, 0xe0, 0x11, 0x30, 0x1d, 0xd6, 0x0e, 0x2d, 0x22, 0x7d, 0x0e, 0x00, 0xf0, + 0xff, 0xcc, 0x5a, 0xcb, 0x19, 0xfc, 0xd2, 0x9d, 0xe3, 0xce, 0x14, 0xfb, 0x4b, + 0x0e, 0xd4, 0xd9, 0xde, 0x1b, 0xa2, 0x00, 0xbc, 0xcf, 0xbf, 0x0a, 0xfc, 0xef, + 0x3f, 0x46, 0x40, 0x41, 0x10, 0x1e, 0xfe, 0x46, 0xe7, 0xce, 0xf8, 0xc3, 0x54, + 0x12, 0x60, 0xd2, 0xf3, 0xeb, 0xc2, 0xfb, 0x32, 0x63, 0x42, 0xd4, 0x41, 0xbf, + 0x41, 0x38, 0xe5, 0x38, 0xea, 0xdf, 0xf8, 0x07, 0x84, 0xb9, 0xf3, 0xe3, 0xcf, + 0xef, 0xcd, 0xc6, 0x34, 0xbd, 0x2c, 0x97, 0xc9, 0x81, 0x07, 0xd0, 0x2e, 0x10, + 0x13, 0xc3, 0xb0, 0x07, 0x05, 0xcb, 0xf0, 0xf8, 0x17, 0x19, 0x15, 0xe9, 0xfe, + 0xe2, 0x29, 0xfa, 0x3d, 0xb8, 0x01, 0xcd, 0x2f, 0xee, 0x04, 0xd8, 0xf6, 0xf8, + 0x5f, 0x98, 0xff, 0xd8, 0xd4, 0x54, 0x6a, 0xe9, 0x2c, 0x39, 0xee, 0x10, 0x19, + 0x19, 0xf8, 0xe8, 0xce, 0xf7, 0xfc, 0xb8, 0x14, 0xd8, 0x6c, 0x19, 0x30, 0x2c, + 0xf5, 0xbe, 0x24, 0xf2, 0xfb, 0xf2, 0xfc, 0xe3, 0xe2, 0xc3, 0xc1, 0xba, 0xaa, + 0x7f, 0x53, 0x08, 0x47, 0xf5, 0x2f, 0xfe, 0x54, 0x14, 0xba, 0x17, 0xea, 0x1c, + 0xff, 0xb6, 0x0e, 0xec, 0x1c, 0xf8, 0x32, 0xd8, 0xce, 0x24, 0x51, 0xe7, 0x1b, + 0x62, 0x60, 0x00, 0xc4, 0xd1, 0xc5, 0xcb, 0xca, 0xba, 0xc0, 0x00, 0x02, 0xfc, + 0x25, 0x9e, 0xff, 0x3f, 0xf6, 0x11, 0x41, 0xf0, 0xf4, 0x26, 0x10, 0x0b, 0xd2, + 0xfc, 0x00, 0x7f, 0x5b, 0x1d, 0xc3, 0x36, 0xc5, 0x3d, 0xfe, 0x10, 0x49, 0x48, + 0xdb, 0xc0, 0x0f, 0xa4, 0x42, 0x96, 0x31, 0xbc, 0xd2, 0x2d, 0x2e, 0x59, 0x24, + 0xe4, 0x0c, 0x22, 0x4d, 0x0b, 0xae, 0xf6, 0xeb, 0xc8, 0x09, 0x02, 0xde, 0x30, + 0x08, 0xbb, 0x3f, 0x3e, 0xbe, 0x0f, 0x09, 0x1b, 0xe8, 0x01, 0x3a, 0x73, 0xe9, + 0x2b, 0xe4, 0x25, 0xec, 0x05, 0x1a, 0x20, 0x13, 0xe9, 0xf8, 0xca, 0xfb, 0x0e, + 0xe7, 0x30, 0xe7, 0x22, 0x1b, 0xd6, 0xe7, 0x5d, 0x7f, 0xce, 0xc2, 0xcf, 0xc8, + 0xfd, 0xe9, 0x6e, 0x00, 0xe9, 0x4b, 0x2b, 0x91, 0xd6, 0xf4, 0xf4, 0x21, 0xbd, + 0xa6, 0x2c, 0xe6, 0xf3, 0xea, 0x1c, 0x0e, 0x07, 0x69, 0xee, 0xd7, 0xf4, 0xf3, + 0xed, 0x14, 0xc5, 0xf0, 0xea, 0xf5, 0xed, 0x0b, 0x35, 0x22, 0xd6, 0x0b, 0xd6, + 0xcc, 0x1c, 0x21, 0x37, 0x05, 0x1c, 0xdd, 0xd0, 0x18, 0xe8, 0x9d, 0x6b, 0x12, + 0x1c, 0x13, 0x4c, 0xdb, 0x3a, 0xee, 0xcb, 0x7f, 0x07, 0xf6, 0xe0, 0x98, 0x01, + 0x0d, 0x31, 0xdb, 0x1c, 0xb9, 0x0c, 0xe0, 0x14, 0xd0, 0x00, 0xe4, 0xda, 0xe8, + 0x3b, 0xcc, 0x04, 0xe3, 0x0d, 0x38, 0xf3, 0xfe, 0xf5, 0xe5, 0x3f, 0xc6, 0xcc, + 0x1c, 0x35, 0xe2, 0xf9, 0x14, 0x1e, 0xb7, 0x03, 0xd5, 0x7f, 0x0a, 0x25, 0x21, + 0x41, 0x32, 0x1d, 0xed, 0x24, 0xfc, 0x22, 0x3a, 0x19, 0xef, 0x11, 0xf5, 0xf7, + 0x0e, 0x30, 0xf6, 0xed, 0x25, 0x1d, 0x77, 0x00, 0xf0, 0xe2, 0x08, 0xf5, 0x28, + 0x7f, 0x16, 0x3d, 0xc9, 0x1b, 0xf3, 0xf0, 0xf1, 0x16, 0x82, 0x10, 0xcb, 0xf2, + 0x2f, 0xef, 0xd9, 0xdd, 0x02, 0xfd, 0xeb, 0x08, 0xf7, 0x21, 0xfd, 0xf6, 0xf1, + 0x0f, 0xd2, 0xd8, 0x10, 0xf0, 0xe1, 0xe5, 0xd3, 0xf1, 0x0a, 0xfd, 0x19, 0x58, + 0xf5, 0x27, 0xf5, 0x32, 0xd2, 0xe5, 0x34, 0xeb, 0x23, 0x5a, 0xf8, 0x23, 0x03, + 0xda, 0x00, 0x15, 0x15, 0x27, 0x33, 0xf7, 0x04, 0xe7, 0xe5, 0x10, 0xf1, 0x2f, + 0x06, 0x0e, 0xcc, 0xd9, 0x09, 0x0d, 0xb7, 0x26, 0x20, 0xfb, 0x0e, 0xc6, 0x01, + 0xf2, 0xe2, 0xee, 0xc6, 0x2b, 0x9f, 0xd2, 0x20, 0x02, 0xed, 0xda, 0x2f, 0xe0, + 0xf1, 0xf8, 0x11, 0x4e, 0xb8, 0x1d, 0xea, 0xf2, 0xee, 0xf8, 0x05, 0x23, 0xf8, + 0xdc, 0xa0, 0x59, 0x24, 0xe1, 0xe9, 0xd9, 0x0e, 0xf8, 0xe7, 0xe4, 0x4e, 0x35, + 0x0c, 0x7f, 0xdd, 0xba, 0xe0, 0xc6, 0xb6, 0x44, 0x16, 0xe1, 0x13, 0xe3, 0x38, + 0xf8, 0xe7, 0x16, 0xae, 0xdc, 0xdf, 0xcd, 0x45, 0xde, 0xfb, 0x3f, 0xd3, 0x06, + 0x22, 0xeb, 0x16, 0x06, 0xe3, 0xf6, 0xd0, 0x08, 0x08, 0xf0, 0x08, 0x1d, 0xda, + 0xba, 0xdd, 0xf7, 0x08, 0xf5, 0xf4, 0x17, 0xec, 0xef, 0x81, 0x37, 0xbd, 0x06, + 0x2a, 0x1f, 0xca, 0xfc, 0xf8, 0xef, 0x12, 0x69, 0x09, 0xfe, 0x06, 0x04, 0xde, + 0x0c, 0xe4, 0x12, 0xe4, 0x0d, 0xec, 0xdb, 0x88, 0xf4, 0xf0, 0x28, 0xeb, 0xe0, + 0x3a, 0xa3, 0xf1, 0xa5, 0x15, 0x0e, 0xea, 0xf9, 0x0a, 0x16, 0x15, 0x19, 0x10, + 0xad, 0x06, 0xf1, 0x06, 0xae, 0x08, 0x24, 0x35, 0xe1, 0xc4, 0x9f, 0xd7, 0xa2, + 0xda, 0xdd, 0x45, 0x19, 0x39, 0x14, 0xf3, 0x3c, 0xf1, 0xdb, 0x34, 0xf2, 0x07, + 0x27, 0xc1, 0x11, 0xdf, 0xd9, 0xb0, 0x1d, 0x5c, 0xfe, 0xe4, 0x0b, 0xe7, 0xf4, + 0x32, 0x1c, 0x7f, 0x35, 0x05, 0xef, 0xf5, 0x03, 0xeb, 0xa3, 0xdd, 0x20, 0x07, + 0x11, 0x2a, 0x13, 0xd8, 0xd9, 0xd3, 0xc0, 0xe3, 0xcc, 0xed, 0xcd, 0xfc, 0xcd, + 0xde, 0x31, 0xda, 0x07, 0xe9, 0xe9, 0xf9, 0x25, 0x42, 0xcb, 0x1b, 0x43, 0xec, + 0x39, 0xd7, 0x32, 0x17, 0xdb, 0xf3, 0x10, 0xf1, 0x3c, 0xc0, 0x07, 0xd6, 0x1d, + 0x81, 0xfa, 0xc3, 0x0d, 0xfc, 0x1c, 0xff, 0xc8, 0x05, 0xf0, 0xc9, 0x1c, 0x18, + 0xe5, 0x3b, 0xf3, 0xe9, 0xf6, 0xc8, 0xdd, 0x3b, 0xd4, 0x46, 0xe5, 0x0c, 0x10, + 0x03, 0x0b, 0x1b, 0x07, 0x44, 0x31, 0x34, 0x03, 0xe9, 0x44, 0xcf, 0x22, 0xe5, + 0xb5, 0x0e, 0x21, 0x66, 0xd7, 0x0c, 0xbd, 0xae, 0xf5, 0xe0, 0x63, 0xef, 0x7f, + 0xec, 0xf1, 0x21, 0xd1, 0xbd, 0x00, 0x32, 0xdf, 0xe6, 0xe0, 0xd3, 0xfc, 0xfa, + 0x2e, 0xe7, 0xf4, 0xf0, 0xaa, 0xde, 0xf5, 0x3a, 0xf8, 0xd8, 0x19, 0xfd, 0xe6, + 0xd1, 0xee, 0xe9, 0xf4, 0xe5, 0xf4, 0x42, 0x20, 0xc3, 0x4f, 0xd5, 0x49, 0x3b, + 0x5c, 0xe2, 0x0d, 0x69, 0x2b, 0x10, 0xea, 0x44, 0x06, 0x7f, 0x17, 0xe7, 0xcc, + 0xcb, 0x21, 0x4a, 0x45, 0xdf, 0x6e, 0x2c, 0xe2, 0x18, 0xc2, 0xd7, 0x3b, 0xa5, + 0x5b, 0x1f, 0x00, 0xfc, 0x1c, 0xa9, 0x9c, 0x9a, 0xee, 0xe3, 0xc1, 0xdd, 0xe3, + 0x4c, 0x45, 0x92, 0xba, 0xfe, 0x08, 0x32, 0xb5, 0x16, 0xf2, 0x0c, 0x2a, 0xce, + 0xad, 0xda, 0xa0, 0x60, 0x12, 0xc0, 0xec, 0x12, 0x06, 0x1e, 0x7f, 0x1c, 0xf3, + 0x10, 0xdc, 0xed, 0xcb, 0xec, 0x0e, 0xff, 0x08, 0xde, 0x0f, 0xf6, 0xf6, 0x0b, + 0xe9, 0x11, 0x0b, 0xf2, 0xf7, 0xce, 0x09, 0x06, 0xe8, 0xe3, 0xf1, 0x22, 0xd7, + 0xff, 0x0b, 0x04, 0x32, 0xe7, 0xe8, 0xed, 0xcf, 0x0a, 0x3b, 0xf5, 0xe9, 0x28, + 0x00, 0x08, 0xda, 0x05, 0x1c, 0xee, 0x01, 0x0b, 0x07, 0xf4, 0xfd, 0xb6, 0x14, + 0x2b, 0xd6, 0xb2, 0x08, 0xe8, 0x2e, 0xff, 0x17, 0x5a, 0x3b, 0x09, 0x24, 0xe0, + 0xdd, 0x55, 0x3b, 0xde, 0x05, 0x11, 0xbe, 0x12, 0x02, 0xe6, 0xde, 0x81, 0x0b, + 0x03, 0xf2, 0xf2, 0x5b, 0x08, 0xce, 0xef, 0x3b, 0xdb, 0x73, 0x08, 0x2c, 0x04, + 0x34, 0x0c, 0x29, 0xf7, 0xea, 0xf9, 0x02, 0xe8, 0x52, 0x02, 0x03, 0xf0, 0x40, + 0xec, 0xe6, 0xf8, 0xb6, 0x48, 0xf1, 0x22, 0x35, 0x12, 0xd7, 0x09, 0x0e, 0xc0, + 0xfd, 0x3c, 0x1b, 0x35, 0x46, 0x6c, 0xdc, 0x22, 0x8d, 0x39, 0xc0, 0x15, 0x2b, + 0x84, 0x29, 0x38, 0x69, 0x07, 0x08, 0x20, 0xff, 0x2f, 0xf4, 0x12, 0xe4, 0xfe, + 0x33, 0xed, 0xe9, 0xe3, 0x04, 0xd9, 0xe0, 0xa1, 0xae, 0x7f, 0x10, 0x12, 0x38, + 0xf0, 0xb3, 0xcd, 0x4d, 0xd5, 0x04, 0xdc, 0x18, 0x23, 0x16, 0x1d, 0x93, 0x0e, + 0xcf, 0x07, 0x1c, 0xa7, 0x61, 0x02, 0x29, 0x14, 0xdd, 0xdc, 0x31, 0xe8, 0xf8, + 0x0e, 0xbc, 0xf2, 0x3f, 0xa7, 0xa2, 0xe2, 0x81, 0x0e, 0xce, 0xf8, 0xfb, 0x08, + 0xe3, 0x1e, 0x13, 0xdf, 0xde, 0xef, 0xe5, 0xd0, 0x1a, 0xee, 0xf8, 0xee, 0x17, + 0xee, 0xe5, 0x3e, 0xf3, 0xde, 0x03, 0x19, 0x2b, 0x54, 0xcb, 0x22, 0x05, 0xf1, + 0x42, 0x22, 0x32, 0x40, 0x39, 0xe2, 0xe4, 0xb9, 0x30, 0xcb, 0x16, 0x2d, 0x19, + 0xf8, 0x89, 0x14, 0x0f, 0x14, 0xe8, 0xe0, 0x0e, 0xc7, 0x50, 0x1e, 0x1e, 0xaa, + 0xf0, 0x1a, 0x0b, 0xc5, 0x17, 0x91, 0xe6, 0x4d, 0xf5, 0xbf, 0xd0, 0xe7, 0xf7, + 0xe9, 0x09, 0x19, 0xef, 0xc6, 0x05, 0x2d, 0xec, 0xab, 0x16, 0x13, 0x01, 0xfd, + 0x10, 0xfd, 0x2c, 0xed, 0x48, 0x12, 0x12, 0x9e, 0x09, 0xf1, 0xfe, 0xd9, 0x1e, + 0xb2, 0xe4, 0x7f, 0x03, 0x0f, 0x2f, 0xd8, 0x3e, 0x19, 0x0e, 0xa6, 0x11, 0x00, + 0x02, 0x1d, 0xfb, 0xc3, 0xb2, 0x0b, 0xf5, 0xfa, 0x30, 0xdd, 0xe4, 0x51, 0xe3, + 0xe4, 0xe4, 0x2a, 0x14, 0xd8, 0x81, 0x60, 0x03, 0x17, 0xa9, 0xef, 0x08, 0x03, + 0xc9, 0xeb, 0xb6, 0xe2, 0xa8, 0x0d, 0x26, 0xcc, 0x0f, 0xf8, 0x77, 0xf8, 0x20, + 0x0b, 0xf9, 0x1d, 0x3b, 0xcd, 0x13, 0xc3, 0x00, 0xa9, 0x36, 0x94, 0x07, 0x24, + 0x1e, 0x1b, 0x11, 0x07, 0x0f, 0xf5, 0xba, 0xfb, 0xf7, 0x7d, 0xf0, 0x0b, 0xc2, + 0x4f, 0x10, 0x23, 0xfc, 0x1c, 0x1e, 0x05, 0xdf, 0xea, 0x10, 0xef, 0x2f, 0xf5, + 0xdd, 0xd2, 0x23, 0x00, 0x40, 0x0f, 0xd6, 0xec, 0x1e, 0x07, 0x05, 0xf9, 0xe6, + 0xd4, 0xeb, 0xfb, 0x14, 0x48, 0x00, 0x32, 0xf3, 0xe4, 0xdc, 0x12, 0xfd, 0xcc, + 0xf4, 0x43, 0x3f, 0x14, 0x1b, 0xeb, 0xd8, 0x0d, 0x02, 0xed, 0xe4, 0xfb, 0x24, + 0x33, 0x1f, 0xf1, 0xf6, 0x3a, 0xf9, 0x09, 0x7f, 0xf9, 0x2c, 0x17, 0xe2, 0x21, + 0xf8, 0xea, 0x03, 0x09, 0xc7, 0x38, 0x3b, 0xef, 0x08, 0xfa, 0x07, 0xa3, 0xd2, + 0xc9, 0xa0, 0x28, 0x57, 0xf1, 0x16, 0x06, 0xd7, 0x34, 0xe5, 0xec, 0xe7, 0x37, + 0x0d, 0xf5, 0x56, 0x2c, 0xcc, 0x2b, 0xf3, 0xf5, 0x0e, 0xc7, 0xde, 0x4d, 0x0a, + 0xe0, 0x47, 0x14, 0x17, 0x11, 0x0f, 0x15, 0xf6, 0x11, 0x0f, 0x27, 0xf9, 0x7f, + 0xe6, 0x22, 0x29, 0x4a, 0xfa, 0xe8, 0xd8, 0x0b, 0x31, 0x02, 0xd0, 0x0a, 0xfb, + 0x29, 0x17, 0x09, 0xd4, 0x3c, 0x51, 0x51, 0x0e, 0xcd, 0xff, 0x0d, 0x19, 0xf8, + 0xd4, 0x7f, 0x0d, 0xb9, 0xca, 0xff, 0xe4, 0xff, 0x28, 0xfd, 0xd2, 0xf7, 0x02, + 0x0f, 0xd9, 0xde, 0xf3, 0x2a, 0x29, 0xd5, 0x05, 0x3b, 0xf1, 0x0a, 0xd5, 0x46, + 0x20, 0xdc, 0x48, 0xd8, 0xe4, 0xf5, 0x42, 0xd2, 0x18, 0xfd, 0x51, 0x32, 0x39, + 0xde, 0xd7, 0x08, 0xe1, 0xb9, 0xe9, 0x4d, 0xeb, 0xf3, 0xde, 0xf7, 0xed, 0xc9, + 0x4b, 0x25, 0xe5, 0xf5, 0x13, 0xe3, 0x0e, 0x0f, 0xd6, 0xe7, 0x37, 0xd2, 0x26, + 0xf9, 0xed, 0xf6, 0x0c, 0x06, 0xf8, 0xed, 0x41, 0x11, 0xe6, 0x33, 0xcb, 0x01, + 0xf6, 0xea, 0x12, 0xeb, 0x08, 0xcd, 0xb1, 0x00, 0x22, 0x4d, 0x7e, 0x10, 0x4d, + 0x45, 0x26, 0xf4, 0x29, 0x43, 0xe3, 0xf1, 0x24, 0x81, 0xd0, 0xa5, 0xe4, 0xed, + 0xf2, 0x1d, 0xcc, 0xdf, 0xfe, 0xe5, 0x09, 0xd8, 0xec, 0x0d, 0x27, 0xf2, 0xd4, + 0x0c, 0xfe, 0x13, 0xd4, 0x51, 0xc4, 0xa3, 0xf5, 0x48, 0xc8, 0x32, 0xa3, 0x8f, + 0x30, 0x0b, 0x15, 0xd4, 0xc1, 0x02, 0xca, 0x02, 0x2f, 0xce, 0xbe, 0x71, 0x0e, + 0x1b, 0xb1, 0xf9, 0x13, 0x4b, 0x1a, 0x29, 0xc6, 0xe9, 0x40, 0xcb, 0xfa, 0xa8, + 0x67, 0xc8, 0xd0, 0x81, 0xf5, 0xf8, 0x29, 0xd7, 0x1c, 0xe1, 0x3b, 0x02, 0xfc, + 0x50, 0x16, 0xc8, 0x09, 0x95, 0x0f, 0x9f, 0x64, 0xf4, 0xf0, 0xdf, 0xfc, 0xf8, + 0x38, 0xa6, 0xfe, 0x1b, 0x0f, 0x67, 0x21, 0x5c, 0x19, 0xda, 0x29, 0xea, 0x05, + 0xec, 0x32, 0x04, 0xd7, 0x81, 0x00, 0xd2, 0x03, 0xe6, 0xef, 0x0a, 0xbe, 0x2d, + 0x24, 0xec, 0x55, 0xf0, 0x4a, 0x1c, 0xd4, 0x09, 0x06, 0x5d, 0x37, 0x2a, 0x31, + 0xc8, 0xf3, 0xbc, 0x1b, 0x05, 0xe8, 0x05, 0x04, 0xd1, 0xe4, 0xd2, 0x13, 0xf5, + 0x93, 0x0f, 0xc5, 0x16, 0x56, 0xfa, 0x14, 0x0d, 0xff, 0x10, 0x10, 0x39, 0xf8, + 0xdf, 0xd1, 0xbe, 0x1c, 0xcd, 0x32, 0x16, 0x28, 0xc8, 0x55, 0x0b, 0xfe, 0x25, + 0x2a, 0xef, 0xdc, 0x9a, 0xd4, 0xf7, 0x05, 0x17, 0xe0, 0xc1, 0x1c, 0x0d, 0x23, + 0x13, 0x07, 0x28, 0xf5, 0x06, 0xc8, 0xc2, 0xbd, 0xf4, 0xc7, 0xfa, 0x2b, 0x7f, + 0x14, 0x24, 0x4e, 0x09, 0x5f, 0x26, 0x08, 0x36, 0x46, 0x24, 0xd7, 0xc2, 0x1f, + 0xf8, 0x11, 0x23, 0x07, 0xbb, 0xdb, 0x11, 0xda, 0xc5, 0x45, 0xde, 0x32, 0x09, + 0x32, 0xbe, 0xc2, 0xf2, 0xd2, 0x5a, 0xb6, 0xfe, 0xe4, 0x47, 0xa0, 0xef, 0xf4, + 0x16, 0x33, 0xf2, 0x23, 0x3d, 0xea, 0xde, 0xe2, 0x52, 0x07, 0xb4, 0x18, 0x31, + 0xe5, 0xff, 0x50, 0x05, 0xe7, 0xf8, 0xf3, 0xe7, 0xd4, 0x41, 0xd0, 0x4e, 0x44, + 0x27, 0xff, 0x2a, 0xd4, 0x41, 0xf3, 0xe1, 0xc8, 0xeb, 0xd7, 0x31, 0x2e, 0x20, + 0xb9, 0xe5, 0x05, 0xf2, 0x36, 0xe3, 0x10, 0xb5, 0xda, 0xff, 0x1c, 0xb1, 0xf0, + 0x27, 0x02, 0x7f, 0xe1, 0xb9, 0x3b, 0xab, 0x25, 0x37, 0x75, 0xa6, 0x46, 0xe8, + 0xcf, 0xb7, 0xf8, 0x1c, 0x48, 0xec, 0x06, 0x2c, 0xf2, 0x9b, 0x18, 0x48, 0xcd, + 0xde, 0x0f, 0xf2, 0xe1, 0x5c, 0xfa, 0xdf, 0xf7, 0xe9, 0x29, 0xd0, 0x13, 0xe5, + 0xe2, 0xe6, 0x0e, 0xd4, 0xf4, 0xf8, 0x1f, 0xc6, 0xe3, 0x40, 0x26, 0xed, 0x33, + 0xfa, 0xce, 0x24, 0x7f, 0xe4, 0xcf, 0x0a, 0xef, 0xe7, 0x02, 0x28, 0x4f, 0xd2, + 0x00, 0x2f, 0x13, 0xfb, 0xe7, 0x22, 0x1b, 0x9f, 0x65, 0xc4, 0x0f, 0xe8, 0x04, + 0x1c, 0x2a, 0x36, 0xe9, 0x6a, 0xbc, 0x27, 0xc4, 0xb6, 0xd3, 0x85, 0xe9, 0xc3, + 0x29, 0xe3, 0x35, 0x00, 0x79, 0x0f, 0x06, 0xb8, 0x0b, 0x2b, 0x25, 0xe4, 0xc7, + 0x1c, 0x02, 0x47, 0xe1, 0x5e, 0xf9, 0x0f, 0xd3, 0x29, 0xdf, 0xcb, 0x20, 0x1d, + 0xaf, 0x2d, 0x7f, 0x1a, 0x18, 0x3f, 0xf9, 0xe8, 0x7c, 0x04, 0x08, 0xfc, 0xd0, + 0xb1, 0x49, 0xf5, 0xc5, 0x09, 0x0f, 0x6b, 0x18, 0xda, 0xef, 0x2c, 0x97, 0xc2, + 0xc6, 0xea, 0xdf, 0xb7, 0xc6, 0x44, 0x23, 0xd2, 0xf6, 0x99, 0x2f, 0x4e, 0x8e, + 0x1f, 0xde, 0x3b, 0x47, 0x33, 0xbb, 0x16, 0x65, 0xca, 0xac, 0x0d, 0xf0, 0xee, + 0xe5, 0x1b, 0xe4, 0xfb, 0x81, 0xa3, 0x05, 0x03, 0xe1, 0x11, 0x0d, 0xfb, 0xa6, + 0x10, 0xf0, 0xd1, 0x2e, 0x0d, 0x2e, 0xe5, 0x2b, 0xd6, 0xd3, 0xf9, 0xee, 0x68, + 0xe9, 0x0a, 0xc8, 0x6c, 0xe3, 0xfa, 0x00, 0x04, 0xfc, 0x0c, 0x01, 0xe1, 0xff, + 0xe5, 0xf3, 0x14, 0xfb, 0xdf, 0x2d, 0x28, 0xde, 0x12, 0xcd, 0xa8, 0xe1, 0xff, + 0x1a, 0xff, 0x4d, 0xc8, 0xf3, 0x0a, 0x05, 0x0c, 0x4e, 0xf2, 0x0b, 0xea, 0xec, + 0x0c, 0xdd, 0x4f, 0xcd, 0x5a, 0x0d, 0x1f, 0x36, 0x37, 0xea, 0xf3, 0x7f, 0x2e, + 0x46, 0xfa, 0xda, 0xd4, 0xc6, 0xf7, 0xd9, 0xf9, 0xf3, 0xd5, 0xca, 0xf4, 0x05, + 0x81, 0x25, 0xd3, 0xf1, 0x78, 0xcc, 0xc8, 0xd4, 0x04, 0x00, 0x35, 0xd0, 0xdc, + 0xbd, 0x17, 0xf0, 0x16, 0x19, 0xa5, 0xee, 0xf3, 0xdd, 0xf4, 0x0b, 0xdd, 0x0c, + 0x01, 0x03, 0xeb, 0x16, 0x27, 0xf7, 0xd6, 0x0b, 0x0e, 0x40, 0x15, 0x20, 0xf7, + 0x14, 0x60, 0x01, 0x09, 0x0d, 0xed, 0x15, 0x1c, 0xbf, 0xe3, 0x13, 0x0f, 0xef, + 0x16, 0xfb, 0x10, 0x12, 0xf4, 0xef, 0x21, 0x1d, 0xf7, 0x17, 0xc4, 0x01, 0xf2, + 0xdc, 0xcf, 0xe6, 0x2d, 0xd0, 0xda, 0x14, 0x32, 0xe9, 0xd1, 0xed, 0x1c, 0x39, + 0x81, 0x0f, 0xd8, 0xef, 0x24, 0xda, 0x18, 0x1c, 0x11, 0xfc, 0x02, 0x9f, 0xed, + 0x2b, 0xfe, 0x12, 0xfa, 0xf6, 0x3b, 0x15, 0x04, 0xf0, 0x0e, 0x1a, 0xc3, 0x09, + 0xc2, 0x0b, 0xcc, 0x4f, 0x04, 0xeb, 0x16, 0xe6, 0x0c, 0xc6, 0xe3, 0x54, 0xfc, + 0xfa, 0xf3, 0x3a, 0xe1, 0x2e, 0xcf, 0x48, 0x36, 0xf4, 0xed, 0x10, 0xd0, 0xc1, + 0xff, 0x09, 0x04, 0x38, 0xfa, 0xef, 0x0c, 0x03, 0xd2, 0xe0, 0x13, 0xf3, 0xf1, + 0xda, 0xd6, 0xec, 0xf9, 0xe7, 0x02, 0xfb, 0x43, 0x49, 0x00, 0x2f, 0x09, 0xf5, + 0xf7, 0x81, 0xcd, 0x98, 0x2f, 0xff, 0xfc, 0x08, 0xd6, 0x05, 0x81, 0xb4, 0x03, + 0xf1, 0x22, 0x26, 0x3c, 0xef, 0x0b, 0x13, 0xf5, 0xde, 0xf9, 0x76, 0xf6, 0xe6, + 0xf2, 0x3b, 0xfd, 0xe4, 0xd5, 0xd6, 0xc2, 0x15, 0x60, 0xe1, 0x02, 0xc3, 0x04, + 0x3b, 0xa8, 0xd6, 0x04, 0x2c, 0x1b, 0x03, 0xf0, 0x24, 0x98, 0xd6, 0xf9, 0x07, + 0x18, 0x29, 0x0e, 0x17, 0x0c, 0x0a, 0x05, 0xec, 0xfb, 0x0a, 0xfd, 0xfe, 0x00, + 0x26, 0x2e, 0x04, 0x11, 0xe8, 0x13, 0xf8, 0x39, 0xf5, 0xfa, 0xcf, 0xe6, 0xdf, + 0xae, 0x08, 0x36, 0xfe, 0x0d, 0xfb, 0xf1, 0x07, 0x3e, 0x18, 0xeb, 0xfa, 0x13, + 0xf5, 0x03, 0x0f, 0x0d, 0xd9, 0x06, 0x7f, 0xe8, 0x17, 0xf4, 0x14, 0x89, 0xd0, + 0xa2, 0xe1, 0xac, 0xfc, 0xff, 0x6b, 0x17, 0x99, 0xfb, 0xdb, 0xf9, 0xe8, 0xca, + 0xe3, 0x14, 0xf5, 0x3b, 0x10, 0x63, 0x57, 0xc5, 0x0f, 0xf1, 0xcd, 0x1c, 0x0e, + 0x0c, 0xd9, 0x0a, 0x04, 0xfb, 0xfb, 0x4e, 0x24, 0xed, 0x0d, 0x12, 0x3e, 0xd5, + 0x1e, 0xd6, 0x81, 0x3f, 0x08, 0xac, 0x13, 0x3c, 0xec, 0x35, 0xb7, 0xe0, 0x1d, + 0x37, 0xdc, 0x10, 0x62, 0x1c, 0xb2, 0xef, 0x41, 0x2a, 0x3c, 0x17, 0x10, 0xe8, + 0xb9, 0x3c, 0x72, 0xdd, 0xdf, 0x2c, 0xe3, 0x1a, 0x0b, 0x6f, 0xc6, 0xd6, 0xef, + 0xde, 0x3f, 0xe8, 0xe6, 0xb6, 0x19, 0xd9, 0xd4, 0xef, 0x15, 0xcc, 0x0a, 0x55, + 0xdd, 0xfa, 0x24, 0xe8, 0xce, 0x08, 0x2e, 0xf1, 0xbb, 0x4e, 0xfb, 0x1d, 0xfd, + 0xfd, 0x06, 0xe8, 0x18, 0x10, 0x7f, 0xd6, 0x31, 0xf8, 0xc6, 0xe9, 0xc7, 0xf2, + 0x47, 0xe7, 0xfd, 0xe3, 0xc1, 0xdd, 0x0f, 0x3a, 0xb7, 0xba, 0x28, 0xe7, 0x16, + 0x8b, 0xf9, 0x1f, 0x9d, 0xfa, 0x0a, 0x28, 0xe5, 0xca, 0xec, 0x3d, 0x29, 0xb6, + 0x16, 0x0a, 0xfb, 0x17, 0xbf, 0x02, 0x24, 0xce, 0xde, 0x36, 0x7f, 0x13, 0xf0, + 0x83, 0x35, 0x25, 0xe6, 0xfb, 0xf1, 0xd0, 0x05, 0x39, 0x26, 0x02, 0xc8, 0xd6, + 0x5f, 0xde, 0xb9, 0x3c, 0x13, 0xbc, 0x2a, 0x10, 0xd5, 0xad, 0xf2, 0xef, 0x0a, + 0xf6, 0x35, 0xd2, 0xad, 0xd5, 0x0a, 0xf6, 0x0c, 0xb6, 0x7f, 0xd4, 0x24, 0x5a, + 0x93, 0xa6, 0xf7, 0x11, 0x00, 0xf1, 0x35, 0x57, 0x17, 0xc7, 0x3b, 0xc9, 0xdb, + 0x1f, 0xbd, 0xc7, 0x81, 0xf9, 0xb1, 0xd2, 0x2c, 0xec, 0x5b, 0xf0, 0xed, 0x83, + 0x27, 0x26, 0x7d, 0xd5, 0x12, 0xab, 0xd5, 0x36, 0xdf, 0x60, 0x44, 0x3a, 0x47, + 0xdc, 0x25, 0x1b, 0x48, 0xc1, 0xec, 0x02, 0xdd, 0x30, 0x06, 0xfd, 0xf4, 0x1f, + 0x2c, 0xc1, 0xe9, 0xfe, 0xf8, 0x15, 0x12, 0x16, 0x44, 0x11, 0xa5, 0x39, 0xb3, + 0x23, 0x0f, 0xde, 0x1f, 0x25, 0xeb, 0x05, 0xfb, 0x15, 0xe1, 0x71, 0x3b, 0xdc, + 0xf0, 0x32, 0xc9, 0xf4, 0xe1, 0xb3, 0x02, 0x46, 0x36, 0x07, 0x40, 0x6b, 0x1b, + 0xd0, 0x36, 0x1a, 0xe3, 0xa8, 0xc9, 0x77, 0x03, 0xd0, 0xe5, 0x2a, 0x36, 0x31, + 0xc5, 0x0e, 0xe5, 0xf1, 0xc7, 0xfa, 0x7f, 0x2e, 0xe6, 0x0a, 0x16, 0x32, 0xd7, + 0x17, 0x2d, 0xd4, 0xf3, 0xee, 0xe1, 0xc3, 0x29, 0x3e, 0x04, 0xc7, 0xe8, 0xe8, + 0xf8, 0xee, 0xfa, 0xf5, 0xd0, 0xfd, 0xfa, 0xf7, 0xe1, 0x93, 0x16, 0x7f, 0xd8, + 0xcf, 0x06, 0x1a, 0x06, 0xdf, 0xfc, 0x08, 0xfe, 0x22, 0x0a, 0xdd, 0xdf, 0xfe, + 0x19, 0xf5, 0x14, 0x13, 0x5c, 0x08, 0x2c, 0xd3, 0x02, 0xe2, 0x0e, 0xec, 0x23, + 0x0a, 0x19, 0xed, 0xcc, 0x33, 0xe0, 0xff, 0x50, 0xeb, 0x3d, 0x06, 0xe1, 0x06, + 0xad, 0xd5, 0x10, 0x12, 0xec, 0xcf, 0x06, 0x12, 0x5e, 0x1c, 0xd5, 0x1d, 0x0d, + 0x07, 0x12, 0xa6, 0xb9, 0xf4, 0xf8, 0xf6, 0x3f, 0xfd, 0xdd, 0x3a, 0x1a, 0x12, + 0xbc, 0x1b, 0xe6, 0xd7, 0x0f, 0xfb, 0x1f, 0x27, 0x1f, 0xd6, 0xee, 0x27, 0xbb, + 0x42, 0xec, 0x3a, 0x0b, 0xc0, 0xfd, 0x04, 0xe0, 0xe4, 0x22, 0x27, 0xe8, 0x06, + 0x39, 0xdf, 0xfb, 0x17, 0xda, 0xfb, 0xed, 0xea, 0xf6, 0xcb, 0xce, 0x7f, 0x21, + 0xdb, 0x10, 0xf6, 0x47, 0xba, 0xbf, 0x08, 0xc6, 0xdc, 0x2c, 0xeb, 0xdd, 0x03, + 0xdb, 0x27, 0x22, 0x1a, 0xe4, 0x49, 0x23, 0xe8, 0xf5, 0xeb, 0x12, 0xfd, 0x21, + 0xf3, 0xf4, 0xe8, 0xdd, 0xdb, 0x3c, 0xf2, 0x26, 0x30, 0xfd, 0xd5, 0xcc, 0x00, + 0x2b, 0xb9, 0xf0, 0x25, 0x0f, 0xeb, 0xe6, 0xc9, 0x01, 0xf4, 0x07, 0xa1, 0x0e, + 0xfb, 0xe7, 0x11, 0xef, 0x0e, 0xdf, 0x19, 0xec, 0x26, 0x3d, 0x18, 0xd5, 0x81, + 0x28, 0xae, 0x29, 0xa8, 0xf9, 0x4d, 0x0e, 0x0f, 0x21, 0x0b, 0x12, 0xdd, 0xb1, + 0xf1, 0x0e, 0x1e, 0x0e, 0x81, 0xd7, 0xbc, 0x10, 0x0a, 0xf6, 0xe9, 0x05, 0xdd, + 0xe9, 0xe6, 0xf1, 0xfb, 0x55, 0x04, 0xd0, 0xfd, 0xd3, 0xe2, 0x21, 0xc2, 0x19, + 0x13, 0xe1, 0x56, 0xe1, 0x27, 0x0e, 0xf0, 0x09, 0xf8, 0x13, 0x23, 0x58, 0xf7, + 0x1d, 0x08, 0xde, 0x08, 0xfa, 0xfd, 0xbf, 0x1e, 0x51, 0x0a, 0x10, 0xa6, 0xfe, + 0x7f, 0x2d, 0x4c, 0x1c, 0xe6, 0xa3, 0xcf, 0xa5, 0x30, 0xe9, 0xc8, 0xf5, 0x30, + 0xfd, 0x3f, 0xad, 0xcc, 0x12, 0xdb, 0x33, 0xfd, 0xe5, 0xfc, 0x4a, 0x1f, 0x12, + 0x9b, 0xe8, 0xcc, 0xcd, 0x06, 0xd6, 0x0a, 0x42, 0x2e, 0x24, 0xe4, 0xcb, 0x58, + 0xb7, 0x15, 0x2f, 0x01, 0x29, 0xf9, 0xe0, 0x0a, 0x08, 0xeb, 0x1c, 0xa5, 0xf7, + 0xee, 0x9e, 0xd5, 0x43, 0x17, 0x78, 0xfe, 0xf1, 0xa8, 0xd8, 0xdd, 0xed, 0x47, + 0xca, 0xb2, 0xd9, 0x02, 0x7f, 0x08, 0x36, 0xd5, 0xe5, 0x45, 0x13, 0xcf, 0x12, + 0x07, 0xe1, 0x5e, 0x35, 0x48, 0xb5, 0xf8, 0x06, 0xed, 0x63, 0x36, 0x6d, 0x27, + 0xd1, 0xb8, 0x21, 0xde, 0xbd, 0xcd, 0xc9, 0x00, 0xd5, 0x12, 0xf6, 0x17, 0x2e, + 0x8f, 0x21, 0xad, 0x0f, 0xa8, 0xef, 0x20, 0x2f, 0xe2, 0x5d, 0x16, 0x31, 0x51, + 0xcb, 0x19, 0xdd, 0x0b, 0x52, 0xf9, 0xe8, 0xae, 0xdf, 0x4e, 0xd7, 0xe5, 0xd5, + 0x71, 0x68, 0x07, 0x64, 0xd0, 0xfc, 0x27, 0xbe, 0x6a, 0xce, 0x1a, 0xef, 0xe0, + 0x04, 0x15, 0xb1, 0x1e, 0x48, 0x1f, 0xfe, 0xd2, 0x3f, 0x22, 0xb0, 0xb5, 0xd8, + 0x35, 0x2d, 0x81, 0x07, 0xa6, 0xfd, 0x0d, 0x1a, 0xbb, 0xd2, 0x17, 0xec, 0xd7, + 0xf5, 0x12, 0x33, 0x50, 0x58, 0xfe, 0xc7, 0x2b, 0x41, 0xb3, 0x39, 0x27, 0x05, + 0xd3, 0x27, 0xe7, 0x30, 0xb6, 0xb6, 0xe8, 0xb3, 0xe9, 0xd9, 0x22, 0xfb, 0xdb, + 0x05, 0x9c, 0xe0, 0xfd, 0x24, 0x16, 0x1f, 0x05, 0xfe, 0x02, 0x11, 0xe7, 0x09, + 0x09, 0x13, 0x19, 0xfe, 0x7f, 0x11, 0x32, 0xf4, 0xc2, 0x3f, 0x15, 0xff, 0xfb, + 0x3e, 0x0c, 0x13, 0xff, 0x0d, 0xfe, 0xbc, 0x17, 0xe2, 0x05, 0xc2, 0xe7, 0x57, + 0x16, 0xed, 0x19, 0xdd, 0xe6, 0xfb, 0xfb, 0x06, 0x2c, 0xc3, 0x3a, 0xc1, 0xf4, + 0xc8, 0xf4, 0xbe, 0x11, 0xdd, 0x1a, 0xff, 0x02, 0xff, 0x77, 0xb5, 0x1e, 0xef, + 0xfd, 0xa1, 0x4f, 0x5e, 0x23, 0x08, 0xb4, 0xf8, 0xef, 0xbd, 0x01, 0xc9, 0xe8, + 0xe2, 0xfd, 0x4a, 0x1c, 0xfe, 0x1b, 0x06, 0x00, 0xfb, 0x07, 0x0f, 0x00, 0x2d, + 0x46, 0xd3, 0xe9, 0xda, 0xf6, 0xea, 0x30, 0xf4, 0x13, 0x15, 0xce, 0xe2, 0xd5, + 0xba, 0xfb, 0x27, 0xf6, 0xe8, 0x05, 0x7f, 0x0f, 0xd7, 0x03, 0xed, 0xe3, 0xa9, + 0xec, 0xea, 0xc8, 0xce, 0x30, 0x56, 0xc4, 0x0a, 0x35, 0xde, 0xd5, 0x04, 0xd2, + 0x23, 0xee, 0x3d, 0x27, 0xeb, 0xb2, 0x15, 0xf7, 0xf8, 0x91, 0x02, 0xfd, 0x16, + 0x14, 0xd6, 0x22, 0x14, 0xf6, 0xe0, 0xf6, 0xb4, 0x20, 0x0e, 0x0f, 0x38, 0x15, + 0x2e, 0xc3, 0x24, 0xf9, 0xba, 0x21, 0x13, 0x29, 0xe4, 0x1e, 0xf0, 0xd8, 0x23, + 0xe8, 0x23, 0x43, 0xf5, 0xe3, 0x19, 0xc9, 0x45, 0xe1, 0xe4, 0xeb, 0xfa, 0xd8, + 0xfd, 0xae, 0xfd, 0x1d, 0xf5, 0x7f, 0xed, 0x00, 0xd6, 0xd9, 0x3d, 0xc4, 0xb9, + 0x1c, 0x56, 0xe8, 0xbb, 0x40, 0xde, 0xf5, 0x50, 0xfa, 0xf5, 0x04, 0xe4, 0xfe, + 0xfb, 0xfe, 0x3b, 0x20, 0xe0, 0xca, 0x1f, 0xb5, 0xf3, 0xcf, 0xfb, 0xe2, 0x0e, + 0xba, 0xd9, 0x81, 0xbe, 0xf9, 0xcf, 0xc7, 0xb5, 0x4a, 0x19, 0xf9, 0x14, 0xf3, + 0x02, 0x17, 0xf8, 0xfd, 0x34, 0x07, 0xdd, 0xff, 0xf1, 0x0f, 0xfa, 0x01, 0x01, + 0x24, 0x25, 0xc3, 0xf5, 0xd3, 0x06, 0xd5, 0x73, 0x07, 0xb8, 0x23, 0x0b, 0x0f, + 0x1d, 0xc5, 0xef, 0x64, 0x24, 0xde, 0xcc, 0x36, 0xd2, 0x7f, 0x1c, 0x09, 0x9a, + 0xe1, 0xf8, 0xbe, 0xb7, 0xe0, 0x8e, 0x70, 0xde, 0x2c, 0xf8, 0x27, 0xc3, 0xe4, + 0x27, 0xf6, 0x7b, 0x10, 0x02, 0x01, 0x23, 0x52, 0xe8, 0xfc, 0xf5, 0x02, 0x25, + 0x0f, 0xc4, 0xba, 0xd3, 0x3d, 0x15, 0xe0, 0xd6, 0xf8, 0x93, 0x14, 0x0c, 0x4d, + 0x40, 0xf2, 0x2b, 0x19, 0xcd, 0x47, 0x08, 0x08, 0x18, 0x7f, 0x0c, 0xbb, 0x3f, + 0xfa, 0xdf, 0xbc, 0x18, 0x05, 0x3f, 0x1c, 0xc0, 0xea, 0x0d, 0x01, 0xcf, 0xd7, + 0x29, 0xf6, 0x12, 0x13, 0xec, 0x24, 0xc9, 0xc5, 0xf9, 0x15, 0x1e, 0x12, 0xe9, + 0x21, 0x2d, 0xfc, 0x02, 0xfd, 0xf7, 0x07, 0x12, 0xb1, 0xe9, 0xc6, 0x34, 0x2b, + 0x01, 0x0c, 0xb2, 0xf6, 0xfc, 0x0a, 0x11, 0xc6, 0xfc, 0xf3, 0xfd, 0xf5, 0xc6, + 0xe6, 0x39, 0x1c, 0xe3, 0x81, 0xc8, 0xd1, 0x0a, 0xb2, 0xf0, 0xd4, 0xdd, 0x01, + 0xd9, 0x0c, 0xd8, 0xb1, 0x13, 0x0c, 0xcc, 0x29, 0x41, 0x2d, 0x18, 0x09, 0x1c, + 0xfa, 0xdd, 0x15, 0x65, 0xff, 0xf5, 0x0c, 0x4d, 0xa9, 0x32, 0x54, 0x6d, 0x0f, + 0xdd, 0xf9, 0xd4, 0xe0, 0xe5, 0x06, 0xca, 0x0f, 0x38, 0xec, 0xb8, 0x4c, 0x6d, + 0xa4, 0x72, 0x27, 0x5f, 0xfb, 0x2c, 0x28, 0x4d, 0xfa, 0x0d, 0xc2, 0x16, 0xf3, + 0xf6, 0xc8, 0x1b, 0x11, 0xde, 0x18, 0xee, 0x91, 0x98, 0x1e, 0xda, 0x0f, 0x7f, + 0xf6, 0xd3, 0x0d, 0xbd, 0xd8, 0x12, 0xaf, 0x0c, 0x05, 0xf9, 0x3a, 0x30, 0x45, + 0x08, 0xd9, 0xcf, 0xee, 0x1f, 0x7e, 0xe2, 0x18, 0xbd, 0x26, 0xde, 0xf6, 0xfb, + 0x24, 0x1a, 0xdd, 0x0d, 0xe9, 0x08, 0xe5, 0xee, 0x08, 0xd7, 0xd0, 0xc6, 0x14, + 0xf6, 0x19, 0xfc, 0xf4, 0xed, 0x12, 0xfc, 0x0b, 0x02, 0x12, 0xce, 0x1a, 0xca, + 0xd4, 0xe4, 0xcc, 0xdc, 0xb7, 0xfa, 0xa1, 0xb0, 0xca, 0x22, 0x26, 0x3e, 0xe8, + 0xd7, 0x14, 0xe9, 0xeb, 0x16, 0xb0, 0xf9, 0x1e, 0x34, 0xf8, 0xe1, 0x0c, 0x08, + 0xd5, 0x01, 0xf6, 0x47, 0xda, 0x1d, 0x9b, 0xf4, 0x37, 0xe0, 0xf8, 0xbd, 0x0f, + 0x30, 0x44, 0x18, 0x3f, 0x13, 0xfd, 0x0e, 0x1e, 0x09, 0x2e, 0x1b, 0x5d, 0x2b, + 0x04, 0x95, 0xc9, 0x43, 0xfd, 0x34, 0xfa, 0xf8, 0xfe, 0x7f, 0xfa, 0xef, 0xaa, + 0x19, 0xeb, 0xe6, 0xc4, 0xfd, 0xdf, 0xde, 0x2f, 0x43, 0xce, 0x3f, 0xfc, 0xf0, + 0xe0, 0xe2, 0xcd, 0x27, 0xfd, 0xfb, 0x40, 0xe5, 0x04, 0xf0, 0xee, 0xe0, 0x17, + 0x89, 0x0c, 0x2f, 0x19, 0x17, 0xc8, 0x26, 0x0b, 0xfa, 0xfd, 0x7f, 0x06, 0x0b, + 0xe4, 0x47, 0x4c, 0x00, 0x8e, 0xf9, 0xe9, 0x0a, 0x39, 0x1a, 0xe5, 0xea, 0x20, + 0xf2, 0x23, 0x4c, 0x01, 0x0c, 0x09, 0x27, 0xe2, 0xfc, 0x08, 0x15, 0x19, 0x16, + 0x1e, 0xe5, 0xf0, 0xd0, 0xa7, 0xf5, 0xdd, 0x3e, 0x04, 0xf5, 0x3d, 0x24, 0x15, + 0x1b, 0xbf, 0xf4, 0x32, 0x02, 0xed, 0xf3, 0xd5, 0x32, 0xfc, 0x59, 0x81, 0xaa, + 0x3e, 0xf6, 0x21, 0x23, 0xf3, 0x24, 0xcf, 0x33, 0x97, 0xe9, 0x0e, 0xf5, 0xd4, + 0x03, 0xca, 0x49, 0xf9, 0x46, 0xc3, 0xcb, 0xed, 0xef, 0x19, 0xc2, 0x00, 0xff, + 0x01, 0xb3, 0x10, 0x20, 0x17, 0x03, 0xf6, 0xd0, 0xcc, 0x12, 0xf7, 0x26, 0x2f, + 0xd4, 0x66, 0xea, 0x01, 0xba, 0xd7, 0x5f, 0x0d, 0xff, 0x31, 0xe9, 0x20, 0xf6, + 0x7f, 0xe5, 0x15, 0x26, 0xf2, 0xef, 0x05, 0x0f, 0xf8, 0xd9, 0xf7, 0x5e, 0x34, + 0xcb, 0xae, 0x92, 0x5d, 0xe1, 0x0c, 0x16, 0x3b, 0xa1, 0x0f, 0x04, 0xce, 0xb8, + 0x28, 0xd8, 0x54, 0xe1, 0x49, 0x01, 0xed, 0x09, 0xe0, 0x1e, 0xf7, 0xe2, 0x0b, + 0xf3, 0xf3, 0xe1, 0x27, 0xb9, 0x39, 0x17, 0x3e, 0xf1, 0x02, 0x1d, 0x0e, 0x67, + 0x19, 0xbc, 0x17, 0xb3, 0x0d, 0xb4, 0xe0, 0x36, 0xc9, 0x1f, 0x11, 0xe3, 0x2f, + 0xd3, 0xdb, 0xf4, 0x26, 0x0b, 0x13, 0xf1, 0x01, 0xd5, 0x04, 0xd0, 0xdf, 0x26, + 0xc4, 0xb2, 0x2b, 0x33, 0x38, 0xde, 0x41, 0xc2, 0xb6, 0xf4, 0x7f, 0x4f, 0xf0, + 0x00, 0x04, 0xfc, 0x00, 0xbd, 0xed, 0xfc, 0xdb, 0x3b, 0xf9, 0x16, 0xf3, 0xff, + 0x02, 0xfb, 0xf0, 0x1d, 0x2f, 0x10, 0xdf, 0x5f, 0xd9, 0x01, 0xfb, 0xe5, 0x29, + 0x38, 0xde, 0x05, 0xd9, 0xc1, 0xf8, 0xe9, 0x1e, 0xa7, 0x13, 0x01, 0xb8, 0xeb, + 0xb5, 0x2b, 0x29, 0xa7, 0xad, 0xf2, 0xdd, 0xe5, 0x0c, 0x1b, 0xee, 0x58, 0xae, + 0x05, 0x62, 0xd9, 0x12, 0xf2, 0x0f, 0x03, 0x27, 0x00, 0x39, 0xac, 0xb8, 0xef, + 0xcd, 0x02, 0x5f, 0x11, 0x1f, 0xfe, 0xa6, 0x02, 0x13, 0xde, 0x35, 0x18, 0x04, + 0xd0, 0xeb, 0x14, 0xdf, 0x81, 0xed, 0xfb, 0x8c, 0x14, 0xfa, 0xe9, 0x1f, 0x01, + 0x12, 0xe7, 0xc2, 0xd2, 0xea, 0xf0, 0xde, 0xf1, 0xfd, 0x01, 0x14, 0xd7, 0x0d, + 0x08, 0x16, 0x1e, 0xab, 0x3a, 0x0e, 0xe0, 0xf6, 0xf5, 0x1c, 0x50, 0x7f, 0xea, + 0x20, 0x0c, 0xdd, 0xc9, 0xfc, 0xe3, 0x0d, 0xee, 0x15, 0xc7, 0xde, 0x0a, 0x0c, + 0xf9, 0x20, 0xe8, 0xff, 0xda, 0xf9, 0xf0, 0x6a, 0xf2, 0xf7, 0x1d, 0xf6, 0xee, + 0xf0, 0x23, 0xe5, 0x0c, 0xde, 0xd6, 0x4c, 0xe8, 0x0e, 0x91, 0xdf, 0xc9, 0x7f, + 0x3c, 0xa9, 0x3b, 0xcb, 0x38, 0xe2, 0x38, 0x5a, 0xea, 0x16, 0xec, 0x2a, 0x5a, + 0xe1, 0x04, 0x00, 0x13, 0xf8, 0xce, 0x15, 0x38, 0x1a, 0xc8, 0x10, 0x4c, 0x2d, + 0x0c, 0xfa, 0xdb, 0x59, 0x2a, 0xee, 0x0c, 0x9d, 0x47, 0x13, 0x22, 0xa1, 0x5c, + 0xdf, 0xff, 0x97, 0xcb, 0x3d, 0xcc, 0x85, 0xd0, 0x76, 0xf2, 0x9f, 0xe7, 0x04, + 0xd4, 0x32, 0x14, 0x1c, 0x0a, 0x14, 0xe9, 0x2b, 0x9d, 0x66, 0xc4, 0xd5, 0xf0, + 0xda, 0x40, 0x4d, 0x0a, 0xb1, 0x51, 0xf9, 0x29, 0x19, 0x03, 0xb1, 0x1b, 0x4f, + 0xcd, 0x0c, 0xe1, 0x1d, 0x3c, 0x0b, 0x96, 0x43, 0xf6, 0xe4, 0xe3, 0x57, 0xa0, + 0xf8, 0xdd, 0x2d, 0x00, 0xa9, 0x35, 0xdb, 0x5a, 0x56, 0xe2, 0xfb, 0x0a, 0xd6, + 0x23, 0x3b, 0xc5, 0x06, 0xf9, 0xe8, 0x03, 0x01, 0x21, 0xee, 0xe7, 0x0b, 0x7f, + 0xf5, 0x2f, 0x11, 0xf7, 0x7d, 0x0c, 0x53, 0xb4, 0xd4, 0xcd, 0xe6, 0x11, 0x2a, + 0x0d, 0xdc, 0xc6, 0x7f, 0x2a, 0x1a, 0xd6, 0xe8, 0xba, 0xe5, 0x03, 0x14, 0xfc, + 0x00, 0x17, 0x0e, 0x16, 0xed, 0x47, 0x6e, 0xbd, 0xd4, 0xfd, 0x10, 0xfe, 0xcb, + 0xd6, 0x09, 0xeb, 0xe8, 0xea, 0xd9, 0xdb, 0x25, 0x20, 0xcf, 0x15, 0x2e, 0x32, + 0xbf, 0x03, 0xe2, 0xf2, 0xe9, 0xdb, 0x2c, 0xd3, 0xe1, 0xe1, 0xf4, 0xd9, 0xee, + 0x12, 0x18, 0xdf, 0xd8, 0xd8, 0x38, 0xf0, 0x13, 0x59, 0xc6, 0x1a, 0xc6, 0x0f, + 0x0a, 0xe6, 0x04, 0x0b, 0xc4, 0x89, 0xb0, 0xcb, 0x45, 0x1a, 0xf6, 0xfa, 0xd7, + 0x12, 0x19, 0x27, 0xad, 0x33, 0xb0, 0x25, 0x41, 0x33, 0xfc, 0x09, 0x0f, 0x3b, + 0xc1, 0xf2, 0x58, 0xd3, 0xfa, 0xcc, 0xf8, 0x7f, 0x0b, 0xd1, 0xe6, 0x94, 0x12, + 0x1d, 0x78, 0xfe, 0xb6, 0x3c, 0x45, 0xe5, 0x5a, 0x22, 0x2d, 0x05, 0x32, 0xd8, + 0xdc, 0xc5, 0x18, 0x65, 0x0f, 0xc7, 0xdb, 0xf3, 0xa0, 0xdd, 0xf9, 0x31, 0xfe, + 0xe9, 0x08, 0xd0, 0x25, 0xdc, 0x07, 0x1d, 0x1d, 0x00, 0x24, 0x26, 0x7f, 0xf6, + 0x10, 0xdf, 0x3c, 0xf9, 0x0f, 0x13, 0x2e, 0xe4, 0x12, 0xf3, 0xfe, 0x19, 0x00, + 0xf1, 0x43, 0xea, 0x02, 0xd8, 0x1a, 0x08, 0x0f, 0xdd, 0x1c, 0xe1, 0x14, 0xe0, + 0xe2, 0x0f, 0x06, 0xea, 0x05, 0xd7, 0xce, 0xbd, 0xe8, 0x3b, 0xea, 0x22, 0xcc, + 0xf0, 0x18, 0x1a, 0xfd, 0xed, 0xfd, 0xee, 0x81, 0xbe, 0xf7, 0x13, 0xfa, 0xfb, + 0xf5, 0xe8, 0x02, 0xf8, 0x1c, 0x0f, 0x01, 0xf2, 0x13, 0x18, 0x42, 0x08, 0x13, + 0x22, 0x3a, 0xc7, 0xef, 0x07, 0x20, 0xdb, 0xea, 0x0a, 0x19, 0xf9, 0x09, 0x01, + 0x13, 0xfd, 0xe9, 0xdb, 0xf2, 0xfc, 0x0a, 0xf6, 0x04, 0xfd, 0xdf, 0x19, 0xca, + 0xee, 0x1c, 0x05, 0xf2, 0xbb, 0xe8, 0xc1, 0xef, 0x18, 0x16, 0xfe, 0xef, 0x01, + 0xe1, 0xff, 0x19, 0xe4, 0x3e, 0x34, 0xe6, 0x1a, 0xe9, 0x29, 0xe5, 0xdf, 0x1c, + 0x2c, 0xf5, 0x0b, 0x13, 0x20, 0x0a, 0x2c, 0xd9, 0xc7, 0xbb, 0x0b, 0xd6, 0x03, + 0x01, 0xc5, 0xea, 0x57, 0xcd, 0xe7, 0x6b, 0x27, 0xf6, 0x3c, 0x29, 0xf4, 0x30, + 0xf1, 0xd8, 0xc1, 0x02, 0xf7, 0x35, 0xde, 0x7f, 0xec, 0x1f, 0xd0, 0xf5, 0x15, + 0xca, 0x05, 0xdb, 0xd0, 0xf7, 0x16, 0xf1, 0x0a, 0x06, 0x25, 0x07, 0x08, 0xff, + 0x35, 0xce, 0xd1, 0x2c, 0xf5, 0x0c, 0x13, 0xf1, 0x97, 0xe2, 0x13, 0xd9, 0x1b, + 0xf0, 0xf8, 0x18, 0xe6, 0xac, 0x24, 0xf0, 0xa1, 0x37, 0x0c, 0x09, 0x02, 0x31, + 0x40, 0xf5, 0xf9, 0xfa, 0x0e, 0xcd, 0x13, 0xc8, 0x09, 0xeb, 0xd9, 0xe5, 0xe0, + 0x34, 0xf9, 0x81, 0xed, 0xd9, 0xf3, 0xf4, 0x1c, 0x47, 0xf6, 0x08, 0xda, 0xff, + 0x00, 0x19, 0xb9, 0xf7, 0x30, 0xe8, 0xc6, 0xd8, 0xda, 0x01, 0xf5, 0x2b, 0xb1, + 0x57, 0x09, 0xce, 0x09, 0x3f, 0xdb, 0xad, 0xf5, 0xf6, 0xf9, 0x02, 0xdd, 0x21, + 0x3a, 0x81, 0xdf, 0x0d, 0x06, 0x2f, 0xd4, 0x34, 0xdd, 0xf5, 0x45, 0x02, 0xd6, + 0xf5, 0xd8, 0xfa, 0xe1, 0x10, 0xcd, 0x10, 0x2b, 0x09, 0x02, 0xff, 0x07, 0x00, + 0xd7, 0x0d, 0x22, 0xe9, 0x1c, 0xfb, 0x1a, 0xf3, 0x0b, 0xed, 0xa2, 0x1d, 0xd9, + 0xea, 0xfb, 0x33, 0x1d, 0xe3, 0x12, 0x66, 0x98, 0xee, 0x1e, 0x97, 0x10, 0xfb, + 0xc2, 0xef, 0x21, 0x03, 0x57, 0xbc, 0x06, 0x1d, 0x15, 0xee, 0xec, 0xf1, 0xe0, + 0xef, 0xe7, 0x08, 0x10, 0xf8, 0xe7, 0x2c, 0xfa, 0xff, 0x03, 0x37, 0x43, 0x14, + 0x22, 0x09, 0x01, 0xe9, 0x18, 0xd9, 0xf4, 0x0a, 0x1e, 0x13, 0xdf, 0x08, 0x2e, + 0xfa, 0x1e, 0x12, 0x1d, 0xe4, 0xc5, 0x2a, 0x5d, 0xed, 0xff, 0x22, 0xe7, 0x3b, + 0x0b, 0x3b, 0xf8, 0x12, 0x21, 0xf5, 0x0f, 0x31, 0xf0, 0x81, 0xfd, 0xbf, 0x0a, + 0x07, 0x3e, 0x03, 0x25, 0x35, 0xdf, 0xe4, 0xd8, 0xf0, 0xda, 0xa5, 0xc2, 0xc5, + 0xe8, 0xe5, 0x15, 0x2b, 0x0c, 0xf1, 0x0a, 0x22, 0xe6, 0xe2, 0xe5, 0x31, 0xef, + 0x17, 0x40, 0xfa, 0x3b, 0xf6, 0x3e, 0xc1, 0xd1, 0xdf, 0x00, 0x6e, 0x04, 0x7f, + 0xde, 0x13, 0xf7, 0x0e, 0x11, 0x37, 0xed, 0xa8, 0x23, 0x3e, 0x13, 0xe2, 0xec, + 0xfb, 0xf1, 0xef, 0xee, 0x0e, 0x0a, 0xfd, 0x02, 0xfd, 0x1b, 0x8d, 0x81, 0xf8, + 0x42, 0xf8, 0x30, 0x0a, 0xc8, 0xe0, 0x35, 0xe3, 0x20, 0x91, 0xc1, 0x03, 0x16, + 0x12, 0xec, 0xf5, 0xdd, 0x10, 0x04, 0xf4, 0x03, 0xf6, 0x2e, 0x29, 0xfc, 0x0f, + 0x15, 0x3d, 0x27, 0xe5, 0xd1, 0xd8, 0xdc, 0x70, 0xde, 0x12, 0x2e, 0x23, 0x05, + 0x09, 0xe2, 0xb8, 0x1b, 0x62, 0x18, 0x4f, 0x14, 0xfb, 0xd4, 0x12, 0x0c, 0x03, + 0xf3, 0xce, 0x43, 0xef, 0xed, 0x50, 0x3d, 0xb5, 0x1b, 0x09, 0x05, 0x00, 0x81, + 0xfd, 0x13, 0x42, 0xdc, 0xc5, 0x34, 0x1f, 0xf5, 0xe5, 0xc0, 0x47, 0x3f, 0xb7, + 0x29, 0x25, 0xb3, 0xed, 0x1c, 0x34, 0xc2, 0xdf, 0x97, 0xfd, 0xcd, 0xea, 0x2c, + 0x22, 0x1d, 0xc2, 0xd7, 0x95, 0x88, 0x26, 0xe0, 0xe3, 0x31, 0x32, 0x17, 0xe1, + 0x72, 0xcc, 0xfc, 0x93, 0xa9, 0xbf, 0xca, 0xc3, 0xcb, 0xf6, 0x29, 0x85, 0xfe, + 0x36, 0x15, 0x24, 0xac, 0x10, 0x28, 0xdf, 0x01, 0x10, 0x05, 0x0b, 0x0c, 0x74, + 0x2b, 0x09, 0x5d, 0xe9, 0xc6, 0xb5, 0xe7, 0x0f, 0xd5, 0xd9, 0x06, 0x01, 0xfd, + 0xc5, 0x1f, 0xc1, 0x03, 0xc4, 0x0b, 0xb4, 0x59, 0x3a, 0xe2, 0x09, 0xdf, 0xb6, + 0xe7, 0x81, 0xff, 0xdb, 0xcb, 0x4c, 0xdf, 0x0b, 0x28, 0x18, 0xfb, 0xf8, 0x13, + 0xdc, 0x02, 0xfe, 0xee, 0xde, 0xfe, 0xea, 0x19, 0x36, 0xe8, 0xe8, 0x02, 0x0d, + 0xa4, 0xa9, 0x27, 0x0f, 0x01, 0xe3, 0xd9, 0x1f, 0x26, 0xee, 0x17, 0xaa, 0xf9, + 0xff, 0x47, 0xf7, 0x23, 0xde, 0xbe, 0xfb, 0x11, 0xeb, 0xc8, 0x15, 0xce, 0xd5, + 0x0d, 0xe6, 0xe8, 0x15, 0x1b, 0xe7, 0x29, 0x59, 0xbb, 0xc0, 0xef, 0x3c, 0xfb, + 0x28, 0x15, 0x03, 0x27, 0x05, 0x7f, 0xf6, 0xb5, 0xcb, 0x05, 0xae, 0xe4, 0xb7, + 0x0f, 0x0b, 0x5f, 0x4c, 0xcd, 0xd6, 0x36, 0x27, 0x00, 0xc5, 0xfe, 0x13, 0xeb, + 0x07, 0x36, 0x4a, 0xb0, 0xdf, 0xfb, 0xef, 0xff, 0x03, 0x38, 0xb3, 0xaf, 0x0b, + 0x20, 0x0f, 0x01, 0x02, 0xea, 0xe9, 0x2d, 0xc7, 0x17, 0xd7, 0xe3, 0xfe, 0xe8, + 0xc2, 0x06, 0xfc, 0x3f, 0xf9, 0xc2, 0xf4, 0x1a, 0x12, 0x17, 0xf3, 0xe2, 0x32, + 0x07, 0xf5, 0x2d, 0xe3, 0xe5, 0xdc, 0x0a, 0x81, 0x03, 0xf7, 0x17, 0x09, 0xb9, + 0x08, 0x39, 0x6d, 0x2d, 0xe9, 0xef, 0x22, 0xec, 0x2f, 0x52, 0x28, 0xf8, 0xb8, + 0xfe, 0xe2, 0xfc, 0xf7, 0x07, 0x05, 0xff, 0x08, 0x41, 0x30, 0x0f, 0xc8, 0x2e, + 0x05, 0xcf, 0xdb, 0xf2, 0x06, 0xaf, 0xd4, 0xb2, 0x56, 0x30, 0xcd, 0xf5, 0x75, + 0xc5, 0xbc, 0x2a, 0x3f, 0xf9, 0xf9, 0xf4, 0x00, 0x6e, 0x16, 0xec, 0xea, 0x12, + 0xfd, 0x02, 0xf9, 0x93, 0x16, 0xd3, 0xf1, 0xbc, 0x9b, 0xe8, 0xdb, 0x29, 0xea, + 0x2b, 0x13, 0x07, 0xdb, 0x4f, 0xd4, 0x83, 0x0e, 0xdf, 0xfd, 0x7f, 0xd8, 0x1d, + 0xab, 0x08, 0xee, 0xc8, 0xe3, 0x28, 0xc3, 0x25, 0x0a, 0x48, 0x81, 0xf1, 0x02, + 0xcd, 0xea, 0xba, 0xd3, 0xde, 0x02, 0xe2, 0x0d, 0xe8, 0x3e, 0x03, 0x1a, 0xec, + 0x37, 0xcd, 0x03, 0x0f, 0xe8, 0xc5, 0x16, 0x34, 0xc8, 0xf8, 0xf9, 0x1b, 0x92, + 0x1b, 0xfa, 0xca, 0xe6, 0xda, 0x52, 0x08, 0x23, 0x3d, 0x03, 0x30, 0x2b, 0xfd, + 0xe8, 0x5c, 0xe5, 0x22, 0x0d, 0x18, 0xdb, 0x0e, 0x15, 0xb8, 0x1b, 0xe0, 0xd5, + 0xf1, 0xda, 0x15, 0xf4, 0xd2, 0x25, 0xe1, 0xde, 0xbd, 0xcd, 0xd1, 0x0f, 0x1a, + 0x5d, 0x40, 0xd7, 0xf2, 0xe8, 0x45, 0x2a, 0xe8, 0x21, 0x97, 0xe5, 0x22, 0x32, + 0xcd, 0x16, 0xce, 0xb9, 0x2d, 0x12, 0x23, 0x2c, 0x30, 0xc7, 0x4b, 0x33, 0x10, + 0xc1, 0xe5, 0x02, 0xeb, 0xdf, 0xf3, 0xff, 0xf1, 0x2c, 0xff, 0xe6, 0x09, 0x3e, + 0xc6, 0x2c, 0x06, 0xf7, 0x12, 0xdb, 0xe1, 0x04, 0xe0, 0xda, 0xc2, 0xd6, 0xfc, + 0x7f, 0x30, 0xf1, 0x34, 0x05, 0xec, 0x25, 0xdc, 0x2c, 0xf3, 0x2a, 0xf1, 0xf4, + 0xe6, 0xf5, 0x1f, 0xeb, 0x07, 0xd3, 0xf5, 0x11, 0x19, 0x17, 0xef, 0xc3, 0x7f, + 0xf8, 0xd6, 0xf5, 0xf0, 0xd0, 0xe4, 0x19, 0xb8, 0xe6, 0xbb, 0x1b, 0x34, 0xff, + 0xf5, 0xc6, 0xf8, 0x35, 0x46, 0x89, 0x52, 0xe6, 0xf5, 0x08, 0x05, 0x0a, 0x41, + 0x3a, 0xe2, 0xd8, 0xb5, 0xdc, 0xf2, 0xf6, 0x44, 0xc8, 0xca, 0x4e, 0x13, 0xa8, + 0x2f, 0x14, 0x26, 0xef, 0xf1, 0x14, 0x3a, 0xc4, 0x19, 0xef, 0x03, 0x01, 0x2f, + 0x03, 0x13, 0xcf, 0xd1, 0xbb, 0x22, 0xe2, 0xfc, 0x56, 0xee, 0x3d, 0xe9, 0x03, + 0x37, 0x4c, 0xb5, 0xc8, 0x22, 0x22, 0x00, 0xe0, 0xf7, 0x07, 0xcd, 0xcf, 0x14, + 0x01, 0x13, 0xcf, 0x15, 0x1e, 0xd4, 0xf8, 0xdd, 0xfc, 0x27, 0x32, 0x2a, 0xf0, + 0xcb, 0x2b, 0xcc, 0xdd, 0x13, 0x29, 0x09, 0x7f, 0x0f, 0x5d, 0xd7, 0xd5, 0x38, + 0xe0, 0x08, 0xfb, 0x24, 0x88, 0x81, 0xfd, 0xdf, 0x01, 0x00, 0x2e, 0xd8, 0xde, + 0xe9, 0xfa, 0x38, 0xd4, 0x9a, 0x4a, 0x32, 0xfc, 0xf7, 0xe1, 0x10, 0xab, 0xdd, + 0xdb, 0xd8, 0x5f, 0x33, 0xd9, 0x03, 0x1f, 0x1f, 0x25, 0x35, 0xd7, 0xcd, 0xea, + 0x39, 0xf1, 0xd5, 0xc3, 0x2a, 0xa6, 0xf7, 0x38, 0x06, 0xda, 0x19, 0xfc, 0xda, + 0x1b, 0xe1, 0x0b, 0x9b, 0x0b, 0x16, 0x26, 0xa1, 0xb2, 0x0f, 0x02, 0x04, 0x08, + 0x0d, 0x2a, 0x1d, 0xbc, 0x7f, 0xea, 0x14, 0x01, 0x19, 0x0b, 0x2e, 0xd5, 0xf7, + 0xe5, 0x1d, 0xc8, 0x3b, 0x25, 0xfa, 0x5d, 0x17, 0xf2, 0x2e, 0xfe, 0x12, 0xeb, + 0xca, 0xdb, 0xe2, 0x03, 0x2e, 0xcd, 0xfd, 0xfb, 0x11, 0x1a, 0xf2, 0x5b, 0xff, + 0x06, 0xfe, 0xd1, 0x36, 0xe4, 0xf6, 0x14, 0xe8, 0x22, 0x2c, 0x47, 0x21, 0x1f, + 0xd4, 0x26, 0xda, 0x09, 0xf4, 0x58, 0xf3, 0xd5, 0xf4, 0xdb, 0x2a, 0x36, 0x3b, + 0xe5, 0x0a, 0xdf, 0xd5, 0xe8, 0xed, 0x2e, 0x06, 0xc6, 0xd8, 0xf2, 0xfb, 0xfa, + 0xf0, 0xbb, 0x03, 0xf2, 0x02, 0xf7, 0xe3, 0xaa, 0x9f, 0x01, 0x17, 0xf4, 0xb7, + 0xbb, 0x55, 0xe1, 0xba, 0xc4, 0xf7, 0x07, 0xb7, 0x09, 0x08, 0xc7, 0xf6, 0x56, + 0xde, 0x7f, 0x09, 0xd3, 0x5f, 0x48, 0x1d, 0x59, 0x4b, 0xc4, 0x11, 0x03, 0xe7, + 0xb1, 0xab, 0xed, 0xed, 0x48, 0xe1, 0x05, 0xb6, 0x9f, 0xde, 0x1a, 0xac, 0xc9, + 0xeb, 0x04, 0xb4, 0xbd, 0xeb, 0x03, 0xe5, 0xc0, 0x20, 0x1c, 0xe9, 0x46, 0xf6, + 0x37, 0x60, 0xb2, 0x09, 0xc9, 0x2d, 0x1d, 0x79, 0x1a, 0xe4, 0x5d, 0xae, 0x30, + 0x41, 0x26, 0xe9, 0x09, 0xd5, 0x34, 0xe7, 0x15, 0xf3, 0x81, 0xbf, 0x26, 0xb5, + 0x93, 0x5b, 0xdb, 0x1d, 0x0c, 0xd9, 0xf8, 0xac, 0xeb, 0xa9, 0x45, 0x91, 0xa3, + 0x63, 0x01, 0x36, 0xb0, 0xc9, 0x33, 0x15, 0x4e, 0xfd, 0x21, 0xd0, 0x9e, 0xca, + 0xea, 0x44, 0xd9, 0x0b, 0x41, 0xe8, 0x1d, 0xe9, 0xdc, 0x28, 0x1b, 0xe2, 0xc5, + 0x10, 0x33, 0xc9, 0x08, 0x1b, 0x1f, 0x81, 0xed, 0xd8, 0x69, 0xd6, 0x08, 0xbd, + 0x3b, 0x07, 0x98, 0xf8, 0xd6, 0x63, 0x00, 0x1f, 0x0a, 0xbd, 0xf1, 0xf7, 0x00, + 0x21, 0x36, 0x10, 0xc1, 0x21, 0x22, 0x10, 0x5c, 0xd0, 0xf8, 0xbf, 0xd9, 0xf2, + 0x07, 0xe3, 0xf6, 0xca, 0xd6, 0x04, 0x05, 0xe3, 0xdd, 0x4e, 0xf8, 0xb4, 0xef, + 0x9d, 0xfc, 0x31, 0xd1, 0xdc, 0xe7, 0xd0, 0xc9, 0x7f, 0xea, 0xde, 0x21, 0x28, + 0x32, 0x10, 0xff, 0xe8, 0xc1, 0x1c, 0x1a, 0x0f, 0x51, 0xae, 0xcf, 0x0d, 0xbe, + 0x0a, 0xf2, 0x28, 0x02, 0xfe, 0xfb, 0xca, 0xb8, 0xdb, 0x9c, 0x0a, 0xcc, 0xdc, + 0x9a, 0xfb, 0x8d, 0x8c, 0xef, 0x0b, 0x1f, 0x48, 0xc8, 0x27, 0x10, 0xaf, 0x26, + 0x1a, 0x31, 0x88, 0xae, 0x1f, 0x1a, 0x07, 0x09, 0xbb, 0xc0, 0xd5, 0x7f, 0x02, + 0xdd, 0xac, 0x6b, 0x10, 0xfc, 0x2a, 0x2a, 0xf2, 0x21, 0xe2, 0xc7, 0x9c, 0x1d, + 0x15, 0xfd, 0xf1, 0x37, 0xa4, 0x41, 0xe6, 0x1e, 0xf5, 0x42, 0x03, 0xf9, 0x14, + 0xee, 0xb9, 0x44, 0x7c, 0xfa, 0x16, 0xf8, 0x78, 0xff, 0x10, 0xa1, 0xd1, 0x40, + 0x11, 0xc6, 0xd2, 0x08, 0x10, 0xe3, 0xef, 0x16, 0x26, 0xe1, 0x1e, 0x1c, 0x46, + 0x31, 0x0b, 0x3a, 0x10, 0x93, 0x0a, 0xe6, 0x33, 0x26, 0x10, 0xef, 0x07, 0xf5, + 0xf1, 0x03, 0x12, 0xc1, 0xcc, 0x25, 0x0a, 0x1f, 0xe8, 0x1b, 0xce, 0x17, 0x28, + 0x0f, 0x0a, 0x33, 0xd0, 0x06, 0x2f, 0xf2, 0x01, 0xf2, 0xe8, 0xdd, 0xd8, 0xff, + 0x02, 0xfe, 0xd2, 0x09, 0xf3, 0x81, 0xe5, 0xf8, 0xf8, 0x1e, 0x35, 0xd4, 0xf5, + 0xf0, 0x42, 0xed, 0xc3, 0x04, 0x00, 0x17, 0xef, 0x2d, 0x1d, 0xdf, 0xc6, 0xfe, + 0xf4, 0xf7, 0x46, 0x08, 0xe2, 0xee, 0xf1, 0xd2, 0x04, 0xf7, 0x24, 0xd5, 0xdf, + 0xf6, 0xd8, 0xeb, 0xd6, 0x08, 0xec, 0x0e, 0xc8, 0x1e, 0xe8, 0x09, 0x05, 0xb3, + 0xf9, 0xfe, 0xe8, 0xe8, 0xe5, 0xe5, 0x39, 0x7f, 0xa4, 0x34, 0x45, 0xc3, 0xcc, + 0xfc, 0xec, 0xe5, 0xf0, 0xf7, 0xf2, 0x05, 0x00, 0x29, 0x0a, 0x09, 0x01, 0x38, + 0x02, 0xdd, 0xdc, 0x32, 0xe1, 0xd3, 0xe7, 0xf5, 0xbc, 0xf3, 0xf9, 0xe5, 0x2e, + 0xeb, 0xeb, 0xee, 0xe9, 0x34, 0xd5, 0x01, 0xda, 0xe3, 0xc3, 0xae, 0x38, 0xbf, + 0xde, 0xeb, 0x0a, 0x6c, 0x23, 0x72, 0x01, 0xfd, 0xc5, 0x41, 0x35, 0x18, 0x01, + 0x7f, 0x15, 0xe5, 0xbb, 0x3d, 0xd6, 0xe9, 0xd2, 0x26, 0xc1, 0xef, 0xf9, 0x37, + 0xbc, 0xb8, 0x31, 0x4d, 0x0e, 0x42, 0xef, 0x46, 0x0d, 0x3f, 0x23, 0xfd, 0xc0, + 0xd6, 0xeb, 0x24, 0xf3, 0x45, 0x63, 0x15, 0xdc, 0xe5, 0x1a, 0xe4, 0x17, 0xfe, + 0x15, 0x0f, 0x03, 0xf1, 0xee, 0xfd, 0xec, 0x1b, 0x3a, 0xbc, 0xb4, 0xfd, 0x23, + 0x25, 0x01, 0xe5, 0x81, 0x10, 0xf0, 0xe9, 0x32, 0xf4, 0x15, 0x0e, 0xd9, 0x23, + 0xbb, 0xfd, 0x3d, 0x06, 0x0e, 0x12, 0xa4, 0x0f, 0xcb, 0xfd, 0x0c, 0x0a, 0x0c, + 0xee, 0x06, 0xa3, 0x00, 0x08, 0x20, 0x2e, 0x4f, 0xee, 0x0f, 0x41, 0x38, 0xe6, + 0xcc, 0x16, 0x42, 0xc0, 0xcc, 0x20, 0x1c, 0x0b, 0x00, 0x1b, 0xde, 0x47, 0xd8, + 0x08, 0xe3, 0x37, 0xfb, 0xfd, 0xdb, 0xc9, 0x08, 0xe9, 0x06, 0xc4, 0x10, 0xf2, + 0xe9, 0xe0, 0xcd, 0xda, 0x04, 0x01, 0x1e, 0x11, 0xd1, 0xb9, 0xff, 0x1c, 0xde, + 0x14, 0xdd, 0xe7, 0x4e, 0x01, 0xeb, 0xb2, 0x61, 0x2c, 0x4b, 0x02, 0xd9, 0x09, + 0xde, 0xc8, 0x06, 0x22, 0x0e, 0x03, 0xe2, 0xf7, 0x18, 0xf0, 0xfe, 0xd2, 0xf7, + 0xe2, 0x2c, 0x1b, 0x2e, 0xf9, 0xf1, 0xdc, 0x18, 0x02, 0x81, 0xe9, 0x06, 0xc5, + 0x22, 0x52, 0x89, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x78, 0xd8, 0xff, 0xff, 0x28, 0x26, 0x00, 0x00, 0xc4, 0x0d, 0x00, 0x00, 0xd4, + 0x0e, 0x00, 0x00, 0xf0, 0x1a, 0x00, 0x00, 0x24, 0x27, 0x00, 0x00, 0x00, 0xd6, + 0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0xbd, 0xd6, 0xff, 0xff, 0x0c, 0xf2, 0xff, + 0xff, 0xbd, 0x01, 0x00, 0x00, 0xb6, 0x03, 0x00, 0x00, 0xce, 0xe2, 0xff, 0xff, + 0x78, 0x5d, 0x00, 0x00, 0x93, 0x50, 0x00, 0x00, 0xb4, 0xd4, 0xff, 0xff, 0x18, + 0xfb, 0xff, 0xff, 0x2c, 0x06, 0x00, 0x00, 0xa4, 0x4b, 0x00, 0x00, 0x3e, 0x59, + 0x00, 0x00, 0x9f, 0x3f, 0x00, 0x00, 0x71, 0x21, 0x00, 0x00, 0xc5, 0x3e, 0x00, + 0x00, 0xc6, 0xc0, 0xff, 0xff, 0x21, 0x18, 0x00, 0x00, 0xd1, 0x7a, 0x00, 0x00, + 0xe1, 0xe7, 0xff, 0xff, 0x83, 0x29, 0x00, 0x00, 0xb5, 0x26, 0x00, 0x00, 0xf0, + 0x33, 0x00, 0x00, 0x96, 0x5a, 0x00, 0x00, 0x15, 0x1d, 0x00, 0x00, 0x21, 0xf2, + 0xff, 0xff, 0xd9, 0x3e, 0x00, 0x00, 0xec, 0x04, 0x00, 0x00, 0x8c, 0xe4, 0xff, + 0xff, 0xa8, 0xf6, 0xff, 0xff, 0x16, 0x43, 0x00, 0x00, 0xdf, 0xd2, 0xff, 0xff, + 0xf7, 0x06, 0x00, 0x00, 0x3a, 0x2d, 0x00, 0x00, 0x3f, 0x34, 0x00, 0x00, 0x1d, + 0x27, 0x00, 0x00, 0x16, 0x4e, 0x00, 0x00, 0x28, 0x11, 0x00, 0x00, 0x8c, 0x03, + 0x00, 0x00, 0x1f, 0x43, 0x00, 0x00, 0x1c, 0xd5, 0xff, 0xff, 0x3a, 0x11, 0x00, + 0x00, 0x4b, 0x3e, 0x00, 0x00, 0x43, 0x1d, 0x00, 0x00, 0xcf, 0x27, 0x00, 0x00, + 0x60, 0xc6, 0xff, 0xff, 0xc1, 0xcd, 0xff, 0xff, 0x97, 0x18, 0x00, 0x00, 0x57, + 0x22, 0x00, 0x00, 0x05, 0x24, 0x00, 0x00, 0x85, 0x15, 0x00, 0x00, 0x16, 0x10, + 0x00, 0x00, 0x50, 0xd2, 0xff, 0xff, 0x04, 0xff, 0xff, 0xff, 0x9f, 0xf9, 0xff, + 0xff, 0x9a, 0x58, 0x00, 0x00, 0x1c, 0xed, 0xff, 0xff, 0x8d, 0x21, 0x00, 0x00, + 0xd1, 0x34, 0x00, 0x00, 0x54, 0x5c, 0x00, 0x00, 0x29, 0xf5, 0xff, 0xff, 0x91, + 0x2b, 0x00, 0x00, 0x27, 0x0d, 0x00, 0x00, 0x72, 0x15, 0x00, 0x00, 0xc2, 0x15, + 0x00, 0x00, 0xcf, 0xce, 0xff, 0xff, 0x34, 0x20, 0x00, 0x00, 0xb3, 0x07, 0x00, + 0x00, 0x02, 0x6c, 0x00, 0x00, 0x86, 0x41, 0x00, 0x00, 0xf2, 0x2e, 0x00, 0x00, + 0x32, 0xc9, 0xff, 0xff, 0x1d, 0xf4, 0xff, 0xff, 0x1d, 0xfc, 0xff, 0xff, 0xf9, + 0x1c, 0x00, 0x00, 0x40, 0xfa, 0xff, 0xff, 0x1d, 0x59, 0x00, 0x00, 0x26, 0x0e, + 0x00, 0x00, 0x5b, 0x0e, 0x00, 0x00, 0x68, 0x08, 0x00, 0x00, 0xed, 0x54, 0x00, + 0x00, 0x83, 0x07, 0x00, 0x00, 0xf2, 0x1f, 0x00, 0x00, 0x1b, 0x32, 0x00, 0x00, + 0xd0, 0xf1, 0xff, 0xff, 0x33, 0x0f, 0x00, 0x00, 0x37, 0x54, 0x00, 0x00, 0x66, + 0x15, 0x00, 0x00, 0x0d, 0xea, 0xff, 0xff, 0x82, 0xdc, 0xff, 0xff, 0xd7, 0x34, + 0x00, 0x00, 0x98, 0xf7, 0xff, 0xff, 0x6c, 0x13, 0x00, 0x00, 0xfd, 0x46, 0x00, + 0x00, 0x82, 0xe1, 0xff, 0xff, 0xca, 0x54, 0x00, 0x00, 0xaf, 0x29, 0x00, 0x00, + 0x22, 0xf5, 0xff, 0xff, 0x89, 0x13, 0x00, 0x00, 0x9c, 0xf1, 0xff, 0xff, 0xcd, + 0x8d, 0x00, 0x00, 0x2a, 0x41, 0x00, 0x00, 0x86, 0x0d, 0x00, 0x00, 0x44, 0x2a, + 0x00, 0x00, 0x7d, 0x3f, 0x00, 0x00, 0x6c, 0x25, 0x00, 0x00, 0x7f, 0x0e, 0x00, + 0x00, 0xbd, 0x2b, 0x00, 0x00, 0x3c, 0x04, 0x00, 0x00, 0xf2, 0x4b, 0x00, 0x00, + 0x11, 0xee, 0xff, 0xff, 0x0c, 0x3c, 0x00, 0x00, 0x42, 0x45, 0x00, 0x00, 0x10, + 0x45, 0x00, 0x00, 0xa7, 0x7f, 0x00, 0x00, 0x3b, 0xf5, 0xff, 0xff, 0x19, 0x2e, + 0x00, 0x00, 0xbd, 0x41, 0x00, 0x00, 0xd7, 0xd8, 0xff, 0xff, 0xbd, 0x30, 0x00, + 0x00, 0x77, 0x55, 0x00, 0x00, 0x5e, 0x8b, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x80, 0x04, 0x00, 0x00, 0xa6, 0xde, 0xf3, 0xa5, 0xde, 0xdb, 0xc4, 0xf3, 0x2a, + 0xd5, 0xdf, 0x81, 0x02, 0xe1, 0xd8, 0x0c, 0xc8, 0x19, 0xca, 0x11, 0xc6, 0xd7, + 0x37, 0x7f, 0x23, 0xd5, 0x0a, 0x10, 0x81, 0x15, 0xab, 0x9c, 0xef, 0x9b, 0x94, + 0xe8, 0xb2, 0x3f, 0x51, 0xe5, 0x0c, 0x23, 0xed, 0x32, 0xb7, 0x81, 0x85, 0x17, + 0x03, 0x0c, 0xb9, 0xba, 0x81, 0xfb, 0x0d, 0xeb, 0x10, 0x7f, 0x35, 0xee, 0x00, + 0xbb, 0x08, 0xe8, 0xe6, 0xe3, 0xe4, 0xd9, 0x32, 0x7f, 0x36, 0xe2, 0x28, 0x48, + 0xdc, 0xe6, 0x8c, 0xc4, 0x49, 0xae, 0xc9, 0xf4, 0xf2, 0xe8, 0xee, 0x7f, 0xf3, + 0xa1, 0xa6, 0xec, 0x07, 0x56, 0x7f, 0xf8, 0x39, 0xb6, 0xdf, 0x05, 0x64, 0xdd, + 0x63, 0x18, 0xea, 0xba, 0xea, 0x73, 0x32, 0x99, 0x41, 0x02, 0x09, 0xee, 0xe2, + 0x05, 0xeb, 0xde, 0xed, 0xfe, 0x04, 0xcd, 0xf8, 0x99, 0x5a, 0xe1, 0xcb, 0x32, + 0x33, 0xae, 0x3b, 0x41, 0x03, 0x3a, 0x84, 0x42, 0x81, 0xb6, 0x57, 0x0e, 0xa6, + 0x4a, 0x0d, 0xcd, 0x34, 0x8e, 0x7f, 0x7f, 0x57, 0xe8, 0x16, 0xcb, 0x7f, 0x35, + 0xd5, 0xb4, 0x27, 0x5d, 0xad, 0x8f, 0xe4, 0xb9, 0x35, 0xcd, 0xc9, 0xfb, 0x9f, + 0x7f, 0x7f, 0xb4, 0x69, 0xd2, 0x62, 0x7f, 0xb1, 0xd6, 0xd4, 0xd0, 0x7f, 0x29, + 0xed, 0xd9, 0x70, 0x03, 0xad, 0xc7, 0x17, 0x5a, 0x2e, 0xe1, 0x01, 0x24, 0xb8, + 0x17, 0xd1, 0xf4, 0xe5, 0x61, 0x59, 0xed, 0xf0, 0x11, 0x7f, 0xe5, 0x1d, 0xb7, + 0xf9, 0x91, 0x43, 0xf8, 0xe9, 0xac, 0xf4, 0x9c, 0xab, 0x65, 0x23, 0x53, 0xd4, + 0xfb, 0x4c, 0xdc, 0x65, 0xa5, 0x49, 0xd6, 0x22, 0x7f, 0x7f, 0xd0, 0xbb, 0xd4, + 0x0f, 0x81, 0x81, 0x7f, 0xe2, 0x81, 0x26, 0xcc, 0x7f, 0x10, 0xc4, 0xf9, 0x8c, + 0xff, 0xd2, 0xd8, 0x7f, 0xcf, 0xd3, 0x81, 0x7f, 0x81, 0xcb, 0x7f, 0x7f, 0x81, + 0x0a, 0x18, 0xe2, 0x17, 0x81, 0x14, 0xb5, 0x44, 0xe3, 0xc4, 0xdd, 0x4b, 0xf0, + 0xe7, 0xd3, 0x83, 0x39, 0x20, 0x20, 0xf1, 0x04, 0xf3, 0x11, 0x2d, 0xe8, 0x81, + 0xd5, 0xf4, 0xa0, 0x04, 0xb1, 0x0a, 0x10, 0xc4, 0x9d, 0xfe, 0xbc, 0x24, 0x65, + 0xe8, 0x8a, 0x15, 0xc9, 0xa4, 0xbc, 0x81, 0x81, 0xe7, 0xcc, 0xe1, 0xda, 0xc3, + 0x56, 0x0c, 0x9b, 0xd8, 0xfa, 0xc3, 0x03, 0xe7, 0x07, 0x28, 0xff, 0xf1, 0xfd, + 0xc1, 0xf0, 0x3a, 0xae, 0x7c, 0xff, 0xe0, 0x0f, 0xd8, 0x08, 0xdc, 0x6e, 0xd4, + 0x26, 0xe0, 0x7f, 0xf7, 0x00, 0x2e, 0xdf, 0x00, 0xf8, 0x48, 0xa4, 0xf8, 0xea, + 0xbd, 0x2b, 0xd6, 0x11, 0xe0, 0xe1, 0x1a, 0x03, 0x0d, 0xba, 0x23, 0xe7, 0xc3, + 0xe9, 0x5a, 0xd0, 0xa2, 0x2b, 0xff, 0xe8, 0xee, 0xdb, 0x01, 0xe1, 0xc1, 0xe9, + 0x13, 0xfd, 0x53, 0x67, 0xb2, 0xe2, 0xe3, 0x38, 0x5b, 0x04, 0xb9, 0xbb, 0x17, + 0x17, 0x81, 0xce, 0x32, 0xe6, 0x48, 0x19, 0x3b, 0x35, 0xb7, 0x0b, 0x00, 0xa9, + 0xb2, 0xe5, 0xcb, 0xec, 0x7f, 0xe1, 0xd6, 0xd3, 0x37, 0xe1, 0xc0, 0xa5, 0xbd, + 0xc6, 0x0b, 0xbd, 0xaa, 0x6a, 0x7f, 0x35, 0xe2, 0xaf, 0xf1, 0xea, 0xb1, 0xf9, + 0x7f, 0x7f, 0x4d, 0xbc, 0xa7, 0x29, 0x7f, 0xd4, 0xff, 0x20, 0x32, 0x8b, 0x78, + 0xa7, 0xc6, 0x17, 0xe8, 0xa8, 0xcf, 0xbf, 0xbb, 0x7f, 0x7f, 0xc3, 0xaa, 0x35, + 0xf2, 0x54, 0xda, 0x7f, 0xfb, 0x15, 0xdc, 0xaf, 0xff, 0x91, 0xb2, 0x08, 0xf1, + 0xf1, 0x1f, 0xe3, 0xa2, 0xbc, 0xdc, 0x01, 0xec, 0x07, 0xf1, 0x33, 0x7a, 0x28, + 0xeb, 0x7f, 0x32, 0x0b, 0xe4, 0xe3, 0x7f, 0x98, 0xc8, 0xda, 0x90, 0xce, 0xde, + 0x3d, 0x92, 0x85, 0xf8, 0xe6, 0x0d, 0xcd, 0xcb, 0xb7, 0xeb, 0xb8, 0x7f, 0x24, + 0xe8, 0xfb, 0x92, 0x11, 0x96, 0x47, 0xca, 0xe0, 0xac, 0x7f, 0x7f, 0x4e, 0x11, + 0xdc, 0x7f, 0xa4, 0x81, 0x7f, 0x7f, 0xf2, 0x3f, 0x7f, 0x7f, 0x81, 0x01, 0xdd, + 0xe3, 0x7f, 0xd5, 0x7f, 0xca, 0xed, 0x4c, 0x07, 0xaa, 0x06, 0x7f, 0xd2, 0x7f, + 0x81, 0x81, 0x7f, 0x30, 0x7f, 0xaf, 0xca, 0xc9, 0xfd, 0x81, 0x7f, 0x2c, 0x1d, + 0x7e, 0x81, 0x95, 0x48, 0xe3, 0x1f, 0x58, 0x7f, 0x7f, 0x24, 0x7f, 0x81, 0x81, + 0x7f, 0xdd, 0xf1, 0x93, 0xef, 0x8e, 0xb0, 0xfb, 0x81, 0x81, 0x7f, 0x7f, 0x7f, + 0xe9, 0x1d, 0x7f, 0x36, 0x81, 0x7f, 0x7f, 0xa6, 0x81, 0x7f, 0x81, 0xa2, 0x7f, + 0x22, 0x81, 0x81, 0xa3, 0x7f, 0x7f, 0x6e, 0x7f, 0x7f, 0xe4, 0x04, 0x81, 0xfb, + 0xff, 0x7f, 0x02, 0x72, 0xdb, 0x16, 0xc2, 0xed, 0xdf, 0x9d, 0xb4, 0x34, 0xaa, + 0x81, 0x7f, 0xea, 0x7f, 0x81, 0xcc, 0x81, 0x7f, 0x81, 0xfd, 0x5c, 0xd2, 0x7f, + 0x15, 0x55, 0xbc, 0x04, 0xf4, 0xe7, 0xb3, 0x67, 0x1e, 0x1e, 0x6f, 0x4c, 0x39, + 0xe6, 0x56, 0x39, 0x1c, 0x51, 0xf4, 0x09, 0xe8, 0xa8, 0x53, 0x29, 0xc6, 0xfa, + 0x13, 0xe3, 0xf6, 0xbd, 0xf6, 0x75, 0xa9, 0x81, 0xc9, 0xbf, 0xf3, 0xc1, 0x17, + 0xd3, 0x1c, 0x2a, 0x03, 0xd2, 0x1c, 0xc8, 0xd2, 0x0f, 0x6c, 0xa7, 0xea, 0x33, + 0xab, 0x3a, 0xe6, 0xe3, 0xe4, 0xf9, 0x26, 0x65, 0x19, 0xb2, 0xd0, 0x23, 0xfe, + 0x1c, 0x11, 0xe2, 0xee, 0xf4, 0xcb, 0xb0, 0xd2, 0x0f, 0x23, 0xc3, 0xfd, 0x63, + 0x0e, 0x04, 0xb7, 0x35, 0xfe, 0x7f, 0x84, 0x4d, 0x05, 0x64, 0xe2, 0xf0, 0x26, + 0xa9, 0xbc, 0x2f, 0xf6, 0xe8, 0xef, 0x1c, 0xcd, 0xc6, 0xc0, 0xab, 0x8f, 0x16, + 0xec, 0xe6, 0xe3, 0x7f, 0x40, 0xe9, 0x9d, 0xb6, 0xdb, 0xaa, 0xad, 0x83, 0xf8, + 0x08, 0xf3, 0xd9, 0x7f, 0xd4, 0xc4, 0x19, 0x8c, 0x0f, 0x7f, 0xb9, 0x92, 0x10, + 0x97, 0x7f, 0xce, 0xd6, 0x9d, 0x06, 0x0c, 0xfb, 0xd9, 0xf2, 0x1b, 0xe2, 0xf0, + 0xcc, 0x34, 0x7f, 0xd6, 0xe1, 0x03, 0xf2, 0xb1, 0xf0, 0xdf, 0x09, 0x21, 0xf7, + 0x4e, 0xff, 0x24, 0xfa, 0xe1, 0xcb, 0xf5, 0xcc, 0xdc, 0xc4, 0xf7, 0xf5, 0x4b, + 0xfb, 0x3f, 0xef, 0xab, 0xe4, 0xf8, 0x08, 0xea, 0x64, 0xfc, 0x2d, 0x17, 0x0c, + 0x19, 0xdd, 0xa7, 0x35, 0x08, 0xa6, 0x09, 0xfa, 0xfc, 0x02, 0xef, 0xb2, 0x72, + 0x31, 0xc9, 0xff, 0x1c, 0xde, 0xa8, 0x05, 0xfe, 0xb5, 0xc9, 0x0a, 0xdd, 0xfd, + 0x17, 0x2d, 0xfd, 0xe4, 0xe0, 0xe9, 0x06, 0xf2, 0xf8, 0x10, 0xc2, 0xed, 0xde, + 0xc7, 0x0d, 0x4c, 0xf1, 0xf3, 0x7f, 0xd2, 0x08, 0x23, 0x1e, 0xdc, 0xf6, 0xfb, + 0x5c, 0x95, 0x2a, 0x16, 0xe4, 0xc9, 0xdb, 0x7f, 0xed, 0x55, 0xff, 0x06, 0xdb, + 0xe3, 0xe6, 0xda, 0xe9, 0xb2, 0x3d, 0xc9, 0xef, 0x43, 0x9d, 0xf5, 0xdc, 0x12, + 0x06, 0xd8, 0xc7, 0x5f, 0xf4, 0x7f, 0x29, 0x43, 0x4e, 0xd3, 0x12, 0x4a, 0x5a, + 0x06, 0xe9, 0x31, 0xf3, 0x90, 0x7f, 0xac, 0xf8, 0xd1, 0xce, 0xf4, 0x7f, 0xe1, + 0x34, 0x7f, 0xdf, 0xa9, 0xfc, 0x01, 0x39, 0xc5, 0xff, 0x52, 0x06, 0x57, 0x7f, + 0x81, 0xb5, 0x92, 0xae, 0xed, 0x0a, 0x03, 0xeb, 0xb7, 0xbb, 0x63, 0x0f, 0x52, + 0x7f, 0x46, 0x46, 0xe1, 0xd7, 0x5f, 0xb4, 0x10, 0xee, 0x81, 0x52, 0x7f, 0x81, + 0xeb, 0xc3, 0xa3, 0xc2, 0xfd, 0xfc, 0x9d, 0x00, 0x5a, 0x0f, 0x20, 0xae, 0xae, + 0xfa, 0xdb, 0x2e, 0xd2, 0xa4, 0x0c, 0x1d, 0x7f, 0xb3, 0xd5, 0xc3, 0x0c, 0xef, + 0x7f, 0xf2, 0xf4, 0xd1, 0xbb, 0xab, 0x23, 0x7f, 0x43, 0x0d, 0xf8, 0xec, 0x40, + 0x7f, 0x7f, 0xdf, 0xf0, 0xf3, 0x1b, 0xd9, 0xe3, 0x59, 0xbc, 0xe5, 0xc4, 0xed, + 0x0b, 0x08, 0xc4, 0x02, 0xf3, 0xe3, 0x3f, 0xbd, 0xc8, 0xf1, 0xbf, 0xc5, 0xdb, + 0xdf, 0x4d, 0xd9, 0x05, 0xf1, 0x29, 0x3e, 0xe3, 0xf7, 0xfe, 0x19, 0x15, 0x0c, + 0xe2, 0x02, 0x00, 0x63, 0xda, 0xd6, 0xf9, 0xe7, 0x01, 0x2a, 0x0d, 0xe7, 0x77, + 0xee, 0xae, 0xeb, 0xcb, 0xf3, 0xe0, 0xfc, 0x2d, 0xfb, 0xfe, 0x04, 0x1a, 0xc5, + 0xbd, 0xf0, 0x46, 0xfa, 0x93, 0x02, 0x1d, 0xfd, 0xfe, 0xf4, 0xd2, 0x0c, 0x23, + 0x01, 0x0b, 0xc9, 0x20, 0xf0, 0xfe, 0xff, 0x99, 0x7f, 0xfb, 0xeb, 0xea, 0xef, + 0xfe, 0xb6, 0xf9, 0x11, 0xca, 0xa1, 0xd9, 0xe6, 0xf2, 0xc4, 0xd9, 0xf8, 0x12, + 0xa3, 0xfc, 0x1c, 0x03, 0xdf, 0x1e, 0xc5, 0xe3, 0xce, 0xd6, 0xf8, 0x23, 0xe9, + 0x02, 0x91, 0xd2, 0xee, 0xee, 0x3c, 0x0b, 0xec, 0xde, 0xd5, 0x4d, 0x13, 0x25, + 0xf7, 0xa1, 0xd1, 0xca, 0xfb, 0xd1, 0xf6, 0x07, 0xea, 0xd6, 0x28, 0xf0, 0xd6, + 0x0b, 0xca, 0xc3, 0xfd, 0xb4, 0xb1, 0xf7, 0xc8, 0xda, 0x05, 0xf6, 0xd0, 0xea, + 0x8f, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xab, 0xe6, + 0xff, 0xff, 0x26, 0x01, 0x00, 0x00, 0xae, 0x02, 0x00, 0x00, 0x85, 0xe8, 0xff, + 0xff, 0xb4, 0xeb, 0xff, 0xff, 0xd0, 0xf5, 0xff, 0xff, 0x1e, 0x0f, 0x00, 0x00, + 0x6b, 0xeb, 0xff, 0xff, 0x4b, 0xe6, 0xff, 0xff, 0xe5, 0xe6, 0xff, 0xff, 0x2e, + 0xf1, 0xff, 0xff, 0x46, 0x01, 0x00, 0x00, 0xa6, 0x15, 0x00, 0x00, 0x32, 0xfe, + 0xff, 0xff, 0x8a, 0x09, 0x00, 0x00, 0xf4, 0xeb, 0xff, 0xff, 0xa7, 0xf8, 0xff, + 0xff, 0xeb, 0xfa, 0xff, 0xff, 0xd0, 0x1f, 0x00, 0x00, 0x0c, 0x24, 0x00, 0x00, + 0x9b, 0xfc, 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0x77, 0xe0, 0xff, 0xff, 0x9a, + 0xef, 0xff, 0xff, 0x19, 0x08, 0x00, 0x00, 0x67, 0x22, 0x00, 0x00, 0xe0, 0x17, + 0x00, 0x00, 0xb6, 0xe9, 0xff, 0xff, 0xbc, 0xef, 0xff, 0xff, 0x33, 0xff, 0xff, + 0xff, 0x8b, 0xf9, 0xff, 0xff, 0x52, 0xdb, 0xff, 0xff, 0x91, 0x0c, 0x00, 0x00, + 0x14, 0xff, 0xff, 0xff, 0x1e, 0xf4, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0xf3, + 0xe5, 0xff, 0xff, 0x29, 0xf1, 0xff, 0xff, 0x15, 0x14, 0x00, 0x00, 0x10, 0x23, + 0x00, 0x00, 0xd7, 0x17, 0x00, 0x00, 0xfc, 0x29, 0x00, 0x00, 0x12, 0x15, 0x00, + 0x00, 0x92, 0xf9, 0xff, 0xff, 0xbb, 0x13, 0x00, 0x00, 0x45, 0xe5, 0xff, 0xff, + 0x26, 0xf6, 0xff, 0xff, 0x32, 0xf9, 0xff, 0xff, 0x46, 0x0c, 0x00, 0x00, 0x0e, + 0x2a, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x78, 0xf5, 0xff, 0xff, 0xaa, 0xf0, + 0xff, 0xff, 0x22, 0xec, 0xff, 0xff, 0xbe, 0x21, 0x00, 0x00, 0x5d, 0xf9, 0xff, + 0xff, 0xea, 0xe7, 0xff, 0xff, 0xb7, 0x2f, 0x00, 0x00, 0xce, 0xf8, 0xff, 0xff, + 0x90, 0x2e, 0x00, 0x00, 0xe5, 0x26, 0x00, 0x00, 0xe1, 0xf2, 0xff, 0xff, 0x33, + 0xf9, 0xff, 0xff, 0x9f, 0x14, 0x00, 0x00, 0x99, 0x1e, 0x00, 0x00, 0x9d, 0xf9, + 0xff, 0xff, 0xef, 0xdb, 0xff, 0xff, 0x45, 0xf0, 0xff, 0xff, 0x08, 0xf4, 0xff, + 0xff, 0x3f, 0xf2, 0xff, 0xff, 0x12, 0xf1, 0xff, 0xff, 0x69, 0xf0, 0xff, 0xff, + 0xd7, 0xeb, 0xff, 0xff, 0xac, 0xcf, 0xff, 0xff, 0xca, 0xe7, 0xff, 0xff, 0x89, + 0xf2, 0xff, 0xff, 0xe6, 0x26, 0x00, 0x00, 0x6d, 0xf1, 0xff, 0xff, 0xee, 0xd4, + 0xff, 0xff, 0xca, 0xfa, 0xff, 0xff, 0x42, 0xec, 0xff, 0xff, 0x20, 0x22, 0x00, + 0x00, 0x71, 0x03, 0x00, 0x00, 0xcd, 0xeb, 0xff, 0xff, 0x15, 0x2a, 0x00, 0x00, + 0xe0, 0xec, 0xff, 0xff, 0x3f, 0xf9, 0xff, 0xff, 0x2c, 0xff, 0xff, 0xff, 0x06, + 0xfa, 0xff, 0xff, 0x72, 0xfe, 0xff, 0xff, 0xf7, 0xfd, 0xff, 0xff, 0xe9, 0xfd, + 0xff, 0xff, 0xcb, 0xf1, 0xff, 0xff, 0xe7, 0xe4, 0xff, 0xff, 0xef, 0xfd, 0xff, + 0xff, 0x80, 0xf6, 0xff, 0xff, 0x1e, 0x06, 0x00, 0x00, 0xdb, 0xfa, 0xff, 0xff, + 0x1c, 0xe5, 0xff, 0xff, 0x24, 0xf5, 0xff, 0xff, 0xfb, 0x1a, 0x00, 0x00, 0xb4, + 0x1c, 0x00, 0x00, 0x18, 0x3a, 0x00, 0x00, 0x02, 0xef, 0xff, 0xff, 0x71, 0x22, + 0x00, 0x00, 0xe1, 0xf2, 0xff, 0xff, 0x7f, 0xef, 0xff, 0xff, 0xd6, 0x02, 0x00, + 0x00, 0x16, 0xf8, 0xff, 0xff, 0x87, 0xf5, 0xff, 0xff, 0x33, 0xff, 0xff, 0xff, + 0x62, 0xfb, 0xff, 0xff, 0x1d, 0x22, 0x00, 0x00, 0x5d, 0xf4, 0xff, 0xff, 0x09, + 0x0b, 0x00, 0x00, 0xd5, 0xd6, 0xff, 0xff, 0x5a, 0xf3, 0xff, 0xff, 0x6c, 0xfe, + 0xff, 0xff, 0x7c, 0xff, 0xff, 0xff, 0x6b, 0x25, 0x00, 0x00, 0x0a, 0xda, 0xff, + 0xff, 0x7d, 0xf8, 0xff, 0xff, 0xac, 0xf3, 0xff, 0xff, 0x71, 0xf9, 0xff, 0xff, + 0x39, 0xf3, 0xff, 0xff, 0x2d, 0xd4, 0xff, 0xff, 0x33, 0xfc, 0xff, 0xff, 0xff, + 0xf2, 0xff, 0xff, 0xf6, 0x91, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0xba, 0xcf, 0x85, 0xce, 0x0c, 0x9f, 0xff, 0xeb, 0x0c, 0xa5, 0xda, + 0xeb, 0x12, 0xda, 0xf0, 0x60, 0xf8, 0x00, 0xf0, 0x9f, 0xe6, 0x09, 0xef, 0xed, + 0x02, 0xf9, 0x4f, 0xe9, 0x44, 0xae, 0x5c, 0x4d, 0xf2, 0xe7, 0xd9, 0x31, 0xf8, + 0xd0, 0xd3, 0x2d, 0x03, 0xdc, 0x00, 0x36, 0x0e, 0xff, 0xfb, 0x1a, 0x5d, 0x7c, + 0xbe, 0xf5, 0xd1, 0x1e, 0x32, 0x50, 0x2b, 0x1c, 0x02, 0xdf, 0x49, 0x3c, 0x21, + 0x1a, 0xf7, 0xfc, 0x48, 0x03, 0xda, 0xfd, 0x01, 0xf7, 0x58, 0x19, 0x22, 0x2e, + 0x0f, 0xd8, 0xb0, 0x3f, 0x25, 0x06, 0x81, 0xf7, 0xcf, 0x22, 0x28, 0x34, 0xc8, + 0xf4, 0xe5, 0xff, 0xc1, 0x32, 0xfa, 0x0c, 0x62, 0x20, 0x0a, 0xf5, 0x4c, 0xcc, + 0xcc, 0xd5, 0xe9, 0x05, 0x45, 0x41, 0x17, 0x3c, 0xe1, 0xfe, 0x1a, 0x25, 0x2c, + 0x03, 0xfa, 0x21, 0xdb, 0xdc, 0x02, 0xec, 0xf9, 0x14, 0x09, 0x0d, 0x23, 0xbe, + 0xe5, 0x00, 0x23, 0x2b, 0x02, 0x0c, 0xf6, 0x1c, 0xc5, 0xec, 0x36, 0x5e, 0x1e, + 0x09, 0x00, 0xff, 0xb3, 0x43, 0xa2, 0x04, 0x3b, 0xf5, 0xd3, 0xd4, 0x39, 0x0a, + 0xdd, 0x00, 0xf1, 0xfe, 0x0d, 0xd2, 0xf5, 0xf1, 0x24, 0xcd, 0xe7, 0x62, 0x03, + 0x07, 0xec, 0x04, 0xcf, 0x16, 0xf0, 0xbd, 0x37, 0xf4, 0xf5, 0xdf, 0x81, 0x15, + 0xf7, 0xf8, 0xbe, 0xda, 0xd2, 0xdd, 0xd6, 0xd5, 0xe2, 0xfa, 0xf6, 0x10, 0x21, + 0xe0, 0x30, 0xd1, 0x18, 0xfd, 0x0b, 0xd7, 0xde, 0xd9, 0xde, 0xc3, 0x2e, 0xf8, + 0xdd, 0xcd, 0x13, 0x12, 0x0b, 0x0f, 0xed, 0x0e, 0xe6, 0xe4, 0xd3, 0x32, 0x02, + 0x29, 0x1e, 0xd8, 0xe6, 0xca, 0xf4, 0x07, 0x2b, 0x1e, 0x11, 0x0a, 0xf9, 0xce, + 0x4c, 0xd1, 0x1c, 0x24, 0xea, 0x11, 0xf1, 0x0f, 0xc4, 0x12, 0xf8, 0x49, 0x06, + 0x41, 0x01, 0x1c, 0xec, 0xe5, 0xe5, 0x1d, 0xfd, 0x2c, 0xde, 0xdb, 0x2f, 0x10, + 0x78, 0x68, 0x04, 0x45, 0xd0, 0xf3, 0xfb, 0x1e, 0x2e, 0xf5, 0xad, 0xd1, 0xf3, + 0xf8, 0x05, 0x0b, 0x19, 0xee, 0xf7, 0xec, 0x14, 0xee, 0xf0, 0x17, 0x2f, 0x16, + 0xa7, 0xe1, 0xb8, 0x11, 0x32, 0xf5, 0x26, 0x1d, 0x26, 0x18, 0xd9, 0x03, 0xfc, + 0x05, 0x45, 0x24, 0xe0, 0xff, 0x0d, 0xfe, 0xf6, 0x19, 0xe5, 0x07, 0x05, 0x10, + 0x0f, 0x2b, 0x29, 0x2b, 0x0c, 0x12, 0xdf, 0x56, 0x00, 0x38, 0x14, 0xe4, 0x0f, + 0xdc, 0x16, 0x58, 0x09, 0x14, 0x01, 0xf9, 0x0f, 0xd2, 0x25, 0x02, 0x13, 0xfc, + 0xe7, 0x1d, 0x27, 0xf8, 0x0c, 0xee, 0xae, 0xe0, 0x07, 0x10, 0xc3, 0x16, 0x04, + 0xd0, 0x11, 0x13, 0xcf, 0x7f, 0xe4, 0x0b, 0xda, 0x05, 0x0f, 0xe6, 0xdc, 0xba, + 0xe4, 0x0f, 0xf3, 0x16, 0xdc, 0x0f, 0xb2, 0x3c, 0xee, 0xf2, 0x21, 0x1c, 0xf1, + 0x1a, 0x39, 0xd6, 0xfc, 0xfe, 0x11, 0xf2, 0x2c, 0x36, 0xfc, 0x9c, 0xfd, 0x3a, + 0x01, 0x90, 0x36, 0xef, 0xf4, 0xc5, 0xfd, 0xfd, 0xa5, 0x35, 0x0f, 0x36, 0x0f, + 0xba, 0xd1, 0x17, 0xe0, 0x4d, 0xb6, 0xbd, 0x1a, 0x15, 0xf5, 0x20, 0xd0, 0x23, + 0x1f, 0xff, 0xe5, 0xfd, 0xae, 0x7f, 0x12, 0xa0, 0xef, 0xf6, 0xed, 0xf2, 0x20, + 0xe4, 0x25, 0xab, 0x23, 0xee, 0x15, 0xe2, 0xbf, 0x03, 0xf2, 0xbd, 0x1a, 0xfe, + 0xed, 0xd3, 0x24, 0x26, 0x22, 0xd6, 0x11, 0xfc, 0x19, 0x10, 0x11, 0xfb, 0xff, + 0xdf, 0xe6, 0x2e, 0xee, 0xf4, 0x1b, 0xf2, 0xf2, 0xf5, 0x4d, 0xbf, 0xfc, 0xf2, + 0xe7, 0xd1, 0x41, 0xe8, 0x45, 0xf2, 0x07, 0x0c, 0x19, 0x01, 0xf3, 0xe2, 0xe9, + 0xfa, 0xe3, 0xfd, 0xfb, 0x3b, 0x42, 0xc7, 0xaa, 0xef, 0x01, 0x27, 0xdf, 0xec, + 0xf6, 0x1b, 0xf7, 0x1c, 0xd9, 0x22, 0x0a, 0x0a, 0xe6, 0x4d, 0xb6, 0x24, 0x03, + 0xd6, 0x08, 0xb6, 0xeb, 0xf6, 0x48, 0x9e, 0xbb, 0x9a, 0x26, 0xd4, 0x2b, 0x9d, + 0xd0, 0xc1, 0xe7, 0xfc, 0x17, 0x06, 0xab, 0x1a, 0x5e, 0x2e, 0x53, 0xc5, 0x08, + 0x3e, 0x20, 0x24, 0xe3, 0xb6, 0xcf, 0x2b, 0x1a, 0x08, 0xe9, 0xc6, 0x19, 0x16, + 0xd4, 0xc7, 0x51, 0x0c, 0x01, 0xf3, 0x4f, 0x2d, 0x07, 0xa5, 0x1c, 0x26, 0x13, + 0xd4, 0xc1, 0xe3, 0xe0, 0xd7, 0x06, 0xb7, 0xef, 0xc1, 0xfe, 0x11, 0xfc, 0x00, + 0x0b, 0x21, 0x62, 0x02, 0x0a, 0x06, 0xf6, 0x15, 0xea, 0xe0, 0x22, 0xcb, 0xe4, + 0x43, 0xf9, 0xf0, 0x11, 0x45, 0xfc, 0xb8, 0x9e, 0x1d, 0xd6, 0x0b, 0x45, 0x15, + 0x35, 0xe2, 0x4c, 0xd7, 0xdd, 0x14, 0x01, 0xe0, 0x2b, 0x49, 0xf4, 0xe0, 0xbb, + 0x18, 0x10, 0xfc, 0x72, 0x30, 0x62, 0xcc, 0xe9, 0x09, 0xd3, 0xe1, 0x30, 0x53, + 0xe7, 0x54, 0xd1, 0x23, 0x1b, 0xd6, 0x09, 0x0f, 0xd9, 0x29, 0xef, 0xd8, 0xaf, + 0xeb, 0xec, 0x11, 0x68, 0x81, 0x3f, 0xef, 0x29, 0x2d, 0x35, 0xc3, 0x69, 0xd0, + 0x05, 0x05, 0x23, 0xe7, 0x0b, 0x2a, 0xf7, 0x34, 0xcc, 0x2a, 0x0c, 0xd7, 0xdb, + 0xdf, 0x35, 0x12, 0xf8, 0xd9, 0x1a, 0x2f, 0xa5, 0xc2, 0x29, 0x10, 0xe6, 0x17, + 0xf2, 0x31, 0x36, 0x23, 0xfa, 0x2c, 0xcd, 0xdc, 0xa6, 0xa6, 0x12, 0x49, 0xff, + 0x16, 0xc6, 0xd8, 0xc3, 0x0f, 0xf4, 0xd8, 0xfe, 0xe3, 0xf0, 0xdd, 0x4c, 0xd9, + 0xe2, 0xe0, 0x0e, 0xfd, 0xfa, 0xe7, 0x3d, 0xdf, 0xb6, 0xf2, 0xf5, 0x83, 0xdb, + 0xff, 0x1c, 0x3d, 0x21, 0x20, 0x96, 0xc6, 0xc8, 0x42, 0x3a, 0x1b, 0x3c, 0x27, + 0xcf, 0x57, 0x0f, 0x1c, 0xc4, 0x3c, 0xc7, 0xe2, 0xda, 0xe8, 0xc5, 0xfb, 0xf7, + 0xd7, 0x03, 0x08, 0xd0, 0xfe, 0xf4, 0xfa, 0x11, 0xaa, 0xe5, 0xdd, 0xa4, 0xdc, + 0x81, 0x19, 0x44, 0x0e, 0xea, 0xfc, 0xf5, 0xd4, 0xe3, 0x13, 0x2c, 0x9c, 0xef, + 0x04, 0x10, 0xa1, 0x51, 0x41, 0xd4, 0xec, 0x23, 0x67, 0x22, 0x0d, 0x0d, 0x34, + 0xca, 0xd2, 0xb6, 0xca, 0x3a, 0xf9, 0xc0, 0x16, 0xa6, 0x22, 0xeb, 0xc3, 0x10, + 0xd4, 0xa1, 0x35, 0xc4, 0x23, 0x52, 0xe6, 0x30, 0x30, 0xe2, 0xc8, 0x26, 0x21, + 0x20, 0x00, 0x66, 0x46, 0xfe, 0x00, 0xdd, 0xaf, 0x4f, 0x4a, 0xdf, 0x16, 0x05, + 0x02, 0xe2, 0x0b, 0xf5, 0xf5, 0x0c, 0xe6, 0x45, 0xeb, 0x46, 0x0a, 0x3d, 0x81, + 0x2a, 0xf6, 0xdb, 0x38, 0xb8, 0xe9, 0x06, 0x1a, 0x27, 0xf3, 0x1d, 0x13, 0xda, + 0x25, 0x07, 0x37, 0xa4, 0x23, 0x0d, 0x1f, 0xd4, 0xf1, 0xdc, 0x43, 0x28, 0x4f, + 0x36, 0xa6, 0x0b, 0x13, 0xf4, 0xf3, 0xe4, 0xe8, 0xe3, 0x01, 0x35, 0x98, 0x2b, + 0x00, 0xc9, 0x26, 0x20, 0xd4, 0x5a, 0x3b, 0x0d, 0xfb, 0x03, 0x28, 0xe6, 0xfe, + 0x12, 0xe1, 0x0c, 0xef, 0x72, 0x1c, 0xd6, 0xa1, 0x51, 0xcf, 0x1e, 0x0c, 0xed, + 0x5c, 0xe2, 0xd1, 0x13, 0xf7, 0xe4, 0xff, 0xf2, 0xe5, 0xf2, 0x10, 0xf9, 0xd2, + 0xdf, 0x1f, 0xff, 0xee, 0x1d, 0x51, 0x02, 0xcc, 0xf0, 0xe3, 0x0f, 0xc4, 0x45, + 0x02, 0x2e, 0x3e, 0x13, 0x34, 0x00, 0xf4, 0xdc, 0x3b, 0x13, 0x0f, 0xe0, 0x4e, + 0x02, 0x55, 0x17, 0xfa, 0xf7, 0x07, 0xcd, 0x04, 0xf6, 0x9f, 0x03, 0xf4, 0xf0, + 0xe4, 0xdf, 0xce, 0x1c, 0x0e, 0x14, 0x03, 0x0c, 0xf8, 0x0d, 0xe4, 0xe1, 0xea, + 0x2f, 0xd8, 0xdf, 0x15, 0xf1, 0xcf, 0xfc, 0x16, 0x3e, 0x08, 0x0c, 0x00, 0xfc, + 0xf0, 0xc6, 0xd6, 0xf1, 0x20, 0x7f, 0x07, 0x43, 0xce, 0x00, 0x06, 0x12, 0x18, + 0x11, 0x11, 0x1b, 0xdb, 0x13, 0x1e, 0xb5, 0x49, 0xdf, 0xee, 0xd4, 0x39, 0xd7, + 0x0e, 0xfe, 0x25, 0xe8, 0x18, 0xc4, 0xf2, 0xd8, 0x07, 0x4d, 0xe6, 0xf6, 0xf9, + 0xf7, 0x05, 0x31, 0xda, 0xea, 0xfe, 0xfd, 0x15, 0xfc, 0x10, 0xea, 0x0f, 0xc8, + 0x35, 0xcb, 0xc9, 0x27, 0xd5, 0x33, 0x24, 0xf9, 0x12, 0x1b, 0xc6, 0x81, 0x1c, + 0xfa, 0x35, 0xee, 0xb0, 0x01, 0xd9, 0x06, 0x20, 0x06, 0x0b, 0x14, 0xb8, 0xf6, + 0x1e, 0x17, 0xf3, 0xf3, 0x1c, 0xbb, 0xcb, 0xa7, 0xc0, 0x35, 0x04, 0xfa, 0x11, + 0x21, 0x7a, 0xaa, 0xe1, 0x12, 0x14, 0x12, 0xd5, 0x0c, 0x11, 0xc2, 0x2c, 0xfb, + 0xb6, 0x2e, 0x3a, 0xfb, 0xd3, 0xed, 0xf4, 0xd0, 0x1d, 0x1c, 0x04, 0xd1, 0x1d, + 0xb7, 0xdd, 0xd6, 0xf1, 0xf4, 0xf0, 0x09, 0x0e, 0xee, 0x39, 0x0a, 0x16, 0xe3, + 0xcb, 0x27, 0x1f, 0xc8, 0xf0, 0x21, 0x49, 0x27, 0x48, 0xfb, 0xe5, 0xee, 0xff, + 0x14, 0xe6, 0xf4, 0xc9, 0xdb, 0x56, 0xff, 0xda, 0xe9, 0xee, 0x1f, 0x1b, 0x0b, + 0xb5, 0xe5, 0x99, 0xdc, 0xdf, 0xdb, 0xdf, 0xc1, 0x07, 0x52, 0x18, 0xd8, 0xfc, + 0x00, 0x0b, 0xcd, 0xe4, 0x0f, 0x38, 0xf0, 0xe5, 0x28, 0x93, 0x26, 0x10, 0x49, + 0x16, 0xf9, 0x18, 0x37, 0xc8, 0x9e, 0x25, 0xf0, 0x16, 0xb2, 0xf5, 0xed, 0xdc, + 0xe4, 0x20, 0xf7, 0x35, 0x1b, 0x40, 0x22, 0xd0, 0xa4, 0xdf, 0x03, 0xd0, 0x39, + 0xd3, 0x5e, 0x10, 0xb8, 0xd8, 0x47, 0x41, 0x1e, 0xf3, 0xe9, 0x29, 0xcd, 0xee, + 0x0a, 0xab, 0x05, 0xd3, 0xe3, 0x07, 0xc9, 0xd2, 0x11, 0xf2, 0x36, 0xef, 0x62, + 0x10, 0xd1, 0xf2, 0xea, 0xb6, 0x14, 0xc8, 0x24, 0x03, 0x1a, 0xce, 0x7f, 0x43, + 0x39, 0x0c, 0xd3, 0xb0, 0x2e, 0x1a, 0x00, 0xf9, 0xed, 0x00, 0xf4, 0xd7, 0xad, + 0x03, 0x01, 0xaf, 0x5a, 0x16, 0x10, 0x30, 0x16, 0x04, 0x3c, 0x19, 0x17, 0x10, + 0xe8, 0xdb, 0xc9, 0xe5, 0x3e, 0xf4, 0x06, 0xe2, 0x16, 0xe5, 0x36, 0x06, 0xdb, + 0x2f, 0xe0, 0xf2, 0x01, 0xee, 0xdf, 0x08, 0x15, 0x5e, 0x0d, 0x5b, 0x25, 0x1a, + 0x41, 0x09, 0xac, 0xe7, 0x02, 0x01, 0xc2, 0xed, 0xf9, 0x1b, 0x7f, 0xd5, 0xfe, + 0x28, 0x12, 0xed, 0xf8, 0x2c, 0x12, 0x04, 0x1b, 0xf8, 0x13, 0xd2, 0x0b, 0xe0, + 0x04, 0xf0, 0x02, 0xc9, 0xc7, 0xdb, 0xd5, 0xfe, 0xe0, 0xfa, 0x13, 0xdd, 0xfa, + 0x12, 0x1c, 0xe2, 0xfa, 0xfd, 0xf2, 0x22, 0xe5, 0x0b, 0x2a, 0x4f, 0xe2, 0xfc, + 0xf3, 0xdd, 0x1d, 0x2c, 0x23, 0xe1, 0x2c, 0xd5, 0x10, 0x05, 0xf5, 0x15, 0x07, + 0x0f, 0x0c, 0x1e, 0x1e, 0xfa, 0x17, 0xf0, 0xfa, 0x03, 0x22, 0x1f, 0x11, 0x03, + 0xe8, 0xf9, 0x14, 0x15, 0x1d, 0xfe, 0x16, 0xe8, 0xd3, 0x0d, 0x19, 0xdd, 0x26, + 0xfa, 0xc7, 0x2e, 0x1e, 0x15, 0xdc, 0xeb, 0xf8, 0x14, 0xfd, 0x15, 0x18, 0xf5, + 0x2e, 0x0b, 0x20, 0xf1, 0x1a, 0x1a, 0x07, 0x0e, 0x18, 0x2f, 0x13, 0xfe, 0xf2, + 0xc7, 0xd1, 0xfe, 0x00, 0xfd, 0x0f, 0x1e, 0x1c, 0x04, 0x28, 0x12, 0xec, 0x0c, + 0xe4, 0xe1, 0xf6, 0xfd, 0xd5, 0x2e, 0x0f, 0x13, 0x19, 0xf6, 0x0a, 0xd9, 0xfa, + 0x01, 0xeb, 0xdc, 0xef, 0x22, 0xfc, 0x24, 0x08, 0x0b, 0xbe, 0xe6, 0xcc, 0x2c, + 0x2a, 0xec, 0x0c, 0x3a, 0xf5, 0xd5, 0xf1, 0xf1, 0x07, 0xec, 0x0c, 0x2b, 0xdf, + 0xdd, 0x01, 0x0e, 0x1e, 0x21, 0x0c, 0xf6, 0xb8, 0x05, 0x20, 0xea, 0x53, 0x1b, + 0xfb, 0xf1, 0x16, 0xe8, 0x06, 0x2d, 0x0f, 0xdc, 0x01, 0xba, 0x0b, 0xc8, 0x05, + 0x15, 0x0f, 0xf2, 0x07, 0xdb, 0x24, 0xd2, 0x3e, 0x30, 0x22, 0xfd, 0xc5, 0x02, + 0xca, 0x18, 0xf1, 0xea, 0x11, 0x1a, 0xef, 0x1e, 0xdd, 0x7f, 0xdf, 0x08, 0x11, + 0xe1, 0xe0, 0xd7, 0xed, 0xcd, 0xcf, 0xf4, 0x0a, 0x1b, 0xd8, 0xdd, 0xfe, 0xef, + 0x3f, 0xf7, 0x34, 0xef, 0x05, 0xdf, 0xe7, 0xe7, 0x21, 0x38, 0xef, 0xfd, 0xec, + 0xe8, 0x12, 0xd9, 0xe0, 0xf3, 0x2c, 0xc3, 0xe0, 0xeb, 0xe6, 0x1e, 0x1f, 0x1b, + 0xf2, 0xbb, 0xfb, 0xf1, 0x44, 0xe4, 0x0e, 0x08, 0x08, 0xd9, 0x3d, 0x39, 0x16, + 0x09, 0x30, 0xd1, 0x4f, 0x33, 0x15, 0xdf, 0x07, 0xf6, 0xf0, 0x20, 0x14, 0x39, + 0x0d, 0xc2, 0xef, 0x81, 0xf4, 0x13, 0x1b, 0xee, 0xc3, 0xba, 0xd7, 0xe6, 0x55, + 0xfa, 0xeb, 0xe0, 0x3a, 0x43, 0x03, 0x01, 0xcc, 0x11, 0xa8, 0x4d, 0x33, 0xe1, + 0x00, 0x00, 0x4a, 0x58, 0xd6, 0xc1, 0xdf, 0x42, 0xf2, 0xb9, 0x33, 0xb7, 0xd0, + 0x20, 0x41, 0xd8, 0x3d, 0xe2, 0x5e, 0x17, 0xcd, 0xe1, 0xd6, 0x14, 0xee, 0x1b, + 0xff, 0xf0, 0xd9, 0xfc, 0xb2, 0xdb, 0xcf, 0xf8, 0xba, 0x3b, 0xfd, 0x1c, 0xc7, + 0xd6, 0x34, 0x29, 0xe2, 0xe1, 0xf8, 0xab, 0xdc, 0x62, 0x4f, 0x17, 0xdf, 0xc7, + 0xef, 0xda, 0x44, 0xfe, 0xd3, 0x4f, 0x45, 0xe1, 0x3c, 0x08, 0xec, 0xdb, 0x3d, + 0xfc, 0x1f, 0xc8, 0xec, 0xb2, 0x2b, 0x20, 0x22, 0x1a, 0xf7, 0xcc, 0xfb, 0x03, + 0x15, 0x58, 0x20, 0xf3, 0xe4, 0x19, 0xf1, 0xce, 0x11, 0xbd, 0x1c, 0x05, 0xcd, + 0x1b, 0xc0, 0xfe, 0x20, 0xf4, 0xf1, 0x18, 0x58, 0xd5, 0x28, 0xec, 0x29, 0x0d, + 0x2b, 0x1f, 0xb3, 0xf1, 0x23, 0xfe, 0x7f, 0x6a, 0x47, 0x2d, 0xdf, 0x04, 0xf2, + 0xc3, 0x01, 0x1e, 0x22, 0x8e, 0x08, 0xfb, 0x44, 0x0f, 0x5b, 0xf7, 0xe0, 0x0c, + 0xf6, 0xb6, 0x34, 0x0b, 0x3e, 0x0d, 0xdd, 0x41, 0xf5, 0xd7, 0xf4, 0x2b, 0x14, + 0xec, 0x0c, 0xca, 0x37, 0x14, 0x2f, 0xda, 0x3d, 0x12, 0x04, 0x12, 0x08, 0xef, + 0xfc, 0x71, 0x21, 0x4d, 0xf6, 0xe0, 0xec, 0xf3, 0xcb, 0x2c, 0x23, 0x11, 0x91, + 0x06, 0xf7, 0x01, 0xd7, 0x2c, 0x16, 0xfe, 0x1b, 0xc8, 0x1b, 0x15, 0xd6, 0x04, + 0x2d, 0x82, 0x44, 0x0e, 0x08, 0xff, 0x3d, 0x06, 0x62, 0x17, 0xb2, 0xee, 0x4b, + 0x19, 0x26, 0x07, 0x86, 0xc7, 0xff, 0xf0, 0x55, 0xd6, 0x04, 0x4a, 0xef, 0xe6, + 0x33, 0x15, 0xe4, 0x03, 0x10, 0xc1, 0xc0, 0xf5, 0xed, 0x1f, 0x09, 0x1d, 0x21, + 0xaf, 0xf9, 0xd5, 0x02, 0x59, 0x06, 0xcc, 0xfd, 0xab, 0xec, 0x27, 0x49, 0xf1, + 0x10, 0xe8, 0xd1, 0x1a, 0xae, 0xf7, 0x14, 0x2a, 0x12, 0x1f, 0xfc, 0xc3, 0x3f, + 0xf3, 0x08, 0xe2, 0xea, 0xb3, 0xef, 0x10, 0xed, 0x04, 0xf8, 0x2b, 0xce, 0xeb, + 0xf4, 0xf9, 0x16, 0xf0, 0xf5, 0x29, 0x2c, 0xcf, 0xf3, 0x15, 0xf6, 0x22, 0xea, + 0x0d, 0xf7, 0xcd, 0xf7, 0x6e, 0x0e, 0xb9, 0xea, 0xd9, 0xf0, 0x1b, 0x01, 0xc9, + 0x0e, 0xd5, 0xf1, 0x1a, 0x00, 0x1e, 0xfb, 0x0e, 0xe4, 0x05, 0x4d, 0xea, 0x81, + 0xee, 0x0e, 0xcc, 0x01, 0x19, 0xc6, 0xfb, 0xe3, 0x14, 0x34, 0xec, 0xe5, 0x39, + 0x13, 0x09, 0x2c, 0xc6, 0xfe, 0xa7, 0xe5, 0x20, 0xd1, 0x0c, 0x0a, 0x0c, 0x43, + 0xe9, 0xb0, 0xf7, 0xf3, 0x02, 0x60, 0x29, 0x1c, 0xd9, 0x28, 0x3f, 0x0d, 0x35, + 0xc2, 0x37, 0x1b, 0x0b, 0x2d, 0xe4, 0xf4, 0xa7, 0xde, 0xf0, 0xbd, 0x1d, 0x22, + 0x21, 0xc5, 0x1f, 0xe7, 0x4e, 0x28, 0xcf, 0xc2, 0xf9, 0xc3, 0xb8, 0xc9, 0xec, + 0xe2, 0xf0, 0x0a, 0x11, 0xd0, 0xc0, 0xb0, 0x25, 0x0d, 0xca, 0xbe, 0x2a, 0xf8, + 0xd7, 0x0f, 0xe5, 0xf7, 0xfa, 0xde, 0xe5, 0xe8, 0xf6, 0x42, 0x2f, 0xe3, 0xdd, + 0x2e, 0xb1, 0xb8, 0xcf, 0xf6, 0x08, 0xc6, 0x2d, 0xd4, 0xe0, 0xee, 0x34, 0xd7, + 0x21, 0x12, 0xb3, 0x48, 0x3c, 0x12, 0xd5, 0x04, 0xcf, 0xdc, 0x25, 0x05, 0x03, + 0xcf, 0x0b, 0x30, 0x9d, 0x1c, 0x30, 0x23, 0x5b, 0x36, 0x27, 0x3d, 0xdf, 0xe0, + 0xfd, 0xde, 0xdb, 0xfd, 0x41, 0x0c, 0xdb, 0xe5, 0x08, 0x1b, 0xef, 0x5c, 0x81, + 0x1d, 0x2a, 0xcb, 0x0e, 0x0b, 0x35, 0x2a, 0xcc, 0x24, 0xe8, 0x2c, 0x2e, 0x18, + 0x18, 0xe8, 0x52, 0xb7, 0x32, 0x16, 0xd7, 0xf6, 0x51, 0xdb, 0xaf, 0x39, 0xfe, + 0xec, 0xf0, 0x8c, 0xee, 0xd5, 0xc5, 0x32, 0x0e, 0xc6, 0xc9, 0xab, 0x06, 0x35, + 0xdb, 0x4d, 0x33, 0x02, 0x1d, 0x05, 0xe9, 0x27, 0xcd, 0x13, 0x00, 0xcb, 0x48, + 0x0b, 0xe1, 0x0d, 0xb3, 0xfc, 0xd9, 0x10, 0x24, 0x07, 0xf9, 0xf3, 0x1c, 0xb3, + 0xba, 0xf4, 0xdf, 0xf7, 0xf3, 0xc9, 0x2e, 0xd2, 0xf6, 0xfa, 0x2a, 0xca, 0xec, + 0xb1, 0xfd, 0xf8, 0xca, 0xc8, 0xea, 0x04, 0x38, 0x25, 0x09, 0xb3, 0xce, 0x27, + 0x1a, 0x4f, 0x11, 0x1a, 0xe3, 0x22, 0x27, 0xfd, 0x03, 0x41, 0xd7, 0x05, 0xe5, + 0x9e, 0x04, 0x0c, 0x04, 0xf5, 0xe3, 0xdf, 0x55, 0xed, 0xea, 0xd0, 0x2b, 0x16, + 0xe2, 0xf3, 0x29, 0xf4, 0x44, 0x27, 0x65, 0xda, 0x45, 0x16, 0xd5, 0xed, 0x04, + 0xf3, 0x13, 0xb9, 0xc8, 0xe6, 0xf8, 0xbc, 0x7f, 0xdc, 0xea, 0xfd, 0xed, 0x10, + 0x10, 0x29, 0x3e, 0xea, 0xf8, 0x9e, 0x11, 0xd2, 0x0d, 0x28, 0x44, 0x30, 0x2a, + 0x49, 0x2b, 0xba, 0xd4, 0x18, 0x07, 0x48, 0x12, 0x21, 0x59, 0x36, 0xea, 0x13, + 0x58, 0xe4, 0xc3, 0x37, 0xdb, 0xcb, 0x19, 0xdf, 0x21, 0x17, 0x50, 0x0d, 0xcd, + 0xbf, 0x2b, 0x0e, 0xd2, 0x06, 0xb9, 0xfe, 0x3b, 0x1d, 0xe9, 0xd8, 0x0d, 0x41, + 0xdd, 0xfe, 0xeb, 0xd5, 0x37, 0xad, 0xf3, 0x00, 0x21, 0x0f, 0xcc, 0xf0, 0xd6, + 0x5e, 0x0b, 0xf2, 0x09, 0x2b, 0x39, 0xd3, 0x1b, 0xe3, 0xb7, 0xed, 0xfb, 0xe3, + 0xd7, 0x40, 0xe3, 0x09, 0x44, 0x0f, 0x26, 0xf5, 0xf9, 0x4b, 0x98, 0xf1, 0x09, + 0x81, 0xe8, 0xcd, 0x34, 0xdc, 0x19, 0x2a, 0x5b, 0xe8, 0xf5, 0xfd, 0x2c, 0xc2, + 0xd4, 0xe1, 0x0c, 0xda, 0xe7, 0xfe, 0xcd, 0x1d, 0xf8, 0x00, 0x08, 0xe5, 0xf1, + 0x51, 0x10, 0x11, 0xa9, 0xc9, 0x28, 0x10, 0xfd, 0x4e, 0x0c, 0x1e, 0x21, 0x28, + 0x0b, 0x0e, 0xe8, 0xcd, 0xff, 0xe3, 0x20, 0xbd, 0xe6, 0x05, 0xef, 0x31, 0xf6, + 0xe4, 0x25, 0x0d, 0xf0, 0xf0, 0x1f, 0x14, 0xe0, 0xf5, 0x15, 0x19, 0xeb, 0x0a, + 0x02, 0xe9, 0xbd, 0x24, 0x0c, 0x0d, 0x44, 0xe9, 0xf7, 0xdf, 0x42, 0xce, 0xf6, + 0x16, 0x12, 0x02, 0xca, 0x28, 0x0f, 0x1c, 0x1c, 0xf5, 0x32, 0xfd, 0x24, 0x43, + 0xdf, 0xe6, 0xea, 0x1c, 0x0a, 0x11, 0xfe, 0xfd, 0x12, 0x19, 0xf5, 0xd2, 0x47, + 0xc4, 0x1f, 0x0c, 0xfe, 0x07, 0xf4, 0x0c, 0xd3, 0xe6, 0xd8, 0x81, 0x6d, 0xff, + 0xf6, 0x05, 0x29, 0xe1, 0x04, 0xd9, 0xf7, 0xf7, 0xea, 0xec, 0xf5, 0xbd, 0x10, + 0x08, 0xf5, 0xd1, 0x47, 0x17, 0x36, 0xe0, 0xf5, 0xf2, 0xe2, 0xd9, 0x10, 0xd9, + 0xdb, 0xe8, 0x47, 0xfd, 0x30, 0x41, 0xfc, 0xdf, 0x10, 0xf4, 0x27, 0x05, 0xea, + 0xed, 0xdb, 0x1b, 0x12, 0x0f, 0xd3, 0x09, 0xfe, 0xf4, 0x08, 0xea, 0xf4, 0x0e, + 0x4e, 0x0f, 0xf3, 0x53, 0x35, 0xc1, 0xd3, 0x06, 0x39, 0xed, 0xc4, 0xe4, 0xd1, + 0xfb, 0xcc, 0x28, 0xeb, 0xb9, 0xfe, 0xd2, 0xfb, 0xf0, 0xc5, 0xf6, 0x48, 0xdf, + 0xb8, 0x16, 0xf4, 0x20, 0x04, 0x32, 0x3e, 0xc8, 0xe0, 0xe5, 0x0e, 0x18, 0x1c, + 0x30, 0x1d, 0xf7, 0x1f, 0x22, 0x0f, 0xb9, 0x3a, 0xa8, 0x2c, 0x55, 0x01, 0x0c, + 0xfb, 0xb5, 0xf1, 0xf5, 0xe6, 0xe5, 0x3a, 0x7f, 0xe0, 0xba, 0xcc, 0xf4, 0xfd, + 0xee, 0xde, 0x61, 0xcd, 0xf8, 0xb7, 0xd6, 0xb1, 0x10, 0x03, 0x10, 0xe6, 0xe4, + 0xf2, 0xe0, 0x2d, 0x96, 0x01, 0x0e, 0xde, 0xc2, 0x0d, 0x22, 0x06, 0xd0, 0x39, + 0xe3, 0xfc, 0x2b, 0xb5, 0xeb, 0xc6, 0xc7, 0xac, 0xe6, 0x1f, 0xf6, 0xf9, 0xbb, + 0x37, 0xec, 0xe9, 0x2d, 0xdf, 0xb9, 0x1a, 0xe4, 0xd5, 0xdb, 0xc3, 0x07, 0x19, + 0xef, 0xf5, 0xd2, 0x1d, 0x03, 0xda, 0x0e, 0x33, 0x42, 0x30, 0x19, 0x09, 0x3c, + 0xb6, 0x03, 0xea, 0x1f, 0xe7, 0xf1, 0xd4, 0x0f, 0xe5, 0xe4, 0x16, 0x05, 0xf5, + 0x05, 0x7f, 0xf3, 0xd2, 0x16, 0xe7, 0x23, 0xda, 0xd7, 0xd0, 0xfe, 0xeb, 0x2d, + 0xf4, 0x47, 0x05, 0x0c, 0xed, 0x08, 0x00, 0x11, 0x0d, 0xe6, 0xb4, 0x24, 0x13, + 0x10, 0x17, 0xf4, 0x17, 0xf5, 0x23, 0xd7, 0x3d, 0x0f, 0xef, 0xee, 0xdf, 0xf2, + 0xde, 0x1b, 0xfb, 0xe3, 0x11, 0x11, 0x1a, 0x21, 0x5a, 0xb5, 0x21, 0x05, 0xd8, + 0xed, 0x36, 0xde, 0xfb, 0xe8, 0xe4, 0xe8, 0x39, 0xd1, 0x08, 0x56, 0xc6, 0xf3, + 0x02, 0x26, 0xde, 0x14, 0xff, 0x38, 0x0a, 0xea, 0x0a, 0xc1, 0xfa, 0xf2, 0xd7, + 0xc8, 0x22, 0xcf, 0xb8, 0x28, 0x10, 0xc6, 0xf0, 0xec, 0xff, 0xdb, 0x2e, 0xf9, + 0x0d, 0x39, 0x02, 0xf0, 0xf9, 0xf9, 0x15, 0x4a, 0x02, 0xd3, 0x11, 0xfe, 0x15, + 0xdd, 0xc7, 0x19, 0xe5, 0x13, 0x08, 0x15, 0x3c, 0x05, 0xcd, 0x1a, 0xf4, 0x10, + 0x07, 0xff, 0xee, 0xed, 0x0f, 0xfc, 0x1b, 0x0a, 0xba, 0xe0, 0xf5, 0xe2, 0xb3, + 0x0c, 0x9f, 0x4d, 0xfd, 0xcd, 0x1a, 0xd8, 0xf9, 0xe3, 0x34, 0xef, 0xf3, 0xfd, + 0x40, 0x47, 0x0e, 0x20, 0x14, 0xec, 0x11, 0xe8, 0x38, 0xfb, 0x45, 0xbf, 0xed, + 0x6a, 0xcf, 0xd4, 0x3c, 0x0e, 0x40, 0x0b, 0x2d, 0x3d, 0x30, 0xd8, 0x32, 0x03, + 0xe5, 0xc5, 0x07, 0x0f, 0x03, 0xfb, 0x92, 0xe6, 0xe3, 0x3c, 0xfd, 0x39, 0xfd, + 0x12, 0x99, 0xdb, 0x0e, 0x3b, 0x31, 0x06, 0xc0, 0xc5, 0x02, 0x49, 0xe3, 0x3a, + 0xcc, 0x38, 0xef, 0xa1, 0x1e, 0x09, 0x01, 0xc4, 0x3b, 0x28, 0x41, 0xb9, 0x12, + 0xeb, 0x10, 0x43, 0xdf, 0x1e, 0xb0, 0xc8, 0x7f, 0x18, 0x05, 0x0e, 0x0e, 0xfe, + 0xde, 0x34, 0xe5, 0x29, 0xe9, 0x06, 0x00, 0x0b, 0x10, 0xd6, 0xeb, 0x1e, 0x14, + 0xe2, 0xd9, 0xba, 0x1e, 0xec, 0x26, 0x09, 0xd0, 0xc0, 0xf7, 0x8e, 0x09, 0xb6, + 0x44, 0x22, 0x29, 0xf6, 0x05, 0xc7, 0x91, 0x09, 0xd2, 0x81, 0x50, 0xdd, 0x10, + 0xf2, 0x05, 0x6b, 0x10, 0x0b, 0x26, 0xe1, 0x79, 0xd5, 0x33, 0xdc, 0x1d, 0xc8, + 0xed, 0xc3, 0x41, 0x8f, 0xca, 0xde, 0x10, 0xec, 0x01, 0xe0, 0xe5, 0xe7, 0x18, + 0x97, 0xe0, 0x09, 0xfd, 0x1b, 0x09, 0xfa, 0x05, 0x0f, 0xf2, 0xbd, 0xeb, 0x39, + 0xf5, 0xe0, 0xd9, 0xe7, 0xda, 0x22, 0x21, 0x2b, 0xf9, 0xdb, 0xf8, 0x19, 0x34, + 0xf2, 0x38, 0xdd, 0xf0, 0xfb, 0xe5, 0x04, 0xf5, 0xbd, 0x59, 0x01, 0x0f, 0x79, + 0x1c, 0xda, 0xcd, 0x1e, 0x30, 0x27, 0x0d, 0x11, 0x0a, 0x0b, 0xf0, 0x4d, 0xb3, + 0x5e, 0xf5, 0x23, 0xf6, 0xfc, 0x2f, 0xd7, 0x5b, 0xc2, 0x5f, 0x21, 0xfd, 0xdf, + 0x06, 0x3e, 0xef, 0x78, 0x5b, 0x9a, 0x3e, 0x18, 0xf0, 0xf2, 0xc4, 0xf4, 0xec, + 0xff, 0x09, 0xe7, 0x23, 0x07, 0x22, 0x1b, 0xe9, 0xdf, 0x3c, 0xe7, 0x0b, 0x01, + 0xc1, 0x07, 0xec, 0xa0, 0x0b, 0xce, 0xf9, 0x02, 0x0a, 0x57, 0x5d, 0xbc, 0x18, + 0xdb, 0x24, 0x08, 0x07, 0x37, 0xfc, 0xd2, 0x3d, 0xe0, 0x12, 0x14, 0x32, 0xe7, + 0x31, 0xf9, 0xe1, 0x5d, 0xf5, 0xc7, 0x25, 0xf8, 0xe5, 0x0a, 0x12, 0x0b, 0x29, + 0xfe, 0xd5, 0x3c, 0x32, 0xf8, 0x02, 0xed, 0x1a, 0x38, 0xdb, 0xee, 0x12, 0xdc, + 0x05, 0x1c, 0xa6, 0xff, 0xde, 0xf3, 0x07, 0x06, 0x1d, 0xb2, 0xd9, 0x03, 0x2b, + 0xa0, 0x10, 0x29, 0xee, 0x27, 0x3d, 0x2b, 0xb4, 0xdb, 0x2a, 0xca, 0xf6, 0xd4, + 0x10, 0x81, 0xff, 0xe7, 0x20, 0xb3, 0x04, 0xbb, 0xe5, 0x0c, 0xd7, 0xbe, 0xde, + 0xa9, 0xed, 0xe0, 0x02, 0xed, 0x19, 0x01, 0x0e, 0xc9, 0xee, 0x3f, 0x4a, 0x63, + 0xfa, 0xfc, 0xf8, 0x12, 0xdf, 0xbf, 0x12, 0x1f, 0x26, 0xd7, 0xfd, 0x08, 0x2d, + 0xc6, 0x38, 0xa5, 0xba, 0x42, 0xed, 0xe2, 0x04, 0x02, 0x22, 0xd2, 0x34, 0x25, + 0x29, 0xfd, 0x05, 0xe4, 0xfe, 0x9f, 0x12, 0x36, 0xb6, 0xf1, 0x3e, 0x02, 0xcf, + 0x54, 0xa5, 0x19, 0xe6, 0x59, 0xfa, 0xf9, 0x1c, 0x15, 0x02, 0xfb, 0x3c, 0x11, + 0x38, 0xed, 0x14, 0xf1, 0x0a, 0x1a, 0x14, 0x03, 0xd0, 0x4c, 0xcc, 0x1a, 0x1c, + 0x1e, 0xe8, 0xd6, 0x2e, 0xd7, 0xef, 0x60, 0xd3, 0x23, 0xfb, 0x0d, 0xe8, 0x35, + 0x7f, 0xf8, 0xde, 0xf7, 0x1b, 0xf2, 0xc9, 0x1a, 0xda, 0xe1, 0xc6, 0x33, 0xc9, + 0x37, 0xce, 0x02, 0x43, 0x05, 0x07, 0xeb, 0x12, 0xf9, 0x32, 0xea, 0xf5, 0x18, + 0x0f, 0x51, 0xd9, 0xd1, 0xdd, 0xd1, 0x02, 0x18, 0xef, 0xc1, 0x29, 0x51, 0xed, + 0xc2, 0x37, 0xee, 0x45, 0x02, 0xdc, 0xff, 0x35, 0xc4, 0x03, 0x0d, 0xc8, 0xdd, + 0x27, 0xeb, 0xb8, 0xd4, 0xdd, 0x2d, 0x2e, 0xe7, 0x26, 0xf2, 0xce, 0xe7, 0x04, + 0x1d, 0x2d, 0x05, 0x0f, 0x06, 0xfd, 0xc0, 0xff, 0xf5, 0x09, 0x21, 0xec, 0xf5, + 0xfe, 0xee, 0xf2, 0x0e, 0xea, 0x16, 0xec, 0x01, 0x14, 0x2c, 0x13, 0xfd, 0xdf, + 0x04, 0xe0, 0x0a, 0xe2, 0x9d, 0xe4, 0x54, 0xd9, 0x06, 0x0b, 0xda, 0x0b, 0xc3, + 0x0e, 0x14, 0xca, 0x13, 0xc7, 0x46, 0xfd, 0x28, 0xea, 0x2d, 0x14, 0x16, 0xd5, + 0x07, 0x0c, 0x27, 0x27, 0x07, 0x10, 0xde, 0x46, 0x02, 0x0c, 0x06, 0x1f, 0xd0, + 0x32, 0xec, 0xf9, 0xb0, 0xfe, 0xcd, 0xea, 0x18, 0x1b, 0x09, 0xcf, 0x3d, 0x01, + 0xee, 0x07, 0xeb, 0xe9, 0xe7, 0xf5, 0x00, 0x2c, 0x48, 0xf8, 0xe5, 0x25, 0xf3, + 0x0e, 0x7f, 0x0b, 0x05, 0xd5, 0xcd, 0x21, 0x0a, 0xdd, 0xc6, 0xef, 0xf0, 0xf1, + 0xfc, 0xc9, 0x29, 0xf2, 0xf9, 0x04, 0xee, 0xe6, 0x19, 0xf7, 0x1f, 0x48, 0x01, + 0xfb, 0xc3, 0xea, 0xb0, 0x0a, 0x23, 0xe5, 0xfa, 0xbc, 0x12, 0xfe, 0xec, 0x0a, + 0xdb, 0x01, 0xc1, 0xed, 0xdd, 0xfe, 0x08, 0xee, 0x8a, 0x01, 0xa4, 0x11, 0xf1, + 0x22, 0xbc, 0x00, 0x08, 0x16, 0x23, 0x02, 0x7c, 0x37, 0xf8, 0xff, 0xfb, 0xe9, + 0xcd, 0xee, 0x55, 0x15, 0x38, 0x42, 0x14, 0xac, 0xb2, 0x5d, 0x21, 0xe5, 0xfc, + 0x1a, 0xd9, 0xf9, 0xc9, 0xd3, 0xd0, 0x0d, 0xe0, 0x29, 0x4f, 0xfd, 0xd1, 0x4f, + 0xca, 0xc8, 0x05, 0xed, 0xe0, 0xfa, 0xf5, 0x36, 0x17, 0x19, 0xd6, 0x4b, 0xd5, + 0x14, 0xda, 0x51, 0xe5, 0xd6, 0xfa, 0x0f, 0xd1, 0x09, 0xe8, 0x93, 0x24, 0x75, + 0x19, 0x2a, 0x11, 0x2e, 0x30, 0x0f, 0x4d, 0xfa, 0xb9, 0xda, 0x94, 0xbe, 0xa0, + 0xf4, 0xee, 0x28, 0xe8, 0x2c, 0x44, 0xdd, 0xb4, 0x7f, 0x9e, 0xee, 0xee, 0xfd, + 0xf0, 0x12, 0xde, 0x28, 0x17, 0xc4, 0x1c, 0x27, 0x95, 0x0f, 0x18, 0x09, 0x33, + 0x3b, 0x0d, 0xe4, 0xd4, 0x14, 0x37, 0x39, 0xc3, 0x4f, 0xc6, 0x0f, 0xe8, 0x03, + 0xdb, 0x01, 0xf9, 0xf2, 0xe6, 0xe3, 0xb6, 0x07, 0xe9, 0x8a, 0x2b, 0x57, 0x10, + 0x2b, 0x21, 0x0a, 0xec, 0x06, 0xad, 0x65, 0xcc, 0x22, 0x1f, 0x35, 0x01, 0x8e, + 0x13, 0x1e, 0x19, 0xc7, 0xfd, 0xfa, 0x32, 0xc9, 0xe2, 0x4b, 0x5f, 0x36, 0xde, + 0xb5, 0xea, 0x4b, 0x1d, 0xdf, 0xf5, 0x13, 0xe4, 0xe1, 0xf7, 0x98, 0xd9, 0xef, + 0xfb, 0x13, 0x08, 0x2b, 0x08, 0xd3, 0xdf, 0xfe, 0x2d, 0x01, 0xbf, 0xef, 0x4d, + 0xe3, 0x11, 0x34, 0xf4, 0x2f, 0xcf, 0x09, 0xbc, 0xfa, 0x63, 0xdb, 0x0f, 0x3e, + 0x0f, 0xc9, 0xdb, 0x12, 0x0b, 0xf3, 0x2b, 0xf2, 0xf8, 0xf0, 0xbb, 0xd2, 0xb5, + 0xe8, 0x49, 0xef, 0x91, 0xdf, 0x07, 0x13, 0x48, 0xdd, 0x46, 0xfc, 0xf5, 0xfa, + 0xdb, 0xdf, 0x23, 0x7f, 0xe5, 0x03, 0xf2, 0x2e, 0x0e, 0xb2, 0xd8, 0x10, 0x48, + 0x03, 0x03, 0xd9, 0xe4, 0x2b, 0xc0, 0x17, 0xfe, 0xa2, 0xfb, 0xde, 0xf7, 0x05, + 0x26, 0x5b, 0xf7, 0x51, 0x0e, 0xe2, 0xcf, 0xcc, 0x58, 0xc1, 0x46, 0x41, 0xfe, + 0xf6, 0x43, 0xc8, 0x48, 0xf6, 0x0c, 0x1c, 0xb3, 0xf4, 0x45, 0xde, 0x3b, 0x38, + 0x2a, 0x5f, 0x90, 0x3e, 0xb5, 0x24, 0x73, 0x1d, 0x17, 0x1c, 0x0b, 0xe7, 0x0e, + 0xdd, 0xfa, 0x22, 0x29, 0x3f, 0x02, 0xf9, 0xe2, 0xf8, 0x59, 0xc9, 0xe7, 0xe8, + 0x14, 0x11, 0x7f, 0x10, 0xf0, 0x4c, 0xc2, 0x39, 0x67, 0x1e, 0x3b, 0x29, 0xa2, + 0x14, 0xc1, 0x45, 0xc4, 0x5a, 0x97, 0x3c, 0x61, 0x13, 0x2e, 0xb4, 0xe8, 0x2b, + 0x26, 0x19, 0xe9, 0xc2, 0xcf, 0xf7, 0xdb, 0xee, 0xfe, 0x61, 0xd7, 0x34, 0xed, + 0xcc, 0xdf, 0x4b, 0x54, 0x02, 0x23, 0x55, 0xff, 0xfd, 0xc2, 0x50, 0x28, 0x31, + 0x03, 0xac, 0x0c, 0x44, 0xe0, 0xdb, 0x20, 0x16, 0x23, 0x10, 0xd5, 0x41, 0x0a, + 0x2c, 0x0b, 0xe5, 0xe7, 0x65, 0xfe, 0xea, 0xe9, 0x4d, 0xad, 0x70, 0xee, 0x19, + 0xab, 0xcb, 0x22, 0x20, 0xc7, 0xf7, 0xe1, 0x2a, 0xa5, 0xf3, 0x20, 0xf8, 0x19, + 0x1c, 0x0b, 0x33, 0x50, 0x1e, 0x3d, 0xf3, 0xce, 0xf3, 0x16, 0x36, 0x19, 0xdb, + 0xf8, 0xdf, 0x1f, 0xe4, 0xe0, 0x19, 0x30, 0x0a, 0xa1, 0xeb, 0xba, 0x0e, 0xf8, + 0xa4, 0xf6, 0x22, 0xdd, 0xb3, 0xf8, 0xeb, 0xbc, 0x22, 0xfa, 0xff, 0xe5, 0x51, + 0xef, 0xf7, 0x08, 0xe3, 0x7f, 0x0a, 0x0a, 0xd5, 0x29, 0xf0, 0x02, 0xc9, 0x28, + 0x30, 0xc3, 0x19, 0xd2, 0x23, 0x0f, 0x6a, 0xd3, 0xb4, 0xf1, 0x12, 0xd5, 0xf3, + 0x19, 0xc8, 0xc6, 0xcd, 0xcd, 0xf5, 0xf9, 0x10, 0x36, 0xf6, 0x26, 0x2b, 0x50, + 0xe4, 0x9b, 0x47, 0x43, 0xee, 0x2f, 0x0a, 0x19, 0xf6, 0x15, 0xff, 0x0b, 0x14, + 0x13, 0x37, 0x27, 0x18, 0x23, 0xfc, 0x13, 0x36, 0x3a, 0xf3, 0xf5, 0xfe, 0xff, + 0x1f, 0xdb, 0x01, 0x15, 0xf2, 0x5f, 0x0e, 0x12, 0xd4, 0xe9, 0x07, 0xdf, 0x32, + 0xc5, 0xcf, 0xf5, 0x28, 0xf8, 0x2e, 0x2d, 0xf0, 0x7f, 0xf1, 0xf0, 0xd9, 0x04, + 0xd2, 0x39, 0x2d, 0xb6, 0xcf, 0xd9, 0x0d, 0x08, 0x6f, 0xfd, 0x2d, 0xfb, 0xd3, + 0xf8, 0x0b, 0x02, 0xdf, 0xf0, 0xc7, 0x52, 0x34, 0xf6, 0x1f, 0xf1, 0xcf, 0xec, + 0x48, 0x1e, 0xfd, 0xed, 0xe2, 0xb4, 0x20, 0x3e, 0xe2, 0xfc, 0xb4, 0xfa, 0xea, + 0x16, 0xf4, 0xd1, 0x04, 0xea, 0x17, 0x51, 0x18, 0x6e, 0x23, 0xec, 0x06, 0xec, + 0x62, 0x04, 0x5f, 0xe4, 0xbd, 0x20, 0x1a, 0xa6, 0xea, 0x19, 0xdf, 0xf1, 0xbf, + 0xf9, 0xfe, 0x8f, 0x05, 0xf7, 0xe9, 0xdd, 0xfb, 0x07, 0xec, 0x12, 0x00, 0x1b, + 0x49, 0x14, 0x2f, 0xd4, 0x06, 0x15, 0x12, 0x19, 0xeb, 0x12, 0xdf, 0xea, 0x44, + 0x07, 0xe1, 0x47, 0xfe, 0x46, 0xe0, 0x39, 0xe5, 0xe2, 0xcd, 0xee, 0x24, 0xde, + 0xe9, 0xfd, 0xb6, 0x2c, 0xc1, 0xed, 0xde, 0xc9, 0x28, 0xef, 0xdf, 0x06, 0x01, + 0xc7, 0xf4, 0xf3, 0x22, 0xde, 0x14, 0x0e, 0x00, 0x0f, 0x0f, 0xf2, 0xcf, 0x55, + 0xe2, 0xf4, 0xe5, 0x0a, 0x05, 0xeb, 0xd2, 0x28, 0xdf, 0x14, 0xc8, 0xcd, 0xda, + 0xfb, 0xf8, 0xed, 0xf3, 0x05, 0xd9, 0x7f, 0xfd, 0x2c, 0x20, 0xf0, 0x10, 0x0f, + 0xc8, 0xd8, 0x23, 0xba, 0xdb, 0xfb, 0x0f, 0x04, 0xca, 0xe8, 0x30, 0xff, 0xea, + 0x03, 0x4f, 0x03, 0xd3, 0xda, 0x20, 0xf0, 0xbe, 0xfd, 0x26, 0xca, 0x03, 0xc9, + 0xdf, 0x03, 0x48, 0xf9, 0x37, 0xf6, 0x13, 0x01, 0x21, 0xf3, 0x21, 0xc7, 0xd8, + 0xff, 0xaa, 0x36, 0x39, 0xef, 0x36, 0x03, 0x00, 0xe5, 0x3b, 0xe4, 0xf8, 0x32, + 0x3d, 0x17, 0x10, 0xe7, 0x28, 0x32, 0xbb, 0x10, 0xd0, 0xc3, 0x1b, 0x0a, 0xed, + 0xed, 0x11, 0x2d, 0x01, 0xd0, 0xf4, 0xf7, 0x03, 0x01, 0x12, 0xb5, 0x0a, 0xf5, + 0x04, 0x02, 0xf6, 0x17, 0x15, 0xf6, 0xaa, 0xea, 0xb3, 0x3a, 0x0d, 0x19, 0x43, + 0xdf, 0xf3, 0xdb, 0xcd, 0x4c, 0xd0, 0xf8, 0x0a, 0xeb, 0x36, 0xd6, 0x8e, 0x65, + 0x3c, 0xc1, 0x0e, 0x04, 0x1d, 0x40, 0xdb, 0x04, 0x27, 0x27, 0xbb, 0x2b, 0xc2, + 0xca, 0x0f, 0xf8, 0x1b, 0x27, 0xe2, 0x12, 0x8f, 0x15, 0xfe, 0xbc, 0xea, 0x4b, + 0xef, 0xe7, 0xfe, 0xbb, 0xc2, 0xe6, 0x08, 0xe3, 0xcc, 0x38, 0x36, 0xdb, 0x10, + 0x1a, 0x11, 0xe1, 0x10, 0xd3, 0xe5, 0xc1, 0xec, 0xd6, 0xe8, 0x30, 0xce, 0x2e, + 0x3b, 0xe7, 0xb9, 0xce, 0x01, 0x39, 0x3a, 0x04, 0x0c, 0x3b, 0xbe, 0xec, 0x2d, + 0xff, 0x07, 0x02, 0xf4, 0x61, 0x81, 0xf0, 0x39, 0x0c, 0xf3, 0xe4, 0xca, 0xc5, + 0xea, 0x21, 0xe5, 0x12, 0xef, 0xe2, 0xef, 0xeb, 0x13, 0xde, 0x21, 0x18, 0xf5, + 0xee, 0x02, 0x04, 0x43, 0xf4, 0xd7, 0xe9, 0x25, 0xd6, 0x4b, 0xff, 0x4e, 0xe1, + 0xe8, 0xd4, 0xfd, 0xe5, 0xfd, 0xf0, 0xde, 0xe7, 0x0e, 0xe9, 0xd3, 0xd0, 0x2f, + 0x25, 0xe1, 0x06, 0xfc, 0x21, 0xd7, 0xdf, 0x25, 0x7f, 0x1b, 0xee, 0x01, 0xed, + 0xf4, 0x29, 0xf3, 0x3e, 0x09, 0x22, 0xd8, 0xd9, 0x0e, 0xc5, 0x2e, 0xe5, 0x16, + 0x15, 0x3d, 0xb9, 0x0d, 0xff, 0xc5, 0xe0, 0xff, 0xfe, 0x33, 0xe3, 0x19, 0x61, + 0xe4, 0xfb, 0xfc, 0x32, 0xbf, 0xea, 0x00, 0x38, 0x45, 0x2b, 0xc5, 0x25, 0xec, + 0xd7, 0x0c, 0xf0, 0x30, 0xd0, 0xc1, 0x02, 0x20, 0xd9, 0xf4, 0x23, 0x5e, 0x21, + 0x45, 0x0f, 0x28, 0xe6, 0x4d, 0x02, 0x39, 0x08, 0xf1, 0xe4, 0xbd, 0x16, 0xff, + 0x02, 0xfe, 0xee, 0xe2, 0xd3, 0xcb, 0x35, 0x6c, 0x65, 0xfe, 0x03, 0x00, 0xf3, + 0xf0, 0xb9, 0x51, 0x0a, 0x4d, 0x01, 0x48, 0xd7, 0x12, 0x17, 0x1a, 0x0a, 0xf2, + 0x2f, 0x07, 0xf8, 0x02, 0xf5, 0x47, 0xca, 0x17, 0x09, 0xd3, 0x57, 0xfd, 0xe1, + 0xec, 0x05, 0xf9, 0x03, 0xfa, 0xdd, 0xf4, 0x3f, 0xb6, 0x00, 0x1c, 0xd9, 0x4a, + 0xea, 0x23, 0x03, 0xf8, 0xf5, 0x11, 0xfc, 0x13, 0x2f, 0x09, 0xb3, 0x0b, 0xeb, + 0x0d, 0x19, 0xf3, 0x27, 0xff, 0x03, 0xcb, 0x18, 0x56, 0xd9, 0x1d, 0xec, 0xbb, + 0xe5, 0x22, 0xf9, 0xf6, 0x14, 0x13, 0x7f, 0x0c, 0x1b, 0xb0, 0x0e, 0x19, 0x2c, + 0x2e, 0x03, 0x31, 0x0c, 0xff, 0x31, 0x11, 0x18, 0x03, 0x28, 0xde, 0x1b, 0xe4, + 0x1e, 0x1b, 0xfb, 0x10, 0xed, 0x0f, 0xff, 0x18, 0xd9, 0x1a, 0xde, 0xfa, 0xe7, + 0xb4, 0x30, 0xbe, 0x4f, 0x01, 0x20, 0x1a, 0x02, 0xfe, 0x61, 0x0e, 0x22, 0x1d, + 0x0e, 0x30, 0x38, 0xc0, 0xdd, 0x2c, 0xf5, 0xd1, 0x03, 0x2f, 0x51, 0x3f, 0xdd, + 0xdb, 0xfc, 0x13, 0x23, 0xc5, 0x07, 0x02, 0xa5, 0x20, 0x35, 0xf9, 0x0b, 0xdd, + 0xf9, 0x1a, 0xfc, 0x0e, 0xfb, 0x23, 0x20, 0x3f, 0x12, 0x1c, 0xe2, 0xff, 0xec, + 0xdf, 0xe5, 0xdb, 0x0a, 0x03, 0x16, 0xc1, 0x0e, 0xe0, 0xf3, 0x09, 0xfc, 0x0a, + 0xd9, 0x03, 0x7f, 0x06, 0x26, 0xfe, 0xfb, 0x06, 0xcd, 0xe9, 0x0f, 0x1e, 0xfa, + 0xe8, 0x18, 0xd5, 0xdf, 0x1b, 0x12, 0xe0, 0x1c, 0xe7, 0x16, 0x15, 0xb4, 0x03, + 0xf5, 0xca, 0xd4, 0x33, 0x0a, 0xf7, 0xfc, 0x31, 0xb2, 0xef, 0xf2, 0xf1, 0xf2, + 0xfe, 0xf3, 0xf9, 0xfd, 0xf6, 0xd4, 0x05, 0x10, 0x60, 0x48, 0x11, 0xd8, 0xf4, + 0x23, 0x08, 0xf4, 0xee, 0xe4, 0xc6, 0x22, 0x14, 0xdc, 0xfc, 0x06, 0xff, 0x18, + 0x0f, 0x1c, 0xf2, 0xdd, 0x30, 0x35, 0x53, 0x01, 0xd0, 0xfa, 0xdd, 0x1a, 0x0d, + 0x54, 0x09, 0xcf, 0x1e, 0xf4, 0x0d, 0xef, 0x02, 0x1a, 0xf0, 0x10, 0xef, 0x18, + 0xfc, 0x0a, 0x1a, 0xfc, 0x0a, 0xec, 0x0f, 0x2e, 0x01, 0xfa, 0x27, 0x19, 0xfd, + 0xef, 0x0f, 0xef, 0x3f, 0xf3, 0x04, 0xf7, 0x0b, 0x3d, 0x2e, 0xef, 0x02, 0xea, + 0xf8, 0xf1, 0xb5, 0x02, 0x3d, 0xb7, 0x0c, 0xc2, 0xf2, 0x24, 0x02, 0xc8, 0x4d, + 0xd7, 0x16, 0xee, 0x2c, 0x22, 0xa4, 0x21, 0x00, 0x0d, 0xe4, 0xc1, 0xff, 0x3b, + 0xf2, 0x18, 0x10, 0x7f, 0x27, 0xd9, 0xfd, 0x0b, 0x11, 0xfa, 0xac, 0xd7, 0x0e, + 0xd2, 0xc8, 0xbd, 0xf9, 0xd4, 0x1c, 0x4f, 0x48, 0xe4, 0xf1, 0x02, 0x2c, 0xab, + 0x3c, 0x0d, 0x97, 0xc9, 0xc2, 0xdb, 0xeb, 0xf6, 0x17, 0x36, 0xb7, 0x09, 0xfb, + 0xea, 0xfa, 0xad, 0xcf, 0xf9, 0xee, 0x2c, 0x38, 0x64, 0xb2, 0xb7, 0xe7, 0xf7, + 0xe4, 0xf6, 0x1b, 0x0f, 0xfb, 0x0a, 0xf4, 0x11, 0xc6, 0x0c, 0xfa, 0xa0, 0xec, + 0xf7, 0xe6, 0xc3, 0x21, 0xd7, 0xe1, 0xfe, 0x9e, 0xc9, 0x01, 0xef, 0x05, 0xbc, + 0xb4, 0x2a, 0x46, 0x42, 0xbc, 0xd7, 0xe9, 0xec, 0x17, 0xfc, 0x24, 0xff, 0x47, + 0x8f, 0x4f, 0xfc, 0xeb, 0xcd, 0xdc, 0xea, 0xec, 0x91, 0xe6, 0xee, 0x26, 0x9f, + 0xf3, 0x0e, 0xe2, 0x1e, 0x18, 0xa9, 0x56, 0xe2, 0x96, 0x3a, 0x02, 0xf9, 0xa0, + 0x21, 0x47, 0x51, 0x28, 0xd2, 0x0f, 0xa6, 0x86, 0x16, 0xf7, 0xec, 0xea, 0xa5, + 0xcf, 0x4b, 0x24, 0x4f, 0xfb, 0xc4, 0x43, 0x47, 0xf2, 0xd5, 0x31, 0xa4, 0x48, + 0xc0, 0xe5, 0xc5, 0xe9, 0x97, 0xa3, 0xbf, 0xe6, 0xed, 0x66, 0xf1, 0xff, 0x0e, + 0x6c, 0x42, 0x5c, 0xef, 0xe3, 0x25, 0x4e, 0xd3, 0xac, 0xc3, 0xf7, 0x25, 0x09, + 0xd3, 0x13, 0x02, 0xea, 0xd6, 0x29, 0x4e, 0xd5, 0x23, 0x35, 0xd0, 0xd8, 0xe8, + 0xc5, 0x3c, 0x81, 0xad, 0x38, 0x02, 0xa9, 0x98, 0xe8, 0xcd, 0x2e, 0xd7, 0xd5, + 0xb7, 0x0e, 0x48, 0x2b, 0x5a, 0x41, 0x57, 0x14, 0xc4, 0x10, 0xeb, 0x61, 0x16, + 0x1b, 0xa3, 0xfc, 0x33, 0xf7, 0xeb, 0x96, 0x24, 0xe9, 0xdf, 0x26, 0x05, 0x19, + 0xe3, 0xf2, 0x08, 0x4a, 0xdb, 0xbc, 0x08, 0x13, 0x0b, 0x81, 0x09, 0xf1, 0x04, + 0x05, 0x09, 0x1c, 0x56, 0xe2, 0x11, 0x0a, 0x0f, 0xc6, 0x54, 0xfd, 0x15, 0xcc, + 0x20, 0xfc, 0x18, 0xfb, 0x0a, 0xee, 0x39, 0x21, 0x35, 0xd4, 0xeb, 0x2b, 0xe1, + 0x2b, 0x11, 0x2e, 0xd9, 0x26, 0xdd, 0xc0, 0x11, 0xf3, 0x31, 0xe2, 0xeb, 0xf0, + 0xf1, 0xf9, 0xe7, 0xfa, 0x14, 0xd2, 0xe7, 0xf3, 0x1f, 0x28, 0x46, 0xf5, 0x36, + 0xcf, 0x14, 0xea, 0x01, 0x10, 0xb8, 0xcb, 0x0b, 0x17, 0xc6, 0xf2, 0xf0, 0xe2, + 0xf4, 0x31, 0xdf, 0x2d, 0x23, 0xf2, 0x02, 0x12, 0x0f, 0x44, 0x1f, 0xfa, 0x2f, + 0x08, 0x39, 0x22, 0xc6, 0xe3, 0xc5, 0x0b, 0x13, 0x02, 0xcf, 0xd8, 0x09, 0x12, + 0xc9, 0xd3, 0xec, 0x0c, 0xe3, 0xe7, 0x17, 0x39, 0x10, 0x27, 0x05, 0x1b, 0x1b, + 0x1c, 0xe8, 0x12, 0x13, 0x2a, 0xde, 0xec, 0xfb, 0xe5, 0xfd, 0x37, 0xe3, 0xcb, + 0x20, 0xe1, 0x2f, 0xc5, 0x20, 0xc2, 0x06, 0x29, 0x0e, 0xdf, 0x5b, 0xf6, 0xfc, + 0xcf, 0x55, 0xf3, 0x7e, 0xca, 0x0d, 0xfd, 0xd3, 0xbd, 0xd0, 0x04, 0x09, 0x99, + 0x30, 0xd9, 0x24, 0xc0, 0xf1, 0xe7, 0x4a, 0xfc, 0x6c, 0xf3, 0x01, 0xd4, 0xfa, + 0x1c, 0x5e, 0x20, 0xea, 0xc3, 0x06, 0xc9, 0x0a, 0x8a, 0x32, 0xe2, 0x2f, 0xf3, + 0x1f, 0x12, 0x39, 0x12, 0x12, 0xaa, 0x02, 0x3f, 0x51, 0xb5, 0x59, 0x1f, 0x32, + 0x13, 0x1a, 0x22, 0xc9, 0xf0, 0xff, 0xef, 0xb1, 0xd9, 0xc6, 0xdd, 0xf2, 0xfa, + 0x2e, 0x3a, 0x4f, 0xd4, 0x02, 0xc7, 0xcf, 0xf7, 0xcb, 0x12, 0x8f, 0x0a, 0x14, + 0xe5, 0x85, 0x0d, 0xbe, 0xd1, 0xa3, 0x22, 0x50, 0xa7, 0x4d, 0xec, 0xe0, 0x0b, + 0x24, 0xb0, 0x31, 0x4c, 0x17, 0xf7, 0x00, 0x8c, 0xe0, 0x7f, 0x1b, 0xe6, 0xdd, + 0xf5, 0x36, 0x04, 0xf7, 0x93, 0xef, 0x38, 0x4c, 0x03, 0x1b, 0x5f, 0xe9, 0x26, + 0x20, 0x14, 0xfb, 0xf1, 0x0a, 0xcf, 0xfe, 0x09, 0x05, 0xaa, 0x34, 0x21, 0xc4, + 0xcb, 0x09, 0xf3, 0xdc, 0xff, 0x7f, 0x0f, 0xda, 0x0e, 0x22, 0x23, 0x2f, 0xf7, + 0x11, 0xf9, 0x13, 0x18, 0x2d, 0xe0, 0x34, 0x34, 0x19, 0xe4, 0x0c, 0x27, 0xbd, + 0x08, 0xe0, 0xe8, 0xeb, 0x19, 0xff, 0x1e, 0x0c, 0xe9, 0xfc, 0x49, 0x07, 0x0c, + 0x10, 0x15, 0xdb, 0x20, 0x02, 0x26, 0x07, 0x1c, 0x25, 0x23, 0xd0, 0x10, 0x12, + 0x46, 0xe4, 0xc8, 0x02, 0xdf, 0x0e, 0x14, 0xfb, 0xe9, 0xf7, 0x1a, 0x0b, 0x0b, + 0x22, 0x02, 0xf9, 0x0f, 0xf9, 0x24, 0x0a, 0x27, 0x10, 0x0f, 0x23, 0x1a, 0x87, + 0x01, 0xf4, 0xde, 0x10, 0x06, 0x04, 0x1b, 0xe9, 0xdd, 0xe2, 0x0c, 0x19, 0xc5, + 0x0a, 0x0b, 0x19, 0xe6, 0x20, 0x35, 0xf3, 0x22, 0xf7, 0xff, 0x39, 0x1a, 0x06, + 0xed, 0x21, 0xf7, 0xd3, 0x09, 0x22, 0x05, 0xe5, 0xf0, 0x0a, 0xf6, 0xfe, 0x0a, + 0x13, 0x05, 0x51, 0x19, 0x10, 0x34, 0xfd, 0x44, 0xf4, 0xe3, 0xf8, 0xf2, 0xf4, + 0x30, 0xe9, 0xf8, 0x19, 0xfa, 0x0a, 0xdb, 0x0e, 0x0a, 0xc9, 0xff, 0xe7, 0xdd, + 0x28, 0xf3, 0x05, 0x42, 0xe6, 0xf3, 0x18, 0xf9, 0xe9, 0xf4, 0x08, 0x20, 0x1d, + 0x20, 0x39, 0xe8, 0x11, 0x07, 0xf7, 0xd1, 0x3a, 0xee, 0xdc, 0xfa, 0x35, 0xf3, + 0x0d, 0x17, 0x12, 0xf9, 0x1c, 0xfa, 0x09, 0x06, 0x05, 0x17, 0x27, 0x00, 0x21, + 0xcb, 0x0c, 0xff, 0x20, 0xc7, 0x03, 0xf4, 0x0a, 0x20, 0x15, 0xe1, 0x26, 0x02, + 0xd9, 0x12, 0x0e, 0x41, 0xfc, 0x24, 0x01, 0xe9, 0x24, 0xeb, 0x05, 0x19, 0x1b, + 0x11, 0xd4, 0x27, 0xe1, 0x08, 0x07, 0xfb, 0xe3, 0xe1, 0x20, 0x1e, 0xfd, 0xe6, + 0xc1, 0x1d, 0xda, 0xe9, 0xd8, 0x03, 0x08, 0xc1, 0x19, 0x0f, 0x33, 0xde, 0xf3, + 0x17, 0xe9, 0x0b, 0x0d, 0x04, 0x7f, 0x1d, 0xfd, 0x05, 0x36, 0xb6, 0xd1, 0x22, + 0x07, 0x5e, 0x1e, 0xeb, 0xfc, 0x3c, 0xd1, 0x15, 0x0a, 0x1b, 0x11, 0xd7, 0x29, + 0x19, 0x3d, 0xa9, 0x20, 0xda, 0xc0, 0xeb, 0xa3, 0x20, 0xdf, 0xe0, 0x8f, 0xee, + 0x0e, 0xf8, 0xf0, 0xfb, 0x16, 0xed, 0x43, 0x0b, 0xb0, 0x1c, 0x06, 0x85, 0x26, + 0xe8, 0x23, 0xc4, 0x65, 0x11, 0x26, 0xf4, 0x2d, 0xfa, 0x11, 0xd1, 0xc9, 0x42, + 0xdd, 0x1f, 0xbe, 0xae, 0x0b, 0x03, 0x52, 0x07, 0xc1, 0xd7, 0x25, 0x23, 0x07, + 0x2c, 0xd5, 0x0b, 0x1a, 0x14, 0x3b, 0xd8, 0x13, 0x31, 0x37, 0x0d, 0x1d, 0x25, + 0xda, 0xe8, 0x03, 0x17, 0xf9, 0x7f, 0x03, 0x01, 0x30, 0x29, 0x53, 0x56, 0xf6, + 0x18, 0x9b, 0xde, 0xe9, 0xc3, 0xed, 0xe6, 0x1a, 0x9e, 0x37, 0xda, 0x0f, 0xcb, + 0x2c, 0x21, 0xd8, 0x42, 0x16, 0x00, 0x22, 0x36, 0x45, 0x18, 0xbf, 0xff, 0x0d, + 0x25, 0xff, 0xaf, 0xf8, 0xef, 0xdc, 0x1c, 0x9f, 0x05, 0xeb, 0x26, 0xe2, 0xdd, + 0x3c, 0x02, 0x06, 0xfa, 0xe9, 0xf7, 0xa9, 0x15, 0x07, 0xf8, 0xf7, 0x0c, 0xfe, + 0xe1, 0xff, 0x24, 0x9e, 0xd7, 0xbe, 0xdf, 0x0a, 0xf6, 0xca, 0x05, 0xf6, 0x15, + 0xe7, 0xf2, 0x3b, 0x0f, 0xdb, 0x2c, 0x27, 0x98, 0x13, 0x74, 0xff, 0xf7, 0x11, + 0xde, 0x40, 0x2d, 0xeb, 0x02, 0xe2, 0xe7, 0xea, 0xdf, 0x00, 0x32, 0xea, 0xd9, + 0xfc, 0xc6, 0xfc, 0xf5, 0xdd, 0x02, 0xd7, 0xd7, 0xe1, 0x23, 0xe5, 0xbf, 0xcd, + 0x64, 0x4a, 0xe4, 0xf3, 0x7f, 0x1d, 0x05, 0x96, 0x53, 0x22, 0xe8, 0xb6, 0xc2, + 0x18, 0x23, 0x1a, 0x64, 0xec, 0x03, 0xe5, 0xcc, 0x4e, 0x6d, 0xf5, 0x5f, 0xf0, + 0x86, 0x00, 0xc0, 0xdd, 0x28, 0x15, 0x47, 0x1a, 0x21, 0x00, 0xdf, 0x0c, 0xd2, + 0xf5, 0x0b, 0xd8, 0xd5, 0x37, 0x2c, 0xf6, 0x1a, 0x15, 0xce, 0xe4, 0xef, 0xf9, + 0x1f, 0x08, 0xd1, 0x41, 0x0f, 0xd1, 0x44, 0xe5, 0x25, 0x36, 0x0e, 0x0c, 0xf6, + 0xf6, 0xf2, 0x2c, 0x22, 0xb1, 0x1d, 0x15, 0x21, 0x5b, 0x25, 0x11, 0x75, 0xba, + 0xd9, 0x10, 0x1e, 0xf7, 0x01, 0xdd, 0xf6, 0x7f, 0xb7, 0xfc, 0x12, 0x1e, 0x02, + 0xcb, 0xeb, 0xf0, 0x00, 0xea, 0xbd, 0x35, 0xbc, 0x1f, 0x10, 0x14, 0xd2, 0x07, + 0xdc, 0xce, 0xc6, 0x02, 0x01, 0x21, 0x50, 0xc8, 0xb7, 0xf2, 0x23, 0xcd, 0xce, + 0x02, 0xb8, 0x4c, 0x01, 0xbf, 0x2e, 0xea, 0x1e, 0x52, 0x3e, 0xc5, 0xfd, 0x37, + 0x07, 0x2b, 0x0f, 0x14, 0xaf, 0xfd, 0x26, 0xdc, 0xe4, 0xf8, 0x1a, 0x0b, 0xff, + 0x65, 0x02, 0x00, 0x35, 0xaf, 0x33, 0xd5, 0x30, 0x62, 0x11, 0x04, 0xe2, 0xe3, + 0xda, 0x39, 0x3b, 0x2e, 0x1f, 0x47, 0x55, 0x39, 0x0c, 0xf8, 0x22, 0x1e, 0x2d, + 0xce, 0x75, 0x07, 0x02, 0x0a, 0xfa, 0x43, 0x58, 0x15, 0xcb, 0xf9, 0x3f, 0xcb, + 0xdc, 0xe0, 0xf0, 0x04, 0x46, 0xbc, 0xca, 0x0f, 0xf9, 0x04, 0xe7, 0x25, 0x15, + 0xb8, 0xe1, 0xd8, 0x14, 0x24, 0x49, 0x0e, 0x2c, 0xe1, 0x98, 0x1c, 0xdb, 0xfe, + 0x34, 0xe8, 0xe7, 0xea, 0x16, 0x0f, 0x00, 0x49, 0x7f, 0x34, 0x41, 0xe3, 0x0b, + 0x0e, 0x49, 0x63, 0x45, 0xf3, 0xe8, 0xe1, 0xcc, 0xcc, 0xbd, 0x49, 0x07, 0xcc, + 0xee, 0xf4, 0x53, 0x02, 0x5e, 0x23, 0x31, 0xe0, 0xf8, 0xfb, 0xf5, 0xe1, 0xeb, + 0xd7, 0xe8, 0x02, 0x2c, 0x30, 0xcd, 0x27, 0x31, 0xcb, 0xf0, 0xe6, 0x03, 0xf9, + 0x67, 0xee, 0xd8, 0x36, 0xb9, 0x02, 0x4c, 0xdf, 0xae, 0xd0, 0xfc, 0xf8, 0xc5, + 0x50, 0xde, 0x46, 0x00, 0xf9, 0xdd, 0xc5, 0x68, 0x12, 0xfc, 0xe2, 0xff, 0xee, + 0xe4, 0xf2, 0xec, 0xf9, 0x77, 0xc7, 0x7f, 0x2a, 0x1e, 0xf2, 0xd0, 0x45, 0x9b, + 0x61, 0xff, 0x33, 0xdd, 0x20, 0xaf, 0xed, 0x6a, 0x03, 0x1a, 0xe2, 0x5a, 0x08, + 0x07, 0x50, 0xc6, 0xd8, 0x1f, 0x02, 0xc5, 0xe6, 0xe4, 0xb3, 0xfe, 0x0f, 0x1f, + 0xe0, 0x02, 0xf5, 0xd1, 0x1e, 0xfb, 0xa4, 0x07, 0x1a, 0xcb, 0x34, 0xcf, 0xf6, + 0x16, 0x38, 0x1b, 0x19, 0x2e, 0x2d, 0xe7, 0xc5, 0xca, 0xe3, 0x19, 0x10, 0x03, + 0xdc, 0xd1, 0xfd, 0x35, 0x0e, 0x0c, 0xb0, 0xe2, 0x5a, 0xdd, 0xf3, 0x81, 0xee, + 0xe0, 0x18, 0xea, 0xe5, 0x42, 0x6f, 0x07, 0xf9, 0xa2, 0x6e, 0xd4, 0x36, 0x14, + 0x49, 0xd0, 0x4f, 0x0b, 0xe6, 0xd6, 0xbf, 0x0b, 0xea, 0x13, 0x1a, 0xc6, 0x08, + 0x1c, 0x1d, 0xb3, 0xfe, 0x0a, 0xe7, 0x23, 0xe6, 0xd0, 0xc7, 0xc9, 0xe7, 0xf3, + 0x43, 0x1b, 0x02, 0x66, 0xee, 0x02, 0x5b, 0xf3, 0x31, 0x0a, 0x5b, 0xc6, 0xef, + 0xdb, 0xd5, 0x35, 0xec, 0xf8, 0x3a, 0xb5, 0xf9, 0x25, 0xfc, 0x40, 0xa3, 0x24, + 0x0f, 0xfb, 0xd4, 0x13, 0xf6, 0xee, 0xb2, 0x2f, 0xef, 0x8b, 0xf5, 0x28, 0x69, + 0xef, 0xc4, 0xdb, 0x03, 0xfe, 0xe8, 0x00, 0x01, 0x3e, 0x1b, 0x2a, 0x3f, 0x2a, + 0x11, 0x0b, 0x03, 0xfa, 0xdc, 0xef, 0x1d, 0x47, 0xd1, 0xfe, 0x23, 0x14, 0x0b, + 0x0e, 0x2c, 0xd5, 0x4d, 0x0e, 0xcc, 0xd0, 0xed, 0x2e, 0x1d, 0x0e, 0x11, 0xfa, + 0xfb, 0xc4, 0xea, 0x33, 0x02, 0x36, 0x1e, 0xd4, 0xc5, 0x0c, 0xdf, 0xd8, 0x25, + 0xc3, 0xfa, 0xcc, 0x2c, 0x39, 0xc0, 0xea, 0xee, 0x06, 0xda, 0x27, 0x31, 0x1e, + 0x19, 0xff, 0x00, 0x0c, 0xf5, 0x12, 0xbe, 0x06, 0xd1, 0x5d, 0x13, 0xe6, 0xcc, + 0xc9, 0xf9, 0x6c, 0xf7, 0xe7, 0x57, 0xcc, 0x03, 0xd8, 0x3a, 0xb4, 0x7f, 0x1b, + 0xf7, 0xd3, 0x1f, 0xfe, 0xcc, 0xeb, 0xf6, 0x34, 0x12, 0xd0, 0xcd, 0x4b, 0xd8, + 0xeb, 0x11, 0x0d, 0xfd, 0x21, 0xf9, 0xd2, 0x90, 0x25, 0x03, 0xe8, 0x01, 0x1a, + 0x0c, 0x22, 0x29, 0x5e, 0xdd, 0xf0, 0xc4, 0x3e, 0xe1, 0xaf, 0x09, 0x1c, 0x03, + 0x4a, 0x1e, 0x27, 0x17, 0xe9, 0x35, 0xe4, 0xfb, 0xe9, 0x11, 0xc6, 0xcf, 0x02, + 0xb8, 0x35, 0x4d, 0x5f, 0xe2, 0xd9, 0x13, 0xff, 0x5a, 0x14, 0x15, 0x0f, 0xd3, + 0xca, 0xdc, 0xf9, 0x21, 0x1d, 0x48, 0xe4, 0x40, 0x20, 0xda, 0xce, 0xf0, 0x38, + 0xfe, 0xc9, 0x08, 0xdf, 0x13, 0x16, 0x27, 0xfe, 0xb1, 0xf0, 0xde, 0xa1, 0x1c, + 0xd9, 0x04, 0xf2, 0xe0, 0xf7, 0xe9, 0xd9, 0x30, 0x1b, 0x01, 0xde, 0xc4, 0xf8, + 0xe2, 0xd2, 0x13, 0xf5, 0x47, 0x07, 0xec, 0x57, 0xe7, 0xd2, 0xf6, 0xe3, 0xb5, + 0xfc, 0xbc, 0x00, 0x36, 0xef, 0x7f, 0x27, 0x43, 0xc8, 0xb1, 0x3a, 0xed, 0xd8, + 0xf0, 0x1b, 0x2e, 0xe4, 0x34, 0x4c, 0xfd, 0xf0, 0x0e, 0x48, 0xd9, 0x18, 0x26, + 0x2d, 0x04, 0xbd, 0xad, 0xd7, 0xbf, 0x08, 0xe4, 0x1e, 0x0c, 0xff, 0x6b, 0x39, + 0xe9, 0x25, 0x25, 0xf6, 0xf2, 0xe2, 0x00, 0x1f, 0xce, 0x53, 0xf6, 0x02, 0xf5, + 0xd2, 0x0b, 0xf9, 0x19, 0xfb, 0x10, 0xfa, 0xdc, 0xd7, 0xfa, 0xf9, 0x0e, 0xf8, + 0xdc, 0x05, 0x0a, 0x20, 0x12, 0x12, 0xf8, 0x1b, 0x39, 0x36, 0x0b, 0xc5, 0xf9, + 0x12, 0x01, 0xb0, 0xa3, 0xd3, 0xcc, 0x03, 0xef, 0x3e, 0x10, 0x28, 0x35, 0x14, + 0x34, 0x17, 0x10, 0xe5, 0x59, 0x2b, 0xfb, 0xcb, 0xe8, 0x06, 0xe6, 0xf9, 0xd8, + 0xd2, 0xf9, 0xa0, 0xe6, 0x99, 0x16, 0xf5, 0x59, 0x47, 0xbd, 0x3c, 0xd6, 0xda, + 0x02, 0xf9, 0x7f, 0xe0, 0xc6, 0xfe, 0xe4, 0x11, 0xc8, 0x0b, 0x19, 0xeb, 0x27, + 0x0a, 0x1e, 0xdd, 0x1a, 0x06, 0x0c, 0x0a, 0x10, 0xfa, 0x36, 0x1e, 0xbe, 0xb8, + 0x9b, 0x16, 0x0f, 0xcc, 0x0c, 0x00, 0x41, 0x1d, 0x44, 0x1a, 0x10, 0xf4, 0xff, + 0x51, 0xfc, 0x23, 0x37, 0xfd, 0xe0, 0x20, 0x2a, 0xe5, 0x2b, 0x4e, 0xf6, 0x09, + 0x3f, 0x1f, 0xeb, 0x0b, 0xe5, 0xe3, 0xcd, 0xd5, 0xb3, 0x15, 0x39, 0x22, 0x95, + 0xd7, 0x32, 0xb2, 0xcc, 0x19, 0xe2, 0x28, 0xd2, 0x55, 0xd7, 0x41, 0x81, 0x44, + 0x0c, 0xfa, 0x22, 0xf5, 0xd9, 0xdd, 0xe9, 0xd9, 0x1b, 0x17, 0x79, 0x96, 0x24, + 0x04, 0x16, 0x19, 0x19, 0xd2, 0x0b, 0xde, 0xce, 0xbb, 0xc9, 0xc2, 0x05, 0x20, + 0x20, 0x0b, 0xce, 0xe6, 0xe4, 0x0c, 0xdd, 0x06, 0xd1, 0x18, 0x0b, 0xfe, 0xf3, + 0xe6, 0x08, 0xf6, 0xeb, 0x92, 0x09, 0xd4, 0x01, 0x14, 0x54, 0x4c, 0x4b, 0x0f, + 0x27, 0x21, 0x32, 0xea, 0xb4, 0xc3, 0x11, 0xcc, 0xc9, 0xf9, 0x19, 0xd3, 0x6a, + 0x09, 0x2b, 0xe2, 0xf7, 0x0f, 0x09, 0x84, 0xc8, 0x64, 0xb1, 0xdb, 0xf7, 0x51, + 0x1e, 0xe5, 0x6a, 0xdf, 0x1e, 0xf4, 0xad, 0x0f, 0xb6, 0x00, 0xea, 0xde, 0x12, + 0x7b, 0xab, 0xdd, 0x39, 0x19, 0xf2, 0x90, 0x30, 0x1b, 0xe4, 0x3d, 0x39, 0x3b, + 0x3b, 0x08, 0x0a, 0xe6, 0xd0, 0x47, 0x01, 0xcf, 0xf7, 0x04, 0xd7, 0x22, 0x9f, + 0xb9, 0x34, 0xdd, 0x81, 0x33, 0x16, 0xda, 0x18, 0x2e, 0x2d, 0xec, 0x1b, 0xf3, + 0xf2, 0xfe, 0xd4, 0x00, 0xf9, 0xc1, 0x4f, 0xd7, 0xff, 0xfe, 0xa4, 0x1a, 0x05, + 0x19, 0xfb, 0xfc, 0x04, 0x15, 0xff, 0xf9, 0xe9, 0x12, 0xfe, 0x02, 0x0e, 0x0f, + 0x06, 0x2f, 0xc1, 0xe7, 0xbb, 0xbe, 0xbf, 0xd7, 0xfa, 0xff, 0xd9, 0xd9, 0xf9, + 0xfa, 0xfd, 0xf9, 0xcd, 0x09, 0xe4, 0xfc, 0xf2, 0x2a, 0x23, 0x20, 0xf6, 0xf2, + 0xb2, 0x55, 0xe5, 0xeb, 0x29, 0xf3, 0xef, 0x17, 0x08, 0xf9, 0x0a, 0x20, 0xfe, + 0x05, 0x3a, 0x43, 0x1b, 0xe0, 0x2b, 0x23, 0x00, 0x16, 0xf4, 0x2d, 0x31, 0x00, + 0x0e, 0xf7, 0x31, 0x39, 0x39, 0x39, 0xef, 0x14, 0x08, 0x32, 0x2e, 0x37, 0xf6, + 0xf9, 0xe3, 0xcb, 0xef, 0xa9, 0xcf, 0x0f, 0xd8, 0xea, 0x97, 0xfa, 0xf4, 0x14, + 0x1d, 0xd5, 0xd9, 0xef, 0xda, 0x38, 0xed, 0x0d, 0xf9, 0x2d, 0xd7, 0xf5, 0xd8, + 0x2b, 0xd4, 0x08, 0xe2, 0x32, 0xfa, 0x4a, 0x7f, 0x2a, 0x3f, 0xe1, 0x19, 0xd9, + 0xef, 0xc0, 0x02, 0x3a, 0x25, 0x2b, 0xe8, 0xc1, 0xa6, 0x30, 0x06, 0xc7, 0x22, + 0xf4, 0x07, 0xea, 0x19, 0x1c, 0x0c, 0x16, 0xe1, 0x30, 0x43, 0x1e, 0xf2, 0xfb, + 0xe2, 0xed, 0x4d, 0x49, 0xb9, 0xb9, 0x9d, 0xd2, 0x27, 0xf7, 0xfb, 0x20, 0xba, + 0x19, 0xdb, 0x22, 0xe6, 0x1f, 0x2b, 0xf2, 0x35, 0x2f, 0xd2, 0x05, 0xd3, 0x27, + 0xef, 0x12, 0xe5, 0x1b, 0xdd, 0x0e, 0xdf, 0xd6, 0xd0, 0xf6, 0xf8, 0xe4, 0xc6, + 0xd0, 0x62, 0x16, 0xd7, 0xc9, 0x1e, 0x17, 0xc9, 0x04, 0x30, 0xd7, 0x04, 0x0e, + 0x02, 0xf1, 0x06, 0x09, 0x01, 0x0d, 0x3c, 0xed, 0x05, 0x0b, 0xaf, 0xca, 0x04, + 0x09, 0xe1, 0x19, 0x06, 0x36, 0x19, 0xe0, 0xe8, 0x06, 0xcb, 0xc4, 0xf2, 0x40, + 0x08, 0xba, 0x4e, 0xfa, 0x93, 0xd6, 0x9d, 0x05, 0x24, 0xa4, 0x04, 0x50, 0x1c, + 0xe0, 0x54, 0x23, 0xd6, 0xbc, 0x66, 0xc7, 0x57, 0x71, 0xfb, 0x59, 0x1e, 0x59, + 0x0d, 0xec, 0xd3, 0xe6, 0x0a, 0x01, 0x57, 0xb5, 0x30, 0xe4, 0xd8, 0x40, 0x1a, + 0x39, 0xd8, 0x50, 0xf3, 0xe6, 0x12, 0x20, 0xea, 0x4b, 0xf9, 0x2a, 0x0a, 0xfc, + 0x29, 0xe1, 0xa1, 0x4d, 0x2b, 0x6e, 0x19, 0x22, 0x46, 0x1a, 0xc4, 0xe5, 0xf6, + 0xce, 0x43, 0xed, 0x2e, 0xe1, 0xe0, 0x2a, 0x41, 0xd4, 0xb4, 0xef, 0xe1, 0x13, + 0x2c, 0x36, 0xd4, 0xef, 0xdc, 0x46, 0x30, 0x4a, 0x03, 0xec, 0x2a, 0xdc, 0xaa, + 0xc6, 0x64, 0x4d, 0xf9, 0xa1, 0x15, 0xbb, 0x1f, 0x93, 0x01, 0x17, 0x07, 0xf7, + 0xab, 0x81, 0x65, 0x23, 0xf6, 0x58, 0x0b, 0x3e, 0x28, 0xc7, 0x92, 0x18, 0x32, + 0x4e, 0xec, 0xf1, 0x20, 0xe5, 0xb8, 0xae, 0xff, 0x5d, 0xd4, 0x57, 0x59, 0x46, + 0xca, 0x15, 0x42, 0xe5, 0x6f, 0x02, 0x40, 0xc2, 0xd1, 0xe1, 0xc7, 0xdc, 0x00, + 0x00, 0xed, 0xaf, 0xea, 0x2f, 0xc7, 0xdb, 0x37, 0xcd, 0x1a, 0x05, 0xd1, 0xe9, + 0xf5, 0x0a, 0xd1, 0x11, 0x6a, 0x2a, 0x30, 0x1e, 0xc8, 0x5c, 0xab, 0x1e, 0x6c, + 0xd1, 0x7a, 0x22, 0xfb, 0xea, 0x58, 0x08, 0x1c, 0x7f, 0x11, 0xe8, 0xdc, 0xc6, + 0xb8, 0x22, 0x98, 0x17, 0xc0, 0xd9, 0xb3, 0x07, 0x02, 0x57, 0xe0, 0xf4, 0x1b, + 0xa9, 0xfa, 0x39, 0xf4, 0xef, 0x23, 0xa9, 0x2d, 0x4e, 0x20, 0xb9, 0x0b, 0xda, + 0x38, 0xbb, 0x99, 0xf7, 0x18, 0xd7, 0xd4, 0x6a, 0x1d, 0x53, 0x89, 0x2c, 0xa7, + 0xcb, 0xf1, 0x04, 0xd9, 0x65, 0xfb, 0x64, 0x18, 0x08, 0xfc, 0xb5, 0x1e, 0x1b, + 0xda, 0x15, 0xb7, 0xe2, 0x18, 0x2f, 0x01, 0x22, 0xc8, 0x20, 0x3e, 0x5c, 0x8e, + 0x1f, 0xea, 0xcd, 0x4a, 0x3b, 0xe3, 0x74, 0x7b, 0x04, 0x93, 0xe1, 0x20, 0xf1, + 0x3a, 0xe5, 0xe8, 0xf5, 0xa6, 0x16, 0x60, 0xde, 0x27, 0xe5, 0xed, 0xf9, 0xbb, + 0x19, 0x20, 0xc6, 0x0f, 0x7c, 0x23, 0xd2, 0xe5, 0x0f, 0x03, 0xd9, 0xda, 0xf2, + 0xdc, 0xde, 0xcc, 0x26, 0x0b, 0x27, 0xdf, 0x19, 0x05, 0xff, 0x49, 0xc9, 0x10, + 0x28, 0x0b, 0xdd, 0xdd, 0x02, 0x01, 0xff, 0xbe, 0xd4, 0x34, 0x09, 0x0a, 0xd8, + 0xe3, 0x00, 0xc6, 0xf6, 0x0a, 0x1f, 0xee, 0xd9, 0xe5, 0x2c, 0x43, 0xe5, 0x14, + 0xec, 0x05, 0x9c, 0x0a, 0xd3, 0xfc, 0x0a, 0xd7, 0x26, 0x3e, 0x24, 0xda, 0xd0, + 0xe2, 0x4f, 0x0c, 0xd8, 0xb7, 0x60, 0x9e, 0xf8, 0xf9, 0xe5, 0x4a, 0xd0, 0xd1, + 0x69, 0x00, 0x9d, 0xb9, 0xb9, 0x28, 0xec, 0xd9, 0x1c, 0x19, 0xda, 0x71, 0xab, + 0x33, 0x7e, 0x41, 0x05, 0xeb, 0x03, 0x0c, 0x5c, 0xf7, 0x14, 0xa1, 0xd5, 0x7f, + 0xe6, 0xd2, 0x2b, 0x5f, 0xfe, 0xc0, 0xc7, 0xf6, 0xe9, 0xdc, 0xf8, 0x18, 0xd6, + 0x62, 0xe2, 0xd6, 0x2d, 0xcc, 0xd7, 0xc3, 0x7f, 0xf5, 0xd1, 0x0c, 0xee, 0x57, + 0xde, 0xbd, 0x09, 0xff, 0xcc, 0xb0, 0xc6, 0xfd, 0xad, 0xf8, 0x4a, 0xf8, 0xf4, + 0xe2, 0xd4, 0x73, 0x39, 0x45, 0xf4, 0x17, 0x11, 0xf4, 0x03, 0xfd, 0x3b, 0x02, + 0xf9, 0x15, 0xde, 0x9b, 0xeb, 0xe6, 0xeb, 0xdd, 0xe1, 0x4a, 0x17, 0xd7, 0x0b, + 0x2b, 0xe3, 0x08, 0xfc, 0x04, 0x36, 0xfe, 0x55, 0xa9, 0x16, 0x0f, 0x18, 0xfb, + 0x0a, 0xf6, 0x07, 0x3d, 0xec, 0x1b, 0x19, 0xfa, 0xbe, 0xf3, 0x2d, 0x36, 0x01, + 0x9a, 0x09, 0x33, 0xc2, 0xe8, 0xc6, 0x28, 0xec, 0x32, 0xac, 0xde, 0x1c, 0xbe, + 0x29, 0xcd, 0xde, 0x2d, 0x2a, 0x43, 0xe2, 0x3f, 0xe7, 0xc9, 0xf1, 0xf1, 0xcf, + 0x32, 0x00, 0x0b, 0xea, 0x39, 0x27, 0xeb, 0xd8, 0xef, 0x06, 0x32, 0xd6, 0xcc, + 0x08, 0xe6, 0xe1, 0xe8, 0xc4, 0x11, 0xe7, 0x0c, 0x0d, 0x1d, 0xe0, 0x0b, 0xe0, + 0x1f, 0x12, 0xf3, 0x47, 0xf5, 0xc2, 0x22, 0xd0, 0xea, 0x0f, 0xbd, 0x76, 0xdf, + 0x31, 0x1e, 0x00, 0xca, 0x26, 0x5c, 0xc1, 0x1f, 0x1b, 0x34, 0x08, 0x22, 0x15, + 0x00, 0x41, 0x2b, 0xb8, 0xf6, 0x42, 0xf9, 0x2b, 0xee, 0xcb, 0x03, 0x6f, 0x1d, + 0xc2, 0xd5, 0x0c, 0xe0, 0x28, 0xc1, 0x26, 0xc1, 0x2a, 0x4a, 0xc9, 0x35, 0xfe, + 0x09, 0xe2, 0xdf, 0xff, 0xe6, 0x2a, 0x08, 0xde, 0x42, 0xf1, 0x1b, 0x2b, 0x2a, + 0x19, 0xc0, 0x23, 0x08, 0x10, 0xbd, 0xe1, 0x88, 0x16, 0xee, 0xfa, 0x21, 0xce, + 0x40, 0xd0, 0xc3, 0xf2, 0x46, 0xd5, 0x05, 0x13, 0xed, 0x0b, 0x00, 0x67, 0x76, + 0xa6, 0x67, 0xfc, 0x64, 0x10, 0x23, 0xdf, 0xf7, 0x11, 0x36, 0x11, 0x0c, 0x2e, + 0xf5, 0xd7, 0x3c, 0xf6, 0x49, 0xdd, 0x58, 0x6b, 0x11, 0x7f, 0x29, 0x7c, 0xbf, + 0xe3, 0x3d, 0x27, 0xff, 0xbb, 0x1f, 0x00, 0xbb, 0xff, 0xdd, 0xdf, 0x0b, 0x7f, + 0x0c, 0x0d, 0x44, 0xfe, 0x67, 0x39, 0xec, 0xb7, 0x53, 0x54, 0xee, 0xcc, 0xde, + 0x39, 0xe9, 0x14, 0xfe, 0x69, 0x3c, 0xc0, 0xc0, 0x33, 0x26, 0xf6, 0x17, 0x11, + 0xcc, 0xcd, 0x66, 0xdd, 0xdf, 0x3f, 0x15, 0xf3, 0x02, 0x44, 0x29, 0x1d, 0x2c, + 0xa1, 0xd0, 0xc6, 0x03, 0x00, 0x0e, 0x66, 0x39, 0x13, 0x32, 0x68, 0xe5, 0x30, + 0x01, 0xfd, 0x56, 0xce, 0xfd, 0x08, 0x01, 0x18, 0x1b, 0x20, 0x08, 0x11, 0x4c, + 0xb2, 0x32, 0x01, 0xda, 0x0a, 0x00, 0x07, 0xbd, 0x2c, 0xdf, 0xe6, 0x35, 0xc7, + 0x22, 0xbd, 0xe7, 0x1c, 0xec, 0xc7, 0xe3, 0x56, 0x18, 0xd5, 0xfc, 0xe4, 0xe4, + 0xde, 0x45, 0x1f, 0x42, 0x00, 0x22, 0xf5, 0xf8, 0x9a, 0x64, 0x5c, 0x16, 0xf2, + 0xe2, 0xe4, 0x22, 0xf1, 0x23, 0x0a, 0x00, 0x31, 0x45, 0x21, 0xb8, 0x95, 0x1b, + 0xdb, 0x42, 0xf3, 0x4c, 0xa7, 0xc8, 0x16, 0xe2, 0xf6, 0xfc, 0xfa, 0xe6, 0xf7, + 0xd2, 0xe8, 0x0f, 0xcd, 0xe8, 0xff, 0x02, 0x09, 0xec, 0xe7, 0xf3, 0xe7, 0xc1, + 0xbd, 0xf6, 0xf7, 0xe0, 0xbd, 0x33, 0xf1, 0xfa, 0xc4, 0x16, 0x3e, 0x38, 0x1c, + 0x06, 0x11, 0xef, 0xd5, 0x37, 0xd5, 0x0a, 0x29, 0xd2, 0x06, 0x22, 0x3d, 0x0d, + 0x08, 0x44, 0x1e, 0x10, 0x14, 0x0f, 0xd4, 0x0e, 0x28, 0xec, 0x41, 0x0f, 0xdc, + 0xf0, 0xec, 0x0d, 0x08, 0xe8, 0xb0, 0x62, 0x0e, 0x25, 0x00, 0x1a, 0x00, 0x24, + 0xcc, 0xd7, 0xfb, 0xe6, 0x22, 0xfe, 0xd0, 0x1c, 0xde, 0xf3, 0xf5, 0xf6, 0x14, + 0xda, 0xe3, 0xfb, 0x06, 0xe4, 0x0b, 0x1d, 0x21, 0x21, 0x22, 0x3d, 0xe4, 0x15, + 0xf5, 0x34, 0x29, 0xca, 0x1a, 0xeb, 0x0b, 0xe2, 0x1b, 0xeb, 0x21, 0xd9, 0x0a, + 0x1c, 0xf7, 0x12, 0xfd, 0xe8, 0xcb, 0x15, 0xe1, 0xd3, 0x81, 0x02, 0x56, 0xe8, + 0xd4, 0x06, 0xd3, 0xf1, 0xf7, 0x09, 0xf2, 0xd6, 0xb8, 0x12, 0x43, 0x9b, 0x0d, + 0xf3, 0x04, 0x16, 0xca, 0xaf, 0xf8, 0x44, 0x23, 0x35, 0xf8, 0xe8, 0xea, 0x3d, + 0x00, 0x07, 0xf7, 0xe5, 0xed, 0xd4, 0xf7, 0xf8, 0x13, 0x0f, 0x2f, 0x0e, 0xd8, + 0x14, 0xe7, 0x0d, 0xd6, 0x2f, 0x3d, 0x37, 0xe8, 0xec, 0xe8, 0xb2, 0x0e, 0xf5, + 0x24, 0xe0, 0x07, 0x08, 0xe8, 0x18, 0x01, 0x10, 0x51, 0x23, 0xde, 0xe8, 0xf9, + 0x02, 0x12, 0x69, 0x05, 0x96, 0xdd, 0xda, 0xdf, 0xe2, 0x1e, 0xc4, 0xd3, 0xf1, + 0xe0, 0xd9, 0x7f, 0x23, 0x07, 0xf2, 0x14, 0x16, 0x28, 0x3d, 0x28, 0xff, 0x01, + 0x19, 0xef, 0x32, 0xf2, 0xd8, 0xde, 0x30, 0xd3, 0x08, 0x2f, 0xf2, 0xd6, 0x2f, + 0xdc, 0xfa, 0xef, 0x05, 0x18, 0xcc, 0xf1, 0x09, 0x43, 0x0f, 0x38, 0xfe, 0xe3, + 0xd5, 0xec, 0x07, 0x11, 0x0b, 0x1c, 0xed, 0x07, 0x1d, 0xdf, 0x07, 0x4d, 0xc9, + 0x21, 0xf7, 0xad, 0x4f, 0x05, 0x20, 0x0f, 0x25, 0xe5, 0xee, 0xf4, 0x1b, 0xe4, + 0x27, 0x5a, 0xd0, 0x09, 0xe0, 0xe5, 0xfd, 0xb3, 0xf8, 0x02, 0x47, 0xad, 0xf7, + 0xd2, 0x55, 0x28, 0x26, 0xd5, 0x3a, 0x12, 0xd7, 0xd0, 0x02, 0x00, 0x51, 0x81, + 0xec, 0xe5, 0xc4, 0xe4, 0xf8, 0x2f, 0x3c, 0xc9, 0xf7, 0x2b, 0xf9, 0xed, 0x30, + 0xf1, 0x6b, 0x06, 0x47, 0xee, 0xbc, 0x27, 0xc5, 0x0e, 0x1e, 0xf9, 0x6c, 0x14, + 0xf6, 0xee, 0x00, 0xd1, 0xde, 0x27, 0xf7, 0x17, 0xec, 0xee, 0x17, 0xfc, 0xe8, + 0xdf, 0xd0, 0xf6, 0xe6, 0x17, 0x0d, 0x09, 0xf5, 0xc5, 0xce, 0xe5, 0xd6, 0xc5, + 0xf3, 0x53, 0xff, 0xd4, 0x13, 0xb4, 0x0b, 0xd4, 0xec, 0xd4, 0x5d, 0x11, 0xe6, + 0xd8, 0x1b, 0xe8, 0xda, 0xab, 0xa3, 0xbb, 0x51, 0x1d, 0xf8, 0x1e, 0xd2, 0x13, + 0xca, 0x01, 0xea, 0xcc, 0xfc, 0xe8, 0x0d, 0xed, 0xa6, 0x16, 0x03, 0x2a, 0xf2, + 0xe1, 0x19, 0x15, 0xe9, 0x0a, 0x0d, 0xe7, 0x1e, 0x20, 0x22, 0xf7, 0xd2, 0x5f, + 0x17, 0x41, 0x07, 0x57, 0xdc, 0xf0, 0xe9, 0xfe, 0xbb, 0xef, 0x0e, 0x26, 0x81, + 0x25, 0x94, 0x95, 0xff, 0x0f, 0xe5, 0xfe, 0xe2, 0xef, 0xf6, 0x02, 0xb2, 0x10, + 0xc8, 0x4e, 0x6f, 0xe0, 0xec, 0xf9, 0x5c, 0x47, 0xe7, 0xa6, 0x45, 0xd7, 0xfb, + 0xfb, 0xc9, 0xf7, 0x1a, 0xd3, 0x17, 0x06, 0xfd, 0xcd, 0xf9, 0x02, 0xf6, 0xed, + 0xa7, 0x15, 0xea, 0xf2, 0x2c, 0xf1, 0xf4, 0x0c, 0x20, 0xf7, 0x38, 0xae, 0x09, + 0xf8, 0x0c, 0x30, 0xe7, 0x45, 0x38, 0x09, 0x16, 0xf2, 0x15, 0x24, 0xa3, 0x0c, + 0x13, 0x42, 0x0a, 0xeb, 0xfd, 0xf1, 0x0f, 0xdd, 0xdf, 0xc7, 0xe2, 0xb4, 0x08, + 0x46, 0x6e, 0xd8, 0x0a, 0xeb, 0xf5, 0x1e, 0xf5, 0x38, 0x04, 0x20, 0x19, 0xdd, + 0xf6, 0xd5, 0xfb, 0x8a, 0xc8, 0x1d, 0xd9, 0xa5, 0xdf, 0xf3, 0xf5, 0xcc, 0xc5, + 0x11, 0xba, 0xa1, 0x10, 0x36, 0xe4, 0xf1, 0xe1, 0xd2, 0x1b, 0x28, 0x93, 0xd2, + 0x50, 0x15, 0x6c, 0x10, 0x2e, 0x5a, 0x12, 0xc4, 0xe9, 0x2c, 0xf6, 0xff, 0xc4, + 0x3f, 0x10, 0xc6, 0xd1, 0x07, 0x0a, 0x15, 0xf7, 0x15, 0xf9, 0x07, 0xb6, 0x16, + 0xd8, 0x02, 0xe9, 0x45, 0xd0, 0x30, 0xbf, 0x1f, 0x39, 0x9f, 0xda, 0xf2, 0x14, + 0xe9, 0xe9, 0x1b, 0xf8, 0x60, 0xc7, 0xce, 0xe9, 0xce, 0x3d, 0x14, 0xc0, 0xad, + 0xd2, 0xa3, 0x2c, 0x4d, 0xd6, 0xf6, 0xcc, 0xf8, 0x11, 0x2d, 0x28, 0x26, 0x01, + 0xdd, 0xcd, 0x7f, 0xc9, 0xfe, 0xf0, 0xf6, 0xff, 0x0d, 0x4a, 0xd5, 0x1d, 0x2a, + 0x14, 0xe4, 0xda, 0xa3, 0xdc, 0xe0, 0xf8, 0xe7, 0xd1, 0xee, 0x2d, 0x3a, 0x09, + 0xbe, 0x52, 0x1b, 0xfa, 0x45, 0xfb, 0x2a, 0xae, 0x1f, 0x35, 0x1d, 0xf7, 0x41, + 0x08, 0xe7, 0x1d, 0x08, 0xd9, 0x04, 0xe0, 0xe3, 0x1f, 0xfb, 0xe8, 0x22, 0xfa, + 0x03, 0xc4, 0x28, 0xa5, 0xee, 0x26, 0x4c, 0x21, 0x36, 0xea, 0x2c, 0x28, 0xee, + 0x1a, 0x0a, 0xd4, 0xea, 0xdc, 0x36, 0x1d, 0xfe, 0xe8, 0xf7, 0xcd, 0xf5, 0xbf, + 0x0b, 0xba, 0xe6, 0xcb, 0xd7, 0x13, 0xee, 0xff, 0xe8, 0xef, 0xf3, 0x0e, 0x0d, + 0xfd, 0xf8, 0xd5, 0x1a, 0x2a, 0x05, 0xf6, 0x1f, 0xa4, 0xde, 0x02, 0x36, 0xfb, + 0xbe, 0x04, 0x23, 0xe7, 0x24, 0xca, 0x11, 0x50, 0x11, 0x18, 0x65, 0x11, 0xdb, + 0xdb, 0x5c, 0xf6, 0xe0, 0xd3, 0xd3, 0x07, 0x0d, 0x04, 0x01, 0x31, 0x10, 0x06, + 0xf8, 0xfa, 0xef, 0xbd, 0x29, 0x05, 0xea, 0xe0, 0xef, 0x20, 0x10, 0x51, 0xd4, + 0x43, 0x05, 0x48, 0x2a, 0xfd, 0x81, 0xfa, 0x2f, 0x23, 0xfb, 0x0f, 0xd0, 0x04, + 0xee, 0xbf, 0x0a, 0xf0, 0x16, 0xf5, 0x18, 0xf3, 0xee, 0xc8, 0xdc, 0x20, 0x12, + 0x40, 0xba, 0x1a, 0xf3, 0xfe, 0x3d, 0xe2, 0xdc, 0xdf, 0xec, 0x00, 0xfc, 0x08, + 0x0e, 0x0e, 0xc4, 0x24, 0xc4, 0x03, 0x24, 0x3f, 0x11, 0x60, 0xcd, 0xd0, 0xbf, + 0xfa, 0xda, 0xac, 0xe9, 0x08, 0xed, 0x0d, 0x19, 0xd8, 0x3b, 0xe1, 0xfe, 0x36, + 0x32, 0x16, 0xf3, 0x26, 0xd7, 0x2f, 0x12, 0x08, 0xd9, 0xf8, 0xf6, 0x0a, 0x11, + 0xbe, 0xfd, 0xfd, 0xdd, 0xf8, 0xc9, 0x9b, 0x6e, 0xfa, 0xe8, 0x04, 0x14, 0x36, + 0x0f, 0xcf, 0xf7, 0xf3, 0x42, 0x07, 0x13, 0xcb, 0xf8, 0xdb, 0x1d, 0x16, 0x1b, + 0xc7, 0xf7, 0xbe, 0x2b, 0xef, 0x25, 0x03, 0xf4, 0xcf, 0xd7, 0xf9, 0x06, 0x2c, + 0x22, 0x08, 0x0a, 0x14, 0x16, 0x1c, 0x47, 0xbf, 0xaf, 0x3c, 0x26, 0x3b, 0xe6, + 0xde, 0xfc, 0x12, 0x1f, 0x11, 0x01, 0xc6, 0x1c, 0x35, 0x51, 0x1b, 0x22, 0xfd, + 0xfc, 0x1a, 0xf9, 0xf8, 0x18, 0xc9, 0xfb, 0x81, 0x08, 0xd1, 0xf2, 0xc7, 0x2c, + 0x2b, 0x1f, 0xc7, 0x15, 0x0e, 0x26, 0xf1, 0xfc, 0xf5, 0xe1, 0x0e, 0xf3, 0xfe, + 0x53, 0x01, 0x13, 0x02, 0xdb, 0x26, 0xf1, 0x03, 0xfa, 0x06, 0xf1, 0xd3, 0x03, + 0xde, 0xe6, 0x28, 0xb6, 0x1d, 0xed, 0xfa, 0xf6, 0xfa, 0xcc, 0xea, 0x13, 0xe6, + 0xe5, 0x0c, 0x2e, 0xfb, 0xf3, 0x0e, 0x25, 0x49, 0x08, 0x08, 0x08, 0x2d, 0xc9, + 0xe8, 0x19, 0x0b, 0xe4, 0x27, 0xec, 0xdd, 0x14, 0x15, 0x1c, 0x2a, 0xed, 0xe0, + 0x26, 0x00, 0x45, 0x15, 0x2a, 0x30, 0xeb, 0x31, 0xf0, 0x01, 0x16, 0xcf, 0x1d, + 0xe1, 0x16, 0x0e, 0x1d, 0xfb, 0xf1, 0x3f, 0x07, 0x1f, 0x26, 0x13, 0xf9, 0x81, + 0xfe, 0xef, 0xf5, 0x1b, 0x08, 0x02, 0xd8, 0x42, 0xe7, 0xbd, 0x0f, 0x25, 0x5a, + 0x18, 0x0d, 0x00, 0x03, 0x14, 0xd7, 0x3b, 0x36, 0xe3, 0x42, 0x17, 0xfe, 0x11, + 0xd5, 0x02, 0x11, 0xb5, 0x1e, 0x14, 0x19, 0xf8, 0x07, 0x34, 0xc2, 0xd7, 0xd7, + 0xe3, 0x27, 0x12, 0xcc, 0xd1, 0xef, 0x13, 0xdb, 0xf7, 0x06, 0xf9, 0x17, 0x0c, + 0xeb, 0x5d, 0x3c, 0x1b, 0x0b, 0x3e, 0x28, 0x01, 0x1e, 0x20, 0xcd, 0xf7, 0xcf, + 0xd0, 0x39, 0xd3, 0xd7, 0x00, 0xea, 0xda, 0xe8, 0x2c, 0xf1, 0xf8, 0x81, 0xf8, + 0xc4, 0x1c, 0xeb, 0x2a, 0xbf, 0xd9, 0xc0, 0xed, 0xe1, 0x01, 0x04, 0xab, 0xdd, + 0xf3, 0x1a, 0xe4, 0x3b, 0xdd, 0x05, 0x3c, 0xf5, 0xf9, 0x19, 0x13, 0xae, 0xcc, + 0xcf, 0x45, 0xd4, 0x21, 0x0c, 0xa7, 0xa9, 0x46, 0xe1, 0xcf, 0x60, 0x28, 0xe6, + 0xf7, 0xe9, 0x45, 0xec, 0x10, 0xc5, 0x43, 0xea, 0x10, 0x08, 0x44, 0xd9, 0xe8, + 0xe4, 0xff, 0x34, 0x04, 0xcb, 0xc7, 0x05, 0x1c, 0x1c, 0xd5, 0x0e, 0x0a, 0xf3, + 0x06, 0xd4, 0xe4, 0x50, 0x0e, 0x2c, 0xfe, 0x4b, 0x91, 0x2e, 0xe8, 0x34, 0xf9, + 0x16, 0xe4, 0xf2, 0xfa, 0x4c, 0x00, 0xbf, 0x09, 0x08, 0xe9, 0x04, 0xf5, 0xb0, + 0x45, 0x1b, 0x1a, 0xef, 0x9e, 0x49, 0x38, 0xf2, 0x02, 0xb6, 0x01, 0xb5, 0xe2, + 0xe1, 0x0b, 0xab, 0x33, 0x7f, 0x0a, 0xec, 0x04, 0xf8, 0x01, 0x0e, 0x35, 0x4a, + 0xd5, 0x4f, 0xcb, 0xd9, 0xbe, 0xea, 0xec, 0x0f, 0x14, 0xb3, 0xfb, 0x0b, 0xfc, + 0x32, 0x1c, 0x0b, 0xf1, 0xe9, 0x05, 0x05, 0xcb, 0xe7, 0x15, 0xd5, 0x15, 0x0b, + 0x11, 0xf0, 0xd6, 0xec, 0x02, 0x0f, 0x3f, 0xf0, 0x29, 0x19, 0xd2, 0xcb, 0xb9, + 0x0b, 0x4e, 0x34, 0x2a, 0x18, 0x0c, 0xca, 0xe4, 0x00, 0x23, 0xec, 0xfe, 0x2e, + 0xc1, 0x48, 0x03, 0xfd, 0xe3, 0xef, 0x12, 0x37, 0xff, 0xf5, 0xdd, 0x2a, 0x03, + 0x12, 0xec, 0xed, 0xe4, 0x20, 0x06, 0x33, 0xb5, 0x49, 0x21, 0xf7, 0xf8, 0xe8, + 0x1a, 0x68, 0xe9, 0xd3, 0x5c, 0x27, 0xc4, 0x37, 0xf2, 0xc7, 0xff, 0xd1, 0x21, + 0x2c, 0x04, 0x55, 0xf0, 0x03, 0xc7, 0x24, 0xe3, 0xd3, 0xc3, 0xcf, 0x2f, 0x0c, + 0xe7, 0xc1, 0xc7, 0x0b, 0x81, 0x39, 0x1f, 0xfd, 0x28, 0xf0, 0xe0, 0x15, 0x0c, + 0xf2, 0xfb, 0x03, 0x3d, 0x0b, 0xc7, 0xea, 0xfc, 0xe1, 0xee, 0x3d, 0x14, 0x30, + 0xba, 0xfc, 0x28, 0xfd, 0x30, 0x2c, 0xfb, 0x16, 0xe9, 0x3e, 0xd1, 0xd1, 0x05, + 0xe6, 0xc2, 0xde, 0x09, 0xdb, 0xee, 0xac, 0xe7, 0xec, 0x5f, 0x21, 0xe1, 0x12, + 0x12, 0xf4, 0x24, 0x14, 0x09, 0x13, 0x03, 0xfa, 0xf5, 0xe1, 0xff, 0x2d, 0xc0, + 0x09, 0x5a, 0xcf, 0xd2, 0x04, 0xfc, 0x42, 0xbd, 0xe2, 0x09, 0xf3, 0x02, 0xd6, + 0x2b, 0x17, 0x21, 0xf4, 0xa0, 0xc9, 0xc4, 0xf2, 0x35, 0x01, 0xc8, 0x5b, 0xb5, + 0xe2, 0x47, 0x0b, 0x16, 0xc4, 0xa6, 0xfe, 0xe1, 0x05, 0xfa, 0xce, 0xd0, 0xf3, + 0x33, 0x23, 0x03, 0xc9, 0xea, 0xd2, 0x1a, 0x04, 0x16, 0xd6, 0xbe, 0x41, 0xd8, + 0xe1, 0x18, 0xae, 0xc7, 0xed, 0x03, 0xe7, 0xd7, 0x0b, 0x17, 0x0b, 0xf2, 0x1b, + 0xb8, 0x10, 0x19, 0xd8, 0xb0, 0x30, 0xcb, 0xfa, 0xfc, 0xef, 0xbf, 0xfa, 0x39, + 0x30, 0x27, 0x1e, 0x24, 0xd9, 0x2b, 0xf4, 0xfe, 0x07, 0x14, 0x1c, 0x08, 0xec, + 0xd1, 0xdd, 0x0f, 0xd5, 0x10, 0xf2, 0xec, 0x3b, 0xc0, 0x41, 0x0c, 0x3b, 0xd9, + 0x9e, 0xd4, 0x16, 0xe4, 0x0f, 0x25, 0x31, 0x10, 0xe1, 0xcd, 0xe2, 0xf1, 0xdf, + 0xe2, 0x67, 0xe3, 0xbb, 0x31, 0xea, 0x03, 0x0d, 0x1f, 0xd5, 0xbd, 0xea, 0xf3, + 0xca, 0x13, 0x03, 0x07, 0x0d, 0x09, 0x27, 0xd0, 0x7f, 0xf9, 0x5b, 0x33, 0x00, + 0xf3, 0xff, 0xfc, 0xf7, 0xb8, 0x24, 0x0f, 0xe3, 0xde, 0xfb, 0xf0, 0x0e, 0x02, + 0x10, 0xf1, 0xef, 0x18, 0xde, 0xea, 0xff, 0xd1, 0xe7, 0x0b, 0x4c, 0xaf, 0xf6, + 0xe3, 0x11, 0x36, 0x33, 0x42, 0x03, 0xfa, 0xfe, 0x41, 0x0e, 0x4f, 0x29, 0x1f, + 0xfa, 0x15, 0xd6, 0x2b, 0xd0, 0xf8, 0x03, 0xf0, 0xdb, 0xc6, 0xd7, 0xf8, 0x0f, + 0xf5, 0x39, 0xfc, 0x07, 0x0c, 0xec, 0xf4, 0xf0, 0xfc, 0xb3, 0x05, 0xf9, 0xd8, + 0xe1, 0x29, 0xdb, 0x31, 0x03, 0xf0, 0x00, 0x03, 0xdb, 0x22, 0xe0, 0xfe, 0xed, + 0xfc, 0xe6, 0xe9, 0xfc, 0x0c, 0xdf, 0x1a, 0x2d, 0x2f, 0x07, 0xe3, 0xd4, 0x06, + 0x10, 0xfe, 0xee, 0x2a, 0x21, 0xcc, 0xf6, 0xf5, 0xd4, 0xe0, 0xf1, 0x01, 0x02, + 0xf1, 0x25, 0xeb, 0xd3, 0xf6, 0x32, 0xe8, 0xe8, 0xf4, 0x13, 0x1c, 0xa7, 0xf3, + 0x1b, 0x21, 0xfd, 0xe4, 0x09, 0xdd, 0x04, 0xe9, 0x27, 0xf2, 0xed, 0xee, 0xea, + 0xef, 0x11, 0xda, 0xf7, 0xf3, 0x26, 0x81, 0xf2, 0xe2, 0x0d, 0x0c, 0xde, 0x0e, + 0x10, 0x00, 0xd3, 0xf1, 0xe4, 0xe7, 0x0c, 0x23, 0x00, 0xfa, 0x27, 0xff, 0x33, + 0xfa, 0x17, 0x11, 0x12, 0xf7, 0x37, 0x3a, 0xd6, 0xc2, 0x0f, 0xd5, 0x0d, 0x0f, + 0x06, 0x28, 0xd4, 0xfc, 0x2a, 0x64, 0xc5, 0xf8, 0xf1, 0xc8, 0xe5, 0x2f, 0x18, + 0x05, 0x46, 0xbe, 0x12, 0xc1, 0x2a, 0xbc, 0xf8, 0x26, 0x61, 0x2c, 0xeb, 0x0b, + 0xf3, 0x29, 0x38, 0x4f, 0xfd, 0x17, 0xd8, 0xc2, 0x0f, 0xff, 0xfd, 0xe1, 0x03, + 0xed, 0xf1, 0x20, 0xfa, 0xdf, 0xd7, 0xe6, 0xca, 0x13, 0xcf, 0xd4, 0x09, 0x17, + 0xf6, 0xea, 0xe3, 0x02, 0x21, 0x27, 0x08, 0xca, 0xe7, 0xe9, 0x29, 0x13, 0xe6, + 0x47, 0xdf, 0xfe, 0xf9, 0x16, 0x5c, 0xd6, 0x33, 0xce, 0x0e, 0x3d, 0x2e, 0xd4, + 0x01, 0x11, 0xc9, 0xbe, 0xe6, 0xf2, 0xd1, 0xe0, 0xfd, 0x2e, 0xe0, 0xfc, 0x60, + 0x3e, 0x33, 0x02, 0x52, 0x0f, 0x0c, 0xe9, 0x2b, 0x7f, 0x25, 0xff, 0x0d, 0xf0, + 0xf2, 0xc0, 0xf2, 0xdc, 0xd7, 0xf1, 0xf0, 0xf1, 0xc1, 0xd9, 0x0d, 0x38, 0x1e, + 0x16, 0xf0, 0x0c, 0x02, 0x0a, 0x5a, 0xea, 0xab, 0xfb, 0x1e, 0x0f, 0xec, 0xf3, + 0xba, 0x1d, 0xed, 0xf3, 0xe4, 0xf3, 0xf0, 0x1e, 0xcb, 0x38, 0x00, 0xae, 0xf4, + 0x56, 0x56, 0x37, 0x08, 0xab, 0xfe, 0x1d, 0xef, 0x25, 0x06, 0xdc, 0x14, 0xef, + 0x0b, 0xc9, 0xf8, 0xf2, 0x02, 0xef, 0x0a, 0x35, 0x34, 0xe8, 0x93, 0xe8, 0xf7, + 0xf7, 0x69, 0xf7, 0x05, 0x5b, 0x0b, 0x43, 0xf0, 0xe4, 0x7f, 0x16, 0xeb, 0x15, + 0xdf, 0xa5, 0x09, 0x4d, 0x31, 0xea, 0xf1, 0x13, 0xe0, 0xe7, 0x0f, 0xdc, 0x2c, + 0xa2, 0xfc, 0x0a, 0x57, 0x4b, 0x1e, 0x61, 0x25, 0xd2, 0x39, 0x0a, 0x0e, 0xac, + 0xe5, 0x09, 0xfe, 0x76, 0xe4, 0xc8, 0xd8, 0x4d, 0xa7, 0xfb, 0xf6, 0xdc, 0x04, + 0xfa, 0x19, 0x05, 0x94, 0xc8, 0x28, 0x1f, 0xcc, 0xfb, 0xad, 0x0b, 0x22, 0xf5, + 0xdb, 0x26, 0x13, 0x0d, 0x0a, 0xf4, 0x09, 0xe1, 0x0b, 0x17, 0x11, 0x48, 0x1c, + 0xd1, 0xbb, 0xe3, 0xdc, 0x73, 0xe7, 0xe0, 0xed, 0x35, 0xe0, 0x09, 0x14, 0xdb, + 0x0d, 0xfb, 0xb4, 0xea, 0x09, 0xe1, 0xf1, 0x20, 0x00, 0x2d, 0xd5, 0xf9, 0xd8, + 0xe3, 0xf6, 0xc7, 0xa3, 0x40, 0xcc, 0xdf, 0x0c, 0x13, 0x02, 0xcf, 0xe3, 0x27, + 0x19, 0x00, 0x2c, 0xd3, 0x31, 0x15, 0x00, 0xdf, 0xc6, 0x26, 0xde, 0x79, 0xd6, + 0x0e, 0xff, 0x1e, 0xf3, 0xdc, 0x44, 0xf2, 0x13, 0xf2, 0x16, 0xf8, 0x17, 0xb7, + 0xbe, 0xeb, 0xd6, 0x1d, 0xaf, 0xe2, 0xc5, 0xa2, 0x39, 0x24, 0xf3, 0xf2, 0x5b, + 0xe4, 0x00, 0x9c, 0xd5, 0xe9, 0x1d, 0x04, 0xf6, 0x2a, 0x0d, 0x06, 0xf7, 0x33, + 0xdd, 0x1a, 0x16, 0xfa, 0xae, 0xe2, 0xf4, 0x23, 0x7f, 0x0b, 0x40, 0xe7, 0x1d, + 0x0c, 0xee, 0xf7, 0xe5, 0xd3, 0xfc, 0xe0, 0xff, 0xda, 0xd2, 0x07, 0xf9, 0x0b, + 0x0f, 0xde, 0xce, 0x20, 0x0c, 0x0a, 0x3a, 0xfe, 0x0d, 0x2b, 0x62, 0xda, 0x1a, + 0xda, 0x0b, 0x21, 0xff, 0xe8, 0xfe, 0xeb, 0xf4, 0x19, 0x20, 0x2b, 0x0d, 0x0a, + 0x20, 0xca, 0x0f, 0x3b, 0xfc, 0x0d, 0x1b, 0x7f, 0xe6, 0x1c, 0xdd, 0xb4, 0x00, + 0x18, 0x48, 0xe5, 0x0f, 0x1e, 0xfa, 0x1d, 0xec, 0xfa, 0x1a, 0x03, 0xea, 0x10, + 0xe4, 0xdc, 0xd5, 0xe2, 0xec, 0x1f, 0xea, 0xeb, 0xfa, 0xf0, 0xff, 0xe4, 0xc6, + 0x10, 0x21, 0x06, 0xf5, 0x1f, 0xe2, 0x01, 0x23, 0x11, 0x0a, 0x0e, 0xfe, 0xf4, + 0x0a, 0xee, 0xd8, 0xfb, 0x0b, 0x11, 0xf6, 0xfc, 0xe2, 0xd0, 0xb0, 0xcf, 0x1d, + 0xd8, 0xc2, 0x10, 0xdd, 0xb9, 0xca, 0xef, 0x16, 0x08, 0xe3, 0x27, 0xfa, 0x44, + 0x28, 0x00, 0xe8, 0x20, 0x2b, 0x49, 0xed, 0x20, 0xf5, 0xf1, 0xd8, 0x50, 0xdd, + 0xf8, 0x15, 0xed, 0x07, 0x21, 0xdb, 0xfb, 0xf2, 0xff, 0x00, 0xf5, 0xf3, 0xf2, + 0x0f, 0xe4, 0xd8, 0x03, 0xd8, 0x04, 0xe4, 0x05, 0xc9, 0x2d, 0xd7, 0x04, 0x1e, + 0x22, 0xea, 0x13, 0x0f, 0xef, 0xd2, 0xf0, 0xfd, 0xe1, 0xda, 0xd6, 0x06, 0x22, + 0xf6, 0xe9, 0x2d, 0xd8, 0x01, 0xf2, 0x1f, 0x3c, 0xe6, 0xf0, 0xf0, 0x14, 0xce, + 0x0e, 0xe0, 0x14, 0xf0, 0xf3, 0x2c, 0x01, 0xe7, 0x23, 0xd1, 0x22, 0xde, 0x7f, + 0xcb, 0xed, 0xfc, 0x16, 0xda, 0xca, 0x03, 0x00, 0xf1, 0xd9, 0xe0, 0xf7, 0xca, + 0xd8, 0xf6, 0xf9, 0x01, 0x21, 0x1d, 0xae, 0xdd, 0x03, 0xee, 0xfd, 0x03, 0x09, + 0x03, 0x09, 0xd7, 0xe0, 0x27, 0xdf, 0x10, 0x5a, 0x10, 0x26, 0xe1, 0xf7, 0xf6, + 0x2b, 0x0d, 0xfe, 0x20, 0xd1, 0x01, 0x16, 0x2e, 0xc7, 0x0e, 0xfc, 0x10, 0x29, + 0x18, 0xdf, 0xfc, 0x1a, 0xf4, 0xe1, 0xf4, 0xd6, 0x24, 0xc8, 0xcc, 0x16, 0x3a, + 0xec, 0x14, 0x04, 0x55, 0xfe, 0xf1, 0x1a, 0xf9, 0x10, 0xf8, 0x0d, 0x14, 0xf5, + 0x2b, 0x15, 0x04, 0x17, 0xfc, 0x1d, 0xe3, 0xe9, 0xe0, 0xe6, 0xf8, 0xfe, 0xf6, + 0xc0, 0x20, 0x09, 0x21, 0x1e, 0xe2, 0x0d, 0x2a, 0x21, 0x96, 0xcc, 0xfc, 0xb5, + 0xf3, 0x46, 0xc7, 0xee, 0xe0, 0x4a, 0xf9, 0x2e, 0x1f, 0x2b, 0x07, 0x07, 0xb9, + 0xab, 0xe0, 0x08, 0xf7, 0x1b, 0x08, 0x8f, 0x20, 0x2c, 0x1f, 0xb3, 0xf3, 0x18, + 0xde, 0xe5, 0x0b, 0x19, 0xfe, 0xe5, 0xe7, 0x2f, 0xcb, 0xec, 0xac, 0xe1, 0x18, + 0x21, 0xd4, 0x0b, 0xa1, 0xce, 0xcb, 0xfd, 0x14, 0x2e, 0x29, 0x14, 0x4a, 0xd9, + 0x59, 0x22, 0x05, 0x02, 0xd8, 0x19, 0xf0, 0xbf, 0xf6, 0xcd, 0xf0, 0xe1, 0x15, + 0x26, 0xe7, 0xf6, 0xa2, 0x3b, 0xdc, 0x12, 0x58, 0x21, 0xee, 0xf8, 0xe2, 0xe5, + 0x09, 0xf2, 0x1f, 0x0a, 0xda, 0xd6, 0x32, 0xde, 0x28, 0x23, 0xfb, 0xac, 0x6f, + 0x13, 0xe5, 0xe6, 0xf7, 0x38, 0x27, 0xd7, 0x02, 0xdd, 0x17, 0xaf, 0x2f, 0xa8, + 0xfd, 0xed, 0x29, 0xe9, 0x3c, 0x7f, 0xef, 0xfb, 0x8f, 0xda, 0xe5, 0x01, 0xef, + 0xfd, 0x12, 0xed, 0xc4, 0x13, 0xa5, 0x45, 0xbb, 0xf7, 0x0f, 0xb6, 0xfe, 0xdd, + 0x04, 0xd2, 0x03, 0x19, 0x1b, 0xf6, 0x07, 0x2c, 0x14, 0x0a, 0x3b, 0xf3, 0xca, + 0x79, 0x12, 0x18, 0x56, 0xe9, 0x3a, 0xe2, 0x39, 0xed, 0xff, 0x6f, 0x1b, 0x13, + 0x37, 0x3a, 0x13, 0xd6, 0xb0, 0xf9, 0x31, 0x5d, 0xec, 0x21, 0xf8, 0xcf, 0xbe, + 0xf5, 0x31, 0xe9, 0xf6, 0xc0, 0xf0, 0x25, 0xe9, 0x4c, 0xcf, 0x0b, 0xf3, 0x22, + 0x1c, 0x0b, 0x05, 0x7f, 0xf1, 0x0c, 0x23, 0x22, 0x64, 0xf7, 0xc9, 0x16, 0x14, + 0x1c, 0x1b, 0xf6, 0xe2, 0x0a, 0xe2, 0xeb, 0x3f, 0x21, 0x22, 0x04, 0x21, 0xf2, + 0x71, 0x10, 0xf5, 0xef, 0x0b, 0xd8, 0xf0, 0xd5, 0xe4, 0x1f, 0x38, 0x4f, 0x07, + 0x0a, 0x1e, 0x2a, 0x3c, 0xe6, 0x1d, 0xf2, 0x20, 0x17, 0x09, 0xf2, 0x27, 0x07, + 0xe0, 0x1e, 0x8f, 0x3e, 0x1f, 0x22, 0x03, 0x1a, 0x2d, 0xe9, 0xf4, 0xe6, 0xe3, + 0xe6, 0xf3, 0xf9, 0xc3, 0x00, 0xfa, 0x26, 0xd6, 0xff, 0x03, 0x2a, 0xca, 0xd5, + 0x7f, 0xe1, 0x01, 0x1c, 0x10, 0xa3, 0xdf, 0x1e, 0x3f, 0x24, 0xfe, 0x0c, 0x38, + 0x21, 0x71, 0x0b, 0xb0, 0x08, 0xc6, 0xb5, 0xeb, 0x43, 0xc0, 0xe8, 0x1c, 0x15, + 0x0c, 0xda, 0x2d, 0x0a, 0xf3, 0xf3, 0x51, 0xb8, 0xea, 0xf7, 0xf8, 0x3a, 0x6f, + 0xe8, 0x01, 0xdc, 0xf2, 0xea, 0xc3, 0x1c, 0xbc, 0xee, 0xf7, 0xf3, 0x34, 0x4c, + 0x21, 0x3a, 0x01, 0xd3, 0x05, 0xd2, 0xd1, 0xfe, 0xf6, 0xe7, 0x24, 0xd1, 0x07, + 0x44, 0x37, 0xf7, 0x0c, 0xf5, 0xa8, 0x2c, 0x22, 0x19, 0xf4, 0xcc, 0xdb, 0x4b, + 0x02, 0x24, 0xee, 0xa9, 0xbc, 0xad, 0xf4, 0x6e, 0xfe, 0xe8, 0xd7, 0xd3, 0xf3, + 0xc2, 0x30, 0xe3, 0x1c, 0x15, 0xe5, 0x08, 0xdb, 0xf5, 0xd8, 0x4e, 0x0d, 0xe2, + 0xb8, 0x0d, 0xc5, 0xe6, 0x19, 0x08, 0xd0, 0x28, 0x27, 0x34, 0x31, 0xe5, 0x26, + 0xfe, 0x1d, 0x3f, 0xdb, 0xb0, 0x19, 0xe0, 0xfe, 0x22, 0xd7, 0xdf, 0x2b, 0x0a, + 0x07, 0x09, 0x32, 0xe6, 0xe6, 0xee, 0x1d, 0xea, 0xda, 0x4e, 0x7f, 0x59, 0x2a, + 0xd8, 0xee, 0x06, 0x0e, 0xed, 0x1c, 0x30, 0xfe, 0x2c, 0x25, 0xf7, 0xc5, 0xfb, + 0x48, 0xe5, 0xd0, 0xe4, 0xd0, 0xe1, 0x27, 0xfc, 0x12, 0x14, 0xd2, 0x0d, 0xb9, + 0x00, 0xc0, 0xfb, 0x1b, 0xd5, 0x06, 0xfb, 0x16, 0xd3, 0xe4, 0x28, 0x1a, 0x2e, + 0xd4, 0x19, 0x0e, 0xf2, 0x10, 0xe2, 0xfa, 0x08, 0x23, 0xf4, 0xfd, 0x14, 0xd3, + 0xe1, 0xbe, 0x1d, 0x16, 0x39, 0x16, 0x1c, 0x09, 0xfb, 0xe4, 0xe9, 0xe3, 0xf3, + 0x1a, 0x16, 0x05, 0xe6, 0xd8, 0xcb, 0x2e, 0xd2, 0x0c, 0xf7, 0x44, 0xc5, 0xe7, + 0xe7, 0x28, 0xe4, 0x27, 0xe7, 0x23, 0xe5, 0xf9, 0xfe, 0x25, 0x1a, 0x13, 0xc8, + 0xe2, 0x3b, 0xf3, 0x37, 0xe7, 0xf6, 0xdf, 0x4c, 0x26, 0x36, 0xf0, 0x17, 0x25, + 0x27, 0x08, 0x50, 0xfc, 0x02, 0xdc, 0x12, 0x16, 0xf9, 0x24, 0x81, 0x00, 0x26, + 0x14, 0xd1, 0xef, 0x06, 0xe1, 0xeb, 0x09, 0x0a, 0xd5, 0x2b, 0x1e, 0xd5, 0x0c, + 0xdf, 0xfe, 0x0d, 0x0d, 0x30, 0xdc, 0xfd, 0xd8, 0xde, 0x2f, 0x1e, 0x12, 0x22, + 0xee, 0xf2, 0xef, 0x47, 0xd4, 0xd8, 0x35, 0x70, 0xf9, 0x1e, 0x44, 0x10, 0xe8, + 0x42, 0xfc, 0xeb, 0xee, 0xb5, 0x29, 0xf7, 0xfb, 0xe4, 0x28, 0x0b, 0x2e, 0x27, + 0xda, 0x23, 0x29, 0xed, 0x2a, 0x19, 0xd7, 0x37, 0xeb, 0xf9, 0x09, 0xfc, 0x58, + 0xef, 0xd1, 0xfa, 0xe9, 0xe2, 0xf9, 0x01, 0x14, 0xfe, 0x1c, 0x1d, 0x21, 0x35, + 0x28, 0x9d, 0x4b, 0xff, 0x43, 0xfe, 0xe9, 0xdf, 0x2e, 0x29, 0x54, 0x1a, 0xd7, + 0xbe, 0x2f, 0xbb, 0xbb, 0xeb, 0x31, 0x1c, 0x3e, 0xf5, 0xee, 0x16, 0x0e, 0xef, + 0xe1, 0xac, 0xc7, 0x0a, 0xfc, 0x1e, 0x37, 0xf5, 0xca, 0x02, 0x54, 0x2e, 0xed, + 0xd1, 0xfb, 0xcc, 0x4f, 0x0e, 0xee, 0xa3, 0xe8, 0xdf, 0x01, 0x14, 0xf0, 0x00, + 0x2c, 0xfe, 0x0a, 0x8c, 0x38, 0x2a, 0xa7, 0xfc, 0xf3, 0xdc, 0xe4, 0x4e, 0xc7, + 0x31, 0x3a, 0xe4, 0xdd, 0x0c, 0xd4, 0xdd, 0x59, 0xea, 0x06, 0x06, 0x49, 0xe7, + 0x20, 0xf3, 0x15, 0xe1, 0xe9, 0xb6, 0xf8, 0xf1, 0x35, 0xda, 0xea, 0x12, 0x7f, + 0x20, 0xec, 0x91, 0x2c, 0xda, 0xf1, 0xfb, 0x52, 0xf2, 0x16, 0xe4, 0x30, 0x3e, + 0x0f, 0x0b, 0x40, 0xfc, 0x10, 0xf1, 0x13, 0xd1, 0x39, 0xf0, 0x11, 0x22, 0x3a, + 0xf9, 0x3c, 0xd7, 0xd9, 0x24, 0x00, 0x19, 0x0a, 0xdf, 0x3a, 0x0b, 0xb4, 0x2d, + 0x07, 0xbc, 0xe0, 0x12, 0xee, 0xe5, 0x17, 0x32, 0xf6, 0x16, 0x35, 0x23, 0xcf, + 0x6d, 0x1f, 0x0b, 0xd5, 0x00, 0x35, 0x05, 0x38, 0xc7, 0x38, 0x0a, 0x1c, 0x03, + 0x18, 0x11, 0x00, 0xef, 0x36, 0xd6, 0x9b, 0xd5, 0x08, 0x06, 0xf2, 0xdb, 0xf8, + 0xf1, 0x81, 0x56, 0xf0, 0xec, 0xe0, 0xf1, 0xe9, 0xcf, 0xf3, 0x6f, 0xff, 0x0f, + 0x0a, 0x01, 0x4a, 0xe4, 0x22, 0xee, 0xf3, 0xe1, 0x2e, 0x05, 0xeb, 0xd6, 0xf9, + 0xcb, 0xe3, 0x2e, 0xc4, 0xc9, 0xfe, 0x03, 0x13, 0xd7, 0x1d, 0xd4, 0x34, 0x1e, + 0x13, 0xc9, 0xf4, 0x07, 0xd5, 0x56, 0x2f, 0x28, 0x07, 0xf1, 0x16, 0x11, 0xcf, + 0x20, 0xeb, 0x13, 0x27, 0xe7, 0x04, 0xe3, 0xdf, 0x25, 0xf1, 0xf6, 0xd6, 0xd4, + 0xb2, 0x50, 0x11, 0xdb, 0x04, 0xf4, 0x0e, 0x3f, 0x6f, 0x56, 0x03, 0x3e, 0x0c, + 0x11, 0x3f, 0x12, 0x24, 0x39, 0xec, 0x0d, 0x16, 0x0f, 0x4a, 0x34, 0x36, 0xe0, + 0xd5, 0x02, 0xe2, 0x23, 0x47, 0x0a, 0x43, 0x0c, 0xd3, 0x0d, 0xcb, 0x24, 0x1f, + 0xe5, 0xfd, 0x15, 0x2f, 0x02, 0xf7, 0xcc, 0xfc, 0xe1, 0x0e, 0x26, 0x2c, 0xf7, + 0xd4, 0x0b, 0x10, 0x14, 0x36, 0x3b, 0x30, 0x04, 0x4b, 0x2a, 0xe7, 0xc7, 0xda, + 0xd4, 0x38, 0xc8, 0xe2, 0xae, 0xde, 0x0f, 0x53, 0xbb, 0xe3, 0xd7, 0xd7, 0xf1, + 0x15, 0x1f, 0x21, 0x4e, 0xdc, 0x04, 0xe2, 0x81, 0x06, 0x2c, 0xd1, 0xd1, 0x1b, + 0xff, 0x3a, 0xc1, 0xd9, 0x03, 0xbf, 0xfd, 0xdb, 0x4a, 0x10, 0x5d, 0xd4, 0xf5, + 0xf1, 0xbc, 0x13, 0x14, 0x6e, 0xdd, 0x19, 0xc0, 0xf2, 0xde, 0xfd, 0xf3, 0x0c, + 0x20, 0xe1, 0xc5, 0xe4, 0x3a, 0x22, 0x1c, 0x09, 0xd4, 0x0b, 0xdb, 0xcf, 0xd4, + 0xfc, 0xda, 0x19, 0xc4, 0xa7, 0x14, 0xd0, 0xbd, 0xd6, 0xe4, 0x03, 0xd4, 0x19, + 0xf3, 0x21, 0xe1, 0x29, 0xcd, 0xfc, 0xf9, 0xf4, 0xe3, 0xe9, 0x35, 0x03, 0xe1, + 0xb1, 0x1a, 0xf1, 0xf6, 0xe3, 0x13, 0xbc, 0x19, 0xde, 0xe2, 0xfa, 0xa5, 0x0e, + 0xef, 0x2a, 0x1c, 0x18, 0xe4, 0xdf, 0xeb, 0xe8, 0x12, 0x02, 0xea, 0xbf, 0xfb, + 0x32, 0xf4, 0x12, 0x11, 0x2c, 0x17, 0x1c, 0xf0, 0xf5, 0xeb, 0xe1, 0x31, 0x25, + 0xf2, 0x05, 0x12, 0x46, 0xdf, 0xbc, 0x00, 0xf5, 0xee, 0x10, 0xe9, 0x09, 0xf9, + 0x15, 0xeb, 0x00, 0x1a, 0x23, 0x07, 0xef, 0x0b, 0x0b, 0x08, 0xfc, 0xfa, 0xc7, + 0x0f, 0xf7, 0x0b, 0x28, 0x25, 0x15, 0x02, 0x2b, 0xe3, 0xf8, 0x1a, 0x33, 0x1e, + 0x27, 0x26, 0x34, 0xdc, 0x24, 0xe7, 0xc1, 0x37, 0x21, 0xe9, 0x11, 0x18, 0x20, + 0xd6, 0x0e, 0xde, 0xd8, 0x0e, 0xf3, 0xfe, 0x24, 0xd0, 0xf5, 0x4c, 0xcd, 0xd4, + 0xfc, 0x1d, 0x15, 0xee, 0xf5, 0x1e, 0x23, 0xe0, 0x41, 0xb8, 0xd8, 0xd9, 0x1c, + 0x14, 0x01, 0xcc, 0x35, 0xca, 0x18, 0xf1, 0x31, 0xf8, 0xf1, 0x13, 0x04, 0xec, + 0x18, 0x0b, 0x1e, 0x59, 0x01, 0xff, 0xd3, 0xcf, 0x29, 0x41, 0xd7, 0xf2, 0x2b, + 0x3a, 0x0c, 0x18, 0xff, 0x27, 0x53, 0x24, 0x14, 0x24, 0xe5, 0x10, 0x7f, 0x03, + 0x4b, 0x0b, 0xc4, 0x07, 0x4f, 0xe7, 0x29, 0x46, 0x3d, 0x5d, 0x0b, 0x06, 0x0c, + 0xb1, 0xa9, 0x23, 0xf0, 0x1d, 0x85, 0x09, 0x18, 0xcd, 0x1b, 0xc8, 0xc3, 0xc5, + 0x51, 0x30, 0x9c, 0xda, 0x48, 0xed, 0xe3, 0x20, 0x12, 0xfa, 0x0d, 0x15, 0xbc, + 0x02, 0xe0, 0xc7, 0xea, 0x28, 0x2a, 0x7f, 0xab, 0xed, 0xaa, 0x50, 0x52, 0x4e, + 0xa8, 0x3d, 0x3d, 0x03, 0xe5, 0xf0, 0x02, 0x01, 0xd9, 0xa9, 0x42, 0x13, 0xf1, + 0xc8, 0x4e, 0xfd, 0x43, 0x0f, 0x20, 0xa7, 0xa7, 0xbd, 0x3c, 0xd1, 0xe7, 0x1b, + 0xb8, 0x01, 0xda, 0xc8, 0xca, 0xce, 0x5f, 0x4a, 0xf9, 0xdc, 0x16, 0xc7, 0x4e, + 0xda, 0xd8, 0x32, 0xd7, 0xd1, 0xd7, 0x06, 0xb6, 0x04, 0x07, 0xdf, 0xe9, 0x00, + 0x21, 0xae, 0xcd, 0x1f, 0x54, 0x3a, 0xfb, 0xc0, 0x01, 0xd5, 0xc2, 0x06, 0x1a, + 0x0d, 0x67, 0xbc, 0xf6, 0x09, 0x17, 0x34, 0xd1, 0x09, 0xdf, 0x27, 0xb2, 0x87, + 0x29, 0x1c, 0xd3, 0xe1, 0xbc, 0xc4, 0xa5, 0x48, 0x24, 0xf5, 0xfd, 0xd5, 0x56, + 0xfa, 0x03, 0xbf, 0x46, 0x3b, 0x13, 0xc7, 0x0d, 0xbc, 0xfd, 0xdf, 0x00, 0x36, + 0x6e, 0x86, 0x77, 0xe7, 0xf8, 0xb8, 0xbe, 0x00, 0x44, 0x00, 0x15, 0xdb, 0xda, + 0x19, 0xcd, 0x07, 0xae, 0xb3, 0xc6, 0x1a, 0x3a, 0x36, 0x97, 0xcf, 0xde, 0x6c, + 0xd7, 0xc8, 0x20, 0xe3, 0x08, 0xef, 0xd6, 0x1a, 0x25, 0x34, 0xd2, 0x41, 0x29, + 0x23, 0xf1, 0xea, 0xd3, 0xcf, 0xfa, 0x54, 0xd1, 0x26, 0xc6, 0x33, 0x45, 0xdb, + 0x18, 0x38, 0x52, 0x4f, 0xcf, 0xdc, 0xe9, 0xc5, 0x3b, 0x0f, 0x17, 0x0f, 0xe5, + 0xf1, 0x41, 0x43, 0xf3, 0x25, 0x3a, 0xf4, 0x28, 0x1a, 0xfe, 0x12, 0xad, 0x25, + 0x42, 0xe4, 0x2a, 0x22, 0x1c, 0x7f, 0x39, 0x83, 0x11, 0x23, 0x0e, 0xab, 0x08, + 0x16, 0x2a, 0xe5, 0xf4, 0xf3, 0x01, 0xbc, 0x45, 0x50, 0xb0, 0xd7, 0xb3, 0xdb, + 0x12, 0xd6, 0xf6, 0xe3, 0xec, 0xd1, 0x08, 0xdd, 0xce, 0xe8, 0x11, 0x09, 0xe3, + 0x7f, 0xf9, 0x0d, 0xff, 0xc8, 0xc4, 0xf8, 0xf1, 0x08, 0xd9, 0xc8, 0x53, 0x1f, + 0xc2, 0x31, 0x6c, 0x35, 0xf2, 0xe9, 0x08, 0x4a, 0x1d, 0x8f, 0x26, 0x43, 0xc1, + 0xe0, 0x13, 0x36, 0xe5, 0x03, 0x01, 0xe4, 0x0b, 0xc9, 0xfd, 0xe5, 0xf2, 0xd5, + 0xfa, 0x2a, 0x03, 0x29, 0xe1, 0xb9, 0x48, 0xbd, 0xf2, 0xc9, 0x48, 0x0f, 0x30, + 0xf6, 0xef, 0x41, 0xf9, 0xd6, 0xe1, 0xfe, 0x43, 0x06, 0x03, 0xbc, 0x04, 0x1a, + 0x85, 0xe2, 0x2b, 0xbf, 0x9f, 0x1c, 0x24, 0xf8, 0xf8, 0x0f, 0x30, 0x1a, 0xe4, + 0x26, 0xb6, 0xaf, 0x32, 0x16, 0x0d, 0xc6, 0xce, 0xf3, 0x05, 0x59, 0xd6, 0xdd, + 0xc1, 0x08, 0xf3, 0x40, 0x63, 0xd9, 0x2b, 0x2d, 0x15, 0xe2, 0x50, 0xc6, 0xf4, + 0x3c, 0xfa, 0xd8, 0xe6, 0xf8, 0x1a, 0x48, 0x52, 0x02, 0xee, 0x29, 0x20, 0x21, + 0x26, 0xfb, 0xe1, 0xf1, 0x0a, 0x29, 0x14, 0xfa, 0xa0, 0xed, 0x4c, 0xde, 0xe2, + 0xf0, 0x65, 0xeb, 0xc7, 0xca, 0x0d, 0x05, 0xa9, 0x11, 0xf1, 0x02, 0x11, 0xe0, + 0x01, 0x43, 0x16, 0xf4, 0x45, 0x08, 0x69, 0x01, 0xfa, 0xdb, 0x2a, 0xb2, 0x07, + 0x15, 0x42, 0xd2, 0xe9, 0xb5, 0x53, 0x1b, 0xf1, 0xda, 0x18, 0x0d, 0xea, 0xf2, + 0x42, 0xec, 0x0b, 0x5f, 0xf0, 0xce, 0x0d, 0xb4, 0x55, 0x0c, 0xf7, 0xc2, 0x43, + 0xe9, 0x52, 0xb2, 0xdc, 0xe3, 0x04, 0x81, 0xf4, 0x24, 0xe4, 0x11, 0x1a, 0xff, + 0x08, 0xe6, 0x10, 0xf4, 0x75, 0xd0, 0x56, 0x2c, 0xf4, 0xe9, 0xfb, 0xfc, 0x1a, + 0xcc, 0xd7, 0x11, 0x5e, 0x06, 0x13, 0x5c, 0x29, 0x04, 0xea, 0x0e, 0x0a, 0x02, + 0xef, 0x21, 0x02, 0x0c, 0xe4, 0x07, 0x81, 0xd1, 0xe0, 0x1a, 0x44, 0xd3, 0xd6, + 0x24, 0x30, 0xd1, 0xe2, 0xff, 0xa7, 0x30, 0xb7, 0x28, 0xd2, 0x2a, 0xc3, 0x24, + 0x11, 0x03, 0x2f, 0xe9, 0x4b, 0xe5, 0xee, 0x32, 0xb8, 0xb0, 0xe4, 0xa0, 0xfd, + 0x34, 0xaa, 0x3c, 0xd2, 0x32, 0x01, 0x08, 0xd2, 0xd1, 0xf7, 0xd1, 0xed, 0x36, + 0x00, 0x1b, 0xf5, 0xd7, 0xb1, 0x47, 0x1b, 0x0a, 0x0b, 0x39, 0x3c, 0x31, 0x25, + 0x03, 0xe7, 0x0b, 0xec, 0xf3, 0x8b, 0xed, 0xcc, 0x62, 0xcd, 0x05, 0xf9, 0xd7, + 0xa8, 0x17, 0xc1, 0xd8, 0xa4, 0x37, 0x5f, 0x34, 0xe7, 0xc5, 0xed, 0x4d, 0xce, + 0xf8, 0xd6, 0x1a, 0xff, 0xab, 0xd3, 0x0c, 0x3d, 0xda, 0xe6, 0x23, 0xcc, 0x1b, + 0x36, 0xc2, 0xf3, 0xf4, 0xf2, 0x5c, 0x26, 0xeb, 0xc8, 0x28, 0xdf, 0x5b, 0xc7, + 0x59, 0x1c, 0x7f, 0xfd, 0x07, 0x8a, 0x09, 0xd2, 0xf3, 0x2b, 0xe3, 0x47, 0xe2, + 0x61, 0xd5, 0x33, 0x37, 0xd9, 0xf4, 0x5d, 0xda, 0xf7, 0x10, 0xfd, 0xde, 0xef, + 0xb6, 0xcc, 0xfb, 0xec, 0x1a, 0x11, 0xf1, 0xc3, 0xe9, 0xcf, 0xca, 0xc7, 0xee, + 0xf1, 0xd1, 0xf2, 0x0b, 0xca, 0xdc, 0xdb, 0x0a, 0xc7, 0x28, 0xe5, 0x03, 0xfc, + 0x0b, 0x07, 0x74, 0xf1, 0xbe, 0x1a, 0xe5, 0x22, 0xd7, 0xf2, 0x1a, 0x00, 0x12, + 0x16, 0x1b, 0x27, 0xcd, 0xdd, 0xe4, 0xc6, 0x0c, 0x26, 0x2e, 0x02, 0x05, 0x12, + 0x49, 0x04, 0xe6, 0x31, 0x34, 0xce, 0x51, 0xfe, 0xec, 0xfe, 0xda, 0x1f, 0x10, + 0xf6, 0xf6, 0x42, 0x00, 0xe7, 0x10, 0x16, 0x07, 0x7f, 0xb4, 0x05, 0xd1, 0x33, + 0xfc, 0x09, 0xe4, 0x16, 0x1b, 0x0a, 0xbb, 0xa4, 0x3d, 0x36, 0x26, 0xde, 0x29, + 0x09, 0xce, 0xe5, 0xfb, 0xed, 0xfe, 0xe4, 0xbb, 0x0c, 0x15, 0xe4, 0x06, 0x40, + 0xcb, 0xf5, 0x33, 0x10, 0xee, 0x24, 0x1f, 0x62, 0xef, 0xcb, 0x08, 0xfa, 0x1d, + 0xf4, 0x37, 0xc2, 0x4d, 0xe4, 0xea, 0x2a, 0x05, 0xf2, 0x11, 0xda, 0x23, 0x2d, + 0xf8, 0xea, 0x16, 0xf0, 0x2d, 0x99, 0xb7, 0xe7, 0x22, 0x04, 0xb8, 0xe7, 0x46, + 0x29, 0x7f, 0x28, 0x37, 0xff, 0x0b, 0xab, 0xe3, 0xe8, 0xf9, 0x10, 0x20, 0x11, + 0xe2, 0xef, 0x45, 0xf8, 0x5c, 0x08, 0x51, 0x0d, 0xb2, 0xf3, 0x12, 0xd7, 0xfe, + 0xca, 0xe1, 0x1d, 0x04, 0xcc, 0x37, 0x52, 0xe7, 0xe4, 0xa8, 0xaf, 0xdd, 0xd1, + 0xd9, 0x06, 0xff, 0xd2, 0x04, 0x16, 0xe9, 0xac, 0x0f, 0x1c, 0x05, 0xec, 0xef, + 0x45, 0x00, 0xfe, 0xbf, 0x1a, 0xc6, 0xca, 0xc9, 0xe7, 0x10, 0x26, 0x0f, 0x31, + 0xda, 0xe9, 0xdd, 0xf2, 0x2f, 0x09, 0xe7, 0xf7, 0x1d, 0xd0, 0xcb, 0xc8, 0xd9, + 0xd6, 0xb7, 0xef, 0xcc, 0x1d, 0x86, 0xb0, 0xa8, 0x1f, 0xcc, 0xc6, 0xdf, 0xf4, + 0x1f, 0xd2, 0xfc, 0xfc, 0x0f, 0xe1, 0x29, 0xf9, 0xa8, 0x14, 0x0b, 0x28, 0x49, + 0x08, 0xfa, 0xef, 0x19, 0xe8, 0xe8, 0x37, 0xc2, 0x09, 0xed, 0xe2, 0x0b, 0x0f, + 0x18, 0x40, 0xff, 0xd2, 0x6c, 0x3a, 0xd8, 0x8a, 0x5d, 0xf5, 0x5f, 0xc4, 0xb7, + 0xf4, 0x1c, 0xf5, 0xde, 0x23, 0x21, 0x0c, 0xb7, 0x27, 0xcc, 0x81, 0xe1, 0xd0, + 0x19, 0x6b, 0xc8, 0x47, 0xa8, 0xea, 0xea, 0xdb, 0xc5, 0xb0, 0xf3, 0x4e, 0xe8, + 0x27, 0x3b, 0x3b, 0x3a, 0xe7, 0x98, 0x09, 0x31, 0x14, 0x36, 0x1c, 0x35, 0x2f, + 0xfe, 0x1f, 0xf1, 0xf1, 0x4f, 0xa6, 0x25, 0x29, 0x34, 0xfa, 0xb3, 0x0d, 0x26, + 0x41, 0xf4, 0xd2, 0xe3, 0xc1, 0xd8, 0x3f, 0xdc, 0x12, 0x13, 0xbb, 0x98, 0x55, + 0x41, 0x64, 0xe0, 0xc2, 0xfe, 0x03, 0xf2, 0x5a, 0x27, 0x3b, 0x3d, 0x11, 0xfd, + 0x34, 0x40, 0x1b, 0x13, 0xe1, 0x23, 0xc5, 0x2e, 0x02, 0xe0, 0x16, 0x21, 0x27, + 0x65, 0x0a, 0x11, 0xb7, 0x26, 0x18, 0xf3, 0x45, 0xb6, 0x07, 0xed, 0x19, 0xc8, + 0xe6, 0x1d, 0xc1, 0xfd, 0x35, 0x24, 0xfd, 0xb6, 0x73, 0x08, 0xfb, 0x15, 0x1a, + 0xec, 0xf3, 0x1c, 0x00, 0xef, 0xf9, 0x0c, 0x0c, 0xd6, 0xf4, 0xc9, 0x24, 0xeb, + 0xf3, 0xea, 0x0e, 0xeb, 0xdd, 0x14, 0x03, 0x08, 0xe5, 0x10, 0x00, 0xca, 0xf3, + 0xcb, 0xfc, 0xeb, 0x13, 0xf1, 0xf5, 0x02, 0x3b, 0xec, 0xf2, 0x28, 0xb2, 0x0d, + 0xf6, 0x38, 0x39, 0x2f, 0xef, 0xd6, 0xf1, 0xda, 0x12, 0x1b, 0x1b, 0xe6, 0x16, + 0xcd, 0x14, 0x21, 0x26, 0xf0, 0x2b, 0xec, 0xe1, 0xdf, 0xef, 0xc7, 0x23, 0x22, + 0xd1, 0xaa, 0x1c, 0xfd, 0xeb, 0xff, 0x22, 0xf4, 0x21, 0xf4, 0x11, 0xea, 0x1c, + 0x41, 0x0a, 0x0e, 0xc7, 0x05, 0xcb, 0xe2, 0x09, 0xb3, 0xe3, 0xff, 0x01, 0x32, + 0x10, 0xfc, 0xde, 0x1d, 0xda, 0x1d, 0x00, 0x08, 0x1d, 0xd9, 0xeb, 0x19, 0x09, + 0x0d, 0x81, 0xf8, 0x07, 0xd8, 0xfc, 0xcf, 0x12, 0xc6, 0x34, 0x1e, 0xeb, 0x0b, + 0xfe, 0x02, 0xfb, 0xfb, 0xeb, 0xe7, 0x23, 0xcf, 0x08, 0x25, 0xe3, 0x2e, 0xd4, + 0xbd, 0x06, 0xe0, 0xb7, 0x1c, 0xf7, 0xcb, 0xe7, 0xde, 0xf3, 0xf1, 0xfb, 0xf2, + 0x32, 0xe9, 0x00, 0xf4, 0xd8, 0x20, 0xe2, 0x2f, 0x35, 0xe1, 0x1d, 0xd2, 0x06, + 0xdc, 0xf4, 0x11, 0x35, 0x04, 0xe0, 0xf6, 0x07, 0x14, 0xcc, 0xf7, 0xdc, 0x08, + 0x1c, 0xc1, 0xf8, 0x0c, 0x1f, 0x9a, 0x07, 0x1d, 0xf1, 0xb5, 0xc9, 0x04, 0x2f, + 0x24, 0xdc, 0xe8, 0x0c, 0x2c, 0x11, 0x01, 0x19, 0xf7, 0xcf, 0xe5, 0xeb, 0x09, + 0x72, 0x23, 0x9f, 0x28, 0xf4, 0xf8, 0x08, 0xf2, 0xeb, 0xfb, 0x09, 0x3b, 0x1e, + 0x3f, 0xc6, 0xdc, 0x21, 0x81, 0x24, 0xec, 0xe6, 0x0b, 0xea, 0x01, 0xfb, 0xd0, + 0xca, 0x06, 0x12, 0x37, 0xed, 0x52, 0x18, 0xff, 0xf7, 0xf4, 0x1e, 0x03, 0x14, + 0x16, 0x43, 0xf9, 0x3d, 0xe6, 0xe9, 0x1e, 0xe9, 0xec, 0xfe, 0xfa, 0x21, 0x64, + 0xf0, 0x0f, 0x01, 0x0c, 0x0d, 0x38, 0x15, 0x23, 0x3e, 0xf3, 0x0e, 0xdc, 0xf5, + 0xe9, 0xe7, 0x47, 0x00, 0xe3, 0xdd, 0xd6, 0xce, 0x15, 0xf2, 0x6f, 0x41, 0xeb, + 0x15, 0xe6, 0x0f, 0x3c, 0xf1, 0x47, 0x2f, 0x00, 0x0d, 0xe3, 0xb2, 0xb0, 0xd9, + 0x13, 0xc1, 0xc9, 0xe5, 0x08, 0x16, 0xd4, 0x0c, 0xd7, 0x65, 0x0e, 0x42, 0xbc, + 0xf1, 0xfb, 0x43, 0xf4, 0x26, 0xfd, 0xfb, 0x2b, 0xf6, 0xf7, 0x25, 0x81, 0x02, + 0x03, 0x52, 0x29, 0x0d, 0xea, 0xf4, 0xbd, 0x0d, 0x3d, 0x1e, 0x0e, 0x66, 0xd5, + 0xd1, 0xda, 0xc9, 0xf1, 0xfb, 0xce, 0x1e, 0xee, 0xd1, 0xe2, 0x1d, 0xf9, 0x23, + 0xec, 0x38, 0xf4, 0x7b, 0x45, 0x16, 0x4f, 0x56, 0x06, 0x16, 0x42, 0xeb, 0x24, + 0x04, 0xed, 0x10, 0xc8, 0x5a, 0x03, 0x07, 0x19, 0xbb, 0xe6, 0xf1, 0xd2, 0xcd, + 0x1b, 0x45, 0xd2, 0x0b, 0xcf, 0xf4, 0x0b, 0x05, 0xe2, 0x0f, 0x07, 0xfb, 0xb8, + 0xfe, 0x3c, 0xc0, 0xf0, 0xf2, 0xf7, 0xb5, 0xfb, 0xd4, 0xe7, 0x3a, 0xe4, 0xf6, + 0x03, 0x09, 0xc8, 0x22, 0xc6, 0xdb, 0xc8, 0x33, 0xf3, 0xf9, 0xf5, 0x0f, 0xc5, + 0x48, 0x25, 0x23, 0x27, 0x0b, 0x0a, 0x0e, 0x50, 0xee, 0x92, 0xf8, 0x08, 0xef, + 0x11, 0xd8, 0x00, 0xf4, 0x01, 0x08, 0x05, 0x3c, 0x16, 0x37, 0xf5, 0xcd, 0x28, + 0xb9, 0x01, 0xdc, 0xf9, 0x32, 0x00, 0x11, 0x03, 0x2e, 0xc9, 0xf9, 0xb8, 0x2a, + 0x23, 0xc9, 0x07, 0x24, 0xd0, 0x1a, 0xed, 0xf7, 0x0b, 0x6e, 0xe2, 0x1d, 0xca, + 0xf2, 0xb9, 0x16, 0xb6, 0xf2, 0x20, 0xda, 0x1a, 0xd9, 0xd4, 0xf6, 0x20, 0xcc, + 0xf0, 0x7e, 0x1c, 0xe7, 0xe0, 0x6c, 0xfe, 0xfd, 0xe5, 0xfc, 0xd1, 0x44, 0xed, + 0x0f, 0xf8, 0x30, 0x0c, 0x37, 0x05, 0x9d, 0x11, 0xf0, 0xee, 0xb8, 0xe7, 0x4d, + 0xea, 0x33, 0x81, 0xb4, 0x44, 0x1b, 0xfc, 0xdc, 0xe9, 0x31, 0x01, 0xd7, 0xdd, + 0xfa, 0x10, 0xdf, 0x08, 0x7f, 0xfd, 0x14, 0x1f, 0xeb, 0xf1, 0x1d, 0x00, 0x16, + 0xe7, 0xf8, 0xff, 0x03, 0x20, 0xd1, 0x1e, 0x0c, 0x0c, 0x02, 0xe2, 0x00, 0xc5, + 0x18, 0xb0, 0xf9, 0xda, 0x03, 0xd7, 0x2c, 0xea, 0xe2, 0xd7, 0x0d, 0xfd, 0xdd, + 0xe7, 0x16, 0xfb, 0xee, 0x09, 0xfa, 0xff, 0x0e, 0x0d, 0x02, 0xe2, 0xf8, 0x0a, + 0xea, 0x08, 0x04, 0xee, 0x06, 0xcb, 0xfc, 0x0e, 0xf1, 0xeb, 0x12, 0x1d, 0xf4, + 0x0c, 0x05, 0xd8, 0xc6, 0xea, 0x12, 0x2d, 0x00, 0x19, 0x21, 0xef, 0xfb, 0x31, + 0xf1, 0xc2, 0x2a, 0x06, 0x12, 0x29, 0x0a, 0xf1, 0xf7, 0xf5, 0x0f, 0x05, 0x45, + 0x32, 0x31, 0x1f, 0x06, 0x07, 0xff, 0x1c, 0x06, 0xef, 0x06, 0xe3, 0xd7, 0xf3, + 0xd0, 0x29, 0xdf, 0x14, 0xef, 0xf2, 0xde, 0x0e, 0xf9, 0xdb, 0xe4, 0xfe, 0xfa, + 0x05, 0x25, 0xfe, 0xf3, 0x13, 0xc0, 0x0a, 0xf0, 0x00, 0x1e, 0xe2, 0x0c, 0xc8, + 0x6a, 0xeb, 0x0d, 0x49, 0x1d, 0x49, 0x32, 0x20, 0x01, 0xd8, 0x0e, 0xfc, 0x64, + 0xdd, 0xd8, 0x21, 0x08, 0xf3, 0xfd, 0xfa, 0x9c, 0xaf, 0x09, 0xd6, 0x0e, 0xb8, + 0xeb, 0xd1, 0x31, 0xc8, 0x3e, 0x04, 0xed, 0xea, 0x38, 0x16, 0xd1, 0x3c, 0x42, + 0x08, 0xed, 0xe5, 0xe0, 0xea, 0x05, 0x59, 0x16, 0x03, 0xf5, 0xab, 0xd9, 0x19, + 0x49, 0x3b, 0x32, 0xcb, 0xfa, 0x44, 0xdb, 0xf1, 0x10, 0xf4, 0xee, 0x10, 0x1a, + 0xe5, 0xf0, 0xef, 0xc6, 0xee, 0x24, 0xe7, 0x1a, 0x1b, 0xf8, 0xf3, 0x17, 0xaa, + 0xd9, 0x0f, 0x0f, 0x54, 0xef, 0xd0, 0x0c, 0x7d, 0xeb, 0xba, 0xbc, 0x09, 0x03, + 0x0e, 0x81, 0xd8, 0x42, 0xc5, 0xf5, 0x85, 0xe7, 0x03, 0x2b, 0xe9, 0x34, 0xd6, + 0x32, 0x0f, 0x2c, 0xe8, 0xf9, 0xe5, 0x0a, 0xc1, 0xde, 0x0b, 0xfe, 0x22, 0xe1, + 0xbe, 0xe4, 0x15, 0x2b, 0x28, 0x00, 0x22, 0x1c, 0xe0, 0x1b, 0x09, 0x05, 0xb6, + 0x36, 0x00, 0x0a, 0x05, 0xfa, 0xb5, 0x21, 0x29, 0x1e, 0xba, 0xd2, 0x10, 0xf6, + 0xad, 0x08, 0x41, 0x17, 0x0b, 0xfd, 0x07, 0x02, 0x10, 0x88, 0x3c, 0xee, 0x8a, + 0x29, 0x2b, 0xf1, 0xe2, 0xf5, 0x04, 0xea, 0x29, 0xfa, 0xe2, 0xec, 0x00, 0x1d, + 0x11, 0xe9, 0x25, 0x19, 0x1c, 0xe1, 0xf5, 0x07, 0xef, 0x25, 0xae, 0xbc, 0xe2, + 0x50, 0xca, 0x05, 0xf4, 0xf8, 0x01, 0x43, 0x0b, 0xe9, 0xdd, 0xe2, 0x04, 0x83, + 0xfb, 0xfa, 0x17, 0xfc, 0xe0, 0xf0, 0x05, 0xeb, 0xd7, 0xe9, 0x17, 0x05, 0x17, + 0x10, 0x1e, 0xdd, 0x44, 0xee, 0xcf, 0x00, 0xcf, 0xe6, 0xe9, 0x02, 0xeb, 0x38, + 0xf4, 0xc4, 0x0e, 0x10, 0x0b, 0x04, 0x21, 0x81, 0xda, 0xbc, 0x40, 0x03, 0xc5, + 0x27, 0x0a, 0xab, 0xd8, 0x01, 0xc7, 0xeb, 0xdc, 0x1a, 0xe6, 0x22, 0xd6, 0x3c, + 0xfa, 0x0d, 0xde, 0xfb, 0xc4, 0xe6, 0x12, 0x26, 0xc3, 0x40, 0xb1, 0x59, 0x05, + 0x0f, 0x1e, 0x00, 0xcc, 0x9d, 0x20, 0x46, 0xe7, 0x38, 0xfb, 0x1e, 0x11, 0x1a, + 0x18, 0x71, 0xff, 0x33, 0x1a, 0x27, 0xe6, 0x17, 0x19, 0xec, 0xd9, 0xd2, 0xf5, + 0x16, 0xf5, 0xd0, 0x00, 0x1a, 0x35, 0xce, 0xdb, 0xad, 0xf3, 0xbb, 0x24, 0xf3, + 0x31, 0x3b, 0xf7, 0x21, 0xf9, 0xd0, 0x0b, 0xe2, 0xcd, 0x93, 0x09, 0x67, 0x56, + 0xd9, 0xdf, 0xf7, 0xee, 0xf2, 0xce, 0xe9, 0xea, 0x5c, 0x32, 0xe8, 0x54, 0xc2, + 0xce, 0x01, 0xe9, 0x67, 0x0d, 0x14, 0xc9, 0x13, 0x1d, 0xd2, 0xd8, 0xe9, 0xce, + 0x9c, 0x08, 0x00, 0xdd, 0xc6, 0xb5, 0x13, 0x42, 0xd5, 0x06, 0xaf, 0x55, 0xc6, + 0xdd, 0xf1, 0xc6, 0xd0, 0x2e, 0x45, 0xfe, 0x21, 0x55, 0xc6, 0xf9, 0xef, 0x06, + 0x05, 0xbd, 0xdc, 0x81, 0x01, 0x19, 0x2d, 0xfb, 0x23, 0xed, 0x37, 0xd6, 0xe4, + 0xfa, 0xec, 0x19, 0xcf, 0x09, 0x13, 0xe4, 0x02, 0xe8, 0xd8, 0xde, 0x0d, 0xe5, + 0xf2, 0x05, 0xf7, 0xe3, 0x44, 0xd1, 0xfd, 0x38, 0x0f, 0x36, 0x6b, 0xeb, 0x28, + 0x0d, 0x14, 0xbe, 0xf0, 0xf2, 0xf8, 0x0d, 0xff, 0xc3, 0xf8, 0xe9, 0xf8, 0x39, + 0xc7, 0x04, 0x0b, 0x09, 0x38, 0x06, 0x4a, 0xdb, 0xa0, 0x13, 0xee, 0x1d, 0xf6, + 0x32, 0xeb, 0x1e, 0xfb, 0xc8, 0xde, 0x1d, 0x2a, 0xf0, 0x05, 0xf7, 0x20, 0x08, + 0xb3, 0xfd, 0xf7, 0xfb, 0xc7, 0xac, 0x81, 0x26, 0xee, 0x45, 0xfb, 0xe0, 0xe2, + 0x4f, 0x22, 0xaf, 0x3b, 0xe5, 0x1b, 0xec, 0x31, 0x04, 0xe7, 0x06, 0xf5, 0x18, + 0xf7, 0x34, 0xf5, 0x4b, 0x14, 0xc1, 0xda, 0x0e, 0xe4, 0x23, 0xf7, 0x12, 0xf9, + 0x1c, 0x0d, 0x10, 0xd6, 0xf5, 0xdc, 0xff, 0x26, 0xe4, 0x02, 0x10, 0x36, 0x0f, + 0x12, 0x03, 0xfd, 0xbb, 0x03, 0x02, 0x0b, 0x19, 0x28, 0x04, 0xee, 0xf6, 0xaf, + 0xdf, 0x51, 0xb3, 0xc9, 0xfb, 0xdc, 0x10, 0xe5, 0xe0, 0x0a, 0x07, 0xf0, 0xe9, + 0xdc, 0x08, 0xf2, 0xce, 0xb8, 0xdd, 0xad, 0x06, 0xed, 0x07, 0xe5, 0x37, 0xfb, + 0xf3, 0xec, 0x4b, 0xdd, 0xf7, 0x39, 0xe9, 0x62, 0xf9, 0x17, 0x20, 0x1f, 0xfb, + 0xf1, 0x0a, 0x39, 0x0d, 0x16, 0xe7, 0x16, 0x09, 0xff, 0xfd, 0x39, 0xfd, 0xc8, + 0xf4, 0x1d, 0xe4, 0xd0, 0x20, 0xa4, 0xd5, 0x41, 0xdb, 0x06, 0xf7, 0xf8, 0x81, + 0x25, 0x18, 0x1a, 0x19, 0x08, 0x20, 0xff, 0x00, 0xad, 0xd5, 0x55, 0xff, 0xe1, + 0xd8, 0xe7, 0xef, 0x39, 0xf0, 0x01, 0xe4, 0xf1, 0xf7, 0xf6, 0xda, 0x09, 0x01, + 0x06, 0xff, 0x36, 0xed, 0xdf, 0xe0, 0xf1, 0xd2, 0xdc, 0x32, 0xcb, 0xff, 0x25, + 0xe3, 0xe8, 0xe6, 0x03, 0x16, 0x2d, 0xb4, 0xf0, 0x01, 0x5f, 0xd6, 0xde, 0x26, + 0xdb, 0xdf, 0x1f, 0xfd, 0xe3, 0x12, 0xca, 0xf6, 0x1b, 0x03, 0x11, 0xf5, 0xb4, + 0x13, 0x01, 0xd0, 0x07, 0xf4, 0x0a, 0xcf, 0x31, 0x46, 0x04, 0x68, 0xce, 0xf7, + 0x13, 0xe4, 0x09, 0xf1, 0x51, 0xd7, 0xce, 0x13, 0xbf, 0x51, 0xe5, 0x1c, 0xeb, + 0xfa, 0x14, 0x2f, 0xc6, 0xe3, 0x03, 0xe8, 0x1b, 0x3b, 0x4f, 0x3d, 0xe3, 0xfa, + 0x0f, 0xf0, 0x09, 0x7f, 0x46, 0x3c, 0x21, 0xdb, 0x08, 0x45, 0x73, 0x2c, 0x8e, + 0x3a, 0x29, 0x09, 0xec, 0xe1, 0xea, 0xf9, 0xd1, 0x49, 0xed, 0x2c, 0x1d, 0x25, + 0x40, 0x55, 0xf1, 0xea, 0x13, 0xe5, 0xe7, 0xfe, 0x4a, 0x46, 0x17, 0xc7, 0xf3, + 0xbc, 0x00, 0xe5, 0x4c, 0xe0, 0xff, 0x20, 0xd7, 0x18, 0x21, 0x3a, 0x1f, 0xa8, + 0x4f, 0xd9, 0x43, 0x44, 0x39, 0x08, 0x30, 0x59, 0x33, 0x15, 0xbe, 0xf1, 0x0d, + 0x11, 0xf8, 0x0b, 0xdb, 0xd5, 0xb1, 0x36, 0xe3, 0x0b, 0x2e, 0x22, 0x30, 0xe6, + 0x00, 0x3c, 0xcc, 0x04, 0xce, 0x3c, 0x10, 0x27, 0xf8, 0xff, 0x29, 0x44, 0x02, + 0xa8, 0x21, 0x23, 0x05, 0x29, 0xd1, 0xf5, 0x02, 0xe4, 0x78, 0xd4, 0xda, 0xea, + 0x12, 0x27, 0xe4, 0xf4, 0xfa, 0x21, 0xf2, 0x0e, 0x06, 0xee, 0xde, 0x05, 0xe4, + 0xfb, 0x45, 0xc2, 0xb0, 0xaa, 0x29, 0xd5, 0x07, 0x52, 0xe3, 0x25, 0xe5, 0x04, + 0x21, 0x0d, 0x91, 0xdf, 0xfc, 0xe2, 0x04, 0x36, 0x58, 0x20, 0xf7, 0x16, 0xf6, + 0x2d, 0xbd, 0x06, 0x0f, 0x16, 0xda, 0x1f, 0x01, 0xf3, 0xf9, 0x14, 0x04, 0x5f, + 0x49, 0x20, 0x15, 0xbf, 0x04, 0xf8, 0xb8, 0x1e, 0x29, 0x0b, 0x1d, 0xfb, 0xb9, + 0xd9, 0xb8, 0xfe, 0x20, 0xf4, 0xfe, 0xdc, 0x06, 0xe2, 0x35, 0x25, 0xd5, 0x81, + 0x19, 0xf3, 0xb5, 0xe0, 0x01, 0xfa, 0xe8, 0x45, 0xf7, 0xe6, 0x19, 0xef, 0x2c, + 0x45, 0xe7, 0xf6, 0x01, 0x12, 0x15, 0x09, 0xf7, 0xfa, 0xef, 0x63, 0x06, 0x22, + 0x01, 0x0f, 0xdb, 0xd4, 0xee, 0xe7, 0x10, 0xd9, 0x05, 0x28, 0xe7, 0xc4, 0xdc, + 0xd5, 0xf4, 0xe7, 0xba, 0x03, 0xf0, 0xeb, 0xc7, 0xf8, 0x24, 0xac, 0x03, 0x56, + 0x13, 0xfc, 0xff, 0xe9, 0x2c, 0x13, 0xaf, 0x13, 0x05, 0xe6, 0x19, 0x26, 0xef, + 0x13, 0x17, 0xf6, 0x21, 0xb9, 0x0e, 0x29, 0xe6, 0xcf, 0x2e, 0xea, 0x1e, 0x2c, + 0x1a, 0x1e, 0xef, 0x0c, 0xb7, 0x19, 0xe9, 0x1f, 0x2a, 0xea, 0x2c, 0x00, 0xc5, + 0x17, 0x24, 0x05, 0xe3, 0x14, 0x2b, 0x15, 0x11, 0xf2, 0x05, 0xf3, 0xd1, 0x36, + 0xcf, 0x16, 0x02, 0xf6, 0xf2, 0x1c, 0x3b, 0xb8, 0x02, 0xe3, 0xcc, 0xe1, 0x42, + 0x41, 0xf9, 0xfa, 0xfe, 0xe5, 0x0e, 0x38, 0x47, 0xfa, 0x12, 0xc1, 0x0d, 0x0e, + 0x60, 0x13, 0xf4, 0x7f, 0x15, 0x1c, 0x25, 0x09, 0x0c, 0xd1, 0x07, 0x26, 0x28, + 0xd5, 0x1d, 0x23, 0xd7, 0x28, 0xcb, 0x52, 0x10, 0x00, 0x21, 0x1a, 0xdd, 0xda, + 0x1a, 0xfd, 0xc9, 0xf2, 0xc1, 0xf7, 0x1c, 0x3c, 0xeb, 0xad, 0x28, 0xe1, 0xcd, + 0xe0, 0x31, 0x0b, 0x13, 0x16, 0xb2, 0xfa, 0xf5, 0xfd, 0xf8, 0x23, 0x1f, 0xfb, + 0x00, 0x1a, 0xae, 0xd2, 0xba, 0x1e, 0x1e, 0xc4, 0xca, 0x42, 0xf9, 0xdf, 0xd7, + 0xd5, 0xef, 0x45, 0x1c, 0x29, 0xf5, 0x00, 0xda, 0x16, 0x36, 0xf8, 0xf2, 0x11, + 0x7f, 0xdd, 0x3a, 0xf3, 0x2f, 0x1f, 0xe1, 0x5c, 0xf7, 0xd7, 0xea, 0x00, 0x1e, + 0xf0, 0x05, 0x11, 0xe5, 0xee, 0xf7, 0x0f, 0x6c, 0x0c, 0xcc, 0xcb, 0x23, 0xdc, + 0x05, 0x40, 0x1d, 0x03, 0x0a, 0x05, 0xfc, 0xd5, 0xb4, 0xc3, 0x0e, 0xe9, 0x37, + 0x2e, 0xe4, 0x26, 0x4f, 0xe6, 0x32, 0xb0, 0xf8, 0xda, 0x15, 0x61, 0xfa, 0xf4, + 0xe1, 0x59, 0xf1, 0x0d, 0xfe, 0x0e, 0xc9, 0x6f, 0x0f, 0x14, 0xe2, 0x0a, 0x0a, + 0xdb, 0x0a, 0xff, 0x5e, 0x97, 0x2e, 0x1e, 0x14, 0x1a, 0xe5, 0x3f, 0x0b, 0xee, + 0x0a, 0xfd, 0xe7, 0xdc, 0x15, 0x0a, 0x40, 0xcd, 0x1c, 0xcf, 0x0b, 0x25, 0xf9, + 0xdb, 0x03, 0xf7, 0xea, 0x1b, 0x0e, 0x99, 0x62, 0xe3, 0x41, 0xf3, 0xd1, 0x4f, + 0x0a, 0x05, 0x2b, 0x13, 0xc1, 0x9f, 0xc3, 0xb8, 0x2a, 0x38, 0x01, 0x11, 0xf5, + 0x1f, 0x06, 0x17, 0x32, 0xd5, 0xce, 0xba, 0x1f, 0x1b, 0x13, 0x0b, 0xfb, 0xab, + 0xcf, 0x5c, 0x26, 0xf6, 0x22, 0xd8, 0x31, 0x2b, 0x2b, 0x82, 0x2c, 0xf9, 0x2b, + 0x61, 0xff, 0x0b, 0xe9, 0xf3, 0x1c, 0xdb, 0x3e, 0xf6, 0xec, 0xe4, 0x53, 0x14, + 0x31, 0xb3, 0xf4, 0xe3, 0x00, 0xb8, 0xed, 0x98, 0xe8, 0x04, 0xd6, 0xe2, 0xcb, + 0xd7, 0x0c, 0x12, 0xf3, 0x28, 0x23, 0xc4, 0x13, 0xdf, 0xed, 0x54, 0x9a, 0xf9, + 0x0f, 0xb7, 0xc7, 0x4a, 0x3c, 0xfc, 0xaf, 0xf4, 0x0c, 0x28, 0x1e, 0xe6, 0x12, + 0x2c, 0x35, 0xa1, 0x39, 0xe0, 0x55, 0x3a, 0xf5, 0x81, 0xc8, 0x2e, 0xe7, 0x18, + 0xae, 0x1a, 0xf0, 0x45, 0xd9, 0xf2, 0x15, 0xf5, 0x0f, 0x3c, 0x07, 0xb1, 0x3f, + 0xd4, 0x97, 0x45, 0xa6, 0x19, 0x0f, 0xde, 0xca, 0xdd, 0xef, 0xda, 0xfb, 0xd5, + 0xfc, 0x39, 0xf2, 0x7f, 0xeb, 0x0a, 0x3d, 0x46, 0x41, 0xdd, 0x98, 0x0f, 0xe9, + 0xf0, 0xb6, 0xef, 0x06, 0xf1, 0x54, 0xe9, 0x1d, 0x2a, 0x48, 0xee, 0x28, 0x18, + 0x2b, 0x09, 0x2f, 0xfe, 0x69, 0x3e, 0xe8, 0xf3, 0x3d, 0xe7, 0x31, 0xdc, 0xe1, + 0x04, 0xfa, 0x28, 0x08, 0x36, 0xbf, 0x34, 0xe3, 0x2a, 0x30, 0xd1, 0x43, 0xaa, + 0x63, 0x2f, 0x1d, 0xdb, 0x35, 0xf6, 0x13, 0xfe, 0xcd, 0xbd, 0x0e, 0xe1, 0xe6, + 0xec, 0x7e, 0x33, 0x4e, 0xcc, 0x2e, 0xfa, 0xe3, 0xc1, 0x18, 0x10, 0xe1, 0xc2, + 0x4e, 0xd8, 0x01, 0x00, 0x27, 0x03, 0x26, 0xcc, 0xff, 0xee, 0xe5, 0xf5, 0x2f, + 0x2e, 0xda, 0xcf, 0x1d, 0xdd, 0xff, 0x36, 0x11, 0x2a, 0x28, 0x1d, 0x14, 0xd1, + 0x0a, 0x3e, 0xf6, 0xb0, 0x05, 0x35, 0x4d, 0xf9, 0x37, 0x5e, 0x31, 0x14, 0x5c, + 0xdb, 0xf5, 0x05, 0x9b, 0xd9, 0xf5, 0x0f, 0x11, 0xc5, 0xb7, 0xa4, 0xf0, 0xe6, + 0x1a, 0xe4, 0xde, 0x05, 0x19, 0xe6, 0xcb, 0xe7, 0x1f, 0x37, 0xfc, 0xe9, 0xdd, + 0x1c, 0xb1, 0xf0, 0x20, 0x12, 0xdd, 0x1f, 0xe4, 0x06, 0x25, 0xa7, 0x3a, 0x43, + 0x20, 0x34, 0x14, 0xe6, 0xd6, 0x25, 0x70, 0x29, 0xc9, 0x18, 0xc1, 0x2d, 0xf2, + 0xe0, 0x06, 0x56, 0x0f, 0x0e, 0x00, 0xd4, 0x85, 0xdd, 0x01, 0x16, 0x43, 0x17, + 0xe3, 0x22, 0x18, 0x19, 0xb9, 0xef, 0xe5, 0x35, 0xb9, 0x37, 0x0a, 0xdd, 0x19, + 0xd4, 0xe1, 0x0e, 0x05, 0xbb, 0x13, 0xfc, 0xff, 0x20, 0xf9, 0xb2, 0xa2, 0xf8, + 0xe1, 0xc5, 0x43, 0x2f, 0x14, 0x09, 0xbb, 0xf1, 0x1a, 0xe8, 0xa2, 0xf1, 0xf3, + 0x09, 0x02, 0x22, 0x24, 0x25, 0xf4, 0xf8, 0x35, 0xf5, 0x13, 0x1f, 0x81, 0xd3, + 0x1a, 0xfa, 0xcc, 0x24, 0xf2, 0xf5, 0xdc, 0xf5, 0x0d, 0xf7, 0x2f, 0x01, 0x12, + 0xe9, 0xde, 0xe0, 0xe2, 0xe1, 0x16, 0xca, 0x29, 0xfb, 0xe4, 0xde, 0xf8, 0x2f, + 0x22, 0x38, 0xdb, 0xed, 0xbe, 0x15, 0xd3, 0x12, 0x1d, 0x3a, 0x04, 0x1b, 0xe8, + 0xc4, 0x00, 0x13, 0xdc, 0xd9, 0xfd, 0x13, 0x0b, 0xbd, 0xe9, 0x17, 0xad, 0x2f, + 0x12, 0x09, 0xd8, 0xf3, 0xe8, 0xa8, 0x08, 0xf5, 0xd8, 0x0a, 0xe4, 0xe5, 0xc8, + 0xc6, 0x1b, 0x00, 0x2c, 0xd5, 0x14, 0x3e, 0xdc, 0x01, 0xff, 0x0a, 0xeb, 0x1e, + 0x1a, 0x02, 0x24, 0xe4, 0xf4, 0xfc, 0x3c, 0x16, 0x0d, 0xc6, 0xf5, 0xf2, 0xf3, + 0xca, 0x0b, 0xc6, 0x21, 0xe6, 0xd8, 0x3f, 0x05, 0x1a, 0xfe, 0xe9, 0xd0, 0x5d, + 0x2d, 0xf2, 0xea, 0xf9, 0xe3, 0xf9, 0xcb, 0xd5, 0xeb, 0x00, 0xe7, 0x37, 0x02, + 0xcf, 0x1b, 0xf6, 0x18, 0xf1, 0x30, 0xf8, 0x2c, 0xfc, 0xcd, 0x81, 0x08, 0x27, + 0xff, 0x2e, 0x02, 0xfb, 0xe1, 0xf9, 0x06, 0x2e, 0xe9, 0x26, 0x13, 0xde, 0x02, + 0x17, 0x04, 0x03, 0x09, 0x37, 0x7f, 0x02, 0xdf, 0x29, 0xd9, 0xf3, 0xe8, 0xe5, + 0x0f, 0x03, 0xdc, 0x1c, 0x2a, 0xd3, 0xac, 0xf0, 0x44, 0x06, 0xf4, 0xe1, 0xe0, + 0x17, 0x00, 0xfd, 0xcf, 0xfa, 0x21, 0xfe, 0xb3, 0xe1, 0xe9, 0x2e, 0x14, 0xf9, + 0xe3, 0x02, 0xf3, 0x02, 0x11, 0x23, 0x29, 0x18, 0x13, 0x02, 0xf0, 0x12, 0xe9, + 0x13, 0xf7, 0x0f, 0xce, 0xcc, 0xf5, 0x06, 0x1a, 0x07, 0x0f, 0xf2, 0x15, 0xf2, + 0xe6, 0x08, 0xf3, 0xf2, 0xeb, 0xf8, 0xd6, 0x23, 0x08, 0xe5, 0x09, 0x2f, 0xe3, + 0xe5, 0xfc, 0x37, 0x00, 0x08, 0xea, 0x05, 0x31, 0xfa, 0xe9, 0x35, 0xf6, 0x1f, + 0x02, 0xfd, 0xde, 0xcf, 0xea, 0xd0, 0x30, 0xea, 0x07, 0xf3, 0x06, 0xfe, 0x2b, + 0xc4, 0x1c, 0xe4, 0xd2, 0xe6, 0x10, 0xf9, 0xdd, 0x11, 0xcb, 0x15, 0xb1, 0xfb, + 0x48, 0xf4, 0x23, 0x02, 0x15, 0x42, 0x1c, 0xef, 0x38, 0xc0, 0xe6, 0x04, 0x17, + 0x05, 0xef, 0xe8, 0x47, 0x24, 0xf6, 0x2d, 0x1b, 0xf4, 0x55, 0x3a, 0x37, 0xb9, + 0x10, 0xda, 0x96, 0xd4, 0x34, 0xba, 0xff, 0x09, 0x02, 0xf9, 0x1f, 0xcc, 0xf1, + 0x40, 0xbc, 0xeb, 0xe0, 0x47, 0xee, 0xef, 0xfc, 0x3c, 0x11, 0x7a, 0x08, 0xd7, + 0xf5, 0xf3, 0xd6, 0xb6, 0xf5, 0xf1, 0x25, 0xe8, 0xac, 0xfb, 0xc2, 0xce, 0x81, + 0x74, 0xcd, 0xf0, 0x43, 0xb2, 0xbd, 0xc2, 0xff, 0x04, 0x2e, 0x61, 0xbf, 0xec, + 0x03, 0xf8, 0xf7, 0xf1, 0x9d, 0xee, 0x1a, 0x1f, 0xd8, 0x4a, 0xe1, 0xdb, 0x4a, + 0x3c, 0xed, 0xee, 0x23, 0x4a, 0xcb, 0xce, 0x16, 0x3c, 0x3d, 0xf1, 0x05, 0xde, + 0x50, 0x01, 0x11, 0xcc, 0x92, 0xf9, 0x14, 0xd1, 0xd6, 0x08, 0xd9, 0x8d, 0x9c, + 0xcd, 0x2e, 0xc3, 0xed, 0x04, 0x05, 0x7a, 0x2b, 0x02, 0x1d, 0xa1, 0x26, 0xd4, + 0x32, 0x26, 0x96, 0x64, 0xe8, 0xdb, 0x0b, 0x2a, 0xd5, 0x04, 0x13, 0x2c, 0x5e, + 0xf1, 0x06, 0x0e, 0x9d, 0xdd, 0xd8, 0xe8, 0x2f, 0x23, 0x2f, 0xcd, 0xc5, 0xee, + 0x30, 0xed, 0x5e, 0xdb, 0xf4, 0xe9, 0x20, 0xe3, 0x1b, 0xe1, 0xf4, 0xd4, 0xed, + 0x2e, 0xd2, 0xb7, 0x5a, 0x0f, 0xc9, 0xca, 0xce, 0x9e, 0x53, 0x2f, 0x4b, 0x18, + 0x82, 0x00, 0xda, 0xe3, 0xbc, 0x1b, 0xc6, 0xfe, 0xde, 0x4b, 0x32, 0xbc, 0xef, + 0xb3, 0xf3, 0xfc, 0x61, 0x2f, 0xfa, 0xa1, 0x86, 0x5c, 0xd0, 0xdc, 0x02, 0x4b, + 0xeb, 0x1f, 0x5a, 0x24, 0x16, 0x0f, 0xd1, 0xd1, 0xbf, 0xd9, 0x8f, 0xa8, 0x11, + 0x3b, 0xd8, 0x32, 0xda, 0xe6, 0x59, 0x7f, 0x11, 0x40, 0xe4, 0x34, 0xf0, 0x06, + 0xd4, 0xf4, 0xd5, 0xc3, 0x1e, 0x2e, 0x1b, 0xe9, 0xf6, 0x12, 0xe5, 0x0b, 0xe4, + 0x3b, 0x14, 0xd0, 0x45, 0x0c, 0xdb, 0xdb, 0xf5, 0xfa, 0x06, 0x1a, 0xc8, 0xe3, + 0xe5, 0x06, 0x14, 0x28, 0xf6, 0xbf, 0xc9, 0x09, 0xb1, 0x35, 0xd8, 0x10, 0xf5, + 0x35, 0x09, 0x0c, 0x18, 0xfd, 0xfa, 0x16, 0xfc, 0x41, 0xd5, 0x27, 0xc1, 0xa4, + 0x0e, 0xdc, 0xdc, 0x48, 0x38, 0xff, 0x0e, 0x4b, 0x0a, 0xa5, 0xee, 0x30, 0x1b, + 0x0b, 0x01, 0x0f, 0x53, 0xf7, 0xd7, 0xed, 0xec, 0xf9, 0xd1, 0x2a, 0x26, 0x2d, + 0xfa, 0x35, 0x22, 0x36, 0xed, 0xfc, 0x14, 0x8e, 0xef, 0xdd, 0x0b, 0x3b, 0x29, + 0xd6, 0xf4, 0xd0, 0x51, 0x00, 0xf5, 0xc8, 0x35, 0x09, 0xf1, 0x11, 0xd2, 0x5a, + 0xf9, 0x4f, 0xdd, 0x05, 0xc8, 0x0b, 0xe8, 0xf6, 0x2a, 0x2b, 0xfe, 0x81, 0x07, + 0x45, 0xce, 0x16, 0x1b, 0xe8, 0x46, 0xef, 0x4e, 0x0e, 0x21, 0xfa, 0x2b, 0xce, + 0x18, 0xfc, 0x2e, 0x09, 0x04, 0x5b, 0xd6, 0x27, 0x0f, 0xc9, 0x21, 0x14, 0xf3, + 0xfc, 0xe3, 0x02, 0xf4, 0xec, 0xff, 0xff, 0x2c, 0x12, 0x1c, 0x03, 0x02, 0xdd, + 0xe5, 0x19, 0x0a, 0x0e, 0x2c, 0xf5, 0x23, 0xfa, 0xd0, 0x08, 0x1f, 0xe0, 0xdb, + 0x14, 0xf9, 0xe9, 0x00, 0x1c, 0x16, 0xd5, 0xf9, 0xc5, 0xfb, 0x26, 0x15, 0xfe, + 0x05, 0x07, 0xd5, 0x25, 0x1a, 0xe4, 0xf9, 0xf9, 0xea, 0x0d, 0x0b, 0x23, 0x14, + 0xf0, 0xef, 0xdb, 0xe8, 0x1f, 0x2e, 0x0f, 0x09, 0xdd, 0x22, 0x0e, 0x05, 0xee, + 0xfd, 0x03, 0xc6, 0x0b, 0x05, 0xf1, 0xd6, 0x04, 0xdd, 0xe0, 0xfb, 0xfa, 0x01, + 0x17, 0xf0, 0xf1, 0x1e, 0x09, 0xfe, 0x00, 0x11, 0x02, 0x00, 0xc7, 0x04, 0xd2, + 0xf5, 0xdd, 0xfa, 0x09, 0xdc, 0x0f, 0xe4, 0xe1, 0xfa, 0xcb, 0x27, 0xed, 0xef, + 0xfc, 0xd4, 0xea, 0x04, 0xd3, 0xe8, 0x23, 0x02, 0x08, 0xce, 0x0a, 0x19, 0xf7, + 0xe7, 0xf9, 0x15, 0x2c, 0x03, 0xf0, 0xf5, 0x3f, 0x0b, 0x7f, 0x16, 0x18, 0x21, + 0xf6, 0x38, 0xd5, 0xfe, 0x01, 0xeb, 0x3b, 0xbe, 0xdb, 0xba, 0xa2, 0xae, 0x01, + 0x2d, 0x6a, 0x46, 0x29, 0x2b, 0x29, 0x81, 0x04, 0xff, 0x23, 0x1b, 0xfd, 0xab, + 0x26, 0x37, 0x3f, 0x21, 0x20, 0x23, 0x9d, 0xc1, 0xc6, 0xcf, 0x7a, 0x49, 0xea, + 0xf4, 0xd5, 0x2f, 0xcc, 0x48, 0xd7, 0x13, 0xfd, 0x3e, 0x0f, 0xef, 0x50, 0xe0, + 0x11, 0xd2, 0x37, 0x2e, 0x3d, 0x20, 0x55, 0xe5, 0x3a, 0xe4, 0x12, 0x2a, 0x27, + 0x04, 0x57, 0x4d, 0xf4, 0x0f, 0x29, 0x27, 0xf8, 0x2c, 0xfd, 0x69, 0x2d, 0xfe, + 0x32, 0xfd, 0xa6, 0xc8, 0xe2, 0xf6, 0x31, 0xbf, 0x52, 0xf8, 0xff, 0xe1, 0xdb, + 0x50, 0xdc, 0xea, 0xf0, 0xdb, 0x18, 0x93, 0xca, 0x65, 0x8f, 0x09, 0x10, 0x62, + 0xe5, 0x3c, 0x4c, 0x03, 0xe7, 0x0d, 0xff, 0x9c, 0x4d, 0xe3, 0xe1, 0xf9, 0xce, + 0x36, 0xe7, 0x1d, 0x9f, 0x19, 0x13, 0x2f, 0x4d, 0xf5, 0xeb, 0xe4, 0x68, 0x10, + 0x2d, 0xe5, 0x17, 0xe3, 0xd0, 0xd5, 0xec, 0x13, 0x1b, 0x10, 0xd6, 0x39, 0xd4, + 0x24, 0xe3, 0xc3, 0x14, 0xee, 0xfd, 0xee, 0x45, 0x0e, 0x23, 0xf0, 0x32, 0x03, + 0xe7, 0xdc, 0x26, 0x3e, 0xec, 0xbe, 0xd9, 0x7f, 0xda, 0x0c, 0x23, 0x19, 0x17, + 0xf2, 0x52, 0x37, 0xce, 0xfd, 0xec, 0x25, 0x19, 0xf5, 0x01, 0xf1, 0xf0, 0x02, + 0xe8, 0x1b, 0xf7, 0xe1, 0xf2, 0x01, 0xd5, 0xdf, 0xe6, 0xff, 0x0d, 0xeb, 0xdc, + 0x18, 0xdc, 0xf1, 0x1f, 0xf8, 0xe7, 0xff, 0xf1, 0xe0, 0xd6, 0x2e, 0x0e, 0x09, + 0xdc, 0x25, 0xfc, 0x05, 0xdb, 0x1c, 0xdf, 0xca, 0xf3, 0xec, 0x27, 0x1c, 0x3e, + 0xc2, 0xde, 0x26, 0x37, 0xf6, 0xfe, 0x2f, 0x1a, 0x0b, 0xd9, 0xf5, 0xca, 0xf6, + 0xca, 0x1d, 0x10, 0x01, 0xfc, 0x08, 0xfd, 0xcf, 0x03, 0x1f, 0x1e, 0x32, 0xa4, + 0xe6, 0xed, 0x00, 0xd2, 0x27, 0xd7, 0xeb, 0x10, 0xe6, 0x1d, 0xe3, 0x00, 0xcf, + 0xff, 0x16, 0xdd, 0xcb, 0x09, 0x12, 0xe0, 0xf0, 0xee, 0x08, 0xf7, 0xc6, 0x24, + 0x44, 0x04, 0xaf, 0x22, 0xd7, 0x39, 0xef, 0x2c, 0xf8, 0x2b, 0xd9, 0x2b, 0xf8, + 0x0b, 0x4d, 0xca, 0xf8, 0xcb, 0x19, 0x1e, 0xfb, 0xd7, 0xf3, 0x1a, 0xf8, 0x4c, + 0x23, 0xe7, 0xf3, 0x00, 0x1d, 0x13, 0xe7, 0xf5, 0x39, 0xb3, 0x1c, 0xe8, 0x0b, + 0x27, 0xf0, 0xe6, 0x06, 0x40, 0x14, 0xd9, 0xe4, 0xce, 0x24, 0xd8, 0xc2, 0x16, + 0xdb, 0xf7, 0x29, 0xbb, 0x38, 0xf1, 0x01, 0xf9, 0x2a, 0x05, 0x07, 0xac, 0x13, + 0x0c, 0x04, 0xe9, 0xf6, 0x02, 0x04, 0x0c, 0x51, 0x07, 0xfa, 0xe0, 0x25, 0x2d, + 0x81, 0xe7, 0x0a, 0x02, 0x0c, 0xe8, 0x59, 0xd3, 0xf3, 0xf4, 0xec, 0xeb, 0x4e, + 0xef, 0xdb, 0x04, 0xf8, 0x0c, 0x13, 0x20, 0xde, 0xd4, 0x0b, 0xe1, 0x32, 0xd6, + 0xfa, 0x08, 0x02, 0xe2, 0x20, 0x2a, 0x28, 0x3a, 0xdd, 0xb2, 0x61, 0x5c, 0x21, + 0x1e, 0xf4, 0xb4, 0x0a, 0x30, 0xf2, 0x15, 0xd9, 0xd5, 0x25, 0x06, 0xbe, 0xca, + 0x04, 0xd4, 0xd6, 0x26, 0x5f, 0x02, 0xcd, 0x37, 0x54, 0x14, 0xd1, 0x35, 0x08, + 0x0e, 0x53, 0x17, 0x20, 0x35, 0x2d, 0x16, 0x61, 0x0f, 0xdb, 0xfb, 0xcd, 0xd0, + 0xee, 0x00, 0x47, 0x1c, 0x39, 0x14, 0x08, 0xe7, 0x2d, 0xcf, 0xfb, 0x13, 0x26, + 0xf5, 0xe6, 0xc4, 0xce, 0x3c, 0xe5, 0x11, 0x07, 0x37, 0x1b, 0xf6, 0x3f, 0x16, + 0x60, 0x07, 0xdf, 0x93, 0xcf, 0xd3, 0x9d, 0xbd, 0xda, 0x2d, 0x05, 0x01, 0xa1, + 0xe7, 0xe2, 0xcd, 0x1a, 0x20, 0xc5, 0xf0, 0x08, 0xd1, 0xc3, 0xa7, 0xd2, 0xbb, + 0x34, 0xf1, 0xe3, 0x7f, 0xe4, 0xe7, 0x18, 0xec, 0xf4, 0x59, 0xd9, 0xa3, 0x1c, + 0x0f, 0x41, 0xde, 0xe0, 0x09, 0xe6, 0x4d, 0xf2, 0x2c, 0xc2, 0x6a, 0x06, 0xbe, + 0xab, 0xbe, 0x36, 0x33, 0xd1, 0x1a, 0xba, 0xe1, 0xe5, 0x29, 0x37, 0x12, 0xb4, + 0xe2, 0xea, 0xd5, 0xd5, 0xfd, 0xcf, 0xde, 0xd0, 0xd0, 0x09, 0xf8, 0x19, 0x31, + 0x26, 0xcd, 0x3d, 0xcb, 0xfa, 0x00, 0x13, 0x07, 0xf4, 0x1a, 0xeb, 0x08, 0xde, + 0x04, 0xd9, 0x05, 0x3d, 0x0a, 0x0f, 0x0f, 0x37, 0x3f, 0xfe, 0xe5, 0x29, 0x16, + 0x1b, 0x15, 0xe2, 0xee, 0xfa, 0xf7, 0xb4, 0x0a, 0x12, 0x09, 0xf1, 0xf9, 0x6f, + 0xf0, 0xe5, 0x0c, 0x13, 0xe1, 0xac, 0xd0, 0xdd, 0xc1, 0x3f, 0xe8, 0xe1, 0x17, + 0x70, 0xf8, 0xb2, 0xf2, 0xf5, 0xdd, 0x45, 0xf7, 0x1e, 0xf1, 0x1c, 0x05, 0xe4, + 0x1f, 0xcb, 0x07, 0x10, 0x3a, 0xe3, 0xf6, 0xfe, 0x14, 0xed, 0x27, 0xcb, 0xdf, + 0xd4, 0x19, 0xe3, 0xdd, 0x15, 0xe6, 0x17, 0x13, 0xfe, 0xe7, 0x09, 0x0f, 0xcc, + 0x48, 0x6b, 0xfc, 0xfd, 0x17, 0xf7, 0x02, 0x11, 0xea, 0x19, 0xe9, 0xf0, 0x81, + 0xdd, 0x06, 0xea, 0x06, 0x03, 0xd8, 0x46, 0x24, 0x18, 0xb9, 0xd7, 0x1c, 0x0e, + 0x0d, 0x0a, 0xe1, 0x20, 0x26, 0x2c, 0x12, 0x94, 0x5f, 0x2c, 0x22, 0xcd, 0xe7, + 0x09, 0x1c, 0x1b, 0xd8, 0xea, 0x1e, 0x00, 0x56, 0xcf, 0x22, 0xef, 0xe3, 0xe5, + 0x31, 0x1a, 0xbe, 0xd5, 0x28, 0x2b, 0xfe, 0x27, 0xda, 0x17, 0x25, 0xdf, 0x51, + 0x22, 0xdb, 0x4d, 0x18, 0x2a, 0x4e, 0x3e, 0xec, 0xaf, 0x2f, 0x1d, 0x46, 0xcf, + 0x1f, 0x00, 0xe8, 0xfc, 0xd9, 0x04, 0x1f, 0x57, 0x72, 0x38, 0x05, 0x2f, 0xf6, + 0xfc, 0xe1, 0xf2, 0x2a, 0x0f, 0x32, 0xc7, 0x15, 0xf0, 0x0c, 0xea, 0x19, 0x7f, + 0x37, 0x0a, 0x2e, 0x47, 0xcd, 0x17, 0xee, 0x0c, 0x24, 0xf5, 0xb3, 0xfd, 0xd3, + 0xd3, 0xba, 0x11, 0xc8, 0xf2, 0xd4, 0xdb, 0x2c, 0x2f, 0xc9, 0xd3, 0x43, 0x0b, + 0xf8, 0xf6, 0x0c, 0xe7, 0x16, 0x0a, 0x84, 0xc7, 0xfc, 0xbd, 0x04, 0xe8, 0x06, + 0xf8, 0xea, 0x16, 0xf1, 0xc5, 0x02, 0x05, 0xee, 0xbf, 0xce, 0x1a, 0xe3, 0x82, + 0x01, 0x13, 0xeb, 0x57, 0xed, 0x15, 0x1e, 0xec, 0x38, 0x4b, 0x76, 0x10, 0x26, + 0xd4, 0xee, 0xf7, 0x2b, 0xe8, 0x02, 0x1b, 0x04, 0xbf, 0xcc, 0x17, 0x0a, 0x1d, + 0x13, 0x30, 0xf6, 0x19, 0x2b, 0x0a, 0xc7, 0x04, 0x47, 0x4c, 0x04, 0xdf, 0x26, + 0xd9, 0x00, 0xf7, 0xe4, 0xf5, 0x02, 0xe6, 0xc7, 0x09, 0x10, 0x96, 0x04, 0xfe, + 0x0c, 0xf3, 0xbe, 0x15, 0xba, 0x1c, 0x03, 0x10, 0xda, 0xf2, 0x81, 0xf5, 0xff, + 0x18, 0xa7, 0x1f, 0xff, 0x26, 0xd6, 0x45, 0xf3, 0x30, 0xea, 0xe2, 0xb1, 0xfe, + 0x36, 0x2f, 0x31, 0xb0, 0xfe, 0x33, 0x69, 0x1b, 0x0c, 0xe0, 0x3b, 0xbb, 0x13, + 0xfd, 0x2d, 0x25, 0x07, 0x0b, 0xd1, 0xf0, 0xc5, 0xdf, 0x4d, 0x63, 0x1e, 0x1c, + 0xf8, 0xd6, 0x15, 0xd4, 0xf8, 0x2c, 0xf9, 0x4e, 0xb4, 0x29, 0x15, 0xd0, 0x05, + 0x38, 0x2f, 0x12, 0xfe, 0x1a, 0x05, 0xee, 0xb5, 0xf9, 0xd6, 0xbd, 0x31, 0xfd, + 0xe8, 0x13, 0xc2, 0xf4, 0xad, 0xf4, 0x09, 0x12, 0xfa, 0x34, 0xf2, 0xe5, 0x0f, + 0xe8, 0xc0, 0x01, 0xc8, 0x2b, 0x01, 0xac, 0xda, 0x10, 0x35, 0x23, 0xf6, 0xfe, + 0x32, 0xe5, 0x09, 0x02, 0x1e, 0x7f, 0xbc, 0x21, 0x4b, 0x33, 0xff, 0xf7, 0xe7, + 0xe9, 0x08, 0x10, 0xed, 0x26, 0x32, 0x9f, 0xbf, 0x06, 0xf3, 0x50, 0x21, 0x1a, + 0x1b, 0x19, 0xf4, 0xbf, 0xe6, 0xf7, 0x1c, 0x12, 0xe6, 0xc0, 0x47, 0xe3, 0x13, + 0x27, 0xea, 0x0a, 0x35, 0xf8, 0x20, 0xcd, 0x92, 0x0b, 0x2c, 0xe5, 0xde, 0x11, + 0x04, 0x03, 0x0c, 0x42, 0xe0, 0xce, 0xd4, 0x20, 0xff, 0x22, 0x1f, 0xe8, 0xd2, + 0x03, 0xbd, 0x31, 0x6d, 0xf4, 0x0f, 0x06, 0x52, 0xcd, 0xc3, 0xf1, 0xc3, 0xe2, + 0x20, 0x0d, 0x10, 0x01, 0x15, 0xd1, 0x1f, 0xdc, 0x22, 0xf3, 0x2f, 0xe7, 0xf7, + 0x00, 0x0b, 0x0b, 0x12, 0x17, 0x44, 0xf5, 0xa2, 0xe5, 0x14, 0xf4, 0x0f, 0x3b, + 0xc6, 0x31, 0xf4, 0xcf, 0x2b, 0x08, 0xdf, 0xe1, 0xa3, 0x09, 0xfd, 0xf4, 0xc3, + 0xf0, 0xf0, 0x18, 0x3c, 0xf2, 0xb8, 0xf5, 0xe5, 0xe5, 0x05, 0x3a, 0xe6, 0x28, + 0xed, 0xe5, 0x2d, 0x2b, 0x17, 0xcf, 0x0e, 0xe4, 0xbd, 0x27, 0x09, 0xf8, 0x0c, + 0x15, 0xe2, 0xe9, 0xde, 0x24, 0x02, 0x08, 0xe8, 0x02, 0x04, 0x07, 0xcd, 0xf7, + 0x9a, 0xf3, 0x01, 0xec, 0xcf, 0xe1, 0xd5, 0xf8, 0x4f, 0x06, 0x1f, 0x15, 0xf5, + 0x2a, 0x0b, 0xea, 0xfc, 0x18, 0xd4, 0xf9, 0x33, 0x16, 0xf8, 0x7f, 0x39, 0x21, + 0x00, 0x13, 0x5f, 0xe3, 0xd7, 0xd6, 0xc4, 0x30, 0xf2, 0x08, 0xfd, 0xba, 0xf7, + 0x22, 0x0d, 0x1d, 0xf3, 0x31, 0xe7, 0xed, 0xd1, 0x39, 0xf5, 0x08, 0xce, 0xfa, + 0x1b, 0x01, 0x54, 0xfa, 0xb3, 0xf0, 0xc5, 0x3d, 0xfb, 0x01, 0x39, 0xd9, 0x02, + 0x1e, 0x25, 0xd1, 0xbd, 0x0a, 0x10, 0xd7, 0x24, 0x1b, 0xdd, 0xf1, 0xf7, 0xf8, + 0xf4, 0xea, 0x81, 0x27, 0x11, 0x2d, 0xfb, 0x64, 0x2c, 0x10, 0x16, 0x11, 0xed, + 0x0a, 0x09, 0xc1, 0x1b, 0x0c, 0xf3, 0x24, 0x0d, 0x39, 0x1d, 0x05, 0x18, 0xc8, + 0xde, 0x00, 0x1d, 0xf4, 0xf7, 0xea, 0xf8, 0x11, 0xcb, 0xfe, 0x11, 0x19, 0xed, + 0xea, 0xfc, 0x0f, 0xf0, 0xe3, 0xcc, 0xe0, 0xea, 0xa4, 0x25, 0x10, 0x04, 0xef, + 0x15, 0xeb, 0xc4, 0x01, 0xfe, 0x01, 0xd1, 0x01, 0xfe, 0xf9, 0x6f, 0x09, 0x17, + 0xdc, 0xe6, 0x2d, 0x08, 0xcd, 0xbe, 0x99, 0x30, 0xe4, 0x10, 0xb2, 0xaa, 0x22, + 0xc5, 0x00, 0x00, 0x06, 0xfd, 0xe3, 0xef, 0xc8, 0xf0, 0xe8, 0xb4, 0xf0, 0xf2, + 0x05, 0xe8, 0x11, 0xf9, 0x13, 0x1f, 0xf1, 0xf7, 0xe3, 0xe1, 0xc6, 0xc8, 0x00, + 0xf8, 0xf7, 0x42, 0x15, 0x19, 0xf7, 0xf5, 0xea, 0xf0, 0xbf, 0x19, 0x05, 0x13, + 0xe0, 0xc0, 0xdd, 0xd7, 0xcb, 0x13, 0xe7, 0x1d, 0x2e, 0xec, 0x08, 0xfe, 0xfc, + 0x18, 0x18, 0xdd, 0x10, 0x0b, 0xe3, 0x27, 0xe6, 0xf9, 0x11, 0x67, 0xfc, 0x1e, + 0xd4, 0x0b, 0xee, 0xf2, 0x1f, 0xfd, 0xb2, 0x02, 0x32, 0xcd, 0xc8, 0xf9, 0x0d, + 0x0c, 0xe6, 0xfd, 0x11, 0xe2, 0x0b, 0xee, 0xcd, 0x3a, 0xf3, 0xd8, 0x11, 0x10, + 0x05, 0x10, 0xf4, 0xdc, 0x0d, 0x36, 0x0a, 0xda, 0xf2, 0x38, 0x2f, 0x0c, 0x0c, + 0x05, 0x2a, 0xe4, 0xca, 0xfb, 0xd9, 0xfc, 0x05, 0xfc, 0xe1, 0xf7, 0xed, 0xcb, + 0x52, 0xfe, 0x00, 0x7f, 0xd9, 0x39, 0x32, 0xb1, 0x0d, 0xc0, 0x08, 0xfb, 0x16, + 0xb5, 0x10, 0x0e, 0x12, 0x31, 0xdb, 0x43, 0xc8, 0xca, 0xf0, 0xd1, 0xff, 0xf6, + 0x0f, 0xfe, 0x5f, 0xc2, 0x36, 0xe7, 0x0c, 0x1d, 0x15, 0xeb, 0x10, 0xf1, 0xc7, + 0x0a, 0x2b, 0xed, 0xd6, 0x2c, 0xc2, 0x02, 0xd2, 0xfd, 0xff, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0, 0x32, 0xf7, 0x38, 0xec, 0xf3, 0xe0, + 0x99, 0xc8, 0x0a, 0x05, 0xb2, 0x2f, 0x1c, 0xc9, 0x08, 0xe5, 0x0b, 0x19, 0x05, + 0x12, 0x05, 0x29, 0xcc, 0x12, 0xef, 0xf6, 0x37, 0xe9, 0xc1, 0xe6, 0xf2, 0xef, + 0x28, 0xe8, 0xd4, 0xf8, 0x14, 0xc6, 0x41, 0x23, 0x06, 0x59, 0x26, 0x09, 0xf3, + 0xeb, 0xdc, 0x44, 0xfa, 0xdc, 0xca, 0xd0, 0x12, 0x31, 0x37, 0xe9, 0xf5, 0x0d, + 0x03, 0x07, 0xb4, 0xe7, 0xfe, 0xf1, 0xa4, 0x62, 0xf5, 0x3c, 0x36, 0xf1, 0x27, + 0x06, 0xc6, 0x0f, 0x2c, 0xd8, 0xdd, 0xf9, 0x03, 0x4c, 0x0b, 0xb0, 0xa9, 0x24, + 0xfd, 0x81, 0x31, 0x96, 0xce, 0x63, 0xca, 0x17, 0x58, 0x33, 0x0d, 0x12, 0xca, + 0xc6, 0x48, 0xae, 0xeb, 0x49, 0xe8, 0xe0, 0x43, 0x08, 0x40, 0xb6, 0xc8, 0x8f, + 0x3d, 0x5b, 0xcc, 0xf6, 0x56, 0x63, 0xf5, 0x0a, 0x0d, 0xd9, 0x99, 0xe4, 0x06, + 0xde, 0x24, 0xd3, 0x0d, 0x21, 0x39, 0x2f, 0x81, 0x12, 0x41, 0xaf, 0x0a, 0xf2, + 0xd3, 0xcf, 0xdb, 0x1f, 0x04, 0xf1, 0x04, 0x3c, 0x1a, 0x53, 0x31, 0x16, 0xe9, + 0x1c, 0xe3, 0x26, 0x32, 0xbb, 0xf1, 0x01, 0x01, 0x34, 0xc2, 0x08, 0x12, 0x1b, + 0x67, 0xfb, 0x40, 0xde, 0xc6, 0xdd, 0x6b, 0xc5, 0x0f, 0x01, 0xb9, 0xd6, 0xfa, + 0xf5, 0x28, 0xe4, 0x15, 0xe9, 0x08, 0x35, 0x5f, 0x29, 0xbe, 0xf6, 0x03, 0x02, + 0xaa, 0x3a, 0x06, 0x09, 0xc6, 0x2c, 0xf5, 0xc7, 0x09, 0x25, 0xdf, 0xee, 0x06, + 0x3f, 0x25, 0x08, 0x20, 0xf0, 0xe6, 0x9c, 0xfc, 0xa8, 0xdf, 0x07, 0x48, 0xdd, + 0xad, 0xed, 0xfa, 0x06, 0xe5, 0xd6, 0xb6, 0x27, 0xb8, 0x1c, 0x1f, 0x40, 0x29, + 0xf5, 0x19, 0x14, 0xe8, 0xe5, 0x33, 0x9a, 0x26, 0x0e, 0x47, 0xe2, 0xcf, 0x0c, + 0x00, 0x39, 0xe8, 0x2a, 0x2b, 0x0e, 0xe1, 0x29, 0x66, 0xf5, 0xf9, 0xc3, 0xde, + 0xcf, 0x0f, 0xde, 0xdb, 0xd8, 0x22, 0x10, 0x01, 0xf2, 0xc7, 0xca, 0x10, 0x15, + 0xcf, 0xeb, 0x08, 0xf0, 0xe5, 0x23, 0x0d, 0x20, 0x05, 0x06, 0x31, 0xe7, 0x03, + 0xdd, 0x4e, 0xd5, 0xf8, 0x4c, 0x5e, 0x17, 0x40, 0x7f, 0xca, 0x46, 0xbc, 0xb7, + 0xbe, 0x25, 0x14, 0x1b, 0xc6, 0x08, 0xea, 0x22, 0x98, 0xef, 0xe9, 0x18, 0xd0, + 0xe1, 0x1d, 0x3e, 0xd8, 0x06, 0x18, 0xd8, 0x38, 0xe8, 0xef, 0x36, 0xfa, 0x06, + 0xff, 0x14, 0xe5, 0xae, 0x33, 0x68, 0xdc, 0x00, 0x41, 0xe4, 0x2e, 0x0b, 0x26, + 0x19, 0xfb, 0xfc, 0x27, 0x53, 0xcd, 0xf9, 0x97, 0xdc, 0x21, 0x00, 0xd3, 0x32, + 0xd0, 0x13, 0x33, 0xee, 0x65, 0x48, 0x13, 0x9d, 0x00, 0x19, 0x28, 0xb1, 0x2a, + 0xdd, 0xd5, 0xfa, 0x1c, 0xd2, 0x09, 0xd6, 0x18, 0x28, 0xe4, 0xf3, 0x07, 0x0a, + 0xfa, 0x16, 0x12, 0xfd, 0xd2, 0xcc, 0x15, 0xf7, 0x1a, 0xe9, 0xed, 0xdd, 0xea, + 0x18, 0x03, 0xd8, 0x12, 0x0c, 0x15, 0xf9, 0x00, 0x6a, 0x41, 0xd8, 0xf4, 0xf8, + 0x0c, 0x1a, 0x37, 0x1e, 0x01, 0xf8, 0xd8, 0xe6, 0xf8, 0xe2, 0xdf, 0xb7, 0x09, + 0xe3, 0x3a, 0x08, 0x1b, 0xb3, 0xeb, 0xd0, 0x2b, 0xd8, 0x00, 0xf1, 0x5e, 0x31, + 0xcb, 0xc8, 0x7c, 0xf9, 0x81, 0xd4, 0x2f, 0xfe, 0x97, 0xcc, 0x1c, 0x75, 0xee, + 0xed, 0x4e, 0xf8, 0x14, 0xde, 0x49, 0x02, 0xe0, 0xe3, 0x58, 0xfd, 0xfb, 0xdf, + 0xfb, 0x14, 0x72, 0x19, 0x1f, 0xe8, 0x55, 0xd5, 0x0a, 0x4a, 0xd7, 0xbb, 0x1e, + 0x11, 0xe0, 0xcc, 0xe6, 0xf2, 0x27, 0xc8, 0x15, 0xf0, 0xf4, 0xfd, 0xdd, 0x42, + 0x1b, 0x2f, 0xcb, 0x13, 0xe5, 0xb1, 0x09, 0x1a, 0xcb, 0x23, 0x02, 0xe7, 0xe1, + 0x0b, 0xf2, 0x02, 0xcc, 0xeb, 0x12, 0x20, 0x24, 0xe3, 0xe1, 0xb9, 0xff, 0xbd, + 0x1a, 0x89, 0xfc, 0x1e, 0x38, 0xec, 0x04, 0x1b, 0x22, 0xf8, 0x0e, 0xf4, 0x41, + 0x0d, 0xf9, 0xf5, 0xfe, 0xe3, 0xf4, 0xfa, 0x10, 0x0b, 0xec, 0xc4, 0x24, 0x11, + 0x15, 0x05, 0x26, 0x10, 0xf0, 0xeb, 0x10, 0x04, 0xd4, 0x00, 0x29, 0xf8, 0x14, + 0x11, 0x18, 0xf8, 0x23, 0xe4, 0x10, 0x7f, 0x02, 0x13, 0x3e, 0xf8, 0xfb, 0x2e, + 0xd4, 0x0d, 0xfc, 0xdc, 0xfb, 0x52, 0xe2, 0x1d, 0xfb, 0x05, 0x07, 0xe7, 0xed, + 0x24, 0xff, 0xf0, 0xd9, 0xe4, 0xf8, 0x3b, 0x46, 0x05, 0xec, 0xea, 0xd7, 0x0b, + 0xec, 0x08, 0xf1, 0x3a, 0x22, 0xfa, 0xe5, 0x06, 0xfb, 0xf8, 0x12, 0x11, 0xee, + 0x0d, 0xee, 0xea, 0x0b, 0xf0, 0xed, 0x12, 0xe6, 0xe0, 0x05, 0xe2, 0xf6, 0x07, + 0xe2, 0xd9, 0x05, 0xe6, 0xf2, 0x3e, 0x02, 0xce, 0x19, 0x02, 0x31, 0xfe, 0xda, + 0xfa, 0x3b, 0x19, 0xf6, 0x04, 0x07, 0x14, 0xfc, 0x52, 0xf6, 0xf9, 0x2f, 0x16, + 0x0b, 0x15, 0x04, 0x1d, 0xf3, 0xdf, 0x29, 0xbf, 0xeb, 0xf2, 0xae, 0x12, 0xe3, + 0x2a, 0x0a, 0xe1, 0xcc, 0x13, 0x34, 0x0d, 0xf1, 0xe2, 0x2e, 0xcb, 0x00, 0x1a, + 0x24, 0x0c, 0xe0, 0x08, 0x0a, 0xeb, 0xed, 0x2a, 0x0b, 0x26, 0x07, 0x27, 0xf3, + 0xee, 0xf2, 0x09, 0xf3, 0x19, 0xc8, 0x27, 0x26, 0xef, 0xef, 0xcb, 0x08, 0x25, + 0xf2, 0xdb, 0xc4, 0x05, 0xd8, 0xf5, 0x09, 0xde, 0x07, 0xe2, 0xe3, 0x11, 0xbe, + 0xce, 0xc1, 0xa0, 0x58, 0x0b, 0x09, 0x35, 0xf1, 0x81, 0xed, 0xe2, 0x2e, 0x07, + 0x34, 0xd0, 0xe5, 0x20, 0x1a, 0x01, 0x0e, 0x41, 0xd6, 0xea, 0x26, 0x3c, 0xf8, + 0xd3, 0x12, 0x1e, 0x02, 0x4e, 0x02, 0x01, 0xe0, 0x0e, 0x05, 0xfc, 0x0c, 0x07, + 0x27, 0xd9, 0x00, 0x08, 0x11, 0xfe, 0xe1, 0x11, 0xf1, 0x16, 0xe6, 0x04, 0x05, + 0xf3, 0x51, 0x3e, 0xeb, 0xfa, 0xd5, 0x0e, 0xd7, 0x00, 0xfe, 0xfa, 0xd7, 0xe9, + 0x42, 0x03, 0xdf, 0x04, 0xe6, 0x16, 0xfa, 0xb6, 0x06, 0x06, 0xd6, 0xf8, 0xa2, + 0xce, 0x2c, 0xfb, 0xb7, 0x1c, 0xef, 0xe4, 0x1e, 0x33, 0xf7, 0xa9, 0x03, 0x60, + 0x2e, 0x5e, 0x1d, 0x08, 0x28, 0x44, 0xdd, 0xf3, 0xfd, 0xd1, 0x0b, 0xbd, 0xed, + 0xfc, 0x31, 0x26, 0x20, 0x52, 0xe7, 0x07, 0xa3, 0x12, 0xfe, 0x5c, 0x01, 0xbc, + 0xd8, 0x2f, 0xfd, 0x0e, 0xc9, 0xdc, 0x28, 0xfd, 0xf1, 0xd0, 0x10, 0xa2, 0xd0, + 0x0c, 0xda, 0x0d, 0xc9, 0xea, 0x02, 0x14, 0xc6, 0xed, 0xde, 0xde, 0xc1, 0xc9, + 0xcd, 0xe2, 0xd1, 0xf6, 0xd4, 0x38, 0x08, 0x20, 0xf3, 0xb5, 0xf8, 0xbb, 0x17, + 0xc0, 0x1d, 0xd3, 0x26, 0x3f, 0xe0, 0xfc, 0x9c, 0x15, 0xec, 0x3f, 0xdf, 0x3b, + 0xd9, 0x1b, 0x56, 0x9f, 0x35, 0xfd, 0xdc, 0x18, 0xfc, 0x9e, 0xe7, 0x29, 0x01, + 0x23, 0xb7, 0xf8, 0xf0, 0x54, 0xe4, 0x05, 0x00, 0x7f, 0xd9, 0xf7, 0x5b, 0xdf, + 0x13, 0xbf, 0xe5, 0xed, 0xe6, 0xff, 0x30, 0x16, 0x5f, 0x2f, 0xde, 0x5e, 0x08, + 0x28, 0xbd, 0x1e, 0x09, 0x53, 0xb5, 0x32, 0xf6, 0xd1, 0xe2, 0x04, 0xd7, 0x64, + 0xfb, 0xe2, 0xf9, 0xfc, 0x50, 0x1a, 0x23, 0xc1, 0x09, 0x31, 0x15, 0x50, 0x29, + 0xf9, 0x38, 0xe8, 0xbe, 0x7c, 0xbc, 0xe8, 0x3c, 0x2a, 0xdb, 0x09, 0xe2, 0xd5, + 0x3a, 0x52, 0x3d, 0xb6, 0xda, 0xdd, 0x22, 0xfc, 0xfc, 0xec, 0xed, 0x40, 0xd8, + 0x17, 0xae, 0xef, 0xf6, 0xdb, 0xe6, 0x7f, 0xfa, 0x16, 0x09, 0x11, 0x04, 0xfc, + 0x22, 0xbc, 0xde, 0x4d, 0xf9, 0x15, 0x52, 0xf9, 0x0b, 0xf4, 0x38, 0x23, 0xfb, + 0xa7, 0x29, 0xde, 0x2e, 0x34, 0x0c, 0x45, 0xff, 0x2a, 0x05, 0xb8, 0xed, 0xf9, + 0x22, 0x9d, 0x02, 0x36, 0x02, 0xd6, 0xad, 0x17, 0xe0, 0x2e, 0x38, 0x7e, 0x09, + 0x1b, 0xd4, 0x41, 0xfd, 0xe5, 0x0d, 0x2c, 0xe6, 0x0b, 0xf7, 0x00, 0xb3, 0x0e, + 0xff, 0xae, 0x21, 0xad, 0xd4, 0x28, 0xc1, 0x16, 0x48, 0x75, 0x01, 0xfe, 0xe6, + 0x49, 0xf0, 0xad, 0xcf, 0xd6, 0x02, 0xee, 0xdb, 0x16, 0xa4, 0xbc, 0x01, 0xe2, + 0x22, 0x17, 0xf1, 0x0e, 0xf2, 0xdb, 0xe1, 0xe2, 0x44, 0xe4, 0x19, 0xe6, 0x2f, + 0xe2, 0xf1, 0x2e, 0x36, 0x06, 0xa8, 0x2d, 0x22, 0xef, 0xeb, 0xd4, 0x69, 0x35, + 0xc1, 0x09, 0xd4, 0xc6, 0xc3, 0xd4, 0x7f, 0x37, 0xdf, 0xd5, 0xff, 0xf1, 0x89, + 0x22, 0x49, 0xba, 0x29, 0x28, 0x09, 0x0e, 0x48, 0x00, 0xec, 0xf1, 0x08, 0xeb, + 0x32, 0xe3, 0xf4, 0x04, 0xff, 0x24, 0xff, 0x70, 0xe0, 0xea, 0x17, 0xf2, 0x22, + 0xa5, 0x0a, 0x2b, 0x02, 0x06, 0x10, 0x18, 0x0a, 0x5d, 0xef, 0x58, 0x0a, 0xd2, + 0xe3, 0xa7, 0x24, 0x5f, 0x18, 0xd3, 0x16, 0x08, 0x36, 0xd9, 0xf5, 0x0c, 0xde, + 0xbd, 0xf5, 0x0e, 0xe0, 0xae, 0x21, 0x22, 0x6e, 0x24, 0xf9, 0xdd, 0x09, 0x29, + 0x5b, 0x0f, 0xdb, 0x1a, 0xa7, 0xd8, 0x13, 0xfa, 0xf1, 0x38, 0xef, 0x1b, 0x18, + 0x37, 0x11, 0x05, 0xf5, 0x13, 0x21, 0x30, 0x11, 0xcb, 0xe5, 0xf0, 0xdd, 0xf3, + 0x09, 0x08, 0x34, 0xfa, 0xee, 0xfe, 0x0f, 0x00, 0x7f, 0xed, 0x1b, 0x98, 0xce, + 0xcd, 0xc5, 0xec, 0x23, 0xf2, 0xe0, 0xe0, 0xdb, 0xea, 0xd0, 0xf7, 0xeb, 0x1d, + 0xd2, 0x47, 0x24, 0xfe, 0x13, 0xd1, 0xfd, 0xd3, 0x31, 0xc4, 0xd9, 0x28, 0x2d, + 0x1f, 0xe8, 0x1f, 0xfe, 0xe2, 0x06, 0xcf, 0xea, 0x1b, 0xc5, 0xed, 0xe3, 0xc0, + 0x1f, 0xe8, 0x04, 0xf5, 0xde, 0xda, 0xcc, 0x03, 0x1b, 0xf8, 0x15, 0x14, 0x09, + 0xf0, 0xcb, 0xbe, 0xfb, 0xc8, 0xef, 0x0e, 0xfa, 0x1b, 0x34, 0xe1, 0x14, 0x0d, + 0xfd, 0x0c, 0x07, 0xe9, 0x52, 0xb1, 0xec, 0xf6, 0xe7, 0xcc, 0xf1, 0xb4, 0xed, + 0xdc, 0xe7, 0xd9, 0x2a, 0x14, 0xec, 0xf5, 0x0c, 0xbf, 0xef, 0xf8, 0xd6, 0xb0, + 0x46, 0xda, 0xee, 0xd9, 0x11, 0x2b, 0x48, 0x2b, 0xd3, 0xc9, 0xcd, 0x0e, 0xa7, + 0x08, 0x05, 0xe4, 0x30, 0x14, 0xcc, 0xf0, 0x61, 0x16, 0xfb, 0x87, 0x01, 0x1e, + 0x68, 0x0b, 0x38, 0xe7, 0xad, 0x0e, 0x27, 0xe1, 0xc8, 0x37, 0xe3, 0x32, 0x46, + 0xf6, 0xdd, 0x32, 0xcd, 0xbd, 0xfd, 0xd4, 0xc7, 0x0b, 0xff, 0x19, 0xb9, 0xf6, + 0x53, 0x1b, 0xf1, 0xda, 0xfb, 0xa9, 0x17, 0xce, 0x35, 0x27, 0x2f, 0xa7, 0x33, + 0xf6, 0x0c, 0x0c, 0xec, 0xcb, 0xd3, 0x22, 0xe7, 0x81, 0x2a, 0x01, 0xd6, 0x29, + 0xf6, 0xf9, 0x0d, 0xfc, 0xf5, 0xc8, 0xf0, 0x07, 0xf9, 0xdd, 0x12, 0xd4, 0x33, + 0xfc, 0x1c, 0xfc, 0xcc, 0xcb, 0xa5, 0xfa, 0x64, 0xdd, 0x44, 0xe2, 0xfc, 0xf2, + 0xd4, 0x31, 0x66, 0x05, 0x2c, 0xe2, 0x1f, 0xd4, 0x49, 0xd8, 0xf7, 0xad, 0x4c, + 0xf2, 0xe2, 0x06, 0x1a, 0x00, 0x22, 0x21, 0x10, 0xa9, 0xec, 0xdd, 0xe4, 0x11, + 0x09, 0xf2, 0xf4, 0xf3, 0xcb, 0x26, 0x55, 0xf9, 0xdd, 0xd8, 0x23, 0x2a, 0x33, + 0x2c, 0x04, 0x17, 0xb4, 0xb8, 0x0e, 0xcc, 0xf4, 0x37, 0x2f, 0xe5, 0x40, 0x04, + 0x07, 0xe3, 0x0d, 0x18, 0x17, 0x0d, 0x18, 0x39, 0x2d, 0xd8, 0xf1, 0xb5, 0xea, + 0x1a, 0xfc, 0xd3, 0xe2, 0x00, 0x13, 0xf2, 0xc5, 0xe2, 0xe6, 0xae, 0xd6, 0x13, + 0xdf, 0xc0, 0xb2, 0xd2, 0x00, 0x39, 0x09, 0x27, 0xfb, 0x81, 0x01, 0xde, 0x2b, + 0xfe, 0x33, 0x39, 0xfb, 0xfe, 0xfe, 0xf1, 0x06, 0xc3, 0xe4, 0x00, 0xd3, 0xc6, + 0x1f, 0x4b, 0x0e, 0xaf, 0x03, 0x36, 0xe7, 0xdd, 0xe4, 0xfd, 0xc8, 0xf4, 0xcb, + 0x1a, 0xf4, 0x0f, 0x03, 0x2f, 0xe5, 0xcd, 0x30, 0xbc, 0x2a, 0x2a, 0xf0, 0xfb, + 0xd7, 0x4c, 0x30, 0xdf, 0xcc, 0xcb, 0xe8, 0xe4, 0xf9, 0x07, 0x17, 0xf2, 0x02, + 0xc6, 0xf2, 0x39, 0x37, 0xfa, 0x21, 0xe5, 0xe6, 0x1d, 0xfe, 0xfc, 0x31, 0xef, + 0xd0, 0x19, 0x28, 0x0e, 0x4e, 0x1d, 0x1b, 0x46, 0xef, 0xef, 0x40, 0xd7, 0xf9, + 0x05, 0x15, 0x16, 0xf4, 0x01, 0x15, 0xa0, 0x04, 0x06, 0xaf, 0xc8, 0xe0, 0x08, + 0x00, 0xd5, 0x0d, 0x35, 0x03, 0x15, 0xdd, 0xdc, 0xe6, 0x33, 0xa0, 0xe6, 0xdf, + 0x37, 0xc6, 0x25, 0xdb, 0xde, 0xff, 0xfe, 0xfc, 0xc1, 0x24, 0x03, 0x5e, 0xe5, + 0xd7, 0xc7, 0xb2, 0xdc, 0x9c, 0x30, 0x12, 0xe9, 0xef, 0xde, 0x30, 0x11, 0xfb, + 0xff, 0xd7, 0x26, 0xfa, 0xd2, 0x52, 0x25, 0xe4, 0x24, 0x31, 0x1c, 0xf9, 0x14, + 0xec, 0x98, 0x1c, 0xeb, 0x20, 0xc5, 0xed, 0x81, 0xed, 0x08, 0xf7, 0x85, 0x0b, + 0xee, 0xb2, 0xf6, 0x1a, 0xf1, 0x04, 0x11, 0xcf, 0xea, 0xe9, 0x02, 0xf1, 0x01, + 0x29, 0x4d, 0xc9, 0xf6, 0x57, 0xdf, 0xc6, 0x3c, 0x39, 0x1c, 0xee, 0x04, 0xbd, + 0x43, 0xe5, 0xc8, 0xec, 0x03, 0xb5, 0xd1, 0x4a, 0x01, 0x51, 0x02, 0xe1, 0xb6, + 0xfb, 0x03, 0xfa, 0xde, 0xae, 0xa2, 0xff, 0xda, 0x01, 0xf5, 0xfa, 0xf1, 0x21, + 0x55, 0x28, 0x05, 0xf1, 0xe7, 0x20, 0x06, 0x15, 0x12, 0xf3, 0xe6, 0xf7, 0x6b, + 0x22, 0xfb, 0xf1, 0xef, 0x4e, 0x64, 0x28, 0x1f, 0x81, 0xc2, 0xfe, 0xbc, 0x1c, + 0xce, 0xac, 0x14, 0x99, 0x13, 0x0f, 0xd6, 0x07, 0x08, 0x1d, 0x30, 0x2c, 0xfd, + 0x1e, 0x0e, 0xda, 0xcc, 0xdc, 0xcf, 0x0d, 0xbf, 0xf7, 0x25, 0xaf, 0x3e, 0xad, + 0xe0, 0x01, 0x26, 0x0c, 0xae, 0x1f, 0x04, 0xf3, 0xbe, 0xf4, 0xc8, 0x4e, 0x02, + 0xcb, 0xf7, 0xec, 0xbb, 0x18, 0x3a, 0x44, 0xe1, 0xea, 0x05, 0xf7, 0x6f, 0x2a, + 0xa5, 0x3c, 0xf1, 0xfd, 0x7c, 0x22, 0xfa, 0xed, 0x23, 0xce, 0x0e, 0xd8, 0xee, + 0x29, 0x0f, 0xfc, 0x2d, 0x14, 0xd4, 0xe8, 0xed, 0xe6, 0xfb, 0x0d, 0xf4, 0xf9, + 0xff, 0xfc, 0x0a, 0xef, 0x2e, 0x14, 0x19, 0xe9, 0xbe, 0x7e, 0x30, 0x25, 0x6f, + 0x22, 0xd2, 0x11, 0xee, 0x10, 0xbe, 0xec, 0xdf, 0xa4, 0x28, 0xe3, 0xd0, 0xfe, + 0xe0, 0x07, 0x1d, 0x18, 0x91, 0x20, 0xf4, 0xac, 0x06, 0x0d, 0x36, 0x3f, 0x0b, + 0x15, 0x03, 0xb7, 0xce, 0x14, 0xec, 0x0f, 0xe1, 0xe1, 0x14, 0xaa, 0xda, 0x0e, + 0xeb, 0x0b, 0x06, 0xe8, 0x2b, 0x34, 0x0d, 0x2c, 0x38, 0x27, 0xb9, 0x70, 0x1d, + 0xfe, 0x4e, 0xf8, 0x16, 0x3a, 0x07, 0x4c, 0x27, 0x10, 0x45, 0xe2, 0xd9, 0x4b, + 0xec, 0xab, 0xa2, 0x02, 0xcb, 0x5d, 0xe2, 0x4d, 0x5b, 0x94, 0xf1, 0x6c, 0x20, + 0xc9, 0x00, 0xf6, 0x03, 0xfa, 0xef, 0x3a, 0x06, 0xe9, 0x30, 0xed, 0x11, 0xdd, + 0xdb, 0x15, 0xc3, 0x08, 0x4f, 0x59, 0x8e, 0xaf, 0x30, 0x29, 0x81, 0xdf, 0xe9, + 0xe6, 0xdb, 0xf8, 0x38, 0x40, 0x99, 0x5d, 0xeb, 0xc9, 0x0a, 0x17, 0x51, 0xc8, + 0x1b, 0xfb, 0x0a, 0xc1, 0xf0, 0x28, 0xf7, 0xa2, 0xf0, 0xc9, 0x34, 0xe6, 0xc0, + 0x8a, 0xf9, 0x06, 0x3c, 0xe3, 0xb9, 0xf7, 0x09, 0xec, 0xcd, 0x39, 0xd8, 0x03, + 0xc3, 0xf6, 0x0c, 0xe1, 0x04, 0xa2, 0x12, 0xc3, 0xe9, 0xd3, 0x05, 0x7f, 0x55, + 0xd0, 0xdb, 0x5c, 0x15, 0xef, 0xfc, 0x16, 0xcf, 0xc8, 0xd5, 0x1f, 0xfe, 0x5f, + 0x02, 0x51, 0x0c, 0x22, 0xff, 0xd7, 0x2c, 0xeb, 0x34, 0x19, 0x51, 0xfc, 0xe5, + 0xed, 0x37, 0xfd, 0xc5, 0x1c, 0xde, 0xd3, 0xf0, 0xd4, 0xf1, 0x07, 0xee, 0x3c, + 0xf2, 0xdc, 0xf0, 0xe3, 0x0f, 0x06, 0x32, 0x6d, 0xef, 0xc5, 0xe4, 0xda, 0x96, + 0xfe, 0xe1, 0x56, 0x00, 0xda, 0xf0, 0x2f, 0xd4, 0xe6, 0xe2, 0x15, 0xee, 0xfc, + 0xec, 0x3c, 0x25, 0xed, 0x2e, 0xcc, 0xd5, 0xe9, 0x91, 0xf8, 0xff, 0xf1, 0x59, + 0xd8, 0x0e, 0xe4, 0x18, 0xd1, 0xb6, 0x42, 0xef, 0x06, 0x02, 0x02, 0xce, 0xe3, + 0xf9, 0xe9, 0xd7, 0xe3, 0xfb, 0xd1, 0x2d, 0xf3, 0x17, 0xd5, 0x37, 0xd5, 0x2b, + 0xf4, 0xc7, 0x00, 0x1a, 0x2e, 0xff, 0xff, 0x0e, 0xce, 0x15, 0x00, 0x19, 0x2f, + 0x12, 0xf9, 0x25, 0x4a, 0xd3, 0xd6, 0xed, 0xa9, 0xe0, 0xd6, 0xff, 0x33, 0xfb, + 0x51, 0x0b, 0xe5, 0x4f, 0xda, 0x39, 0x42, 0xb4, 0x34, 0xee, 0xd2, 0x20, 0xf9, + 0x50, 0xd9, 0xff, 0xf2, 0x77, 0x12, 0xf6, 0x66, 0x1e, 0xe0, 0xb9, 0xfb, 0xb7, + 0x2a, 0xec, 0x03, 0x24, 0xdc, 0xed, 0xfa, 0xf4, 0xd2, 0xd6, 0xd6, 0xec, 0xfb, + 0xf9, 0x27, 0x54, 0xd9, 0x43, 0x0f, 0xfb, 0xfa, 0x01, 0xcf, 0xf1, 0x03, 0x0b, + 0x3b, 0xcd, 0x56, 0x14, 0x29, 0x00, 0xb6, 0x01, 0x48, 0xf9, 0xf8, 0x02, 0xf4, + 0x44, 0x7f, 0xf1, 0x1c, 0xeb, 0xac, 0x18, 0x14, 0xd0, 0x12, 0xef, 0x22, 0xf1, + 0x04, 0x09, 0xf4, 0xfa, 0xc2, 0x54, 0xdf, 0x31, 0xe1, 0x0a, 0xf3, 0xaf, 0x18, + 0x06, 0x36, 0xd8, 0x2d, 0x14, 0xbe, 0xe9, 0xe6, 0xe4, 0xfb, 0x0f, 0x2c, 0x18, + 0x01, 0x33, 0xf8, 0xeb, 0xed, 0xb8, 0xf0, 0x05, 0x05, 0xd7, 0xe3, 0xf5, 0xf6, + 0x09, 0x13, 0x0e, 0x02, 0xfb, 0xff, 0xe4, 0x08, 0x17, 0xf9, 0x1f, 0x13, 0xe6, + 0xf3, 0x7f, 0x0c, 0xae, 0xe5, 0x07, 0xf4, 0x27, 0x25, 0x45, 0x08, 0xc0, 0xa9, + 0x0f, 0x12, 0x2b, 0xe5, 0x6f, 0x26, 0x28, 0xe0, 0x1f, 0xee, 0x39, 0xeb, 0x32, + 0x0a, 0x12, 0x28, 0x16, 0x05, 0xe9, 0xe8, 0x16, 0xe9, 0x0a, 0xfc, 0x22, 0xe9, + 0x06, 0x00, 0x3d, 0x1a, 0x2b, 0x16, 0xaa, 0x0f, 0xfe, 0x01, 0x11, 0xda, 0x2b, + 0xea, 0xf3, 0xc7, 0x37, 0xea, 0xd7, 0xef, 0x2a, 0xd1, 0x26, 0x3b, 0xfa, 0xbe, + 0x04, 0xc3, 0xd5, 0xe6, 0x65, 0x4b, 0x0c, 0xfc, 0x1e, 0x32, 0x1c, 0x47, 0xe8, + 0x19, 0x05, 0xd9, 0x0e, 0xe7, 0xfc, 0xff, 0xb6, 0xe4, 0x1f, 0x15, 0x3a, 0x0d, + 0xbf, 0x07, 0xf1, 0x74, 0xef, 0x81, 0xe6, 0x38, 0x23, 0xe5, 0x24, 0xcc, 0x11, + 0x38, 0xec, 0x3d, 0xd1, 0x02, 0xdc, 0xd2, 0x0c, 0x14, 0x17, 0xff, 0xfc, 0xe7, + 0x13, 0xe1, 0x0a, 0xed, 0x28, 0x23, 0x14, 0xe5, 0x5d, 0xdd, 0x02, 0x46, 0xe0, + 0xe2, 0x2d, 0xf6, 0xfe, 0xc9, 0x0a, 0xc4, 0xe9, 0xba, 0xb2, 0x27, 0xc7, 0xfc, + 0x45, 0xc4, 0x92, 0xd0, 0xaf, 0x0e, 0xc3, 0x1a, 0xfd, 0xfa, 0x00, 0xc8, 0xfa, + 0xb0, 0xfb, 0x10, 0xd9, 0x23, 0x2a, 0xe2, 0x2c, 0x50, 0xf9, 0x2a, 0xe1, 0xf9, + 0x1a, 0xd0, 0xe5, 0xe2, 0xfe, 0xe9, 0x3e, 0x13, 0x28, 0xee, 0xe1, 0x29, 0xff, + 0xc2, 0x0d, 0xe7, 0x21, 0x47, 0xe5, 0x51, 0x0a, 0xdb, 0x8c, 0xef, 0x0e, 0x2c, + 0xf1, 0xeb, 0x15, 0x0e, 0xf2, 0x0f, 0xfa, 0xdd, 0xaf, 0x23, 0x33, 0xf0, 0x10, + 0x3d, 0x16, 0x0b, 0xff, 0x46, 0xdb, 0xe7, 0x12, 0xa4, 0x17, 0x1e, 0xbf, 0xdc, + 0x20, 0x12, 0xea, 0x1c, 0x19, 0x5d, 0x71, 0x32, 0xe2, 0xfe, 0x01, 0x35, 0x3b, + 0xf8, 0x8e, 0xfe, 0x3e, 0x4b, 0xd2, 0xfb, 0xcc, 0xd9, 0xc9, 0xf2, 0xf5, 0x04, + 0x30, 0x22, 0xe0, 0xf2, 0xc0, 0x05, 0x05, 0xd5, 0xee, 0x40, 0xa6, 0x91, 0x40, + 0x58, 0x20, 0xce, 0xa8, 0xd6, 0x61, 0xec, 0x1b, 0xec, 0xf3, 0x42, 0xb1, 0xfd, + 0xd9, 0xc3, 0x92, 0xd6, 0xcf, 0x1f, 0xfc, 0xd8, 0x59, 0x23, 0x0b, 0xc2, 0xf1, + 0x55, 0x05, 0xf0, 0x27, 0x32, 0x49, 0x62, 0x06, 0x26, 0x0d, 0xfc, 0xe0, 0xcf, + 0x1f, 0xcd, 0x81, 0xc1, 0x05, 0xeb, 0x15, 0xce, 0x54, 0x10, 0xd3, 0x57, 0xd4, + 0xf4, 0x29, 0x10, 0xe5, 0x2c, 0x3f, 0xf4, 0xa6, 0xf5, 0xed, 0x06, 0xf5, 0x0d, + 0xcc, 0xff, 0x2b, 0x0a, 0xe5, 0xe3, 0x0c, 0xe2, 0x28, 0x50, 0x22, 0x18, 0xe0, + 0x0b, 0xbf, 0x0d, 0x0e, 0xec, 0xdf, 0xf9, 0x10, 0xf6, 0x1c, 0x0a, 0xf3, 0x17, + 0xe9, 0xd2, 0x3c, 0x1c, 0x16, 0x06, 0xe7, 0x38, 0xd0, 0xed, 0x05, 0x1c, 0xc5, + 0xf8, 0xec, 0x10, 0xf7, 0xc1, 0xda, 0x1b, 0xda, 0x0d, 0xf5, 0xe3, 0x15, 0xf8, + 0xea, 0xdb, 0xd4, 0x21, 0x07, 0x10, 0x19, 0x45, 0x66, 0xd1, 0x15, 0x09, 0x1f, + 0xec, 0x19, 0xd6, 0x18, 0x0a, 0xe3, 0xee, 0xf5, 0xf9, 0xfb, 0xdd, 0x01, 0xec, + 0x33, 0xfe, 0xed, 0xd3, 0xe0, 0xf0, 0x78, 0x07, 0xe9, 0xf8, 0xc9, 0x7f, 0x2d, + 0xbe, 0xf5, 0xf0, 0x10, 0x23, 0x20, 0x08, 0xea, 0xe9, 0xb3, 0xe7, 0x0d, 0xea, + 0x2f, 0xef, 0x1d, 0xfd, 0xff, 0x01, 0x0a, 0x1c, 0x09, 0xd7, 0x0f, 0xf9, 0x00, + 0xed, 0xd0, 0xf6, 0xd4, 0xdc, 0x1b, 0x0a, 0xe9, 0x38, 0x06, 0xed, 0x32, 0xf8, + 0xee, 0x15, 0xe1, 0x13, 0x1c, 0x13, 0x0b, 0xbb, 0x21, 0x05, 0x0b, 0xcb, 0xfe, + 0xf3, 0xdb, 0xf7, 0xf5, 0xd7, 0x25, 0xfb, 0xd1, 0x07, 0x00, 0xa8, 0x12, 0x1f, + 0x0b, 0xd3, 0x41, 0x17, 0xe7, 0xfe, 0xea, 0x14, 0xfc, 0xf3, 0x45, 0xf8, 0xcd, + 0x09, 0x5b, 0xc9, 0xdb, 0x9e, 0xfd, 0x2c, 0x10, 0x04, 0x27, 0x4c, 0x08, 0x0a, + 0xb6, 0xe8, 0xc1, 0xda, 0x03, 0xaa, 0x7f, 0xfc, 0xde, 0xc1, 0x2d, 0xd9, 0x13, + 0xe6, 0x18, 0x05, 0xe8, 0xee, 0xfc, 0x4c, 0xcf, 0xe4, 0x1d, 0xcd, 0xbd, 0xaf, + 0x04, 0xda, 0xf5, 0xcc, 0xfa, 0x1e, 0xea, 0xdf, 0xb7, 0x03, 0x43, 0xfb, 0xf7, + 0x42, 0x53, 0xac, 0x09, 0x02, 0x41, 0x42, 0x04, 0x05, 0x26, 0x82, 0x98, 0xe7, + 0x2e, 0x28, 0x16, 0x01, 0x43, 0xe0, 0xd4, 0x34, 0xf2, 0xd9, 0x20, 0x60, 0x00, + 0x15, 0x1f, 0x27, 0xa9, 0x33, 0xcb, 0x08, 0x19, 0xde, 0xaf, 0x21, 0x24, 0x06, + 0xec, 0xfc, 0x05, 0x1b, 0xcf, 0xe4, 0x3d, 0x22, 0xec, 0xfa, 0xd6, 0x0b, 0xf6, + 0x15, 0xf8, 0xf4, 0x05, 0xec, 0xe9, 0x32, 0xe3, 0x19, 0x30, 0x29, 0xf8, 0x15, + 0xf4, 0xeb, 0xae, 0x4d, 0x15, 0x32, 0xf8, 0xf9, 0xe5, 0x19, 0x08, 0x2f, 0xe1, + 0x31, 0xf9, 0x17, 0xbf, 0xee, 0x11, 0x14, 0xb6, 0x08, 0x08, 0xf2, 0xd4, 0x17, + 0xfb, 0x2e, 0x7f, 0x09, 0xea, 0xdf, 0xf9, 0xff, 0x0e, 0xef, 0xbc, 0xe3, 0xc4, + 0x37, 0xf9, 0xcf, 0xca, 0x03, 0xcf, 0x06, 0x2c, 0xc0, 0x16, 0xd6, 0xc9, 0x0e, + 0xe5, 0x3c, 0x02, 0x5e, 0x02, 0x19, 0x33, 0x1c, 0x02, 0xf0, 0xf0, 0xf4, 0x03, + 0x0a, 0x6b, 0x1f, 0xf9, 0xfa, 0x06, 0xe6, 0x11, 0x10, 0x0d, 0xde, 0x22, 0x10, + 0xb5, 0x26, 0xf7, 0xfa, 0xfd, 0x16, 0x7b, 0xc1, 0xf8, 0x1c, 0x10, 0x0e, 0xf4, + 0xfb, 0xf8, 0x0b, 0xfa, 0xf9, 0x0a, 0x45, 0xcb, 0xff, 0x14, 0x42, 0xf6, 0xec, + 0xdb, 0x54, 0x09, 0x1b, 0x35, 0xd1, 0x62, 0xdf, 0xdd, 0xb4, 0x2a, 0x0b, 0x41, + 0x19, 0x2c, 0xde, 0xf1, 0xf6, 0xd6, 0x5f, 0xc0, 0xd8, 0x49, 0xeb, 0xe6, 0x2e, + 0x0b, 0xff, 0x57, 0x26, 0x3e, 0x0f, 0xfd, 0x21, 0xe0, 0x1e, 0xc9, 0x93, 0x7f, + 0x18, 0xfd, 0xe8, 0x1c, 0x23, 0x1f, 0x51, 0x17, 0xc5, 0xf1, 0x16, 0x03, 0x24, + 0xf6, 0xfa, 0x1d, 0xf1, 0xea, 0xf7, 0x38, 0x00, 0xfc, 0xc0, 0xe7, 0xfb, 0x10, + 0x11, 0xe2, 0x01, 0xe5, 0xb7, 0xfe, 0x23, 0xc7, 0x0f, 0x35, 0x0f, 0x63, 0x05, + 0x31, 0x04, 0x0d, 0xd9, 0x06, 0xdc, 0x16, 0x09, 0x36, 0x11, 0x01, 0x00, 0x3d, + 0x15, 0x11, 0xdf, 0xef, 0xd1, 0xf1, 0xf5, 0x04, 0x28, 0xd4, 0x14, 0xe5, 0x0d, + 0xd7, 0x14, 0x47, 0xfb, 0xf8, 0xd4, 0xf7, 0x39, 0x05, 0x14, 0x26, 0x19, 0x1d, + 0xff, 0x09, 0x0e, 0x02, 0xfd, 0xf9, 0xc3, 0x6f, 0xcf, 0xf7, 0x50, 0x00, 0x3d, + 0x1e, 0xed, 0x11, 0xeb, 0x31, 0x03, 0x1e, 0xf8, 0xc3, 0xe9, 0x37, 0xa6, 0x2a, + 0x81, 0xfd, 0x11, 0x1e, 0xa5, 0xbd, 0xe6, 0x06, 0xe2, 0xb9, 0x0f, 0x24, 0xf2, + 0x13, 0xca, 0xb1, 0xc8, 0x17, 0xa2, 0xc3, 0xe1, 0x30, 0xe6, 0x1c, 0x13, 0x14, + 0xf8, 0x1e, 0x25, 0x1f, 0xd6, 0x3c, 0x02, 0x04, 0x44, 0xea, 0x22, 0x22, 0xd2, + 0xee, 0xe8, 0xfa, 0x56, 0x4f, 0x6b, 0xfb, 0xf3, 0x09, 0x9a, 0xdb, 0x23, 0x02, + 0xcb, 0xc3, 0x1d, 0xd4, 0x1c, 0x02, 0xfa, 0x0a, 0xff, 0x13, 0xe8, 0x29, 0x04, + 0x1c, 0x48, 0xe8, 0x35, 0x18, 0x28, 0xfa, 0x16, 0xed, 0xeb, 0x05, 0xa0, 0xca, + 0x11, 0x4a, 0xe1, 0x25, 0xd9, 0x04, 0x10, 0x00, 0x15, 0x3c, 0x1e, 0x14, 0xc0, + 0x3a, 0x15, 0x3e, 0x1c, 0xf4, 0x0e, 0x26, 0xbe, 0x23, 0xff, 0x07, 0x24, 0xd6, + 0xee, 0xf1, 0xdf, 0x2c, 0x07, 0xe0, 0xcd, 0xee, 0x0e, 0xec, 0x02, 0xdf, 0x28, + 0xff, 0xc2, 0x20, 0x2b, 0xcc, 0x1e, 0xdd, 0xfe, 0xf3, 0x4e, 0x07, 0x1b, 0x1a, + 0xea, 0x44, 0x16, 0xc7, 0xff, 0x3c, 0xb6, 0xf4, 0xef, 0x58, 0xe0, 0xdc, 0x36, + 0x15, 0xcb, 0xfd, 0x63, 0x08, 0x04, 0x68, 0xd9, 0x94, 0xb1, 0xee, 0x49, 0xf6, + 0xb5, 0xf1, 0x28, 0xfc, 0x37, 0x84, 0x07, 0x35, 0xdd, 0x14, 0x23, 0x06, 0xff, + 0x30, 0x22, 0x48, 0xb8, 0x41, 0x0f, 0x15, 0x18, 0xef, 0xbe, 0xa2, 0xa5, 0x7d, + 0xec, 0xb9, 0xf5, 0xdd, 0x72, 0xfc, 0x06, 0x01, 0x1b, 0xda, 0xc3, 0xdb, 0x15, + 0x0b, 0x04, 0xd1, 0x05, 0xe9, 0xe2, 0xd5, 0x4a, 0xe9, 0x56, 0x47, 0x25, 0xd3, + 0x7b, 0x15, 0xf5, 0xf2, 0x32, 0x07, 0xe9, 0x7f, 0x57, 0xd5, 0x29, 0xf7, 0x45, + 0x1a, 0x17, 0x00, 0x14, 0xae, 0xd3, 0x0c, 0x19, 0x10, 0x3d, 0xdf, 0xf7, 0x15, + 0xe2, 0x0f, 0xf5, 0x02, 0xe4, 0xb3, 0xf1, 0xe4, 0xb1, 0xd7, 0x2c, 0x09, 0x38, + 0x01, 0x15, 0xfc, 0xcb, 0x06, 0x08, 0x08, 0xee, 0x1b, 0xd9, 0xb7, 0x10, 0xfc, + 0x4f, 0xc0, 0xe1, 0x1a, 0x5f, 0xad, 0x52, 0x42, 0xe8, 0xdf, 0xd8, 0xcc, 0x7f, + 0x5a, 0x3e, 0x2e, 0x14, 0x3d, 0xfd, 0x38, 0xd1, 0xd9, 0x13, 0xfe, 0x03, 0xf8, + 0x4c, 0xea, 0x31, 0x1b, 0xef, 0x16, 0x3b, 0xfc, 0xc0, 0xcc, 0x67, 0xff, 0xde, + 0x1d, 0x41, 0x52, 0xd3, 0x26, 0x10, 0x0a, 0x46, 0x08, 0x34, 0x46, 0xf1, 0x4a, + 0x07, 0x06, 0xd8, 0xdb, 0x3d, 0xf4, 0xc8, 0x65, 0xbb, 0xee, 0xe1, 0x18, 0xe3, + 0xf3, 0x11, 0x4e, 0x33, 0x4e, 0x07, 0xfc, 0xbd, 0x0c, 0x28, 0xbd, 0xfb, 0xe2, + 0xe4, 0xc4, 0x01, 0x24, 0x0a, 0xec, 0xc7, 0x09, 0xab, 0x41, 0x06, 0x0b, 0x57, + 0xed, 0x20, 0xad, 0x70, 0xab, 0x47, 0xf1, 0xb7, 0xf8, 0xab, 0x47, 0x19, 0x37, + 0xdf, 0x01, 0x21, 0x01, 0x2e, 0x2f, 0xdb, 0x1c, 0x1d, 0xce, 0xd1, 0x19, 0x21, + 0xd2, 0xfc, 0x5c, 0x52, 0xee, 0x1f, 0xfe, 0x3e, 0x1f, 0x23, 0xd2, 0xf2, 0x03, + 0x0e, 0xcc, 0xfa, 0x16, 0x06, 0x0b, 0x07, 0x0e, 0x06, 0x08, 0x16, 0xdc, 0x17, + 0x01, 0xc6, 0x01, 0x2a, 0xb5, 0xfe, 0x25, 0xe9, 0x7f, 0xe9, 0xee, 0xde, 0xad, + 0x16, 0x0d, 0x04, 0xbd, 0xf2, 0x24, 0x1d, 0x11, 0xfe, 0xb8, 0xfa, 0xd0, 0xf2, + 0xdd, 0x20, 0xe2, 0x12, 0x12, 0x0f, 0x31, 0x2d, 0xc3, 0xd3, 0x0d, 0x23, 0x24, + 0xcb, 0x19, 0x07, 0x20, 0x21, 0xdf, 0x00, 0x01, 0x3f, 0x26, 0x1e, 0x03, 0x10, + 0xff, 0x3a, 0xf0, 0xb4, 0x32, 0x11, 0xe0, 0x01, 0x07, 0xfe, 0xde, 0xeb, 0xff, + 0xd0, 0x07, 0x0f, 0xea, 0x3a, 0x02, 0xf0, 0x22, 0x1c, 0xf8, 0x0a, 0x10, 0xea, + 0xf5, 0x3b, 0xed, 0x0a, 0x24, 0xfd, 0x01, 0xd1, 0xf5, 0x07, 0xfd, 0x16, 0xa7, + 0x21, 0xd1, 0xef, 0x0d, 0x19, 0x13, 0xd6, 0x21, 0x5e, 0x10, 0xe3, 0xed, 0x07, + 0x38, 0xcf, 0x43, 0xd8, 0x0c, 0x0a, 0x31, 0xdb, 0x52, 0xc0, 0xf9, 0xcc, 0xfc, + 0xe5, 0xcc, 0xd6, 0x06, 0xfb, 0xad, 0x24, 0x2e, 0xdc, 0x9b, 0xfb, 0x35, 0xf4, + 0xf1, 0xe6, 0x10, 0xbe, 0xe4, 0x13, 0xef, 0x95, 0xc5, 0x45, 0xdb, 0x1e, 0x5a, + 0x24, 0xf5, 0x0c, 0xfa, 0xfa, 0xdf, 0x3b, 0xfe, 0x41, 0x35, 0x00, 0xd7, 0xe8, + 0xf0, 0xf1, 0xae, 0xc8, 0xe7, 0x5c, 0x7a, 0xa8, 0x0f, 0x34, 0x57, 0x29, 0xe6, + 0x2a, 0x23, 0x47, 0x25, 0x04, 0x24, 0xc9, 0x7f, 0xee, 0x29, 0xfb, 0xcd, 0x3d, + 0x2a, 0x32, 0x2b, 0xed, 0x2f, 0xe2, 0x12, 0x30, 0x23, 0xda, 0x15, 0x13, 0xed, + 0x60, 0x2e, 0xdf, 0x0d, 0xef, 0xa9, 0x08, 0xd1, 0xe4, 0x37, 0xc1, 0xfa, 0x06, + 0x41, 0x3f, 0xe2, 0x1b, 0x59, 0xdb, 0xa1, 0x20, 0xae, 0xf2, 0xdc, 0xa3, 0xd6, + 0x0f, 0xfa, 0xfb, 0xe7, 0x33, 0xff, 0xf3, 0x56, 0x01, 0x2a, 0xd8, 0x48, 0x93, + 0xc1, 0xc7, 0x00, 0xe7, 0x37, 0x06, 0x00, 0xf3, 0xa3, 0x50, 0xc0, 0xeb, 0x23, + 0xc3, 0x1f, 0xc6, 0xf9, 0xfd, 0xb8, 0xf3, 0xe3, 0xc7, 0xdc, 0xe3, 0xea, 0xdb, + 0xd4, 0xcd, 0xb2, 0x06, 0xd5, 0x22, 0xd5, 0x28, 0xee, 0x2a, 0x7f, 0x3f, 0xdb, + 0xf1, 0xea, 0xf2, 0x2a, 0xb3, 0x10, 0x1a, 0x19, 0x4d, 0xe5, 0xe5, 0xd9, 0xb9, + 0x9e, 0x12, 0xe6, 0x3e, 0xd4, 0x1c, 0xf9, 0xd2, 0xed, 0x32, 0x2e, 0x3e, 0xdc, + 0x17, 0xd5, 0xd1, 0x08, 0x02, 0x12, 0x2a, 0xeb, 0xec, 0x0c, 0x08, 0x1f, 0x1e, + 0x03, 0xd0, 0x23, 0x17, 0x9c, 0x09, 0x1d, 0xf1, 0xd7, 0x05, 0x27, 0x1e, 0x04, + 0xd9, 0xf9, 0xde, 0xe7, 0x3a, 0x37, 0xc8, 0x09, 0x50, 0x14, 0x0a, 0x05, 0x17, + 0x09, 0xb3, 0xcc, 0x20, 0x1b, 0x26, 0x11, 0x5d, 0x15, 0xf0, 0xff, 0x0d, 0x05, + 0xc7, 0xde, 0xe5, 0x09, 0xde, 0x27, 0x23, 0x0a, 0xf3, 0xb3, 0xff, 0x00, 0x42, + 0xd0, 0xe6, 0x0a, 0xee, 0xe2, 0x42, 0xc7, 0xd7, 0x37, 0x4d, 0xca, 0x03, 0x0d, + 0x12, 0xcf, 0x0f, 0xb7, 0x15, 0xf4, 0xbf, 0xea, 0x3a, 0xf3, 0x19, 0xf0, 0x28, + 0xe7, 0x0e, 0x04, 0xd4, 0xe0, 0x05, 0x02, 0xd6, 0xf9, 0x36, 0xfc, 0xe4, 0xf4, + 0x09, 0x1d, 0xbf, 0xcb, 0x06, 0xe0, 0xca, 0x00, 0xee, 0xd6, 0xea, 0xf4, 0xce, + 0x18, 0xfb, 0x32, 0x1d, 0x02, 0xf5, 0xe3, 0xe6, 0x16, 0x41, 0xe5, 0x4f, 0x38, + 0x05, 0xe4, 0xda, 0xf8, 0x81, 0x01, 0xaf, 0xfc, 0x06, 0xb4, 0x2c, 0x0c, 0x1a, + 0xda, 0xfc, 0xaf, 0x26, 0xec, 0xe6, 0xed, 0x16, 0x02, 0xf9, 0x29, 0x13, 0xda, + 0xbb, 0xe1, 0x20, 0xcf, 0x0a, 0xfc, 0x01, 0x36, 0xcd, 0x47, 0x00, 0xdb, 0xff, + 0x08, 0xf4, 0xfc, 0x2a, 0x52, 0xfb, 0xf1, 0x03, 0xd3, 0xee, 0xd3, 0xdf, 0xe0, + 0x07, 0x2e, 0xe7, 0xda, 0xfd, 0x0a, 0x27, 0xcf, 0x09, 0xf0, 0xbd, 0xec, 0xf8, + 0xea, 0x03, 0x22, 0x3f, 0xda, 0x07, 0xe8, 0x28, 0xd7, 0x12, 0x0c, 0x03, 0x11, + 0xf3, 0x2e, 0xd2, 0xe3, 0xe1, 0x4d, 0xe6, 0x06, 0xe8, 0xde, 0xed, 0xc1, 0x36, + 0xe6, 0x17, 0xd6, 0xf4, 0xd0, 0x04, 0xfe, 0xfb, 0xea, 0x02, 0x45, 0xc8, 0xb5, + 0x54, 0xfe, 0xde, 0xf6, 0xf9, 0xec, 0x0d, 0xd7, 0xf5, 0xc4, 0x81, 0xc8, 0x29, + 0x11, 0xc4, 0x1a, 0x1c, 0x19, 0x32, 0xd1, 0xbe, 0x0f, 0xfc, 0xf6, 0x50, 0xe5, + 0x4a, 0x31, 0x03, 0x06, 0xee, 0x1d, 0x54, 0x0c, 0xf6, 0x3a, 0xc2, 0xe7, 0x25, + 0x2d, 0x18, 0xf9, 0xfe, 0x07, 0xe5, 0x0d, 0xc0, 0xac, 0x4b, 0xe7, 0xa0, 0xad, + 0x34, 0x50, 0x45, 0xdc, 0xe9, 0xe3, 0x18, 0xcc, 0xb9, 0xfe, 0xc2, 0xf2, 0xf8, + 0xe7, 0x07, 0x4c, 0xea, 0x53, 0xfe, 0x14, 0xed, 0x08, 0xd2, 0x5d, 0x31, 0x0f, + 0x15, 0x05, 0x01, 0xc7, 0x03, 0x0b, 0xc6, 0xff, 0xde, 0xf5, 0x9c, 0xc5, 0x19, + 0x41, 0xf9, 0xf0, 0x0d, 0xdd, 0xdf, 0x24, 0x0c, 0x90, 0x17, 0x4e, 0xd9, 0xce, + 0xd9, 0xc8, 0xd7, 0x0e, 0x09, 0x3c, 0x0b, 0xb7, 0xea, 0xf2, 0x3f, 0xc4, 0xa8, + 0xd5, 0x02, 0xdf, 0xda, 0xe5, 0xf9, 0xfe, 0x19, 0x0c, 0xd2, 0x07, 0x0d, 0xb7, + 0x4b, 0x1e, 0x10, 0x08, 0xf5, 0x45, 0xf3, 0x04, 0x3c, 0xdc, 0xe9, 0xde, 0xec, + 0xc1, 0x05, 0x1a, 0xd4, 0xff, 0x10, 0xbf, 0x3f, 0xf7, 0x2b, 0x17, 0xea, 0xe6, + 0xdc, 0x16, 0x24, 0x0d, 0x07, 0x0e, 0x3c, 0xf4, 0x21, 0xcc, 0x09, 0xcc, 0x42, + 0x26, 0xc8, 0xcc, 0xfd, 0x19, 0xef, 0xef, 0x07, 0xf6, 0xfe, 0x0e, 0x2f, 0x31, + 0x43, 0xfe, 0x29, 0xc1, 0xcf, 0x35, 0xc1, 0x10, 0xff, 0xce, 0x22, 0x07, 0x0d, + 0x13, 0xee, 0x7f, 0x13, 0x00, 0x02, 0xef, 0x06, 0xf0, 0xde, 0x1a, 0x1c, 0xe7, + 0xfa, 0xcd, 0x17, 0x23, 0xc3, 0xba, 0xfe, 0xba, 0xea, 0x21, 0x09, 0x20, 0x00, + 0x22, 0xf7, 0x15, 0x46, 0xbd, 0xce, 0xc2, 0xfb, 0x12, 0xf2, 0xf0, 0x52, 0xd3, + 0x0f, 0x45, 0xde, 0xe9, 0xe8, 0x1f, 0x0b, 0x02, 0x2c, 0xe1, 0xea, 0x54, 0x03, + 0x0f, 0x0d, 0xd7, 0xf3, 0x13, 0x36, 0xfc, 0xd2, 0xc2, 0xe6, 0xed, 0xa1, 0x81, + 0xdd, 0x22, 0xd0, 0x31, 0xa8, 0xd2, 0xcb, 0x39, 0x10, 0xb7, 0xea, 0x99, 0xb6, + 0xde, 0xe7, 0x1c, 0x28, 0xf7, 0x07, 0x27, 0xe2, 0xf3, 0x60, 0xe9, 0x11, 0x22, + 0xfa, 0x0f, 0xe5, 0xd8, 0xe4, 0x19, 0xeb, 0x04, 0xcd, 0x0c, 0x8e, 0x63, 0x07, + 0xf0, 0xe4, 0xc6, 0xda, 0x3e, 0x31, 0xe0, 0x30, 0xcf, 0xe2, 0x04, 0xec, 0x69, + 0x4b, 0xa9, 0x0d, 0xc2, 0xf3, 0xc9, 0x25, 0xec, 0xe4, 0x25, 0x18, 0x64, 0xf4, + 0x2c, 0xea, 0xe1, 0x18, 0x33, 0x07, 0xd9, 0x22, 0x08, 0x0c, 0x26, 0x03, 0x2c, + 0x0f, 0x15, 0x0f, 0x3b, 0xc2, 0xe2, 0xf6, 0x52, 0x12, 0xcd, 0xd3, 0xda, 0x1d, + 0x35, 0x41, 0xd9, 0x2d, 0xfe, 0xe4, 0x0b, 0x0d, 0xa8, 0x15, 0x03, 0xce, 0x14, + 0xbe, 0x2c, 0x81, 0xd7, 0xfa, 0x2e, 0xaa, 0x4f, 0xe0, 0xc9, 0x0f, 0x0f, 0xde, + 0x17, 0x2f, 0x37, 0x4b, 0xf7, 0xfc, 0x07, 0xe8, 0x0c, 0x06, 0x02, 0xeb, 0xbd, + 0xb5, 0x0c, 0x2d, 0xd3, 0xc4, 0xf0, 0xd8, 0xf4, 0xe0, 0xcf, 0x1c, 0xfc, 0x3e, + 0xc6, 0xf1, 0x43, 0x30, 0xca, 0x0e, 0x0d, 0xd2, 0xdb, 0xbe, 0x4e, 0xce, 0xfb, + 0xe1, 0xed, 0x0d, 0x71, 0xe5, 0xe7, 0x42, 0xb9, 0x0a, 0x42, 0x05, 0xef, 0x27, + 0xc9, 0xe1, 0x07, 0x24, 0xff, 0x2f, 0xe9, 0xf2, 0x0e, 0xfb, 0x2a, 0xba, 0x3e, + 0xe8, 0x1e, 0xcc, 0xfd, 0xe7, 0x0f, 0x29, 0x1c, 0xba, 0xda, 0xe0, 0xea, 0xea, + 0xd6, 0x24, 0xe2, 0x2f, 0xb6, 0x1d, 0x62, 0xe9, 0x6c, 0xea, 0x05, 0xd8, 0xd9, + 0x26, 0x12, 0x0a, 0x21, 0xd7, 0xf6, 0xe2, 0x0a, 0xee, 0x0a, 0xf7, 0x0d, 0x51, + 0xdb, 0x01, 0xcc, 0xee, 0x05, 0xf6, 0xf8, 0x2c, 0x1c, 0xea, 0xdf, 0x28, 0xc8, + 0xa6, 0xa5, 0x21, 0xf9, 0xa6, 0x49, 0x1c, 0xb8, 0x2f, 0x0a, 0x81, 0xd4, 0xeb, + 0xe3, 0x17, 0x02, 0xd4, 0x0d, 0x25, 0xb0, 0x00, 0x19, 0x56, 0x7f, 0xff, 0xf9, + 0xe4, 0x33, 0x2e, 0xf3, 0x1c, 0xe3, 0xfa, 0xf3, 0xf9, 0xed, 0xe6, 0xed, 0xfb, + 0x3b, 0x29, 0x21, 0xdf, 0x0f, 0xc8, 0x1b, 0x06, 0xd1, 0x01, 0x01, 0xbb, 0x0c, + 0x25, 0x55, 0x14, 0xe0, 0x35, 0xdb, 0xd8, 0x29, 0x09, 0xd8, 0x56, 0x08, 0xfa, + 0xdd, 0xfa, 0xeb, 0xf4, 0xe9, 0xe1, 0xab, 0x08, 0xf2, 0xfc, 0xd3, 0xf8, 0x0d, + 0xf0, 0xcf, 0xe4, 0xe3, 0xf8, 0xf4, 0xba, 0x22, 0x15, 0x00, 0xe6, 0xdf, 0xf9, + 0x1a, 0x55, 0xff, 0xef, 0x41, 0xc9, 0x79, 0x19, 0xcd, 0x29, 0xc1, 0x16, 0xf1, + 0x27, 0x23, 0xe5, 0xf8, 0xf2, 0x0b, 0x43, 0xfa, 0xe1, 0x10, 0xf9, 0xed, 0x0c, + 0x27, 0x06, 0xd9, 0xd9, 0x0c, 0xde, 0xf6, 0x24, 0x0e, 0xe7, 0x21, 0x0b, 0xe6, + 0xfe, 0x2f, 0xe9, 0x0e, 0xf9, 0x3f, 0xf7, 0x26, 0xdc, 0x21, 0xe9, 0xcc, 0xf7, + 0xda, 0xda, 0xec, 0x20, 0x21, 0xe3, 0xf0, 0x3c, 0x1e, 0xcb, 0xf7, 0xf6, 0x47, + 0x15, 0xa9, 0xb9, 0xd7, 0x1a, 0xea, 0xe0, 0xd7, 0xdc, 0x30, 0xe8, 0x22, 0x12, + 0x39, 0x0f, 0x1b, 0xff, 0xf6, 0x02, 0xc5, 0x3f, 0x27, 0xdf, 0xcd, 0xe0, 0x06, + 0x36, 0x00, 0xef, 0x0f, 0xe8, 0xe2, 0x2e, 0x18, 0x24, 0xe5, 0xc6, 0x0b, 0xdf, + 0xf6, 0x0d, 0xde, 0xd6, 0xc9, 0x3f, 0xf1, 0x26, 0x0d, 0x10, 0xf2, 0x06, 0xe9, + 0xd2, 0x10, 0xe1, 0x37, 0xd8, 0x26, 0x21, 0x03, 0x0b, 0x7f, 0xfc, 0xe6, 0x0e, + 0x20, 0x19, 0xf0, 0x0e, 0x07, 0x07, 0x1f, 0x0c, 0xcb, 0xdd, 0x03, 0xa2, 0xea, + 0x23, 0xd1, 0x21, 0x07, 0xf4, 0xd0, 0xfd, 0xff, 0x22, 0x23, 0x0c, 0x28, 0xe1, + 0x03, 0x75, 0x24, 0x41, 0xd3, 0xef, 0x34, 0xfc, 0x48, 0x2a, 0xd5, 0xd8, 0xe0, + 0xe4, 0xda, 0xdd, 0xf6, 0x27, 0xc7, 0x07, 0x13, 0x17, 0x08, 0x27, 0x22, 0x19, + 0xf5, 0xf9, 0x16, 0xf8, 0xe7, 0x20, 0xdf, 0x10, 0x18, 0xe1, 0xba, 0xc5, 0xf4, + 0xee, 0x3e, 0xe1, 0x0d, 0xd7, 0xfe, 0x17, 0x01, 0x48, 0x25, 0xd3, 0x0d, 0xd4, + 0x39, 0x07, 0x0d, 0xff, 0xf5, 0xf4, 0x37, 0xf3, 0x0f, 0x36, 0x10, 0xbc, 0xea, + 0xe5, 0x22, 0xed, 0x1a, 0x0f, 0x18, 0xfa, 0xdf, 0x30, 0x04, 0x11, 0xea, 0xba, + 0xb0, 0x7f, 0x35, 0xe2, 0xea, 0x20, 0xdc, 0x10, 0x0f, 0x01, 0xcc, 0xc6, 0x31, + 0xc3, 0x07, 0x28, 0x1d, 0xfd, 0xf0, 0x03, 0x13, 0x1b, 0xc1, 0xff, 0x3c, 0xe2, + 0x01, 0xcb, 0x25, 0x2b, 0xe0, 0xf7, 0x04, 0xcf, 0xea, 0x08, 0xfb, 0x0d, 0xf3, + 0x3a, 0xea, 0x11, 0x3b, 0xe5, 0x1d, 0x1b, 0xdd, 0x23, 0x0b, 0x11, 0xe8, 0x07, + 0x01, 0x1b, 0x87, 0xfc, 0x23, 0xd7, 0x10, 0xed, 0x31, 0x0e, 0x03, 0x01, 0x0c, + 0xfe, 0xcf, 0xeb, 0x13, 0xdc, 0x22, 0x2c, 0x09, 0xd4, 0x2c, 0x04, 0xff, 0xe3, + 0xec, 0x45, 0xfb, 0xab, 0xed, 0xfb, 0xf1, 0x06, 0xf0, 0x8e, 0x13, 0x1c, 0xb2, + 0xd6, 0x7f, 0x0d, 0x25, 0xc3, 0x07, 0x6c, 0xd3, 0x4d, 0xe4, 0xf7, 0xbf, 0x5d, + 0xfb, 0xd7, 0x14, 0xde, 0x18, 0x1c, 0xd6, 0x30, 0x45, 0xb3, 0xca, 0xde, 0x56, + 0xe9, 0x20, 0x21, 0xf0, 0xea, 0xeb, 0xe7, 0xf7, 0xf2, 0xc0, 0xe7, 0x15, 0xdf, + 0x48, 0x21, 0x1a, 0xf8, 0x2c, 0x2c, 0xf3, 0xd4, 0x3e, 0x00, 0x32, 0xdb, 0xdc, + 0xea, 0xd1, 0xf6, 0xe6, 0xed, 0xef, 0x0d, 0xde, 0x17, 0x5d, 0x20, 0x19, 0xa4, + 0x00, 0xf7, 0xa6, 0x04, 0xab, 0xf2, 0xe6, 0xf7, 0x59, 0xdc, 0x1e, 0x4e, 0x32, + 0x26, 0x38, 0x3a, 0xe8, 0xe7, 0x31, 0x3e, 0xfe, 0x36, 0x04, 0x31, 0x3a, 0xe4, + 0xd8, 0xea, 0xbf, 0x21, 0x20, 0xdb, 0x01, 0x69, 0x9d, 0x3f, 0xd1, 0x4f, 0xbe, + 0x07, 0xef, 0x20, 0xa6, 0x24, 0xf6, 0x04, 0xff, 0x07, 0x11, 0xd1, 0x0d, 0xe0, + 0xfa, 0x0c, 0xaf, 0xe7, 0x00, 0x02, 0x82, 0xe2, 0xd1, 0xf3, 0x22, 0xab, 0x00, + 0xae, 0xb6, 0x19, 0x09, 0xdc, 0xce, 0xf4, 0x40, 0x3e, 0x06, 0x02, 0xac, 0xc2, + 0x40, 0x13, 0x09, 0x1f, 0x1f, 0x54, 0xe3, 0xe3, 0x0c, 0xff, 0x0c, 0xf6, 0xb3, + 0x19, 0xd5, 0x00, 0x6a, 0xd8, 0x1e, 0xf5, 0x1b, 0xf0, 0x0d, 0xfe, 0xdf, 0x0c, + 0x20, 0x7f, 0x50, 0x41, 0x0a, 0xf8, 0xed, 0xe2, 0x1c, 0xe5, 0x0d, 0xed, 0xe4, + 0xbc, 0x11, 0x4e, 0xc4, 0xd9, 0x11, 0xfa, 0x16, 0xe4, 0x1a, 0x15, 0x45, 0x1c, + 0xdb, 0x06, 0x03, 0xc3, 0xcf, 0xf5, 0xfd, 0x7f, 0xf2, 0xfa, 0x03, 0x3a, 0xe4, + 0xd2, 0x23, 0x43, 0x37, 0x16, 0x20, 0x0b, 0x1e, 0xd3, 0x2b, 0xde, 0xce, 0xc9, + 0xe7, 0x2d, 0xe7, 0x18, 0xbb, 0x09, 0x0f, 0x18, 0x08, 0xd1, 0x3c, 0xff, 0x6c, + 0xc4, 0x17, 0xa7, 0xff, 0xb4, 0x58, 0x28, 0x00, 0xfe, 0xfc, 0xc5, 0xfa, 0x07, + 0x32, 0xb1, 0xe3, 0x0c, 0x31, 0xde, 0x4d, 0xc3, 0xf1, 0xf0, 0xe0, 0xe1, 0x21, + 0x1c, 0x02, 0x0e, 0x38, 0xe8, 0x09, 0x21, 0xf2, 0x36, 0x47, 0x06, 0xd6, 0x2d, + 0x18, 0xd2, 0x12, 0x0d, 0x35, 0x13, 0x2e, 0x05, 0xcb, 0x16, 0xfc, 0x05, 0xd7, + 0xff, 0xd3, 0xe9, 0xdd, 0x01, 0x11, 0x05, 0xff, 0x03, 0xbf, 0x10, 0x26, 0x1d, + 0x59, 0xd4, 0x03, 0xca, 0xea, 0xa5, 0x3a, 0x2b, 0x07, 0x09, 0x20, 0x08, 0xd9, + 0x0a, 0x25, 0x01, 0x00, 0x26, 0x1a, 0xf2, 0xfa, 0xea, 0x1d, 0xdc, 0xe1, 0xf0, + 0xc1, 0x26, 0x18, 0xf0, 0xe1, 0x14, 0xfd, 0xe4, 0x10, 0x35, 0x00, 0x48, 0xce, + 0xeb, 0xeb, 0xe6, 0x1f, 0xfd, 0xe2, 0xfa, 0x0b, 0xd8, 0xcd, 0x08, 0x2b, 0x14, + 0xda, 0x2c, 0xdb, 0xdd, 0x05, 0xe4, 0x40, 0xc2, 0x04, 0xf1, 0xe0, 0x2a, 0x39, + 0x20, 0xe3, 0xf2, 0x12, 0xe5, 0xf5, 0xf7, 0xc2, 0xd6, 0xb5, 0x23, 0x0f, 0x1a, + 0xef, 0x1b, 0x05, 0xf6, 0xe8, 0x07, 0xd3, 0x1b, 0x34, 0x92, 0x2c, 0xec, 0xa4, + 0x09, 0xd5, 0xcc, 0x07, 0x41, 0x06, 0x1d, 0x28, 0xd0, 0x0d, 0x65, 0x01, 0xfc, + 0xfd, 0x1b, 0x0f, 0x18, 0x81, 0x2c, 0x6a, 0xf6, 0xfb, 0x04, 0x63, 0xd7, 0x24, + 0xcd, 0xa0, 0xfc, 0xd4, 0x01, 0xdb, 0x20, 0x25, 0xc8, 0xf2, 0xea, 0xb8, 0x04, + 0xe3, 0xe7, 0x27, 0xce, 0x1e, 0x30, 0x08, 0xfe, 0x04, 0x09, 0xdf, 0x1a, 0x2b, + 0xe5, 0x01, 0xe6, 0x1d, 0x1f, 0xfd, 0x34, 0x1b, 0xdd, 0xf0, 0xb8, 0x5e, 0xe3, + 0xe7, 0xb6, 0xc8, 0xe8, 0x12, 0x14, 0xa4, 0x44, 0xf8, 0xf1, 0x2c, 0xb0, 0xf7, + 0x3e, 0x2b, 0xf7, 0xf7, 0xe9, 0x59, 0xc1, 0xda, 0xbe, 0xca, 0xb3, 0xf4, 0xdb, + 0xc8, 0x8b, 0xbb, 0xc1, 0x48, 0xe7, 0xab, 0xfd, 0x9d, 0x44, 0x34, 0xef, 0x1c, + 0x33, 0xdd, 0x2c, 0x0c, 0xdf, 0x62, 0xac, 0xe2, 0xe2, 0xc8, 0x39, 0x9f, 0x38, + 0x47, 0xf8, 0x17, 0x81, 0x26, 0x46, 0x9f, 0xd6, 0x51, 0xc6, 0x11, 0xed, 0x63, + 0xc1, 0xf3, 0xe8, 0x14, 0xf3, 0x14, 0x2e, 0x23, 0x1c, 0xec, 0x41, 0x65, 0xf3, + 0xff, 0xc5, 0x36, 0x20, 0x0c, 0xd9, 0x09, 0xe7, 0xfb, 0xfc, 0xe9, 0x39, 0x8f, + 0xe1, 0xbf, 0x40, 0x1c, 0x19, 0x07, 0x0c, 0x02, 0x0f, 0xff, 0x2f, 0xac, 0x30, + 0x45, 0x1d, 0x35, 0xb1, 0xd5, 0x0d, 0xc5, 0xe3, 0x2e, 0x01, 0x28, 0x14, 0x67, + 0x29, 0x10, 0x41, 0xee, 0x01, 0x56, 0xd0, 0xd6, 0x48, 0x1a, 0xd7, 0x1d, 0xe0, + 0x07, 0x0a, 0x16, 0xe5, 0x01, 0xf6, 0xe8, 0xee, 0xf4, 0x00, 0x20, 0x02, 0xf7, + 0x03, 0x07, 0xdb, 0x07, 0xc7, 0x2d, 0x1d, 0x03, 0xf9, 0x03, 0x09, 0xf5, 0xd7, + 0xf5, 0xd6, 0xed, 0x19, 0x21, 0xfa, 0xec, 0xe4, 0xef, 0xb0, 0xcf, 0x1c, 0xc4, + 0x09, 0x0d, 0xbb, 0x23, 0x26, 0x0f, 0x0d, 0xec, 0x2f, 0x0c, 0xf0, 0xc1, 0x14, + 0xbc, 0x13, 0x45, 0x17, 0xdc, 0xf9, 0xeb, 0x14, 0x05, 0xef, 0xfe, 0xd2, 0x45, + 0x03, 0x15, 0x09, 0xd8, 0xda, 0x29, 0xe6, 0x07, 0xef, 0x12, 0xe0, 0x01, 0x2f, + 0x7f, 0xec, 0xfd, 0xd1, 0x03, 0x2f, 0xeb, 0xff, 0xba, 0xe0, 0x08, 0x12, 0x0f, + 0x4f, 0x47, 0xed, 0xc4, 0xc4, 0xdc, 0x2f, 0x09, 0x2b, 0x08, 0x1e, 0xdd, 0x35, + 0xd8, 0x09, 0xfa, 0xe6, 0x1c, 0xd8, 0xff, 0xd0, 0x04, 0xda, 0x1a, 0x37, 0x1d, + 0x2a, 0xe6, 0xc6, 0xf7, 0x32, 0x41, 0x1d, 0xd5, 0x3a, 0xde, 0x43, 0x07, 0x3d, + 0xfb, 0x0b, 0xd4, 0x22, 0xc9, 0x2f, 0xe5, 0xd5, 0x0f, 0x24, 0x0b, 0xc8, 0xe8, + 0x1f, 0x1f, 0x57, 0x9e, 0x2f, 0x30, 0x88, 0xf9, 0x2d, 0xd7, 0xb3, 0x1c, 0x84, + 0x2c, 0xc3, 0x07, 0x32, 0x3a, 0xb6, 0xd6, 0xca, 0x13, 0x02, 0xcf, 0xe1, 0xaa, + 0xd0, 0xd9, 0xed, 0xc7, 0xfe, 0x09, 0x09, 0xd0, 0x1e, 0x6d, 0x56, 0x37, 0xef, + 0xd9, 0xed, 0x1a, 0xe7, 0xbe, 0x56, 0xf3, 0x0a, 0x48, 0xda, 0xf0, 0xd3, 0x2a, + 0xe6, 0x12, 0x7b, 0xe0, 0xbe, 0x25, 0x0f, 0x1e, 0xdb, 0x58, 0xed, 0xec, 0x12, + 0xc4, 0xf4, 0xc0, 0x29, 0xee, 0x11, 0xdc, 0xd2, 0x19, 0x37, 0x1e, 0xf1, 0x4d, + 0xdd, 0xf4, 0x88, 0xa3, 0x32, 0xd8, 0xab, 0xc1, 0x0e, 0x27, 0x6c, 0x20, 0x36, + 0x29, 0x06, 0x08, 0x31, 0x1d, 0x35, 0x7f, 0xfe, 0x24, 0x4b, 0x17, 0xcb, 0x19, + 0x03, 0x21, 0x05, 0x0c, 0x34, 0x60, 0x18, 0x02, 0xd4, 0xf6, 0x0e, 0xfe, 0xdd, + 0x4f, 0x1c, 0x83, 0xe8, 0xbe, 0xba, 0x48, 0x30, 0xfa, 0xf3, 0x0d, 0x13, 0x47, + 0x36, 0x13, 0x34, 0x1c, 0x3e, 0xb4, 0x4b, 0xa1, 0xb9, 0xf4, 0xf9, 0x0a, 0xe3, + 0x2b, 0x36, 0xa2, 0xce, 0x32, 0x29, 0x11, 0x10, 0x3a, 0xa0, 0x28, 0x6f, 0xca, + 0xfc, 0xf0, 0xb0, 0xdb, 0xe9, 0x10, 0xfb, 0xf4, 0xef, 0x53, 0xc2, 0xf6, 0x45, + 0x2d, 0x14, 0xf8, 0xdf, 0xce, 0x17, 0xa7, 0xf3, 0x12, 0x81, 0x38, 0xac, 0x10, + 0xd6, 0xf9, 0xef, 0x43, 0x0d, 0x0c, 0x1c, 0xea, 0x1d, 0x3f, 0x1f, 0xc2, 0xe2, + 0xf6, 0x00, 0x1a, 0xe9, 0x2a, 0x02, 0x1c, 0xec, 0xf5, 0x04, 0xd1, 0x18, 0x21, + 0x11, 0xe7, 0x32, 0xb1, 0x1d, 0x21, 0x1c, 0xf5, 0xdc, 0xf8, 0xe7, 0xe9, 0x38, + 0x5a, 0x08, 0xf1, 0x2d, 0xbb, 0x08, 0xe6, 0x08, 0x13, 0x2e, 0x07, 0x35, 0x34, + 0xff, 0x11, 0xfb, 0x09, 0xf3, 0x0d, 0x5b, 0xef, 0x37, 0x38, 0x0c, 0xe5, 0x2b, + 0xcd, 0x11, 0x4a, 0x03, 0xf5, 0xf6, 0x01, 0xfc, 0x22, 0xc2, 0x0a, 0xd7, 0xdb, + 0xee, 0xf9, 0xe8, 0x07, 0xfa, 0xdf, 0xf9, 0xe5, 0x36, 0x1a, 0x07, 0xd9, 0xe7, + 0xd4, 0xff, 0xde, 0x02, 0x60, 0xf8, 0xeb, 0xe8, 0xc7, 0x3d, 0xf3, 0xf8, 0x0c, + 0xc9, 0xe8, 0x28, 0x2e, 0x1e, 0x15, 0xf0, 0xec, 0x32, 0x06, 0x39, 0x4c, 0x0a, + 0x36, 0xc7, 0xd8, 0xeb, 0x52, 0xe2, 0xda, 0xaf, 0xfe, 0x23, 0x0b, 0x02, 0x43, + 0x19, 0xda, 0x09, 0xed, 0x05, 0x0f, 0x0d, 0x29, 0xeb, 0xd8, 0x40, 0x0e, 0xd5, + 0x30, 0xf8, 0x46, 0x0b, 0xfe, 0x1e, 0x03, 0xe5, 0xef, 0x38, 0xd5, 0x05, 0xbd, + 0x07, 0xb0, 0xe2, 0x4a, 0xc5, 0x06, 0xa3, 0xeb, 0x7f, 0x28, 0x02, 0xba, 0x2c, + 0x1b, 0xeb, 0xe8, 0xdd, 0xfa, 0xf8, 0x1a, 0x03, 0x69, 0xfe, 0x0b, 0xcb, 0x26, + 0xf5, 0xfb, 0x33, 0xb2, 0xd9, 0x18, 0xcc, 0xe6, 0x4d, 0xde, 0x11, 0x0f, 0x10, + 0x0d, 0x26, 0xa3, 0xfc, 0x10, 0x22, 0xd9, 0xdb, 0x11, 0xec, 0x06, 0x36, 0x42, + 0x14, 0x33, 0xe8, 0x1a, 0xe2, 0xcd, 0xeb, 0x1d, 0xbc, 0xcb, 0x37, 0xc3, 0xf7, + 0xbb, 0x1c, 0x0b, 0x0c, 0x05, 0xb7, 0xb4, 0x6c, 0xc0, 0x0f, 0xf3, 0xe7, 0xf2, + 0x05, 0xff, 0xde, 0xde, 0xc9, 0xe8, 0xd2, 0xdd, 0x1a, 0x18, 0x36, 0x25, 0x27, + 0x24, 0x08, 0x18, 0xed, 0x19, 0x05, 0xdc, 0x1f, 0x19, 0xed, 0x16, 0xe5, 0x3e, + 0x04, 0xef, 0x07, 0xfa, 0xf7, 0xcf, 0x0f, 0x04, 0x7f, 0xf9, 0x1a, 0x0d, 0x23, + 0xd7, 0x33, 0xdc, 0xdf, 0xd5, 0x06, 0x05, 0xe5, 0xb1, 0x48, 0xe9, 0xfa, 0x1a, + 0x1c, 0xbe, 0x51, 0x03, 0x15, 0xf0, 0xfe, 0xfd, 0xdf, 0xb0, 0xe5, 0x0b, 0xf8, + 0xfb, 0x44, 0xac, 0xf2, 0xe0, 0x5b, 0x07, 0x6f, 0xdb, 0xfd, 0x21, 0x06, 0x24, + 0xee, 0x42, 0xe1, 0x0f, 0xb2, 0xb8, 0xea, 0xb3, 0xf7, 0xf9, 0xf7, 0x2f, 0xd2, + 0xab, 0x0c, 0x0d, 0x09, 0x21, 0x9d, 0x59, 0xc7, 0x07, 0xdb, 0x15, 0xfd, 0x21, + 0xf2, 0x49, 0xc8, 0x12, 0xdb, 0x70, 0xdb, 0x09, 0x2f, 0x6e, 0xbe, 0xc7, 0xb1, + 0xf2, 0xfd, 0x1e, 0xef, 0x0a, 0xe8, 0xcb, 0xeb, 0x39, 0xf7, 0x06, 0x9d, 0x1b, + 0x3e, 0xb0, 0xe5, 0xed, 0xe5, 0xf7, 0x13, 0x01, 0x43, 0x7f, 0xcd, 0xfd, 0xf5, + 0x6a, 0x35, 0x08, 0xdd, 0xf8, 0xf5, 0x1b, 0xe6, 0xd9, 0xd5, 0xf5, 0xef, 0xdc, + 0x12, 0x61, 0x41, 0x4b, 0x09, 0x04, 0xcb, 0x03, 0xfd, 0xc2, 0xe0, 0x85, 0xea, + 0xba, 0xf7, 0xfd, 0x6b, 0xc0, 0x26, 0xc8, 0x0a, 0xce, 0xe2, 0xfe, 0xfe, 0xb2, + 0x59, 0x08, 0xc9, 0x31, 0x2d, 0xef, 0x57, 0x06, 0xe0, 0x48, 0x95, 0x73, 0x29, + 0x49, 0xea, 0x77, 0x31, 0x3b, 0x24, 0x55, 0x34, 0x2e, 0xc1, 0x23, 0x26, 0xe7, + 0x1d, 0x50, 0x1a, 0xb7, 0xe9, 0xbd, 0x49, 0x20, 0x29, 0xe3, 0x0f, 0x7b, 0x0f, + 0xed, 0x2c, 0x64, 0xa7, 0xda, 0xfa, 0xef, 0x21, 0xbf, 0x05, 0xff, 0x99, 0xe1, + 0x5c, 0xcc, 0xd8, 0xd6, 0xea, 0xc0, 0x34, 0x1f, 0xad, 0xe1, 0xe6, 0xc9, 0xdc, + 0xbb, 0x19, 0xec, 0x31, 0x11, 0x04, 0xd8, 0x50, 0xf1, 0xdf, 0x68, 0x06, 0xca, + 0x5d, 0x1d, 0x68, 0xd5, 0x2c, 0x2f, 0xcf, 0x91, 0xbc, 0xc4, 0x0f, 0xb4, 0x5c, + 0x68, 0xd0, 0x14, 0x46, 0x42, 0x85, 0x21, 0x12, 0xf5, 0x24, 0xf6, 0xda, 0x2b, + 0xd7, 0x69, 0xc7, 0xd9, 0x42, 0xe9, 0x1e, 0x9f, 0xfd, 0x4f, 0x05, 0x0f, 0xe8, + 0x0f, 0x4e, 0x21, 0xd2, 0xc7, 0x87, 0x6e, 0x64, 0x5d, 0x3e, 0x23, 0xd9, 0xc7, + 0x05, 0xda, 0x0f, 0xec, 0xfc, 0x88, 0xb5, 0x0c, 0xec, 0xe2, 0xb1, 0x09, 0xbf, + 0x21, 0x0f, 0xfc, 0x3d, 0xb6, 0xf9, 0x29, 0x05, 0x7f, 0x28, 0xe9, 0x03, 0xf7, + 0xf1, 0x0f, 0xfa, 0xcc, 0xec, 0x01, 0xda, 0xf1, 0xc1, 0xe0, 0x5d, 0x47, 0x05, + 0xfb, 0x16, 0xe7, 0x16, 0x20, 0x1d, 0xdd, 0xdd, 0x2b, 0x5a, 0x1b, 0x45, 0x67, + 0xfb, 0x00, 0xe7, 0xd9, 0x1b, 0xed, 0xe3, 0x17, 0x1d, 0x59, 0x1c, 0xd2, 0x56, + 0x7f, 0xeb, 0xfe, 0xcc, 0xe9, 0xfc, 0x1a, 0xcc, 0x37, 0x27, 0xec, 0x30, 0x16, + 0x41, 0xc1, 0x29, 0x8c, 0xe4, 0x01, 0x36, 0xe0, 0xfe, 0x16, 0x1b, 0x17, 0xb5, + 0xfb, 0xe6, 0x8b, 0xed, 0xf9, 0xe6, 0x11, 0xe5, 0x2a, 0xec, 0xd3, 0xf1, 0xdd, + 0x0f, 0xc9, 0x38, 0xc4, 0xdf, 0xc7, 0x0a, 0xcb, 0x12, 0x32, 0x59, 0x17, 0x4b, + 0x1f, 0xe6, 0x03, 0x1a, 0xda, 0xe6, 0x3d, 0x36, 0x11, 0x14, 0xc1, 0xa6, 0x2e, + 0xd2, 0xf8, 0x1e, 0x06, 0x37, 0x16, 0xca, 0xdd, 0x3a, 0x25, 0xee, 0x42, 0xb7, + 0xe3, 0xdf, 0xfd, 0xdf, 0x29, 0xed, 0xa3, 0x20, 0xc2, 0x37, 0x95, 0x57, 0xea, + 0x0c, 0x0e, 0x08, 0xf3, 0xf9, 0xf9, 0x9a, 0x1c, 0xb6, 0x04, 0xdd, 0x14, 0xea, + 0x06, 0x96, 0xeb, 0x60, 0x26, 0xc6, 0x7f, 0x01, 0xe2, 0xb4, 0x21, 0xb9, 0x38, + 0x41, 0x1d, 0x3b, 0x22, 0x6e, 0xe0, 0xc4, 0xa3, 0x1e, 0xd5, 0xf5, 0xa8, 0x46, + 0xb8, 0xf5, 0x1f, 0x20, 0xfa, 0x73, 0xe5, 0x9a, 0xcb, 0x68, 0x06, 0x79, 0x59, + 0xf9, 0x37, 0x2f, 0x0b, 0xa9, 0xbf, 0xb9, 0x3f, 0x0b, 0xca, 0xaa, 0x1f, 0x05, + 0x1e, 0x41, 0x05, 0x08, 0x0f, 0xfb, 0xc5, 0x32, 0xb4, 0xc8, 0xf4, 0x05, 0xf1, + 0x93, 0x0a, 0x4c, 0x46, 0xfe, 0xbd, 0x3a, 0xc2, 0xc3, 0x4e, 0xbe, 0xcb, 0xd7, + 0xa9, 0xc6, 0xe5, 0xed, 0x95, 0xdf, 0xfa, 0x32, 0xf2, 0xc6, 0xfd, 0x95, 0xe9, + 0x45, 0x0c, 0x13, 0x17, 0x01, 0xcf, 0x23, 0x23, 0xd8, 0xc9, 0x05, 0xac, 0x21, + 0xac, 0xc0, 0x2e, 0xec, 0xe7, 0x3c, 0xf9, 0xdc, 0xde, 0x0f, 0xe8, 0xf9, 0x27, + 0xbe, 0xd7, 0x06, 0xfe, 0xdb, 0xa6, 0xd4, 0xc1, 0x0e, 0x07, 0xd9, 0x2b, 0xe4, + 0x07, 0xff, 0xef, 0xe5, 0xdd, 0xb6, 0x4d, 0x81, 0x06, 0xeb, 0x48, 0xe3, 0xea, + 0xd0, 0xee, 0x5f, 0x3f, 0xb8, 0x21, 0xf1, 0xb7, 0x0b, 0x2c, 0x17, 0x07, 0xcd, + 0xe7, 0xfe, 0x34, 0x0b, 0xfd, 0xc8, 0x0e, 0x66, 0x1b, 0x4a, 0xfa, 0xb1, 0xfc, + 0xee, 0x5c, 0xd1, 0xd4, 0x1e, 0x12, 0xb0, 0xcb, 0x22, 0x15, 0x03, 0x02, 0xf3, + 0x0f, 0x91, 0x0a, 0x03, 0x2f, 0xbf, 0xd4, 0x0a, 0xc3, 0xef, 0xa3, 0x0b, 0xf9, + 0xf0, 0x46, 0x06, 0xcc, 0xfd, 0x04, 0x11, 0xec, 0xd6, 0x61, 0xee, 0xd3, 0x20, + 0x60, 0xe5, 0xff, 0xc7, 0xfc, 0xf4, 0x63, 0x29, 0xd8, 0x2f, 0xff, 0xe9, 0xfd, + 0x15, 0xff, 0x0c, 0x25, 0x1a, 0x36, 0x11, 0xd3, 0xc5, 0xf1, 0x47, 0xec, 0xf4, + 0xd8, 0x11, 0x41, 0xe5, 0xf2, 0xa8, 0xea, 0x1a, 0x0e, 0xf8, 0x2b, 0xf9, 0x1d, + 0xc6, 0x3f, 0x3b, 0xb6, 0xd5, 0x95, 0x05, 0x0e, 0xe2, 0xf2, 0xb1, 0x03, 0xf2, + 0x36, 0xb3, 0x3b, 0x24, 0x1a, 0x2c, 0xe2, 0x5c, 0x37, 0xe4, 0xcb, 0x01, 0x2d, + 0xe6, 0xee, 0xe9, 0x23, 0xe5, 0x08, 0xa6, 0xb4, 0xfe, 0x90, 0xdf, 0xf0, 0x36, + 0x21, 0xbd, 0xb6, 0x08, 0x07, 0x2d, 0xe7, 0x99, 0xff, 0x29, 0xe9, 0xd2, 0xe9, + 0xc5, 0x22, 0x18, 0x4b, 0x0a, 0x01, 0x26, 0x06, 0x20, 0xed, 0xde, 0xe5, 0x0d, + 0xfd, 0xf7, 0xb3, 0x0a, 0x12, 0x3e, 0xed, 0x00, 0x0d, 0xb6, 0x3f, 0xff, 0x1a, + 0x17, 0x1d, 0xee, 0x06, 0x01, 0x04, 0x68, 0xf2, 0xd7, 0xc4, 0xf1, 0x15, 0xe6, + 0x17, 0xf2, 0x0e, 0x2b, 0xd8, 0x39, 0xf5, 0xdf, 0x18, 0x44, 0x00, 0x23, 0xf8, + 0x35, 0x21, 0x7f, 0x86, 0x37, 0xdc, 0x13, 0xdd, 0xd1, 0x14, 0x0a, 0x25, 0x14, + 0x28, 0x19, 0xed, 0xd9, 0xfd, 0xcb, 0xe8, 0x36, 0xf6, 0x3a, 0x10, 0xda, 0xe5, + 0xc6, 0x4b, 0x94, 0x04, 0x32, 0xa1, 0x57, 0xbb, 0x14, 0x21, 0x36, 0x28, 0x0f, + 0x39, 0x93, 0xd0, 0xd7, 0xc8, 0x14, 0xdc, 0x34, 0xe9, 0x43, 0x24, 0xfe, 0xda, + 0xaf, 0x10, 0x19, 0xf5, 0x1a, 0xd9, 0xeb, 0x23, 0x05, 0xe4, 0x35, 0x0d, 0x30, + 0x13, 0xc7, 0xc1, 0x19, 0xc3, 0x32, 0x8a, 0x48, 0x2c, 0xad, 0x15, 0xf8, 0x09, + 0x52, 0x0e, 0xe2, 0x03, 0xea, 0x1b, 0xa4, 0xc4, 0xc4, 0x5d, 0xca, 0x17, 0x09, + 0xca, 0x1e, 0x33, 0xab, 0x2b, 0xe6, 0x9d, 0xa9, 0xb9, 0x0e, 0x3b, 0xfa, 0xb3, + 0x21, 0xcd, 0x29, 0x52, 0x32, 0x63, 0x0c, 0xfa, 0xd0, 0x11, 0xfd, 0x81, 0x15, + 0x2b, 0xd0, 0xec, 0x09, 0xee, 0xb3, 0x3e, 0x06, 0x25, 0x30, 0xe2, 0x0e, 0x18, + 0x1c, 0xe6, 0x01, 0xf2, 0x66, 0xef, 0x33, 0xca, 0x41, 0xf1, 0x33, 0xdd, 0xfa, + 0xf3, 0x5c, 0xc8, 0x7f, 0xe3, 0x14, 0x31, 0x3f, 0xc9, 0xff, 0xf7, 0xfc, 0x20, + 0xfc, 0x0b, 0x10, 0x20, 0xf2, 0x36, 0xea, 0xd1, 0xf7, 0x2c, 0x1b, 0xfb, 0x25, + 0x0f, 0xfb, 0xdf, 0x17, 0x4e, 0xf6, 0x5e, 0xcb, 0xe3, 0xcc, 0xe1, 0xe2, 0xb3, + 0x0b, 0xf0, 0x36, 0xc0, 0xd9, 0x12, 0xe7, 0xfd, 0xfc, 0xf6, 0xdc, 0x1a, 0x0a, + 0xf1, 0x16, 0xfb, 0x1b, 0x0e, 0xfd, 0x3f, 0xf5, 0xe3, 0xb8, 0x23, 0xec, 0x46, + 0x1f, 0x28, 0xf1, 0xe1, 0xfb, 0x10, 0xfc, 0x09, 0xf4, 0x23, 0x0c, 0xf7, 0x17, + 0x2d, 0x12, 0xc3, 0xf9, 0xf7, 0xe6, 0x0d, 0x22, 0x03, 0x3b, 0xf9, 0x0b, 0xeb, + 0xb9, 0x13, 0x15, 0x2a, 0x0f, 0xc7, 0x1a, 0x1b, 0xee, 0x40, 0xe9, 0x01, 0x06, + 0xf9, 0x45, 0x06, 0xf4, 0x1c, 0x0e, 0x33, 0xcb, 0x56, 0x0f, 0x07, 0x15, 0xf5, + 0x46, 0x22, 0xe8, 0x08, 0xd5, 0x12, 0xe4, 0xe3, 0x13, 0x2b, 0x19, 0x1b, 0x73, + 0x14, 0xff, 0xd8, 0x57, 0xe7, 0x32, 0x1b, 0x02, 0x3c, 0xc9, 0x19, 0x00, 0xc7, + 0x19, 0xff, 0x12, 0xfc, 0x38, 0xfe, 0xf3, 0x11, 0xb2, 0x30, 0xe3, 0x07, 0x30, + 0xde, 0x42, 0x07, 0xd2, 0xc5, 0xe4, 0xf4, 0xd3, 0x0d, 0x9b, 0xcd, 0xcd, 0x1e, + 0x2b, 0xf9, 0xe4, 0x2d, 0x1c, 0x26, 0xe3, 0x40, 0xd2, 0x0f, 0xa4, 0x26, 0x0b, + 0xeb, 0x2a, 0xdf, 0xf2, 0xd7, 0x36, 0xd0, 0xad, 0xbe, 0x36, 0x0e, 0x21, 0xf7, + 0x1b, 0xc0, 0x1c, 0x27, 0x01, 0xe8, 0xdc, 0x18, 0x17, 0xe0, 0xf5, 0x1a, 0xf5, + 0x02, 0x02, 0xe9, 0x20, 0x07, 0x06, 0x81, 0xec, 0x42, 0x18, 0x1d, 0xd7, 0x47, + 0xaf, 0xca, 0xea, 0xfa, 0xbe, 0x35, 0x2a, 0xc7, 0x03, 0xd5, 0xf6, 0xe6, 0x20, + 0xb9, 0xb4, 0xc1, 0xec, 0x01, 0xc6, 0xc5, 0x00, 0xd0, 0x01, 0xf3, 0xd4, 0x66, + 0x08, 0x03, 0x1f, 0xeb, 0x00, 0x19, 0xb1, 0x38, 0xca, 0x0e, 0x3c, 0x81, 0xa9, + 0xe8, 0x35, 0xbb, 0x07, 0xf3, 0x3c, 0xea, 0x2a, 0x4a, 0xd3, 0x0a, 0xc7, 0xed, + 0xe4, 0x08, 0x1e, 0xd7, 0xe1, 0x42, 0x29, 0xcc, 0xda, 0x23, 0x01, 0xbb, 0x26, + 0xbf, 0x1c, 0xc3, 0xef, 0xdd, 0xd4, 0x38, 0xff, 0x0d, 0x47, 0x37, 0x44, 0xd2, + 0xe6, 0x8d, 0x47, 0x28, 0x2a, 0xf5, 0xd6, 0x4d, 0xac, 0xca, 0xe0, 0xb9, 0x2a, + 0x2d, 0x4f, 0xe1, 0x29, 0xf2, 0xe2, 0x14, 0xf4, 0xb8, 0x43, 0x2e, 0x24, 0xeb, + 0x40, 0x2f, 0xe4, 0x21, 0xf5, 0xd4, 0x21, 0x3f, 0xd4, 0x1c, 0x29, 0x25, 0x1a, + 0x93, 0x30, 0xab, 0x55, 0xf3, 0xc0, 0x14, 0xe0, 0x7f, 0xe7, 0x1a, 0xe6, 0xd5, + 0xeb, 0xe0, 0x36, 0x0d, 0x21, 0x2c, 0x58, 0xc7, 0xfa, 0x18, 0xe4, 0x4f, 0xb6, + 0x27, 0xd3, 0xe3, 0xd6, 0xff, 0xde, 0xd2, 0xe9, 0xdf, 0x00, 0x39, 0x02, 0xe7, + 0x84, 0xbb, 0x01, 0x1b, 0xd9, 0x04, 0xfb, 0x24, 0x05, 0x1d, 0xdb, 0x20, 0x1c, + 0xea, 0x3a, 0xf9, 0x1e, 0xf3, 0xe4, 0xea, 0x35, 0x04, 0x16, 0x28, 0x26, 0x3f, + 0x1e, 0xf4, 0xf2, 0x06, 0x28, 0xfa, 0x27, 0x01, 0x45, 0x02, 0xea, 0xec, 0x0e, + 0x20, 0x1f, 0xdb, 0xed, 0xdd, 0x10, 0x24, 0xfe, 0x5a, 0x0c, 0xda, 0xf2, 0xe8, + 0xda, 0xd0, 0xf9, 0xa5, 0x15, 0xdc, 0x0a, 0xe7, 0xd3, 0x3e, 0xd7, 0xfe, 0xf5, + 0x35, 0x28, 0xe5, 0xe3, 0x1b, 0xfe, 0xcd, 0x09, 0x1c, 0xcb, 0x4a, 0x0e, 0xdf, + 0xdf, 0x08, 0x18, 0x19, 0x39, 0x28, 0x2b, 0x12, 0x02, 0x14, 0x08, 0x4a, 0xcf, + 0xb3, 0xf7, 0xf8, 0x9c, 0x3e, 0x05, 0xaf, 0x6c, 0x12, 0x03, 0xeb, 0x7f, 0x31, + 0xad, 0x04, 0x4d, 0x00, 0x39, 0x31, 0x00, 0xe6, 0xe9, 0x38, 0xd8, 0xbb, 0x25, + 0xfe, 0xce, 0xd9, 0x3b, 0xe1, 0x0b, 0xfb, 0xe6, 0x06, 0xfa, 0x2d, 0x26, 0x3f, + 0xed, 0xac, 0xd7, 0x0b, 0xcc, 0xbc, 0xf9, 0xec, 0xc6, 0x1f, 0x22, 0xd9, 0x0d, + 0xef, 0xe5, 0xf6, 0x4d, 0x17, 0x7f, 0x2d, 0xbc, 0xec, 0x01, 0xf9, 0x6f, 0xb6, + 0xfb, 0x11, 0xd5, 0x0f, 0xe5, 0xdf, 0xe9, 0xd7, 0xe5, 0x23, 0xf8, 0xdf, 0x08, + 0xfd, 0xf3, 0xdf, 0x50, 0xd6, 0x2a, 0x01, 0xe8, 0x0b, 0xca, 0xfc, 0xd4, 0xe5, + 0xdf, 0xdd, 0xfc, 0x02, 0x42, 0xf0, 0xde, 0x25, 0xf3, 0xbb, 0x01, 0xd0, 0xdb, + 0xb6, 0x59, 0xeb, 0xe5, 0xdd, 0xdf, 0x20, 0xdb, 0xb4, 0xe1, 0xc3, 0xf0, 0x1f, + 0xcf, 0x01, 0xf3, 0x2a, 0x53, 0xf3, 0xb4, 0x47, 0xf1, 0x14, 0xd3, 0x33, 0xcb, + 0x16, 0xcb, 0xfc, 0x05, 0x01, 0xfb, 0xe8, 0xb1, 0x18, 0x20, 0xcf, 0xcd, 0xde, + 0x23, 0x8f, 0x32, 0x04, 0xfc, 0xba, 0x3a, 0xf5, 0x4d, 0xef, 0xd0, 0xdb, 0xd4, + 0xe0, 0xf8, 0x18, 0x28, 0x1e, 0xd7, 0x24, 0xe8, 0xd6, 0x0b, 0x5a, 0xcd, 0x40, + 0xfe, 0xb3, 0x16, 0xcb, 0xde, 0x4b, 0xe8, 0x25, 0xe0, 0x03, 0x2c, 0x20, 0x22, + 0xaa, 0xda, 0xc8, 0xf6, 0xf2, 0xe2, 0xe7, 0x17, 0xb2, 0x13, 0x6f, 0x30, 0xd3, + 0xe1, 0x2d, 0x0d, 0x00, 0x5b, 0xb1, 0x1c, 0x03, 0xfa, 0xa0, 0x0d, 0xfd, 0xb6, + 0xbf, 0xf9, 0x55, 0x3e, 0x22, 0xe3, 0x8f, 0xdb, 0x5e, 0xb3, 0xe5, 0x13, 0x14, + 0x2c, 0x33, 0xf3, 0xb6, 0xe1, 0x8a, 0x09, 0x16, 0x04, 0x15, 0x00, 0x62, 0xf8, + 0x1c, 0x36, 0x6f, 0xd6, 0xca, 0x02, 0xcd, 0x87, 0x4c, 0x85, 0x22, 0x2f, 0xbc, + 0x0a, 0x23, 0x41, 0x10, 0x08, 0x50, 0xd8, 0xa3, 0x13, 0x0d, 0xe1, 0x1f, 0x02, + 0xee, 0x26, 0xe3, 0xf4, 0x21, 0x0f, 0xe6, 0x13, 0x04, 0xff, 0x45, 0x4f, 0x89, + 0xc4, 0x7f, 0xfd, 0x29, 0xfc, 0x5b, 0xc2, 0x30, 0xe6, 0xb2, 0xee, 0xc0, 0x30, + 0xc8, 0xfb, 0xf3, 0xd8, 0xc3, 0x74, 0x0f, 0xf2, 0x41, 0x1a, 0xfe, 0x18, 0xd2, + 0xdd, 0xbc, 0xda, 0x3f, 0xfd, 0xc6, 0xb3, 0xdf, 0x0e, 0x27, 0xe1, 0xfb, 0x27, + 0x0e, 0x43, 0xaa, 0x66, 0x16, 0x29, 0x1a, 0x0c, 0x0c, 0xe7, 0x14, 0x10, 0x22, + 0x64, 0xa9, 0x16, 0xff, 0x11, 0x14, 0xdd, 0x2a, 0x42, 0x0f, 0xf0, 0x11, 0xbb, + 0xf3, 0xe9, 0x4e, 0xe2, 0x16, 0x92, 0xe0, 0xce, 0x11, 0xf2, 0xf4, 0xc6, 0xfe, + 0x7f, 0xfc, 0xbc, 0xf8, 0xd1, 0xe9, 0xe1, 0xe6, 0xe2, 0x13, 0x45, 0x1e, 0xe7, + 0xc8, 0xf8, 0x08, 0x31, 0xae, 0x13, 0xf4, 0xc2, 0xfc, 0xf5, 0x27, 0x0c, 0x2c, + 0x63, 0x3d, 0xda, 0x3b, 0xcc, 0xe4, 0xd1, 0xf8, 0x0c, 0xe0, 0xe2, 0xa5, 0xe5, + 0xf5, 0xe5, 0xff, 0x2f, 0xe9, 0x28, 0xca, 0x0e, 0xe7, 0x24, 0xb4, 0x3f, 0xdb, + 0x05, 0xc6, 0x25, 0xf2, 0x43, 0x05, 0xc5, 0xde, 0xd9, 0x26, 0xd5, 0xfe, 0xf4, + 0x1b, 0x3c, 0x25, 0x17, 0x23, 0xf2, 0xe2, 0x00, 0xe2, 0x20, 0xba, 0xdb, 0xff, + 0xdd, 0xc0, 0x11, 0xfe, 0x14, 0x03, 0x31, 0x00, 0x0c, 0x7f, 0xf8, 0x0d, 0x1c, + 0x05, 0xfe, 0x2b, 0xbe, 0x32, 0x04, 0xfd, 0xad, 0x38, 0xe9, 0x25, 0x19, 0xca, + 0xe5, 0x19, 0xe3, 0x69, 0xf3, 0x45, 0xfb, 0x42, 0x17, 0xe1, 0xe8, 0xf4, 0xf6, + 0xe2, 0xe5, 0xb1, 0xbf, 0x14, 0xd6, 0x2b, 0x3b, 0x04, 0xf1, 0xce, 0xfb, 0xbb, + 0xcd, 0xfb, 0xec, 0xfc, 0xd5, 0xf6, 0x11, 0x5e, 0xf0, 0x34, 0xc0, 0x1f, 0xbc, + 0xdb, 0x23, 0xe9, 0x21, 0x22, 0xe1, 0x04, 0x35, 0xdf, 0x0a, 0x26, 0xed, 0x05, + 0x60, 0xe9, 0x1f, 0xdf, 0x47, 0x67, 0x03, 0xf3, 0xf7, 0x4e, 0x27, 0xee, 0x01, + 0x01, 0xe6, 0x37, 0x0d, 0x0e, 0x1e, 0xfb, 0xf1, 0xfb, 0xcc, 0xb5, 0x44, 0xf8, + 0xb5, 0xee, 0x23, 0x31, 0x09, 0xce, 0xfb, 0xdc, 0x02, 0x17, 0x01, 0x6d, 0x26, + 0xe4, 0x31, 0x33, 0xc8, 0x27, 0xea, 0xfe, 0x05, 0xfc, 0x25, 0x08, 0x47, 0xe8, + 0x2b, 0xdc, 0xfb, 0xe8, 0xf3, 0x10, 0x31, 0x08, 0x23, 0x22, 0x03, 0xcb, 0x05, + 0xf9, 0x0f, 0x0e, 0x02, 0x09, 0xc9, 0x00, 0x36, 0x12, 0x05, 0xca, 0xec, 0xbd, + 0xd8, 0xf0, 0x25, 0x1c, 0x0f, 0x21, 0xdf, 0x25, 0xdc, 0x04, 0xd8, 0x1c, 0x01, + 0xde, 0xe8, 0x42, 0x04, 0xce, 0xd0, 0xe7, 0xc8, 0xb2, 0x53, 0x07, 0xfa, 0xd5, + 0x17, 0xe0, 0xe6, 0x02, 0xf6, 0xd2, 0xfc, 0x07, 0xdf, 0x05, 0x1f, 0xfd, 0xe3, + 0xdb, 0xc7, 0x22, 0x06, 0x0a, 0xfe, 0x30, 0x3a, 0x02, 0xed, 0x29, 0x2e, 0xfb, + 0x22, 0x0d, 0xee, 0x1b, 0xf6, 0xc9, 0xe9, 0xfa, 0xc0, 0xa6, 0xac, 0x09, 0xcc, + 0xd2, 0x50, 0xea, 0xdc, 0x76, 0xf6, 0x46, 0x32, 0xef, 0xd7, 0x24, 0x07, 0x7f, + 0x22, 0xda, 0xf9, 0x15, 0x0a, 0x4b, 0xc8, 0xc2, 0xc1, 0xca, 0x1c, 0x13, 0xf5, + 0x1d, 0x45, 0x25, 0x2e, 0xf0, 0xf2, 0x30, 0x07, 0x36, 0xce, 0x28, 0xeb, 0x33, + 0xde, 0xe5, 0x0b, 0x0e, 0xe6, 0xe4, 0xdc, 0x30, 0xfa, 0x8f, 0xdf, 0xd0, 0x58, + 0xcd, 0x5c, 0xf4, 0xee, 0x25, 0xdf, 0x1a, 0x36, 0x05, 0xcc, 0x24, 0xfb, 0xea, + 0xb2, 0x00, 0x53, 0x2a, 0xde, 0xa7, 0x20, 0xe2, 0x1a, 0x4b, 0xe0, 0x56, 0x24, + 0x06, 0xc8, 0x00, 0x09, 0x05, 0xf1, 0xc3, 0xa2, 0x8e, 0xfa, 0x6d, 0x12, 0xf4, + 0x22, 0xe4, 0xeb, 0x32, 0x6b, 0x19, 0x60, 0x0f, 0xa0, 0xf2, 0x88, 0xf3, 0x99, + 0xdf, 0x0f, 0xdc, 0xdc, 0x20, 0xe7, 0x41, 0x54, 0xdb, 0xf3, 0x27, 0xde, 0xcc, + 0x45, 0xe0, 0xe5, 0x21, 0xbe, 0xcc, 0x0c, 0xe8, 0x35, 0x3e, 0x3c, 0xd2, 0x76, + 0xe7, 0xc4, 0xed, 0x31, 0x00, 0x4c, 0x7f, 0xd8, 0xb2, 0xe6, 0x1b, 0x29, 0x0b, + 0x2c, 0x0b, 0x92, 0x43, 0x1b, 0x26, 0xfe, 0xce, 0x1b, 0x17, 0xb9, 0xff, 0xf7, + 0x17, 0x16, 0x2a, 0xc1, 0x06, 0xc6, 0xde, 0xd1, 0x07, 0x08, 0x18, 0x00, 0xf7, + 0xf9, 0x3a, 0x14, 0x02, 0x0f, 0x1d, 0xc8, 0xd4, 0x48, 0xf7, 0xf4, 0xe9, 0xf6, + 0x06, 0x45, 0xf0, 0xee, 0x00, 0x1f, 0x27, 0x46, 0x17, 0x41, 0x7f, 0xfd, 0xe5, + 0x06, 0x19, 0x05, 0xea, 0xf4, 0x11, 0x01, 0x15, 0xb8, 0xe0, 0xd6, 0xdd, 0xeb, + 0x30, 0xcc, 0xe8, 0x1b, 0x01, 0x0f, 0xf1, 0xd7, 0x20, 0xef, 0x04, 0x09, 0xbf, + 0x3a, 0x21, 0x01, 0xd2, 0xe3, 0x18, 0x15, 0xbe, 0x48, 0xf3, 0x1a, 0x10, 0xe0, + 0xe2, 0xed, 0x48, 0x2b, 0xe7, 0x53, 0x64, 0xd3, 0xe6, 0xdb, 0xef, 0xf5, 0xb8, + 0xfc, 0xc2, 0x4c, 0x23, 0x0d, 0x12, 0x1b, 0x04, 0x09, 0xca, 0x2c, 0xc3, 0x91, + 0xcb, 0x12, 0xd3, 0x3d, 0xc2, 0xfc, 0xf4, 0x1b, 0x04, 0x10, 0xbe, 0xf6, 0xcb, + 0xcd, 0xd9, 0x03, 0xe9, 0xf4, 0xec, 0x34, 0x05, 0xf0, 0x0d, 0x2b, 0x06, 0x2d, + 0xe4, 0xf5, 0xb9, 0xe4, 0xc1, 0x43, 0xd6, 0xd5, 0x14, 0x13, 0xe8, 0x05, 0x2f, + 0xf6, 0x2a, 0xed, 0xb8, 0xc9, 0x05, 0x0d, 0xec, 0x4d, 0x49, 0x42, 0xef, 0xce, + 0xcf, 0x27, 0x3d, 0x71, 0x02, 0x61, 0x24, 0xe5, 0xb6, 0xf5, 0xeb, 0xd3, 0x3a, + 0xca, 0x43, 0xd8, 0x47, 0x04, 0x2d, 0x1f, 0x3f, 0xc4, 0xba, 0xb1, 0xf3, 0x36, + 0xec, 0xeb, 0xdd, 0x04, 0x1c, 0xda, 0x50, 0x34, 0x95, 0x2a, 0x96, 0xf9, 0x62, + 0xd9, 0x08, 0xa2, 0xc1, 0x03, 0x9e, 0xa9, 0xe0, 0xf8, 0xd2, 0x1c, 0xf1, 0xbd, + 0x52, 0xa0, 0xc9, 0xdf, 0xfc, 0x11, 0xdf, 0x03, 0xfd, 0xd2, 0x81, 0x04, 0x03, + 0x0a, 0x8f, 0x3b, 0x0b, 0x93, 0xd5, 0x22, 0x06, 0x25, 0xc3, 0x19, 0x5c, 0xc9, + 0xed, 0x2e, 0x24, 0xda, 0xd2, 0xf5, 0xf6, 0xfc, 0xcb, 0x1a, 0xa3, 0xdd, 0x18, + 0xa0, 0x9a, 0xce, 0xec, 0x27, 0x04, 0xfc, 0xf9, 0x04, 0x50, 0x0b, 0xcd, 0x2f, + 0xc3, 0xba, 0xe0, 0x1d, 0x28, 0x37, 0x3c, 0x6f, 0xc8, 0x11, 0xb0, 0xf5, 0xb5, + 0x12, 0x6c, 0x13, 0x35, 0x92, 0x3b, 0x06, 0xff, 0x06, 0xc2, 0xa6, 0xc1, 0xaf, + 0xfa, 0xdf, 0xdc, 0x2f, 0x00, 0xc3, 0x0b, 0xf3, 0xf4, 0xd4, 0xb5, 0xd6, 0x22, + 0x1e, 0x1d, 0xe4, 0x30, 0xe9, 0xff, 0x44, 0xb9, 0xab, 0x10, 0xff, 0xee, 0xdf, + 0x07, 0x0a, 0xe8, 0xdf, 0x15, 0xbc, 0xe1, 0x03, 0xf3, 0x2d, 0x24, 0xf6, 0x51, + 0xfc, 0x81, 0xf5, 0xf9, 0xd7, 0x23, 0x2a, 0xa1, 0xd0, 0x2c, 0x11, 0xfd, 0xfc, + 0xf4, 0xfd, 0xd6, 0x30, 0x26, 0x06, 0xe8, 0xd3, 0xca, 0x79, 0x19, 0xef, 0x37, + 0xfc, 0x3d, 0xd2, 0xc5, 0xc8, 0x10, 0xc2, 0xec, 0x4c, 0xfc, 0x37, 0x11, 0xf8, + 0x12, 0x08, 0x13, 0xb6, 0x13, 0x01, 0xb4, 0x15, 0xf7, 0xca, 0x25, 0x29, 0xc6, + 0xab, 0xc0, 0xe1, 0x9f, 0x07, 0x27, 0x3c, 0xd1, 0x3f, 0xd9, 0xb1, 0xff, 0xce, + 0xee, 0xd3, 0x0b, 0x25, 0x02, 0x07, 0x27, 0x0f, 0xfb, 0x5e, 0xf7, 0x20, 0x27, + 0x10, 0xce, 0x3c, 0xf9, 0x2c, 0xc6, 0xb6, 0xa4, 0xd6, 0x9a, 0x30, 0xe4, 0x20, + 0xbe, 0x1b, 0xa2, 0xdb, 0x0f, 0x88, 0xf7, 0x0f, 0x03, 0x43, 0xc7, 0xfe, 0xd0, + 0xd2, 0x11, 0xce, 0x31, 0x25, 0xf9, 0x2f, 0xfc, 0xd4, 0xe2, 0xab, 0xc1, 0x6d, + 0x00, 0xda, 0xb0, 0xd9, 0xe2, 0x57, 0x4b, 0xe6, 0x05, 0xfe, 0xc0, 0x07, 0x40, + 0xf9, 0x22, 0x66, 0xf7, 0xe5, 0xf7, 0x11, 0x1b, 0x9a, 0xfe, 0x1e, 0x02, 0x2c, + 0x66, 0x1e, 0xf1, 0xd0, 0x2e, 0xe1, 0x11, 0x66, 0xcd, 0xe5, 0x2d, 0xf7, 0x12, + 0xe8, 0xf4, 0xd2, 0xd6, 0x30, 0x5a, 0x20, 0xc4, 0x26, 0x46, 0x27, 0x4c, 0x0f, + 0xd3, 0xe7, 0xee, 0x10, 0x1d, 0xfc, 0x81, 0xf9, 0xce, 0x06, 0xfd, 0x08, 0xf9, + 0xc3, 0xe4, 0xc4, 0x1b, 0x01, 0x01, 0x27, 0xba, 0xea, 0x3f, 0x7f, 0x74, 0x04, + 0xe9, 0xe7, 0xe5, 0x13, 0x2a, 0x34, 0x0b, 0xf4, 0x47, 0xf1, 0xd9, 0xdc, 0x10, + 0x3f, 0x40, 0x2a, 0xff, 0xbb, 0xd8, 0x4c, 0x08, 0x16, 0xbe, 0xff, 0xfd, 0xd2, + 0xfc, 0x0e, 0xd1, 0xbd, 0xfd, 0x3f, 0xd0, 0x08, 0xdc, 0xff, 0x14, 0x0a, 0xe7, + 0x1b, 0xdb, 0x08, 0xbf, 0xf2, 0x0e, 0xc8, 0xfa, 0x7c, 0x0f, 0x13, 0xc9, 0xe7, + 0xfd, 0x6a, 0x20, 0xe9, 0x59, 0x4a, 0xfa, 0x29, 0x30, 0x11, 0x37, 0x08, 0xfd, + 0xda, 0x32, 0x05, 0x04, 0x32, 0x2e, 0x10, 0x0e, 0xf5, 0xd3, 0xf8, 0xde, 0xf1, + 0xae, 0x25, 0x1d, 0x98, 0xe6, 0x43, 0x14, 0x11, 0xba, 0xd9, 0xb6, 0x06, 0xe3, + 0xf4, 0xfa, 0xce, 0xe2, 0xe5, 0xb8, 0xaa, 0x24, 0xfc, 0x1a, 0xea, 0x6b, 0xc0, + 0x8f, 0xf5, 0xb0, 0x2d, 0xe0, 0xed, 0x5b, 0x99, 0xbe, 0x12, 0xc2, 0xeb, 0xf1, + 0x6e, 0x5a, 0x20, 0x20, 0x1d, 0xdb, 0x25, 0xec, 0x03, 0x18, 0x13, 0xe2, 0xf8, + 0xfa, 0x0d, 0x08, 0x1a, 0x26, 0x09, 0x46, 0xd7, 0xdf, 0xe9, 0xaa, 0xe4, 0x08, + 0xf7, 0x36, 0xe3, 0xe6, 0xff, 0x05, 0xfe, 0x0f, 0xcf, 0xe3, 0xe1, 0xcd, 0xf7, + 0x1a, 0x00, 0x2f, 0x10, 0xd5, 0x1c, 0x02, 0xaf, 0x21, 0xea, 0xd3, 0x00, 0xef, + 0xe7, 0xf7, 0xe2, 0xed, 0xc9, 0xf3, 0x04, 0xdd, 0x21, 0x38, 0xda, 0x00, 0x20, + 0xed, 0x3c, 0xfe, 0x3f, 0x06, 0xd2, 0xdd, 0xce, 0x4e, 0xe3, 0x05, 0x0c, 0x05, + 0xdb, 0x29, 0x08, 0xf2, 0xda, 0x16, 0x23, 0xf2, 0x18, 0x28, 0xe8, 0x31, 0x0c, + 0x21, 0xd6, 0xe6, 0x04, 0xf3, 0x07, 0x25, 0xef, 0xf7, 0xfb, 0x03, 0x28, 0xf7, + 0xe0, 0xef, 0x05, 0xe5, 0xf6, 0x03, 0xf9, 0x04, 0xe6, 0xfd, 0xf8, 0xe9, 0x0e, + 0xe7, 0x03, 0x0b, 0xbe, 0x44, 0x21, 0xcd, 0x2a, 0x27, 0xdf, 0x14, 0x31, 0x7f, + 0x03, 0x63, 0x2a, 0x31, 0x17, 0x0b, 0xbc, 0xf6, 0x34, 0x25, 0x01, 0xd0, 0xd5, + 0x13, 0x0d, 0xf3, 0x1b, 0xf9, 0xfb, 0xbc, 0x18, 0x16, 0x07, 0xf4, 0x2c, 0x2c, + 0x01, 0xe5, 0xf2, 0x06, 0x34, 0x49, 0x27, 0xc8, 0x1d, 0xde, 0x57, 0xff, 0x12, + 0xbe, 0x10, 0x07, 0xe5, 0xf2, 0x1d, 0xc8, 0xce, 0x17, 0xb7, 0x03, 0xfb, 0x29, + 0xd2, 0xc5, 0xa4, 0x10, 0xd8, 0x24, 0xde, 0xfa, 0x0f, 0x27, 0xcb, 0xf8, 0x00, + 0x23, 0xfb, 0xfb, 0xe0, 0xdd, 0x2f, 0xeb, 0x47, 0x7f, 0x0e, 0x04, 0xc7, 0xfe, + 0x1e, 0xc9, 0xd4, 0x06, 0x01, 0x04, 0x3d, 0x2a, 0xf2, 0xf8, 0x36, 0xca, 0x16, + 0x28, 0x1a, 0x13, 0x0c, 0x3d, 0x04, 0x3a, 0x0e, 0x03, 0xd9, 0x3c, 0x2c, 0x14, + 0xd6, 0xe9, 0x05, 0xf2, 0xc5, 0x05, 0xe2, 0xd8, 0x1a, 0x0d, 0x04, 0xf5, 0x17, + 0xef, 0x01, 0x39, 0xff, 0x0e, 0x5b, 0xd1, 0xfd, 0xdc, 0x13, 0xf7, 0x0f, 0xd2, + 0x27, 0xde, 0x11, 0xe1, 0xdd, 0x10, 0x29, 0x46, 0xdb, 0x1c, 0xef, 0x02, 0x65, + 0xd8, 0xef, 0xd4, 0x34, 0xa8, 0xe7, 0x36, 0xf7, 0x11, 0x1d, 0xf5, 0x06, 0xdf, + 0xde, 0xeb, 0x07, 0x5c, 0x7f, 0x0d, 0xe6, 0x1f, 0xee, 0x05, 0x0f, 0x20, 0xd0, + 0x1d, 0x11, 0x29, 0x4f, 0x14, 0xfa, 0xfb, 0x9e, 0xa0, 0x4a, 0x08, 0xff, 0x15, + 0x20, 0x64, 0x02, 0xe5, 0xd7, 0x1b, 0xd2, 0x14, 0xe1, 0x2a, 0x50, 0x9b, 0x21, + 0x1d, 0x17, 0x1d, 0x28, 0x9f, 0xdb, 0x31, 0xd4, 0x14, 0xfc, 0xf8, 0xfc, 0xd7, + 0xd9, 0x46, 0x1c, 0x45, 0xdb, 0xe0, 0xa9, 0x2d, 0x0f, 0x43, 0x35, 0x46, 0x0d, + 0x2d, 0xdc, 0xef, 0xd6, 0x01, 0xb4, 0xf9, 0x22, 0x20, 0x35, 0x12, 0xf4, 0xf4, + 0x0f, 0xbb, 0x29, 0xe0, 0xfc, 0xc8, 0x08, 0xf6, 0x48, 0xaf, 0xf2, 0xbc, 0xe4, + 0x1f, 0xba, 0xc3, 0xb5, 0xdb, 0xde, 0xdc, 0xea, 0x02, 0x29, 0xf6, 0x0f, 0x12, + 0xfe, 0x3f, 0x36, 0xe3, 0xeb, 0xea, 0x0d, 0x1d, 0x1f, 0xdd, 0xf0, 0xfa, 0x15, + 0x0a, 0xfe, 0xd8, 0x06, 0x21, 0x0f, 0xf5, 0x24, 0xe0, 0xbb, 0xf7, 0x1a, 0xd8, + 0x02, 0x18, 0x20, 0xef, 0xe5, 0x02, 0x0e, 0x06, 0xf9, 0x12, 0xc4, 0x07, 0x44, + 0x07, 0xdb, 0xe0, 0xcf, 0x09, 0xce, 0x16, 0xec, 0xec, 0xe0, 0xf5, 0xec, 0x0b, + 0x1d, 0x08, 0x3a, 0xd8, 0x0b, 0xd8, 0xf9, 0x03, 0x03, 0xed, 0x0a, 0x19, 0xe9, + 0xe8, 0xe1, 0xd7, 0xe6, 0x0a, 0x40, 0xe1, 0xf2, 0x2b, 0x4c, 0xe6, 0x06, 0xf5, + 0x07, 0x1c, 0xda, 0xf5, 0x27, 0xde, 0xe3, 0xbb, 0xe3, 0xfe, 0xf4, 0xfb, 0x12, + 0xe6, 0x19, 0x7f, 0x4a, 0xf9, 0x1d, 0x2b, 0xf3, 0x19, 0x09, 0x00, 0x12, 0xd2, + 0x0d, 0x0d, 0xed, 0xf5, 0xe0, 0xed, 0x0e, 0x05, 0x06, 0x06, 0xe5, 0x19, 0x23, + 0x31, 0x33, 0x03, 0x20, 0xf5, 0xde, 0x06, 0xfa, 0xfc, 0xdd, 0xdf, 0xd6, 0x14, + 0x0e, 0xed, 0xff, 0x2c, 0x10, 0xef, 0x42, 0x25, 0xd0, 0x0f, 0x13, 0x05, 0xc4, + 0xf1, 0x28, 0xfd, 0x0f, 0xf2, 0xed, 0xd6, 0xc7, 0x1a, 0xf3, 0xfd, 0xdf, 0xd1, + 0xc9, 0xfd, 0x11, 0x08, 0x01, 0xee, 0x29, 0x3e, 0x05, 0xf8, 0xc0, 0x23, 0x27, + 0xce, 0x1c, 0x0b, 0x55, 0xe5, 0xa1, 0x09, 0x08, 0x70, 0xef, 0x22, 0xe6, 0x14, + 0x1f, 0xc7, 0x28, 0xd1, 0xf0, 0x10, 0xd2, 0x29, 0x16, 0x3a, 0xed, 0x0c, 0x29, + 0x08, 0xf6, 0x2a, 0xd9, 0xe8, 0xce, 0x04, 0xf3, 0xde, 0x20, 0x27, 0xfd, 0x0c, + 0x08, 0x01, 0xd9, 0xf0, 0xe1, 0x18, 0x4c, 0x0b, 0xf6, 0xd8, 0xfa, 0x36, 0x20, + 0x0c, 0xe1, 0xfe, 0x00, 0x4b, 0xfe, 0x7f, 0x2f, 0x0d, 0xf6, 0x25, 0xfb, 0x36, + 0x11, 0x12, 0x48, 0xf1, 0x1a, 0x26, 0xfb, 0x20, 0x08, 0x19, 0xe0, 0xd5, 0xf5, + 0x04, 0xd8, 0x06, 0x06, 0xe6, 0xac, 0x19, 0xed, 0xe5, 0x21, 0x23, 0xe1, 0xd5, + 0x29, 0x32, 0xf7, 0x0c, 0xc0, 0xf0, 0x40, 0x0c, 0xee, 0x25, 0x17, 0xec, 0xef, + 0x26, 0xe5, 0x16, 0xff, 0x19, 0x00, 0x34, 0x27, 0xfb, 0x05, 0x2f, 0x10, 0x7f, + 0x67, 0xf3, 0xf6, 0xcf, 0x42, 0x11, 0x10, 0xb4, 0x2d, 0xb9, 0xfb, 0x4d, 0xa4, + 0x12, 0x49, 0xef, 0xc5, 0x48, 0xf9, 0xe8, 0x18, 0xf9, 0x00, 0x23, 0xb2, 0xf6, + 0xcf, 0xd6, 0xfe, 0x1f, 0x22, 0x25, 0xf0, 0xb8, 0x34, 0x1c, 0x0f, 0xe2, 0x39, + 0xea, 0xf8, 0xd2, 0x37, 0xf7, 0xd1, 0x1d, 0xb0, 0x15, 0xed, 0x95, 0xfc, 0xd8, + 0x06, 0xdd, 0xb9, 0x07, 0x48, 0xd1, 0x2c, 0xdd, 0x27, 0x32, 0xe2, 0x31, 0x0a, + 0xdb, 0x0c, 0xde, 0xd0, 0x22, 0x1d, 0x17, 0x37, 0xd0, 0x04, 0x00, 0xe6, 0x11, + 0xae, 0x47, 0x19, 0xc6, 0xea, 0xc1, 0x0e, 0xdb, 0x18, 0xd4, 0xe1, 0x01, 0xec, + 0x53, 0x17, 0xd8, 0xdd, 0xff, 0xff, 0x1a, 0xa3, 0xdc, 0x08, 0xf2, 0xf0, 0xed, + 0x22, 0xee, 0xf2, 0xb4, 0xd7, 0x20, 0x09, 0x0a, 0xd1, 0xc6, 0xe5, 0xb3, 0xfc, + 0x15, 0x2c, 0xd0, 0x23, 0xc6, 0x10, 0xfa, 0x0e, 0xd8, 0xd4, 0x21, 0xf7, 0x7f, + 0x05, 0x06, 0xc1, 0x09, 0xbf, 0x16, 0xeb, 0x07, 0x0d, 0x04, 0xed, 0xd9, 0x2f, + 0x31, 0xec, 0xf8, 0x31, 0x24, 0x13, 0xdc, 0xf4, 0x26, 0x15, 0x0d, 0xf2, 0x1d, + 0x4f, 0x25, 0x09, 0x05, 0x39, 0xf2, 0xfb, 0xfa, 0xc8, 0x01, 0x15, 0xe8, 0x12, + 0x2a, 0xf2, 0x64, 0xbc, 0x0a, 0x2d, 0xe8, 0x37, 0x29, 0x01, 0xf0, 0x1e, 0x4e, + 0xc8, 0xe6, 0xec, 0xe9, 0x0d, 0xd1, 0x0b, 0xfd, 0x0a, 0xe8, 0x06, 0x31, 0x12, + 0x1b, 0x2d, 0xd0, 0x06, 0xf7, 0xf8, 0x18, 0xfc, 0xd9, 0xf8, 0xf9, 0x26, 0x23, + 0x0b, 0xf1, 0xf1, 0x1c, 0xbc, 0xbe, 0x31, 0xfa, 0xd7, 0x15, 0x10, 0xf1, 0xeb, + 0x09, 0xef, 0x0d, 0x2c, 0x08, 0xf1, 0xd8, 0xfa, 0xe4, 0xb4, 0x05, 0xac, 0xc6, + 0x95, 0xf0, 0x3a, 0x56, 0x06, 0x58, 0x12, 0x81, 0x13, 0xac, 0xf3, 0xb0, 0x14, + 0x26, 0xdb, 0x1d, 0x38, 0xf7, 0x1c, 0x5a, 0x02, 0x0a, 0x19, 0x0f, 0xf6, 0x30, + 0x14, 0x69, 0x42, 0xe0, 0xec, 0xcf, 0xae, 0xdd, 0xec, 0xd7, 0x3c, 0xc5, 0xd2, + 0x19, 0xdc, 0xc3, 0x09, 0x1d, 0xf2, 0x48, 0xee, 0x7c, 0xe9, 0x13, 0xe7, 0x58, + 0x43, 0x33, 0x13, 0x0e, 0xbc, 0xf3, 0xd5, 0xa0, 0x41, 0x50, 0x1f, 0xfe, 0xfd, + 0x28, 0xd7, 0xde, 0xc0, 0xe1, 0x12, 0x18, 0x40, 0xca, 0xf1, 0x10, 0xed, 0xcc, + 0xf9, 0xe2, 0x34, 0xa3, 0x0a, 0xe6, 0xfd, 0x14, 0xc6, 0x0a, 0xcd, 0x10, 0x25, + 0xf1, 0x0c, 0x03, 0xda, 0xfa, 0xa9, 0xd4, 0xfc, 0x2f, 0x34, 0x15, 0xfc, 0x13, + 0x0b, 0x05, 0xcf, 0xe2, 0xb2, 0xb0, 0xf6, 0x22, 0x00, 0xc5, 0x26, 0xeb, 0x09, + 0x02, 0x3c, 0x35, 0x0b, 0x6a, 0xe3, 0xe9, 0xf9, 0xca, 0x51, 0xe8, 0xf7, 0xe4, + 0x1b, 0x3c, 0x16, 0xcc, 0x02, 0xe1, 0x1c, 0x2c, 0x12, 0x2d, 0x1e, 0x58, 0x24, + 0xe6, 0xe7, 0xd6, 0xf5, 0x0d, 0xe7, 0xf9, 0xe7, 0xfd, 0xd5, 0xe1, 0x15, 0x0a, + 0x3e, 0x19, 0xc4, 0x11, 0x27, 0x9e, 0x12, 0x1c, 0xd6, 0xb6, 0x1a, 0xf2, 0xf1, + 0x45, 0x3f, 0x29, 0xbf, 0xc7, 0x21, 0xd3, 0xa1, 0x33, 0xf6, 0x06, 0x3c, 0x04, + 0x95, 0x10, 0x3d, 0x55, 0xee, 0x24, 0xf7, 0xe8, 0xf3, 0x17, 0xfa, 0x1b, 0xbc, + 0xf2, 0x0d, 0x30, 0x36, 0xff, 0x1e, 0xeb, 0xf8, 0x21, 0xff, 0x08, 0xc5, 0x26, + 0x00, 0xb0, 0xf3, 0xfe, 0xf6, 0xeb, 0xc5, 0xac, 0xcf, 0xf7, 0x3a, 0x42, 0x1c, + 0x27, 0x18, 0xe9, 0xf7, 0xd6, 0xf9, 0x2c, 0xec, 0x29, 0x25, 0xe3, 0xde, 0x3b, + 0xe1, 0xf3, 0x34, 0x05, 0x1e, 0x7f, 0x05, 0xf2, 0x1c, 0x12, 0xf1, 0x13, 0x16, + 0xbb, 0x32, 0x68, 0xb3, 0x2c, 0xda, 0xf6, 0x4a, 0xdf, 0x06, 0x3c, 0xca, 0xab, + 0x7c, 0xd8, 0xe0, 0x40, 0x18, 0xb8, 0xfc, 0xf2, 0x54, 0x38, 0xfe, 0x2f, 0x0a, + 0xbe, 0x41, 0xbf, 0xeb, 0x10, 0xab, 0x32, 0xbe, 0xe4, 0x00, 0x2c, 0x04, 0xf6, + 0x33, 0xcf, 0x07, 0x38, 0x18, 0x06, 0x88, 0xe1, 0x27, 0x70, 0x2f, 0x4d, 0x2a, + 0x15, 0xf1, 0x0a, 0xc6, 0xca, 0x35, 0xf4, 0xec, 0x45, 0xd2, 0x48, 0xb7, 0x25, + 0x48, 0xd4, 0x85, 0xd7, 0xe8, 0x22, 0x59, 0x13, 0xd7, 0x00, 0xc7, 0xf9, 0x12, + 0x3c, 0x51, 0x1c, 0x5b, 0xca, 0x06, 0x37, 0xed, 0xaf, 0xd7, 0x44, 0xd7, 0xb6, + 0x1e, 0xea, 0x01, 0x62, 0xe8, 0x2e, 0xd6, 0x16, 0x4d, 0x9c, 0x19, 0x48, 0xf3, + 0x18, 0xfa, 0x1d, 0x28, 0xe4, 0xb3, 0xcb, 0xed, 0x7f, 0x49, 0xfe, 0xce, 0xd8, + 0x12, 0x31, 0x25, 0x13, 0x04, 0x09, 0xac, 0x1c, 0x31, 0x0d, 0x4b, 0xfc, 0x12, + 0xc4, 0x0f, 0x60, 0xc1, 0x03, 0x04, 0x56, 0xc8, 0x40, 0x18, 0xfc, 0x14, 0xc2, + 0xeb, 0xc3, 0x98, 0xfb, 0x17, 0xf8, 0x22, 0xf8, 0xf8, 0x02, 0x27, 0x04, 0xc0, + 0x0b, 0x33, 0x4e, 0xf5, 0xef, 0x47, 0x02, 0xf7, 0xf2, 0xe1, 0x18, 0x36, 0x16, + 0x1e, 0x54, 0x3b, 0xfe, 0xd7, 0xec, 0xc1, 0x0d, 0x25, 0xd2, 0xad, 0xec, 0x2e, + 0x08, 0xfe, 0xec, 0x00, 0xd5, 0x36, 0x07, 0x39, 0x07, 0xe3, 0x04, 0xce, 0xeb, + 0x28, 0x23, 0x37, 0xee, 0x10, 0xf6, 0xf2, 0x12, 0xe8, 0x15, 0x00, 0x36, 0xd7, + 0x14, 0x10, 0x02, 0xff, 0xbc, 0xea, 0xcd, 0x1d, 0xf1, 0xf5, 0xe5, 0x37, 0xf9, + 0xf0, 0x0f, 0x32, 0x29, 0x11, 0x06, 0x06, 0x0a, 0xca, 0xea, 0x15, 0x4f, 0x16, + 0x4b, 0xff, 0xe0, 0xef, 0xe1, 0xfa, 0x32, 0xd9, 0xee, 0x7f, 0x06, 0x17, 0xe9, + 0xf0, 0xdc, 0x0b, 0xde, 0x5d, 0x0e, 0x35, 0x2c, 0x23, 0x29, 0x18, 0xe6, 0x23, + 0x1c, 0xe0, 0x2c, 0xf4, 0x06, 0xef, 0xec, 0x11, 0xdd, 0x07, 0xfc, 0x38, 0x35, + 0x40, 0x3d, 0xf1, 0xe4, 0xf1, 0x05, 0xfd, 0x18, 0x21, 0xd0, 0x05, 0x2c, 0xfc, + 0x26, 0xd6, 0xdb, 0xd5, 0x17, 0xeb, 0x43, 0x08, 0x2c, 0x21, 0xfb, 0xe4, 0xeb, + 0xea, 0xb9, 0xf4, 0xba, 0xe9, 0x4a, 0xf3, 0x30, 0x0c, 0xe8, 0x10, 0x5f, 0x1a, + 0x04, 0xec, 0x2b, 0xf5, 0x07, 0xcf, 0xfa, 0xd7, 0x81, 0x09, 0xf3, 0x06, 0xe7, + 0xfa, 0x13, 0xf3, 0x2a, 0xff, 0x33, 0xf3, 0x02, 0x1c, 0xe7, 0x05, 0x2d, 0x34, + 0xce, 0x10, 0x2c, 0xfc, 0x2b, 0x17, 0xfd, 0x3a, 0xdb, 0x22, 0xf1, 0x0a, 0xea, + 0xf2, 0x32, 0xf1, 0xec, 0xef, 0xf5, 0xf6, 0x1a, 0x14, 0x02, 0x07, 0x0b, 0x12, + 0xc1, 0x34, 0x38, 0xe0, 0x19, 0x4d, 0xf5, 0xfa, 0xec, 0xea, 0xd5, 0xf3, 0x54, + 0xe6, 0x1b, 0x08, 0x17, 0x14, 0xd6, 0x06, 0x00, 0xea, 0x1b, 0x2d, 0x27, 0xf4, + 0xf5, 0x07, 0xdd, 0x07, 0x1d, 0xe9, 0xde, 0x04, 0x61, 0xf2, 0xf3, 0xf4, 0xbe, + 0xba, 0xe6, 0x12, 0x14, 0x1e, 0x0c, 0xdf, 0xee, 0x0f, 0x0b, 0xd4, 0x14, 0x29, + 0xf1, 0xd8, 0x11, 0x39, 0xfd, 0x4c, 0x2b, 0xc6, 0x2e, 0xe1, 0xe9, 0x14, 0x27, + 0xc2, 0x04, 0xf3, 0xe0, 0xc5, 0x16, 0xec, 0xea, 0xfc, 0x1a, 0x18, 0xc7, 0xff, + 0xfc, 0xfa, 0xef, 0xd2, 0x01, 0x21, 0x33, 0x00, 0x7f, 0xe9, 0x2b, 0x08, 0x49, + 0xe0, 0x27, 0x2a, 0xf4, 0xdd, 0xfa, 0x21, 0x1c, 0x62, 0xd9, 0xf5, 0xcc, 0xf1, + 0x29, 0xe3, 0x8e, 0xe9, 0x19, 0x31, 0xb2, 0x67, 0xff, 0x37, 0x1a, 0xf6, 0x0c, + 0xe6, 0x0c, 0xcb, 0x08, 0x04, 0x10, 0xfb, 0xfc, 0x09, 0xde, 0x01, 0x03, 0xee, + 0xfd, 0xd1, 0x0d, 0x4a, 0xcd, 0xd0, 0x1d, 0x2d, 0xd4, 0x09, 0x2a, 0x30, 0x02, + 0x1a, 0x10, 0x0d, 0xf9, 0x4b, 0xdd, 0xf3, 0x24, 0x14, 0xe9, 0x01, 0xef, 0x17, + 0x4c, 0x1a, 0x26, 0xf3, 0x06, 0xee, 0xe3, 0x26, 0xd5, 0x36, 0x4a, 0x00, 0x08, + 0x02, 0xfb, 0xad, 0x24, 0x04, 0xf4, 0xdb, 0x0d, 0x2b, 0xe1, 0xf8, 0xe1, 0xc7, + 0x1a, 0xd0, 0x0d, 0xcb, 0x1b, 0xeb, 0x07, 0xdb, 0xe9, 0xd3, 0xdc, 0xb7, 0x41, + 0xf9, 0x0b, 0x1e, 0x17, 0xfc, 0x17, 0x09, 0xc7, 0x1b, 0x1d, 0xd9, 0xda, 0xf9, + 0x15, 0x04, 0xe7, 0xc8, 0x5a, 0xe3, 0xec, 0xfb, 0x4c, 0xe8, 0xf5, 0x49, 0x04, + 0xd5, 0x2c, 0xb8, 0x81, 0xde, 0xef, 0x0c, 0x30, 0xe8, 0xe7, 0x02, 0x1c, 0xfb, + 0x03, 0x20, 0x19, 0x07, 0xef, 0x07, 0xd7, 0x0a, 0x3c, 0xeb, 0x1d, 0x1b, 0x0c, + 0xf5, 0x05, 0xf0, 0x2d, 0x21, 0xce, 0xdf, 0xf9, 0xfb, 0x5a, 0x14, 0xf0, 0x2a, + 0x01, 0x4d, 0xf0, 0xeb, 0xf3, 0x14, 0xca, 0x0d, 0x34, 0xfb, 0x22, 0xfa, 0xe4, + 0x08, 0x16, 0xd3, 0xf1, 0x0b, 0x32, 0x18, 0x15, 0xf8, 0xe2, 0x33, 0xe1, 0x0c, + 0x1a, 0xfe, 0x03, 0xfb, 0xe6, 0xd4, 0x16, 0xe7, 0xca, 0x19, 0x1b, 0x16, 0x1a, + 0xfc, 0x1e, 0xfa, 0xcc, 0xc0, 0x44, 0xd8, 0x12, 0x30, 0xfe, 0xfd, 0xd6, 0xdb, + 0xfc, 0xf5, 0xf6, 0x2f, 0xfe, 0xcc, 0xd8, 0x12, 0x16, 0xcc, 0x81, 0x1c, 0x9a, + 0x29, 0x20, 0x13, 0x0e, 0x2e, 0x00, 0xfa, 0xfb, 0xca, 0x1d, 0x12, 0xfa, 0x15, + 0xdc, 0xe7, 0xd4, 0x03, 0xe5, 0xf7, 0x45, 0x00, 0xb9, 0x22, 0xf3, 0xde, 0x09, + 0x39, 0x0a, 0xdb, 0x00, 0xf8, 0xda, 0xe9, 0x0c, 0x15, 0x11, 0x12, 0xc7, 0x1a, + 0xff, 0x12, 0xdb, 0xfb, 0xef, 0xd7, 0xad, 0xfc, 0xff, 0xf6, 0xdc, 0x01, 0xf3, + 0x0b, 0x24, 0xf1, 0xed, 0xd1, 0xd6, 0x43, 0xd3, 0xff, 0xdd, 0x23, 0xf2, 0x28, + 0xc9, 0x03, 0x13, 0x0a, 0xee, 0xdf, 0x02, 0xcf, 0x02, 0xda, 0x0d, 0x29, 0xfc, + 0x21, 0xe5, 0xe8, 0x41, 0xef, 0xc7, 0xd3, 0xf4, 0xcd, 0x0a, 0x03, 0x06, 0xf9, + 0x26, 0xe3, 0x28, 0x20, 0x3f, 0xe2, 0xd6, 0x25, 0x44, 0x06, 0x45, 0x67, 0x21, + 0xdd, 0x21, 0x16, 0x0c, 0x2c, 0xf0, 0x1a, 0xcc, 0xc1, 0x10, 0x17, 0xf6, 0x05, + 0x2f, 0xe2, 0xe9, 0xec, 0xf3, 0xb5, 0xf2, 0x20, 0x0d, 0x11, 0xca, 0xa0, 0xff, + 0xe4, 0xe1, 0x97, 0x26, 0xc8, 0xc4, 0xe0, 0x43, 0x21, 0xd5, 0xc9, 0xca, 0x00, + 0x33, 0x32, 0x26, 0x0f, 0xef, 0xae, 0xda, 0x3c, 0xe0, 0x3f, 0x1c, 0xc3, 0x1a, + 0xf8, 0xd5, 0x11, 0x21, 0x58, 0xc8, 0x08, 0x2e, 0x23, 0x21, 0xd7, 0x08, 0xf2, + 0x31, 0xe6, 0xe7, 0xef, 0xe7, 0xca, 0xee, 0xdd, 0xe1, 0x47, 0x0b, 0x1a, 0x04, + 0xfe, 0xf2, 0xf2, 0xc9, 0xf5, 0x1d, 0xe7, 0x03, 0x11, 0x02, 0x32, 0x14, 0xf9, + 0xe2, 0xc5, 0xea, 0xdc, 0x0e, 0x45, 0xf2, 0x2d, 0xd6, 0xf2, 0x04, 0x2c, 0xe3, + 0x7f, 0x2f, 0x29, 0x59, 0xf8, 0x24, 0x52, 0x46, 0xef, 0x59, 0x73, 0x8d, 0x15, + 0xfc, 0xcc, 0x7e, 0xec, 0x0e, 0xc6, 0xe2, 0x4f, 0x15, 0x2c, 0xeb, 0x3c, 0xfa, + 0x04, 0x03, 0x5c, 0xda, 0x15, 0x35, 0xe4, 0xdf, 0xbc, 0x07, 0x1d, 0xfd, 0xfa, + 0x51, 0x3a, 0xf6, 0x54, 0x09, 0x91, 0x04, 0xe4, 0xec, 0x27, 0x15, 0xe1, 0xae, + 0x3c, 0x08, 0xf0, 0xea, 0x01, 0xe3, 0xf5, 0x7f, 0x35, 0x3f, 0x04, 0xc4, 0xdd, + 0x75, 0x28, 0x10, 0x50, 0xf4, 0xdc, 0xaa, 0x42, 0xd2, 0x9b, 0x09, 0xf4, 0x47, + 0x57, 0xf1, 0x3f, 0xe6, 0xdb, 0xec, 0x30, 0x72, 0x90, 0x96, 0x4f, 0xe6, 0xd2, + 0xf4, 0x01, 0x22, 0xea, 0x21, 0x0c, 0xa4, 0xfe, 0xf6, 0x3b, 0x6d, 0xc0, 0xf0, + 0xf5, 0xf0, 0xf5, 0x00, 0x5e, 0xce, 0x38, 0xb3, 0x27, 0x96, 0x97, 0xf9, 0xec, + 0xb8, 0xc5, 0x10, 0xf8, 0x12, 0xc5, 0xf3, 0x97, 0x20, 0xe7, 0xf3, 0xe5, 0xb4, + 0x23, 0xe4, 0x0d, 0x3f, 0xa8, 0x17, 0xcf, 0x0d, 0x4c, 0x18, 0xdd, 0x10, 0xf8, + 0x81, 0x28, 0x00, 0xeb, 0xd8, 0xfa, 0x36, 0x49, 0xfa, 0x2b, 0xdc, 0xea, 0x24, + 0xdb, 0xb8, 0x09, 0x20, 0x67, 0x12, 0x0f, 0x12, 0x07, 0x01, 0x9b, 0xba, 0x0d, + 0xc0, 0x6f, 0x07, 0xec, 0xc0, 0x20, 0x27, 0x11, 0xe1, 0x22, 0x1b, 0x0f, 0x2f, + 0xe9, 0x34, 0xc1, 0x11, 0xbf, 0xd6, 0xce, 0xad, 0x02, 0x1a, 0x2d, 0x1f, 0xe1, + 0x06, 0x2e, 0x06, 0xe6, 0x02, 0x34, 0xd2, 0xab, 0x1b, 0x71, 0x08, 0xec, 0xd7, + 0xd4, 0x2b, 0xe2, 0x26, 0xf7, 0x01, 0xfc, 0x30, 0x00, 0x57, 0xea, 0xc0, 0x0b, + 0x0a, 0xc0, 0x1b, 0xdd, 0x51, 0x1d, 0xda, 0x6d, 0xc6, 0x29, 0xfe, 0x04, 0x38, + 0xf4, 0x0f, 0x1b, 0xfc, 0xbb, 0x51, 0xd6, 0x2c, 0xf4, 0x2e, 0xa5, 0xc7, 0xe9, + 0x23, 0xec, 0x51, 0x12, 0xfb, 0xcc, 0x0c, 0xed, 0x75, 0xac, 0xe9, 0x31, 0x37, + 0x21, 0x5b, 0xcc, 0xcf, 0xde, 0xd0, 0x6c, 0x63, 0x0d, 0xc9, 0x2b, 0x4c, 0xe8, + 0xb8, 0x27, 0xe2, 0xa3, 0x47, 0xef, 0x1b, 0x26, 0xec, 0xc6, 0xfb, 0x64, 0x14, + 0xcd, 0xf3, 0x08, 0x30, 0x19, 0xbf, 0x28, 0xe4, 0x06, 0xd7, 0x84, 0xd4, 0x45, + 0x8b, 0x06, 0xe8, 0xab, 0xdc, 0x39, 0x17, 0x2c, 0xd2, 0xa8, 0x4e, 0x10, 0xd9, + 0xb0, 0xe4, 0x3d, 0xb7, 0x01, 0xce, 0xe3, 0xd5, 0x03, 0x10, 0xed, 0xe5, 0x32, + 0x4c, 0xbb, 0x1d, 0x2f, 0xbf, 0xba, 0x22, 0x08, 0x2e, 0x6f, 0x28, 0xa5, 0xbc, + 0xfa, 0xe8, 0xad, 0x8f, 0x92, 0xe3, 0xe4, 0x29, 0x14, 0xe4, 0xdd, 0xd2, 0xf6, + 0xd1, 0xd2, 0x29, 0x06, 0xc9, 0xe7, 0xe8, 0x0c, 0x6d, 0x5d, 0x27, 0x20, 0xc4, + 0xaf, 0x0b, 0xeb, 0x26, 0x91, 0xe2, 0xf2, 0x14, 0x0f, 0x81, 0x21, 0x04, 0xd0, + 0x17, 0x5e, 0x07, 0x1b, 0x62, 0x26, 0x15, 0x23, 0xfb, 0xe3, 0x2f, 0x00, 0xe3, + 0xe4, 0xcc, 0xf7, 0x9f, 0x18, 0x0b, 0x08, 0x2b, 0xf3, 0xd6, 0xfc, 0xf0, 0xf5, + 0xc2, 0xba, 0xd6, 0xa3, 0xb3, 0x0f, 0x10, 0xfb, 0x11, 0x26, 0xde, 0x18, 0x12, + 0xfa, 0x13, 0xfe, 0xb6, 0xf4, 0xf5, 0x30, 0xd1, 0xcf, 0xfc, 0xfe, 0x19, 0xd4, + 0xbf, 0x24, 0xc1, 0xc4, 0xdc, 0x2f, 0xec, 0x47, 0x49, 0xa8, 0xe4, 0x19, 0x11, + 0xfb, 0x9b, 0x1f, 0xe1, 0xd2, 0x38, 0xe3, 0xf1, 0x32, 0xff, 0xd8, 0x0a, 0x14, + 0xd6, 0x1c, 0xb9, 0x54, 0xdd, 0x37, 0xce, 0xd1, 0xfd, 0xde, 0x09, 0xbb, 0xe8, + 0x12, 0xfc, 0xf2, 0x10, 0x1e, 0xfb, 0xe5, 0xe5, 0x1d, 0xd0, 0x0a, 0xdb, 0x81, + 0xe3, 0xe8, 0xe8, 0x3f, 0xa6, 0xd9, 0xf3, 0xf3, 0x20, 0x2b, 0xf8, 0x3b, 0x19, + 0x40, 0xf1, 0xc0, 0x1d, 0x7d, 0x0e, 0x55, 0x46, 0xc1, 0xf5, 0xe3, 0x14, 0x62, + 0xf0, 0x13, 0xe5, 0x05, 0xe5, 0x0b, 0xca, 0x10, 0xf9, 0xe0, 0xde, 0x45, 0xd2, + 0x28, 0x2c, 0x3f, 0xef, 0x47, 0xd3, 0x1d, 0xd6, 0xe1, 0xb4, 0x10, 0xff, 0x29, + 0x36, 0x5d, 0xe8, 0x1b, 0x02, 0xe4, 0x0f, 0x04, 0x0e, 0xf5, 0xdd, 0x09, 0x28, + 0x0c, 0x1a, 0x26, 0x0e, 0xe6, 0xab, 0x81, 0xda, 0xdc, 0x38, 0xcc, 0xef, 0xc6, + 0xb3, 0x12, 0x01, 0xc4, 0xd1, 0xe8, 0xf2, 0xfa, 0x38, 0x0f, 0x53, 0x42, 0xfd, + 0xfc, 0xc4, 0xc0, 0x19, 0xd9, 0x30, 0x12, 0xf8, 0x23, 0xad, 0xfa, 0x19, 0xf0, + 0x27, 0x14, 0xf3, 0xb3, 0xdd, 0xf9, 0xbf, 0x42, 0xdc, 0x1f, 0x2c, 0x35, 0xe6, + 0xd3, 0xc3, 0xee, 0x0b, 0x03, 0xe1, 0x1b, 0xa0, 0x07, 0x09, 0x04, 0x8d, 0xfe, + 0x0c, 0xda, 0x34, 0xc0, 0xfa, 0x25, 0x0a, 0x2f, 0x1e, 0xe4, 0xf3, 0x13, 0xe6, + 0xf1, 0xbd, 0xd0, 0xf8, 0x43, 0xe2, 0x04, 0xce, 0x33, 0x00, 0x1e, 0xbb, 0xb3, + 0xe5, 0xf2, 0xe7, 0xed, 0xea, 0x11, 0x19, 0xfe, 0xfc, 0x19, 0x27, 0xd8, 0xc0, + 0x09, 0x75, 0xfe, 0xf2, 0xf9, 0xcf, 0xf8, 0xf7, 0x03, 0xeb, 0x10, 0x19, 0x3f, + 0x3d, 0xe0, 0x3d, 0x22, 0x23, 0xef, 0x02, 0x42, 0xe5, 0xd6, 0x32, 0xfa, 0x08, + 0x38, 0xe3, 0xca, 0x5f, 0x16, 0xc3, 0xc4, 0x02, 0x4c, 0xd5, 0x08, 0xa4, 0xfa, + 0x29, 0xf9, 0xe6, 0x37, 0xfe, 0xfd, 0xdc, 0xbd, 0x48, 0x12, 0x3c, 0xf4, 0xed, + 0x0d, 0x04, 0x04, 0xe5, 0x12, 0x04, 0xe2, 0xc7, 0x17, 0xdc, 0x40, 0x2c, 0xe5, + 0xe5, 0x31, 0x0b, 0xd3, 0xcb, 0x25, 0xf0, 0xfd, 0xff, 0x12, 0x25, 0xda, 0x18, + 0x1c, 0x0c, 0xf7, 0xd3, 0x11, 0x4c, 0xd9, 0x05, 0xd2, 0x08, 0xee, 0x3f, 0x19, + 0xd3, 0xf5, 0xd9, 0xe4, 0x12, 0x0f, 0x25, 0x30, 0xeb, 0x11, 0xe9, 0x22, 0x12, + 0x81, 0x04, 0xd9, 0xe1, 0x1a, 0x22, 0x07, 0x35, 0x01, 0xb6, 0xdf, 0xef, 0x06, + 0x15, 0xdb, 0x3e, 0x0b, 0xcb, 0x0b, 0x01, 0x3e, 0x0f, 0xbc, 0xe7, 0xf3, 0x2f, + 0x08, 0x27, 0x3a, 0xb6, 0xd3, 0x4d, 0xf8, 0xe7, 0x2e, 0x77, 0x8f, 0xed, 0x21, + 0x28, 0xe9, 0xfb, 0xee, 0x0c, 0xd1, 0xfc, 0xec, 0xfa, 0xfa, 0xf5, 0xf1, 0x1f, + 0x1d, 0xce, 0x04, 0x22, 0xb6, 0x1d, 0x1a, 0xd5, 0x72, 0x9f, 0x34, 0x01, 0xc9, + 0x03, 0x08, 0xe4, 0x39, 0xff, 0xcf, 0x13, 0xf6, 0xf0, 0x35, 0xfb, 0x79, 0xa8, + 0xe8, 0xf3, 0xee, 0x0b, 0xe9, 0x15, 0x3c, 0xf8, 0xc0, 0x44, 0xb8, 0xe2, 0xec, + 0x08, 0x24, 0xbf, 0x14, 0x2b, 0xe5, 0xe6, 0x22, 0xfc, 0x12, 0x0d, 0x1d, 0xc8, + 0xf6, 0x0c, 0xdb, 0x46, 0xfe, 0xc5, 0x8b, 0x83, 0x0e, 0x25, 0x32, 0x46, 0xbe, + 0x8f, 0xd8, 0xc4, 0xd9, 0xf6, 0x3d, 0x41, 0xed, 0x20, 0xf2, 0xd5, 0x42, 0xe0, + 0x2e, 0x20, 0xfe, 0x0e, 0x2e, 0xe3, 0xed, 0x0b, 0x7f, 0x24, 0x5b, 0xdf, 0xed, + 0xfa, 0xd1, 0xf2, 0x69, 0x29, 0x72, 0x13, 0xd0, 0x60, 0xee, 0xf9, 0xc3, 0x2d, + 0xff, 0xf8, 0xfd, 0x1b, 0xf8, 0x07, 0x3d, 0x1b, 0xbe, 0xe6, 0x02, 0xd6, 0x2f, + 0x29, 0x15, 0xe3, 0x26, 0xc7, 0xde, 0x30, 0x2f, 0xf6, 0xe9, 0x2a, 0x8f, 0x1c, + 0x0b, 0xd9, 0x1c, 0x01, 0xc8, 0x06, 0xf3, 0x31, 0xc0, 0x00, 0xf4, 0x33, 0x11, + 0xe9, 0x23, 0xdd, 0xf2, 0xfc, 0x11, 0xfb, 0x4f, 0x1f, 0xb7, 0x19, 0xc0, 0x19, + 0xf4, 0x22, 0x26, 0x0a, 0x1e, 0xd9, 0xfb, 0x18, 0x12, 0x12, 0xf5, 0x10, 0x08, + 0xf9, 0x12, 0x4e, 0x37, 0x38, 0xeb, 0xfd, 0xf0, 0x24, 0xdb, 0xc6, 0xfc, 0xeb, + 0x1f, 0xfd, 0xc6, 0x10, 0xf1, 0x36, 0xe9, 0x16, 0xfa, 0x4a, 0xf1, 0x0a, 0xf4, + 0xee, 0xe2, 0x81, 0x33, 0x47, 0xef, 0x0c, 0x30, 0xcb, 0xe4, 0x15, 0x2d, 0x3d, + 0xf6, 0x1e, 0x32, 0xfd, 0x23, 0x04, 0xbe, 0x22, 0xfe, 0x0e, 0x30, 0xff, 0x57, + 0x19, 0xf3, 0xf5, 0x12, 0xe7, 0x21, 0x0c, 0xd4, 0xf9, 0x32, 0x1f, 0x46, 0xe1, + 0x36, 0x06, 0x4f, 0xdc, 0x02, 0x4a, 0xe5, 0x29, 0xd1, 0x41, 0xfc, 0x2e, 0x58, + 0xdb, 0xee, 0xfd, 0x11, 0x34, 0xf3, 0x0e, 0xeb, 0x51, 0xd6, 0xb8, 0x12, 0xe5, + 0x1c, 0x17, 0x3e, 0x38, 0x0a, 0xd6, 0xf1, 0x28, 0x09, 0xf1, 0x1c, 0xee, 0xaf, + 0xb0, 0x10, 0xc1, 0xe9, 0x2c, 0xc8, 0xaa, 0xb0, 0x52, 0xf0, 0x4c, 0x37, 0xd1, + 0x21, 0xff, 0x24, 0xbf, 0x38, 0x0a, 0xf4, 0xa2, 0xdc, 0x28, 0xb7, 0xf5, 0xf6, + 0xf0, 0xbd, 0x09, 0xf5, 0xe6, 0x02, 0x08, 0xfe, 0xa2, 0xdb, 0x28, 0x26, 0x26, + 0xdd, 0x15, 0x38, 0xfd, 0xe6, 0xdd, 0x00, 0xdb, 0xea, 0xc7, 0x08, 0xa0, 0x08, + 0x30, 0x07, 0xf6, 0xb4, 0xf2, 0x1f, 0xf1, 0xcb, 0x91, 0x4b, 0xe4, 0x37, 0xf1, + 0x7f, 0x2f, 0x53, 0x03, 0xeb, 0x65, 0x05, 0xbe, 0xb3, 0xdb, 0xd3, 0x1c, 0xcb, + 0x4a, 0xf4, 0x23, 0xd8, 0x1a, 0x33, 0xc8, 0xd5, 0xfe, 0x21, 0x17, 0x35, 0x3f, + 0xfb, 0xcb, 0x06, 0xc8, 0x07, 0xf6, 0xde, 0xd3, 0xdc, 0x07, 0x02, 0x23, 0x4f, + 0x30, 0x08, 0xe5, 0xfb, 0x1c, 0xf8, 0xc6, 0xce, 0x07, 0x1d, 0x1f, 0x41, 0xea, + 0xf0, 0xce, 0x44, 0xee, 0x0c, 0xd6, 0xc6, 0x08, 0xe4, 0xd8, 0x2f, 0xf7, 0xf7, + 0xbc, 0xad, 0xe0, 0x32, 0xbf, 0xed, 0x86, 0x1b, 0xe4, 0xfc, 0xfc, 0x42, 0x16, + 0x2a, 0xc6, 0xca, 0xe8, 0xf8, 0x42, 0xf7, 0x0b, 0xf5, 0xfd, 0xf8, 0xe2, 0xe3, + 0x20, 0xfb, 0xee, 0x14, 0x25, 0x12, 0x3a, 0xe6, 0xd9, 0x16, 0xef, 0xbb, 0xed, + 0x3d, 0xe9, 0xe4, 0x1e, 0xe5, 0x17, 0x45, 0xa1, 0x32, 0xe2, 0xc0, 0x90, 0x17, + 0x29, 0x2a, 0xe5, 0x1f, 0x0a, 0x36, 0x1c, 0xd0, 0xed, 0x2f, 0x1b, 0xe9, 0x18, + 0x82, 0x0b, 0x81, 0x00, 0x15, 0x32, 0xd6, 0xe5, 0x2b, 0x24, 0xf2, 0xf1, 0xe6, + 0xc5, 0xf9, 0x0a, 0xec, 0x25, 0xd6, 0xe8, 0xdb, 0x21, 0xff, 0xc0, 0xee, 0xe7, + 0xee, 0x29, 0xe2, 0x40, 0x1b, 0x1f, 0xf9, 0x48, 0x10, 0xe1, 0x0b, 0xf9, 0xdd, + 0x20, 0xf5, 0x28, 0xdf, 0x02, 0xdf, 0xdb, 0xc5, 0x02, 0xfd, 0x45, 0x28, 0x38, + 0x1f, 0xf0, 0x40, 0xc7, 0xf0, 0xf5, 0x16, 0x18, 0xf7, 0xba, 0x36, 0xe7, 0xcf, + 0xd0, 0xf3, 0xeb, 0xc9, 0x14, 0x00, 0xee, 0xfc, 0x1c, 0xee, 0xe4, 0x0e, 0xdc, + 0x1d, 0xdb, 0x35, 0xe2, 0x05, 0x19, 0xc0, 0x4d, 0xe8, 0x16, 0xd9, 0x0c, 0xe5, + 0xe5, 0x1e, 0x03, 0xce, 0x19, 0x14, 0x81, 0x1f, 0xfb, 0x47, 0x0b, 0x03, 0x15, + 0xe8, 0x01, 0xf8, 0x13, 0xfc, 0x08, 0x02, 0x02, 0xf5, 0x0d, 0xf4, 0x28, 0x04, + 0xfd, 0xfd, 0xc2, 0x09, 0x15, 0xf9, 0xaa, 0x06, 0x0a, 0x0e, 0x00, 0x10, 0x04, + 0xb7, 0xb2, 0xc3, 0xee, 0xc9, 0x30, 0x48, 0x10, 0x5a, 0xd2, 0xe2, 0x08, 0xee, + 0xef, 0xdb, 0x00, 0x06, 0x53, 0xfe, 0x28, 0xeb, 0xf4, 0xb6, 0xfe, 0x0d, 0x25, + 0xe1, 0x17, 0x06, 0x00, 0xfc, 0x04, 0xdc, 0x3a, 0x33, 0x11, 0x41, 0x1b, 0xee, + 0x1b, 0x06, 0xd6, 0xdd, 0x2a, 0x03, 0x3e, 0xe4, 0xe7, 0x46, 0xf5, 0xec, 0x2d, + 0x1b, 0xe0, 0xe9, 0x02, 0xed, 0xfc, 0xd7, 0xfe, 0xe3, 0xf5, 0xbd, 0x27, 0xc5, + 0x2c, 0x07, 0x02, 0x38, 0x27, 0xd7, 0x37, 0xe3, 0x32, 0x81, 0xff, 0xf2, 0xd8, + 0x13, 0x52, 0xc4, 0x4e, 0x19, 0xe6, 0x30, 0xc2, 0xe5, 0xc6, 0x02, 0x9c, 0xf7, + 0xd9, 0xee, 0x02, 0x14, 0x98, 0xe2, 0x18, 0xee, 0x1a, 0xf8, 0x30, 0xdc, 0x0f, + 0x5e, 0x15, 0xe9, 0x09, 0xcf, 0xd2, 0xee, 0xe7, 0xdc, 0x2b, 0x1f, 0x62, 0x3b, + 0x00, 0x32, 0xd7, 0x1f, 0xcb, 0xe2, 0x13, 0x9b, 0x18, 0xd4, 0xde, 0x1a, 0xd7, + 0x69, 0x22, 0xeb, 0xc9, 0xaf, 0x1e, 0x1a, 0xff, 0xdb, 0xcd, 0xc7, 0xfe, 0xe7, + 0xce, 0xea, 0xb7, 0xf1, 0x16, 0xe1, 0xd8, 0xf0, 0xdf, 0x38, 0xe4, 0x4c, 0xdf, + 0x18, 0xd9, 0x3e, 0xc3, 0xca, 0x30, 0x27, 0x03, 0xf6, 0xec, 0x04, 0xc3, 0x16, + 0xb9, 0x2f, 0x16, 0x0d, 0x11, 0x31, 0xec, 0xc9, 0xf0, 0x1d, 0x02, 0xdf, 0xb5, + 0x4b, 0x3a, 0xaf, 0x22, 0xa0, 0xe2, 0x10, 0xf2, 0x52, 0x54, 0xe8, 0xb7, 0xe7, + 0x28, 0x3f, 0xcb, 0x06, 0xaa, 0x1e, 0xda, 0xd0, 0xcd, 0x1d, 0xf0, 0xc8, 0x05, + 0x03, 0x26, 0x0a, 0x11, 0xf5, 0xed, 0xf8, 0x5b, 0xed, 0x9e, 0xdd, 0xbd, 0xf7, + 0x7e, 0xba, 0xa1, 0x1b, 0x81, 0xd0, 0xe7, 0xa1, 0xfb, 0xed, 0xf6, 0xf3, 0x3c, + 0xc6, 0xc1, 0xfd, 0x2b, 0x28, 0x0d, 0xd9, 0xce, 0xf9, 0xf4, 0x44, 0xf0, 0x05, + 0x28, 0x06, 0x99, 0xba, 0x9c, 0xf4, 0x99, 0x06, 0xf0, 0x1f, 0xea, 0xe0, 0xd7, + 0xd4, 0xe6, 0x05, 0x3f, 0xab, 0x1d, 0x0c, 0xaa, 0xa2, 0xce, 0x48, 0xd1, 0xbb, + 0xc6, 0x1b, 0xe0, 0xfe, 0xd2, 0xcf, 0xc8, 0xff, 0xd5, 0xf2, 0xdd, 0x3a, 0xac, + 0x59, 0x11, 0x06, 0xb1, 0x3f, 0xfb, 0xe5, 0xbc, 0x50, 0x35, 0x20, 0x18, 0xea, + 0x6a, 0x26, 0xdd, 0x38, 0xdb, 0x36, 0xf3, 0x1c, 0xe3, 0x48, 0xf8, 0x60, 0x67, + 0x1e, 0xd9, 0xeb, 0xe0, 0xf2, 0xdd, 0xce, 0x1c, 0x3e, 0x18, 0x0e, 0xa6, 0xfe, + 0xdf, 0x0c, 0xd1, 0xcc, 0x2c, 0xdb, 0x0e, 0xec, 0xc0, 0x17, 0x2b, 0xe5, 0xfa, + 0x41, 0x21, 0xb0, 0xfb, 0xc2, 0x42, 0x24, 0x2b, 0x2f, 0xdb, 0xe4, 0xc8, 0x40, + 0x3f, 0x17, 0xb5, 0xd2, 0xf7, 0x15, 0x2e, 0x18, 0xc0, 0xa2, 0x3f, 0x6d, 0xe3, + 0xe1, 0xb8, 0xc3, 0xba, 0xfb, 0x2c, 0x0d, 0xea, 0x15, 0xc7, 0x06, 0xdf, 0xe0, + 0x55, 0xc5, 0xbf, 0x0a, 0xf1, 0xe3, 0xe3, 0xef, 0x1d, 0x7f, 0xef, 0xef, 0x4a, + 0xfd, 0x1a, 0x25, 0x04, 0xfe, 0x03, 0xd9, 0xf2, 0xef, 0x12, 0x28, 0xef, 0x36, + 0xcf, 0x21, 0x14, 0x0d, 0x21, 0xf6, 0xfa, 0xfc, 0xf3, 0xe7, 0xed, 0xd6, 0xdd, + 0xe2, 0xed, 0xb8, 0xf0, 0xe6, 0x1d, 0x17, 0xf3, 0x13, 0xf0, 0xd6, 0x00, 0xcc, + 0xe6, 0x00, 0x09, 0xff, 0xe5, 0xb7, 0xd8, 0xf8, 0x04, 0x07, 0xe2, 0xf6, 0xe3, + 0xf5, 0x06, 0xfd, 0xde, 0xfb, 0xb8, 0x18, 0xff, 0x02, 0xf1, 0x6d, 0xfe, 0x0d, + 0xfc, 0x21, 0xbb, 0x0b, 0xdf, 0xe1, 0xf8, 0xde, 0x27, 0xe6, 0xfa, 0x3c, 0xbb, + 0xfe, 0x17, 0x00, 0xdb, 0x1d, 0xf0, 0xd9, 0xbe, 0x12, 0x7f, 0xe9, 0xd1, 0xf7, + 0xe4, 0x08, 0xcc, 0xe6, 0xfb, 0xda, 0xe6, 0xf9, 0xf3, 0xeb, 0xf1, 0xec, 0xef, + 0x17, 0x11, 0xf0, 0xfc, 0x2d, 0xf7, 0xf9, 0xc6, 0xec, 0x43, 0xf6, 0x01, 0xfb, + 0xcc, 0xe4, 0xdb, 0x3c, 0x3e, 0xff, 0x0f, 0x15, 0xe4, 0xfb, 0xdd, 0xfe, 0x02, + 0xfa, 0xe3, 0x11, 0x24, 0x0f, 0x0a, 0x0f, 0xe4, 0x05, 0xcd, 0xa7, 0x0d, 0x8a, + 0x33, 0xe8, 0x2d, 0xfc, 0x49, 0x06, 0xb4, 0xe7, 0xe1, 0x1f, 0x0c, 0xf3, 0x3c, + 0xfc, 0xc4, 0xf7, 0xf8, 0x27, 0x2c, 0xe8, 0xcc, 0xe7, 0xa3, 0xb8, 0x44, 0xdc, + 0xf8, 0x2a, 0x54, 0x92, 0xd7, 0x04, 0xca, 0x81, 0xc5, 0xdd, 0xf7, 0xc9, 0x63, + 0x07, 0xfc, 0x00, 0x0a, 0x34, 0x2b, 0x43, 0xd8, 0xca, 0xe0, 0xc3, 0xb0, 0x12, + 0xfa, 0xf9, 0xa5, 0xd6, 0xc4, 0xe3, 0xff, 0xe7, 0xf9, 0x23, 0xbf, 0x4c, 0xbb, + 0xc5, 0xfe, 0x2b, 0x43, 0xf6, 0xbb, 0xfe, 0x39, 0xdc, 0x09, 0xc1, 0x99, 0x4f, + 0xf8, 0xe1, 0xe6, 0x38, 0xd8, 0x16, 0x11, 0xf7, 0x41, 0xd5, 0x1c, 0x02, 0x00, + 0xa9, 0x13, 0x02, 0xf1, 0x3f, 0x3a, 0x52, 0xba, 0xa1, 0x85, 0x8d, 0x25, 0xc9, + 0xdf, 0xdf, 0x01, 0x1f, 0x38, 0xea, 0x16, 0x26, 0x2c, 0x12, 0x26, 0xfd, 0x2c, + 0x13, 0xf6, 0x1e, 0x1f, 0x1c, 0xdd, 0xc9, 0x7f, 0x03, 0xcd, 0x04, 0x0a, 0xf3, + 0x15, 0xe2, 0x48, 0x0e, 0x38, 0xd6, 0x24, 0x11, 0x36, 0x05, 0x32, 0x17, 0x00, + 0x24, 0xf9, 0xd1, 0x24, 0x2b, 0xc2, 0xc0, 0xf9, 0xff, 0xcc, 0x0b, 0x34, 0xf0, + 0x27, 0xfb, 0xe4, 0x2c, 0x0a, 0xf7, 0xf3, 0xe1, 0xac, 0xfd, 0xe2, 0xf5, 0xdc, + 0xd8, 0x05, 0xa0, 0x0d, 0x5d, 0x04, 0xe5, 0xca, 0xfd, 0x35, 0xef, 0xd4, 0x1f, + 0x04, 0xb9, 0x0b, 0xd7, 0xed, 0xd8, 0x09, 0x05, 0xf4, 0x0e, 0xdd, 0xf2, 0xd5, + 0xf9, 0x37, 0xdf, 0x25, 0x20, 0xdb, 0xf5, 0x14, 0xf1, 0x12, 0xec, 0xcd, 0xd9, + 0xca, 0x2c, 0x2c, 0xe1, 0xfa, 0x5f, 0xb8, 0xf5, 0x01, 0x09, 0x26, 0x0f, 0xd5, + 0xf1, 0x14, 0x3c, 0xec, 0xd3, 0xdf, 0x41, 0x11, 0x3a, 0xf6, 0xce, 0x11, 0xd7, + 0x2a, 0x4d, 0x01, 0x0b, 0xec, 0xfb, 0x0a, 0x55, 0xd7, 0x01, 0xbc, 0x38, 0xe4, + 0xd3, 0xf6, 0xef, 0x34, 0xb8, 0xf2, 0x92, 0x2d, 0x91, 0xb8, 0x22, 0xf5, 0x2b, + 0xce, 0x1a, 0xbf, 0x70, 0x07, 0x36, 0xe9, 0x99, 0x1d, 0x0a, 0x08, 0x29, 0xce, + 0xee, 0xfc, 0x5d, 0xb7, 0xf2, 0xa2, 0xd3, 0x38, 0x2f, 0x6a, 0x31, 0x34, 0x41, + 0xc4, 0x0e, 0x1d, 0x20, 0x5d, 0x94, 0x1a, 0xbd, 0xb5, 0xc6, 0xd0, 0x43, 0xdb, + 0x3d, 0x44, 0xf8, 0xba, 0x0a, 0xe5, 0x2d, 0xf2, 0xd8, 0x03, 0xf7, 0x33, 0xbe, + 0x1d, 0x4b, 0x09, 0xd6, 0x09, 0x1c, 0xe9, 0x46, 0x0c, 0x17, 0xf5, 0xf0, 0xc9, + 0x34, 0x56, 0xb1, 0xba, 0x31, 0xcf, 0x0e, 0x22, 0x0b, 0x47, 0x4e, 0x1d, 0x05, + 0x38, 0x81, 0x73, 0x2a, 0xce, 0x01, 0x4f, 0xe4, 0xb0, 0x4e, 0x94, 0xf5, 0xac, + 0xd1, 0xe8, 0x16, 0x10, 0x0c, 0xf8, 0x3b, 0xb8, 0x12, 0xe3, 0xf5, 0x59, 0x64, + 0x1c, 0x38, 0xe6, 0x10, 0xd0, 0xcc, 0xc9, 0x23, 0xd6, 0xf8, 0xf9, 0xf8, 0xf1, + 0x19, 0x0b, 0x0f, 0x0f, 0x05, 0xc7, 0xe7, 0x0c, 0xdd, 0x0c, 0x0f, 0x17, 0xf8, + 0xf8, 0xf6, 0x09, 0xf9, 0xd6, 0x1b, 0x53, 0x5b, 0xf0, 0xde, 0xe9, 0x1b, 0x33, + 0x05, 0x37, 0xbd, 0x2d, 0x24, 0xde, 0x19, 0xac, 0x21, 0x4c, 0x0b, 0x1b, 0x14, + 0xd5, 0x36, 0x23, 0xe6, 0x20, 0x26, 0x22, 0xf7, 0xad, 0xe6, 0xd1, 0xdc, 0x97, + 0xca, 0x20, 0x3e, 0x12, 0xb4, 0x2d, 0x34, 0xe7, 0x35, 0x1c, 0x39, 0xc1, 0xb5, + 0x08, 0xc0, 0x21, 0x1d, 0xec, 0x31, 0x0a, 0x1d, 0x17, 0xd4, 0xe2, 0xff, 0xf4, + 0xdf, 0x3d, 0xf5, 0xdf, 0x02, 0x48, 0xe8, 0x06, 0xd7, 0x15, 0x17, 0xf7, 0xee, + 0x7f, 0x24, 0x07, 0xe2, 0x01, 0xc9, 0x18, 0x2e, 0xfc, 0xfe, 0x12, 0xda, 0xd8, + 0x07, 0x08, 0xfb, 0xea, 0xfa, 0x01, 0x07, 0xe5, 0x1b, 0x00, 0xd9, 0xcf, 0x32, + 0xf2, 0xef, 0xb4, 0xeb, 0xfd, 0xf9, 0x33, 0xd7, 0x07, 0xbb, 0xf4, 0x0f, 0xe9, + 0xf9, 0x66, 0xf7, 0x2c, 0x24, 0xa3, 0xef, 0xf8, 0x2a, 0x1c, 0x3e, 0x8e, 0xf0, + 0xaa, 0xd1, 0x05, 0x12, 0x9e, 0x14, 0xec, 0x47, 0x20, 0x27, 0x56, 0xe8, 0x36, + 0xa0, 0x81, 0xa5, 0xa2, 0xf7, 0x0b, 0x1b, 0xdc, 0xb0, 0xb6, 0xf6, 0xff, 0xf4, + 0x26, 0xe7, 0xce, 0xc3, 0x02, 0x95, 0x5e, 0x8f, 0xd4, 0xb3, 0xb9, 0xe2, 0x28, + 0xfa, 0x00, 0x0f, 0x1a, 0xee, 0x2a, 0x02, 0xcf, 0xb9, 0xea, 0xa8, 0x03, 0x3a, + 0xff, 0xcf, 0x07, 0xe5, 0x2d, 0x3f, 0x32, 0xc0, 0x0f, 0xdf, 0xd3, 0xd5, 0x0d, + 0xe6, 0x10, 0xe4, 0x11, 0xbd, 0xb0, 0x09, 0x12, 0x00, 0xd6, 0x37, 0x22, 0x36, + 0xd3, 0xf6, 0x8a, 0xeb, 0xd9, 0x20, 0xe2, 0xfb, 0xde, 0x14, 0x8c, 0xc0, 0xd0, + 0xe8, 0x21, 0xe9, 0xab, 0xd6, 0x0c, 0x1c, 0x03, 0x4e, 0xf7, 0x14, 0xbf, 0x0e, + 0xab, 0x03, 0x3f, 0x22, 0xcf, 0x52, 0xc6, 0x33, 0x7f, 0xc7, 0xd2, 0x14, 0x10, + 0x1d, 0x0d, 0x02, 0xae, 0xcd, 0xc8, 0xd8, 0xff, 0xfc, 0xd7, 0x1e, 0x13, 0xe0, + 0x2d, 0xff, 0x28, 0x1f, 0x00, 0x22, 0x21, 0x10, 0x0e, 0xf9, 0xc0, 0x1c, 0x28, + 0x26, 0x9d, 0x20, 0x1a, 0xd6, 0x21, 0x2a, 0x2d, 0x1a, 0xe4, 0xf3, 0xea, 0x14, + 0x0d, 0x0c, 0x19, 0x09, 0xcb, 0x4f, 0x51, 0xd0, 0x09, 0x2f, 0xdc, 0x8c, 0x23, + 0x12, 0xae, 0x29, 0xe2, 0xf6, 0x21, 0x29, 0x32, 0x22, 0x18, 0x23, 0xf9, 0x47, + 0xd0, 0x44, 0x23, 0x05, 0xe6, 0x17, 0x04, 0x07, 0x05, 0xf8, 0xff, 0x49, 0x0a, + 0x1f, 0x0b, 0xf0, 0x54, 0x23, 0x0a, 0x0a, 0x05, 0x0c, 0x01, 0x1b, 0xde, 0xf7, + 0xde, 0xe1, 0xd5, 0x08, 0x4f, 0x1b, 0xf1, 0x22, 0x27, 0xb5, 0x1e, 0x14, 0xdb, + 0x23, 0xc8, 0xfa, 0xd9, 0xf2, 0xf0, 0xd6, 0x17, 0xee, 0x38, 0xec, 0x29, 0xe2, + 0x26, 0xcf, 0xbc, 0xe3, 0xf9, 0x1b, 0xdd, 0xcf, 0x0b, 0xe8, 0xea, 0xea, 0x3d, + 0xea, 0x2c, 0xfa, 0xc5, 0x1c, 0xfa, 0xe4, 0xea, 0xfb, 0xd4, 0x31, 0xef, 0xe6, + 0xf9, 0xcd, 0xd3, 0xe4, 0xf0, 0xc2, 0xec, 0xe9, 0x08, 0xbb, 0x01, 0x4a, 0x19, + 0x1a, 0xfc, 0x22, 0x81, 0xee, 0x44, 0xf6, 0x2e, 0x2a, 0xf3, 0x04, 0x1a, 0xde, + 0xef, 0xf5, 0x22, 0x03, 0xe2, 0xf9, 0xf9, 0x0b, 0x0d, 0x4f, 0xf6, 0xd1, 0xe2, + 0xb6, 0x2e, 0x17, 0xf3, 0x0b, 0xd7, 0x47, 0xed, 0xb8, 0xf2, 0xfa, 0x29, 0xee, + 0x00, 0xf9, 0x19, 0xe2, 0xf0, 0xf6, 0xde, 0xe7, 0x2d, 0x29, 0x14, 0x0b, 0x18, + 0x37, 0xf8, 0x05, 0x1e, 0xeb, 0xe6, 0x22, 0xf7, 0x08, 0xfb, 0x05, 0x0a, 0x02, + 0x2f, 0xef, 0x0e, 0x00, 0xea, 0xfa, 0xe2, 0x07, 0x07, 0xee, 0xd1, 0xfc, 0xc9, + 0xf3, 0x19, 0x21, 0x28, 0xe5, 0x0c, 0xf0, 0xe1, 0x11, 0x3e, 0xe6, 0x4b, 0xd4, + 0x24, 0x1d, 0x1a, 0xc3, 0x94, 0x34, 0x3c, 0x1e, 0xfe, 0x3e, 0xb6, 0x43, 0x5b, + 0x33, 0xe1, 0xdc, 0x01, 0x2d, 0x25, 0x30, 0x38, 0xc6, 0xd3, 0xa1, 0x50, 0xcb, + 0x11, 0x0c, 0xc3, 0xe7, 0x2b, 0x44, 0x07, 0x11, 0x18, 0x14, 0x00, 0xf2, 0xc0, + 0x57, 0xb4, 0xae, 0xea, 0x06, 0xed, 0xb9, 0xf4, 0xe5, 0xe4, 0x36, 0x39, 0x0c, + 0xfa, 0xba, 0x05, 0x31, 0x2a, 0xc8, 0x50, 0x38, 0xde, 0xee, 0x2d, 0x3c, 0xfd, + 0x31, 0xd1, 0xff, 0x33, 0xa9, 0x2c, 0x21, 0x6d, 0x31, 0xdb, 0xd3, 0x04, 0x55, + 0x1f, 0xbe, 0x09, 0x28, 0x90, 0x0e, 0x79, 0xf5, 0xdb, 0x3a, 0xc0, 0xd9, 0x33, + 0xb5, 0xda, 0xd2, 0xb2, 0x17, 0x0a, 0xe8, 0xf9, 0x20, 0x24, 0x04, 0xf8, 0x11, + 0x1f, 0x12, 0xf5, 0x32, 0xa9, 0xfb, 0xe6, 0x08, 0xf2, 0xe7, 0x10, 0x12, 0x42, + 0x2a, 0xd3, 0xdb, 0x21, 0xd0, 0x7f, 0xab, 0x1b, 0x1f, 0x27, 0xd5, 0xad, 0x27, + 0x1c, 0xed, 0x0c, 0x31, 0xcd, 0x10, 0x17, 0xa7, 0x26, 0x56, 0x16, 0xee, 0x0f, + 0x68, 0x41, 0x1c, 0xdd, 0x0d, 0xdc, 0x19, 0x3c, 0xeb, 0x04, 0xae, 0x35, 0xe6, + 0x2f, 0xf8, 0x12, 0x08, 0xff, 0xc5, 0xd6, 0xac, 0xf1, 0x2f, 0xdd, 0xb5, 0xd5, + 0xfa, 0x37, 0x71, 0xeb, 0xf6, 0xa5, 0xe8, 0xfa, 0xda, 0x00, 0xd9, 0xf5, 0xc2, + 0xd0, 0x37, 0xee, 0x1c, 0xdd, 0x1a, 0xdb, 0xd9, 0x2a, 0x0b, 0xe3, 0xbe, 0x10, + 0xe6, 0xdf, 0xd2, 0x14, 0xcf, 0x7f, 0x4a, 0xde, 0xc8, 0xf9, 0xe1, 0x32, 0xf0, + 0x9f, 0xe2, 0xd8, 0xf8, 0x12, 0xc9, 0xf4, 0x04, 0x1b, 0x05, 0x27, 0x2f, 0x0d, + 0x21, 0x03, 0x20, 0x2f, 0xf9, 0xf5, 0xec, 0x29, 0x07, 0xd4, 0x2f, 0xea, 0xc7, + 0x02, 0x04, 0xa6, 0x16, 0xcc, 0xc5, 0xc5, 0xf9, 0xe5, 0xf8, 0xba, 0xfd, 0x1c, + 0x2e, 0xf6, 0x19, 0x10, 0xf1, 0x4c, 0x26, 0x09, 0xf1, 0xed, 0xc4, 0xc4, 0x75, + 0xde, 0xfe, 0xd7, 0x20, 0x50, 0xf3, 0xb1, 0xe1, 0xea, 0x28, 0x12, 0x05, 0xe7, + 0xe6, 0x1c, 0xe5, 0xd3, 0xea, 0xf0, 0xd8, 0x3f, 0xef, 0x09, 0xd5, 0xe4, 0x1a, + 0x40, 0xf2, 0x5f, 0xfc, 0x30, 0xd9, 0x82, 0xea, 0x29, 0xc5, 0x1b, 0xfa, 0xaf, + 0xd2, 0xf4, 0xd8, 0xec, 0x53, 0xdd, 0x2e, 0x37, 0xef, 0xf9, 0xe7, 0x1d, 0xff, + 0x16, 0x38, 0x18, 0x7f, 0xd8, 0xe0, 0xbc, 0xf8, 0x9a, 0xe0, 0xf5, 0x2a, 0x05, + 0x22, 0x15, 0x51, 0xef, 0xd0, 0x70, 0x22, 0x6b, 0x1a, 0xcd, 0xbb, 0x60, 0xc2, + 0xf3, 0xd8, 0x5f, 0x5f, 0xdd, 0x0c, 0xc1, 0xe0, 0xb9, 0x12, 0x0b, 0xed, 0x03, + 0x2b, 0x39, 0x1e, 0x4e, 0x2e, 0xfa, 0x3e, 0x18, 0xad, 0xca, 0x74, 0xcc, 0xe9, + 0x1b, 0x1e, 0xf6, 0x13, 0xe1, 0x14, 0x9f, 0x46, 0xcd, 0x05, 0x35, 0x47, 0x57, + 0xdf, 0xf0, 0x2c, 0x25, 0xde, 0x28, 0xc7, 0x11, 0xfe, 0x19, 0xe2, 0xfd, 0xfe, + 0xd8, 0x5d, 0xd5, 0xca, 0x97, 0x59, 0x21, 0x1e, 0x04, 0xff, 0x09, 0x4b, 0x17, + 0xc4, 0x1d, 0xc9, 0xda, 0x0a, 0xf5, 0xd0, 0x01, 0x30, 0xff, 0xb8, 0x3d, 0x20, + 0x38, 0xb9, 0x40, 0xf9, 0x2d, 0xf0, 0xe2, 0xbd, 0xcc, 0xc4, 0x07, 0xde, 0xf7, + 0xea, 0xfc, 0x46, 0xd4, 0xfb, 0x09, 0xc6, 0xf9, 0x43, 0x6b, 0xdd, 0xe2, 0xd3, + 0x18, 0xdc, 0x0b, 0x39, 0x93, 0x32, 0xfd, 0x22, 0x4c, 0x06, 0x72, 0xfd, 0xd0, + 0x18, 0x14, 0xeb, 0x43, 0x22, 0x08, 0xb6, 0x29, 0x00, 0x32, 0x7f, 0x13, 0x42, + 0xdc, 0xd5, 0x0d, 0x53, 0x10, 0x09, 0xfa, 0x5a, 0x0e, 0x13, 0xff, 0xc0, 0x18, + 0x34, 0x1f, 0x38, 0x38, 0x27, 0xc4, 0xf6, 0x19, 0x40, 0xdc, 0x30, 0xc5, 0xd7, + 0xad, 0xf2, 0xf5, 0x06, 0x07, 0xdc, 0x30, 0x01, 0x1c, 0xe8, 0x34, 0xb8, 0x3c, + 0xd1, 0xdd, 0x0c, 0xf9, 0x04, 0xc0, 0xb1, 0xf5, 0x35, 0xbb, 0x18, 0x26, 0xd4, + 0x00, 0x30, 0xf4, 0xde, 0xb9, 0xba, 0x0a, 0x13, 0xaa, 0x0c, 0xd6, 0xe7, 0x42, + 0x17, 0xe3, 0x19, 0xc8, 0x74, 0xe8, 0x13, 0xf8, 0x34, 0xd2, 0x1f, 0xee, 0xe9, + 0xef, 0xdd, 0x03, 0xc8, 0x4a, 0x48, 0x0a, 0xaf, 0xda, 0xe1, 0xee, 0xca, 0x75, + 0xaf, 0x31, 0xf6, 0x0a, 0x2a, 0x2a, 0xfc, 0xf1, 0x07, 0xc4, 0x9f, 0xf9, 0xba, + 0x1e, 0x2d, 0x15, 0x12, 0x5a, 0xfe, 0x16, 0xec, 0x0a, 0x36, 0xe7, 0xbf, 0xd0, + 0xe4, 0xc5, 0x0e, 0x18, 0xf7, 0x0e, 0xfe, 0x4b, 0x10, 0xb3, 0x35, 0xd7, 0x0d, + 0xe4, 0x01, 0xba, 0xe6, 0x22, 0xd4, 0x81, 0x05, 0x47, 0x3f, 0x05, 0xd7, 0xd7, + 0x12, 0xfe, 0x09, 0x0d, 0x1f, 0xd8, 0xff, 0xc2, 0xf5, 0x1a, 0x0f, 0xe9, 0xec, + 0x65, 0xb3, 0xc9, 0x06, 0xea, 0x3b, 0xe5, 0xf1, 0xf4, 0xe5, 0xd1, 0x57, 0xc0, + 0xc4, 0x34, 0x07, 0xb5, 0x05, 0x07, 0x12, 0x3a, 0xdf, 0xe6, 0xce, 0xc7, 0x1c, + 0x33, 0xe4, 0x95, 0xf7, 0x09, 0x20, 0x40, 0x54, 0xc0, 0xde, 0x17, 0x4c, 0xfa, + 0xff, 0xc0, 0x02, 0x24, 0x3a, 0xf5, 0xee, 0x0d, 0x91, 0x2c, 0x25, 0x53, 0xcf, + 0xdb, 0x4f, 0x4e, 0xfa, 0xd3, 0xff, 0xd2, 0x2c, 0xf0, 0x12, 0x18, 0xf1, 0x1e, + 0xcd, 0xee, 0xe6, 0x03, 0xe9, 0x01, 0xca, 0xed, 0xdb, 0x1d, 0x04, 0xb1, 0x7e, + 0xe6, 0xf9, 0xce, 0xcd, 0xf0, 0x01, 0xf0, 0x3e, 0x19, 0x05, 0x0e, 0x3d, 0x0a, + 0xe6, 0x2a, 0x20, 0xd4, 0xe0, 0x1e, 0x26, 0x1e, 0xbe, 0x42, 0x24, 0xc8, 0x31, + 0x22, 0x39, 0x23, 0xc2, 0x6a, 0xe7, 0x22, 0x11, 0x37, 0x26, 0x1e, 0x08, 0xb9, + 0x1f, 0x01, 0xef, 0x02, 0xef, 0xfa, 0x1d, 0x1b, 0x0e, 0x1c, 0x09, 0x22, 0xfc, + 0xdd, 0xba, 0x7f, 0xdb, 0x0f, 0xe3, 0x4f, 0x0b, 0xd9, 0x0d, 0xc6, 0xee, 0x29, + 0xfe, 0x9d, 0x10, 0xbc, 0x02, 0xe6, 0x17, 0x26, 0x20, 0x39, 0xe1, 0x1f, 0x07, + 0xdf, 0xe8, 0x16, 0x18, 0xdd, 0x26, 0xe1, 0xb2, 0x46, 0x1d, 0x04, 0xe3, 0xf8, + 0x0e, 0x38, 0x1e, 0xea, 0x0a, 0x30, 0x2a, 0x36, 0x31, 0x2d, 0x16, 0xd1, 0xd0, + 0xda, 0x03, 0x11, 0xb7, 0xc0, 0xf7, 0xd9, 0xd3, 0x2e, 0x02, 0xd7, 0x2b, 0xf9, + 0x94, 0xf6, 0xee, 0xfe, 0xdd, 0x3f, 0x61, 0xf5, 0x98, 0xf7, 0x02, 0xe9, 0x16, + 0xdb, 0x44, 0x2d, 0x4c, 0xf9, 0x0c, 0x09, 0x6b, 0x2e, 0x27, 0xba, 0x04, 0xf0, + 0xcb, 0x01, 0xd3, 0xe4, 0xbe, 0xe6, 0x22, 0xcc, 0x05, 0xe0, 0xec, 0x13, 0x0c, + 0xcd, 0xba, 0xe8, 0x16, 0xfd, 0x66, 0x7f, 0xfe, 0x49, 0xc3, 0x39, 0xd8, 0xce, + 0xe2, 0xfc, 0x0a, 0x12, 0xfd, 0xd2, 0x01, 0xb2, 0x11, 0xfa, 0xf0, 0xff, 0x06, + 0x3d, 0xde, 0xed, 0x9b, 0x08, 0xf8, 0xca, 0xd1, 0xca, 0xbe, 0xe8, 0x08, 0x63, + 0xc2, 0xa8, 0x1f, 0x5b, 0x4c, 0x11, 0xd0, 0x31, 0x19, 0x2d, 0xf5, 0xab, 0xe1, + 0xef, 0xe2, 0xfd, 0xf5, 0x1d, 0xe6, 0x38, 0x07, 0x2d, 0xf4, 0xcb, 0x0d, 0xc5, + 0x17, 0x02, 0x34, 0xb0, 0x55, 0xec, 0xca, 0xef, 0x1e, 0xd8, 0x17, 0x03, 0xd6, + 0xf1, 0x49, 0x06, 0xdc, 0xf8, 0x2f, 0xf6, 0x00, 0xeb, 0x81, 0x1e, 0xb7, 0xe4, + 0xe4, 0xc3, 0x22, 0x28, 0x03, 0x08, 0xbb, 0x56, 0x2e, 0xf4, 0xda, 0x00, 0xff, + 0xfc, 0x69, 0x14, 0x09, 0x06, 0xc9, 0x0f, 0x3f, 0x0f, 0xef, 0xbd, 0xe4, 0x58, + 0xe8, 0x1f, 0x5f, 0x14, 0xf5, 0xec, 0xe7, 0xfb, 0x1e, 0xa7, 0xd7, 0xfa, 0xf2, + 0x11, 0x27, 0x00, 0xe4, 0xed, 0x14, 0xf2, 0x04, 0x1d, 0xaf, 0x53, 0x04, 0x43, + 0x2c, 0xe5, 0xd9, 0x1f, 0xbe, 0x1c, 0xc8, 0xcf, 0xe4, 0x04, 0xa2, 0x1a, 0xdf, + 0xff, 0x20, 0xfe, 0xd9, 0xf9, 0x11, 0xf4, 0xeb, 0xe4, 0xc5, 0x95, 0x19, 0x2f, + 0x09, 0xcc, 0xc7, 0xda, 0x11, 0xd9, 0x36, 0x01, 0x67, 0xf3, 0xde, 0xfc, 0x2c, + 0xbe, 0x6e, 0xfa, 0xfa, 0x34, 0xb5, 0xf8, 0xb1, 0xac, 0x15, 0xdb, 0x12, 0xec, + 0x1a, 0xed, 0x2d, 0x31, 0xd2, 0xff, 0x70, 0x12, 0x0d, 0x0c, 0x08, 0xa9, 0x4d, + 0xf3, 0xf1, 0x1f, 0x45, 0x6c, 0xff, 0x5b, 0xc2, 0x8c, 0x0b, 0xff, 0x14, 0xce, + 0x45, 0x55, 0x0d, 0x66, 0x66, 0x13, 0x3d, 0x02, 0xf1, 0x0b, 0xe8, 0xe5, 0x54, + 0xf2, 0xc7, 0xd9, 0xda, 0x01, 0xda, 0xcc, 0xce, 0x29, 0xd0, 0x17, 0xdf, 0xbd, + 0xa6, 0x0c, 0x23, 0x19, 0x22, 0xf6, 0xf4, 0x1a, 0xec, 0xcb, 0x18, 0x57, 0xec, + 0x71, 0x18, 0x34, 0x1c, 0x0e, 0xf8, 0x19, 0xe2, 0x51, 0xa2, 0x3e, 0x90, 0xda, + 0x0d, 0xc8, 0x10, 0x0a, 0x28, 0xa7, 0x72, 0x81, 0xbd, 0x1f, 0x40, 0x1f, 0x9d, + 0x26, 0x0a, 0xdf, 0x0e, 0x1b, 0xde, 0xcf, 0xe1, 0xfe, 0xdb, 0xea, 0x09, 0xf9, + 0x30, 0x45, 0x1c, 0x0d, 0x05, 0xf1, 0xc5, 0xd5, 0x46, 0x04, 0x02, 0x3b, 0xe0, + 0xd5, 0x08, 0x1c, 0x3b, 0x07, 0x54, 0xec, 0x3c, 0xf1, 0xed, 0x7f, 0x15, 0x1d, + 0xf6, 0x2f, 0xd8, 0xc2, 0xfa, 0xd0, 0xd2, 0x34, 0x20, 0x3d, 0x04, 0xe6, 0xde, + 0xf4, 0xef, 0xe2, 0xee, 0x0b, 0xe7, 0xbb, 0xcd, 0x33, 0xf7, 0xca, 0xfd, 0xe9, + 0x42, 0x43, 0x25, 0x7e, 0xdb, 0x4e, 0x16, 0xde, 0xfb, 0xf3, 0x75, 0xfd, 0x8f, + 0xff, 0x13, 0x18, 0x2b, 0x17, 0xdc, 0x0d, 0xd6, 0x0f, 0x37, 0x73, 0xbe, 0x14, + 0xe0, 0x26, 0x38, 0x0f, 0x16, 0x11, 0x02, 0xe3, 0xed, 0x01, 0x23, 0x10, 0x26, + 0x0d, 0xe2, 0x20, 0xff, 0xfb, 0xe2, 0x3d, 0x00, 0x13, 0x01, 0xb4, 0xf3, 0xc0, + 0xfb, 0x4f, 0x56, 0xc7, 0x0a, 0xea, 0x22, 0xd7, 0x15, 0x71, 0xfb, 0x2a, 0x4c, + 0xd9, 0xf8, 0xd7, 0x2c, 0x1e, 0x06, 0xc7, 0xe6, 0xe5, 0xe8, 0x24, 0x20, 0xd6, + 0xbf, 0x1f, 0xf3, 0x08, 0x1e, 0xfb, 0xcd, 0xad, 0xf6, 0x16, 0x6a, 0x31, 0x3e, + 0x32, 0xa6, 0x0a, 0xe3, 0x90, 0x4b, 0xf8, 0x31, 0xcf, 0xc3, 0x10, 0xdf, 0xb8, + 0xfe, 0xb5, 0x0d, 0x9f, 0x2a, 0x1d, 0xf0, 0x0e, 0xd0, 0x5c, 0x0c, 0x0e, 0xd6, + 0x1a, 0xd6, 0x2a, 0xbc, 0xf7, 0x44, 0x22, 0xc4, 0xe2, 0xe4, 0x27, 0x9f, 0xda, + 0x13, 0x38, 0x20, 0x17, 0x44, 0x16, 0xb8, 0xcd, 0x0a, 0x0e, 0x09, 0x53, 0xf0, + 0x2e, 0x0b, 0xb6, 0x7f, 0xfc, 0x41, 0xe6, 0xe2, 0x34, 0xd0, 0x0c, 0x47, 0x19, + 0x4c, 0xa5, 0x0a, 0x04, 0xc5, 0x01, 0xb7, 0xed, 0x3d, 0x35, 0x63, 0xe5, 0x43, + 0xce, 0x22, 0xd1, 0x07, 0x20, 0x6e, 0xe7, 0x29, 0x16, 0x0f, 0x07, 0xf6, 0xd7, + 0xfd, 0x24, 0xf7, 0xd6, 0x16, 0x52, 0xe1, 0xe6, 0xa1, 0xe5, 0x13, 0xf2, 0xb7, + 0x0e, 0xe7, 0x05, 0xe4, 0xe0, 0x20, 0x0e, 0xf4, 0xd5, 0x1a, 0x0e, 0xea, 0xea, + 0xfe, 0xdc, 0x29, 0x30, 0xd6, 0xb7, 0xdd, 0x38, 0xea, 0x2e, 0x18, 0x62, 0x30, + 0xe4, 0xe6, 0xe5, 0xef, 0x1e, 0xf4, 0x03, 0x0e, 0x09, 0xdc, 0x4f, 0x4c, 0x17, + 0xe2, 0x33, 0xf4, 0xfd, 0xe6, 0xf2, 0x24, 0xff, 0x22, 0x50, 0x1d, 0xdd, 0xfd, + 0xc5, 0x21, 0x42, 0x11, 0xce, 0xdf, 0x3c, 0xc2, 0xc6, 0xcd, 0xea, 0xd7, 0x14, + 0x53, 0xc5, 0x02, 0xb8, 0x2b, 0x0b, 0xfc, 0x32, 0xe7, 0xe7, 0x28, 0xc8, 0xd3, + 0x8b, 0x13, 0x0a, 0x50, 0x70, 0xf5, 0x7d, 0x92, 0x45, 0x29, 0xea, 0xf8, 0xdb, + 0xdb, 0xee, 0x17, 0x56, 0x6b, 0x25, 0x08, 0xd8, 0xd7, 0xb5, 0xff, 0xb5, 0x05, + 0x0e, 0x25, 0x13, 0x4f, 0x6a, 0x81, 0x48, 0x24, 0x37, 0x72, 0xc2, 0x25, 0xf8, + 0x59, 0x19, 0xf8, 0x3c, 0xe8, 0x02, 0xff, 0x47, 0xef, 0x59, 0xeb, 0xf9, 0xe9, + 0xf9, 0x35, 0xe2, 0xb8, 0x10, 0xed, 0xb9, 0xfa, 0x2b, 0x1b, 0x0a, 0xf6, 0xb7, + 0xf2, 0xb0, 0x40, 0x1c, 0x15, 0x07, 0xd4, 0xe1, 0x2a, 0x08, 0xf0, 0x20, 0x39, + 0xd8, 0x13, 0x2b, 0x22, 0x2d, 0xdf, 0xe5, 0xf6, 0x13, 0x14, 0x99, 0xc4, 0xc5, + 0x17, 0x2e, 0xeb, 0x0e, 0xd1, 0x1e, 0x17, 0x14, 0xad, 0xdf, 0xbd, 0xf4, 0x24, + 0xef, 0xe8, 0xfa, 0xf6, 0x1c, 0xec, 0xe0, 0x15, 0x08, 0xdc, 0xcc, 0xf1, 0x26, + 0x07, 0xf0, 0x34, 0xdd, 0x21, 0x1f, 0x8f, 0x4c, 0xf3, 0xec, 0x4c, 0x2e, 0xc5, + 0x64, 0x27, 0x37, 0x04, 0xd8, 0xec, 0xe2, 0xeb, 0xa3, 0x21, 0xfa, 0x11, 0x07, + 0x0f, 0x1d, 0x57, 0x40, 0x06, 0xc3, 0xd8, 0x38, 0xd1, 0x08, 0x02, 0x22, 0x18, + 0x19, 0xcd, 0xe8, 0xf3, 0x44, 0xe9, 0xb5, 0xe4, 0xfc, 0x41, 0xd1, 0x1a, 0xf4, + 0x48, 0xe8, 0x0e, 0x6e, 0x2a, 0x7f, 0xec, 0xe3, 0x03, 0xe8, 0x17, 0xf1, 0xe6, + 0x12, 0x4f, 0xeb, 0xe6, 0x20, 0x2b, 0xea, 0x97, 0xfa, 0xda, 0xdd, 0x1c, 0x21, + 0x1c, 0x01, 0x11, 0x12, 0x03, 0xaf, 0x13, 0xd9, 0x2f, 0x10, 0xfc, 0xc4, 0x31, + 0x16, 0xbf, 0xfb, 0x30, 0x03, 0xb4, 0xeb, 0xd9, 0xc6, 0x0b, 0x50, 0x2c, 0x54, + 0xe5, 0xbf, 0x70, 0xba, 0x10, 0xe6, 0xe8, 0x23, 0x17, 0x24, 0x46, 0x18, 0xc9, + 0x2a, 0xb5, 0xec, 0xf4, 0x81, 0x85, 0x21, 0x8e, 0x1a, 0x79, 0xe8, 0x22, 0xf4, + 0xf1, 0xd1, 0xa8, 0xf9, 0x98, 0xba, 0xfe, 0xcc, 0xfb, 0xe7, 0x33, 0x1d, 0x3c, + 0x0a, 0xe5, 0x10, 0x05, 0x30, 0x17, 0xbd, 0x59, 0xe6, 0x49, 0xe2, 0xd0, 0xcf, + 0xb4, 0x35, 0x0d, 0x6e, 0x58, 0xe4, 0x58, 0xac, 0xbe, 0x07, 0x13, 0xd3, 0xf5, + 0xf5, 0x13, 0xfb, 0x35, 0xc0, 0x2d, 0xca, 0x36, 0xa2, 0xff, 0x40, 0x38, 0xef, + 0xf2, 0x1c, 0x1c, 0x05, 0x42, 0xaf, 0x45, 0x25, 0xca, 0x00, 0xdf, 0x3f, 0xb0, + 0xec, 0xd0, 0xe4, 0x1e, 0xec, 0x15, 0x15, 0xf0, 0x2b, 0xef, 0xbc, 0xfc, 0x14, + 0xfd, 0xe0, 0x36, 0x05, 0xad, 0xe2, 0xbd, 0xdc, 0x08, 0x0d, 0xfd, 0xdd, 0xdc, + 0x11, 0xf4, 0xcc, 0x1a, 0xef, 0xe2, 0x07, 0x25, 0x20, 0xd1, 0xe8, 0xd0, 0x45, + 0x7b, 0xdc, 0xee, 0x01, 0xfb, 0xfa, 0xf6, 0x11, 0xc9, 0xa5, 0xda, 0xde, 0x13, + 0xfc, 0xfe, 0xc7, 0x49, 0x08, 0xdb, 0x16, 0x2d, 0xd5, 0xe5, 0xdc, 0xc8, 0x0e, + 0xfd, 0xff, 0xe3, 0x31, 0x48, 0x9f, 0xde, 0x46, 0xdb, 0xf6, 0x0d, 0x3a, 0xf7, + 0xb5, 0x7f, 0x02, 0xc7, 0xa6, 0xdf, 0x04, 0xdc, 0x0c, 0xcb, 0x0b, 0xbb, 0xf7, + 0x4f, 0xf7, 0x46, 0x11, 0x2a, 0x64, 0x1e, 0x37, 0xec, 0xd5, 0x8c, 0xef, 0x3a, + 0x1f, 0x1d, 0x46, 0xdd, 0xeb, 0xcc, 0x1d, 0xe7, 0x99, 0x17, 0x10, 0x12, 0xb8, + 0x17, 0x00, 0xcb, 0x0f, 0x02, 0xcb, 0x10, 0x3e, 0x31, 0x04, 0x51, 0x26, 0x2d, + 0xf9, 0xfe, 0xe0, 0xd0, 0x18, 0xc9, 0x71, 0x32, 0x2a, 0x12, 0xd1, 0xed, 0x2b, + 0x43, 0xb1, 0xe2, 0xf8, 0x28, 0xc6, 0xf7, 0xd8, 0x04, 0x2c, 0xc5, 0x09, 0xf9, + 0x0c, 0xe6, 0x0b, 0xdc, 0x45, 0x31, 0x31, 0xe1, 0x15, 0x40, 0xef, 0x0c, 0x03, + 0xf9, 0xf5, 0xc5, 0x15, 0x1b, 0x05, 0x35, 0xe8, 0xc2, 0xf8, 0xe6, 0x24, 0xcf, + 0x40, 0x37, 0xfc, 0x7f, 0xf1, 0xdd, 0x02, 0x0a, 0xbb, 0xe1, 0x1e, 0x12, 0xd3, + 0xe3, 0x12, 0xd5, 0xec, 0x21, 0xf1, 0xd2, 0x2d, 0xc1, 0xe3, 0xec, 0xf5, 0xfa, + 0xf9, 0xd0, 0x96, 0x2e, 0xfb, 0xcd, 0x20, 0xd6, 0xd2, 0xe5, 0x05, 0x23, 0x23, + 0x2d, 0xff, 0x13, 0x53, 0xec, 0xc7, 0xdb, 0x03, 0xff, 0xf4, 0x2c, 0x04, 0xe6, + 0xea, 0xf2, 0xee, 0xed, 0x5f, 0x12, 0xe0, 0xf4, 0x27, 0xbb, 0xf9, 0xff, 0x14, + 0x0e, 0xcd, 0x00, 0x16, 0xc5, 0xc5, 0x4f, 0x0a, 0xb9, 0x15, 0xfc, 0xca, 0x0f, + 0xf8, 0x0f, 0xde, 0xdc, 0xdd, 0x23, 0x01, 0xf8, 0xf2, 0x2e, 0xe0, 0xf9, 0xf0, + 0x40, 0xe5, 0xf5, 0x2b, 0x1f, 0xc1, 0x02, 0x6b, 0xf4, 0xf2, 0xde, 0xcb, 0x41, + 0x1a, 0x01, 0x52, 0xf3, 0xe5, 0x06, 0xc4, 0x26, 0x21, 0xb3, 0x19, 0xd5, 0xed, + 0x0e, 0xe8, 0xe7, 0xf4, 0xef, 0x1e, 0xdc, 0xef, 0xe8, 0x0d, 0xf9, 0x06, 0xe8, + 0xe9, 0xd2, 0xbd, 0xff, 0x19, 0x1c, 0x14, 0x14, 0x00, 0xfd, 0xdc, 0x04, 0xe8, + 0x81, 0x35, 0x0b, 0x05, 0xcb, 0x00, 0xe7, 0x14, 0xea, 0xd6, 0x0f, 0xe2, 0x03, + 0xbb, 0x00, 0xc3, 0xf7, 0x01, 0xf9, 0x17, 0x0c, 0x1a, 0xe0, 0xe0, 0xcc, 0x63, + 0xf1, 0x22, 0x17, 0xfa, 0xea, 0x2e, 0xea, 0x1b, 0xf5, 0xde, 0x0f, 0xc8, 0xe9, + 0xcc, 0xe3, 0xe7, 0xf1, 0x18, 0x1a, 0x01, 0xe9, 0x15, 0xf9, 0xe2, 0xd2, 0x33, + 0x0d, 0xed, 0x1e, 0x25, 0xf8, 0xb0, 0x13, 0x0d, 0xf2, 0xdf, 0xf3, 0xcf, 0x2e, + 0x24, 0xa0, 0xe6, 0xd2, 0xf7, 0xf7, 0x1f, 0x24, 0x02, 0x2e, 0xde, 0x22, 0xa4, + 0x15, 0xcf, 0xec, 0x05, 0xc8, 0xf9, 0x25, 0x1d, 0x2e, 0x0f, 0xee, 0xc4, 0x64, + 0xaf, 0xcc, 0x38, 0x07, 0x26, 0xba, 0x36, 0x95, 0xfb, 0xbc, 0xfb, 0xf5, 0xb7, + 0xf2, 0xc1, 0x33, 0xc8, 0x44, 0xf9, 0x08, 0xc4, 0x0a, 0xd7, 0x05, 0xd7, 0x58, + 0x44, 0xdc, 0xeb, 0xd8, 0xca, 0xd1, 0x18, 0x18, 0xc3, 0x3a, 0x3c, 0x1c, 0x3f, + 0x0b, 0x1c, 0xec, 0x38, 0xf8, 0xa7, 0xec, 0xef, 0xc5, 0xda, 0xf9, 0xe1, 0x09, + 0x3c, 0x1c, 0x43, 0xfe, 0xc8, 0xef, 0xe1, 0xc1, 0x03, 0xaf, 0x60, 0x2a, 0x9f, + 0xf6, 0x0e, 0xeb, 0x1b, 0xaf, 0x04, 0x38, 0xe6, 0x3e, 0xc1, 0xb7, 0x2a, 0x0b, + 0x04, 0xd0, 0xce, 0x43, 0x81, 0xf7, 0xfc, 0x7c, 0x10, 0xe3, 0xf6, 0xdc, 0xfc, + 0x22, 0xf5, 0x0a, 0x15, 0xdc, 0xed, 0x06, 0xe5, 0xf7, 0x1d, 0x0f, 0x20, 0x51, + 0xe5, 0xe1, 0x0e, 0x3b, 0xef, 0xf4, 0xf0, 0x2f, 0xdc, 0xf1, 0xe7, 0xb6, 0xda, + 0x27, 0xf7, 0xfc, 0xe0, 0xfb, 0x38, 0xfe, 0xb5, 0x01, 0x37, 0x32, 0xf3, 0xfe, + 0xc9, 0xf4, 0x18, 0xd6, 0x39, 0xcd, 0x1b, 0xb1, 0x28, 0xd0, 0x07, 0xee, 0x11, + 0x7f, 0x18, 0xd8, 0xe9, 0xec, 0xd3, 0xd7, 0xd4, 0xdd, 0x05, 0x1e, 0xfd, 0xfb, + 0x54, 0x10, 0xf8, 0x49, 0xe4, 0x08, 0xc2, 0x24, 0x27, 0xb3, 0xe1, 0xdf, 0x47, + 0x0f, 0x3a, 0xd4, 0x02, 0x49, 0x17, 0x1b, 0x04, 0xc7, 0x9e, 0x0a, 0x11, 0x01, + 0x2d, 0x2d, 0x01, 0xf6, 0xfb, 0xfb, 0xff, 0xd8, 0xd6, 0x16, 0x06, 0x42, 0xde, + 0xf4, 0xf3, 0xd8, 0xda, 0x2c, 0xf7, 0xf2, 0xf4, 0x08, 0xc6, 0x1e, 0x2d, 0x30, + 0x05, 0x45, 0x13, 0xee, 0x32, 0xe0, 0x38, 0xfe, 0xd6, 0xdf, 0xd3, 0x19, 0x1b, + 0xd6, 0xfe, 0xe9, 0x06, 0x18, 0x3b, 0xf7, 0xa2, 0x1a, 0x19, 0x39, 0x3c, 0x1e, + 0xec, 0xf1, 0xfd, 0x20, 0xec, 0xd4, 0x52, 0xe8, 0xc7, 0xe9, 0x11, 0xfe, 0xd4, + 0xb2, 0x3e, 0xd5, 0xc1, 0xe3, 0xf4, 0xff, 0xfc, 0x5a, 0xd2, 0x30, 0xb9, 0x01, + 0x0b, 0x51, 0x3c, 0xd2, 0x49, 0x50, 0x11, 0xeb, 0x12, 0x2e, 0xed, 0x0d, 0x39, + 0xf9, 0xf1, 0xa4, 0x58, 0x81, 0xbd, 0x36, 0x30, 0x01, 0xe0, 0xf4, 0xdb, 0xdc, + 0x0e, 0xd4, 0x3a, 0xfc, 0x0c, 0x10, 0x1e, 0x79, 0xb4, 0xd2, 0x25, 0x33, 0x07, + 0xfd, 0xfc, 0x26, 0x2b, 0x00, 0xee, 0x12, 0xd8, 0x37, 0x0c, 0x3a, 0xa4, 0xf4, + 0xcc, 0x22, 0xf6, 0x18, 0x06, 0xde, 0xd8, 0xf7, 0x22, 0xc0, 0x24, 0x1b, 0x2d, + 0x52, 0x00, 0xb8, 0x46, 0xc7, 0xdd, 0x37, 0xbb, 0x18, 0xe8, 0x1c, 0x2b, 0xc4, + 0xde, 0xcd, 0x3f, 0xf9, 0x5e, 0xf5, 0x16, 0xcd, 0x0a, 0x0e, 0x12, 0xfe, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x37, 0x1e, 0x00, 0x00, 0x73, + 0x14, 0x00, 0x00, 0xee, 0x10, 0x00, 0x00, 0xab, 0xe6, 0xff, 0xff, 0xb5, 0x24, + 0x00, 0x00, 0xbc, 0x1e, 0x00, 0x00, 0x49, 0xf0, 0xff, 0xff, 0xd7, 0xfd, 0xff, + 0xff, 0x94, 0x13, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0xf8, 0xfe, 0xff, 0xff, + 0xe0, 0x04, 0x00, 0x00, 0x45, 0xfd, 0xff, 0xff, 0x28, 0xf7, 0xff, 0xff, 0x4a, + 0x16, 0x00, 0x00, 0x13, 0xe3, 0xff, 0xff, 0x3d, 0x06, 0x00, 0x00, 0xc9, 0x1a, + 0x00, 0x00, 0x2b, 0xf5, 0xff, 0xff, 0x5c, 0x31, 0x00, 0x00, 0x3d, 0x10, 0x00, + 0x00, 0xe8, 0xef, 0xff, 0xff, 0x88, 0x2e, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, + 0x0f, 0xfe, 0xff, 0xff, 0x9c, 0xec, 0xff, 0xff, 0x7c, 0xf9, 0xff, 0xff, 0x49, + 0x03, 0x00, 0x00, 0x96, 0xf4, 0xff, 0xff, 0x87, 0xf7, 0xff, 0xff, 0x37, 0xdb, + 0xff, 0xff, 0x52, 0x10, 0x00, 0x00, 0xd3, 0xfb, 0xff, 0xff, 0x15, 0xf7, 0xff, + 0xff, 0xfa, 0xe9, 0xff, 0xff, 0x54, 0xf6, 0xff, 0xff, 0x16, 0x22, 0x00, 0x00, + 0xb7, 0xf1, 0xff, 0xff, 0x3a, 0xfe, 0xff, 0xff, 0x67, 0xe4, 0xff, 0xff, 0x84, + 0xfd, 0xff, 0xff, 0x5c, 0x09, 0x00, 0x00, 0x5d, 0xfb, 0xff, 0xff, 0x4d, 0x1c, + 0x00, 0x00, 0x40, 0x28, 0x00, 0x00, 0x5a, 0xe0, 0xff, 0xff, 0x6f, 0xf3, 0xff, + 0xff, 0xdd, 0xf8, 0xff, 0xff, 0xc4, 0x03, 0x00, 0x00, 0x71, 0x23, 0x00, 0x00, + 0xe8, 0x21, 0x00, 0x00, 0xce, 0xf2, 0xff, 0xff, 0x42, 0xed, 0xff, 0xff, 0xe7, + 0xf1, 0xff, 0xff, 0xb6, 0xf2, 0xff, 0xff, 0x66, 0xfd, 0xff, 0xff, 0xc8, 0xf0, + 0xff, 0xff, 0xba, 0xfd, 0xff, 0xff, 0xc6, 0xff, 0xff, 0xff, 0x2e, 0xfb, 0xff, + 0xff, 0x1b, 0x1b, 0x00, 0x00, 0x41, 0xe0, 0xff, 0xff, 0xfe, 0xfd, 0xff, 0xff, + 0x61, 0xf0, 0xff, 0xff, 0x50, 0xf0, 0xff, 0xff, 0x8a, 0xea, 0xff, 0xff, 0x04, + 0xe3, 0xff, 0xff, 0x5b, 0xe1, 0xff, 0xff, 0xb5, 0xeb, 0xff, 0xff, 0x90, 0xf8, + 0xff, 0xff, 0x89, 0xe8, 0xff, 0xff, 0x83, 0xfa, 0xff, 0xff, 0x0e, 0xef, 0xff, + 0xff, 0x19, 0x22, 0x00, 0x00, 0xe8, 0xf9, 0xff, 0xff, 0xfc, 0xf4, 0xff, 0xff, + 0x2f, 0xff, 0xff, 0xff, 0x62, 0x05, 0x00, 0x00, 0x93, 0xf9, 0xff, 0xff, 0x00, + 0xfc, 0xff, 0xff, 0xcb, 0x1a, 0x00, 0x00, 0x2c, 0xea, 0xff, 0xff, 0x53, 0x17, + 0x00, 0x00, 0xbb, 0xdc, 0xff, 0xff, 0x77, 0x01, 0x00, 0x00, 0x5f, 0xf2, 0xff, + 0xff, 0x95, 0x03, 0x00, 0x00, 0x29, 0x04, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, + 0x4a, 0x25, 0x00, 0x00, 0xfc, 0xfd, 0xff, 0xff, 0xfd, 0x01, 0x00, 0x00, 0x49, + 0xf4, 0xff, 0xff, 0xba, 0xf9, 0xff, 0xff, 0xc2, 0xf8, 0xff, 0xff, 0xf9, 0x0d, + 0x00, 0x00, 0x88, 0x06, 0x00, 0x00, 0xbd, 0x0d, 0x00, 0x00, 0x79, 0xec, 0xff, + 0xff, 0x71, 0xed, 0xff, 0xff, 0x90, 0x15, 0x00, 0x00, 0x56, 0xeb, 0xff, 0xff, + 0x32, 0x2c, 0x00, 0x00, 0xda, 0xfd, 0xff, 0xff, 0x87, 0xf9, 0xff, 0xff, 0x0d, + 0x07, 0x00, 0x00, 0xe0, 0x12, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x7c, 0xfb, + 0xff, 0xff, 0xbb, 0x04, 0x00, 0x00, 0xdf, 0xdf, 0xff, 0xff, 0x98, 0xeb, 0xff, + 0xff, 0x2d, 0xf4, 0xff, 0xff, 0xfc, 0x09, 0x00, 0x00, 0xa9, 0x17, 0x00, 0x00, + 0x5a, 0x04, 0x00, 0x00, 0x98, 0xef, 0xff, 0xff, 0xb4, 0xec, 0xff, 0xff, 0x80, + 0x02, 0x00, 0x00, 0xc4, 0xfe, 0xff, 0xff, 0x04, 0x05, 0x00, 0x00, 0xb3, 0x09, + 0x00, 0x00, 0xc1, 0x1e, 0x00, 0x00, 0x19, 0x12, 0x00, 0x00, 0x75, 0xf7, 0xff, + 0xff, 0x02, 0x03, 0x00, 0x00, 0x1b, 0x0a, 0x00, 0x00, 0x94, 0x0b, 0x00, 0x00, + 0x1a, 0x14, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x9b, + 0x00, 0x00, 0x00, 0xff, 0xf3, 0xff, 0xff, 0x23, 0x01, 0x00, 0x00, 0x7a, 0xfc, + 0xff, 0xff, 0x2a, 0xd9, 0xff, 0xff, 0x8c, 0x05, 0x00, 0x00, 0xda, 0x38, 0x00, + 0x00, 0xc8, 0xdb, 0xff, 0xff, 0x19, 0xe9, 0xff, 0xff, 0xc0, 0x3e, 0x00, 0x00, + 0x17, 0x20, 0x00, 0x00, 0x22, 0x24, 0x00, 0x00, 0x66, 0x31, 0x00, 0x00, 0x73, + 0x21, 0x00, 0x00, 0x22, 0xe6, 0xff, 0xff, 0xfb, 0x3b, 0x00, 0x00, 0xfa, 0xe4, + 0xff, 0xff, 0x63, 0xf2, 0xff, 0xff, 0xef, 0x27, 0x00, 0x00, 0x55, 0xfe, 0xff, + 0xff, 0x92, 0x09, 0x00, 0x00, 0xa7, 0x24, 0x00, 0x00, 0x6f, 0xc0, 0xff, 0xff, + 0xe4, 0xad, 0xff, 0xff, 0x64, 0x13, 0x00, 0x00, 0xe8, 0xf3, 0xff, 0xff, 0x64, + 0xb3, 0xff, 0xff, 0xee, 0xea, 0xff, 0xff, 0xe8, 0xde, 0xff, 0xff, 0x59, 0x2a, + 0x00, 0x00, 0xaa, 0x3f, 0x00, 0x00, 0xf8, 0x12, 0x00, 0x00, 0x25, 0x0f, 0x00, + 0x00, 0x7b, 0x15, 0x00, 0x00, 0xfe, 0x0a, 0x00, 0x00, 0x1c, 0x24, 0x00, 0x00, + 0xa9, 0x05, 0x00, 0x00, 0xb3, 0xef, 0xff, 0xff, 0x75, 0xfc, 0xff, 0xff, 0x5f, + 0xec, 0xff, 0xff, 0x35, 0x06, 0x00, 0x00, 0xe6, 0x13, 0x00, 0x00, 0x33, 0xf6, + 0xff, 0xff, 0x46, 0xfe, 0xff, 0xff, 0x60, 0xef, 0xff, 0xff, 0x53, 0xee, 0xff, + 0xff, 0x80, 0xf4, 0xff, 0xff, 0xe9, 0xf3, 0xff, 0xff, 0xe5, 0xdf, 0xff, 0xff, + 0x68, 0xf8, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x01, 0x3e, 0x00, 0x00, 0xb2, + 0x28, 0x00, 0x00, 0x56, 0x14, 0x00, 0x00, 0x13, 0x09, 0x00, 0x00, 0x32, 0xd7, + 0xff, 0xff, 0x7c, 0x27, 0x00, 0x00, 0x61, 0x0d, 0x00, 0x00, 0x26, 0xd1, 0xff, + 0xff, 0xa2, 0x39, 0x00, 0x00, 0x69, 0xf4, 0xff, 0xff, 0x60, 0xf9, 0xff, 0xff, + 0x99, 0xe1, 0xff, 0xff, 0xd2, 0x02, 0x00, 0x00, 0x33, 0xe6, 0xff, 0xff, 0x1f, + 0x17, 0x00, 0x00, 0x71, 0x51, 0x00, 0x00, 0xed, 0x41, 0x00, 0x00, 0x9d, 0x26, + 0x00, 0x00, 0xa0, 0xf2, 0xff, 0xff, 0xe1, 0xf2, 0xff, 0xff, 0xee, 0xe8, 0xff, + 0xff, 0x0d, 0xe7, 0xff, 0xff, 0xef, 0x01, 0x00, 0x00, 0x11, 0xd0, 0xff, 0xff, + 0xee, 0x0e, 0x00, 0x00, 0xdc, 0xf4, 0xff, 0xff, 0xa1, 0xff, 0xff, 0xff, 0x67, + 0xdf, 0xff, 0xff, 0x4a, 0xd0, 0xff, 0xff, 0xcd, 0xd2, 0xff, 0xff, 0x10, 0xdd, + 0xff, 0xff, 0xcc, 0xdd, 0xff, 0xff, 0xd7, 0xf8, 0xff, 0xff, 0x61, 0x37, 0x00, + 0x00, 0xcb, 0xed, 0xff, 0xff, 0xb4, 0xe5, 0xff, 0xff, 0xc6, 0xe4, 0xff, 0xff, + 0x32, 0x0c, 0x00, 0x00, 0x8c, 0x3d, 0x00, 0x00, 0x03, 0x3d, 0x00, 0x00, 0x69, + 0xe8, 0xff, 0xff, 0xd6, 0x20, 0x00, 0x00, 0xc0, 0xd5, 0xff, 0xff, 0x56, 0xe8, + 0xff, 0xff, 0x41, 0x2f, 0x00, 0x00, 0xbf, 0x21, 0x00, 0x00, 0xbb, 0x02, 0x00, + 0x00, 0x4a, 0x71, 0x00, 0x00, 0x73, 0x18, 0x00, 0x00, 0x7e, 0x3b, 0x00, 0x00, + 0xc2, 0x6d, 0x00, 0x00, 0x83, 0xfc, 0xff, 0xff, 0x65, 0xfe, 0xff, 0xff, 0x67, + 0xfc, 0xff, 0xff, 0xcc, 0x8d, 0x00, 0x00, 0xf9, 0xd0, 0xff, 0xff, 0x2a, 0x14, + 0x00, 0x00, 0x33, 0xe4, 0xff, 0xff, 0x1b, 0x1e, 0x00, 0x00, 0x75, 0xf8, 0xff, + 0xff, 0xb9, 0xc9, 0xff, 0xff, 0x8a, 0x34, 0x00, 0x00, 0x78, 0xe6, 0xff, 0xff, + 0xa9, 0x27, 0x00, 0x00, 0xab, 0x04, 0x00, 0x00, 0x66, 0xe5, 0xff, 0xff, 0x70, + 0xa2, 0xff, 0xff, 0x23, 0xe8, 0xff, 0xff, 0x5f, 0xe5, 0xff, 0xff, 0x48, 0xe7, + 0xff, 0xff, 0x3e, 0x08, 0x00, 0x00, 0xa6, 0x3d, 0x00, 0x00, 0x0d, 0x11, 0x00, + 0x00, 0xe5, 0x2f, 0x00, 0x00, 0x3c, 0x55, 0x00, 0x00, 0xd9, 0xf8, 0xff, 0xff, + 0xc8, 0x00, 0x00, 0x00, 0x26, 0x16, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0xf1, 0xf7, 0xff, 0xff, 0x03, 0x2a, 0x00, 0x00, 0xfb, 0xd0, + 0xff, 0xff, 0xef, 0xe6, 0xff, 0xff, 0x63, 0x08, 0x00, 0x00, 0x6c, 0xe5, 0xff, + 0xff, 0x15, 0x20, 0x00, 0x00, 0x25, 0xf0, 0xff, 0xff, 0x94, 0x2a, 0x00, 0x00, + 0x2b, 0x29, 0x00, 0x00, 0xa3, 0xee, 0xff, 0xff, 0xb1, 0x01, 0x00, 0x00, 0xa4, + 0x27, 0x00, 0x00, 0xde, 0xdd, 0xff, 0xff, 0x9b, 0xfd, 0xff, 0xff, 0x54, 0xfb, + 0xff, 0xff, 0x8b, 0xed, 0xff, 0xff, 0x4d, 0xe5, 0xff, 0xff, 0x4b, 0xe5, 0xff, + 0xff, 0x0f, 0xc8, 0xff, 0xff, 0x31, 0xf6, 0xff, 0xff, 0xdc, 0xdb, 0xff, 0xff, + 0x92, 0xf7, 0xff, 0xff, 0xdb, 0xef, 0xff, 0xff, 0x49, 0xfe, 0xff, 0xff, 0x8d, + 0xf2, 0xff, 0xff, 0x56, 0xe5, 0xff, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xbb, 0xf1, + 0xff, 0xff, 0xe3, 0x05, 0x00, 0x00, 0x51, 0xf5, 0xff, 0xff, 0x0a, 0xfb, 0xff, + 0xff, 0x6e, 0xe7, 0xff, 0xff, 0x42, 0x1c, 0x00, 0x00, 0x89, 0xeb, 0xff, 0xff, + 0x71, 0xf0, 0xff, 0xff, 0x53, 0xeb, 0xff, 0xff, 0x24, 0x05, 0x00, 0x00, 0x0b, + 0x20, 0x00, 0x00, 0x28, 0xfe, 0xff, 0xff, 0xd0, 0x2d, 0x00, 0x00, 0x49, 0x07, + 0x00, 0x00, 0xef, 0x24, 0x00, 0x00, 0xf1, 0xfb, 0xff, 0xff, 0x44, 0x0e, 0x00, + 0x00, 0x9c, 0x22, 0x00, 0x00, 0x5f, 0xe6, 0xff, 0xff, 0x39, 0xe5, 0xff, 0xff, + 0xc1, 0xff, 0xff, 0xff, 0xa8, 0xfa, 0xff, 0xff, 0x90, 0xe7, 0xff, 0xff, 0xdd, + 0xf9, 0xff, 0xff, 0x81, 0xee, 0xff, 0xff, 0xa5, 0x26, 0x00, 0x00, 0xe4, 0xeb, + 0xff, 0xff, 0xb7, 0x23, 0x00, 0x00, 0xcf, 0xe4, 0xff, 0xff, 0x39, 0xf6, 0xff, + 0xff, 0x07, 0xfd, 0xff, 0xff, 0x14, 0xfe, 0xff, 0xff, 0xf5, 0x1e, 0x00, 0x00, + 0xde, 0xf7, 0xff, 0xff, 0xad, 0xef, 0xff, 0xff, 0x2a, 0xe7, 0xff, 0xff, 0x5b, + 0xec, 0xff, 0xff, 0xba, 0xfe, 0xff, 0xff, 0x63, 0xee, 0xff, 0xff, 0x92, 0xff, + 0xff, 0xff, 0xd5, 0xf8, 0xff, 0xff, 0xda, 0xdb, 0xff, 0xff, 0x79, 0x05, 0x00, + 0x00, 0xed, 0xf2, 0xff, 0xff, 0x8c, 0xe2, 0xff, 0xff, 0x5c, 0xee, 0xff, 0xff, + 0x07, 0xe5, 0xff, 0xff, 0xee, 0x01, 0x00, 0x00, 0xe2, 0xe6, 0xff, 0xff, 0xf7, + 0xed, 0xff, 0xff, 0x8f, 0x2a, 0x00, 0x00, 0x2e, 0x28, 0x00, 0x00, 0xc1, 0x26, + 0x00, 0x00, 0x9f, 0xe5, 0xff, 0xff, 0x6a, 0x03, 0x00, 0x00, 0xc1, 0xef, 0xff, + 0xff, 0x37, 0xf8, 0xff, 0xff, 0x47, 0xf0, 0xff, 0xff, 0xfa, 0x22, 0x00, 0x00, + 0xb5, 0xf5, 0xff, 0xff, 0xd0, 0xfd, 0xff, 0xff, 0x11, 0xef, 0xff, 0xff, 0x1f, + 0x2e, 0x00, 0x00, 0x65, 0xe9, 0xff, 0xff, 0x08, 0x1d, 0x00, 0x00, 0x77, 0xdb, + 0xff, 0xff, 0x36, 0xf9, 0xff, 0xff, 0xab, 0xe2, 0xff, 0xff, 0xfb, 0x16, 0x00, + 0x00, 0x53, 0xf5, 0xff, 0xff, 0x96, 0x2c, 0x00, 0x00, 0x10, 0xe1, 0xff, 0xff, + 0xb4, 0xf8, 0xff, 0xff, 0x20, 0x1a, 0x00, 0x00, 0x98, 0xe4, 0xff, 0xff, 0x9b, + 0x27, 0x00, 0x00, 0x23, 0x2c, 0x00, 0x00, 0x07, 0x2e, 0x00, 0x00, 0xd2, 0xfb, + 0xff, 0xff, 0x15, 0xec, 0xff, 0xff, 0x52, 0x20, 0x00, 0x00, 0x9a, 0xf0, 0xff, + 0xff, 0xcc, 0x2c, 0x00, 0x00, 0x58, 0xee, 0xff, 0xff, 0x79, 0x25, 0x00, 0x00, + 0xaf, 0xea, 0xff, 0xff, 0x90, 0xf4, 0xff, 0xff, 0x4c, 0x21, 0x00, 0x00, 0x3d, + 0xf0, 0xff, 0xff, 0x56, 0xf9, 0xff, 0xff, 0x36, 0xef, 0xff, 0xff, 0x77, 0xea, + 0xff, 0xff, 0x77, 0xfc, 0xff, 0xff, 0xf0, 0xd8, 0xff, 0xff, 0x18, 0x29, 0x00, + 0x00, 0x9d, 0x0c, 0x00, 0x00, 0x0f, 0x26, 0x00, 0x00, 0xa1, 0x30, 0x00, 0x00, + 0x74, 0xea, 0xff, 0xff, 0x47, 0xf1, 0xff, 0xff, 0x32, 0x18, 0xfe, 0xff, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xdb, 0x02, 0x20, 0x9a, 0x25, 0x14, + 0x19, 0x7f, 0xc5, 0x6c, 0xfe, 0xd7, 0x27, 0xd0, 0x05, 0xef, 0x21, 0xdb, 0x5c, + 0xc6, 0x0f, 0x08, 0xf8, 0x01, 0x2a, 0xff, 0xcb, 0xf5, 0xe1, 0x28, 0xa5, 0x94, + 0x45, 0xfd, 0xdd, 0xf7, 0xd6, 0xfb, 0x18, 0xda, 0x0a, 0xf8, 0xec, 0x23, 0xe2, + 0x28, 0xd7, 0x3a, 0x11, 0x15, 0x15, 0x0d, 0xe2, 0xb6, 0x0a, 0xf1, 0x9f, 0xab, + 0xf4, 0xed, 0x18, 0x0e, 0x0f, 0xef, 0xf1, 0xea, 0xeb, 0x11, 0xf5, 0xbd, 0xfd, + 0xf0, 0x52, 0x1f, 0xdd, 0xe3, 0xcd, 0xc3, 0x10, 0xc0, 0xdd, 0xe6, 0x01, 0x33, + 0xfa, 0x1b, 0x6a, 0xb7, 0x1a, 0xeb, 0x43, 0x0e, 0x32, 0x07, 0xed, 0xe0, 0xdd, + 0x2c, 0x2c, 0xe9, 0xc9, 0x17, 0xfa, 0x1e, 0x4b, 0x7f, 0x28, 0xef, 0x51, 0xed, + 0x9d, 0x57, 0x6a, 0xe6, 0xcb, 0x1d, 0xba, 0x20, 0xb6, 0x7c, 0x1c, 0x06, 0xf2, + 0xb2, 0xfb, 0x2b, 0x13, 0x1a, 0xcd, 0x03, 0xce, 0xda, 0xb9, 0x27, 0x38, 0x05, + 0xe9, 0x33, 0x2b, 0xf9, 0x4e, 0x32, 0xbb, 0xe8, 0x15, 0xae, 0x31, 0x18, 0xce, + 0x47, 0x1e, 0xf7, 0x3b, 0xe2, 0x02, 0x23, 0xcf, 0x08, 0xf4, 0xe4, 0xf7, 0x23, + 0xe9, 0x2f, 0xbb, 0xde, 0xe9, 0xe4, 0xf7, 0x1b, 0x01, 0x19, 0xf5, 0x58, 0x42, + 0x06, 0x04, 0x12, 0x08, 0x7f, 0x0d, 0x2c, 0x06, 0x0e, 0x06, 0xee, 0xe2, 0x20, + 0xb7, 0xe0, 0xf4, 0x1e, 0xf6, 0xc9, 0x1b, 0x10, 0xf6, 0x64, 0xe0, 0xcc, 0xdc, + 0x14, 0x2d, 0x30, 0xfd, 0xc3, 0x21, 0x21, 0xcd, 0xc6, 0xf3, 0x10, 0x12, 0xec, + 0x01, 0xdc, 0xe9, 0xde, 0x23, 0xe0, 0x1a, 0x23, 0xfa, 0x24, 0xe7, 0x1b, 0x0f, + 0x11, 0x0f, 0x37, 0xdc, 0xee, 0x11, 0x0a, 0x16, 0x73, 0xf1, 0xcf, 0xd4, 0x20, + 0xf6, 0x4d, 0x1d, 0x0d, 0x25, 0x09, 0x0e, 0xc4, 0xf6, 0xd0, 0xe2, 0x34, 0xe4, + 0xf1, 0xf9, 0xe1, 0x42, 0xf6, 0xef, 0x0c, 0x67, 0x35, 0xf9, 0xe8, 0xc7, 0x03, + 0x23, 0x1e, 0x20, 0x3b, 0x3e, 0xd8, 0xf5, 0x47, 0xcb, 0xb1, 0xac, 0xcf, 0xe4, + 0xfa, 0x14, 0x07, 0x07, 0x76, 0xc3, 0xeb, 0x66, 0x1f, 0x52, 0xe5, 0xbb, 0xc5, + 0x59, 0x1a, 0xd8, 0xf7, 0x02, 0xdd, 0x2c, 0x4d, 0x96, 0x44, 0x00, 0x1a, 0x2e, + 0xd8, 0x08, 0x44, 0x1b, 0xfd, 0xfb, 0x39, 0xc1, 0xf1, 0xde, 0x4c, 0xed, 0x56, + 0x19, 0x48, 0xc3, 0xeb, 0xec, 0x08, 0xb8, 0x0d, 0x16, 0xdf, 0xdd, 0xce, 0x0b, + 0x59, 0xde, 0x99, 0xe6, 0x0c, 0xac, 0xd0, 0x43, 0x1d, 0xb2, 0xd9, 0x03, 0xd9, + 0xfc, 0xde, 0xf7, 0xa9, 0xf9, 0x33, 0xf6, 0xde, 0x1d, 0xd8, 0x3a, 0xe8, 0x43, + 0xaa, 0x8f, 0xd6, 0xb5, 0x11, 0x4f, 0x24, 0x15, 0xa2, 0xb2, 0xf6, 0xce, 0xfa, + 0xc4, 0x0b, 0x1c, 0x84, 0x65, 0xf9, 0xb1, 0x15, 0x0c, 0xf7, 0xc8, 0xca, 0x81, + 0xf0, 0xe2, 0x4c, 0xba, 0x0e, 0x23, 0xc0, 0x36, 0x11, 0xe9, 0x11, 0xf9, 0xb4, + 0xe8, 0xe8, 0xf5, 0x30, 0xb6, 0x0d, 0xc1, 0x08, 0xb6, 0xb3, 0x23, 0x9e, 0xf3, + 0xe2, 0xb0, 0x00, 0x37, 0xf5, 0xf9, 0x0b, 0xb1, 0x22, 0xc0, 0xed, 0x01, 0x23, + 0xeb, 0xec, 0x24, 0xee, 0xe2, 0x1d, 0xfb, 0xe0, 0xf9, 0xc5, 0x2a, 0xf9, 0x81, + 0x19, 0xb9, 0xf7, 0x4b, 0x28, 0x10, 0xe1, 0x34, 0x02, 0x1f, 0xd2, 0x05, 0xf9, + 0xdf, 0xf6, 0x27, 0x06, 0x16, 0xfe, 0xcf, 0xf6, 0xff, 0xfc, 0xce, 0xe8, 0xe8, + 0xf4, 0xd9, 0x13, 0xb4, 0x1b, 0x08, 0x0a, 0x40, 0xf4, 0x27, 0x0a, 0x21, 0x1e, + 0xf4, 0xdc, 0x17, 0x50, 0x0f, 0xe5, 0x36, 0xf6, 0xe8, 0xe0, 0x41, 0x22, 0xe9, + 0x24, 0x2c, 0x40, 0x18, 0xe5, 0xfa, 0xf2, 0x16, 0xf6, 0x34, 0x09, 0xfa, 0x46, + 0x01, 0xf2, 0x9d, 0x2b, 0x38, 0x2e, 0x1f, 0xd4, 0x25, 0x17, 0xf8, 0x05, 0x39, + 0xb2, 0xf3, 0x2b, 0xd6, 0xfe, 0xc6, 0xb4, 0xf0, 0x0f, 0x90, 0x45, 0xc0, 0xa4, + 0x24, 0x44, 0x13, 0x08, 0x14, 0x03, 0xa6, 0xca, 0x98, 0xa5, 0x0f, 0x47, 0xd4, + 0xef, 0x36, 0x0d, 0x9a, 0x6f, 0xbb, 0xf7, 0x0a, 0x1b, 0xd6, 0xe4, 0x07, 0x00, + 0x02, 0x27, 0xb3, 0xff, 0x6c, 0x1b, 0xd9, 0x00, 0x2e, 0xa9, 0x7f, 0xdc, 0x28, + 0x9c, 0x97, 0xc2, 0xdb, 0x30, 0xeb, 0x1c, 0x2d, 0x3b, 0x09, 0x15, 0xe9, 0x39, + 0x41, 0x63, 0xe4, 0x9a, 0x3f, 0x08, 0xf0, 0x59, 0x00, 0xf8, 0x38, 0x17, 0xdc, + 0x24, 0x31, 0xb7, 0x58, 0xe9, 0x00, 0xf7, 0xf5, 0x2a, 0x28, 0x01, 0xf5, 0xf2, + 0xf4, 0x0d, 0x49, 0xfc, 0x12, 0xd4, 0x64, 0xae, 0x35, 0x34, 0xb7, 0x2d, 0xf8, + 0x03, 0xd2, 0x06, 0x23, 0xcb, 0x09, 0xd9, 0xee, 0x54, 0xb5, 0x0a, 0xc4, 0x66, + 0x14, 0xc7, 0x17, 0xd7, 0xde, 0x23, 0xd8, 0x11, 0x16, 0x22, 0xfc, 0xff, 0xce, + 0x3f, 0x10, 0xf5, 0xf9, 0x3e, 0x13, 0xf8, 0xfc, 0xdb, 0xe3, 0x55, 0x09, 0xec, + 0xdc, 0x11, 0x04, 0x15, 0x13, 0x19, 0xfc, 0x7f, 0xef, 0x02, 0x0a, 0xee, 0xed, + 0x28, 0xe4, 0x13, 0x2d, 0x08, 0x0b, 0x21, 0xfd, 0xe4, 0x09, 0xc6, 0xc1, 0x34, + 0x04, 0x04, 0x0a, 0xe5, 0xfa, 0xd1, 0x22, 0x04, 0x0f, 0x03, 0xdc, 0xf9, 0x2c, + 0xe1, 0xd1, 0xfa, 0xdc, 0xed, 0x2a, 0x65, 0x06, 0x2e, 0xf9, 0x2f, 0x02, 0x9b, + 0xeb, 0x2f, 0xe8, 0x02, 0xe3, 0x0c, 0x10, 0x10, 0xe9, 0x02, 0xfa, 0xfe, 0x13, + 0x12, 0xd4, 0xcb, 0xd4, 0xfd, 0xe8, 0xe1, 0xf2, 0x25, 0x05, 0xc8, 0xec, 0xf7, + 0xce, 0x01, 0x3c, 0xda, 0xfb, 0xcf, 0xfd, 0xf0, 0x44, 0xf9, 0x11, 0x0a, 0xf3, + 0x04, 0x26, 0xf8, 0xdf, 0xed, 0x0e, 0xdd, 0x1c, 0x02, 0xc9, 0xd8, 0xfb, 0xdb, + 0x0d, 0xf5, 0x10, 0xd5, 0xf5, 0xea, 0x3a, 0xea, 0x03, 0xfd, 0x17, 0xf5, 0x04, + 0x16, 0xff, 0xf8, 0x09, 0xe2, 0xe9, 0x4c, 0xf8, 0x4f, 0xd5, 0x27, 0xd4, 0x4a, + 0x20, 0x40, 0x7f, 0xeb, 0xcf, 0xe4, 0x26, 0xfd, 0x18, 0x08, 0xce, 0x0c, 0x13, + 0x08, 0xda, 0x12, 0x24, 0xe2, 0x25, 0x3f, 0xeb, 0x08, 0x24, 0xb4, 0x1e, 0x03, + 0xf1, 0xcc, 0x00, 0xbe, 0xb6, 0x0d, 0x21, 0x10, 0x1a, 0xf5, 0xf7, 0x05, 0xfa, + 0x03, 0x14, 0x00, 0xe7, 0x3c, 0x28, 0xe8, 0x58, 0x1e, 0xbf, 0x12, 0x62, 0xcb, + 0x7a, 0xfb, 0x1e, 0xf5, 0x1d, 0xf1, 0xe7, 0xf7, 0xd8, 0x06, 0xcc, 0xda, 0xfc, + 0x19, 0xc5, 0xf6, 0xdd, 0x10, 0xd5, 0x24, 0xfd, 0x26, 0xf1, 0xbd, 0xbf, 0x40, + 0xf6, 0x41, 0x3e, 0x1f, 0x51, 0xdc, 0xbe, 0x39, 0x19, 0x20, 0xe0, 0xbe, 0x04, + 0x1e, 0x08, 0xfb, 0xf6, 0x26, 0x0b, 0xc2, 0xc9, 0x13, 0x2c, 0x34, 0x37, 0xfe, + 0xf2, 0x1a, 0xe6, 0xe8, 0x29, 0x1a, 0x18, 0x15, 0xe7, 0x75, 0xd2, 0xdd, 0x13, + 0xde, 0x0b, 0xec, 0x24, 0xd8, 0xd9, 0xd2, 0x06, 0x2a, 0x10, 0xbe, 0xc6, 0xf9, + 0x19, 0x22, 0x57, 0xb9, 0xef, 0x1a, 0xd2, 0xe7, 0xfe, 0x07, 0x22, 0x0c, 0x2c, + 0x26, 0x81, 0xb0, 0xcb, 0xf6, 0x34, 0x15, 0x43, 0xf2, 0x0a, 0x42, 0xdf, 0xdc, + 0xc8, 0xe7, 0xd2, 0xef, 0xf9, 0x17, 0xee, 0x0e, 0xe1, 0x19, 0x0c, 0xb0, 0x36, + 0x0e, 0x24, 0xee, 0x37, 0x24, 0x09, 0xf8, 0xb4, 0x0c, 0x38, 0xfc, 0xf5, 0x4c, + 0xc0, 0x27, 0xff, 0x19, 0xf1, 0x23, 0x0a, 0xba, 0x4a, 0x54, 0x46, 0xae, 0x00, + 0xcf, 0xe4, 0xd7, 0xd6, 0xc6, 0x05, 0x13, 0xbb, 0x08, 0xed, 0xd0, 0x05, 0x5f, + 0xcd, 0xf2, 0xdf, 0xff, 0xca, 0xc1, 0xc6, 0xfc, 0x0f, 0x7c, 0xd2, 0x17, 0x40, + 0x00, 0xed, 0x98, 0xcd, 0x23, 0xbd, 0xf2, 0xce, 0xf8, 0x07, 0x35, 0x4f, 0xed, + 0x02, 0xee, 0x14, 0x46, 0x25, 0xe9, 0xe7, 0x90, 0x38, 0x24, 0xec, 0x09, 0xa8, + 0xf5, 0x59, 0x15, 0x28, 0xf7, 0x05, 0xee, 0x0e, 0x1b, 0xe5, 0x64, 0xfe, 0x36, + 0xd4, 0x2f, 0x72, 0xe8, 0x37, 0xda, 0xd7, 0x15, 0xc1, 0x92, 0x19, 0x01, 0x21, + 0xa9, 0xb1, 0xdf, 0x46, 0x1c, 0x2e, 0x08, 0xd1, 0x48, 0xe8, 0xe3, 0x37, 0x5d, + 0x0d, 0x3c, 0xf6, 0xa3, 0xeb, 0xa5, 0xce, 0x07, 0xf5, 0xae, 0x1c, 0x0f, 0x5d, + 0x5b, 0x2d, 0xa3, 0x24, 0x4e, 0x50, 0x10, 0xe1, 0x1d, 0x2a, 0x26, 0x18, 0x4b, + 0xdc, 0x32, 0xcd, 0x20, 0xf9, 0xe0, 0xfe, 0x9a, 0xe3, 0xe2, 0xb5, 0x3f, 0xfe, + 0x35, 0xe6, 0xa9, 0x37, 0xb6, 0xf0, 0x40, 0x0a, 0xc4, 0xd7, 0xf0, 0x72, 0x03, + 0xe8, 0xeb, 0x11, 0xf3, 0xf1, 0xcd, 0x1c, 0xe2, 0x29, 0x1b, 0xe1, 0x21, 0x1b, + 0xe4, 0x25, 0x09, 0xc7, 0x37, 0xbf, 0x81, 0x33, 0x86, 0x0d, 0xcc, 0xe7, 0xce, + 0x32, 0xf7, 0x11, 0x03, 0x1c, 0xed, 0xe8, 0xea, 0x42, 0x96, 0x00, 0x3f, 0x07, + 0xf2, 0xfd, 0x19, 0x2a, 0xc7, 0x0a, 0x0e, 0x62, 0xb3, 0x1a, 0xab, 0x0f, 0xb2, + 0x28, 0x19, 0xf3, 0xdb, 0x1c, 0x26, 0xf0, 0xf5, 0x2a, 0x19, 0xad, 0xcc, 0xcf, + 0x26, 0x3a, 0x34, 0xc1, 0xff, 0x07, 0x1d, 0xec, 0x21, 0xcc, 0x1a, 0xbf, 0x11, + 0xcb, 0x0c, 0x2d, 0x3a, 0x0a, 0xcd, 0x10, 0x4c, 0x12, 0xfa, 0xd0, 0xf9, 0xe6, + 0x1b, 0xb1, 0xe5, 0xd8, 0x2b, 0x13, 0xf5, 0xe4, 0x22, 0x21, 0x01, 0x45, 0xf9, + 0x1d, 0xfb, 0x25, 0xf8, 0x35, 0x4d, 0xca, 0x19, 0x30, 0xcf, 0xee, 0x02, 0xe3, + 0xf1, 0x1b, 0x0d, 0xe2, 0x23, 0x3f, 0x26, 0x34, 0x00, 0x5a, 0x0a, 0x7f, 0xed, + 0x39, 0x1b, 0x09, 0xdd, 0x0e, 0xca, 0xbf, 0xc1, 0x1b, 0x54, 0x3c, 0x38, 0xb0, + 0xf8, 0x32, 0x24, 0x24, 0x0a, 0xe7, 0x25, 0x5c, 0xca, 0x33, 0x18, 0xdc, 0x3c, + 0xc9, 0xfa, 0x06, 0x47, 0x08, 0xfc, 0x17, 0x07, 0x10, 0xfe, 0xbe, 0xe1, 0xe5, + 0x31, 0x49, 0xdb, 0xdc, 0xab, 0x2b, 0x04, 0xe2, 0xe2, 0xc6, 0x40, 0xff, 0x02, + 0xdc, 0xe2, 0xe8, 0x21, 0x07, 0xf0, 0xf7, 0xe8, 0x32, 0xf0, 0x46, 0x36, 0x0a, + 0xe6, 0xd4, 0x04, 0xd2, 0xc1, 0x52, 0xe1, 0x13, 0x17, 0x0c, 0xca, 0x2d, 0xe3, + 0x28, 0xdc, 0xc8, 0x06, 0xf0, 0xb5, 0x0c, 0xc9, 0x47, 0x43, 0xde, 0x2b, 0x3f, + 0x23, 0x37, 0xb9, 0x09, 0x1a, 0x25, 0x57, 0x74, 0xec, 0xbe, 0x09, 0xe7, 0x54, + 0xd0, 0xf1, 0x19, 0x07, 0x3e, 0x81, 0xca, 0x21, 0xe4, 0x07, 0x10, 0x1a, 0xca, + 0x2c, 0xe9, 0xc3, 0xce, 0x4c, 0xf8, 0x1b, 0x33, 0x12, 0x26, 0x12, 0x1b, 0x09, + 0xdd, 0xe3, 0xef, 0x00, 0xdc, 0xed, 0xbb, 0xef, 0x13, 0xf9, 0x07, 0xf0, 0x14, + 0xf8, 0x1a, 0xf2, 0xf0, 0x32, 0x13, 0xf1, 0x16, 0x01, 0x25, 0xef, 0x9a, 0xc3, + 0xfa, 0x02, 0x03, 0x0e, 0xe4, 0xb7, 0x11, 0x10, 0xd3, 0xec, 0x11, 0x3c, 0x30, + 0xe5, 0xe3, 0x37, 0x0a, 0xd3, 0xf0, 0xfb, 0xf8, 0x20, 0x06, 0x14, 0xfc, 0x1d, + 0x18, 0x24, 0xfa, 0x3e, 0x6c, 0x0c, 0xce, 0xe4, 0x36, 0x38, 0xb6, 0x1b, 0xe4, + 0xf8, 0x23, 0xe8, 0x00, 0xe8, 0x06, 0x0a, 0xcf, 0xeb, 0xfb, 0xde, 0xf7, 0x44, + 0xef, 0xde, 0xee, 0x98, 0x11, 0xfe, 0x35, 0xef, 0xde, 0x23, 0x07, 0xbf, 0x35, + 0x0e, 0x02, 0xfc, 0x7f, 0xd5, 0x09, 0xd7, 0x1e, 0xf6, 0x09, 0xcb, 0xef, 0x09, + 0x24, 0xf0, 0xec, 0xf3, 0xa7, 0xea, 0x22, 0x26, 0x1b, 0x39, 0x13, 0x4d, 0xf7, + 0xc4, 0xd7, 0xe7, 0xf4, 0x07, 0xf6, 0xf8, 0x08, 0xe3, 0xd6, 0x1c, 0x60, 0xb3, + 0xbc, 0x0c, 0xf5, 0xd0, 0x05, 0x31, 0xf0, 0x60, 0xbf, 0x00, 0xbc, 0xcd, 0x4b, + 0xbc, 0xdb, 0x0d, 0xf4, 0xec, 0xf2, 0x26, 0xc9, 0x1c, 0x25, 0xae, 0x5f, 0x4f, + 0xf6, 0xea, 0xd3, 0xb9, 0x96, 0xe6, 0x3a, 0x2f, 0xff, 0x05, 0x2d, 0xa4, 0x12, + 0x56, 0x5b, 0xec, 0xcb, 0xd1, 0x29, 0x9a, 0xb9, 0x27, 0x02, 0x22, 0x3c, 0x0f, + 0x1f, 0xec, 0x9f, 0xfc, 0x97, 0xf5, 0x0c, 0xfb, 0x10, 0x03, 0xf0, 0x27, 0xb6, + 0x67, 0xe9, 0xd9, 0xa3, 0xbd, 0x3a, 0xe2, 0xe1, 0xa0, 0xcb, 0x40, 0x2f, 0x3f, + 0x01, 0xf1, 0xfe, 0x81, 0xf8, 0x4e, 0x8b, 0x06, 0x09, 0x2f, 0x46, 0x12, 0xc5, + 0x15, 0xd0, 0x14, 0x8f, 0x1a, 0xea, 0x1d, 0x14, 0x3b, 0x0c, 0x74, 0x1c, 0x87, + 0x31, 0xd4, 0xd6, 0x39, 0xac, 0xc2, 0x32, 0x3d, 0x04, 0xcd, 0xd2, 0x16, 0x6d, + 0xc3, 0x3d, 0xf7, 0x02, 0xe4, 0x02, 0xd6, 0xac, 0x2a, 0x66, 0x02, 0xa3, 0xb8, + 0xec, 0xe3, 0xea, 0x4a, 0xeb, 0xec, 0x2c, 0xf8, 0x42, 0xec, 0x2b, 0xe0, 0x2f, + 0x30, 0xfb, 0x1d, 0xe3, 0xed, 0x2a, 0x5a, 0xd7, 0x5d, 0x12, 0x9f, 0x06, 0xdd, + 0x09, 0xce, 0x09, 0xc6, 0x09, 0xf1, 0xfd, 0xe5, 0x1e, 0xe4, 0xe6, 0xab, 0x17, + 0x97, 0xe4, 0xcb, 0xdc, 0x32, 0xd6, 0xc4, 0xb6, 0x0e, 0xfe, 0x38, 0x2d, 0xc1, + 0x03, 0xe1, 0x0f, 0xf8, 0xaf, 0xf2, 0x02, 0xba, 0xfc, 0x16, 0xaf, 0xc1, 0x26, + 0x0b, 0xe7, 0x3e, 0x35, 0x0a, 0x59, 0x0e, 0x7a, 0xc4, 0x55, 0xf8, 0xe2, 0xce, + 0x7c, 0xc7, 0xb9, 0xff, 0xcb, 0xf1, 0xed, 0xf5, 0x06, 0xe3, 0xa7, 0x81, 0xec, + 0xcb, 0x04, 0xc0, 0x16, 0xf6, 0x3d, 0xcc, 0x2d, 0xe6, 0xe5, 0x09, 0x12, 0x58, + 0x24, 0x21, 0x17, 0xc7, 0xeb, 0xe8, 0xcb, 0x08, 0xd8, 0x09, 0x83, 0xdc, 0xb5, + 0x16, 0xf5, 0xf2, 0xc8, 0xa6, 0x2a, 0xe1, 0xf7, 0x37, 0xf0, 0x2a, 0xe9, 0xf5, + 0x19, 0xe8, 0x19, 0xc8, 0x2c, 0x13, 0xdb, 0x57, 0x2b, 0xd1, 0x49, 0xff, 0x0d, + 0xff, 0x0e, 0x15, 0xd9, 0x14, 0x1d, 0x05, 0x24, 0xb6, 0x6d, 0xed, 0x03, 0xaf, + 0x3d, 0x2f, 0x9b, 0xfe, 0x00, 0xed, 0xf8, 0xd9, 0x3d, 0xfc, 0x2c, 0x1f, 0xdc, + 0xa4, 0xcc, 0x1e, 0xd0, 0x32, 0x10, 0xbb, 0x09, 0xff, 0xea, 0x94, 0xf3, 0x1b, + 0xf7, 0xeb, 0xea, 0xfa, 0x30, 0xc8, 0xdf, 0xdb, 0x08, 0xea, 0x18, 0xd1, 0x41, + 0x30, 0xf6, 0xf5, 0xd3, 0xdf, 0xad, 0x1b, 0xb0, 0x0b, 0x14, 0xf9, 0xf6, 0xf3, + 0x11, 0xe7, 0xed, 0xfb, 0x35, 0x1c, 0xcf, 0x1e, 0xb9, 0xfd, 0x4b, 0xe4, 0xd8, + 0x23, 0x12, 0x05, 0x0d, 0xf5, 0x43, 0x08, 0x11, 0xed, 0x03, 0xde, 0xe7, 0x34, + 0xfe, 0xc9, 0xfa, 0xdb, 0x2a, 0x16, 0x28, 0x87, 0x1f, 0x09, 0xe2, 0x25, 0x27, + 0xdd, 0x4d, 0x1a, 0xff, 0xd9, 0x4f, 0x1e, 0x36, 0xe3, 0xde, 0x81, 0x4f, 0x53, + 0x43, 0xf3, 0x3b, 0x03, 0xeb, 0xc4, 0xe7, 0x21, 0x4b, 0x02, 0x17, 0x19, 0xff, + 0x04, 0xdb, 0xbb, 0x0d, 0xf0, 0xe3, 0x74, 0xc0, 0x15, 0xef, 0x06, 0x0a, 0xfb, + 0xfd, 0x0b, 0xc9, 0xd5, 0x28, 0x09, 0xc9, 0x2d, 0x19, 0x01, 0x27, 0x2f, 0x1d, + 0x7b, 0xde, 0xe4, 0xd9, 0xfa, 0x09, 0x2d, 0xed, 0xfd, 0xe2, 0x3d, 0x02, 0xde, + 0xaf, 0x02, 0xe5, 0x2f, 0xca, 0x66, 0xc4, 0xcd, 0x0d, 0x06, 0x06, 0xa5, 0x2b, + 0xc9, 0xe6, 0x02, 0x1f, 0xbc, 0x35, 0x04, 0xf7, 0xd8, 0x2c, 0xec, 0x20, 0x1c, + 0x0f, 0x13, 0x75, 0xed, 0x1a, 0x21, 0x23, 0x38, 0x22, 0x12, 0x08, 0xed, 0xc3, + 0xe7, 0xff, 0x32, 0xa1, 0x18, 0x46, 0xf0, 0x4c, 0xe8, 0x08, 0x7a, 0xe0, 0xe2, + 0x15, 0x81, 0xa2, 0x0f, 0xdb, 0xac, 0x1f, 0xf5, 0x14, 0x4a, 0x24, 0x3c, 0x05, + 0xe6, 0x5e, 0x3f, 0x05, 0x36, 0xef, 0xb3, 0x0d, 0x2d, 0xe4, 0xb3, 0xe7, 0x02, + 0x29, 0xf4, 0xf1, 0x6b, 0xe0, 0x02, 0x3f, 0xe3, 0x3e, 0x33, 0x21, 0xef, 0x4e, + 0xfd, 0xe9, 0x4e, 0x30, 0xe1, 0x09, 0xa6, 0xf5, 0xf3, 0xc2, 0x04, 0x9c, 0xe2, + 0xd9, 0x0d, 0xdf, 0x06, 0x9c, 0xbd, 0xf7, 0xd6, 0x0b, 0xf8, 0xda, 0xf3, 0x26, + 0xf9, 0x15, 0xeb, 0x2c, 0xc1, 0xa8, 0xcf, 0xed, 0x20, 0x92, 0x21, 0xde, 0xd0, + 0xf4, 0xc5, 0x28, 0x0c, 0x0f, 0xe1, 0x3b, 0xf9, 0xd7, 0xe4, 0x04, 0xe9, 0x84, + 0x00, 0x3a, 0xeb, 0xea, 0x04, 0x0d, 0xb2, 0xd7, 0xfb, 0x2f, 0xf8, 0x06, 0xeb, + 0xf2, 0xf9, 0x06, 0xf1, 0xc2, 0x0e, 0xf7, 0x00, 0x89, 0xd3, 0x62, 0xda, 0xed, + 0x19, 0x1a, 0xf5, 0x07, 0x15, 0xe6, 0xf5, 0x7f, 0xeb, 0x36, 0xe2, 0x5b, 0x16, + 0xdc, 0x0a, 0x00, 0xcc, 0xfd, 0xf5, 0x01, 0xe9, 0x02, 0xc7, 0x25, 0x40, 0xac, + 0xd0, 0x4a, 0xf5, 0xeb, 0xf8, 0xfb, 0x8c, 0x3d, 0x1f, 0x0b, 0x11, 0x2f, 0x3d, + 0x21, 0xb2, 0xfc, 0x36, 0xfa, 0x2f, 0x20, 0x0d, 0x26, 0x1d, 0xec, 0xca, 0x12, + 0x0d, 0x3d, 0x11, 0x2c, 0x9c, 0x1c, 0x3b, 0x25, 0x15, 0x16, 0xd4, 0x3b, 0xce, + 0x63, 0x7f, 0x50, 0xe2, 0x18, 0xdc, 0xbd, 0xd5, 0xe8, 0x42, 0xdd, 0x7c, 0xd6, + 0xce, 0x0c, 0x16, 0xf6, 0x05, 0xf7, 0x19, 0xde, 0xf8, 0xff, 0xe8, 0xf4, 0xef, + 0xd7, 0xee, 0xee, 0x02, 0x6a, 0x49, 0x57, 0xd2, 0x09, 0xdc, 0xb6, 0x4d, 0x00, + 0xfd, 0x4b, 0xf5, 0x3d, 0x01, 0x35, 0xf5, 0x1e, 0x10, 0xef, 0x35, 0x05, 0x71, + 0x23, 0x1e, 0x03, 0xfe, 0xd3, 0xe2, 0x48, 0xfa, 0x1a, 0xc5, 0x48, 0xda, 0x44, + 0xe2, 0xc3, 0x08, 0xc0, 0x16, 0xd9, 0xaa, 0x36, 0xdd, 0x1b, 0xe2, 0x40, 0xf5, + 0x09, 0x3c, 0x88, 0x1c, 0x3e, 0x15, 0x1f, 0xd2, 0x04, 0xde, 0xfd, 0xc9, 0xe4, + 0x29, 0x02, 0x0d, 0xd0, 0x1f, 0x20, 0xff, 0x7a, 0xd9, 0xd2, 0x0f, 0xed, 0x05, + 0x43, 0x38, 0x18, 0xd1, 0xf6, 0x0e, 0x18, 0x0c, 0xb4, 0xef, 0xc0, 0xfd, 0xdb, + 0x41, 0x33, 0xa3, 0x2a, 0x10, 0x57, 0x52, 0x27, 0x54, 0x06, 0x0b, 0xe6, 0xf9, + 0xf6, 0xff, 0xef, 0xa6, 0x20, 0xbc, 0x34, 0xda, 0xfa, 0x20, 0xcf, 0x1a, 0x02, + 0xd0, 0xc4, 0xc3, 0xdd, 0x47, 0xe0, 0xb6, 0xbd, 0xe5, 0x48, 0x1a, 0x38, 0xa8, + 0x26, 0x14, 0x25, 0x08, 0xdc, 0xc8, 0xa5, 0xbe, 0x71, 0xc6, 0x81, 0x13, 0xb3, + 0xee, 0xcf, 0x19, 0xe4, 0x07, 0x08, 0x19, 0xae, 0xa0, 0x92, 0xab, 0x55, 0xc0, + 0xc6, 0xf3, 0xbf, 0x0d, 0xe3, 0x6b, 0xb3, 0xe4, 0xfa, 0x82, 0x58, 0x3b, 0xd9, + 0xb7, 0xef, 0xbb, 0x22, 0xdb, 0x1c, 0xc1, 0x14, 0xec, 0x08, 0xc7, 0x29, 0xca, + 0x71, 0x8c, 0xcf, 0xef, 0x69, 0xde, 0x4a, 0x68, 0xeb, 0x13, 0x07, 0xf9, 0x19, + 0x0a, 0xa4, 0x11, 0xf8, 0x1b, 0x28, 0x25, 0xea, 0x68, 0xea, 0xb8, 0xd2, 0x12, + 0xc4, 0xff, 0x27, 0xa4, 0xf1, 0xf6, 0x26, 0x4f, 0x43, 0xf8, 0xca, 0xf1, 0xf9, + 0xcf, 0xe7, 0xec, 0xe5, 0xfd, 0xc9, 0xdf, 0x41, 0x04, 0xe5, 0xef, 0xf8, 0xa7, + 0xf0, 0x00, 0xfd, 0x1c, 0xd0, 0xa7, 0xcc, 0x05, 0xc5, 0x03, 0x18, 0x15, 0xf5, + 0x03, 0xc2, 0x7f, 0xc2, 0x25, 0xf6, 0xcf, 0x1a, 0xe5, 0xf4, 0xda, 0x2b, 0x11, + 0x09, 0x21, 0xa8, 0x09, 0xde, 0x54, 0xcf, 0xc5, 0x05, 0x48, 0xf9, 0x06, 0x36, + 0xc5, 0xde, 0xdb, 0xc2, 0xd2, 0x3e, 0x17, 0x35, 0xee, 0x00, 0x17, 0xe7, 0xf8, + 0xf5, 0x1c, 0x03, 0x48, 0x2a, 0xff, 0x35, 0x32, 0x16, 0xfb, 0x1c, 0xf8, 0xea, + 0x07, 0xdf, 0x02, 0x47, 0x33, 0x16, 0x02, 0x11, 0xda, 0xef, 0x3c, 0x04, 0x1b, + 0xd0, 0xb7, 0x03, 0xf9, 0x04, 0x57, 0x45, 0xc8, 0xae, 0xf1, 0x1b, 0xfd, 0x40, + 0xf3, 0x24, 0xae, 0x11, 0xd4, 0x1a, 0x31, 0x16, 0x0f, 0x2a, 0x9d, 0xef, 0x26, + 0x0d, 0x07, 0x10, 0xfd, 0xc0, 0x4e, 0xfd, 0xe4, 0xb0, 0x28, 0xd3, 0xc0, 0xdc, + 0xf1, 0xed, 0xe9, 0x2d, 0x04, 0xd2, 0x13, 0x65, 0xfa, 0xd8, 0xe8, 0x30, 0x7f, + 0xdd, 0xf9, 0xfb, 0x63, 0x11, 0xcd, 0x1e, 0xf1, 0xc2, 0xc9, 0x3e, 0x8f, 0xf0, + 0x32, 0xd4, 0xf4, 0xaf, 0x03, 0xe7, 0x71, 0x20, 0x32, 0xe9, 0xb6, 0xfd, 0xed, + 0x42, 0x01, 0xb2, 0xef, 0xc2, 0xf8, 0xe8, 0xe4, 0xc9, 0x1a, 0xc1, 0x27, 0x6d, + 0xe9, 0x17, 0x24, 0xd0, 0x03, 0x24, 0xca, 0xd8, 0xd3, 0xf1, 0x0a, 0x09, 0xd9, + 0xfa, 0x0b, 0xe1, 0x20, 0xce, 0xe9, 0x29, 0x3a, 0xf7, 0xe9, 0xe8, 0xec, 0xfd, + 0x16, 0xf9, 0xee, 0xf1, 0xf4, 0xee, 0xd3, 0xda, 0x9f, 0xe2, 0xbb, 0xf4, 0x06, + 0x12, 0xf5, 0x04, 0xf4, 0x1a, 0xda, 0x4c, 0x25, 0x1a, 0xdd, 0x0d, 0x18, 0xc1, + 0xc4, 0x26, 0x1a, 0xdb, 0x13, 0xf9, 0x21, 0xf8, 0xf5, 0x51, 0xd3, 0x2f, 0xf2, + 0x4b, 0xb7, 0xfb, 0x2a, 0x1e, 0x1c, 0xdd, 0xea, 0x00, 0xce, 0x33, 0x2e, 0x02, + 0xde, 0x22, 0xf0, 0xe4, 0x0b, 0x2c, 0xf2, 0x7f, 0xaa, 0x20, 0x1b, 0x0a, 0x2d, + 0xe4, 0xfe, 0x36, 0xea, 0xe8, 0x1f, 0x1e, 0xe2, 0x3c, 0x0e, 0xcc, 0xf4, 0x05, + 0x2a, 0xd9, 0x11, 0x03, 0xda, 0xf9, 0xf9, 0x24, 0x00, 0x18, 0x10, 0x22, 0x2d, + 0xcf, 0x16, 0x24, 0x0f, 0x22, 0x2a, 0x02, 0xee, 0xe3, 0xd6, 0xf5, 0x5b, 0xf5, + 0x44, 0x09, 0xc3, 0xb4, 0xf0, 0x36, 0xe2, 0xb4, 0x0a, 0xea, 0x9b, 0xbf, 0xea, + 0x07, 0xd5, 0x53, 0xf4, 0x2a, 0x06, 0x1c, 0x1c, 0xe5, 0xf2, 0xdc, 0x0b, 0x0d, + 0x5d, 0x03, 0xf7, 0xcb, 0xe6, 0x16, 0xee, 0xe1, 0x17, 0x07, 0xb8, 0xe5, 0xe5, + 0x01, 0xeb, 0xe2, 0xec, 0xd8, 0x1a, 0xe7, 0x47, 0xd0, 0x11, 0x04, 0xf7, 0x29, + 0xe1, 0xfb, 0x0f, 0x45, 0xc7, 0x19, 0x36, 0xd1, 0xc3, 0xed, 0x2f, 0xd3, 0xee, + 0xbc, 0x00, 0xf0, 0xe6, 0xc6, 0x09, 0xe1, 0x17, 0x01, 0x2d, 0x10, 0xb4, 0x39, + 0x04, 0xc0, 0xda, 0x18, 0xde, 0xc9, 0xbf, 0x7f, 0x28, 0x05, 0x0e, 0x02, 0x35, + 0xfc, 0xf4, 0x39, 0xfa, 0xea, 0x22, 0x2e, 0xee, 0x29, 0xf8, 0x3e, 0x18, 0xe7, + 0x36, 0xe0, 0xf4, 0xbd, 0x0c, 0x33, 0x04, 0x0e, 0xfd, 0x39, 0x16, 0x0f, 0x13, + 0xc8, 0xc6, 0x13, 0xd6, 0x21, 0x4e, 0x0d, 0x0c, 0x0f, 0x35, 0x2d, 0x2e, 0x11, + 0x3c, 0x4c, 0x2d, 0x9a, 0x05, 0x10, 0x1f, 0xf2, 0xb7, 0xc2, 0xca, 0xe5, 0x02, + 0xc9, 0x19, 0xec, 0x34, 0x02, 0xd5, 0x4b, 0x15, 0xe9, 0x6e, 0xea, 0xda, 0xed, + 0x04, 0xd7, 0x20, 0xfa, 0xdd, 0xde, 0x17, 0x01, 0x13, 0x05, 0x18, 0x25, 0xc9, + 0x43, 0x19, 0x09, 0xbe, 0xe6, 0xfd, 0xda, 0xc4, 0xf1, 0xe8, 0xb7, 0x21, 0x5e, + 0x2b, 0x02, 0x34, 0x1c, 0x0c, 0x39, 0xb0, 0xff, 0xe3, 0x05, 0x00, 0x60, 0xf0, + 0x16, 0xf8, 0x0e, 0x2a, 0x9f, 0x31, 0x19, 0xc8, 0xcd, 0xd6, 0xd9, 0x28, 0x23, + 0xdb, 0x4d, 0x4e, 0xd8, 0xeb, 0xec, 0xc7, 0xcf, 0x37, 0xbc, 0x51, 0x64, 0x79, + 0xf5, 0x38, 0xfa, 0xeb, 0xf8, 0xd1, 0x5a, 0xc9, 0x00, 0x50, 0xe8, 0xe9, 0x0c, + 0xec, 0x30, 0x54, 0xdf, 0xfb, 0x5e, 0x17, 0xe9, 0x6d, 0x25, 0x53, 0xe2, 0xba, + 0xfb, 0xb0, 0xee, 0xda, 0xfb, 0x33, 0xaa, 0xcc, 0xe9, 0xd1, 0xeb, 0x0a, 0xbf, + 0x10, 0xd1, 0xdd, 0x08, 0x14, 0x12, 0x91, 0x3c, 0xd3, 0x14, 0xc2, 0xf4, 0x69, + 0xc9, 0xeb, 0x22, 0xfd, 0xfd, 0xe6, 0x19, 0x52, 0xfa, 0xd5, 0xe8, 0x06, 0xe2, + 0x04, 0xce, 0x81, 0x07, 0xa0, 0x37, 0x24, 0x1a, 0x03, 0xce, 0x18, 0x21, 0x44, + 0x1d, 0x37, 0xc1, 0xce, 0x3e, 0x38, 0xc7, 0xb7, 0xe6, 0xd5, 0x1e, 0xa5, 0xf1, + 0x5b, 0xdf, 0xf0, 0x50, 0x4e, 0xf6, 0x0a, 0x2d, 0x09, 0xec, 0xf6, 0x01, 0xab, + 0xde, 0xb5, 0x1f, 0xfc, 0xfc, 0x98, 0x05, 0x32, 0xcf, 0xd3, 0xd0, 0xcd, 0xc7, + 0x02, 0xc6, 0x01, 0x17, 0x05, 0x01, 0xe6, 0xd9, 0x10, 0xc5, 0x15, 0x17, 0x72, + 0x15, 0xe8, 0xdb, 0x41, 0x43, 0xff, 0xcf, 0xc9, 0xbf, 0xce, 0xf2, 0x08, 0x1c, + 0xd8, 0xf9, 0xc8, 0x2a, 0xc3, 0xf5, 0x26, 0xd1, 0x0a, 0xae, 0x55, 0x38, 0x6c, + 0xbc, 0xd6, 0xf7, 0x83, 0x0b, 0x51, 0x69, 0xed, 0x6e, 0x50, 0xb2, 0x28, 0xbf, + 0x5c, 0x1d, 0x37, 0x1c, 0x85, 0xec, 0x18, 0xf0, 0xba, 0x65, 0xdd, 0x05, 0xfd, + 0x18, 0xd8, 0x28, 0xdc, 0x26, 0xce, 0xce, 0xe6, 0x7f, 0x29, 0xbc, 0x51, 0x2d, + 0xff, 0x04, 0xbd, 0x01, 0xa9, 0xea, 0x24, 0xca, 0x0b, 0xf7, 0xe7, 0x19, 0x5b, + 0x1f, 0x12, 0x0a, 0xb5, 0xde, 0x20, 0x30, 0x39, 0xe4, 0xec, 0xb2, 0x30, 0xd3, + 0xc2, 0xc9, 0xb0, 0x03, 0xe6, 0x30, 0xe0, 0xed, 0x43, 0xd2, 0xd8, 0xfd, 0xfd, + 0xdd, 0x14, 0xfc, 0xfc, 0xf9, 0xee, 0x16, 0x15, 0x28, 0x07, 0x16, 0x1e, 0x19, + 0x40, 0x19, 0x28, 0xf9, 0x0c, 0xeb, 0x09, 0x1e, 0xf5, 0xec, 0xdd, 0x33, 0x15, + 0xf8, 0xe9, 0x0b, 0xd9, 0x16, 0x02, 0x00, 0x24, 0xdc, 0xe8, 0xda, 0x31, 0x08, + 0xe5, 0x0f, 0x1d, 0xf0, 0xf3, 0xd9, 0xe5, 0x0b, 0x0a, 0x16, 0x02, 0x0c, 0x9b, + 0xff, 0xf5, 0xf6, 0xe6, 0x31, 0x06, 0xf4, 0xf9, 0xca, 0xe0, 0x1e, 0xfc, 0xec, + 0x27, 0x3e, 0xd1, 0xd1, 0xf0, 0xda, 0x24, 0x1d, 0xd7, 0x15, 0xf5, 0xf2, 0xfe, + 0xfd, 0xdf, 0xf1, 0xdc, 0xc5, 0xec, 0xf4, 0x02, 0xe7, 0xea, 0x04, 0xda, 0x1c, + 0x14, 0x0a, 0xf9, 0x27, 0x13, 0xee, 0xf2, 0x12, 0x03, 0x12, 0x05, 0x7f, 0x0a, + 0xf4, 0xf9, 0xe0, 0x10, 0x09, 0x20, 0xf3, 0x14, 0xe5, 0x0c, 0x17, 0x15, 0xf5, + 0xd8, 0xf1, 0x38, 0x0e, 0x00, 0xf0, 0x34, 0x06, 0x15, 0x6c, 0x55, 0x16, 0xfa, + 0xeb, 0xd9, 0xb6, 0x28, 0x2b, 0xb9, 0x1b, 0x32, 0xd1, 0x50, 0x45, 0x81, 0x05, + 0x09, 0x02, 0xb6, 0xfb, 0xa8, 0x19, 0x62, 0xe4, 0xe0, 0x0f, 0xef, 0x4e, 0x37, + 0xd0, 0xeb, 0xd5, 0xb0, 0xa6, 0x54, 0xb7, 0xf8, 0xe9, 0xfd, 0x17, 0xdd, 0x3a, + 0x0c, 0x5a, 0xf2, 0x44, 0x01, 0xe6, 0xa6, 0x9d, 0x12, 0xb3, 0x20, 0xec, 0xb8, + 0xbb, 0x02, 0xdf, 0x0b, 0x16, 0x09, 0x02, 0x38, 0x3f, 0x04, 0x28, 0x49, 0x39, + 0x1c, 0x05, 0xff, 0xe1, 0x22, 0xcd, 0x1d, 0x09, 0xea, 0xca, 0xc2, 0xf2, 0xf8, + 0x1e, 0xf9, 0x93, 0x13, 0xe4, 0x46, 0x26, 0x08, 0xac, 0xe0, 0xcb, 0x96, 0x09, + 0x01, 0xff, 0xae, 0x10, 0xf8, 0x46, 0x22, 0x2b, 0xda, 0x1a, 0xd7, 0xef, 0xf2, + 0xc0, 0x33, 0xed, 0xa4, 0x20, 0xf8, 0xd9, 0x08, 0xc8, 0xec, 0x65, 0x13, 0x1c, + 0x05, 0x1c, 0xdc, 0x1b, 0xe5, 0x0b, 0x0d, 0x02, 0x0e, 0xca, 0x2d, 0xff, 0x24, + 0x00, 0x15, 0xfc, 0xea, 0x00, 0xf4, 0xfc, 0xfa, 0xe0, 0x04, 0x3c, 0xe1, 0x0c, + 0xfa, 0x42, 0xf9, 0xf5, 0x25, 0xeb, 0xb5, 0xfa, 0x0c, 0x32, 0x35, 0xcf, 0xf2, + 0xcc, 0xf5, 0x12, 0x1f, 0x0d, 0x1b, 0xc6, 0x25, 0xdb, 0xe6, 0xfb, 0xff, 0xcc, + 0xd9, 0xe3, 0xe9, 0xd4, 0xcf, 0x3e, 0xd5, 0x2c, 0x1c, 0x12, 0xfa, 0x39, 0xde, + 0xe1, 0xd3, 0x0d, 0xe9, 0x7f, 0x0b, 0xd5, 0x0e, 0xfc, 0xdf, 0xcc, 0xef, 0xf9, + 0x5a, 0xe2, 0xfc, 0xd9, 0xe2, 0xce, 0xe6, 0xf4, 0xa5, 0x12, 0x32, 0x13, 0xf4, + 0x29, 0x04, 0xec, 0xfd, 0x24, 0x1b, 0x01, 0xd8, 0x25, 0x18, 0x1e, 0xec, 0xef, + 0xa7, 0x20, 0x10, 0xe5, 0xf7, 0x02, 0xc0, 0xe0, 0x33, 0x10, 0x20, 0x2e, 0x3e, + 0xf6, 0x0d, 0xf3, 0x2f, 0xe4, 0xe3, 0x13, 0x2f, 0xcf, 0xd3, 0x29, 0xf1, 0xf6, + 0x02, 0x3b, 0xf7, 0xf5, 0xf8, 0xfa, 0xea, 0x0e, 0x46, 0x0e, 0xfe, 0xed, 0xe1, + 0x0a, 0x09, 0xea, 0x11, 0x16, 0xe3, 0xd6, 0xfc, 0x7f, 0xf6, 0xce, 0x26, 0xe7, + 0xef, 0xf4, 0xec, 0xff, 0xf0, 0xfe, 0x25, 0x28, 0x28, 0xdc, 0xd4, 0x15, 0x04, + 0xdd, 0x40, 0xce, 0x0e, 0xf8, 0x03, 0x20, 0x0a, 0xf9, 0x01, 0x15, 0x2d, 0xeb, + 0x08, 0x03, 0xd9, 0xe4, 0xc7, 0xfb, 0x24, 0x20, 0x14, 0xe4, 0x13, 0xfd, 0xd9, + 0xfb, 0xf7, 0x20, 0xd8, 0xdf, 0x11, 0xe7, 0x0e, 0xe1, 0xf6, 0xbe, 0xfd, 0xe8, + 0xef, 0x0b, 0xee, 0x02, 0x1b, 0x11, 0x06, 0x05, 0xf5, 0x14, 0x23, 0xf5, 0xf2, + 0xe9, 0x13, 0xca, 0x2c, 0x1c, 0xeb, 0xc8, 0x02, 0x04, 0xf3, 0xcd, 0x19, 0x25, + 0xbf, 0xe4, 0xed, 0x07, 0x0b, 0xea, 0x1a, 0x09, 0xec, 0xef, 0x1c, 0xd7, 0x0b, + 0x0a, 0xef, 0x22, 0x19, 0x02, 0x1c, 0xd2, 0xf6, 0xd1, 0xed, 0x4c, 0xfb, 0xf7, + 0x28, 0x20, 0x2e, 0x0b, 0xea, 0x03, 0x2b, 0x05, 0xde, 0xed, 0x00, 0x18, 0x73, + 0x26, 0xc4, 0x1e, 0x0e, 0xd5, 0xe2, 0x05, 0x15, 0xf8, 0x40, 0xd7, 0xe9, 0x45, + 0xdb, 0x01, 0xcf, 0x06, 0xfd, 0x09, 0xff, 0x0a, 0x17, 0xec, 0x81, 0xae, 0x0e, + 0xfd, 0x04, 0x20, 0xff, 0xe8, 0x7e, 0x25, 0x4d, 0xc3, 0xe9, 0x12, 0xfa, 0x16, + 0x12, 0x07, 0x0d, 0x42, 0x98, 0x00, 0x05, 0xdd, 0x00, 0x33, 0x0d, 0xe0, 0xfe, + 0xe8, 0xab, 0xa1, 0xf4, 0x10, 0x25, 0xd4, 0xf3, 0x1b, 0x03, 0x1a, 0x07, 0xff, + 0xc8, 0xf5, 0xf1, 0xf5, 0x8d, 0xea, 0xe2, 0x12, 0xc5, 0xe9, 0x5f, 0x2c, 0xd0, + 0x0c, 0xf2, 0x23, 0x2f, 0xf7, 0x0f, 0x21, 0x13, 0x1a, 0x15, 0x5b, 0x11, 0xf8, + 0xf3, 0xfa, 0xf7, 0xf8, 0x06, 0xf2, 0x36, 0xcc, 0x3e, 0x2c, 0xff, 0x12, 0x0c, + 0xf4, 0xfa, 0xf3, 0xfd, 0xf6, 0xdd, 0x06, 0x22, 0x0a, 0xa4, 0xdf, 0x1f, 0x28, + 0xf8, 0x42, 0xdf, 0xe9, 0x36, 0x19, 0xc6, 0x14, 0x27, 0xc6, 0x00, 0xeb, 0x04, + 0x0f, 0x2e, 0x41, 0xc0, 0xea, 0xab, 0xf4, 0xc9, 0x0e, 0xf5, 0xbb, 0x7d, 0xdd, + 0xdf, 0x48, 0x0e, 0x12, 0xe3, 0x2c, 0x4e, 0xe6, 0xd6, 0xfc, 0xd8, 0x44, 0xfe, + 0x17, 0x53, 0x0b, 0x0b, 0xfa, 0x2c, 0x37, 0x38, 0xea, 0x7f, 0x9d, 0x21, 0x24, + 0x13, 0x9f, 0x0b, 0xe0, 0xff, 0xc7, 0xbf, 0x21, 0xe3, 0x05, 0x1f, 0xff, 0xeb, + 0x8e, 0x2c, 0x30, 0xb6, 0xe5, 0x0c, 0xf7, 0x3f, 0x49, 0x07, 0x0d, 0xd2, 0xf1, + 0xd4, 0xfb, 0x0d, 0x0e, 0x06, 0x1b, 0xb5, 0x21, 0xcd, 0xfa, 0xe7, 0x00, 0x2a, + 0xea, 0x50, 0x40, 0x10, 0x36, 0x04, 0x40, 0xea, 0x28, 0x08, 0xf7, 0xfd, 0x08, + 0x18, 0xec, 0x07, 0xdb, 0x04, 0x2b, 0x48, 0x45, 0xd9, 0xc9, 0xf3, 0xf7, 0x03, + 0xdc, 0xc5, 0xf1, 0x1c, 0x37, 0xde, 0x02, 0x13, 0xf7, 0xa7, 0xc1, 0xfc, 0x07, + 0x20, 0xe0, 0xdb, 0x00, 0x02, 0x0b, 0xf0, 0x08, 0x3b, 0x11, 0x00, 0x03, 0x01, + 0x2d, 0x39, 0x0a, 0x3a, 0x07, 0x33, 0xfb, 0xd5, 0xca, 0xd3, 0x05, 0xfa, 0xe9, + 0x05, 0x1e, 0xea, 0xce, 0x20, 0x1a, 0xca, 0xbf, 0xed, 0xf8, 0xfb, 0xda, 0xfb, + 0x35, 0xef, 0x08, 0x22, 0xc5, 0x15, 0xe5, 0x34, 0xcf, 0x24, 0x0c, 0xe5, 0x08, + 0x8f, 0xf3, 0xec, 0xfb, 0xdb, 0x4b, 0xf3, 0xa4, 0x2b, 0xf6, 0xde, 0xfe, 0x07, + 0xcd, 0x26, 0x2d, 0x62, 0xf6, 0xd6, 0xde, 0xf7, 0x28, 0xe1, 0x7f, 0x39, 0xf1, + 0xe6, 0x08, 0x13, 0x08, 0x37, 0xf4, 0xf5, 0x06, 0x09, 0xf4, 0x4a, 0x1e, 0xed, + 0x3b, 0xd5, 0xf9, 0xec, 0x0e, 0xda, 0x17, 0xf8, 0x39, 0xf3, 0xff, 0xf7, 0xf2, + 0x38, 0x1a, 0xe2, 0x27, 0xb6, 0x03, 0x05, 0x0e, 0x2d, 0x17, 0x06, 0x28, 0x59, + 0xe1, 0xce, 0x53, 0x19, 0x1d, 0x5e, 0xc6, 0x01, 0xe4, 0x27, 0xfb, 0xf8, 0xeb, + 0xc9, 0xfc, 0xfa, 0x04, 0x02, 0xfe, 0x13, 0xef, 0x81, 0xf8, 0xed, 0x60, 0xf7, + 0x0d, 0x18, 0xb6, 0x05, 0x24, 0x1f, 0xfa, 0x19, 0xd9, 0xef, 0xcf, 0x17, 0xc8, + 0xeb, 0xd0, 0xf8, 0x03, 0x08, 0x17, 0x15, 0x17, 0xfa, 0x09, 0xdd, 0xc7, 0xc8, + 0x3d, 0x1f, 0x46, 0xda, 0xe7, 0x38, 0xdd, 0xf7, 0x0c, 0xcf, 0x02, 0xed, 0x01, + 0xc9, 0x02, 0x0a, 0x3f, 0xf2, 0xff, 0x19, 0xe2, 0x0f, 0x12, 0x09, 0xe1, 0xee, + 0x25, 0x1a, 0xae, 0xed, 0xf4, 0xe3, 0xea, 0x43, 0x06, 0xd7, 0x25, 0xe1, 0x45, + 0x23, 0x45, 0xee, 0x06, 0x02, 0x2e, 0x38, 0x24, 0xfb, 0xf8, 0x30, 0x23, 0xe3, + 0xeb, 0xf8, 0x28, 0x11, 0xe0, 0xf0, 0x07, 0xf7, 0x06, 0xf7, 0xe1, 0xf8, 0x00, + 0x52, 0x47, 0xeb, 0xf8, 0x0c, 0x0e, 0xfe, 0xd4, 0x17, 0xd4, 0xfb, 0x4b, 0xdc, + 0x1f, 0xf4, 0x05, 0x18, 0x0f, 0x9f, 0x16, 0xf2, 0xac, 0x81, 0xaf, 0x56, 0x57, + 0x11, 0xd1, 0x0b, 0x01, 0x3b, 0x0f, 0x1b, 0xe3, 0xe2, 0x16, 0x0b, 0xe0, 0xe4, + 0x0b, 0x32, 0x05, 0xd7, 0xe4, 0xdd, 0x03, 0x05, 0xf2, 0x01, 0xfd, 0xfe, 0x5a, + 0x1a, 0xd2, 0x10, 0x14, 0x25, 0x14, 0xe7, 0xce, 0xe4, 0x1f, 0x40, 0x07, 0xe0, + 0xb5, 0xd0, 0xfb, 0x0d, 0x22, 0x10, 0x42, 0x05, 0xdd, 0xaf, 0x9b, 0x3a, 0x07, + 0xff, 0xf4, 0x1a, 0xff, 0x1c, 0xc2, 0xd1, 0x83, 0x0c, 0xe5, 0x14, 0xf2, 0xb1, + 0x3a, 0x4a, 0xee, 0x0d, 0xeb, 0xd4, 0xb5, 0xcf, 0x1e, 0xd3, 0xdd, 0x0d, 0xe5, + 0xfa, 0x5c, 0x96, 0xf6, 0xe8, 0x40, 0xf1, 0x16, 0x00, 0x33, 0xd9, 0x03, 0xd6, + 0xee, 0x2b, 0x0c, 0x4d, 0x78, 0xea, 0xe0, 0xe9, 0xdc, 0x6d, 0x5c, 0xfc, 0xac, + 0xf9, 0x0b, 0x0b, 0x8f, 0x25, 0xaf, 0xdf, 0xf3, 0x3b, 0x0c, 0xd5, 0xcd, 0xfe, + 0x1f, 0xa3, 0x8d, 0xd7, 0x2c, 0x11, 0x03, 0x69, 0xd8, 0xf0, 0x03, 0x2a, 0x13, + 0x17, 0x29, 0xfb, 0xfa, 0xfc, 0xee, 0xc9, 0x12, 0xed, 0xe3, 0x1e, 0x7f, 0xf2, + 0x5d, 0xe5, 0x4f, 0xee, 0xb7, 0xce, 0x07, 0x0f, 0xea, 0x04, 0xfc, 0x08, 0x49, + 0x54, 0x06, 0x0d, 0xf4, 0x38, 0xef, 0x11, 0x1c, 0x26, 0xe8, 0x13, 0xae, 0xf6, + 0x10, 0xfa, 0x36, 0xfe, 0xbb, 0x2b, 0x26, 0xef, 0x00, 0xfb, 0xf8, 0xf8, 0x12, + 0x0b, 0x02, 0xff, 0xe3, 0x32, 0x03, 0xef, 0x45, 0xc6, 0xf5, 0xff, 0xf5, 0x0c, + 0x1c, 0xc3, 0x01, 0xdb, 0x05, 0xe4, 0xf4, 0x25, 0x13, 0x43, 0x0c, 0x03, 0x03, + 0x0c, 0xf2, 0x0d, 0x24, 0xdc, 0xcf, 0xf1, 0x14, 0x03, 0x0d, 0x18, 0x16, 0xbe, + 0x42, 0x21, 0xe9, 0x18, 0xce, 0xc8, 0x26, 0x12, 0x1e, 0xcb, 0xfe, 0xf0, 0xf4, + 0x05, 0xb8, 0x41, 0x02, 0xf7, 0xe9, 0xe1, 0xe7, 0xf8, 0xe9, 0x54, 0x0e, 0xbe, + 0x4c, 0xfe, 0xe2, 0x0b, 0xf0, 0xd9, 0xdf, 0x1d, 0x15, 0xe2, 0xfc, 0x5b, 0xf3, + 0xde, 0x35, 0x3e, 0xf9, 0x34, 0xf7, 0xee, 0xb3, 0x81, 0xc1, 0xc8, 0xef, 0x60, + 0xda, 0x34, 0xc9, 0xf5, 0xed, 0x18, 0xcf, 0xcc, 0xed, 0x0d, 0xf0, 0x2d, 0x34, + 0xbf, 0x0a, 0x00, 0x11, 0x14, 0xe4, 0x49, 0xea, 0x52, 0x23, 0xd7, 0x1d, 0xd2, + 0x03, 0x25, 0x2f, 0x2e, 0x57, 0x1f, 0xdf, 0xf7, 0x03, 0xda, 0xc4, 0xce, 0x33, + 0xe2, 0xc8, 0xf7, 0xcc, 0x1c, 0x06, 0x28, 0x22, 0x9f, 0xe4, 0xb1, 0x10, 0xea, + 0x1f, 0xef, 0x12, 0xd7, 0x05, 0xd9, 0x28, 0x52, 0x08, 0x06, 0x15, 0x42, 0x1d, + 0x12, 0x2f, 0x37, 0xee, 0xbb, 0xe1, 0xf1, 0xc0, 0x1d, 0xe6, 0xce, 0x0e, 0xb7, + 0x1d, 0x2f, 0xd4, 0x2a, 0xf5, 0xe6, 0xd9, 0xe2, 0x41, 0xd1, 0xe9, 0xa0, 0xe5, + 0xb2, 0xc8, 0x40, 0x85, 0xe5, 0x6d, 0x5d, 0x03, 0xd8, 0xf8, 0x01, 0xd7, 0x12, + 0xce, 0xdf, 0x0f, 0xbf, 0x28, 0x1d, 0xd1, 0xdd, 0x18, 0xc2, 0xcc, 0xe9, 0xaf, + 0xf4, 0x54, 0xee, 0xed, 0x10, 0x14, 0xe2, 0x2c, 0xb9, 0x03, 0xd5, 0xdb, 0xe3, + 0x70, 0xdb, 0xbc, 0x06, 0xc1, 0xe9, 0xf1, 0xf4, 0xd0, 0x21, 0x4c, 0x04, 0xed, + 0x1d, 0xe5, 0x1d, 0xda, 0xf7, 0x10, 0x14, 0xb4, 0xea, 0x51, 0xd8, 0xf4, 0x48, + 0x35, 0xdf, 0xf0, 0x04, 0x46, 0x0b, 0xff, 0x0d, 0x1d, 0x36, 0xbe, 0x19, 0xbd, + 0xfb, 0x4b, 0xed, 0x2d, 0xf4, 0x0d, 0xc1, 0xff, 0x17, 0xed, 0x2e, 0xdb, 0x3c, + 0xfe, 0x07, 0x47, 0x53, 0x2b, 0xf5, 0xc8, 0x2a, 0x1c, 0x21, 0x0c, 0x1d, 0xcd, + 0xe7, 0xdc, 0xf4, 0xf6, 0xf7, 0x2f, 0xd1, 0xd4, 0xf5, 0x1b, 0x18, 0xc4, 0x4d, + 0x17, 0xaf, 0xd5, 0xe0, 0xfc, 0xab, 0xb4, 0x17, 0x0c, 0x5a, 0x4f, 0xe7, 0x08, + 0x01, 0x7f, 0x0b, 0xcb, 0xeb, 0xff, 0xba, 0xf3, 0xe3, 0xf1, 0xed, 0xe7, 0xfe, + 0xf6, 0x10, 0x1c, 0x2c, 0x4b, 0x00, 0xab, 0xee, 0xf8, 0x07, 0xc9, 0x1c, 0x2e, + 0x0d, 0xd1, 0x18, 0x68, 0xb9, 0xca, 0xfa, 0xbb, 0xf9, 0xe7, 0x1d, 0x44, 0xd0, + 0x01, 0xf4, 0xfb, 0x01, 0xf3, 0xae, 0xb3, 0xb8, 0x04, 0x01, 0xf7, 0xfc, 0x13, + 0x0c, 0x14, 0x1c, 0x4f, 0xef, 0xd9, 0xfc, 0xdb, 0x00, 0x1a, 0xf3, 0xbc, 0xdd, + 0x09, 0x0a, 0xf5, 0x0b, 0xd8, 0xe8, 0xbf, 0xf0, 0xce, 0xda, 0x10, 0x01, 0xe6, + 0x0d, 0xe3, 0x25, 0xfd, 0x33, 0x41, 0xf2, 0xff, 0xce, 0xd8, 0x5f, 0x29, 0x25, + 0x33, 0xe3, 0xfd, 0xf0, 0xe9, 0x3f, 0xdd, 0x20, 0x31, 0x0e, 0x2f, 0x25, 0xf6, + 0xf8, 0xf1, 0xf9, 0x44, 0xc5, 0xd7, 0x22, 0xf7, 0x08, 0x81, 0xee, 0xfc, 0x30, + 0xf7, 0xdc, 0x17, 0xea, 0x21, 0x19, 0xaf, 0xf2, 0x4d, 0xbf, 0xd6, 0x40, 0xe0, + 0xd4, 0x27, 0x49, 0xc8, 0xe4, 0x5f, 0x33, 0xd1, 0x20, 0xe0, 0x09, 0xf7, 0xcd, + 0xd4, 0x1a, 0x1d, 0x30, 0x3b, 0xf1, 0x17, 0x0f, 0x4c, 0x50, 0xe5, 0xe1, 0xdd, + 0xf9, 0xd7, 0xbf, 0x35, 0xb9, 0xc0, 0x0e, 0x93, 0xfd, 0x00, 0x67, 0xd1, 0x0c, + 0x8d, 0xb9, 0x2a, 0x35, 0xd9, 0x15, 0x29, 0x3a, 0x2c, 0xeb, 0x3a, 0xf2, 0x15, + 0xee, 0x29, 0xfe, 0xd9, 0x22, 0xb0, 0xd7, 0x21, 0x16, 0x0d, 0x2a, 0xbd, 0x0a, + 0x0a, 0xfc, 0xad, 0xbd, 0xdb, 0xef, 0xc1, 0xe5, 0x22, 0xc7, 0xe1, 0x2f, 0xd2, + 0xf8, 0x2a, 0xfe, 0xdb, 0x54, 0x81, 0xc4, 0xfd, 0x00, 0x41, 0xf5, 0xe5, 0x22, + 0xdf, 0xcb, 0x09, 0xe2, 0x2b, 0xf6, 0x53, 0xe5, 0x19, 0xd8, 0x3b, 0xb2, 0x13, + 0x0f, 0xd0, 0xc8, 0x1c, 0xe0, 0x4d, 0x0d, 0xb9, 0x04, 0x06, 0x99, 0xb4, 0xe0, + 0xe8, 0xee, 0xf0, 0xe9, 0x4e, 0x79, 0x19, 0x1a, 0x02, 0x9a, 0x18, 0xfa, 0xf2, + 0xed, 0x11, 0xaa, 0xd6, 0xa9, 0xcd, 0xc8, 0xd1, 0x17, 0x37, 0x18, 0x2a, 0x18, + 0x15, 0xf9, 0xf4, 0x3f, 0xc5, 0x0d, 0x04, 0x35, 0x0e, 0xf9, 0xef, 0x04, 0x0b, + 0xd5, 0xf9, 0xf4, 0x03, 0x0a, 0xf2, 0x2a, 0xb5, 0xde, 0x2d, 0xff, 0xb5, 0xe2, + 0x4f, 0xfa, 0xdf, 0x11, 0x05, 0xda, 0xf7, 0xeb, 0xdc, 0x2d, 0xfc, 0xee, 0x00, + 0x1a, 0xfd, 0xf8, 0x0d, 0xfd, 0x07, 0x09, 0x1c, 0xad, 0x22, 0xd2, 0x12, 0xb3, + 0x02, 0x04, 0x0b, 0x0a, 0xc5, 0x16, 0x36, 0xff, 0xf1, 0x05, 0x10, 0xe3, 0xd8, + 0xab, 0xf3, 0xee, 0xf0, 0x0a, 0xf2, 0x0c, 0x23, 0x20, 0xfd, 0xbc, 0x09, 0x0e, + 0x0c, 0x43, 0x35, 0x00, 0xef, 0x19, 0xe9, 0xf4, 0xd1, 0xfb, 0xe7, 0xab, 0x1b, + 0xe8, 0x02, 0x08, 0x1d, 0xc7, 0x2e, 0x08, 0xf2, 0x12, 0xd8, 0x7f, 0xd9, 0x13, + 0xe4, 0x17, 0x03, 0xfa, 0xff, 0x47, 0xde, 0x38, 0xd6, 0x16, 0x11, 0x06, 0x0e, + 0x0c, 0x0f, 0x2e, 0x20, 0xdb, 0xeb, 0x02, 0xfa, 0xdf, 0x01, 0x29, 0x01, 0xf3, + 0x4d, 0xf0, 0xdc, 0x1c, 0xe9, 0x3e, 0xf3, 0x1e, 0xc6, 0xc1, 0xc5, 0xbf, 0xda, + 0x3b, 0xf8, 0x3f, 0x24, 0x22, 0xe7, 0xbb, 0xc5, 0x21, 0xfd, 0xf3, 0x12, 0x01, + 0xd0, 0xa4, 0x08, 0xb7, 0x1e, 0xe7, 0x0b, 0xea, 0x07, 0x05, 0xe1, 0xf0, 0xd2, + 0x12, 0xc6, 0xf4, 0xe1, 0x17, 0x2e, 0x24, 0xb0, 0x38, 0xf6, 0x4e, 0xe6, 0x03, + 0xbc, 0x17, 0x3f, 0xe0, 0xca, 0x33, 0x10, 0xf7, 0x1d, 0xf1, 0xfb, 0x0f, 0xc4, + 0x0e, 0x3a, 0xfb, 0xf0, 0xfa, 0x25, 0xfb, 0x10, 0x7f, 0xf1, 0x03, 0x41, 0xcb, + 0x29, 0xf8, 0x14, 0x35, 0x2f, 0x25, 0xfa, 0x23, 0xc8, 0xfb, 0xc3, 0x2c, 0xf3, + 0xf8, 0xdd, 0xf3, 0x1d, 0x0a, 0xfb, 0x0a, 0x09, 0xd2, 0x06, 0x18, 0x30, 0xfb, + 0x1a, 0xfe, 0xdf, 0xfa, 0xe0, 0xe4, 0x2b, 0xfb, 0xd8, 0x75, 0xfa, 0xe3, 0x1a, + 0x04, 0xb7, 0x3a, 0xde, 0xd1, 0xd9, 0xe6, 0xfd, 0xec, 0xf5, 0xc3, 0xf9, 0xe8, + 0xcb, 0x2d, 0x19, 0x47, 0x11, 0x2b, 0x2b, 0xf9, 0xf1, 0xb0, 0xa8, 0x35, 0x28, + 0x47, 0xf4, 0xf7, 0xe6, 0x11, 0xde, 0xfd, 0xf8, 0x0e, 0xed, 0xbb, 0x42, 0xf7, + 0x24, 0xd3, 0x10, 0xd2, 0x1c, 0x09, 0xe6, 0xf3, 0x0c, 0xfe, 0x1c, 0xfd, 0x11, + 0x0d, 0x3e, 0x0c, 0x2d, 0x13, 0x12, 0x05, 0x29, 0x03, 0x00, 0xbb, 0x15, 0x0c, + 0xd0, 0xce, 0xca, 0xef, 0xf8, 0x0c, 0xfd, 0xf2, 0x10, 0xcb, 0xc9, 0xfc, 0xc6, + 0x0b, 0xf3, 0x22, 0xd5, 0xd0, 0x11, 0xe4, 0x14, 0x0b, 0xc5, 0xbe, 0xdc, 0xf4, + 0x0b, 0xc6, 0xe0, 0xe9, 0x14, 0x98, 0x29, 0x0f, 0xb6, 0x05, 0xf8, 0xfe, 0xf0, + 0x0d, 0xf5, 0x25, 0xe7, 0x1e, 0xe7, 0xd9, 0xff, 0xe8, 0xe3, 0xf3, 0x05, 0x1e, + 0xe4, 0xed, 0x31, 0x08, 0xd7, 0x29, 0x24, 0xdd, 0x29, 0x25, 0x81, 0xff, 0x01, + 0xbb, 0x36, 0x30, 0x11, 0xc7, 0xfd, 0x57, 0x1a, 0x1c, 0x4b, 0x1b, 0x8a, 0xfb, + 0xfa, 0xd9, 0xef, 0x0e, 0x23, 0xe8, 0xf6, 0x58, 0x2b, 0x19, 0xa6, 0xe4, 0x1e, + 0xca, 0x3d, 0x0d, 0x47, 0xec, 0xe1, 0xcf, 0xe3, 0x29, 0xdd, 0xb5, 0xf7, 0xfe, + 0x25, 0xeb, 0x03, 0x09, 0xfa, 0xbb, 0xf2, 0xcb, 0x90, 0x2a, 0x2c, 0x63, 0x25, + 0xf7, 0xed, 0x46, 0x9b, 0xea, 0x1e, 0xfe, 0xe9, 0x00, 0x47, 0x24, 0xfc, 0x05, + 0xf0, 0xe3, 0x4b, 0xd9, 0xeb, 0xd3, 0x2b, 0xe6, 0x21, 0xf9, 0xe1, 0xec, 0xe6, + 0x8e, 0x16, 0xe2, 0x08, 0xe8, 0xf2, 0xe5, 0xef, 0x23, 0x2e, 0x90, 0x1b, 0xc7, + 0x09, 0xe5, 0x51, 0x09, 0x26, 0xd5, 0xd6, 0xf9, 0xfe, 0x81, 0x12, 0x48, 0x08, + 0xf5, 0x04, 0xda, 0xb4, 0x0f, 0xdb, 0xdb, 0x02, 0x48, 0x12, 0x06, 0x31, 0x29, + 0xdc, 0xad, 0xee, 0xf2, 0x3c, 0xa2, 0x13, 0xbb, 0xb1, 0x16, 0x94, 0x0e, 0x98, + 0xee, 0xdc, 0xca, 0xcd, 0xfb, 0x1f, 0x21, 0x35, 0xdb, 0xe1, 0x03, 0x10, 0xc5, + 0x3d, 0xdf, 0xe1, 0xee, 0xea, 0xad, 0x25, 0x10, 0xda, 0xc7, 0x37, 0xef, 0xcc, + 0xcb, 0xe9, 0x51, 0x35, 0x92, 0x9c, 0x02, 0xec, 0x55, 0x24, 0xf8, 0x1d, 0x00, + 0x03, 0x00, 0x46, 0x13, 0x20, 0x04, 0xcf, 0x1e, 0x28, 0xfe, 0x29, 0xf1, 0x3a, + 0x27, 0x18, 0x42, 0x64, 0x81, 0xf7, 0x1a, 0xd2, 0x4a, 0xbd, 0x54, 0xe5, 0xb9, + 0xbf, 0x11, 0xbb, 0xb5, 0x0b, 0xd1, 0x1b, 0x06, 0xef, 0x0e, 0x1b, 0xfd, 0x5e, + 0xe8, 0xfe, 0x06, 0x01, 0xeb, 0xa7, 0xe5, 0xc4, 0xcb, 0xf8, 0x02, 0xf6, 0xbc, + 0xfb, 0x24, 0x26, 0xc5, 0x36, 0x2f, 0xe2, 0xc0, 0xe9, 0xd3, 0xe5, 0x6c, 0x2e, + 0x02, 0xf0, 0xd1, 0xda, 0xe3, 0xdf, 0x1a, 0x1f, 0xcf, 0x15, 0x09, 0xee, 0xc8, + 0x6d, 0x09, 0xec, 0xeb, 0x26, 0xca, 0x0b, 0x18, 0xb9, 0x23, 0xea, 0x97, 0xe9, + 0x2b, 0xda, 0xf9, 0xf4, 0x89, 0xcd, 0xa5, 0xaa, 0xe4, 0xd0, 0xfd, 0x1e, 0xda, + 0xf2, 0x1a, 0xff, 0x59, 0x11, 0x16, 0xf8, 0xaf, 0x05, 0xca, 0x37, 0x32, 0xf0, + 0xe2, 0xcb, 0x0a, 0xca, 0xad, 0xbe, 0xbb, 0xb7, 0x54, 0xc2, 0x23, 0x06, 0xdc, + 0x0d, 0xed, 0x0c, 0xea, 0xbf, 0xc4, 0xb5, 0xd3, 0x8d, 0x60, 0xb6, 0x03, 0xc8, + 0x1e, 0x54, 0xcf, 0xec, 0xfd, 0x0d, 0x1e, 0x2e, 0x04, 0x18, 0xfc, 0x45, 0x02, + 0xd5, 0x55, 0xd8, 0x10, 0x46, 0x45, 0xe6, 0xc8, 0xd2, 0x21, 0x23, 0x67, 0x14, + 0x4d, 0xb8, 0xc0, 0x4e, 0x14, 0xf5, 0xd2, 0xfa, 0xfe, 0xdf, 0x19, 0x1b, 0x3f, + 0x17, 0xac, 0x0a, 0x09, 0xee, 0x0b, 0xb9, 0xea, 0xe1, 0xc8, 0x6f, 0x81, 0xda, + 0xfb, 0x42, 0xdb, 0x25, 0xd2, 0xe9, 0x31, 0x45, 0xf7, 0x15, 0x51, 0x96, 0xe8, + 0x27, 0x0b, 0x54, 0x2b, 0x9c, 0x15, 0xed, 0xc9, 0xdf, 0xc8, 0xc7, 0xe9, 0xf7, + 0xf8, 0xdd, 0x2e, 0xd4, 0xf3, 0x1d, 0x4d, 0xdf, 0xf1, 0x04, 0xf2, 0xce, 0x14, + 0x45, 0xf9, 0x1a, 0xd6, 0x01, 0xdc, 0xf3, 0xf5, 0xf9, 0xed, 0xd4, 0x02, 0x20, + 0x25, 0xe0, 0x02, 0xf4, 0x24, 0xb7, 0x3a, 0xb5, 0x38, 0xf6, 0x13, 0xfe, 0xc6, + 0x17, 0x27, 0xe7, 0xdc, 0x3d, 0xec, 0x07, 0xe1, 0xf9, 0x04, 0xca, 0xfc, 0x12, + 0xff, 0xf2, 0x05, 0x0e, 0x00, 0xdb, 0x22, 0xf0, 0x15, 0x5d, 0x1f, 0x0f, 0xeb, + 0x64, 0x1a, 0x7f, 0x1e, 0x01, 0xee, 0xb6, 0x0f, 0x09, 0x50, 0x15, 0x90, 0x1d, + 0x1d, 0xff, 0x0a, 0x03, 0xe6, 0x12, 0x58, 0xe6, 0x12, 0xdc, 0x1a, 0x4d, 0x07, + 0xe6, 0xcd, 0xce, 0x2d, 0xd5, 0xe8, 0xd9, 0x2b, 0x04, 0x1a, 0x28, 0xd5, 0x2b, + 0x95, 0xa7, 0x01, 0xd2, 0x28, 0xa2, 0x1b, 0xe7, 0x25, 0xc6, 0xe6, 0x2d, 0x09, + 0xa9, 0x20, 0x28, 0xac, 0x5e, 0xea, 0xf0, 0xe5, 0xeb, 0x09, 0xf6, 0xfe, 0x27, + 0xcc, 0x12, 0xe5, 0x05, 0x14, 0xde, 0x14, 0xe8, 0xe0, 0xf2, 0x0c, 0x20, 0x30, + 0x2e, 0xfc, 0x0a, 0xfc, 0xfb, 0xdb, 0xbd, 0xca, 0xe5, 0x0e, 0x26, 0x24, 0x1d, + 0xfb, 0xcd, 0xa2, 0x18, 0x19, 0x09, 0xf4, 0xa3, 0x14, 0xc2, 0xec, 0x9d, 0xe5, + 0x1a, 0xdb, 0x7c, 0xec, 0xe3, 0xd7, 0x00, 0xe4, 0x22, 0x0a, 0x02, 0xb1, 0x0e, + 0xd1, 0x1d, 0x10, 0x18, 0xd0, 0x51, 0x00, 0x2e, 0x02, 0x28, 0xda, 0xe0, 0xe6, + 0xc3, 0x5c, 0xb3, 0x26, 0xde, 0x0b, 0xab, 0xf5, 0x3d, 0x97, 0xf7, 0xd6, 0xeb, + 0xc2, 0xf4, 0xca, 0xd9, 0x1e, 0x17, 0x3f, 0xde, 0xb7, 0xdb, 0x46, 0x15, 0xd1, + 0x19, 0xb4, 0xe0, 0xe9, 0xf6, 0xee, 0xf8, 0xe3, 0xdc, 0xe3, 0xfc, 0x4d, 0x01, + 0x10, 0xf1, 0x17, 0x11, 0x0a, 0xc6, 0x9f, 0x23, 0x7f, 0xf7, 0x0c, 0x25, 0xfa, + 0xe6, 0x28, 0xff, 0x0c, 0xd5, 0x01, 0x5b, 0xb7, 0x0d, 0xe3, 0x19, 0x31, 0x1d, + 0x0e, 0x04, 0xd9, 0x13, 0xd7, 0xcf, 0xc0, 0x1c, 0x01, 0x06, 0xe1, 0x56, 0x03, + 0x60, 0x61, 0xa9, 0xf5, 0xec, 0x16, 0x0c, 0xe2, 0x09, 0xfe, 0x41, 0x1b, 0x3d, + 0x2c, 0xcd, 0xb6, 0x24, 0x1c, 0xcd, 0x4b, 0xdf, 0x5d, 0xe2, 0x37, 0x3a, 0xfd, + 0x25, 0xe3, 0xa2, 0xcd, 0x22, 0xff, 0x7f, 0xb5, 0xfd, 0xfb, 0x00, 0xdf, 0x30, + 0xdd, 0x4b, 0x4e, 0x26, 0xfe, 0xda, 0x23, 0xe3, 0x37, 0x19, 0xd9, 0x1e, 0xe0, + 0x05, 0xe2, 0xda, 0xee, 0xd6, 0xef, 0xf7, 0xb7, 0x07, 0x05, 0xfa, 0xc9, 0x1e, + 0x00, 0xeb, 0xf3, 0x11, 0x12, 0xe7, 0xda, 0x28, 0x83, 0xd7, 0xf5, 0x04, 0xf8, + 0xa8, 0x14, 0x4b, 0xe6, 0x09, 0xfe, 0x34, 0xb9, 0x18, 0x49, 0xd8, 0xcf, 0xf3, + 0xdf, 0x0c, 0x07, 0xef, 0x21, 0xd3, 0xd5, 0x66, 0xd9, 0x08, 0xdc, 0x0e, 0x0c, + 0x21, 0xf2, 0xd6, 0x0c, 0xc5, 0xdd, 0x13, 0xd0, 0xff, 0x57, 0xba, 0xe5, 0x24, + 0xc3, 0xd0, 0x2e, 0x07, 0xfe, 0x5d, 0x0f, 0x14, 0x5b, 0xde, 0x11, 0x4b, 0xee, + 0xf1, 0xd5, 0xd0, 0xf9, 0x14, 0x05, 0x88, 0xf9, 0x08, 0x0d, 0xbe, 0x0f, 0xf0, + 0x17, 0x1c, 0x08, 0xf4, 0x32, 0x14, 0x93, 0xd3, 0xda, 0x94, 0x0f, 0xf6, 0x38, + 0x07, 0x1e, 0x11, 0xc1, 0xdc, 0xdb, 0xd7, 0xf3, 0x31, 0xfb, 0x22, 0x06, 0xe2, + 0x01, 0xc1, 0xf6, 0x10, 0x17, 0xb9, 0x27, 0xf8, 0xfa, 0x0c, 0xdc, 0xb7, 0xe5, + 0x05, 0x28, 0x2b, 0xce, 0xeb, 0x3b, 0x2c, 0xb7, 0xfd, 0x27, 0xf8, 0xfe, 0x9e, + 0x31, 0xf2, 0x81, 0x05, 0xf3, 0xef, 0x1e, 0x05, 0x19, 0x07, 0xb3, 0xd2, 0xf9, + 0xfe, 0xa3, 0x16, 0x07, 0xdf, 0xf7, 0x62, 0xec, 0x20, 0xee, 0xe2, 0x0f, 0xf8, + 0x12, 0xe4, 0x06, 0xd3, 0xd7, 0x44, 0x17, 0x03, 0xbb, 0x0b, 0xee, 0xff, 0xf0, + 0xfb, 0x26, 0xe8, 0x39, 0xdd, 0x0e, 0x02, 0xe1, 0x07, 0x27, 0x09, 0x03, 0x28, + 0x01, 0xe3, 0xb0, 0xf8, 0xf5, 0x30, 0x0c, 0x57, 0x02, 0x01, 0xbe, 0xb8, 0x1b, + 0x25, 0x0b, 0x53, 0x17, 0x1c, 0xeb, 0x22, 0x1a, 0xaf, 0xdf, 0xd3, 0x3f, 0x07, + 0x04, 0x2c, 0xe0, 0x15, 0x29, 0x02, 0xc4, 0xf8, 0xbc, 0xaa, 0x16, 0xf7, 0xce, + 0xfa, 0x01, 0x53, 0x0a, 0x15, 0xdb, 0x27, 0xa8, 0xfc, 0x03, 0x08, 0xc5, 0x22, + 0xeb, 0xf1, 0xfe, 0x2a, 0xf5, 0xaa, 0x41, 0xcb, 0x4a, 0x22, 0xfb, 0x38, 0xc3, + 0x2c, 0xd4, 0xec, 0xfc, 0x25, 0xfe, 0xfe, 0x32, 0xe3, 0xd4, 0x12, 0x06, 0xf7, + 0xec, 0x19, 0x63, 0x3a, 0x81, 0xf5, 0x30, 0xfe, 0xe9, 0xe5, 0x04, 0xeb, 0xd2, + 0x13, 0x3a, 0x36, 0xeb, 0x13, 0x18, 0x16, 0x16, 0x0d, 0xe4, 0xfa, 0x1e, 0xe3, + 0xe9, 0x10, 0xfd, 0x22, 0x25, 0xf2, 0xe1, 0x1d, 0xf9, 0x04, 0x10, 0xc2, 0x01, + 0x0f, 0x1a, 0x15, 0xc0, 0x04, 0x81, 0xe5, 0x44, 0x02, 0xa2, 0xe6, 0x40, 0xf3, + 0x84, 0x21, 0xff, 0xb4, 0x30, 0xde, 0x4c, 0x26, 0x12, 0x1b, 0x4b, 0xe7, 0x11, + 0x6f, 0xb5, 0x6d, 0x1e, 0xe4, 0x06, 0xf3, 0x12, 0x0a, 0xf5, 0x0a, 0xd8, 0x17, + 0x5c, 0xcd, 0x7d, 0xd5, 0xc7, 0x94, 0xf4, 0x30, 0x31, 0x02, 0x28, 0xd6, 0x22, + 0xf5, 0x07, 0xc0, 0xd6, 0x29, 0xdb, 0x2b, 0x4d, 0x3b, 0xf6, 0xf7, 0x72, 0x46, + 0xe2, 0xec, 0xd8, 0xc5, 0x3f, 0xbc, 0x30, 0xfd, 0xdd, 0x22, 0xaa, 0x15, 0xf9, + 0xb3, 0xd6, 0x3f, 0xf2, 0x07, 0x44, 0xf5, 0xf7, 0x22, 0xe5, 0x28, 0xf4, 0xf9, + 0xc9, 0x93, 0x40, 0x4b, 0xf6, 0x19, 0x54, 0xc2, 0x18, 0xde, 0xe1, 0xde, 0x7e, + 0x34, 0xbe, 0x09, 0xdf, 0x11, 0x06, 0x1b, 0xbc, 0xf8, 0x2f, 0xde, 0x50, 0xd6, + 0xa9, 0x2b, 0x17, 0x03, 0xab, 0x23, 0x3d, 0x11, 0x54, 0xd5, 0xdd, 0xb7, 0x08, + 0x23, 0x23, 0x16, 0xf4, 0x13, 0xe6, 0x39, 0xd8, 0xf7, 0x0e, 0x3b, 0xf6, 0xb0, + 0xa9, 0xfc, 0x12, 0xa6, 0xf0, 0xfe, 0x3f, 0x07, 0xfd, 0xcf, 0xd5, 0xbc, 0x18, + 0xef, 0x2b, 0x43, 0x19, 0x04, 0xb3, 0xb2, 0xf9, 0x05, 0xff, 0x0f, 0x0f, 0x01, + 0xfe, 0xeb, 0xfa, 0x1b, 0xd3, 0x0b, 0x0b, 0x02, 0xe8, 0x1d, 0x29, 0xdf, 0xfb, + 0xc4, 0x25, 0xf5, 0x02, 0x14, 0xe2, 0x0f, 0x46, 0x11, 0x0c, 0x15, 0x09, 0xf7, + 0x08, 0x0c, 0x99, 0x17, 0xe9, 0xd4, 0x1a, 0x17, 0xef, 0x02, 0x37, 0x01, 0x01, + 0xd9, 0x81, 0x0c, 0x40, 0x28, 0xeb, 0x1a, 0xf6, 0xff, 0xdb, 0xf5, 0xce, 0xd2, + 0x24, 0xc9, 0x1a, 0x17, 0x08, 0x44, 0xee, 0x2e, 0x4e, 0x0d, 0x19, 0x0d, 0xb7, + 0xfa, 0xd0, 0xda, 0xe2, 0xdb, 0x12, 0x4f, 0xe1, 0x40, 0x2d, 0x33, 0x03, 0xe2, + 0xd2, 0xe1, 0xd4, 0x2b, 0xe3, 0xc1, 0x00, 0x75, 0x02, 0x30, 0x31, 0xf9, 0x07, + 0x07, 0xe6, 0x3d, 0x3a, 0xc4, 0x13, 0x0c, 0xe1, 0x0d, 0xc2, 0xf7, 0xb5, 0xf7, + 0xc1, 0xce, 0xbb, 0x15, 0xed, 0xa3, 0xf4, 0x12, 0xd9, 0x0c, 0xeb, 0x17, 0x8d, + 0xe5, 0x2a, 0x87, 0x01, 0xae, 0xe5, 0x1a, 0xf0, 0xf1, 0x05, 0xff, 0x04, 0xfd, + 0x2d, 0xee, 0x3f, 0x04, 0x4c, 0x2b, 0xc2, 0xd3, 0x03, 0xc4, 0x20, 0x7f, 0x2b, + 0xd5, 0x1f, 0x04, 0xf6, 0x02, 0x21, 0xfc, 0xd2, 0xd8, 0xf6, 0xec, 0xeb, 0x12, + 0xcd, 0xed, 0x10, 0xd7, 0xf7, 0x24, 0xf4, 0x22, 0x0b, 0xea, 0x07, 0xf5, 0x0d, + 0x1c, 0x28, 0x0b, 0xbc, 0xe0, 0xca, 0x00, 0x39, 0x1b, 0xf8, 0x32, 0x08, 0xfd, + 0x18, 0xf4, 0xeb, 0xf0, 0xfb, 0x0d, 0xfd, 0xeb, 0x11, 0x0a, 0xd4, 0xe7, 0xc8, + 0xd1, 0x47, 0x23, 0xe7, 0x1f, 0x24, 0xaf, 0xf7, 0xff, 0xe0, 0xf8, 0xef, 0x30, + 0xbe, 0xe7, 0x05, 0x03, 0x09, 0x37, 0xef, 0xe0, 0x19, 0xd3, 0x06, 0x12, 0xa2, + 0x19, 0xf4, 0xe0, 0xe4, 0x24, 0xe9, 0x4d, 0xec, 0xfb, 0xf8, 0xe0, 0x19, 0xf4, + 0x61, 0xe3, 0x65, 0x03, 0x0d, 0x82, 0x10, 0x14, 0x16, 0x7f, 0xa3, 0x08, 0x1f, + 0x29, 0x32, 0x1f, 0x13, 0xe0, 0x08, 0xf1, 0x03, 0x14, 0x20, 0xfa, 0x1f, 0xe8, + 0xca, 0x28, 0x07, 0xdd, 0x01, 0xc2, 0x16, 0xd9, 0x0b, 0xe8, 0x43, 0x10, 0x01, + 0x24, 0x21, 0x31, 0x48, 0xd3, 0x0d, 0x07, 0xd7, 0x42, 0xfe, 0xe5, 0x41, 0xd2, + 0x04, 0x02, 0x1c, 0xb4, 0xd8, 0xb2, 0xde, 0xeb, 0x51, 0x50, 0xc5, 0xcf, 0x00, + 0xd4, 0x01, 0x2f, 0xc3, 0xdf, 0xbc, 0xfc, 0xe2, 0xf3, 0x26, 0xfc, 0x40, 0x42, + 0x2d, 0xc0, 0xbb, 0xef, 0xe1, 0xeb, 0x13, 0x15, 0xa0, 0x15, 0x5a, 0xee, 0x09, + 0xfe, 0xe6, 0x38, 0x0c, 0x97, 0xe2, 0x3b, 0xca, 0xc2, 0xf6, 0x2e, 0x17, 0xf2, + 0xf6, 0x29, 0x00, 0xe7, 0x34, 0x58, 0x26, 0xe2, 0x1f, 0x21, 0x1c, 0x14, 0x0a, + 0xe6, 0x06, 0xe6, 0xd0, 0xf4, 0x05, 0x1a, 0x1a, 0xf0, 0xc8, 0x25, 0x0e, 0xf3, + 0xee, 0xb3, 0xc7, 0xee, 0xf7, 0xe2, 0xf5, 0xfe, 0xea, 0xbb, 0x39, 0x0d, 0xf4, + 0x1f, 0x09, 0x29, 0xff, 0xde, 0xd4, 0xd1, 0x06, 0xdd, 0xf7, 0x10, 0xf3, 0x3b, + 0x21, 0xd5, 0x03, 0xf2, 0xf9, 0x00, 0xe0, 0xdc, 0xec, 0x1c, 0xf4, 0x08, 0x34, + 0x7f, 0x17, 0xee, 0x0c, 0xdd, 0x2b, 0x18, 0xb1, 0x33, 0xe1, 0xc9, 0xf4, 0xe0, + 0x07, 0xef, 0xd3, 0xd5, 0x11, 0x3d, 0x15, 0x0c, 0x3c, 0x02, 0x00, 0x25, 0xf9, + 0xf1, 0xe2, 0xd6, 0xf2, 0xff, 0x50, 0x23, 0x24, 0x0d, 0xea, 0xf0, 0x3f, 0x08, + 0xf7, 0xeb, 0x38, 0xec, 0xfe, 0xe2, 0xce, 0xdf, 0xf1, 0x10, 0x14, 0x31, 0x01, + 0xea, 0xed, 0xeb, 0x07, 0xf1, 0x3f, 0x0f, 0x0b, 0x0b, 0xea, 0x26, 0x02, 0x19, + 0x0e, 0x1d, 0x27, 0xbd, 0x39, 0x03, 0x02, 0xd4, 0xc4, 0xe0, 0x2a, 0x19, 0x08, + 0x04, 0x2e, 0xde, 0x0d, 0x2c, 0x0e, 0x01, 0x33, 0xdf, 0x1e, 0xfc, 0xeb, 0xfb, + 0x09, 0xbf, 0xf0, 0xf9, 0x1a, 0xe4, 0xd8, 0x16, 0x01, 0xc1, 0x98, 0xec, 0xeb, + 0xe7, 0x37, 0x19, 0xd3, 0x15, 0x0b, 0x11, 0x23, 0x02, 0x04, 0xef, 0x1a, 0x52, + 0xfa, 0x2a, 0x34, 0xf9, 0x0b, 0x14, 0xc0, 0xf8, 0xd9, 0xfb, 0x24, 0xba, 0x2c, + 0x09, 0x2a, 0xb0, 0xef, 0x45, 0xb4, 0x1f, 0xff, 0x3c, 0x0a, 0x08, 0xfe, 0xf7, + 0x0f, 0x32, 0xcc, 0xbd, 0xc1, 0xf0, 0x0c, 0xd0, 0x08, 0x06, 0xfe, 0xf6, 0xde, + 0x3c, 0x01, 0xb9, 0x1a, 0x35, 0x0e, 0x26, 0x00, 0xdc, 0xe9, 0xcd, 0x1d, 0xe1, + 0x11, 0x81, 0x2d, 0x20, 0xcd, 0x24, 0xc5, 0xfc, 0xe5, 0x00, 0xed, 0xe1, 0x3e, + 0xf4, 0x1c, 0x0c, 0xe0, 0xe7, 0x12, 0x17, 0x1d, 0xed, 0xe9, 0x18, 0xa9, 0xe2, + 0xe8, 0xea, 0x44, 0x49, 0x13, 0x13, 0xc1, 0x12, 0xcb, 0x2b, 0xea, 0x1a, 0x22, + 0x35, 0x28, 0x27, 0xd5, 0x2d, 0xfb, 0xfd, 0x42, 0x5c, 0xee, 0x68, 0x0e, 0xeb, + 0xea, 0x2d, 0x46, 0xee, 0x3d, 0x7d, 0x07, 0x02, 0xf8, 0xe8, 0xf1, 0xe5, 0x02, + 0x0a, 0xe5, 0xf4, 0x09, 0xed, 0x6d, 0x31, 0x89, 0xf0, 0xea, 0xf2, 0xce, 0x0e, + 0x18, 0x09, 0x10, 0x41, 0xd8, 0x12, 0x0c, 0xd4, 0x08, 0x2e, 0x81, 0x33, 0x0d, + 0x54, 0xf5, 0x25, 0xb9, 0xc2, 0x12, 0xf7, 0xe1, 0x2c, 0x0f, 0x36, 0xea, 0x28, + 0x28, 0x10, 0x19, 0xfc, 0x07, 0x2a, 0xff, 0xf5, 0x0f, 0xed, 0x04, 0x1c, 0x0c, + 0xf5, 0x2d, 0xca, 0x18, 0x14, 0x19, 0x0d, 0x39, 0xaf, 0x05, 0x0f, 0xe9, 0xf7, + 0xd6, 0xef, 0xc8, 0x4a, 0xe8, 0x55, 0x03, 0xbb, 0xff, 0xe3, 0xda, 0xf8, 0xe3, + 0x28, 0x8c, 0x1a, 0x0e, 0x15, 0x7c, 0x04, 0x0f, 0xfe, 0x34, 0xe5, 0xe9, 0xf5, + 0xfc, 0xbd, 0xe3, 0x24, 0x2a, 0x44, 0xf1, 0xb5, 0xe5, 0x10, 0xde, 0x0c, 0xe6, + 0xd7, 0xe4, 0xdc, 0x83, 0xa2, 0xe5, 0xc3, 0x41, 0xeb, 0x13, 0xc3, 0xf4, 0x1e, + 0xff, 0x25, 0xb9, 0x11, 0x54, 0x53, 0xf9, 0x36, 0xd5, 0xf6, 0xf8, 0xe7, 0x1b, + 0xe0, 0x0b, 0xeb, 0xef, 0x27, 0x16, 0x40, 0x0b, 0x11, 0x4a, 0x00, 0x2a, 0xb8, + 0x02, 0x4a, 0x71, 0x05, 0xaf, 0x01, 0x30, 0x07, 0xda, 0xe8, 0xd4, 0xd9, 0xbb, + 0xff, 0x36, 0xe5, 0xe0, 0x0c, 0xcb, 0x4e, 0x2d, 0xe5, 0xd5, 0x19, 0x0e, 0x2f, + 0x28, 0xe2, 0x3a, 0xbd, 0xbd, 0xe9, 0x13, 0xed, 0x15, 0x17, 0xdf, 0x03, 0x67, + 0xfb, 0x28, 0xd3, 0x3f, 0x1e, 0xce, 0x59, 0xf0, 0x56, 0x58, 0xdc, 0x28, 0x1a, + 0xcc, 0xb4, 0xce, 0x36, 0xf3, 0x31, 0xde, 0xe5, 0xd8, 0xf3, 0x0c, 0x1f, 0x54, + 0xe3, 0xf1, 0x7f, 0x23, 0x0a, 0x62, 0x08, 0x34, 0xd0, 0xf9, 0xc2, 0x0a, 0xf4, + 0x53, 0x0a, 0x17, 0x20, 0xf7, 0x05, 0xfa, 0x78, 0xd8, 0xc1, 0xfd, 0x1b, 0xf4, + 0x81, 0xa5, 0xe4, 0x16, 0xdc, 0xec, 0xf1, 0xff, 0x02, 0xf4, 0x1e, 0xe7, 0xc8, + 0x00, 0x13, 0x0d, 0x26, 0x24, 0xf0, 0xdd, 0x22, 0xfc, 0x2f, 0x12, 0x08, 0xe9, + 0x04, 0x02, 0xee, 0xf4, 0xe2, 0x1d, 0x24, 0xdb, 0xfc, 0x2e, 0xb7, 0x15, 0xb3, + 0x1f, 0xf6, 0x5b, 0x14, 0xc7, 0xbc, 0xcb, 0x65, 0x00, 0xd4, 0x37, 0xde, 0x1b, + 0xe3, 0x07, 0x33, 0xb6, 0x25, 0x11, 0x36, 0x48, 0x0c, 0x1f, 0x11, 0xfa, 0xf9, + 0xd2, 0xdd, 0xdc, 0x14, 0x05, 0xff, 0x3a, 0x3f, 0x18, 0x4b, 0xf3, 0xed, 0xd0, + 0xb4, 0x01, 0xde, 0xdc, 0xfb, 0x07, 0x00, 0xf6, 0x27, 0xf7, 0xd1, 0x38, 0x0b, + 0xf3, 0xbb, 0x1d, 0x1c, 0x23, 0x0e, 0xf9, 0xb9, 0xa5, 0x20, 0x0c, 0x00, 0xcb, + 0x02, 0xfe, 0xf7, 0xf7, 0xfc, 0x55, 0xd6, 0xd7, 0x4d, 0xeb, 0xfc, 0xee, 0x0c, + 0x02, 0x20, 0x05, 0xcc, 0xfb, 0xfa, 0xed, 0x23, 0xd8, 0xca, 0x08, 0xfa, 0x81, + 0xfb, 0xc2, 0xf2, 0x1f, 0xa1, 0xe1, 0x3a, 0xe7, 0x0e, 0xf9, 0xfa, 0xd2, 0xec, + 0x04, 0x37, 0x40, 0x18, 0x46, 0x13, 0xd4, 0x0e, 0x24, 0xe7, 0xfc, 0x26, 0xe1, + 0x17, 0x33, 0x21, 0x0f, 0xc4, 0xef, 0xf1, 0xde, 0xda, 0xb9, 0x2f, 0x11, 0x2c, + 0xd5, 0xef, 0xec, 0x26, 0x1a, 0xf0, 0xd9, 0xe9, 0xeb, 0xf1, 0x00, 0x05, 0xd9, + 0xdd, 0xc6, 0xaa, 0xdb, 0x0b, 0x23, 0xd8, 0x22, 0x12, 0x04, 0x0e, 0x0e, 0x10, + 0xfb, 0xd6, 0xf4, 0xd3, 0x19, 0xe4, 0x31, 0xcd, 0xeb, 0xba, 0xd9, 0xfa, 0xe0, + 0xcb, 0x0e, 0x1c, 0x11, 0x0e, 0x2f, 0xf9, 0xe9, 0xed, 0xc4, 0xcb, 0xec, 0xd9, + 0x01, 0xf3, 0x3f, 0x1d, 0x11, 0xfa, 0x52, 0x14, 0x35, 0x33, 0xee, 0x29, 0xda, + 0x18, 0x14, 0xf3, 0xcc, 0xe3, 0x10, 0x81, 0xc6, 0xd0, 0x31, 0x47, 0xe0, 0xe6, + 0xf1, 0x02, 0x54, 0x02, 0x76, 0x09, 0x05, 0x29, 0x23, 0xd3, 0xd4, 0xfb, 0x1c, + 0x4f, 0xdc, 0x45, 0xd6, 0x1b, 0xf4, 0x50, 0x17, 0x63, 0x0e, 0x40, 0x44, 0xe0, + 0xe3, 0x09, 0x1c, 0xeb, 0x2b, 0x16, 0x09, 0xc6, 0xd8, 0x31, 0x11, 0x06, 0x37, + 0x34, 0x3f, 0xde, 0x27, 0x3e, 0xd8, 0xd1, 0xd1, 0xb0, 0x9d, 0x3a, 0xed, 0x0d, + 0x23, 0x10, 0xc6, 0x0e, 0xc6, 0xf9, 0x39, 0x17, 0x65, 0x02, 0xff, 0x14, 0xd5, + 0x02, 0xff, 0x28, 0x2c, 0x0a, 0x2c, 0xf9, 0xf1, 0x0c, 0x1c, 0x13, 0xe6, 0x06, + 0x00, 0x11, 0x13, 0xf7, 0x3a, 0xc9, 0xc0, 0x1b, 0xd7, 0x10, 0x18, 0xf5, 0x1d, + 0x78, 0xfe, 0x1a, 0x26, 0x19, 0xdf, 0xf3, 0xcd, 0x02, 0xe2, 0xfa, 0x26, 0x07, + 0x13, 0x07, 0x42, 0xe8, 0x0f, 0xe2, 0xf7, 0xca, 0xdd, 0x4d, 0x49, 0x40, 0x11, + 0xc6, 0x42, 0xb8, 0xe8, 0x03, 0xdd, 0x0b, 0x14, 0x2a, 0x2a, 0x3e, 0x18, 0xac, + 0xb3, 0xef, 0x1c, 0xef, 0xfc, 0xed, 0x0e, 0xfb, 0xf8, 0x14, 0x7f, 0x39, 0x8a, + 0x03, 0xe8, 0x5e, 0xdb, 0xd4, 0x5c, 0x02, 0x02, 0x39, 0xf6, 0xa4, 0xc7, 0xd4, + 0x28, 0xf3, 0xd2, 0xf9, 0xf8, 0xf9, 0x9f, 0xff, 0xb0, 0x28, 0xdb, 0x11, 0xe3, + 0xd1, 0xf6, 0xd0, 0x0f, 0x41, 0x26, 0x11, 0xe4, 0x1b, 0xed, 0xac, 0x33, 0x42, + 0x14, 0x45, 0x16, 0x0f, 0x09, 0x3b, 0xb3, 0x45, 0xeb, 0xb3, 0x3a, 0x00, 0xe9, + 0xcc, 0x37, 0xd4, 0x26, 0x10, 0xf7, 0xfd, 0xc1, 0x0d, 0x2d, 0xe4, 0x01, 0xbb, + 0x1b, 0x2e, 0x23, 0xe5, 0xf9, 0xec, 0xda, 0xc7, 0x0c, 0xee, 0xf9, 0xd6, 0xf9, + 0xd9, 0xf4, 0x4a, 0x30, 0xd6, 0xf3, 0xe7, 0x4c, 0x3b, 0x4b, 0x02, 0x05, 0x19, + 0x24, 0x0b, 0xa8, 0x02, 0x44, 0xff, 0x22, 0x25, 0xb8, 0x3b, 0x59, 0x9c, 0x1e, + 0xc4, 0x17, 0x20, 0xff, 0x0e, 0xdf, 0xd7, 0xfb, 0x0b, 0x0d, 0x05, 0xf6, 0x4e, + 0x00, 0xeb, 0x99, 0x1a, 0x3a, 0x26, 0xa6, 0x23, 0x1b, 0x0c, 0xbb, 0x13, 0x47, + 0x27, 0xdc, 0xe6, 0xfc, 0x37, 0x18, 0xbb, 0xfa, 0xb1, 0xdb, 0x65, 0xfa, 0x16, + 0xb6, 0xf7, 0x0a, 0xd8, 0x1d, 0xb0, 0xf4, 0xf4, 0xee, 0xdf, 0xf8, 0x2c, 0xd2, + 0x31, 0xe0, 0xf9, 0xdd, 0xa5, 0xbc, 0xb0, 0x1c, 0x3f, 0xdd, 0x2f, 0xf5, 0xc2, + 0xf6, 0xe1, 0xf8, 0xf2, 0xca, 0x1b, 0xbb, 0x94, 0xf6, 0x92, 0xed, 0xd9, 0xe4, + 0x3b, 0xb0, 0xda, 0xfe, 0xf2, 0x20, 0x8e, 0xf0, 0x5b, 0xd8, 0x0a, 0xf3, 0x3d, + 0xab, 0x16, 0xf7, 0xf8, 0x21, 0x00, 0xe9, 0x39, 0x09, 0xc7, 0x78, 0x3c, 0x08, + 0x1f, 0x1f, 0x1c, 0x4e, 0x53, 0x81, 0xc8, 0x13, 0x20, 0x3b, 0xdd, 0x22, 0x21, + 0x30, 0xaa, 0x05, 0xd8, 0x6f, 0xf4, 0xe5, 0xd3, 0xd7, 0x28, 0x78, 0xbc, 0xd7, + 0xea, 0xb2, 0x15, 0x1d, 0xbf, 0x91, 0xef, 0xe0, 0x2d, 0xed, 0x0f, 0x9a, 0xbf, + 0x38, 0xf1, 0xef, 0xe8, 0x17, 0xa0, 0xff, 0x81, 0x17, 0x63, 0xfa, 0xb9, 0x19, + 0x42, 0x08, 0xd4, 0x9c, 0xfc, 0x29, 0x23, 0x5f, 0x00, 0x37, 0xf8, 0x18, 0x16, + 0xb7, 0xd7, 0xdc, 0x30, 0xd3, 0x34, 0xac, 0x04, 0xe3, 0xab, 0xd1, 0x23, 0xe1, + 0xe4, 0x2b, 0xf2, 0x44, 0xc6, 0xf0, 0x3d, 0x20, 0xab, 0x3d, 0xde, 0xde, 0x40, + 0xf8, 0xe6, 0x63, 0x4f, 0x3d, 0x2a, 0x03, 0xe0, 0x14, 0x04, 0xf7, 0x08, 0xf1, + 0xab, 0x34, 0xe2, 0xd8, 0x05, 0xee, 0xea, 0xd2, 0x1c, 0xfa, 0xe6, 0xf9, 0x00, + 0xbf, 0x05, 0xe9, 0x1b, 0x1c, 0x2a, 0xd9, 0xbf, 0x1f, 0x2d, 0x22, 0xee, 0xe6, + 0x2e, 0xc1, 0xfb, 0xed, 0xc0, 0x3a, 0xfa, 0xe0, 0xdc, 0x0e, 0xb6, 0xac, 0xe7, + 0xea, 0x11, 0x37, 0x16, 0x47, 0xff, 0x1c, 0xdc, 0x70, 0x1d, 0xce, 0xfe, 0xce, + 0xef, 0x0f, 0xfc, 0xdc, 0xd5, 0x02, 0xff, 0x13, 0xcb, 0xc0, 0x2a, 0xf4, 0x2b, + 0xf4, 0x4c, 0x28, 0xd6, 0x0f, 0x12, 0x28, 0xd2, 0xf5, 0x14, 0x0e, 0x22, 0xd5, + 0x1f, 0xfe, 0x28, 0xd2, 0xdd, 0xe3, 0xe8, 0x0c, 0x12, 0xec, 0xee, 0x0c, 0xbd, + 0xdf, 0xe4, 0xbf, 0x81, 0x53, 0xf7, 0xce, 0x37, 0x1b, 0x30, 0x04, 0xd5, 0x1d, + 0xde, 0xf7, 0x10, 0x05, 0x11, 0x32, 0x03, 0xc6, 0xfc, 0xe8, 0xda, 0xea, 0xd4, + 0x3e, 0x0b, 0xfc, 0x17, 0x34, 0xd6, 0x56, 0x96, 0x25, 0xf0, 0xfc, 0x30, 0xe0, + 0xe7, 0x16, 0xe8, 0xcf, 0xe7, 0xe6, 0xfe, 0x97, 0xe4, 0xc1, 0x09, 0xe9, 0x6c, + 0x0e, 0xf8, 0xec, 0x2a, 0x04, 0x00, 0xe4, 0x23, 0x3c, 0xea, 0xb1, 0xf8, 0xcd, + 0x25, 0xdf, 0xcf, 0xfb, 0x05, 0x01, 0xf2, 0xf2, 0xb8, 0x0e, 0xcf, 0xf0, 0xec, + 0xf2, 0x19, 0xec, 0xea, 0xda, 0xe6, 0xef, 0xee, 0xe0, 0x81, 0xfc, 0xc5, 0x46, + 0xec, 0xca, 0x00, 0xf8, 0xe6, 0x07, 0xd6, 0x07, 0x3f, 0x03, 0x01, 0x25, 0x26, + 0xf1, 0xd0, 0xea, 0x0a, 0x0f, 0xeb, 0xe4, 0xec, 0xbc, 0xe0, 0x46, 0xe7, 0xf7, + 0xf1, 0x02, 0xdf, 0xe4, 0xdc, 0x51, 0xd0, 0xd7, 0xda, 0x38, 0xf0, 0x05, 0xf9, + 0x15, 0xf7, 0x01, 0x1a, 0xe9, 0xf2, 0x07, 0x19, 0xd7, 0xee, 0xd6, 0x2c, 0x24, + 0xa4, 0x33, 0xfd, 0x22, 0x13, 0x17, 0x59, 0xf0, 0x07, 0x25, 0xd8, 0xd9, 0xdf, + 0x35, 0xd7, 0xeb, 0x06, 0x00, 0xde, 0xf9, 0xe3, 0x0f, 0x54, 0xc6, 0x01, 0xfc, + 0x1f, 0x2d, 0x20, 0xcd, 0xc1, 0xfb, 0xc3, 0xb1, 0xc8, 0xf3, 0x49, 0xd4, 0x0a, + 0xf2, 0xfc, 0xe1, 0xd7, 0x19, 0xa0, 0x4d, 0x14, 0x33, 0x25, 0xf3, 0x0f, 0xa6, + 0xe8, 0x32, 0xf2, 0xde, 0xee, 0xd3, 0xf7, 0x38, 0xf7, 0x04, 0x43, 0x0a, 0xe5, + 0x17, 0xf2, 0x15, 0x0d, 0x46, 0x0a, 0x18, 0xb3, 0xf2, 0xe9, 0xaf, 0x03, 0xe0, + 0x0d, 0x42, 0xf3, 0xef, 0x36, 0xeb, 0xdf, 0xe7, 0xeb, 0xff, 0x13, 0x30, 0xb7, + 0xeb, 0xe9, 0xf9, 0xe6, 0x12, 0x11, 0x09, 0x25, 0xef, 0xf8, 0xf8, 0xf4, 0x03, + 0xf2, 0xdb, 0x10, 0x25, 0x06, 0xe6, 0x1f, 0x24, 0x16, 0xd3, 0xde, 0x0d, 0xb1, + 0xec, 0x30, 0x06, 0xf5, 0xd9, 0xb6, 0x11, 0x03, 0x11, 0xd8, 0xc3, 0xe1, 0x0b, + 0x04, 0x13, 0x37, 0xec, 0xd5, 0xda, 0xe6, 0xed, 0xf7, 0x16, 0x0f, 0x40, 0x29, + 0xd5, 0x20, 0xf9, 0x0c, 0xe8, 0x36, 0x3a, 0xe6, 0x26, 0xfe, 0xea, 0x22, 0xd6, + 0x0a, 0xc0, 0xee, 0x14, 0x44, 0x38, 0x2e, 0xe4, 0x0c, 0xd7, 0x27, 0xd0, 0x53, + 0xdd, 0xb1, 0x35, 0xf4, 0xdf, 0xd6, 0x7f, 0xf1, 0xcb, 0x33, 0xf2, 0x0d, 0x3c, + 0xee, 0x2e, 0x11, 0x2a, 0x38, 0x0d, 0xec, 0x6d, 0xe8, 0x2e, 0x28, 0xa4, 0xd7, + 0x44, 0x0e, 0x58, 0xfd, 0xd4, 0xfb, 0x2e, 0x0c, 0xf3, 0x04, 0x4f, 0x12, 0xf3, + 0x33, 0xf2, 0xf6, 0xc5, 0xd7, 0xfe, 0xf9, 0x2a, 0xef, 0xd0, 0x02, 0xb2, 0xfd, + 0x49, 0xae, 0xd9, 0x38, 0xf4, 0x1d, 0xf2, 0x42, 0x19, 0x10, 0x43, 0xb2, 0x15, + 0x03, 0x0c, 0xcb, 0x0d, 0x02, 0xde, 0x05, 0xd4, 0x05, 0x43, 0xcd, 0xa7, 0xe7, + 0xfd, 0xf5, 0x5f, 0x81, 0x5a, 0xd3, 0x0e, 0x00, 0x21, 0x00, 0xfa, 0xbc, 0x0a, + 0xd9, 0xdb, 0x00, 0xc5, 0x14, 0xef, 0xf4, 0x1f, 0xee, 0x4d, 0x5f, 0xaa, 0x19, + 0xd5, 0x04, 0x2c, 0xde, 0xd1, 0x21, 0xf9, 0xee, 0x6e, 0xc9, 0xbb, 0x15, 0xf0, + 0x10, 0xc4, 0x7c, 0xe3, 0xe3, 0x27, 0xe0, 0x4d, 0x16, 0x27, 0xaf, 0x0f, 0xbf, + 0xf1, 0x53, 0xfb, 0xa1, 0xde, 0x04, 0xcc, 0x36, 0xf3, 0x65, 0xf3, 0x01, 0xcd, + 0xea, 0x12, 0xe2, 0xd6, 0xa1, 0xa8, 0xf1, 0x04, 0x13, 0x41, 0xc5, 0xdc, 0x65, + 0xc9, 0x21, 0xfc, 0xf9, 0xfa, 0x18, 0xba, 0x3b, 0xd0, 0x81, 0xf4, 0x30, 0x25, + 0xff, 0xe2, 0x28, 0xff, 0xe8, 0xd2, 0xc2, 0x94, 0xc2, 0xe7, 0x1d, 0x48, 0xdf, + 0xbe, 0xe1, 0xce, 0xca, 0xfa, 0x12, 0x1e, 0xe3, 0xd6, 0x20, 0x44, 0xae, 0xcc, + 0xf8, 0xec, 0xe7, 0x22, 0x10, 0xa4, 0x4f, 0x21, 0x2a, 0x0a, 0xcf, 0x1b, 0xb6, + 0xec, 0xe8, 0x02, 0x0b, 0xe6, 0x1a, 0xe4, 0xcb, 0xa6, 0x13, 0xe1, 0xbf, 0xc7, + 0x96, 0xc0, 0xee, 0xd8, 0x00, 0x2c, 0x3d, 0xda, 0xe6, 0xc0, 0xf7, 0x13, 0xf8, + 0x1a, 0x30, 0xf0, 0xe5, 0x4d, 0x07, 0x18, 0x22, 0xa1, 0x04, 0xd1, 0xbe, 0x19, + 0xff, 0xef, 0xe0, 0xaa, 0x5b, 0xe0, 0xb9, 0xf3, 0x27, 0xc5, 0xd0, 0x04, 0x62, + 0xee, 0xda, 0x7b, 0x3a, 0xf8, 0x56, 0xbf, 0x26, 0x04, 0x09, 0xcb, 0x25, 0xf9, + 0xfd, 0x68, 0x04, 0xcf, 0x4e, 0x40, 0x32, 0x72, 0x18, 0x2b, 0xf1, 0xfd, 0x16, + 0x0a, 0xe3, 0xa4, 0x3b, 0x58, 0xf3, 0xba, 0x26, 0x41, 0xc8, 0x5a, 0x07, 0x6a, + 0x22, 0x4e, 0x2e, 0xaa, 0x37, 0x3f, 0x31, 0x14, 0x03, 0xf4, 0x10, 0xef, 0x31, + 0xce, 0x1e, 0xfe, 0xdf, 0x18, 0xe8, 0x18, 0x1a, 0x1b, 0xfb, 0xc5, 0xd1, 0x1f, + 0xdb, 0x1a, 0x31, 0xdd, 0x14, 0xb5, 0x6c, 0x74, 0x6d, 0xfe, 0x32, 0xec, 0xb0, + 0x24, 0x15, 0xfb, 0xd3, 0xca, 0xc4, 0x04, 0x02, 0xf2, 0x45, 0xcd, 0xfc, 0x0c, + 0x27, 0xe4, 0xf6, 0x29, 0x18, 0xd7, 0x35, 0xda, 0x01, 0x1b, 0x52, 0x13, 0x0b, + 0xef, 0xf0, 0x9a, 0x12, 0xbb, 0xc5, 0xdb, 0xda, 0xf5, 0xd3, 0x31, 0xcf, 0x49, + 0x23, 0x9a, 0xe4, 0xea, 0xd1, 0xe5, 0x05, 0xc9, 0xd3, 0x0b, 0xf2, 0x02, 0x36, + 0x13, 0xb2, 0x18, 0x1f, 0x33, 0xca, 0x0a, 0xe7, 0xfa, 0x41, 0xe9, 0xa3, 0xc1, + 0x7f, 0x98, 0x1a, 0x0f, 0x91, 0xe6, 0xe8, 0x1e, 0x40, 0xd4, 0xc4, 0xf6, 0x27, + 0xfe, 0x0b, 0x32, 0x1b, 0xfe, 0x19, 0x31, 0xfd, 0x14, 0xc2, 0xbe, 0xc0, 0xc9, + 0x26, 0xe3, 0xa3, 0xeb, 0x73, 0x5a, 0x44, 0xe4, 0xe3, 0xf2, 0x25, 0xed, 0xee, + 0x22, 0x1f, 0x08, 0xfb, 0x2b, 0xf3, 0x2a, 0xd3, 0xbc, 0xd2, 0xeb, 0x1d, 0xdc, + 0x02, 0x39, 0x04, 0x1b, 0x1b, 0xc2, 0xd3, 0x14, 0xeb, 0x1f, 0x05, 0x43, 0x10, + 0xec, 0xcb, 0xcb, 0x00, 0x15, 0x24, 0xf2, 0x00, 0x2b, 0xda, 0xf9, 0x02, 0xf0, + 0xfc, 0xce, 0x13, 0xfa, 0x11, 0xe4, 0xea, 0xc5, 0x61, 0xee, 0xd4, 0x1d, 0x08, + 0x7f, 0x1a, 0x44, 0x12, 0xef, 0x0a, 0xe2, 0xed, 0x08, 0x02, 0x21, 0x04, 0x4f, + 0x1c, 0x21, 0x04, 0x14, 0x10, 0xf7, 0xdb, 0xc8, 0x18, 0xde, 0x0a, 0x50, 0xac, + 0x25, 0x0e, 0xc4, 0x26, 0xeb, 0x28, 0x02, 0xed, 0x17, 0x2d, 0xf5, 0x0c, 0xf9, + 0xe1, 0x72, 0xe6, 0xbc, 0x23, 0x06, 0x01, 0xda, 0x1a, 0x15, 0xb4, 0x33, 0x02, + 0xe2, 0x1c, 0xcd, 0x0d, 0xd6, 0x19, 0x72, 0x17, 0xa9, 0x0e, 0x8e, 0xc6, 0xfa, + 0xd5, 0x29, 0x03, 0xd0, 0x26, 0x7f, 0x42, 0x18, 0xa7, 0x2a, 0x0c, 0x01, 0x00, + 0xfb, 0xe1, 0x23, 0x6e, 0x2c, 0xeb, 0x2f, 0x06, 0x1b, 0xf7, 0x16, 0x16, 0x5b, + 0xf8, 0x2f, 0x0c, 0x37, 0xde, 0xfc, 0xec, 0xff, 0x58, 0x18, 0x01, 0xc4, 0x9d, + 0xe5, 0xfc, 0x05, 0x37, 0x14, 0x12, 0xb5, 0xc4, 0xe8, 0xdf, 0x21, 0x33, 0x29, + 0x2b, 0x02, 0xa4, 0x3c, 0xd6, 0xfa, 0x20, 0xf5, 0x11, 0x03, 0x07, 0xb7, 0xd8, + 0xd0, 0xc0, 0xd5, 0x0f, 0xe3, 0xf4, 0xeb, 0xf0, 0xd7, 0x0e, 0x0b, 0x39, 0x29, + 0xdc, 0x0a, 0xfc, 0xf0, 0xec, 0x4c, 0x46, 0xf2, 0xfd, 0x33, 0x19, 0x13, 0x2c, + 0xe6, 0xc3, 0xdc, 0xfe, 0x1e, 0x23, 0x3a, 0x09, 0xfe, 0xfe, 0xce, 0x0e, 0xad, + 0x37, 0x4b, 0xc5, 0xec, 0xfa, 0xc4, 0x1b, 0x09, 0xf7, 0x1d, 0xef, 0xc1, 0x11, + 0x11, 0xfc, 0xe6, 0xc4, 0x0b, 0x15, 0x1d, 0x0b, 0xc8, 0xd2, 0xf9, 0x08, 0xb2, + 0x21, 0xf5, 0xf6, 0x2d, 0x30, 0xc4, 0x04, 0x0a, 0xe4, 0xc6, 0x09, 0x0b, 0xb0, + 0xf5, 0x06, 0x2b, 0x09, 0xcb, 0xc4, 0xf1, 0xf7, 0x41, 0x05, 0x08, 0xee, 0x41, + 0xeb, 0x34, 0x19, 0x28, 0x13, 0x03, 0xc4, 0xda, 0x1a, 0x27, 0x04, 0xf3, 0xda, + 0xf7, 0x02, 0xbe, 0x00, 0x36, 0xda, 0xb2, 0x60, 0xf9, 0xbf, 0x02, 0xe2, 0xce, + 0xf3, 0xd4, 0x11, 0x20, 0xe3, 0xc2, 0xac, 0x0f, 0x02, 0xf5, 0xef, 0x33, 0x38, + 0xe8, 0x1c, 0x12, 0x0e, 0x46, 0xc0, 0xe1, 0xf8, 0xda, 0x20, 0x21, 0xf2, 0x50, + 0xd7, 0x0e, 0x20, 0x04, 0x01, 0xfe, 0xb8, 0x35, 0xfb, 0x30, 0xc5, 0xe1, 0xe9, + 0xe2, 0xdc, 0x81, 0x70, 0xe7, 0x15, 0xfc, 0x6c, 0x05, 0xf9, 0x1b, 0x28, 0x29, + 0x06, 0x1b, 0xed, 0x86, 0x07, 0x17, 0xd7, 0x1c, 0xff, 0xb1, 0x18, 0xcd, 0xc1, + 0xeb, 0x31, 0xfe, 0xf8, 0xda, 0xf7, 0x02, 0x20, 0x09, 0xd6, 0x15, 0xd7, 0xe4, + 0x06, 0xdb, 0x11, 0xdb, 0xf4, 0x11, 0x15, 0xcc, 0x19, 0xed, 0xe4, 0x41, 0x2f, + 0xef, 0xfa, 0x0c, 0xe2, 0x07, 0x31, 0xf1, 0x30, 0xee, 0xf5, 0x09, 0x10, 0xe0, + 0xcb, 0x36, 0x20, 0x0d, 0xe4, 0x27, 0x3b, 0x1c, 0x1c, 0x3f, 0x0f, 0xd6, 0xef, + 0xee, 0x81, 0x30, 0x0d, 0xd5, 0x36, 0xf9, 0xd8, 0x12, 0xe5, 0x99, 0xf9, 0xb5, + 0x00, 0x0c, 0x3c, 0x18, 0x36, 0x30, 0xc0, 0x13, 0x06, 0xd7, 0xf6, 0x19, 0xbf, + 0xd5, 0x05, 0xfb, 0xbe, 0xf5, 0x20, 0xc8, 0x01, 0xe5, 0xd7, 0xf8, 0xe7, 0xe7, + 0xf4, 0xcc, 0xbc, 0xb8, 0x08, 0x1d, 0x24, 0x2d, 0x09, 0xf6, 0x1f, 0xef, 0xf0, + 0xff, 0x16, 0xef, 0x24, 0x0f, 0xf4, 0xed, 0xe9, 0x11, 0x16, 0x0e, 0xe6, 0x27, + 0x12, 0xe1, 0x0b, 0xdd, 0x2c, 0x12, 0x4e, 0xf0, 0x01, 0x08, 0xf5, 0x27, 0xcc, + 0xeb, 0xfc, 0x20, 0xf5, 0x23, 0xff, 0x2b, 0xaf, 0x0a, 0x6a, 0x57, 0xd8, 0xd1, + 0xec, 0xe3, 0xfc, 0x1b, 0xd9, 0x0e, 0xf7, 0x05, 0x05, 0x08, 0xbf, 0x05, 0xc6, + 0x0b, 0xf5, 0xdd, 0x0b, 0x1a, 0x00, 0x03, 0xdf, 0xc6, 0xf6, 0x0a, 0xfa, 0x05, + 0x19, 0xcf, 0xe1, 0x36, 0xd7, 0xb5, 0xf9, 0xe8, 0x14, 0x00, 0x08, 0xe3, 0x00, + 0x32, 0xda, 0xf6, 0x0f, 0x01, 0xec, 0x0a, 0x13, 0x04, 0xe4, 0xf3, 0x3e, 0xed, + 0x48, 0xf3, 0xf6, 0x03, 0x1a, 0x10, 0x02, 0xe7, 0xf0, 0xf9, 0xe1, 0xc8, 0xe8, + 0xec, 0x36, 0x19, 0x1f, 0x06, 0xdd, 0xe2, 0x05, 0xfb, 0x1b, 0x07, 0xec, 0xdc, + 0x00, 0xe1, 0x2b, 0xf7, 0x0b, 0xf7, 0x00, 0x03, 0x12, 0x15, 0x24, 0x0b, 0x00, + 0x00, 0x1d, 0xe6, 0xd6, 0x0f, 0x25, 0x7f, 0xe9, 0xd0, 0x44, 0x14, 0xcc, 0xe4, + 0xd8, 0xe4, 0xd6, 0xf2, 0x24, 0xf3, 0xfc, 0xc0, 0x05, 0xf9, 0x09, 0xe3, 0x03, + 0x46, 0xf3, 0xd3, 0xea, 0xe6, 0xea, 0xe6, 0xed, 0x02, 0xe7, 0xf5, 0xb4, 0x42, + 0x2e, 0xf5, 0xe2, 0x18, 0x36, 0xf2, 0x20, 0x12, 0xd7, 0xb3, 0x02, 0x0f, 0xfe, + 0x32, 0x08, 0xee, 0xde, 0xcf, 0xe7, 0xf9, 0xbd, 0x2a, 0x17, 0xf1, 0x0f, 0xdf, + 0x42, 0xe8, 0x24, 0x0c, 0xc7, 0xf3, 0x20, 0xfe, 0xec, 0x07, 0x31, 0xd9, 0xef, + 0x1b, 0x29, 0x0a, 0x32, 0xfa, 0xf8, 0x7f, 0xd4, 0x6f, 0x16, 0x1b, 0xae, 0xf6, + 0x25, 0x11, 0x04, 0xed, 0x07, 0xbf, 0x20, 0x06, 0xfd, 0xe1, 0xf7, 0xcd, 0xec, + 0x1e, 0xeb, 0x0a, 0xe0, 0xc2, 0xee, 0x17, 0x24, 0xc9, 0xdc, 0x17, 0x1f, 0x08, + 0xe7, 0x1c, 0xf3, 0x0a, 0x22, 0x09, 0xc3, 0xf2, 0x10, 0x27, 0xed, 0x07, 0x1e, + 0x36, 0x02, 0x12, 0x0e, 0x19, 0x12, 0x09, 0xe9, 0xfc, 0x20, 0xf5, 0xf0, 0x30, + 0xfb, 0x11, 0x45, 0x7f, 0xe6, 0x23, 0xb3, 0xfe, 0xe9, 0xff, 0x02, 0x1a, 0x1b, + 0x39, 0x01, 0xe7, 0xdf, 0xd3, 0x34, 0xce, 0xe3, 0x17, 0xed, 0xe4, 0x27, 0x2b, + 0xf7, 0x25, 0xc7, 0xf2, 0x2a, 0xbd, 0x28, 0xe7, 0xfd, 0xe4, 0x11, 0x27, 0x25, + 0x11, 0xf5, 0x0d, 0x21, 0xfc, 0xec, 0x09, 0xef, 0xdc, 0xd0, 0x05, 0x0b, 0xef, + 0x4e, 0x0f, 0x21, 0x0f, 0x42, 0xfa, 0xd5, 0x25, 0xd7, 0x2f, 0x24, 0x1d, 0x50, + 0xf6, 0x04, 0x1f, 0x27, 0x0a, 0x52, 0xca, 0xfb, 0xc1, 0x14, 0x1c, 0x2d, 0x3c, + 0x06, 0x0d, 0x33, 0x1c, 0x03, 0x02, 0xf9, 0xfa, 0x21, 0xeb, 0xeb, 0xf9, 0x06, + 0xe2, 0xf0, 0x1a, 0xe7, 0x01, 0xb2, 0x15, 0x0f, 0xb8, 0x2a, 0x04, 0xfb, 0x14, + 0xda, 0xe7, 0xff, 0x5f, 0xe1, 0xf2, 0x0d, 0xd8, 0xff, 0xf7, 0xbc, 0xe8, 0xa4, + 0x28, 0x1b, 0xee, 0xeb, 0x50, 0xef, 0x06, 0x04, 0xd0, 0xfa, 0xcd, 0x00, 0xc8, + 0xe7, 0x81, 0xf0, 0xdc, 0xee, 0xfb, 0xc1, 0xa8, 0xf9, 0x38, 0x12, 0x4c, 0x14, + 0x76, 0xe3, 0xf8, 0xf2, 0x50, 0xf9, 0xe5, 0x1c, 0xd8, 0x39, 0xf5, 0x76, 0x00, + 0x32, 0xca, 0x1b, 0xfd, 0xf9, 0x00, 0xf8, 0x12, 0x10, 0xed, 0x3b, 0x0c, 0x10, + 0xe9, 0x06, 0xee, 0xe9, 0xfc, 0xf0, 0x0c, 0x13, 0x1b, 0x06, 0x14, 0x15, 0xc4, + 0xc1, 0xbf, 0xfb, 0x34, 0xfc, 0xe4, 0x3b, 0x02, 0xcd, 0x35, 0x35, 0xed, 0x33, + 0x03, 0xef, 0x04, 0x36, 0xcc, 0xf6, 0xf2, 0x21, 0xe9, 0x15, 0xe1, 0xed, 0xdb, + 0x27, 0xf7, 0xbc, 0xb4, 0x20, 0xee, 0x01, 0xac, 0x4f, 0xc2, 0xbd, 0xfe, 0xc7, + 0xe5, 0x0a, 0x08, 0xbb, 0xf3, 0xf8, 0x47, 0xeb, 0xd6, 0x19, 0xf2, 0x65, 0x21, + 0x17, 0xb6, 0x0a, 0x11, 0x0f, 0xf0, 0xf4, 0x26, 0x19, 0xce, 0xd2, 0x4d, 0x2b, + 0xfa, 0x06, 0x10, 0x06, 0xe2, 0x37, 0x20, 0x3f, 0xef, 0x44, 0x4e, 0x1a, 0x57, + 0x43, 0x81, 0xae, 0x1e, 0x46, 0x1f, 0x0b, 0x3a, 0x03, 0xae, 0x0d, 0xeb, 0xd8, + 0xcc, 0x25, 0xe2, 0x32, 0xc8, 0xe5, 0x18, 0xcd, 0x1a, 0x1e, 0xe1, 0xde, 0x20, + 0x12, 0x30, 0xcf, 0xe5, 0xe8, 0x16, 0x31, 0x0e, 0x25, 0xfe, 0x17, 0x05, 0xe9, + 0xb7, 0xa1, 0x2e, 0xc2, 0x0d, 0xb8, 0x4a, 0xf7, 0xdf, 0xd8, 0xf9, 0xcf, 0xaa, + 0x36, 0x08, 0x2f, 0x0c, 0xca, 0x99, 0x02, 0xf8, 0x04, 0x22, 0xdd, 0x2c, 0xcb, + 0xf6, 0x13, 0x20, 0xef, 0x0f, 0xe4, 0x39, 0x32, 0x17, 0xef, 0xc3, 0xe6, 0x04, + 0xc3, 0xf0, 0xde, 0xcf, 0xdc, 0x4d, 0xf8, 0xbc, 0x12, 0xd4, 0x2b, 0xbe, 0xf7, + 0xb5, 0x12, 0x05, 0x02, 0xcb, 0x2e, 0xcc, 0x03, 0xbd, 0x5c, 0x11, 0xde, 0x2a, + 0xca, 0x33, 0xfb, 0xe9, 0xd8, 0x11, 0x64, 0xf6, 0xf7, 0x2f, 0xeb, 0x09, 0x47, + 0xf5, 0x29, 0x05, 0xfc, 0x27, 0xf2, 0xe0, 0xc3, 0x3e, 0x09, 0xf7, 0xec, 0xb5, + 0x11, 0xf8, 0x0d, 0x7f, 0xfa, 0xc4, 0x0c, 0xec, 0xf0, 0xea, 0x22, 0xe7, 0xd5, + 0xb4, 0xf5, 0xac, 0x14, 0xd8, 0xfb, 0xe0, 0xee, 0x22, 0xc7, 0x1c, 0xd8, 0x02, + 0xaa, 0xd9, 0xe2, 0x1f, 0x1f, 0xff, 0x25, 0x25, 0x1a, 0x20, 0xcd, 0xfa, 0x01, + 0xee, 0xec, 0xbf, 0x2e, 0x35, 0x07, 0x25, 0x16, 0x2d, 0x01, 0xcd, 0x19, 0x49, + 0xe4, 0x57, 0xff, 0xfb, 0xf2, 0xef, 0x09, 0x28, 0xf5, 0xa9, 0xd6, 0x00, 0xcf, + 0xf3, 0xe5, 0xc2, 0xfc, 0xca, 0xfd, 0x0d, 0x18, 0xde, 0x1d, 0xf4, 0xd7, 0x27, + 0x02, 0x33, 0x1e, 0xd7, 0x0c, 0x18, 0x41, 0x03, 0x1b, 0xee, 0x05, 0x26, 0x30, + 0x09, 0xd7, 0x14, 0xbd, 0xdf, 0x0e, 0xff, 0xe5, 0xfb, 0x28, 0xf8, 0x38, 0x17, + 0x08, 0xdd, 0xda, 0x15, 0xce, 0x08, 0xe6, 0xc4, 0xdc, 0x19, 0xe9, 0xd8, 0xc4, + 0x03, 0xe6, 0xcc, 0x4b, 0x0f, 0x1f, 0xc0, 0xfe, 0x15, 0xf1, 0x04, 0xec, 0x24, + 0xf7, 0xe8, 0x1f, 0x3c, 0xe9, 0x39, 0x23, 0x81, 0xac, 0xbf, 0x35, 0x2c, 0x14, + 0x00, 0xd5, 0x3b, 0xd0, 0x09, 0x03, 0xc3, 0xd6, 0x01, 0x01, 0xa9, 0xc0, 0x07, + 0x39, 0xa9, 0x2e, 0x0f, 0x44, 0xfb, 0x0a, 0x22, 0xe2, 0xc5, 0x21, 0x02, 0x21, + 0x08, 0x88, 0x10, 0xbc, 0xec, 0x9f, 0x27, 0x0e, 0xf8, 0xcd, 0xc6, 0x33, 0xf4, + 0x28, 0xc6, 0x07, 0x0f, 0x0c, 0x03, 0xc8, 0xde, 0xb4, 0xe9, 0x30, 0x1b, 0x37, + 0xe2, 0xcb, 0xef, 0x03, 0xc8, 0xdb, 0xcc, 0x0b, 0xf1, 0xc4, 0x34, 0x16, 0xb8, + 0x24, 0x40, 0x47, 0xe2, 0x10, 0x22, 0x0d, 0xaf, 0x01, 0x00, 0x18, 0x9a, 0x08, + 0xfd, 0x12, 0xd7, 0x0c, 0x37, 0x93, 0xdc, 0xcd, 0x20, 0xf0, 0x49, 0x14, 0x11, + 0xe3, 0x0c, 0xb8, 0xf0, 0x25, 0xd3, 0x30, 0x2d, 0x16, 0x47, 0x1f, 0x3e, 0xf6, + 0xc3, 0xfa, 0xb4, 0x41, 0x1d, 0xd1, 0x11, 0xff, 0xd5, 0xf3, 0xd6, 0x00, 0xef, + 0xcd, 0xb5, 0x13, 0xd4, 0xf8, 0xbb, 0xf0, 0x34, 0x6f, 0xb7, 0x1a, 0x05, 0xde, + 0xef, 0xf0, 0x2e, 0xd1, 0x10, 0xf0, 0xf2, 0xfb, 0x04, 0x04, 0xf3, 0xfe, 0x2a, + 0x23, 0x1d, 0xfa, 0x05, 0xc8, 0xcf, 0xb8, 0xcd, 0xb2, 0xf3, 0xe1, 0xd2, 0xc9, + 0x46, 0x26, 0x15, 0x0b, 0xea, 0x0d, 0x03, 0x0e, 0xa8, 0x00, 0xf7, 0x34, 0x1e, + 0x14, 0xe9, 0xed, 0x0f, 0x06, 0x12, 0xfb, 0xbe, 0x9f, 0x4d, 0xa7, 0x14, 0xd3, + 0x2f, 0xb5, 0xf7, 0x4b, 0x06, 0x2a, 0xdb, 0x23, 0x12, 0xaf, 0x05, 0xeb, 0x1c, + 0xad, 0xf4, 0xe9, 0xfd, 0x7f, 0xe1, 0xd3, 0xf7, 0x0f, 0x31, 0x28, 0xe0, 0xd3, + 0x2c, 0x16, 0xee, 0xcb, 0xfe, 0x12, 0xf0, 0xe8, 0xe9, 0xfa, 0x02, 0xc3, 0xcc, + 0xdd, 0xe8, 0xcc, 0xe2, 0xec, 0xf2, 0x00, 0x1f, 0xf9, 0xfc, 0xe7, 0xe3, 0xc6, + 0xb9, 0xdb, 0x58, 0x19, 0x2e, 0x04, 0x2e, 0x31, 0x39, 0x2c, 0xc8, 0xd4, 0xdd, + 0x1b, 0xf7, 0x22, 0xad, 0xd8, 0x13, 0x07, 0xc2, 0x27, 0xe6, 0x04, 0xee, 0xd2, + 0x0f, 0xd8, 0x16, 0x0a, 0x1b, 0x03, 0x09, 0xe9, 0xe0, 0x0d, 0xd2, 0x04, 0x09, + 0xc8, 0x29, 0x16, 0xe3, 0xe9, 0x23, 0xf5, 0x03, 0x40, 0xda, 0x58, 0x0e, 0x13, + 0x11, 0x01, 0x0d, 0x1d, 0x0a, 0x18, 0xa1, 0x3b, 0x7f, 0x7f, 0x1b, 0x3f, 0x06, + 0xd2, 0xee, 0xf8, 0x0f, 0x18, 0xf3, 0xca, 0xed, 0xe9, 0xef, 0x03, 0x2d, 0xe6, + 0xf6, 0x3e, 0x07, 0xf9, 0xe5, 0xf5, 0x2b, 0xee, 0xed, 0x1c, 0xfa, 0xfe, 0x14, + 0x1d, 0x12, 0x2d, 0xe8, 0xd1, 0xe7, 0x59, 0x9d, 0x0f, 0x02, 0xb8, 0xf9, 0x10, + 0x19, 0x10, 0xc5, 0x08, 0x5a, 0x19, 0xe2, 0x3c, 0xeb, 0x19, 0x0c, 0xc0, 0xe3, + 0x01, 0xed, 0xed, 0xc8, 0x08, 0xfc, 0xee, 0x29, 0xfc, 0x0c, 0x1a, 0xe3, 0x01, + 0xfe, 0xe1, 0x53, 0x0d, 0xd8, 0x01, 0xe6, 0x23, 0xfc, 0xfc, 0xbf, 0xfd, 0x14, + 0x4f, 0x08, 0xf8, 0x23, 0x05, 0xe1, 0xd3, 0xd6, 0xe1, 0x56, 0xb4, 0x01, 0xff, + 0xd6, 0xe6, 0xdd, 0x14, 0x0f, 0x2a, 0xf1, 0x00, 0xca, 0x21, 0xdf, 0x16, 0x0a, + 0x1f, 0xcf, 0x2a, 0x02, 0x56, 0xf8, 0x19, 0x1e, 0x10, 0xde, 0xf9, 0x0f, 0xdd, + 0xb2, 0x3c, 0x25, 0x1a, 0x30, 0xf8, 0x12, 0xf5, 0xbc, 0x5e, 0x0c, 0x1b, 0xfe, + 0x02, 0xec, 0x58, 0x29, 0x2e, 0xda, 0x07, 0xc8, 0x16, 0x1b, 0x1a, 0x2e, 0xd9, + 0xbb, 0x03, 0x24, 0xf5, 0x2c, 0x0f, 0xcf, 0x06, 0x7f, 0xf8, 0xc7, 0x14, 0xe2, + 0xd9, 0x05, 0xe5, 0x12, 0xf8, 0xd6, 0x01, 0xf0, 0xd4, 0x0e, 0x18, 0x1b, 0xd0, + 0x4c, 0xe3, 0xf5, 0xf9, 0xf6, 0xd5, 0xe4, 0xe9, 0x1a, 0xd1, 0x0b, 0x2d, 0xea, + 0x40, 0xf7, 0x29, 0xfb, 0xfa, 0x1f, 0xf8, 0xe0, 0xff, 0x05, 0x62, 0xf8, 0x08, + 0x7f, 0xaf, 0xdb, 0xe7, 0xe2, 0x39, 0xd6, 0xf7, 0xf7, 0xff, 0xce, 0xfc, 0x24, + 0x45, 0x0e, 0xfd, 0x58, 0xf7, 0xe0, 0x25, 0xdb, 0x1b, 0x19, 0xb7, 0x17, 0x1f, + 0x21, 0x11, 0xdd, 0x29, 0x26, 0x4a, 0x0a, 0x3a, 0x26, 0x07, 0x44, 0xcc, 0xe3, + 0x22, 0x3f, 0xb9, 0xe3, 0xf5, 0xcf, 0x30, 0xec, 0x27, 0xd7, 0x2f, 0x25, 0x04, + 0x13, 0x07, 0x1c, 0x05, 0x11, 0xef, 0xd2, 0x2c, 0xd5, 0x66, 0xf3, 0xea, 0xe1, + 0xff, 0xe3, 0xd3, 0x26, 0xc0, 0xd6, 0x2a, 0x40, 0x2d, 0xeb, 0x08, 0xed, 0x18, + 0x20, 0xf0, 0xe1, 0x13, 0x04, 0x12, 0x13, 0x27, 0x03, 0x0b, 0x04, 0x11, 0xf4, + 0xfe, 0x08, 0xdf, 0x2e, 0xd3, 0x17, 0xd1, 0xcd, 0xe9, 0xf0, 0x13, 0x08, 0x22, + 0x33, 0xda, 0xd9, 0xf9, 0xe9, 0x17, 0xfd, 0xe8, 0x05, 0x8f, 0xc6, 0xeb, 0xf9, + 0xc8, 0x31, 0xce, 0xa6, 0xde, 0xb9, 0xfb, 0xe1, 0x1d, 0xff, 0x0c, 0x78, 0xff, + 0xca, 0xf2, 0xb3, 0xfa, 0x0f, 0x23, 0xcb, 0x11, 0xbb, 0x3a, 0xe9, 0xda, 0xe6, + 0x12, 0xee, 0xeb, 0x01, 0xd7, 0xf8, 0xbb, 0xe7, 0xea, 0x23, 0x30, 0xff, 0xdb, + 0x0d, 0xc2, 0x33, 0x24, 0xcf, 0x56, 0xe1, 0xb0, 0xed, 0xe4, 0xfc, 0xdf, 0x2b, + 0x8e, 0x03, 0x1e, 0xeb, 0x05, 0xc0, 0xea, 0xbc, 0x2b, 0xce, 0x34, 0xd6, 0xdd, + 0xeb, 0x08, 0xeb, 0xd8, 0xc3, 0x5a, 0xc9, 0x05, 0x26, 0xc5, 0xd4, 0x0f, 0x65, + 0x26, 0x36, 0xde, 0xdf, 0xf1, 0x37, 0x27, 0x3e, 0xf3, 0xac, 0xbf, 0xfa, 0xd6, + 0x27, 0x0a, 0xda, 0x2d, 0xbf, 0x24, 0xc4, 0xe9, 0x63, 0xd8, 0xc0, 0x10, 0xe6, + 0x4f, 0xfc, 0x91, 0xb9, 0x1b, 0xec, 0xeb, 0x96, 0xf3, 0xd7, 0x5b, 0xe8, 0x74, + 0x1b, 0xdc, 0x07, 0x1d, 0x20, 0xf8, 0xef, 0xf9, 0xe2, 0x2d, 0x07, 0x3f, 0x28, + 0xf5, 0x7f, 0xdf, 0xc7, 0x1a, 0x18, 0x16, 0xcc, 0xd4, 0xf1, 0xf4, 0x19, 0xfc, + 0x22, 0xcf, 0xe4, 0xd8, 0x20, 0xf8, 0xaa, 0x3c, 0xde, 0x73, 0x0c, 0x25, 0x04, + 0x30, 0x19, 0xb3, 0x09, 0x4c, 0x46, 0x15, 0xfc, 0xd6, 0xe6, 0xcb, 0xef, 0xd6, + 0xfd, 0x26, 0x7f, 0x40, 0xcd, 0xd9, 0xfe, 0xfd, 0x1e, 0x19, 0xb9, 0xe2, 0x4d, + 0xfe, 0xf4, 0x05, 0xcb, 0x1f, 0xd2, 0x0d, 0xcc, 0xf6, 0xaf, 0x13, 0xf8, 0x0b, + 0x68, 0xcc, 0xd2, 0x6f, 0xac, 0x04, 0x36, 0x52, 0xf7, 0xef, 0xce, 0x00, 0x3c, + 0xb9, 0xd4, 0x0f, 0xf1, 0xe3, 0xf3, 0x33, 0x34, 0xef, 0x0c, 0xce, 0x59, 0x26, + 0x1f, 0xd9, 0xe3, 0x21, 0x16, 0x15, 0xf4, 0x08, 0x24, 0x20, 0x0a, 0x29, 0x02, + 0xe5, 0xcb, 0xf9, 0xe1, 0x32, 0x01, 0xf7, 0x05, 0x16, 0xe7, 0x28, 0xfd, 0x2f, + 0xce, 0xcf, 0x15, 0xdd, 0x55, 0xdd, 0xf3, 0x4b, 0x2e, 0xf9, 0xd4, 0x1d, 0x2f, + 0x43, 0x19, 0x99, 0xde, 0x81, 0xd3, 0xcd, 0xfa, 0x26, 0xcd, 0xcf, 0xcd, 0x10, + 0xe4, 0x0d, 0x44, 0xe9, 0x14, 0x6f, 0xcb, 0x46, 0xec, 0xf8, 0x11, 0xb7, 0xc6, + 0xf1, 0xee, 0xb8, 0x06, 0x83, 0xe2, 0xf1, 0xad, 0xec, 0x2e, 0x4a, 0xbe, 0x0b, + 0xf7, 0xf9, 0x03, 0x16, 0x0a, 0x16, 0xc7, 0x21, 0xe3, 0xc0, 0xd4, 0xf7, 0x49, + 0x17, 0xb5, 0x76, 0x03, 0x26, 0xc7, 0xe0, 0x2a, 0x1e, 0xd2, 0x28, 0x0f, 0xb2, + 0xf9, 0xf6, 0xbe, 0x60, 0x06, 0x15, 0xcf, 0xbc, 0x2c, 0xef, 0x08, 0xd7, 0x0d, + 0x02, 0xe6, 0x39, 0xb1, 0xc7, 0x0b, 0x0a, 0x40, 0x51, 0xe7, 0xe6, 0xcf, 0x11, + 0xa0, 0xce, 0xf7, 0x0f, 0xac, 0x14, 0xdd, 0x22, 0xe5, 0x01, 0xd0, 0xd6, 0x33, + 0xff, 0xa2, 0x1c, 0x02, 0xee, 0x24, 0x17, 0x46, 0xf3, 0x03, 0xf4, 0x17, 0xf8, + 0x01, 0xee, 0x47, 0x78, 0xf3, 0x24, 0x95, 0x16, 0xf0, 0x18, 0xc1, 0x21, 0xe9, + 0x45, 0x02, 0xf4, 0x21, 0x03, 0x2a, 0xe1, 0x27, 0x43, 0xdb, 0x2f, 0xf4, 0x1c, + 0xf1, 0xd3, 0x2a, 0xde, 0x45, 0xbd, 0x25, 0x65, 0xea, 0x09, 0x03, 0x0a, 0x43, + 0xec, 0x27, 0x2b, 0xe1, 0x9b, 0x0e, 0xf9, 0xe4, 0xda, 0x05, 0xc1, 0xe8, 0xe4, + 0x00, 0x05, 0x0e, 0xec, 0x02, 0xf3, 0xd8, 0x40, 0x33, 0x13, 0xc7, 0x04, 0xf7, + 0x3f, 0xf5, 0xe8, 0x16, 0x1e, 0xd1, 0xec, 0x0a, 0x15, 0x11, 0xd1, 0x09, 0x0e, + 0xd7, 0xf4, 0x0b, 0xd2, 0x28, 0xdf, 0xc2, 0x29, 0xe7, 0x43, 0x31, 0xeb, 0x52, + 0x0c, 0x20, 0xf2, 0xe2, 0xea, 0x00, 0xd3, 0x02, 0x61, 0x61, 0x0c, 0xed, 0xe7, + 0x1d, 0x06, 0xa3, 0xf7, 0xf0, 0xd8, 0xd3, 0x41, 0xe0, 0xe9, 0xc0, 0xf7, 0x07, + 0x35, 0x25, 0xf5, 0xb9, 0x05, 0xd5, 0xf2, 0x12, 0x16, 0x37, 0xdc, 0x00, 0x1d, + 0xba, 0xc4, 0x13, 0xe2, 0x37, 0x10, 0x09, 0x27, 0x7f, 0x01, 0xb9, 0x0b, 0xf7, + 0xf1, 0x1f, 0xe6, 0x13, 0xbc, 0xf2, 0xd4, 0x25, 0x31, 0x30, 0xff, 0xf3, 0xcb, + 0xc9, 0xd4, 0xe9, 0xe0, 0x00, 0xcb, 0x2d, 0xcd, 0xdb, 0xfc, 0xfd, 0x05, 0xdb, + 0xe0, 0xe6, 0x7f, 0xf5, 0x27, 0x19, 0xbf, 0xce, 0xed, 0xe5, 0x19, 0x11, 0xd4, + 0xc0, 0x11, 0x1b, 0x0f, 0x00, 0xcd, 0xe8, 0x08, 0x15, 0x05, 0xd0, 0x1c, 0xe1, + 0xf6, 0x28, 0x13, 0x1d, 0xf7, 0xef, 0xe9, 0xcc, 0x13, 0x54, 0x6e, 0x18, 0xe0, + 0xfe, 0x08, 0xc1, 0xc9, 0xfd, 0xee, 0xef, 0x03, 0x30, 0x3b, 0xd9, 0x01, 0xe9, + 0x11, 0xca, 0xc1, 0xe7, 0xfd, 0x49, 0x16, 0x0d, 0xb3, 0x0d, 0xfe, 0x3c, 0xfd, + 0xec, 0x15, 0xd5, 0x1c, 0x38, 0x0e, 0x37, 0xd9, 0x00, 0x33, 0xda, 0xfd, 0x19, + 0xfc, 0x21, 0xef, 0xe4, 0x3d, 0xfb, 0xd3, 0xf4, 0xfe, 0x1f, 0x17, 0x0b, 0x0e, + 0xd6, 0xae, 0xd1, 0xf7, 0x33, 0x0a, 0xf3, 0x1d, 0x07, 0xd8, 0xef, 0x27, 0xf7, + 0xe3, 0xec, 0xeb, 0x10, 0x37, 0x32, 0xe2, 0x06, 0xe9, 0xdb, 0x02, 0xd7, 0xd6, + 0xf3, 0xf2, 0x0f, 0x18, 0xf6, 0x26, 0xda, 0x20, 0x22, 0x1e, 0x01, 0xff, 0xef, + 0x25, 0x23, 0x25, 0x7f, 0x4f, 0x18, 0xd5, 0x1c, 0x01, 0x0b, 0xe7, 0xef, 0xe4, + 0xe5, 0x0c, 0xf0, 0xf8, 0xe3, 0x28, 0xbb, 0x35, 0xea, 0xec, 0x35, 0xf3, 0xc8, + 0xf2, 0xc4, 0xe7, 0x10, 0x00, 0x10, 0x01, 0x19, 0xf2, 0x0e, 0xff, 0x07, 0x0c, + 0xce, 0x40, 0x22, 0x3d, 0x0d, 0x07, 0xee, 0xcb, 0x30, 0xf8, 0x0b, 0xd6, 0xdb, + 0x01, 0xed, 0xed, 0xd0, 0xea, 0x32, 0x05, 0xe1, 0xf2, 0x1a, 0x1d, 0xec, 0x33, + 0xd0, 0x2a, 0x08, 0x20, 0xe3, 0x30, 0x03, 0xb1, 0x0c, 0x04, 0x30, 0xe7, 0xde, + 0xf8, 0xe5, 0x1b, 0x14, 0x05, 0xe0, 0x08, 0x1a, 0xee, 0xe1, 0x10, 0x12, 0x22, + 0x19, 0x1f, 0xfa, 0xc3, 0x14, 0x1b, 0x41, 0xd5, 0x46, 0x1b, 0xea, 0xde, 0x31, + 0x18, 0xfc, 0x39, 0xf6, 0xfd, 0x02, 0x1f, 0x5e, 0xed, 0x47, 0x0d, 0x81, 0xe8, + 0xc6, 0x35, 0x04, 0x2e, 0x10, 0x0d, 0xb4, 0x17, 0xf3, 0x19, 0x0e, 0x0c, 0x0e, + 0x14, 0x01, 0x60, 0x45, 0xda, 0x09, 0xd2, 0x10, 0xe8, 0xf7, 0x12, 0x53, 0xf1, + 0xff, 0x4f, 0x01, 0xe7, 0xd2, 0x00, 0xc2, 0xb3, 0xed, 0x2b, 0xf1, 0x28, 0xc1, + 0xfe, 0x3a, 0xf9, 0x1b, 0x16, 0xeb, 0x19, 0xf9, 0xff, 0x08, 0x43, 0x25, 0xf3, + 0x1a, 0x34, 0xb5, 0x33, 0xf8, 0xea, 0x87, 0x18, 0x18, 0xec, 0xe8, 0x13, 0xd1, + 0x24, 0xea, 0x00, 0xed, 0x13, 0xf2, 0xd0, 0x02, 0x01, 0x18, 0x17, 0xf9, 0x0e, + 0x23, 0x23, 0xf2, 0x13, 0x21, 0x1e, 0x01, 0xe8, 0x22, 0xd6, 0xc9, 0xee, 0xd9, + 0x1f, 0xfd, 0x08, 0xc4, 0x56, 0x2f, 0x2d, 0x8b, 0x15, 0x1b, 0xef, 0xf8, 0x0d, + 0xe2, 0x22, 0xeb, 0x15, 0x07, 0x55, 0xf4, 0x24, 0xf6, 0xd8, 0x06, 0xd7, 0x56, + 0x2b, 0x3a, 0xe1, 0x0a, 0x10, 0xa1, 0xfd, 0x7f, 0x22, 0xc6, 0xf9, 0x0c, 0xd3, + 0xdd, 0xd6, 0x15, 0x23, 0xfe, 0x6d, 0xdf, 0xe1, 0x21, 0xe1, 0xef, 0xed, 0xf6, + 0xcc, 0x1b, 0xdb, 0xf8, 0xfa, 0xeb, 0xf6, 0xef, 0xe5, 0xf4, 0x04, 0x24, 0x30, + 0x01, 0x2d, 0xf9, 0xfc, 0xfc, 0xf8, 0x06, 0x13, 0x31, 0x2f, 0xc8, 0xc5, 0xe8, + 0x61, 0xf2, 0x03, 0x00, 0xf4, 0xcd, 0xfb, 0xf5, 0x01, 0xf1, 0x0f, 0x26, 0x06, + 0xf5, 0xe8, 0xea, 0xc6, 0x00, 0x0a, 0xf5, 0xff, 0x2e, 0x08, 0xfa, 0xdb, 0xb7, + 0x24, 0x12, 0x1d, 0xf5, 0x1c, 0xd1, 0x3c, 0x0b, 0xef, 0x10, 0xea, 0x06, 0x16, + 0xe0, 0xa8, 0xd5, 0xdb, 0x19, 0xfe, 0x18, 0xe8, 0x08, 0x1c, 0x2b, 0x25, 0x27, + 0x0b, 0x38, 0x22, 0xf8, 0x17, 0xb1, 0x5f, 0xea, 0xe0, 0xa0, 0x53, 0x60, 0xe8, + 0x17, 0x12, 0x2d, 0x10, 0x49, 0x2b, 0xc0, 0xf4, 0xf0, 0xdc, 0x08, 0xb8, 0x0c, + 0x10, 0x16, 0x2a, 0xf7, 0xe7, 0xe4, 0x06, 0xfe, 0xc5, 0x31, 0x03, 0xef, 0xf6, + 0x4a, 0x1a, 0x27, 0x4b, 0x54, 0xd8, 0xcc, 0x00, 0xfa, 0xe0, 0xf0, 0x30, 0x0f, + 0x40, 0xdf, 0x00, 0x33, 0xf4, 0xd0, 0x13, 0x15, 0xfb, 0x29, 0xc6, 0x48, 0x0d, + 0x13, 0x06, 0x43, 0xcc, 0xe7, 0x7f, 0xe9, 0xed, 0x0b, 0x1c, 0x25, 0xfe, 0xf9, + 0xf9, 0xbd, 0xc4, 0xea, 0x2c, 0xdf, 0x0d, 0xc7, 0x20, 0x20, 0xe1, 0xde, 0x68, + 0xf2, 0x22, 0xcf, 0xef, 0x13, 0xff, 0xe8, 0x27, 0x0a, 0x48, 0xd4, 0x08, 0x68, + 0x1f, 0x14, 0xff, 0x0b, 0x1b, 0x49, 0xc7, 0xea, 0x04, 0xce, 0x0d, 0xd2, 0x99, + 0xe1, 0xd4, 0xff, 0xf6, 0x0c, 0x25, 0x30, 0x03, 0x43, 0x15, 0x35, 0xfa, 0xe9, + 0x21, 0x05, 0x1f, 0x27, 0x33, 0x1b, 0xd1, 0xdc, 0xf2, 0x29, 0xd0, 0xee, 0xfa, + 0xc1, 0x06, 0x13, 0xf0, 0x4b, 0x05, 0x17, 0xcf, 0xf8, 0x08, 0x0d, 0xf9, 0x36, + 0x11, 0xdf, 0xfe, 0xc7, 0xb0, 0xda, 0xea, 0x33, 0x5f, 0x3c, 0x20, 0xff, 0xff, + 0x17, 0x08, 0xd8, 0xf5, 0x22, 0xfa, 0xd6, 0xe6, 0x43, 0x17, 0xe2, 0x91, 0xfe, + 0xf6, 0x7a, 0xe3, 0xf2, 0xf1, 0x04, 0xff, 0xda, 0xf8, 0xee, 0x0d, 0xc8, 0xea, + 0xc5, 0xeb, 0x17, 0x06, 0x11, 0xd2, 0xfd, 0x7f, 0x1b, 0x0c, 0x37, 0xe1, 0x0d, + 0x3d, 0x3c, 0x3c, 0x35, 0x15, 0xe0, 0x32, 0x03, 0x1d, 0xe3, 0x0e, 0x13, 0xdd, + 0xd9, 0x14, 0x12, 0x08, 0xc5, 0x25, 0x1b, 0xd3, 0xfd, 0xe9, 0x05, 0x22, 0x18, + 0x29, 0x0c, 0xbc, 0xe0, 0x01, 0xdb, 0xdb, 0xe8, 0x39, 0x1b, 0x2d, 0x1c, 0xdf, + 0xf0, 0xfe, 0x2c, 0xec, 0xf5, 0x3f, 0x0f, 0xed, 0xf2, 0x2f, 0xf3, 0xf7, 0x23, + 0xff, 0x4e, 0xd2, 0xe6, 0x6b, 0x0b, 0x05, 0x11, 0xf4, 0xfb, 0x15, 0xe9, 0xed, + 0x16, 0x25, 0xa5, 0xfe, 0x47, 0x2a, 0xd7, 0xf6, 0x4c, 0x0b, 0xd7, 0xc7, 0xd6, + 0xe6, 0xcb, 0xcd, 0xfb, 0xec, 0xe7, 0x00, 0xd4, 0xda, 0x52, 0xe0, 0x21, 0xbf, + 0xcf, 0x3b, 0xe3, 0x1e, 0xbb, 0xab, 0x44, 0x56, 0x7e, 0xac, 0x26, 0x25, 0xfc, + 0xdb, 0xec, 0x01, 0xe9, 0xea, 0xf9, 0x49, 0x36, 0x03, 0x32, 0x04, 0x18, 0xfe, + 0xc3, 0xb2, 0xba, 0x7f, 0xec, 0xe6, 0xbf, 0x34, 0x01, 0x25, 0x0e, 0xde, 0xe6, + 0x0e, 0x8d, 0xcc, 0x28, 0x0c, 0x1a, 0x24, 0x1f, 0xd2, 0x1f, 0x01, 0x0b, 0x28, + 0xd7, 0xc9, 0x38, 0xf3, 0xc4, 0x5f, 0xf3, 0xcb, 0xea, 0xf3, 0xcf, 0xd0, 0xdc, + 0xe6, 0xd5, 0x1f, 0xc1, 0x1d, 0xfe, 0xfd, 0x88, 0x1e, 0xf1, 0x11, 0x05, 0x1b, + 0xec, 0xb0, 0xa4, 0xf1, 0x1c, 0xb8, 0x7b, 0x29, 0x10, 0x5d, 0x16, 0xf5, 0xb4, + 0xb7, 0x0a, 0x2b, 0x1d, 0x3c, 0xc0, 0xfd, 0xde, 0xe7, 0x32, 0xc6, 0x1a, 0xd4, + 0xc6, 0x17, 0x02, 0x06, 0xc4, 0xe0, 0x35, 0xaf, 0xd9, 0x02, 0xbf, 0x22, 0x59, + 0xc8, 0x14, 0xed, 0xb6, 0xd3, 0x5b, 0xf3, 0xb3, 0xd4, 0x19, 0xfd, 0x7f, 0xde, + 0x2d, 0xd5, 0xfe, 0xe5, 0x1e, 0xf5, 0xd5, 0xf0, 0x36, 0x07, 0xe1, 0x25, 0xc9, + 0x11, 0x29, 0x8b, 0xed, 0xbd, 0x19, 0x14, 0x74, 0xb3, 0xd9, 0xf0, 0x2d, 0x11, + 0x1e, 0xd4, 0x30, 0xb6, 0xe0, 0xff, 0xc4, 0x5d, 0xf5, 0x30, 0xc0, 0x96, 0x0c, + 0x03, 0x06, 0x11, 0xe5, 0xf3, 0xa1, 0x03, 0xe6, 0xe3, 0x31, 0xb7, 0x1b, 0x3c, + 0xec, 0xff, 0xef, 0x21, 0x10, 0x21, 0xdf, 0x18, 0xf2, 0x2e, 0xdf, 0xbc, 0x23, + 0x73, 0x0f, 0x05, 0xd4, 0x26, 0x0d, 0xf3, 0x02, 0xc9, 0x0d, 0x33, 0x3e, 0xd3, + 0xda, 0x21, 0xd8, 0xe9, 0x24, 0x18, 0x03, 0xd1, 0xf1, 0xdd, 0xec, 0xf0, 0x15, + 0x29, 0x12, 0x18, 0x00, 0xf4, 0x1c, 0xc1, 0x14, 0x47, 0xf6, 0xba, 0x5e, 0x0d, + 0x46, 0x17, 0x1e, 0x15, 0x05, 0x04, 0xd5, 0x1e, 0x6b, 0xea, 0x2e, 0x21, 0xab, + 0xf7, 0xc5, 0x4c, 0xdb, 0x31, 0x0a, 0x15, 0x07, 0x4d, 0x1a, 0xcf, 0xf3, 0x24, + 0xbf, 0x0e, 0x0d, 0xdf, 0xdb, 0x14, 0x01, 0x01, 0x38, 0x2d, 0x34, 0x2f, 0x1c, + 0x09, 0xde, 0x2c, 0x0c, 0xc0, 0xf0, 0x23, 0x02, 0xb5, 0x04, 0x3c, 0xd7, 0x1c, + 0xfb, 0x20, 0xc5, 0x04, 0xdf, 0x48, 0x15, 0x3d, 0x12, 0xeb, 0xe6, 0x12, 0xd1, + 0xde, 0x39, 0x33, 0x33, 0x05, 0xfb, 0xdb, 0xf3, 0x24, 0xd4, 0x1b, 0xd1, 0x30, + 0xe8, 0xff, 0x0e, 0xea, 0xfc, 0xf9, 0xcc, 0x4b, 0xd8, 0x36, 0xcd, 0x3e, 0xdd, + 0xf9, 0x03, 0xe2, 0xf9, 0x0a, 0xd2, 0xae, 0xf0, 0x1c, 0xe9, 0xf0, 0x28, 0x15, + 0x28, 0xac, 0x63, 0x33, 0x7f, 0xc7, 0xe9, 0xc8, 0x15, 0x34, 0xcd, 0xf4, 0xbe, + 0x08, 0x23, 0x39, 0xfc, 0x22, 0xf2, 0x02, 0xf9, 0x15, 0xb2, 0x21, 0xc6, 0x24, + 0x02, 0x93, 0xf1, 0xc3, 0x1d, 0x18, 0x1e, 0xde, 0xae, 0x01, 0xee, 0xb6, 0x67, + 0xe1, 0x26, 0xc2, 0x05, 0x01, 0x06, 0x28, 0x33, 0xfe, 0xe2, 0xe5, 0xd0, 0xbc, + 0x1b, 0xcf, 0x1b, 0xdb, 0x3f, 0xe4, 0x16, 0x15, 0x2d, 0x52, 0x5e, 0xfb, 0x22, + 0xd2, 0x46, 0xec, 0x15, 0xe9, 0x2c, 0xcd, 0x24, 0x22, 0xed, 0xea, 0xfa, 0xf5, + 0xc3, 0xf5, 0xb3, 0x81, 0x04, 0xf3, 0x90, 0xcc, 0x4f, 0xcd, 0x43, 0xe5, 0xfd, + 0x22, 0x9b, 0x15, 0x01, 0xc4, 0x2a, 0x3b, 0xe5, 0x04, 0x09, 0xe5, 0xaa, 0xf8, + 0xc2, 0xcc, 0x13, 0x11, 0x8b, 0x39, 0xaf, 0x0d, 0xfc, 0xee, 0xff, 0xfd, 0x1c, + 0xfe, 0xd6, 0x5f, 0xec, 0xcf, 0xc2, 0xc1, 0x0f, 0x68, 0x22, 0xf2, 0x3c, 0xd3, + 0xba, 0x12, 0x06, 0xfe, 0x11, 0x7d, 0xd1, 0xca, 0xdd, 0xcc, 0x15, 0x10, 0xed, + 0x05, 0xb8, 0xad, 0xbf, 0x16, 0x58, 0x2b, 0xed, 0x21, 0x1b, 0xf4, 0x27, 0xe7, + 0x00, 0xe0, 0x5f, 0x12, 0xc0, 0xc1, 0x0f, 0x45, 0xfa, 0xd1, 0x44, 0xed, 0x16, + 0x22, 0x02, 0xdc, 0xca, 0x4a, 0xca, 0xfb, 0xe7, 0xd9, 0xea, 0x2b, 0x12, 0xbb, + 0xcf, 0x21, 0xca, 0x1c, 0x1d, 0x39, 0xeb, 0xc8, 0xab, 0x21, 0xd5, 0xd0, 0x03, + 0xca, 0xf6, 0xcb, 0xe4, 0xf0, 0x3e, 0xd9, 0x2d, 0x03, 0x16, 0xfb, 0xfe, 0x08, + 0xeb, 0x36, 0x12, 0x16, 0x23, 0x17, 0x1d, 0x34, 0xe4, 0xfa, 0x19, 0x1a, 0xb1, + 0xfb, 0xea, 0x2b, 0x9a, 0xfe, 0xfb, 0x3d, 0x40, 0xd1, 0x5d, 0x5b, 0xe4, 0x2d, + 0xac, 0xd0, 0xc7, 0xfd, 0xca, 0x11, 0x7e, 0x2c, 0x01, 0xf9, 0xd2, 0x2b, 0xe4, + 0x7f, 0x20, 0xdd, 0xfc, 0xe6, 0x0c, 0x8c, 0x17, 0xff, 0xf5, 0x50, 0x23, 0x10, + 0xc7, 0x0f, 0x09, 0x20, 0xb1, 0xfe, 0xfa, 0xf9, 0x3e, 0x0a, 0xf6, 0xfa, 0x36, + 0xe2, 0xca, 0xf5, 0x26, 0x97, 0x3f, 0x0a, 0xcb, 0x17, 0xf6, 0x05, 0xdd, 0x41, + 0x00, 0xdc, 0xcc, 0x28, 0xed, 0xe7, 0xcd, 0xf4, 0xe9, 0xba, 0x81, 0xcb, 0xc1, + 0xc1, 0xfc, 0xde, 0x18, 0x11, 0xfc, 0xe8, 0x02, 0xf4, 0x05, 0x22, 0xd0, 0x06, + 0x0f, 0xed, 0x2c, 0x33, 0xfc, 0xf4, 0xf7, 0xd3, 0xf5, 0xb1, 0xcf, 0x01, 0xe3, + 0xf8, 0x05, 0xc9, 0xe7, 0xfb, 0x47, 0xad, 0xfc, 0x08, 0x0e, 0xb2, 0x20, 0xcb, + 0x16, 0xf9, 0x1e, 0x22, 0xec, 0xe4, 0x46, 0xf9, 0xf2, 0x5a, 0x01, 0xc7, 0xeb, + 0xfa, 0x25, 0xf2, 0xf5, 0x06, 0x26, 0xdc, 0x09, 0x05, 0xe1, 0xbd, 0xdc, 0x15, + 0x08, 0xa9, 0x10, 0x1d, 0xf9, 0x02, 0x28, 0xe1, 0xf9, 0x19, 0x0e, 0xf0, 0xed, + 0xe1, 0xef, 0x20, 0x44, 0x43, 0xd1, 0xf1, 0xfd, 0xc0, 0x1e, 0xda, 0x95, 0xd4, + 0xe8, 0x49, 0xed, 0xb3, 0xee, 0x2f, 0xc8, 0x03, 0xe9, 0x0c, 0x14, 0xde, 0xd9, + 0x2a, 0x75, 0xe6, 0xfd, 0x0d, 0x2e, 0x47, 0xd1, 0x33, 0x16, 0x12, 0xd0, 0x3a, + 0x7e, 0x12, 0xc5, 0xc4, 0xf8, 0xa0, 0xc1, 0x3e, 0x1e, 0xe6, 0x99, 0x3d, 0x06, + 0x00, 0xf5, 0xe8, 0xea, 0x73, 0xe3, 0x18, 0x07, 0x63, 0x26, 0xf2, 0xcf, 0xcc, + 0x0a, 0x1d, 0xcc, 0x35, 0x54, 0xd6, 0x3d, 0xcc, 0x44, 0xd2, 0xf2, 0x38, 0x09, + 0x07, 0xc2, 0x7f, 0xd3, 0xfb, 0x31, 0xfa, 0xdb, 0x07, 0xf8, 0x43, 0xab, 0x63, + 0x0f, 0xd5, 0x01, 0xff, 0xfb, 0xdb, 0x08, 0xfa, 0x1b, 0x38, 0xf9, 0x0f, 0x0c, + 0x40, 0xe6, 0xa5, 0xe0, 0xc5, 0x4f, 0x20, 0xe8, 0x3c, 0x2d, 0x21, 0xe6, 0xd9, + 0xef, 0x0a, 0xd1, 0xfd, 0xc7, 0xb6, 0x08, 0xb9, 0x95, 0x39, 0x60, 0x14, 0x0f, + 0xee, 0xdd, 0x12, 0x47, 0xe7, 0xaf, 0xdb, 0x10, 0xf9, 0x5d, 0x2b, 0x16, 0x0f, + 0xf8, 0x29, 0xda, 0x12, 0x00, 0x0f, 0xdf, 0xe0, 0x00, 0x0e, 0xdb, 0x0a, 0xc1, + 0x7f, 0x07, 0xf7, 0x47, 0xa1, 0xf5, 0xcc, 0xd9, 0xf8, 0x2b, 0xed, 0xf8, 0x1b, + 0xa4, 0xd2, 0xd2, 0x6b, 0x38, 0x26, 0x49, 0xee, 0x2e, 0x21, 0x0f, 0xee, 0xfe, + 0xe9, 0x40, 0xd5, 0xee, 0xe8, 0xd6, 0x3a, 0xbc, 0xd4, 0x1c, 0xf9, 0x10, 0xfa, + 0xde, 0xd3, 0x11, 0x2a, 0x00, 0x2c, 0x00, 0x25, 0xe1, 0x2d, 0xff, 0x1a, 0xfa, + 0x23, 0xf0, 0x26, 0xd7, 0xfd, 0xe7, 0x21, 0x3e, 0x02, 0xfa, 0x05, 0x08, 0x63, + 0x15, 0xc4, 0xcd, 0x1c, 0x34, 0xd3, 0x1d, 0xee, 0xea, 0x05, 0xa7, 0xed, 0xf8, + 0xed, 0xe9, 0xd7, 0xd7, 0x00, 0x0f, 0xcd, 0xdd, 0xfc, 0xd1, 0x09, 0xcf, 0xfe, + 0x3c, 0x00, 0xf5, 0xee, 0xf3, 0x04, 0x00, 0x44, 0xcf, 0x24, 0xe8, 0xf0, 0xcc, + 0xe1, 0x08, 0x14, 0x33, 0x18, 0xf0, 0x0b, 0x48, 0x64, 0xed, 0x0c, 0x2e, 0xe1, + 0xce, 0x27, 0xef, 0xee, 0x41, 0xf7, 0xba, 0xce, 0xce, 0xfa, 0x1d, 0xda, 0x90, + 0x11, 0xb5, 0xfb, 0xf7, 0xbd, 0xfa, 0xfb, 0x1b, 0x2d, 0xc1, 0xfa, 0x4c, 0x7f, + 0x0e, 0x9f, 0xc0, 0xce, 0x0f, 0xe9, 0xcb, 0xd1, 0x2f, 0x28, 0x03, 0xc9, 0xd5, + 0x39, 0x00, 0xec, 0xfa, 0x17, 0xef, 0xcf, 0xd9, 0xee, 0x1c, 0x65, 0xf8, 0x38, + 0x02, 0xfa, 0x2f, 0x1c, 0x23, 0xed, 0x3a, 0xde, 0x0b, 0x36, 0xf3, 0x50, 0x04, + 0x05, 0x13, 0xe5, 0x13, 0xec, 0xcd, 0xc8, 0xef, 0x09, 0xa9, 0xfd, 0x00, 0x0c, + 0x26, 0xe9, 0x04, 0x98, 0x05, 0xdf, 0x25, 0x38, 0x2f, 0xfb, 0x28, 0x90, 0x11, + 0x23, 0xbf, 0xc7, 0x0d, 0xe2, 0xce, 0x09, 0x21, 0x29, 0xe8, 0xeb, 0xc1, 0x15, + 0x40, 0xd3, 0x08, 0x12, 0xe2, 0x26, 0x36, 0x15, 0xab, 0x0b, 0x70, 0x05, 0x3d, + 0xf9, 0xcb, 0x52, 0xf5, 0xfb, 0xab, 0xdf, 0x0b, 0x2b, 0xd5, 0x1a, 0xde, 0x31, + 0xaa, 0x5e, 0x33, 0x01, 0x29, 0x0c, 0xad, 0x00, 0x07, 0x3c, 0x14, 0xd2, 0x22, + 0x07, 0xd6, 0x01, 0xed, 0xef, 0x26, 0x13, 0xf8, 0xe2, 0x28, 0xd8, 0xe8, 0x0f, + 0xf9, 0x34, 0xc2, 0xbc, 0xf3, 0xb5, 0x29, 0xe1, 0xd6, 0x39, 0x24, 0x3c, 0xff, + 0x09, 0x29, 0xc7, 0x25, 0x10, 0x08, 0xfe, 0x12, 0x02, 0xf0, 0x3e, 0xd5, 0x29, + 0x10, 0xb4, 0xe3, 0xda, 0xe8, 0x4a, 0xeb, 0x21, 0x1a, 0xe9, 0xfa, 0x3b, 0xe0, + 0xd1, 0xf2, 0xd5, 0x00, 0xc0, 0x22, 0x0d, 0xe2, 0x16, 0xe3, 0xe0, 0xa9, 0x03, + 0x7f, 0x02, 0x1d, 0x1d, 0xc7, 0x1b, 0x0c, 0x2d, 0xda, 0xf3, 0xde, 0xf8, 0x50, + 0x0e, 0xea, 0x0a, 0xb1, 0x15, 0x25, 0xdf, 0xff, 0x14, 0x03, 0xfc, 0xa3, 0xf7, + 0xd5, 0x3e, 0xa1, 0xc6, 0xe8, 0x56, 0xf0, 0xde, 0xd7, 0xe5, 0xe9, 0x1b, 0x27, + 0x17, 0x40, 0xf9, 0xd6, 0xde, 0x47, 0x4a, 0xd2, 0x1b, 0x15, 0xe9, 0xd4, 0x15, + 0x1b, 0xfa, 0x0a, 0xea, 0xe9, 0xfb, 0xd5, 0xd5, 0xcf, 0xf5, 0x36, 0xfb, 0x3a, + 0xf6, 0xf8, 0xf1, 0xec, 0x05, 0xe9, 0xf2, 0xfa, 0x14, 0xba, 0xec, 0xeb, 0x7f, + 0x4a, 0xfe, 0x16, 0x46, 0xd4, 0x09, 0xfe, 0xda, 0x08, 0xf7, 0xf1, 0x19, 0x38, + 0xf7, 0x33, 0xdf, 0xd7, 0x1b, 0x15, 0x28, 0xe7, 0x1b, 0xed, 0xeb, 0xed, 0x20, + 0x1a, 0xc0, 0x4c, 0xf7, 0x45, 0x59, 0xdc, 0x02, 0xcb, 0x07, 0x42, 0xd7, 0xd1, + 0xf8, 0xfc, 0x27, 0xea, 0x0d, 0xd9, 0xd3, 0xf1, 0xcc, 0x36, 0x10, 0x49, 0x29, + 0x14, 0x06, 0x14, 0xae, 0x16, 0x35, 0xc5, 0xf9, 0x02, 0x16, 0xde, 0xd7, 0x10, + 0x41, 0xbc, 0x2a, 0xfa, 0x1b, 0xc7, 0x13, 0xc9, 0x15, 0x2e, 0xe3, 0x0f, 0x2b, + 0xc3, 0xc0, 0x2a, 0xf3, 0x0e, 0x00, 0xd7, 0x24, 0x0d, 0x2f, 0xc8, 0xc8, 0xd4, + 0x14, 0x66, 0xc5, 0xd0, 0xd9, 0xe4, 0x3e, 0x8f, 0xb5, 0xe2, 0x27, 0x04, 0x3d, + 0xe4, 0xe4, 0x58, 0x28, 0xfa, 0xe8, 0xc6, 0x20, 0xf0, 0xf3, 0xfd, 0x12, 0x1a, + 0x09, 0xd0, 0xe1, 0xcb, 0xf2, 0xce, 0xd7, 0xa6, 0x18, 0x6c, 0x2e, 0x35, 0x4c, + 0x24, 0x48, 0xe3, 0x2b, 0xfe, 0xde, 0x18, 0xf6, 0xf0, 0x14, 0x27, 0xb9, 0xe2, + 0xc8, 0x08, 0xd9, 0x03, 0xf9, 0xcd, 0x30, 0x56, 0x1c, 0x24, 0x0a, 0xd9, 0xca, + 0xe2, 0xff, 0x04, 0xcb, 0x04, 0x19, 0x05, 0x35, 0xcf, 0x54, 0x17, 0x28, 0x04, + 0x00, 0x25, 0x08, 0xe2, 0xd3, 0x33, 0xc8, 0xde, 0xb4, 0x37, 0x0d, 0xd9, 0xf8, + 0xdf, 0x14, 0x81, 0x52, 0x36, 0x03, 0xdb, 0x12, 0x1f, 0xfe, 0x4a, 0x0c, 0xfd, + 0xe2, 0xec, 0xda, 0xfd, 0x21, 0x12, 0xf4, 0xe5, 0xc8, 0x0b, 0x12, 0x41, 0xae, + 0xe6, 0xfb, 0xee, 0x1c, 0xef, 0x04, 0x41, 0x11, 0xf0, 0x11, 0xe4, 0xdb, 0x21, + 0x1f, 0x07, 0xcf, 0x0c, 0x27, 0x1e, 0x1a, 0xde, 0xee, 0xcf, 0x24, 0x1b, 0x03, + 0xd9, 0xee, 0x06, 0xd6, 0xeb, 0xd4, 0xaa, 0x1a, 0xe4, 0x0a, 0x37, 0x07, 0x40, + 0xb7, 0xa3, 0x15, 0xe2, 0xc8, 0xd4, 0x11, 0x41, 0xff, 0x20, 0x3f, 0x4d, 0x31, + 0xbd, 0x14, 0xbb, 0x09, 0xfb, 0x3a, 0x40, 0xd1, 0x00, 0xed, 0xc5, 0xe6, 0x30, + 0xdb, 0x2f, 0xb1, 0x17, 0xdc, 0x21, 0x8d, 0xf2, 0x68, 0xd4, 0x27, 0xe7, 0xc8, + 0xbc, 0x08, 0xc4, 0xf6, 0xca, 0xd3, 0xcc, 0x23, 0xfc, 0x46, 0x3c, 0x52, 0xf6, + 0x14, 0x2f, 0xda, 0xf2, 0x18, 0xee, 0x42, 0xc5, 0xff, 0x09, 0xee, 0x1c, 0xf4, + 0xb4, 0xf7, 0x07, 0x45, 0xab, 0x1a, 0xd7, 0x9f, 0x20, 0x01, 0xbe, 0x0a, 0xbe, + 0xff, 0xf6, 0x1b, 0xef, 0x10, 0xce, 0xfe, 0xf4, 0x60, 0x2d, 0xd8, 0x14, 0x1b, + 0x26, 0x7f, 0x4e, 0xe2, 0xd7, 0xfb, 0xde, 0xd5, 0xe6, 0x32, 0xe8, 0x0a, 0x32, + 0xe4, 0xf8, 0x33, 0x2d, 0x32, 0x1b, 0x3a, 0xfa, 0x56, 0x18, 0x0e, 0xda, 0x2e, + 0xed, 0x81, 0x08, 0xe5, 0x32, 0xf5, 0xfd, 0xe4, 0xf7, 0xde, 0x00, 0x29, 0x05, + 0x34, 0x47, 0xc5, 0xdc, 0xd1, 0xe5, 0x75, 0x24, 0xc0, 0xda, 0xe5, 0xde, 0x19, + 0xfe, 0x19, 0x07, 0x61, 0xe5, 0xf7, 0xf9, 0x31, 0x0f, 0x06, 0xdf, 0x50, 0xdf, + 0x09, 0x10, 0x19, 0xf1, 0xde, 0x34, 0xc1, 0x7a, 0xfd, 0xcb, 0xda, 0xdf, 0xb6, + 0xa9, 0xf4, 0x37, 0xf2, 0x1d, 0xaf, 0x17, 0x16, 0x03, 0xf2, 0xc7, 0xd4, 0xd1, + 0x5d, 0x08, 0xc7, 0xb9, 0xf7, 0x33, 0x26, 0xf5, 0xd3, 0xf5, 0xce, 0xcb, 0x17, + 0x1e, 0x0e, 0xa2, 0xfe, 0xf7, 0x18, 0xfe, 0x68, 0x31, 0x67, 0xc4, 0x23, 0xc7, + 0x2b, 0x9f, 0x13, 0x34, 0xdc, 0x30, 0xcf, 0xea, 0xd3, 0xfb, 0x1a, 0xf9, 0x62, + 0x12, 0x15, 0xdf, 0x12, 0x2b, 0xcb, 0x0a, 0xee, 0x9e, 0xc6, 0xe6, 0x52, 0xf6, + 0x1b, 0xb3, 0x9c, 0x46, 0xf3, 0x29, 0x40, 0x18, 0xc7, 0xb5, 0x48, 0x22, 0xf0, + 0xae, 0xbf, 0xda, 0xfe, 0xbe, 0x36, 0xef, 0x01, 0xfd, 0xcf, 0xc0, 0x21, 0x52, + 0xf8, 0xf9, 0xdc, 0x98, 0xec, 0xf8, 0x08, 0x54, 0x3a, 0xf5, 0xc2, 0xea, 0x0d, + 0x03, 0xbc, 0xd2, 0xa6, 0x24, 0x7d, 0x4b, 0x01, 0xc9, 0x06, 0x10, 0x0a, 0xb6, + 0xf8, 0x12, 0x4c, 0xf5, 0xcc, 0xf4, 0x3a, 0xdf, 0xf8, 0xbf, 0x14, 0xdd, 0xbb, + 0xab, 0xea, 0xe0, 0x37, 0xa8, 0x7b, 0x0a, 0xea, 0x3c, 0x8c, 0x09, 0xf8, 0xe8, + 0xfc, 0xf1, 0x0d, 0x9d, 0x25, 0x1f, 0xf9, 0x16, 0xb2, 0xbb, 0x03, 0x07, 0xed, + 0xe0, 0xff, 0xbe, 0xab, 0xdc, 0xdd, 0x36, 0x56, 0xc3, 0x32, 0xe3, 0x2b, 0x81, + 0xfa, 0x68, 0xda, 0xd8, 0x55, 0x08, 0x0a, 0x05, 0x0a, 0x16, 0x01, 0xf9, 0xde, + 0xa5, 0x21, 0x38, 0xcf, 0x8e, 0x3d, 0xcd, 0xe3, 0xdd, 0xb4, 0x21, 0x19, 0xe7, + 0x2c, 0xa3, 0x0c, 0xca, 0xe4, 0xfd, 0x3d, 0xdd, 0xf5, 0xe8, 0x30, 0x06, 0x1e, + 0xab, 0xf0, 0xef, 0xda, 0x02, 0xe1, 0xe7, 0xcf, 0xeb, 0xfc, 0x1d, 0x16, 0x15, + 0x27, 0x06, 0xe3, 0x13, 0xe3, 0xee, 0x03, 0xdd, 0x10, 0x09, 0x1e, 0x02, 0xf8, + 0xf7, 0xd5, 0xe7, 0xd7, 0x01, 0xd9, 0xdd, 0x05, 0x28, 0xfb, 0x08, 0x01, 0x07, + 0xff, 0xf7, 0xca, 0x11, 0x30, 0x06, 0x11, 0xf6, 0x19, 0x00, 0x07, 0xe0, 0xf6, + 0xf3, 0xf7, 0x0e, 0x19, 0xc9, 0x08, 0xfd, 0xe2, 0x0a, 0x15, 0x01, 0x1f, 0x17, + 0xf9, 0xec, 0x46, 0xf7, 0xe6, 0xd5, 0xe3, 0x33, 0x0e, 0x0b, 0xf1, 0xfe, 0xe7, + 0x7f, 0xe8, 0xee, 0xe8, 0x1d, 0x11, 0xdd, 0xfd, 0x16, 0xfc, 0xe0, 0x07, 0xee, + 0x1f, 0x15, 0x01, 0x42, 0xd6, 0xe9, 0x0a, 0xeb, 0xea, 0xd2, 0xe1, 0xe1, 0x27, + 0xd4, 0x15, 0x23, 0x19, 0x03, 0xf2, 0xe9, 0xfd, 0xef, 0x03, 0x07, 0xf2, 0x11, + 0x06, 0xf9, 0xf3, 0x20, 0x07, 0x02, 0x5b, 0xf0, 0xd6, 0x3b, 0xf3, 0xf0, 0xcc, + 0x1e, 0xbf, 0xcb, 0x21, 0x12, 0xe9, 0x39, 0xea, 0xcd, 0xd6, 0x09, 0x43, 0x41, + 0x25, 0x0f, 0x35, 0x38, 0xf5, 0x26, 0x3d, 0x15, 0x02, 0x0b, 0xd8, 0x13, 0x1d, + 0x29, 0x0a, 0x03, 0xf6, 0x04, 0x36, 0x1f, 0x66, 0x1a, 0x41, 0x01, 0xe2, 0x01, + 0xf5, 0x09, 0xc9, 0xcf, 0x1a, 0x58, 0x4a, 0x1d, 0xf2, 0x69, 0xf7, 0x01, 0x3b, + 0x32, 0xda, 0xde, 0x19, 0xc3, 0x11, 0x05, 0x70, 0xb9, 0x07, 0x2e, 0xc0, 0xce, + 0x21, 0x2b, 0xfb, 0x16, 0xd3, 0xb8, 0xdc, 0xed, 0x3a, 0x20, 0xd8, 0xc6, 0x20, + 0xe6, 0xcd, 0x26, 0x2a, 0xd2, 0xf9, 0xeb, 0x2c, 0x52, 0xa9, 0x39, 0x11, 0x46, + 0xa1, 0x3f, 0x2e, 0xf6, 0x96, 0xe6, 0xcc, 0xca, 0xff, 0x2f, 0x1b, 0x81, 0x15, + 0x4f, 0x1e, 0x7d, 0xd4, 0x22, 0x02, 0xf2, 0xe3, 0xba, 0xf5, 0xde, 0xeb, 0x04, + 0x9c, 0xd7, 0x29, 0xd9, 0x43, 0xe6, 0x7f, 0x19, 0xec, 0x31, 0x40, 0xeb, 0x14, + 0x04, 0xf3, 0x0d, 0x04, 0x18, 0x15, 0xe5, 0xfa, 0xfc, 0xc7, 0xf8, 0x2a, 0xed, + 0x0a, 0xfa, 0x0c, 0xf1, 0xd5, 0x31, 0xdd, 0xe3, 0xf1, 0xe2, 0xec, 0x54, 0x00, + 0xd2, 0xf1, 0x28, 0x14, 0x10, 0xfb, 0xff, 0xeb, 0x08, 0xe1, 0x17, 0x22, 0x28, + 0xfe, 0x0d, 0xf7, 0x04, 0x16, 0x06, 0x12, 0xfe, 0xb4, 0xf4, 0x1e, 0xe0, 0xf3, + 0xec, 0x1c, 0xd2, 0x0c, 0x09, 0x39, 0x1b, 0xe2, 0x2e, 0xfb, 0xba, 0x00, 0x28, + 0xf1, 0x10, 0x08, 0x2c, 0xd7, 0x05, 0x20, 0xe7, 0xf9, 0x07, 0x24, 0xfd, 0xf1, + 0xe7, 0x1c, 0x04, 0xd5, 0xc8, 0xec, 0x2f, 0xfb, 0xfc, 0x0c, 0xe4, 0xec, 0x2a, + 0x2a, 0xc9, 0xf7, 0xff, 0xe3, 0xd3, 0xf2, 0x08, 0xe1, 0x35, 0xe6, 0xe9, 0x03, + 0x04, 0x04, 0x03, 0x0c, 0xce, 0xd0, 0x01, 0x2f, 0x39, 0x13, 0x15, 0x38, 0xfa, + 0xff, 0xf9, 0x20, 0x3b, 0x04, 0xbc, 0xe3, 0xd2, 0xfd, 0x0e, 0x11, 0x19, 0xe1, + 0x11, 0x0c, 0x19, 0xfb, 0xe7, 0xdd, 0x3b, 0xd4, 0xec, 0x31, 0x5f, 0x7f, 0x30, + 0x1c, 0xc2, 0xd7, 0x01, 0xcb, 0xe5, 0xf8, 0x14, 0xd5, 0x42, 0xf8, 0xf9, 0xb8, + 0xff, 0xd7, 0x1a, 0xf9, 0x28, 0xf0, 0x05, 0xe9, 0xdf, 0x0d, 0x0d, 0xce, 0x08, + 0xd7, 0xe2, 0x00, 0x49, 0x18, 0xf4, 0xb6, 0xe9, 0x34, 0x22, 0xf1, 0x10, 0x0e, + 0x1b, 0x28, 0x09, 0x29, 0xda, 0x23, 0x3d, 0xf1, 0x14, 0x12, 0xce, 0xf8, 0x27, + 0x0b, 0x0e, 0xf9, 0x4b, 0x10, 0xde, 0x1a, 0xc3, 0xf8, 0x3a, 0x0d, 0xef, 0x0d, + 0xff, 0x06, 0xb6, 0x02, 0x20, 0x0d, 0xee, 0xd4, 0xcb, 0xf5, 0x11, 0xd2, 0xfa, + 0xd7, 0x08, 0x5c, 0x11, 0xf6, 0x29, 0x0e, 0xec, 0x06, 0xde, 0xd0, 0xc7, 0xe2, + 0xef, 0x54, 0xfa, 0xec, 0xd6, 0x1f, 0xfd, 0xf4, 0xb2, 0x2a, 0x2a, 0x15, 0xfc, + 0x1c, 0x2e, 0x04, 0x1a, 0xb4, 0xd8, 0x03, 0x00, 0x19, 0xec, 0xb7, 0xfd, 0x2c, + 0x93, 0x65, 0xaa, 0xf9, 0x1a, 0x24, 0x37, 0x55, 0x7c, 0xe0, 0x52, 0x1c, 0x0d, + 0xf8, 0x2d, 0xef, 0xef, 0x1b, 0xd4, 0x21, 0x25, 0x16, 0x48, 0xe9, 0xef, 0xf1, + 0xe9, 0x0a, 0x35, 0x64, 0x35, 0xb9, 0x03, 0xe9, 0x0c, 0xab, 0xef, 0x57, 0xf2, + 0xd1, 0x23, 0x6a, 0x46, 0xbc, 0xf2, 0xfa, 0xc5, 0xf1, 0x3b, 0x0f, 0x22, 0xec, + 0xef, 0x1e, 0xfc, 0xe8, 0x94, 0xdf, 0xf5, 0xcb, 0x41, 0xd4, 0xef, 0x1d, 0x81, + 0x15, 0x40, 0x0d, 0x32, 0xf0, 0xa5, 0xe2, 0x17, 0x15, 0xd7, 0x04, 0xfa, 0xfb, + 0x89, 0x3e, 0x4d, 0x4b, 0x1c, 0x44, 0xdf, 0x0c, 0xdd, 0xec, 0x10, 0xf6, 0x2d, + 0xd4, 0xde, 0xfd, 0x16, 0x47, 0xe1, 0xb1, 0x31, 0x0a, 0x47, 0x90, 0xed, 0xd1, + 0xd2, 0xdb, 0xf4, 0xde, 0xea, 0xb2, 0xbc, 0xdc, 0x0f, 0xf0, 0xa9, 0x27, 0x16, + 0x57, 0x1d, 0x11, 0xff, 0x43, 0xcb, 0x22, 0x07, 0x15, 0xf4, 0x43, 0xc7, 0x02, + 0xc9, 0xb2, 0xee, 0x4f, 0xe6, 0x56, 0xbf, 0x02, 0xb9, 0x20, 0xb5, 0xde, 0x3b, + 0xa3, 0x0f, 0xe2, 0xfe, 0x1c, 0xf4, 0x33, 0x52, 0x04, 0xb5, 0x2e, 0x26, 0x88, + 0xc7, 0x10, 0xfc, 0xe5, 0x5c, 0xe6, 0xbc, 0xe9, 0x1c, 0x6b, 0xf2, 0x03, 0xd0, + 0x18, 0xb6, 0x18, 0x0f, 0x00, 0xde, 0xfc, 0x02, 0x6c, 0xca, 0xf1, 0xf8, 0x4a, + 0x3f, 0xeb, 0xaf, 0x14, 0xbe, 0xe1, 0xcc, 0x50, 0x15, 0x30, 0xeb, 0x06, 0xc2, + 0xfb, 0xce, 0xf9, 0x25, 0xe4, 0x1f, 0x1d, 0x08, 0x0e, 0xeb, 0xd9, 0xad, 0x19, + 0x0e, 0x02, 0xd9, 0x03, 0xf2, 0xfb, 0x14, 0xd9, 0xe2, 0xc6, 0x07, 0x81, 0xe4, + 0x1f, 0xcf, 0xe7, 0x3c, 0xb8, 0xda, 0x02, 0x61, 0x0d, 0xfe, 0x0c, 0x41, 0xc7, + 0xed, 0xf1, 0x2a, 0xce, 0x08, 0x2c, 0xe4, 0x28, 0xe9, 0x06, 0xa0, 0x28, 0xcc, + 0x0f, 0x14, 0xea, 0x15, 0x03, 0xee, 0xb3, 0x0a, 0xe7, 0x04, 0x38, 0xeb, 0xe8, + 0x28, 0x09, 0xe7, 0x13, 0x5b, 0x0f, 0x8d, 0x01, 0xd6, 0xcd, 0xed, 0xeb, 0xf7, + 0xf3, 0x00, 0x0a, 0x21, 0x4b, 0x19, 0xb6, 0xb0, 0x01, 0xdc, 0xe6, 0x43, 0xc8, + 0xce, 0x06, 0xb8, 0x3f, 0x31, 0xe0, 0xea, 0xcf, 0xf9, 0x56, 0xec, 0xc5, 0x81, + 0x32, 0xbd, 0xc3, 0xf9, 0x22, 0x53, 0x22, 0x00, 0xf2, 0x3b, 0xef, 0x1a, 0x45, + 0x9e, 0x60, 0x09, 0x42, 0xdd, 0x2a, 0x32, 0xf3, 0x3b, 0xfd, 0x2d, 0x08, 0xde, + 0x1d, 0x41, 0xdc, 0xd7, 0xdd, 0xe1, 0xf6, 0x09, 0xc3, 0x17, 0xd6, 0x69, 0x48, + 0xb6, 0xfa, 0xe4, 0x1a, 0xfb, 0x5b, 0xfc, 0xba, 0x08, 0x01, 0xec, 0xd6, 0xe0, + 0x26, 0xd2, 0xf5, 0x0c, 0xf6, 0x1c, 0xba, 0xdb, 0xf6, 0x21, 0xf9, 0x0d, 0x12, + 0x33, 0xe8, 0x04, 0xc8, 0xc2, 0x25, 0x0c, 0x18, 0xf6, 0xae, 0xd9, 0xef, 0xb7, + 0xbf, 0x3a, 0x20, 0x0a, 0x0a, 0x48, 0x05, 0x06, 0xcb, 0x0b, 0xb3, 0x24, 0xe2, + 0x51, 0xce, 0x17, 0xfd, 0xb3, 0x2d, 0x29, 0xf2, 0x04, 0x09, 0x61, 0xcc, 0xf1, + 0xb0, 0x2e, 0x4f, 0x19, 0x81, 0x2f, 0xfe, 0x3e, 0xae, 0xca, 0x11, 0x15, 0x79, + 0xd9, 0xb2, 0xf2, 0xe0, 0xed, 0x42, 0xaf, 0xba, 0x0a, 0xee, 0x2c, 0xd1, 0xee, + 0xf1, 0xbc, 0xe8, 0xd7, 0xd5, 0xfd, 0x02, 0xfd, 0x16, 0x46, 0xcf, 0xc5, 0xe8, + 0x37, 0x2d, 0xf5, 0x23, 0xe5, 0xf1, 0xc6, 0x17, 0x23, 0x3b, 0x55, 0xe6, 0x0f, + 0xeb, 0x5f, 0x07, 0x1f, 0x20, 0x27, 0x18, 0xd6, 0x01, 0xfc, 0x58, 0x02, 0xf1, + 0xe5, 0xe9, 0x13, 0x23, 0x16, 0xa9, 0xe7, 0x16, 0xe8, 0xc0, 0xfd, 0x48, 0x9a, + 0xfc, 0x15, 0xfa, 0xde, 0xce, 0x05, 0xb6, 0x20, 0xb0, 0xf2, 0x17, 0xf8, 0xd9, + 0x0a, 0x15, 0x34, 0x20, 0xcb, 0x05, 0x0d, 0x13, 0xe4, 0xed, 0xf2, 0xeb, 0xd2, + 0xff, 0x21, 0x0a, 0x24, 0x19, 0xc5, 0xff, 0xf5, 0xd8, 0xfc, 0xe4, 0xe9, 0xdd, + 0xf0, 0x22, 0x27, 0xf9, 0xda, 0xe7, 0xbc, 0x26, 0xfd, 0xdc, 0x0a, 0xc7, 0xf2, + 0xf8, 0x44, 0xd9, 0x57, 0x2a, 0xfd, 0x02, 0xf9, 0xf4, 0x28, 0x0e, 0x29, 0x39, + 0xe4, 0x7f, 0x62, 0xd6, 0x14, 0xd4, 0xda, 0x17, 0xdd, 0x3a, 0x1e, 0xcd, 0xea, + 0xfe, 0xd4, 0x00, 0xf1, 0xf9, 0xf2, 0x13, 0xe6, 0xf5, 0xe3, 0x7e, 0xfc, 0x18, + 0xbd, 0x10, 0x11, 0xde, 0x0f, 0x01, 0xd6, 0xcc, 0xbc, 0x1a, 0xe7, 0xdb, 0x0c, + 0x01, 0x08, 0x3c, 0x07, 0xe2, 0xfe, 0xc9, 0xd1, 0x04, 0xef, 0x34, 0xfe, 0x0b, + 0x20, 0x2c, 0x41, 0x66, 0x03, 0xe3, 0x24, 0xfe, 0xfc, 0x02, 0x44, 0xeb, 0x08, + 0xf3, 0x62, 0xfe, 0xfe, 0xf5, 0x28, 0xf8, 0x05, 0x08, 0xfe, 0xf4, 0x00, 0x02, + 0x37, 0xdc, 0xe9, 0x0c, 0xfd, 0x81, 0x22, 0xfa, 0xde, 0x2e, 0x05, 0xff, 0xfc, + 0x26, 0xf0, 0xf2, 0xcf, 0xf1, 0xf0, 0xdd, 0xd5, 0xee, 0x0d, 0xf3, 0xe6, 0xe1, + 0xfd, 0x06, 0x21, 0xdb, 0xf9, 0x32, 0xff, 0x2b, 0x15, 0xfe, 0x05, 0x19, 0x03, + 0xf3, 0x45, 0x02, 0x0a, 0x0f, 0x02, 0xe5, 0xfc, 0xd7, 0x03, 0xf1, 0xc9, 0x34, + 0xf2, 0x0d, 0x38, 0xf2, 0x06, 0x28, 0x2e, 0xc5, 0xc8, 0xf1, 0x0c, 0xd8, 0xe1, + 0x0b, 0xd3, 0xe7, 0xe7, 0x0d, 0xfb, 0xe8, 0x40, 0xf4, 0x14, 0x13, 0x13, 0xd0, + 0x01, 0xff, 0x13, 0x18, 0xf9, 0xf9, 0x58, 0xeb, 0xcf, 0xd8, 0x2b, 0xd4, 0xcb, + 0xe7, 0x26, 0x0b, 0xf0, 0x0a, 0x20, 0xf0, 0x11, 0xed, 0xd9, 0xe8, 0x07, 0xd3, + 0xd0, 0xed, 0xfd, 0x0b, 0x33, 0xf2, 0x03, 0x0f, 0x0e, 0x0a, 0x22, 0xea, 0xf7, + 0x24, 0xe0, 0x0f, 0x2c, 0xc2, 0x0e, 0x2b, 0xb9, 0x10, 0x16, 0xea, 0x04, 0x0b, + 0xe4, 0xf4, 0xcb, 0x81, 0xf3, 0x0b, 0x13, 0x03, 0x13, 0x31, 0xd5, 0xde, 0xf9, + 0x01, 0x00, 0xf3, 0xfd, 0xd3, 0xfd, 0x16, 0xcd, 0xef, 0x34, 0xb8, 0x31, 0x06, + 0x1a, 0x1a, 0xdf, 0x2c, 0x11, 0x25, 0xfb, 0x4a, 0x3e, 0xf5, 0xed, 0xed, 0x1b, + 0x25, 0xf7, 0xfd, 0xed, 0xf7, 0xe5, 0xfa, 0xea, 0xef, 0x24, 0x12, 0x04, 0xeb, + 0x08, 0x1e, 0xd8, 0xd9, 0x1e, 0xfc, 0xf6, 0xde, 0xe6, 0xe1, 0x10, 0xfe, 0x48, + 0x0f, 0x0c, 0xfd, 0xdd, 0x2e, 0x1a, 0xca, 0xfe, 0x33, 0x0a, 0xe2, 0x23, 0xcf, + 0xd1, 0x15, 0xed, 0x10, 0x2b, 0x05, 0xd7, 0x00, 0xf2, 0x18, 0xce, 0xe9, 0x0c, + 0x01, 0xf4, 0xed, 0x31, 0x21, 0x01, 0x09, 0x29, 0x06, 0x09, 0x3a, 0xdc, 0x55, + 0x10, 0xf4, 0x14, 0xfc, 0xa7, 0xf8, 0xb7, 0x33, 0xec, 0x23, 0xd5, 0xf6, 0xdc, + 0x09, 0xe0, 0x2c, 0x20, 0xd9, 0xb6, 0x36, 0x0a, 0x0a, 0x33, 0xef, 0x09, 0x1f, + 0xeb, 0xf6, 0x0a, 0x2d, 0xd5, 0xe1, 0xee, 0x17, 0xc0, 0xd6, 0x08, 0x44, 0xfd, + 0xd6, 0x17, 0x31, 0x09, 0xfc, 0x39, 0x48, 0x3b, 0x32, 0x0f, 0x30, 0xd9, 0xb1, + 0x6a, 0x03, 0x08, 0xf7, 0x11, 0xce, 0x2b, 0x0e, 0x2a, 0xe7, 0x34, 0xf8, 0x41, + 0x50, 0xed, 0x03, 0x25, 0x14, 0x38, 0xcd, 0xfe, 0xfe, 0xeb, 0x1a, 0x0d, 0x07, + 0x25, 0xcf, 0x2a, 0xe5, 0xfb, 0xe7, 0x60, 0xe6, 0x05, 0xf6, 0xed, 0xf1, 0xec, + 0x65, 0x01, 0x43, 0xf8, 0x33, 0x1a, 0xef, 0xf3, 0x16, 0xf5, 0xf8, 0xde, 0x19, + 0x35, 0xc8, 0xdf, 0xfe, 0xc5, 0x0d, 0xa7, 0x0f, 0x22, 0xef, 0x02, 0x18, 0xb5, + 0x0e, 0x18, 0x13, 0x63, 0x16, 0x57, 0xfc, 0xbf, 0xc2, 0x09, 0xea, 0xda, 0xf4, + 0xf8, 0xce, 0x1b, 0x56, 0xd0, 0x1d, 0xc3, 0x0b, 0xab, 0x20, 0x05, 0xf1, 0xcc, + 0xea, 0xa6, 0xec, 0xfa, 0xf0, 0x26, 0x06, 0x0b, 0x81, 0xe5, 0x21, 0xd7, 0x10, + 0xf3, 0xff, 0xf3, 0xf1, 0xed, 0x1c, 0x09, 0x18, 0x18, 0x0a, 0xf9, 0xee, 0xbd, + 0x6f, 0x11, 0xdc, 0xac, 0xd0, 0x24, 0xf0, 0xe8, 0xf1, 0x1a, 0xc8, 0xea, 0xd1, + 0x29, 0x23, 0xc2, 0xf0, 0x21, 0xb8, 0xe7, 0xfe, 0xec, 0x2c, 0xdb, 0x07, 0x13, + 0xca, 0x2a, 0xd3, 0xe6, 0x14, 0x20, 0xf4, 0xe2, 0x13, 0x02, 0x32, 0xff, 0x0d, + 0x02, 0x0b, 0x0f, 0x0c, 0x0e, 0x17, 0xf9, 0x21, 0x1b, 0xf2, 0x08, 0xb5, 0xfc, + 0xf5, 0xe6, 0xc4, 0xf1, 0xe9, 0x0d, 0x0b, 0xf7, 0xcf, 0xc9, 0x13, 0xf8, 0x33, + 0x0a, 0x02, 0x24, 0xc3, 0xf6, 0x0d, 0xc2, 0xdb, 0xf8, 0x45, 0xfe, 0x14, 0xf3, + 0xeb, 0xe1, 0xd3, 0x15, 0x32, 0x0d, 0xd0, 0xde, 0xec, 0x19, 0x14, 0x0b, 0xfe, + 0x0f, 0xf5, 0xe0, 0xea, 0x00, 0x22, 0x17, 0xd3, 0xd2, 0xfb, 0xf1, 0x17, 0x45, + 0x16, 0x19, 0x37, 0x81, 0xea, 0x0b, 0x3a, 0xf1, 0x49, 0x4c, 0xa8, 0x0d, 0x23, + 0xe5, 0x0c, 0xda, 0xea, 0x12, 0xda, 0xe3, 0xcd, 0x7c, 0x0d, 0x53, 0x0c, 0xc5, + 0x93, 0x45, 0xc9, 0x6e, 0x4f, 0xbb, 0xb7, 0xf1, 0x4c, 0xe2, 0xd4, 0xf6, 0xaa, + 0xe3, 0xce, 0xe7, 0x36, 0x98, 0xf2, 0x2d, 0x1e, 0x51, 0x15, 0xd3, 0x19, 0x5d, + 0xdf, 0xa7, 0x0a, 0x00, 0xea, 0xc4, 0x0b, 0x07, 0xe2, 0x45, 0xe9, 0x14, 0xd7, + 0x0b, 0x77, 0xb9, 0x26, 0xfb, 0xe4, 0x4d, 0x26, 0x16, 0x01, 0x8d, 0x49, 0x9e, + 0xf0, 0x00, 0x47, 0x95, 0x01, 0x27, 0xcd, 0xd8, 0x84, 0x09, 0xff, 0xcf, 0x17, + 0x81, 0x15, 0x17, 0xcf, 0xd2, 0x25, 0x31, 0x09, 0xa0, 0x8f, 0x0e, 0x21, 0x91, + 0x00, 0x04, 0xb2, 0x40, 0x1b, 0xea, 0xa6, 0x0d, 0x41, 0x16, 0xd5, 0xe9, 0xff, + 0x76, 0x16, 0x09, 0x1b, 0x02, 0x37, 0x44, 0x48, 0xf9, 0xef, 0xed, 0x2e, 0xe9, + 0x2c, 0x20, 0x17, 0xd5, 0xbe, 0xad, 0x4f, 0xe4, 0xfb, 0xee, 0xbb, 0x04, 0x0c, + 0xda, 0x2b, 0xe7, 0x0c, 0x20, 0x03, 0x2d, 0x01, 0xff, 0xc6, 0x2c, 0x30, 0xb0, + 0x31, 0xe4, 0xe4, 0xd4, 0xf3, 0xe0, 0xce, 0xe7, 0x04, 0x9d, 0x57, 0x0e, 0xf4, + 0xe3, 0x24, 0xf1, 0xe4, 0xef, 0xc4, 0xde, 0x32, 0xea, 0xfa, 0x0d, 0xa7, 0xf4, + 0x15, 0xc8, 0x11, 0xc2, 0x58, 0x2e, 0x8e, 0x28, 0xf2, 0x32, 0xc2, 0xfa, 0x2f, + 0xfa, 0x46, 0xf0, 0x73, 0x09, 0x9a, 0xca, 0x42, 0xaf, 0xa8, 0x18, 0xe5, 0x0f, + 0x05, 0x0d, 0x0c, 0xca, 0x0e, 0xd7, 0x27, 0x05, 0xe9, 0xc6, 0x19, 0x81, 0x0e, + 0xf6, 0xfc, 0xe7, 0x41, 0xe7, 0xd5, 0xe8, 0x0a, 0x10, 0x07, 0xd4, 0x3e, 0x06, + 0xcd, 0xc2, 0x01, 0x2d, 0xcd, 0x5a, 0xb4, 0x36, 0x05, 0x31, 0xd7, 0x10, 0xca, + 0x3c, 0x17, 0x00, 0x38, 0x20, 0xf9, 0xe7, 0xdd, 0xf8, 0x18, 0xad, 0x12, 0xa5, + 0xd4, 0xe2, 0xbf, 0xfa, 0x10, 0xbd, 0x1d, 0xb0, 0x2e, 0x20, 0xd9, 0x0e, 0xee, + 0xfb, 0xa3, 0xcd, 0xc4, 0xec, 0xef, 0xf2, 0xe4, 0x9e, 0xdb, 0xae, 0x0d, 0xff, + 0xec, 0x17, 0xa2, 0x09, 0x1b, 0xfb, 0xdf, 0x29, 0x00, 0xf2, 0xab, 0xe3, 0xdf, + 0xe5, 0xe5, 0x13, 0x73, 0x0f, 0x14, 0xf3, 0xba, 0xde, 0xdc, 0xc0, 0x14, 0x24, + 0x36, 0x2c, 0xbe, 0xe4, 0x11, 0xeb, 0x0e, 0x05, 0xd0, 0xfe, 0x2d, 0xc8, 0xf1, + 0x15, 0x17, 0x05, 0x7f, 0x17, 0xe1, 0xee, 0xfa, 0xf9, 0x22, 0x02, 0xfc, 0x2d, + 0xde, 0x37, 0x07, 0x0d, 0xef, 0x10, 0xdf, 0xfc, 0xc7, 0x42, 0xf4, 0x1d, 0xfe, + 0xfe, 0x04, 0xf9, 0x04, 0x3b, 0xd3, 0xf6, 0x54, 0xd0, 0xe5, 0xef, 0x2a, 0x13, + 0xd7, 0x0a, 0xde, 0xf3, 0x1c, 0x0b, 0x07, 0xae, 0xd7, 0xf4, 0x12, 0xe6, 0x18, + 0xa5, 0x16, 0xe3, 0xc7, 0xf7, 0xfa, 0x23, 0x06, 0x1a, 0x1d, 0xf0, 0x0a, 0x35, + 0x17, 0xef, 0xf6, 0x2f, 0xb1, 0xeb, 0x3a, 0xf6, 0x18, 0xed, 0x22, 0xff, 0xf0, + 0xee, 0x1c, 0xce, 0xdd, 0xe7, 0x1f, 0x0a, 0x0a, 0x23, 0x2e, 0xf2, 0xca, 0xff, + 0xd0, 0xf7, 0xef, 0x43, 0xdd, 0xf7, 0x7f, 0xe2, 0xfe, 0xe7, 0xe0, 0x07, 0xef, + 0xe1, 0xf6, 0x10, 0xef, 0xf2, 0x03, 0x9d, 0xef, 0x07, 0xf1, 0x4f, 0xf8, 0xfe, + 0x03, 0xf2, 0xf8, 0xf8, 0x02, 0xca, 0xaa, 0x53, 0x10, 0x1b, 0xfc, 0x08, 0x22, + 0xcc, 0xc1, 0xcf, 0xff, 0x00, 0xde, 0xea, 0x20, 0xcb, 0xfd, 0x12, 0xf3, 0xee, + 0xd5, 0xd0, 0xff, 0xf6, 0xff, 0x0a, 0xeb, 0xb2, 0xe6, 0x0e, 0xf5, 0x62, 0x02, + 0xff, 0x12, 0xdf, 0x13, 0x0c, 0x0b, 0x0a, 0xe6, 0xdc, 0x0b, 0x35, 0xea, 0x0d, + 0xd5, 0x12, 0xd8, 0xdd, 0x07, 0xf7, 0x23, 0xc5, 0x26, 0xbd, 0x25, 0xe9, 0xee, + 0x09, 0x0d, 0xb5, 0x13, 0xec, 0xc5, 0xe4, 0x03, 0x2a, 0x06, 0x18, 0xd0, 0xfb, + 0xe4, 0xf4, 0x30, 0x1f, 0x0d, 0x00, 0xfd, 0xef, 0xdb, 0x0a, 0x15, 0xe3, 0x18, + 0xfb, 0xed, 0x02, 0x39, 0x1b, 0x71, 0x53, 0xbb, 0xf3, 0x15, 0x1d, 0xd6, 0x3a, + 0x1d, 0x2f, 0x03, 0xd9, 0x1a, 0x0a, 0xf2, 0xe9, 0x1d, 0x2c, 0x4b, 0x10, 0x25, + 0xb4, 0x36, 0xd3, 0x04, 0xcd, 0x05, 0x18, 0xf0, 0xa9, 0xe7, 0xec, 0xdf, 0x0f, + 0xe5, 0x17, 0x1b, 0x4f, 0x21, 0x1a, 0x09, 0x11, 0xde, 0x32, 0xf8, 0xce, 0xfc, + 0x11, 0x00, 0x15, 0xbb, 0xf0, 0x03, 0xfd, 0x3c, 0x0a, 0xf3, 0xe5, 0x36, 0x1d, + 0xff, 0xe7, 0xe9, 0x03, 0xec, 0x32, 0x19, 0xcb, 0xd9, 0xc0, 0xe5, 0x49, 0x33, + 0x1f, 0xfa, 0xfe, 0xc8, 0x48, 0x2a, 0x0f, 0xd8, 0x1b, 0xda, 0xfc, 0xda, 0xfd, + 0xd8, 0x25, 0xc5, 0x2f, 0x01, 0xd0, 0x19, 0x05, 0x0a, 0xcd, 0xff, 0xf4, 0x19, + 0xfe, 0x0f, 0xfa, 0xf3, 0xe1, 0xd6, 0x17, 0xca, 0xe2, 0x7f, 0x23, 0x3e, 0x58, + 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xb0, 0xf8, 0xff, + 0xff, 0x83, 0xe2, 0xff, 0xff, 0xaa, 0x36, 0x00, 0x00, 0x77, 0x0c, 0x00, 0x00, + 0x9a, 0xfd, 0xff, 0xff, 0x9c, 0x0c, 0x00, 0x00, 0x0e, 0xde, 0xff, 0xff, 0xc0, + 0x1b, 0x00, 0x00, 0x7c, 0x04, 0x00, 0x00, 0x2e, 0xc5, 0xff, 0xff, 0xbe, 0x01, + 0x00, 0x00, 0xb1, 0x17, 0x00, 0x00, 0xb5, 0x0f, 0x00, 0x00, 0xf8, 0x48, 0x00, + 0x00, 0xc9, 0xfc, 0xff, 0xff, 0x57, 0xe2, 0xff, 0xff, 0x4b, 0x2a, 0x00, 0x00, + 0x08, 0xc1, 0xff, 0xff, 0xb2, 0x25, 0x00, 0x00, 0xb9, 0x01, 0x00, 0x00, 0xe9, + 0x24, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0xeb, 0xef, 0xff, 0xff, 0x4f, 0x0b, + 0x00, 0x00, 0xcd, 0x27, 0x00, 0x00, 0x3a, 0x07, 0x00, 0x00, 0x77, 0x25, 0x00, + 0x00, 0x61, 0x07, 0x00, 0x00, 0x54, 0x1c, 0x00, 0x00, 0x24, 0xfd, 0xff, 0xff, + 0xd9, 0xe1, 0xff, 0xff, 0xe5, 0xda, 0xff, 0xff, 0x6e, 0xf4, 0xff, 0xff, 0x9f, + 0x37, 0x00, 0x00, 0x64, 0xdf, 0xff, 0xff, 0xbb, 0x1c, 0x00, 0x00, 0xb9, 0x1d, + 0x00, 0x00, 0x8d, 0x09, 0x00, 0x00, 0x2f, 0x30, 0x00, 0x00, 0x66, 0x00, 0x00, + 0x00, 0xb2, 0xf9, 0xff, 0xff, 0x0a, 0x41, 0x00, 0x00, 0x53, 0x21, 0x00, 0x00, + 0xf0, 0x1a, 0x00, 0x00, 0x58, 0x43, 0x00, 0x00, 0xe0, 0x0d, 0x00, 0x00, 0x09, + 0x3b, 0x00, 0x00, 0xee, 0x06, 0x00, 0x00, 0xfa, 0x34, 0x00, 0x00, 0x8f, 0xff, + 0xff, 0xff, 0xa5, 0xef, 0xff, 0xff, 0xb6, 0x0f, 0x00, 0x00, 0x21, 0x1b, 0x00, + 0x00, 0x96, 0x05, 0x00, 0x00, 0xed, 0xf8, 0xff, 0xff, 0x5f, 0x15, 0x00, 0x00, + 0xa0, 0xc4, 0xff, 0xff, 0xa2, 0xe0, 0xff, 0xff, 0x52, 0x06, 0x00, 0x00, 0xbc, + 0x33, 0x00, 0x00, 0x54, 0xb9, 0xff, 0xff, 0xd5, 0xfd, 0xff, 0xff, 0xe2, 0x13, + 0x00, 0x00, 0xc4, 0x29, 0x00, 0x00, 0x09, 0x43, 0x00, 0x00, 0x25, 0x26, 0x00, + 0x00, 0xd0, 0xec, 0xff, 0xff, 0xea, 0x15, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, + 0xa2, 0x01, 0x00, 0x00, 0xde, 0xe7, 0xff, 0xff, 0x91, 0xe7, 0xff, 0xff, 0x4a, + 0x21, 0x00, 0x00, 0xf1, 0x25, 0x00, 0x00, 0xbb, 0x07, 0x00, 0x00, 0x1e, 0x04, + 0x00, 0x00, 0x2f, 0xe6, 0xff, 0xff, 0x31, 0x08, 0x00, 0x00, 0xa6, 0x1e, 0x00, + 0x00, 0x62, 0x1a, 0x00, 0x00, 0xc0, 0x17, 0x00, 0x00, 0xa5, 0x4d, 0x00, 0x00, + 0x6a, 0xe4, 0xff, 0xff, 0x4c, 0xf2, 0xff, 0xff, 0xad, 0x01, 0x00, 0x00, 0x94, + 0x22, 0x00, 0x00, 0x32, 0xe5, 0xff, 0xff, 0xd7, 0x3f, 0x00, 0x00, 0x80, 0xed, + 0xff, 0xff, 0x4f, 0x15, 0x00, 0x00, 0x08, 0xec, 0xff, 0xff, 0xc1, 0xe8, 0xff, + 0xff, 0x7d, 0xd4, 0xff, 0xff, 0x6e, 0xe7, 0xff, 0xff, 0x51, 0xd9, 0xff, 0xff, + 0x65, 0x2b, 0x00, 0x00, 0xc3, 0x13, 0x00, 0x00, 0x3e, 0xd4, 0xff, 0xff, 0x40, + 0x3e, 0x00, 0x00, 0xd7, 0xe5, 0xff, 0xff, 0x25, 0x53, 0x00, 0x00, 0xb2, 0xef, + 0xff, 0xff, 0x57, 0x1f, 0x00, 0x00, 0x0e, 0xf3, 0xff, 0xff, 0x71, 0x0a, 0x00, + 0x00, 0x0e, 0xfc, 0xff, 0xff, 0x43, 0x00, 0x00, 0x00, 0x60, 0x11, 0x00, 0x00, + 0x95, 0x09, 0x00, 0x00, 0xf8, 0x3a, 0x00, 0x00, 0x6b, 0x16, 0x00, 0x00, 0xe2, + 0xf2, 0xff, 0xff, 0x0b, 0xf8, 0xff, 0xff, 0x5c, 0xf6, 0xff, 0xff, 0xd7, 0x09, + 0x00, 0x00, 0x94, 0x26, 0x00, 0x00, 0xaa, 0x27, 0x00, 0x00, 0x40, 0x0d, 0x00, + 0x00, 0xd7, 0xf3, 0xff, 0xff, 0xa1, 0x1a, 0x00, 0x00, 0x97, 0xfa, 0xff, 0xff, + 0xce, 0xe1, 0xff, 0xff, 0x5e, 0x1c, 0x00, 0x00, 0x36, 0x13, 0x00, 0x00, 0xa1, + 0x37, 0x00, 0x00, 0xfe, 0x32, 0x00, 0x00, 0x9a, 0x26, 0x00, 0x00, 0x12, 0xf1, + 0xff, 0xff, 0x4a, 0x5a, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x0c, 0xb1, 0x0a, 0x7f, 0x0c, 0xfe, 0xf6, 0xff, 0x9a, 0xd5, 0xc9, 0x00, + 0xf8, 0xbc, 0xe4, 0xe0, 0x21, 0x28, 0x06, 0xed, 0x30, 0x1e, 0xca, 0xcf, 0x0f, + 0x05, 0xdb, 0xe9, 0xea, 0xd4, 0x0d, 0xb5, 0x30, 0xdd, 0xe8, 0x4b, 0xa3, 0xdc, + 0x1c, 0x2b, 0xf0, 0x3b, 0xcf, 0x1f, 0xda, 0x12, 0xfd, 0xfb, 0xd0, 0x20, 0xcb, + 0xb3, 0x12, 0x36, 0xd7, 0x35, 0xde, 0x03, 0x70, 0x03, 0x39, 0x05, 0xe8, 0xce, + 0x30, 0xf3, 0x3b, 0xfd, 0x35, 0x0b, 0x36, 0xaa, 0xff, 0xc6, 0x1a, 0xfd, 0x18, + 0x01, 0xc1, 0x2b, 0xc1, 0xfe, 0x0e, 0xef, 0x13, 0xd4, 0x04, 0x17, 0xde, 0xd9, + 0x01, 0xfb, 0xd7, 0xf8, 0xff, 0x0a, 0xf9, 0xf8, 0x0b, 0x23, 0xc1, 0x34, 0x52, + 0xd7, 0x2b, 0x8f, 0xe4, 0x39, 0x37, 0x39, 0xf5, 0xe4, 0x14, 0xed, 0xe2, 0x20, + 0xf8, 0x0f, 0x02, 0xba, 0x11, 0x24, 0xf7, 0x00, 0xc2, 0xf2, 0xe7, 0xf5, 0xb3, + 0xfa, 0xfa, 0xad, 0x42, 0x3c, 0x0d, 0x02, 0x20, 0x9f, 0x21, 0xb0, 0xfc, 0x22, + 0xf8, 0x29, 0xf9, 0x32, 0x1c, 0xf7, 0xbc, 0xff, 0xee, 0xa8, 0xfd, 0x31, 0x07, + 0x2b, 0x84, 0x03, 0xf6, 0x2e, 0xcc, 0xd9, 0x1e, 0x02, 0x0b, 0x10, 0x97, 0x49, + 0xcf, 0xcd, 0xd1, 0x38, 0xc5, 0xe6, 0xed, 0xb0, 0x2d, 0xdb, 0x2b, 0xfa, 0xf8, + 0xf0, 0xf5, 0xf5, 0x04, 0x44, 0x4f, 0xf1, 0x44, 0x44, 0xd0, 0x0f, 0x30, 0x27, + 0xaa, 0x22, 0x89, 0x00, 0xe5, 0x0f, 0xcb, 0x05, 0xef, 0x9e, 0xe9, 0xe5, 0xbd, + 0xe5, 0xd5, 0xe5, 0xd4, 0xd1, 0xff, 0xa6, 0xd8, 0x3a, 0xfb, 0x08, 0x09, 0xe9, + 0xde, 0x27, 0x54, 0xf2, 0xe4, 0x73, 0xe8, 0x0a, 0xfe, 0x1c, 0x61, 0x32, 0x22, + 0x16, 0xfe, 0xaf, 0x43, 0xcc, 0x1f, 0x26, 0x21, 0x50, 0x00, 0x7f, 0x05, 0xf0, + 0xf0, 0xf1, 0xad, 0x20, 0xfa, 0xe3, 0x40, 0xdc, 0xfc, 0x97, 0xef, 0xc5, 0x07, + 0x1f, 0xaf, 0xe6, 0xf5, 0x13, 0xf6, 0x08, 0x1e, 0xfe, 0xc4, 0xc7, 0x28, 0xde, + 0xf1, 0x11, 0xcb, 0x0c, 0x23, 0x1b, 0x15, 0x05, 0xe2, 0x00, 0x1e, 0xfd, 0x19, + 0xfc, 0x53, 0xe5, 0xfe, 0xb7, 0xab, 0x21, 0x0a, 0x46, 0x07, 0xcb, 0x3a, 0x1a, + 0x51, 0xfb, 0x01, 0xcd, 0xe6, 0xf7, 0xfc, 0xc3, 0x35, 0xcb, 0xf7, 0xd7, 0x21, + 0xe0, 0xfc, 0xea, 0x25, 0x9c, 0x24, 0xec, 0xfc, 0x4e, 0x1a, 0x21, 0x28, 0xb1, + 0xfd, 0xda, 0xde, 0x81, 0xf7, 0xc8, 0xe9, 0xaa, 0x1e, 0xd5, 0x4d, 0xf5, 0x36, + 0x05, 0x13, 0x03, 0x29, 0xfe, 0x09, 0x00, 0x05, 0xf0, 0xfc, 0xeb, 0xe2, 0xb9, + 0x27, 0x19, 0xd5, 0xca, 0xf9, 0xf8, 0x03, 0xee, 0x1c, 0xd9, 0xf5, 0xca, 0xf0, + 0xe0, 0xfa, 0xdb, 0x3d, 0x1f, 0x2b, 0x34, 0xf9, 0xe6, 0xd7, 0xdc, 0xd3, 0xfd, + 0xe9, 0xf2, 0xdd, 0x22, 0xcc, 0x2d, 0xff, 0xd5, 0xec, 0xda, 0x46, 0xb9, 0x5d, + 0x32, 0xda, 0xfe, 0xc0, 0xe1, 0x28, 0x28, 0x0c, 0x39, 0xec, 0x39, 0xf7, 0x25, + 0xf2, 0x0d, 0xf4, 0xcf, 0x22, 0xfa, 0x26, 0x11, 0x00, 0xb6, 0x81, 0x1e, 0x11, + 0xc1, 0xd6, 0x14, 0x1f, 0x12, 0x4f, 0xd0, 0xc7, 0xef, 0xf2, 0xd6, 0xf6, 0xed, + 0x1b, 0xfd, 0xda, 0xf3, 0x26, 0x08, 0xd4, 0x18, 0x2c, 0xc7, 0xf8, 0x15, 0xbd, + 0xf6, 0x24, 0x29, 0x0f, 0xa5, 0x1e, 0xcd, 0xd9, 0xf5, 0xa7, 0xea, 0x02, 0xd3, + 0x82, 0xf0, 0xfc, 0xdf, 0xbd, 0x45, 0x18, 0x70, 0x99, 0x21, 0x08, 0xc1, 0x1e, + 0xef, 0xee, 0xe7, 0x13, 0xbf, 0xcd, 0xe1, 0x30, 0xe7, 0xcf, 0xf3, 0x0e, 0x58, + 0xed, 0xd2, 0xf3, 0x10, 0xf1, 0x07, 0xe1, 0x06, 0xe5, 0xf8, 0xda, 0x2c, 0x05, + 0x03, 0xc2, 0xea, 0xfd, 0xc3, 0xf4, 0xe5, 0x5c, 0xf1, 0x06, 0xcc, 0x59, 0xd7, + 0x33, 0xda, 0x58, 0xee, 0xf6, 0xdf, 0x23, 0xc3, 0xde, 0xaf, 0xf4, 0x38, 0x2b, + 0x08, 0x43, 0xd8, 0x0d, 0x55, 0x22, 0x67, 0x5b, 0x54, 0xd2, 0xf9, 0x6b, 0xdf, + 0x18, 0x01, 0x0b, 0x1f, 0x5f, 0x01, 0xfc, 0x18, 0x2e, 0x15, 0x73, 0xea, 0xec, + 0x10, 0xa3, 0x9f, 0x19, 0xe8, 0xfe, 0x81, 0xff, 0xfd, 0x2c, 0xc1, 0xd7, 0xc6, + 0xf9, 0x47, 0xfa, 0x3f, 0x03, 0xd4, 0x11, 0x2c, 0xbe, 0xd9, 0xa0, 0x1c, 0x12, + 0xfc, 0x07, 0x03, 0x0e, 0xea, 0x4a, 0xe4, 0xb9, 0xab, 0xf6, 0xf9, 0x1c, 0xfe, + 0x08, 0xe7, 0xe6, 0xe5, 0xce, 0x22, 0xe3, 0x9a, 0xd8, 0xf6, 0x25, 0xbb, 0x95, + 0x5c, 0x09, 0xd1, 0xe1, 0x10, 0xf4, 0xe0, 0xca, 0x10, 0x19, 0xb4, 0xfe, 0x34, + 0x3a, 0xc7, 0x0e, 0xc1, 0xa2, 0x7a, 0xdd, 0xef, 0x39, 0xfc, 0x13, 0xdf, 0xad, + 0xea, 0xeb, 0xd7, 0x45, 0x1d, 0xd9, 0x13, 0x6b, 0x33, 0xb3, 0x33, 0xcb, 0xdb, + 0x94, 0x0a, 0x64, 0xf7, 0xee, 0x0b, 0x04, 0xdb, 0x55, 0x37, 0x2a, 0x66, 0xeb, + 0xb6, 0x13, 0xf2, 0xdb, 0x2d, 0xe9, 0x29, 0xff, 0xe9, 0x10, 0xe5, 0xc1, 0xf7, + 0xb3, 0x4b, 0xdc, 0x24, 0x10, 0xe2, 0xcc, 0xc5, 0xd2, 0xc2, 0xd2, 0x37, 0xe9, + 0xb5, 0x4a, 0x0e, 0x46, 0xda, 0x35, 0xca, 0x40, 0xf4, 0xcf, 0xcb, 0x05, 0xe1, + 0xa6, 0x1c, 0xce, 0x89, 0xc6, 0x4c, 0xe6, 0x32, 0x85, 0x0c, 0xaa, 0x16, 0xe6, + 0xef, 0x2d, 0xf2, 0x05, 0xb6, 0x5e, 0x2a, 0x39, 0x24, 0x96, 0x4c, 0xbd, 0xc8, + 0xea, 0x22, 0xb9, 0x01, 0x2a, 0x27, 0x12, 0xe8, 0xf3, 0xaa, 0x5e, 0x24, 0x26, + 0x01, 0xe2, 0xf5, 0x61, 0x31, 0x9e, 0xc4, 0x4c, 0xb4, 0x0f, 0xbf, 0xd8, 0xf2, + 0xe4, 0x10, 0x12, 0xa1, 0x48, 0xdd, 0xec, 0x3b, 0xc0, 0x9f, 0x4a, 0xb4, 0xf0, + 0x6c, 0x4b, 0xae, 0x12, 0x2b, 0xdc, 0x02, 0x8a, 0x6f, 0x08, 0xb1, 0x81, 0xb7, + 0x23, 0x42, 0xfc, 0x4b, 0xda, 0x64, 0xe5, 0xff, 0xc3, 0x32, 0x63, 0xc0, 0xdf, + 0xb6, 0x3d, 0xfc, 0xfa, 0xec, 0xea, 0x4d, 0x28, 0xe4, 0xdc, 0x47, 0xcb, 0xf6, + 0xb9, 0xfc, 0x06, 0x2d, 0xb2, 0xc0, 0xdb, 0x40, 0xcb, 0x2d, 0x15, 0xfb, 0xf9, + 0xfd, 0x39, 0x19, 0x19, 0x1c, 0xc5, 0x05, 0x03, 0xc1, 0x49, 0xe4, 0x05, 0x40, + 0x2f, 0xb8, 0x34, 0x81, 0xf8, 0xe6, 0xa2, 0xbb, 0xf4, 0xed, 0x5d, 0x0b, 0x1b, + 0x10, 0x1a, 0xfa, 0x5b, 0x01, 0xfc, 0xf2, 0xd6, 0xdb, 0x37, 0x0d, 0x4e, 0x32, + 0x36, 0xe1, 0x2a, 0x2a, 0x37, 0x3e, 0xd8, 0x1e, 0x53, 0xe8, 0x79, 0x1d, 0x23, + 0x15, 0x0e, 0x42, 0x40, 0xed, 0xca, 0x2c, 0x03, 0xe0, 0xbd, 0xda, 0x33, 0xfd, + 0x46, 0x25, 0xfd, 0x78, 0xd0, 0xc4, 0x29, 0xc6, 0xe7, 0xd8, 0x4c, 0xd4, 0xf7, + 0x28, 0x62, 0xcc, 0xef, 0x0d, 0x4f, 0xf1, 0x12, 0xdb, 0x12, 0xc9, 0xc8, 0xe8, + 0xbe, 0x7b, 0xf3, 0xc0, 0xe4, 0x16, 0x16, 0x3c, 0xd7, 0xe9, 0x01, 0xf5, 0x2a, + 0x19, 0x41, 0x9a, 0x8e, 0xc5, 0xd8, 0xec, 0xe4, 0x1f, 0xff, 0xdb, 0xf7, 0xbd, + 0x17, 0xfa, 0xda, 0x01, 0x06, 0x48, 0xf6, 0x2e, 0xcc, 0xc9, 0xbd, 0xf5, 0xdf, + 0x55, 0xf7, 0x12, 0xcf, 0xd4, 0x78, 0xb3, 0x11, 0x43, 0x37, 0x68, 0x47, 0xc6, + 0xf4, 0x1e, 0x4d, 0xc6, 0x3c, 0xb9, 0xb8, 0x21, 0x31, 0x02, 0x25, 0xe9, 0x18, + 0xec, 0x02, 0x81, 0x09, 0xf6, 0xec, 0x04, 0xff, 0xed, 0x26, 0xa4, 0x4f, 0x9f, + 0xba, 0x0d, 0x4d, 0x42, 0x3f, 0x3a, 0x28, 0x02, 0x48, 0x59, 0xdb, 0xdb, 0xf1, + 0xe7, 0x3f, 0x41, 0xaf, 0xba, 0x32, 0x8c, 0xcb, 0x2e, 0x23, 0xca, 0x20, 0x05, + 0x53, 0x00, 0x03, 0xc2, 0x15, 0x1f, 0xa6, 0xaf, 0x21, 0xe1, 0xc0, 0xb0, 0xc8, + 0xde, 0xa9, 0x43, 0xd7, 0x33, 0x03, 0x1f, 0x43, 0xb1, 0x09, 0x9e, 0x0c, 0x14, + 0x0d, 0xbc, 0x36, 0x10, 0x0d, 0x13, 0xc6, 0xe3, 0x4f, 0x1d, 0xd1, 0xc8, 0xca, + 0x08, 0xee, 0xb1, 0x07, 0x23, 0xe7, 0x04, 0x0d, 0x04, 0x1a, 0x15, 0x00, 0x3f, + 0x06, 0xf4, 0xc9, 0xde, 0x08, 0xd3, 0x74, 0x10, 0x1d, 0x2f, 0x27, 0xa3, 0xf4, + 0xc4, 0xff, 0xe8, 0x02, 0x1f, 0x0e, 0xe7, 0xfd, 0x23, 0x08, 0xd9, 0xe5, 0xb8, + 0xba, 0xf4, 0x3e, 0xca, 0xe9, 0xc6, 0xe7, 0xaf, 0x15, 0x20, 0xed, 0x7b, 0xd8, + 0x02, 0x06, 0xf3, 0xa2, 0x39, 0xf3, 0x81, 0xeb, 0xce, 0xef, 0xf8, 0x22, 0x25, + 0xf5, 0xde, 0x12, 0xf1, 0x14, 0x47, 0xe0, 0xf0, 0xf6, 0xfe, 0xba, 0xec, 0xea, + 0xe6, 0x2e, 0x0f, 0x10, 0x1a, 0x58, 0xef, 0xf9, 0x0e, 0x0c, 0xc2, 0xe2, 0xd3, + 0xee, 0xfc, 0x12, 0x1c, 0x3d, 0xdf, 0xd9, 0x35, 0x1a, 0xe6, 0x0b, 0x21, 0xc6, + 0x0a, 0x07, 0xeb, 0xc5, 0xe2, 0x33, 0xef, 0x0b, 0xed, 0x1b, 0x23, 0x03, 0x1e, + 0xdb, 0x10, 0xde, 0xc2, 0x7f, 0x2d, 0xe8, 0xa9, 0x15, 0x03, 0xe2, 0xd0, 0x41, + 0x5c, 0x1d, 0xdf, 0xff, 0x0e, 0xea, 0xe1, 0xc6, 0xef, 0x15, 0x09, 0x1a, 0x21, + 0x14, 0xec, 0xfa, 0xe9, 0xe8, 0x1c, 0x75, 0x1b, 0xb6, 0x2c, 0x11, 0x25, 0xfd, + 0x37, 0x12, 0xc5, 0xcd, 0x1f, 0x1d, 0x24, 0xd9, 0x25, 0x1c, 0xb0, 0xfb, 0x03, + 0xca, 0x13, 0x13, 0x22, 0x09, 0x08, 0x33, 0x13, 0xfe, 0xd7, 0x4a, 0xfc, 0xcc, + 0xfa, 0x04, 0xee, 0xe8, 0xbb, 0xc7, 0xfa, 0xdf, 0x13, 0xd8, 0xed, 0x20, 0x1b, + 0xbc, 0x09, 0xf3, 0x1c, 0x05, 0x3c, 0x55, 0xef, 0x24, 0x1a, 0x18, 0x65, 0xe0, + 0x31, 0xcb, 0x21, 0x41, 0x0a, 0x18, 0xf9, 0xed, 0xf0, 0x20, 0xee, 0x01, 0x28, + 0xe0, 0xc6, 0xc7, 0xc2, 0xf6, 0xee, 0x07, 0x40, 0xe7, 0xf7, 0xfc, 0x2a, 0xf3, + 0x15, 0x53, 0x0e, 0x09, 0xd9, 0x18, 0xcf, 0x02, 0x0f, 0x21, 0xfe, 0xfe, 0x04, + 0xf1, 0xc4, 0x47, 0xd7, 0x1f, 0xf9, 0xfd, 0x08, 0x41, 0xf5, 0xe7, 0xed, 0x1b, + 0x03, 0xc8, 0xe0, 0xf6, 0xf5, 0x05, 0x23, 0x03, 0x33, 0x2a, 0x11, 0x2b, 0xfe, + 0x23, 0x03, 0xf9, 0x08, 0x20, 0xc7, 0xfd, 0xeb, 0xf9, 0xf4, 0x0b, 0x0a, 0xfa, + 0xcb, 0x33, 0x08, 0xf1, 0x26, 0xdf, 0xf8, 0x09, 0xbc, 0x03, 0x13, 0x4e, 0xfc, + 0x1e, 0xf0, 0x29, 0x0e, 0x16, 0x31, 0x1b, 0xfb, 0x0b, 0x06, 0xed, 0xcf, 0xf3, + 0xc5, 0x16, 0x05, 0x05, 0xec, 0xfd, 0x1c, 0x37, 0xd2, 0xe2, 0x1b, 0x03, 0x24, + 0xfa, 0x3f, 0x1e, 0xf9, 0xe2, 0x1f, 0x05, 0xcc, 0x02, 0x7f, 0xff, 0xfe, 0x09, + 0x4f, 0x23, 0x00, 0x18, 0x0a, 0x01, 0x42, 0x05, 0xea, 0xd1, 0xdc, 0xfb, 0x16, + 0x3f, 0x23, 0x00, 0xe6, 0xf7, 0x0a, 0x1e, 0xdd, 0x02, 0x18, 0xf9, 0x14, 0xdd, + 0xf2, 0x31, 0x19, 0xfd, 0x2e, 0xf7, 0xf4, 0xe7, 0x24, 0x9e, 0xd1, 0x05, 0x5c, + 0xde, 0xb1, 0x1a, 0xe0, 0x32, 0xb6, 0x05, 0x0b, 0x14, 0x46, 0xde, 0x3a, 0xe4, + 0xfa, 0x14, 0xe2, 0xe2, 0xdc, 0x32, 0x02, 0xd1, 0x21, 0xfd, 0x14, 0x22, 0x13, + 0x02, 0xfd, 0x08, 0x9a, 0x02, 0xd1, 0x4b, 0xf3, 0xe4, 0x13, 0xc1, 0xcb, 0x09, + 0x02, 0xec, 0xbb, 0x17, 0x25, 0x81, 0x48, 0x27, 0xea, 0xcd, 0x0e, 0x18, 0xdc, + 0x17, 0x04, 0x15, 0x38, 0x04, 0xeb, 0xd3, 0xe2, 0xf6, 0xac, 0xe8, 0xbf, 0xb9, + 0x3f, 0xed, 0xe4, 0xee, 0x2c, 0x13, 0x11, 0xee, 0xba, 0x0f, 0x14, 0x07, 0xc1, + 0x0f, 0xde, 0xea, 0xe4, 0x57, 0xfb, 0x00, 0x27, 0x3d, 0x31, 0x1e, 0x3d, 0xf0, + 0x0e, 0x0b, 0x15, 0xdc, 0xcc, 0xd5, 0x27, 0x6f, 0xf7, 0xe6, 0xfb, 0x32, 0x56, + 0xf8, 0xe0, 0xcc, 0x48, 0x06, 0x1e, 0xfb, 0x08, 0xf9, 0xff, 0x1e, 0x03, 0x1b, + 0x17, 0xa0, 0x6a, 0xc6, 0x63, 0x0d, 0x62, 0xd6, 0xd1, 0xc9, 0xea, 0x35, 0x41, + 0xe8, 0x0c, 0x12, 0x32, 0xe1, 0xe1, 0x12, 0x70, 0xff, 0x05, 0x35, 0x19, 0xf1, + 0xf3, 0x07, 0xec, 0x0e, 0xd5, 0xe6, 0xed, 0x6d, 0xd5, 0xf9, 0x32, 0xea, 0x30, + 0xb9, 0xe5, 0x3d, 0xe2, 0xe3, 0xfb, 0xd2, 0x05, 0x23, 0xcc, 0x9c, 0xa5, 0xc5, + 0xe9, 0x03, 0x1d, 0x52, 0xe0, 0x09, 0x0b, 0xe4, 0xeb, 0xd5, 0xba, 0x12, 0x1d, + 0xdd, 0x19, 0x25, 0xbb, 0xba, 0x2b, 0x4c, 0xf8, 0xbe, 0xe3, 0xf3, 0x32, 0xff, + 0xb0, 0x31, 0x0c, 0x21, 0x0f, 0x0e, 0x3b, 0x0d, 0xc1, 0x0a, 0xc9, 0x15, 0x91, + 0x17, 0xd4, 0x19, 0x99, 0xea, 0xb4, 0xdb, 0x3c, 0x10, 0xef, 0xaa, 0x04, 0xf8, + 0xfe, 0x04, 0xd3, 0xf4, 0x36, 0xf9, 0x7f, 0xc4, 0xf0, 0x29, 0xd9, 0x0d, 0x00, + 0xc1, 0x31, 0xf3, 0xee, 0x23, 0x27, 0x37, 0xe6, 0xd1, 0xcf, 0xe0, 0xfb, 0xc8, + 0x2a, 0x36, 0x17, 0xd0, 0xcf, 0xfa, 0xe1, 0x34, 0x0d, 0x1a, 0x01, 0x2a, 0xe4, + 0xf2, 0xf8, 0x10, 0x49, 0xd8, 0xff, 0x18, 0xea, 0x2c, 0xf4, 0xb5, 0x37, 0x00, + 0x14, 0x13, 0xed, 0xfe, 0xd4, 0x9f, 0xf6, 0xf3, 0xd5, 0xbc, 0x0f, 0xe8, 0xb5, + 0x1e, 0x1a, 0x48, 0x10, 0x27, 0xc7, 0xf0, 0x26, 0xea, 0x40, 0xf8, 0x0c, 0x53, + 0x00, 0xdf, 0x28, 0xdf, 0xf3, 0xbc, 0x19, 0xf5, 0x1d, 0x98, 0x33, 0xfa, 0xeb, + 0x1c, 0xeb, 0xbb, 0x03, 0xf7, 0x45, 0x11, 0x27, 0x08, 0xfd, 0x06, 0x0b, 0xe3, + 0xd9, 0xf1, 0xb0, 0xff, 0xe5, 0xf0, 0xed, 0x08, 0x29, 0xc5, 0x05, 0xf1, 0xd5, + 0x1a, 0xd7, 0xc8, 0xcb, 0x7f, 0x81, 0xea, 0xe3, 0xef, 0xb9, 0xef, 0x1a, 0x10, + 0xe0, 0x2c, 0xd0, 0x34, 0x4d, 0xf2, 0x08, 0x25, 0xff, 0xb5, 0x0d, 0xfe, 0xd8, + 0x13, 0x50, 0x2f, 0x2c, 0xee, 0x68, 0xdd, 0x3c, 0x03, 0xf1, 0xf5, 0x3b, 0xe9, + 0xc4, 0xf4, 0x33, 0x06, 0xe1, 0xfd, 0x21, 0xb7, 0xf7, 0x15, 0xf9, 0xc0, 0xf9, + 0xd2, 0x1a, 0xfb, 0xbe, 0xd5, 0x37, 0x20, 0x02, 0xe4, 0x2b, 0xef, 0xe6, 0xec, + 0xad, 0xc2, 0xf6, 0xe7, 0x08, 0x15, 0xe3, 0x5f, 0xdc, 0xff, 0xaa, 0xfa, 0x02, + 0x1c, 0xf8, 0xf9, 0x12, 0x1a, 0x42, 0xc0, 0x00, 0x34, 0x02, 0x02, 0x27, 0x3c, + 0xeb, 0x11, 0x59, 0xd4, 0xea, 0x33, 0x1e, 0xb7, 0x07, 0x32, 0x01, 0xf5, 0x28, + 0x7f, 0x09, 0x0b, 0xde, 0xe8, 0x46, 0x54, 0xa0, 0xff, 0x08, 0x15, 0x19, 0x02, + 0x12, 0xa5, 0xd4, 0x05, 0xbe, 0x1f, 0x2d, 0xae, 0xd4, 0x2c, 0x29, 0xe9, 0xe3, + 0x18, 0x9e, 0x49, 0x4a, 0xe8, 0xe5, 0xbc, 0x84, 0xbe, 0x47, 0x3f, 0xb9, 0x25, + 0xc5, 0xbe, 0x19, 0xeb, 0x36, 0xf3, 0xe2, 0x0f, 0x10, 0x32, 0xe9, 0x04, 0x1a, + 0xe9, 0xe2, 0xc2, 0xf7, 0x22, 0x02, 0xff, 0xfa, 0xff, 0xcb, 0x0b, 0xcd, 0x08, + 0xd2, 0xf2, 0x17, 0xf4, 0x30, 0x30, 0x29, 0xdd, 0xc0, 0xfa, 0xed, 0x04, 0xff, + 0xfd, 0x2c, 0x02, 0xc6, 0x09, 0x01, 0x03, 0x3b, 0x00, 0x0e, 0x01, 0xe1, 0xd8, + 0x0d, 0x2c, 0x02, 0x0c, 0xe4, 0xf6, 0x2e, 0x39, 0xe1, 0xc3, 0x33, 0xfa, 0xe0, + 0xd7, 0x17, 0x00, 0x10, 0x29, 0x2c, 0xec, 0x43, 0xfe, 0xc6, 0x19, 0xe1, 0x18, + 0x51, 0xec, 0x0e, 0x3b, 0xda, 0xf1, 0xb5, 0xd7, 0xfc, 0xb1, 0xe7, 0x4d, 0xcb, + 0xf8, 0xe1, 0xb9, 0xec, 0x09, 0xb4, 0xd5, 0x53, 0x23, 0xc5, 0x2d, 0x1b, 0xaf, + 0xd8, 0xc8, 0xf3, 0x14, 0x50, 0x03, 0xf9, 0x2d, 0x1c, 0xe0, 0x0a, 0xda, 0xd7, + 0xf4, 0x29, 0x37, 0x26, 0xec, 0xc4, 0x07, 0x17, 0x58, 0xef, 0x2f, 0xfc, 0x17, + 0x23, 0xe4, 0x55, 0x39, 0x0c, 0x32, 0x0d, 0xc1, 0x0c, 0x4a, 0x12, 0x02, 0xf7, + 0x12, 0x25, 0x03, 0xfa, 0x7f, 0x21, 0x03, 0xd2, 0x49, 0x29, 0x07, 0xa4, 0x24, + 0x11, 0xfb, 0xd2, 0x01, 0x02, 0xf7, 0x04, 0x12, 0xe0, 0x03, 0x14, 0x40, 0x11, + 0xea, 0x15, 0x03, 0x43, 0xe1, 0x23, 0xed, 0xdb, 0xe1, 0xe8, 0xe9, 0x00, 0x3e, + 0xd3, 0x6b, 0xdc, 0xe1, 0x05, 0x0a, 0xe5, 0xe8, 0xda, 0xf4, 0xcb, 0x00, 0x7f, + 0x45, 0xfc, 0x37, 0x36, 0xcd, 0x05, 0x09, 0xc8, 0x33, 0x56, 0x02, 0xd9, 0xda, + 0xfe, 0x04, 0xeb, 0x07, 0xd4, 0xdf, 0xd0, 0x07, 0xe4, 0xf7, 0x10, 0x38, 0x14, + 0xd6, 0x1b, 0x44, 0x22, 0xdf, 0xef, 0x19, 0xde, 0xf2, 0xdb, 0x04, 0x19, 0xd4, + 0x35, 0xf9, 0xd6, 0xba, 0x02, 0xe8, 0xcc, 0xec, 0x35, 0x0f, 0x2e, 0xf1, 0xf5, + 0xef, 0xdc, 0x0b, 0xcb, 0xe3, 0x16, 0x05, 0xce, 0xff, 0x07, 0xae, 0x45, 0xe9, + 0x1e, 0x0d, 0xc5, 0x33, 0x27, 0xd4, 0x21, 0x2c, 0x05, 0xed, 0xdd, 0xe6, 0xf4, + 0x29, 0xc4, 0xf0, 0xc7, 0xca, 0x21, 0x68, 0xf9, 0x09, 0x01, 0xc4, 0xf8, 0xf5, + 0x9a, 0x22, 0x0b, 0x2c, 0xf1, 0x18, 0xfa, 0x37, 0x0b, 0x03, 0x28, 0xcf, 0x05, + 0x20, 0x15, 0xe8, 0x42, 0xe7, 0xe0, 0x02, 0x98, 0xa1, 0x50, 0x1b, 0x16, 0x5a, + 0x22, 0xb6, 0x2c, 0x61, 0xea, 0xce, 0x96, 0x45, 0xfd, 0xd2, 0xfe, 0xff, 0xbd, + 0xee, 0x54, 0xff, 0xf6, 0x17, 0x20, 0xf5, 0x31, 0x22, 0xe8, 0xbd, 0xfa, 0xfc, + 0xb5, 0xe1, 0xad, 0x07, 0xe0, 0xf2, 0xf4, 0x1b, 0xb0, 0x22, 0xfd, 0x11, 0x35, + 0x38, 0xb8, 0xb9, 0xcf, 0x03, 0x2d, 0x10, 0xd8, 0x16, 0xb7, 0x04, 0x2a, 0x4f, + 0x06, 0x03, 0x1c, 0x5f, 0xfc, 0x11, 0x23, 0xe0, 0xe9, 0x33, 0x73, 0x2f, 0x40, + 0x31, 0xbe, 0x10, 0xd8, 0xd4, 0x1e, 0xea, 0xd5, 0xf4, 0x0e, 0x3c, 0x5d, 0xcb, + 0xd1, 0xef, 0x92, 0xf6, 0x2c, 0xdc, 0x03, 0x1c, 0xfa, 0x7f, 0xdd, 0xd9, 0xc0, + 0xea, 0xe6, 0xf4, 0xea, 0xf9, 0xd4, 0x01, 0xde, 0xc4, 0xfc, 0x01, 0x07, 0xd7, + 0xd3, 0xef, 0xe5, 0x1b, 0x2f, 0x29, 0x2a, 0xdb, 0x3d, 0x1a, 0xc2, 0xf7, 0xf2, + 0x12, 0xe2, 0x30, 0x3f, 0x21, 0x0d, 0xda, 0xfa, 0x0a, 0x55, 0xdd, 0xfa, 0x1f, + 0xd0, 0xfd, 0xc3, 0xfd, 0x35, 0xfb, 0x2b, 0xeb, 0xe3, 0xf9, 0x42, 0xed, 0x1a, + 0x12, 0x3a, 0x19, 0xa6, 0x4e, 0x27, 0x13, 0x1e, 0xe4, 0xf8, 0x66, 0x57, 0x70, + 0x93, 0x8a, 0xeb, 0x03, 0xb7, 0xfd, 0x64, 0x1b, 0xde, 0xfd, 0x20, 0xd2, 0x49, + 0xc8, 0x27, 0x12, 0x05, 0x24, 0x21, 0x15, 0x0e, 0x0a, 0x1a, 0xfb, 0x68, 0xcb, + 0xd1, 0x0d, 0xf3, 0xf7, 0x7f, 0x71, 0xc7, 0x0b, 0xd7, 0x35, 0xfd, 0xd0, 0xcb, + 0x1d, 0x19, 0xdc, 0x1c, 0x35, 0xe0, 0xcd, 0xfb, 0x13, 0x43, 0x32, 0x4a, 0xfa, + 0x21, 0xf8, 0x07, 0x4e, 0x1a, 0xf8, 0xe7, 0xbf, 0x06, 0xec, 0xeb, 0x29, 0x21, + 0xd4, 0x38, 0x1e, 0xd7, 0x0a, 0x81, 0xe0, 0x00, 0x12, 0xf7, 0x6b, 0xd5, 0xf9, + 0x0e, 0xee, 0x09, 0x08, 0x12, 0xee, 0x3d, 0x39, 0x0b, 0xe7, 0x12, 0x18, 0x34, + 0x19, 0x08, 0x0b, 0xfb, 0x33, 0xe2, 0x39, 0x2f, 0x01, 0xda, 0xfc, 0xde, 0x0a, + 0xfe, 0x1e, 0xf9, 0xeb, 0x2f, 0xbc, 0xed, 0xf3, 0xc1, 0x05, 0x2c, 0xea, 0xf2, + 0xfb, 0xe0, 0xf5, 0xf2, 0x11, 0x22, 0xd4, 0x67, 0x02, 0x1e, 0x14, 0xdc, 0x1b, + 0xf4, 0xc2, 0xf5, 0xcf, 0x04, 0x44, 0x36, 0xe7, 0xdd, 0xc4, 0xde, 0x10, 0xe1, + 0xf6, 0x20, 0x2f, 0x17, 0x11, 0xfe, 0xfc, 0x03, 0xd9, 0x5b, 0x16, 0xff, 0xdc, + 0xf6, 0xfb, 0xdc, 0xda, 0x0e, 0x15, 0x14, 0xfc, 0x3b, 0xe3, 0xc8, 0x6f, 0x22, + 0x9d, 0xf3, 0xf7, 0x28, 0x44, 0x0b, 0x19, 0x21, 0xf7, 0xfe, 0x0f, 0xe0, 0x36, + 0xd3, 0x32, 0xe4, 0xdf, 0x32, 0x31, 0x07, 0xdf, 0xd3, 0xe1, 0x48, 0xe6, 0xde, + 0x08, 0xda, 0xd9, 0xf2, 0x1c, 0x06, 0xbe, 0xfc, 0x19, 0xd7, 0xe8, 0x03, 0xf2, + 0x04, 0x2a, 0x06, 0x1d, 0x0b, 0x1a, 0x21, 0x20, 0x47, 0xfe, 0x32, 0xc4, 0x17, + 0x13, 0x03, 0x26, 0xc3, 0xd6, 0xff, 0xe2, 0x81, 0x2b, 0xe9, 0xfc, 0x01, 0xf0, + 0x37, 0x11, 0x16, 0xb9, 0x01, 0xf5, 0x0c, 0xdf, 0x07, 0xd6, 0xe8, 0x3d, 0xf2, + 0xeb, 0xd5, 0x09, 0xfa, 0xc6, 0xf0, 0xe5, 0xfa, 0x24, 0x0e, 0xef, 0xdc, 0x07, + 0xfb, 0x64, 0x54, 0xd4, 0xf0, 0x26, 0x5d, 0xd0, 0xd8, 0xe5, 0xe7, 0x2b, 0xe9, + 0x13, 0x1d, 0x69, 0x4c, 0x2f, 0x68, 0x18, 0xd4, 0x62, 0x31, 0x33, 0x3e, 0xf1, + 0x42, 0x25, 0x90, 0xd6, 0x6b, 0xdf, 0xef, 0xc4, 0x0d, 0x05, 0x04, 0x32, 0x20, + 0x17, 0x13, 0x0f, 0xcb, 0x09, 0x04, 0x18, 0x1f, 0x21, 0x51, 0xe9, 0xdf, 0x18, + 0xa4, 0x30, 0xfd, 0xba, 0xb9, 0xca, 0x5f, 0xe7, 0xd9, 0xc7, 0x94, 0x30, 0x23, + 0xfb, 0x1d, 0xd8, 0xf7, 0xf3, 0xb1, 0x3e, 0xfa, 0xf9, 0xcb, 0x09, 0x33, 0x34, + 0xe3, 0xf3, 0x27, 0xf6, 0xf5, 0xf7, 0xd2, 0xfa, 0xe4, 0xdf, 0xd7, 0x42, 0xca, + 0x11, 0x11, 0x2e, 0x3c, 0x12, 0x3f, 0xcf, 0x0e, 0xf4, 0xd5, 0x23, 0xf1, 0x2c, + 0x1b, 0x14, 0xdb, 0xf7, 0xfe, 0xec, 0x00, 0xc4, 0xe4, 0x01, 0x04, 0x1d, 0xe9, + 0x2c, 0xde, 0x1e, 0x28, 0xe0, 0xe9, 0x06, 0xf4, 0x34, 0xf3, 0xf5, 0xdf, 0xb1, + 0x0d, 0x20, 0xd5, 0x21, 0xf3, 0x31, 0x57, 0xfd, 0x09, 0x17, 0x2a, 0x21, 0xe3, + 0xf2, 0xf8, 0x0d, 0xcc, 0x0d, 0x45, 0x05, 0x05, 0x13, 0x05, 0x25, 0x06, 0xe5, + 0x0d, 0xd4, 0xe7, 0x1e, 0x2c, 0x1f, 0x24, 0x1f, 0xe5, 0x0f, 0x19, 0xe5, 0xfd, + 0x0b, 0xd8, 0x20, 0xd8, 0x0a, 0x30, 0x32, 0xde, 0x02, 0xc0, 0xee, 0xf5, 0x32, + 0x12, 0x7f, 0x0d, 0x0a, 0xc0, 0x01, 0x05, 0xfb, 0x05, 0x13, 0xf9, 0xf9, 0x72, + 0x09, 0x3e, 0x1f, 0xf8, 0x40, 0x28, 0x3c, 0x1a, 0x26, 0xde, 0xf6, 0xc6, 0x27, + 0x28, 0xc7, 0x28, 0x31, 0x0b, 0x28, 0x21, 0xe5, 0xd0, 0x08, 0x1e, 0x69, 0x42, + 0xf0, 0x0b, 0x21, 0x2f, 0xe3, 0xf0, 0x17, 0xd7, 0xdb, 0xc8, 0x02, 0x3b, 0x4b, + 0xe5, 0xe5, 0xe9, 0xfc, 0x0d, 0x0c, 0xf1, 0xf1, 0xd3, 0xe5, 0xc5, 0x3b, 0xd8, + 0x3d, 0xfc, 0x0f, 0x03, 0xfa, 0x1f, 0xf4, 0x1a, 0x09, 0x24, 0xf4, 0xad, 0xeb, + 0x23, 0x6a, 0xee, 0x59, 0x69, 0x1d, 0xf9, 0x3d, 0xe3, 0x11, 0x64, 0x4b, 0x15, + 0x1e, 0x7f, 0x3e, 0x14, 0x05, 0xfc, 0x0a, 0x0b, 0x70, 0xf3, 0x0f, 0x29, 0x35, + 0xec, 0x1a, 0x5b, 0x26, 0x20, 0x33, 0xb8, 0x32, 0x05, 0xf6, 0xd2, 0xfc, 0xcc, + 0x22, 0x89, 0x01, 0x43, 0x0b, 0x04, 0x41, 0x3e, 0xf6, 0x00, 0xea, 0x15, 0x2a, + 0xf1, 0xf4, 0xa8, 0x24, 0xf1, 0xe0, 0x21, 0xae, 0xd7, 0xf1, 0xe6, 0x7f, 0x51, + 0xc4, 0x46, 0x00, 0x27, 0x41, 0xb9, 0xf4, 0x20, 0xfb, 0xdf, 0xdc, 0x16, 0xfa, + 0xb7, 0xf1, 0x0c, 0x0d, 0xe2, 0x02, 0xe4, 0xf8, 0x5c, 0xfd, 0x0b, 0x25, 0xcb, + 0xb4, 0xed, 0xd8, 0x98, 0x4e, 0xf2, 0xd1, 0x00, 0x32, 0xd2, 0x45, 0x1d, 0xff, + 0x9c, 0xec, 0x65, 0x26, 0x28, 0x16, 0x32, 0x29, 0x2d, 0x11, 0x2c, 0xce, 0xef, + 0x11, 0xfe, 0xc9, 0x1e, 0xec, 0x58, 0xfd, 0x2f, 0xe8, 0xbf, 0x38, 0x4c, 0x1d, + 0x18, 0xde, 0xb2, 0xd6, 0xa0, 0xe8, 0x2c, 0xf1, 0x2f, 0xe4, 0xab, 0x61, 0x0f, + 0x36, 0xc4, 0xc3, 0x09, 0x0d, 0xd6, 0xbb, 0x03, 0xfa, 0xfd, 0x27, 0xcf, 0xc1, + 0x53, 0xdf, 0x3e, 0x02, 0x1d, 0x1e, 0xf5, 0x39, 0x0e, 0x79, 0x09, 0x13, 0xe6, + 0x47, 0xd5, 0xe8, 0x31, 0x5f, 0x03, 0x1b, 0x1a, 0x3e, 0x04, 0xfa, 0xf6, 0x41, + 0x12, 0xef, 0x5a, 0x47, 0x16, 0xed, 0xfc, 0x18, 0x11, 0x1d, 0xdc, 0xd5, 0xfd, + 0xaa, 0xc3, 0xeb, 0x3f, 0xe0, 0xcf, 0xf9, 0x41, 0xac, 0x13, 0x1c, 0x02, 0x24, + 0x1a, 0xfe, 0x81, 0x3b, 0x1a, 0x1a, 0x2a, 0xd4, 0x20, 0xdf, 0xc7, 0x37, 0xa8, + 0xe6, 0xa4, 0xdc, 0xb3, 0x17, 0xe6, 0x23, 0xd7, 0x03, 0xdb, 0xdd, 0x16, 0x14, + 0xf0, 0xf1, 0x11, 0xff, 0x4b, 0x66, 0xf4, 0x09, 0xe8, 0x00, 0x12, 0xe3, 0x12, + 0xae, 0x09, 0xbb, 0x25, 0x02, 0xd1, 0x20, 0x17, 0x05, 0x33, 0x5c, 0x34, 0xc0, + 0xb0, 0xf4, 0x0e, 0x11, 0xd9, 0xcd, 0x28, 0xbf, 0xe2, 0xfd, 0xa8, 0x05, 0xe5, + 0x1e, 0x0e, 0x0b, 0x10, 0xfd, 0x14, 0x2c, 0xd8, 0xbc, 0xcd, 0x58, 0x4d, 0xaa, + 0xc4, 0x04, 0x30, 0xea, 0x01, 0x46, 0xef, 0x60, 0x3d, 0xe8, 0x39, 0xbb, 0x21, + 0xee, 0x31, 0x41, 0xa8, 0xdc, 0x27, 0xf8, 0xe7, 0xf5, 0x0a, 0xf6, 0x3b, 0xdd, + 0xe8, 0xf8, 0xea, 0x2f, 0xc8, 0xdf, 0xe9, 0x09, 0x2a, 0x0f, 0xff, 0x06, 0x0d, + 0xdf, 0x01, 0xc4, 0xf9, 0xdc, 0x30, 0x0b, 0xe0, 0xcf, 0xf8, 0x02, 0x0c, 0xec, + 0xd6, 0x1b, 0x19, 0xee, 0xfe, 0x19, 0x0b, 0x5d, 0xd8, 0x53, 0x2b, 0xb0, 0x3f, + 0x11, 0xb5, 0xb8, 0x2f, 0xad, 0xe5, 0xfd, 0x2a, 0x00, 0xd3, 0x45, 0x0b, 0x00, + 0xba, 0xeb, 0xd1, 0x36, 0xea, 0x2f, 0x08, 0x99, 0xed, 0x7f, 0x1a, 0x2e, 0xff, + 0x29, 0x04, 0x0e, 0x1b, 0x05, 0xba, 0xd5, 0x27, 0xaf, 0xf9, 0x24, 0x5b, 0xf6, + 0x7a, 0x42, 0x12, 0xc3, 0x5c, 0xf6, 0x07, 0x21, 0x0e, 0x38, 0x15, 0x20, 0xe0, + 0xf4, 0xe5, 0xde, 0xe1, 0xc2, 0xda, 0xe0, 0xe7, 0xde, 0xcb, 0xf7, 0xfe, 0xd3, + 0x02, 0x49, 0x21, 0x02, 0x4b, 0x9d, 0x07, 0x44, 0x8f, 0x16, 0x47, 0x2b, 0xfe, + 0x17, 0x22, 0x4a, 0xff, 0xd6, 0xe7, 0x8e, 0xf7, 0x31, 0xff, 0x24, 0x17, 0x2c, + 0xdb, 0xfd, 0x4c, 0xb6, 0x40, 0xc5, 0xe6, 0x0f, 0x1f, 0xc4, 0x3c, 0xba, 0xf9, + 0x05, 0x03, 0xee, 0x09, 0x09, 0x11, 0xde, 0xfb, 0xd8, 0x06, 0xe1, 0x30, 0x0a, + 0xf5, 0x20, 0xc9, 0xd5, 0x04, 0x13, 0xe9, 0x00, 0xef, 0xfb, 0x12, 0x03, 0x09, + 0x2b, 0xbe, 0xd8, 0x02, 0x0d, 0xf4, 0x23, 0xc5, 0xfd, 0x1d, 0xe1, 0xef, 0x27, + 0xe4, 0x11, 0xcc, 0x30, 0x10, 0x36, 0xe5, 0x20, 0x1c, 0x06, 0x26, 0x1d, 0xfe, + 0x15, 0xd5, 0xe4, 0xbf, 0x18, 0xda, 0xd6, 0x10, 0x14, 0xda, 0xcb, 0xeb, 0xea, + 0x15, 0xf3, 0x08, 0x59, 0x25, 0xf5, 0x19, 0x2a, 0xf8, 0xdb, 0x00, 0x7f, 0x0c, + 0xf1, 0xe1, 0x26, 0x00, 0xfc, 0xfb, 0x05, 0xf8, 0xae, 0x05, 0xf2, 0xe5, 0xfc, + 0xf2, 0xfb, 0xfc, 0xf7, 0xf6, 0xe4, 0x17, 0x31, 0xc3, 0xf3, 0xf7, 0xd0, 0x69, + 0xef, 0xfc, 0xeb, 0x1c, 0xd0, 0xda, 0x1b, 0x09, 0x38, 0xc0, 0xfc, 0xfb, 0x03, + 0xca, 0xcf, 0x7f, 0x0b, 0xfb, 0xe1, 0xd4, 0x1d, 0xad, 0xd7, 0xe5, 0x0f, 0x12, + 0x33, 0x50, 0x01, 0x00, 0x08, 0x14, 0x30, 0x15, 0xd2, 0xdb, 0xcd, 0xe7, 0x02, + 0x2b, 0xf9, 0xfb, 0x04, 0xf9, 0x08, 0xc7, 0xca, 0xf1, 0xec, 0xd1, 0xf0, 0xde, + 0xe5, 0x0c, 0xff, 0xe9, 0x24, 0xe7, 0xfb, 0x4b, 0xc8, 0xeb, 0x2c, 0x36, 0xe1, + 0x53, 0xfb, 0xe9, 0xf3, 0xc7, 0x00, 0xe2, 0xee, 0x61, 0xea, 0x09, 0x30, 0xea, + 0xc3, 0xec, 0x0e, 0x57, 0xcd, 0xde, 0x35, 0xe4, 0xf2, 0xcd, 0x0a, 0x01, 0x56, + 0x37, 0xdc, 0xf1, 0x26, 0x0c, 0x34, 0xd2, 0x45, 0x11, 0x0e, 0xef, 0xce, 0x03, + 0xc4, 0xfd, 0x1e, 0x0e, 0xf8, 0x50, 0x07, 0x38, 0xf3, 0x00, 0x03, 0x34, 0x12, + 0xd9, 0x2b, 0x0a, 0xed, 0xdc, 0x24, 0xef, 0xcb, 0x3b, 0x10, 0x1a, 0xc9, 0xdc, + 0x28, 0x13, 0x4b, 0xd5, 0x03, 0xdb, 0xf3, 0x49, 0xff, 0xb3, 0xb3, 0xf9, 0x0a, + 0xc4, 0xf0, 0xf5, 0xf1, 0x0d, 0xda, 0x0d, 0xec, 0x0b, 0x0d, 0xdb, 0xfa, 0xcd, + 0x14, 0x0d, 0x0b, 0xce, 0x1b, 0x17, 0x01, 0xf6, 0xf1, 0x07, 0x09, 0xe4, 0x1e, + 0xe5, 0xee, 0x29, 0x10, 0xda, 0x92, 0xf1, 0x21, 0xec, 0xe5, 0x27, 0xfa, 0x14, + 0x08, 0xe8, 0x03, 0xdc, 0xfa, 0xee, 0x18, 0xeb, 0xfd, 0xf0, 0xe5, 0xf9, 0xea, + 0xf3, 0xb4, 0xff, 0xde, 0xff, 0xeb, 0xf9, 0x39, 0x03, 0x09, 0xf0, 0x0e, 0xe1, + 0xfd, 0x1c, 0x13, 0xd5, 0xff, 0xdf, 0x10, 0x10, 0x2f, 0xef, 0x08, 0x81, 0xe7, + 0xd9, 0x33, 0xe3, 0xf9, 0x2a, 0xda, 0xf7, 0xd8, 0xe1, 0xb5, 0xfb, 0x10, 0xfa, + 0xd9, 0xf1, 0xe1, 0x05, 0x0c, 0x14, 0xf3, 0x0f, 0x36, 0xfe, 0xf8, 0x26, 0x0d, + 0x05, 0x04, 0xbd, 0x2a, 0xd1, 0xf7, 0xe1, 0x08, 0xe4, 0xde, 0xfd, 0xd2, 0xe8, + 0xf1, 0x0e, 0x0d, 0x01, 0xe1, 0xdc, 0x45, 0xb3, 0x98, 0xb8, 0xe3, 0xf7, 0x05, + 0xc8, 0x19, 0xf3, 0x02, 0xe4, 0xf2, 0x13, 0xe6, 0xf8, 0xf2, 0x17, 0xc4, 0xf0, + 0xe3, 0xdc, 0x01, 0xd0, 0xe4, 0x3a, 0xcc, 0xfb, 0x04, 0x08, 0xd7, 0xfc, 0xd3, + 0x08, 0x22, 0xeb, 0x3e, 0x55, 0xa9, 0xcd, 0xf4, 0x16, 0x41, 0x17, 0x1b, 0xd4, + 0xfd, 0xfa, 0xd4, 0x4d, 0x23, 0x30, 0x42, 0x62, 0x54, 0xd9, 0xd6, 0x35, 0xf7, + 0x26, 0x65, 0x09, 0x20, 0xdb, 0x7f, 0xfa, 0xf7, 0xf4, 0x19, 0xab, 0xb5, 0x17, + 0xd4, 0x04, 0xde, 0xbd, 0xbb, 0x0b, 0x2e, 0xe8, 0x06, 0x0b, 0xf2, 0x0e, 0x0a, + 0x07, 0x21, 0x16, 0xe4, 0xda, 0x69, 0xd8, 0x1a, 0x63, 0x1d, 0xe9, 0xf3, 0xf0, + 0x09, 0xdc, 0xbf, 0xcf, 0xc9, 0x1e, 0x22, 0xdf, 0x43, 0x39, 0x20, 0x30, 0x42, + 0x20, 0xd2, 0xc3, 0x1a, 0x00, 0x1d, 0xda, 0x2b, 0x34, 0x1d, 0x18, 0xda, 0x2e, + 0xfe, 0xdc, 0x03, 0xb6, 0xee, 0x00, 0x2e, 0xe7, 0x12, 0xcd, 0xf4, 0x4d, 0x1f, + 0x19, 0x3d, 0xc9, 0xfc, 0x00, 0xfd, 0xfe, 0xf2, 0x22, 0xca, 0x2f, 0xe5, 0xff, + 0x01, 0xef, 0x2f, 0xc3, 0xf3, 0x36, 0x19, 0x31, 0x15, 0xc5, 0x07, 0x0b, 0x21, + 0x2b, 0xae, 0xe6, 0x63, 0xe4, 0x03, 0xf4, 0xe4, 0xfe, 0xd6, 0x2b, 0xdc, 0x10, + 0xfa, 0x08, 0x02, 0xd3, 0xd9, 0xc5, 0x37, 0xe4, 0x18, 0xa3, 0x45, 0xee, 0xc1, + 0xf1, 0x20, 0x03, 0xf8, 0x27, 0xfc, 0x37, 0x2e, 0x1c, 0xb2, 0xf7, 0xf4, 0xad, + 0x04, 0xb5, 0xf6, 0x11, 0x1f, 0xe2, 0x00, 0x20, 0x03, 0x0d, 0x07, 0xf7, 0x2b, + 0xf6, 0x5d, 0xc7, 0x0e, 0x55, 0xf0, 0xfc, 0x86, 0x0a, 0x4c, 0xdb, 0xfc, 0x33, + 0xa3, 0xff, 0x75, 0x26, 0x03, 0xe0, 0xc5, 0xca, 0x1d, 0x22, 0x1d, 0xed, 0xe8, + 0x96, 0x7d, 0x05, 0x3e, 0xdb, 0x4b, 0x38, 0xd3, 0x7f, 0x26, 0xfb, 0xfa, 0xf8, + 0xcc, 0x0a, 0x10, 0x40, 0x66, 0x5b, 0x27, 0x21, 0xc0, 0x0a, 0x1d, 0xeb, 0x1c, + 0x1f, 0xb9, 0xf8, 0x1f, 0xf2, 0xff, 0xc9, 0x5c, 0xd3, 0x58, 0xda, 0x02, 0xe6, + 0xdf, 0xe3, 0xf8, 0x10, 0x10, 0x37, 0xfa, 0x02, 0x58, 0xec, 0xdf, 0x28, 0xb3, + 0x40, 0xf4, 0x26, 0xd8, 0xf6, 0xad, 0x06, 0xe8, 0x0e, 0xf4, 0xa7, 0x19, 0x26, + 0xd3, 0xe5, 0x2c, 0x13, 0xa8, 0xf6, 0xbc, 0x81, 0xda, 0xea, 0xd7, 0xf9, 0xf6, + 0x60, 0x53, 0x06, 0xd8, 0xff, 0xcc, 0xf0, 0x0d, 0xe3, 0xee, 0xc0, 0xe8, 0xf8, + 0xed, 0x1f, 0x2a, 0x11, 0x26, 0xbb, 0x44, 0x07, 0x0a, 0xd9, 0xe8, 0xe6, 0x10, + 0xb8, 0x19, 0x25, 0xd6, 0xbe, 0x3d, 0x1d, 0xdd, 0xe1, 0xfd, 0xf3, 0xee, 0x38, + 0x0a, 0xe0, 0x0c, 0xeb, 0x02, 0x04, 0x00, 0x24, 0x0a, 0xdf, 0x29, 0x15, 0x0b, + 0xba, 0xf6, 0x95, 0x46, 0xc3, 0x04, 0x63, 0x4e, 0xb3, 0x12, 0xd5, 0xd5, 0x72, + 0xe1, 0xf6, 0xf1, 0x16, 0x40, 0xfd, 0xf7, 0x4e, 0x6d, 0xfc, 0xbf, 0xf2, 0xfb, + 0x18, 0x15, 0xd1, 0x00, 0x0e, 0x00, 0xea, 0xfa, 0xfd, 0x77, 0x3b, 0xe0, 0x7f, + 0xf7, 0x01, 0xf8, 0x14, 0xfc, 0x93, 0xcd, 0xcc, 0xe0, 0xe5, 0xdd, 0x03, 0xec, + 0xce, 0x1e, 0xe0, 0x1f, 0x18, 0xf9, 0xd1, 0xe5, 0xf6, 0x4c, 0xf1, 0xcb, 0x03, + 0x3a, 0xcf, 0xd7, 0xe1, 0xce, 0xc9, 0x0d, 0x37, 0xae, 0x0e, 0xd4, 0x39, 0xea, + 0xe7, 0xf2, 0xfa, 0x11, 0xf5, 0xeb, 0x17, 0xf7, 0x3b, 0x10, 0xd2, 0x32, 0x02, + 0xee, 0xe5, 0xb9, 0xf7, 0xcb, 0xfa, 0x14, 0xf7, 0x0a, 0xf3, 0x34, 0x1f, 0xf4, + 0x3c, 0xf8, 0x0b, 0xcd, 0xd3, 0x18, 0x0f, 0x21, 0x0c, 0xd8, 0xdf, 0x22, 0x09, + 0xfd, 0xdb, 0x1b, 0xe4, 0x19, 0x1e, 0x11, 0xff, 0x18, 0xbe, 0xdf, 0x26, 0x4b, + 0xe2, 0x11, 0x69, 0xfe, 0x3f, 0x26, 0x68, 0xea, 0x04, 0xae, 0xd4, 0x05, 0xfd, + 0xf9, 0x0e, 0x4e, 0xde, 0x21, 0xf0, 0x48, 0x0f, 0x2f, 0xc0, 0xc3, 0x90, 0xf6, + 0x0f, 0x1e, 0x64, 0x03, 0xb7, 0x41, 0x24, 0x7f, 0x25, 0xcd, 0xe6, 0x10, 0xdf, + 0xb9, 0xb9, 0xe3, 0xd5, 0x90, 0xc2, 0x19, 0xd9, 0x0f, 0xc5, 0xe0, 0xd6, 0x34, + 0xb5, 0xf2, 0xf6, 0x6b, 0x4e, 0x0b, 0xe1, 0xcb, 0x33, 0xf3, 0x4e, 0xf5, 0xf5, + 0xc9, 0x7b, 0xc4, 0xb6, 0xc4, 0x25, 0xc0, 0x0b, 0xc5, 0x40, 0xbb, 0x12, 0x1c, + 0x9e, 0xb5, 0x40, 0x01, 0xc3, 0x2f, 0xfc, 0x3a, 0x1a, 0xc9, 0xe0, 0xff, 0x9d, + 0x8e, 0x3e, 0xd9, 0x09, 0xc1, 0xf7, 0x12, 0xd0, 0xe3, 0x0d, 0xd9, 0xbf, 0x35, + 0x21, 0xa1, 0x8a, 0x46, 0xb7, 0xed, 0xee, 0xaa, 0xbc, 0x02, 0x13, 0x00, 0xda, + 0x51, 0x92, 0x59, 0x64, 0xfc, 0xce, 0xec, 0xd2, 0x08, 0xda, 0x22, 0xf2, 0x0d, + 0x65, 0x14, 0x06, 0x0c, 0x18, 0x4d, 0x08, 0xb8, 0xc5, 0x3b, 0x90, 0x57, 0xec, + 0xdf, 0x08, 0x32, 0xf6, 0x3a, 0x16, 0x59, 0xd1, 0x44, 0xd8, 0x03, 0x12, 0x22, + 0xe6, 0xf3, 0x1f, 0xf2, 0x16, 0x71, 0xe1, 0x0b, 0xe8, 0xeb, 0xdc, 0xdb, 0xd9, + 0x2e, 0x04, 0xe5, 0x39, 0x29, 0x5d, 0x11, 0x11, 0x18, 0x2b, 0xd5, 0xda, 0xfc, + 0x1d, 0x2b, 0x2c, 0xe6, 0xf2, 0xff, 0x0d, 0xd4, 0xfb, 0xfc, 0x66, 0x07, 0xf7, + 0x2c, 0xef, 0xf3, 0x27, 0x13, 0x0f, 0xeb, 0xdd, 0x1b, 0x9d, 0xdb, 0xf6, 0xbe, + 0xd2, 0x0f, 0xa7, 0x13, 0x41, 0x32, 0x0b, 0x1d, 0x3d, 0xd7, 0xfa, 0x1a, 0xd7, + 0xfe, 0x01, 0x0b, 0xe9, 0xd6, 0x2d, 0xfb, 0x02, 0xed, 0x12, 0xed, 0xcd, 0xd6, + 0x06, 0x7f, 0x6f, 0x01, 0x46, 0x2f, 0xf8, 0x24, 0x00, 0xa9, 0x48, 0x07, 0xff, + 0x1d, 0xe2, 0x38, 0x17, 0xf5, 0x3b, 0xfc, 0x01, 0x56, 0xbf, 0x47, 0x03, 0x19, + 0x5c, 0x16, 0x03, 0x44, 0xce, 0xe5, 0x22, 0xeb, 0xb0, 0x2a, 0x0f, 0xdb, 0x01, + 0xe0, 0x0c, 0x13, 0x18, 0xd5, 0x16, 0x57, 0x09, 0xf5, 0x4c, 0x1f, 0x3e, 0xf3, + 0xed, 0xd5, 0xfd, 0xee, 0xd8, 0xf0, 0xdd, 0xd7, 0xf9, 0x2e, 0x1d, 0xe7, 0xb3, + 0x33, 0xe1, 0x16, 0x38, 0xff, 0x17, 0x08, 0xab, 0xfa, 0xd8, 0xa7, 0xdb, 0xfa, + 0x02, 0x05, 0xb7, 0x59, 0xf0, 0xde, 0xd6, 0x12, 0xc1, 0x08, 0x00, 0x05, 0xd4, + 0xf0, 0xe7, 0x21, 0xcb, 0x0c, 0xf1, 0x34, 0x02, 0x0a, 0xfb, 0x29, 0xe4, 0xed, + 0xb9, 0xac, 0xda, 0x10, 0x2f, 0x2f, 0xf5, 0x18, 0x7f, 0xfa, 0x6f, 0x35, 0x15, + 0x4a, 0xf9, 0x20, 0x0f, 0x1e, 0x04, 0x23, 0x0c, 0x0b, 0x31, 0x3e, 0x3a, 0xfb, + 0xea, 0xfd, 0x06, 0x05, 0xd6, 0x0e, 0x13, 0x3f, 0xed, 0xf5, 0x53, 0xcc, 0xbc, + 0x21, 0xd1, 0xd8, 0x0e, 0x20, 0xc6, 0x03, 0x0d, 0x55, 0xef, 0xe7, 0xe0, 0x15, + 0xd6, 0xfb, 0x42, 0x35, 0xeb, 0x95, 0xa0, 0xd5, 0x0b, 0x07, 0x10, 0xda, 0x28, + 0x04, 0xe9, 0xdf, 0x2d, 0xed, 0x0e, 0x13, 0xc5, 0xf8, 0x09, 0xe7, 0x35, 0xc5, + 0xfc, 0x12, 0x03, 0xf9, 0xe6, 0x15, 0x03, 0xf0, 0x23, 0xe8, 0xe3, 0xed, 0xf0, + 0x10, 0xec, 0x15, 0x28, 0xf6, 0xf0, 0x1d, 0x2d, 0x2b, 0x19, 0x06, 0xf4, 0x03, + 0x1c, 0x3a, 0xe0, 0x09, 0xc6, 0xe7, 0xea, 0x24, 0xf0, 0x2a, 0x5a, 0xfb, 0xfe, + 0x13, 0x48, 0x0b, 0x14, 0xed, 0x18, 0xf5, 0xeb, 0x29, 0x24, 0xe0, 0x08, 0x3d, + 0x09, 0xc6, 0x81, 0xec, 0x29, 0xfa, 0xed, 0xe5, 0x0a, 0xfa, 0x11, 0xf9, 0xa2, + 0x1d, 0xe6, 0xf5, 0xf4, 0x05, 0xe9, 0x1d, 0x54, 0xeb, 0xcc, 0x19, 0x52, 0xea, + 0x2e, 0xf9, 0xf4, 0x04, 0x05, 0x34, 0xd2, 0x2b, 0xd6, 0x02, 0x1e, 0xfc, 0x09, + 0x07, 0x2d, 0x17, 0x3b, 0x08, 0xc2, 0x28, 0x14, 0xf0, 0x21, 0xe0, 0x20, 0xc6, + 0x40, 0xfd, 0xfb, 0x2a, 0x1f, 0xf1, 0x0b, 0x0f, 0x0f, 0x09, 0xf2, 0xf3, 0xd2, + 0x5c, 0x46, 0xdc, 0x04, 0xc8, 0x9b, 0xeb, 0xf9, 0x99, 0x33, 0xdc, 0x3a, 0x02, + 0xe1, 0xf1, 0xe6, 0xcb, 0x21, 0x0e, 0xea, 0xa8, 0x15, 0xe7, 0x41, 0xe8, 0x15, + 0xf6, 0x3f, 0x35, 0xe2, 0xe2, 0xe1, 0x44, 0x38, 0x40, 0xc1, 0xac, 0xde, 0x1f, + 0xd5, 0xd5, 0xfb, 0x01, 0x4e, 0x43, 0x2d, 0xea, 0xe4, 0xdb, 0xa9, 0xbf, 0x8b, + 0x21, 0xc2, 0x18, 0xf0, 0x30, 0x11, 0x2e, 0x11, 0xfe, 0x9d, 0xb9, 0xc2, 0x7f, + 0xbd, 0x12, 0x0f, 0x19, 0x41, 0x6f, 0xfe, 0xf9, 0xd4, 0x21, 0x0a, 0x60, 0x0b, + 0x09, 0xcb, 0xf4, 0x09, 0xe4, 0xee, 0x0e, 0x35, 0x3e, 0x08, 0x26, 0x73, 0x15, + 0x33, 0x12, 0x1b, 0xf0, 0xed, 0xdf, 0x22, 0x27, 0x0f, 0x09, 0x06, 0xc0, 0x52, + 0xfb, 0x22, 0x29, 0x39, 0x2a, 0xf6, 0xed, 0x38, 0x22, 0xe8, 0x24, 0x1e, 0xe0, + 0xbe, 0xe7, 0xec, 0x28, 0x46, 0x0f, 0x2e, 0xf6, 0x0e, 0xfb, 0xd9, 0x53, 0xef, + 0xcf, 0x18, 0x20, 0xdd, 0xb6, 0xf8, 0x3d, 0xeb, 0xd6, 0xdd, 0xe4, 0xd3, 0xd2, + 0xed, 0xdf, 0xc3, 0xd0, 0x02, 0x3b, 0xf9, 0xd7, 0xfb, 0x0f, 0xff, 0xf7, 0x19, + 0xcc, 0xfe, 0xe5, 0xe8, 0x35, 0xda, 0xf4, 0x06, 0xfc, 0x1b, 0xcd, 0xdf, 0x13, + 0xd5, 0xee, 0xdf, 0x32, 0xf6, 0x2f, 0x2c, 0xbb, 0xfc, 0xf0, 0x00, 0xe5, 0xe3, + 0x1f, 0xda, 0x10, 0xd7, 0x3d, 0x29, 0xec, 0xf0, 0xf3, 0xe9, 0x7f, 0xe3, 0xb8, + 0xdf, 0x40, 0x4e, 0xd4, 0xec, 0x1f, 0x16, 0x30, 0xe7, 0x17, 0x12, 0x0c, 0xe2, + 0xd3, 0x18, 0x04, 0x1c, 0xc8, 0x21, 0xd4, 0x11, 0xf0, 0xbd, 0xdf, 0xe1, 0xf5, + 0xd2, 0x14, 0x56, 0xeb, 0x14, 0x09, 0x04, 0xfe, 0x14, 0xfb, 0xac, 0xec, 0xc1, + 0x1e, 0x2f, 0x1e, 0xfa, 0xdd, 0x00, 0x68, 0xdd, 0xee, 0xd2, 0x31, 0x4d, 0xfe, + 0x01, 0xf3, 0x6e, 0xbc, 0xbd, 0xff, 0x0a, 0xf2, 0xc3, 0xeb, 0x12, 0xcc, 0xc2, + 0x91, 0x03, 0x0d, 0x66, 0xe2, 0xd6, 0xd3, 0xc6, 0xd1, 0xd4, 0x3c, 0xe0, 0xdb, + 0x4d, 0x0f, 0xd8, 0xa0, 0xe3, 0xd0, 0xbd, 0x01, 0x0c, 0xe6, 0xed, 0x0f, 0x3d, + 0x16, 0x26, 0x36, 0x0e, 0x0c, 0x07, 0x00, 0x68, 0x34, 0x05, 0x14, 0xf1, 0x87, + 0xea, 0x32, 0xbd, 0x5b, 0xaf, 0x42, 0x31, 0xec, 0xd4, 0x2f, 0x81, 0x65, 0x25, + 0x07, 0x3e, 0x3e, 0x30, 0x15, 0x8e, 0xcf, 0x9e, 0x13, 0xf8, 0x03, 0xc6, 0x2a, + 0x37, 0x1a, 0xfc, 0x13, 0x27, 0xe2, 0x96, 0xd2, 0x2c, 0xe6, 0xfd, 0x32, 0xca, + 0xc6, 0x1a, 0x2d, 0xa5, 0xe0, 0x05, 0xed, 0xfe, 0x2c, 0x17, 0xdb, 0x19, 0x18, + 0xf4, 0x4e, 0x10, 0xf9, 0x6b, 0x15, 0x0a, 0x30, 0x1c, 0x3e, 0x50, 0x86, 0xdf, + 0x29, 0x24, 0x13, 0xe6, 0xbe, 0x2d, 0x24, 0x1d, 0x04, 0xc5, 0xd0, 0x11, 0x1a, + 0x04, 0x04, 0xdb, 0xf6, 0xe8, 0x0f, 0x15, 0xe3, 0xc4, 0x08, 0x2d, 0xfb, 0xd7, + 0x17, 0x35, 0xc2, 0x1b, 0x23, 0xdd, 0x0f, 0x17, 0xf8, 0xf0, 0x0d, 0x1c, 0xd1, + 0x6e, 0xc5, 0xc6, 0x08, 0x13, 0xd3, 0xed, 0x56, 0x10, 0xde, 0xf5, 0x23, 0x01, + 0x06, 0x0b, 0x19, 0xee, 0xff, 0x0d, 0x5c, 0xe3, 0x07, 0x27, 0x0e, 0x35, 0xdb, + 0x14, 0xe5, 0x1f, 0x2d, 0x23, 0xf5, 0x32, 0xee, 0xc9, 0xd4, 0xe2, 0xe9, 0x18, + 0xec, 0x3b, 0xe6, 0xd0, 0x04, 0x05, 0xd9, 0xff, 0xa8, 0xf0, 0xcc, 0xd2, 0xed, + 0x09, 0x00, 0xf6, 0xeb, 0xec, 0xbe, 0x0d, 0x20, 0xf7, 0x40, 0x22, 0x0f, 0x08, + 0x30, 0xd5, 0x28, 0xb1, 0x1f, 0x1b, 0x15, 0x09, 0xf1, 0x0b, 0xd4, 0xd1, 0x17, + 0x81, 0x15, 0x01, 0x2a, 0x03, 0x3d, 0xe0, 0xce, 0x1a, 0x37, 0xd6, 0xb6, 0x14, + 0xe5, 0xe3, 0xbe, 0x18, 0xee, 0x27, 0xe0, 0xff, 0xc5, 0xf6, 0xea, 0xcb, 0x5a, + 0xdf, 0xf0, 0x49, 0xc1, 0xe9, 0xdc, 0xab, 0x3d, 0x0d, 0x17, 0xf8, 0x1c, 0xdb, + 0x02, 0xcf, 0x24, 0xe7, 0x16, 0xee, 0x20, 0x06, 0x13, 0x39, 0x30, 0x19, 0xd0, + 0xb6, 0x25, 0x01, 0xe8, 0x62, 0xc8, 0x00, 0xd5, 0x5b, 0xf5, 0x16, 0xec, 0x16, + 0x04, 0x55, 0x28, 0xf3, 0xdb, 0xde, 0xea, 0x40, 0xe1, 0x4c, 0x33, 0xca, 0xdd, + 0x0d, 0x21, 0xfc, 0x00, 0x41, 0x23, 0xec, 0x3d, 0xe0, 0xdf, 0xd2, 0x1b, 0x4b, + 0x38, 0xfd, 0xd2, 0xf1, 0xc9, 0x95, 0xfe, 0x55, 0xea, 0xdc, 0xfd, 0xcc, 0x37, + 0x26, 0x24, 0x28, 0xf3, 0x49, 0xd4, 0xdb, 0x25, 0xdf, 0x11, 0x13, 0x24, 0x19, + 0x04, 0x4e, 0x14, 0xc7, 0x0c, 0xfb, 0x0c, 0x26, 0x13, 0xf0, 0x05, 0x16, 0x81, + 0xa2, 0x22, 0xf5, 0xf9, 0xe1, 0x11, 0xc7, 0xea, 0xf4, 0xec, 0xf2, 0x1d, 0x1d, + 0x33, 0x34, 0x55, 0xaf, 0x06, 0x2d, 0xde, 0x90, 0xc1, 0x4c, 0x0a, 0x07, 0xc5, + 0xfa, 0x6f, 0x2c, 0xdf, 0x40, 0x06, 0xe6, 0xff, 0x27, 0x18, 0xab, 0x60, 0x7f, + 0xf0, 0x55, 0xf7, 0x9b, 0xdf, 0xc7, 0xe3, 0x19, 0xed, 0x20, 0xa5, 0xfe, 0xfa, + 0xdd, 0xd7, 0x0b, 0xe1, 0x7c, 0x38, 0xea, 0x00, 0x1e, 0xea, 0xd4, 0x12, 0xba, + 0xe7, 0xa3, 0x23, 0xbd, 0x5b, 0x04, 0x24, 0x3f, 0xe0, 0xbc, 0x13, 0x19, 0xf6, + 0xf4, 0xeb, 0xeb, 0x0d, 0x58, 0x52, 0x2b, 0x0d, 0x3b, 0x1f, 0xfa, 0xdf, 0xfb, + 0xb2, 0xc3, 0xe2, 0x58, 0xb0, 0xf4, 0xd2, 0xdf, 0xe5, 0xe9, 0xf9, 0xc5, 0xda, + 0xcf, 0x48, 0x0c, 0xdb, 0xe4, 0xcf, 0xd6, 0x2f, 0x2d, 0xea, 0x38, 0x34, 0x17, + 0xfd, 0x3a, 0xe9, 0xce, 0x1b, 0x00, 0x29, 0x13, 0xc4, 0xe6, 0xef, 0xc8, 0x1d, + 0xdd, 0x3f, 0x0a, 0x2a, 0xc4, 0x05, 0x0e, 0x43, 0xdb, 0xea, 0xf1, 0xe9, 0xb1, + 0x53, 0xea, 0xa5, 0x11, 0xf7, 0x2a, 0x17, 0xb4, 0x06, 0xda, 0xcc, 0xe9, 0x09, + 0xcc, 0xe2, 0x81, 0x39, 0xd4, 0xdd, 0xf6, 0x06, 0x06, 0x9c, 0xd7, 0x20, 0x60, + 0xe6, 0x2d, 0xea, 0xc8, 0x42, 0xd4, 0x26, 0xf3, 0x20, 0x18, 0xf0, 0x37, 0x56, + 0xcc, 0xe3, 0x50, 0xe8, 0xef, 0x2e, 0xe2, 0x46, 0xdd, 0x68, 0xe2, 0xfe, 0x07, + 0xa6, 0x98, 0xed, 0x4e, 0xd6, 0xe2, 0x9f, 0xd3, 0x5f, 0xc9, 0xd5, 0x1f, 0xc9, + 0x09, 0xd5, 0xa8, 0x06, 0xfe, 0xe1, 0xe1, 0xc2, 0x70, 0x25, 0xf1, 0xc4, 0x42, + 0x3c, 0x57, 0xa9, 0xce, 0xea, 0x17, 0x3f, 0x00, 0xdc, 0x1b, 0xdc, 0xd0, 0xf8, + 0xb7, 0xfe, 0xd5, 0x00, 0xcd, 0xe7, 0xe9, 0xcd, 0xbf, 0x0b, 0x46, 0x1f, 0xe4, + 0x32, 0xde, 0xbc, 0x19, 0x18, 0xd7, 0x20, 0xd2, 0xf2, 0x39, 0x4d, 0x30, 0x26, + 0x41, 0xec, 0xcd, 0xc8, 0x10, 0xeb, 0xcf, 0xe3, 0xdd, 0xeb, 0x2a, 0xfd, 0x3c, + 0x2b, 0x8e, 0xe5, 0xfa, 0xc9, 0xf0, 0x08, 0x19, 0xb0, 0xb9, 0xeb, 0x1e, 0xd0, + 0xfb, 0xf9, 0xce, 0x12, 0x50, 0x31, 0xcb, 0x5b, 0xae, 0xf5, 0xf4, 0xec, 0x08, + 0xcd, 0x37, 0xdf, 0x1b, 0xfa, 0x0d, 0xf5, 0xf4, 0xf8, 0xb2, 0xff, 0xd8, 0x3f, + 0xe6, 0xcc, 0x0c, 0xeb, 0xf3, 0x28, 0xee, 0x01, 0xf2, 0x14, 0x81, 0x22, 0x0d, + 0xfb, 0x00, 0xf0, 0xe1, 0x2b, 0xee, 0x1a, 0xec, 0xf5, 0x0b, 0xe9, 0xb6, 0x0e, + 0xdf, 0xc6, 0x21, 0x11, 0xfd, 0xdf, 0xd2, 0x15, 0xf9, 0x17, 0xf6, 0x2d, 0xfd, + 0xf9, 0xda, 0x02, 0xcf, 0x16, 0xff, 0x0e, 0x11, 0x20, 0x55, 0x29, 0xdd, 0xd1, + 0x62, 0xc9, 0xfd, 0xb5, 0x26, 0x1e, 0xc1, 0x0b, 0x22, 0xf7, 0x19, 0x0e, 0x11, + 0x08, 0xa6, 0x14, 0x02, 0xe1, 0xf8, 0xd4, 0xc8, 0x16, 0xd2, 0xf2, 0xee, 0xf2, + 0xb0, 0x05, 0xf1, 0xf9, 0x0c, 0xc1, 0x09, 0x1a, 0x0b, 0xf2, 0x45, 0xf3, 0x74, + 0xdb, 0x0e, 0x0d, 0xda, 0xf1, 0xd2, 0x19, 0xdf, 0xf4, 0xd9, 0xad, 0xf5, 0x0b, + 0x2d, 0x1a, 0xda, 0x17, 0xfd, 0x0f, 0x2f, 0x2a, 0x1a, 0xf0, 0xea, 0x06, 0xc0, + 0x00, 0x2a, 0x56, 0x0d, 0x65, 0xad, 0x37, 0xd8, 0xfa, 0xde, 0xae, 0xe8, 0x14, + 0xf2, 0xec, 0xf2, 0x23, 0x13, 0x2f, 0xcd, 0xec, 0x09, 0xf0, 0xa5, 0xee, 0x0a, + 0xee, 0xfa, 0xe0, 0xb2, 0x0f, 0xd6, 0x2a, 0x40, 0xff, 0x0d, 0xe0, 0x0a, 0xdd, + 0x1c, 0x09, 0x62, 0x07, 0x47, 0x08, 0xf9, 0xec, 0xa0, 0xbf, 0x30, 0x04, 0x10, + 0xdd, 0x39, 0x34, 0x7f, 0x1a, 0x18, 0x41, 0xc4, 0xe5, 0xf4, 0x34, 0x4d, 0xf8, + 0xde, 0xfa, 0x1d, 0x2e, 0x19, 0xff, 0xec, 0x1f, 0xff, 0xea, 0xfd, 0x0b, 0x0a, + 0x0b, 0x2d, 0x1d, 0xc5, 0xd0, 0xda, 0xe7, 0xd4, 0x3e, 0x3a, 0xff, 0x14, 0x1c, + 0xc9, 0x92, 0x21, 0x17, 0xe4, 0xfc, 0xd4, 0xc1, 0x6b, 0xe1, 0xf4, 0xd0, 0x08, + 0xc6, 0xdd, 0x5d, 0xc6, 0x61, 0x62, 0x16, 0x2a, 0xd8, 0xcd, 0x21, 0x19, 0xe0, + 0xd4, 0x1d, 0x41, 0xde, 0xdd, 0x10, 0x1d, 0x08, 0x37, 0x57, 0x06, 0x0d, 0xe9, + 0x0f, 0x67, 0x8e, 0x29, 0xf8, 0xd8, 0xba, 0xf7, 0xb9, 0xde, 0xfa, 0xaa, 0x07, + 0xa1, 0x07, 0xda, 0x02, 0x00, 0xf6, 0x18, 0x09, 0xe8, 0x1b, 0x1d, 0x07, 0x07, + 0x20, 0x54, 0xd3, 0x00, 0xc6, 0x4b, 0xb4, 0x41, 0xfb, 0xee, 0xf7, 0xf1, 0xdd, + 0xdf, 0xf7, 0x0e, 0x31, 0xc4, 0x39, 0x0e, 0x00, 0xcd, 0x06, 0xd5, 0x18, 0x1a, + 0x01, 0xf5, 0x17, 0x81, 0x3d, 0x3e, 0xd9, 0x1a, 0x3c, 0x0b, 0xf2, 0x45, 0x0d, + 0xa6, 0xd2, 0x1a, 0xb9, 0x4e, 0x0b, 0xcb, 0x3c, 0xeb, 0xfd, 0x28, 0xdc, 0xc6, + 0x12, 0xa4, 0xe5, 0xe4, 0xdd, 0xae, 0xa7, 0xe3, 0xd4, 0xe3, 0x20, 0xb9, 0xc2, + 0x01, 0x0b, 0xd4, 0x11, 0xe3, 0x44, 0xdd, 0xee, 0xcc, 0xf0, 0xb5, 0x1c, 0xf9, + 0x04, 0x52, 0xc3, 0x39, 0xf8, 0xeb, 0x03, 0x75, 0xf4, 0x17, 0x32, 0x25, 0x31, + 0xc0, 0x25, 0xf6, 0xfc, 0x58, 0xe8, 0xcf, 0xe7, 0x1e, 0xe7, 0x23, 0x04, 0x30, + 0x12, 0x1e, 0xec, 0xd6, 0x11, 0x37, 0x12, 0xdd, 0x23, 0xc4, 0xfe, 0x00, 0x05, + 0x02, 0xfc, 0xbb, 0xf4, 0xea, 0x01, 0x1c, 0x37, 0xe6, 0xd5, 0x52, 0x05, 0x13, + 0x31, 0xf7, 0xde, 0x10, 0xe9, 0xdd, 0xf2, 0xef, 0xdc, 0x01, 0x0d, 0xc9, 0x5f, + 0x09, 0xdd, 0x2f, 0x15, 0xdb, 0xe7, 0xf9, 0x97, 0x50, 0x0e, 0xf0, 0x60, 0xdd, + 0x4b, 0x54, 0xeb, 0x02, 0x1d, 0xf6, 0x1a, 0x24, 0xc4, 0xd9, 0x0f, 0x26, 0x91, + 0x7f, 0xdc, 0xf8, 0xf6, 0x3c, 0x4f, 0x32, 0x11, 0xf7, 0x3d, 0x1a, 0x26, 0xf0, + 0x0b, 0x17, 0xfa, 0xd5, 0xe2, 0x04, 0x15, 0xf3, 0xe9, 0xff, 0xba, 0xf9, 0x28, + 0xe9, 0xe9, 0xe8, 0x0a, 0xf3, 0x1f, 0x42, 0xdc, 0x0b, 0x0a, 0x08, 0x3f, 0xf5, + 0x01, 0x30, 0x10, 0xce, 0x93, 0xc9, 0x11, 0x13, 0xd9, 0xf0, 0xc2, 0xb7, 0xeb, + 0x0c, 0x0a, 0xde, 0xe3, 0x1e, 0x75, 0xc7, 0x3b, 0x32, 0xf5, 0x28, 0x1e, 0x26, + 0xf0, 0x4e, 0xfe, 0xa7, 0xeb, 0xd1, 0xf6, 0xa6, 0xf1, 0xdd, 0x2c, 0x06, 0x3c, + 0x25, 0xfc, 0x62, 0x30, 0xa0, 0x0c, 0xe2, 0x94, 0xca, 0xa4, 0x1c, 0xd7, 0xc4, + 0x32, 0x11, 0xc0, 0xe3, 0xe9, 0xce, 0xee, 0xf7, 0x02, 0x7f, 0xf3, 0xd9, 0xe1, + 0xe3, 0x46, 0x57, 0xe7, 0xa9, 0xaf, 0x14, 0x0d, 0x1a, 0x0a, 0xc3, 0xfc, 0xc8, + 0xfc, 0x18, 0xc7, 0xde, 0x17, 0x00, 0xd7, 0x59, 0x17, 0xe2, 0xed, 0x3d, 0x9e, + 0x6a, 0x1c, 0x39, 0x18, 0x43, 0x0b, 0x0f, 0xd9, 0xab, 0xed, 0x13, 0x41, 0x11, + 0xcd, 0xe4, 0x60, 0xeb, 0xee, 0xb1, 0x02, 0xe9, 0x0a, 0x05, 0xee, 0x29, 0xe5, + 0xfc, 0xe3, 0xb5, 0xd4, 0xb2, 0x0f, 0xd9, 0xf7, 0xf8, 0xf6, 0x01, 0xf5, 0xfd, + 0xf5, 0x0b, 0xe9, 0xd7, 0x10, 0x0a, 0xca, 0xd8, 0xd7, 0xf4, 0xc7, 0x12, 0xe7, + 0x34, 0xd5, 0xf9, 0xeb, 0xff, 0x1b, 0x12, 0xe7, 0xd4, 0xc3, 0xee, 0xec, 0x4d, + 0x22, 0xf2, 0xe6, 0x37, 0x1b, 0xc5, 0x06, 0x2d, 0x03, 0xd2, 0xcf, 0x0f, 0xfe, + 0x20, 0xef, 0xe1, 0x17, 0xf1, 0xdf, 0x08, 0x3b, 0xd8, 0xd8, 0x03, 0xfd, 0x2e, + 0xdf, 0x4c, 0xed, 0xb9, 0x10, 0xe3, 0xdc, 0x19, 0xff, 0xdf, 0xf5, 0x05, 0x42, + 0xb1, 0x92, 0x87, 0xd0, 0xf6, 0xe7, 0xec, 0xe7, 0xf5, 0xd0, 0xdb, 0xd5, 0xe0, + 0xc9, 0xc9, 0xf9, 0xc1, 0x16, 0xfd, 0x65, 0xeb, 0x18, 0xfc, 0xeb, 0x01, 0x07, + 0x05, 0xe9, 0x05, 0xdc, 0x18, 0xee, 0xe7, 0x3f, 0xf9, 0x23, 0x16, 0x06, 0x20, + 0xfd, 0x01, 0x0d, 0x00, 0xde, 0xfb, 0xe4, 0x27, 0xea, 0xca, 0xbb, 0xe3, 0x0a, + 0xd8, 0x27, 0x81, 0xed, 0x14, 0x1a, 0xfa, 0x15, 0x8f, 0x1d, 0xf2, 0xed, 0xf3, + 0x65, 0xe6, 0x1c, 0x52, 0xd7, 0x2b, 0xe5, 0x10, 0xaf, 0x30, 0x4b, 0xd2, 0xfd, + 0x2a, 0x22, 0x2b, 0x34, 0xe6, 0xeb, 0x07, 0x37, 0xe9, 0x1b, 0x70, 0x06, 0xe1, + 0xe5, 0x02, 0x02, 0xd9, 0x03, 0x07, 0x05, 0x19, 0xfd, 0xf4, 0xe0, 0xad, 0x07, + 0xf8, 0x2f, 0x08, 0x1c, 0x1a, 0x1e, 0xfb, 0xef, 0xf4, 0xcd, 0x00, 0x10, 0xff, + 0x1a, 0x05, 0xb1, 0xb8, 0xd7, 0x08, 0x90, 0xe7, 0xc2, 0xf6, 0xcb, 0x10, 0xce, + 0x9f, 0x91, 0x0e, 0xbc, 0x3d, 0xbb, 0xd8, 0xc9, 0xe9, 0xf7, 0xc3, 0xf8, 0x2f, + 0x09, 0xaa, 0x01, 0x20, 0xe0, 0x3b, 0x04, 0x7f, 0x5c, 0xd7, 0x11, 0x38, 0x06, + 0xe7, 0x25, 0x0f, 0x9d, 0x2f, 0x2c, 0xea, 0x32, 0x3f, 0x21, 0x1b, 0x01, 0xb4, + 0xe3, 0xf3, 0x6a, 0xce, 0xf6, 0x19, 0xbd, 0xe7, 0x0d, 0xec, 0xc8, 0xba, 0x9a, + 0x1e, 0x41, 0x18, 0x29, 0x28, 0x03, 0xef, 0x07, 0xe7, 0xf4, 0xce, 0xf5, 0xed, + 0xcb, 0x3c, 0xdd, 0x05, 0x02, 0xe1, 0x00, 0xf7, 0x14, 0x25, 0x23, 0x06, 0xe6, + 0x33, 0x13, 0x0c, 0xe4, 0xc8, 0x7f, 0xc4, 0xf8, 0x15, 0x18, 0x0b, 0xe9, 0xed, + 0x36, 0x39, 0xfe, 0xfa, 0x0c, 0x20, 0x47, 0xe2, 0x00, 0x32, 0xcc, 0xc3, 0xf3, + 0x2d, 0xef, 0x04, 0x05, 0xb6, 0x03, 0xea, 0xc4, 0xfc, 0xf7, 0xe4, 0xfe, 0xfd, + 0xfd, 0x10, 0x05, 0x0f, 0xee, 0x0d, 0x2b, 0x18, 0xe2, 0xe8, 0x17, 0xfc, 0x24, + 0xf0, 0xec, 0x1f, 0xd1, 0xa1, 0x07, 0xfb, 0x13, 0x09, 0x00, 0x00, 0x02, 0xfb, + 0x10, 0x0a, 0x27, 0x04, 0xf3, 0xf6, 0xee, 0xf5, 0x04, 0x46, 0x08, 0x07, 0xf7, + 0x0d, 0x02, 0x01, 0x20, 0x1b, 0xfc, 0x24, 0x28, 0xc9, 0x02, 0x01, 0x12, 0xe9, + 0xf8, 0x17, 0x58, 0x0f, 0xfa, 0x28, 0xed, 0xfb, 0x16, 0xc0, 0xfe, 0xd8, 0xfb, + 0x1e, 0x2e, 0xeb, 0x23, 0x7f, 0x06, 0xfc, 0x01, 0x25, 0x38, 0xcd, 0x2b, 0xed, + 0xf4, 0x1d, 0x00, 0x28, 0xe4, 0x62, 0x0e, 0x03, 0x1c, 0xc4, 0x1e, 0xce, 0xe2, + 0x0d, 0xeb, 0xf3, 0x1e, 0xfe, 0xff, 0x7a, 0x32, 0xdd, 0xb6, 0xda, 0x09, 0x3e, + 0xf1, 0xc3, 0x1b, 0x37, 0x0a, 0x13, 0xe0, 0x11, 0x22, 0xef, 0xe6, 0xfe, 0xdc, + 0xf1, 0x04, 0xbb, 0xfe, 0xe5, 0x97, 0xc8, 0x2a, 0x9d, 0xcf, 0x11, 0xea, 0xf0, + 0xfe, 0x24, 0x08, 0xb9, 0x07, 0xf4, 0x18, 0x44, 0xea, 0x36, 0x09, 0x2a, 0xfa, + 0x42, 0x5f, 0x9c, 0xe1, 0xf0, 0x06, 0x22, 0x4d, 0xaf, 0xfb, 0xfb, 0x07, 0xe5, + 0xfd, 0xf4, 0xc8, 0xe8, 0x0f, 0x0b, 0x0f, 0x52, 0x4b, 0x26, 0xfb, 0x0e, 0x31, + 0x2e, 0xdf, 0xe3, 0x31, 0x22, 0x31, 0xcd, 0x33, 0x19, 0x00, 0x06, 0x01, 0xb8, + 0xee, 0x09, 0xf7, 0x08, 0xe1, 0xd7, 0xfe, 0xf8, 0xc4, 0x38, 0xf7, 0xfc, 0xd4, + 0xe0, 0x04, 0x1a, 0x1d, 0x33, 0x12, 0x05, 0xb7, 0xd9, 0x65, 0xee, 0x1c, 0x15, + 0xe8, 0x31, 0xc9, 0xc8, 0x1a, 0x1a, 0xfd, 0x23, 0x2a, 0xe7, 0xf4, 0xc1, 0x39, + 0xd2, 0xaa, 0xd2, 0xf7, 0xe1, 0x21, 0xe6, 0x1f, 0xe4, 0x32, 0x16, 0x11, 0xbd, + 0x1b, 0x98, 0x2d, 0x0a, 0x24, 0x0c, 0x6d, 0x6a, 0xdd, 0x00, 0x23, 0x3c, 0xbb, + 0x58, 0xc9, 0x0e, 0xd6, 0xec, 0xdc, 0xc8, 0xa1, 0x2d, 0xea, 0x3a, 0xff, 0x01, + 0x99, 0xd0, 0xc0, 0x7f, 0xfc, 0x89, 0x9f, 0x2d, 0x2e, 0xf3, 0xb0, 0x2a, 0x01, + 0x1a, 0xc0, 0xde, 0x39, 0xe2, 0xe6, 0xda, 0xc5, 0x51, 0x20, 0xf9, 0x4b, 0x05, + 0xf2, 0xe2, 0xe1, 0x17, 0xbb, 0x3c, 0xff, 0xd1, 0xd4, 0x13, 0xed, 0x25, 0x1c, + 0xe6, 0x02, 0x1e, 0xf5, 0x02, 0x21, 0x27, 0xbb, 0x32, 0x06, 0xa7, 0xe5, 0xef, + 0x06, 0xbc, 0x70, 0xff, 0x17, 0x4c, 0x1e, 0xd3, 0xef, 0x17, 0xe5, 0xf4, 0x00, + 0x6a, 0x0d, 0x0e, 0x0e, 0x51, 0x03, 0xe6, 0x24, 0xf0, 0xfa, 0xee, 0x38, 0x04, + 0x62, 0x12, 0x3a, 0xde, 0x1c, 0x11, 0x5a, 0xdf, 0xe0, 0x31, 0xe6, 0xc6, 0xe3, + 0xe8, 0x51, 0xe4, 0xc4, 0xf9, 0x19, 0xf3, 0xf1, 0x53, 0x07, 0xdf, 0x25, 0x2e, + 0x10, 0xda, 0x1f, 0xb4, 0xed, 0xfd, 0xf6, 0xfb, 0x0d, 0xc1, 0x1d, 0xdd, 0xd9, + 0x27, 0xbe, 0xbc, 0x39, 0xbb, 0x11, 0xcc, 0xe2, 0xcf, 0x34, 0x00, 0x34, 0x13, + 0xe8, 0x1f, 0x11, 0x81, 0x07, 0xb0, 0x32, 0x01, 0x22, 0x07, 0xc3, 0x0a, 0x0a, + 0xfd, 0x1c, 0x34, 0x4b, 0xd4, 0xfe, 0x05, 0xab, 0x0c, 0xcf, 0x07, 0x14, 0xd1, + 0x29, 0xf3, 0xf4, 0xb6, 0xd5, 0x54, 0xf5, 0x07, 0x70, 0xfb, 0xfa, 0xe3, 0xcc, + 0x12, 0xe6, 0xfd, 0x34, 0xac, 0x00, 0xf9, 0x03, 0x48, 0x3c, 0xce, 0xbe, 0x12, + 0xe4, 0xc7, 0x04, 0x1f, 0xe3, 0x0d, 0xd9, 0x32, 0xf5, 0x48, 0x04, 0x4f, 0xf7, + 0xeb, 0x2e, 0x34, 0x18, 0x2e, 0xef, 0x15, 0x02, 0x04, 0x16, 0xbb, 0xe3, 0xdd, + 0x16, 0x18, 0xfa, 0xee, 0xe0, 0xf7, 0x28, 0x22, 0x07, 0x0c, 0x0f, 0x37, 0xe5, + 0xf2, 0xdd, 0xe3, 0xfd, 0xfb, 0xcc, 0x7c, 0xf2, 0x1d, 0xf5, 0x2d, 0x08, 0xd3, + 0xc0, 0xdb, 0xeb, 0x09, 0x0f, 0xf3, 0x08, 0x03, 0xed, 0x1e, 0x02, 0x1a, 0x42, + 0xd9, 0xf4, 0x0c, 0xfe, 0xf1, 0xe7, 0xf1, 0x15, 0x0f, 0x11, 0xc7, 0xf5, 0xc4, + 0x01, 0xf4, 0x04, 0xe0, 0x13, 0xbf, 0xd2, 0x0d, 0x40, 0xec, 0x2a, 0x21, 0xdb, + 0x5a, 0x0d, 0x5b, 0xb5, 0x17, 0xf3, 0xf3, 0x15, 0xfd, 0xea, 0xf7, 0xdd, 0x10, + 0x07, 0xfd, 0x36, 0x7f, 0xb2, 0xf6, 0x28, 0x19, 0xff, 0xc0, 0x03, 0x16, 0x17, + 0xec, 0x03, 0xec, 0xdf, 0xc7, 0xf8, 0xe8, 0xc3, 0x03, 0x2b, 0x08, 0xef, 0x0c, + 0x18, 0x22, 0xf7, 0x2b, 0xe5, 0xde, 0x9f, 0x11, 0x20, 0x0f, 0x32, 0xbd, 0xfe, + 0x1d, 0x13, 0xac, 0x3d, 0xf7, 0xdd, 0x54, 0x09, 0x5a, 0x45, 0xd1, 0x10, 0xf6, + 0x19, 0xe1, 0x07, 0x6d, 0xda, 0xf8, 0xc5, 0x17, 0x13, 0xf7, 0xb8, 0x03, 0x27, + 0xee, 0x1c, 0xc9, 0xed, 0x58, 0xdc, 0xcb, 0x12, 0x04, 0x00, 0xee, 0xda, 0xfc, + 0xfd, 0xe8, 0x00, 0xfb, 0x06, 0x23, 0xf6, 0x1d, 0xf8, 0x2b, 0xe0, 0x1e, 0x41, + 0xe4, 0xd1, 0x7f, 0x06, 0x0f, 0xf8, 0xcb, 0x33, 0x09, 0x32, 0xec, 0x23, 0xfb, + 0xf0, 0x19, 0x05, 0x17, 0xf1, 0x2a, 0x11, 0xba, 0xbc, 0xd9, 0xea, 0xf0, 0xdf, + 0x4e, 0xff, 0x1a, 0xf2, 0x12, 0x1f, 0xe9, 0xf6, 0xd6, 0x1b, 0xa9, 0xfc, 0xf3, + 0xd2, 0xc1, 0x17, 0x17, 0xe7, 0x0e, 0x13, 0xf1, 0xff, 0x21, 0xe7, 0xf8, 0xd8, + 0xf3, 0xbe, 0x3d, 0xd3, 0x9b, 0xf7, 0x2b, 0x2f, 0xe4, 0xae, 0x56, 0xd6, 0x20, + 0xd3, 0x14, 0xcf, 0x25, 0xd4, 0xd8, 0x07, 0x81, 0xee, 0x24, 0x01, 0x1a, 0x0c, + 0xd4, 0xc5, 0xf9, 0x09, 0xeb, 0xf9, 0xd4, 0xcd, 0xe3, 0x07, 0x0c, 0xd5, 0x08, + 0x03, 0xfc, 0xea, 0x0f, 0x10, 0x00, 0x4e, 0xee, 0x23, 0xda, 0xca, 0xce, 0xff, + 0x09, 0xea, 0x26, 0xd2, 0x2a, 0x06, 0xd9, 0xf5, 0x04, 0x01, 0xdc, 0xf9, 0xf9, + 0x6b, 0x01, 0xeb, 0xfe, 0x09, 0x05, 0xef, 0xd0, 0x30, 0xe8, 0xf4, 0xfa, 0xed, + 0x03, 0x29, 0xc6, 0x00, 0xe2, 0xd0, 0xf5, 0xb9, 0xf9, 0x09, 0xb3, 0xf5, 0xd7, + 0xeb, 0xee, 0x24, 0x2f, 0xf6, 0x05, 0x05, 0xfe, 0x09, 0xd7, 0xcb, 0x4a, 0xea, + 0x36, 0x17, 0xeb, 0xd0, 0x14, 0xee, 0x12, 0xb8, 0xe0, 0x0a, 0x21, 0xe8, 0x1c, + 0x13, 0x07, 0x08, 0xf2, 0x39, 0xe5, 0x0a, 0x0e, 0x4e, 0x3f, 0x2d, 0x0e, 0x11, + 0xb3, 0xdf, 0xe7, 0xf3, 0xe8, 0x0a, 0xfd, 0x19, 0x29, 0x2c, 0x2d, 0xef, 0x3f, + 0xf6, 0x51, 0x2f, 0xf8, 0x1c, 0xea, 0x1c, 0x6a, 0x3a, 0x40, 0xcf, 0x49, 0xfc, + 0x2d, 0x11, 0xd4, 0x42, 0x2b, 0x1c, 0xde, 0xfa, 0x1b, 0x2f, 0xee, 0x24, 0xfd, + 0x21, 0xff, 0x0f, 0x24, 0xe8, 0x25, 0xb6, 0xd8, 0xe0, 0xef, 0xdb, 0x25, 0xb4, + 0xc4, 0xfc, 0xb5, 0x34, 0x2f, 0x58, 0xfe, 0x3a, 0xe4, 0x1d, 0x7a, 0x3e, 0xf0, + 0x33, 0x20, 0xf2, 0x11, 0xea, 0xd6, 0xec, 0xd9, 0xa0, 0x36, 0xb9, 0x01, 0xdc, + 0x14, 0x07, 0x32, 0xc3, 0x50, 0x7f, 0x14, 0x53, 0x50, 0x11, 0xd8, 0x62, 0xe7, + 0xfa, 0x00, 0x4b, 0xe6, 0x15, 0x3b, 0x20, 0x1d, 0x27, 0xfc, 0x9f, 0x01, 0x50, + 0x15, 0x0a, 0x59, 0x60, 0x37, 0x44, 0xd3, 0xf6, 0x1c, 0xfd, 0x13, 0x02, 0x0c, + 0x3d, 0x04, 0xc2, 0xdd, 0x39, 0x1e, 0x3a, 0xbc, 0xf9, 0xcb, 0xf9, 0x20, 0x0d, + 0xdd, 0xcc, 0xfd, 0x27, 0x0c, 0xf2, 0xfa, 0x30, 0x17, 0x9a, 0xa7, 0xf6, 0xc5, + 0x0a, 0x3c, 0x22, 0xca, 0xe6, 0x17, 0x09, 0xbc, 0x5f, 0xc4, 0x22, 0xb0, 0xfe, + 0x60, 0xfb, 0x61, 0xc6, 0x0b, 0x10, 0xdb, 0xed, 0x0f, 0x4c, 0x4d, 0xf5, 0xf0, + 0xe2, 0x1a, 0xfc, 0x07, 0xe2, 0xd5, 0x29, 0x01, 0x4e, 0x08, 0xba, 0xf7, 0x05, + 0xdb, 0x13, 0x02, 0x06, 0x0b, 0x32, 0x57, 0xc0, 0x23, 0x01, 0xd8, 0x25, 0x3c, + 0x43, 0x37, 0x09, 0x36, 0x1d, 0x1d, 0x69, 0x70, 0x03, 0xb2, 0x4e, 0xea, 0xf9, + 0xce, 0x10, 0xe9, 0x7f, 0xd5, 0xe5, 0x09, 0x4a, 0xd4, 0x82, 0x43, 0x21, 0x13, + 0x9d, 0x83, 0x32, 0x11, 0xf5, 0x2f, 0xcc, 0xd9, 0xfb, 0xb6, 0x6b, 0x09, 0x4c, + 0x65, 0x30, 0xae, 0x02, 0x1e, 0x06, 0xfb, 0xc5, 0xa6, 0xbc, 0xbe, 0xf1, 0x10, + 0x27, 0xd3, 0x66, 0xc6, 0x1b, 0x08, 0x16, 0xd3, 0x11, 0xe7, 0xef, 0xf5, 0x58, + 0x1b, 0xe6, 0xaf, 0x18, 0xe5, 0x3e, 0xef, 0xd9, 0xc6, 0x2f, 0x46, 0xc2, 0x09, + 0x2b, 0x08, 0x0a, 0x08, 0x17, 0x11, 0x1c, 0x1d, 0x2c, 0xf7, 0xf8, 0x14, 0xfc, + 0x2f, 0xff, 0xe3, 0xf0, 0x35, 0x4a, 0x28, 0xe4, 0x09, 0xf8, 0xfd, 0xce, 0x36, + 0xbe, 0xf3, 0xdc, 0x9f, 0x3c, 0xdd, 0xe1, 0xe7, 0x13, 0xb2, 0xeb, 0xe9, 0xfd, + 0xb7, 0x1a, 0xf7, 0x09, 0x46, 0xf5, 0x13, 0x0d, 0x01, 0x13, 0x5d, 0x22, 0xfa, + 0xe7, 0xe4, 0x37, 0x1d, 0x14, 0xf5, 0xf4, 0xff, 0xd1, 0x1e, 0xf0, 0xff, 0x8c, + 0xf8, 0xcf, 0x0e, 0xbc, 0x24, 0x09, 0xd8, 0xc1, 0xfe, 0xca, 0x04, 0xd7, 0x09, + 0xf8, 0xc9, 0xf0, 0xaf, 0xd4, 0xb6, 0xd8, 0x2b, 0xe0, 0xfe, 0x0a, 0xf0, 0xd9, + 0x00, 0x7f, 0xf4, 0xf0, 0x2d, 0xbb, 0x18, 0xdb, 0x02, 0xed, 0xd1, 0x0c, 0xb6, + 0xcf, 0x0f, 0x16, 0xe5, 0x0a, 0xfc, 0xd7, 0x5e, 0x1d, 0xc0, 0x31, 0xe5, 0xd0, + 0x20, 0x0e, 0x5b, 0xee, 0x6a, 0xf4, 0x1c, 0xfa, 0xeb, 0xda, 0xff, 0x2a, 0x26, + 0x43, 0x04, 0x20, 0xd1, 0xfd, 0x46, 0x00, 0xf1, 0x30, 0x36, 0x63, 0xe8, 0xf1, + 0xe7, 0x4a, 0x42, 0xf4, 0xe8, 0xcc, 0x4e, 0xdc, 0xac, 0x0c, 0xb7, 0xb8, 0x1f, + 0xff, 0x27, 0xbd, 0xe1, 0x02, 0xdb, 0x2c, 0x1e, 0xe8, 0xb2, 0xea, 0xa0, 0x16, + 0x13, 0x59, 0xf0, 0xc2, 0x12, 0x1a, 0x5d, 0xea, 0xd9, 0xf5, 0x0f, 0xdc, 0xdf, + 0xdb, 0xc9, 0xff, 0xc9, 0xd7, 0xde, 0xdb, 0xf6, 0xca, 0x98, 0xed, 0xcd, 0x57, + 0xc9, 0xc8, 0xbf, 0x5d, 0xfe, 0x01, 0x99, 0xfb, 0x6d, 0x2a, 0xed, 0xe1, 0xdd, + 0x2b, 0x40, 0x19, 0xdb, 0xd5, 0x18, 0x04, 0xa1, 0x4c, 0xb6, 0x52, 0xb5, 0x10, + 0x0e, 0x07, 0x0f, 0xd1, 0xfb, 0xf6, 0x05, 0x33, 0xc6, 0xee, 0xe1, 0x91, 0xd5, + 0x0e, 0xca, 0xfd, 0xc9, 0x1b, 0xce, 0xff, 0xfb, 0x25, 0xdb, 0x7f, 0x03, 0x3c, + 0x0f, 0xcf, 0xfc, 0x49, 0x2e, 0x4e, 0xc1, 0xeb, 0xdf, 0x08, 0xc1, 0x26, 0xe7, + 0xee, 0xd0, 0xea, 0xf6, 0xf2, 0xc6, 0xe4, 0x0b, 0xef, 0x1b, 0x01, 0xa5, 0x09, + 0x24, 0xdf, 0xd7, 0xe0, 0xf7, 0xc6, 0x36, 0x44, 0xde, 0xcb, 0x1a, 0xcc, 0xe7, + 0xd0, 0xe9, 0x7f, 0x63, 0x0d, 0x21, 0x08, 0x01, 0x0f, 0x15, 0x05, 0xcc, 0x0a, + 0xcd, 0xee, 0xd5, 0x0a, 0x2b, 0xb2, 0x49, 0xf0, 0x16, 0x08, 0x2d, 0xff, 0x37, + 0x05, 0x19, 0x04, 0xcd, 0xfc, 0x1f, 0xe0, 0xd0, 0xa6, 0xf7, 0x6b, 0xcd, 0xf6, + 0x54, 0x26, 0xb8, 0xb5, 0x27, 0x0c, 0x01, 0xe1, 0x58, 0xdf, 0x15, 0xf6, 0xd2, + 0x1c, 0x21, 0xd5, 0x16, 0x07, 0xeb, 0xf2, 0x43, 0xd0, 0xbe, 0xf3, 0xca, 0xf5, + 0x0e, 0xdd, 0x0b, 0x01, 0xe2, 0xf5, 0xf5, 0xe4, 0xfa, 0xf0, 0x01, 0xe5, 0x0c, + 0xf9, 0x16, 0xfa, 0xe0, 0xf4, 0x12, 0xfb, 0x16, 0x33, 0xe7, 0xc5, 0x07, 0x25, + 0x12, 0xa6, 0xcd, 0x03, 0x08, 0xe1, 0xe1, 0xec, 0xf4, 0xe0, 0x20, 0x0c, 0x73, + 0xc2, 0x33, 0xed, 0x00, 0xf3, 0x2c, 0xed, 0x1f, 0x04, 0x24, 0x3e, 0xdd, 0x3c, + 0x15, 0x4d, 0x1b, 0x0e, 0x0a, 0xf9, 0x35, 0x29, 0xdd, 0x1b, 0xbd, 0x51, 0x32, + 0x04, 0x0d, 0xfa, 0x38, 0x6a, 0xd5, 0x2c, 0x25, 0x1c, 0x07, 0xd4, 0xf5, 0x0e, + 0xbf, 0x06, 0xfc, 0x2c, 0x0b, 0x2a, 0x3b, 0xf9, 0xab, 0x24, 0x1e, 0xf0, 0x04, + 0xe7, 0x18, 0xd9, 0xf1, 0x00, 0xeb, 0x09, 0xe1, 0xd2, 0xfc, 0xf1, 0xf4, 0xf0, + 0xf3, 0x48, 0x1b, 0x0d, 0xd7, 0xfa, 0xcf, 0xff, 0xc4, 0xf0, 0xe0, 0xc9, 0x81, + 0x70, 0x09, 0xbe, 0x17, 0xad, 0x19, 0x99, 0xea, 0xd4, 0x02, 0x1d, 0x1c, 0xd4, + 0xdb, 0xf3, 0x3c, 0xbe, 0xc9, 0x2a, 0x1f, 0xe4, 0x4a, 0xeb, 0x06, 0x04, 0x47, + 0xfd, 0xc7, 0xa7, 0xca, 0xed, 0xf0, 0xca, 0xd0, 0xc6, 0xf4, 0x16, 0xc0, 0xe4, + 0xdb, 0x0b, 0xde, 0x0d, 0xd2, 0xda, 0xbd, 0xe4, 0x09, 0x0d, 0xa3, 0x04, 0x91, + 0x06, 0xfa, 0x26, 0x00, 0xfb, 0xe1, 0xe6, 0xe4, 0x1f, 0xf7, 0x04, 0xef, 0x5a, + 0x11, 0xe2, 0x27, 0x40, 0xe7, 0x0d, 0xd4, 0x3a, 0xf9, 0xe5, 0x2f, 0xac, 0xf8, + 0x3a, 0xd7, 0xe7, 0x07, 0xda, 0xd9, 0xec, 0xd7, 0xfa, 0x25, 0xc2, 0xfd, 0xed, + 0xd9, 0x02, 0xc4, 0x4e, 0x2f, 0x48, 0x0c, 0xc5, 0x25, 0xc2, 0xf5, 0x3b, 0x0a, + 0x42, 0xe2, 0x32, 0xdd, 0xba, 0xfc, 0xe2, 0xda, 0x2a, 0xd7, 0xd0, 0x1c, 0xc2, + 0x22, 0x6b, 0xe0, 0xf1, 0x06, 0x02, 0xfe, 0xeb, 0xdb, 0x16, 0x17, 0x07, 0xc5, + 0x10, 0x00, 0xeb, 0x2f, 0x11, 0xd4, 0xfc, 0x0b, 0x1f, 0xee, 0xc1, 0xe4, 0x7f, + 0x1e, 0xe6, 0xc3, 0xe6, 0x19, 0x10, 0xd3, 0x0e, 0xea, 0x19, 0xef, 0x5c, 0xf8, + 0x2a, 0x08, 0xfe, 0x0d, 0x2a, 0x44, 0x10, 0xe3, 0xf4, 0x04, 0x4f, 0x2e, 0xd7, + 0xcb, 0x05, 0x45, 0xf6, 0xf2, 0x0f, 0x03, 0xe7, 0x0e, 0x0c, 0xf6, 0x0b, 0xf0, + 0x26, 0xe9, 0xfd, 0xc8, 0xad, 0x15, 0x25, 0xc7, 0xf6, 0x4f, 0x13, 0xed, 0x09, + 0x14, 0xe8, 0xc2, 0xfc, 0xe9, 0x0a, 0xbf, 0x48, 0x42, 0xf1, 0x53, 0x37, 0xdb, + 0x36, 0xcf, 0xdf, 0x0e, 0x11, 0x19, 0x02, 0xe7, 0x09, 0x5d, 0x0f, 0xf5, 0x2a, + 0x22, 0xd6, 0x27, 0xe2, 0xf4, 0x4e, 0x86, 0x00, 0xbc, 0xbc, 0xec, 0xca, 0xfc, + 0xf4, 0xfb, 0x24, 0xf5, 0x2b, 0x14, 0x0b, 0x31, 0x51, 0xae, 0xb8, 0x1f, 0x13, + 0xff, 0x34, 0xee, 0xd1, 0x0f, 0x19, 0x1b, 0x72, 0xfe, 0x5f, 0x15, 0x00, 0x0f, + 0xbe, 0x09, 0x1b, 0xeb, 0xf4, 0x41, 0x21, 0x73, 0xa9, 0xc3, 0x17, 0xf0, 0x27, + 0xc2, 0x06, 0x57, 0xd5, 0xf1, 0x34, 0x39, 0x1b, 0x81, 0x4a, 0x09, 0x23, 0x9e, + 0x2b, 0xee, 0xdb, 0x21, 0x65, 0x03, 0x33, 0xdd, 0x0b, 0x06, 0x1f, 0x6e, 0x2b, + 0x02, 0xe8, 0x11, 0x09, 0x16, 0xfc, 0xf0, 0xfe, 0xda, 0xf2, 0xd3, 0xfc, 0xb3, + 0xfd, 0x07, 0xea, 0x05, 0x3a, 0xc6, 0x02, 0xff, 0x5c, 0xa1, 0x42, 0x36, 0x1b, + 0x36, 0x04, 0xd2, 0xfc, 0x03, 0x2b, 0xf4, 0x08, 0xfc, 0xb0, 0x14, 0x52, 0x06, + 0x13, 0x60, 0x26, 0xde, 0xd4, 0x06, 0xfb, 0xcf, 0xd4, 0xe6, 0xf4, 0x1f, 0x02, + 0x1c, 0xfd, 0xf8, 0x04, 0x33, 0xc4, 0x07, 0xe3, 0x56, 0x47, 0x03, 0x36, 0x1a, + 0x7f, 0x19, 0xb0, 0x1c, 0x53, 0x0c, 0xb4, 0xfc, 0x44, 0x14, 0x01, 0x2e, 0x22, + 0x1a, 0xf5, 0x11, 0xf3, 0xd1, 0xe6, 0xd7, 0x37, 0xfb, 0xc8, 0x17, 0xe7, 0x2d, + 0x07, 0x36, 0xe4, 0xd4, 0x0e, 0x19, 0x10, 0x0e, 0x3c, 0x1a, 0xb8, 0x3c, 0x37, + 0x14, 0xeb, 0xf4, 0xda, 0xe0, 0xed, 0x0f, 0x04, 0x06, 0xe8, 0xc7, 0x27, 0xed, + 0xf5, 0xcf, 0xc8, 0x18, 0x4c, 0x2c, 0xf0, 0xb4, 0x28, 0x3b, 0x0e, 0xf6, 0xd9, + 0x12, 0xdd, 0xe6, 0xce, 0xf5, 0xdf, 0x01, 0xb9, 0xef, 0x08, 0x3c, 0x1b, 0xe1, + 0xcc, 0x0f, 0x18, 0xf8, 0xf0, 0xfd, 0xc3, 0xf9, 0xf4, 0xd8, 0x07, 0xe7, 0xdb, + 0xe8, 0xe2, 0x2a, 0x11, 0x0d, 0x2c, 0x3e, 0xe8, 0x14, 0x3e, 0xdf, 0x0b, 0xef, + 0x28, 0xea, 0x24, 0xd6, 0x1f, 0xf3, 0xef, 0x1c, 0x16, 0xfd, 0xcd, 0xd4, 0x42, + 0xc3, 0x7f, 0x0a, 0x07, 0x1d, 0x09, 0x28, 0x3e, 0x01, 0xec, 0xf0, 0x11, 0xd1, + 0x58, 0xf0, 0x39, 0x43, 0x1f, 0x1b, 0x48, 0x05, 0xec, 0x34, 0x0a, 0x23, 0x08, + 0x01, 0xfd, 0x08, 0x01, 0x41, 0xec, 0x12, 0xed, 0xf1, 0xed, 0xe8, 0xc3, 0x20, + 0xf2, 0xe1, 0x11, 0xce, 0xd7, 0xd8, 0xf2, 0xcf, 0x01, 0x0c, 0x0c, 0x17, 0xc9, + 0x06, 0x26, 0x27, 0x09, 0xed, 0x0d, 0x20, 0x04, 0xcf, 0xb2, 0xe4, 0xe9, 0xda, + 0x08, 0x12, 0x5b, 0xcd, 0xe9, 0xef, 0x14, 0xe2, 0x4d, 0xcc, 0xf0, 0x15, 0x06, + 0x10, 0xec, 0xd8, 0x51, 0xea, 0xce, 0x0b, 0x35, 0xcc, 0xdb, 0xcf, 0xfa, 0x0e, + 0x32, 0xe5, 0x11, 0x16, 0x05, 0x2e, 0xd0, 0xf8, 0xee, 0xf9, 0x15, 0xf7, 0x25, + 0xf4, 0xe3, 0x12, 0xe6, 0xcf, 0xdb, 0xf8, 0x06, 0x0f, 0xe3, 0x36, 0xed, 0x09, + 0xf8, 0xe4, 0x0d, 0xe0, 0xe2, 0x08, 0xe3, 0xee, 0x09, 0xe4, 0x11, 0x1c, 0x3b, + 0xaf, 0xee, 0x08, 0xfe, 0xed, 0x00, 0xf8, 0xf9, 0xe2, 0x4c, 0x0a, 0x0f, 0x0d, + 0xff, 0x07, 0xf1, 0xfc, 0x09, 0xf8, 0x21, 0xf0, 0xc6, 0x0d, 0xf5, 0xf8, 0xd8, + 0x35, 0x20, 0xeb, 0x16, 0xea, 0xfd, 0x20, 0xd1, 0xe0, 0xd6, 0xde, 0xfe, 0xe3, + 0xe1, 0x0f, 0x81, 0xf9, 0x29, 0xf5, 0x60, 0xca, 0xf8, 0x0f, 0xff, 0x0a, 0x0c, + 0xd9, 0xe2, 0xc9, 0x1e, 0xf3, 0x06, 0xfc, 0xff, 0xe6, 0xd9, 0x25, 0x1c, 0xf0, + 0x19, 0xfa, 0xef, 0xd3, 0xcb, 0xdb, 0x0b, 0x06, 0xe1, 0xfb, 0xec, 0xe8, 0x00, + 0x16, 0x11, 0xf8, 0x1d, 0xf4, 0x06, 0x1e, 0x09, 0xe6, 0x18, 0xdc, 0xe7, 0x04, + 0x0c, 0x06, 0xd2, 0x08, 0xec, 0xf6, 0xd3, 0xf2, 0xfc, 0xf7, 0xd3, 0xe8, 0xfd, + 0x0a, 0xf0, 0x07, 0x0e, 0xc6, 0xe2, 0x0e, 0x13, 0xd8, 0x04, 0x0e, 0xf2, 0xef, + 0x01, 0x03, 0xea, 0x22, 0xdd, 0x03, 0x00, 0xaa, 0x21, 0xe2, 0x23, 0xdf, 0x06, + 0xe0, 0xec, 0xe6, 0x26, 0xd6, 0xf2, 0xeb, 0x04, 0xf5, 0xcd, 0xee, 0x10, 0xfd, + 0xc9, 0x7f, 0x15, 0x0f, 0xfc, 0x16, 0x26, 0x19, 0xca, 0x10, 0x11, 0xda, 0x1f, + 0x06, 0x0b, 0x12, 0x1d, 0xfa, 0xf5, 0x04, 0xd3, 0xfe, 0xfd, 0x21, 0xee, 0x1a, + 0x05, 0x12, 0x0e, 0x0d, 0xe4, 0xe5, 0x10, 0xf5, 0xd8, 0xf2, 0x1a, 0x0c, 0x29, + 0x0f, 0xfe, 0xdd, 0xda, 0xe2, 0x02, 0xf8, 0x01, 0xf6, 0x04, 0xdf, 0x2e, 0xf2, + 0xd4, 0x40, 0xb5, 0xf4, 0xa3, 0xcb, 0x09, 0x54, 0x33, 0xea, 0xe8, 0xb3, 0x16, + 0x1a, 0x41, 0x06, 0x1e, 0x39, 0x1c, 0x09, 0xed, 0x31, 0x26, 0x69, 0xce, 0x19, + 0xba, 0x52, 0xea, 0xab, 0x21, 0xd8, 0xc9, 0xca, 0x0b, 0x3c, 0xd4, 0x7f, 0xda, + 0x01, 0x51, 0x12, 0xe7, 0x29, 0x1c, 0x9e, 0xea, 0xea, 0xea, 0xe0, 0xf4, 0xeb, + 0xf0, 0x1e, 0xed, 0x0e, 0xc8, 0x0d, 0xbb, 0xc6, 0xcc, 0xc7, 0xc6, 0xc2, 0xf3, + 0xf8, 0x2f, 0x14, 0x90, 0xe5, 0x9c, 0xcf, 0xf3, 0xb5, 0xa2, 0x8d, 0x09, 0xcc, + 0xe7, 0x00, 0xed, 0x6c, 0x83, 0xc1, 0xc6, 0xab, 0xf6, 0xef, 0x04, 0x4e, 0xe4, + 0x43, 0x12, 0xdd, 0x1a, 0xb0, 0x2e, 0xc8, 0xff, 0xe4, 0xf5, 0xce, 0xe7, 0x1d, + 0xd4, 0x18, 0x0c, 0x19, 0x18, 0x2f, 0x9c, 0x49, 0x13, 0x54, 0x1b, 0x07, 0x0f, + 0xc6, 0xb4, 0xcf, 0xd8, 0xed, 0x0f, 0xeb, 0x3b, 0xfd, 0x49, 0xf9, 0x60, 0x08, + 0x26, 0xec, 0xfe, 0x05, 0xee, 0x12, 0x76, 0xde, 0xdf, 0x0c, 0xe1, 0x18, 0xfc, + 0x24, 0xeb, 0x98, 0x20, 0x39, 0x9f, 0xfc, 0xd6, 0x2e, 0x3b, 0xee, 0xfc, 0x0e, + 0xdd, 0xd5, 0x1e, 0x18, 0xb0, 0xb3, 0xeb, 0xb3, 0xf4, 0xf9, 0x28, 0x71, 0xe2, + 0x91, 0x07, 0xe1, 0x1a, 0xd9, 0xc5, 0xfb, 0x20, 0xcb, 0x7a, 0x27, 0xe0, 0x26, + 0x38, 0xde, 0x65, 0xf7, 0xba, 0xd1, 0xe6, 0x05, 0x0b, 0x00, 0xff, 0x28, 0x9c, + 0xe9, 0xff, 0x08, 0x23, 0xca, 0xb7, 0x3b, 0xc8, 0x06, 0x64, 0xc3, 0xe0, 0xe8, + 0x33, 0xdb, 0x6d, 0x46, 0x81, 0xce, 0x21, 0x0a, 0x6e, 0x02, 0x19, 0xee, 0xbf, + 0x2a, 0x9b, 0xf0, 0x2b, 0xe9, 0x76, 0x16, 0x69, 0xfa, 0x05, 0xd5, 0xf5, 0x3d, + 0x1f, 0xc0, 0x24, 0x1e, 0x0d, 0x38, 0xe5, 0x48, 0xf9, 0xf5, 0xf9, 0x35, 0x21, + 0x9a, 0x5b, 0x1d, 0x19, 0x17, 0x18, 0xda, 0x53, 0xe1, 0xf5, 0x06, 0xf5, 0x0a, + 0xf1, 0xff, 0xf1, 0x4c, 0xe8, 0x02, 0xdd, 0x0e, 0x91, 0x56, 0xd9, 0xdb, 0xf5, + 0xea, 0x44, 0xfb, 0xe0, 0x21, 0xc9, 0xd8, 0x27, 0xc4, 0xc3, 0x0d, 0xf0, 0xd2, + 0xf3, 0xfe, 0x8d, 0x32, 0xfc, 0xf5, 0x29, 0x45, 0x40, 0x3a, 0xf5, 0x2f, 0x24, + 0xe6, 0x47, 0xef, 0x35, 0x1b, 0x07, 0x29, 0xd9, 0xe2, 0x14, 0xe0, 0x01, 0x32, + 0xf7, 0xbb, 0x20, 0xe2, 0x6b, 0x01, 0x7f, 0xed, 0xe0, 0x1c, 0xe0, 0x18, 0xe2, + 0x4a, 0x17, 0xb8, 0x22, 0xa2, 0xeb, 0x59, 0xe9, 0x1c, 0x1e, 0x99, 0x3a, 0x3b, + 0x44, 0xf8, 0xb2, 0x23, 0xe9, 0xc4, 0x0d, 0xa7, 0xe1, 0x16, 0x0b, 0xc8, 0xac, + 0xce, 0xb2, 0xcd, 0x17, 0x20, 0xd7, 0xdc, 0x15, 0x2b, 0xd7, 0x9d, 0x33, 0x8d, + 0x10, 0x43, 0x94, 0x35, 0x14, 0xd6, 0xf6, 0x3c, 0x02, 0x5e, 0xf7, 0x4a, 0xc0, + 0xfa, 0xf2, 0xfe, 0xf8, 0x28, 0x04, 0x17, 0xb8, 0xee, 0x19, 0xf1, 0xb9, 0x81, + 0xcc, 0x3a, 0xfe, 0xe4, 0x07, 0x51, 0x7a, 0x84, 0x29, 0x13, 0xb6, 0xb7, 0xf4, + 0x0c, 0x04, 0x93, 0xc4, 0x33, 0xe9, 0x38, 0xc6, 0x09, 0x0b, 0x01, 0xec, 0xec, + 0xfc, 0x3a, 0xc2, 0x4f, 0x4a, 0xc4, 0xcf, 0x1d, 0xaa, 0x27, 0xe9, 0x0a, 0x78, + 0xee, 0x1a, 0xfa, 0xc2, 0x01, 0xe7, 0xef, 0xf8, 0x10, 0x3c, 0x45, 0x43, 0xe8, + 0x24, 0x10, 0xaf, 0x60, 0x3a, 0x52, 0x17, 0xed, 0xce, 0xf5, 0xe7, 0x23, 0x3a, + 0xa3, 0xf8, 0x4f, 0x6e, 0x35, 0xd6, 0x6d, 0x23, 0xdb, 0xaf, 0xce, 0x4a, 0xfd, + 0xd8, 0xb1, 0x0f, 0xbb, 0xa3, 0x3b, 0xcf, 0xbf, 0xf6, 0xfc, 0xd1, 0xc6, 0x96, + 0xf5, 0x4f, 0xea, 0x0a, 0x0d, 0x32, 0xbd, 0xac, 0xe3, 0x9a, 0x29, 0x0b, 0xde, + 0x1a, 0x05, 0x21, 0x4c, 0x22, 0x2b, 0xbc, 0x47, 0x4e, 0xcc, 0xe1, 0x57, 0xe4, + 0xbf, 0x89, 0x36, 0xd6, 0x69, 0xf9, 0x91, 0x14, 0xc4, 0x17, 0x4c, 0xf6, 0xec, + 0xe6, 0x17, 0x02, 0xf7, 0xde, 0x0d, 0x0b, 0xd9, 0x10, 0xee, 0xcd, 0xdc, 0xf8, + 0x04, 0xbc, 0xf7, 0x00, 0xff, 0xfb, 0xd7, 0xb7, 0xd5, 0x21, 0xf1, 0xad, 0xd6, + 0xec, 0x38, 0x12, 0x7c, 0x07, 0xec, 0xc0, 0xf8, 0xeb, 0xba, 0x3f, 0xdd, 0xfb, + 0xd5, 0x2c, 0x0a, 0x01, 0xe4, 0xfe, 0xbe, 0xf5, 0x24, 0xba, 0xf2, 0x1a, 0xda, + 0xe5, 0x2e, 0xdf, 0xdc, 0xf0, 0x0f, 0x56, 0x0e, 0xf9, 0xe4, 0x03, 0x9c, 0xcb, + 0xca, 0xc9, 0xeb, 0x11, 0x15, 0x26, 0x0d, 0x1a, 0xc5, 0x2f, 0x14, 0x16, 0x04, + 0xf3, 0xfc, 0x21, 0xc8, 0xd7, 0x24, 0xe5, 0xfc, 0x81, 0xe9, 0x1c, 0xe9, 0xd6, + 0x13, 0xf9, 0x50, 0xdd, 0xe6, 0x30, 0x0d, 0xdf, 0xc9, 0xe2, 0xfd, 0x4f, 0x00, + 0x30, 0xd6, 0xf7, 0x0e, 0xee, 0xd0, 0x01, 0x12, 0x16, 0xf3, 0x17, 0x39, 0xa2, + 0xd6, 0x21, 0xf4, 0x02, 0xcf, 0xe9, 0xe6, 0x7f, 0xf6, 0x2d, 0x1b, 0x05, 0xe3, + 0x31, 0xf8, 0x4d, 0xfb, 0xa2, 0xe8, 0xef, 0x49, 0x04, 0x0d, 0xfd, 0xfc, 0x34, + 0x11, 0x37, 0xfd, 0x1c, 0x28, 0xca, 0xf3, 0xcd, 0x18, 0x2d, 0xde, 0xf9, 0xf0, + 0x19, 0x22, 0xb8, 0xab, 0xd2, 0x1e, 0x2c, 0xd0, 0x50, 0x31, 0xfa, 0xde, 0xf2, + 0x1d, 0xec, 0x5b, 0xef, 0xf2, 0x17, 0x04, 0x2a, 0x27, 0xd8, 0x87, 0x15, 0xf4, + 0xe0, 0x0a, 0xb4, 0x1a, 0xda, 0xe5, 0xf2, 0x13, 0x2f, 0x59, 0x29, 0x02, 0x66, + 0x5e, 0x00, 0xb4, 0x1e, 0x10, 0xf9, 0x9e, 0xda, 0xb0, 0x1b, 0xd2, 0xe5, 0x06, + 0x0d, 0x14, 0xff, 0x0c, 0x30, 0x3b, 0x24, 0x26, 0xd5, 0xcb, 0xcb, 0x1f, 0xf7, + 0x30, 0xf5, 0x36, 0xfa, 0x10, 0xac, 0xfb, 0x03, 0x2d, 0x4d, 0x2f, 0xe3, 0xf1, + 0x1a, 0xe4, 0xc7, 0x1d, 0x09, 0xd4, 0x5a, 0x39, 0xe5, 0xe6, 0x4b, 0x13, 0x23, + 0xcb, 0xf7, 0xde, 0x14, 0x38, 0x50, 0x2a, 0x26, 0xe1, 0xbc, 0xf4, 0x16, 0xe3, + 0x08, 0x32, 0x30, 0x75, 0x10, 0x07, 0x1d, 0xd9, 0x15, 0xa5, 0xf9, 0xc2, 0xf1, + 0xf2, 0x10, 0x18, 0xf5, 0x01, 0x4c, 0xf6, 0x6e, 0xf1, 0x0e, 0xdb, 0xc8, 0xf9, + 0x3c, 0x07, 0xe5, 0xfb, 0xea, 0xa4, 0x1c, 0x10, 0x29, 0x26, 0x27, 0x13, 0x0a, + 0x6c, 0xec, 0x0b, 0xc2, 0xd2, 0x15, 0xa3, 0xfa, 0xcd, 0x9a, 0x11, 0x08, 0x23, + 0xe1, 0xed, 0x3c, 0xf9, 0x1f, 0x00, 0xeb, 0x04, 0x47, 0x2f, 0x0f, 0x1f, 0x7f, + 0xcf, 0xd5, 0xe3, 0x5e, 0x20, 0x6e, 0x13, 0x33, 0x1c, 0xed, 0x7b, 0x18, 0xc1, + 0xeb, 0xbf, 0x38, 0x60, 0x4c, 0xd9, 0xf7, 0xee, 0xf7, 0x03, 0x49, 0xb6, 0xee, + 0xc3, 0x3d, 0x05, 0x73, 0xa3, 0x1b, 0x22, 0xfa, 0x14, 0x25, 0xc5, 0xf5, 0x9a, + 0x0b, 0x00, 0xde, 0x33, 0xff, 0x10, 0x1b, 0x3e, 0xff, 0x00, 0xea, 0xdb, 0xb4, + 0x48, 0xde, 0xe8, 0xeb, 0x0d, 0xe4, 0xfc, 0x14, 0x1c, 0x0d, 0x4d, 0xf4, 0x04, + 0x40, 0xae, 0x1e, 0x5c, 0x61, 0x66, 0xda, 0xa7, 0xed, 0xde, 0xfd, 0x21, 0xa4, + 0x3f, 0xd0, 0x04, 0x76, 0xe9, 0xfd, 0x60, 0xe3, 0xa4, 0x34, 0x00, 0x39, 0x08, + 0xce, 0xcf, 0xd3, 0x0a, 0xd7, 0xd5, 0x2d, 0x07, 0x1c, 0xe4, 0xf4, 0x6a, 0xf5, + 0x38, 0xf8, 0xf3, 0x24, 0x4b, 0x25, 0x17, 0x10, 0x01, 0x16, 0x1f, 0x17, 0x02, + 0x02, 0xf6, 0x08, 0xd6, 0xd0, 0x3e, 0x3f, 0xeb, 0x2f, 0x4d, 0x3f, 0x7f, 0x90, + 0xf4, 0xe2, 0x08, 0x23, 0x10, 0xd6, 0xf5, 0xc7, 0xb4, 0x23, 0x2e, 0xaf, 0xff, + 0xed, 0x94, 0xb6, 0xec, 0xea, 0xb7, 0x49, 0x43, 0xb6, 0x41, 0x3b, 0x0a, 0xe0, + 0xdb, 0x29, 0x0b, 0x6a, 0x9c, 0xcb, 0x15, 0x16, 0xe5, 0xd6, 0x4b, 0xb6, 0x0b, + 0x42, 0xed, 0x06, 0x04, 0x4b, 0xcb, 0x52, 0x51, 0x18, 0x41, 0x1c, 0x0c, 0xfb, + 0x12, 0xe9, 0xce, 0x0f, 0xca, 0x4d, 0x3f, 0x2e, 0x12, 0x0d, 0xd2, 0x2a, 0xf9, + 0xed, 0x3e, 0x2d, 0xd5, 0xb9, 0x75, 0xe1, 0x0a, 0x31, 0xda, 0x39, 0x42, 0xc0, + 0xda, 0x2a, 0x38, 0x12, 0xdc, 0xde, 0xc5, 0xe1, 0x28, 0x0c, 0x55, 0xd4, 0xfd, + 0xf5, 0xea, 0x38, 0xe9, 0xfe, 0x0c, 0x55, 0x51, 0x2a, 0x2f, 0x17, 0xee, 0xf6, + 0xed, 0x07, 0xb2, 0xf6, 0xf4, 0x22, 0xf9, 0x55, 0x28, 0xf5, 0xdf, 0xc9, 0xd5, + 0x09, 0x2f, 0xd6, 0xae, 0x3b, 0xc3, 0xf1, 0x44, 0xd4, 0x0b, 0xb8, 0x46, 0x18, + 0xc5, 0xdb, 0xf4, 0x1e, 0xe9, 0x4a, 0x64, 0x00, 0x33, 0xbc, 0x03, 0xe6, 0x3e, + 0x2a, 0x20, 0xf9, 0xb8, 0x2a, 0xec, 0xc9, 0x11, 0xcc, 0xea, 0x2f, 0x1b, 0x1d, + 0xe6, 0x1c, 0xd9, 0xd9, 0xd7, 0x22, 0xd8, 0x17, 0xd7, 0x0c, 0x45, 0xbb, 0xed, + 0xb8, 0x74, 0x0d, 0x20, 0xd1, 0x19, 0x1d, 0xf0, 0xf9, 0x7f, 0x2f, 0xee, 0x30, + 0x2c, 0xf4, 0xf6, 0x1a, 0x05, 0x10, 0xfe, 0xca, 0xff, 0xf6, 0xdb, 0x0c, 0xde, + 0x23, 0xcc, 0xec, 0x08, 0x09, 0xf4, 0xd8, 0xda, 0xd6, 0xf7, 0xfd, 0x0c, 0x3c, + 0xfe, 0xdb, 0xdd, 0x00, 0x20, 0xfa, 0x32, 0xdb, 0x11, 0xee, 0xc7, 0xf6, 0x0c, + 0xe9, 0xe8, 0xf2, 0x3d, 0x18, 0xf3, 0x28, 0xba, 0x08, 0xdc, 0x04, 0xca, 0x04, + 0xbb, 0xfe, 0x24, 0x8f, 0xf1, 0xc3, 0x1c, 0x48, 0x0b, 0x13, 0x08, 0xd1, 0x05, + 0x5c, 0xf2, 0xfd, 0x0d, 0xee, 0xf8, 0x27, 0xc2, 0x3d, 0xd6, 0x1e, 0x2c, 0x03, + 0xef, 0x55, 0xfd, 0xef, 0xe2, 0x18, 0x08, 0xee, 0x04, 0x0b, 0xdd, 0xfe, 0x0c, + 0x5a, 0xd3, 0xf9, 0xec, 0x05, 0x2e, 0x02, 0x5a, 0x2f, 0xf0, 0x3c, 0xe4, 0xee, + 0x28, 0xe1, 0x15, 0xda, 0xbd, 0xda, 0x22, 0x4d, 0xe2, 0x6e, 0xab, 0x22, 0xec, + 0xfd, 0x12, 0xfb, 0xec, 0x20, 0x12, 0x81, 0xf8, 0xe9, 0xef, 0x11, 0x17, 0x28, + 0x45, 0x92, 0x0a, 0xb5, 0x10, 0x35, 0xbe, 0xf3, 0xdb, 0x31, 0xea, 0xf1, 0xeb, + 0xe4, 0x2c, 0xfe, 0xe1, 0x1c, 0xf4, 0x20, 0xd9, 0x23, 0xfc, 0x07, 0x2b, 0xab, + 0x13, 0x2d, 0x2b, 0xdf, 0x2b, 0xf6, 0x31, 0xe7, 0x06, 0xef, 0x06, 0xfb, 0x02, + 0xec, 0x18, 0x33, 0x81, 0x23, 0x0c, 0x01, 0xba, 0x09, 0x3e, 0x6a, 0x67, 0x1b, + 0xe1, 0x0e, 0x07, 0xfd, 0xd9, 0xd7, 0x04, 0xff, 0xd2, 0x2b, 0x08, 0x2c, 0xad, + 0xc6, 0x10, 0x2f, 0x11, 0xf0, 0xde, 0x03, 0xd6, 0x40, 0xe7, 0x38, 0x04, 0xfa, + 0xfb, 0xfa, 0x40, 0x14, 0x0f, 0xe8, 0xea, 0xdb, 0xf9, 0xc7, 0x35, 0x27, 0xe3, + 0x16, 0x45, 0x1c, 0xe8, 0x2c, 0x2a, 0x36, 0xc3, 0xf2, 0x2e, 0xee, 0x6f, 0x5b, + 0xe8, 0x27, 0x27, 0xf5, 0xa3, 0x1b, 0x00, 0x44, 0xec, 0xcf, 0xd9, 0x2b, 0x53, + 0x12, 0xeb, 0xd8, 0xeb, 0xbf, 0x0e, 0x43, 0xa8, 0x0f, 0xd3, 0x17, 0xcf, 0x10, + 0x2e, 0x0d, 0xe8, 0xff, 0xe2, 0xf6, 0x1a, 0xd6, 0x08, 0x24, 0x4a, 0xa8, 0x0d, + 0x13, 0x28, 0x3a, 0x1c, 0x69, 0x25, 0x08, 0xfc, 0x15, 0x0a, 0x17, 0x14, 0xe4, + 0xb7, 0xe9, 0xdc, 0x06, 0xd8, 0xf9, 0x3a, 0x02, 0xe4, 0x16, 0x35, 0x3f, 0xfb, + 0x11, 0x7f, 0x0b, 0x1e, 0x10, 0x4b, 0x10, 0x48, 0xe5, 0x20, 0xe3, 0xe4, 0x3f, + 0x28, 0xd9, 0x0b, 0xe4, 0xec, 0xe3, 0x0b, 0xbd, 0xe3, 0xe2, 0x77, 0x1e, 0xdd, + 0x07, 0x30, 0x1e, 0xd6, 0xe9, 0x0d, 0xeb, 0xc4, 0xfd, 0x14, 0xed, 0xe1, 0x21, + 0xfc, 0xe8, 0xcb, 0x31, 0xd4, 0x2b, 0xff, 0x4e, 0xff, 0xf3, 0xe6, 0x32, 0xff, + 0x16, 0x10, 0xfe, 0xce, 0xc4, 0x04, 0xf6, 0xe6, 0x25, 0xa6, 0x1a, 0x15, 0x08, + 0x1c, 0x21, 0xd2, 0xd2, 0xd9, 0x1f, 0xd3, 0x09, 0xff, 0x1c, 0xeb, 0xf1, 0x08, + 0xda, 0xc6, 0xff, 0xd7, 0x3c, 0x38, 0x29, 0xf2, 0x22, 0x01, 0xf8, 0x00, 0xec, + 0xd1, 0xe6, 0x34, 0x1d, 0xe9, 0xe4, 0x03, 0xda, 0xfe, 0x11, 0x09, 0xf9, 0xef, + 0x38, 0x0c, 0xe1, 0x59, 0xc6, 0xbe, 0xff, 0xcf, 0x1b, 0xe6, 0xf5, 0xf4, 0x2d, + 0x15, 0xe5, 0xca, 0x32, 0x3a, 0x09, 0xa1, 0x0e, 0x17, 0xd9, 0xe4, 0x02, 0xee, + 0xeb, 0x19, 0xcd, 0xcd, 0xf0, 0xe0, 0xdc, 0x1f, 0xec, 0xcc, 0xd3, 0x16, 0xfb, + 0xbf, 0xa6, 0x0f, 0xf0, 0x17, 0xd6, 0xcd, 0x18, 0xcc, 0xca, 0x56, 0x1e, 0xe9, + 0x1f, 0xb8, 0x7f, 0xc6, 0x30, 0xe2, 0xf3, 0xba, 0x0b, 0xf8, 0xcd, 0xf8, 0x1e, + 0xc8, 0x01, 0xeb, 0xec, 0xe4, 0x1a, 0x21, 0x27, 0xab, 0xe5, 0xe9, 0xed, 0x0a, + 0xfd, 0xe5, 0x1f, 0x02, 0xee, 0xfa, 0xef, 0x14, 0x61, 0x39, 0xf6, 0xf0, 0xeb, + 0x01, 0x15, 0xee, 0x1b, 0xf0, 0xe2, 0xb0, 0x0a, 0x33, 0x58, 0xc4, 0xd4, 0x02, + 0xe1, 0x0e, 0xb6, 0xce, 0x4e, 0xd5, 0x2b, 0x13, 0x11, 0x0e, 0x18, 0xce, 0xf6, + 0x49, 0x01, 0x5a, 0xc9, 0x27, 0x00, 0x38, 0xfd, 0x06, 0x2a, 0x3b, 0xd6, 0x29, + 0xe7, 0x34, 0xc6, 0x0b, 0xe4, 0xf5, 0x5b, 0xe3, 0x04, 0xbb, 0xb3, 0x2f, 0xac, + 0xd9, 0x35, 0x53, 0x2f, 0xb3, 0xf6, 0x18, 0x38, 0xb0, 0x05, 0x12, 0x37, 0x1d, + 0x00, 0x0b, 0xda, 0x42, 0xd7, 0xb3, 0xda, 0xd9, 0x00, 0xf7, 0xe8, 0xdc, 0x01, + 0xd4, 0x20, 0x18, 0xe0, 0x6e, 0xf5, 0x44, 0x28, 0xdb, 0xcd, 0xe3, 0x2f, 0xc3, + 0x25, 0x32, 0xef, 0x39, 0x0c, 0x0e, 0xf0, 0xd4, 0x0c, 0xe0, 0xee, 0x12, 0x49, + 0x2b, 0xbe, 0x1f, 0x38, 0xe4, 0xec, 0x8e, 0x01, 0xf5, 0xf2, 0xc8, 0xad, 0xfe, + 0xe8, 0x03, 0xd3, 0xc9, 0x3d, 0x18, 0x13, 0x26, 0xd4, 0xd5, 0x26, 0xcf, 0xef, + 0xf8, 0xec, 0xea, 0x5e, 0x17, 0x32, 0xf0, 0x0b, 0xe1, 0x68, 0x81, 0x31, 0xe6, + 0xc0, 0x09, 0x06, 0xe9, 0xf0, 0x1b, 0xef, 0x51, 0x4f, 0x50, 0xfa, 0xdb, 0xe0, + 0x0b, 0xf5, 0xe8, 0xd4, 0xd8, 0x1d, 0x06, 0x15, 0xf0, 0x05, 0xfd, 0xd6, 0x01, + 0xff, 0x3b, 0xd7, 0x07, 0xf2, 0xa4, 0xd4, 0x06, 0xfa, 0x10, 0xf9, 0xe9, 0xf0, + 0x17, 0x28, 0xff, 0x0b, 0x1b, 0xe2, 0x1f, 0xfa, 0xf9, 0x2b, 0x19, 0xd1, 0xe8, + 0xe2, 0xcd, 0x25, 0xd6, 0xf5, 0xcf, 0x4a, 0xff, 0xec, 0x09, 0x1f, 0xee, 0xfd, + 0x1c, 0xde, 0x7f, 0x4d, 0x50, 0xd1, 0xef, 0x25, 0xe1, 0xc5, 0xcc, 0xae, 0x1a, + 0xc9, 0x11, 0xf9, 0x13, 0x1b, 0x0f, 0xf5, 0xef, 0x23, 0x0f, 0x09, 0x22, 0x18, + 0x3c, 0x2b, 0xcc, 0xdf, 0xf1, 0x12, 0x17, 0xdc, 0x39, 0xe1, 0xf0, 0xee, 0x1a, + 0x04, 0xf3, 0x1a, 0x0e, 0x14, 0xe5, 0xf2, 0x41, 0x1f, 0xeb, 0x39, 0xe7, 0xfa, + 0x0b, 0x26, 0xc7, 0xe9, 0xd8, 0xde, 0xfa, 0x17, 0x55, 0x08, 0xe7, 0xe4, 0xba, + 0xf5, 0xfe, 0xf6, 0x40, 0x10, 0x0c, 0xda, 0x02, 0x19, 0xe3, 0x19, 0xe5, 0xf0, + 0xaf, 0xe7, 0xd1, 0x34, 0x2b, 0xfa, 0x07, 0xec, 0xd4, 0xcc, 0x15, 0xdb, 0xf9, + 0x20, 0x1b, 0xc8, 0x08, 0xf0, 0xda, 0xe0, 0xef, 0x30, 0x19, 0xe1, 0xfa, 0xf1, + 0x1b, 0xe7, 0xd1, 0x00, 0xbc, 0xc7, 0x1a, 0xcd, 0xfb, 0x1a, 0xf5, 0x3b, 0xde, + 0xd0, 0x81, 0xf1, 0xe5, 0x08, 0xe8, 0xe6, 0xdf, 0x03, 0x42, 0xff, 0x41, 0x14, + 0x15, 0xde, 0xc1, 0x01, 0xfc, 0x93, 0xe2, 0x02, 0xae, 0x55, 0xfc, 0xbf, 0xd9, + 0x0a, 0xff, 0x3a, 0xc5, 0xf3, 0xf5, 0x36, 0xeb, 0x25, 0x01, 0xd1, 0xeb, 0xcc, + 0xeb, 0x29, 0x73, 0x11, 0xd5, 0xed, 0x1f, 0x19, 0x07, 0xf5, 0xe3, 0x6e, 0xe2, + 0x0e, 0x09, 0x02, 0x32, 0xf7, 0x96, 0xdd, 0x2a, 0x34, 0x06, 0x25, 0x4a, 0xf6, + 0xef, 0xd7, 0x22, 0x1f, 0xe1, 0x15, 0x16, 0x05, 0x69, 0xe4, 0x10, 0x11, 0x5a, + 0x10, 0xd5, 0xf4, 0xce, 0xb4, 0xd1, 0x2f, 0xbf, 0x0f, 0x38, 0xfc, 0xbe, 0xf2, + 0xb4, 0xee, 0x99, 0xeb, 0x10, 0xf4, 0x25, 0xf9, 0x05, 0x04, 0xec, 0xff, 0x2b, + 0x4f, 0x16, 0xc3, 0xe7, 0xfb, 0xed, 0xf6, 0xe4, 0xfd, 0xbf, 0xf7, 0x1b, 0x43, + 0x11, 0xd2, 0x37, 0x49, 0xe6, 0x11, 0xd6, 0x10, 0xdc, 0xed, 0x21, 0xf2, 0xcd, + 0x14, 0x1f, 0x04, 0x2e, 0x02, 0xf3, 0xf4, 0x18, 0xe3, 0x0b, 0x36, 0xeb, 0xe5, + 0xec, 0xc3, 0x17, 0xac, 0xd1, 0xce, 0x99, 0xdd, 0x00, 0x0e, 0x33, 0xe1, 0x7c, + 0xff, 0x50, 0x19, 0x02, 0x3c, 0xe9, 0x0d, 0x59, 0xf5, 0x23, 0xd4, 0x2a, 0x37, + 0xf3, 0x7f, 0xb9, 0xef, 0x0d, 0xe0, 0x00, 0x37, 0x0f, 0xf7, 0x07, 0x1e, 0x43, + 0xb6, 0x15, 0x0e, 0xce, 0xf8, 0x24, 0x50, 0x00, 0x13, 0x99, 0xe1, 0x10, 0x17, + 0x44, 0xd7, 0x23, 0xe2, 0x65, 0xbe, 0xed, 0x0e, 0x30, 0x08, 0x59, 0xa0, 0x48, + 0xf4, 0x06, 0xf4, 0x9e, 0xb8, 0xfb, 0x09, 0xfb, 0x18, 0x2f, 0x1a, 0x24, 0xdc, + 0xa5, 0xd1, 0xda, 0xc6, 0xb2, 0xea, 0xd4, 0xc8, 0x2e, 0x3c, 0xd5, 0xf8, 0x1d, + 0xa2, 0xdb, 0x29, 0xf3, 0xb9, 0x95, 0x04, 0x09, 0xa0, 0x38, 0x14, 0xba, 0xfb, + 0xfc, 0x2a, 0xa7, 0xb9, 0xd0, 0x35, 0xfb, 0x47, 0xf4, 0xa3, 0xb4, 0x33, 0x9d, + 0xa5, 0x06, 0x55, 0xbc, 0xe3, 0x54, 0x43, 0x18, 0xff, 0xdd, 0xce, 0x3f, 0xca, + 0xa4, 0x3c, 0x1b, 0x3a, 0x09, 0xe9, 0xb6, 0xd9, 0x1b, 0xf9, 0x31, 0x99, 0x06, + 0x23, 0x59, 0x61, 0xef, 0xeb, 0x33, 0xb6, 0x8b, 0xd7, 0x96, 0x4e, 0xfe, 0x23, + 0x81, 0x09, 0xf5, 0x61, 0xb0, 0x2d, 0x21, 0x56, 0x54, 0xfe, 0xf9, 0x22, 0x32, + 0x63, 0xfa, 0xd4, 0x59, 0x53, 0x72, 0x26, 0xf9, 0xfa, 0x0a, 0xda, 0x08, 0xfa, + 0x4d, 0x52, 0x2e, 0xac, 0x10, 0xc9, 0x0a, 0x27, 0x14, 0xff, 0xcf, 0xf8, 0x10, + 0x18, 0x24, 0xa9, 0x1d, 0xe8, 0xf1, 0x22, 0x18, 0xde, 0xd3, 0xd7, 0x1b, 0xdd, + 0xf5, 0x22, 0xae, 0x17, 0xea, 0xf3, 0x00, 0xf5, 0xd4, 0x2a, 0xe3, 0xf7, 0x1c, + 0xf2, 0x29, 0x1f, 0x96, 0xc9, 0x08, 0x19, 0x1d, 0x40, 0xe4, 0x90, 0x0b, 0xff, + 0x5c, 0xe7, 0x81, 0x08, 0xf1, 0x09, 0xe4, 0xf3, 0x26, 0xe0, 0x1d, 0xee, 0xfa, + 0x41, 0x1e, 0x32, 0xcd, 0xec, 0x27, 0x2f, 0xe1, 0x6d, 0x0f, 0xac, 0xcf, 0x24, + 0xd4, 0x09, 0xde, 0xeb, 0x05, 0x22, 0x35, 0xb9, 0x36, 0xd9, 0x02, 0x02, 0x99, + 0x06, 0x0e, 0x41, 0xd1, 0xc6, 0xb8, 0xb5, 0x48, 0xed, 0x49, 0x3b, 0xea, 0xaa, + 0xff, 0x32, 0x20, 0xdc, 0xf9, 0xee, 0x4b, 0xe8, 0xcd, 0x07, 0xfd, 0xa3, 0xf7, + 0x7b, 0xea, 0x13, 0xe4, 0x0c, 0x0c, 0x58, 0x45, 0xf5, 0xf3, 0x39, 0x2b, 0xff, + 0xab, 0xdc, 0x16, 0x2f, 0xf2, 0x26, 0x49, 0xf7, 0x37, 0x00, 0xcc, 0xc6, 0xd3, + 0x09, 0xe9, 0x05, 0xea, 0x12, 0x49, 0x11, 0xe9, 0x17, 0x01, 0xdd, 0x13, 0xf3, + 0x0a, 0x84, 0xdf, 0x0a, 0x23, 0xc9, 0x22, 0xef, 0xd8, 0x12, 0xd5, 0x28, 0x07, + 0x01, 0xb6, 0xd9, 0xcf, 0x0a, 0xc6, 0xef, 0xe3, 0x11, 0xcb, 0xf6, 0x1c, 0x06, + 0xe7, 0xfd, 0xe9, 0x08, 0xfc, 0x58, 0xb7, 0x25, 0x0c, 0x6c, 0xc0, 0x25, 0xb6, + 0xef, 0x1c, 0x04, 0x5c, 0x1f, 0xef, 0xf4, 0xd1, 0xe1, 0x0e, 0xf9, 0xd1, 0xe1, + 0x2c, 0xff, 0x45, 0xe5, 0xf1, 0x4b, 0x01, 0xcb, 0x1e, 0xfd, 0xf0, 0x21, 0xcd, + 0x25, 0x26, 0x12, 0xe0, 0xfb, 0x20, 0xd5, 0xf1, 0xf7, 0x19, 0x0e, 0x18, 0x3b, + 0xde, 0xca, 0xaf, 0x41, 0x20, 0xbf, 0x93, 0x81, 0x09, 0xf9, 0xba, 0xe6, 0xff, + 0xf1, 0xb8, 0x09, 0x4b, 0xf3, 0xe7, 0xdd, 0xe6, 0x07, 0xfd, 0xf4, 0xf1, 0x60, + 0x63, 0xf6, 0x0c, 0xd1, 0x12, 0xf9, 0xf6, 0x01, 0xdf, 0xf0, 0x81, 0xd9, 0xfb, + 0xdd, 0x01, 0xbf, 0x47, 0x25, 0xdd, 0xd8, 0x84, 0x00, 0x1d, 0x26, 0x0f, 0xf4, + 0x3a, 0x26, 0xeb, 0x18, 0x02, 0xf6, 0xfd, 0xf3, 0x01, 0xf8, 0x24, 0xb8, 0xbf, + 0xf1, 0xdc, 0x23, 0xfb, 0x0b, 0xbb, 0x09, 0x48, 0x3b, 0xfc, 0x0d, 0x1b, 0x06, + 0x4d, 0xfe, 0xa7, 0xf6, 0x23, 0xf8, 0xb9, 0x4b, 0x02, 0x75, 0xf5, 0xf5, 0x16, + 0x06, 0x14, 0xcc, 0xf4, 0xfa, 0x7d, 0x03, 0xc3, 0x0e, 0x01, 0x13, 0x1a, 0xcd, + 0xed, 0x20, 0xef, 0x25, 0xa7, 0xf4, 0xea, 0x11, 0x55, 0xe6, 0x14, 0xe1, 0x09, + 0xe1, 0xdd, 0xfb, 0xc5, 0x62, 0x2a, 0xfb, 0xfa, 0xea, 0xfb, 0x24, 0xac, 0xec, + 0xd8, 0xe0, 0xf2, 0xea, 0xda, 0xda, 0xe2, 0x73, 0xc8, 0x0f, 0x96, 0xdb, 0xe4, + 0xc7, 0xd0, 0xf6, 0x47, 0xd4, 0x08, 0xbe, 0x5b, 0xe7, 0xfc, 0x2e, 0x43, 0x24, + 0xbb, 0x2d, 0xff, 0xe7, 0x3a, 0xf9, 0x06, 0xf7, 0xeb, 0xf4, 0xf3, 0xc3, 0xd2, + 0xe3, 0x0c, 0xd3, 0xe2, 0xee, 0x0a, 0x04, 0xef, 0xf6, 0x30, 0x26, 0x0f, 0xec, + 0xbb, 0xc8, 0x0a, 0xd0, 0x14, 0xe1, 0xf1, 0x27, 0x00, 0xe9, 0xe8, 0xdd, 0x01, + 0x20, 0xd8, 0x47, 0x16, 0xf0, 0xe6, 0x0a, 0xd6, 0x1b, 0x34, 0xe7, 0x26, 0x14, + 0xf6, 0xfe, 0x2d, 0xdc, 0xec, 0xdf, 0xed, 0xea, 0xea, 0x10, 0x30, 0x0a, 0xdb, + 0xe6, 0x35, 0x24, 0xf7, 0xf9, 0x44, 0xfd, 0x1b, 0xac, 0xc1, 0x2e, 0xc7, 0x15, + 0xd4, 0xd4, 0xd4, 0x1a, 0xeb, 0xe7, 0x21, 0x2f, 0xe6, 0x0c, 0xe8, 0x38, 0x3e, + 0xd9, 0x05, 0x38, 0xac, 0xf2, 0xe0, 0xeb, 0xd7, 0x0b, 0xf9, 0xfb, 0xf7, 0x08, + 0x02, 0x24, 0x10, 0x7f, 0xe9, 0xe1, 0x1c, 0x2b, 0x0f, 0x10, 0x05, 0xec, 0x4e, + 0xc7, 0xf6, 0xd4, 0xf6, 0x1e, 0xd8, 0x0a, 0xdc, 0x1b, 0xbb, 0xc6, 0xde, 0x1a, + 0xfe, 0x30, 0xae, 0x1b, 0x29, 0x53, 0x06, 0xed, 0xd9, 0x08, 0xf4, 0xd2, 0x1c, + 0x19, 0x14, 0x14, 0xc1, 0x20, 0x11, 0x14, 0x31, 0x00, 0x0c, 0x26, 0xe7, 0x1c, + 0xbf, 0x1a, 0xe5, 0xcf, 0xb5, 0xe9, 0x00, 0xec, 0x1d, 0xc0, 0x7f, 0x33, 0xd1, + 0xfb, 0x1b, 0x30, 0x02, 0xf5, 0x25, 0x00, 0xe9, 0xcd, 0x4a, 0x21, 0x16, 0xc2, + 0x49, 0xe2, 0xfc, 0xc4, 0x39, 0xbc, 0x11, 0xce, 0x4e, 0xf2, 0xff, 0xfe, 0x01, + 0xe9, 0x23, 0x30, 0xfa, 0x27, 0xd8, 0x24, 0xeb, 0x52, 0xd5, 0xec, 0xce, 0x09, + 0xcf, 0xe6, 0xe9, 0x12, 0xe8, 0xe0, 0x06, 0x0a, 0x46, 0xfe, 0x09, 0x29, 0xcf, + 0xc1, 0x10, 0x42, 0x27, 0xec, 0xf8, 0x30, 0x00, 0x21, 0x2b, 0x02, 0xc4, 0x21, + 0xbe, 0x2a, 0xfc, 0xe6, 0xf9, 0xf3, 0xdd, 0xf7, 0x05, 0xd6, 0xc8, 0xd8, 0x23, + 0x1b, 0xeb, 0x20, 0x11, 0x2f, 0x11, 0xe2, 0xf6, 0xe7, 0xb6, 0x26, 0xec, 0xfb, + 0x02, 0xef, 0x01, 0xec, 0x08, 0xed, 0xe3, 0xc8, 0x2c, 0x13, 0x37, 0x14, 0x3e, + 0xd3, 0xe0, 0x0b, 0xdc, 0x14, 0xee, 0xcf, 0x2b, 0xe4, 0xf2, 0xf3, 0xbc, 0xdd, + 0xfa, 0xfa, 0xd2, 0xf0, 0x26, 0xb7, 0x31, 0xd0, 0x07, 0x0e, 0x03, 0x4a, 0x43, + 0x0a, 0x1a, 0xf1, 0x25, 0xf4, 0x4b, 0x06, 0xef, 0x37, 0xf0, 0x13, 0x1c, 0xe2, + 0xe1, 0xd7, 0x1d, 0xe1, 0xe6, 0xf6, 0x44, 0xe9, 0xd1, 0x05, 0xf2, 0x36, 0x2e, + 0xfd, 0x34, 0x0a, 0xc2, 0x43, 0xd2, 0x15, 0xfc, 0x20, 0x0a, 0xd5, 0xe7, 0xcb, + 0xf6, 0x0f, 0xe5, 0xf8, 0xfd, 0x06, 0x0a, 0xdf, 0xe5, 0x14, 0x1b, 0x24, 0xb8, + 0x00, 0xc9, 0x16, 0x0b, 0x0b, 0xdd, 0x03, 0x34, 0xfa, 0x10, 0x2b, 0x08, 0x2a, + 0x5e, 0xdd, 0x7f, 0xf4, 0xe6, 0xcf, 0xd6, 0xfb, 0x06, 0xe3, 0xcb, 0x06, 0xf3, + 0x2b, 0x15, 0xee, 0xa3, 0xc6, 0xee, 0x06, 0xf2, 0x2f, 0xef, 0x20, 0xee, 0x0d, + 0x0f, 0x05, 0xf5, 0xf6, 0xe0, 0xcf, 0xde, 0xfc, 0x17, 0xea, 0xec, 0xd0, 0x17, + 0xf2, 0x1e, 0x02, 0x1c, 0xe8, 0x0a, 0x47, 0xd8, 0xdf, 0xed, 0xfb, 0xf1, 0xf4, + 0x0b, 0x3b, 0x08, 0xf0, 0x13, 0xf3, 0xe3, 0xcd, 0x3f, 0xc4, 0x15, 0x00, 0x7a, + 0x35, 0x05, 0x0a, 0xda, 0x09, 0xf3, 0x06, 0xfb, 0x1d, 0x23, 0xf8, 0xe1, 0xda, + 0xe6, 0xfd, 0x4b, 0x26, 0x20, 0x50, 0xe5, 0xf1, 0x30, 0xbf, 0xfd, 0xf3, 0x25, + 0xf3, 0xc1, 0x0a, 0x23, 0xb9, 0x51, 0x11, 0xde, 0xbf, 0x1f, 0x0c, 0x08, 0xf7, + 0x00, 0x1a, 0xe2, 0x0b, 0xe5, 0xed, 0xea, 0x10, 0xda, 0x0e, 0x16, 0xfa, 0xf7, + 0xf3, 0xfc, 0xa2, 0xde, 0xe8, 0x29, 0x44, 0xa0, 0x16, 0xcf, 0x81, 0x34, 0xf7, + 0xea, 0xf6, 0xe9, 0x3f, 0x30, 0x17, 0x1a, 0xe9, 0x06, 0xfc, 0xd4, 0xd6, 0xf8, + 0x30, 0x0c, 0x4c, 0xe9, 0x07, 0x02, 0xf8, 0xe4, 0xf5, 0xdd, 0xea, 0xfa, 0x1a, + 0xad, 0xbb, 0x41, 0x60, 0x0f, 0x31, 0x18, 0x43, 0xdd, 0x1f, 0x04, 0x0a, 0x1f, + 0x06, 0xb0, 0xd2, 0xbd, 0x38, 0x15, 0x1e, 0xfe, 0xf4, 0xc1, 0x27, 0xeb, 0xe8, + 0x05, 0x18, 0xea, 0x39, 0xf1, 0xdd, 0x44, 0xc6, 0xda, 0x12, 0xef, 0xe9, 0x36, + 0x0e, 0x1b, 0x23, 0x17, 0x07, 0xf9, 0xfd, 0x81, 0x28, 0x2e, 0x26, 0xf3, 0xae, + 0xf5, 0x19, 0x35, 0x2c, 0x1b, 0x05, 0xda, 0xd2, 0x0a, 0xe0, 0x0b, 0xb3, 0xf5, + 0xd6, 0xcd, 0xf1, 0x0f, 0xf9, 0xf8, 0xed, 0xb9, 0x22, 0x23, 0xbf, 0x19, 0x07, + 0xec, 0xd9, 0x06, 0xce, 0xbd, 0xfd, 0xdf, 0xfb, 0xdc, 0x03, 0xb6, 0xdd, 0xd3, + 0xb3, 0x01, 0xe4, 0x0f, 0x3c, 0xa9, 0xd8, 0xc8, 0x8f, 0x0c, 0x39, 0xce, 0x22, + 0x00, 0x1e, 0xb2, 0xf3, 0xec, 0x1f, 0xfb, 0x0b, 0xf8, 0x26, 0xfc, 0x47, 0x34, + 0x33, 0x08, 0x16, 0xe5, 0x0a, 0x05, 0xd4, 0xe5, 0xdd, 0xe9, 0x0d, 0xc7, 0xdf, + 0x11, 0xf9, 0x05, 0x21, 0x01, 0x27, 0xf3, 0xdb, 0xfa, 0xd4, 0x07, 0xc8, 0xd9, + 0xf8, 0x05, 0xd6, 0xdb, 0xf0, 0xbd, 0x21, 0xec, 0xfd, 0x04, 0x39, 0x4d, 0xc9, + 0x29, 0x7f, 0xea, 0xf1, 0xfb, 0xd0, 0xdb, 0x25, 0xda, 0x19, 0xd2, 0x0c, 0xec, + 0xa8, 0xe2, 0xf5, 0x13, 0xcc, 0x05, 0x0a, 0xa0, 0xee, 0xe4, 0x0a, 0x1e, 0x06, + 0x0c, 0xf1, 0xd0, 0xef, 0x02, 0xde, 0x30, 0x06, 0x03, 0x10, 0xda, 0x31, 0x74, + 0x21, 0xd1, 0xff, 0xe9, 0xf6, 0xd8, 0xf9, 0x25, 0x56, 0xf3, 0xe7, 0x06, 0x25, + 0x06, 0xf3, 0xf7, 0x03, 0xd6, 0x08, 0xeb, 0xf7, 0xea, 0xf0, 0x1d, 0x64, 0x0b, + 0xcf, 0xf5, 0x30, 0x48, 0xce, 0x2e, 0xc1, 0xe5, 0xd9, 0xf2, 0xdc, 0x3c, 0x0d, + 0xf3, 0x07, 0xfa, 0xf3, 0xc5, 0xc0, 0xd9, 0x11, 0xd3, 0x02, 0xe6, 0x32, 0xba, + 0x43, 0x31, 0x07, 0xfd, 0xc1, 0xed, 0xfe, 0xef, 0x43, 0xd7, 0x06, 0x52, 0xf8, + 0x2c, 0xf1, 0x51, 0x1a, 0xd8, 0x23, 0x03, 0x1e, 0x23, 0x21, 0xb8, 0xf7, 0x1e, + 0xf7, 0xff, 0x04, 0x28, 0xfc, 0xff, 0x14, 0x6c, 0x13, 0x1c, 0xbb, 0xca, 0x13, + 0x47, 0x19, 0x29, 0xff, 0xde, 0x1d, 0xfe, 0xee, 0xb6, 0x18, 0xc3, 0xf1, 0x1a, + 0xd5, 0x11, 0xc7, 0xd7, 0x2c, 0xc5, 0x27, 0x24, 0x07, 0x19, 0x02, 0xb3, 0xe0, + 0xfc, 0x0a, 0x3d, 0xc0, 0x13, 0x04, 0x37, 0xca, 0x1f, 0x02, 0x32, 0xd3, 0xdf, + 0x0b, 0xf7, 0x1c, 0xd1, 0x39, 0x14, 0xe4, 0xec, 0xf2, 0xef, 0x02, 0x12, 0x1a, + 0xf1, 0xce, 0x15, 0xe5, 0xef, 0xdd, 0x1b, 0x15, 0x26, 0x48, 0x1b, 0xd1, 0x28, + 0x1e, 0x4a, 0x38, 0xc6, 0x81, 0xb2, 0x42, 0x1c, 0xa6, 0x16, 0xd5, 0xee, 0xc5, + 0x00, 0xd8, 0x09, 0xda, 0x18, 0xde, 0xdb, 0xfa, 0xec, 0x34, 0xd2, 0x15, 0x34, + 0x0d, 0x61, 0x1b, 0xc2, 0xe0, 0xe2, 0xef, 0xec, 0xf4, 0x13, 0xe7, 0x13, 0xde, + 0xf3, 0x4d, 0xe5, 0xdf, 0x22, 0xde, 0x13, 0x40, 0x06, 0x1d, 0xe2, 0xf6, 0xad, + 0x6f, 0xaf, 0x23, 0x3f, 0xda, 0xf1, 0xfd, 0xf8, 0xae, 0xdd, 0xf9, 0xc1, 0x0a, + 0xfa, 0x42, 0x81, 0x23, 0xf9, 0xf8, 0x54, 0xcb, 0xbb, 0x21, 0xfa, 0xbd, 0xe8, + 0xca, 0x38, 0x51, 0xe0, 0xdd, 0x10, 0x69, 0xf0, 0x2b, 0x0d, 0x23, 0xf3, 0x0e, + 0xd3, 0xa8, 0xe9, 0x22, 0xf4, 0xec, 0x3b, 0x6b, 0x0e, 0xce, 0xfb, 0x50, 0xe1, + 0x1d, 0x60, 0x2d, 0x2f, 0x0d, 0x16, 0xe2, 0x67, 0xa3, 0x09, 0x2b, 0xed, 0x06, + 0x02, 0x7c, 0x29, 0xc7, 0xc6, 0x1a, 0xe6, 0x4e, 0xc6, 0x3a, 0xdc, 0xb9, 0x2e, + 0xaf, 0x31, 0x51, 0x94, 0x39, 0x12, 0xd6, 0x2a, 0x0d, 0xd9, 0xd8, 0x35, 0x3e, + 0x15, 0x26, 0x17, 0xd8, 0x33, 0x0e, 0x93, 0x76, 0x01, 0x01, 0xdf, 0x11, 0x07, + 0xda, 0xa0, 0xa9, 0x46, 0x36, 0x3f, 0xe2, 0xa4, 0xd2, 0x0a, 0xf9, 0xae, 0x0f, + 0xad, 0x09, 0x20, 0xec, 0x9c, 0x6a, 0x6e, 0xee, 0xba, 0x08, 0x47, 0xd2, 0x03, + 0xf2, 0xc0, 0x4f, 0x34, 0xfb, 0xa3, 0x62, 0x5a, 0xdf, 0xfd, 0x1e, 0xfe, 0xf5, + 0x6f, 0xe6, 0x12, 0x08, 0x30, 0x20, 0xbd, 0xcd, 0x0f, 0xe6, 0xde, 0x01, 0xad, + 0x1d, 0x62, 0xef, 0x20, 0x4c, 0x61, 0x10, 0xba, 0x2b, 0x19, 0x08, 0xcf, 0x50, + 0xf7, 0xdc, 0xc6, 0x4e, 0xe5, 0xee, 0x2b, 0xd7, 0x03, 0x1a, 0xf6, 0xe8, 0xe5, + 0xbd, 0x33, 0x1c, 0xe4, 0xf1, 0x95, 0xcd, 0xce, 0x58, 0x1b, 0x00, 0x42, 0x7f, + 0x84, 0x6e, 0xce, 0x0f, 0xbd, 0x20, 0xe9, 0x18, 0x1b, 0x1e, 0xfd, 0x14, 0x32, + 0x2b, 0xfd, 0xd3, 0x25, 0xe2, 0x13, 0xfb, 0x02, 0x57, 0xfd, 0x58, 0x20, 0xfc, + 0xf1, 0x9d, 0xfc, 0x02, 0xf5, 0xf4, 0xfc, 0xba, 0xcd, 0x77, 0xfe, 0x04, 0x7a, + 0xa9, 0x01, 0x19, 0xc0, 0xef, 0xeb, 0xd4, 0xe3, 0x19, 0x22, 0x54, 0xe5, 0xd7, + 0x06, 0xfe, 0xb5, 0xe7, 0xdc, 0xa0, 0x15, 0xc1, 0xfc, 0x23, 0xf5, 0xd9, 0x29, + 0x23, 0x47, 0xfe, 0x3c, 0x8c, 0xe8, 0xd6, 0xb7, 0xff, 0x04, 0xdb, 0xf9, 0xe3, + 0xe7, 0x20, 0x90, 0x10, 0xed, 0x11, 0xde, 0xff, 0xfc, 0xf6, 0xf1, 0x0c, 0xa8, + 0x6b, 0xc3, 0x12, 0x0f, 0x26, 0x1e, 0x07, 0x5b, 0x3f, 0xc4, 0xee, 0xf0, 0x40, + 0xdb, 0x7f, 0xba, 0x23, 0x5d, 0xac, 0xcf, 0x15, 0x42, 0x32, 0x0f, 0x51, 0x32, + 0x06, 0xc3, 0x23, 0xe3, 0xfa, 0x24, 0x2d, 0xf8, 0x35, 0xdf, 0x4c, 0x34, 0xb1, + 0x88, 0x08, 0x16, 0x2a, 0x3d, 0x15, 0x95, 0x3c, 0x4e, 0xe4, 0xdc, 0xb4, 0x1b, + 0xdb, 0xc0, 0x14, 0x5e, 0xd5, 0xe5, 0xc8, 0xb7, 0x0f, 0xe4, 0xdd, 0x40, 0x22, + 0xde, 0xfb, 0x1d, 0x38, 0xe5, 0xf7, 0xd4, 0xeb, 0xfe, 0x0d, 0xed, 0x63, 0x30, + 0x43, 0x5d, 0xd5, 0xf9, 0xe3, 0x09, 0xf5, 0xee, 0x13, 0x07, 0xd0, 0x03, 0xf3, + 0xe1, 0x48, 0x1f, 0x41, 0x29, 0xdf, 0x02, 0x1b, 0x1f, 0x0d, 0x10, 0xf1, 0xc2, + 0x00, 0x2a, 0x9b, 0x08, 0xcd, 0x30, 0x01, 0xd9, 0x06, 0x1b, 0x07, 0xee, 0xf3, + 0x06, 0x2d, 0x4a, 0xf4, 0xfd, 0x1b, 0x2f, 0xc9, 0x1b, 0xda, 0xc8, 0x19, 0x1b, + 0xcd, 0x19, 0xf9, 0x00, 0x13, 0xf5, 0xe7, 0x09, 0x22, 0x7f, 0x0d, 0xed, 0x11, + 0x71, 0x01, 0x1e, 0x02, 0x09, 0x08, 0x27, 0xe0, 0x4b, 0xec, 0xe8, 0x0a, 0x2c, + 0xe4, 0x2c, 0x00, 0xff, 0xf6, 0x20, 0x14, 0xe7, 0xcb, 0xc5, 0xf8, 0xf1, 0x04, + 0x26, 0x17, 0x18, 0xff, 0x10, 0xd1, 0x0d, 0x2b, 0xe8, 0x06, 0x19, 0xcf, 0xf3, + 0xe0, 0xc5, 0xcd, 0x31, 0x27, 0xe3, 0x52, 0x0c, 0x0f, 0xcf, 0x0a, 0x18, 0x20, + 0xe7, 0xf1, 0xa9, 0xdb, 0x13, 0xf4, 0x02, 0x16, 0xf2, 0xfb, 0x36, 0xea, 0xf9, + 0x2c, 0x1f, 0x13, 0x3e, 0x2a, 0x5f, 0xb2, 0x3e, 0xd9, 0xee, 0xdf, 0x1d, 0x32, + 0x2d, 0xf4, 0x30, 0x1b, 0xfc, 0xf1, 0xee, 0xca, 0xf9, 0x20, 0xb4, 0xfc, 0x18, + 0x3f, 0x4b, 0xb2, 0xa4, 0x17, 0xeb, 0x39, 0xc9, 0xe1, 0xef, 0x1a, 0x4e, 0xea, + 0x50, 0xf5, 0x00, 0x1f, 0x05, 0x20, 0x70, 0x08, 0x28, 0x08, 0xd1, 0xc0, 0xf1, + 0xfe, 0xc6, 0xbc, 0xdf, 0x1c, 0xca, 0x75, 0x42, 0x1f, 0x5a, 0xda, 0x44, 0x38, + 0x0f, 0xde, 0x81, 0x10, 0xea, 0x39, 0xec, 0xf5, 0x1b, 0xfc, 0x12, 0x2a, 0xdf, + 0xa4, 0xee, 0xf0, 0xed, 0xaa, 0xf3, 0xaf, 0xfc, 0x03, 0x7d, 0x17, 0xe2, 0x01, + 0xf2, 0x07, 0xcd, 0x14, 0x02, 0xc5, 0xf7, 0xaa, 0x21, 0xe9, 0x7e, 0xe0, 0xdd, + 0xf6, 0xec, 0xfa, 0x0a, 0x52, 0x15, 0x0a, 0xef, 0x3a, 0x33, 0xe1, 0xfa, 0x4f, + 0x28, 0x7b, 0xc6, 0x9f, 0xe6, 0x42, 0x18, 0x68, 0xdf, 0x0f, 0x5d, 0xef, 0xda, + 0x3d, 0x0f, 0xad, 0xb0, 0x40, 0xee, 0xbc, 0xcd, 0xdf, 0x09, 0x01, 0xdf, 0x54, + 0xe7, 0x18, 0x00, 0xd6, 0x26, 0xf7, 0x41, 0xc3, 0xa7, 0x0f, 0x0b, 0xc4, 0x02, + 0x13, 0x14, 0x2a, 0xc6, 0x5c, 0xf6, 0x33, 0xb5, 0x09, 0x22, 0x66, 0xbe, 0xdd, + 0x3e, 0xe8, 0x7a, 0xfc, 0xec, 0xbd, 0xb5, 0x23, 0x35, 0xd7, 0x20, 0x98, 0x2b, + 0x03, 0xe9, 0xef, 0x0e, 0x13, 0x0c, 0xcf, 0xb3, 0x26, 0x53, 0x0f, 0xca, 0x00, + 0x2c, 0xf6, 0x9b, 0x30, 0xf7, 0xfd, 0xa8, 0x4e, 0xb6, 0xe1, 0x49, 0x1b, 0x21, + 0x02, 0x29, 0xff, 0xe9, 0xc4, 0xc5, 0x20, 0x73, 0x3a, 0xd1, 0x56, 0x00, 0xc4, + 0x30, 0xcd, 0xc6, 0x18, 0xe8, 0x64, 0x6f, 0xd5, 0x22, 0xec, 0x17, 0x81, 0xff, + 0x06, 0xad, 0xa8, 0xe0, 0x04, 0xe1, 0xfd, 0xfc, 0x23, 0x46, 0x20, 0xb9, 0xe6, + 0xf5, 0x3b, 0x0d, 0x15, 0x2f, 0xfd, 0x0a, 0x43, 0xe4, 0x26, 0x12, 0x30, 0x07, + 0x36, 0x2d, 0x0e, 0xca, 0xf4, 0x22, 0xf7, 0x01, 0x2a, 0xf1, 0x25, 0xdf, 0x72, + 0x27, 0x27, 0x2d, 0x38, 0x41, 0xb9, 0xcb, 0xb3, 0xff, 0x1d, 0x09, 0x20, 0x23, + 0xdf, 0x29, 0xfe, 0x16, 0x20, 0xb1, 0x31, 0xfe, 0xf2, 0xe6, 0xf8, 0x1f, 0xf4, + 0xe8, 0xe1, 0xa7, 0xe4, 0x30, 0x12, 0xe1, 0xdf, 0xf5, 0x49, 0xf7, 0xe8, 0xf7, + 0x09, 0xc3, 0xf4, 0x5b, 0xf2, 0xb3, 0x90, 0xb9, 0xfe, 0x25, 0xe6, 0xff, 0xde, + 0x91, 0xcf, 0xe2, 0xfa, 0x7f, 0xeb, 0x15, 0xcf, 0x1d, 0xc7, 0x08, 0x24, 0xf2, + 0xd9, 0xe8, 0x19, 0xf2, 0xf5, 0x07, 0x18, 0xfc, 0x17, 0xfb, 0xfc, 0x1c, 0x1a, + 0x7b, 0xf0, 0x1d, 0x06, 0x10, 0x42, 0x3b, 0xdb, 0x09, 0xf2, 0xbc, 0x8c, 0x38, + 0xfa, 0xd4, 0x5c, 0x2e, 0xfc, 0x23, 0x13, 0x22, 0xfe, 0x24, 0xeb, 0x5a, 0xe1, + 0xe9, 0x0e, 0x81, 0xee, 0x63, 0xf3, 0xf7, 0xfe, 0xd6, 0x29, 0xec, 0x15, 0xe4, + 0x0e, 0xe7, 0xe1, 0xd0, 0xe2, 0xf1, 0xc8, 0x22, 0x29, 0xf3, 0x25, 0x39, 0x3a, + 0xfe, 0x1c, 0xdf, 0x05, 0x31, 0x12, 0x13, 0xc7, 0xea, 0xd5, 0x1e, 0xc8, 0xf2, + 0x14, 0xef, 0xd0, 0x26, 0x59, 0xb4, 0x1d, 0xf2, 0xeb, 0x07, 0xfe, 0x20, 0xf3, + 0xb6, 0x21, 0xac, 0xd0, 0xda, 0xe8, 0xfa, 0x3f, 0x10, 0xf7, 0x04, 0x1b, 0x40, + 0x11, 0x33, 0xeb, 0xfe, 0x25, 0xda, 0xbd, 0xe9, 0x22, 0xe0, 0x39, 0xf0, 0xb0, + 0xf1, 0x68, 0x15, 0x0b, 0xe2, 0x09, 0xc0, 0xac, 0x06, 0xdf, 0x13, 0xc9, 0xcb, + 0x36, 0xe1, 0x22, 0xde, 0x0d, 0x25, 0x1d, 0xf7, 0x07, 0xcf, 0x39, 0x47, 0x1f, + 0x7b, 0x2f, 0xf9, 0x4a, 0xea, 0x1b, 0x14, 0x11, 0xef, 0x10, 0x27, 0x07, 0x0a, + 0xec, 0x33, 0x07, 0x1a, 0xed, 0x32, 0xff, 0x28, 0xe0, 0xe1, 0xfe, 0xe8, 0x11, + 0xdf, 0x28, 0xba, 0x10, 0x20, 0xb6, 0xfb, 0x0a, 0xf3, 0x00, 0xe2, 0x0d, 0xfb, + 0xf0, 0xda, 0xe8, 0x15, 0xe1, 0x2d, 0xdb, 0x27, 0xfe, 0xe2, 0xfb, 0xfb, 0xcd, + 0x0a, 0x0d, 0xe2, 0x1a, 0xfd, 0xf0, 0x42, 0x29, 0x03, 0xe9, 0x0d, 0xf7, 0xf3, + 0xed, 0xf0, 0xeb, 0x16, 0xf0, 0xde, 0x18, 0x0b, 0x15, 0xed, 0x54, 0xbc, 0x07, + 0xe1, 0xff, 0xf9, 0x14, 0xf9, 0xe1, 0xf3, 0xfe, 0xdd, 0x00, 0xe8, 0xe4, 0xe0, + 0xe6, 0x0a, 0xcc, 0x01, 0xd0, 0xe6, 0xd7, 0x0b, 0xe4, 0x02, 0x40, 0x2d, 0xcb, + 0xe4, 0x15, 0xd8, 0xfb, 0xf9, 0xf2, 0x10, 0xd4, 0xef, 0x18, 0xcd, 0xcd, 0xda, + 0x7f, 0xfe, 0x05, 0x2b, 0xea, 0xf7, 0xe6, 0x0e, 0x2d, 0xed, 0x01, 0xd4, 0xfa, + 0xe5, 0x02, 0x07, 0x29, 0x03, 0xf7, 0x1b, 0x1a, 0x06, 0xdf, 0x27, 0xef, 0xec, + 0xdf, 0x26, 0x03, 0xf5, 0xee, 0xfc, 0xda, 0xd2, 0xf9, 0x0a, 0x4a, 0xf7, 0xcc, + 0x63, 0x39, 0x36, 0xcb, 0x2c, 0x05, 0xdd, 0x36, 0xe4, 0xbd, 0xdc, 0xb2, 0x0a, + 0xc5, 0xb9, 0x17, 0x7f, 0x02, 0xd4, 0xf7, 0x07, 0x19, 0x3d, 0x0e, 0xc6, 0xc8, + 0xcd, 0xc9, 0x06, 0xe3, 0xb2, 0xac, 0xd3, 0x25, 0xdb, 0xfb, 0x21, 0x33, 0xe9, + 0x30, 0x8c, 0x21, 0xc4, 0xbc, 0xa1, 0x24, 0xaa, 0xc3, 0x06, 0xec, 0xe3, 0x36, + 0x32, 0xa2, 0x62, 0xf9, 0xa2, 0x17, 0x25, 0x0e, 0xee, 0x06, 0x32, 0xdb, 0xfd, + 0x00, 0x77, 0xf4, 0xc2, 0x1c, 0x47, 0xee, 0x06, 0xb0, 0x4a, 0xaf, 0xe8, 0x03, + 0xc2, 0x1f, 0xc9, 0xe7, 0xd9, 0xea, 0xf7, 0x00, 0xe5, 0xc7, 0x10, 0x39, 0x6c, + 0xd7, 0x19, 0xf8, 0x0d, 0x12, 0xd1, 0x0d, 0x2b, 0x01, 0xfe, 0x50, 0xc4, 0xb5, + 0xe8, 0x06, 0x0c, 0xe7, 0x38, 0x77, 0xe9, 0xec, 0x0e, 0x0c, 0xf0, 0xff, 0xef, + 0x02, 0x0b, 0x05, 0xa3, 0x27, 0xc5, 0x2a, 0x20, 0x14, 0xed, 0x26, 0xbf, 0x20, + 0x04, 0xd0, 0x19, 0x30, 0x06, 0x2e, 0x43, 0x1a, 0xe5, 0xef, 0xd5, 0xf2, 0xe7, + 0xf4, 0xc4, 0x24, 0xee, 0x4b, 0xf1, 0x2d, 0x00, 0xe4, 0xe9, 0x16, 0x3c, 0x34, + 0x1a, 0x9d, 0xf4, 0xe1, 0xc8, 0xf9, 0x38, 0x0d, 0xff, 0x26, 0x10, 0x24, 0xf9, + 0x97, 0xa9, 0x3c, 0x34, 0xd8, 0xcd, 0xf8, 0x21, 0x0c, 0xc9, 0xe8, 0x07, 0xc2, + 0xfc, 0x3c, 0xb3, 0xe1, 0xdc, 0x13, 0xed, 0xa4, 0x59, 0xe6, 0x11, 0xfa, 0x22, + 0xd5, 0x0c, 0x1d, 0x27, 0x1e, 0x25, 0xb9, 0x03, 0xe8, 0xfe, 0x36, 0xf1, 0xd9, + 0x3f, 0x1d, 0xe5, 0x32, 0xca, 0xf7, 0x0d, 0x28, 0x37, 0xe3, 0xf2, 0xf3, 0xef, + 0xe9, 0xf8, 0xfa, 0x22, 0xd9, 0x5f, 0x06, 0x55, 0xf8, 0xd3, 0x05, 0x17, 0x37, + 0x72, 0xf6, 0xb3, 0x12, 0x2b, 0x06, 0xd3, 0xee, 0x17, 0x13, 0x3b, 0x29, 0x81, + 0x87, 0xe5, 0x40, 0x4c, 0x06, 0xd2, 0x3f, 0x7f, 0x0b, 0x4c, 0x48, 0x3e, 0xc6, + 0xf4, 0x36, 0xc2, 0xde, 0x28, 0x02, 0x2d, 0xef, 0x08, 0x06, 0x27, 0x48, 0x62, + 0x19, 0x3c, 0x0f, 0xe7, 0x10, 0x1f, 0xd4, 0xcb, 0x87, 0xff, 0xd0, 0xfb, 0xe4, + 0xfd, 0x13, 0x21, 0xff, 0xcb, 0x1f, 0xe4, 0x4e, 0x0d, 0x18, 0xf8, 0x6b, 0x30, + 0xeb, 0xfe, 0x35, 0x34, 0xd3, 0x33, 0xe3, 0xb8, 0x57, 0xd8, 0xee, 0xc0, 0xbd, + 0xa8, 0xea, 0xfd, 0xc5, 0x02, 0x1b, 0xda, 0x61, 0xf2, 0xe5, 0xf7, 0x15, 0x05, + 0x13, 0xda, 0xda, 0xc0, 0x06, 0xaf, 0x1c, 0xd7, 0xd0, 0x58, 0x45, 0x2e, 0xdd, + 0xfa, 0xd6, 0x5b, 0xec, 0xbd, 0x14, 0xc5, 0x26, 0xd7, 0x18, 0x0c, 0x19, 0xba, + 0xf1, 0x08, 0x13, 0x22, 0x1c, 0xda, 0x68, 0x44, 0x0d, 0x30, 0x2c, 0xf3, 0xdc, + 0x4a, 0x19, 0x1d, 0x2d, 0x1c, 0x21, 0x30, 0x00, 0xf3, 0x1f, 0x01, 0xed, 0xea, + 0xc2, 0x56, 0xe7, 0xe6, 0xce, 0xf1, 0xfc, 0x15, 0x19, 0x7f, 0x9a, 0x9c, 0xa4, + 0x47, 0xf6, 0x08, 0xe9, 0x8c, 0x11, 0xaa, 0x12, 0xcc, 0x22, 0xea, 0xb8, 0xe5, + 0xea, 0x16, 0x01, 0xdf, 0x9f, 0x96, 0xfd, 0x46, 0x22, 0x0e, 0xc1, 0x11, 0x04, + 0xa9, 0xf6, 0xc7, 0xf0, 0x04, 0x4e, 0xea, 0xdb, 0x8e, 0x39, 0x05, 0xdb, 0xe4, + 0xf4, 0x8d, 0xd7, 0x15, 0x27, 0xb0, 0x18, 0xf3, 0xe0, 0xd8, 0xf1, 0x3b, 0x1b, + 0x17, 0x5c, 0xd4, 0x31, 0x13, 0xc9, 0x08, 0x00, 0xbf, 0x2a, 0x5e, 0x4e, 0x03, + 0x1b, 0xe1, 0x32, 0x20, 0xfa, 0x38, 0x2e, 0x26, 0x4d, 0xe0, 0x0c, 0x28, 0x00, + 0x54, 0x99, 0xd7, 0x10, 0x2f, 0x27, 0xef, 0x0c, 0x14, 0xd4, 0xa5, 0x45, 0x18, + 0xf1, 0x10, 0xec, 0x43, 0x9f, 0xdc, 0xe7, 0xce, 0xbb, 0x13, 0x32, 0xdd, 0x29, + 0x91, 0x3f, 0xdc, 0x02, 0x02, 0xf8, 0xcf, 0x2b, 0x47, 0xa4, 0x48, 0xdb, 0x29, + 0x2b, 0xe8, 0xfd, 0x08, 0x0d, 0xf6, 0x4a, 0x02, 0xf4, 0x13, 0x28, 0x17, 0xd9, + 0x2f, 0x0b, 0x3a, 0xd5, 0x0e, 0xee, 0x00, 0x0a, 0x0e, 0x26, 0xf8, 0xf1, 0x1a, + 0x0a, 0x13, 0x53, 0x01, 0xda, 0xac, 0x50, 0xfb, 0xe0, 0xe0, 0x14, 0xf8, 0x02, + 0xdd, 0xe6, 0x10, 0x3f, 0xc6, 0xff, 0x33, 0x0f, 0x32, 0xf7, 0x2f, 0x09, 0x69, + 0xeb, 0xd9, 0xe3, 0x36, 0xec, 0xeb, 0x25, 0x11, 0xed, 0xdc, 0x3d, 0x0c, 0x02, + 0x41, 0xd1, 0xe4, 0xff, 0xc5, 0x1a, 0xf3, 0x08, 0x14, 0xd9, 0x7f, 0xee, 0x12, + 0xda, 0x2e, 0xd4, 0xfd, 0xe2, 0xcf, 0xe9, 0xc1, 0x34, 0xcc, 0xe1, 0x1d, 0x15, + 0x24, 0xcf, 0x22, 0x5b, 0xa4, 0x09, 0x11, 0xca, 0xd6, 0xdf, 0xea, 0x18, 0x0e, + 0x58, 0xce, 0x0b, 0x1c, 0x02, 0x08, 0xce, 0x26, 0xca, 0x27, 0x45, 0xce, 0x2b, + 0x13, 0xcf, 0xea, 0xdf, 0x5f, 0x54, 0xcf, 0xe5, 0x88, 0x0d, 0x13, 0xfb, 0xf6, + 0xcf, 0xe3, 0xf1, 0xfb, 0xd1, 0x03, 0x21, 0x41, 0xd5, 0x09, 0x0c, 0xd7, 0xda, + 0x0e, 0xcb, 0xf8, 0xe4, 0xe8, 0x02, 0xee, 0xbc, 0x2b, 0x08, 0x2c, 0xf8, 0xdc, + 0xdb, 0xcc, 0x2f, 0x14, 0x19, 0x3f, 0x14, 0x3f, 0xe1, 0xde, 0xfc, 0x0c, 0xc7, + 0xea, 0x30, 0x07, 0xfc, 0xe4, 0x18, 0xe9, 0xe8, 0xdb, 0xf4, 0xae, 0xeb, 0xf9, + 0x3b, 0xb2, 0xf2, 0xe4, 0xf9, 0x01, 0x28, 0xd9, 0x49, 0x03, 0xc5, 0xdb, 0xd5, + 0x1e, 0x1b, 0x10, 0xfe, 0xea, 0xef, 0x23, 0x40, 0x45, 0x13, 0xe3, 0x27, 0xeb, + 0x29, 0x1e, 0xfe, 0xf8, 0x4f, 0x1a, 0x2f, 0xea, 0x0b, 0x09, 0x1f, 0x10, 0xda, + 0xed, 0xe7, 0xfa, 0xee, 0x3e, 0xee, 0xcd, 0x10, 0xed, 0x51, 0xe6, 0x1b, 0x21, + 0xca, 0x1a, 0x7f, 0xed, 0x1b, 0xbd, 0xfc, 0x28, 0xf2, 0xe2, 0x2f, 0xec, 0xd1, + 0x2b, 0xf8, 0xdc, 0x6a, 0x16, 0x35, 0x44, 0x42, 0xf9, 0x24, 0xf3, 0xf1, 0xb8, + 0x39, 0xd9, 0xeb, 0xfe, 0x46, 0x0b, 0xd4, 0xf6, 0xf8, 0x3c, 0xf8, 0x27, 0x22, + 0x16, 0x1b, 0x10, 0x37, 0x28, 0xfa, 0x02, 0x05, 0xc5, 0xdd, 0x27, 0xdb, 0x46, + 0xe4, 0xb9, 0x0d, 0xfc, 0x0b, 0xc8, 0xf6, 0xeb, 0xf9, 0x0b, 0x16, 0xfc, 0xf7, + 0xd6, 0xd3, 0x00, 0xdc, 0x11, 0xe3, 0x35, 0xf9, 0xf1, 0xea, 0xde, 0x11, 0x15, + 0x5b, 0x29, 0xeb, 0xeb, 0xfe, 0x0e, 0xcf, 0xe1, 0xe6, 0xf7, 0xe7, 0xf7, 0xda, + 0x0a, 0xed, 0x16, 0x66, 0xcc, 0xd2, 0x24, 0xf8, 0x35, 0x10, 0xc9, 0xdb, 0xe3, + 0x26, 0x1d, 0xdc, 0xd7, 0x1c, 0x26, 0x58, 0x0d, 0x0f, 0x15, 0x41, 0x02, 0x09, + 0xc6, 0x15, 0x1e, 0xff, 0xf8, 0xe2, 0x19, 0xdd, 0xeb, 0x12, 0x81, 0x1b, 0xe6, + 0x41, 0xe2, 0x1f, 0xe5, 0xfc, 0xa1, 0xe8, 0xe5, 0x06, 0x1c, 0xd8, 0xf7, 0x23, + 0x30, 0xd3, 0xd1, 0x5c, 0xa7, 0xcb, 0x35, 0x01, 0x07, 0x67, 0xe0, 0x15, 0x1b, + 0x0f, 0xf9, 0x17, 0x4b, 0xe9, 0xfc, 0xf9, 0xad, 0xe6, 0x0d, 0x12, 0x07, 0x23, + 0xd3, 0x0d, 0xef, 0x0a, 0x42, 0xff, 0xe6, 0x17, 0xe4, 0x19, 0xd5, 0x24, 0x43, + 0xde, 0x4a, 0xc7, 0xca, 0xde, 0xeb, 0x28, 0xbe, 0x27, 0x10, 0xe3, 0x0e, 0x0c, + 0xc6, 0xaf, 0x34, 0xc5, 0xc5, 0xa9, 0xdd, 0xde, 0x10, 0xfc, 0xdd, 0x3a, 0x20, + 0x2e, 0x05, 0xbb, 0xe3, 0xfe, 0xca, 0x10, 0x09, 0x4e, 0x0b, 0x7f, 0xf5, 0xf3, + 0x08, 0x0b, 0x27, 0xc9, 0xdb, 0x1d, 0xe0, 0xd7, 0xf4, 0xfb, 0x0c, 0x05, 0xf7, + 0x1f, 0xe5, 0xce, 0xd9, 0xda, 0x4a, 0xd6, 0xd6, 0x4e, 0x88, 0x31, 0xee, 0xfb, + 0xd5, 0x36, 0xc7, 0x1d, 0xee, 0xef, 0x08, 0xdd, 0x34, 0x34, 0x31, 0xce, 0xf1, + 0xda, 0xdf, 0x0e, 0xda, 0xd6, 0x18, 0xdf, 0xdf, 0xfd, 0x1b, 0xde, 0xfc, 0xde, + 0xc0, 0x9d, 0xfe, 0xde, 0xf2, 0x1c, 0x04, 0xbf, 0x0a, 0x05, 0x8b, 0x11, 0xb2, + 0x1e, 0x1d, 0xa5, 0xea, 0x1d, 0xe9, 0xe4, 0x19, 0xcc, 0x13, 0xcb, 0x19, 0x0f, + 0xf1, 0xb0, 0xcf, 0xe6, 0xec, 0x01, 0xdb, 0x11, 0xf4, 0x3e, 0x33, 0x16, 0xcc, + 0x1a, 0xf2, 0xff, 0xa5, 0xef, 0xce, 0x13, 0x12, 0x18, 0x12, 0xf0, 0xe4, 0xf3, + 0xea, 0x06, 0xbf, 0xc4, 0xf9, 0x33, 0xc1, 0x06, 0x1f, 0xe1, 0xd0, 0x27, 0xef, + 0xfb, 0xfa, 0xdb, 0x06, 0x2b, 0xff, 0xe2, 0xbe, 0x17, 0xdb, 0x1b, 0x09, 0xf7, + 0x2d, 0x0d, 0x4a, 0x2c, 0x0c, 0x33, 0xfd, 0x03, 0x01, 0xe1, 0xf4, 0x4b, 0x05, + 0x0b, 0xcf, 0x36, 0x33, 0xed, 0x26, 0x09, 0xe1, 0x13, 0x09, 0x04, 0x35, 0x17, + 0xf2, 0x35, 0xd3, 0xfe, 0x2b, 0xdc, 0x56, 0x3a, 0xdc, 0x1c, 0xd2, 0x2f, 0x01, + 0xe4, 0x9f, 0x36, 0x71, 0xd5, 0x30, 0xe3, 0x12, 0x44, 0x25, 0xec, 0x81, 0xfb, + 0x4a, 0x08, 0xe3, 0x4a, 0x22, 0xd4, 0x37, 0xd4, 0x37, 0x1f, 0x37, 0xd1, 0x07, + 0x1d, 0xdd, 0x06, 0xfb, 0x10, 0x0c, 0xd8, 0x74, 0x07, 0xa3, 0xe4, 0x31, 0xe8, + 0xd0, 0xce, 0x21, 0x1b, 0xea, 0xb1, 0x0b, 0x5e, 0xef, 0x1c, 0x3d, 0xab, 0x42, + 0xfe, 0xf0, 0x43, 0x02, 0xd9, 0x3e, 0xe1, 0x36, 0x08, 0x89, 0x0a, 0xeb, 0xf9, + 0xdb, 0x3d, 0xca, 0xfa, 0x15, 0xed, 0x31, 0xab, 0xef, 0x41, 0xe8, 0x1a, 0xb3, + 0x4d, 0x18, 0x25, 0x39, 0x2d, 0x3e, 0xd9, 0xf9, 0x69, 0xd5, 0x30, 0x44, 0x0c, + 0x12, 0x31, 0x19, 0x51, 0x4b, 0x41, 0x26, 0x09, 0x38, 0x09, 0xcc, 0xe1, 0xed, + 0xd2, 0xf5, 0xe1, 0xe5, 0x0f, 0x0b, 0x04, 0xe0, 0xcc, 0xbe, 0x3b, 0x40, 0x18, + 0xfa, 0x10, 0xde, 0xf8, 0x2b, 0x81, 0xf7, 0x16, 0x87, 0x31, 0x47, 0x23, 0x38, + 0x12, 0x69, 0x5b, 0xd9, 0xff, 0xe7, 0xf3, 0xcb, 0x63, 0xfb, 0x48, 0x17, 0xfc, + 0x06, 0xf2, 0x15, 0xde, 0x20, 0xc8, 0x03, 0xd8, 0xe7, 0xfe, 0x31, 0xd3, 0xa7, + 0x0d, 0xf3, 0x1c, 0xf4, 0x7e, 0xd6, 0x28, 0x35, 0x13, 0x23, 0x0b, 0x00, 0xd9, + 0x09, 0x1d, 0xe0, 0x81, 0xb9, 0x45, 0xd1, 0x05, 0xe7, 0x32, 0xe5, 0x5e, 0x76, + 0xd4, 0x1a, 0x05, 0xfb, 0xef, 0xe5, 0xd3, 0x04, 0xbe, 0xea, 0xd3, 0xd7, 0xcd, + 0x43, 0xad, 0x0f, 0x0e, 0xf2, 0xed, 0x5c, 0x0a, 0x27, 0xe7, 0x08, 0xa2, 0x1f, + 0x18, 0x13, 0x12, 0x1d, 0xcc, 0x15, 0x12, 0xbc, 0xf5, 0xc1, 0x08, 0x00, 0x07, + 0xc9, 0xd6, 0xda, 0xf6, 0xcf, 0x2a, 0x14, 0xe2, 0xf8, 0xad, 0x37, 0xee, 0xfc, + 0xdd, 0xdb, 0x2b, 0x0f, 0x07, 0xf7, 0xdb, 0x26, 0xf8, 0x28, 0xf9, 0x1d, 0xf3, + 0x30, 0xed, 0x75, 0xff, 0xf7, 0x29, 0xf8, 0x16, 0x64, 0x15, 0xe1, 0xf9, 0x09, + 0xd9, 0xb8, 0xd9, 0xed, 0x47, 0xd6, 0xdd, 0x2c, 0x1c, 0xca, 0xe8, 0x94, 0x37, + 0x04, 0x20, 0x7f, 0x3d, 0x60, 0xfa, 0x1a, 0xdf, 0xc4, 0x1e, 0xf5, 0x02, 0xee, + 0x22, 0x2b, 0xfe, 0x15, 0xcf, 0x0f, 0x51, 0xfd, 0xf7, 0xdc, 0xd3, 0xf3, 0xf0, + 0xf4, 0xd8, 0xb6, 0xd2, 0x01, 0xed, 0x17, 0x1b, 0xdf, 0xf7, 0xc6, 0xf0, 0xd0, + 0x06, 0xdf, 0xd0, 0xd1, 0x22, 0x1c, 0x08, 0x28, 0x08, 0x20, 0xff, 0x64, 0x1b, + 0xa8, 0x05, 0x44, 0xdf, 0xe6, 0xca, 0xed, 0x08, 0x1f, 0xd7, 0x21, 0xff, 0xb5, + 0x6a, 0xa8, 0x45, 0x15, 0x06, 0x46, 0xa7, 0xe2, 0x10, 0xfa, 0x0e, 0xfe, 0xc2, + 0x27, 0xc3, 0x21, 0xd2, 0xef, 0x13, 0xa9, 0xed, 0x05, 0xac, 0x2d, 0xf4, 0x16, + 0xdc, 0xae, 0x3b, 0x15, 0xdf, 0xdc, 0xcc, 0x19, 0xfa, 0xfd, 0x21, 0xb0, 0xe3, + 0xe3, 0x46, 0xbd, 0xf8, 0xae, 0xd8, 0xed, 0x1f, 0x5b, 0xe4, 0xdc, 0x26, 0xff, + 0x01, 0xdb, 0x4f, 0x2d, 0x4c, 0xe1, 0xf9, 0xcc, 0xef, 0xbc, 0xb1, 0x0a, 0x20, + 0x0e, 0xef, 0x23, 0x18, 0x26, 0xaa, 0xea, 0xce, 0x0b, 0xc3, 0xb3, 0xf9, 0xf0, + 0xe3, 0xf4, 0xf0, 0xf9, 0xf2, 0x35, 0xda, 0xe8, 0x1b, 0xe0, 0xbc, 0x1e, 0xf2, + 0xbe, 0x1a, 0x28, 0x07, 0x10, 0xfb, 0xca, 0xe5, 0x19, 0xe9, 0x1f, 0x07, 0x1e, + 0xee, 0x58, 0xde, 0x05, 0xfe, 0xd2, 0xc1, 0xfc, 0x38, 0x2f, 0xdb, 0x09, 0x37, + 0xea, 0xd2, 0x23, 0x38, 0xe3, 0xde, 0xbe, 0x24, 0xd3, 0x06, 0x33, 0xda, 0xea, + 0xea, 0x1e, 0x2a, 0x23, 0x38, 0x1c, 0x13, 0x10, 0x24, 0xed, 0x7f, 0x01, 0xb5, + 0xad, 0xe0, 0x03, 0x04, 0xb3, 0xf4, 0xfe, 0xfe, 0x1e, 0xb9, 0xe3, 0xd2, 0x15, + 0xfe, 0x22, 0xf5, 0x26, 0x71, 0xe5, 0xa6, 0x0f, 0x14, 0x6f, 0xe2, 0xca, 0xbb, + 0x10, 0x97, 0xed, 0xea, 0x3f, 0xcf, 0x3b, 0xe6, 0xbe, 0xdf, 0x10, 0xbc, 0xa9, + 0x15, 0xea, 0x20, 0x09, 0x30, 0x95, 0x2f, 0xa0, 0x27, 0x17, 0xb8, 0xd6, 0x2c, + 0x25, 0x3f, 0xec, 0xb4, 0x76, 0xf3, 0xf9, 0x36, 0x45, 0x0d, 0xc6, 0x55, 0x39, + 0x3b, 0xe9, 0x13, 0x20, 0xa0, 0x36, 0xdc, 0x07, 0x26, 0xb2, 0xcc, 0x81, 0x02, + 0xba, 0x24, 0xc5, 0xf2, 0x01, 0xdf, 0xc9, 0x5f, 0x26, 0x04, 0x18, 0x2f, 0xdb, + 0x27, 0x2c, 0x53, 0xc1, 0x9a, 0xe2, 0x65, 0xcd, 0x0b, 0xd8, 0xbe, 0x15, 0x41, + 0x35, 0x24, 0x36, 0xf2, 0xb1, 0x07, 0xfc, 0xfb, 0x44, 0x58, 0x3c, 0x2a, 0x24, + 0xf4, 0xd9, 0xe8, 0xd1, 0xb5, 0x28, 0xed, 0xcf, 0xb6, 0xc6, 0xd4, 0x09, 0x09, + 0xdd, 0x0e, 0xc5, 0xeb, 0xf5, 0x17, 0xfe, 0xbf, 0x25, 0xc4, 0x15, 0x00, 0x3c, + 0xf8, 0xe4, 0xea, 0x16, 0xe6, 0xf7, 0xfd, 0xb1, 0x19, 0xe1, 0xf2, 0xfd, 0xcc, + 0x33, 0x18, 0x5e, 0x00, 0xc1, 0xfe, 0x51, 0x1c, 0x5b, 0x0e, 0xde, 0x05, 0xe5, + 0xef, 0xee, 0xef, 0xbe, 0x5b, 0xf2, 0xbb, 0xb6, 0x0d, 0x20, 0xef, 0xd9, 0x1a, + 0x50, 0x04, 0x32, 0xe8, 0xf6, 0x04, 0xe9, 0x12, 0xd0, 0xf7, 0x20, 0xe6, 0xd9, + 0xb7, 0xe4, 0xd6, 0xc9, 0x4a, 0x0e, 0x4f, 0xbf, 0xf1, 0x19, 0x2e, 0x5b, 0xbe, + 0xec, 0xac, 0x2a, 0x19, 0xb3, 0xef, 0x21, 0xe0, 0x1a, 0xf0, 0x33, 0x16, 0x12, + 0xe1, 0xe0, 0xeb, 0xec, 0xd2, 0xdf, 0xf3, 0xb0, 0x2e, 0x2a, 0x53, 0xef, 0xf5, + 0x1c, 0x2b, 0xbd, 0x8a, 0xea, 0x2c, 0xd0, 0x24, 0x27, 0xef, 0x1e, 0xf9, 0x81, + 0xcf, 0x00, 0x3b, 0x0d, 0xfe, 0x20, 0x23, 0xf0, 0x0e, 0x1a, 0x2b, 0x02, 0xdc, + 0x46, 0xcb, 0xf4, 0x1e, 0xfb, 0x1e, 0xdf, 0x6c, 0xd3, 0xe8, 0xfd, 0x06, 0x53, + 0x0d, 0x2f, 0x26, 0x11, 0x22, 0xc0, 0xcf, 0x7e, 0xff, 0xc4, 0xfe, 0x14, 0xf9, + 0x06, 0x35, 0xed, 0xd5, 0x3e, 0xdf, 0xf9, 0xe9, 0x0d, 0xe6, 0x36, 0xa0, 0xe2, + 0x24, 0xc9, 0x25, 0xab, 0xf7, 0xec, 0x15, 0x33, 0x98, 0xd7, 0x22, 0xb0, 0xdd, + 0x5d, 0x1f, 0xda, 0x01, 0xe5, 0x0d, 0xe7, 0xdf, 0xee, 0x9c, 0x33, 0xc4, 0xf0, + 0xfc, 0x3d, 0x1d, 0xea, 0x1b, 0x2c, 0xcf, 0x37, 0x32, 0xdc, 0xc2, 0x0c, 0xc0, + 0x53, 0x0b, 0xc8, 0xd6, 0x2f, 0xeb, 0xfc, 0xb7, 0x1e, 0x26, 0xaf, 0x25, 0x0e, + 0x2b, 0x05, 0x2f, 0x05, 0x20, 0x93, 0x0c, 0xd1, 0xa7, 0x0f, 0x6e, 0xf2, 0x01, + 0xc1, 0x32, 0xdd, 0x00, 0xea, 0xef, 0xcc, 0xc7, 0xf8, 0xec, 0xa3, 0x25, 0x0a, + 0xb6, 0xb1, 0x00, 0x26, 0xa6, 0x22, 0x34, 0x11, 0x07, 0x1b, 0xd1, 0xf1, 0xba, + 0x46, 0x08, 0xe0, 0xcf, 0x81, 0x36, 0xd9, 0x24, 0xf8, 0xff, 0x54, 0x39, 0x25, + 0xf2, 0x17, 0x3a, 0xd5, 0x15, 0xfd, 0xd8, 0x12, 0x19, 0x24, 0x08, 0x22, 0x0a, + 0x01, 0xd7, 0x24, 0xbb, 0x00, 0xbf, 0x0c, 0xcf, 0xd8, 0xde, 0x25, 0x2c, 0x68, + 0xf3, 0xf5, 0xd8, 0xab, 0x18, 0x17, 0x46, 0x0a, 0xd9, 0x31, 0xaa, 0x30, 0x68, + 0xe8, 0x08, 0xc7, 0xf2, 0x01, 0x90, 0xf7, 0xca, 0x76, 0xba, 0x53, 0xe9, 0xef, + 0x0a, 0xb3, 0x1f, 0xe9, 0x27, 0x1a, 0x7b, 0xff, 0xef, 0x3f, 0x08, 0xb2, 0x24, + 0x85, 0x03, 0xbf, 0x44, 0xdc, 0xe2, 0x00, 0xf7, 0xe7, 0x9a, 0x3d, 0xf6, 0xbc, + 0x99, 0xff, 0x1f, 0x3c, 0xca, 0x8c, 0x85, 0xef, 0x18, 0xf3, 0xfd, 0xbc, 0xcd, + 0x14, 0x3c, 0x27, 0xf8, 0x23, 0xcc, 0xfc, 0x81, 0xa6, 0x28, 0x1b, 0x48, 0xd8, + 0x16, 0xfe, 0x0b, 0x13, 0xbb, 0xdb, 0xdd, 0x04, 0xd0, 0xda, 0x05, 0xf9, 0x0f, + 0xd7, 0xfe, 0xce, 0x38, 0x33, 0x25, 0x26, 0xfb, 0x3f, 0x46, 0xe4, 0xb9, 0xe4, + 0x97, 0xb3, 0xfa, 0x15, 0x31, 0x00, 0x06, 0xa0, 0x04, 0xdf, 0xb4, 0x1e, 0x1c, + 0x0b, 0xd6, 0xcc, 0xc4, 0x10, 0xc7, 0xf6, 0xde, 0x07, 0x3e, 0x87, 0xef, 0x49, + 0x13, 0xf5, 0xfe, 0xdf, 0x29, 0x69, 0x0c, 0xf9, 0x13, 0x2d, 0x7f, 0x33, 0xdc, + 0x36, 0xfe, 0x03, 0xd7, 0x09, 0x0c, 0x2c, 0x1c, 0x2f, 0x73, 0x00, 0x25, 0xff, + 0xd5, 0x52, 0xd9, 0xe2, 0x5e, 0xa6, 0x00, 0x12, 0x12, 0x0a, 0xe5, 0x07, 0x33, + 0xbc, 0x21, 0x00, 0xf2, 0xe5, 0xf4, 0x22, 0xfd, 0x07, 0xf7, 0x33, 0xef, 0x52, + 0x14, 0xf3, 0xdd, 0xd8, 0x43, 0xf7, 0xbe, 0xf6, 0xf0, 0xd9, 0x35, 0x00, 0xe3, + 0x4b, 0xf0, 0x0f, 0xfa, 0xfe, 0x2c, 0x3e, 0xe0, 0xf7, 0xcf, 0x1e, 0xf1, 0x3b, + 0xf3, 0xd3, 0x35, 0xbd, 0x51, 0x15, 0xed, 0xdd, 0x00, 0xec, 0x24, 0x1e, 0x3f, + 0x1e, 0xdf, 0xed, 0xfb, 0x58, 0x0a, 0xf9, 0x28, 0xeb, 0xc6, 0xda, 0xd9, 0x0a, + 0x01, 0xc4, 0x1d, 0xe4, 0xfc, 0xcb, 0xc6, 0xba, 0xc7, 0xef, 0x0e, 0xca, 0x40, + 0xe5, 0x02, 0xce, 0x30, 0xcd, 0x47, 0xe3, 0x10, 0x02, 0x16, 0x07, 0xf2, 0x03, + 0xf1, 0xec, 0x0a, 0x32, 0x19, 0xf3, 0x03, 0xe0, 0x26, 0x1e, 0xc8, 0x00, 0xf4, + 0x11, 0x14, 0xd8, 0xe4, 0x0e, 0x0a, 0x27, 0x16, 0x26, 0x0b, 0x04, 0x2f, 0x12, + 0x67, 0x10, 0xce, 0xf5, 0xb7, 0xf4, 0xe1, 0xed, 0xcf, 0xed, 0xfa, 0x12, 0xf0, + 0x0b, 0xf7, 0xe9, 0x0d, 0xe7, 0x25, 0xdf, 0xe9, 0xe9, 0x3d, 0xea, 0xe6, 0x1e, + 0x20, 0xee, 0x15, 0x02, 0x2f, 0x11, 0x07, 0xb0, 0x1a, 0xce, 0xf0, 0x61, 0xae, + 0x0c, 0xe5, 0xdf, 0x06, 0x15, 0xed, 0xe2, 0x12, 0x27, 0xfe, 0x03, 0xf7, 0x0a, + 0xf8, 0x06, 0x38, 0xfe, 0xfd, 0x26, 0xfa, 0xf2, 0xf9, 0x2d, 0xea, 0xb2, 0x11, + 0xd7, 0x19, 0x7f, 0xcf, 0x17, 0x29, 0x03, 0x35, 0xfb, 0xe1, 0xd1, 0xf7, 0xdd, + 0x7c, 0xfb, 0x16, 0x31, 0x14, 0x16, 0xe4, 0xcf, 0xe4, 0xc3, 0x4e, 0x1e, 0x10, + 0xf5, 0x07, 0xe7, 0xe8, 0xf1, 0x05, 0x21, 0xe3, 0xb3, 0x18, 0x07, 0x12, 0x45, + 0x04, 0xaf, 0x0a, 0xca, 0x16, 0x7a, 0xf6, 0x09, 0x04, 0xf8, 0x09, 0x1e, 0xe9, + 0x4b, 0xbf, 0x14, 0xe9, 0x0d, 0xbc, 0x0d, 0x23, 0x01, 0xd1, 0xfe, 0x1f, 0xce, + 0x4c, 0x17, 0xc1, 0x2e, 0xdc, 0x07, 0x09, 0x5a, 0x06, 0x23, 0x03, 0x2d, 0x18, + 0x33, 0xf5, 0xfe, 0xc6, 0xbe, 0x07, 0xd4, 0x5d, 0x0a, 0x0a, 0x29, 0x28, 0xf6, + 0x53, 0x19, 0xea, 0x15, 0xcf, 0x2b, 0xe9, 0x28, 0xda, 0x96, 0xf2, 0x36, 0x7e, + 0xe7, 0xfc, 0x42, 0xe6, 0x81, 0x2a, 0x4f, 0xec, 0xe6, 0xe2, 0x1f, 0x96, 0xe2, + 0xc7, 0xe1, 0xfe, 0x19, 0xe4, 0x04, 0x29, 0xb7, 0x2c, 0x2c, 0xde, 0xa7, 0x1d, + 0x94, 0x56, 0xe2, 0x0d, 0xc1, 0xe0, 0xc5, 0x72, 0xf6, 0x20, 0x40, 0xd1, 0x7c, + 0xce, 0xb8, 0x54, 0xe4, 0x4d, 0x0c, 0xfb, 0xad, 0xf0, 0x45, 0x3f, 0x18, 0xef, + 0xf3, 0x19, 0xfe, 0x14, 0x92, 0x61, 0xf8, 0x31, 0xe5, 0x1a, 0xd4, 0x0a, 0xe8, + 0x19, 0xe9, 0xd7, 0x0e, 0x6d, 0x00, 0x0e, 0x32, 0x22, 0xc5, 0xe7, 0x07, 0x2d, + 0xfe, 0xd0, 0x5b, 0x35, 0xf5, 0xc2, 0xef, 0xd6, 0xd0, 0xca, 0xc1, 0x20, 0xcd, + 0x11, 0xce, 0xee, 0xf7, 0x7f, 0x2b, 0x39, 0x98, 0xfe, 0x1b, 0xc4, 0x28, 0xd1, + 0x1a, 0x03, 0x0c, 0xd8, 0x25, 0x11, 0xf5, 0x41, 0xfd, 0xe6, 0x20, 0x37, 0x0a, + 0x08, 0xe8, 0xbb, 0xbe, 0x96, 0xe5, 0x0b, 0x06, 0xf0, 0x14, 0x25, 0x3a, 0x61, + 0xe6, 0x63, 0x22, 0x3c, 0xe8, 0xd9, 0xf6, 0xf1, 0xa2, 0x1e, 0xf7, 0x19, 0x1d, + 0xfb, 0xbf, 0x32, 0x0f, 0xdf, 0x11, 0x37, 0x2f, 0xf2, 0x6c, 0x4a, 0xf3, 0x1d, + 0x1f, 0xa1, 0xde, 0x3a, 0x3f, 0xd4, 0xdf, 0xea, 0xd1, 0x03, 0xe3, 0xb9, 0x16, + 0x44, 0xb3, 0xd1, 0xda, 0xfc, 0x44, 0x42, 0xea, 0x27, 0x58, 0xd8, 0x08, 0xe0, + 0xea, 0x02, 0xf9, 0x25, 0x26, 0x56, 0x9a, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x80, 0x04, 0x00, 0x00, 0x81, 0x60, 0xec, 0x3a, 0xec, 0xce, 0xe9, 0xca, 0x06, + 0xcc, 0xe2, 0x3f, 0xee, 0x7f, 0x81, 0x6d, 0xe5, 0xaa, 0x7f, 0x89, 0x78, 0x19, + 0xbb, 0xcc, 0x3e, 0x59, 0x17, 0x4d, 0x3b, 0xc4, 0x54, 0xf7, 0x98, 0xf1, 0xe8, + 0xc3, 0xa9, 0xcb, 0xe8, 0xf1, 0x51, 0xe5, 0x50, 0xb1, 0xcb, 0x5f, 0x3d, 0x7f, + 0x01, 0xb4, 0xab, 0xe4, 0x42, 0xf5, 0x3e, 0x7f, 0xfe, 0xad, 0x60, 0x71, 0x96, + 0x47, 0xd3, 0x08, 0xf2, 0xf9, 0x4d, 0x34, 0x60, 0x7f, 0x71, 0x7f, 0xba, 0xc9, + 0xd9, 0xac, 0x9c, 0x5c, 0x31, 0x70, 0x81, 0xfb, 0xc7, 0x21, 0x88, 0x57, 0x7f, + 0xf8, 0x99, 0xa6, 0x2f, 0xdd, 0xf5, 0x7f, 0x18, 0x0d, 0x59, 0x96, 0xb0, 0xd1, + 0xf2, 0xad, 0xc6, 0x5e, 0x84, 0xb4, 0x81, 0xd1, 0xf3, 0xae, 0x7f, 0x77, 0x0b, + 0xd7, 0xbc, 0x27, 0x04, 0xd0, 0xcf, 0xae, 0xd1, 0x5a, 0xd6, 0xfe, 0x7f, 0x1d, + 0xc8, 0x21, 0xb2, 0xfa, 0xcf, 0x04, 0xc6, 0x32, 0xf6, 0xd6, 0x10, 0xcc, 0xce, + 0x60, 0x32, 0x4b, 0x14, 0x73, 0x81, 0xd5, 0x33, 0x83, 0xeb, 0x3c, 0x85, 0xa4, + 0x7f, 0xc9, 0xdd, 0xcb, 0x7f, 0x0a, 0x52, 0xec, 0x42, 0xcc, 0x20, 0xd2, 0x81, + 0xd9, 0xe4, 0x4a, 0x7f, 0x45, 0xf5, 0x30, 0xc4, 0xff, 0x35, 0x69, 0xc2, 0xdc, + 0xc5, 0xd0, 0x4e, 0x31, 0x69, 0xd8, 0x15, 0x5f, 0x59, 0x35, 0x31, 0x13, 0xbf, + 0xf7, 0x33, 0x1c, 0xd6, 0x51, 0x7f, 0x50, 0xf7, 0x4c, 0x1e, 0xed, 0x81, 0xf5, + 0xec, 0x1e, 0x3a, 0x21, 0x9e, 0xf2, 0xf7, 0x7c, 0x36, 0xbd, 0xe8, 0xb8, 0x86, + 0xe1, 0xd9, 0x7f, 0x5e, 0x2f, 0xb0, 0xdc, 0x89, 0x15, 0xd3, 0x38, 0x81, 0xd5, + 0x8e, 0x16, 0x18, 0x2d, 0xc1, 0xf7, 0x31, 0xc5, 0x70, 0x3c, 0xf3, 0xae, 0x81, + 0xb7, 0xcf, 0xcf, 0xc3, 0x37, 0xab, 0x7f, 0x39, 0x97, 0x0b, 0xde, 0xe3, 0x81, + 0x8b, 0xb9, 0x02, 0x0b, 0xb0, 0xac, 0x4d, 0xaa, 0x01, 0x56, 0x56, 0x36, 0x74, + 0x84, 0x94, 0x7f, 0xd6, 0xd8, 0x47, 0xad, 0xbc, 0xbf, 0xe0, 0x81, 0x9e, 0x2b, + 0xf0, 0xcc, 0x42, 0xbb, 0xdc, 0x11, 0xbc, 0x83, 0xd0, 0xe5, 0xd5, 0x04, 0xd6, + 0x5b, 0x02, 0x51, 0xbe, 0x87, 0xc6, 0x31, 0x2a, 0xe5, 0xf6, 0xe8, 0x81, 0x02, + 0x7f, 0x32, 0x3d, 0xc8, 0x7f, 0xcd, 0x4c, 0x7f, 0x81, 0x25, 0x1a, 0x0d, 0x1a, + 0x6c, 0x7f, 0x22, 0x48, 0x70, 0x63, 0x58, 0x18, 0x81, 0xcf, 0xdc, 0x96, 0x7d, + 0xb0, 0x74, 0xd1, 0xdf, 0x81, 0x46, 0x3a, 0xe3, 0x52, 0x28, 0x7f, 0x81, 0xcd, + 0x56, 0xf2, 0xd9, 0xfb, 0x81, 0xd8, 0x1c, 0xad, 0xf9, 0xcc, 0x46, 0x95, 0xd2, + 0x92, 0xca, 0xe3, 0xdd, 0x6d, 0x2e, 0x3c, 0xfb, 0xd0, 0xc1, 0xde, 0x96, 0xe5, + 0x3a, 0x7f, 0x40, 0xaf, 0x6b, 0xde, 0xb4, 0xf9, 0xfb, 0xce, 0x1e, 0xee, 0xc7, + 0x03, 0x30, 0x14, 0xc5, 0xed, 0xe6, 0x81, 0x7f, 0x89, 0xee, 0xb9, 0xf9, 0xcd, + 0x1b, 0x66, 0xb9, 0x5a, 0x86, 0x34, 0x4c, 0x9f, 0xf0, 0x54, 0x23, 0x0c, 0x7f, + 0xf6, 0x7f, 0x00, 0x81, 0x5f, 0x46, 0x0a, 0x3b, 0xc5, 0x19, 0x2c, 0x12, 0x19, + 0xb4, 0x7f, 0x81, 0x81, 0x53, 0xdd, 0x29, 0x3a, 0x81, 0xf5, 0x7f, 0x1d, 0x09, + 0x0c, 0x2b, 0x2d, 0x13, 0x8f, 0xe0, 0x12, 0x04, 0xef, 0x4c, 0x7f, 0x0f, 0x04, + 0x4a, 0x35, 0xdf, 0x7f, 0xb4, 0xff, 0x85, 0x38, 0xfa, 0x40, 0x05, 0x7f, 0x32, + 0xd5, 0x7f, 0xc7, 0x12, 0x81, 0x53, 0x99, 0xc2, 0xb6, 0xd9, 0xea, 0x27, 0x20, + 0xe9, 0xf4, 0xff, 0x3c, 0x99, 0x7d, 0x62, 0x0b, 0x7f, 0x81, 0x7f, 0x34, 0xa2, + 0xd4, 0x19, 0xcf, 0xb0, 0x1f, 0x7b, 0x1e, 0xcb, 0xd7, 0x4c, 0x34, 0xc0, 0xb3, + 0xb6, 0xcf, 0x9c, 0xf8, 0xb0, 0x04, 0xd7, 0x07, 0xbf, 0x00, 0xb0, 0x4a, 0x7f, + 0x81, 0x81, 0x13, 0x11, 0xd8, 0x88, 0xba, 0x0d, 0x81, 0xe8, 0xc2, 0x2c, 0x1b, + 0x36, 0x0d, 0x24, 0x81, 0x7f, 0xbd, 0x78, 0x3c, 0x04, 0x05, 0xe0, 0x2f, 0x08, + 0x44, 0xaf, 0x57, 0x7f, 0x48, 0xe5, 0xc1, 0x03, 0x03, 0x49, 0xf9, 0xf2, 0xf4, + 0xad, 0xd8, 0x02, 0x58, 0x41, 0x81, 0xc2, 0xaa, 0x0b, 0x1b, 0x01, 0x64, 0x19, + 0xee, 0x7f, 0xf0, 0xe7, 0xd0, 0x19, 0xe5, 0x2f, 0x01, 0x25, 0x17, 0x7f, 0xf0, + 0x06, 0xdd, 0xc1, 0x1d, 0x03, 0x66, 0x39, 0x52, 0xcc, 0x4a, 0x81, 0xde, 0x35, + 0x45, 0x7f, 0x44, 0xef, 0xa4, 0x21, 0xc0, 0xe1, 0x18, 0xfd, 0x7f, 0x42, 0xf6, + 0x9e, 0x81, 0x81, 0x5c, 0x7f, 0xa9, 0x6f, 0x9e, 0x0a, 0x73, 0xe5, 0xdd, 0xd1, + 0xf1, 0x38, 0x4a, 0x1e, 0xf0, 0xb6, 0xde, 0xfc, 0xf6, 0x39, 0xe0, 0xf8, 0x5a, + 0x9e, 0x81, 0xaa, 0xb5, 0xd9, 0xe5, 0xe2, 0xe8, 0xd3, 0xa4, 0x24, 0xc7, 0xc3, + 0x7f, 0x1a, 0xdc, 0xeb, 0x2e, 0x16, 0x0a, 0x30, 0xf0, 0xf2, 0xab, 0xb8, 0x66, + 0x81, 0x95, 0x17, 0x81, 0x7f, 0xba, 0x1a, 0xe9, 0xdd, 0x09, 0x2d, 0x7f, 0x35, + 0xab, 0x04, 0x13, 0x7f, 0xc7, 0x45, 0x09, 0x7f, 0x56, 0x0c, 0x09, 0xea, 0xc4, + 0x19, 0x7f, 0x08, 0x0e, 0xcf, 0xcd, 0x33, 0x28, 0x06, 0x3c, 0xe6, 0x75, 0x08, + 0xd8, 0xf1, 0xb4, 0x2e, 0xff, 0x7f, 0x3d, 0x7f, 0x6f, 0x17, 0x0f, 0x2a, 0x09, + 0x04, 0x1c, 0x96, 0x33, 0x2c, 0x7f, 0xf6, 0x89, 0xe9, 0x09, 0x65, 0xa8, 0x2c, + 0x42, 0xe4, 0xb9, 0xd5, 0xef, 0xed, 0x81, 0x00, 0x45, 0xe5, 0x7f, 0x20, 0x13, + 0x6c, 0x4f, 0x02, 0xbd, 0x59, 0x8c, 0xbc, 0xdd, 0xe1, 0x57, 0xe5, 0x6e, 0x7f, + 0x7e, 0x27, 0x3f, 0xa7, 0x0a, 0x9f, 0x7f, 0x7f, 0x51, 0x16, 0xed, 0xba, 0x91, + 0x06, 0x69, 0xf2, 0xc3, 0x46, 0xb4, 0x81, 0xd7, 0x54, 0xa1, 0x83, 0x20, 0x3f, + 0xef, 0x58, 0x7f, 0xb7, 0x37, 0xd0, 0xf5, 0x23, 0x50, 0xa0, 0xb3, 0x85, 0x4a, + 0x1f, 0xf4, 0x89, 0x3d, 0x7f, 0x7f, 0x96, 0xdb, 0x51, 0x5f, 0xf0, 0x7f, 0xdf, + 0x64, 0x3a, 0x87, 0x7f, 0x7f, 0x25, 0x99, 0xaa, 0xdc, 0xda, 0xd2, 0x67, 0xd9, + 0xab, 0x5c, 0x82, 0xc9, 0x20, 0xe2, 0xfd, 0xdf, 0xf9, 0x09, 0xaa, 0x81, 0xf4, + 0x89, 0x7f, 0x14, 0xf2, 0x0e, 0x24, 0x6b, 0x31, 0x23, 0xd6, 0x00, 0xe2, 0x4a, + 0xac, 0x31, 0x1c, 0xfb, 0xc4, 0x98, 0xd0, 0xcc, 0x66, 0x13, 0x13, 0xcf, 0x5a, + 0x38, 0x81, 0xfc, 0x98, 0x08, 0xaa, 0xc1, 0xbe, 0x33, 0x99, 0x4a, 0xd7, 0x7f, + 0x3f, 0x09, 0x2c, 0xfc, 0xf9, 0x11, 0xcd, 0xa1, 0x30, 0x81, 0xde, 0x7d, 0x7f, + 0x7f, 0x3b, 0xcd, 0x4d, 0x1e, 0x3c, 0x39, 0x83, 0x86, 0xad, 0xb6, 0x7f, 0xd8, + 0x7f, 0x7f, 0xa5, 0xf5, 0xb6, 0xbf, 0x16, 0xfc, 0xc0, 0x18, 0x7f, 0xad, 0x97, + 0x23, 0x81, 0xf2, 0x5f, 0xe8, 0x04, 0xf9, 0x81, 0x89, 0x8c, 0xbd, 0xe9, 0xb6, + 0xd9, 0xbb, 0x3e, 0x26, 0xd2, 0xce, 0x15, 0x6d, 0xe7, 0xd7, 0x62, 0x7f, 0x50, + 0xc3, 0x3d, 0xd4, 0x54, 0xc6, 0x81, 0xe2, 0xd0, 0x8b, 0x5f, 0x92, 0xd2, 0xbc, + 0xdc, 0x93, 0x22, 0x04, 0x7f, 0xc8, 0xf2, 0xa1, 0xe6, 0x3a, 0xba, 0xb1, 0x6c, + 0x31, 0xea, 0xff, 0xfb, 0x19, 0x19, 0x23, 0xf7, 0xfc, 0xf5, 0x35, 0xd1, 0x1e, + 0x4e, 0xd9, 0x81, 0x21, 0xb7, 0xa0, 0xf6, 0xf6, 0x34, 0xfd, 0x17, 0x34, 0x1c, + 0x00, 0xbf, 0x43, 0x9b, 0x07, 0x0e, 0x0f, 0xf2, 0xda, 0xd1, 0x42, 0x2a, 0xb3, + 0x32, 0x89, 0xf3, 0x7f, 0x7f, 0xd7, 0x7f, 0xab, 0x13, 0xd5, 0xea, 0x68, 0x54, + 0xc8, 0x7f, 0x2d, 0x4a, 0xde, 0x14, 0x7f, 0xbe, 0x84, 0xe3, 0x0f, 0xba, 0xee, + 0xff, 0xc0, 0x1f, 0x81, 0x29, 0x88, 0xc1, 0x64, 0x31, 0xd8, 0xdc, 0x20, 0x9d, + 0x70, 0x14, 0xf3, 0x49, 0xee, 0xf1, 0xe0, 0xb5, 0xa0, 0xf3, 0x94, 0x4c, 0xb0, + 0x1c, 0xf8, 0x3c, 0xed, 0x1e, 0x4e, 0xb8, 0x99, 0xfa, 0x4e, 0x16, 0x18, 0x6a, + 0x08, 0x57, 0xa6, 0x4b, 0xe4, 0x94, 0x9e, 0x7f, 0x31, 0xb9, 0x50, 0xab, 0x11, + 0x3a, 0xd5, 0x18, 0x81, 0xf0, 0x50, 0xbf, 0x46, 0xda, 0xae, 0x3e, 0x7f, 0x11, + 0x02, 0x26, 0x07, 0x2a, 0xa6, 0xb6, 0x7f, 0xc1, 0x7f, 0xb6, 0x4f, 0x7f, 0xbe, + 0x05, 0xd6, 0x35, 0x01, 0x2f, 0x9f, 0x68, 0x49, 0x7f, 0x1e, 0x75, 0x3c, 0xb7, + 0x6f, 0xac, 0xfd, 0x07, 0x48, 0x15, 0x05, 0x6d, 0x15, 0xd5, 0x3d, 0x00, 0xf3, + 0xa4, 0x10, 0xf9, 0xa1, 0xdf, 0x6d, 0xaf, 0x03, 0xa9, 0x37, 0x7f, 0xbb, 0x91, + 0x75, 0x5e, 0xc1, 0x7f, 0x3c, 0x07, 0xb5, 0xd2, 0x34, 0xda, 0xe3, 0xf1, 0xe2, + 0x9e, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x12, 0xd3, + 0xfd, 0xe4, 0x0c, 0x1f, 0x00, 0x20, 0xd0, 0xd2, 0xbf, 0x02, 0x26, 0x05, 0x27, + 0xdf, 0x04, 0x17, 0x3b, 0xf9, 0xde, 0xdc, 0x14, 0x32, 0xce, 0xc8, 0x26, 0x11, + 0x0d, 0xd0, 0xda, 0xfd, 0x0e, 0x33, 0x3c, 0x29, 0xdf, 0xe9, 0xea, 0x03, 0xc2, + 0xe8, 0x1c, 0xca, 0xdb, 0x7f, 0xbb, 0xeb, 0xcb, 0x29, 0x16, 0x1d, 0xbb, 0x1b, + 0xeb, 0xf4, 0x05, 0xf2, 0x23, 0xff, 0xc1, 0x1b, 0xdf, 0x58, 0x03, 0x22, 0xa7, + 0xdf, 0x2e, 0x06, 0x90, 0x1d, 0xf7, 0x04, 0x06, 0x28, 0x2c, 0x21, 0xff, 0xf1, + 0x12, 0x9f, 0x06, 0x2a, 0xce, 0xd6, 0xdd, 0x0e, 0xf2, 0x1e, 0x05, 0xfd, 0x38, + 0xdd, 0x38, 0xff, 0x43, 0xfb, 0xc4, 0x1e, 0x2f, 0xee, 0x53, 0xcb, 0xdd, 0xf8, + 0xf4, 0x47, 0xbb, 0x16, 0x3e, 0xc4, 0xf8, 0x0f, 0xeb, 0xfa, 0x0a, 0x36, 0xcf, + 0xe7, 0xe5, 0x0a, 0x0e, 0xe4, 0x9a, 0x14, 0xcc, 0x01, 0xf5, 0x07, 0xd5, 0xba, + 0xe2, 0xef, 0xfc, 0xc5, 0xe4, 0x17, 0x25, 0xed, 0x11, 0xf8, 0xf3, 0xd7, 0xdf, + 0xe7, 0xef, 0x42, 0xed, 0xcc, 0xd0, 0x05, 0xb8, 0xf1, 0xdc, 0x23, 0x63, 0x2e, + 0x16, 0xf0, 0x02, 0xd5, 0x23, 0xfc, 0x43, 0xf9, 0xe4, 0x31, 0xce, 0x0d, 0xdd, + 0x36, 0xed, 0x02, 0xcf, 0xd1, 0xc6, 0x0b, 0x29, 0x7f, 0x33, 0xda, 0x3c, 0xbc, + 0xed, 0xed, 0x18, 0xb3, 0xfc, 0x11, 0x19, 0x55, 0x0f, 0x16, 0xbd, 0x2c, 0xec, + 0x25, 0xf0, 0xe4, 0x08, 0x35, 0x38, 0x05, 0x2a, 0xd1, 0xdc, 0xd9, 0x0c, 0xe2, + 0xda, 0xee, 0x24, 0xd1, 0x01, 0x02, 0x2e, 0xd1, 0x0f, 0x35, 0xcf, 0xd4, 0xe6, + 0x13, 0x19, 0xff, 0x36, 0x02, 0x0f, 0xe5, 0x14, 0xe4, 0xf6, 0xee, 0xed, 0xdd, + 0xd4, 0xcd, 0xc3, 0xff, 0xfb, 0x49, 0xe4, 0xe2, 0xc9, 0xf7, 0xb6, 0xf0, 0xed, + 0x0d, 0x23, 0xf8, 0xdd, 0xff, 0xd8, 0xcf, 0x03, 0x0a, 0x16, 0xdc, 0xf3, 0x0c, + 0x27, 0xfa, 0x00, 0x0d, 0x24, 0x0a, 0xea, 0x2d, 0x11, 0x1c, 0x06, 0xef, 0x75, + 0xfb, 0x0e, 0x10, 0xf0, 0x29, 0xc6, 0xff, 0xe1, 0xfb, 0xf0, 0xeb, 0xee, 0x0c, + 0x35, 0x31, 0x4e, 0x3b, 0x16, 0x09, 0xb2, 0x05, 0x31, 0x28, 0xba, 0x33, 0xd9, + 0x18, 0x3a, 0xb7, 0xf0, 0xe5, 0x17, 0xd8, 0x0d, 0x2f, 0xf8, 0xdc, 0xbc, 0xdd, + 0xf4, 0x3c, 0x20, 0xf4, 0x12, 0x11, 0x1d, 0x3f, 0xee, 0x0d, 0x16, 0x17, 0xaf, + 0xfd, 0xd8, 0xdd, 0x16, 0xf8, 0x1c, 0xc0, 0xff, 0xe7, 0xfa, 0xef, 0x18, 0x03, + 0x0a, 0xdd, 0xfe, 0x18, 0x19, 0xed, 0xec, 0x7f, 0xf2, 0x06, 0xf4, 0x30, 0x04, + 0x10, 0x0a, 0xfb, 0x15, 0xd6, 0x25, 0xd2, 0xe2, 0x02, 0xd8, 0x16, 0x1b, 0x47, + 0x1a, 0x0b, 0xe9, 0xc9, 0x27, 0xd1, 0xc7, 0xfc, 0x06, 0x04, 0x25, 0xd7, 0xe8, + 0xfa, 0x17, 0x07, 0x4d, 0xe8, 0x1d, 0xe3, 0x20, 0xfb, 0xc4, 0xd4, 0xbe, 0x81, + 0xd0, 0xf0, 0x03, 0x0a, 0x0b, 0x5b, 0x00, 0x3c, 0x31, 0x43, 0x3c, 0xfa, 0x23, + 0xcf, 0x2b, 0xdf, 0x3e, 0x5a, 0xed, 0x05, 0xab, 0x5f, 0xcb, 0x05, 0xfb, 0x0b, + 0xd5, 0xed, 0xe9, 0xca, 0x18, 0x2e, 0x39, 0x49, 0xca, 0x0f, 0x44, 0xf4, 0x9c, + 0xa9, 0x14, 0xef, 0xd3, 0x04, 0xed, 0xd0, 0x13, 0xe4, 0x05, 0x2d, 0xb2, 0x11, + 0xff, 0xcb, 0x06, 0xd4, 0x15, 0xad, 0x19, 0x43, 0x0b, 0xf9, 0xec, 0xd8, 0x1f, + 0xcf, 0xd7, 0x03, 0xe3, 0x11, 0x29, 0x1a, 0x24, 0x00, 0x1a, 0xdc, 0x2b, 0x1d, + 0x48, 0xfb, 0xdb, 0xe4, 0xe9, 0xb8, 0x0b, 0x2c, 0x2a, 0x1a, 0xc4, 0x12, 0xc2, + 0xbf, 0xeb, 0xdb, 0x17, 0x7c, 0xfa, 0xe6, 0xfe, 0xe5, 0x0a, 0xdc, 0x11, 0x49, + 0xe3, 0x08, 0x21, 0xf3, 0x39, 0xe7, 0x50, 0x44, 0x03, 0x11, 0xf9, 0x51, 0xfc, + 0xff, 0x2b, 0x2c, 0x12, 0xf5, 0xde, 0x15, 0x12, 0xa7, 0x18, 0xea, 0x12, 0xba, + 0xf2, 0x01, 0xe1, 0x0e, 0x2c, 0xf3, 0xff, 0x10, 0xbd, 0xcc, 0x34, 0xf0, 0x0c, + 0x0b, 0xf3, 0x1b, 0xf9, 0xf9, 0xbf, 0x7f, 0xf0, 0x06, 0x58, 0x4b, 0xcb, 0xf7, + 0x0d, 0xa3, 0x0e, 0x06, 0xe1, 0x17, 0x0d, 0xe4, 0x1d, 0x46, 0x0f, 0xd5, 0xdf, + 0x27, 0xfc, 0x2e, 0xec, 0x30, 0x09, 0xf2, 0x10, 0xc6, 0xd9, 0x00, 0xde, 0x68, + 0x3e, 0x73, 0xea, 0x12, 0xf9, 0xc5, 0xdf, 0x3c, 0x4c, 0x42, 0xe1, 0x08, 0x22, + 0x1f, 0x11, 0x10, 0xcc, 0x22, 0x18, 0x02, 0x51, 0x11, 0x03, 0xee, 0xd6, 0xf1, + 0x31, 0x02, 0xd8, 0x10, 0x0e, 0xf5, 0xd5, 0x3f, 0x0e, 0xea, 0xbf, 0x1d, 0x26, + 0x3a, 0x36, 0x0e, 0x2d, 0x10, 0xf8, 0x4c, 0x5a, 0x2c, 0x16, 0x52, 0xe4, 0x1a, + 0x29, 0xf7, 0x96, 0xcc, 0x38, 0xf2, 0xe3, 0x13, 0x4f, 0x13, 0xc0, 0xfb, 0x14, + 0xe9, 0xf3, 0x01, 0x00, 0x25, 0xce, 0xe7, 0xd4, 0xde, 0xe0, 0xe0, 0x10, 0xd0, + 0x04, 0xfe, 0xce, 0x10, 0xd6, 0xf3, 0x18, 0xaa, 0x07, 0xe4, 0x38, 0x15, 0xe0, + 0xd6, 0xb8, 0xf3, 0x12, 0xc6, 0xf6, 0x3b, 0xfe, 0x6f, 0xfe, 0xe3, 0x13, 0xdd, + 0xcd, 0xf8, 0x12, 0x42, 0x15, 0xf2, 0x4f, 0x04, 0x14, 0xc7, 0xf5, 0xc8, 0xd8, + 0xec, 0xe4, 0x0b, 0xfa, 0xe2, 0x21, 0x1e, 0xdd, 0x3b, 0xd7, 0xf8, 0xe8, 0x44, + 0xc2, 0x10, 0xb0, 0xc8, 0x01, 0xfc, 0x1c, 0xf0, 0xec, 0x00, 0xd2, 0x1f, 0xeb, + 0xe0, 0x07, 0xeb, 0x2d, 0x4c, 0x33, 0x2a, 0x21, 0x99, 0xea, 0x17, 0xe9, 0x2c, + 0xe2, 0xee, 0x11, 0xd3, 0x3a, 0x11, 0x25, 0xd7, 0x89, 0x25, 0x33, 0x43, 0x0e, + 0x24, 0x21, 0x0b, 0xe5, 0x0f, 0x20, 0x0e, 0xc8, 0x39, 0xaa, 0xd8, 0x21, 0x81, + 0xca, 0xed, 0x22, 0x46, 0xf5, 0x0e, 0x20, 0x06, 0xf1, 0x10, 0xce, 0xec, 0xe8, + 0xd8, 0x34, 0x01, 0x13, 0x03, 0x19, 0x18, 0x29, 0xde, 0xbc, 0x0f, 0x3c, 0xcc, + 0xf8, 0x7f, 0xf4, 0xd2, 0x63, 0x00, 0xf0, 0x27, 0xfc, 0xd4, 0xe6, 0x03, 0x32, + 0xf7, 0x4b, 0xc4, 0x0e, 0xdc, 0x0a, 0x05, 0xb4, 0xec, 0xe2, 0xce, 0x04, 0xe4, + 0x0a, 0xb6, 0x1b, 0x12, 0xea, 0x40, 0x0f, 0x56, 0x0a, 0xe5, 0x00, 0x30, 0x25, + 0x04, 0x34, 0x0a, 0xe7, 0xf3, 0xed, 0x07, 0x1d, 0x19, 0x18, 0xf4, 0x11, 0xe6, + 0x01, 0xe4, 0x3e, 0x44, 0xd8, 0xc3, 0x89, 0x05, 0xdb, 0xd0, 0x13, 0x1a, 0xe1, + 0xd0, 0xdf, 0x30, 0x21, 0xd5, 0xf5, 0xcf, 0x24, 0xea, 0xe7, 0x07, 0xd5, 0x15, + 0xfc, 0x18, 0x70, 0xea, 0x27, 0xf8, 0x12, 0x18, 0xe9, 0xb6, 0xeb, 0xeb, 0xdb, + 0x1d, 0xe0, 0x05, 0xc1, 0xef, 0xdc, 0xc3, 0x2c, 0x1d, 0x37, 0xeb, 0xf4, 0x6f, + 0xd8, 0xe9, 0x20, 0xf5, 0xff, 0x15, 0xbd, 0x2a, 0x0f, 0x02, 0xee, 0x02, 0x1a, + 0x4b, 0xeb, 0xd3, 0x03, 0xd0, 0xf0, 0xf3, 0x1b, 0xf3, 0x29, 0x10, 0x06, 0x72, + 0xf6, 0xfa, 0xec, 0xec, 0x30, 0xed, 0xff, 0x3e, 0xdb, 0x1b, 0x17, 0x32, 0xa2, + 0xee, 0x03, 0xe8, 0x7f, 0x1b, 0xdf, 0x5d, 0xea, 0xa0, 0x20, 0x2d, 0x15, 0x0e, + 0xdb, 0x0f, 0xf9, 0x0d, 0x1b, 0xe0, 0x55, 0xce, 0xd9, 0xc2, 0xa5, 0xb6, 0xfa, + 0xf0, 0xbb, 0xe6, 0xea, 0x5c, 0x31, 0x76, 0xa8, 0xc6, 0xd1, 0x47, 0xfa, 0x21, + 0xdd, 0x10, 0x0d, 0x35, 0xd2, 0xfe, 0xe4, 0xe4, 0xf4, 0xcc, 0x3d, 0x67, 0x0a, + 0x12, 0x4c, 0x2b, 0xfa, 0xc8, 0x58, 0xe9, 0x2e, 0xfe, 0x2b, 0xc7, 0x09, 0x5f, + 0x35, 0x34, 0x21, 0x14, 0xe7, 0x3e, 0x19, 0x00, 0x15, 0x6b, 0x21, 0x0c, 0xf8, + 0x5a, 0x27, 0x78, 0x0b, 0x45, 0xf8, 0x21, 0xe1, 0x2e, 0x2d, 0xd5, 0x19, 0xf8, + 0xcf, 0x5e, 0xfd, 0xe1, 0x36, 0x20, 0xcd, 0xef, 0xfa, 0x2a, 0xcf, 0x5d, 0x2a, + 0xda, 0xe5, 0xe1, 0xf5, 0xd9, 0xe1, 0xb5, 0x0e, 0x03, 0xb5, 0xe5, 0xea, 0xbb, + 0xeb, 0x06, 0xf9, 0xe7, 0x16, 0x0d, 0xfe, 0xbe, 0x23, 0xd5, 0x14, 0x1d, 0xf7, + 0xd5, 0xdf, 0xef, 0xec, 0xd4, 0x2d, 0xda, 0xce, 0x3c, 0x98, 0x24, 0x02, 0xfe, + 0xac, 0xd4, 0x53, 0x26, 0xcf, 0xfa, 0xd0, 0xeb, 0x5c, 0xcb, 0x19, 0xd2, 0x21, + 0xde, 0x18, 0x4f, 0xfd, 0x35, 0x16, 0xd7, 0x1e, 0x13, 0x92, 0x1d, 0x1f, 0x00, + 0x54, 0x24, 0x37, 0xf0, 0xd1, 0xe3, 0xba, 0xd5, 0x21, 0xd9, 0xf6, 0xfd, 0xb7, + 0x08, 0xb4, 0xd5, 0x43, 0xe3, 0x1e, 0x05, 0x56, 0xc5, 0x56, 0xd8, 0x3e, 0xef, + 0xe2, 0x08, 0xd4, 0xc5, 0xed, 0x13, 0x2e, 0x25, 0xd1, 0x20, 0xd4, 0xe0, 0xfd, + 0xfb, 0x81, 0xe7, 0xf0, 0xb2, 0xde, 0x00, 0xe5, 0xef, 0xec, 0xd1, 0x08, 0xee, + 0xed, 0xe1, 0x4e, 0xd2, 0xd2, 0xee, 0x25, 0x25, 0x39, 0x8f, 0x05, 0xfa, 0x52, + 0x0f, 0x27, 0x01, 0x07, 0x06, 0xc8, 0x81, 0x11, 0x2d, 0x17, 0xc3, 0xe2, 0x00, + 0x34, 0x6e, 0xf5, 0xe3, 0x36, 0x19, 0x2b, 0xed, 0xe9, 0xc5, 0x61, 0xdb, 0x16, + 0xe3, 0xfe, 0xfe, 0x0f, 0x5c, 0xe7, 0xd4, 0xe0, 0xdb, 0xe9, 0x3a, 0x04, 0xed, + 0xbe, 0xb6, 0x28, 0x25, 0x1a, 0x3e, 0x27, 0xb7, 0xc7, 0x11, 0xb2, 0x1d, 0xbc, + 0x1f, 0x5a, 0x03, 0xa7, 0xeb, 0x4c, 0x47, 0x38, 0x55, 0xf8, 0x0e, 0xff, 0xf8, + 0xc5, 0x19, 0xca, 0xe0, 0x34, 0xed, 0x20, 0x17, 0xc5, 0xc7, 0x09, 0x18, 0xd3, + 0x95, 0xdc, 0xb3, 0x0f, 0xf7, 0xf8, 0x78, 0xc3, 0x29, 0xeb, 0x16, 0xf0, 0x16, + 0x09, 0xf9, 0xe2, 0xdf, 0xe9, 0xa4, 0x15, 0x39, 0x25, 0xf1, 0xe6, 0xf6, 0x1a, + 0xc1, 0x12, 0xd6, 0xd0, 0x0c, 0xfa, 0x00, 0xe6, 0xe5, 0xd6, 0xb9, 0x29, 0x64, + 0x07, 0x10, 0xc9, 0x0c, 0x17, 0xfc, 0xf9, 0x3a, 0xe4, 0xc1, 0x15, 0xdb, 0x01, + 0xcd, 0x4f, 0xc8, 0xbf, 0xda, 0x2a, 0x28, 0x0c, 0x14, 0x0a, 0xbb, 0x15, 0xda, + 0xe8, 0x23, 0xfa, 0x36, 0xf4, 0xe7, 0xd1, 0xe1, 0x27, 0x05, 0x5e, 0x1c, 0x39, + 0x49, 0xf4, 0x0d, 0x12, 0x09, 0x37, 0xcc, 0xc2, 0xcc, 0xff, 0x5e, 0xce, 0xd1, + 0x32, 0x19, 0xf7, 0x02, 0xde, 0x27, 0x0d, 0xcb, 0xf9, 0xf1, 0x16, 0x0d, 0xf9, + 0x16, 0xfe, 0x7f, 0xf7, 0x0b, 0x7a, 0xc7, 0xdf, 0xbd, 0x01, 0x0e, 0x07, 0xe6, + 0xe7, 0x3d, 0x10, 0x04, 0xd3, 0xf7, 0x08, 0xd8, 0x29, 0x76, 0xca, 0xea, 0xf9, + 0x0a, 0x0a, 0x33, 0xe9, 0x15, 0x40, 0xce, 0xd7, 0x28, 0x12, 0xfe, 0xd8, 0xba, + 0xe6, 0x05, 0x3f, 0x43, 0x13, 0xce, 0xf3, 0x2a, 0x30, 0x23, 0x70, 0x1c, 0x11, + 0xca, 0xf1, 0x08, 0x21, 0x1b, 0x05, 0x9f, 0xcc, 0xe4, 0x24, 0xf9, 0x0e, 0x15, + 0x04, 0xfa, 0x0d, 0x17, 0x17, 0x26, 0xe5, 0xf9, 0xbd, 0xea, 0xf8, 0xe2, 0x10, + 0xe1, 0xf4, 0x39, 0xfd, 0x05, 0x0c, 0x10, 0x11, 0xd2, 0x27, 0xf2, 0xf3, 0x01, + 0x21, 0x0c, 0xdd, 0x24, 0x09, 0xf2, 0xf4, 0x02, 0x3f, 0x51, 0xfd, 0x1f, 0xfc, + 0x0f, 0xf3, 0x28, 0xf0, 0xfc, 0xd4, 0xcb, 0xee, 0x50, 0xd6, 0xff, 0x31, 0x22, + 0x06, 0x2a, 0xd5, 0x2b, 0x02, 0xee, 0xd3, 0x0f, 0xf7, 0x0c, 0xef, 0x7f, 0xdb, + 0x36, 0xec, 0xcf, 0x0e, 0xf0, 0x1a, 0xf5, 0x41, 0x2f, 0x10, 0xdd, 0x13, 0xe5, + 0xf5, 0x06, 0x2a, 0x02, 0x13, 0x00, 0x1a, 0x10, 0xea, 0x05, 0x13, 0x12, 0x15, + 0x08, 0x1e, 0x07, 0x2d, 0x5e, 0x2c, 0x14, 0x09, 0x4c, 0xe5, 0x31, 0xf1, 0xff, + 0x24, 0x33, 0xb9, 0x08, 0xfb, 0x03, 0x28, 0xf0, 0x08, 0x4f, 0xde, 0x18, 0xe2, + 0xea, 0x19, 0xf1, 0xfc, 0x33, 0x36, 0x2a, 0x04, 0xf8, 0x21, 0x3f, 0xd7, 0x0d, + 0xdf, 0xf4, 0x26, 0xe0, 0xfc, 0xf9, 0xe4, 0xff, 0x07, 0x00, 0xe1, 0x12, 0xfe, + 0x55, 0xd4, 0x51, 0x10, 0x1a, 0x4b, 0x0c, 0x26, 0xf9, 0xfe, 0x28, 0x05, 0x20, + 0xfe, 0x0e, 0xb8, 0xc2, 0x18, 0xe5, 0x19, 0x3a, 0xce, 0xf7, 0x06, 0x06, 0xb3, + 0xea, 0xfc, 0xf6, 0xf1, 0xe9, 0xfa, 0xf4, 0xe7, 0xd7, 0x1b, 0x10, 0xd9, 0x28, + 0xc7, 0xfe, 0xfa, 0x20, 0x23, 0x03, 0x0c, 0xfc, 0xdc, 0xf2, 0xe0, 0xf0, 0xf0, + 0x15, 0x3e, 0xb7, 0xd5, 0x04, 0xf6, 0x7f, 0x14, 0xdb, 0xef, 0x56, 0xe2, 0x07, + 0x29, 0x06, 0x0d, 0xe7, 0x13, 0x43, 0xef, 0xee, 0xf6, 0x26, 0xec, 0xfb, 0xdf, + 0xb5, 0x08, 0x1c, 0xde, 0x07, 0x37, 0xe0, 0xa4, 0x1a, 0x17, 0xe7, 0x20, 0xdf, + 0xce, 0x07, 0x1e, 0x4a, 0x00, 0xf9, 0x0e, 0xb7, 0x1d, 0xf5, 0xe8, 0xd7, 0x3e, + 0xc0, 0xd6, 0xf7, 0x01, 0x25, 0x0d, 0xec, 0x05, 0x13, 0x0d, 0xf4, 0xa2, 0x14, + 0x26, 0xe8, 0x22, 0xcd, 0x15, 0x1d, 0xe2, 0xf1, 0x3e, 0xf5, 0x05, 0xfa, 0xc4, + 0x11, 0x30, 0x32, 0xd7, 0xd4, 0x04, 0x12, 0x0d, 0x48, 0xe3, 0xa7, 0x07, 0xf0, + 0x87, 0x7a, 0xe9, 0x60, 0x5b, 0x00, 0xcb, 0xd4, 0xb6, 0x9d, 0x4a, 0x51, 0xf4, + 0xd5, 0xc5, 0xe2, 0x7f, 0xf6, 0x33, 0xc8, 0x6b, 0x06, 0x37, 0xdc, 0xdf, 0x26, + 0x0a, 0x50, 0x00, 0x1c, 0x3f, 0xc1, 0x0d, 0x33, 0xd7, 0x1f, 0x90, 0xf9, 0xf3, + 0xe7, 0x15, 0xac, 0xe6, 0x11, 0x12, 0xfe, 0x26, 0x22, 0x22, 0x63, 0xf8, 0xa5, + 0x4d, 0xeb, 0xc5, 0x54, 0x34, 0xc2, 0xec, 0x33, 0x33, 0x65, 0x0d, 0x3a, 0x4e, + 0x1a, 0x05, 0xcf, 0x11, 0x1c, 0xbf, 0x46, 0x6a, 0xe1, 0xfc, 0x34, 0x89, 0x42, + 0x2a, 0xea, 0xc4, 0xdb, 0xcc, 0x40, 0xe7, 0xf7, 0xf2, 0x92, 0xdc, 0x0d, 0x55, + 0x0e, 0x0a, 0xfc, 0x14, 0x06, 0xf5, 0x1a, 0xb6, 0x0e, 0xd1, 0x53, 0xdb, 0x36, + 0x12, 0x16, 0x08, 0xd4, 0x16, 0x0f, 0x33, 0xef, 0xc4, 0x4b, 0xb1, 0x1e, 0xf6, + 0xe5, 0x47, 0x0a, 0xfe, 0xc4, 0xfd, 0x04, 0x35, 0xfc, 0x15, 0x2b, 0xe2, 0x23, + 0x0c, 0x2a, 0x17, 0x7f, 0xc5, 0xe2, 0xb6, 0xb3, 0x23, 0xf3, 0xd0, 0xac, 0xe5, + 0xd0, 0xc5, 0xf7, 0xe2, 0xf4, 0x06, 0x1b, 0x0d, 0x1e, 0xe8, 0x10, 0x0b, 0xe8, + 0x1d, 0xe3, 0xdd, 0xc0, 0xe2, 0x15, 0xc7, 0x3f, 0xe9, 0xf5, 0xca, 0x0b, 0xf1, + 0x5e, 0x4c, 0x6e, 0xf3, 0xce, 0xde, 0xf9, 0xec, 0x33, 0xe8, 0xf3, 0x13, 0xe1, + 0x1a, 0xf5, 0x08, 0xf3, 0x1b, 0x3c, 0x1e, 0xf0, 0xd7, 0x18, 0xfe, 0x2e, 0x24, + 0xff, 0x08, 0x3f, 0xa6, 0x36, 0x31, 0xe0, 0x12, 0x0d, 0xd1, 0x49, 0xeb, 0x6e, + 0xdb, 0x3e, 0xea, 0x08, 0xe0, 0xc0, 0x19, 0xd8, 0x04, 0xcc, 0xd9, 0x02, 0xff, + 0x0d, 0x31, 0x00, 0xcb, 0x0e, 0xed, 0x57, 0x1d, 0xe0, 0xdb, 0x6a, 0xf0, 0xf3, + 0xee, 0xbd, 0xc2, 0x27, 0x06, 0xe4, 0xf0, 0x15, 0xcb, 0x09, 0xdf, 0x10, 0xe4, + 0xdf, 0xbb, 0xe2, 0x1b, 0x1b, 0x19, 0x14, 0xb6, 0x1a, 0x95, 0x50, 0xdf, 0x32, + 0xfd, 0xd6, 0x20, 0x1e, 0x00, 0x20, 0x14, 0x3f, 0x3d, 0x38, 0x09, 0x10, 0x31, + 0x28, 0x0f, 0xeb, 0xfb, 0xda, 0xd2, 0x0c, 0xe7, 0x31, 0xe8, 0x0f, 0x1e, 0xdb, + 0x30, 0x27, 0xa2, 0x00, 0x03, 0xfe, 0x01, 0x08, 0xe7, 0x89, 0xdd, 0x9b, 0x7f, + 0x0b, 0x01, 0xf1, 0xea, 0xf5, 0xdc, 0xae, 0xf5, 0x28, 0x02, 0x42, 0xfb, 0x53, + 0xea, 0x25, 0x13, 0x18, 0xfc, 0x19, 0x10, 0x3a, 0xe5, 0x04, 0xe5, 0xf4, 0x0b, + 0xf8, 0xfa, 0xff, 0x29, 0x3e, 0x0b, 0x15, 0x00, 0x26, 0xfb, 0x2f, 0x08, 0x2c, + 0xc9, 0x12, 0xda, 0xe2, 0x1f, 0xe1, 0x2c, 0x4f, 0x69, 0x13, 0x07, 0xcb, 0xd6, + 0xe6, 0x1c, 0xf7, 0x15, 0x04, 0x19, 0xd8, 0x06, 0x24, 0x03, 0x04, 0x0b, 0xe3, + 0xf8, 0x1b, 0xce, 0xeb, 0x01, 0x05, 0xf9, 0x05, 0xff, 0xdd, 0xe9, 0x16, 0x1f, + 0x0b, 0x0f, 0xed, 0xd8, 0x32, 0x27, 0xda, 0xe4, 0x2a, 0xfb, 0xd1, 0xed, 0x07, + 0xd9, 0xfd, 0x13, 0xe9, 0x11, 0x0d, 0xd3, 0xf9, 0x11, 0xf8, 0xfa, 0xc4, 0xe6, + 0xe5, 0x0c, 0xd8, 0xed, 0x10, 0xcf, 0xf9, 0xd9, 0x50, 0x0b, 0x18, 0xf8, 0xe2, + 0xf5, 0xe9, 0xee, 0xea, 0xe3, 0x10, 0x2f, 0xd5, 0xf4, 0xe5, 0xdf, 0xd3, 0xde, + 0x22, 0x09, 0xf2, 0x02, 0xe1, 0xfc, 0xf2, 0xe3, 0xb7, 0x25, 0x05, 0x22, 0xd0, + 0x1d, 0x10, 0x39, 0xf4, 0xf8, 0xd2, 0x09, 0x20, 0x7f, 0xe8, 0x1a, 0x13, 0x0c, + 0x11, 0xf6, 0x10, 0xe9, 0xf0, 0x17, 0x33, 0xd2, 0xf7, 0xde, 0x0a, 0xe3, 0xd6, + 0xf8, 0x12, 0x00, 0xb4, 0x05, 0xe0, 0x00, 0x1a, 0xef, 0xdc, 0xd0, 0x11, 0xe0, + 0x41, 0xdf, 0x06, 0x13, 0x15, 0x1e, 0xe8, 0xc2, 0xc0, 0xe7, 0x16, 0x19, 0xed, + 0x50, 0xd5, 0xe2, 0x04, 0xcb, 0x17, 0x04, 0x0c, 0xa6, 0xa6, 0x06, 0xee, 0x33, + 0x1a, 0x44, 0x30, 0x12, 0xda, 0x39, 0x15, 0x9a, 0xea, 0x22, 0x1a, 0xc8, 0x21, + 0xd2, 0xcb, 0x37, 0xcb, 0x04, 0xe6, 0x48, 0x03, 0x28, 0x13, 0x0a, 0xf4, 0xdd, + 0xea, 0xd8, 0xed, 0x99, 0xfa, 0xb7, 0xce, 0xec, 0x26, 0xfb, 0x2e, 0x23, 0x3e, + 0xfa, 0x9e, 0xb7, 0xc7, 0x3d, 0x36, 0xdc, 0xf3, 0x32, 0x33, 0xe3, 0xf3, 0xe4, + 0xfd, 0x0e, 0xef, 0xef, 0xc8, 0xe1, 0xeb, 0x52, 0x11, 0xd7, 0xf2, 0xd3, 0x30, + 0xec, 0x53, 0xe4, 0xe8, 0x7f, 0x01, 0xf3, 0x28, 0xdb, 0x45, 0x2c, 0xf7, 0x33, + 0x0b, 0x20, 0x00, 0x5d, 0xf6, 0x25, 0xd4, 0x04, 0xf7, 0x1b, 0x1a, 0x03, 0x14, + 0xb8, 0x10, 0xdd, 0xe9, 0x31, 0x3c, 0xd5, 0x01, 0xfb, 0xfd, 0xd2, 0xd7, 0x37, + 0xdf, 0x0a, 0x40, 0x1f, 0xe5, 0xd8, 0xd7, 0x9f, 0xcd, 0xe6, 0x1f, 0x02, 0xf9, + 0xe2, 0x7b, 0x2f, 0x2f, 0x22, 0x03, 0xf1, 0xfc, 0x19, 0xd5, 0x41, 0x03, 0x4d, + 0xf7, 0xd1, 0x19, 0x30, 0x04, 0xae, 0x25, 0x59, 0x7f, 0xc4, 0x09, 0x28, 0x31, + 0x0b, 0x24, 0xb8, 0x6e, 0xbd, 0xe7, 0x33, 0xd4, 0xfa, 0xda, 0x1e, 0xe3, 0xe6, + 0x2a, 0xb5, 0x2d, 0x1f, 0xf8, 0xbc, 0x48, 0x09, 0x2e, 0xfe, 0x4a, 0x24, 0x13, + 0xd1, 0xde, 0x52, 0xb8, 0x34, 0x9f, 0x12, 0xd2, 0xd5, 0xf5, 0xd6, 0x03, 0x14, + 0x1f, 0x11, 0x15, 0x47, 0x71, 0x13, 0x02, 0xde, 0xdc, 0xd9, 0x01, 0x64, 0x51, + 0x04, 0xb0, 0x1d, 0x22, 0x03, 0xc7, 0xbc, 0x24, 0xc1, 0xca, 0x0d, 0x04, 0x41, + 0x1c, 0x3b, 0xcc, 0x11, 0xdd, 0x0b, 0xe8, 0x34, 0x30, 0xf9, 0xf1, 0x30, 0xba, + 0xde, 0x94, 0x07, 0x4a, 0x30, 0x4d, 0x20, 0x13, 0x04, 0xf5, 0xda, 0xf1, 0xe4, + 0xfe, 0x24, 0x43, 0xf2, 0xfc, 0x0a, 0xd3, 0x1b, 0x14, 0x0f, 0xd6, 0xf4, 0xfa, + 0xf4, 0x15, 0xed, 0x41, 0x37, 0xdc, 0xe3, 0xe6, 0xe9, 0x0d, 0xff, 0x11, 0xcc, + 0x1b, 0x66, 0x44, 0x9e, 0x27, 0x1a, 0x33, 0xf7, 0x18, 0xc2, 0xdf, 0xea, 0x28, + 0x0f, 0xf5, 0x02, 0x06, 0x1c, 0xe7, 0x09, 0xf2, 0x35, 0xf1, 0x05, 0x1d, 0x9d, + 0x3a, 0x03, 0x1c, 0x41, 0xd4, 0xfb, 0x56, 0x12, 0x1d, 0x15, 0xf6, 0x09, 0x0e, + 0xe4, 0xee, 0x05, 0x0c, 0xb3, 0xee, 0xc9, 0xea, 0xe2, 0x41, 0xe0, 0xdb, 0x19, + 0x35, 0xf7, 0x6b, 0x2f, 0xdf, 0xc2, 0xff, 0x03, 0xeb, 0xf2, 0x3e, 0x19, 0xcf, + 0x32, 0xfa, 0xb8, 0x2f, 0x04, 0x25, 0xca, 0x1f, 0x09, 0x68, 0x3e, 0x13, 0x07, + 0xdc, 0x07, 0x01, 0xe4, 0x1b, 0x7f, 0x38, 0xf5, 0xff, 0xf8, 0xe0, 0xf3, 0x05, + 0x04, 0xdb, 0xdf, 0x33, 0x31, 0x1d, 0xf6, 0x1e, 0xe2, 0x0b, 0x10, 0xf9, 0x0a, + 0x0d, 0xaf, 0xdb, 0xe6, 0xde, 0x10, 0x04, 0x11, 0xb5, 0xd3, 0x37, 0xd0, 0xe7, + 0x0f, 0x16, 0xd5, 0xd1, 0x13, 0xd0, 0x1e, 0x18, 0x3b, 0xda, 0x01, 0x35, 0x1c, + 0xe7, 0xba, 0xfd, 0xe3, 0x2d, 0x8e, 0x18, 0x3c, 0xf1, 0x05, 0x29, 0x05, 0x30, + 0xa6, 0xd5, 0x09, 0xf0, 0x7f, 0xe2, 0xe0, 0xdf, 0xe6, 0xd6, 0xef, 0x0d, 0xb9, + 0x16, 0x3f, 0x06, 0x0c, 0x2a, 0xdf, 0x2f, 0x16, 0xeb, 0xe8, 0xbf, 0x6e, 0xf2, + 0xe8, 0xc9, 0x7c, 0x30, 0xf4, 0xdd, 0xef, 0xeb, 0xd2, 0xbb, 0x1e, 0x01, 0x01, + 0x3c, 0xdf, 0xe1, 0xff, 0xc1, 0x28, 0xde, 0x07, 0x2b, 0x0a, 0x14, 0xb9, 0x13, + 0xcc, 0x23, 0xfe, 0x57, 0xfb, 0xbb, 0xed, 0x05, 0x20, 0x36, 0xc1, 0x52, 0xf7, + 0xb6, 0x59, 0x0e, 0xf0, 0xe8, 0xe1, 0xf9, 0xee, 0xf6, 0x30, 0x07, 0x0a, 0x52, + 0x3d, 0xf4, 0xe8, 0xe0, 0x06, 0xdb, 0xe8, 0x0a, 0x45, 0x18, 0x2d, 0xd2, 0xb4, + 0xef, 0xc7, 0xb6, 0xe9, 0xc8, 0x5f, 0x0d, 0xc9, 0x05, 0xef, 0x4a, 0xd9, 0xb1, + 0x32, 0x0d, 0x44, 0x18, 0x90, 0x0a, 0x1f, 0xf4, 0xe8, 0xf2, 0x86, 0xec, 0x66, + 0x19, 0x1e, 0x04, 0x6f, 0xb0, 0xda, 0x1f, 0x07, 0x00, 0xde, 0x41, 0xc9, 0xeb, + 0x41, 0xeb, 0x14, 0xa1, 0x0a, 0xec, 0xb1, 0x62, 0xae, 0x0d, 0x9b, 0xd7, 0x14, + 0xeb, 0x0e, 0x13, 0xff, 0x47, 0xcc, 0xfc, 0x49, 0xca, 0x58, 0xc2, 0x26, 0xb8, + 0x1d, 0x45, 0xa7, 0xec, 0xe5, 0x33, 0x0f, 0x01, 0xc7, 0x06, 0xca, 0xf3, 0xd3, + 0x2a, 0xfc, 0xda, 0x0c, 0x05, 0xc4, 0x03, 0xda, 0x44, 0xd1, 0xed, 0xd8, 0x2a, + 0x0f, 0x2e, 0x19, 0xf1, 0x06, 0x2f, 0xee, 0xcd, 0xe9, 0xda, 0x30, 0x03, 0x19, + 0x04, 0x62, 0xf6, 0x19, 0xdc, 0xe5, 0x61, 0xb4, 0xef, 0xf6, 0x81, 0xa6, 0xdb, + 0x59, 0xdf, 0xf1, 0x00, 0xdb, 0x08, 0xf0, 0x2c, 0xc7, 0xef, 0xc0, 0xe0, 0xe5, + 0x0a, 0x01, 0x2b, 0x2d, 0x09, 0xff, 0x82, 0xf4, 0xe0, 0xf0, 0xd0, 0xd2, 0x59, + 0x7d, 0x20, 0xc5, 0x34, 0xa9, 0x3f, 0x4b, 0xd5, 0x02, 0xe3, 0x1a, 0xf0, 0xbb, + 0xe6, 0xd9, 0xe7, 0xfa, 0x0f, 0x35, 0xef, 0xd7, 0xdb, 0x06, 0x40, 0xf0, 0xa9, + 0xff, 0xf0, 0x22, 0x37, 0xfe, 0xe7, 0x25, 0xa3, 0x34, 0xd4, 0x2d, 0xdf, 0x14, + 0x90, 0x29, 0x2a, 0x1c, 0xc5, 0x3f, 0xd3, 0xdc, 0x06, 0x0c, 0xb6, 0x7f, 0x69, + 0x52, 0x10, 0xca, 0x10, 0x27, 0xc2, 0xc1, 0xdc, 0xc1, 0x02, 0xe8, 0x21, 0xff, + 0xf6, 0x15, 0x17, 0xf7, 0xcb, 0x1f, 0x14, 0xa2, 0xe3, 0xcc, 0x5a, 0x0e, 0x46, + 0x10, 0xcd, 0x00, 0x12, 0xd5, 0x0e, 0xf4, 0xc9, 0x28, 0xc3, 0xb8, 0xf0, 0x01, + 0xb4, 0xf4, 0x1d, 0x8a, 0x33, 0x1a, 0xde, 0xdb, 0x37, 0x11, 0xf1, 0x1a, 0x14, + 0xfd, 0x4f, 0xd4, 0xc2, 0x09, 0xed, 0x3a, 0xf8, 0xb3, 0xc3, 0xec, 0x34, 0x05, + 0xe0, 0x35, 0x11, 0xd6, 0x08, 0xe8, 0xc4, 0x2b, 0x22, 0xf6, 0xf8, 0x02, 0x24, + 0x19, 0x46, 0xde, 0xaf, 0x34, 0xff, 0x04, 0xe7, 0x11, 0x16, 0xe5, 0xbd, 0xe5, + 0x1a, 0x1a, 0xf9, 0xe1, 0x16, 0x16, 0x5d, 0xf1, 0xbe, 0x32, 0xd7, 0x05, 0x01, + 0xd5, 0xee, 0xd2, 0x39, 0xd2, 0x1a, 0xe3, 0xea, 0x57, 0x6a, 0x31, 0xa5, 0xe4, + 0xc9, 0xf8, 0x05, 0xa4, 0xc8, 0x25, 0xde, 0xaf, 0x13, 0x7f, 0x16, 0xb7, 0xb2, + 0xfa, 0x32, 0xe2, 0x4e, 0x11, 0xa5, 0x3b, 0x06, 0xee, 0x42, 0xd8, 0x3a, 0xfd, + 0xc6, 0x1f, 0x50, 0x11, 0xf8, 0x30, 0xf6, 0xeb, 0xfd, 0xf4, 0xfa, 0xf7, 0x38, + 0x0b, 0x3a, 0x34, 0x47, 0xf8, 0x25, 0xfc, 0xe4, 0x19, 0x35, 0x2e, 0xd2, 0xcb, + 0xd5, 0xe8, 0x24, 0xcb, 0x05, 0x21, 0x12, 0xf2, 0xfb, 0x1e, 0x34, 0xed, 0xfe, + 0xf6, 0x39, 0xde, 0x27, 0x0a, 0x28, 0x1a, 0x21, 0x0b, 0x11, 0x00, 0xf5, 0xf7, + 0x02, 0x35, 0x0f, 0xe0, 0x1f, 0xe5, 0xd9, 0x70, 0x2e, 0x08, 0xd6, 0x3a, 0x1f, + 0xda, 0x0f, 0x0a, 0xf0, 0xdb, 0xe3, 0x01, 0xe6, 0xe2, 0xdb, 0xec, 0xf5, 0xf6, + 0x0a, 0x8e, 0xd8, 0xf7, 0xb1, 0xef, 0x26, 0x0a, 0x1a, 0x19, 0xc2, 0x09, 0xe1, + 0xe4, 0x44, 0xdc, 0x35, 0x19, 0x16, 0xea, 0xb9, 0x27, 0x05, 0x24, 0x25, 0xda, + 0xfa, 0xe7, 0x0e, 0x0c, 0xfc, 0x42, 0xa9, 0xd8, 0x1c, 0x23, 0x4a, 0x4c, 0xf8, + 0x40, 0x11, 0xf4, 0x26, 0xf2, 0xeb, 0xca, 0x0b, 0xe7, 0xfc, 0x2a, 0xd2, 0x08, + 0xd0, 0xf5, 0xb8, 0xf9, 0x61, 0x0e, 0xf6, 0xdc, 0xe4, 0xdb, 0xd5, 0xfd, 0xb2, + 0x07, 0x0f, 0xc0, 0x81, 0x00, 0x22, 0xfe, 0xdb, 0x0c, 0xc6, 0xff, 0x15, 0x20, + 0xfa, 0xbc, 0xd2, 0xc6, 0xb9, 0xf6, 0xf2, 0xfa, 0x19, 0x28, 0xef, 0x32, 0xe3, + 0xec, 0x28, 0x1a, 0x59, 0xc9, 0xf8, 0x08, 0xc6, 0x20, 0xf3, 0x22, 0xcd, 0xbe, + 0x20, 0x29, 0xd4, 0x0f, 0x30, 0x36, 0xc2, 0x1f, 0x0e, 0xdc, 0x4f, 0xf9, 0x03, + 0xd6, 0x1c, 0x42, 0xed, 0xee, 0x15, 0x24, 0x33, 0xe7, 0x61, 0x05, 0xc8, 0x0d, + 0x3c, 0xc8, 0x00, 0xdd, 0xe1, 0x15, 0x4e, 0x22, 0xfe, 0x2d, 0x04, 0x00, 0x44, + 0xc3, 0xee, 0x17, 0xf8, 0x36, 0xee, 0x2c, 0x3c, 0xec, 0x7f, 0x04, 0x18, 0xc6, + 0xc3, 0x1f, 0xd6, 0x1f, 0xcb, 0xfe, 0x26, 0xeb, 0x09, 0x4a, 0x33, 0x15, 0x41, + 0x27, 0x05, 0x18, 0x5d, 0x06, 0xf7, 0xf9, 0x04, 0xd5, 0xf3, 0xff, 0x2d, 0xea, + 0xd7, 0x5c, 0x1c, 0xcb, 0x1c, 0x1d, 0x0d, 0xd6, 0x42, 0x15, 0x6f, 0x6f, 0x27, + 0xdf, 0x02, 0x1b, 0x03, 0x21, 0x2d, 0x43, 0x0a, 0x14, 0xf5, 0xe8, 0xef, 0x49, + 0x10, 0x1e, 0x1e, 0xf6, 0x52, 0x33, 0xfe, 0x21, 0x23, 0xd3, 0xed, 0xd6, 0x15, + 0xed, 0xdb, 0x27, 0x02, 0xb8, 0x30, 0x2c, 0xf7, 0xe4, 0xf4, 0x35, 0xc2, 0xbf, + 0xd7, 0xdd, 0xf9, 0x42, 0xfe, 0xd7, 0x20, 0xd8, 0x7f, 0xf7, 0xc2, 0x2b, 0x28, + 0xee, 0x00, 0xce, 0x09, 0xe3, 0x23, 0x23, 0xc9, 0x13, 0xf7, 0x14, 0xe7, 0xd4, + 0xf8, 0xf3, 0x22, 0xf3, 0xf4, 0x07, 0xa1, 0xf4, 0xbb, 0x03, 0xb3, 0x29, 0x17, + 0x20, 0xff, 0xe8, 0x05, 0x56, 0x72, 0x2a, 0x3b, 0x3c, 0xf6, 0x03, 0x27, 0xb6, + 0xf5, 0x15, 0xdc, 0x7f, 0x56, 0x0c, 0xd7, 0xed, 0x76, 0xb2, 0x15, 0x49, 0xf5, + 0x03, 0xde, 0xd6, 0x09, 0xc6, 0xe2, 0x28, 0x32, 0xe1, 0x29, 0x53, 0xfe, 0x34, + 0xf8, 0xe5, 0x05, 0x29, 0x09, 0xed, 0x51, 0x0a, 0x33, 0xf6, 0xf1, 0xfa, 0x0c, + 0xf4, 0x24, 0xad, 0x42, 0xe0, 0xa7, 0xfc, 0xc9, 0xad, 0x04, 0xeb, 0x31, 0x22, + 0xdd, 0x14, 0xf7, 0x0b, 0x9e, 0x0d, 0xd2, 0xee, 0xdd, 0xfb, 0x03, 0xca, 0x0a, + 0x0c, 0xdf, 0xd8, 0x16, 0xf3, 0xcb, 0x5a, 0x38, 0xe7, 0xd9, 0xee, 0xd6, 0x01, + 0x0c, 0xc4, 0x5d, 0xfd, 0xe7, 0xee, 0x0a, 0xf7, 0x25, 0x5d, 0x0b, 0xd9, 0x10, + 0xda, 0xd4, 0xfb, 0xc3, 0x06, 0x2f, 0x1f, 0x20, 0xe1, 0x09, 0xf6, 0x19, 0x0a, + 0x2c, 0xda, 0xa2, 0xec, 0xda, 0x21, 0x0f, 0x25, 0xc3, 0xf3, 0xeb, 0x40, 0xe5, + 0x01, 0xe9, 0x04, 0xf8, 0x05, 0xcf, 0xe4, 0x51, 0x35, 0x0c, 0xea, 0xe3, 0xc0, + 0xdc, 0xd6, 0xec, 0x64, 0x38, 0x7f, 0xd3, 0x5f, 0xde, 0x08, 0xe7, 0x2e, 0xfe, + 0xec, 0xd5, 0xeb, 0x33, 0xe0, 0xcf, 0x19, 0xde, 0x36, 0xf4, 0xe8, 0x19, 0xdb, + 0xee, 0xf3, 0xf4, 0x27, 0x22, 0x12, 0xf4, 0xd8, 0xe3, 0xd0, 0xe2, 0x14, 0x3e, + 0xfa, 0xed, 0xeb, 0x03, 0xfb, 0x49, 0x0a, 0x31, 0xec, 0x22, 0xe4, 0x8e, 0xf7, + 0xed, 0xd5, 0xf2, 0x09, 0xe0, 0x0f, 0xea, 0xa8, 0xec, 0x3a, 0x11, 0xd7, 0xc9, + 0x14, 0x93, 0x17, 0xff, 0x01, 0xeb, 0x0e, 0x02, 0xe8, 0x6a, 0xe1, 0x3d, 0x3a, + 0xb7, 0xd2, 0xdd, 0x18, 0x3f, 0xf2, 0x4a, 0xc6, 0x08, 0x7f, 0x56, 0xe5, 0xe5, + 0x36, 0xe7, 0xee, 0xe4, 0xa1, 0x95, 0xb0, 0x47, 0x04, 0x19, 0xfd, 0xdd, 0x28, + 0xd6, 0x4a, 0xd1, 0x04, 0xcf, 0xbd, 0xf1, 0x9b, 0xfc, 0xe5, 0x2a, 0x2c, 0x29, + 0xfc, 0xcd, 0x2a, 0xb3, 0x0a, 0xe9, 0x0f, 0x94, 0x6d, 0x20, 0x2b, 0xff, 0xc3, + 0xe9, 0x12, 0xb3, 0xa6, 0x5a, 0xbf, 0xfb, 0x14, 0x36, 0x2a, 0x05, 0x3b, 0x51, + 0x0f, 0xf9, 0xc7, 0xdd, 0xdb, 0x30, 0x9d, 0xbc, 0x2f, 0x07, 0x0b, 0x28, 0x1a, + 0xb4, 0xbd, 0x1c, 0x0a, 0x5c, 0x32, 0xe0, 0xee, 0x1a, 0x15, 0x22, 0x13, 0x03, + 0x1d, 0xfb, 0x02, 0x6c, 0xcb, 0x01, 0x62, 0xc2, 0x1f, 0x4d, 0x19, 0x3d, 0x31, + 0xf5, 0x04, 0xee, 0xf9, 0x45, 0x38, 0x05, 0x08, 0xe9, 0xdd, 0x2a, 0xe4, 0xc3, + 0xfc, 0x13, 0x02, 0xe5, 0x30, 0xf0, 0x12, 0xe9, 0x4a, 0xda, 0x21, 0x29, 0x30, + 0x2e, 0xc0, 0x36, 0x05, 0xe0, 0xaa, 0xda, 0x10, 0xd2, 0x32, 0xeb, 0xf3, 0xf0, + 0x7f, 0x22, 0x36, 0x08, 0xec, 0x9b, 0xb6, 0xdb, 0xe1, 0xfe, 0x07, 0xd7, 0xf2, + 0xb3, 0x0e, 0x1e, 0xec, 0x25, 0x32, 0x1d, 0x2d, 0x11, 0x1e, 0xe1, 0x69, 0x35, + 0x23, 0x51, 0x00, 0xf1, 0x64, 0xfd, 0xba, 0x51, 0xdb, 0xfb, 0xcb, 0xfa, 0x4f, + 0x01, 0x22, 0x37, 0x3c, 0x2d, 0x47, 0xc9, 0xe4, 0x0e, 0x0a, 0xc2, 0x6b, 0xa4, + 0x01, 0xbd, 0xe4, 0xd4, 0xde, 0x60, 0x0e, 0x00, 0xc6, 0x39, 0x06, 0xed, 0xf3, + 0xcf, 0xfb, 0x3a, 0xf4, 0xdd, 0xf4, 0xd5, 0x22, 0x2f, 0x10, 0x57, 0x25, 0x09, + 0xdc, 0x37, 0xb7, 0x09, 0xf5, 0x18, 0xfe, 0x28, 0x27, 0x10, 0x49, 0x18, 0xde, + 0x08, 0xd3, 0x1b, 0x1d, 0xee, 0xc6, 0x55, 0xde, 0xd0, 0xf1, 0xff, 0xeb, 0x18, + 0x79, 0xfd, 0xbf, 0xf3, 0x05, 0x09, 0x1e, 0x24, 0xec, 0xc7, 0xe5, 0xfe, 0x0c, + 0x25, 0x3a, 0x7f, 0xf9, 0x0a, 0xd2, 0x3a, 0xc1, 0x01, 0x50, 0x05, 0xe9, 0x37, + 0x20, 0xfc, 0xe7, 0x1b, 0xf8, 0xeb, 0xdc, 0x13, 0xec, 0x1e, 0x0f, 0xef, 0x29, + 0xe7, 0xbf, 0x03, 0xda, 0x02, 0xdf, 0xea, 0x10, 0xe9, 0xfa, 0x77, 0xed, 0x47, + 0xe2, 0x1d, 0x1d, 0x0c, 0x66, 0xe4, 0xca, 0xc0, 0x1d, 0x6f, 0xfa, 0xeb, 0x0f, + 0xb3, 0xfb, 0xec, 0xff, 0x04, 0xd4, 0xe1, 0x08, 0x34, 0xc3, 0xe3, 0xe2, 0x03, + 0xde, 0x0c, 0xeb, 0xfb, 0x1a, 0x12, 0xe6, 0xdc, 0x19, 0x31, 0xfe, 0xe0, 0x16, + 0x4d, 0x32, 0x51, 0xe7, 0xdf, 0x13, 0xcf, 0x41, 0xf9, 0x4b, 0x28, 0xf9, 0xea, + 0xe9, 0xbd, 0x15, 0xcc, 0x28, 0x18, 0xef, 0xba, 0xdf, 0x26, 0x2c, 0x1b, 0xde, + 0x09, 0xeb, 0xe9, 0x0d, 0xb4, 0x6e, 0xcc, 0x43, 0x1a, 0x2b, 0xf1, 0xf9, 0x3c, + 0xe5, 0x30, 0x28, 0x05, 0xd8, 0x3e, 0x45, 0x17, 0xe2, 0xde, 0x1f, 0x2e, 0x30, + 0x34, 0xcc, 0xb2, 0xda, 0xd8, 0xf7, 0xe0, 0x0f, 0xf4, 0x94, 0x03, 0xc4, 0xcf, + 0x46, 0x3f, 0x18, 0xd8, 0x7f, 0x29, 0x0a, 0xa1, 0x27, 0x48, 0xfa, 0xe3, 0xf4, + 0xbe, 0xcf, 0x29, 0x0a, 0xf5, 0xf7, 0x39, 0x00, 0xc7, 0x47, 0x08, 0xeb, 0xa8, + 0xb7, 0xc6, 0x07, 0xf2, 0xf3, 0x37, 0x53, 0x4b, 0x0c, 0x19, 0xc4, 0xff, 0xe3, + 0x2a, 0x18, 0x17, 0x12, 0x9a, 0x25, 0x06, 0x21, 0x3e, 0xd0, 0xb5, 0x11, 0x0d, + 0x0b, 0x8e, 0x51, 0xdc, 0xed, 0x9f, 0x13, 0xa6, 0x25, 0x23, 0x07, 0xf5, 0xcc, + 0xf9, 0xf0, 0x76, 0x08, 0xd0, 0xe5, 0x0d, 0xf0, 0xf2, 0xd7, 0xeb, 0x74, 0xe0, + 0x29, 0xd7, 0xdb, 0xcb, 0xc1, 0x2a, 0xb6, 0x12, 0xd7, 0x17, 0x2e, 0x3a, 0x38, + 0xd9, 0x34, 0xe3, 0x11, 0x19, 0x03, 0x05, 0x1f, 0xd5, 0xe4, 0x4a, 0x24, 0xdf, + 0x16, 0xf2, 0x21, 0x08, 0xcd, 0x2c, 0xdb, 0x21, 0xbd, 0x3a, 0xf7, 0xf9, 0xba, + 0xfb, 0x8a, 0x88, 0x23, 0xd3, 0xc6, 0xcd, 0x34, 0xd8, 0x0c, 0xed, 0xc3, 0xee, + 0x1b, 0xbe, 0xf2, 0x40, 0xe0, 0xc3, 0x03, 0x1b, 0xe9, 0x36, 0x02, 0xf1, 0xf5, + 0xb3, 0x31, 0x2f, 0xf7, 0xdf, 0xf4, 0x6c, 0x0d, 0x81, 0xf8, 0x15, 0x0e, 0x10, + 0xf7, 0x45, 0xc4, 0xdf, 0xb6, 0xdf, 0x34, 0x02, 0xe5, 0xff, 0xfd, 0xfe, 0x19, + 0xfa, 0x15, 0xe7, 0x27, 0xfb, 0x6d, 0xcd, 0xea, 0xa7, 0x07, 0x85, 0x37, 0x07, + 0xd7, 0xf5, 0x07, 0xf5, 0xee, 0xc8, 0x37, 0xd1, 0xd7, 0x03, 0xe5, 0xe8, 0x11, + 0xf7, 0x3c, 0xe4, 0x29, 0x40, 0x20, 0xd6, 0x07, 0xaf, 0x35, 0xb7, 0xe6, 0xeb, + 0x2e, 0x2d, 0x0b, 0xfd, 0xf2, 0xeb, 0xe8, 0xf0, 0x4d, 0xf8, 0x28, 0xf8, 0xf1, + 0xf2, 0x0e, 0xd8, 0x18, 0xf7, 0xe9, 0x0b, 0xdb, 0x29, 0xf7, 0xed, 0xfb, 0x0e, + 0x5b, 0x10, 0xd6, 0x45, 0xf3, 0xae, 0xd6, 0xdc, 0x3a, 0x3c, 0xbc, 0xed, 0xb7, + 0xed, 0x1e, 0xe7, 0xe6, 0x05, 0x1a, 0x04, 0x20, 0xe4, 0xdd, 0xd8, 0xfb, 0x00, + 0xe1, 0xfb, 0xe4, 0xdc, 0x04, 0xc3, 0xf6, 0x37, 0x14, 0x02, 0x26, 0xe7, 0xe3, + 0xe8, 0xbd, 0xea, 0x23, 0xbe, 0x0e, 0xe6, 0x3f, 0x1c, 0x3a, 0x74, 0xcf, 0x38, + 0xc2, 0xf6, 0xc2, 0x12, 0x41, 0xfd, 0x35, 0x45, 0x35, 0xf8, 0x20, 0x0c, 0x07, + 0xad, 0xfa, 0x10, 0x0b, 0xd3, 0xf3, 0xd4, 0xdd, 0xf4, 0x03, 0x0b, 0xd7, 0x2a, + 0x3a, 0x07, 0x26, 0x14, 0xd9, 0xb3, 0x01, 0xdf, 0xdb, 0xf3, 0xdf, 0xd6, 0xfa, + 0x3e, 0xb8, 0xea, 0x37, 0xe8, 0x03, 0x1e, 0xe0, 0x0c, 0x3e, 0xf9, 0xca, 0xbe, + 0x7f, 0xfe, 0x4a, 0x17, 0x3d, 0x01, 0xcc, 0xf9, 0x4e, 0xdb, 0xd6, 0xd5, 0xdc, + 0xd2, 0xfe, 0x2b, 0x03, 0xdb, 0xd9, 0x40, 0xf2, 0xf3, 0x2a, 0xb8, 0x0e, 0xff, + 0xc0, 0x02, 0xad, 0xed, 0xf2, 0xed, 0x25, 0xf8, 0x8f, 0xec, 0xfa, 0x20, 0xe6, + 0xf0, 0x0b, 0xcd, 0x3d, 0x03, 0x11, 0x15, 0x18, 0x09, 0x0a, 0x46, 0x14, 0xff, + 0xfd, 0xb1, 0x1f, 0x30, 0xf7, 0x1d, 0xf5, 0x04, 0x23, 0x2c, 0xf6, 0x33, 0x4b, + 0xc1, 0x0a, 0x33, 0xb6, 0xc2, 0x1c, 0xac, 0x04, 0x45, 0xee, 0xfc, 0xa2, 0x16, + 0xfc, 0x00, 0x16, 0xee, 0x16, 0xf3, 0x26, 0xcc, 0x05, 0xea, 0xca, 0x34, 0xba, + 0x0f, 0x2e, 0x16, 0xd9, 0xcc, 0x06, 0x0c, 0x06, 0x29, 0x30, 0x14, 0xfb, 0xe3, + 0xfc, 0xfe, 0x37, 0x52, 0xdd, 0xfd, 0xea, 0xc2, 0x1e, 0xdf, 0x2a, 0x3b, 0x0d, + 0xf2, 0xed, 0x1c, 0xf2, 0x81, 0xd9, 0xe8, 0x25, 0x78, 0x2e, 0x20, 0xe8, 0xa8, + 0x12, 0x29, 0x26, 0xf8, 0x3c, 0xfb, 0x3f, 0x14, 0x75, 0xfd, 0xb5, 0x06, 0x65, + 0x92, 0xe5, 0x44, 0x0a, 0xc7, 0xba, 0x28, 0xff, 0xde, 0x0c, 0x20, 0x35, 0xd1, + 0x21, 0x1a, 0x69, 0x33, 0x50, 0x1d, 0x27, 0xda, 0x8d, 0x1c, 0xea, 0x31, 0x12, + 0x57, 0x11, 0x1f, 0xfc, 0xa4, 0xfd, 0xe3, 0xea, 0x09, 0xef, 0xce, 0x27, 0x09, + 0x4a, 0xe7, 0xea, 0x0c, 0xcc, 0xef, 0x3c, 0x56, 0xee, 0xfa, 0x3b, 0x1b, 0xdb, + 0x23, 0xec, 0x23, 0xb4, 0xc9, 0xdd, 0xfd, 0x56, 0xe1, 0x44, 0xbd, 0xb8, 0x3f, + 0xc5, 0xc6, 0xef, 0xe1, 0x1e, 0xea, 0xe7, 0xd4, 0x0d, 0x3b, 0x5d, 0x73, 0x29, + 0x0b, 0xdd, 0xfb, 0xf0, 0x53, 0xc7, 0xb3, 0x21, 0x3d, 0x81, 0xb6, 0x11, 0xbb, + 0xb9, 0x0d, 0x14, 0x6a, 0x65, 0xfe, 0x9e, 0x0d, 0x2a, 0x45, 0x9d, 0x29, 0x31, + 0x04, 0xe5, 0xf5, 0x37, 0x40, 0x25, 0xca, 0xfc, 0x57, 0x1f, 0xde, 0x37, 0x50, + 0x33, 0x1b, 0x04, 0xfd, 0x14, 0xef, 0x37, 0x34, 0x3f, 0xf3, 0xd3, 0xc3, 0xa8, + 0xf4, 0x1d, 0xd7, 0x91, 0x2d, 0xe1, 0x02, 0xb9, 0xf9, 0xb9, 0xcb, 0x2b, 0xd3, + 0x04, 0xe0, 0x34, 0x17, 0xec, 0x0a, 0xda, 0xe3, 0x14, 0xd4, 0x25, 0x24, 0x97, + 0xfe, 0xe4, 0x0e, 0x35, 0xe9, 0xb5, 0xdd, 0x1b, 0x2b, 0x24, 0xc0, 0xdf, 0x0a, + 0xd6, 0xf6, 0xf3, 0x12, 0xe0, 0xe8, 0xf8, 0xdb, 0xdf, 0x26, 0xdd, 0xaf, 0x1b, + 0xf4, 0x0c, 0x15, 0x54, 0x0c, 0x06, 0xea, 0x11, 0xe1, 0x3b, 0xbc, 0xc0, 0x3a, + 0xf7, 0xb6, 0x1b, 0xc9, 0xea, 0x6c, 0xd3, 0xe4, 0x06, 0xcc, 0xfd, 0x5e, 0x11, + 0x3d, 0xfb, 0xea, 0x08, 0xd5, 0xad, 0xe3, 0x31, 0xd5, 0xd4, 0x17, 0x02, 0x09, + 0x24, 0xcb, 0x04, 0xed, 0x10, 0xf5, 0x06, 0xcf, 0xe1, 0x17, 0x17, 0xc2, 0x23, + 0xeb, 0x17, 0x1e, 0xff, 0x81, 0xd6, 0xe5, 0xea, 0xea, 0xf2, 0x05, 0x11, 0xe5, + 0xd5, 0xe8, 0x6d, 0x14, 0x15, 0x12, 0xdd, 0x99, 0x55, 0x96, 0xb2, 0xfc, 0xe4, + 0xb3, 0xba, 0x22, 0xee, 0x0b, 0xe3, 0x32, 0xfb, 0xe0, 0x20, 0xfb, 0x09, 0x39, + 0xde, 0xe6, 0xe0, 0x09, 0xc3, 0xf6, 0x25, 0x18, 0x01, 0x20, 0x38, 0x30, 0x0a, + 0x16, 0xeb, 0x29, 0xdc, 0x18, 0x09, 0xf2, 0x7e, 0xed, 0x5e, 0xcb, 0x1c, 0xf9, + 0xec, 0x21, 0x2b, 0x20, 0xe9, 0x38, 0x42, 0x04, 0x06, 0x21, 0xb6, 0xf7, 0x15, + 0xda, 0xd7, 0xd8, 0x53, 0xb7, 0x00, 0xc8, 0xef, 0x28, 0x56, 0x10, 0x13, 0x14, + 0x14, 0xe2, 0x28, 0xc1, 0x50, 0xb7, 0x28, 0x42, 0xd5, 0x48, 0xf2, 0x2a, 0xef, + 0x0c, 0xeb, 0x00, 0xfd, 0xeb, 0xe0, 0x54, 0x4a, 0xdb, 0xcc, 0x0b, 0x22, 0x35, + 0x16, 0x18, 0xf5, 0x01, 0xfa, 0x7f, 0xfb, 0xa9, 0x44, 0x2c, 0x1e, 0xff, 0x30, + 0xb6, 0x2c, 0x92, 0x22, 0xcb, 0x64, 0xf0, 0x64, 0x11, 0x29, 0x0a, 0xdb, 0xfe, + 0x0f, 0xdc, 0xf0, 0x70, 0xcf, 0x1e, 0x0d, 0x00, 0x2c, 0xe3, 0x15, 0x1e, 0xc0, + 0xd1, 0x6c, 0xed, 0x14, 0x36, 0xcb, 0xc0, 0xe2, 0x14, 0xc7, 0x26, 0x0d, 0x10, + 0xc6, 0x0d, 0xab, 0x19, 0xfa, 0xf4, 0x0b, 0x01, 0xeb, 0x40, 0x1d, 0xee, 0x0b, + 0xeb, 0x76, 0xeb, 0xd8, 0xe7, 0x03, 0x2f, 0xca, 0x11, 0xf1, 0x08, 0xec, 0xc8, + 0x07, 0xf5, 0xdc, 0x05, 0xfd, 0x61, 0x43, 0xcf, 0xe9, 0xa4, 0x0e, 0x4c, 0xe7, + 0xe5, 0x59, 0xc0, 0xe0, 0xd0, 0xd9, 0xdc, 0xd9, 0xee, 0x23, 0xd0, 0x01, 0xed, + 0x14, 0xa4, 0xd9, 0x02, 0x0c, 0x4c, 0x47, 0x4b, 0x33, 0x23, 0x2a, 0x25, 0xd1, + 0x17, 0x16, 0xf3, 0x10, 0x04, 0x09, 0xde, 0x17, 0x0e, 0xff, 0x60, 0x11, 0xf2, + 0xd7, 0x07, 0x05, 0xe4, 0xe1, 0x15, 0x7f, 0x2c, 0x06, 0xe6, 0x22, 0xdb, 0x17, + 0x11, 0x03, 0x33, 0x2c, 0xbc, 0x15, 0xfe, 0xcc, 0x21, 0x23, 0x08, 0xd9, 0xf7, + 0xfd, 0xc3, 0x10, 0x27, 0xf2, 0x37, 0x4c, 0xd0, 0xec, 0x12, 0xeb, 0x55, 0x07, + 0xcd, 0xf6, 0x07, 0x3f, 0xe8, 0x09, 0xe6, 0x36, 0xf3, 0xe5, 0x19, 0x12, 0x18, + 0xdc, 0xd7, 0xc6, 0xe5, 0xc5, 0x2e, 0xc8, 0x14, 0x07, 0xc8, 0x01, 0x04, 0x7f, + 0x03, 0x47, 0x2a, 0xc2, 0xaf, 0x6a, 0x1b, 0xe9, 0xe3, 0x00, 0xfb, 0xe3, 0x08, + 0x29, 0x3f, 0xf7, 0xe4, 0x27, 0x9b, 0x2c, 0xa4, 0xb5, 0xe3, 0xc9, 0xc3, 0xd2, + 0x10, 0xe6, 0x7f, 0x87, 0x0e, 0xde, 0xf3, 0xd9, 0xde, 0xb7, 0xd7, 0xed, 0x41, + 0xc8, 0x1a, 0xdf, 0xae, 0xe8, 0xbb, 0x11, 0xd0, 0xfa, 0xe9, 0x71, 0xe3, 0x2d, + 0xa5, 0x35, 0xf4, 0xed, 0xf1, 0xea, 0x13, 0x31, 0x3b, 0x08, 0x33, 0x39, 0x27, + 0x18, 0xb6, 0xcb, 0xc3, 0x18, 0xfc, 0x1d, 0x0a, 0x27, 0xa2, 0x1e, 0xa5, 0xdb, + 0xfb, 0xcf, 0xda, 0xa7, 0xd2, 0xa3, 0xe5, 0xf6, 0xf6, 0xdd, 0xfb, 0x10, 0x05, + 0xf0, 0x44, 0xe1, 0xb1, 0x1c, 0xec, 0xe0, 0x16, 0x05, 0xdb, 0x68, 0xc9, 0x0a, + 0xf2, 0xf2, 0x1f, 0x21, 0x3c, 0xd0, 0xca, 0xe9, 0x2a, 0xd8, 0xe1, 0x76, 0xb3, + 0x61, 0xef, 0xd0, 0xf2, 0x2d, 0xf8, 0x4a, 0xfd, 0xf1, 0x01, 0xba, 0xfd, 0x02, + 0x41, 0xba, 0x3b, 0xe9, 0xd4, 0xe6, 0x53, 0x1a, 0x04, 0xba, 0xe6, 0x46, 0xb5, + 0xfa, 0x1b, 0xcc, 0x2f, 0xeb, 0x0f, 0xe9, 0xdc, 0x61, 0xbe, 0xed, 0x20, 0x27, + 0x9e, 0xed, 0x94, 0x34, 0x24, 0x14, 0xaa, 0xf9, 0xf2, 0x1f, 0x2a, 0x24, 0x22, + 0xe8, 0xb5, 0x0d, 0xbd, 0xda, 0xef, 0xd3, 0xca, 0x7f, 0x56, 0xd4, 0x02, 0x06, + 0xf3, 0xe6, 0xe0, 0x6c, 0xc8, 0xa0, 0xd8, 0xd0, 0xef, 0x3a, 0xbe, 0x42, 0xd7, + 0x22, 0xfe, 0x36, 0xe6, 0x06, 0x1a, 0xf3, 0x0d, 0x1c, 0x10, 0xe9, 0xce, 0xde, + 0x19, 0x20, 0x0b, 0xc8, 0xfc, 0x0a, 0xd4, 0xf3, 0xe0, 0x0a, 0xe0, 0xe0, 0xd2, + 0x0c, 0xf6, 0xfc, 0xf8, 0x22, 0xe6, 0xee, 0x65, 0x0a, 0x7f, 0x35, 0x0b, 0x2f, + 0xee, 0x08, 0xeb, 0xf7, 0xdd, 0xf8, 0x1d, 0x25, 0x21, 0xf1, 0x07, 0xe5, 0xf5, + 0x3c, 0x66, 0xf6, 0x0d, 0xe9, 0x0e, 0xe0, 0x17, 0xe5, 0xf5, 0xee, 0x0b, 0x14, + 0x06, 0xfa, 0x00, 0x23, 0x17, 0xd0, 0x00, 0xe4, 0xcc, 0x38, 0xf2, 0xd1, 0x12, + 0xf0, 0x12, 0xe5, 0xed, 0x0b, 0xe6, 0x38, 0x42, 0x2e, 0xb9, 0xfd, 0x14, 0xd3, + 0x09, 0xf4, 0xe4, 0x1e, 0x45, 0xd8, 0xc4, 0xff, 0x3d, 0xea, 0xf7, 0x01, 0x0d, + 0xea, 0x0c, 0xf2, 0x06, 0x07, 0x0c, 0xd0, 0x05, 0xda, 0x3b, 0xfb, 0x19, 0x0e, + 0x70, 0xc2, 0xfb, 0xdc, 0x2a, 0x22, 0x10, 0xe6, 0xd3, 0xf0, 0x1d, 0x4b, 0xb1, + 0x36, 0xf5, 0x1f, 0xdb, 0xf5, 0x03, 0x15, 0xe6, 0xe9, 0xee, 0xf8, 0x0f, 0x18, + 0x2e, 0x02, 0x0e, 0x23, 0xfe, 0x1a, 0x33, 0x1c, 0xa6, 0x0f, 0xf7, 0x67, 0x0e, + 0x0b, 0x33, 0xc7, 0x0a, 0x92, 0x19, 0x1c, 0x35, 0x17, 0xe6, 0xf8, 0x05, 0xd5, + 0x0b, 0x11, 0x13, 0xfa, 0x63, 0x15, 0xee, 0xcd, 0xdc, 0x2c, 0xe5, 0xed, 0x17, + 0x14, 0xdb, 0xcd, 0xec, 0x09, 0x37, 0x3b, 0x71, 0xfe, 0xed, 0x44, 0xc5, 0x4a, + 0xbb, 0xaa, 0x12, 0xec, 0x06, 0x20, 0xde, 0x88, 0xac, 0xfc, 0x7d, 0x08, 0xf8, + 0x0e, 0xb1, 0xef, 0xd2, 0xea, 0xf8, 0x5e, 0xfa, 0xd8, 0xb1, 0x2d, 0xf0, 0x0f, + 0x2b, 0xfe, 0x21, 0x0a, 0xc2, 0xe4, 0x0a, 0xe2, 0xa3, 0x2b, 0x40, 0x3c, 0xa7, + 0xcb, 0x28, 0x21, 0xd4, 0xa2, 0xd8, 0xdd, 0x28, 0xbc, 0xdd, 0x2f, 0x7f, 0x29, + 0xd4, 0x20, 0xa9, 0x32, 0xb9, 0x3a, 0x2d, 0x06, 0x12, 0x00, 0x82, 0xfe, 0xd2, + 0x4b, 0x5d, 0x12, 0xf4, 0x42, 0xae, 0xbd, 0x62, 0xbc, 0xfe, 0x29, 0x04, 0x10, + 0xe9, 0xd0, 0x00, 0x40, 0x28, 0x3f, 0xd9, 0x0b, 0x01, 0x1a, 0x10, 0x21, 0x01, + 0xe5, 0x5f, 0x26, 0x06, 0x26, 0x15, 0x25, 0xbc, 0x32, 0x19, 0x07, 0x44, 0xba, + 0x07, 0xe7, 0xf4, 0x06, 0x14, 0x33, 0xf4, 0x15, 0xf9, 0xd2, 0xe5, 0x27, 0x1e, + 0x15, 0x57, 0x00, 0xfb, 0xe3, 0x12, 0xf1, 0x36, 0x02, 0x38, 0x03, 0x1b, 0xda, + 0x42, 0x0a, 0x31, 0x66, 0x19, 0x16, 0xc4, 0xf1, 0x1d, 0xf9, 0x36, 0x52, 0xea, + 0x4d, 0x2b, 0x20, 0xdd, 0xfd, 0x3a, 0x4a, 0x7f, 0xd5, 0xf9, 0xc5, 0x2e, 0x40, + 0xe9, 0x19, 0xe7, 0x16, 0xd0, 0xd1, 0xf4, 0xdb, 0xd4, 0xe4, 0xe0, 0x06, 0x09, + 0xee, 0xe5, 0xe6, 0x5d, 0xd9, 0x49, 0xcf, 0x25, 0xef, 0x17, 0x13, 0xea, 0xd5, + 0xe1, 0xe4, 0xf2, 0x39, 0x14, 0x22, 0xe6, 0x37, 0xf6, 0x08, 0x0a, 0x17, 0x09, + 0xfc, 0x12, 0xef, 0xf0, 0xfe, 0xdb, 0x0f, 0x29, 0x2e, 0x03, 0xeb, 0xfa, 0x00, + 0xf9, 0x0c, 0x3a, 0xf2, 0xdf, 0xe8, 0xe4, 0xfa, 0xfa, 0xdd, 0x11, 0x01, 0xe7, + 0x0a, 0x0c, 0xde, 0x02, 0xf8, 0xe9, 0x25, 0x28, 0x08, 0x0c, 0x03, 0x0c, 0xe2, + 0xdb, 0xe1, 0x17, 0xfe, 0x06, 0xdb, 0x19, 0x19, 0x0e, 0x21, 0x3f, 0x12, 0x19, + 0xa7, 0x04, 0x96, 0x01, 0x12, 0xfe, 0xfb, 0xd7, 0xfc, 0xe8, 0x2b, 0xfc, 0x0d, + 0x00, 0xfe, 0xf6, 0x49, 0x02, 0xeb, 0xf0, 0x22, 0x5b, 0x09, 0x7f, 0x07, 0x02, + 0xc5, 0x24, 0xbe, 0x13, 0x3a, 0x02, 0x1f, 0x32, 0x45, 0xe9, 0xf9, 0xee, 0xea, + 0x0a, 0x11, 0xeb, 0xf0, 0xeb, 0xfc, 0xe2, 0x0b, 0xc4, 0xfe, 0xf2, 0x14, 0xe2, + 0x01, 0xf3, 0xde, 0x1c, 0xd3, 0x11, 0x17, 0x25, 0xc9, 0xfa, 0x06, 0xdf, 0xc6, + 0xf3, 0x0b, 0xef, 0x18, 0x0e, 0xf9, 0xff, 0x0c, 0xec, 0xff, 0xf7, 0xed, 0xe9, + 0x02, 0xc1, 0xd1, 0x12, 0xdd, 0xe3, 0x18, 0x17, 0x07, 0x33, 0x1b, 0xf3, 0x06, + 0x1a, 0x0c, 0x2d, 0xe0, 0xe9, 0xf2, 0xd0, 0xf2, 0xec, 0x1d, 0xdf, 0x03, 0xfc, + 0x06, 0x05, 0xea, 0x20, 0x20, 0xd8, 0x1d, 0xf4, 0xff, 0x13, 0xf2, 0x19, 0xec, + 0xf3, 0xe2, 0xeb, 0xd9, 0x04, 0x2d, 0x15, 0x13, 0x2e, 0xfd, 0xd0, 0xed, 0x20, + 0xfd, 0x06, 0xf1, 0xdd, 0x1c, 0x4d, 0x08, 0xf1, 0x13, 0x01, 0xfc, 0x1a, 0xf4, + 0x0d, 0xff, 0xf6, 0x14, 0x03, 0x1c, 0x3a, 0xf0, 0x7f, 0xe9, 0xff, 0xec, 0xec, + 0x2a, 0xfa, 0x04, 0xd9, 0x27, 0x23, 0xd0, 0xec, 0xff, 0x14, 0xf8, 0x07, 0x08, + 0xe6, 0x0c, 0x29, 0x0e, 0x18, 0xeb, 0xdf, 0x0d, 0x18, 0xe5, 0x21, 0x01, 0x18, + 0x3a, 0xf9, 0xf2, 0x2a, 0x25, 0x11, 0xd6, 0x1f, 0x0b, 0x29, 0x4a, 0x03, 0xee, + 0x00, 0xf8, 0x15, 0x07, 0x27, 0x05, 0xff, 0x06, 0x05, 0xe9, 0xd9, 0x2f, 0x0b, + 0x13, 0x06, 0xff, 0x0b, 0x1e, 0xed, 0x22, 0x17, 0x0b, 0xfd, 0xea, 0x38, 0xd1, + 0x23, 0x08, 0x1b, 0xce, 0xaa, 0x34, 0x09, 0x3a, 0xd8, 0xe0, 0x15, 0x10, 0xf8, + 0x29, 0xec, 0xf3, 0xf4, 0x23, 0x21, 0xba, 0xf9, 0x0d, 0x12, 0x30, 0x03, 0xbb, + 0xfa, 0xfb, 0xd2, 0xd4, 0x06, 0x16, 0x07, 0xff, 0xfc, 0x0d, 0xfe, 0xd9, 0xc8, + 0xe1, 0x46, 0xc0, 0x13, 0xe3, 0xe5, 0xed, 0xf2, 0x31, 0xae, 0x29, 0x98, 0xfb, + 0xca, 0xdc, 0xea, 0x08, 0xdb, 0x2b, 0x2d, 0xf3, 0x16, 0x67, 0xe0, 0xef, 0x13, + 0x40, 0xfb, 0xe2, 0x35, 0x62, 0x30, 0x57, 0xa1, 0x12, 0xf1, 0xc1, 0xed, 0xe5, + 0xe2, 0x1e, 0xc3, 0xd9, 0xf2, 0x3f, 0x4a, 0x05, 0xba, 0x24, 0x81, 0xb0, 0x18, + 0x01, 0xea, 0x04, 0x5b, 0x36, 0xcc, 0xab, 0xe0, 0xe9, 0xc8, 0xc8, 0x50, 0xdd, + 0xde, 0x42, 0x02, 0xd3, 0xe3, 0xdd, 0x10, 0xef, 0x63, 0xf8, 0xdd, 0xba, 0xdf, + 0xd4, 0xe1, 0xff, 0xfc, 0xc6, 0x26, 0xfa, 0xc5, 0x39, 0x11, 0x2d, 0x29, 0xfd, + 0xaa, 0x2d, 0xbd, 0xbe, 0x04, 0xde, 0xea, 0xe6, 0xd1, 0xf0, 0xfd, 0x62, 0x0c, + 0xf7, 0x15, 0x0e, 0xc0, 0x33, 0xff, 0xe9, 0x33, 0xee, 0xdc, 0xc8, 0xdd, 0x11, + 0x04, 0xe3, 0x24, 0xe7, 0x0f, 0x27, 0xf3, 0x07, 0x0d, 0xc3, 0x05, 0x15, 0xde, + 0x2e, 0xfc, 0xf9, 0x17, 0x41, 0x01, 0xf5, 0x7f, 0x38, 0xd6, 0xff, 0xfd, 0xef, + 0x02, 0xd1, 0xca, 0xe4, 0xfc, 0xfe, 0x5b, 0xeb, 0xfb, 0x16, 0xda, 0xda, 0xd3, + 0x00, 0x16, 0xcf, 0xe3, 0x1b, 0x52, 0x08, 0x3f, 0x1e, 0xe0, 0x3c, 0xc5, 0x1c, + 0x6a, 0xf5, 0xf6, 0xff, 0x0c, 0xf6, 0x04, 0xc6, 0xa2, 0x1f, 0xf1, 0xe9, 0x25, + 0x1e, 0x0b, 0xc6, 0x0b, 0x1c, 0xca, 0x00, 0xf8, 0xb6, 0xda, 0xe2, 0x19, 0xd7, + 0xd1, 0x00, 0xe7, 0x0c, 0x1b, 0x1a, 0xc7, 0x04, 0xd8, 0xee, 0xd2, 0xdf, 0xf0, + 0x3b, 0xff, 0xc0, 0x6c, 0x20, 0xed, 0x24, 0x07, 0x0f, 0x18, 0x3c, 0xd9, 0x2d, + 0x29, 0x05, 0xf3, 0xf3, 0x06, 0xe0, 0xde, 0x13, 0xdc, 0xf9, 0x38, 0xb0, 0x22, + 0x24, 0x02, 0x56, 0x1e, 0xf1, 0xf1, 0x02, 0xe0, 0xd7, 0xf4, 0x22, 0xdb, 0xf3, + 0xf6, 0xc3, 0x0d, 0xda, 0xc8, 0xf4, 0x21, 0xd8, 0xf5, 0x2f, 0x24, 0x37, 0xfc, + 0x23, 0x28, 0xd5, 0x16, 0x1f, 0xb9, 0x0b, 0xfa, 0xd6, 0xf9, 0xe1, 0xdd, 0xe1, + 0xe1, 0xf5, 0xd3, 0xd8, 0x39, 0x04, 0x19, 0x2f, 0xc1, 0x04, 0xe3, 0xb8, 0x10, + 0xc7, 0x36, 0x56, 0xf1, 0xf4, 0xea, 0xf4, 0x60, 0x1e, 0xe3, 0x05, 0x40, 0xe8, + 0x98, 0xed, 0xed, 0x01, 0x2b, 0x0d, 0xea, 0xc0, 0xee, 0x7f, 0xee, 0x03, 0x03, + 0x14, 0xa6, 0xf7, 0x2d, 0xdf, 0xf9, 0xd7, 0x29, 0x01, 0xe8, 0x06, 0x04, 0xeb, + 0xe0, 0x0e, 0x1d, 0x3e, 0x26, 0x14, 0x9c, 0xf3, 0xc9, 0x02, 0xc1, 0x13, 0x1b, + 0x03, 0x0c, 0xfa, 0xf7, 0xe6, 0xf9, 0xfc, 0xfd, 0xc9, 0xc8, 0x5f, 0xc9, 0xfb, + 0xd9, 0x10, 0xb6, 0xd9, 0xc4, 0xd0, 0xcd, 0xf6, 0x14, 0x3e, 0xc1, 0xff, 0xef, + 0x1c, 0x0f, 0xe2, 0xab, 0x03, 0xf1, 0x02, 0xd6, 0x2b, 0x17, 0x16, 0xfd, 0xdb, + 0x1b, 0xda, 0xee, 0xc4, 0x34, 0x2a, 0xf2, 0xcd, 0xfc, 0x24, 0xdb, 0x14, 0xbc, + 0x28, 0xc3, 0xc0, 0xce, 0xbd, 0x25, 0x08, 0xe0, 0x21, 0xf9, 0x48, 0xeb, 0xdd, + 0x9e, 0xe1, 0xb7, 0x14, 0xbd, 0xd1, 0x17, 0x03, 0xbc, 0xe4, 0x2f, 0x29, 0x05, + 0x13, 0x7f, 0x0e, 0x04, 0xf4, 0x18, 0x05, 0x05, 0x3e, 0x55, 0x3f, 0xeb, 0x0d, + 0x17, 0xe9, 0x44, 0xfc, 0x84, 0xdc, 0x1f, 0xc0, 0x48, 0xe3, 0x01, 0xb5, 0xe7, + 0xfb, 0x2b, 0xf9, 0xdc, 0x1f, 0xdd, 0x15, 0x55, 0xfa, 0xfa, 0xc3, 0xdd, 0x09, + 0x20, 0xe8, 0xf3, 0x0b, 0xda, 0xf3, 0xf3, 0x15, 0x1d, 0x1d, 0x18, 0x07, 0x20, + 0x35, 0x32, 0xf7, 0x2b, 0x17, 0x59, 0xc7, 0xc2, 0xec, 0xd6, 0xfc, 0xfc, 0x2f, + 0xec, 0xea, 0x37, 0xb9, 0x0d, 0x2e, 0xf4, 0x55, 0xb2, 0xd6, 0xbb, 0x0b, 0xca, + 0x35, 0xdc, 0x12, 0xfe, 0x09, 0x45, 0xec, 0xfb, 0xe8, 0x23, 0x0c, 0xda, 0xe6, + 0xf8, 0x40, 0xf9, 0x12, 0xd0, 0x17, 0xc8, 0xe8, 0x7f, 0x1e, 0xe3, 0x21, 0x18, + 0x08, 0x16, 0xc8, 0x3c, 0x31, 0xdc, 0x78, 0xc4, 0x01, 0x52, 0xeb, 0x69, 0x0b, + 0xf9, 0x0b, 0xce, 0x36, 0xcf, 0x3b, 0xd8, 0xe4, 0x1d, 0xcc, 0xea, 0x04, 0x0d, + 0x18, 0x2f, 0x05, 0xe5, 0x15, 0x01, 0x10, 0x37, 0xde, 0xe6, 0x24, 0x03, 0xcf, + 0x11, 0xb5, 0xeb, 0x4c, 0x3d, 0x17, 0xfc, 0x18, 0x4d, 0xb8, 0x72, 0x32, 0xc8, + 0x04, 0x12, 0xed, 0xe8, 0xc0, 0x30, 0x3c, 0x12, 0xdb, 0x18, 0xd9, 0xd5, 0xd8, + 0x05, 0xbb, 0xb9, 0x4d, 0x04, 0xd9, 0x37, 0xed, 0xfa, 0xf2, 0xf6, 0xed, 0xbd, + 0x4e, 0x8d, 0xf4, 0x2d, 0x09, 0xd8, 0x83, 0xed, 0xad, 0xec, 0x37, 0xe7, 0x21, + 0xdd, 0xd3, 0x23, 0xc7, 0x07, 0xe8, 0xc7, 0x18, 0xd3, 0x5f, 0x13, 0xe4, 0x00, + 0xdc, 0xff, 0x02, 0x28, 0x4a, 0x5f, 0xf3, 0x1a, 0x4b, 0xe8, 0xc5, 0x3e, 0x17, + 0x1d, 0x42, 0x02, 0x20, 0x01, 0x2c, 0x1d, 0xf7, 0x04, 0xe3, 0x29, 0x09, 0x45, + 0x11, 0x11, 0xe3, 0x09, 0x2c, 0xe0, 0x19, 0x17, 0xd7, 0x65, 0x0e, 0x05, 0x14, + 0x4b, 0xc9, 0xfa, 0xed, 0x0b, 0xe4, 0x13, 0xe6, 0xce, 0xad, 0xc3, 0xdb, 0xf8, + 0x1f, 0x20, 0x25, 0x01, 0xd7, 0x47, 0xb7, 0xfe, 0x29, 0x0a, 0xd5, 0x24, 0xfe, + 0x7f, 0xbe, 0xe1, 0xd7, 0x05, 0xd5, 0xae, 0x7c, 0x5c, 0x3c, 0xaf, 0xd7, 0x57, + 0xb7, 0x16, 0xaf, 0x28, 0xdd, 0xef, 0x23, 0x0d, 0xc6, 0x0b, 0x0c, 0x22, 0x96, + 0xc8, 0x1d, 0x9b, 0xdd, 0xe7, 0x01, 0xea, 0x2d, 0x0f, 0xc9, 0xff, 0x45, 0x13, + 0x26, 0x29, 0x08, 0x31, 0x98, 0xcf, 0xd2, 0xdc, 0x07, 0xd4, 0xeb, 0x0b, 0xd1, + 0x3c, 0x74, 0xc8, 0xe4, 0xef, 0x0c, 0xc4, 0xc8, 0x11, 0xa6, 0x64, 0xf9, 0xf9, + 0xf5, 0x4a, 0xc7, 0x2c, 0x19, 0x30, 0x27, 0x0d, 0xff, 0x44, 0x56, 0xc6, 0xc7, + 0xe8, 0xf5, 0xe8, 0xf7, 0xf6, 0x9e, 0x20, 0xf9, 0x19, 0x0b, 0x30, 0xe3, 0x0b, + 0xb4, 0x14, 0xd6, 0x57, 0xef, 0xb7, 0x06, 0xfd, 0xf7, 0xc7, 0x05, 0xf9, 0xfb, + 0x00, 0x29, 0x23, 0xbf, 0x99, 0x26, 0x16, 0xd6, 0x03, 0xa5, 0x46, 0x49, 0xd2, + 0x37, 0x7f, 0x24, 0xe7, 0xfc, 0xa2, 0x38, 0x43, 0x53, 0xd9, 0xdb, 0xf5, 0xe9, + 0xdb, 0x78, 0xd2, 0xd9, 0x4e, 0xec, 0x0c, 0x1b, 0xb5, 0xc5, 0xa7, 0xe6, 0x2e, + 0xf4, 0x0a, 0xf5, 0x18, 0xa6, 0x23, 0x0f, 0xc0, 0xfe, 0xf3, 0x16, 0xd4, 0xfa, + 0x74, 0x11, 0x16, 0xda, 0x13, 0xc1, 0x2a, 0xd7, 0x0c, 0xf8, 0x0e, 0xe1, 0xcb, + 0x12, 0x28, 0xb4, 0x43, 0x0e, 0xe0, 0x27, 0xd0, 0xd0, 0xc1, 0x0c, 0x12, 0xd7, + 0xe1, 0xc8, 0x40, 0xf3, 0x7d, 0xa7, 0x14, 0xd0, 0x38, 0xdb, 0x1d, 0x2b, 0xc2, + 0x3a, 0xd1, 0xa3, 0xbf, 0x50, 0xea, 0xf7, 0x32, 0xe9, 0xfd, 0x01, 0x1d, 0x15, + 0x06, 0x1f, 0x9a, 0xe4, 0xf7, 0x32, 0x29, 0xff, 0xc5, 0x02, 0xb3, 0xd8, 0x61, + 0x0a, 0x10, 0xf8, 0xfb, 0xf5, 0xfe, 0xd6, 0x06, 0x05, 0xe4, 0xc4, 0x0a, 0x7f, + 0x90, 0xa0, 0x05, 0xce, 0x2e, 0xe3, 0xab, 0x24, 0xe9, 0x17, 0x10, 0xc2, 0xf8, + 0xcc, 0x00, 0xf5, 0x11, 0xf0, 0x24, 0xd5, 0xe5, 0x08, 0x07, 0xc8, 0xf3, 0x00, + 0x23, 0xb0, 0x28, 0x54, 0xd0, 0x45, 0xe9, 0x03, 0xdf, 0xf3, 0xf5, 0x21, 0xcc, + 0x14, 0xfb, 0xfa, 0xbc, 0x1d, 0x04, 0xe3, 0xf9, 0x26, 0x03, 0x08, 0xf8, 0xfd, + 0x2e, 0xc9, 0xd6, 0x0f, 0xe2, 0x37, 0x4a, 0x14, 0xec, 0x1d, 0x61, 0xb6, 0x1c, + 0xdc, 0xbe, 0x09, 0x04, 0x2e, 0x02, 0xa8, 0xe2, 0xeb, 0x0b, 0x64, 0x20, 0x5a, + 0xe9, 0x16, 0xbd, 0xf3, 0xba, 0x19, 0x22, 0xe5, 0x18, 0xfc, 0xd6, 0xa2, 0x29, + 0x2e, 0x23, 0x1d, 0xdd, 0x16, 0x19, 0x01, 0xcf, 0x5a, 0x1e, 0xfe, 0xe5, 0xf5, + 0x7f, 0xee, 0xb4, 0x1c, 0xf6, 0xbf, 0xe0, 0xfb, 0xd1, 0x01, 0xf7, 0xef, 0xdf, + 0xd9, 0x56, 0xe0, 0x35, 0xc6, 0xd2, 0xd0, 0xc5, 0x2d, 0xc8, 0xf6, 0x93, 0x6c, + 0xf9, 0xe4, 0x0b, 0xe6, 0xf6, 0x9c, 0xfd, 0x67, 0xb7, 0xfb, 0x2b, 0x25, 0xff, + 0xf5, 0x1f, 0xe2, 0x03, 0x04, 0x03, 0xf3, 0xb8, 0x40, 0x6b, 0x09, 0xee, 0x7e, + 0xeb, 0xa1, 0x0a, 0x38, 0xe3, 0x0a, 0x73, 0xfd, 0xbc, 0xcb, 0x4e, 0x9f, 0xe3, + 0xd1, 0xfe, 0x00, 0xd9, 0xfa, 0x0f, 0x00, 0x36, 0x86, 0x50, 0x33, 0x0d, 0xfe, + 0xff, 0x17, 0xd4, 0x70, 0xd9, 0xc9, 0xc6, 0x10, 0xeb, 0x36, 0x16, 0x15, 0xe2, + 0x41, 0xf1, 0xe8, 0xdb, 0xfb, 0x00, 0xed, 0x44, 0x51, 0x2d, 0xf7, 0xe8, 0xe3, + 0x27, 0x38, 0x22, 0x16, 0xfa, 0x30, 0xe9, 0x4f, 0x5c, 0xe3, 0x30, 0x46, 0xd2, + 0xeb, 0xd2, 0xac, 0xc3, 0xf4, 0xb9, 0x02, 0xb6, 0xd8, 0xea, 0x4a, 0xa3, 0xf8, + 0xbf, 0xcb, 0xc2, 0x1e, 0xfa, 0xb5, 0x35, 0xdf, 0xf6, 0xfb, 0xe8, 0xf8, 0x2d, + 0x39, 0x81, 0xd7, 0xea, 0xc4, 0x67, 0x9b, 0xb2, 0x3d, 0xe1, 0xdb, 0xf0, 0x12, + 0xd9, 0xea, 0xda, 0xca, 0xa9, 0xf5, 0xdc, 0x0d, 0xf9, 0x13, 0xc7, 0xe7, 0xc2, + 0x1d, 0xed, 0xc0, 0x5a, 0xcf, 0x67, 0x26, 0xce, 0x04, 0x16, 0x2f, 0xdd, 0xee, + 0x3a, 0x1c, 0xe5, 0x25, 0x20, 0xd1, 0xd7, 0x14, 0x77, 0xff, 0xea, 0xc1, 0xca, + 0xbc, 0x06, 0x13, 0xff, 0x21, 0xc2, 0x03, 0xff, 0x03, 0x03, 0x0c, 0x60, 0x06, + 0x26, 0xc5, 0x24, 0x3b, 0x0b, 0x2e, 0x14, 0xf4, 0x06, 0x14, 0x00, 0x12, 0xeb, + 0xe6, 0x29, 0xe1, 0x18, 0x16, 0x27, 0x15, 0xde, 0x28, 0xe6, 0xef, 0x26, 0xd2, + 0xe9, 0xaf, 0xf6, 0xfd, 0x3f, 0x2c, 0x18, 0x0e, 0xfe, 0xd1, 0xc0, 0x22, 0x0e, + 0x37, 0x00, 0xfb, 0xf6, 0xf1, 0xdf, 0x0f, 0x27, 0xfb, 0x34, 0xf9, 0x24, 0xdd, + 0xec, 0xf7, 0x01, 0xff, 0x1b, 0x3e, 0x29, 0xc5, 0xf4, 0x43, 0x27, 0x3c, 0xed, + 0x17, 0x0d, 0x04, 0x22, 0xcc, 0xff, 0x39, 0x08, 0x81, 0xc8, 0x44, 0x13, 0x0e, + 0xe7, 0x15, 0x2d, 0xda, 0xef, 0xed, 0x17, 0x1e, 0xc5, 0x01, 0x03, 0x08, 0x0a, + 0x15, 0x1b, 0x03, 0xfa, 0x04, 0xed, 0xf0, 0xd8, 0xfc, 0xe7, 0x24, 0x12, 0xcb, + 0x17, 0x18, 0x10, 0x4d, 0xe7, 0x0a, 0x10, 0x12, 0xf8, 0xa0, 0x02, 0xfb, 0x35, + 0x0f, 0xe6, 0x17, 0x21, 0xe1, 0x1e, 0x02, 0x13, 0x15, 0x0f, 0x12, 0x0b, 0xe6, + 0x06, 0x62, 0x40, 0xdd, 0x72, 0xe8, 0x00, 0xb4, 0xef, 0x2b, 0x02, 0xe9, 0xd5, + 0x02, 0x99, 0x1c, 0xc4, 0x2b, 0xf6, 0xf8, 0x04, 0xeb, 0x1b, 0xfd, 0xe3, 0xa1, + 0x49, 0x95, 0xe8, 0x0a, 0x14, 0xc8, 0xaf, 0xb1, 0x8f, 0xf3, 0x1f, 0x0b, 0xda, + 0x10, 0x9f, 0xdc, 0x02, 0xd8, 0xce, 0x3d, 0xf5, 0x02, 0x0d, 0x1b, 0x16, 0x17, + 0x29, 0xf2, 0xeb, 0x3e, 0x54, 0xba, 0x96, 0xcf, 0xbf, 0x2d, 0x2d, 0x00, 0x1c, + 0xcd, 0x2e, 0xe3, 0xce, 0x0c, 0x9c, 0x3d, 0x36, 0xa5, 0x3b, 0xdd, 0xb2, 0x30, + 0x07, 0xfd, 0x39, 0x00, 0x09, 0x03, 0x11, 0xa0, 0xfc, 0x66, 0xfd, 0xe8, 0xec, + 0xf3, 0xac, 0xb9, 0xcf, 0x1a, 0x98, 0xfe, 0x9a, 0xbc, 0x17, 0x1e, 0xe0, 0x0f, + 0x0d, 0x59, 0xbd, 0xfd, 0xeb, 0x27, 0xec, 0xda, 0x0e, 0x44, 0xd4, 0x3c, 0xb9, + 0x27, 0xbd, 0x07, 0xd8, 0x34, 0xa1, 0xf5, 0x24, 0x7f, 0x41, 0x15, 0x17, 0x69, + 0x43, 0x08, 0x09, 0x18, 0xe6, 0xd0, 0xf1, 0xf4, 0x10, 0x06, 0xd1, 0xda, 0xeb, + 0xcb, 0x55, 0x24, 0xd9, 0xe1, 0x22, 0x09, 0xbd, 0x11, 0xe8, 0x00, 0xe6, 0x3a, + 0xfd, 0x27, 0x31, 0x03, 0x00, 0x1a, 0x33, 0x76, 0x5a, 0x40, 0x7f, 0x44, 0x33, + 0x00, 0xff, 0xc3, 0x18, 0xca, 0x9b, 0xfe, 0xf5, 0x3b, 0x02, 0xf6, 0x1d, 0xef, + 0xe4, 0xf9, 0x1a, 0xc6, 0x1f, 0x1c, 0xff, 0x12, 0x0c, 0xed, 0x0e, 0xf9, 0x05, + 0x30, 0xfe, 0x3a, 0xd7, 0xba, 0xbc, 0x3c, 0x1d, 0xe9, 0x0d, 0x13, 0xc8, 0x5a, + 0x3d, 0xdd, 0xef, 0x23, 0x07, 0xf1, 0x12, 0x00, 0xd5, 0x01, 0xff, 0xde, 0xd3, + 0x06, 0x05, 0xce, 0x26, 0x19, 0xcc, 0xf6, 0xf2, 0x08, 0xe3, 0xbb, 0xf3, 0xe9, + 0x04, 0x08, 0x25, 0x51, 0xe8, 0xd3, 0x54, 0x0f, 0x1a, 0xf3, 0x68, 0x1f, 0x61, + 0x1a, 0xdf, 0xff, 0xfa, 0x1b, 0xb9, 0x59, 0x33, 0xd7, 0x03, 0x0c, 0x35, 0x1d, + 0x14, 0xcf, 0x81, 0x96, 0xce, 0x91, 0xf0, 0x20, 0xc3, 0xe5, 0x3e, 0xb8, 0x05, + 0x03, 0xfd, 0x19, 0xac, 0xee, 0xcc, 0x60, 0x55, 0xe8, 0x52, 0x0a, 0x25, 0xb8, + 0x28, 0xd4, 0xcc, 0x00, 0xc4, 0x29, 0x1c, 0x26, 0xf6, 0x1b, 0x0e, 0xdd, 0x0d, + 0x36, 0x0b, 0x41, 0xe6, 0x49, 0xec, 0x04, 0x0d, 0xe4, 0xea, 0xad, 0xdf, 0xc7, + 0x06, 0x6a, 0xf9, 0x1d, 0xfc, 0x31, 0xf4, 0xfb, 0x59, 0x00, 0x97, 0x72, 0x00, + 0xb7, 0xc8, 0x47, 0x48, 0xff, 0xdc, 0xe8, 0xf0, 0x21, 0xee, 0x27, 0xf6, 0x26, + 0x2b, 0xf0, 0x3f, 0xac, 0x40, 0x4b, 0x11, 0x06, 0x21, 0x0a, 0x32, 0x12, 0x54, + 0xf5, 0x1c, 0xe1, 0x1c, 0x64, 0x4e, 0x65, 0x45, 0xfd, 0xcf, 0xeb, 0xff, 0xf3, + 0xe1, 0x28, 0x25, 0x11, 0xeb, 0xe8, 0xbc, 0xf3, 0x59, 0xe1, 0xa3, 0xc5, 0xc0, + 0xc0, 0xea, 0x48, 0xaf, 0xb6, 0x0f, 0xc7, 0x06, 0xe6, 0x0e, 0x32, 0xfe, 0xf8, + 0x14, 0xde, 0x58, 0x27, 0x49, 0x1f, 0xe9, 0x3b, 0x5d, 0xde, 0x09, 0xe8, 0x04, + 0x20, 0xec, 0xf9, 0xc2, 0x25, 0x62, 0x1b, 0xbf, 0x28, 0x23, 0x09, 0x3d, 0x06, + 0xf9, 0x52, 0x3b, 0xdd, 0xf9, 0xbd, 0x8a, 0x4a, 0x1b, 0xe5, 0xfb, 0xec, 0x0e, + 0x13, 0xdd, 0xa7, 0xc3, 0xeb, 0xd4, 0x24, 0xb7, 0xc9, 0xc4, 0xe5, 0xd4, 0xc8, + 0x4d, 0x2f, 0xf9, 0x1e, 0x4a, 0xf6, 0x12, 0xf4, 0x47, 0x1d, 0xff, 0xf3, 0xfb, + 0xa2, 0xda, 0xf2, 0xfe, 0x2c, 0xf5, 0x0d, 0xbb, 0x2d, 0x07, 0x0a, 0xcd, 0x41, + 0xd7, 0xcd, 0xec, 0xbf, 0x13, 0x12, 0xf0, 0x05, 0xf3, 0xe7, 0x7f, 0x06, 0x1c, + 0x0e, 0x1c, 0xf8, 0x55, 0xd2, 0xd1, 0x16, 0x36, 0xd9, 0x1a, 0x19, 0x39, 0x34, + 0x01, 0xe4, 0xfa, 0xb7, 0x2c, 0x29, 0xf3, 0x06, 0xe8, 0xac, 0x12, 0xcc, 0x05, + 0x13, 0xee, 0x14, 0x10, 0xda, 0xf8, 0xe4, 0xc9, 0xed, 0x10, 0x0a, 0xce, 0x66, + 0xbf, 0x0a, 0x11, 0x0a, 0xdd, 0xf2, 0x1c, 0x0f, 0x26, 0xd6, 0x2b, 0x25, 0xef, + 0x01, 0xcc, 0x24, 0xfa, 0x7f, 0xe8, 0xff, 0x1b, 0xf4, 0x40, 0xd1, 0xf5, 0xf2, + 0xcf, 0xae, 0xd3, 0x01, 0xec, 0xda, 0x34, 0x11, 0x0d, 0x17, 0xe3, 0x09, 0xe3, + 0xfb, 0xe9, 0xe4, 0xf1, 0xdc, 0xaa, 0x9c, 0x58, 0x02, 0xcf, 0xff, 0xfc, 0x30, + 0x3e, 0xdc, 0xc0, 0xf9, 0x23, 0xee, 0xed, 0x15, 0xcb, 0xc6, 0xe3, 0x30, 0x36, + 0x6f, 0xc6, 0x27, 0xe3, 0xf0, 0xcc, 0xee, 0x0a, 0xe0, 0x32, 0xfd, 0x39, 0x0b, + 0x16, 0x04, 0x06, 0x58, 0x1d, 0xd8, 0x6b, 0xe8, 0x20, 0x1b, 0x08, 0x68, 0x0b, + 0xd6, 0xe5, 0x0a, 0xee, 0x2f, 0x26, 0xbf, 0xee, 0xe8, 0xc7, 0x23, 0xcc, 0x54, + 0x12, 0xef, 0x06, 0x18, 0xb7, 0x17, 0xb5, 0x2a, 0xd5, 0xed, 0xe8, 0x31, 0x39, + 0x0b, 0x07, 0xb1, 0xf1, 0x15, 0x18, 0x32, 0xe1, 0xf3, 0xda, 0x00, 0x14, 0x1c, + 0xe4, 0xf3, 0x19, 0x1b, 0x0a, 0x56, 0x09, 0x24, 0xf8, 0x19, 0x07, 0x14, 0x3c, + 0xd3, 0xa6, 0xbb, 0xe5, 0x4e, 0xfe, 0xb6, 0xc1, 0x16, 0xea, 0xcd, 0xf6, 0xf6, + 0xf2, 0x45, 0x23, 0xd8, 0xe8, 0xf4, 0xf9, 0x41, 0x2f, 0xd8, 0x0c, 0x0e, 0xb4, + 0x1c, 0xee, 0x3c, 0xbb, 0xd8, 0xe9, 0x7f, 0xe2, 0x11, 0x0d, 0x87, 0x4a, 0x58, + 0x19, 0x1f, 0xf6, 0xeb, 0xdf, 0xc0, 0xda, 0x30, 0xd6, 0xe6, 0xe6, 0x9c, 0x41, + 0x1a, 0x19, 0x1c, 0xbc, 0x6d, 0x02, 0x1b, 0x01, 0x20, 0xb7, 0x00, 0xdc, 0x0d, + 0xf0, 0xfe, 0xf9, 0x05, 0x14, 0x06, 0x20, 0xdc, 0xf7, 0x04, 0xec, 0x19, 0xf5, + 0xd6, 0xeb, 0x25, 0xd0, 0x49, 0xcc, 0x15, 0x00, 0xfe, 0xce, 0xfe, 0xe3, 0x0d, + 0x41, 0x1b, 0x0c, 0x0e, 0xec, 0xdf, 0xdc, 0x1b, 0xb8, 0x0f, 0x4a, 0xd4, 0xee, + 0x2d, 0xcf, 0x61, 0x14, 0xed, 0x28, 0xe6, 0xc1, 0x25, 0x35, 0xc1, 0x21, 0xe3, + 0x38, 0x0e, 0xe1, 0xf6, 0xe9, 0xe9, 0x08, 0xe8, 0xf7, 0xd3, 0xf0, 0x02, 0xeb, + 0x08, 0x07, 0x32, 0xf6, 0xd6, 0xfd, 0x27, 0x05, 0xf1, 0xea, 0x2d, 0xff, 0xeb, + 0xd0, 0xeb, 0xec, 0xed, 0x06, 0xfe, 0xec, 0x3a, 0x7f, 0x37, 0x23, 0xee, 0x17, + 0xd4, 0x14, 0xed, 0x48, 0x21, 0x08, 0x12, 0x17, 0x0b, 0x38, 0xca, 0xdf, 0x48, + 0x2d, 0xcb, 0x29, 0x2e, 0xf6, 0x33, 0xf7, 0xe8, 0xc6, 0xf1, 0xc9, 0xf5, 0x35, + 0x0e, 0xf6, 0xbc, 0x03, 0xf9, 0x1a, 0xfa, 0x3c, 0x07, 0x13, 0x29, 0x13, 0xe4, + 0x0f, 0x2e, 0x49, 0xec, 0xeb, 0x08, 0x07, 0x0f, 0x0e, 0xb8, 0x2e, 0xf1, 0xfb, + 0x06, 0xcb, 0x4f, 0x2d, 0xec, 0x5a, 0x00, 0x03, 0x17, 0xba, 0xe3, 0xcd, 0x01, + 0x98, 0xe3, 0x65, 0x29, 0xb4, 0x0b, 0x53, 0x3a, 0xed, 0x0f, 0x02, 0xee, 0xd0, + 0x12, 0x39, 0xda, 0x11, 0x09, 0xe0, 0x1e, 0x13, 0x08, 0x0a, 0xf4, 0xd5, 0x20, + 0xb8, 0x06, 0x29, 0x3b, 0xc3, 0xd8, 0x3d, 0x2e, 0x08, 0xe5, 0x0f, 0x02, 0xb1, + 0xf9, 0xe2, 0xef, 0x14, 0x4a, 0x09, 0xe7, 0xdf, 0x21, 0x2b, 0x2c, 0xd2, 0x39, + 0xef, 0xd5, 0x05, 0xd0, 0xff, 0xde, 0xbb, 0x0e, 0x1b, 0x0f, 0xf8, 0x01, 0x0a, + 0x4e, 0xe8, 0xd8, 0xfb, 0xf6, 0xe6, 0x01, 0x13, 0x4b, 0x00, 0xfa, 0xe6, 0xd1, + 0x11, 0x18, 0x56, 0x06, 0xf0, 0xd6, 0xf5, 0x6f, 0x09, 0x04, 0xcc, 0x01, 0xf7, + 0x2a, 0x57, 0xfc, 0xd3, 0x19, 0xfd, 0x3f, 0xc4, 0xf2, 0xe3, 0x03, 0xff, 0xff, + 0xc7, 0xc9, 0xf4, 0x0a, 0x18, 0xf0, 0x03, 0xfa, 0x06, 0xdd, 0x23, 0xc6, 0xfe, + 0xfb, 0x2d, 0x22, 0x0d, 0xd7, 0x39, 0x38, 0x11, 0xfc, 0xc5, 0x01, 0x0e, 0x58, + 0x81, 0xd7, 0xe5, 0xf7, 0x06, 0xfc, 0xfe, 0x13, 0x11, 0xe1, 0x09, 0xf1, 0xc0, + 0x39, 0x17, 0xc3, 0xcd, 0xf1, 0xf2, 0x19, 0xf2, 0xc0, 0xf5, 0x06, 0xe9, 0xeb, + 0x36, 0xe5, 0x22, 0x54, 0x08, 0xea, 0xd5, 0x4f, 0xd3, 0x0b, 0x12, 0xd2, 0x2d, + 0xf0, 0xea, 0x44, 0xec, 0xe1, 0xa5, 0x1c, 0x29, 0x0b, 0xd4, 0xd2, 0x0a, 0x50, + 0xed, 0x1a, 0x0c, 0x75, 0xfc, 0x63, 0x13, 0x09, 0x32, 0xd9, 0x03, 0x0d, 0x11, + 0xb0, 0xb5, 0x54, 0x2d, 0xd8, 0xff, 0xb2, 0x0b, 0x24, 0xf9, 0xf4, 0xc0, 0x18, + 0xf2, 0x19, 0xb8, 0x26, 0x08, 0xd1, 0xda, 0xd9, 0xf9, 0xc5, 0x22, 0xef, 0xcb, + 0x00, 0x1e, 0x06, 0x71, 0xf2, 0x7f, 0xa4, 0xfc, 0xff, 0x04, 0xd1, 0xeb, 0x04, + 0xd8, 0x48, 0xf5, 0x0e, 0xd0, 0xe9, 0x12, 0x1a, 0x07, 0xf0, 0xee, 0xb3, 0x20, + 0x19, 0x8a, 0xc8, 0xf1, 0x2d, 0x09, 0x2e, 0x19, 0x3d, 0x0b, 0x56, 0x11, 0x54, + 0x50, 0x0b, 0x00, 0x1e, 0x43, 0x19, 0x1e, 0xfa, 0x1e, 0xff, 0xde, 0x38, 0x19, + 0xf6, 0xee, 0x0f, 0x13, 0xd6, 0x04, 0x01, 0x00, 0xf2, 0x32, 0x03, 0x1b, 0x29, + 0x56, 0x23, 0xd7, 0xce, 0x44, 0x0a, 0x09, 0x04, 0x1d, 0x00, 0xf9, 0xc8, 0x3a, + 0xec, 0x36, 0x28, 0x4f, 0x2e, 0x03, 0xf3, 0xe7, 0xdb, 0xf9, 0xdd, 0x3e, 0xd1, + 0xd9, 0x60, 0xaa, 0x3d, 0xe0, 0x16, 0xe1, 0x01, 0xfe, 0xb1, 0xe4, 0x03, 0x26, + 0xb2, 0xf3, 0x2a, 0x7f, 0xbc, 0x07, 0x42, 0xa5, 0xf4, 0x09, 0x51, 0x31, 0x2f, + 0xbb, 0xe6, 0x01, 0xec, 0xf0, 0xb2, 0x38, 0x11, 0x65, 0x1b, 0x1f, 0x1d, 0xc9, + 0x36, 0xf2, 0xed, 0xd0, 0x06, 0x0a, 0xdf, 0x1d, 0x58, 0x44, 0xe7, 0x0a, 0x0f, + 0x20, 0x04, 0xde, 0x35, 0x3d, 0x04, 0x27, 0x5d, 0xfd, 0x44, 0x0c, 0x03, 0x3d, + 0x2a, 0xf9, 0xdd, 0x0a, 0xca, 0x06, 0xfc, 0xc5, 0x19, 0xd7, 0x44, 0x47, 0x17, + 0x3d, 0x31, 0x09, 0x16, 0x0e, 0xfb, 0x00, 0xdb, 0xf4, 0x17, 0x59, 0x08, 0xe9, + 0x30, 0xe0, 0x28, 0x03, 0xfe, 0x16, 0x04, 0xd0, 0x26, 0xed, 0x20, 0x34, 0xbd, + 0xc6, 0x02, 0xd9, 0xfe, 0x09, 0xf9, 0x36, 0x5f, 0x24, 0xba, 0xea, 0x2a, 0xde, + 0xd2, 0x9d, 0x9f, 0xf9, 0x02, 0x9d, 0x29, 0xb0, 0x2c, 0xca, 0x11, 0x15, 0x2c, + 0x04, 0xe4, 0xc4, 0x03, 0xba, 0x1a, 0xdd, 0x0f, 0x1b, 0x7f, 0xfb, 0x51, 0x18, + 0x10, 0x31, 0x18, 0x4b, 0x07, 0xe3, 0x22, 0xb7, 0xf5, 0xba, 0xed, 0x3e, 0x2d, + 0x16, 0xf7, 0xeb, 0x48, 0xdd, 0x1a, 0xe0, 0xdf, 0xee, 0x20, 0xca, 0xf9, 0x1b, + 0x23, 0x3e, 0xd1, 0xcd, 0xc7, 0xde, 0x62, 0x44, 0xce, 0x0d, 0xc4, 0xee, 0x17, + 0xda, 0x03, 0x35, 0xed, 0xd2, 0x4c, 0xfc, 0x5a, 0x09, 0x33, 0x5f, 0xdc, 0xe6, + 0xdc, 0x45, 0xab, 0x4b, 0x1c, 0x0b, 0xac, 0xf6, 0x2f, 0xb9, 0x4d, 0x18, 0xd5, + 0x59, 0xb1, 0x20, 0x58, 0xe4, 0xc2, 0x2c, 0x02, 0x24, 0xfd, 0x31, 0x04, 0xd4, + 0xcd, 0xe0, 0x26, 0x05, 0xe5, 0xe3, 0xef, 0xf2, 0xd3, 0x22, 0x7f, 0xdf, 0xf2, + 0xd3, 0x02, 0x08, 0xc0, 0xe3, 0xd5, 0xfc, 0xf8, 0xf4, 0xc4, 0x30, 0xd5, 0x22, + 0x0c, 0xea, 0x1c, 0xde, 0xc4, 0xf2, 0xdc, 0xe5, 0x0b, 0xbe, 0xf9, 0x66, 0x0c, + 0x05, 0xfa, 0xe1, 0xdc, 0x31, 0xdc, 0xe6, 0x13, 0x30, 0x1e, 0x1b, 0xf8, 0x01, + 0x10, 0x5f, 0x16, 0x07, 0xcd, 0x2a, 0x24, 0xec, 0xc6, 0x2d, 0x1e, 0x00, 0xf6, + 0xdd, 0xb9, 0xf3, 0xf9, 0x14, 0x35, 0xd8, 0x53, 0x07, 0x1c, 0xec, 0x52, 0xc6, + 0x14, 0xe0, 0x0e, 0x1f, 0xe7, 0x12, 0x05, 0xf1, 0x2d, 0xcf, 0xf9, 0xef, 0xf4, + 0xeb, 0xfd, 0xfc, 0x0e, 0xf7, 0xd3, 0x1a, 0xf0, 0xee, 0xd6, 0xe9, 0xf9, 0xea, + 0xc6, 0xce, 0x16, 0xd8, 0xe7, 0x01, 0x2f, 0x3d, 0x00, 0xfe, 0xee, 0xf7, 0xfb, + 0xd7, 0x1d, 0xdc, 0x4f, 0xed, 0xf8, 0x2d, 0x1d, 0xd6, 0x50, 0xd3, 0x07, 0x36, + 0x35, 0xcb, 0xde, 0xe0, 0x14, 0x03, 0xfd, 0xd4, 0xe5, 0x5b, 0xdc, 0xee, 0xf9, + 0xda, 0x23, 0x34, 0x0e, 0xee, 0xe6, 0xdd, 0x2c, 0xd8, 0xec, 0xe8, 0xd4, 0x61, + 0xf4, 0x36, 0xfc, 0x1f, 0x29, 0xeb, 0x05, 0x11, 0xe7, 0xa6, 0x14, 0x03, 0x08, + 0x0e, 0x02, 0xe3, 0xd1, 0xcd, 0x34, 0x14, 0x05, 0xf7, 0xd0, 0xce, 0x32, 0x81, + 0xff, 0xc6, 0xf7, 0x14, 0x00, 0x5b, 0xfb, 0xf6, 0x43, 0x30, 0x0e, 0x1d, 0x14, + 0x43, 0xe1, 0xcf, 0x05, 0x45, 0xe9, 0xa7, 0x0c, 0x55, 0xe7, 0x1c, 0x17, 0xc7, + 0x18, 0xd9, 0x97, 0xd0, 0xbf, 0xe3, 0x0f, 0xe0, 0xc9, 0x26, 0xe3, 0xb5, 0xc3, + 0xe8, 0x29, 0x27, 0xfa, 0xb4, 0x1d, 0xd4, 0x35, 0xce, 0x28, 0xf9, 0x30, 0xc0, + 0x24, 0xf0, 0x58, 0x08, 0xf6, 0x28, 0xe7, 0xe2, 0x19, 0x0d, 0x00, 0xd5, 0x01, + 0x26, 0xfb, 0x7f, 0xf7, 0xeb, 0xc0, 0xcc, 0xe3, 0xc3, 0xc9, 0xf8, 0x2d, 0xae, + 0x17, 0x25, 0x25, 0xbe, 0xc9, 0x2e, 0x3f, 0x94, 0x39, 0xbe, 0x01, 0xf9, 0x1d, + 0x9a, 0xb7, 0x03, 0xdd, 0xdb, 0x1a, 0xfd, 0x32, 0x0d, 0x0d, 0xf2, 0x38, 0xca, + 0x42, 0x67, 0xfc, 0x0b, 0xa9, 0xf4, 0xd4, 0x35, 0xee, 0xfa, 0x20, 0x12, 0xea, + 0x2d, 0xcb, 0xdd, 0xe3, 0xec, 0xe2, 0xf5, 0x44, 0x18, 0xef, 0x66, 0xdd, 0xfa, + 0xe2, 0xaf, 0x3e, 0xdc, 0xbc, 0xf2, 0x95, 0x4a, 0xa9, 0xed, 0x08, 0x4f, 0x0d, + 0x3d, 0x3b, 0x32, 0x3b, 0xf8, 0xda, 0x28, 0x77, 0xff, 0x00, 0x26, 0x46, 0x49, + 0xfc, 0xc8, 0xf9, 0x41, 0xd6, 0x02, 0x3e, 0xf3, 0xb4, 0xee, 0x0f, 0x3b, 0x28, + 0x2e, 0x1e, 0x0b, 0xc9, 0x37, 0x20, 0xf2, 0xed, 0x20, 0xa1, 0x06, 0xfa, 0xe0, + 0xc6, 0xca, 0x1f, 0x04, 0x23, 0x2b, 0x0f, 0x3d, 0xc7, 0x20, 0xf6, 0xd2, 0x5e, + 0xcc, 0xf7, 0xcf, 0x20, 0xca, 0xe2, 0x17, 0xba, 0x1b, 0x13, 0x01, 0xc3, 0xa7, + 0xe2, 0x66, 0xe8, 0xd6, 0xa1, 0x1f, 0x20, 0x98, 0x39, 0x1f, 0x6f, 0xeb, 0xc1, + 0x18, 0xec, 0xc6, 0x41, 0x13, 0x10, 0xff, 0xe1, 0x17, 0xe7, 0x53, 0xc9, 0x1a, + 0xd5, 0x03, 0x0e, 0x20, 0x29, 0xaf, 0x0f, 0xfc, 0x06, 0xe6, 0x1a, 0xfe, 0x47, + 0xee, 0x82, 0xa3, 0xc9, 0xfc, 0xaa, 0x9d, 0xff, 0xef, 0xd2, 0x1c, 0xff, 0x16, + 0x17, 0x9e, 0x44, 0x7f, 0x9e, 0x4c, 0xba, 0x17, 0x4c, 0xe0, 0x09, 0xca, 0xa8, + 0x45, 0x27, 0xcb, 0xdb, 0x55, 0x16, 0xf8, 0x13, 0xf2, 0xd5, 0xf8, 0xf2, 0x43, + 0x9e, 0xa4, 0x4e, 0xe7, 0x05, 0x38, 0xdd, 0x33, 0x62, 0xf9, 0xdf, 0xd6, 0x88, + 0xd1, 0xf8, 0x05, 0xcf, 0xe8, 0x57, 0xe8, 0x17, 0xe1, 0xef, 0x1d, 0x2c, 0xc7, + 0xb0, 0xcd, 0x2b, 0x88, 0x0e, 0xc5, 0xc1, 0x07, 0xff, 0xdc, 0x0f, 0x07, 0x17, + 0x49, 0xd9, 0xe5, 0x34, 0xe1, 0xe6, 0xef, 0xf2, 0xcb, 0xdd, 0x1c, 0xf6, 0x38, + 0xfe, 0xf4, 0xe5, 0x14, 0x21, 0xcc, 0x36, 0x28, 0x07, 0x4c, 0xfc, 0x03, 0xbe, + 0x2f, 0xe3, 0xf6, 0xfb, 0xfb, 0x1a, 0x1c, 0x20, 0x11, 0xe2, 0x1b, 0xc8, 0x01, + 0xf8, 0xc6, 0x1a, 0x81, 0x69, 0xd5, 0x3d, 0xfa, 0xe3, 0xef, 0xb2, 0x29, 0xe6, + 0xdd, 0x1b, 0xf8, 0xf6, 0x37, 0xf6, 0x3a, 0x5f, 0xca, 0xdc, 0x49, 0x0a, 0xcf, + 0xd3, 0xd6, 0x29, 0x6a, 0xf6, 0xeb, 0x00, 0x31, 0x2e, 0x4d, 0xf2, 0x15, 0xec, + 0xf8, 0xf0, 0x2f, 0xd3, 0xf0, 0xd6, 0x22, 0x27, 0x24, 0xf2, 0xe2, 0x20, 0x12, + 0x25, 0xfb, 0x2c, 0xec, 0xd0, 0xdc, 0x0f, 0x37, 0x09, 0xfd, 0xe6, 0xfd, 0x25, + 0xe0, 0xfe, 0x38, 0x09, 0xde, 0xf8, 0xe6, 0xed, 0xe6, 0x0f, 0xe4, 0x12, 0xd2, + 0xbf, 0xef, 0x09, 0x33, 0x1a, 0x2d, 0xe8, 0xdb, 0xd5, 0xe8, 0x2d, 0x12, 0x01, + 0x2a, 0xe3, 0x81, 0xf9, 0xd0, 0x0e, 0xd7, 0xfc, 0x1d, 0xea, 0x17, 0xf1, 0x00, + 0x4b, 0xd0, 0x0b, 0xe4, 0x10, 0xfa, 0x19, 0xd2, 0xf1, 0x11, 0xe9, 0xcf, 0xc6, + 0x16, 0x20, 0x1d, 0x04, 0x15, 0x04, 0xe5, 0xc6, 0x14, 0x2b, 0x03, 0xd4, 0xc2, + 0xfd, 0xfb, 0x10, 0xc2, 0x0b, 0xd3, 0xfe, 0x2f, 0xec, 0x16, 0xfc, 0x32, 0xdf, + 0xfe, 0xe1, 0x0b, 0xf7, 0x42, 0xfc, 0xf7, 0xc8, 0xc0, 0x38, 0xed, 0xc9, 0xd5, + 0x43, 0xf6, 0xd6, 0xc5, 0xcc, 0xf8, 0xd0, 0x20, 0xf9, 0xe2, 0x30, 0xf4, 0x27, + 0x20, 0x0d, 0x5b, 0x13, 0xe0, 0x01, 0x18, 0xe9, 0xff, 0xde, 0x00, 0x44, 0xea, + 0xdd, 0x11, 0xf8, 0x05, 0x01, 0xfb, 0x3c, 0x0e, 0xe6, 0xf2, 0xba, 0x00, 0xfa, + 0x09, 0x0d, 0x03, 0xcf, 0xec, 0x3c, 0x12, 0x05, 0xc5, 0x07, 0xd6, 0xf7, 0x2c, + 0xf3, 0x2a, 0xe9, 0x18, 0xef, 0xe4, 0x0e, 0xd0, 0x8e, 0x1c, 0xb9, 0x2b, 0xa7, + 0x1f, 0xe6, 0xfc, 0xb9, 0x54, 0xda, 0x2b, 0xd8, 0xd2, 0xee, 0xfd, 0x7f, 0x0f, + 0xfc, 0xae, 0xc7, 0xd8, 0xfd, 0x0a, 0xa7, 0xdf, 0xc9, 0x0d, 0xf8, 0xe6, 0x21, + 0x01, 0x23, 0x0b, 0x28, 0xb5, 0x30, 0xdf, 0x4e, 0xc1, 0x42, 0x37, 0xd0, 0xd1, + 0x15, 0xfc, 0xfd, 0x48, 0x24, 0xd8, 0xd3, 0x46, 0x0f, 0x2e, 0x37, 0xb9, 0xde, + 0xc3, 0x9f, 0x4b, 0x29, 0x13, 0x04, 0xc8, 0x0c, 0xdc, 0x8d, 0x47, 0x18, 0x0d, + 0x3f, 0xb9, 0x42, 0xfe, 0x17, 0x40, 0xcb, 0xd0, 0x4a, 0x0d, 0xcc, 0x05, 0x0f, + 0xd5, 0x74, 0x5f, 0x3e, 0xba, 0xcf, 0xe9, 0xf9, 0x92, 0xd7, 0xf3, 0x13, 0x28, + 0x1a, 0xbf, 0xf7, 0xcd, 0xeb, 0x32, 0x48, 0x0f, 0xcf, 0x2e, 0xec, 0x4d, 0x04, + 0x3a, 0xe1, 0xff, 0x1f, 0x29, 0xb4, 0xf6, 0xe6, 0x26, 0x0d, 0x99, 0xae, 0xbb, + 0xed, 0xfa, 0xbd, 0xea, 0xd3, 0x09, 0x57, 0x1b, 0x0f, 0x10, 0x00, 0xb0, 0x38, + 0xf8, 0xfe, 0xdf, 0xff, 0x1a, 0xd2, 0x66, 0xe5, 0x22, 0x22, 0xfe, 0xe7, 0xe2, + 0xfb, 0x7f, 0x10, 0xd2, 0xf4, 0x42, 0x59, 0x63, 0xc7, 0x52, 0x0b, 0x0c, 0xf5, + 0xda, 0x04, 0xc7, 0x09, 0xe2, 0xfb, 0xf0, 0xf7, 0x23, 0x1e, 0xb7, 0x65, 0xf2, + 0xec, 0xf5, 0x10, 0xd6, 0xae, 0xff, 0x30, 0xd0, 0x2e, 0x14, 0xc9, 0x30, 0xec, + 0x2f, 0xdd, 0xea, 0xf2, 0x39, 0x0d, 0xf0, 0xfd, 0x0e, 0x08, 0x33, 0x00, 0x05, + 0xe3, 0x01, 0x21, 0xba, 0x1f, 0xf3, 0xea, 0xe1, 0x19, 0xa8, 0xea, 0xbf, 0xf6, + 0xb2, 0x17, 0x39, 0x0f, 0x25, 0x29, 0x3f, 0x2f, 0x12, 0x0a, 0x3a, 0xdd, 0x37, + 0x26, 0xed, 0x51, 0xeb, 0xdc, 0xdd, 0x27, 0x02, 0xfe, 0x38, 0x31, 0xcc, 0xb3, + 0x17, 0x15, 0xc9, 0xea, 0xea, 0x19, 0x08, 0xf7, 0x25, 0x02, 0xdc, 0xc6, 0xd2, + 0xe8, 0x32, 0xe9, 0xe8, 0x01, 0x38, 0xc8, 0xea, 0x30, 0xdb, 0x1c, 0x05, 0x21, + 0xca, 0x9d, 0x2c, 0x1e, 0xe2, 0xa6, 0x5e, 0x68, 0xb6, 0x14, 0xee, 0xe5, 0x05, + 0x1a, 0xf7, 0xb0, 0x1c, 0xd5, 0x16, 0xcb, 0x29, 0x23, 0xe4, 0x03, 0x03, 0xd9, + 0xee, 0xb8, 0xf7, 0x4a, 0x1d, 0xc8, 0xd1, 0x70, 0x14, 0x1d, 0xf0, 0x35, 0xb7, + 0x97, 0xfd, 0x81, 0x28, 0xb7, 0x46, 0xe7, 0x10, 0x42, 0xf5, 0x2b, 0x17, 0xd5, + 0x2b, 0xb7, 0xcf, 0x60, 0xfa, 0xe4, 0xf3, 0xf2, 0xd3, 0x19, 0xc8, 0xb5, 0xda, + 0xea, 0x4f, 0x04, 0xd5, 0xe0, 0x47, 0x69, 0x4c, 0x3c, 0xe8, 0x40, 0x00, 0xc2, + 0x40, 0x99, 0xf4, 0x0a, 0x2e, 0xe6, 0xdb, 0x1d, 0x00, 0x8b, 0x0f, 0xd8, 0xfb, + 0x1d, 0x13, 0xf8, 0x36, 0x2b, 0x28, 0xfe, 0xe6, 0xc6, 0x78, 0xbc, 0x12, 0xea, + 0xa2, 0xf7, 0x26, 0x0d, 0x15, 0x31, 0x2e, 0x0a, 0xd4, 0x0f, 0xf2, 0x64, 0x37, + 0x45, 0xa7, 0xf1, 0x2a, 0xdf, 0xe8, 0x0e, 0xd8, 0xac, 0x33, 0x1f, 0xe1, 0xc3, + 0x06, 0xf5, 0x27, 0x00, 0x27, 0xd7, 0xc6, 0x23, 0xbc, 0x29, 0x31, 0xe2, 0x29, + 0xe6, 0x3f, 0xda, 0x35, 0xb8, 0x18, 0x46, 0x4b, 0x78, 0x4b, 0x24, 0xfd, 0xf8, + 0x2e, 0x11, 0x50, 0xb0, 0xe1, 0xf8, 0x5b, 0x0a, 0xf5, 0x0e, 0x18, 0xba, 0xce, + 0x1a, 0x72, 0xc4, 0x06, 0xf2, 0x0c, 0x10, 0x7e, 0xc5, 0x28, 0x55, 0xfe, 0x08, + 0xe8, 0x22, 0x9d, 0x0c, 0xcb, 0x7f, 0xb3, 0xe5, 0xe6, 0xd3, 0xa0, 0xab, 0xc6, + 0xbd, 0xfe, 0x1a, 0x15, 0xf1, 0x44, 0xfe, 0xe8, 0x1e, 0x13, 0xef, 0x11, 0xc6, + 0x4d, 0x66, 0x0d, 0xde, 0xd5, 0x41, 0xf5, 0x9b, 0x7c, 0x2c, 0x1a, 0x51, 0x08, + 0xce, 0xdf, 0xec, 0x4e, 0x4b, 0x2c, 0xfa, 0x3c, 0x09, 0xac, 0xea, 0xd0, 0x2c, + 0xfc, 0x06, 0x0f, 0x0d, 0x3b, 0xd1, 0x10, 0x12, 0x5f, 0xdb, 0x12, 0xfe, 0x01, + 0xeb, 0xcb, 0xe7, 0xb3, 0x29, 0xdd, 0xf7, 0x14, 0x0b, 0x02, 0x12, 0xe1, 0xf9, + 0x05, 0x5f, 0xfb, 0x0a, 0xed, 0xe9, 0xcd, 0x04, 0x14, 0x1a, 0xe7, 0x40, 0x1c, + 0xab, 0xfc, 0x48, 0xf4, 0x0c, 0xfc, 0xfd, 0x00, 0x0e, 0x27, 0x1c, 0x2f, 0x29, + 0x09, 0x08, 0x08, 0xf9, 0xea, 0x2e, 0x0b, 0x1f, 0x06, 0xe8, 0xe2, 0xdd, 0xff, + 0x19, 0x21, 0x55, 0x03, 0xed, 0x4d, 0xcc, 0x64, 0x09, 0x64, 0x06, 0x57, 0x11, + 0xcb, 0x08, 0xd1, 0x7d, 0x28, 0x23, 0xf9, 0x39, 0x17, 0xed, 0x0c, 0xda, 0xe0, + 0x08, 0xf4, 0x06, 0xed, 0x21, 0x06, 0xda, 0x3d, 0x1d, 0x01, 0x28, 0xec, 0xc7, + 0x2a, 0x1d, 0x1a, 0x4d, 0x2f, 0xb4, 0xf8, 0x0c, 0xe2, 0x07, 0x02, 0xd5, 0x0c, + 0xe3, 0x25, 0x03, 0x31, 0x41, 0xf8, 0xeb, 0xed, 0xe8, 0xd3, 0x1c, 0xb0, 0x12, + 0x05, 0x81, 0x26, 0x10, 0x02, 0x3d, 0x4a, 0xf3, 0xdf, 0x4e, 0xf4, 0x16, 0x27, + 0xf3, 0xee, 0xe1, 0xac, 0xd4, 0xbe, 0x1c, 0x18, 0xe9, 0x4d, 0xf9, 0xd4, 0xca, + 0x3b, 0xe7, 0xde, 0x20, 0xf3, 0x07, 0x0f, 0x07, 0xe6, 0xfe, 0xf1, 0xc5, 0x64, + 0xe4, 0x01, 0x06, 0x10, 0xff, 0xe8, 0x22, 0x1e, 0x34, 0xee, 0x47, 0x15, 0x25, + 0xbc, 0xee, 0x4d, 0x2b, 0xf6, 0xe5, 0x17, 0xc6, 0x37, 0x05, 0x13, 0x84, 0x05, + 0x1e, 0x0d, 0x0d, 0xee, 0xcf, 0x4e, 0x4a, 0xdf, 0xd7, 0xf2, 0x06, 0xfa, 0x90, + 0xd0, 0x72, 0xdc, 0xcc, 0xbc, 0x08, 0x0a, 0xa6, 0xb7, 0xf0, 0xcc, 0x13, 0xbe, + 0x5c, 0x3e, 0x08, 0x0e, 0x14, 0x02, 0x30, 0xdf, 0x3b, 0x4a, 0x13, 0xf0, 0x2f, + 0x27, 0x02, 0xdf, 0x27, 0x24, 0x23, 0xfe, 0x10, 0x08, 0x69, 0x3f, 0xbb, 0xfc, + 0x6d, 0x3d, 0x28, 0xed, 0xed, 0xed, 0x3a, 0xe3, 0xda, 0x81, 0x14, 0xd6, 0xe3, + 0xd6, 0xc5, 0xec, 0x37, 0x38, 0x25, 0x1c, 0xe7, 0x0a, 0x1b, 0x16, 0xe9, 0xfa, + 0xf4, 0xe6, 0x0b, 0x07, 0x22, 0x12, 0x16, 0xf4, 0x0a, 0xd1, 0xfe, 0x06, 0xdd, + 0xe3, 0xfa, 0x0e, 0x14, 0x25, 0x05, 0xed, 0x44, 0xf6, 0xd1, 0xeb, 0xfd, 0xf5, + 0x19, 0xe9, 0xe8, 0x1b, 0x0d, 0xed, 0x0b, 0x1c, 0x33, 0xec, 0xeb, 0xe5, 0x08, + 0x09, 0x25, 0x09, 0xe6, 0xf3, 0x01, 0x38, 0x00, 0x0d, 0x11, 0x05, 0x17, 0x0a, + 0x08, 0x08, 0xfb, 0x7f, 0xe8, 0x02, 0xff, 0x1c, 0x4d, 0xe8, 0xf9, 0xd3, 0x0f, + 0x21, 0xdb, 0xda, 0x17, 0xca, 0xf6, 0x1f, 0x07, 0x00, 0x09, 0x0d, 0xfb, 0x34, + 0x0e, 0x01, 0xfa, 0xd8, 0xf5, 0x23, 0x00, 0x48, 0x14, 0xfd, 0x0d, 0x20, 0x0d, + 0xf3, 0x03, 0x01, 0x1b, 0xf5, 0x2f, 0xf4, 0xe7, 0xe9, 0xdf, 0xb7, 0xd3, 0x1e, + 0x41, 0x0a, 0xe6, 0x18, 0xe6, 0xf7, 0xfa, 0x0f, 0x2b, 0x01, 0xe5, 0xcb, 0x27, + 0xfc, 0xf6, 0x07, 0xe0, 0xed, 0xe6, 0x12, 0xe1, 0xd9, 0xf2, 0xec, 0x19, 0x18, + 0xf3, 0xf9, 0x16, 0xd3, 0x00, 0x0b, 0x19, 0xee, 0x23, 0x02, 0x1e, 0xec, 0xfe, + 0xfd, 0xee, 0x07, 0x03, 0xe6, 0x00, 0xd9, 0xe4, 0x19, 0x07, 0x02, 0xfb, 0xf1, + 0xda, 0xbf, 0xe6, 0xd1, 0xf7, 0xf5, 0xc8, 0x14, 0x08, 0x04, 0xed, 0x7f, 0x01, + 0xd7, 0x48, 0x02, 0x0a, 0x4f, 0x05, 0xdb, 0x0d, 0x39, 0x1d, 0x00, 0xf0, 0xe6, + 0x02, 0x17, 0xd9, 0x21, 0xf4, 0xf1, 0x36, 0xe8, 0xe1, 0x07, 0xa2, 0xfc, 0xe3, + 0xf7, 0x05, 0x1c, 0x19, 0xf0, 0x19, 0x19, 0xe6, 0xe3, 0x03, 0x08, 0x1e, 0xe2, + 0x26, 0x17, 0xeb, 0x0e, 0x17, 0x33, 0xe3, 0x14, 0xef, 0xf3, 0xd6, 0xfb, 0xe3, + 0x2a, 0xd7, 0x0d, 0x16, 0x0b, 0x05, 0xf4, 0xe7, 0xf6, 0x28, 0xf3, 0x05, 0xde, + 0xab, 0xf3, 0xeb, 0xf7, 0xd2, 0xd0, 0x14, 0xfb, 0xfc, 0x0b, 0x1b, 0x18, 0xe8, + 0x14, 0x27, 0xfe, 0x3b, 0x19, 0x0a, 0xc0, 0x18, 0xef, 0x01, 0x2d, 0x04, 0x10, + 0x26, 0x33, 0x3b, 0xef, 0x20, 0xeb, 0xfc, 0x0e, 0xc7, 0x1c, 0x12, 0x22, 0xeb, + 0x23, 0xe2, 0x4f, 0x00, 0x32, 0xc3, 0x0d, 0x27, 0xb4, 0xf5, 0xca, 0xd1, 0xdf, + 0x2b, 0x8e, 0xc5, 0xe7, 0xf2, 0x15, 0xf7, 0x3c, 0xac, 0xba, 0x17, 0xec, 0xfb, + 0x0a, 0x0a, 0xc5, 0x3f, 0x93, 0x3e, 0x1c, 0xe9, 0xf3, 0xff, 0xd7, 0x2e, 0xcb, + 0x04, 0x1a, 0x1e, 0x18, 0xfa, 0x0d, 0x18, 0xdd, 0xf1, 0x55, 0x15, 0x60, 0xb8, + 0x2e, 0xd1, 0x11, 0x0b, 0x64, 0x02, 0xa6, 0x0f, 0x12, 0x06, 0x19, 0x08, 0xd9, + 0xec, 0xf5, 0xee, 0x05, 0x81, 0x5e, 0xc6, 0x16, 0x0b, 0x08, 0xf0, 0xec, 0xde, + 0x12, 0xf4, 0xe6, 0x63, 0xff, 0x22, 0xd8, 0xf3, 0xfb, 0x1c, 0xe6, 0x2d, 0x14, + 0x0b, 0x1c, 0x08, 0xb7, 0xee, 0xe9, 0x1f, 0xe4, 0x12, 0x19, 0x18, 0x09, 0xcf, + 0xcc, 0xb0, 0x21, 0xf9, 0xda, 0x08, 0x01, 0x38, 0xe7, 0x37, 0xe5, 0x04, 0xfc, + 0x30, 0x05, 0xec, 0x58, 0x12, 0x20, 0xfd, 0x11, 0x0a, 0xe7, 0x28, 0xfb, 0x01, + 0xe7, 0xec, 0xde, 0x49, 0x21, 0xf4, 0xfc, 0x19, 0x0f, 0xa5, 0xf2, 0xd2, 0xec, + 0xf4, 0x47, 0xd6, 0xc7, 0xb6, 0x5d, 0xf7, 0x0e, 0xc1, 0x36, 0xed, 0x16, 0x25, + 0xd7, 0xe6, 0x05, 0x14, 0x40, 0x3d, 0x01, 0xee, 0xdf, 0x35, 0x5c, 0xe2, 0x0a, + 0x3c, 0xf5, 0xe8, 0x0a, 0x33, 0x09, 0x2b, 0xc2, 0x03, 0x3c, 0xfe, 0xfd, 0x39, + 0xdc, 0x03, 0x12, 0xf6, 0x14, 0x07, 0xf0, 0xd8, 0x2a, 0xe0, 0x34, 0x0e, 0x13, + 0x0e, 0xfc, 0x0d, 0x39, 0x1c, 0xe3, 0x04, 0x25, 0xfd, 0x1c, 0x1d, 0xdb, 0x25, + 0xdd, 0x4a, 0x06, 0x0f, 0x0e, 0x11, 0xe4, 0x1f, 0xd6, 0xf0, 0x23, 0xec, 0x10, + 0xf5, 0x87, 0xb0, 0x36, 0xf7, 0x19, 0x2b, 0x1a, 0xbc, 0x04, 0x81, 0xdc, 0xd0, + 0xd4, 0xd7, 0x37, 0x09, 0xe8, 0xc0, 0xcc, 0x30, 0xf9, 0x25, 0xd4, 0x9f, 0x09, + 0x2c, 0xf8, 0x15, 0x71, 0x01, 0xfe, 0x20, 0xeb, 0x0a, 0xd9, 0x22, 0xe4, 0xfc, + 0x4e, 0x15, 0xef, 0xfe, 0x11, 0x3b, 0xf9, 0x1c, 0xc8, 0xec, 0xf2, 0x08, 0xf3, + 0xda, 0x24, 0xdf, 0xe4, 0x1e, 0x56, 0xfd, 0xc8, 0xf9, 0x1a, 0xec, 0xcb, 0xbb, + 0x3e, 0xfe, 0xdf, 0x4e, 0x12, 0x1d, 0x6f, 0xac, 0x01, 0x2e, 0x2f, 0xe2, 0xd3, + 0xf1, 0x05, 0xdd, 0xc4, 0xdc, 0xdd, 0xf1, 0x03, 0x0e, 0xd0, 0xdb, 0xbb, 0xb6, + 0x13, 0x42, 0x2b, 0x1b, 0x45, 0xf5, 0x16, 0xad, 0xc7, 0xf6, 0x28, 0xc5, 0xe9, + 0x45, 0x3d, 0xbd, 0x08, 0x03, 0x02, 0x86, 0x26, 0x1c, 0x2b, 0x7f, 0xf2, 0xcb, + 0xf9, 0xbd, 0x60, 0x04, 0x37, 0x37, 0xdf, 0xd6, 0x00, 0x09, 0x22, 0x17, 0x01, + 0x32, 0xd0, 0xcf, 0x3f, 0x35, 0x7b, 0x36, 0x1e, 0xcb, 0x08, 0xe9, 0x20, 0xd9, + 0x39, 0x3c, 0x20, 0x4d, 0xa2, 0x1c, 0xe4, 0xef, 0xf7, 0xd7, 0x05, 0xfe, 0xc0, + 0xe8, 0x3a, 0xff, 0x0f, 0xf2, 0xec, 0x0a, 0xe6, 0x00, 0x2f, 0xe5, 0x19, 0xa6, + 0xf1, 0xd4, 0xef, 0xd5, 0x29, 0xa5, 0x31, 0x02, 0x9c, 0xf9, 0x04, 0x08, 0xac, + 0xfb, 0xf9, 0xe1, 0xea, 0xe8, 0xd1, 0xe8, 0xe0, 0x2d, 0xb8, 0xd7, 0xde, 0x2f, + 0xc1, 0xf7, 0x0e, 0x07, 0xe8, 0x06, 0xb1, 0x4a, 0x42, 0xd1, 0x9e, 0xcf, 0x21, + 0x98, 0x7f, 0xef, 0x23, 0x30, 0xff, 0xee, 0xc5, 0xc3, 0x2d, 0x06, 0xc4, 0x34, + 0x00, 0x41, 0xb3, 0x07, 0x52, 0xf7, 0x24, 0x14, 0xee, 0xfe, 0xde, 0xf2, 0xae, + 0x11, 0xef, 0xe7, 0x21, 0xde, 0x26, 0x19, 0x1a, 0x14, 0xfb, 0xb5, 0x36, 0xcc, + 0x36, 0xf8, 0x01, 0xb9, 0xe7, 0x07, 0xe2, 0x61, 0x02, 0x3e, 0x14, 0x20, 0xd4, + 0x09, 0xf9, 0xc8, 0xe2, 0xf6, 0x11, 0x1f, 0x30, 0xd0, 0xfb, 0xfa, 0x31, 0x50, + 0x6b, 0xdb, 0xf3, 0x2d, 0xf5, 0xf1, 0xb1, 0x36, 0x00, 0xf9, 0xee, 0x01, 0x14, + 0x36, 0xe1, 0x19, 0xea, 0xea, 0xeb, 0x2d, 0x25, 0x06, 0xb4, 0x47, 0x48, 0xcf, + 0x2f, 0x00, 0xdc, 0x14, 0xd3, 0x95, 0xe1, 0x1f, 0x1b, 0xb6, 0xfe, 0xc8, 0xdf, + 0xa8, 0xc0, 0xff, 0x06, 0xca, 0xd4, 0x05, 0x07, 0x07, 0xcc, 0xa7, 0xb2, 0xca, + 0x5a, 0x7f, 0x22, 0x09, 0xc1, 0xaf, 0xaf, 0xf9, 0xf2, 0xcb, 0xde, 0x04, 0x07, + 0x91, 0x95, 0x6c, 0xd8, 0xc7, 0xaf, 0xba, 0x0a, 0xe8, 0x33, 0x35, 0x0c, 0x06, + 0xaf, 0xf7, 0xd6, 0x46, 0x39, 0xeb, 0xf2, 0x62, 0x26, 0x02, 0xec, 0x14, 0x17, + 0xee, 0x52, 0x5a, 0x1e, 0xe8, 0xe4, 0x06, 0x18, 0x12, 0x42, 0x0d, 0x42, 0xdb, + 0x23, 0xca, 0x0e, 0xfe, 0x0a, 0xfe, 0xd6, 0x23, 0xf1, 0x2c, 0x7e, 0xee, 0xae, + 0xa2, 0x33, 0x82, 0xc3, 0xe3, 0x00, 0xf0, 0xff, 0xd7, 0xd0, 0xd3, 0xf1, 0xbe, + 0x4c, 0x4f, 0xe8, 0x48, 0x0c, 0xa2, 0xdd, 0x42, 0x21, 0xc9, 0x2b, 0x8c, 0x11, + 0xf6, 0x1b, 0xcf, 0x5a, 0xd0, 0x30, 0xd4, 0x1d, 0x34, 0xf0, 0xf9, 0xcb, 0xef, + 0xb7, 0xda, 0xf5, 0x2a, 0xeb, 0xce, 0x1a, 0x8a, 0xda, 0xff, 0x78, 0xd3, 0x01, + 0x3c, 0xea, 0xf4, 0xe2, 0x34, 0x81, 0x04, 0xa4, 0x1c, 0x1a, 0x12, 0xb6, 0x62, + 0xbd, 0x11, 0xa1, 0xf3, 0x37, 0x51, 0xb7, 0x2f, 0x05, 0xd2, 0xed, 0xac, 0x44, + 0x07, 0xdf, 0x1c, 0x0f, 0xf3, 0xcf, 0xf1, 0x2d, 0xc1, 0xc0, 0xd8, 0x0b, 0x47, + 0xf9, 0x42, 0xde, 0x1d, 0x05, 0x02, 0xfd, 0x02, 0x0a, 0xae, 0x45, 0x12, 0x0f, + 0xc8, 0x29, 0xbb, 0xc0, 0x07, 0xe3, 0xd3, 0x32, 0xeb, 0x4f, 0xc7, 0x58, 0x63, + 0x96, 0xe3, 0x7b, 0xc6, 0xff, 0xe2, 0xf4, 0x48, 0x53, 0xf0, 0xda, 0x0a, 0xd4, + 0xd4, 0x19, 0x63, 0xf9, 0x0f, 0x16, 0x26, 0x1f, 0xec, 0xff, 0x18, 0x7f, 0x1e, + 0x0b, 0x13, 0x31, 0xfe, 0xf8, 0x1a, 0xec, 0x28, 0xe7, 0xcc, 0xf1, 0xe1, 0xd3, + 0xfd, 0x0e, 0xdd, 0xef, 0xeb, 0xf0, 0xae, 0x00, 0xc9, 0x10, 0xf1, 0xf4, 0xc7, + 0x16, 0x51, 0xdf, 0xe1, 0x0e, 0xef, 0x0e, 0x0b, 0x1b, 0xd4, 0xd8, 0xdb, 0xc4, + 0x21, 0xdf, 0xe5, 0xea, 0x5a, 0xe9, 0x26, 0x4f, 0x1e, 0x1e, 0x13, 0x24, 0x34, + 0x3f, 0xb9, 0xfb, 0xf3, 0xe8, 0x3d, 0x40, 0x06, 0x0b, 0x1c, 0xf0, 0x2b, 0x26, + 0xe7, 0x14, 0x18, 0xff, 0x40, 0xeb, 0x0b, 0xd6, 0x12, 0xc1, 0x45, 0xda, 0xfc, + 0x0b, 0x25, 0x14, 0x3d, 0xe9, 0xf8, 0x08, 0x52, 0x15, 0xf9, 0x01, 0xa7, 0xe4, + 0xc3, 0xee, 0xfa, 0xe3, 0x10, 0x17, 0xef, 0xea, 0x05, 0x1b, 0x0c, 0xec, 0x0a, + 0x39, 0xf1, 0xdf, 0xe3, 0xb8, 0xdb, 0xfb, 0x2a, 0xd9, 0xc8, 0x39, 0x0b, 0x1b, + 0xe0, 0xf4, 0x0e, 0xf0, 0x43, 0xb3, 0x13, 0xcd, 0xfd, 0xd0, 0xdb, 0x03, 0xe6, + 0xe4, 0xf4, 0xf1, 0xf8, 0x36, 0x01, 0x0f, 0xfe, 0x15, 0x0f, 0xf3, 0x0e, 0x35, + 0xfe, 0x04, 0xd3, 0xca, 0x00, 0xd4, 0xd9, 0x2e, 0x16, 0x48, 0x33, 0x25, 0xbc, + 0x14, 0x23, 0xf3, 0xaa, 0xec, 0xc6, 0xea, 0x08, 0x7f, 0xc1, 0x04, 0x27, 0x0e, + 0xfb, 0x54, 0xad, 0x08, 0xea, 0x1a, 0xfb, 0xe0, 0xcc, 0xf3, 0xd6, 0xd6, 0x50, + 0x20, 0xe7, 0x0a, 0xdc, 0x24, 0x05, 0xeb, 0xd4, 0xbe, 0xdf, 0xe6, 0x12, 0x0a, + 0xfc, 0x1d, 0xe7, 0xca, 0x10, 0xf9, 0x02, 0xde, 0xe9, 0xc1, 0xe3, 0xd6, 0x1f, + 0x02, 0xec, 0xda, 0x1f, 0xd3, 0x05, 0x21, 0xd8, 0x22, 0xfb, 0x11, 0x0e, 0x32, + 0x40, 0xdc, 0x05, 0xeb, 0xca, 0x31, 0x26, 0xd4, 0xf8, 0xfa, 0xf6, 0x0f, 0xcd, + 0xd3, 0x1c, 0x5f, 0xd7, 0xda, 0xee, 0x3a, 0x26, 0x14, 0xe5, 0xe0, 0xeb, 0xfa, + 0xf6, 0x0e, 0x17, 0x2d, 0xca, 0xad, 0x4d, 0x32, 0xe2, 0xfe, 0x3a, 0xed, 0xda, + 0x17, 0xde, 0xba, 0xf2, 0x2b, 0xf0, 0x0c, 0xe0, 0xca, 0x0a, 0x38, 0x04, 0x25, + 0xe9, 0x0e, 0xd2, 0x52, 0xd5, 0x20, 0x2f, 0xe5, 0x4c, 0x1d, 0x1f, 0x11, 0xdc, + 0x34, 0x3c, 0x34, 0x1f, 0xe2, 0x24, 0x0b, 0xf8, 0x25, 0x35, 0xe0, 0xf1, 0x97, + 0xf3, 0x1a, 0xfb, 0x02, 0x4b, 0xeb, 0x2c, 0x32, 0xea, 0x3e, 0xdd, 0x14, 0x2c, + 0xf2, 0x12, 0x24, 0xc7, 0xe4, 0x47, 0x67, 0x32, 0x81, 0x0e, 0x03, 0x40, 0x39, + 0x4f, 0x33, 0x15, 0x12, 0xe2, 0x26, 0xc7, 0xf9, 0x09, 0xff, 0x22, 0x3f, 0xf3, + 0x01, 0xab, 0x15, 0xd1, 0x31, 0xdf, 0xd6, 0xdf, 0x24, 0xe4, 0x10, 0x04, 0x5e, + 0x19, 0xe0, 0x09, 0xfe, 0x39, 0x10, 0x23, 0x7e, 0x17, 0x1e, 0xc7, 0xa6, 0x22, + 0x0b, 0x3f, 0x11, 0xf3, 0x05, 0x3c, 0x1b, 0x40, 0x0e, 0x44, 0xf4, 0x0d, 0x1c, + 0x0d, 0xdb, 0xe0, 0xe0, 0x30, 0x1a, 0xf6, 0xf4, 0x20, 0x4d, 0x3c, 0x01, 0xff, + 0x09, 0xd6, 0x02, 0xe8, 0x12, 0xe7, 0xde, 0xc6, 0x19, 0xe3, 0x15, 0x1e, 0x11, + 0xda, 0xca, 0x46, 0x07, 0xe9, 0xba, 0x1a, 0x1d, 0xec, 0xd5, 0xfc, 0x31, 0x18, + 0x0e, 0x55, 0x04, 0xe5, 0xd4, 0x02, 0x0c, 0xfe, 0xfe, 0xc6, 0x2c, 0xfe, 0xa2, + 0xed, 0xe7, 0x25, 0xe4, 0xfe, 0xf5, 0x55, 0x1d, 0xe7, 0x7f, 0xe6, 0x00, 0xeb, + 0x00, 0xfb, 0xde, 0xe5, 0x0a, 0xa8, 0x36, 0xe7, 0x26, 0xf4, 0xb7, 0xf7, 0x4d, + 0x05, 0xfc, 0xc3, 0xfd, 0xec, 0xfb, 0xe4, 0xfc, 0xfe, 0xe4, 0xfc, 0x20, 0xe3, + 0xd6, 0x1b, 0xf2, 0x46, 0xe8, 0x3b, 0x03, 0xe2, 0x4b, 0xec, 0x0e, 0x37, 0x14, + 0xf9, 0x2e, 0xde, 0xd6, 0x3b, 0xdf, 0x14, 0xd6, 0xec, 0x3e, 0x24, 0xeb, 0xd3, + 0xc8, 0xd6, 0x3c, 0xfd, 0xf8, 0xe9, 0xde, 0x11, 0xed, 0x08, 0x16, 0x08, 0xe4, + 0xd4, 0x0f, 0xbb, 0xe4, 0x1e, 0x1f, 0xe5, 0xd9, 0xdb, 0x31, 0x03, 0xff, 0x0d, + 0xf8, 0x3e, 0x0a, 0x7f, 0x67, 0xe0, 0xdb, 0xf6, 0x09, 0x01, 0x57, 0xf5, 0xe8, + 0x04, 0x0f, 0xed, 0x11, 0xfe, 0xe0, 0x24, 0x04, 0xfb, 0xe0, 0x28, 0xc3, 0xe0, + 0x09, 0x03, 0x41, 0xf3, 0xd7, 0xde, 0x2b, 0x21, 0xc6, 0xe7, 0x1c, 0x38, 0xe3, + 0xb8, 0xed, 0x18, 0x3b, 0x25, 0xaf, 0xfb, 0xe1, 0xd0, 0xd5, 0xf7, 0x25, 0x16, + 0xfb, 0xbf, 0xed, 0x29, 0xf4, 0x1e, 0xdc, 0xf4, 0xb8, 0x20, 0x32, 0xe6, 0xe7, + 0x11, 0xec, 0xe7, 0xff, 0x43, 0x12, 0x01, 0xf5, 0x92, 0x0e, 0xef, 0x10, 0xd3, + 0x19, 0xdf, 0xfe, 0x32, 0xf5, 0xf1, 0xf7, 0x21, 0xc6, 0x36, 0x1a, 0xf4, 0x1f, + 0xd6, 0xf4, 0xf4, 0xf4, 0xd4, 0x01, 0x17, 0x17, 0x07, 0xf6, 0x1f, 0x33, 0xf9, + 0xd2, 0x0f, 0xe7, 0x13, 0x15, 0x2f, 0xd4, 0x1c, 0xe2, 0xf0, 0x38, 0x1f, 0xfd, + 0x39, 0xee, 0xe4, 0x18, 0x14, 0xdc, 0xc0, 0xe1, 0xea, 0x20, 0xbf, 0x06, 0xda, + 0x38, 0x0c, 0xb9, 0x15, 0x0c, 0xf3, 0x27, 0xde, 0xc2, 0x18, 0xee, 0xf6, 0x1a, + 0xdf, 0x1b, 0xbc, 0x3b, 0x01, 0x6a, 0xdf, 0xeb, 0xd3, 0xc7, 0x06, 0xff, 0x58, + 0xf5, 0xbd, 0x32, 0x0c, 0xcc, 0xe2, 0x2c, 0x37, 0x9d, 0x1e, 0x0d, 0x91, 0x4a, + 0xc9, 0xb6, 0x4a, 0xc4, 0x12, 0xbd, 0xce, 0xed, 0x43, 0x15, 0x22, 0x10, 0x54, + 0xe5, 0xd2, 0x57, 0xd3, 0xe7, 0xb9, 0x18, 0x2a, 0x13, 0x43, 0xa2, 0x39, 0xec, + 0x01, 0xb0, 0x03, 0x56, 0x10, 0xf8, 0xb5, 0xfb, 0x2a, 0xbb, 0x58, 0xc4, 0x18, + 0x2f, 0xd0, 0xac, 0xfa, 0xeb, 0x04, 0xf4, 0x66, 0xfb, 0x00, 0xae, 0xb8, 0xef, + 0x52, 0x81, 0x1d, 0xef, 0xcc, 0x1a, 0x16, 0x26, 0xce, 0x20, 0x0b, 0x3f, 0x01, + 0x2c, 0xf5, 0xf1, 0xf8, 0x12, 0xec, 0xfd, 0x55, 0xf9, 0x90, 0xdd, 0x35, 0xf9, + 0xf2, 0xe2, 0x12, 0xc9, 0x0c, 0xe2, 0x0c, 0xfe, 0xd6, 0x16, 0x41, 0xe4, 0xea, + 0xce, 0x07, 0xff, 0xdb, 0x37, 0xd6, 0xd3, 0xc7, 0xd9, 0x0c, 0x11, 0x06, 0x3c, + 0x4b, 0xfc, 0x09, 0x8f, 0xd1, 0x19, 0x28, 0xfa, 0x26, 0xcc, 0xf5, 0x1b, 0x7f, + 0x08, 0x12, 0xde, 0xce, 0xd0, 0xc8, 0xc3, 0xf8, 0x1f, 0x27, 0xd2, 0x09, 0x55, + 0xbc, 0x3e, 0xc6, 0x0e, 0xcf, 0x43, 0x34, 0xbf, 0xb3, 0xe4, 0xdd, 0x0b, 0xa6, + 0x9a, 0x93, 0x7b, 0x13, 0x68, 0xff, 0x15, 0x14, 0xfe, 0x1c, 0x49, 0x38, 0xaf, + 0x46, 0xd6, 0x1c, 0x12, 0x18, 0x34, 0x10, 0xff, 0xc5, 0xe8, 0x37, 0xfe, 0xa2, + 0x00, 0x0e, 0xfe, 0x1d, 0x29, 0x15, 0xd6, 0xb3, 0x11, 0x06, 0x24, 0x16, 0x23, + 0x97, 0xbf, 0xf2, 0x89, 0x09, 0xe1, 0xf5, 0x20, 0xc7, 0x01, 0xfc, 0xa3, 0x03, + 0x28, 0xf3, 0x10, 0x30, 0x34, 0x7f, 0xce, 0x54, 0xdf, 0x42, 0x29, 0xcc, 0x0d, + 0xb7, 0x03, 0xd3, 0xec, 0xe2, 0xf1, 0x03, 0xed, 0xd4, 0x30, 0x76, 0xe5, 0x24, + 0xe8, 0x3e, 0xfd, 0x65, 0x2d, 0xe5, 0xe8, 0xea, 0x13, 0x0e, 0x45, 0xf7, 0x1d, + 0xd6, 0x34, 0x23, 0x06, 0xb4, 0x25, 0x26, 0x53, 0xac, 0x18, 0xdf, 0xf4, 0x32, + 0x1a, 0x3f, 0xf6, 0x07, 0x18, 0x00, 0xf8, 0xa5, 0x0c, 0xfa, 0xf3, 0x3b, 0xd7, + 0x22, 0xb6, 0x65, 0xe4, 0xf9, 0x4c, 0x06, 0xc4, 0xf2, 0x05, 0x45, 0xe7, 0x3f, + 0x07, 0xf7, 0xea, 0x4b, 0xff, 0xb5, 0xbd, 0x53, 0xfa, 0xe9, 0xc5, 0xde, 0x6d, + 0x50, 0xc3, 0xfb, 0xc8, 0x06, 0x04, 0xcc, 0x13, 0x16, 0x14, 0xbd, 0xce, 0x18, + 0xc4, 0xee, 0xc0, 0xe4, 0xe2, 0xe5, 0xf9, 0x17, 0xb4, 0x25, 0x82, 0x1e, 0x3b, + 0x15, 0x13, 0x2e, 0xd8, 0x00, 0x3a, 0x18, 0xfc, 0xe6, 0xf7, 0xf2, 0xf0, 0xec, + 0x1b, 0x19, 0xf5, 0x3e, 0x86, 0x1e, 0x1a, 0x31, 0xc6, 0xf7, 0x01, 0x00, 0xf9, + 0x3d, 0x27, 0xfa, 0xd5, 0x0b, 0xef, 0x7f, 0x06, 0x26, 0xc3, 0xf5, 0xad, 0xe9, + 0x2a, 0x8b, 0x09, 0x7f, 0x21, 0x4f, 0x1d, 0xf0, 0x5e, 0x5b, 0xe0, 0xf7, 0x53, + 0x2a, 0x1e, 0xd7, 0xed, 0x09, 0x55, 0xda, 0xed, 0xcd, 0x25, 0x06, 0x05, 0x57, + 0xd8, 0xc8, 0x99, 0x01, 0xc7, 0xd3, 0x16, 0x20, 0x0f, 0x20, 0x03, 0xb3, 0xd2, + 0x28, 0x54, 0x0b, 0x5d, 0x25, 0xaa, 0x83, 0xa2, 0x71, 0x14, 0xdc, 0x63, 0x50, + 0xee, 0xf4, 0x33, 0x12, 0x06, 0x0d, 0x8e, 0xce, 0xd3, 0xbc, 0xf3, 0x08, 0x07, + 0xf0, 0x0c, 0xd3, 0x1d, 0xba, 0x0b, 0xd8, 0x30, 0x37, 0xdc, 0xc5, 0xce, 0xfe, + 0xbc, 0xee, 0xd0, 0xf2, 0xec, 0x38, 0xbf, 0xee, 0xcb, 0x2b, 0x78, 0xfb, 0x1b, + 0x19, 0xd6, 0xce, 0xdd, 0xfe, 0x34, 0x31, 0xf5, 0xd2, 0xfd, 0xc9, 0xf4, 0x0b, + 0xff, 0xf2, 0x52, 0xee, 0xd4, 0xbd, 0x91, 0xdc, 0xf9, 0x81, 0xf4, 0xbd, 0xcc, + 0xea, 0xe6, 0xe6, 0x12, 0x45, 0xcf, 0xef, 0xcc, 0x0c, 0xe2, 0x2d, 0x32, 0xca, + 0x36, 0xdd, 0x2c, 0x0e, 0x18, 0x18, 0x2b, 0x02, 0x14, 0x19, 0x1a, 0xf9, 0xfe, + 0x46, 0xf3, 0xb3, 0xd1, 0xed, 0xe6, 0x1e, 0xee, 0x35, 0x3e, 0xbb, 0x31, 0x91, + 0xdd, 0xd3, 0x40, 0x3a, 0x2d, 0xb9, 0x24, 0xb3, 0x49, 0xe4, 0xf2, 0xef, 0x32, + 0x27, 0xcb, 0xd3, 0x09, 0x12, 0x18, 0x08, 0xc3, 0xc0, 0x0b, 0xd3, 0xe0, 0x08, + 0xfa, 0x1a, 0xfe, 0xf0, 0x2b, 0xc1, 0x2b, 0x51, 0x23, 0x04, 0xc9, 0xed, 0xa8, + 0x10, 0xfe, 0x11, 0x07, 0x33, 0x12, 0xf6, 0x09, 0x40, 0x28, 0xf7, 0x05, 0xe9, + 0xe5, 0xeb, 0x49, 0x45, 0x08, 0x43, 0x26, 0xf9, 0xa9, 0x77, 0x00, 0x07, 0xaa, + 0xdd, 0xd1, 0xe4, 0xbe, 0xf0, 0x17, 0xfd, 0x47, 0xee, 0xf4, 0x19, 0x4e, 0xd5, + 0xb5, 0x24, 0xfa, 0x04, 0xfd, 0x2b, 0x04, 0xc2, 0x4b, 0x25, 0xed, 0x1f, 0xe1, + 0xfc, 0xb6, 0xeb, 0x30, 0xfa, 0x03, 0xf7, 0x33, 0x03, 0xd6, 0x1d, 0x10, 0x90, + 0xd2, 0xb8, 0x04, 0x17, 0xb6, 0x14, 0xe0, 0x27, 0xf4, 0x28, 0x15, 0xd3, 0xeb, + 0x24, 0x0b, 0x98, 0xb7, 0xc5, 0x63, 0xef, 0x1d, 0x02, 0xc1, 0x23, 0xaf, 0x75, + 0x24, 0xca, 0x17, 0xb6, 0xb8, 0x34, 0xcf, 0x2e, 0x1b, 0xd6, 0x47, 0xbe, 0x45, + 0xff, 0xdb, 0xff, 0xea, 0x45, 0xf3, 0x27, 0xb8, 0xff, 0xd2, 0xdc, 0x18, 0xb4, + 0xbe, 0xe5, 0xe3, 0xdf, 0xa9, 0xd6, 0xf6, 0xfb, 0xc1, 0xee, 0x09, 0x00, 0x28, + 0x8a, 0x24, 0x00, 0xe3, 0x81, 0xd7, 0x1d, 0xc1, 0xd6, 0x23, 0xad, 0x2c, 0xd1, + 0xa7, 0x01, 0xe6, 0x0b, 0xb0, 0x07, 0x00, 0x29, 0xfa, 0xc5, 0xd3, 0xd1, 0xcb, + 0xc6, 0x28, 0xe7, 0xb6, 0x20, 0x2d, 0xee, 0x00, 0x07, 0xc3, 0xf8, 0xf5, 0xf2, + 0xc3, 0x28, 0x2f, 0x1e, 0x34, 0xe3, 0xf0, 0xcf, 0xe1, 0xec, 0x2c, 0xdb, 0x0c, + 0x17, 0xe4, 0xfa, 0xd0, 0xfe, 0xed, 0x32, 0x0c, 0xdc, 0xdd, 0xe8, 0x4d, 0x10, + 0xfe, 0xe4, 0xfd, 0xf1, 0x03, 0xf7, 0xdd, 0xf6, 0xe5, 0xe7, 0x14, 0xc7, 0xfe, + 0x09, 0xc4, 0x33, 0x19, 0x15, 0x39, 0x07, 0x2e, 0xca, 0x06, 0xcb, 0x7f, 0x07, + 0x07, 0xf8, 0xf3, 0xe8, 0xd9, 0x29, 0xec, 0xf6, 0xe1, 0x06, 0xca, 0x0b, 0xfe, + 0xce, 0x05, 0xe6, 0x22, 0xfb, 0xe5, 0xd5, 0xd1, 0xbe, 0x03, 0x06, 0x20, 0x24, + 0x18, 0xe8, 0x11, 0xc7, 0xed, 0xf0, 0x1e, 0xfc, 0x10, 0xcb, 0x17, 0x00, 0x1f, + 0x20, 0x04, 0xdd, 0xe9, 0x0a, 0x45, 0x35, 0x2b, 0x08, 0xfa, 0x4d, 0xcb, 0xd6, + 0xd9, 0x0d, 0xd1, 0x1e, 0xee, 0xda, 0x09, 0x60, 0xfd, 0xf1, 0x3d, 0xf2, 0xfa, + 0x0f, 0x27, 0x73, 0xd7, 0x78, 0x21, 0xeb, 0xc7, 0xec, 0x1f, 0x40, 0x04, 0x52, + 0xdb, 0x13, 0xe5, 0xf6, 0x09, 0xef, 0xc2, 0xef, 0x0d, 0x45, 0xd5, 0x06, 0x41, + 0x14, 0xee, 0xe8, 0x0a, 0x15, 0xf1, 0x62, 0xe0, 0x05, 0xe7, 0x14, 0xff, 0x11, + 0xf1, 0xf7, 0x7f, 0x02, 0x41, 0xd9, 0x12, 0xf7, 0xe7, 0xdb, 0x03, 0xf0, 0xc7, + 0xc0, 0xe2, 0x0b, 0xf1, 0x33, 0xf1, 0x29, 0xe0, 0xf1, 0xe9, 0xc3, 0x37, 0xd0, + 0xf1, 0x18, 0xe7, 0xbb, 0x0a, 0xf5, 0xf8, 0x27, 0x19, 0xdd, 0x25, 0x0f, 0x25, + 0x2d, 0xff, 0x2b, 0xcf, 0x02, 0x0e, 0x00, 0x19, 0xc8, 0xee, 0x12, 0x15, 0xd6, + 0x09, 0xf6, 0xcf, 0x10, 0xfd, 0x0f, 0xe1, 0xba, 0xfe, 0x09, 0x0d, 0x2a, 0xdf, + 0x34, 0xeb, 0xfc, 0x3b, 0xf4, 0x24, 0xf9, 0xf4, 0xfb, 0xe7, 0xdc, 0xeb, 0x1c, + 0xf0, 0x5c, 0xe6, 0x0f, 0x0b, 0x41, 0xce, 0xec, 0xe1, 0xad, 0x10, 0x19, 0x10, + 0x02, 0x28, 0x15, 0xdc, 0x10, 0xf8, 0xdb, 0x3e, 0x43, 0xec, 0x27, 0xfd, 0x1c, + 0xc2, 0x49, 0xee, 0xed, 0x06, 0x09, 0xfb, 0x3e, 0x4d, 0xd2, 0x25, 0x1d, 0x01, + 0x09, 0x01, 0xfd, 0xef, 0x3e, 0xe1, 0xd6, 0x05, 0x0e, 0xfc, 0x1c, 0xd2, 0xd6, + 0x3f, 0xe3, 0xff, 0xfb, 0xf8, 0x5a, 0xe8, 0x2d, 0x0a, 0x10, 0xb0, 0x1b, 0x70, + 0xa0, 0xbc, 0xdc, 0xb8, 0xb6, 0x23, 0xde, 0x42, 0xe7, 0x64, 0x51, 0xe8, 0x1b, + 0xa1, 0x07, 0x3f, 0xc3, 0xcd, 0x4a, 0xdb, 0xa0, 0xb4, 0x2e, 0x19, 0x35, 0x23, + 0x55, 0xf4, 0x07, 0xf7, 0x1c, 0xb8, 0x07, 0x09, 0x2d, 0x25, 0x56, 0xe9, 0xed, + 0x0d, 0x19, 0x25, 0xf2, 0xfa, 0xe4, 0x08, 0xa0, 0xed, 0xe8, 0x2e, 0x07, 0xdd, + 0x47, 0x7f, 0x12, 0xdb, 0xd0, 0x18, 0x37, 0x32, 0x07, 0xe2, 0xc6, 0xfa, 0xf6, + 0x1e, 0x43, 0x34, 0x0d, 0x5e, 0xce, 0xd7, 0xc8, 0xc0, 0xe2, 0xee, 0xf9, 0x1b, + 0x4c, 0x15, 0xfd, 0xf7, 0x19, 0xe7, 0x0e, 0x19, 0xb0, 0x0b, 0x25, 0x81, 0xf3, + 0x04, 0xe3, 0xe8, 0x1a, 0xd9, 0xdb, 0xee, 0xee, 0x3b, 0x10, 0xe1, 0xce, 0x0f, + 0xca, 0xec, 0x75, 0x48, 0x31, 0xcd, 0xef, 0xf9, 0xcb, 0xee, 0x07, 0xe5, 0x56, + 0xf3, 0x0f, 0x3e, 0xc9, 0x65, 0xe5, 0x3c, 0x0f, 0xd5, 0xd8, 0xf7, 0xfc, 0xf7, + 0xea, 0xdb, 0x09, 0xce, 0xfb, 0xc9, 0xb9, 0x5d, 0xf7, 0xdb, 0x13, 0xd7, 0x09, + 0x1d, 0x24, 0xec, 0xed, 0xe4, 0x5e, 0xdd, 0xc7, 0x1d, 0x0c, 0x25, 0xe2, 0xed, + 0x18, 0xbc, 0x1f, 0xfe, 0x23, 0xfe, 0xe5, 0xf2, 0xae, 0x17, 0xb3, 0x23, 0x62, + 0xef, 0xd5, 0xfc, 0xe0, 0xe0, 0xe0, 0xc1, 0xfd, 0xf6, 0x0f, 0xd1, 0x07, 0x08, + 0x03, 0xe2, 0xe2, 0x05, 0x18, 0x00, 0x2b, 0xfe, 0x00, 0xa6, 0xdf, 0x30, 0x11, + 0xf5, 0x17, 0x0b, 0xd7, 0xf0, 0xc3, 0x29, 0xfc, 0xd0, 0xe9, 0xe9, 0x0a, 0xce, + 0x35, 0xdb, 0x2b, 0xee, 0xc5, 0x0b, 0x10, 0xa7, 0x15, 0x18, 0x0f, 0xb5, 0xf4, + 0x2e, 0x0a, 0x22, 0xe9, 0x2c, 0x2f, 0xcd, 0x09, 0x63, 0xcb, 0x06, 0xeb, 0x28, + 0xdc, 0x40, 0x7f, 0xeb, 0x47, 0x25, 0xf8, 0x06, 0x76, 0x10, 0x24, 0x68, 0xa0, + 0x05, 0x2a, 0x02, 0xbf, 0xf3, 0x09, 0x5f, 0x2c, 0xe4, 0xd7, 0x01, 0xdb, 0x1b, + 0x25, 0x1e, 0xeb, 0xe4, 0xcb, 0x21, 0xe2, 0x06, 0xcf, 0xc3, 0x58, 0x03, 0x61, + 0x1b, 0x4b, 0xcf, 0x05, 0x29, 0xe4, 0xca, 0xe3, 0xe3, 0xdd, 0xfc, 0xe3, 0xba, + 0xd8, 0x0c, 0x0c, 0xe4, 0xfc, 0x0e, 0x1a, 0xf2, 0x16, 0x2d, 0x14, 0x06, 0xda, + 0x52, 0xee, 0xdc, 0xf4, 0xf7, 0xfe, 0x07, 0x2c, 0xd5, 0xd7, 0xfd, 0x03, 0x05, + 0xc4, 0x12, 0xeb, 0xdd, 0x0d, 0x0b, 0x4a, 0xd1, 0xf8, 0xc4, 0x22, 0x15, 0x02, + 0xf8, 0xf8, 0x12, 0x13, 0xf9, 0x17, 0xb0, 0x06, 0xc4, 0x1a, 0x23, 0x3b, 0xfd, + 0xee, 0xb7, 0x03, 0x14, 0x3a, 0x1b, 0x48, 0xd6, 0x2c, 0x36, 0x3c, 0xb3, 0x18, + 0x09, 0x0c, 0x08, 0x01, 0x5a, 0xf0, 0x21, 0xc3, 0x2b, 0x08, 0xce, 0xbb, 0xec, + 0x21, 0xa5, 0x20, 0xbd, 0xe0, 0xe9, 0x1d, 0x2d, 0x06, 0x55, 0x50, 0x14, 0x92, + 0xcd, 0x3b, 0x76, 0xdc, 0xfc, 0xf0, 0x69, 0x0a, 0x36, 0x35, 0xc5, 0x7b, 0x06, + 0x73, 0x0a, 0xfb, 0x11, 0xcb, 0xdf, 0x47, 0xd9, 0x0f, 0xc1, 0x30, 0x23, 0xc1, + 0xf8, 0x15, 0x3d, 0x2c, 0x05, 0x63, 0x35, 0xfa, 0x15, 0x0e, 0xe4, 0xea, 0x2c, + 0xb2, 0x19, 0xd9, 0x81, 0xf4, 0x33, 0x35, 0xfc, 0xc6, 0xec, 0x0c, 0xcc, 0x89, + 0x5d, 0xcd, 0x02, 0xf5, 0x27, 0x2b, 0xcf, 0xb7, 0xf0, 0xb6, 0x03, 0x29, 0x2b, + 0x71, 0x1c, 0xe9, 0x11, 0x23, 0xeb, 0x1b, 0x40, 0xed, 0x27, 0x6d, 0x56, 0xdb, + 0xac, 0xf9, 0xaf, 0x08, 0x22, 0xf0, 0x15, 0x13, 0x00, 0x2d, 0x29, 0xf2, 0xa7, + 0x16, 0xee, 0x28, 0x3a, 0x21, 0x17, 0xef, 0x10, 0xfc, 0xde, 0x12, 0x1f, 0x32, + 0xc9, 0x09, 0x5c, 0x0f, 0xe9, 0xc9, 0x0a, 0x11, 0x29, 0x1f, 0x1f, 0xb0, 0xd7, + 0x34, 0xd6, 0xe5, 0xe9, 0xe6, 0x48, 0x0c, 0xe7, 0xdd, 0x0c, 0x12, 0xfb, 0xdc, + 0x49, 0xec, 0xd8, 0x00, 0xd8, 0xe7, 0x38, 0xff, 0xf6, 0x47, 0xe0, 0xfe, 0xfc, + 0x28, 0xdf, 0x09, 0xcf, 0x2b, 0xdc, 0xe7, 0xc3, 0x2c, 0x3b, 0xe3, 0x21, 0x14, + 0x3b, 0xec, 0x1a, 0x23, 0x0a, 0x0e, 0xd6, 0x1a, 0x2b, 0x23, 0xfb, 0xff, 0xdf, + 0xe5, 0xf2, 0x1d, 0x16, 0x04, 0xf2, 0x44, 0xbf, 0xd8, 0xe2, 0xd5, 0x14, 0x00, + 0x23, 0x03, 0x0f, 0x81, 0xd1, 0xda, 0xb4, 0xc3, 0x08, 0xfd, 0xf6, 0xfc, 0xee, + 0xef, 0x10, 0x41, 0xc5, 0x44, 0x12, 0xff, 0xf4, 0xf8, 0xc1, 0xdc, 0xf2, 0x27, + 0x0a, 0x0c, 0x04, 0x0b, 0xe7, 0x0d, 0x05, 0x20, 0x34, 0xed, 0xe4, 0x3e, 0xfe, + 0x01, 0xfd, 0x08, 0xd1, 0x04, 0xf2, 0x22, 0xe3, 0x1c, 0x09, 0x26, 0xf6, 0xe2, + 0x47, 0xee, 0xf4, 0xc9, 0xe8, 0xd1, 0xf7, 0x5d, 0xed, 0x9d, 0x2a, 0x34, 0xee, + 0xc9, 0xd7, 0xcf, 0xf6, 0xff, 0x0d, 0x10, 0xfb, 0xb6, 0x0d, 0x18, 0x29, 0xde, + 0x9d, 0xd3, 0x35, 0xeb, 0xe0, 0x34, 0xe8, 0x53, 0x02, 0x1a, 0xd5, 0xda, 0x10, + 0xad, 0xc4, 0x10, 0x81, 0xe8, 0x39, 0x43, 0x05, 0xe7, 0xfb, 0x0c, 0xe1, 0xc8, + 0xe9, 0x13, 0x28, 0x54, 0xf9, 0xcb, 0xcf, 0xe3, 0x02, 0xd9, 0x16, 0xe7, 0xce, + 0xf3, 0x12, 0xe2, 0x19, 0xff, 0xcb, 0x26, 0xc0, 0xa8, 0xa7, 0x3e, 0x15, 0x03, + 0xdf, 0x41, 0xf2, 0xf2, 0x07, 0xbb, 0xe1, 0xbb, 0x00, 0xde, 0x1c, 0xf6, 0x06, + 0xcf, 0xdb, 0xd8, 0xf4, 0x21, 0x1f, 0x30, 0xeb, 0xc7, 0xf1, 0xd4, 0x25, 0x2a, + 0x0d, 0xad, 0x03, 0x0a, 0x02, 0x14, 0x2c, 0x12, 0x0a, 0x32, 0x0b, 0x36, 0xb4, + 0xf6, 0xf3, 0xfa, 0x72, 0xf9, 0xd0, 0x32, 0xaa, 0xd0, 0x0b, 0xbc, 0x2f, 0x29, + 0x3e, 0xea, 0xf1, 0xd8, 0xb4, 0x64, 0x2e, 0xc6, 0xcb, 0x18, 0x11, 0xe9, 0xd8, + 0xdd, 0xe7, 0x0c, 0x36, 0x0c, 0x1c, 0x16, 0xe0, 0x17, 0x1d, 0x0e, 0xd3, 0x99, + 0xb9, 0xee, 0xf7, 0xe7, 0xe0, 0xf2, 0xd2, 0x68, 0xc9, 0xe7, 0xe6, 0x17, 0x27, + 0x37, 0xf4, 0x7f, 0x16, 0xea, 0x3c, 0xc3, 0x20, 0x15, 0xf4, 0xf4, 0x09, 0x3e, + 0x39, 0x23, 0xd6, 0xdf, 0x18, 0x35, 0xd0, 0xd9, 0xb9, 0x2a, 0xd6, 0x23, 0xe4, + 0xbb, 0xe1, 0xd1, 0x0e, 0xae, 0x3f, 0xff, 0xa7, 0x0f, 0x26, 0x0c, 0x04, 0x03, + 0xcb, 0xe1, 0xff, 0xff, 0xf8, 0xd4, 0xe9, 0x14, 0xd7, 0x09, 0xee, 0x44, 0xe3, + 0xeb, 0xee, 0xfe, 0x0a, 0xf5, 0xf0, 0x20, 0xe5, 0x4c, 0xf1, 0x10, 0xf1, 0xf5, + 0xce, 0x23, 0xe0, 0xfe, 0xe7, 0xe5, 0x0b, 0x0d, 0x20, 0xe0, 0x0e, 0xdf, 0xf5, + 0xed, 0x7f, 0xf7, 0xf4, 0x33, 0x09, 0x45, 0xf2, 0xf3, 0x1f, 0x0d, 0x0f, 0x1c, + 0x32, 0x03, 0x04, 0x69, 0xff, 0x6e, 0x5a, 0xf1, 0xfc, 0x07, 0xf5, 0x07, 0xcd, + 0xdc, 0x0c, 0x4e, 0x2a, 0x2b, 0x28, 0x21, 0x20, 0xf3, 0x9e, 0xe3, 0x1d, 0x17, + 0xfe, 0x03, 0xa3, 0x07, 0x17, 0x14, 0xee, 0xed, 0x34, 0x10, 0xaa, 0x3c, 0x23, + 0xe8, 0x02, 0x28, 0x1c, 0xb9, 0xad, 0xe6, 0x4c, 0xaa, 0xb2, 0xfa, 0x1c, 0xfa, + 0x23, 0x62, 0x00, 0xf3, 0x32, 0xd2, 0x1f, 0xf0, 0xaa, 0x06, 0xf8, 0x9f, 0x2b, + 0x2c, 0xdc, 0xd7, 0xdb, 0xa9, 0xd6, 0xef, 0x0e, 0xe1, 0x08, 0xfe, 0x3d, 0x02, + 0xfa, 0xf7, 0x0b, 0x0f, 0xdf, 0x4d, 0x38, 0xf5, 0xea, 0x07, 0xea, 0xfa, 0x22, + 0xf0, 0xfb, 0x22, 0xe6, 0xd7, 0xdc, 0xdc, 0x65, 0x25, 0xf5, 0xdf, 0xc9, 0x09, + 0xe3, 0x4d, 0x0f, 0xee, 0xcb, 0x00, 0xf8, 0x5e, 0xd2, 0xc1, 0xfb, 0xd9, 0x2d, + 0x17, 0x93, 0x29, 0xf2, 0xfe, 0xe9, 0x8d, 0xba, 0xd8, 0xda, 0x39, 0x1b, 0xec, + 0xe7, 0xdc, 0xcb, 0xc4, 0xe7, 0x14, 0xdf, 0xd5, 0xce, 0xf2, 0x24, 0x2f, 0x3d, + 0xc0, 0xc9, 0x08, 0xa8, 0xf7, 0x2c, 0xf2, 0xce, 0x33, 0xcb, 0x39, 0x2d, 0x0c, + 0xdf, 0xaf, 0xd2, 0xda, 0xb9, 0x9e, 0x25, 0xbe, 0xa7, 0x12, 0x8e, 0x0b, 0xdc, + 0xe9, 0x23, 0xdd, 0xea, 0xb0, 0x4c, 0xdd, 0x1d, 0xc3, 0x0e, 0xd8, 0x37, 0xf2, + 0x0a, 0x01, 0x36, 0x00, 0x81, 0xeb, 0x40, 0xee, 0xb7, 0xee, 0xf3, 0x49, 0x35, + 0xdc, 0xbc, 0xd3, 0xe3, 0xf2, 0x0c, 0x19, 0xfd, 0xb0, 0xb7, 0x37, 0xe2, 0xda, + 0x32, 0x22, 0xe4, 0xe7, 0xc6, 0xeb, 0x01, 0x38, 0xc5, 0x2a, 0x34, 0x57, 0x52, + 0x34, 0xec, 0x09, 0xfc, 0x0e, 0x03, 0xcc, 0xde, 0xb4, 0xe9, 0x19, 0x16, 0x38, + 0x31, 0xff, 0xf1, 0xc2, 0xf6, 0xbb, 0x06, 0x22, 0x0e, 0x3e, 0xfc, 0xae, 0x12, + 0xf5, 0xe9, 0xc3, 0xed, 0x21, 0x58, 0x74, 0x3e, 0x00, 0xf9, 0xc3, 0x21, 0x29, + 0xfd, 0x0e, 0xdb, 0x17, 0xdb, 0xe4, 0xe6, 0xfc, 0xe9, 0xfa, 0x35, 0x11, 0xf2, + 0xdc, 0x2e, 0x3a, 0xf5, 0x1e, 0xf7, 0xd5, 0x05, 0xe3, 0x3c, 0xec, 0x0a, 0xbf, + 0xc6, 0xf2, 0x08, 0xf0, 0x04, 0xdf, 0x04, 0x23, 0xf6, 0xfb, 0xef, 0x45, 0xaf, + 0x06, 0x35, 0xec, 0xfd, 0x04, 0xe4, 0xeb, 0xf6, 0x06, 0xe0, 0x0e, 0x12, 0xf2, + 0xfc, 0xda, 0x13, 0x66, 0xe9, 0xde, 0xfe, 0xdd, 0x24, 0xf5, 0xd1, 0xed, 0xf3, + 0xc4, 0x33, 0xcb, 0x28, 0xe0, 0xfb, 0x19, 0xf2, 0xf3, 0xed, 0xe9, 0xdc, 0xf8, + 0x01, 0x0a, 0xf3, 0x01, 0xd7, 0xf6, 0xf6, 0x16, 0xea, 0xcb, 0x7f, 0xdf, 0xee, + 0xca, 0xbd, 0x1e, 0xe9, 0xe3, 0xd3, 0xf0, 0x49, 0xd5, 0xee, 0x0b, 0xed, 0xf5, + 0x24, 0xd7, 0x20, 0xf2, 0xcc, 0x21, 0xf2, 0x2e, 0xd7, 0xde, 0xe6, 0x02, 0xcc, + 0x37, 0xd1, 0xd5, 0x0e, 0x32, 0x42, 0x0c, 0xff, 0xd8, 0x5e, 0x46, 0xe6, 0xe5, + 0xec, 0xfa, 0xe3, 0xd1, 0xdf, 0x2d, 0x30, 0x1f, 0xde, 0xf9, 0xe6, 0xef, 0xdc, + 0x09, 0xdc, 0xe9, 0xcf, 0x2a, 0x03, 0xbc, 0xd0, 0x2e, 0x77, 0x30, 0xe5, 0xe7, + 0x2d, 0xc2, 0xf5, 0xcb, 0x0f, 0x1e, 0x7f, 0xf8, 0x2d, 0x07, 0x24, 0xf6, 0x24, + 0xc3, 0x14, 0x76, 0x0e, 0xee, 0x04, 0x05, 0xf0, 0x31, 0xed, 0xa1, 0xe1, 0x30, + 0x13, 0x26, 0xf4, 0xe4, 0xa4, 0xca, 0xbf, 0x22, 0xd9, 0x58, 0xd1, 0xde, 0xd3, + 0xff, 0x2f, 0xca, 0xf4, 0x72, 0xe8, 0xd3, 0xe0, 0xfb, 0x0a, 0xf7, 0x26, 0x07, + 0xdb, 0x3e, 0xe7, 0x45, 0xf1, 0x19, 0x09, 0xdf, 0xcd, 0x3d, 0x0c, 0x25, 0x16, + 0x0e, 0xe6, 0xd8, 0xe4, 0x2b, 0x06, 0x1d, 0x37, 0x12, 0xee, 0x0e, 0x49, 0x0f, + 0x1d, 0x29, 0xe2, 0x11, 0xec, 0xb7, 0xff, 0x3a, 0xce, 0x07, 0xd5, 0x14, 0xfb, + 0xfa, 0xc2, 0x06, 0x7f, 0x19, 0x0d, 0x06, 0xf7, 0x3c, 0xcb, 0xf0, 0x68, 0x1a, + 0xf1, 0xdf, 0xf3, 0x22, 0x1e, 0xe5, 0x0d, 0xde, 0x1c, 0xcd, 0xda, 0x09, 0xe4, + 0xf9, 0xed, 0xd5, 0xf7, 0xe4, 0xaa, 0xe6, 0x99, 0xe3, 0x1a, 0x02, 0x16, 0xa8, + 0x22, 0xee, 0x37, 0x03, 0xf0, 0x3c, 0xd7, 0xe4, 0xbf, 0xb1, 0xd2, 0x1b, 0x69, + 0x51, 0xe5, 0x16, 0xf7, 0x03, 0xb2, 0x9a, 0xbe, 0x04, 0xe6, 0xe3, 0x1b, 0x05, + 0x0a, 0x07, 0x08, 0x21, 0xd5, 0xf7, 0x0a, 0x0e, 0x1a, 0xda, 0x12, 0x33, 0xf8, + 0x24, 0xf2, 0x4d, 0x01, 0x0c, 0x31, 0xe6, 0xd7, 0xcb, 0xf9, 0x09, 0x1a, 0xdf, + 0x02, 0xb3, 0xd2, 0x13, 0xe8, 0x0e, 0x1b, 0x42, 0xcd, 0x00, 0x2a, 0x34, 0x73, + 0xca, 0xc5, 0x25, 0x07, 0x08, 0xf6, 0x3b, 0xcb, 0x0e, 0xbf, 0x07, 0xf0, 0xc7, + 0x33, 0xf0, 0xdc, 0x40, 0x09, 0x5b, 0xc3, 0x00, 0x5f, 0xcd, 0xf0, 0xf3, 0x38, + 0xf9, 0x42, 0xe1, 0x07, 0x04, 0x36, 0x2a, 0xd1, 0xba, 0xfc, 0x62, 0xd4, 0x0f, + 0xe3, 0x7f, 0x2e, 0xee, 0x65, 0xd1, 0xdb, 0xbd, 0x35, 0x03, 0x47, 0xfd, 0x9c, + 0x37, 0x30, 0xce, 0x3a, 0x18, 0xe6, 0x35, 0xb2, 0x11, 0x97, 0xa7, 0xf9, 0xe4, + 0xea, 0x3a, 0x07, 0xf6, 0xe7, 0x57, 0x1a, 0xf4, 0xe6, 0x56, 0xdc, 0x96, 0x30, + 0x58, 0x35, 0xe8, 0x0e, 0x05, 0xfa, 0x0b, 0x36, 0x0a, 0xaa, 0xdc, 0x14, 0x01, + 0x06, 0x2c, 0xe7, 0x23, 0xda, 0x08, 0x23, 0xbd, 0xa4, 0x19, 0x24, 0xfb, 0x1f, + 0x25, 0xe2, 0x1a, 0x1b, 0xf6, 0x0b, 0x23, 0xcf, 0x30, 0xc5, 0xfd, 0xe9, 0x2d, + 0xdf, 0x64, 0xe2, 0x05, 0x50, 0x08, 0xcc, 0xd1, 0xbc, 0xe0, 0x93, 0xfe, 0x09, + 0xa5, 0x04, 0xf4, 0xec, 0x03, 0x28, 0xbe, 0x38, 0x24, 0x11, 0x0b, 0x2d, 0xdd, + 0x1c, 0xc9, 0x0f, 0x40, 0xfd, 0x03, 0x06, 0xe8, 0x11, 0xa0, 0x07, 0xe1, 0x0a, + 0xf9, 0xcc, 0xbb, 0x43, 0x0b, 0x32, 0xcf, 0xbe, 0x2c, 0xbc, 0xb0, 0xe8, 0x05, + 0x1b, 0x21, 0xb5, 0xfe, 0xd7, 0x4a, 0xa6, 0x08, 0x0c, 0x0c, 0x83, 0xea, 0x11, + 0xfe, 0x45, 0xdb, 0xe8, 0x22, 0xc5, 0xfe, 0xee, 0x11, 0x0a, 0x13, 0xdb, 0xf1, + 0x81, 0xf7, 0x29, 0x1b, 0xd1, 0xfc, 0xd6, 0x22, 0xb5, 0x9b, 0x36, 0x17, 0x1e, + 0x45, 0xa9, 0x4f, 0x13, 0x29, 0x04, 0xae, 0xee, 0x0b, 0xe4, 0x03, 0x64, 0x20, + 0xf2, 0x1a, 0x04, 0xf1, 0x48, 0xd9, 0xd0, 0x2d, 0xf2, 0xd7, 0x13, 0x37, 0x1c, + 0xe0, 0xc6, 0xd3, 0xd7, 0x17, 0x37, 0xba, 0xb2, 0xa0, 0xce, 0x2b, 0xb1, 0xf8, + 0xd6, 0x14, 0xf3, 0xea, 0x23, 0xff, 0xdb, 0x20, 0xba, 0xdf, 0xff, 0xd7, 0xfd, + 0x0e, 0xe0, 0x11, 0xec, 0xfd, 0xcc, 0x02, 0x2a, 0xfb, 0x28, 0x2e, 0xf2, 0xe4, + 0x2c, 0x44, 0xf1, 0x36, 0xc6, 0xeb, 0x19, 0xbd, 0x30, 0x07, 0xf3, 0xe9, 0x15, + 0xe6, 0xef, 0xf4, 0x01, 0x08, 0x3a, 0x00, 0xdf, 0x02, 0xeb, 0xfc, 0xf4, 0x21, + 0xa2, 0x5d, 0x06, 0xd1, 0x10, 0x03, 0x12, 0xcb, 0xf5, 0xb2, 0x05, 0xdf, 0xd0, + 0x1a, 0x1b, 0x15, 0x18, 0x05, 0xe1, 0xf1, 0xee, 0xf5, 0xdc, 0xff, 0x81, 0x1e, + 0x02, 0x25, 0xc9, 0xe5, 0xfd, 0xd2, 0xf2, 0xfb, 0xcb, 0x13, 0x29, 0x79, 0x1a, + 0x07, 0xb1, 0xea, 0xed, 0xf6, 0xdf, 0xeb, 0xd2, 0xdf, 0x35, 0xea, 0xed, 0x48, + 0xb2, 0xc3, 0xe1, 0xb6, 0xdb, 0x13, 0x01, 0x16, 0x10, 0xcd, 0xfb, 0xeb, 0x10, + 0xe5, 0x0e, 0x11, 0xfa, 0x2d, 0x0b, 0xf4, 0xd6, 0xf6, 0xbf, 0x2a, 0xda, 0x17, + 0xfd, 0xde, 0xfd, 0xf2, 0xce, 0xdb, 0x36, 0xe9, 0x1e, 0xcc, 0x20, 0xed, 0x15, + 0x13, 0xe1, 0x1f, 0xec, 0xdb, 0x21, 0xc5, 0x1d, 0xf3, 0xf7, 0x09, 0x1f, 0xd5, + 0x01, 0x25, 0xc7, 0xfc, 0x11, 0xc2, 0x2f, 0xff, 0x34, 0x10, 0x15, 0xf3, 0x0e, + 0x33, 0x24, 0x37, 0xea, 0x04, 0x10, 0xff, 0x16, 0xcf, 0x0e, 0x07, 0x17, 0xb5, + 0xfe, 0xb2, 0x49, 0xe6, 0xda, 0xff, 0x12, 0x05, 0x1e, 0xdc, 0xea, 0x21, 0x0b, + 0xde, 0xe8, 0xeb, 0x4f, 0xe3, 0xf7, 0xe3, 0x1e, 0x04, 0xdf, 0x1d, 0x00, 0xfa, + 0xcd, 0xe2, 0x0d, 0xd7, 0x1a, 0x00, 0xf1, 0xd8, 0xf1, 0xf8, 0xe2, 0xf9, 0xdc, + 0xe5, 0xc7, 0xfd, 0x09, 0x0c, 0xe7, 0x05, 0x10, 0xc8, 0xd6, 0x0f, 0x11, 0xb9, + 0x45, 0xdc, 0x09, 0xd3, 0xfc, 0xba, 0xe7, 0x5c, 0xda, 0x0e, 0xfb, 0x24, 0xf3, + 0x6a, 0xc1, 0x04, 0xd4, 0x13, 0xb9, 0x02, 0xd9, 0xf0, 0x16, 0xf1, 0x18, 0x03, + 0x06, 0x20, 0x0f, 0xe6, 0xee, 0xef, 0xc1, 0xe5, 0xe2, 0x7f, 0x28, 0xf9, 0x06, + 0xed, 0x7e, 0xa6, 0x2f, 0x1d, 0xc2, 0xf6, 0xdd, 0x03, 0xed, 0x05, 0x1c, 0x1d, + 0x8c, 0xe5, 0x0f, 0xe2, 0x9b, 0x1d, 0xf3, 0x14, 0xdf, 0x2d, 0x22, 0x08, 0x48, + 0xed, 0xef, 0xf2, 0x05, 0xc2, 0xd4, 0xd9, 0x1a, 0x59, 0x01, 0xeb, 0x9c, 0xdc, + 0xe0, 0x01, 0xce, 0x09, 0x16, 0xd6, 0xed, 0xe6, 0xda, 0xbf, 0xbe, 0x0a, 0x03, + 0xf5, 0xd7, 0xdd, 0x3c, 0x22, 0x66, 0xf2, 0x4b, 0x2c, 0x7f, 0x0c, 0xa9, 0x62, + 0x8f, 0xb3, 0x6b, 0x2f, 0x13, 0x0b, 0xff, 0xbf, 0x01, 0xa8, 0xd2, 0xe4, 0x8e, + 0x39, 0x59, 0xc7, 0x4c, 0xff, 0x1e, 0xeb, 0x32, 0xf9, 0x0e, 0xf2, 0x50, 0x56, + 0x2b, 0xe5, 0x0c, 0x25, 0xf8, 0xe9, 0xf0, 0x30, 0xf7, 0x17, 0x47, 0xaf, 0xfa, + 0xd8, 0x22, 0x2b, 0xd1, 0xca, 0x3e, 0xda, 0x01, 0x21, 0xf5, 0x63, 0x0d, 0xfa, + 0xed, 0x33, 0x7c, 0xc8, 0xd5, 0x49, 0x28, 0x0d, 0xe1, 0xe4, 0x1c, 0x41, 0xfb, + 0x12, 0xec, 0xae, 0x5f, 0x1b, 0xe8, 0x3b, 0x05, 0xb7, 0xe8, 0x04, 0x1d, 0xd1, + 0xfe, 0xbd, 0x10, 0xe9, 0x2b, 0xc9, 0x35, 0x04, 0x0e, 0x3e, 0xe7, 0xe8, 0xd0, + 0x76, 0xe3, 0xec, 0xd8, 0x43, 0xf8, 0xbe, 0x12, 0x0a, 0x21, 0xd0, 0xfc, 0x3a, + 0xd7, 0xf5, 0xe2, 0x4b, 0xea, 0xda, 0x1c, 0xce, 0x05, 0x37, 0xff, 0x2f, 0xda, + 0x40, 0x0f, 0x22, 0xfa, 0xd8, 0x01, 0xcc, 0xd2, 0x2c, 0xf7, 0x1d, 0x4e, 0x7f, + 0xdd, 0xe6, 0x0f, 0xcc, 0xe2, 0xe7, 0x12, 0xa9, 0xda, 0xcb, 0xe9, 0x06, 0x0e, + 0x04, 0x3e, 0xf7, 0xed, 0x06, 0xc4, 0xd3, 0xdf, 0xcf, 0xbe, 0xa9, 0xd8, 0xf2, + 0x2d, 0x21, 0x54, 0xc1, 0x19, 0xfa, 0x1f, 0xfa, 0xbb, 0xed, 0x48, 0x29, 0x04, + 0x41, 0x0e, 0x72, 0x06, 0x19, 0x2a, 0x16, 0x05, 0x25, 0xf1, 0x35, 0x1f, 0xfc, + 0x0e, 0x06, 0xc1, 0x0e, 0xf6, 0x2b, 0xad, 0x1e, 0xfe, 0x26, 0xf3, 0x81, 0x27, + 0xaf, 0x9b, 0x08, 0xf9, 0x38, 0xf2, 0x9a, 0x92, 0x21, 0xe5, 0x3b, 0x3b, 0x5b, + 0xa0, 0xf8, 0x07, 0x1e, 0x39, 0xe7, 0x0c, 0xbf, 0x33, 0x41, 0xed, 0xb0, 0x27, + 0x42, 0x02, 0x2a, 0xf8, 0x15, 0xd1, 0x10, 0xbe, 0xfd, 0x04, 0xfc, 0xb9, 0x4a, + 0x2f, 0x0f, 0xfc, 0xfe, 0xbf, 0xae, 0x47, 0xc9, 0x12, 0xa2, 0xe0, 0xea, 0x41, + 0x47, 0x59, 0xdb, 0x21, 0x09, 0x15, 0x1a, 0xf1, 0x23, 0xcb, 0xab, 0x53, 0x35, + 0x0d, 0x8a, 0xcf, 0x06, 0xf1, 0x28, 0xe3, 0xfd, 0x2f, 0xe8, 0x2c, 0x0c, 0xe8, + 0x3d, 0xed, 0x5a, 0xe1, 0xb1, 0x18, 0x1b, 0x4e, 0xf4, 0x2e, 0xd3, 0x0c, 0x20, + 0x23, 0x3c, 0xd6, 0xbc, 0x25, 0x1c, 0x26, 0x33, 0xe9, 0x0f, 0xcb, 0x2c, 0x2b, + 0x13, 0xda, 0xb5, 0x08, 0xeb, 0xc2, 0xd1, 0x1b, 0xd5, 0x26, 0xf0, 0x33, 0xf6, + 0xec, 0x00, 0xf1, 0x14, 0x23, 0x02, 0x0d, 0xf8, 0x26, 0x2a, 0xef, 0xdf, 0xc6, + 0xdd, 0xd5, 0xeb, 0xf3, 0x09, 0x0d, 0x4f, 0x06, 0x39, 0xf5, 0xea, 0x05, 0x3d, + 0x15, 0xb7, 0x27, 0xa0, 0xed, 0xdb, 0xe7, 0x02, 0xa3, 0x17, 0xdf, 0xdf, 0xc0, + 0x07, 0x13, 0xef, 0x39, 0xd9, 0xe5, 0x92, 0x2f, 0xf1, 0x3b, 0x29, 0x7f, 0x78, + 0xdb, 0xea, 0xf1, 0x3d, 0x4d, 0x5f, 0x17, 0x52, 0xcf, 0x1b, 0xdc, 0x24, 0x40, + 0x0a, 0x03, 0x21, 0xea, 0x01, 0xd9, 0x4c, 0xfa, 0x08, 0x35, 0xe5, 0xfe, 0xf6, + 0x0f, 0x46, 0xf5, 0x17, 0x15, 0x24, 0xed, 0x09, 0x15, 0x0c, 0x23, 0xe9, 0x3f, + 0x14, 0xf7, 0xc0, 0xfb, 0x13, 0x41, 0xd5, 0xe5, 0xd1, 0xe2, 0xb0, 0xee, 0x1f, + 0x20, 0xec, 0x23, 0xf9, 0xe9, 0x75, 0xfb, 0x1c, 0x5b, 0x0e, 0x28, 0x01, 0xea, + 0xf6, 0xe0, 0x0f, 0xfc, 0xe5, 0x25, 0x47, 0xaa, 0x1e, 0xf2, 0x3f, 0xf9, 0x0f, + 0x07, 0x12, 0xd3, 0xb2, 0xc5, 0xd3, 0x3d, 0xd7, 0x07, 0x2c, 0xc7, 0xcb, 0x39, + 0x16, 0xf7, 0xdf, 0x4f, 0xc7, 0x21, 0x22, 0x30, 0xaa, 0xb5, 0x18, 0xbf, 0x2d, + 0xf3, 0x0d, 0xf8, 0x46, 0x10, 0x86, 0x3d, 0xef, 0x3c, 0x4f, 0x29, 0xfc, 0xe4, + 0xd3, 0x27, 0xf7, 0x1f, 0x26, 0x29, 0xf1, 0xd0, 0x29, 0xe6, 0xf0, 0xd1, 0x04, + 0xac, 0xdd, 0xd9, 0xa6, 0xfc, 0xd0, 0xd4, 0x09, 0x11, 0x4a, 0x32, 0xe2, 0xf9, + 0xeb, 0xfc, 0xcb, 0xf9, 0x3b, 0xc5, 0xd3, 0x95, 0x50, 0x3e, 0x16, 0x94, 0xe7, + 0xcb, 0xcb, 0xda, 0x3e, 0xd5, 0x0a, 0xc7, 0x1d, 0x06, 0xe0, 0x7f, 0x31, 0x62, + 0x01, 0x1d, 0x37, 0x4e, 0xeb, 0x14, 0x04, 0xf2, 0x2a, 0x05, 0xd9, 0x4a, 0x34, + 0xec, 0x1f, 0x32, 0x89, 0xf6, 0xcd, 0x5e, 0x1e, 0x28, 0x1a, 0x3e, 0xea, 0xdd, + 0x1a, 0x49, 0xfd, 0x25, 0x26, 0x2d, 0xde, 0xe5, 0xdb, 0xd9, 0x33, 0x42, 0xda, + 0x0b, 0x21, 0xf3, 0xd6, 0xe5, 0x13, 0x1e, 0x12, 0xcb, 0x45, 0x12, 0x2c, 0x1f, + 0x3b, 0xba, 0x1c, 0x0d, 0xfe, 0x9e, 0xe5, 0x3d, 0x17, 0x47, 0x81, 0xe8, 0xd8, + 0x28, 0xe5, 0xf9, 0x0e, 0xc2, 0x2b, 0xe2, 0xb7, 0xf2, 0x2c, 0x02, 0x04, 0x51, + 0xfa, 0x07, 0xb7, 0x25, 0x05, 0x10, 0xb0, 0xe3, 0xd9, 0x0f, 0x03, 0x0f, 0x03, + 0x15, 0xeb, 0xea, 0xdf, 0xe6, 0x96, 0xfe, 0xf0, 0x0d, 0x19, 0xdd, 0xea, 0xfd, + 0xf3, 0x4a, 0xb3, 0xc6, 0x0e, 0x19, 0xe7, 0xf9, 0x0d, 0x1c, 0x22, 0xff, 0xd7, + 0x15, 0xce, 0x31, 0xde, 0xd4, 0xe1, 0xee, 0x16, 0x04, 0x2d, 0x01, 0xe6, 0xd2, + 0x22, 0x1b, 0x9c, 0xc9, 0xdc, 0xef, 0xf4, 0x2d, 0x0f, 0xaf, 0xb0, 0x0c, 0xde, + 0xf4, 0x2c, 0x32, 0x19, 0x99, 0x10, 0xe2, 0x08, 0xbe, 0x0a, 0xe3, 0x13, 0x4c, + 0x08, 0x0b, 0xeb, 0x03, 0xfb, 0x3d, 0xc4, 0xcb, 0xf5, 0xff, 0x22, 0xd6, 0xe8, + 0x0e, 0xd3, 0xc0, 0x55, 0xbc, 0x2b, 0x3c, 0xe4, 0x18, 0x0e, 0xd5, 0xe5, 0xd0, + 0xe3, 0x2e, 0x27, 0x18, 0x2a, 0x02, 0x09, 0xf2, 0xf1, 0x12, 0x32, 0x14, 0xbd, + 0xe9, 0x46, 0x0b, 0xe5, 0xf4, 0x1b, 0xf7, 0xde, 0xf9, 0xf4, 0xcd, 0xe9, 0xbe, + 0x05, 0xc8, 0x4c, 0xd7, 0x0e, 0x1c, 0xec, 0xca, 0x23, 0xe4, 0xf1, 0xf0, 0xf6, + 0xfe, 0x27, 0xcf, 0x9f, 0xda, 0xd6, 0x3a, 0xfe, 0xd3, 0xd8, 0xf2, 0xb3, 0x77, + 0x08, 0xba, 0xc9, 0xbb, 0x8e, 0x14, 0xed, 0x1d, 0x17, 0xe3, 0xfd, 0xcf, 0xef, + 0x7f, 0x1a, 0xde, 0x0a, 0x38, 0x15, 0xc5, 0xef, 0xbf, 0xf5, 0x32, 0xd4, 0x08, + 0xcc, 0xcb, 0x05, 0xfc, 0x1e, 0xf3, 0xda, 0xdb, 0x2c, 0x19, 0x14, 0xf0, 0x1a, + 0x38, 0x23, 0xa8, 0xa2, 0x09, 0x1f, 0x1c, 0x22, 0xe2, 0xe1, 0x04, 0x53, 0x1d, + 0xf7, 0x50, 0x0f, 0xf3, 0x2d, 0x1b, 0x2e, 0xe3, 0xfb, 0x25, 0x17, 0xe2, 0xef, + 0x68, 0xfe, 0xff, 0x3d, 0xdb, 0xed, 0xdd, 0xe2, 0xbe, 0x07, 0xfd, 0x41, 0x1c, + 0x1e, 0xed, 0xca, 0xf0, 0x1b, 0xe6, 0x0b, 0xe4, 0x1e, 0x30, 0xf0, 0xfd, 0x1a, + 0x5c, 0xa1, 0xc4, 0x16, 0x15, 0xfa, 0x15, 0x11, 0xe4, 0xdb, 0x28, 0xd5, 0xfa, + 0xf7, 0xdd, 0xf3, 0x9a, 0x67, 0xc6, 0xfc, 0xf8, 0x0b, 0x07, 0xaf, 0x38, 0xaa, + 0xea, 0xf1, 0x10, 0x49, 0x3c, 0x19, 0x7f, 0x33, 0xc8, 0xeb, 0x59, 0x12, 0xc7, + 0xe4, 0xea, 0x24, 0x4c, 0x07, 0x44, 0x1a, 0x0b, 0x00, 0x61, 0x0f, 0x10, 0xef, + 0x20, 0xd9, 0x69, 0x4c, 0xc5, 0xd1, 0xe1, 0x1e, 0x0a, 0xf2, 0xe9, 0xef, 0x4c, + 0x4a, 0xf5, 0x35, 0x00, 0xcd, 0xd8, 0xe9, 0x71, 0x53, 0x1a, 0xff, 0xfb, 0x22, + 0x16, 0xf0, 0x1d, 0xdf, 0xb1, 0xc3, 0xef, 0xf9, 0xe5, 0x10, 0xde, 0x02, 0x4f, + 0xe4, 0x12, 0xfd, 0x0c, 0x66, 0x28, 0xc7, 0xf6, 0x5d, 0x06, 0xfe, 0xcd, 0x99, + 0x03, 0xc8, 0xc8, 0x06, 0xc5, 0xcf, 0x06, 0x4f, 0xb1, 0x50, 0x1b, 0xf4, 0xbd, + 0xb1, 0x40, 0x5f, 0x23, 0x9e, 0x27, 0x16, 0xd3, 0x4e, 0x2c, 0xe7, 0xaf, 0xe0, + 0xf3, 0xed, 0xc9, 0x35, 0x0a, 0x15, 0x2b, 0xea, 0x81, 0x9f, 0x08, 0x0c, 0x25, + 0x14, 0x12, 0xb0, 0xc3, 0x2c, 0x5a, 0xe9, 0x3f, 0x70, 0xf0, 0x00, 0xdb, 0xd1, + 0xeb, 0xf8, 0x08, 0x33, 0xf6, 0xfb, 0x51, 0xde, 0xd6, 0xc4, 0x46, 0x36, 0xf0, + 0x8f, 0x0c, 0x5a, 0x44, 0xf6, 0x15, 0xfa, 0xf2, 0xf7, 0xcb, 0x01, 0xa2, 0xe0, + 0x3d, 0xeb, 0x43, 0x12, 0xf7, 0xfd, 0xe8, 0x64, 0x12, 0xe5, 0xd7, 0xcb, 0xf1, + 0x32, 0xfb, 0x0a, 0x81, 0x13, 0xf8, 0xf9, 0xc9, 0xab, 0xec, 0x09, 0xe6, 0xdf, + 0xf1, 0x10, 0x0c, 0xe8, 0xcd, 0xf2, 0xfe, 0x34, 0x05, 0xf7, 0x9d, 0xfb, 0xeb, + 0x55, 0x06, 0xe5, 0x1f, 0xc0, 0xa1, 0xb8, 0xd0, 0x21, 0xdd, 0x5a, 0xd1, 0x14, + 0x09, 0xfb, 0xfa, 0x24, 0xf5, 0x7f, 0x06, 0xe1, 0x38, 0xd2, 0x0f, 0x14, 0x07, + 0xf4, 0x10, 0x16, 0x20, 0x09, 0x16, 0x2f, 0xff, 0x2a, 0xdf, 0xd8, 0xea, 0x0d, + 0xe1, 0xd2, 0xe8, 0xda, 0xba, 0xd8, 0x24, 0x15, 0xc4, 0x14, 0xc7, 0x08, 0x00, + 0x1e, 0xc3, 0xe0, 0xaf, 0xf9, 0x05, 0x0f, 0xe9, 0x2c, 0xc9, 0x36, 0xff, 0xcc, + 0xf2, 0xec, 0xdb, 0xda, 0x2f, 0x26, 0xe4, 0x11, 0xeb, 0x56, 0x1c, 0x62, 0xd2, + 0x03, 0xd1, 0x26, 0xc6, 0xe0, 0xc0, 0xef, 0xe3, 0x30, 0xe4, 0xc1, 0x35, 0x1c, + 0x1d, 0xc9, 0x0b, 0xd2, 0xe0, 0x14, 0x2e, 0xf2, 0xd9, 0x0d, 0xd9, 0xea, 0x33, + 0xeb, 0x09, 0x15, 0xfb, 0x11, 0xb0, 0xe7, 0xe7, 0x0c, 0xdd, 0xca, 0x16, 0xe1, + 0xfe, 0xd9, 0x06, 0x04, 0x1e, 0x06, 0xe3, 0x0d, 0xeb, 0x02, 0xe7, 0x05, 0xfd, + 0xb0, 0xee, 0xd1, 0xf3, 0xa5, 0xee, 0xf1, 0xd2, 0xf3, 0xd6, 0x07, 0x12, 0xf3, + 0x0a, 0xf5, 0x0b, 0xd9, 0x13, 0xbd, 0x10, 0x1a, 0x4d, 0x04, 0xcf, 0x02, 0x00, + 0x0e, 0x2f, 0xfc, 0xec, 0x2d, 0x2c, 0x50, 0x12, 0xdf, 0xf0, 0x23, 0xdc, 0xb8, + 0xf0, 0xcf, 0xcd, 0x06, 0x63, 0x04, 0x42, 0x12, 0x2b, 0x3f, 0x29, 0x48, 0xdd, + 0xd9, 0xcc, 0xc6, 0xf8, 0xb5, 0xff, 0xeb, 0xc6, 0x51, 0xfd, 0x3b, 0xf0, 0x12, + 0x8e, 0x03, 0xea, 0x38, 0x81, 0xea, 0x18, 0x06, 0xcd, 0xc3, 0xfb, 0x08, 0xff, + 0xd5, 0x17, 0xc5, 0xa1, 0xfd, 0x12, 0x08, 0xfb, 0x3c, 0x0a, 0x12, 0xf9, 0xd9, + 0xe5, 0xc8, 0x25, 0x2e, 0xba, 0x1f, 0xfd, 0xf7, 0x03, 0x41, 0xd9, 0x9d, 0x34, + 0xde, 0x39, 0x5c, 0x2b, 0x05, 0x2d, 0x00, 0x34, 0x28, 0xe6, 0x21, 0x38, 0xd2, + 0x09, 0x06, 0xb9, 0x47, 0xdf, 0x07, 0xc7, 0x23, 0xfc, 0x27, 0x32, 0xf5, 0xe0, + 0x24, 0x22, 0xee, 0xde, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x83, 0x0b, 0x00, 0x00, 0xa8, 0x27, 0x00, 0x00, 0x47, 0xe1, 0xff, 0xff, + 0xd6, 0xfd, 0xff, 0xff, 0x40, 0xca, 0xff, 0xff, 0xd3, 0x25, 0x00, 0x00, 0xc2, + 0xff, 0xff, 0xff, 0xeb, 0xc2, 0xff, 0xff, 0xb1, 0x52, 0x00, 0x00, 0x51, 0x09, + 0x00, 0x00, 0x31, 0xea, 0xff, 0xff, 0x65, 0xc3, 0xff, 0xff, 0x59, 0x09, 0x00, + 0x00, 0x6a, 0xe3, 0xff, 0xff, 0x33, 0x02, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, + 0x2f, 0x23, 0x00, 0x00, 0x26, 0x02, 0x00, 0x00, 0x66, 0xd9, 0xff, 0xff, 0x7a, + 0xd8, 0xff, 0xff, 0x0b, 0x15, 0x00, 0x00, 0xfd, 0x2e, 0x00, 0x00, 0xd7, 0x2c, + 0x00, 0x00, 0x87, 0xef, 0xff, 0xff, 0x41, 0x23, 0x00, 0x00, 0x3a, 0x9e, 0xff, + 0xff, 0x43, 0xfe, 0xff, 0xff, 0x16, 0x10, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, + 0x72, 0xda, 0xff, 0xff, 0x66, 0xfa, 0xff, 0xff, 0x64, 0xfe, 0xff, 0xff, 0x34, + 0x2d, 0x00, 0x00, 0x62, 0x0b, 0x00, 0x00, 0xa6, 0x08, 0x00, 0x00, 0xf3, 0xd2, + 0xff, 0xff, 0x7d, 0x49, 0x00, 0x00, 0x8a, 0xd6, 0xff, 0xff, 0x06, 0xf0, 0xff, + 0xff, 0x90, 0x3d, 0x00, 0x00, 0xfd, 0x18, 0x00, 0x00, 0xe3, 0xee, 0xff, 0xff, + 0x05, 0x01, 0x00, 0x00, 0x6e, 0xb2, 0xff, 0xff, 0xb3, 0x0a, 0x00, 0x00, 0xaa, + 0xdd, 0xff, 0xff, 0x1c, 0x39, 0x00, 0x00, 0xa0, 0x10, 0x00, 0x00, 0x90, 0x05, + 0x00, 0x00, 0x95, 0x29, 0x00, 0x00, 0x4f, 0xfc, 0xff, 0xff, 0x92, 0x0a, 0x00, + 0x00, 0xb0, 0x0a, 0x00, 0x00, 0x3d, 0x2d, 0x00, 0x00, 0x52, 0x0c, 0x00, 0x00, + 0xdc, 0x25, 0x00, 0x00, 0x4a, 0xdb, 0xff, 0xff, 0x9c, 0x36, 0x00, 0x00, 0xff, + 0xd2, 0xff, 0xff, 0xa3, 0xff, 0xff, 0xff, 0x14, 0xf2, 0xff, 0xff, 0x3d, 0x0d, + 0x00, 0x00, 0x45, 0x03, 0x00, 0x00, 0x39, 0xe4, 0xff, 0xff, 0xdb, 0x02, 0x00, + 0x00, 0xf0, 0xed, 0xff, 0xff, 0xfb, 0xbf, 0xff, 0xff, 0xd1, 0xee, 0xff, 0xff, + 0x42, 0x1d, 0x00, 0x00, 0x27, 0x0f, 0x00, 0x00, 0xbc, 0x02, 0x00, 0x00, 0xd1, + 0x39, 0x00, 0x00, 0x96, 0xf2, 0xff, 0xff, 0xe6, 0x2b, 0x00, 0x00, 0x0a, 0x27, + 0x00, 0x00, 0x06, 0xe2, 0xff, 0xff, 0x10, 0x0b, 0x00, 0x00, 0x6e, 0xdf, 0xff, + 0xff, 0x57, 0xde, 0xff, 0xff, 0x74, 0xf7, 0xff, 0xff, 0x30, 0xf3, 0xff, 0xff, + 0xbf, 0x13, 0x00, 0x00, 0x3f, 0x05, 0x00, 0x00, 0x0c, 0xe5, 0xff, 0xff, 0xe7, + 0xf8, 0xff, 0xff, 0xd3, 0x1e, 0x00, 0x00, 0xa7, 0x1f, 0x00, 0x00, 0x44, 0x21, + 0x00, 0x00, 0xf1, 0xf6, 0xff, 0xff, 0xe1, 0x1a, 0x00, 0x00, 0x60, 0xbc, 0xff, + 0xff, 0x73, 0x09, 0x00, 0x00, 0x71, 0x06, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x9e, 0x31, 0x00, 0x00, 0xac, 0xe8, 0xff, 0xff, 0xff, 0x06, 0x00, 0x00, 0xff, + 0x21, 0x00, 0x00, 0xa2, 0x5b, 0x00, 0x00, 0x1e, 0xfc, 0xff, 0xff, 0x56, 0x04, + 0x00, 0x00, 0xf1, 0xd9, 0xff, 0xff, 0xca, 0x27, 0x00, 0x00, 0x21, 0xf1, 0xff, + 0xff, 0x40, 0xd0, 0xff, 0xff, 0xdb, 0x06, 0x00, 0x00, 0xec, 0x3e, 0x00, 0x00, + 0x9e, 0x0e, 0x00, 0x00, 0x0b, 0xe9, 0xff, 0xff, 0x7e, 0x4a, 0x00, 0x00, 0x0a, + 0x1e, 0x00, 0x00, 0x30, 0xfe, 0xff, 0xff, 0x95, 0x0b, 0x00, 0x00, 0x06, 0xf8, + 0xff, 0xff, 0x74, 0x43, 0x00, 0x00, 0x71, 0x2a, 0x00, 0x00, 0x8a, 0x16, 0x00, + 0x00, 0x65, 0xf5, 0xff, 0xff, 0x23, 0x02, 0x00, 0x00, 0xc6, 0x01, 0x00, 0x00, + 0x4f, 0xd5, 0xff, 0xff, 0x5e, 0x0a, 0x00, 0x00, 0x88, 0x32, 0x00, 0x00, 0x7a, + 0x18, 0x00, 0x00, 0x51, 0xd4, 0xff, 0xff, 0xc7, 0x25, 0x00, 0x00, 0xc8, 0x2f, + 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0xfa, 0xe0, 0xfe, 0xff, 0x04, 0x00, 0x00, + 0x00, 0x80, 0x04, 0x00, 0x00, 0x7a, 0x88, 0xba, 0x3f, 0xcb, 0xb5, 0x1d, 0xad, + 0x81, 0xb9, 0xc1, 0x77, 0x18, 0xa7, 0xd0, 0x76, 0xe0, 0xc9, 0x65, 0x02, 0x04, + 0x58, 0xcb, 0x92, 0x70, 0x2b, 0x7f, 0x0d, 0x7f, 0x0f, 0xfd, 0xf2, 0xe0, 0x7f, + 0xc6, 0xe5, 0xd2, 0x81, 0xe6, 0xe8, 0x7f, 0xd1, 0xf3, 0x34, 0xc3, 0x2c, 0x86, + 0x8f, 0x7f, 0xdf, 0x81, 0xa4, 0x7f, 0x19, 0x0d, 0x08, 0x1e, 0x8b, 0xff, 0xbf, + 0x04, 0x2c, 0x70, 0xff, 0x7f, 0xc1, 0xe3, 0xe3, 0xac, 0xd1, 0x71, 0xf6, 0xe3, + 0xb3, 0x8f, 0x22, 0x5a, 0x1b, 0x81, 0x87, 0x3a, 0xd1, 0x12, 0x05, 0x1a, 0x4e, + 0x7d, 0xba, 0x7f, 0xfe, 0xf9, 0x65, 0x0e, 0xbe, 0x90, 0xb0, 0x91, 0xcc, 0xb0, + 0x84, 0xbd, 0x7f, 0x1e, 0x81, 0xec, 0x7f, 0x9e, 0x6f, 0x9e, 0x0a, 0xe9, 0x81, + 0x3f, 0xe3, 0x81, 0x81, 0x34, 0x46, 0xc9, 0xc9, 0x06, 0x96, 0x09, 0x27, 0xbe, + 0x2a, 0xdb, 0x46, 0x74, 0xef, 0xe6, 0xe0, 0x81, 0xa7, 0x58, 0x06, 0xd8, 0x7f, + 0xf5, 0x7c, 0x4c, 0xaa, 0xb5, 0x18, 0x7f, 0xea, 0x7f, 0xf0, 0x19, 0x7f, 0x11, + 0xed, 0xbf, 0x7f, 0x95, 0x77, 0x46, 0x18, 0x62, 0xf5, 0xe2, 0x27, 0x9a, 0x81, + 0xf6, 0xf1, 0x42, 0x00, 0x5c, 0xf9, 0xc1, 0x7f, 0xb7, 0x6b, 0x81, 0x47, 0x68, + 0x23, 0xad, 0xb4, 0x38, 0xf8, 0xfa, 0x37, 0x96, 0x5f, 0x81, 0x16, 0x74, 0x7f, + 0x47, 0x19, 0x2b, 0xb0, 0xa7, 0x8f, 0xb8, 0xd1, 0xca, 0x69, 0x11, 0xf8, 0x81, + 0x81, 0x2e, 0x7f, 0xfe, 0x81, 0x2d, 0xdb, 0xe0, 0xf9, 0x1b, 0x41, 0xeb, 0x06, + 0x24, 0x81, 0x8d, 0x81, 0x19, 0xab, 0x8c, 0x33, 0xa2, 0x81, 0xc8, 0xd3, 0x55, + 0x29, 0x03, 0xe4, 0xdd, 0x26, 0x0b, 0x52, 0x12, 0x07, 0x5a, 0x91, 0x67, 0x0e, + 0x99, 0xbf, 0x7f, 0x3c, 0x50, 0xbe, 0x81, 0x99, 0xac, 0x03, 0x78, 0x0f, 0xbc, + 0xdc, 0x81, 0x81, 0xbc, 0x95, 0x15, 0xc7, 0x7f, 0xe8, 0xc8, 0x76, 0x19, 0xb4, + 0x6b, 0xd6, 0x81, 0x3f, 0xf5, 0x1b, 0xd0, 0xfd, 0x42, 0x58, 0x81, 0x16, 0x95, + 0x7e, 0xe2, 0x7f, 0x18, 0xd9, 0x20, 0xe2, 0x15, 0xde, 0xdd, 0x2b, 0x93, 0x8e, + 0x7f, 0xe1, 0x2c, 0x15, 0x1a, 0x12, 0xc0, 0xfc, 0xfc, 0x20, 0x20, 0x00, 0x24, + 0x52, 0xd6, 0x9b, 0x8f, 0xec, 0x11, 0x2b, 0xaf, 0xda, 0xd6, 0x09, 0x2e, 0x2d, + 0xe9, 0x22, 0x0c, 0x81, 0xf4, 0x1c, 0x81, 0x4e, 0x02, 0x9b, 0xa4, 0x99, 0x48, + 0xe7, 0x17, 0x52, 0x07, 0xd3, 0xd8, 0xc8, 0xeb, 0x7f, 0xfe, 0x01, 0xff, 0xbd, + 0x1f, 0x89, 0xb2, 0xef, 0x8a, 0x83, 0xe1, 0xcd, 0x1c, 0x19, 0x36, 0x8d, 0xdf, + 0x9b, 0xfb, 0x5a, 0xf5, 0x09, 0x97, 0x03, 0xbd, 0x63, 0x14, 0x16, 0xbe, 0xc0, + 0xe8, 0x7f, 0x8c, 0xf0, 0x47, 0xab, 0xf6, 0xc4, 0x7f, 0x2f, 0xb1, 0xdd, 0x75, + 0xd0, 0x7f, 0x1e, 0x30, 0xa4, 0x07, 0x79, 0xb2, 0x0b, 0xce, 0x23, 0xb7, 0x81, + 0xb9, 0xcc, 0xf1, 0xea, 0x03, 0x7e, 0x18, 0x01, 0x36, 0x81, 0xc4, 0xf5, 0xe2, + 0xe5, 0x17, 0x7f, 0xb9, 0x2f, 0x81, 0x41, 0xb9, 0xdb, 0x44, 0x22, 0x76, 0xbc, + 0x71, 0xe7, 0x78, 0x6a, 0x37, 0x40, 0xf8, 0x0d, 0x08, 0xf7, 0xc1, 0x84, 0x0b, + 0x63, 0x5c, 0x27, 0x81, 0x81, 0xdb, 0xa3, 0xb3, 0xe8, 0x41, 0xbb, 0x3a, 0x37, + 0xb5, 0xc1, 0x81, 0xb7, 0x7b, 0x53, 0xe7, 0xce, 0x77, 0x72, 0x7f, 0x4f, 0xd2, + 0xb9, 0x7f, 0xeb, 0x69, 0x7f, 0x09, 0x5a, 0x1b, 0xd4, 0xca, 0xd5, 0xce, 0x1b, + 0x18, 0xb5, 0x1b, 0x1e, 0x82, 0x78, 0xf0, 0xc1, 0xe6, 0x18, 0x7f, 0x22, 0x81, + 0x71, 0x06, 0x60, 0xbf, 0x03, 0x2f, 0x9c, 0x17, 0x5d, 0x52, 0xa2, 0x03, 0x40, + 0x81, 0xa1, 0xf8, 0xdd, 0xe2, 0x7f, 0x34, 0x2e, 0x7f, 0x20, 0x05, 0x8d, 0x3b, + 0x7f, 0x02, 0xbb, 0xcd, 0x7f, 0xfb, 0x2f, 0x57, 0x7f, 0x3d, 0x07, 0xaf, 0x42, + 0x04, 0x81, 0x04, 0xe5, 0x38, 0x26, 0x40, 0x0c, 0x81, 0x21, 0xdd, 0x33, 0xee, + 0x39, 0x3c, 0x4c, 0xb4, 0x1a, 0xf8, 0xd5, 0x81, 0xb2, 0x63, 0xe8, 0x25, 0x2a, + 0x1e, 0x10, 0x2a, 0x7f, 0xdf, 0xe6, 0x36, 0x38, 0x90, 0xc6, 0x12, 0xcf, 0x0b, + 0x35, 0x8c, 0xd9, 0x88, 0x81, 0x94, 0x2f, 0x09, 0x07, 0x43, 0xd2, 0x81, 0x2e, + 0xc2, 0x19, 0x8b, 0x7f, 0x53, 0x81, 0x71, 0x4c, 0x2a, 0x16, 0x31, 0x02, 0x09, + 0xfb, 0x39, 0x40, 0x1b, 0xe4, 0x15, 0x81, 0xe9, 0xcb, 0x81, 0xb3, 0x44, 0xdf, + 0x7f, 0x7f, 0xfb, 0xc7, 0x81, 0x81, 0x31, 0xfd, 0xdc, 0x1b, 0xb1, 0x47, 0x81, + 0xdb, 0x82, 0x25, 0x7f, 0x14, 0x21, 0x2d, 0x01, 0xd2, 0xd4, 0x06, 0xa5, 0xc4, + 0xd8, 0xb2, 0x86, 0x2e, 0x57, 0x2d, 0x4e, 0x0b, 0xb1, 0xfe, 0x00, 0xa3, 0x20, + 0xe1, 0x3f, 0xef, 0xa2, 0xfa, 0x6f, 0xc5, 0x2e, 0xb2, 0xea, 0x3a, 0x32, 0xb7, + 0xef, 0x7f, 0x7f, 0x39, 0xa9, 0xdd, 0xbb, 0x1f, 0xa9, 0x20, 0x24, 0x15, 0x4e, + 0x20, 0xf1, 0xd2, 0x0d, 0x11, 0x47, 0x88, 0x32, 0xc1, 0x75, 0x1b, 0xbb, 0xe9, + 0xe2, 0x0d, 0x1c, 0xe3, 0x21, 0x7f, 0xe5, 0x81, 0x0f, 0xa2, 0xaa, 0xd1, 0xeb, + 0x12, 0xa6, 0xc4, 0xbe, 0x41, 0x16, 0xc3, 0x29, 0x1d, 0xf7, 0x12, 0xd8, 0x6f, + 0x89, 0x6c, 0x30, 0xb6, 0xea, 0x59, 0x45, 0x09, 0x2b, 0x17, 0xf4, 0xd5, 0x33, + 0xd7, 0xe7, 0xe7, 0xe6, 0xb4, 0xd9, 0xff, 0xc2, 0x7c, 0x81, 0x81, 0x65, 0xdb, + 0x81, 0xfa, 0xfe, 0x46, 0xf2, 0xc2, 0xb9, 0xb0, 0xfc, 0xef, 0xc8, 0x9f, 0xb1, + 0x16, 0xd4, 0x6f, 0x7f, 0x46, 0xd7, 0xb0, 0x9b, 0xde, 0xc0, 0x20, 0xd7, 0x81, + 0x0c, 0xc9, 0x71, 0x08, 0xf4, 0xff, 0x21, 0xd8, 0xc4, 0x3f, 0xef, 0x81, 0x8c, + 0xaf, 0xa5, 0xd0, 0xc4, 0xdc, 0xfe, 0x2f, 0xb4, 0x81, 0x0d, 0x06, 0x76, 0x53, + 0xeb, 0xc9, 0x6c, 0xa9, 0xbf, 0xea, 0xe6, 0x08, 0xe5, 0x27, 0x81, 0x7f, 0xac, + 0xf6, 0xd0, 0xf9, 0xd5, 0x8c, 0xf2, 0xd8, 0x41, 0xe9, 0x7f, 0xfe, 0x7f, 0xed, + 0xb2, 0x06, 0xe3, 0x7b, 0xe7, 0xba, 0xfc, 0x7f, 0xfc, 0xf4, 0x9c, 0xb9, 0xcf, + 0x4f, 0x81, 0xe2, 0x81, 0x9a, 0xf7, 0x06, 0xfe, 0x29, 0xdf, 0xfd, 0x78, 0x5f, + 0x1d, 0x94, 0xd2, 0x54, 0x49, 0x9c, 0xb8, 0xbc, 0xc2, 0x21, 0x08, 0x30, 0x1e, + 0xcc, 0x1c, 0x88, 0xd9, 0xf7, 0x03, 0xd9, 0x9d, 0x90, 0x07, 0xc3, 0xd9, 0x98, + 0xc7, 0xb3, 0x81, 0xd2, 0x0c, 0xd3, 0xc7, 0xab, 0x38, 0xab, 0x51, 0x1b, 0xfe, + 0xdc, 0x1e, 0x7f, 0x4f, 0x00, 0x2c, 0x0f, 0xe1, 0xb9, 0xb7, 0xe7, 0xc2, 0xfe, + 0x0d, 0x7f, 0xf2, 0x7f, 0xff, 0xbd, 0xb0, 0x45, 0x16, 0x16, 0xb6, 0x03, 0xf5, + 0xd4, 0x02, 0xf2, 0x81, 0x04, 0xbd, 0xe3, 0x39, 0xae, 0x2b, 0xff, 0x58, 0x07, + 0x39, 0x4a, 0xa2, 0xf0, 0xb2, 0x2d, 0xe7, 0x0f, 0xc4, 0x78, 0x43, 0xe8, 0xae, + 0xe0, 0x88, 0xc5, 0x11, 0x81, 0x8e, 0x1e, 0x06, 0xad, 0x74, 0xe4, 0x8a, 0x59, + 0x18, 0x6e, 0x61, 0xff, 0x47, 0xe9, 0x7f, 0x7f, 0x86, 0xda, 0xda, 0xc1, 0x99, + 0x0b, 0xc2, 0xa0, 0xf8, 0x81, 0xb4, 0x2b, 0xff, 0x7f, 0x38, 0x2f, 0x7f, 0xbc, + 0xcd, 0x4a, 0x21, 0xc1, 0x18, 0x84, 0xd6, 0x7f, 0x7f, 0x6e, 0x7f, 0x09, 0x7f, + 0xbc, 0xdc, 0x3a, 0x8e, 0xa6, 0xd4, 0x50, 0x5a, 0xfd, 0x67, 0xf0, 0x83, 0xa1, + 0x56, 0x0c, 0x08, 0xb5, 0x2b, 0xb4, 0xa8, 0x81, 0x7f, 0x7f, 0x10, 0xc1, 0x1b, + 0x1d, 0xa1, 0x16, 0xde, 0xfd, 0x01, 0x81, 0xad, 0x92, 0x81, 0xf5, 0x70, 0x51, + 0x16, 0x33, 0x09, 0x0e, 0x1b, 0xf7, 0x40, 0x20, 0xf2, 0x88, 0xde, 0xf3, 0x7f, + 0xea, 0xc2, 0xe6, 0xff, 0x93, 0x43, 0x1e, 0xb8, 0x50, 0x06, 0x3d, 0xa5, 0x4d, + 0x92, 0xe3, 0xc6, 0xf8, 0x0e, 0x21, 0xb3, 0xe4, 0x65, 0xe7, 0x81, 0xd6, 0xb5, + 0x2a, 0x0a, 0x24, 0x3d, 0x7f, 0xe5, 0xdd, 0xe5, 0xcf, 0x30, 0x7f, 0xeb, 0x56, + 0x35, 0xa5, 0x36, 0xd0, 0x98, 0x62, 0xec, 0xbd, 0xe4, 0xdd, 0x0d, 0xe7, 0xb9, + 0x81, 0x32, 0x87, 0xb6, 0x3d, 0x23, 0x62, 0xb7, 0x08, 0x4f, 0xba, 0xa0, 0x27, + 0x17, 0x85, 0x78, 0xd1, 0xf7, 0x26, 0x58, 0xe9, 0x1c, 0xf8, 0x41, 0x2c, 0xed, + 0x19, 0xd6, 0x37, 0x0b, 0xe4, 0x1c, 0xf6, 0xfb, 0xd0, 0xb6, 0x3a, 0x56, 0xc1, + 0xfa, 0xac, 0x2d, 0x85, 0x10, 0xa9, 0x4d, 0x58, 0xe1, 0x5f, 0xdf, 0x43, 0xc4, + 0x4d, 0xcb, 0x05, 0x84, 0x8b, 0x0f, 0x3c, 0xf5, 0x11, 0xec, 0x42, 0x1f, 0x07, + 0x86, 0xe5, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x6d, + 0xed, 0xff, 0xff, 0xdb, 0x1e, 0x00, 0x00, 0x18, 0xfe, 0xff, 0xff, 0x76, 0xf4, + 0xff, 0xff, 0xae, 0x0b, 0x00, 0x00, 0x99, 0x20, 0x00, 0x00, 0xc0, 0xfa, 0xff, + 0xff, 0xb1, 0xf6, 0xff, 0xff, 0xed, 0x27, 0x00, 0x00, 0xa2, 0xf4, 0xff, 0xff, + 0xd0, 0xf9, 0xff, 0xff, 0x66, 0xee, 0xff, 0xff, 0xfc, 0xfa, 0xff, 0xff, 0xed, + 0x18, 0x00, 0x00, 0x3a, 0x25, 0x00, 0x00, 0x7f, 0xfb, 0xff, 0xff, 0xd1, 0xf3, + 0xff, 0xff, 0xcf, 0x13, 0x00, 0x00, 0x83, 0xf0, 0xff, 0xff, 0x7d, 0xf0, 0xff, + 0xff, 0xd8, 0xeb, 0xff, 0xff, 0x9a, 0xe8, 0xff, 0xff, 0x66, 0x05, 0x00, 0x00, + 0xe2, 0x15, 0x00, 0x00, 0x28, 0x22, 0x00, 0x00, 0xcf, 0xf4, 0xff, 0xff, 0xca, + 0x0a, 0x00, 0x00, 0xb4, 0xe9, 0xff, 0xff, 0xf8, 0xf3, 0xff, 0xff, 0x63, 0xee, + 0xff, 0xff, 0x31, 0xfd, 0xff, 0xff, 0xd9, 0xed, 0xff, 0xff, 0x3f, 0x15, 0x00, + 0x00, 0x93, 0xf1, 0xff, 0xff, 0x87, 0x1b, 0x00, 0x00, 0x27, 0x12, 0x00, 0x00, + 0x04, 0x16, 0x00, 0x00, 0xfb, 0x1f, 0x00, 0x00, 0x8f, 0xe9, 0xff, 0xff, 0x89, + 0x12, 0x00, 0x00, 0x49, 0xde, 0xff, 0xff, 0x40, 0xfa, 0xff, 0xff, 0xaa, 0xf6, + 0xff, 0xff, 0x6a, 0xf2, 0xff, 0xff, 0xe6, 0xfb, 0xff, 0xff, 0x08, 0xf5, 0xff, + 0xff, 0x5c, 0x23, 0x00, 0x00, 0xdd, 0xf9, 0xff, 0xff, 0xd2, 0xe6, 0xff, 0xff, + 0x41, 0xee, 0xff, 0xff, 0x23, 0x13, 0x00, 0x00, 0xb0, 0x1e, 0x00, 0x00, 0xfb, + 0xed, 0xff, 0xff, 0x8e, 0x00, 0x00, 0x00, 0x5b, 0xfe, 0xff, 0xff, 0xe9, 0xf1, + 0xff, 0xff, 0xed, 0x21, 0x00, 0x00, 0x71, 0x0e, 0x00, 0x00, 0xab, 0x1e, 0x00, + 0x00, 0x1a, 0x18, 0x00, 0x00, 0x09, 0x0f, 0x00, 0x00, 0xc1, 0xf1, 0xff, 0xff, + 0xe8, 0xf4, 0xff, 0xff, 0x88, 0x15, 0x00, 0x00, 0xc7, 0xe9, 0xff, 0xff, 0xbc, + 0x09, 0x00, 0x00, 0x67, 0x1e, 0x00, 0x00, 0xe3, 0x0b, 0x00, 0x00, 0x99, 0x1e, + 0x00, 0x00, 0xda, 0xfc, 0xff, 0xff, 0x18, 0xf8, 0xff, 0xff, 0x84, 0xe0, 0xff, + 0xff, 0x9f, 0xf1, 0xff, 0xff, 0xb7, 0x2b, 0x00, 0x00, 0xc3, 0x15, 0x00, 0x00, + 0x48, 0xe7, 0xff, 0xff, 0x39, 0xdd, 0xff, 0xff, 0x72, 0xfe, 0xff, 0xff, 0x52, + 0x02, 0x00, 0x00, 0xcd, 0x24, 0x00, 0x00, 0x7b, 0xf6, 0xff, 0xff, 0x4f, 0xff, + 0xff, 0xff, 0xa7, 0xea, 0xff, 0xff, 0x04, 0xf1, 0xff, 0xff, 0xd9, 0xf1, 0xff, + 0xff, 0xb5, 0xee, 0xff, 0xff, 0xc0, 0xec, 0xff, 0xff, 0x99, 0x1b, 0x00, 0x00, + 0x8e, 0xfd, 0xff, 0xff, 0xb7, 0x10, 0x00, 0x00, 0x9d, 0x1d, 0x00, 0x00, 0x75, + 0x09, 0x00, 0x00, 0x62, 0x06, 0x00, 0x00, 0xf7, 0x15, 0x00, 0x00, 0x17, 0xfc, + 0xff, 0xff, 0x5a, 0x01, 0x00, 0x00, 0xe4, 0x1d, 0x00, 0x00, 0xe8, 0x14, 0x00, + 0x00, 0x56, 0x1a, 0x00, 0x00, 0xa1, 0x15, 0x00, 0x00, 0x35, 0xf8, 0xff, 0xff, + 0x02, 0xfb, 0xff, 0xff, 0x84, 0xf9, 0xff, 0xff, 0xf8, 0x1c, 0x00, 0x00, 0x3d, + 0x12, 0x00, 0x00, 0xa0, 0xef, 0xff, 0xff, 0xff, 0x11, 0x00, 0x00, 0x81, 0xfc, + 0xff, 0xff, 0x4e, 0x12, 0x00, 0x00, 0x17, 0xf6, 0xff, 0xff, 0x27, 0xf4, 0xff, + 0xff, 0xae, 0x09, 0x00, 0x00, 0x51, 0xe8, 0xff, 0xff, 0x5d, 0xed, 0xff, 0xff, + 0x5d, 0x14, 0x00, 0x00, 0xb7, 0x1a, 0x00, 0x00, 0xdd, 0xfd, 0xff, 0xff, 0xf6, + 0xeb, 0xff, 0xff, 0x0c, 0x18, 0x00, 0x00, 0x21, 0x1f, 0x00, 0x00, 0xfe, 0x10, + 0x00, 0x00, 0xdd, 0x26, 0x00, 0x00, 0xe9, 0x19, 0x00, 0x00, 0x75, 0xf6, 0xff, + 0xff, 0x11, 0xe2, 0xff, 0xff, 0x66, 0xe5, 0xff, 0xff, 0x5d, 0xf3, 0xff, 0xff, + 0x38, 0xf3, 0xff, 0xff, 0x92, 0xe7, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x83, 0xe7, 0xff, 0xff, 0x46, 0xa8, 0xff, 0xff, 0x14, 0x34, + 0x00, 0x00, 0x10, 0xc0, 0xff, 0xff, 0x53, 0x11, 0x00, 0x00, 0xdd, 0x11, 0x00, + 0x00, 0xc2, 0xfc, 0xff, 0xff, 0xbe, 0xe0, 0xff, 0xff, 0x50, 0xa6, 0xff, 0xff, + 0x1a, 0xdd, 0xff, 0xff, 0xfa, 0x08, 0x00, 0x00, 0xb3, 0xff, 0xff, 0xff, 0x51, + 0x9b, 0xff, 0xff, 0x87, 0x11, 0x00, 0x00, 0x50, 0xc7, 0xff, 0xff, 0x3a, 0xe3, + 0xff, 0xff, 0xa8, 0xd9, 0xff, 0xff, 0x4d, 0xac, 0xff, 0xff, 0x4d, 0x2b, 0x00, + 0x00, 0x07, 0x05, 0x00, 0x00, 0x9f, 0xf2, 0xff, 0xff, 0x4b, 0xb8, 0xff, 0xff, + 0x71, 0xf0, 0xff, 0xff, 0xa4, 0x2b, 0x00, 0x00, 0xfc, 0xd5, 0xff, 0xff, 0x24, + 0x0d, 0x00, 0x00, 0xc8, 0xd9, 0xff, 0xff, 0x6e, 0xff, 0xff, 0xff, 0x1b, 0x38, + 0x00, 0x00, 0x4e, 0xbf, 0xff, 0xff, 0x3e, 0x9b, 0x00, 0x00, 0xb4, 0xf5, 0xff, + 0xff, 0xc7, 0xff, 0xff, 0xff, 0x2a, 0xd5, 0xff, 0xff, 0x56, 0xc7, 0xff, 0xff, + 0x6d, 0x11, 0x00, 0x00, 0x3c, 0xda, 0xff, 0xff, 0x5a, 0x32, 0x00, 0x00, 0x0a, + 0xf8, 0xff, 0xff, 0x47, 0x00, 0x00, 0x00, 0x86, 0xf1, 0xff, 0xff, 0x1d, 0x04, + 0x00, 0x00, 0x4a, 0xe3, 0xff, 0xff, 0xe1, 0xa5, 0xff, 0xff, 0xef, 0x3e, 0x00, + 0x00, 0x27, 0xb7, 0xff, 0xff, 0xf4, 0x28, 0x00, 0x00, 0x86, 0x27, 0x00, 0x00, + 0xb4, 0xed, 0xff, 0xff, 0x29, 0xf4, 0xff, 0xff, 0x5f, 0xe3, 0xff, 0xff, 0x46, + 0x14, 0x00, 0x00, 0xa7, 0x1c, 0x00, 0x00, 0x83, 0x1f, 0x00, 0x00, 0xc6, 0x24, + 0x00, 0x00, 0x63, 0x1c, 0x00, 0x00, 0xf9, 0xf6, 0xff, 0xff, 0xad, 0x0f, 0x00, + 0x00, 0x8a, 0xbb, 0xff, 0xff, 0xf0, 0xe4, 0xff, 0xff, 0xcf, 0xce, 0xff, 0xff, + 0x15, 0xe9, 0xff, 0xff, 0xf4, 0xbf, 0xff, 0xff, 0x77, 0xbf, 0xff, 0xff, 0x01, + 0x0e, 0x00, 0x00, 0xf9, 0x16, 0x00, 0x00, 0x06, 0xd7, 0xff, 0xff, 0x6b, 0xe6, + 0xff, 0xff, 0x34, 0xd2, 0xff, 0xff, 0xb6, 0x2d, 0x00, 0x00, 0xf8, 0x95, 0xff, + 0xff, 0xaa, 0x16, 0x00, 0x00, 0xba, 0x02, 0x00, 0x00, 0x49, 0xe0, 0xff, 0xff, + 0x48, 0x14, 0x00, 0x00, 0x9d, 0x09, 0x00, 0x00, 0x7e, 0x89, 0xff, 0xff, 0x6b, + 0xfb, 0xff, 0xff, 0x66, 0xc7, 0xff, 0xff, 0xe1, 0xe6, 0xff, 0xff, 0x27, 0x2c, + 0x00, 0x00, 0x08, 0xf3, 0xff, 0xff, 0x31, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x00, 0xf6, 0xec, 0xff, 0xff, 0x0c, 0x25, 0x00, 0x00, 0x1d, 0x0c, 0x00, 0x00, + 0xd1, 0xc1, 0xff, 0xff, 0x73, 0x87, 0xff, 0xff, 0x65, 0xf8, 0xff, 0xff, 0x79, + 0xbe, 0xff, 0xff, 0xb1, 0xcf, 0xff, 0xff, 0x37, 0xf7, 0xff, 0xff, 0xe6, 0xc0, + 0xff, 0xff, 0x7b, 0xef, 0xff, 0xff, 0x52, 0xe0, 0xff, 0xff, 0x24, 0xa5, 0xff, + 0xff, 0x72, 0xad, 0xff, 0xff, 0x4e, 0x25, 0x00, 0x00, 0x2c, 0xfd, 0xff, 0xff, + 0x52, 0x29, 0x00, 0x00, 0x42, 0xf8, 0xff, 0xff, 0xde, 0xe4, 0xff, 0xff, 0x79, + 0x04, 0x00, 0x00, 0xe1, 0x1b, 0x00, 0x00, 0x5c, 0x10, 0x00, 0x00, 0x2b, 0x2a, + 0x00, 0x00, 0x45, 0x0b, 0x00, 0x00, 0x04, 0xc5, 0xff, 0xff, 0x5c, 0x39, 0x00, + 0x00, 0x50, 0xf1, 0xff, 0xff, 0x17, 0xb8, 0xff, 0xff, 0xf4, 0xf8, 0xff, 0xff, + 0x1b, 0xe6, 0xff, 0xff, 0xb2, 0x0d, 0x00, 0x00, 0xd2, 0xae, 0xff, 0xff, 0x4a, + 0xee, 0xff, 0xff, 0x7d, 0x2e, 0x00, 0x00, 0x8d, 0xe7, 0xff, 0xff, 0x92, 0x03, + 0x00, 0x00, 0xd6, 0x34, 0x00, 0x00, 0x1c, 0xdf, 0xff, 0xff, 0x85, 0xab, 0xff, + 0xff, 0xbf, 0x4b, 0x00, 0x00, 0x9b, 0x3e, 0x00, 0x00, 0x09, 0xd6, 0xff, 0xff, + 0x7a, 0x00, 0x00, 0x00, 0x1c, 0x18, 0x00, 0x00, 0x76, 0x36, 0x00, 0x00, 0x80, + 0x94, 0xff, 0xff, 0x6b, 0xf7, 0xff, 0xff, 0x0c, 0x1b, 0x00, 0x00, 0xa6, 0x95, + 0xff, 0xff, 0x64, 0xd4, 0xff, 0xff, 0xc0, 0x0f, 0x00, 0x00, 0xea, 0x1c, 0x00, + 0x00, 0x41, 0x01, 0x00, 0x00, 0xba, 0x1d, 0x00, 0x00, 0x80, 0x2a, 0x00, 0x00, + 0x9a, 0x13, 0x00, 0x00, 0xf0, 0x27, 0x00, 0x00, 0x31, 0x0d, 0x00, 0x00, 0x9f, + 0x13, 0x00, 0x00, 0xde, 0xf1, 0xff, 0xff, 0x9b, 0xcf, 0xff, 0xff, 0xe5, 0xf4, + 0xff, 0xff, 0xbc, 0xc5, 0xff, 0xff, 0xea, 0xf1, 0xff, 0xff, 0x32, 0xf6, 0xff, + 0xff, 0x12, 0xf2, 0xff, 0xff, 0x6e, 0xdf, 0xff, 0xff, 0x44, 0xd2, 0xff, 0xff, + 0xa6, 0x54, 0x00, 0x00, 0x6b, 0x31, 0x00, 0x00, 0x48, 0x09, 0x00, 0x00, 0x77, + 0xee, 0xff, 0xff, 0xbb, 0xbc, 0xff, 0xff, 0x7c, 0xb5, 0xff, 0xff, 0x87, 0x1c, + 0x00, 0x00, 0xba, 0xda, 0xff, 0xff, 0x2e, 0xe9, 0xff, 0xff, 0xd0, 0xff, 0xff, + 0xff, 0x8a, 0xc1, 0xff, 0xff, 0x23, 0x42, 0xff, 0xff, 0xdf, 0xe8, 0xff, 0xff, + 0x13, 0x12, 0x00, 0x00, 0x63, 0xe5, 0xff, 0xff, 0xdf, 0xe9, 0xff, 0xff, 0xcc, + 0xc5, 0xff, 0xff, 0xfd, 0xe2, 0xff, 0xff, 0x43, 0xf5, 0xff, 0xff, 0x30, 0xf5, + 0xff, 0xff, 0x60, 0x1e, 0x00, 0x00, 0x62, 0x9f, 0xff, 0xff, 0xcb, 0x0b, 0x00, + 0x00, 0xd1, 0x5c, 0x00, 0x00, 0xe9, 0xdf, 0xff, 0xff, 0xec, 0x20, 0x00, 0x00, + 0x47, 0xfb, 0xff, 0xff, 0x94, 0x9e, 0xff, 0xff, 0x45, 0x0e, 0x00, 0x00, 0x27, + 0x0b, 0x00, 0x00, 0x26, 0xdb, 0xff, 0xff, 0xdf, 0xbb, 0xff, 0xff, 0x61, 0x51, + 0x00, 0x00, 0xd9, 0x1d, 0x00, 0x00, 0xa9, 0xb5, 0xff, 0xff, 0xb9, 0x5a, 0x00, + 0x00, 0xea, 0xd7, 0xff, 0xff, 0x02, 0xfb, 0xff, 0xff, 0x0c, 0x48, 0x00, 0x00, + 0x29, 0xea, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x00, 0xf5, 0x1a, 0x00, 0x00, 0x14, + 0x14, 0x00, 0x00, 0x22, 0x0b, 0x00, 0x00, 0xbc, 0x24, 0x00, 0x00, 0xeb, 0xda, + 0xff, 0xff, 0xed, 0xe8, 0xff, 0xff, 0x13, 0x12, 0x00, 0x00, 0xcd, 0x0a, 0x00, + 0x00, 0x8a, 0x28, 0x00, 0x00, 0x62, 0x03, 0x00, 0x00, 0xd2, 0x8f, 0xff, 0xff, + 0x0f, 0x08, 0x00, 0x00, 0x4c, 0x41, 0x00, 0x00, 0x95, 0xd9, 0xff, 0xff, 0xea, + 0xfc, 0xff, 0xff, 0x6a, 0x01, 0x00, 0x00, 0x4b, 0x95, 0xff, 0xff, 0x6e, 0x0f, + 0x00, 0x00, 0x41, 0x0f, 0x00, 0x00, 0xea, 0xfc, 0xff, 0xff, 0x55, 0xe8, 0xff, + 0xff, 0xab, 0x8a, 0xff, 0xff, 0x77, 0xa9, 0xff, 0xff, 0x6e, 0x38, 0x00, 0x00, + 0xc8, 0x1e, 0x00, 0x00, 0x31, 0xf0, 0xff, 0xff, 0x41, 0x99, 0xff, 0xff, 0x0c, + 0x0a, 0x00, 0x00, 0x51, 0xc6, 0xff, 0xff, 0xdc, 0x28, 0x00, 0x00, 0x22, 0xad, + 0xff, 0xff, 0xee, 0x2b, 0x00, 0x00, 0x99, 0xf0, 0xff, 0xff, 0x0b, 0xf2, 0xff, + 0xff, 0xba, 0x32, 0x00, 0x00, 0xc4, 0x3c, 0x00, 0x00, 0x7c, 0xb2, 0xff, 0xff, + 0xac, 0x07, 0x00, 0x00, 0x6d, 0x0d, 0x00, 0x00, 0xef, 0x15, 0x00, 0x00, 0xce, + 0xf9, 0xff, 0xff, 0x2f, 0x11, 0x00, 0x00, 0x8f, 0x10, 0x00, 0x00, 0xe2, 0x05, + 0x00, 0x00, 0xda, 0xdc, 0xff, 0xff, 0xff, 0x06, 0x00, 0x00, 0xc1, 0x10, 0x00, + 0x00, 0xc0, 0xeb, 0xff, 0xff, 0x4b, 0xe1, 0xff, 0xff, 0x72, 0xec, 0xff, 0xff, + 0xeb, 0xe4, 0xff, 0xff, 0x34, 0x31, 0x00, 0x00, 0xe0, 0xf9, 0xff, 0xff, 0x9b, + 0x23, 0x00, 0x00, 0xa3, 0xd8, 0xff, 0xff, 0xb1, 0xb6, 0xff, 0xff, 0xa7, 0xec, + 0xff, 0xff, 0x15, 0x23, 0x00, 0x00, 0xd3, 0xa3, 0xff, 0xff, 0xa2, 0xb1, 0xff, + 0xff, 0x3d, 0x29, 0x00, 0x00, 0xfb, 0xbc, 0xff, 0xff, 0x77, 0x29, 0x00, 0x00, + 0x9e, 0xeb, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x95, + 0xe3, 0x77, 0xf4, 0x7f, 0x81, 0x9d, 0xe6, 0x15, 0xa6, 0xc2, 0xba, 0xf5, 0xf3, + 0xe8, 0x03, 0xf1, 0xfb, 0x0d, 0xf2, 0x23, 0xfb, 0xef, 0x4c, 0xfd, 0xab, 0xd0, + 0x0e, 0xcf, 0xb8, 0x81, 0x84, 0xf1, 0xdf, 0xfb, 0xdb, 0xf8, 0xed, 0xe9, 0x07, + 0x2a, 0xac, 0xd3, 0xee, 0x40, 0x81, 0xc6, 0x20, 0xe7, 0xe4, 0xdd, 0x7f, 0xf8, + 0xe1, 0x24, 0x7f, 0xe7, 0x4f, 0xd3, 0x0c, 0xbc, 0x16, 0xc7, 0xc7, 0xec, 0xca, + 0xa6, 0x84, 0xae, 0xe2, 0x1d, 0x19, 0xb8, 0xe5, 0xc8, 0x89, 0xfb, 0xca, 0xf3, + 0xf9, 0xd6, 0xd1, 0xdf, 0xca, 0x2a, 0x46, 0x81, 0x2a, 0xf8, 0xc2, 0x09, 0xb0, + 0xa9, 0xf4, 0x0b, 0xb7, 0xfd, 0xdf, 0x74, 0xa9, 0xda, 0xed, 0x19, 0xba, 0xa3, + 0x01, 0xf1, 0x9e, 0xec, 0x17, 0x10, 0xf8, 0x95, 0x09, 0x20, 0xc7, 0xa0, 0xb3, + 0xc9, 0x1f, 0xd1, 0xcf, 0xe7, 0xf3, 0x7f, 0xe4, 0xcc, 0xbc, 0x81, 0xe9, 0xd9, + 0xc9, 0xf3, 0x02, 0xd3, 0x46, 0x3c, 0x81, 0xbc, 0xdf, 0xee, 0xe3, 0xdf, 0x02, + 0x23, 0xfe, 0xf8, 0xd4, 0x19, 0xd4, 0xa0, 0x7f, 0x0a, 0x0e, 0x26, 0xe4, 0x16, + 0x8b, 0x81, 0xee, 0xf8, 0xf1, 0xe8, 0xdb, 0xeb, 0x90, 0xc4, 0x2c, 0x9b, 0xf2, + 0xe9, 0x7f, 0x81, 0xb4, 0xf6, 0xaf, 0x8a, 0x51, 0xee, 0xee, 0x21, 0xe1, 0xa7, + 0xfb, 0x89, 0xd3, 0xce, 0x25, 0xcf, 0xa4, 0xb1, 0xe2, 0x6b, 0x14, 0x56, 0x81, + 0xa5, 0x20, 0xe2, 0xd1, 0xe2, 0xb6, 0x7f, 0x35, 0xff, 0xb6, 0xdd, 0x37, 0xf1, + 0x06, 0x18, 0x56, 0x02, 0xfd, 0xdd, 0xd1, 0x8c, 0x93, 0xfc, 0xee, 0xeb, 0xf8, + 0xf1, 0xbb, 0xa8, 0x2c, 0xbb, 0xdf, 0xeb, 0xf2, 0x13, 0xd8, 0xe1, 0x18, 0xfa, + 0x86, 0xd4, 0xb5, 0x81, 0xa2, 0xdb, 0xd5, 0x0a, 0xe0, 0x15, 0x2c, 0xca, 0xe9, + 0x05, 0xec, 0xc6, 0xf0, 0xa5, 0xe2, 0x0e, 0x0b, 0xed, 0x2e, 0x1e, 0xf8, 0x35, + 0xc5, 0xb3, 0x35, 0x33, 0x1f, 0xe4, 0x92, 0x2a, 0xcc, 0xf7, 0x8c, 0x02, 0x23, + 0x81, 0x0b, 0x41, 0xfa, 0x53, 0x0a, 0xfb, 0xe1, 0xd0, 0xd8, 0xf2, 0x8d, 0xc0, + 0x5d, 0xc2, 0xe0, 0x81, 0x81, 0xfd, 0x10, 0xbc, 0x1b, 0x81, 0xef, 0x38, 0x09, + 0xe8, 0x47, 0x9b, 0x35, 0x7f, 0x84, 0xcd, 0x60, 0xce, 0x81, 0x12, 0xb2, 0xa0, + 0x7f, 0xbe, 0x74, 0x7f, 0x81, 0x36, 0x25, 0x25, 0xfd, 0x92, 0x1e, 0xf9, 0xb9, + 0x1d, 0x12, 0xc7, 0xf2, 0x72, 0xfd, 0x74, 0xe0, 0x05, 0xf6, 0xad, 0xd1, 0xec, + 0xe8, 0x1c, 0x15, 0x0c, 0x1d, 0xf1, 0x81, 0xe7, 0x4a, 0x81, 0x0d, 0x0d, 0xbf, + 0xf5, 0x27, 0x0b, 0x44, 0xff, 0x19, 0x81, 0x53, 0xb8, 0x1e, 0xcb, 0x39, 0xeb, + 0x81, 0x7f, 0xfd, 0xd0, 0xd0, 0x81, 0x24, 0x7f, 0xa6, 0xf1, 0x81, 0xcb, 0x46, + 0xc7, 0x88, 0xe6, 0x81, 0x09, 0xff, 0x3c, 0x2a, 0xb1, 0x81, 0xf9, 0xe2, 0x81, + 0xa4, 0x04, 0x8f, 0xcc, 0x7f, 0xd0, 0x47, 0xf2, 0x45, 0xef, 0xd9, 0xa9, 0xec, + 0xf1, 0xc7, 0x68, 0xf4, 0xd0, 0xdf, 0xa0, 0xe1, 0xfd, 0x85, 0x6a, 0xda, 0x45, + 0x97, 0x6c, 0x7f, 0x00, 0xb0, 0x42, 0xf9, 0x7f, 0xe0, 0x16, 0xb7, 0xb1, 0xe7, + 0x89, 0x1e, 0x0a, 0x81, 0x20, 0x08, 0x81, 0xdd, 0x32, 0x3a, 0x9c, 0x03, 0x7f, + 0x08, 0xfb, 0xd2, 0x81, 0x10, 0xfa, 0x1c, 0xa0, 0x9b, 0x81, 0x3a, 0xd7, 0xb5, + 0x43, 0x73, 0x90, 0x36, 0x53, 0x88, 0x15, 0x9d, 0x9b, 0xdf, 0xc3, 0x7f, 0x8e, + 0x42, 0xdf, 0x1e, 0xf0, 0x37, 0x81, 0x60, 0xdc, 0x2f, 0xc5, 0x0e, 0x22, 0x2e, + 0x1b, 0xa9, 0x06, 0x01, 0xd9, 0xbd, 0xf7, 0x7f, 0x7f, 0x81, 0xef, 0x81, 0xc8, + 0x81, 0x06, 0xb1, 0xcb, 0x81, 0xf7, 0x14, 0x4b, 0x0e, 0x11, 0xe4, 0xdb, 0xf4, + 0x34, 0xb9, 0x91, 0xda, 0x0e, 0x30, 0x7f, 0x06, 0x37, 0x41, 0xe4, 0x7f, 0x7e, + 0x7f, 0xe3, 0x81, 0xe2, 0xb8, 0x04, 0x25, 0x7b, 0x00, 0x1d, 0x74, 0xb6, 0x0f, + 0x40, 0xbb, 0xcb, 0xa5, 0x81, 0xc0, 0xef, 0x0e, 0x28, 0x27, 0xdb, 0x56, 0xdd, + 0x2e, 0xd9, 0xed, 0x4b, 0xec, 0x20, 0x5e, 0x32, 0x1f, 0xc3, 0xd6, 0xb1, 0xe4, + 0x3f, 0xe6, 0xff, 0x1c, 0xd6, 0xbc, 0x12, 0xe8, 0x81, 0x20, 0x11, 0x7f, 0x42, + 0x42, 0x3f, 0x08, 0x81, 0x97, 0xd0, 0x7f, 0x81, 0xeb, 0x58, 0xda, 0x57, 0x1d, + 0x08, 0x81, 0x38, 0x81, 0xef, 0xe1, 0x03, 0xa3, 0x32, 0x14, 0x90, 0xf8, 0x48, + 0xe3, 0x09, 0xb1, 0xd1, 0x10, 0x22, 0x26, 0x89, 0xe3, 0x15, 0xc9, 0x08, 0x44, + 0xc1, 0x9f, 0xde, 0x7f, 0xec, 0x7f, 0xdf, 0xfe, 0xf4, 0x21, 0x6e, 0x05, 0xe6, + 0xf1, 0xda, 0x7f, 0xb4, 0x56, 0x47, 0xe7, 0x9d, 0x7f, 0x91, 0x67, 0x03, 0xc2, + 0xed, 0x01, 0xe2, 0xee, 0x81, 0xcc, 0xea, 0xed, 0x8b, 0xbb, 0xad, 0xcf, 0x98, + 0x1d, 0xe1, 0xfa, 0xf4, 0x01, 0x7f, 0x00, 0x7f, 0x6b, 0xc7, 0xfb, 0x7f, 0x97, + 0x16, 0xd8, 0x19, 0x10, 0xf8, 0x60, 0x4d, 0xb2, 0x8c, 0xe6, 0x32, 0x2d, 0x18, + 0x25, 0xc9, 0xa2, 0x7d, 0x61, 0x7f, 0x3d, 0x0d, 0xd8, 0xcd, 0xe6, 0x11, 0x0c, + 0x17, 0xd4, 0x4d, 0xde, 0xf9, 0x79, 0x49, 0x7f, 0xec, 0x81, 0xc4, 0xb0, 0xca, + 0xfd, 0xc2, 0x63, 0xa0, 0xf5, 0xbe, 0x43, 0x12, 0x45, 0xc6, 0x7f, 0xb2, 0x7f, + 0xe6, 0x94, 0x24, 0x1c, 0xda, 0x1b, 0x5a, 0xa8, 0x2d, 0x1d, 0x35, 0xde, 0x36, + 0x4a, 0x0f, 0x22, 0x11, 0xc5, 0x7e, 0xff, 0x5c, 0xbb, 0xd3, 0xa8, 0xd9, 0xb4, + 0x09, 0xdc, 0xbf, 0xed, 0x23, 0xdd, 0xd1, 0xdd, 0x0a, 0x1c, 0x05, 0x81, 0x91, + 0xd3, 0xd0, 0xa3, 0x33, 0xe4, 0x0e, 0x0c, 0x81, 0x15, 0x89, 0xd7, 0x81, 0x39, + 0x0c, 0x3f, 0xef, 0xff, 0xcc, 0xe8, 0x78, 0x48, 0x5c, 0xec, 0x2c, 0x78, 0xed, + 0x7f, 0x7f, 0xd2, 0xca, 0x34, 0xfe, 0x10, 0x9d, 0xcd, 0x0a, 0xb0, 0xed, 0xa3, + 0x86, 0xe5, 0x51, 0x81, 0xa6, 0x0c, 0x46, 0x35, 0x57, 0x88, 0xed, 0x81, 0xb8, + 0xfb, 0x13, 0xa7, 0x2b, 0x2e, 0x0c, 0xae, 0x7f, 0x81, 0x81, 0x7f, 0x7f, 0xed, + 0x84, 0xd9, 0x0f, 0xb2, 0x76, 0x00, 0xc9, 0x19, 0xdb, 0xf1, 0xf1, 0xf2, 0x41, + 0x27, 0x7f, 0x0c, 0x15, 0xfa, 0x36, 0x29, 0x92, 0x1f, 0xe5, 0x19, 0x7f, 0x33, + 0x7f, 0x7f, 0x81, 0x3a, 0x55, 0x8e, 0xa9, 0x7f, 0x25, 0xaa, 0xde, 0x25, 0xa7, + 0xaa, 0x58, 0x00, 0x20, 0x41, 0x0d, 0x08, 0x81, 0x1e, 0x7f, 0xe2, 0xb8, 0xc9, + 0x35, 0xca, 0xb9, 0xa6, 0x31, 0x66, 0x25, 0xdc, 0x54, 0xbc, 0x63, 0x35, 0xa7, + 0xe1, 0x0c, 0xc6, 0xbf, 0xee, 0xd8, 0xb7, 0xe2, 0x0d, 0xf5, 0xe5, 0x00, 0x28, + 0x72, 0x6f, 0xd9, 0xdb, 0xf6, 0x54, 0xe2, 0x8a, 0xe8, 0x0a, 0x70, 0x16, 0xdc, + 0x60, 0xb8, 0xe0, 0x25, 0x73, 0x7f, 0x2c, 0xe6, 0xf3, 0xbd, 0x7f, 0x7f, 0x1e, + 0xcb, 0xc5, 0xdc, 0xdf, 0xaa, 0x1e, 0x69, 0x72, 0xdb, 0x9e, 0xc8, 0xf2, 0xc5, + 0x1e, 0xf0, 0x6e, 0x5c, 0x98, 0x03, 0x54, 0x30, 0x41, 0x7f, 0x7f, 0xe8, 0xc2, + 0x81, 0x32, 0x81, 0xcc, 0xea, 0xf7, 0xb6, 0x7f, 0x04, 0x03, 0x02, 0x83, 0x28, + 0x62, 0x22, 0xd1, 0xbe, 0xd9, 0xf1, 0xfb, 0x5c, 0x3b, 0x81, 0x60, 0x3e, 0x81, + 0xdd, 0xde, 0x7f, 0xe4, 0xa6, 0xe0, 0x54, 0xdc, 0x7f, 0xd7, 0x2b, 0x6d, 0x1b, + 0x7f, 0x81, 0x33, 0xad, 0x7f, 0x9b, 0x83, 0x7f, 0xdc, 0x7f, 0x4c, 0x4b, 0x04, + 0x01, 0x49, 0xef, 0xe5, 0xfe, 0xbf, 0xfc, 0xa5, 0x2f, 0x08, 0x5e, 0xa2, 0xb8, + 0x7f, 0x61, 0x7f, 0xbd, 0x65, 0x0f, 0x7f, 0x3b, 0xd9, 0x53, 0x2d, 0xd8, 0x7f, + 0x89, 0xdf, 0x34, 0x3f, 0x51, 0x0a, 0x7f, 0xb7, 0x68, 0xd3, 0x2a, 0x7f, 0x7f, + 0x38, 0xa5, 0xf4, 0xff, 0x7f, 0x7f, 0xb2, 0x7f, 0xaa, 0xe1, 0x81, 0xfc, 0xe4, + 0x92, 0x7f, 0x7f, 0x7f, 0x0e, 0x38, 0x71, 0xb0, 0x7f, 0x81, 0x98, 0xbe, 0x7f, + 0x7f, 0x81, 0xef, 0xee, 0x1f, 0xf8, 0x3f, 0x4e, 0x14, 0x1d, 0x31, 0x81, 0x9c, + 0xe3, 0xa9, 0xc2, 0x7d, 0x6d, 0x00, 0x28, 0x04, 0x06, 0xc3, 0xb8, 0xeb, 0x53, + 0x12, 0x65, 0x81, 0xdd, 0x7f, 0xe9, 0xaf, 0x75, 0xbb, 0x2e, 0x55, 0xf8, 0x1d, + 0xdd, 0x7f, 0x81, 0x2f, 0xbe, 0x81, 0x64, 0x0f, 0x81, 0x7f, 0x0f, 0x14, 0xc1, + 0x7f, 0x6b, 0x7f, 0xb3, 0x15, 0x10, 0x54, 0xf8, 0x1d, 0x6f, 0xce, 0xa2, 0x81, + 0x33, 0x10, 0x79, 0x77, 0x1a, 0x7f, 0x10, 0x51, 0xd2, 0xd9, 0x38, 0xe8, 0xfc, + 0x35, 0x09, 0x5b, 0xc8, 0x20, 0x7f, 0x7f, 0x33, 0x72, 0xd2, 0xaf, 0x4c, 0x7f, + 0x3f, 0x81, 0x81, 0xa8, 0x71, 0xd5, 0x7f, 0x57, 0x10, 0x43, 0xce, 0x7f, 0xe1, + 0xf3, 0x10, 0xf3, 0xf9, 0xab, 0xd9, 0xdf, 0xa4, 0x7f, 0x76, 0x1a, 0xe4, 0x7f, + 0xac, 0xb8, 0x7f, 0x0b, 0x7f, 0xb0, 0x7f, 0x81, 0x17, 0x9f, 0xf5, 0x9a, 0xd4, + 0x4f, 0x66, 0xea, 0x7f, 0x97, 0x0f, 0x16, 0xdf, 0x52, 0xd3, 0x7f, 0xf0, 0x0f, + 0x20, 0xee, 0x00, 0x23, 0x50, 0x2d, 0x19, 0x48, 0xbd, 0xf2, 0x13, 0x81, 0xdb, + 0x81, 0x51, 0xfe, 0x1e, 0x17, 0x1d, 0x28, 0x7f, 0xd1, 0x11, 0x3d, 0x73, 0x90, + 0xdf, 0x7f, 0x4a, 0x2f, 0x35, 0x0c, 0x97, 0x7f, 0x7f, 0x13, 0xad, 0xdf, 0x86, + 0x14, 0x29, 0xbb, 0x19, 0x7f, 0x05, 0x23, 0x20, 0xfb, 0xf5, 0x10, 0x7f, 0xa5, + 0xfe, 0xf7, 0x1b, 0xfd, 0x0e, 0xbb, 0x20, 0xac, 0x81, 0x00, 0x14, 0x26, 0xd0, + 0x7f, 0x7f, 0x06, 0x16, 0xd3, 0xfe, 0x7f, 0xd6, 0x6c, 0x99, 0xba, 0x0d, 0xf7, + 0x13, 0x39, 0x30, 0xb7, 0x7f, 0xaf, 0x1a, 0x30, 0x59, 0x78, 0x0d, 0x7d, 0x4a, + 0x67, 0xfc, 0x45, 0x32, 0x40, 0xea, 0xd5, 0xf2, 0xf6, 0xa0, 0x75, 0xe0, 0x03, + 0xc8, 0x43, 0xe7, 0x23, 0xee, 0x4e, 0x09, 0x39, 0x45, 0x18, 0xc8, 0xd9, 0x40, + 0xe7, 0xde, 0xe3, 0x03, 0xcf, 0xf8, 0xcb, 0x08, 0x37, 0xc6, 0xc7, 0x7f, 0x19, + 0x6c, 0x0e, 0x7f, 0x17, 0xc1, 0xf8, 0x21, 0xc3, 0xaf, 0x7f, 0x7f, 0xa9, 0x7f, + 0x24, 0x81, 0x40, 0x16, 0x1e, 0x0e, 0x63, 0x56, 0x08, 0xee, 0x52, 0xb4, 0xf3, + 0xf2, 0xb1, 0x44, 0x07, 0xe8, 0x4d, 0xf7, 0x7f, 0xe9, 0xed, 0x7f, 0x1b, 0xcc, + 0x09, 0x0f, 0x7f, 0xc7, 0x15, 0x81, 0x1c, 0x81, 0xa6, 0x37, 0x22, 0x98, 0x7f, + 0x7f, 0x56, 0xca, 0x72, 0xf8, 0x81, 0xab, 0x3a, 0xf5, 0x3b, 0x07, 0xe5, 0xd2, + 0x2b, 0xf6, 0xaf, 0x23, 0x0d, 0x89, 0x7c, 0x7f, 0x77, 0x7c, 0xb7, 0xae, 0x4b, + 0x81, 0x4e, 0xda, 0x7f, 0x4b, 0x42, 0xd3, 0x05, 0x2d, 0x25, 0xf5, 0xdc, 0x4c, + 0x06, 0x7f, 0x0d, 0x5b, 0x20, 0x7f, 0xad, 0x84, 0x06, 0x9b, 0xd6, 0x6e, 0x05, + 0x58, 0x06, 0xeb, 0xe6, 0xa9, 0xd2, 0x01, 0xce, 0xcb, 0x81, 0x7f, 0xb7, 0x89, + 0xd3, 0x0d, 0x36, 0x19, 0xd7, 0x90, 0x55, 0xb2, 0x13, 0xd0, 0x2a, 0x81, 0xe9, + 0xeb, 0x78, 0x31, 0x1b, 0xc2, 0xf5, 0x0f, 0x40, 0xa1, 0x0e, 0x81, 0xd7, 0xeb, + 0xfd, 0xf6, 0x3d, 0xf8, 0xde, 0xdd, 0x7f, 0xb1, 0xff, 0x7f, 0x06, 0x81, 0x7f, + 0xd7, 0x54, 0xfc, 0x38, 0x3d, 0xd4, 0x41, 0xdb, 0xf9, 0xce, 0x64, 0xcf, 0xfd, + 0x6c, 0xd9, 0x81, 0xcd, 0xa5, 0x0a, 0xd0, 0xf7, 0xf6, 0x90, 0x60, 0x7f, 0xfa, + 0xa6, 0x0f, 0xf1, 0x7f, 0xf9, 0xc6, 0x37, 0xd3, 0x25, 0x0b, 0x4a, 0x0d, 0xae, + 0x81, 0x0f, 0x47, 0xf5, 0x38, 0xe7, 0x48, 0x38, 0xae, 0x7f, 0x0d, 0xef, 0x1b, + 0xcd, 0xbc, 0xfd, 0x35, 0xfd, 0x41, 0x20, 0xc9, 0x81, 0x15, 0xe6, 0xfe, 0x08, + 0x25, 0x23, 0x14, 0x7f, 0xb8, 0x1c, 0xf7, 0x6c, 0xf2, 0xe0, 0x1f, 0xca, 0x97, + 0xe6, 0x0d, 0x41, 0xfb, 0x28, 0x57, 0x9d, 0xa0, 0xfe, 0x07, 0xe3, 0x0f, 0xeb, + 0x11, 0x69, 0x3e, 0x0e, 0xf1, 0xcb, 0x1d, 0xef, 0xd2, 0xd3, 0x7f, 0x52, 0x7f, + 0x56, 0x71, 0xdc, 0x4d, 0xf3, 0x22, 0xf5, 0xb0, 0x0f, 0x2c, 0x0a, 0x9d, 0x65, + 0x5d, 0xff, 0x09, 0xde, 0x7f, 0xe1, 0xc2, 0x48, 0xd2, 0x02, 0x0f, 0xfe, 0xe7, + 0xf0, 0xfe, 0xd4, 0x10, 0x3d, 0xd9, 0x0f, 0xdf, 0x4b, 0x97, 0x32, 0xcf, 0xc3, + 0xc2, 0xb2, 0xe8, 0x27, 0xb5, 0x7f, 0xea, 0x05, 0xf3, 0xee, 0x10, 0x71, 0xa7, + 0xa9, 0x1b, 0x7f, 0x93, 0xc4, 0x12, 0x95, 0xb0, 0xe2, 0xd1, 0x10, 0x8e, 0xb7, + 0x7f, 0x43, 0xc0, 0x01, 0xba, 0xf4, 0x2a, 0xa5, 0xd8, 0x4f, 0xc1, 0xc6, 0xf9, + 0x1a, 0xc1, 0xc9, 0xb6, 0x16, 0xd9, 0x2d, 0x7f, 0xcb, 0xd0, 0x52, 0xbc, 0x3a, + 0x2a, 0xe3, 0x23, 0xd0, 0xcd, 0x43, 0x04, 0xc8, 0x2f, 0xf7, 0x50, 0x20, 0x53, + 0x11, 0xc9, 0xfe, 0x04, 0xf8, 0xd0, 0x09, 0x81, 0xbf, 0xaf, 0x12, 0x53, 0x1f, + 0xda, 0x4a, 0xf4, 0xfa, 0x0f, 0x0f, 0x18, 0xd6, 0x50, 0xc9, 0x2b, 0x7f, 0xfe, + 0x85, 0x58, 0x67, 0x1b, 0x7f, 0xfd, 0xf1, 0x05, 0x9f, 0x7f, 0x29, 0x4c, 0x2b, + 0xde, 0x4d, 0xe4, 0x17, 0x32, 0xd2, 0xee, 0x7b, 0xe8, 0x28, 0x81, 0x24, 0x6f, + 0x16, 0x2d, 0x21, 0xb6, 0x11, 0xa9, 0xd2, 0xaf, 0xc0, 0xed, 0xf4, 0x05, 0x7f, + 0xaf, 0x06, 0x2b, 0xb9, 0xb8, 0x38, 0xad, 0x13, 0xf8, 0xfb, 0xeb, 0x81, 0x1e, + 0xca, 0x5b, 0x4b, 0x09, 0x39, 0x01, 0x6d, 0xd9, 0x32, 0xfe, 0x81, 0xec, 0xf8, + 0x36, 0xaf, 0xe4, 0x7f, 0xe8, 0xa3, 0xc1, 0x08, 0xad, 0x43, 0xd7, 0xf1, 0xf7, + 0xde, 0x40, 0x00, 0x81, 0x46, 0xa5, 0xac, 0x8f, 0x1f, 0xc9, 0x5c, 0xe2, 0xe6, + 0xf8, 0xf9, 0xf9, 0x6e, 0x1f, 0x89, 0x52, 0x7f, 0xb9, 0xeb, 0xbd, 0x0d, 0xe7, + 0x0e, 0x0e, 0xfc, 0xe9, 0x95, 0x43, 0x16, 0x2a, 0x24, 0xed, 0x7f, 0x25, 0xf4, + 0x09, 0x49, 0x08, 0x30, 0x70, 0xf0, 0x84, 0x5b, 0x35, 0xa8, 0x81, 0x7e, 0x95, + 0x1d, 0xcd, 0xbb, 0xfd, 0xcf, 0x24, 0xd4, 0xe0, 0xff, 0x57, 0x17, 0xfc, 0xd2, + 0x0f, 0x81, 0xbf, 0x8c, 0xef, 0xbe, 0x6a, 0x7f, 0x61, 0xcb, 0xe6, 0x2e, 0xf3, + 0x2a, 0xb9, 0x22, 0xef, 0x4d, 0x81, 0x0a, 0xee, 0x1e, 0x9d, 0xc9, 0xcb, 0x2e, + 0xe5, 0x0c, 0xee, 0xd7, 0xe6, 0x13, 0x43, 0x7c, 0x1f, 0x00, 0x09, 0x22, 0x28, + 0x07, 0xd4, 0x81, 0x81, 0xd0, 0xad, 0xf3, 0xd9, 0xec, 0x61, 0xa0, 0xab, 0x1d, + 0xd6, 0x43, 0xe3, 0xe9, 0xd7, 0x29, 0xd1, 0xc2, 0xeb, 0xf4, 0x81, 0xdf, 0xf9, + 0x0e, 0x81, 0x11, 0x0d, 0xe4, 0x81, 0xff, 0xfb, 0xe2, 0xd5, 0x2a, 0x5d, 0x5d, + 0x0c, 0xef, 0x99, 0x1e, 0x46, 0xd8, 0x81, 0xb1, 0xfb, 0x48, 0x22, 0xd8, 0xf3, + 0xf0, 0x00, 0xb2, 0xb1, 0xf3, 0xcf, 0xe5, 0xc8, 0x8d, 0x26, 0xba, 0xe9, 0xa2, + 0xba, 0xe0, 0x43, 0xce, 0xb4, 0xfb, 0x7f, 0x7f, 0x81, 0xc1, 0x06, 0x2f, 0x41, + 0x59, 0xe5, 0x17, 0x00, 0x2b, 0x46, 0xc1, 0x7f, 0x09, 0x5c, 0x11, 0xe9, 0x1e, + 0x0f, 0xab, 0xf9, 0x2b, 0x21, 0x59, 0x35, 0xf5, 0x36, 0xc8, 0x1a, 0xb3, 0x81, + 0x81, 0xb3, 0x81, 0x81, 0xbe, 0xdd, 0xce, 0xe1, 0x25, 0x16, 0xfd, 0x22, 0xe6, + 0x91, 0x4f, 0x2d, 0x05, 0xdd, 0x9b, 0xf0, 0xdd, 0xf4, 0x1b, 0x0f, 0xe7, 0x02, + 0x41, 0x19, 0x75, 0xce, 0xb0, 0x97, 0x16, 0x63, 0xe2, 0x36, 0x9a, 0xf4, 0xf6, + 0xb8, 0x75, 0x16, 0x14, 0x1e, 0xfe, 0xcc, 0xcb, 0xd7, 0x42, 0x7f, 0x20, 0xdf, + 0x1f, 0x2a, 0x1f, 0x81, 0x51, 0x7f, 0xec, 0x2e, 0xdf, 0xf0, 0x16, 0xb3, 0x28, + 0x75, 0x40, 0x9f, 0x3a, 0x58, 0x0c, 0x2f, 0x56, 0x81, 0xe7, 0xe5, 0x3e, 0xbe, + 0xdb, 0xfc, 0x09, 0x22, 0xf4, 0xf1, 0x72, 0x0c, 0xf2, 0x8d, 0x32, 0xc2, 0xb8, + 0xbb, 0x9c, 0xd8, 0xa0, 0xf0, 0x10, 0x16, 0xf5, 0xd0, 0x9b, 0x7f, 0xda, 0x14, + 0xce, 0x13, 0xcd, 0xed, 0xc3, 0x5d, 0x1e, 0xf6, 0x13, 0xdb, 0xf0, 0xdb, 0xde, + 0x18, 0xfa, 0x24, 0x5a, 0xe8, 0x3f, 0xee, 0xb1, 0x0c, 0x81, 0x41, 0xea, 0x4a, + 0x4c, 0xe9, 0x1c, 0xff, 0x29, 0xf5, 0xa7, 0xaf, 0xbf, 0xe7, 0xe3, 0xbf, 0x04, + 0x23, 0xd8, 0x23, 0xba, 0xc8, 0xda, 0x31, 0xac, 0x5d, 0x7f, 0x28, 0xcf, 0xb8, + 0x07, 0xf2, 0xfa, 0x91, 0x2b, 0xd0, 0x36, 0xb2, 0x6c, 0x54, 0xce, 0xf4, 0x32, + 0xc8, 0x88, 0x07, 0xe3, 0x07, 0x7f, 0xc0, 0xd6, 0x1d, 0x40, 0x14, 0xcf, 0xf6, + 0xec, 0x97, 0xf7, 0xc5, 0x0f, 0xe1, 0x0e, 0x81, 0xcd, 0xbc, 0x7f, 0x7f, 0xdd, + 0x18, 0x52, 0xa3, 0xe7, 0xba, 0xf1, 0x81, 0x21, 0x18, 0xbb, 0xbd, 0xf6, 0x20, + 0xed, 0x0a, 0x06, 0x04, 0xbb, 0x7f, 0x15, 0xf5, 0xa0, 0x23, 0x2e, 0x3d, 0xdf, + 0x1e, 0xba, 0x4a, 0x5e, 0x40, 0x81, 0x10, 0x10, 0x2d, 0x24, 0xf4, 0x23, 0x29, + 0x85, 0x60, 0xd0, 0x79, 0x19, 0xc9, 0x81, 0x4a, 0x36, 0x3a, 0xf3, 0x5f, 0xaa, + 0xf7, 0xd7, 0xb9, 0x31, 0xca, 0xb9, 0xee, 0xe1, 0x55, 0xed, 0x13, 0xc2, 0x6d, + 0x0a, 0x0d, 0xee, 0xe3, 0xcd, 0x9f, 0x12, 0xa3, 0xd0, 0x28, 0xc3, 0x29, 0x27, + 0xbc, 0x81, 0xbd, 0xd4, 0x4c, 0xf1, 0xe6, 0x7f, 0xc2, 0x34, 0xf5, 0xda, 0xbb, + 0x05, 0xe1, 0xaa, 0xf4, 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x4d, 0x01, 0x00, 0x00, 0x79, 0xed, 0xff, 0xff, 0xca, 0xfe, 0xff, 0xff, + 0x59, 0xf6, 0xff, 0xff, 0xc4, 0x12, 0x00, 0x00, 0xf6, 0x08, 0x00, 0x00, 0x87, + 0xf9, 0xff, 0xff, 0x54, 0xf8, 0xff, 0xff, 0x99, 0xeb, 0xff, 0xff, 0x08, 0xfd, + 0xff, 0xff, 0x78, 0xf8, 0xff, 0xff, 0xa9, 0x0a, 0x00, 0x00, 0xf6, 0xf3, 0xff, + 0xff, 0xaa, 0x06, 0x00, 0x00, 0x1e, 0xf9, 0xff, 0xff, 0x54, 0xfd, 0xff, 0xff, + 0x55, 0xf5, 0xff, 0xff, 0x0b, 0xed, 0xff, 0xff, 0x00, 0x09, 0x00, 0x00, 0xa0, + 0xfe, 0xff, 0xff, 0x26, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0x4b, 0xf5, + 0xff, 0xff, 0xa6, 0x0d, 0x00, 0x00, 0x49, 0xf8, 0xff, 0xff, 0xef, 0x09, 0x00, + 0x00, 0x42, 0x0b, 0x00, 0x00, 0x1f, 0x0a, 0x00, 0x00, 0xb6, 0xfc, 0xff, 0xff, + 0x5e, 0x12, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x5d, 0xf5, 0xff, 0xff, 0x5f, + 0xf4, 0xff, 0xff, 0x81, 0xf5, 0xff, 0xff, 0xec, 0x07, 0x00, 0x00, 0x86, 0x06, + 0x00, 0x00, 0x1f, 0xfb, 0xff, 0xff, 0x94, 0x0d, 0x00, 0x00, 0x0d, 0xfe, 0xff, + 0xff, 0x7f, 0x04, 0x00, 0x00, 0x48, 0x04, 0x00, 0x00, 0xdb, 0x0d, 0x00, 0x00, + 0xad, 0xef, 0xff, 0xff, 0xc9, 0xf1, 0xff, 0xff, 0x9e, 0x0b, 0x00, 0x00, 0x30, + 0x0c, 0x00, 0x00, 0x0c, 0x07, 0x00, 0x00, 0x51, 0xfe, 0xff, 0xff, 0x76, 0xfe, + 0xff, 0xff, 0x12, 0xfd, 0xff, 0xff, 0x1c, 0xf9, 0xff, 0xff, 0x44, 0xf8, 0xff, + 0xff, 0xdf, 0xf9, 0xff, 0xff, 0x12, 0x07, 0x00, 0x00, 0x6c, 0x03, 0x00, 0x00, + 0xbf, 0x07, 0x00, 0x00, 0x15, 0x07, 0x00, 0x00, 0x81, 0xf9, 0xff, 0xff, 0xd3, + 0x07, 0x00, 0x00, 0xd5, 0xee, 0xff, 0xff, 0xb3, 0xfb, 0xff, 0xff, 0x80, 0x05, + 0x00, 0x00, 0xb4, 0xf6, 0xff, 0xff, 0xe6, 0xf9, 0xff, 0xff, 0xe5, 0x03, 0x00, + 0x00, 0xc2, 0x07, 0x00, 0x00, 0xbc, 0x05, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, + 0xc9, 0x04, 0x00, 0x00, 0xfb, 0xfc, 0xff, 0xff, 0x8e, 0xee, 0xff, 0xff, 0x1c, + 0x0a, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0xfa, 0xf4, 0xff, 0xff, 0xb5, 0x06, + 0x00, 0x00, 0x65, 0x0d, 0x00, 0x00, 0x82, 0xe8, 0xff, 0xff, 0x20, 0x03, 0x00, + 0x00, 0x2a, 0xf7, 0xff, 0xff, 0x60, 0xf3, 0xff, 0xff, 0xaf, 0x09, 0x00, 0x00, + 0xcd, 0xfb, 0xff, 0xff, 0x43, 0x05, 0x00, 0x00, 0x77, 0x04, 0x00, 0x00, 0x70, + 0x0c, 0x00, 0x00, 0x85, 0xf3, 0xff, 0xff, 0x78, 0x05, 0x00, 0x00, 0x62, 0x06, + 0x00, 0x00, 0x8b, 0xf8, 0xff, 0xff, 0xd1, 0x06, 0x00, 0x00, 0x1b, 0x0f, 0x00, + 0x00, 0x16, 0xfb, 0xff, 0xff, 0x22, 0x06, 0x00, 0x00, 0x1b, 0xf8, 0xff, 0xff, + 0x7a, 0x08, 0x00, 0x00, 0xee, 0xff, 0xff, 0xff, 0xe4, 0xf4, 0xff, 0xff, 0xc0, + 0xf7, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, 0x5b, 0x05, 0x00, 0x00, 0xed, 0xf7, + 0xff, 0xff, 0x4f, 0xfc, 0xff, 0xff, 0x31, 0x09, 0x00, 0x00, 0x78, 0x03, 0x00, + 0x00, 0x5c, 0x09, 0x00, 0x00, 0x1d, 0x03, 0x00, 0x00, 0x9b, 0x0d, 0x00, 0x00, + 0xeb, 0x12, 0x00, 0x00, 0xdd, 0xf8, 0xff, 0xff, 0x4b, 0xff, 0xff, 0xff, 0xe7, + 0xee, 0xff, 0xff, 0xf4, 0xf7, 0xff, 0xff, 0x40, 0xfe, 0xff, 0xff, 0xc6, 0xfa, + 0xff, 0xff, 0x2e, 0xfa, 0xff, 0xff, 0x1b, 0xf1, 0xff, 0xff, 0x72, 0x07, 0x00, + 0x00, 0xb3, 0x09, 0x00, 0x00, 0x77, 0xfc, 0xff, 0xff, 0x35, 0x08, 0x00, 0x00, + 0x47, 0x06, 0x00, 0x00, 0x2b, 0xf9, 0xff, 0xff, 0x4e, 0x0f, 0x00, 0x00, 0x78, + 0x0a, 0x00, 0x00, 0xf9, 0x03, 0x00, 0x00, 0x76, 0x0a, 0x00, 0x00, 0xa6, 0xfc, + 0xff, 0xff, 0xfa, 0x03, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xee, 0xff, + 0xff, 0x86, 0x0b, 0x00, 0x00, 0xba, 0x09, 0x00, 0x00, 0x40, 0xfb, 0xff, 0xff, + 0x11, 0xfc, 0xff, 0xff, 0x17, 0x06, 0x00, 0x00, 0xf2, 0x08, 0x00, 0x00, 0x52, + 0x0e, 0x00, 0x00, 0xe3, 0x18, 0x00, 0x00, 0x92, 0x05, 0x00, 0x00, 0x90, 0xfb, + 0xff, 0xff, 0xc9, 0xff, 0xff, 0xff, 0x6c, 0xf4, 0xff, 0xff, 0x8e, 0xfe, 0xff, + 0xff, 0x44, 0xf9, 0xff, 0xff, 0xe7, 0x05, 0x00, 0x00, 0xb1, 0xfc, 0xff, 0xff, + 0x7e, 0xfb, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xbe, 0xfa, 0xff, 0xff, 0x00, + 0x02, 0x00, 0x00, 0xf3, 0xfd, 0xff, 0xff, 0x0a, 0x0f, 0x00, 0x00, 0xca, 0xfc, + 0xff, 0xff, 0x10, 0x03, 0x00, 0x00, 0x6f, 0xfd, 0xff, 0xff, 0x0f, 0xf9, 0xff, + 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x32, 0x0a, 0x00, 0x00, 0x70, 0x03, 0x00, 0x00, + 0x74, 0xff, 0xff, 0xff, 0x8d, 0x09, 0x00, 0x00, 0x7b, 0x0a, 0x00, 0x00, 0x20, + 0xe9, 0xff, 0xff, 0x2b, 0xef, 0xff, 0xff, 0x82, 0xfa, 0xff, 0xff, 0xeb, 0x12, + 0x00, 0x00, 0xd2, 0xfc, 0xff, 0xff, 0x88, 0x08, 0x00, 0x00, 0xd6, 0xfa, 0xff, + 0xff, 0x3a, 0x08, 0x00, 0x00, 0x8d, 0xfe, 0xff, 0xff, 0xbd, 0x01, 0x00, 0x00, + 0x51, 0x09, 0x00, 0x00, 0x98, 0x0b, 0x00, 0x00, 0x40, 0xfe, 0xff, 0xff, 0x66, + 0x09, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x20, 0x0c, 0x00, 0x00, 0x9b, 0xf8, + 0xff, 0xff, 0x6c, 0xf8, 0xff, 0xff, 0x6d, 0x08, 0x00, 0x00, 0x5c, 0x00, 0x00, + 0x00, 0xb7, 0x0c, 0x00, 0x00, 0x88, 0xeb, 0xff, 0xff, 0xe2, 0x12, 0x00, 0x00, + 0xa7, 0x01, 0x00, 0x00, 0xf0, 0xfb, 0xff, 0xff, 0xfc, 0xfb, 0xff, 0xff, 0x29, + 0x0e, 0x00, 0x00, 0x89, 0xff, 0xff, 0xff, 0xef, 0x09, 0x00, 0x00, 0xdb, 0xf5, + 0xff, 0xff, 0xba, 0xec, 0xff, 0xff, 0xc1, 0x01, 0x00, 0x00, 0x5a, 0x12, 0x00, + 0x00, 0xc6, 0x04, 0x00, 0x00, 0x26, 0x06, 0x00, 0x00, 0x85, 0xfb, 0xff, 0xff, + 0xf6, 0x05, 0x00, 0x00, 0x98, 0x0d, 0x00, 0x00, 0x15, 0xfe, 0xff, 0xff, 0xc3, + 0xfc, 0xff, 0xff, 0xa9, 0xff, 0xff, 0xff, 0x9d, 0xe8, 0xff, 0xff, 0x22, 0x03, + 0x00, 0x00, 0x77, 0xf8, 0xff, 0xff, 0x3b, 0xf3, 0xff, 0xff, 0x0c, 0x0b, 0x00, + 0x00, 0x48, 0x07, 0x00, 0x00, 0x20, 0xfc, 0xff, 0xff, 0xcd, 0xf0, 0xff, 0xff, + 0x0b, 0x01, 0x00, 0x00, 0xb4, 0x04, 0x00, 0x00, 0xb8, 0xf3, 0xff, 0xff, 0x65, + 0xfa, 0xff, 0xff, 0x14, 0xfd, 0xff, 0xff, 0x8f, 0xf8, 0xff, 0xff, 0x02, 0x02, + 0x00, 0x00, 0x76, 0x0a, 0x00, 0x00, 0xc9, 0xeb, 0xff, 0xff, 0x2f, 0xf9, 0xff, + 0xff, 0xd3, 0xf6, 0xff, 0xff, 0xe9, 0x0b, 0x00, 0x00, 0x6e, 0x06, 0x00, 0x00, + 0x04, 0x12, 0x00, 0x00, 0x8c, 0xfc, 0xff, 0xff, 0xa1, 0x09, 0x00, 0x00, 0x8f, + 0x13, 0x00, 0x00, 0xc1, 0xff, 0xff, 0xff, 0x7f, 0xfa, 0xff, 0xff, 0x26, 0xff, + 0xff, 0xff, 0x99, 0x05, 0x00, 0x00, 0x81, 0xf9, 0xff, 0xff, 0x40, 0x00, 0x00, + 0x00, 0xf5, 0xf9, 0xff, 0xff, 0x6f, 0x06, 0x00, 0x00, 0xbf, 0xff, 0xff, 0xff, + 0x86, 0x14, 0x00, 0x00, 0xde, 0x09, 0x00, 0x00, 0xed, 0x08, 0x00, 0x00, 0xc3, + 0xf8, 0xff, 0xff, 0x97, 0x11, 0x00, 0x00, 0x2c, 0x0e, 0x00, 0x00, 0xe1, 0x0e, + 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1a, 0x0b, 0x00, + 0x00, 0xef, 0xf8, 0xff, 0xff, 0x6b, 0xf2, 0xff, 0xff, 0x84, 0xfa, 0xff, 0xff, + 0xf4, 0x03, 0x00, 0x00, 0xa0, 0xf2, 0xff, 0xff, 0x09, 0xf4, 0xff, 0xff, 0xe5, + 0x01, 0x00, 0x00, 0xcf, 0x07, 0x00, 0x00, 0x03, 0x0b, 0x00, 0x00, 0xb6, 0xf8, + 0xfe, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x26, 0xe0, 0xe1, + 0x99, 0x03, 0x3c, 0xd2, 0xd9, 0xe7, 0x1b, 0xd9, 0xfc, 0x13, 0xfd, 0xc8, 0xf4, + 0xf1, 0xd0, 0xde, 0x12, 0x10, 0x00, 0x1b, 0xf6, 0xcc, 0xb8, 0xb2, 0x38, 0x35, + 0xf0, 0xfa, 0x07, 0xfe, 0xe4, 0x1b, 0x21, 0x2b, 0xdd, 0xee, 0x36, 0xe1, 0xe5, + 0xc3, 0xfd, 0xff, 0xfe, 0xe7, 0xdb, 0xeb, 0x08, 0xc4, 0xcf, 0xb6, 0xe8, 0xff, + 0x1d, 0x2c, 0xf2, 0xe8, 0xfd, 0x1e, 0x51, 0x30, 0xca, 0x11, 0x30, 0xde, 0xb4, + 0x00, 0xf1, 0xed, 0x25, 0xfc, 0x8b, 0xfd, 0x26, 0xe2, 0xfb, 0x9e, 0xe3, 0xde, + 0xbb, 0x08, 0xf7, 0xef, 0x01, 0x0d, 0xca, 0xde, 0x01, 0xe6, 0x00, 0x34, 0xfa, + 0x31, 0x0b, 0xa5, 0xe9, 0x02, 0x4a, 0x28, 0xf1, 0xaa, 0x08, 0xdf, 0x36, 0xce, + 0xbe, 0xf6, 0x14, 0xf4, 0xd9, 0x2d, 0xbf, 0xe0, 0x25, 0x04, 0xeb, 0xd0, 0xf7, + 0xca, 0xfb, 0x12, 0x25, 0x3b, 0x14, 0xf2, 0xf9, 0x08, 0xf9, 0x00, 0xc4, 0x3c, + 0x0f, 0x23, 0xe8, 0xc8, 0xec, 0x0b, 0xd0, 0x05, 0xbc, 0xeb, 0xfd, 0xb8, 0xfb, + 0x26, 0xe7, 0xea, 0xfb, 0x12, 0x43, 0xf6, 0xc2, 0x10, 0x81, 0xcb, 0xc3, 0x12, + 0xfe, 0x1b, 0xfc, 0xea, 0x12, 0x1c, 0x04, 0xea, 0x46, 0x12, 0x37, 0x28, 0x12, + 0x32, 0x1a, 0xdd, 0x23, 0xe5, 0x01, 0xff, 0xfa, 0x25, 0x33, 0x03, 0x10, 0xed, + 0x0a, 0xde, 0xff, 0x19, 0xcf, 0xd6, 0xdc, 0x2c, 0xf7, 0x09, 0x1a, 0xf1, 0xed, + 0xde, 0xee, 0xe8, 0x14, 0x0e, 0x33, 0xe8, 0xd9, 0xa7, 0xec, 0x45, 0x2f, 0x06, + 0xd9, 0x19, 0xed, 0xd0, 0x2d, 0xcd, 0x1d, 0xe4, 0xc8, 0xee, 0xc4, 0xf2, 0xcb, + 0xff, 0xda, 0x41, 0x4a, 0xd5, 0xe1, 0x15, 0xed, 0xc4, 0x1b, 0x11, 0xdd, 0x24, + 0x30, 0x0a, 0x23, 0xbe, 0xfc, 0x23, 0xf0, 0x56, 0xd1, 0xdd, 0xf4, 0xd8, 0xd1, + 0x19, 0xd5, 0x27, 0x2e, 0xb0, 0xd2, 0x23, 0xe4, 0x30, 0x01, 0xe8, 0xef, 0x41, + 0x23, 0x12, 0xfd, 0xe8, 0xd8, 0xec, 0x4b, 0xdd, 0x02, 0xb9, 0xae, 0x0f, 0xe0, + 0x14, 0xf1, 0x18, 0x33, 0xf8, 0xf7, 0x43, 0xf4, 0x27, 0xf8, 0xed, 0x18, 0xe0, + 0x5b, 0xc4, 0xed, 0xde, 0x17, 0xf0, 0x2f, 0xc5, 0x1a, 0xda, 0xe6, 0xc5, 0xfa, + 0x34, 0xe0, 0xe6, 0xaf, 0xc0, 0xcf, 0x25, 0xe4, 0xed, 0xf4, 0xd6, 0x18, 0x1a, + 0xbb, 0xf4, 0xd3, 0xa8, 0x81, 0xef, 0xd0, 0x27, 0x28, 0xda, 0x45, 0xe8, 0x4f, + 0x0e, 0xd9, 0x20, 0x0a, 0xdc, 0xe0, 0x03, 0x2a, 0xfb, 0xd6, 0x1a, 0x2d, 0x42, + 0xef, 0x1e, 0x20, 0x12, 0xda, 0x2c, 0x02, 0xd8, 0xb6, 0x21, 0x56, 0xd5, 0x9a, + 0x1d, 0x18, 0x02, 0x1c, 0xd3, 0xe4, 0x07, 0x19, 0xfe, 0xd5, 0xfe, 0x02, 0xf1, + 0xf2, 0x20, 0x2f, 0x17, 0x21, 0xc3, 0xdf, 0x27, 0xf6, 0x18, 0x11, 0x9b, 0xe4, + 0x3d, 0x03, 0xe9, 0x31, 0x0d, 0xce, 0x0b, 0x0f, 0xb0, 0xfa, 0x08, 0xe3, 0xf2, + 0x1e, 0x2a, 0xff, 0x50, 0xc1, 0x13, 0x09, 0xf3, 0xea, 0xe8, 0x3f, 0x19, 0x22, + 0xc2, 0x14, 0xfd, 0x2c, 0x0c, 0xb9, 0x09, 0x30, 0x1a, 0xf8, 0xe7, 0xde, 0xbc, + 0x9a, 0xfd, 0xc0, 0x1c, 0x22, 0xee, 0x00, 0x30, 0xc9, 0xf5, 0x3d, 0xdd, 0x32, + 0x13, 0x36, 0xc0, 0xf1, 0x3a, 0x16, 0x0e, 0xd6, 0xb1, 0x12, 0x08, 0x03, 0x03, + 0xfa, 0xf1, 0x24, 0xfc, 0x1c, 0xd5, 0x2b, 0xd0, 0xc2, 0xcc, 0xe9, 0x17, 0x30, + 0x0b, 0xb2, 0x15, 0x6e, 0xeb, 0xf4, 0xf2, 0x2a, 0xb6, 0x2f, 0x17, 0xd8, 0x24, + 0xf3, 0x04, 0x04, 0xd8, 0xc2, 0x02, 0x2d, 0xd9, 0xf0, 0xe8, 0xe0, 0x2c, 0x06, + 0x11, 0xd4, 0xe2, 0x1e, 0x32, 0x2c, 0xf1, 0xc2, 0x10, 0xca, 0xfa, 0xe6, 0x35, + 0xc3, 0xee, 0x14, 0x39, 0x29, 0x1b, 0xf5, 0xc8, 0x24, 0xfa, 0x2b, 0x08, 0x4f, + 0x37, 0xcb, 0x1e, 0x1a, 0xb0, 0xf4, 0xbd, 0xfa, 0xe7, 0xda, 0x06, 0x11, 0xdd, + 0xfd, 0xee, 0xf7, 0x04, 0xce, 0xfe, 0x07, 0x25, 0xd4, 0xec, 0xf6, 0xe7, 0x2e, + 0xec, 0x17, 0xed, 0x1b, 0xe7, 0xdf, 0xf3, 0x0d, 0xdf, 0x16, 0x3a, 0x6a, 0x10, + 0x1e, 0x0f, 0x03, 0xfa, 0xfd, 0x09, 0xcf, 0xde, 0xfc, 0x08, 0xfd, 0xf3, 0x16, + 0xe6, 0x11, 0x04, 0x1d, 0xf9, 0xba, 0xf2, 0x06, 0xfa, 0x21, 0xae, 0x29, 0x0f, + 0xc7, 0xed, 0x09, 0x44, 0xfd, 0x20, 0xe5, 0xf5, 0x2a, 0xcd, 0xd6, 0xec, 0x01, + 0x27, 0xd9, 0xff, 0x02, 0x34, 0xde, 0x31, 0xbc, 0xd6, 0xfc, 0xf5, 0xfd, 0xe2, + 0xf4, 0xe9, 0xbb, 0xfc, 0x37, 0xe9, 0x06, 0xfc, 0xeb, 0xdc, 0xf5, 0xd6, 0xe8, + 0x07, 0x23, 0x15, 0x10, 0xe7, 0xcb, 0xcb, 0x2f, 0x04, 0xe2, 0xff, 0xf1, 0x0d, + 0x3a, 0xfb, 0x01, 0xf9, 0xfe, 0x48, 0xef, 0xf1, 0xea, 0xc9, 0xe4, 0xcc, 0xd9, + 0x06, 0xdd, 0xf1, 0xfe, 0xdd, 0xd0, 0x00, 0x03, 0xce, 0xf8, 0x25, 0xfe, 0xf1, + 0x00, 0xd7, 0xe7, 0x1c, 0xce, 0x16, 0xec, 0x26, 0xdd, 0x23, 0xe1, 0xf0, 0xee, + 0xd0, 0x04, 0xb5, 0xfc, 0xcc, 0x49, 0xfc, 0xf0, 0x01, 0xff, 0xb8, 0xfc, 0x24, + 0x16, 0xde, 0x16, 0x14, 0x31, 0x0a, 0xf2, 0x1d, 0xe4, 0x08, 0xfd, 0xfd, 0x00, + 0xd2, 0x1b, 0x11, 0xf3, 0x37, 0xee, 0x39, 0xfc, 0xde, 0xd6, 0x04, 0xe4, 0xd7, + 0xc6, 0xc8, 0x0f, 0x25, 0x25, 0xdb, 0x14, 0x04, 0x1c, 0xf1, 0xcf, 0xab, 0x66, + 0xe4, 0x1a, 0x03, 0xe8, 0xed, 0x20, 0x1a, 0x0d, 0xfc, 0xd3, 0xd8, 0xc3, 0xf3, + 0x12, 0xaa, 0x2b, 0x0e, 0x11, 0xea, 0xd5, 0xfc, 0xf0, 0xd7, 0xe7, 0x08, 0x33, + 0xcd, 0xec, 0xfe, 0x10, 0xf2, 0xf8, 0x18, 0x17, 0x01, 0xf8, 0xfb, 0x33, 0xaf, + 0x21, 0xdd, 0xef, 0x00, 0xe7, 0x7f, 0xf4, 0x10, 0xf7, 0x09, 0x13, 0xfc, 0x06, + 0x3d, 0xbf, 0x39, 0x9c, 0xd6, 0xd2, 0xf8, 0xfa, 0xc4, 0xdb, 0x01, 0x2b, 0xb8, + 0xef, 0x12, 0x15, 0xf3, 0xd8, 0xca, 0xe4, 0xfc, 0xda, 0x03, 0xaf, 0x0b, 0xff, + 0xcf, 0xfc, 0xca, 0xd1, 0xcf, 0xe5, 0x10, 0xb0, 0xf4, 0x26, 0xf2, 0x04, 0x1f, + 0xcd, 0xca, 0x02, 0x00, 0xe4, 0xd1, 0x2d, 0x01, 0xe5, 0xc1, 0xfa, 0x82, 0xfb, + 0x0d, 0x1e, 0x2f, 0xfa, 0x16, 0x02, 0xd3, 0x12, 0xef, 0xfc, 0x3f, 0xfa, 0x0c, + 0x91, 0xf5, 0x02, 0x0f, 0xf3, 0xb5, 0xcc, 0xc6, 0xc9, 0xee, 0x24, 0xaa, 0xc7, + 0xf8, 0xd9, 0xc4, 0x9d, 0xe8, 0x0c, 0xf1, 0x25, 0xe6, 0x17, 0xdf, 0xaa, 0xf8, + 0x20, 0x02, 0xb2, 0xca, 0xee, 0xdf, 0x07, 0x0d, 0x1a, 0xda, 0xd4, 0xa5, 0xe5, + 0xbb, 0xb2, 0xe0, 0x2b, 0xe9, 0xb1, 0x2a, 0xdb, 0xd1, 0xeb, 0xf1, 0xde, 0xe3, + 0x00, 0xbc, 0x10, 0xd7, 0xc1, 0x2d, 0x9e, 0xe8, 0xf2, 0x09, 0xbd, 0xe6, 0xc0, + 0xea, 0xed, 0xde, 0x3e, 0xf7, 0xc2, 0xdd, 0x24, 0xe0, 0xf5, 0xb1, 0x2c, 0x1a, + 0xd7, 0x2d, 0x2b, 0xe6, 0xd9, 0x0e, 0xdc, 0x19, 0x3e, 0x02, 0xb9, 0xd1, 0xec, + 0xb0, 0x03, 0x09, 0xcc, 0x24, 0xf0, 0xc6, 0xf2, 0xf5, 0x30, 0xb5, 0x03, 0x06, + 0x1f, 0xe2, 0xc8, 0xb4, 0xe8, 0xfd, 0x38, 0xf9, 0xfa, 0x09, 0xf5, 0xf4, 0xd0, + 0xec, 0xde, 0x05, 0xed, 0xcc, 0xf4, 0xee, 0xde, 0xfb, 0xd7, 0x06, 0xba, 0x07, + 0xd3, 0xf3, 0xeb, 0x1a, 0x43, 0x29, 0x04, 0x22, 0xaa, 0xbb, 0xea, 0xf4, 0xbe, + 0x1d, 0xf9, 0x11, 0xf9, 0xeb, 0xc4, 0x0a, 0xa0, 0xfd, 0xfb, 0x16, 0xd7, 0x12, + 0x07, 0xe8, 0x46, 0xef, 0xed, 0x5a, 0xd0, 0x10, 0xd6, 0xbc, 0x08, 0x27, 0x08, + 0x5a, 0x00, 0xe7, 0x1a, 0xbb, 0x81, 0x11, 0xd4, 0x3f, 0xe7, 0xfb, 0xef, 0xce, + 0xd0, 0x21, 0xd5, 0xfb, 0x65, 0xf8, 0x0f, 0x16, 0x4f, 0xdb, 0xf4, 0xde, 0xfe, + 0x2c, 0xc5, 0xf7, 0x06, 0xd0, 0x2d, 0xf5, 0xe1, 0x92, 0x27, 0x28, 0xea, 0xfe, + 0xf3, 0x0c, 0xc6, 0xd9, 0xeb, 0xd9, 0xef, 0xf5, 0x23, 0x00, 0x06, 0x1b, 0x24, + 0xd1, 0xff, 0xdf, 0x57, 0xb7, 0x17, 0xd8, 0x0c, 0x12, 0x48, 0xf0, 0xbe, 0x18, + 0x1a, 0x58, 0xf0, 0xc6, 0xd3, 0xc2, 0x1d, 0x17, 0xfa, 0x42, 0xdf, 0x20, 0xe8, + 0xdb, 0xf1, 0xdf, 0x04, 0xcf, 0x0b, 0xdd, 0xe0, 0x00, 0x5e, 0x02, 0x68, 0xc4, + 0x0c, 0x1b, 0x14, 0x11, 0x35, 0xf9, 0x4a, 0xb3, 0xf0, 0xb9, 0x91, 0x1e, 0xff, + 0xe3, 0x2f, 0x0f, 0xf0, 0xed, 0xd1, 0xe9, 0x21, 0xd5, 0x06, 0x1f, 0xef, 0xad, + 0x18, 0xf2, 0x99, 0xc5, 0xea, 0xf2, 0x71, 0xef, 0xe5, 0x2a, 0x2a, 0x4e, 0x7f, + 0x40, 0x44, 0xc9, 0x2b, 0xde, 0x2e, 0x0e, 0xf3, 0x61, 0x45, 0xd0, 0xe7, 0x3a, + 0xac, 0x21, 0x5a, 0xe2, 0x0f, 0xe5, 0x18, 0xdf, 0xd5, 0xd9, 0x1e, 0xe9, 0xe7, + 0x2d, 0x29, 0xe5, 0xa1, 0x06, 0x00, 0xcc, 0x02, 0x01, 0xc8, 0x05, 0xd5, 0x4f, + 0xbc, 0xee, 0xfd, 0x5f, 0xbf, 0x34, 0xd1, 0x10, 0xf1, 0xe6, 0x64, 0xf2, 0x1f, + 0x08, 0x3c, 0xb6, 0x05, 0x4d, 0x00, 0x0c, 0xe5, 0x0d, 0xde, 0xf3, 0x06, 0x7e, + 0x44, 0xc2, 0xae, 0xe4, 0xef, 0xd2, 0xe9, 0xfd, 0xff, 0x34, 0x9a, 0xd8, 0x28, + 0x24, 0x0a, 0xe8, 0xe8, 0xa2, 0xd9, 0xed, 0x06, 0xee, 0xd9, 0xfc, 0xf7, 0x0d, + 0xa6, 0xfb, 0x2c, 0xfd, 0xb2, 0xcc, 0xfc, 0xd8, 0x13, 0xdd, 0xde, 0xe8, 0xe4, + 0x17, 0xee, 0x20, 0x49, 0xd6, 0x41, 0x30, 0xe7, 0xfc, 0x05, 0xdb, 0xe0, 0x21, + 0xe4, 0xcc, 0xcc, 0xee, 0xcc, 0xf2, 0xb3, 0xed, 0x04, 0xf8, 0xc2, 0x72, 0x0c, + 0xea, 0x4d, 0x31, 0x2c, 0xb7, 0x37, 0xdd, 0xbe, 0xfe, 0xe6, 0x22, 0x20, 0xf6, + 0xea, 0x02, 0x05, 0x65, 0xda, 0xd1, 0xff, 0xee, 0x34, 0x0c, 0x92, 0x85, 0xed, + 0xde, 0x1b, 0xd3, 0x65, 0xe1, 0xb2, 0x25, 0x23, 0x02, 0xb0, 0xbf, 0x41, 0xb2, + 0xc7, 0xfb, 0x10, 0x04, 0x1b, 0xc1, 0xe6, 0xde, 0xaf, 0x0d, 0x01, 0x8f, 0xff, + 0xd8, 0xf6, 0xa0, 0x1d, 0xd5, 0x03, 0xdd, 0xc6, 0xf8, 0x05, 0xc6, 0x25, 0x3f, + 0x05, 0x9f, 0xfd, 0x1c, 0xd0, 0x0c, 0xc2, 0xe0, 0x09, 0xec, 0x1e, 0xcf, 0x30, + 0x18, 0xdb, 0x5a, 0x09, 0x87, 0xda, 0xd8, 0xc8, 0x00, 0x47, 0x2d, 0x09, 0x09, + 0xf0, 0x1e, 0x0d, 0xfa, 0xfd, 0xc3, 0xbd, 0xfe, 0x4f, 0x3b, 0x03, 0x1e, 0xe0, + 0x8f, 0xcb, 0x97, 0x05, 0xbc, 0xea, 0xec, 0x2b, 0xfd, 0x1b, 0xb2, 0x04, 0x9e, + 0xe7, 0xf3, 0x38, 0xe7, 0x46, 0x37, 0x24, 0x1c, 0x44, 0xa7, 0xeb, 0x03, 0xd7, + 0x27, 0xed, 0x0d, 0x14, 0xbd, 0xbf, 0xea, 0x11, 0x0b, 0xd6, 0x33, 0x2f, 0x62, + 0xdd, 0x3e, 0xf9, 0x3e, 0x23, 0x10, 0xf3, 0x30, 0xf3, 0x3f, 0xe2, 0xe4, 0x14, + 0xf9, 0x3f, 0x13, 0xd3, 0xfe, 0xd0, 0x27, 0x0f, 0x81, 0xd5, 0xf6, 0xf9, 0xe0, + 0xec, 0x19, 0x92, 0x50, 0x90, 0x27, 0x48, 0xf8, 0x13, 0xd6, 0x90, 0x4b, 0x07, + 0x25, 0x07, 0x08, 0xd0, 0x23, 0xdc, 0xfe, 0xe9, 0xe1, 0x12, 0x23, 0x2f, 0x85, + 0xdd, 0xc6, 0x32, 0x30, 0xea, 0x28, 0x0b, 0xd7, 0xf5, 0xe8, 0xa1, 0x0f, 0xe2, + 0x18, 0x38, 0xed, 0xda, 0x1a, 0xe6, 0x1f, 0xb7, 0x06, 0xdc, 0xe5, 0xda, 0xbc, + 0x15, 0x83, 0x18, 0xfa, 0xbd, 0xc6, 0xe7, 0xf0, 0x53, 0xe9, 0x07, 0x2a, 0x38, + 0xfe, 0x16, 0xd7, 0xe4, 0xfa, 0x2b, 0xfc, 0x9b, 0x17, 0x3b, 0x1d, 0x13, 0xa9, + 0x16, 0xb6, 0x57, 0xcf, 0xff, 0x21, 0xde, 0x45, 0x30, 0x81, 0x0f, 0x14, 0xe7, + 0xec, 0xf7, 0xeb, 0xc8, 0xb7, 0xed, 0xda, 0xbb, 0xa2, 0x06, 0x03, 0xfa, 0x59, + 0xfa, 0xf8, 0xa5, 0xf2, 0x06, 0xf0, 0xd2, 0xdb, 0x38, 0xaf, 0xf1, 0x29, 0x39, + 0xf9, 0xe8, 0xfb, 0xcf, 0x1a, 0xe5, 0xff, 0xab, 0xb8, 0xf5, 0x13, 0xba, 0xb9, + 0xe6, 0xd6, 0xe5, 0xeb, 0x11, 0x9b, 0xc4, 0x1c, 0x36, 0x26, 0x2c, 0x15, 0xf7, + 0x17, 0xf9, 0xf1, 0x0b, 0x07, 0x9c, 0x23, 0xfd, 0xbd, 0xe0, 0xb8, 0xfb, 0x33, + 0xc9, 0x08, 0xd7, 0xf4, 0x29, 0xeb, 0xf9, 0x22, 0xe4, 0x0f, 0xd3, 0x4a, 0xe3, + 0x31, 0x12, 0x3d, 0x39, 0xfc, 0xba, 0xe6, 0xaf, 0xd5, 0x1d, 0x15, 0xe4, 0xed, + 0xfa, 0xe1, 0xf3, 0x65, 0xa2, 0xc9, 0xca, 0xf3, 0x32, 0xc4, 0xf8, 0xb6, 0xf3, + 0x25, 0x2f, 0x1e, 0xc3, 0xc3, 0xdb, 0x06, 0xe0, 0x31, 0xe7, 0x2c, 0x3d, 0xfd, + 0xde, 0xdd, 0x34, 0xd1, 0x17, 0xcf, 0x0a, 0xc6, 0xfe, 0x04, 0xdd, 0x25, 0x10, + 0xde, 0x08, 0xe9, 0x28, 0xc8, 0xe7, 0x25, 0x81, 0xad, 0xe6, 0x12, 0xfe, 0x61, + 0x19, 0xb1, 0x05, 0x55, 0x75, 0x29, 0xc9, 0xe3, 0xe7, 0xf6, 0xc8, 0x95, 0x01, + 0x19, 0xe1, 0x06, 0xe2, 0x02, 0x4a, 0x59, 0x28, 0xe8, 0x16, 0x19, 0x21, 0xe8, + 0xd6, 0x89, 0x61, 0xb7, 0xe7, 0xcf, 0xbb, 0xcd, 0xe2, 0xbe, 0x70, 0x09, 0xf8, + 0x3b, 0xd4, 0x15, 0xee, 0x1a, 0x3c, 0x15, 0x3d, 0xff, 0xcc, 0xb9, 0x9e, 0x3d, + 0xcc, 0xe9, 0x0e, 0xf6, 0x01, 0x94, 0xf0, 0xf7, 0x0c, 0xb6, 0x14, 0x12, 0x26, + 0xe8, 0x2c, 0xd6, 0xce, 0xee, 0xd7, 0x4a, 0xae, 0x37, 0xa9, 0x12, 0x0c, 0x09, + 0xb0, 0x17, 0x0b, 0xce, 0xc6, 0x11, 0xd6, 0x40, 0x0e, 0x13, 0x1e, 0x07, 0x1a, + 0xf3, 0xdb, 0x26, 0x12, 0xc6, 0xf7, 0xff, 0xf3, 0x05, 0x2d, 0xc9, 0xe4, 0xf4, + 0xf8, 0x45, 0x12, 0x03, 0x23, 0x16, 0xc0, 0xeb, 0x25, 0x1a, 0xe4, 0xf0, 0x06, + 0x07, 0x04, 0x56, 0xaa, 0x0f, 0x20, 0x07, 0xba, 0x12, 0xcb, 0x0d, 0x1b, 0x46, + 0xd7, 0xf1, 0x29, 0xf6, 0xe6, 0x3d, 0xf5, 0xd0, 0x2f, 0xe6, 0x0f, 0x96, 0xe0, + 0x0c, 0xde, 0x34, 0xd1, 0x1c, 0xa5, 0xb3, 0x03, 0x5e, 0xd2, 0xd5, 0xaf, 0xf4, + 0xed, 0x25, 0xd2, 0x0d, 0x18, 0xdc, 0xa4, 0x09, 0x05, 0xcb, 0x2e, 0x1c, 0xe6, + 0xd0, 0xc2, 0xba, 0x22, 0xc6, 0xb9, 0xf4, 0xd2, 0x37, 0x17, 0x4b, 0xf7, 0x16, + 0xe8, 0xe6, 0x0e, 0x32, 0x5d, 0x0c, 0x6b, 0x3b, 0x1d, 0x68, 0xf7, 0xf1, 0xd0, + 0xaa, 0x25, 0x10, 0x0a, 0x36, 0xe9, 0xd0, 0x2a, 0xf8, 0xb5, 0x06, 0xe6, 0x54, + 0xec, 0xe8, 0x40, 0xfc, 0x1d, 0xcc, 0xd3, 0x0b, 0x17, 0x46, 0xc6, 0x54, 0xf9, + 0xec, 0xee, 0x07, 0x2f, 0xf5, 0x2b, 0xf7, 0x0f, 0xeb, 0x0d, 0xe9, 0xe2, 0xea, + 0xdb, 0xf0, 0xbf, 0x24, 0xe7, 0xd9, 0x22, 0x11, 0xed, 0x32, 0xff, 0xe8, 0x3a, + 0xec, 0x0a, 0xf6, 0xe8, 0xc9, 0xf1, 0xca, 0xee, 0x1b, 0x0d, 0xf2, 0xf4, 0x1a, + 0x57, 0x1a, 0x01, 0xcc, 0xcb, 0xb5, 0xcc, 0x2a, 0xcd, 0xf1, 0xd4, 0x24, 0x19, + 0xa6, 0xf6, 0x2a, 0x15, 0x3a, 0x07, 0x28, 0xcf, 0xdf, 0x24, 0x20, 0x0e, 0xe7, + 0x1e, 0xf1, 0x00, 0x0a, 0x4f, 0xfb, 0x0f, 0x19, 0x13, 0xbd, 0xc8, 0x1a, 0xdb, + 0x11, 0xf8, 0x01, 0xd1, 0x12, 0xb8, 0x3d, 0x31, 0x24, 0xd9, 0xf0, 0x2a, 0xfb, + 0xf2, 0x32, 0xf3, 0x07, 0x25, 0xd6, 0x09, 0x29, 0x2d, 0x22, 0xe2, 0x1a, 0x08, + 0x62, 0x1d, 0x7f, 0x18, 0x0e, 0x0a, 0x40, 0x0b, 0xd2, 0xac, 0x31, 0x47, 0xe9, + 0xf1, 0xf6, 0xff, 0x25, 0x06, 0x17, 0xce, 0xd9, 0xc2, 0xfe, 0xf8, 0x26, 0x23, + 0xc0, 0xfd, 0xca, 0xd1, 0xbf, 0x02, 0xe4, 0x15, 0xf1, 0xc7, 0xf9, 0xeb, 0x60, + 0xdc, 0x47, 0xe0, 0xdf, 0xe2, 0x16, 0xf5, 0xe4, 0xda, 0x42, 0x51, 0x37, 0xf0, + 0xeb, 0xdc, 0x27, 0xb1, 0x1a, 0xf8, 0xeb, 0xb9, 0xee, 0x33, 0xef, 0xdd, 0x90, + 0xd3, 0x22, 0xc8, 0xb8, 0xe5, 0xf5, 0x13, 0x06, 0x07, 0xda, 0xfa, 0x04, 0xf0, + 0xaf, 0x35, 0xd0, 0xd0, 0x14, 0x08, 0x2d, 0xf6, 0xed, 0x27, 0x27, 0xf8, 0xcb, + 0x23, 0xfb, 0x07, 0x2a, 0x27, 0x0c, 0xfc, 0xd9, 0xd4, 0x1f, 0xde, 0x0b, 0x0d, + 0x12, 0xd1, 0x08, 0x2b, 0xd1, 0x11, 0x03, 0xf3, 0x04, 0x45, 0xff, 0xd9, 0xef, + 0x19, 0x01, 0xec, 0x3d, 0xf3, 0x1a, 0xb7, 0xd8, 0xc2, 0xca, 0x18, 0x27, 0x01, + 0x29, 0x09, 0xd8, 0x14, 0xda, 0x11, 0x2d, 0x63, 0x40, 0xd6, 0xd0, 0xd4, 0xf7, + 0x1d, 0xde, 0xe1, 0xdc, 0xa6, 0x24, 0x13, 0xbb, 0xe4, 0x27, 0x3d, 0xf1, 0xd4, + 0x44, 0xd6, 0x17, 0xc4, 0xc5, 0xf8, 0xda, 0xc9, 0x4f, 0xe2, 0x13, 0x10, 0xf8, + 0xd0, 0x23, 0xdc, 0xf2, 0x26, 0x61, 0x1f, 0x02, 0xd1, 0xe0, 0xe6, 0xfb, 0xfe, + 0x1d, 0xac, 0xfb, 0xbd, 0x0d, 0x08, 0xe0, 0xb6, 0x2f, 0x11, 0xb5, 0x04, 0x4d, + 0xc0, 0xc9, 0xdf, 0xd8, 0xfe, 0xd5, 0xbb, 0xbf, 0x15, 0x0f, 0xf4, 0xf8, 0xd5, + 0xa2, 0xda, 0xbb, 0xd0, 0xae, 0xb9, 0xec, 0x07, 0xe2, 0x23, 0x16, 0x21, 0x0a, + 0x42, 0xae, 0xba, 0xb1, 0xea, 0x1b, 0x6b, 0x31, 0xb1, 0x0a, 0x17, 0x3a, 0xdc, + 0xae, 0x12, 0x03, 0xcf, 0xd2, 0xf6, 0xd4, 0xdf, 0x3a, 0xb6, 0xf8, 0x2d, 0xe2, + 0xa4, 0xe3, 0xf7, 0xfb, 0xd7, 0x0b, 0x9d, 0xde, 0xd7, 0xc9, 0x56, 0xee, 0x98, + 0x1c, 0x08, 0xab, 0xc2, 0x59, 0xa3, 0x30, 0x3f, 0x2d, 0xd0, 0x08, 0x1e, 0xed, + 0xdc, 0x1e, 0xc0, 0x64, 0xc9, 0x4e, 0xd7, 0xe7, 0xeb, 0xe2, 0xe8, 0x20, 0xe2, + 0xcd, 0xfc, 0x37, 0xc9, 0x5a, 0x1f, 0x23, 0x14, 0x0c, 0xee, 0xe7, 0x06, 0xc8, + 0xc7, 0x12, 0x9a, 0xfa, 0xd9, 0xff, 0xe9, 0x3c, 0xff, 0xff, 0x7f, 0xc3, 0xe8, + 0xe3, 0x01, 0xa0, 0x19, 0x3e, 0x16, 0xce, 0x1b, 0xe8, 0x27, 0x52, 0xec, 0x49, + 0xf5, 0xe9, 0x3c, 0xc3, 0xab, 0x3f, 0xfc, 0x02, 0x05, 0xbe, 0x49, 0x08, 0xd7, + 0x20, 0xea, 0x0f, 0x43, 0xd3, 0xf6, 0x03, 0x43, 0x2f, 0x07, 0x0e, 0xdb, 0xb5, + 0x1c, 0x3e, 0x19, 0xbe, 0xe8, 0xe9, 0x12, 0xed, 0xd5, 0x08, 0x02, 0xf6, 0xf9, + 0x01, 0xde, 0x01, 0xcf, 0xe6, 0x83, 0x35, 0x9d, 0xc9, 0xbf, 0x8a, 0xbe, 0xf2, + 0xf4, 0x11, 0xd1, 0x0e, 0xa4, 0xdd, 0x0d, 0xb4, 0xd2, 0x95, 0xf4, 0xb4, 0x2a, + 0xa3, 0xc9, 0xe0, 0x25, 0xbd, 0xf9, 0xaf, 0xba, 0x2f, 0xf4, 0xeb, 0x03, 0xf3, + 0x37, 0xd9, 0xaf, 0xd7, 0x0c, 0xcb, 0x19, 0xd1, 0x0c, 0xeb, 0x1e, 0x0a, 0x2b, + 0xf1, 0x16, 0x0f, 0x11, 0xea, 0x00, 0x81, 0xfe, 0xc5, 0x31, 0xe8, 0x8c, 0xb9, + 0x21, 0xfe, 0xd8, 0xfa, 0x9e, 0xf9, 0x23, 0x16, 0x15, 0x1c, 0x10, 0xe3, 0xf2, + 0x23, 0x15, 0xe3, 0x0e, 0xdf, 0x47, 0x42, 0x2e, 0x28, 0x0d, 0xc1, 0x28, 0x25, + 0xe6, 0xd2, 0xe9, 0xe9, 0xe2, 0xf4, 0xef, 0x38, 0x04, 0xc6, 0x0d, 0x25, 0xff, + 0xc7, 0x15, 0xe2, 0x06, 0xe5, 0x0b, 0x99, 0xb8, 0x2c, 0xf6, 0x56, 0x19, 0x14, + 0x1b, 0x05, 0x07, 0xec, 0xed, 0xfe, 0x4a, 0x0b, 0x18, 0x29, 0xeb, 0xda, 0xd8, + 0x68, 0xe0, 0xfe, 0xec, 0xc1, 0x01, 0xd8, 0xe7, 0x48, 0x12, 0x1f, 0x1c, 0x33, + 0x05, 0xb5, 0x16, 0x08, 0x90, 0xc7, 0x3b, 0xc8, 0xf1, 0x16, 0x26, 0xa2, 0xb9, + 0xc0, 0x0b, 0xba, 0xe4, 0xd9, 0x0f, 0xb3, 0x17, 0xdc, 0xea, 0x2c, 0xf8, 0xe7, + 0x18, 0xec, 0x1b, 0xaa, 0xf3, 0x50, 0x0a, 0x34, 0x30, 0xca, 0xf0, 0xfe, 0xb3, + 0x3b, 0x22, 0xde, 0x20, 0x14, 0x0f, 0x41, 0xe9, 0x29, 0xf9, 0x2a, 0x0b, 0x05, + 0x34, 0x00, 0xa9, 0xff, 0x06, 0xdf, 0x3f, 0xed, 0x37, 0xfe, 0x07, 0xc9, 0x12, + 0xfd, 0x02, 0x42, 0xbc, 0xe7, 0xc7, 0x03, 0xdc, 0xe6, 0x1d, 0xd8, 0x34, 0x07, + 0xa0, 0xd9, 0xf6, 0xe6, 0xe5, 0xb0, 0xe7, 0xa4, 0xfc, 0x02, 0xed, 0xf0, 0xaa, + 0xed, 0xff, 0x05, 0xca, 0x3a, 0xc7, 0x10, 0xed, 0x1d, 0x48, 0xe8, 0x16, 0xe1, + 0xdc, 0x13, 0x24, 0xfa, 0x2a, 0x3d, 0xdd, 0x0a, 0xeb, 0xe0, 0x22, 0xe5, 0x03, + 0xe9, 0x2a, 0x06, 0x2e, 0x3d, 0x07, 0xd4, 0x05, 0x55, 0xea, 0x38, 0x12, 0xcd, + 0xff, 0xb7, 0x11, 0x06, 0xb2, 0x12, 0xb7, 0xc6, 0x09, 0x06, 0xc6, 0xfe, 0xdb, + 0xe5, 0xbc, 0xd3, 0xcc, 0x06, 0xe9, 0xd1, 0xdf, 0xda, 0x2f, 0x2f, 0xf8, 0x10, + 0xd8, 0xc4, 0x04, 0xf8, 0xe7, 0x40, 0xcc, 0xbe, 0xc6, 0xe7, 0xea, 0xd6, 0xd3, + 0xff, 0xed, 0x01, 0xec, 0x00, 0x05, 0x16, 0xfe, 0xc6, 0xe6, 0x14, 0xea, 0xd7, + 0xcc, 0xd4, 0xfc, 0x4e, 0xbf, 0xd6, 0xce, 0x35, 0xbc, 0x29, 0xed, 0x12, 0xcc, + 0xf5, 0x0f, 0xee, 0xc4, 0xd0, 0xaf, 0x0b, 0x1d, 0xfa, 0xbb, 0xfc, 0xde, 0x2f, + 0x11, 0xf7, 0x36, 0xe2, 0xdc, 0x02, 0xfd, 0x05, 0xfe, 0xf4, 0x1c, 0xd5, 0x24, + 0x28, 0xca, 0x14, 0xf7, 0xdf, 0x0a, 0xe0, 0x0f, 0x7f, 0xbe, 0x2e, 0xf7, 0x0f, + 0x0d, 0xd5, 0xf6, 0x12, 0xdc, 0x02, 0x16, 0x03, 0xc8, 0xe8, 0xfe, 0xe1, 0xf9, + 0xc7, 0xfa, 0xa9, 0x1c, 0x20, 0x18, 0xe2, 0xde, 0x11, 0xf6, 0xbf, 0xd3, 0xdc, + 0x09, 0x20, 0xe4, 0x06, 0xdb, 0x49, 0xd2, 0xcf, 0xd8, 0xf7, 0xea, 0xee, 0xdd, + 0xf6, 0x03, 0xc5, 0xd8, 0xf8, 0xd5, 0xf1, 0xbe, 0x0e, 0x14, 0xfb, 0x50, 0x28, + 0x17, 0xfa, 0x10, 0xc9, 0xda, 0xff, 0xdb, 0x14, 0x03, 0xf1, 0xd8, 0x4e, 0x1c, + 0x00, 0xfb, 0xef, 0xbb, 0x0b, 0xf9, 0xcd, 0xf9, 0xd9, 0xff, 0x12, 0xf1, 0x16, + 0xea, 0xf6, 0x5b, 0xd7, 0xf6, 0xe7, 0xd1, 0x9f, 0x97, 0x0f, 0x59, 0xfe, 0xb6, + 0xdc, 0x84, 0xa7, 0x1c, 0x19, 0x0a, 0xba, 0xe9, 0x05, 0xfd, 0x30, 0xc8, 0xc5, + 0xd1, 0x90, 0xc1, 0xda, 0x07, 0x09, 0x14, 0x40, 0xf7, 0xe3, 0xd6, 0x32, 0xe0, + 0x0d, 0xda, 0x59, 0xf9, 0xf5, 0xd1, 0xff, 0xf9, 0xb8, 0x88, 0xfe, 0x34, 0xff, + 0xdd, 0xf3, 0x14, 0x30, 0x25, 0x1a, 0x14, 0x23, 0x51, 0xc3, 0xfa, 0x0c, 0x81, + 0x29, 0x24, 0x89, 0x18, 0x52, 0x44, 0xa0, 0x1a, 0xfd, 0xf3, 0xfa, 0x66, 0x1a, + 0x27, 0xd1, 0xd6, 0xa8, 0xcf, 0xf5, 0xbb, 0xeb, 0xd7, 0x1c, 0xcb, 0x71, 0xd1, + 0x10, 0xd9, 0x38, 0x40, 0x24, 0x0c, 0x2f, 0xed, 0x22, 0x1f, 0xd8, 0xdb, 0x5b, + 0xf5, 0xe2, 0x87, 0xf1, 0x04, 0xcb, 0xd6, 0x05, 0x17, 0xef, 0x4e, 0xe0, 0x8b, + 0xa5, 0x3a, 0xf0, 0xfc, 0xff, 0x62, 0x14, 0x18, 0xcb, 0xa1, 0x03, 0x1a, 0x0f, + 0x2b, 0x0a, 0x06, 0x27, 0x23, 0x1f, 0xf0, 0x50, 0xd7, 0x09, 0xb2, 0x05, 0xeb, + 0x42, 0x16, 0x43, 0xea, 0xb0, 0x08, 0x0f, 0x5a, 0x91, 0xdc, 0xdc, 0x54, 0xa6, + 0xc4, 0xdc, 0xed, 0x1d, 0xa3, 0x33, 0xf4, 0xff, 0xd8, 0xef, 0x10, 0xf3, 0x35, + 0xd0, 0x24, 0xff, 0x25, 0xf3, 0x07, 0xe9, 0xf7, 0x44, 0xf3, 0x03, 0x20, 0x09, + 0xc4, 0x48, 0x36, 0x69, 0x31, 0x29, 0xb2, 0xea, 0x0c, 0xc5, 0xbe, 0x09, 0x10, + 0xfd, 0xb7, 0x93, 0x1d, 0x1d, 0x04, 0xf4, 0x47, 0xea, 0x19, 0xcf, 0xd0, 0x1d, + 0xd3, 0x04, 0x1c, 0xf0, 0x66, 0x12, 0x03, 0xad, 0xcf, 0xc1, 0xdf, 0xb0, 0x08, + 0xee, 0xf6, 0xf1, 0xef, 0xcf, 0xfe, 0xfb, 0xe0, 0x06, 0x28, 0xc8, 0x10, 0xe5, + 0xac, 0xa3, 0xd4, 0xce, 0x22, 0xe6, 0xa8, 0x1c, 0x3b, 0x3b, 0x14, 0xe8, 0x0c, + 0xf4, 0xb3, 0xee, 0x1d, 0x92, 0x27, 0x57, 0x04, 0x27, 0xf3, 0x4c, 0xdb, 0xfa, + 0xf5, 0xc4, 0xd5, 0xc7, 0xdf, 0xf5, 0xd3, 0x14, 0xd4, 0xd6, 0xf3, 0x42, 0xed, + 0x15, 0xf1, 0xee, 0xd3, 0x5d, 0xed, 0xc6, 0x6b, 0x08, 0xd3, 0xdc, 0x88, 0xd4, + 0xe2, 0xf6, 0xc7, 0xfb, 0xd9, 0xf7, 0xc5, 0x2d, 0xd4, 0xec, 0xf8, 0xd6, 0x4a, + 0xff, 0xc6, 0x0a, 0xf7, 0xdc, 0xc3, 0xcf, 0x13, 0x0f, 0x01, 0xe6, 0x08, 0xfa, + 0xfd, 0x03, 0x07, 0xf4, 0x0d, 0xf5, 0x37, 0xc2, 0xc1, 0xf4, 0xf7, 0x2d, 0x01, + 0x2d, 0x15, 0xfc, 0xc5, 0x09, 0x3b, 0xf1, 0xac, 0x3c, 0x05, 0xe2, 0xd3, 0x17, + 0xfd, 0xd5, 0xe1, 0x2f, 0x13, 0x17, 0x1a, 0xec, 0xf0, 0xfb, 0xf0, 0xc3, 0x2c, + 0x01, 0x5b, 0xf5, 0x05, 0x31, 0x53, 0xc1, 0xc9, 0xf4, 0x1c, 0xef, 0xef, 0xd1, + 0x19, 0xf7, 0x06, 0x1d, 0x11, 0xdb, 0x04, 0x1d, 0xbc, 0xd1, 0xfb, 0x0c, 0x09, + 0x25, 0xf8, 0x33, 0x3c, 0x0c, 0x27, 0xf1, 0x12, 0xbd, 0x1d, 0xdf, 0x2e, 0x7f, + 0xde, 0x17, 0x03, 0xcf, 0xfd, 0x06, 0xf0, 0xe3, 0xe7, 0xfd, 0xc5, 0xfa, 0x1e, + 0xd0, 0x23, 0x32, 0x10, 0x14, 0x2d, 0xe7, 0x14, 0xf6, 0x19, 0xdb, 0x31, 0x14, + 0xe0, 0x02, 0xdc, 0x05, 0xf8, 0xf3, 0x0a, 0xe3, 0xe5, 0xbe, 0x17, 0xcf, 0x3a, + 0xc8, 0xd4, 0xc5, 0xdf, 0x10, 0xc1, 0xf7, 0xf0, 0xbd, 0xf7, 0xf1, 0xc3, 0xd3, + 0xb7, 0x17, 0xe0, 0x22, 0xe6, 0x38, 0xcc, 0x00, 0xba, 0xd0, 0x23, 0xfe, 0xe4, + 0x17, 0x1a, 0xed, 0x28, 0xee, 0x09, 0xee, 0x4e, 0xc8, 0xfa, 0x34, 0xf5, 0x32, + 0xe9, 0x1d, 0x14, 0x02, 0xf7, 0x23, 0xfb, 0xf7, 0x0a, 0x04, 0xf6, 0xde, 0x8e, + 0xdb, 0xe8, 0x4d, 0x1c, 0xf8, 0xf6, 0x03, 0x53, 0xf2, 0x11, 0xc1, 0xd6, 0xe3, + 0x28, 0xba, 0xde, 0xff, 0xcc, 0xd1, 0x68, 0xfb, 0xd5, 0xd9, 0xe7, 0xf8, 0xfe, + 0xec, 0x3e, 0xea, 0xc5, 0x01, 0xed, 0xe4, 0x2d, 0xd8, 0xd7, 0xd5, 0xed, 0x17, + 0xe9, 0x25, 0xfe, 0xdf, 0xcc, 0x01, 0xe3, 0x0c, 0xf9, 0xb7, 0xb8, 0xfc, 0xf7, + 0x89, 0x1c, 0x13, 0xab, 0x14, 0xc6, 0xde, 0x1d, 0xb0, 0x3c, 0xb0, 0x05, 0x04, + 0x0a, 0x18, 0x16, 0xff, 0xda, 0xf7, 0xe1, 0xe6, 0x17, 0xee, 0x4e, 0x9d, 0x45, + 0xd0, 0xf4, 0x3b, 0xe9, 0x0a, 0x14, 0xbe, 0x04, 0x23, 0x38, 0x0d, 0x2a, 0xf9, + 0xe9, 0x29, 0xee, 0xc4, 0xf8, 0x0c, 0xaa, 0x13, 0xb4, 0x4c, 0xe2, 0xf5, 0x26, + 0xf6, 0x0c, 0x26, 0x06, 0xdc, 0xf0, 0xde, 0xf1, 0xff, 0x1b, 0xb3, 0xd6, 0xf5, + 0xf2, 0x2d, 0xdc, 0x28, 0x45, 0x0e, 0x18, 0xfb, 0x27, 0xd2, 0x39, 0x0e, 0x9d, + 0x48, 0x2c, 0xd0, 0x06, 0x3c, 0x3a, 0x5b, 0xa6, 0xcf, 0xea, 0x7f, 0xcd, 0x31, + 0xe4, 0x1a, 0x1a, 0xf9, 0x05, 0xaa, 0xca, 0x11, 0xee, 0x40, 0xaf, 0xce, 0xc8, + 0x3b, 0x1a, 0x4c, 0xd8, 0x32, 0x37, 0xc9, 0xfb, 0x95, 0xf6, 0x05, 0xdc, 0xb5, + 0x1b, 0xf2, 0x4b, 0xf1, 0x03, 0x0b, 0x3b, 0x29, 0xd0, 0x24, 0x40, 0x2e, 0xdd, + 0xca, 0xc5, 0xfe, 0x07, 0x0b, 0xe8, 0x99, 0xc8, 0x09, 0xd8, 0xdd, 0x63, 0x50, + 0xf5, 0x3e, 0x47, 0xb9, 0xea, 0xf0, 0xed, 0x40, 0xfe, 0x4d, 0x0e, 0xce, 0xfc, + 0xed, 0xbf, 0xde, 0xeb, 0x01, 0x13, 0x01, 0xcd, 0x44, 0xdb, 0x3e, 0xc0, 0x07, + 0xc0, 0x39, 0x0d, 0xfb, 0xf2, 0x04, 0xa8, 0xbc, 0xf3, 0x2d, 0xc3, 0x3c, 0x01, + 0x41, 0x1b, 0x1a, 0xf0, 0x65, 0x14, 0x0c, 0xf5, 0x01, 0x5e, 0x04, 0xb4, 0xf8, + 0x3b, 0x19, 0x13, 0x19, 0xbe, 0xa0, 0x12, 0xe2, 0x0f, 0xab, 0xcf, 0xb0, 0xd5, + 0xf2, 0x12, 0xf0, 0x18, 0x1d, 0xa0, 0x07, 0xe1, 0xf6, 0x08, 0x08, 0x0a, 0x0f, + 0x57, 0x00, 0xd9, 0x1f, 0x88, 0xf5, 0x1f, 0xd7, 0x07, 0x1e, 0xe3, 0xe3, 0x00, + 0x12, 0xe4, 0x08, 0xf2, 0x11, 0x29, 0xd3, 0x98, 0xd0, 0xed, 0xd9, 0xe1, 0x24, + 0x43, 0xfa, 0xd3, 0x0e, 0xed, 0xc2, 0x20, 0xaf, 0xfc, 0xaf, 0x1b, 0xf9, 0xb8, + 0xbd, 0xb2, 0xac, 0xf1, 0x05, 0xf6, 0xc5, 0x2a, 0x16, 0xa0, 0x2d, 0xc9, 0x20, + 0xff, 0x16, 0x22, 0x06, 0xd5, 0xea, 0xf9, 0xa2, 0x1e, 0xe8, 0xb1, 0x1f, 0xd8, + 0xca, 0xc7, 0xf4, 0xa3, 0x24, 0x0b, 0xff, 0xdf, 0x03, 0x10, 0xd6, 0xf3, 0xcf, + 0xbe, 0x25, 0x18, 0x17, 0x41, 0x04, 0x01, 0x41, 0x40, 0xdf, 0xe8, 0xb3, 0x29, + 0x0f, 0x15, 0x64, 0xca, 0x1b, 0x2f, 0xf2, 0x04, 0xe4, 0xd3, 0x51, 0xf2, 0x48, + 0x33, 0x06, 0x27, 0xbc, 0x1e, 0x26, 0x0f, 0x10, 0xc5, 0xd3, 0x0a, 0xe2, 0xc1, + 0x3b, 0xd1, 0x9f, 0xed, 0xc4, 0xec, 0x45, 0xd4, 0x08, 0x1b, 0xf3, 0xf9, 0xf6, + 0xa4, 0xd0, 0xf8, 0xdd, 0xd7, 0x24, 0xf2, 0xc4, 0xf8, 0xe0, 0xe8, 0x1a, 0x13, + 0x3d, 0x07, 0x34, 0x1e, 0x98, 0x0b, 0x1a, 0xb8, 0xdc, 0xf3, 0x10, 0x79, 0xca, + 0xfe, 0x04, 0xf7, 0x44, 0xb0, 0x27, 0x31, 0x23, 0xf2, 0xed, 0x14, 0xd2, 0xe1, + 0xf8, 0xfe, 0xf7, 0xf6, 0x9e, 0xf8, 0xe5, 0xe4, 0x35, 0xe4, 0x24, 0xc7, 0x84, + 0xf4, 0xe6, 0x3a, 0x01, 0xcc, 0xc5, 0xe5, 0xd5, 0xd9, 0x02, 0x3f, 0x05, 0xef, + 0x42, 0xba, 0x23, 0xdd, 0x13, 0x37, 0x42, 0xce, 0xff, 0xd1, 0xfe, 0xe8, 0x28, + 0xd5, 0xc2, 0x14, 0xe2, 0x17, 0xbf, 0x10, 0x0a, 0xe9, 0x0f, 0xdd, 0x7f, 0x44, + 0x58, 0xe3, 0x28, 0xdf, 0x49, 0x3f, 0xe2, 0xd4, 0x2d, 0x2f, 0x07, 0xc1, 0x22, + 0xf3, 0xc2, 0x00, 0xda, 0x99, 0xff, 0xea, 0xb5, 0xf4, 0x35, 0xbe, 0xf1, 0xf3, + 0x12, 0xf2, 0x1e, 0x2e, 0xfd, 0xf0, 0xb2, 0xcf, 0xf7, 0xb4, 0x3f, 0x8a, 0xd8, + 0xd4, 0xe8, 0xf4, 0x14, 0xc6, 0x08, 0xf8, 0xf4, 0x0b, 0xdd, 0xf1, 0xef, 0x07, + 0x07, 0xf5, 0x08, 0x15, 0xe0, 0xdd, 0x37, 0x01, 0xf8, 0xcd, 0xac, 0x19, 0x2e, + 0xd5, 0x14, 0x1f, 0xaa, 0x15, 0x0d, 0x29, 0x1b, 0x28, 0xd2, 0xe0, 0xe6, 0x19, + 0x29, 0xd7, 0x16, 0x1e, 0x1c, 0x5b, 0x40, 0x2e, 0x18, 0x36, 0x02, 0x07, 0x58, + 0x31, 0x81, 0xb7, 0x20, 0xd4, 0x01, 0xe2, 0xaf, 0x44, 0xfd, 0x38, 0x98, 0x46, + 0xa7, 0x50, 0xf4, 0xe0, 0x31, 0xf4, 0xd9, 0x24, 0x26, 0x17, 0x59, 0x30, 0xaa, + 0xc3, 0xf5, 0xf2, 0xf2, 0xe6, 0x32, 0xfe, 0x45, 0x38, 0xa1, 0xc8, 0xee, 0xf2, + 0xce, 0x10, 0xc5, 0x0f, 0xc1, 0xcf, 0x08, 0xd9, 0x3b, 0x2a, 0xb8, 0x3b, 0x0d, + 0xff, 0x3d, 0x08, 0x12, 0x37, 0xed, 0xae, 0x1d, 0x0d, 0xd3, 0xa8, 0x0c, 0x19, + 0xa6, 0x1a, 0x07, 0xe5, 0xdc, 0xf2, 0xd6, 0x67, 0x1d, 0xed, 0x44, 0xe3, 0x1e, + 0xf5, 0xcf, 0x06, 0xfa, 0xff, 0xc3, 0x26, 0xe0, 0xe2, 0xd2, 0xf5, 0x01, 0x38, + 0xf8, 0x20, 0x47, 0xc9, 0xfe, 0x2f, 0xb0, 0xcc, 0xf2, 0x22, 0x60, 0x95, 0x0f, + 0x26, 0xa1, 0x00, 0xdd, 0xfc, 0xf2, 0xff, 0xd1, 0x0e, 0xe5, 0x08, 0xc6, 0xdc, + 0x1a, 0xec, 0x35, 0xdc, 0xe5, 0x01, 0xba, 0xdb, 0xf3, 0xde, 0x07, 0x26, 0x0b, + 0xf0, 0x02, 0x10, 0x08, 0xe1, 0x1b, 0x0c, 0xac, 0xc9, 0xfb, 0xef, 0xd8, 0x92, + 0x07, 0x1b, 0x38, 0xf3, 0xdc, 0xb6, 0xc4, 0xe5, 0x13, 0xc0, 0xc4, 0x3e, 0xd3, + 0xdd, 0xf0, 0xdd, 0xdc, 0x01, 0x1a, 0xd6, 0x15, 0x9a, 0x19, 0x19, 0xe7, 0x32, + 0xb3, 0x0a, 0xe4, 0x04, 0xc9, 0x1b, 0x05, 0xf9, 0xdd, 0xd7, 0xf0, 0x09, 0x02, + 0xb1, 0xaf, 0xad, 0xca, 0xfd, 0x10, 0x90, 0x1b, 0xc8, 0x37, 0x05, 0xcf, 0xb2, + 0x97, 0xec, 0xf4, 0x38, 0xd6, 0xeb, 0xe2, 0xf0, 0x0c, 0x53, 0x1e, 0xec, 0xbc, + 0x2d, 0x27, 0xa9, 0xec, 0xe1, 0xff, 0x8a, 0xe0, 0xf9, 0x07, 0xcc, 0xda, 0xd6, + 0xdf, 0x00, 0xec, 0xef, 0x01, 0x0d, 0x00, 0xed, 0xe8, 0xe6, 0xd4, 0x12, 0x0f, + 0xfa, 0xcb, 0xfe, 0x31, 0xdc, 0x30, 0xce, 0x17, 0x02, 0xd0, 0xf1, 0xe2, 0xfb, + 0xff, 0xe3, 0x14, 0xf7, 0x0c, 0x07, 0x1f, 0xf4, 0xd4, 0xd2, 0xf4, 0x11, 0x06, + 0x1d, 0x05, 0xd6, 0x37, 0xeb, 0x10, 0xd9, 0xfa, 0xd4, 0xfe, 0x6d, 0x18, 0xf8, + 0xf9, 0x23, 0xcc, 0x35, 0xce, 0x07, 0xeb, 0xf2, 0xf6, 0x1e, 0x12, 0x06, 0x0e, + 0x07, 0x05, 0xe9, 0x01, 0x06, 0x36, 0xfb, 0x4c, 0xd9, 0x07, 0xd7, 0x22, 0xc9, + 0xcd, 0xff, 0x0a, 0x07, 0xfa, 0x3d, 0xd4, 0x08, 0xbd, 0xf1, 0x01, 0x06, 0xd8, + 0xdf, 0x07, 0x0f, 0xeb, 0xe7, 0x7b, 0xf2, 0xd7, 0xdd, 0xf0, 0xf3, 0x1e, 0x15, + 0x1d, 0xf9, 0xf1, 0xf1, 0x1f, 0xd1, 0xc5, 0xe7, 0xea, 0xcb, 0xe9, 0xd1, 0xed, + 0xf3, 0x14, 0x05, 0xee, 0x1f, 0x46, 0xf9, 0xeb, 0x1e, 0xc3, 0xea, 0x03, 0x10, + 0xc2, 0xe0, 0xbe, 0x13, 0xe3, 0x0e, 0xe4, 0xdd, 0x54, 0x12, 0x16, 0x07, 0x1e, + 0x04, 0x2d, 0x19, 0xf7, 0xf2, 0x12, 0xed, 0x1a, 0xda, 0x21, 0xf6, 0xfd, 0x11, + 0xeb, 0x02, 0xfe, 0x04, 0xef, 0xe3, 0x07, 0xf9, 0x33, 0xf0, 0xe6, 0xfc, 0x1f, + 0x0d, 0x2f, 0x02, 0x12, 0x2c, 0x22, 0x00, 0x1e, 0x01, 0x1c, 0xf7, 0x00, 0xdd, + 0xf3, 0x03, 0xf3, 0x0b, 0x02, 0xf3, 0xc5, 0x13, 0xd8, 0x1f, 0xf7, 0xe2, 0xf5, + 0x13, 0xfe, 0xd3, 0x22, 0xfa, 0x16, 0x07, 0x01, 0x05, 0x1e, 0xf3, 0xfd, 0xcd, + 0x14, 0x7f, 0x25, 0xf8, 0x50, 0xec, 0xcc, 0xef, 0xea, 0xda, 0xeb, 0x1f, 0xfa, + 0xe5, 0x12, 0xd1, 0x0f, 0xec, 0xc6, 0xd8, 0x36, 0x14, 0x16, 0x13, 0x03, 0xf8, + 0x04, 0xf8, 0xf6, 0xae, 0xe3, 0xeb, 0x05, 0xd3, 0x01, 0xf4, 0xf0, 0x07, 0xf7, + 0x2a, 0xd2, 0xf4, 0xe7, 0xee, 0x0a, 0xf9, 0x38, 0x47, 0xab, 0xc3, 0xad, 0xd0, + 0xc9, 0xb8, 0xc6, 0xd7, 0xdd, 0xfb, 0xe3, 0x28, 0xcf, 0xb6, 0xfb, 0x0d, 0x11, + 0x05, 0xd1, 0xdb, 0xf2, 0xe9, 0xf1, 0x1f, 0xf4, 0xe4, 0xfa, 0xe3, 0xeb, 0xc2, + 0x87, 0xef, 0xf8, 0x1d, 0xec, 0x08, 0x41, 0xaf, 0xff, 0xee, 0x1a, 0x13, 0x00, + 0xed, 0x2b, 0x1f, 0x00, 0x3a, 0xd1, 0x12, 0x0b, 0xfe, 0xff, 0xf8, 0x13, 0x77, + 0x17, 0x35, 0x90, 0xe0, 0x0c, 0x06, 0x62, 0x11, 0x68, 0xad, 0x17, 0xd2, 0x1e, + 0x06, 0xd8, 0xe8, 0x11, 0xf5, 0x14, 0xf1, 0xd0, 0xbd, 0xcb, 0xfd, 0x17, 0x81, + 0xeb, 0xcd, 0xc1, 0x01, 0xda, 0xae, 0x15, 0xd1, 0x58, 0xe3, 0x5e, 0x07, 0xa0, + 0xf1, 0xf6, 0x05, 0x03, 0xd9, 0xc2, 0xe5, 0xb7, 0xeb, 0xfc, 0xc1, 0xe5, 0x0e, + 0x0e, 0xc0, 0xd4, 0xc1, 0x0e, 0x1b, 0x1d, 0xf7, 0xe8, 0x07, 0xca, 0xd9, 0xf7, + 0xcb, 0x1a, 0xea, 0xd5, 0xec, 0x0f, 0xe1, 0xfb, 0xc0, 0xd5, 0xe7, 0xe8, 0x2f, + 0x06, 0xc2, 0xc8, 0x0d, 0xd6, 0xe9, 0xb3, 0x11, 0x14, 0xd4, 0x2a, 0xb6, 0x00, + 0x11, 0xbf, 0x1a, 0xb4, 0xfc, 0x37, 0xc8, 0xc4, 0xba, 0xab, 0x4f, 0x24, 0xcd, + 0x17, 0x29, 0xca, 0xc4, 0xcf, 0x31, 0xe7, 0xe7, 0x24, 0xe4, 0x19, 0xe6, 0xdf, + 0xe1, 0xeb, 0x2d, 0x09, 0xfa, 0xe4, 0xbd, 0xea, 0x03, 0x51, 0xff, 0x13, 0xbd, + 0xb2, 0x1e, 0x2b, 0xd0, 0xcd, 0xe9, 0x1e, 0x0b, 0x09, 0x1f, 0xd0, 0x2f, 0x0e, + 0x07, 0x1a, 0xd5, 0x09, 0x17, 0xbf, 0xc6, 0x23, 0xcf, 0x0d, 0x21, 0x90, 0x25, + 0x0b, 0x06, 0x12, 0xbd, 0xaf, 0x24, 0xd8, 0x1c, 0x08, 0x1f, 0x27, 0x0f, 0xf5, + 0x1d, 0xfa, 0xcc, 0x30, 0x27, 0xdf, 0xe2, 0x35, 0x0d, 0xce, 0xfb, 0x0f, 0x2f, + 0xf7, 0x9e, 0x38, 0xec, 0xf8, 0xde, 0xed, 0xf7, 0xfa, 0xf8, 0x51, 0xdc, 0x10, + 0x07, 0xe0, 0x16, 0xf1, 0xc8, 0xfa, 0x18, 0x29, 0x14, 0xce, 0xeb, 0xff, 0x04, + 0xde, 0xf0, 0x03, 0x9d, 0xf5, 0x92, 0x2a, 0x29, 0xe5, 0xe0, 0x1c, 0xf5, 0x21, + 0x67, 0x0a, 0x23, 0xed, 0x13, 0xd2, 0x28, 0x23, 0xe7, 0xbd, 0xf9, 0xfd, 0x10, + 0x3b, 0x14, 0xe5, 0x0d, 0x07, 0x31, 0x8c, 0x13, 0xfa, 0x49, 0x9a, 0xf8, 0x0e, + 0x22, 0xd3, 0xd6, 0xe4, 0x46, 0x01, 0x18, 0xfe, 0x0d, 0xd9, 0x21, 0x14, 0x1f, + 0xde, 0x90, 0xce, 0xfb, 0xe9, 0xf0, 0x18, 0xfb, 0xdc, 0x28, 0x02, 0xfc, 0x0b, + 0x06, 0xf6, 0xf1, 0x96, 0x15, 0x45, 0xc6, 0xd6, 0x12, 0x3f, 0xf6, 0xeb, 0xd8, + 0xda, 0xf4, 0x35, 0x18, 0xce, 0xc3, 0xeb, 0xa1, 0x93, 0x34, 0xf9, 0x14, 0x81, + 0x25, 0xdf, 0x2a, 0xe5, 0xd2, 0x1c, 0x24, 0xe4, 0x29, 0x28, 0xe8, 0xdc, 0x11, + 0xc3, 0xe8, 0x10, 0xee, 0xb8, 0xf8, 0xd0, 0x2d, 0xf0, 0x4a, 0x92, 0x2d, 0x01, + 0xf0, 0xd0, 0xf2, 0xce, 0x0f, 0x18, 0xe5, 0xbc, 0xbc, 0x2e, 0x48, 0xf9, 0xeb, + 0x35, 0x95, 0x2f, 0xef, 0xd9, 0x1e, 0xe3, 0x22, 0xca, 0xd5, 0x13, 0x31, 0xcc, + 0xa5, 0xbf, 0xaf, 0xf4, 0xdb, 0x2f, 0x50, 0x0b, 0x2d, 0x07, 0x3f, 0x54, 0x1a, + 0x31, 0xf5, 0x1a, 0xf8, 0xdc, 0xee, 0xe2, 0x20, 0xcb, 0x08, 0x01, 0xfe, 0xae, + 0xd5, 0x30, 0xec, 0xc2, 0xbd, 0xd0, 0x3f, 0xdd, 0x29, 0x14, 0xf2, 0x3d, 0xf0, + 0xe2, 0x1e, 0xfe, 0xaa, 0x20, 0x05, 0x09, 0xea, 0x2a, 0xfb, 0xee, 0xd8, 0x07, + 0xe8, 0x3a, 0xf0, 0x36, 0xed, 0xda, 0x1a, 0x17, 0x0c, 0x90, 0x0b, 0x07, 0x17, + 0xcc, 0xaa, 0x57, 0xda, 0xff, 0x37, 0x14, 0xf6, 0x4a, 0xd8, 0xe8, 0x3d, 0xef, + 0x0c, 0x87, 0x35, 0xb3, 0x01, 0x43, 0xfb, 0x19, 0x02, 0xd6, 0x4e, 0x02, 0x37, + 0x01, 0x04, 0x23, 0xb9, 0xcc, 0x83, 0x4d, 0xe6, 0xe4, 0xf1, 0x4d, 0xd1, 0xf5, + 0xd1, 0xcf, 0xe3, 0x0f, 0xd5, 0x05, 0x1c, 0xd8, 0x03, 0x2e, 0xf3, 0xd6, 0xfb, + 0x15, 0x09, 0xdd, 0xc2, 0xd6, 0x0b, 0x24, 0xe2, 0x1d, 0xc1, 0xdd, 0xfa, 0xee, + 0xc5, 0x30, 0xda, 0x15, 0xe3, 0xf5, 0x28, 0x12, 0xeb, 0xce, 0x96, 0xd4, 0x47, + 0x1d, 0x10, 0xc3, 0xd6, 0x00, 0xf5, 0xf7, 0xd5, 0x10, 0xe3, 0x0d, 0xd8, 0x08, + 0xee, 0x28, 0x0a, 0x23, 0xa6, 0x0f, 0xdf, 0x11, 0x3a, 0x1d, 0x25, 0x17, 0x4a, + 0x43, 0xea, 0xef, 0xfd, 0xcb, 0xfb, 0xce, 0x16, 0x19, 0x03, 0xf6, 0x47, 0xdf, + 0xd5, 0xd1, 0x08, 0x0a, 0xe8, 0x06, 0x11, 0x30, 0xdf, 0xdb, 0x14, 0x19, 0x1e, + 0x7f, 0xb2, 0xe7, 0x11, 0xe1, 0xfc, 0xf4, 0xf9, 0xdd, 0x09, 0x1e, 0xfa, 0xf0, + 0xee, 0xd4, 0xec, 0x0e, 0xb4, 0xe0, 0xea, 0x32, 0xbc, 0xff, 0xcb, 0x15, 0x4d, + 0x3e, 0xd5, 0x05, 0x12, 0x0c, 0x37, 0x91, 0xe3, 0x2d, 0x10, 0xdb, 0xe1, 0x40, + 0xf7, 0xf2, 0xf3, 0x11, 0x70, 0x07, 0x10, 0xe7, 0xcd, 0xd1, 0x05, 0x0e, 0x9f, + 0xc9, 0x1d, 0xf5, 0xf6, 0xe6, 0xfb, 0xe7, 0x2a, 0xde, 0x08, 0xff, 0xc5, 0xd0, + 0xd4, 0x1e, 0xe8, 0xe1, 0xd7, 0x9e, 0x0a, 0xd7, 0x5f, 0xf5, 0xec, 0xd7, 0xe5, + 0x2e, 0xea, 0xd6, 0x0f, 0xea, 0xe7, 0xd9, 0xf3, 0x0f, 0xbe, 0x1a, 0xea, 0xdf, + 0xce, 0xe0, 0xe3, 0xe7, 0x12, 0x02, 0x16, 0xff, 0x2e, 0xe2, 0x39, 0x56, 0xb8, + 0xdb, 0x24, 0xfe, 0x0f, 0x26, 0xda, 0x33, 0xe9, 0x19, 0xee, 0x0f, 0x2a, 0xe8, + 0xdf, 0x1e, 0xff, 0xb6, 0xed, 0x24, 0xa7, 0x54, 0x05, 0xfe, 0x0f, 0xc1, 0xfe, + 0x09, 0xc7, 0x10, 0x1c, 0xe5, 0xfb, 0x24, 0xf9, 0x1d, 0x31, 0xe0, 0xca, 0x16, + 0xec, 0xe9, 0x09, 0x55, 0xc1, 0xbf, 0xfc, 0x05, 0xf4, 0xf2, 0xe1, 0xe9, 0x01, + 0xf7, 0x47, 0x3d, 0x1f, 0xcc, 0x28, 0x00, 0xc9, 0xfc, 0xec, 0x41, 0xce, 0x41, + 0xf7, 0xc9, 0xd0, 0x12, 0x0a, 0x14, 0xff, 0x34, 0xd9, 0xe7, 0xe2, 0xea, 0x1b, + 0x24, 0x0f, 0xdc, 0x2b, 0x0b, 0xbb, 0xb4, 0x02, 0x18, 0x2c, 0xef, 0xe6, 0x0b, + 0xfd, 0xe1, 0xa6, 0x21, 0x81, 0xcd, 0x1a, 0xfc, 0xe1, 0x51, 0xfb, 0xf8, 0xbd, + 0x25, 0xcc, 0xce, 0x48, 0xdd, 0x27, 0xe4, 0xfc, 0x1a, 0xc0, 0xd5, 0x1b, 0x26, + 0x40, 0x24, 0xf0, 0xcf, 0x45, 0xe7, 0x0d, 0xbf, 0xae, 0xbc, 0xa9, 0xc1, 0xba, + 0xea, 0xdc, 0xdc, 0xca, 0xd3, 0x2e, 0xae, 0x68, 0x3a, 0x07, 0xe6, 0x1a, 0x10, + 0xe8, 0xd4, 0xc0, 0xbf, 0x70, 0xee, 0x2a, 0x1a, 0xd7, 0x4c, 0xb9, 0xdb, 0xa5, + 0x16, 0xee, 0x01, 0x07, 0xe9, 0x14, 0xd0, 0xc1, 0xff, 0xd4, 0x11, 0x46, 0xf5, + 0xe7, 0x06, 0x9c, 0xb3, 0x85, 0xcd, 0x14, 0xc3, 0xf2, 0xca, 0x35, 0xaa, 0xd5, + 0x66, 0xcf, 0xe6, 0xf1, 0xc7, 0xf2, 0x13, 0x28, 0xf3, 0x04, 0x27, 0x13, 0xff, + 0xef, 0x24, 0x10, 0xaa, 0x62, 0x0a, 0x9b, 0x11, 0x23, 0x04, 0xca, 0xdc, 0xf0, + 0xf3, 0xd0, 0x0c, 0x1f, 0xd0, 0x47, 0x03, 0xd6, 0xd3, 0x9b, 0x33, 0x1f, 0x1a, + 0xcf, 0xa9, 0x06, 0xe9, 0x3e, 0xf8, 0xf4, 0xf9, 0x38, 0x20, 0xff, 0x30, 0xdd, + 0xc5, 0xcb, 0xfe, 0x22, 0xe4, 0xfa, 0x13, 0x07, 0x2b, 0xfa, 0x38, 0x38, 0x32, + 0xb8, 0x0e, 0x33, 0x12, 0x06, 0x83, 0x02, 0x15, 0x16, 0xb3, 0xbe, 0xa6, 0xd4, + 0x11, 0x11, 0x42, 0xce, 0x06, 0xad, 0x13, 0xec, 0xf3, 0xd6, 0xf3, 0xf6, 0xe0, + 0xb5, 0xc2, 0xcf, 0xeb, 0xc0, 0x2b, 0xde, 0xcd, 0xff, 0xda, 0xfd, 0xed, 0x01, + 0xc6, 0xd1, 0x02, 0x83, 0xef, 0xeb, 0xdb, 0x00, 0xe2, 0xa6, 0x1e, 0xb9, 0xd1, + 0xe6, 0xe4, 0xd2, 0xa5, 0xea, 0xf6, 0xc5, 0x07, 0x26, 0x09, 0xfb, 0xef, 0xbc, + 0xb8, 0xcf, 0x19, 0xc1, 0x37, 0xf9, 0xb6, 0xd2, 0xa6, 0x24, 0xdf, 0xcf, 0xfc, + 0xac, 0xf6, 0xd5, 0x2d, 0x09, 0x1a, 0x1b, 0x10, 0xed, 0x09, 0xf4, 0xee, 0xfc, + 0xb0, 0x1b, 0xe4, 0x28, 0xed, 0xec, 0xcb, 0xc7, 0xf0, 0xd7, 0x4b, 0xda, 0x02, + 0x1e, 0x31, 0x03, 0xb7, 0xe7, 0xe6, 0xcf, 0xf1, 0x13, 0xf9, 0x9c, 0x0d, 0x20, + 0xe1, 0x6c, 0xf6, 0xe8, 0x53, 0x6e, 0x03, 0xf9, 0x04, 0x17, 0x1d, 0x01, 0xe7, + 0xee, 0xcb, 0xc1, 0x09, 0x0c, 0x19, 0xf1, 0x21, 0xe3, 0xdd, 0x1f, 0xea, 0xef, + 0x15, 0xdb, 0x1b, 0xf4, 0x38, 0x3d, 0x04, 0x3e, 0x21, 0xf4, 0xff, 0xe3, 0xe1, + 0xed, 0x4b, 0x07, 0xfc, 0x00, 0xfe, 0x22, 0x2f, 0x07, 0x32, 0xea, 0xd9, 0xcb, + 0xf7, 0xfd, 0xf7, 0xb0, 0x09, 0xed, 0xe1, 0xfc, 0x2b, 0x35, 0xf2, 0x08, 0xfd, + 0x0c, 0x4b, 0x07, 0xd1, 0x39, 0xdf, 0xf0, 0x2b, 0xd3, 0x06, 0xd0, 0xd6, 0xde, + 0xef, 0x08, 0x0f, 0x18, 0xa1, 0xed, 0xe9, 0xff, 0xf5, 0xf4, 0xd0, 0xba, 0x57, + 0xc5, 0xe9, 0xd1, 0xe9, 0x22, 0x14, 0xfd, 0x04, 0xec, 0x0f, 0xfb, 0xe9, 0xdd, + 0xd2, 0xc4, 0xe2, 0xde, 0xfd, 0x0d, 0xf8, 0x6f, 0xf9, 0xf8, 0x02, 0xd6, 0xb6, + 0xf1, 0xeb, 0xe5, 0xf9, 0x0b, 0xe7, 0x48, 0x11, 0x02, 0x3d, 0xf4, 0x2c, 0xf4, + 0xf8, 0x49, 0xf3, 0xf1, 0x06, 0xf6, 0x3b, 0xe1, 0xd3, 0xdb, 0xc5, 0xb3, 0xee, + 0x54, 0x33, 0x04, 0xdf, 0x4f, 0x5e, 0xfe, 0x49, 0xf0, 0x17, 0xa7, 0xe8, 0x0b, + 0xe3, 0x3c, 0xed, 0x25, 0x03, 0xfc, 0x17, 0x09, 0xf0, 0xe3, 0x12, 0xf5, 0xe1, + 0xd7, 0x1a, 0x1d, 0xfe, 0x11, 0xf2, 0x11, 0x06, 0xca, 0x13, 0xdb, 0xed, 0xe7, + 0x22, 0x24, 0x1d, 0xed, 0xdb, 0x11, 0x13, 0xfe, 0x15, 0x0c, 0xf8, 0xc6, 0xf5, + 0x16, 0x99, 0xe5, 0xf3, 0x09, 0x22, 0x42, 0x3d, 0x0c, 0x7f, 0xe2, 0xfc, 0x14, + 0xda, 0xeb, 0x01, 0xf4, 0x0c, 0x0d, 0x03, 0x22, 0x04, 0x04, 0xed, 0xef, 0xda, + 0x1c, 0xd4, 0xe2, 0xd9, 0xf2, 0x24, 0xde, 0x11, 0xef, 0x11, 0xf9, 0xf4, 0xff, + 0xd3, 0xee, 0x0e, 0xe5, 0x08, 0x0e, 0xe3, 0x17, 0x05, 0xfd, 0xde, 0xf9, 0xfc, + 0x09, 0xe5, 0x21, 0xce, 0xe2, 0x26, 0xfa, 0x23, 0xec, 0x04, 0x02, 0x09, 0x41, + 0x20, 0x0e, 0x1e, 0xf2, 0xf0, 0x12, 0x08, 0x08, 0x04, 0x00, 0xf8, 0xe0, 0x0b, + 0xe3, 0xf5, 0x15, 0xfa, 0xf9, 0x1d, 0x1e, 0x02, 0xf6, 0x44, 0xe6, 0xe3, 0xce, + 0xf6, 0xd4, 0xc8, 0xf5, 0x27, 0x29, 0xfd, 0x3f, 0x08, 0x0b, 0xe4, 0x17, 0xf9, + 0x11, 0xd5, 0xee, 0x2f, 0x13, 0xce, 0xd2, 0x34, 0x00, 0xed, 0xe0, 0xf5, 0xf8, + 0x38, 0x0a, 0x15, 0xf6, 0xde, 0xfd, 0x0d, 0xe5, 0xe0, 0xe4, 0x0f, 0xe1, 0xe7, + 0xd8, 0xfd, 0xf6, 0x15, 0x0f, 0xf9, 0x00, 0x49, 0x06, 0xd2, 0x04, 0xc8, 0xed, + 0xfc, 0x18, 0xf1, 0xef, 0xf6, 0x2a, 0xe7, 0x04, 0xeb, 0xe5, 0x51, 0x20, 0x1c, + 0x08, 0xed, 0xfb, 0xfd, 0x33, 0xf8, 0xfb, 0xf9, 0x15, 0xfa, 0xf6, 0xf6, 0x04, + 0xdf, 0x1d, 0xfd, 0xf0, 0x19, 0xf0, 0xfa, 0x0f, 0x0e, 0x1b, 0x22, 0x12, 0xeb, + 0x02, 0xf5, 0xde, 0x12, 0x07, 0x07, 0x24, 0x38, 0xf6, 0xef, 0xe5, 0x21, 0xe8, + 0xe6, 0xce, 0xe1, 0xf8, 0x00, 0x24, 0xe5, 0xe5, 0xdf, 0x0d, 0xf6, 0xfc, 0x19, + 0xfb, 0x15, 0xe8, 0xf9, 0xfa, 0x32, 0x04, 0x0e, 0x02, 0x06, 0x07, 0xf6, 0xfc, + 0xef, 0x01, 0x1f, 0x7f, 0x1f, 0xe8, 0xfd, 0x0e, 0xe6, 0x0c, 0xf9, 0xe0, 0xe4, + 0xef, 0xe7, 0xeb, 0xed, 0xf4, 0x08, 0xe8, 0xda, 0xd1, 0x16, 0x11, 0x04, 0x00, + 0x16, 0xf6, 0x19, 0xf9, 0xf0, 0xc6, 0xf0, 0xff, 0xff, 0xf1, 0x17, 0xf1, 0xf6, + 0xde, 0xf5, 0x10, 0xbc, 0xe7, 0xdc, 0x21, 0x09, 0xec, 0xc0, 0xea, 0x93, 0xaf, + 0xc2, 0x0a, 0x9c, 0xdf, 0xe9, 0x15, 0x93, 0xbc, 0x1f, 0x94, 0xaf, 0x0c, 0xe2, + 0x4d, 0xe1, 0x1a, 0x0d, 0xd9, 0xd2, 0xf8, 0xd1, 0xe5, 0xf1, 0x1c, 0xc5, 0xc3, + 0x96, 0xc2, 0x05, 0xbe, 0x1f, 0xee, 0xee, 0x02, 0xac, 0xd3, 0x3c, 0x10, 0xe0, + 0x51, 0x08, 0xdd, 0x19, 0x3e, 0xde, 0xd5, 0xb6, 0xf2, 0xf3, 0xf1, 0xf1, 0x92, + 0x1c, 0x12, 0x59, 0x63, 0x3e, 0x34, 0xc6, 0xc6, 0xaf, 0x24, 0xf8, 0x23, 0x45, + 0x22, 0x30, 0xde, 0x2b, 0xeb, 0xea, 0xe5, 0x13, 0x0d, 0xbd, 0xac, 0xb4, 0xc3, + 0x4a, 0x58, 0xd7, 0x6c, 0xd3, 0xcd, 0x0a, 0xb8, 0xe7, 0x33, 0xd8, 0xce, 0xfa, + 0xc1, 0x05, 0xe8, 0x3d, 0xf4, 0xa1, 0x14, 0xe0, 0xf3, 0xb4, 0xf8, 0x12, 0xf3, + 0xa3, 0x26, 0x50, 0xd4, 0xf5, 0xb4, 0xed, 0x09, 0xda, 0xfc, 0xbc, 0xd0, 0xa8, + 0x0a, 0x11, 0xe6, 0xed, 0xfb, 0xf7, 0x30, 0xab, 0x00, 0x81, 0x33, 0x16, 0x47, + 0xee, 0x01, 0x0d, 0x14, 0x14, 0x17, 0xe7, 0xc0, 0xd0, 0xc8, 0x1c, 0x2c, 0x15, + 0xab, 0x4b, 0xb3, 0xdf, 0xd5, 0x6d, 0xe1, 0xb7, 0xa5, 0x56, 0xfa, 0x2a, 0xb3, + 0x06, 0xae, 0x33, 0xf5, 0xde, 0xe1, 0x03, 0x25, 0x13, 0xb8, 0xda, 0xcf, 0xfe, + 0x4c, 0x85, 0x97, 0x1d, 0xd1, 0xd6, 0xba, 0xd2, 0x11, 0xe2, 0x20, 0xe2, 0xb1, + 0xf9, 0x15, 0x08, 0xfa, 0x27, 0xfc, 0x9e, 0xc0, 0xb6, 0x3a, 0xdf, 0x60, 0xcd, + 0x16, 0xec, 0x3c, 0xb4, 0xda, 0xd3, 0x64, 0xca, 0xf7, 0x3d, 0x10, 0x9a, 0x46, + 0xdd, 0x52, 0x38, 0xda, 0xe0, 0xd6, 0xc7, 0xeb, 0xf6, 0x11, 0x1a, 0x57, 0x37, + 0x1e, 0x4e, 0xf9, 0xdd, 0xea, 0xc1, 0x25, 0xd9, 0xf1, 0x04, 0x12, 0x30, 0xed, + 0x08, 0x01, 0x0f, 0xa7, 0x00, 0xe3, 0x93, 0x5a, 0x10, 0xca, 0xd3, 0xca, 0x0f, + 0x1f, 0xc8, 0xe9, 0x1b, 0x95, 0xd3, 0xe3, 0x04, 0xed, 0x06, 0xf7, 0x03, 0x22, + 0x06, 0x0e, 0xda, 0xee, 0xed, 0x49, 0xca, 0xe0, 0xa3, 0xf4, 0xfb, 0xe2, 0x35, + 0xa2, 0x11, 0xca, 0x14, 0xf2, 0xec, 0x23, 0x31, 0xba, 0x01, 0x10, 0x0e, 0x66, + 0x15, 0x0f, 0x18, 0x20, 0xe0, 0x20, 0x07, 0x0e, 0xb4, 0xf3, 0x1f, 0xd4, 0x12, + 0xb1, 0x2f, 0xaa, 0xed, 0xf9, 0x2c, 0xdb, 0x1f, 0x26, 0xe4, 0x48, 0xf2, 0x0c, + 0x3b, 0xd1, 0x20, 0xb8, 0x15, 0xc5, 0xda, 0x11, 0xf4, 0xfd, 0x04, 0xef, 0x2f, + 0x26, 0x25, 0xd7, 0xfe, 0xd6, 0x02, 0xd4, 0xdd, 0xd5, 0x37, 0x08, 0x07, 0xb6, + 0x01, 0x16, 0xe7, 0x16, 0x10, 0x1c, 0xf2, 0xbb, 0xfc, 0x77, 0x01, 0xc2, 0x31, + 0xe8, 0xdb, 0xfb, 0xd8, 0xe0, 0x50, 0x1e, 0x47, 0xe4, 0x02, 0x1c, 0x15, 0x10, + 0xba, 0xf0, 0xcc, 0x22, 0xc3, 0xb8, 0xd0, 0xd3, 0x0e, 0x00, 0xb7, 0x13, 0x7b, + 0xf8, 0xf7, 0xfe, 0xf4, 0x0d, 0xd1, 0x25, 0xec, 0xd2, 0xbc, 0x2c, 0xe5, 0x43, + 0x22, 0x09, 0x0e, 0xce, 0xe1, 0xfe, 0x08, 0xf3, 0x0c, 0x09, 0x22, 0x03, 0xce, + 0x0e, 0xd9, 0x2e, 0x2c, 0xfb, 0xf4, 0x16, 0xe9, 0xfa, 0xd5, 0xeb, 0xe6, 0x22, + 0x38, 0x02, 0x59, 0x23, 0xd9, 0x17, 0xf9, 0xe1, 0x2d, 0x2b, 0xef, 0x37, 0x01, + 0xe8, 0x07, 0xf3, 0x17, 0x21, 0x07, 0x93, 0xe7, 0xe4, 0xff, 0x0c, 0xeb, 0xf6, + 0x96, 0x11, 0x0c, 0x49, 0xf7, 0xed, 0xfd, 0xeb, 0xd9, 0xbc, 0x24, 0xeb, 0xe3, + 0xb1, 0xf7, 0x67, 0xd0, 0xfa, 0x25, 0xc1, 0x28, 0x5b, 0x7f, 0xd1, 0xfa, 0xd8, + 0xc7, 0xe9, 0x42, 0xb6, 0xde, 0x23, 0xe6, 0xe5, 0x24, 0xe2, 0x11, 0xe7, 0xda, + 0x09, 0x3b, 0xed, 0x00, 0x38, 0xe6, 0xc3, 0xdc, 0xe3, 0xd9, 0xb5, 0xfd, 0x06, + 0x03, 0xde, 0x04, 0x0e, 0xf2, 0x1d, 0xe6, 0xfc, 0x98, 0xfc, 0xd8, 0x36, 0x16, + 0x00, 0x13, 0xd8, 0xf0, 0x10, 0x23, 0x3a, 0xf4, 0xe9, 0x02, 0xdc, 0xf8, 0x13, + 0xba, 0x1c, 0xd7, 0x19, 0x2e, 0x13, 0x09, 0x11, 0xeb, 0xce, 0xd0, 0xf5, 0x9e, + 0xf3, 0xfc, 0x3d, 0x2b, 0xf5, 0xdf, 0xf8, 0xcf, 0xd4, 0xf9, 0xea, 0xc8, 0x39, + 0x0d, 0xf8, 0x00, 0x4a, 0x13, 0xbe, 0x29, 0x1b, 0xb0, 0x14, 0x0e, 0xfd, 0xfc, + 0xd9, 0x03, 0xa4, 0xed, 0xf3, 0x03, 0x01, 0xda, 0x13, 0xf2, 0xd4, 0xf8, 0x1b, + 0x32, 0x18, 0xe1, 0x3d, 0xc7, 0xdd, 0xd3, 0x2f, 0x07, 0xa9, 0xe8, 0x19, 0xd4, + 0xf5, 0xfd, 0xf2, 0xe1, 0xbc, 0x0b, 0xa7, 0x06, 0xd7, 0x0a, 0xe9, 0x20, 0xfc, + 0x0f, 0x04, 0xfb, 0xbd, 0xdb, 0xf5, 0x05, 0x03, 0x51, 0x62, 0xee, 0xe4, 0x23, + 0xfb, 0xf6, 0x03, 0xfb, 0x4a, 0x2a, 0xde, 0xe2, 0xb3, 0xfc, 0xcf, 0xfa, 0xfc, + 0xc3, 0xea, 0xf9, 0xf5, 0xfc, 0xf1, 0xf1, 0x21, 0x38, 0x08, 0xbd, 0xf6, 0x55, + 0x09, 0xd2, 0xf7, 0xde, 0xe7, 0x1e, 0xf7, 0x56, 0x15, 0xda, 0x81, 0x30, 0xef, + 0x9f, 0xe8, 0xdf, 0xbc, 0x03, 0x08, 0x08, 0xfb, 0x10, 0xdd, 0xf9, 0x27, 0xd5, + 0xc0, 0xbc, 0xda, 0x04, 0xff, 0x2a, 0x2b, 0xe4, 0x20, 0xd4, 0x4e, 0xf3, 0xf2, + 0x53, 0xf7, 0xde, 0xea, 0x01, 0xe9, 0xe9, 0x08, 0xee, 0xd0, 0x11, 0x17, 0x23, + 0xcf, 0xf8, 0xd2, 0x00, 0xdb, 0xe1, 0xf7, 0x06, 0x0c, 0xf1, 0xdf, 0xe7, 0xfc, + 0xb6, 0xe3, 0xef, 0xe0, 0x41, 0xd9, 0x13, 0xcc, 0xda, 0xe9, 0xf8, 0x1f, 0xdc, + 0x03, 0xf3, 0xb3, 0xe9, 0xb8, 0xca, 0xe0, 0x1c, 0xaf, 0x1b, 0x21, 0x23, 0x1b, + 0xf0, 0xfa, 0x06, 0xec, 0x0f, 0x12, 0x18, 0xd4, 0xfe, 0xf8, 0x29, 0xdc, 0xed, + 0xf8, 0xf7, 0xdc, 0x32, 0x07, 0x22, 0xe8, 0xf3, 0xc4, 0xef, 0xe9, 0x34, 0xfe, + 0xe8, 0x4d, 0x0b, 0xf7, 0x14, 0xda, 0xef, 0xb3, 0x11, 0x24, 0xf0, 0xa9, 0xba, + 0xf9, 0xf6, 0x0a, 0xd5, 0x13, 0xf4, 0x2a, 0x2c, 0x1c, 0x05, 0xe7, 0x30, 0xd6, + 0x3f, 0xe2, 0xe6, 0x78, 0x4d, 0xd0, 0xd9, 0x2b, 0x1a, 0xd7, 0x14, 0x17, 0xe9, + 0x81, 0x13, 0x2e, 0xf9, 0xcb, 0xd2, 0xe6, 0x0b, 0xb2, 0x0a, 0xc8, 0xb1, 0xf2, + 0xb2, 0xd8, 0xe6, 0xf8, 0x0f, 0xad, 0xcb, 0xc6, 0xc6, 0xad, 0x56, 0x3b, 0x27, + 0xdc, 0xd6, 0x39, 0xf5, 0xf8, 0x34, 0x1d, 0xdd, 0x3b, 0xd4, 0xeb, 0x15, 0xbe, + 0xf4, 0x1b, 0x08, 0xf0, 0xe6, 0xc7, 0x29, 0x1e, 0x18, 0xc0, 0x10, 0xac, 0xf2, + 0xae, 0x24, 0xeb, 0xfc, 0xfd, 0x06, 0xfa, 0xe1, 0x08, 0xae, 0x26, 0xd4, 0xf9, + 0x41, 0xd4, 0xcd, 0xff, 0x64, 0xff, 0xce, 0xdd, 0xe4, 0xeb, 0xde, 0xf5, 0x4c, + 0x28, 0x02, 0xe2, 0x7a, 0x0d, 0xa5, 0x35, 0x46, 0xa5, 0xfa, 0x07, 0x11, 0x07, + 0x54, 0x0c, 0x05, 0x00, 0x11, 0x01, 0xfa, 0x0b, 0x09, 0xa1, 0x16, 0xfc, 0xa9, + 0xf4, 0x01, 0x35, 0xee, 0x05, 0x3d, 0xec, 0x0e, 0x0c, 0xf6, 0x1b, 0x3a, 0x1c, + 0x17, 0x58, 0xf2, 0x1a, 0x16, 0xea, 0x08, 0x20, 0xfa, 0x3c, 0xef, 0x0d, 0x0b, + 0xf9, 0x0a, 0xef, 0x87, 0xff, 0xeb, 0x07, 0xfd, 0x24, 0x0b, 0xc2, 0xfd, 0x1d, + 0xc0, 0x0f, 0xe7, 0x5d, 0x08, 0x00, 0xc9, 0x1a, 0xea, 0xe8, 0xda, 0xca, 0xe5, + 0x24, 0x3b, 0x18, 0xf8, 0xa4, 0xd0, 0x15, 0x0c, 0xeb, 0x11, 0xfc, 0xfc, 0x11, + 0xf2, 0x28, 0x0c, 0xd6, 0x40, 0x2b, 0xf8, 0x0d, 0x66, 0x1c, 0x0a, 0xf1, 0xf7, + 0x29, 0xf6, 0x05, 0x32, 0xd2, 0xec, 0x07, 0xff, 0xa3, 0x1b, 0x36, 0x5b, 0xd3, + 0x36, 0xd1, 0x07, 0xdd, 0xde, 0x29, 0x1e, 0x22, 0x18, 0xb5, 0xd7, 0xd9, 0x08, + 0xe8, 0x15, 0x90, 0xc3, 0x18, 0x11, 0xcc, 0x1f, 0x29, 0xd5, 0xf7, 0xbd, 0x22, + 0xcc, 0xbd, 0xc2, 0x0e, 0x09, 0x47, 0xcd, 0xa6, 0xc6, 0xbf, 0xd2, 0x1d, 0xee, + 0x36, 0xf7, 0xd4, 0xc2, 0x0d, 0x1b, 0x1f, 0x05, 0xfe, 0x0e, 0xb9, 0xe3, 0x1b, + 0x34, 0x44, 0xe1, 0xeb, 0xbc, 0x3c, 0xec, 0x25, 0x1b, 0xb4, 0x26, 0xc3, 0xdf, + 0x27, 0x1d, 0xed, 0xfc, 0xf9, 0x31, 0x2c, 0xee, 0x09, 0xea, 0xef, 0x02, 0xeb, + 0x0e, 0xe2, 0xc0, 0x09, 0xf0, 0x0f, 0xff, 0xf1, 0x50, 0x11, 0xf7, 0x54, 0xe9, + 0xc5, 0x34, 0xbf, 0x21, 0x01, 0xc5, 0x99, 0x14, 0xe1, 0x0a, 0xeb, 0x03, 0xbb, + 0xe7, 0xd1, 0xf7, 0xe7, 0x03, 0xd9, 0xff, 0x9e, 0x33, 0x17, 0x05, 0x1a, 0x30, + 0xfd, 0x3f, 0x0d, 0xdf, 0xe6, 0x18, 0x15, 0x21, 0xcb, 0x0f, 0x06, 0xcf, 0x9f, + 0x5b, 0x0f, 0x13, 0xf9, 0xcf, 0x67, 0x45, 0x0d, 0xf8, 0xc0, 0xd6, 0x02, 0x19, + 0x03, 0xa6, 0xbc, 0xfe, 0xe7, 0xea, 0x03, 0xb7, 0xba, 0x63, 0x16, 0xcb, 0x06, + 0x50, 0x1a, 0x09, 0x1a, 0x0d, 0x0d, 0xf0, 0xc5, 0xce, 0xfd, 0x9f, 0xbb, 0x12, + 0xfb, 0x08, 0xfe, 0x11, 0x08, 0xe5, 0x7f, 0x5c, 0x1e, 0x29, 0x20, 0x05, 0x21, + 0xfb, 0xcd, 0xe8, 0x2e, 0x24, 0xe7, 0x1b, 0x32, 0xd1, 0x05, 0xeb, 0xce, 0xdc, + 0x0e, 0xfb, 0xec, 0xf0, 0x15, 0xc2, 0xe6, 0xdc, 0xe0, 0x33, 0x2a, 0xd1, 0x37, + 0x0b, 0x4a, 0x01, 0xb8, 0xb0, 0xe6, 0xd6, 0xf5, 0x05, 0x0c, 0x11, 0xcd, 0xcc, + 0xd1, 0xb0, 0xfa, 0x14, 0x2e, 0x2e, 0x02, 0xe4, 0x01, 0xd0, 0xf7, 0xca, 0x60, + 0xa9, 0xe4, 0x1f, 0xe3, 0x4f, 0x2c, 0xfe, 0xfc, 0xbb, 0xe6, 0xcb, 0x00, 0xf4, + 0xe6, 0xdd, 0x21, 0xf0, 0xcb, 0xa5, 0x10, 0x3f, 0xe3, 0xf8, 0xaa, 0x26, 0x06, + 0xd1, 0xee, 0xda, 0xfd, 0x3b, 0xf4, 0xb9, 0xe0, 0xf4, 0xbd, 0xf0, 0xe5, 0xdd, + 0xb2, 0xf9, 0xfb, 0xce, 0xfa, 0x2a, 0xe3, 0x13, 0xd3, 0x07, 0xe1, 0xcb, 0xf8, + 0xd9, 0xed, 0xff, 0xb0, 0xc4, 0xc6, 0x1e, 0xdf, 0xe5, 0x14, 0xbf, 0xe0, 0xe4, + 0xf6, 0x04, 0xbd, 0xd4, 0x1f, 0xc9, 0xd0, 0xdd, 0xf3, 0xe9, 0x32, 0x23, 0x20, + 0xd3, 0x15, 0x25, 0x11, 0xa9, 0x2a, 0xcb, 0x29, 0xde, 0xfe, 0x03, 0xe2, 0x1c, + 0x24, 0xbe, 0xfb, 0x2f, 0x26, 0x06, 0xb9, 0x28, 0x3a, 0xd8, 0x3b, 0x1c, 0xe7, + 0x05, 0x06, 0xf9, 0xd7, 0x0c, 0xf9, 0xe5, 0x17, 0xf7, 0x36, 0x48, 0xfc, 0x12, + 0xe9, 0x9e, 0x09, 0xb8, 0x01, 0xf5, 0x1f, 0xd4, 0x3b, 0x12, 0x00, 0xd1, 0x09, + 0xeb, 0x32, 0xfb, 0xb0, 0x3c, 0x81, 0x17, 0x4c, 0x15, 0xfd, 0x0c, 0x2e, 0xcd, + 0x1f, 0x0f, 0x48, 0x20, 0x48, 0xda, 0xd0, 0xeb, 0xe6, 0x1a, 0xf6, 0xb2, 0xfd, + 0xc3, 0xd4, 0x01, 0x2c, 0xe2, 0xeb, 0xbc, 0x3c, 0xc7, 0xee, 0x0d, 0x21, 0xbb, + 0x0d, 0xf6, 0xda, 0x0a, 0xc5, 0x0d, 0x21, 0x10, 0xeb, 0xdc, 0x06, 0xf0, 0xd8, + 0xc5, 0x1a, 0x1a, 0xc5, 0x1f, 0xf4, 0xe3, 0x24, 0x9c, 0xb1, 0xcb, 0xc3, 0xe4, + 0xcd, 0xe4, 0xe7, 0x2c, 0x23, 0x30, 0xcb, 0xba, 0xc1, 0xf6, 0xab, 0x0b, 0xdc, + 0xaf, 0xd1, 0x13, 0x1f, 0x2c, 0x22, 0x22, 0xb9, 0xfd, 0x0b, 0x10, 0x22, 0x42, + 0xf9, 0x22, 0x02, 0xcf, 0xea, 0xe1, 0x35, 0x6a, 0x05, 0xd9, 0xb7, 0xfa, 0xb2, + 0xff, 0xf0, 0xd2, 0xcf, 0x12, 0xe9, 0xf8, 0x59, 0xd7, 0xcc, 0xbf, 0xc2, 0x82, + 0xc8, 0xd7, 0xe7, 0xa6, 0x3a, 0x22, 0xc4, 0x0e, 0x23, 0xf1, 0xd6, 0x29, 0xf4, + 0xda, 0xd6, 0xfe, 0x08, 0x00, 0x17, 0x06, 0x2a, 0x17, 0xca, 0xe2, 0x37, 0xde, + 0x10, 0x19, 0xe4, 0x38, 0x06, 0x07, 0xce, 0xfc, 0x1b, 0x43, 0xe0, 0xcf, 0xb9, + 0xa3, 0x20, 0x4d, 0xd8, 0x4a, 0xcc, 0x19, 0xe2, 0xb7, 0x18, 0xce, 0xd5, 0xeb, + 0xda, 0x11, 0x9c, 0xdc, 0xe9, 0x29, 0xca, 0xa6, 0xf5, 0x14, 0xe1, 0x1d, 0x1c, + 0xcb, 0xe3, 0x59, 0xf8, 0xcc, 0x4f, 0xd1, 0x4b, 0x16, 0xad, 0x14, 0xaf, 0x95, + 0xcf, 0x39, 0xfc, 0x1e, 0xb2, 0x1f, 0xeb, 0xfb, 0x3d, 0xff, 0xf8, 0xfd, 0xec, + 0x8b, 0x40, 0x2b, 0x10, 0xbf, 0xf6, 0xf5, 0xcc, 0x2f, 0xca, 0x2a, 0xf8, 0x9b, + 0x1a, 0xf5, 0xce, 0x1e, 0xf6, 0x25, 0xc5, 0x25, 0xe7, 0x84, 0xda, 0xc3, 0x1b, + 0xb5, 0xd6, 0x29, 0x36, 0x23, 0xaf, 0x00, 0x30, 0xe6, 0xa3, 0xd4, 0xbb, 0xc6, + 0xb5, 0xd3, 0x14, 0x14, 0x18, 0x1f, 0x30, 0x16, 0x37, 0xcf, 0xd9, 0xe6, 0xf8, + 0xda, 0xa2, 0x39, 0x14, 0x09, 0x33, 0x08, 0xeb, 0xac, 0xcd, 0x04, 0xcd, 0x49, + 0x89, 0xf9, 0xc1, 0xc2, 0xc6, 0x37, 0xdf, 0xdd, 0x01, 0xbf, 0x27, 0xec, 0x1f, + 0xe4, 0x05, 0xed, 0xe7, 0xec, 0x0d, 0x03, 0x4e, 0x2d, 0xc3, 0xe6, 0xf4, 0x07, + 0xeb, 0x23, 0xc8, 0xa5, 0xfc, 0xc4, 0x09, 0xda, 0xf0, 0x3e, 0xbb, 0xf9, 0x06, + 0x05, 0xd6, 0x1c, 0xd0, 0x20, 0xf3, 0x34, 0x00, 0xab, 0xff, 0xfe, 0xdb, 0xdb, + 0xd1, 0xd5, 0xe7, 0xed, 0xf5, 0xec, 0xf2, 0x2b, 0x32, 0xa4, 0xf3, 0x4c, 0x21, + 0xca, 0x2c, 0xb5, 0xe7, 0xd4, 0xc3, 0xfa, 0x56, 0x52, 0x0c, 0x0b, 0xd0, 0xd1, + 0xf5, 0x14, 0xf7, 0xc3, 0xdd, 0x20, 0x05, 0xac, 0x13, 0x56, 0x08, 0xc2, 0xd1, + 0xe1, 0x11, 0x00, 0xfa, 0xe8, 0x84, 0xff, 0x06, 0xf8, 0x09, 0xf8, 0xf3, 0xc1, + 0xde, 0xef, 0xec, 0x26, 0xf2, 0xfe, 0x24, 0xf2, 0x0c, 0xd5, 0xd7, 0x05, 0x01, + 0xce, 0x2d, 0x0c, 0x03, 0x23, 0xf7, 0xeb, 0x01, 0x08, 0x32, 0x81, 0xcb, 0xc2, + 0xd0, 0x2b, 0xda, 0xf1, 0x63, 0x03, 0xde, 0xf4, 0x20, 0xcc, 0xe2, 0x28, 0xdf, + 0x6d, 0xf9, 0xb6, 0x19, 0x9d, 0xfc, 0xf6, 0xe4, 0xc5, 0xdb, 0x06, 0xa6, 0x08, + 0xf0, 0x48, 0xf4, 0xfd, 0x20, 0xf7, 0x08, 0xb2, 0xc2, 0x00, 0xe8, 0xec, 0xbe, + 0xad, 0xf2, 0x4e, 0xf4, 0xf8, 0xe0, 0x17, 0xd8, 0xa7, 0x0f, 0x01, 0x00, 0xe8, + 0xe7, 0x0e, 0xe9, 0xff, 0x2e, 0x17, 0xa4, 0x15, 0xdd, 0xfe, 0x25, 0xf1, 0x1b, + 0xe0, 0xf9, 0xb7, 0xdd, 0x11, 0xd5, 0xb8, 0xe5, 0xfb, 0x0a, 0xb1, 0xe2, 0x48, + 0x3d, 0xa4, 0x1e, 0xc9, 0x48, 0xbb, 0xe0, 0xd7, 0x28, 0xe5, 0x00, 0xca, 0x24, + 0x2c, 0xe1, 0xb2, 0x49, 0x17, 0xe3, 0xc7, 0x05, 0xf1, 0xcd, 0x5e, 0xf5, 0xf1, + 0xc2, 0xf2, 0x2a, 0xd6, 0x03, 0xd9, 0x2b, 0xf8, 0xe0, 0xbb, 0x04, 0xc5, 0xd8, + 0x1f, 0x0a, 0xf8, 0x34, 0x46, 0x19, 0x14, 0xc4, 0xde, 0xfb, 0xeb, 0xe7, 0x4b, + 0xe7, 0xd9, 0x07, 0xc3, 0x1f, 0xe7, 0xe2, 0xe8, 0x7b, 0x07, 0x0d, 0xf2, 0x20, + 0xfc, 0x24, 0xe8, 0xde, 0xfe, 0xe5, 0xf1, 0xe9, 0xdb, 0xcd, 0xbc, 0x00, 0x03, + 0xfd, 0xf5, 0xb2, 0xe6, 0xe6, 0xf5, 0x02, 0x93, 0xc8, 0x2f, 0x0d, 0xfb, 0x25, + 0xe7, 0xc2, 0x24, 0x40, 0xce, 0x95, 0xd3, 0xeb, 0xc8, 0x03, 0x0f, 0x5d, 0xdf, + 0xd8, 0xf3, 0xa6, 0x59, 0x08, 0xde, 0xd2, 0xfc, 0xc9, 0xe5, 0x07, 0x09, 0xe1, + 0xff, 0xf0, 0x0f, 0xf0, 0xc6, 0xe1, 0xb9, 0xe3, 0x1a, 0x01, 0xde, 0x3d, 0x96, + 0xc3, 0x57, 0xb8, 0xc1, 0xa8, 0x14, 0x51, 0x16, 0x0e, 0xfc, 0x17, 0xd8, 0xd0, + 0x27, 0x02, 0x17, 0x36, 0xd0, 0x95, 0xc8, 0xc4, 0xe7, 0x06, 0x2a, 0x14, 0xfc, + 0x36, 0xfa, 0x3c, 0x21, 0x59, 0xd7, 0x10, 0x0b, 0x1e, 0xde, 0x22, 0x19, 0xc9, + 0xd5, 0xf2, 0xe5, 0xd6, 0xeb, 0x06, 0xdd, 0xf1, 0xfc, 0x06, 0xdb, 0x81, 0xeb, + 0xd5, 0xdc, 0x12, 0xd4, 0xee, 0xfd, 0x96, 0xc9, 0x4e, 0xef, 0xf2, 0x9e, 0x20, + 0xe6, 0xbd, 0x04, 0xdc, 0xe3, 0x0b, 0x3c, 0xa8, 0x37, 0xd7, 0xe9, 0xc8, 0x48, + 0xb9, 0xf7, 0xd5, 0x32, 0x02, 0x15, 0xad, 0x30, 0xc2, 0xbf, 0x51, 0xe8, 0x40, + 0x1c, 0xf2, 0x47, 0xe9, 0xbd, 0xb0, 0xc9, 0xfc, 0x36, 0x00, 0x06, 0x1d, 0xe7, + 0xcb, 0xdb, 0x1c, 0x2a, 0xfd, 0xb3, 0x1e, 0x0c, 0x92, 0xef, 0xe8, 0x1a, 0x22, + 0x05, 0xdb, 0x0c, 0x06, 0xf3, 0x22, 0xe8, 0x3c, 0xfc, 0x4d, 0x02, 0x2b, 0x17, + 0x09, 0xde, 0xe8, 0x41, 0x01, 0x2a, 0xb9, 0x0e, 0xc4, 0xc5, 0xdf, 0x0c, 0xcc, + 0xaf, 0xd9, 0xb6, 0xf3, 0x4f, 0xe0, 0xf0, 0xd0, 0xef, 0xc5, 0x15, 0xb3, 0x2e, + 0xd9, 0xd7, 0x54, 0x08, 0x49, 0xff, 0x2a, 0x0d, 0xe7, 0xd2, 0xfd, 0xe0, 0x0b, + 0xbd, 0xea, 0xbc, 0x13, 0xde, 0xad, 0x14, 0x2a, 0xa6, 0x81, 0x32, 0x29, 0x25, + 0xed, 0x49, 0xa3, 0x04, 0x0e, 0x06, 0x1d, 0x08, 0x22, 0x24, 0x01, 0xd0, 0xb5, + 0xe7, 0xe3, 0x2e, 0xf4, 0x1f, 0x25, 0x03, 0xc7, 0xe3, 0x2e, 0x00, 0x36, 0xf8, + 0xf5, 0x28, 0xdb, 0x40, 0xda, 0x0b, 0x2e, 0xe8, 0xfb, 0xf9, 0xca, 0x45, 0xcf, + 0xc9, 0x0e, 0xea, 0xf1, 0x25, 0xd7, 0x1d, 0xe2, 0x0a, 0xf3, 0xfe, 0x3c, 0xe7, + 0x00, 0xf4, 0x17, 0x35, 0xe4, 0x2d, 0xf8, 0x45, 0x10, 0xe2, 0xfd, 0xe6, 0x0a, + 0xaf, 0x05, 0x35, 0xc6, 0xdc, 0xf7, 0xb4, 0x97, 0x0b, 0x26, 0x01, 0xfb, 0xb5, + 0xfc, 0xbf, 0xc2, 0x29, 0xe0, 0x16, 0x54, 0xbf, 0x1a, 0xeb, 0x26, 0xd2, 0xf6, + 0xb2, 0xed, 0x31, 0x4b, 0x35, 0xd1, 0x0e, 0xc5, 0xeb, 0xf8, 0x09, 0x04, 0x62, + 0x1c, 0x07, 0xec, 0xf5, 0xd3, 0xbc, 0xdd, 0x17, 0xed, 0x92, 0xe9, 0xe5, 0x23, + 0xf0, 0xe9, 0xa0, 0xe0, 0x53, 0x33, 0xc8, 0xe6, 0x9e, 0x01, 0xf7, 0xfb, 0xd4, + 0x10, 0x35, 0xc3, 0xf9, 0xf1, 0xf4, 0xf1, 0xeb, 0x2f, 0xbe, 0x1d, 0x14, 0xd5, + 0xd6, 0x13, 0x1d, 0xe6, 0x2e, 0xe1, 0x3c, 0xe4, 0x12, 0xe0, 0xc7, 0x27, 0xec, + 0xfb, 0xda, 0xdc, 0xe7, 0xf8, 0x11, 0x1b, 0xe7, 0xea, 0xef, 0x0c, 0xee, 0xf4, + 0x05, 0x20, 0x81, 0xb3, 0x36, 0x12, 0xf5, 0xe3, 0x00, 0x1d, 0xb5, 0x15, 0xd0, + 0x04, 0x1b, 0xf8, 0xe6, 0xf7, 0x32, 0x0f, 0x27, 0xf9, 0xfe, 0x1b, 0xe8, 0x21, + 0xda, 0x29, 0xf3, 0x0d, 0x45, 0xc8, 0xee, 0xf9, 0x02, 0xfc, 0x04, 0x1c, 0xe2, + 0xf8, 0xfe, 0xf3, 0xfe, 0xfb, 0xc0, 0xd8, 0xd6, 0xd1, 0x12, 0x13, 0xfb, 0x19, + 0x26, 0x1b, 0x00, 0x31, 0xb1, 0xd4, 0x17, 0x36, 0x1f, 0x0c, 0x18, 0xe0, 0xf6, + 0xdb, 0xd0, 0x04, 0x14, 0x0c, 0x1c, 0x0e, 0x0c, 0x17, 0xe9, 0x02, 0xe7, 0x47, + 0x26, 0xc7, 0xd4, 0x1a, 0x0e, 0xff, 0x52, 0xf6, 0xb2, 0xcb, 0x22, 0xf7, 0x22, + 0xea, 0xd7, 0xec, 0xdf, 0xca, 0xe0, 0xbb, 0xc1, 0xf1, 0xd8, 0x0d, 0x39, 0x01, + 0x13, 0xeb, 0xd8, 0xd0, 0xf1, 0xf0, 0x3f, 0x17, 0xee, 0x07, 0xf5, 0xb8, 0x27, + 0xe9, 0xef, 0x06, 0xce, 0x2b, 0xf3, 0xe4, 0x3b, 0x04, 0x3a, 0xc7, 0x08, 0xc4, + 0x14, 0xc0, 0x47, 0x0d, 0x00, 0x24, 0x43, 0xd0, 0xaa, 0xa4, 0xb0, 0xe9, 0x1f, + 0x2d, 0x1a, 0xda, 0xf1, 0xd9, 0x13, 0xd1, 0xa9, 0x4c, 0x0d, 0xcf, 0x0c, 0x3b, + 0xfa, 0xef, 0x0f, 0x32, 0x31, 0xfa, 0x27, 0xe7, 0xed, 0x56, 0xd7, 0x05, 0x23, + 0xe1, 0x2a, 0x2b, 0xeb, 0xf3, 0x02, 0x0d, 0x1d, 0xc9, 0xde, 0x06, 0x26, 0xfa, + 0x13, 0xf6, 0xed, 0xec, 0x1e, 0xea, 0x4a, 0x2f, 0xf0, 0xda, 0x45, 0xf6, 0x1c, + 0xc4, 0x25, 0x18, 0xed, 0xfc, 0x44, 0xbd, 0x1d, 0xe0, 0xff, 0x00, 0xde, 0x33, + 0x31, 0xe6, 0x11, 0xe0, 0xcd, 0x37, 0xde, 0xe0, 0xf9, 0xfe, 0x01, 0xfe, 0xed, + 0x12, 0xf1, 0xf3, 0xe0, 0xa8, 0xeb, 0xc8, 0xe2, 0xf5, 0x0a, 0x22, 0x1f, 0x12, + 0xdd, 0x1b, 0xd8, 0xcd, 0xa4, 0xde, 0xe2, 0x18, 0xf3, 0x5a, 0xb7, 0xde, 0xb1, + 0x00, 0xd4, 0xf4, 0x1f, 0xe5, 0xc7, 0x2a, 0xf8, 0x22, 0x36, 0xb9, 0x0c, 0xf4, + 0x1f, 0xfa, 0xf5, 0xbc, 0xb4, 0x1b, 0xe6, 0x41, 0xdc, 0x32, 0x04, 0x11, 0xf5, + 0xe7, 0xcc, 0x1d, 0x72, 0x50, 0xd3, 0x16, 0x24, 0x8f, 0x29, 0xf3, 0xf9, 0xcc, + 0xdc, 0xdd, 0x4e, 0xff, 0xe1, 0xc9, 0xe0, 0x41, 0x22, 0x4d, 0xee, 0xc9, 0xc0, + 0x14, 0x23, 0xf9, 0xe6, 0xf9, 0x08, 0x10, 0xdb, 0x0a, 0x37, 0x02, 0x3a, 0xd0, + 0x04, 0xff, 0xa4, 0xcf, 0xda, 0x18, 0x1d, 0xe5, 0xe9, 0xfb, 0x22, 0xf8, 0x44, + 0x83, 0xd7, 0xfd, 0xf0, 0xf9, 0xc6, 0x09, 0xdb, 0xee, 0x11, 0xe2, 0x3d, 0xfc, + 0xdf, 0xd0, 0x1c, 0xe0, 0xf5, 0x13, 0x25, 0xcb, 0x07, 0x13, 0xcf, 0xff, 0xc5, + 0x35, 0x2a, 0xf7, 0xe9, 0xff, 0x0d, 0x4d, 0x12, 0xf9, 0x1f, 0x10, 0x16, 0x00, + 0x1d, 0xde, 0x15, 0x15, 0xa3, 0x03, 0xd5, 0xfc, 0x21, 0x01, 0xdb, 0xbf, 0xbf, + 0x09, 0xe0, 0xfc, 0x00, 0x10, 0xd2, 0xc8, 0xae, 0x08, 0x22, 0xf2, 0x51, 0x05, + 0x24, 0xfa, 0xe4, 0x10, 0xb5, 0xcb, 0x3f, 0xfc, 0xf9, 0x01, 0xf1, 0x64, 0xdd, + 0xf3, 0x20, 0xe8, 0xa5, 0xf1, 0x28, 0x44, 0xed, 0x28, 0x28, 0xa6, 0xe0, 0xff, + 0x41, 0xf1, 0x19, 0x0d, 0xfb, 0x0a, 0xe7, 0x15, 0x2c, 0x2b, 0x32, 0x0f, 0x4f, + 0x08, 0xf0, 0xd0, 0x2b, 0xea, 0xb0, 0xfc, 0xec, 0xd9, 0x43, 0x7e, 0xce, 0x0c, + 0xfa, 0x0b, 0x44, 0xc2, 0xc5, 0x18, 0xca, 0xe2, 0x01, 0xea, 0xa7, 0x36, 0xbd, + 0x24, 0xc8, 0xcd, 0xea, 0x1f, 0xd0, 0x14, 0xc0, 0xd3, 0xdc, 0x2b, 0xc9, 0xee, + 0xdd, 0xee, 0xfd, 0xb9, 0x0d, 0x26, 0x18, 0x25, 0xf7, 0x2f, 0xf8, 0xf1, 0x0e, + 0x16, 0xbd, 0xeb, 0xd2, 0x32, 0xc8, 0x10, 0xee, 0xa8, 0x07, 0x1e, 0x7f, 0xbc, + 0xf8, 0x0b, 0x0a, 0x24, 0x13, 0xd4, 0x1f, 0x02, 0xee, 0xd8, 0x1a, 0x00, 0xdb, + 0xc3, 0xe3, 0xf8, 0x09, 0x13, 0xdf, 0x08, 0xb4, 0x01, 0x2b, 0xc5, 0x0e, 0x04, + 0xdc, 0xe4, 0x05, 0x14, 0xc2, 0x0e, 0xf1, 0xda, 0x0c, 0xcf, 0x3e, 0x2d, 0x0b, + 0xf0, 0x0f, 0xea, 0xb3, 0xb6, 0xed, 0x1c, 0xe6, 0xe3, 0x43, 0xf0, 0x1b, 0xc2, + 0xd3, 0xfe, 0xb2, 0x30, 0x0d, 0xe9, 0x3c, 0x11, 0xd9, 0x20, 0xf7, 0xf8, 0x1a, + 0xf9, 0x16, 0xbf, 0xfb, 0xc9, 0x20, 0x1b, 0xc1, 0xd5, 0x92, 0x0e, 0x07, 0x04, + 0x4c, 0xbe, 0xe9, 0xc4, 0x05, 0xfc, 0x0d, 0xea, 0x6a, 0xd6, 0xea, 0xcc, 0x11, + 0xf9, 0xd8, 0x1f, 0xe9, 0x37, 0xcb, 0xb5, 0xf8, 0x69, 0xfd, 0xcb, 0x7f, 0xe7, + 0x20, 0xff, 0x00, 0xe1, 0x1a, 0x11, 0xe3, 0xc6, 0xf2, 0x02, 0x20, 0xd4, 0xe3, + 0xeb, 0xfe, 0xcd, 0xd1, 0x03, 0xdc, 0xfb, 0x05, 0xd9, 0xe7, 0x0c, 0x3f, 0xe7, + 0x22, 0x09, 0xbb, 0xe3, 0xfd, 0xe3, 0xd7, 0xda, 0xaa, 0x1e, 0xdc, 0xc4, 0xd0, + 0xc9, 0x64, 0xca, 0x3f, 0xe8, 0x18, 0xe2, 0x38, 0x28, 0xf1, 0x06, 0x0f, 0x18, + 0xd3, 0xf3, 0xff, 0xe1, 0xbe, 0x41, 0x02, 0x1e, 0x38, 0x15, 0xa3, 0x19, 0xe4, + 0x2c, 0x10, 0x31, 0xe6, 0xf9, 0xd6, 0xcb, 0xf2, 0xde, 0x03, 0x2a, 0x39, 0xf4, + 0xcf, 0x05, 0xf8, 0x51, 0xe2, 0xdc, 0xd8, 0xd3, 0xe5, 0x01, 0xdc, 0x0f, 0xc3, + 0xfb, 0xb8, 0x11, 0xfc, 0x10, 0x04, 0xd0, 0xfa, 0xea, 0x30, 0xa8, 0x13, 0xd9, + 0x2d, 0x00, 0xe0, 0xff, 0x3a, 0xf8, 0x39, 0x7d, 0x2a, 0x92, 0x16, 0xdc, 0xe3, + 0x1e, 0xe1, 0xde, 0xf1, 0x0b, 0xc8, 0xdf, 0xc7, 0xf1, 0xdd, 0xa4, 0xe6, 0xe0, + 0xee, 0x02, 0x0e, 0xfe, 0xcf, 0xb8, 0xe5, 0xde, 0x1f, 0x91, 0xf6, 0xd9, 0xf2, + 0xe0, 0xcb, 0xfe, 0xf5, 0x01, 0xf3, 0x43, 0x99, 0x1b, 0xd1, 0xbd, 0x35, 0xe4, + 0xd0, 0x87, 0xa8, 0xb8, 0x59, 0xf0, 0xa9, 0xd0, 0x88, 0x2e, 0x37, 0xb5, 0x02, + 0x42, 0xbb, 0x57, 0x5e, 0x07, 0xd3, 0x19, 0x4e, 0x1e, 0xe9, 0x20, 0xf9, 0xb5, + 0x27, 0xd6, 0xfe, 0xf6, 0x4b, 0xf7, 0xf1, 0xba, 0x43, 0xe2, 0x2f, 0x09, 0x91, + 0xf6, 0x14, 0xb5, 0x19, 0xa5, 0xe3, 0xda, 0xf4, 0x26, 0xe0, 0xdb, 0x1e, 0xbd, + 0x12, 0xbb, 0x16, 0xec, 0xc7, 0xa5, 0xd1, 0xea, 0xcf, 0x46, 0xb1, 0xc9, 0xde, + 0xdf, 0xd3, 0x07, 0x31, 0x4c, 0xdf, 0x2a, 0xe0, 0x3b, 0xbd, 0x1b, 0xec, 0x35, + 0x94, 0xe1, 0x20, 0xa8, 0x1b, 0x00, 0xd0, 0x1e, 0x29, 0xe8, 0xe7, 0x35, 0x0a, + 0x29, 0x47, 0xbe, 0x14, 0x48, 0xbc, 0x26, 0xdb, 0xdf, 0xec, 0x03, 0x5f, 0x0a, + 0x28, 0xf8, 0x4b, 0xe7, 0x8e, 0xfe, 0x91, 0xc5, 0x9f, 0x49, 0xed, 0xbc, 0x41, + 0x20, 0x9d, 0xc9, 0xcd, 0xf2, 0xf7, 0x34, 0x0e, 0xda, 0x2a, 0x98, 0xe0, 0x81, + 0x9e, 0x5c, 0x29, 0xd0, 0xcb, 0x3b, 0xef, 0x5c, 0x1c, 0xbc, 0xef, 0x03, 0xfe, + 0x42, 0x3f, 0xc2, 0xd6, 0xea, 0xd1, 0x8a, 0xe3, 0x04, 0xc0, 0x15, 0x38, 0x0d, + 0xfa, 0xb9, 0xb4, 0x1a, 0xd1, 0x47, 0xa0, 0x20, 0x40, 0xf1, 0xd0, 0xbb, 0x06, + 0x19, 0x2a, 0x48, 0xd3, 0x27, 0xf0, 0xf2, 0x1e, 0x0f, 0x19, 0x09, 0x3c, 0xe2, + 0xc2, 0xba, 0x31, 0xf3, 0xf6, 0x30, 0xb5, 0xd6, 0xe4, 0x30, 0x50, 0x14, 0x13, + 0x5a, 0x0e, 0x44, 0xfe, 0xd5, 0xf2, 0xb6, 0xde, 0x28, 0x55, 0x10, 0xfd, 0x0e, + 0xc0, 0xf4, 0xfd, 0x2a, 0x11, 0xae, 0xbe, 0x05, 0xd3, 0x33, 0xc2, 0xcd, 0xc5, + 0xc3, 0xad, 0x26, 0xea, 0x29, 0x6d, 0x17, 0xed, 0x4d, 0xe7, 0xed, 0xdc, 0xcf, + 0xc8, 0x49, 0xfb, 0xe5, 0x07, 0x20, 0xbf, 0x28, 0xd9, 0xef, 0xca, 0xe9, 0xc4, + 0x8f, 0xd7, 0xc3, 0xde, 0xb5, 0xf3, 0xeb, 0x99, 0xac, 0xf4, 0xf3, 0xe4, 0xfd, + 0xfc, 0x15, 0xf6, 0x09, 0xc4, 0xf0, 0xf5, 0xd0, 0xf8, 0xf7, 0xb1, 0xf9, 0x0a, + 0xf8, 0x2e, 0xe6, 0xf9, 0xfb, 0x15, 0x15, 0x0c, 0x1b, 0xf7, 0xe8, 0x08, 0xd5, + 0x1b, 0xfd, 0xeb, 0xfb, 0xf4, 0xe0, 0xeb, 0x10, 0x00, 0xf5, 0xcf, 0x1e, 0xfb, + 0xd8, 0x5a, 0xf1, 0x08, 0xe0, 0xd9, 0x95, 0xd4, 0x47, 0x0d, 0x06, 0x18, 0xde, + 0x03, 0xfd, 0xfb, 0xd3, 0xed, 0xe7, 0x0c, 0xeb, 0x2c, 0xe4, 0x2f, 0xfd, 0xf0, + 0xf0, 0xf9, 0x08, 0xdf, 0xec, 0x38, 0xff, 0xe9, 0xc7, 0xe0, 0xc8, 0xd1, 0xcc, + 0x14, 0x0e, 0x03, 0x78, 0xd6, 0xfc, 0xf9, 0xf1, 0xed, 0xf7, 0xda, 0x07, 0x04, + 0x07, 0xf0, 0xee, 0x26, 0xef, 0xd1, 0xff, 0x23, 0x13, 0xdf, 0xfa, 0x18, 0xf4, + 0xe2, 0xe5, 0x17, 0xfe, 0xc6, 0x25, 0xf6, 0xd2, 0xe4, 0xd0, 0x19, 0xf1, 0x11, + 0xfe, 0x02, 0x09, 0x3b, 0x04, 0xf1, 0x13, 0xbe, 0xb8, 0xf2, 0xfb, 0xf8, 0x24, + 0x12, 0x1b, 0xfb, 0x10, 0xe1, 0xf2, 0x60, 0xfd, 0xed, 0x30, 0x2b, 0x27, 0x08, + 0x20, 0xae, 0xf7, 0x06, 0x13, 0xee, 0x00, 0xfe, 0x11, 0x06, 0x1b, 0xe0, 0xfb, + 0x0e, 0x1a, 0xc4, 0xdf, 0x1a, 0xff, 0xfd, 0x15, 0xfe, 0xf3, 0xfe, 0x0b, 0xea, + 0xfa, 0x0e, 0x0e, 0x27, 0xff, 0x03, 0xf4, 0x22, 0xff, 0x02, 0xf0, 0xf9, 0xf5, + 0xf4, 0x39, 0xf2, 0xd4, 0x07, 0x00, 0xf1, 0xff, 0xe8, 0xf4, 0xea, 0x15, 0x18, + 0xe1, 0x25, 0x05, 0x2b, 0xd3, 0x05, 0xf6, 0x01, 0xff, 0x34, 0x05, 0x0e, 0x7f, + 0x1d, 0x02, 0xee, 0x0e, 0xf8, 0x16, 0xdc, 0xc7, 0x12, 0xbc, 0xda, 0xda, 0x16, + 0x02, 0xdd, 0xd8, 0xc7, 0x10, 0xe2, 0x34, 0x03, 0xfc, 0xfe, 0xf1, 0x15, 0xe7, + 0xca, 0xe0, 0x10, 0x07, 0x02, 0x16, 0xfa, 0xf9, 0x05, 0xb5, 0xed, 0xc8, 0xc5, + 0xe5, 0xe4, 0x14, 0xf9, 0x0b, 0x30, 0xee, 0xf5, 0xbf, 0x17, 0xe2, 0x19, 0xc7, + 0xa5, 0xc7, 0xd5, 0x3d, 0xbe, 0x1b, 0xaa, 0xc8, 0x44, 0x09, 0xdb, 0xf2, 0x31, + 0xec, 0xca, 0x11, 0xfb, 0x5d, 0xfe, 0x0d, 0x58, 0x3c, 0xb8, 0xe9, 0x3f, 0xde, + 0xbb, 0xeb, 0x28, 0xd5, 0xff, 0xce, 0x06, 0xb4, 0xbb, 0x81, 0xdf, 0x5e, 0xff, + 0xe6, 0xed, 0x5f, 0xae, 0xe1, 0x0a, 0x23, 0xcd, 0x37, 0x40, 0x32, 0x44, 0x47, + 0xc2, 0x9e, 0x18, 0xdb, 0x49, 0x4f, 0x21, 0xd3, 0x10, 0xd1, 0x08, 0xec, 0xe8, + 0xa6, 0x39, 0x9e, 0xad, 0x23, 0x37, 0x88, 0x16, 0xc7, 0x3e, 0xa6, 0xf4, 0x10, + 0xe6, 0xbc, 0xf3, 0x1d, 0xc7, 0x13, 0x34, 0xaa, 0xc6, 0xec, 0xd4, 0xb6, 0x27, + 0xfa, 0xf0, 0x8e, 0xe4, 0xdb, 0x0d, 0x30, 0xd3, 0x3f, 0xe3, 0xef, 0x2c, 0xd6, + 0xa9, 0xca, 0xaa, 0x27, 0x55, 0x21, 0x1e, 0xb4, 0xf0, 0xf0, 0x00, 0x08, 0x0a, + 0xff, 0xef, 0xd7, 0x36, 0xd5, 0xe2, 0xee, 0xca, 0xf1, 0x42, 0xe6, 0xfd, 0x37, + 0xe8, 0xde, 0xe8, 0xdf, 0x21, 0x17, 0x4c, 0x21, 0xee, 0x12, 0xca, 0x12, 0xab, + 0xde, 0xf4, 0xe2, 0xbd, 0x8b, 0x12, 0xf2, 0x21, 0x28, 0xd5, 0x55, 0xdb, 0x41, + 0xad, 0x48, 0x33, 0x21, 0x4a, 0x20, 0xfb, 0xf4, 0x31, 0x38, 0x1c, 0x08, 0x5d, + 0x43, 0x98, 0xa6, 0x3f, 0xc6, 0xe5, 0xf9, 0x3e, 0x07, 0xef, 0x2e, 0xed, 0x1d, + 0x0d, 0xe9, 0xf1, 0x26, 0x16, 0x12, 0x10, 0x01, 0x3b, 0x32, 0xdf, 0xc9, 0x69, + 0x98, 0x33, 0x25, 0x81, 0xe2, 0x02, 0xff, 0xc7, 0x1f, 0xe6, 0x03, 0xe1, 0xc8, + 0x2d, 0xe6, 0x38, 0xec, 0x12, 0x56, 0x16, 0xea, 0x54, 0xf4, 0xd0, 0x03, 0x1e, + 0xf6, 0xe8, 0xe3, 0x11, 0xed, 0x14, 0xcb, 0xf7, 0xb8, 0xcf, 0xfb, 0xa9, 0xe9, + 0x00, 0xdd, 0xdd, 0xfc, 0xb6, 0xae, 0x0a, 0x12, 0xcd, 0x06, 0xa2, 0xb9, 0x0a, + 0x04, 0xb1, 0x4b, 0xd5, 0xe9, 0x39, 0x23, 0x6e, 0xa5, 0xc3, 0xd5, 0xf4, 0xb3, + 0xf1, 0x08, 0x16, 0x64, 0x3f, 0xde, 0xe2, 0xba, 0x09, 0xe6, 0xee, 0xce, 0xf5, + 0xab, 0xd9, 0x35, 0xcc, 0x0e, 0xfe, 0xe4, 0x21, 0x21, 0x39, 0x04, 0x26, 0x44, + 0xa5, 0x2d, 0x39, 0xe0, 0xfb, 0x25, 0x09, 0x09, 0xb7, 0xf6, 0xde, 0x14, 0x04, + 0x4a, 0xcc, 0x38, 0xfc, 0x12, 0x36, 0x93, 0x36, 0xd3, 0xea, 0xfe, 0xf8, 0xa2, + 0xd0, 0x1e, 0x03, 0xc5, 0xba, 0xe8, 0xf5, 0x28, 0xe8, 0x18, 0x2f, 0xfe, 0xf0, + 0xdc, 0x4d, 0x3b, 0xdf, 0x31, 0x07, 0x0e, 0xd0, 0xfd, 0x24, 0x1a, 0xd9, 0x26, + 0xcc, 0x4a, 0xd2, 0xbf, 0xdb, 0xfc, 0xe4, 0x34, 0x12, 0xf4, 0x26, 0x59, 0x15, + 0xce, 0x3b, 0xbe, 0xe3, 0xdf, 0xf5, 0x03, 0xbc, 0x20, 0x73, 0xfe, 0xc9, 0xe0, + 0x08, 0xeb, 0xc0, 0x31, 0xd1, 0xab, 0x08, 0xd9, 0xa5, 0xda, 0x3d, 0xfc, 0x39, + 0x28, 0xdd, 0xff, 0xc0, 0xd8, 0x6c, 0xf5, 0xff, 0x2d, 0xd7, 0x9e, 0x1e, 0xbc, + 0x1f, 0xc6, 0xf0, 0x28, 0xf2, 0xad, 0x25, 0xbf, 0x8a, 0x37, 0x34, 0xf0, 0x56, + 0xf2, 0x4f, 0x0d, 0x30, 0x0e, 0x1d, 0x17, 0xf2, 0xaa, 0xea, 0x18, 0x29, 0x06, + 0x06, 0xf2, 0x26, 0x64, 0x1c, 0x01, 0xcc, 0x0d, 0x0d, 0x09, 0x02, 0xa4, 0x08, + 0xdd, 0x02, 0xd2, 0x36, 0xe6, 0x8c, 0x2f, 0x0d, 0xdb, 0xfe, 0x3d, 0x10, 0x20, + 0x07, 0xd6, 0x0e, 0x47, 0x34, 0x05, 0xd3, 0x8f, 0x1d, 0x12, 0x29, 0xcf, 0xf8, + 0x1e, 0xbd, 0x50, 0x4d, 0xbf, 0xdc, 0xef, 0xf2, 0xeb, 0x21, 0x1c, 0x08, 0x02, + 0x0f, 0xb3, 0xce, 0xcb, 0xd8, 0x04, 0x2f, 0x02, 0x02, 0xe4, 0xa2, 0xfa, 0xed, + 0xca, 0x81, 0x08, 0xd6, 0xfb, 0xd1, 0x4f, 0xd9, 0x21, 0x4b, 0xe6, 0x2d, 0xeb, + 0xe0, 0xb1, 0x34, 0xfb, 0x2f, 0x46, 0xdd, 0x39, 0xed, 0xd5, 0xfb, 0xe0, 0x11, + 0xe9, 0x0e, 0xc2, 0x39, 0x22, 0xce, 0xd5, 0xdd, 0x28, 0x99, 0xe2, 0xc0, 0x99, + 0xea, 0x0b, 0x4a, 0x0a, 0x20, 0xc2, 0xb5, 0xed, 0xb2, 0x52, 0xba, 0xe5, 0xf9, + 0x1f, 0xcd, 0xc2, 0xca, 0xd5, 0x18, 0xd1, 0xe7, 0x44, 0x25, 0xaa, 0xde, 0x3c, + 0x8e, 0xc6, 0xf0, 0x1a, 0xe5, 0x02, 0xfd, 0xf7, 0x1a, 0xf6, 0x5f, 0xc8, 0xd8, + 0xf9, 0x1d, 0x06, 0x8d, 0xbd, 0x5c, 0xc7, 0xb4, 0xc6, 0x25, 0xd4, 0x5a, 0x34, + 0x11, 0x9f, 0x87, 0xdd, 0x1a, 0x9b, 0xe8, 0x24, 0xdf, 0x1d, 0x2d, 0xce, 0xf8, + 0x40, 0x3a, 0x16, 0xd5, 0xf8, 0xcb, 0xe6, 0x09, 0xf6, 0xce, 0x2f, 0x06, 0xd2, + 0x1b, 0x25, 0xaa, 0xeb, 0xd6, 0xbc, 0xf5, 0x05, 0x57, 0x05, 0x07, 0xf8, 0xbb, + 0x0a, 0xab, 0xe1, 0x4a, 0xb9, 0xf4, 0xc0, 0xea, 0xe0, 0xc3, 0xee, 0x2c, 0xe7, + 0xf9, 0xdd, 0x03, 0xdd, 0x58, 0xf0, 0xf0, 0xd3, 0xda, 0x54, 0x09, 0xe0, 0xc4, + 0xdc, 0xc7, 0xc7, 0x3a, 0x0a, 0xb0, 0xc6, 0x06, 0xe7, 0x1b, 0x00, 0xc2, 0x25, + 0xc5, 0x0f, 0xe9, 0x2f, 0xe0, 0x16, 0x17, 0x16, 0x14, 0x25, 0xd2, 0x12, 0xef, + 0x27, 0x19, 0xc5, 0x0a, 0xe7, 0x10, 0x08, 0x96, 0x41, 0xfe, 0x06, 0x16, 0x0c, + 0x20, 0x3b, 0xb2, 0x0b, 0xd9, 0xe7, 0xe5, 0x09, 0xf8, 0xb8, 0xec, 0xe4, 0x59, + 0xbf, 0x2d, 0x0c, 0x49, 0xff, 0x58, 0xca, 0x00, 0x05, 0x2a, 0x36, 0xa7, 0xf1, + 0x07, 0xa0, 0xb6, 0x17, 0x19, 0xc6, 0x1f, 0x3b, 0xe8, 0x12, 0x46, 0xf9, 0x29, + 0xeb, 0x47, 0x81, 0x07, 0x1a, 0xfc, 0x44, 0x5f, 0xe1, 0xf0, 0xba, 0x40, 0xeb, + 0x42, 0xfa, 0x1b, 0xe8, 0xe7, 0xee, 0xe9, 0xf8, 0x38, 0xf9, 0x4b, 0x11, 0x0e, + 0x03, 0x26, 0x06, 0x19, 0x0e, 0xdc, 0xc3, 0x10, 0x12, 0x01, 0xf1, 0x3e, 0xcd, + 0x06, 0xdf, 0xf3, 0xb4, 0x15, 0x00, 0x13, 0xbf, 0x56, 0x9a, 0xdb, 0xf8, 0xd8, + 0x37, 0xcf, 0xf5, 0x22, 0xd0, 0x21, 0x3f, 0xd8, 0x31, 0xdd, 0xfd, 0xf7, 0xe5, + 0x0a, 0xc3, 0xdd, 0xe9, 0xe9, 0x1f, 0x10, 0x3f, 0x81, 0xfb, 0x27, 0xb4, 0xa3, + 0xd7, 0xf1, 0xfc, 0x12, 0x61, 0xff, 0xfb, 0x37, 0x08, 0xd7, 0x32, 0xf8, 0xa0, + 0xfe, 0x0d, 0xeb, 0xff, 0xef, 0xec, 0xdf, 0xc0, 0x1a, 0x3c, 0xd1, 0xe3, 0xf4, + 0x3c, 0xbe, 0x1c, 0xf2, 0xed, 0x0f, 0xf2, 0x36, 0xd7, 0x1d, 0xfd, 0x12, 0x0a, + 0xf1, 0x06, 0xf9, 0xb8, 0xa5, 0xf8, 0xf5, 0xbd, 0x36, 0x99, 0xc6, 0xf4, 0x0b, + 0x56, 0x17, 0x61, 0x21, 0xa4, 0xc0, 0x43, 0xe9, 0x01, 0xe6, 0xcf, 0xb2, 0xe4, + 0x14, 0x03, 0xde, 0xcc, 0xf5, 0x03, 0xd5, 0xa6, 0x10, 0xc0, 0xe0, 0xfa, 0x19, + 0xbd, 0xe2, 0x29, 0xd2, 0xfa, 0x4c, 0x19, 0xc4, 0x3f, 0x1d, 0xf2, 0x2a, 0xde, + 0xd5, 0x37, 0xde, 0xc8, 0xbc, 0x22, 0x5c, 0xf2, 0x15, 0xd2, 0xde, 0x32, 0x24, + 0xbe, 0xc9, 0x23, 0xe7, 0x90, 0x34, 0x1b, 0xf4, 0xa4, 0x45, 0xe6, 0x11, 0x09, + 0xe7, 0x22, 0xf5, 0x53, 0x4e, 0xc9, 0xe3, 0x26, 0xe4, 0x49, 0x3a, 0xd2, 0x26, + 0xc1, 0xff, 0xd8, 0x23, 0x23, 0x30, 0xc4, 0x04, 0xc8, 0xa0, 0x3b, 0x9b, 0xfb, + 0x4a, 0xdf, 0x17, 0x11, 0xa9, 0x08, 0x0d, 0x21, 0x63, 0x0e, 0x3e, 0x53, 0x28, + 0xdc, 0x1d, 0x06, 0xc6, 0xb1, 0xd3, 0x22, 0xf8, 0x2c, 0x03, 0xcb, 0x28, 0xf7, + 0x0b, 0x00, 0xff, 0xba, 0xfb, 0xf3, 0x0e, 0x2e, 0xaa, 0xe1, 0x29, 0x2c, 0xd6, + 0xfc, 0xc9, 0xd9, 0x23, 0x27, 0x04, 0xeb, 0x45, 0x26, 0xfc, 0x11, 0x81, 0x3c, + 0x2b, 0xf4, 0x54, 0xf9, 0xd4, 0x20, 0x1c, 0xf3, 0xcd, 0x0a, 0x24, 0xda, 0x11, + 0xfb, 0xfa, 0xec, 0xc3, 0x69, 0x17, 0xff, 0xcb, 0xec, 0x2b, 0xde, 0x3b, 0x2a, + 0x2c, 0x32, 0xe5, 0xa7, 0x01, 0xdf, 0xe8, 0xfe, 0x2a, 0x3f, 0x50, 0xe3, 0xf1, + 0xfd, 0x1b, 0xb6, 0xc8, 0xd5, 0x07, 0x07, 0xf9, 0xeb, 0x44, 0xb8, 0xf2, 0x3a, + 0xe0, 0x0e, 0xb9, 0xee, 0xe2, 0x08, 0xdc, 0xd3, 0xd7, 0xdd, 0xf1, 0xea, 0xc9, + 0x24, 0xe0, 0x37, 0xb8, 0x39, 0x3d, 0x28, 0x2d, 0xcf, 0xe9, 0xad, 0xbf, 0x0b, + 0xf8, 0xf0, 0x20, 0x0c, 0xe5, 0xa8, 0xae, 0x14, 0x0c, 0xe0, 0x2e, 0x24, 0x18, + 0xa5, 0x5f, 0xca, 0x24, 0x12, 0xdf, 0x09, 0xf2, 0x1e, 0xde, 0xcc, 0xe8, 0xfc, + 0xe0, 0xdf, 0xa5, 0xad, 0xdd, 0x3a, 0x14, 0x07, 0x25, 0x2c, 0xf5, 0x41, 0xcd, + 0xdf, 0x20, 0x1e, 0x04, 0xe0, 0x53, 0x4d, 0xf2, 0x82, 0xde, 0xfc, 0xca, 0xf4, + 0xd8, 0x3c, 0x36, 0xd6, 0xb3, 0x1e, 0xff, 0x07, 0x2a, 0xdc, 0xb3, 0xe3, 0x17, + 0x13, 0xdf, 0x25, 0xa7, 0xd5, 0x16, 0x23, 0x1b, 0x1c, 0x53, 0xa1, 0xb7, 0x05, + 0x81, 0xec, 0xf7, 0x5d, 0xa0, 0x5b, 0x04, 0x3e, 0xbd, 0x2d, 0xaa, 0xd3, 0x00, + 0xa5, 0x11, 0x2e, 0xe1, 0x0a, 0x83, 0x27, 0x37, 0xb5, 0xce, 0x0d, 0xd4, 0x49, + 0xfe, 0x3f, 0xeb, 0x17, 0xfc, 0x2e, 0x0b, 0x03, 0xfd, 0xc0, 0x91, 0xf1, 0x51, + 0xc6, 0xfb, 0xd5, 0xf6, 0x02, 0x05, 0xd0, 0x08, 0xee, 0x3a, 0x05, 0xaa, 0x42, + 0xbb, 0x09, 0x22, 0x13, 0xd6, 0xd0, 0x57, 0x2e, 0x02, 0x4a, 0xc0, 0xef, 0x1b, + 0xdd, 0xf1, 0xe8, 0x15, 0x18, 0xe6, 0x35, 0x17, 0xad, 0xf5, 0x05, 0x14, 0x03, + 0x02, 0x4a, 0xda, 0x09, 0xea, 0xfc, 0x46, 0x86, 0xe8, 0xcd, 0xc9, 0x1a, 0x42, + 0xbb, 0xca, 0xd6, 0xaf, 0x34, 0x3f, 0xc3, 0xd4, 0xeb, 0x1b, 0x2e, 0xdf, 0x08, + 0x4c, 0x03, 0xed, 0xd5, 0xd5, 0xe7, 0x00, 0x13, 0x1c, 0x04, 0xe0, 0x23, 0x27, + 0xaf, 0x36, 0x86, 0xa3, 0xa3, 0xed, 0x2a, 0x22, 0x4a, 0x07, 0x15, 0xe5, 0xb4, + 0xef, 0xe1, 0x4c, 0x26, 0xfb, 0x15, 0x7d, 0xdb, 0xde, 0x12, 0x11, 0xe8, 0xbf, + 0xf3, 0xa7, 0x56, 0xfb, 0xbc, 0x32, 0xd0, 0x05, 0xfe, 0xfd, 0xca, 0xef, 0x0a, + 0x0f, 0xc3, 0xf7, 0xfd, 0xf8, 0x13, 0x16, 0x1b, 0x0d, 0xc9, 0xc0, 0xeb, 0xbb, + 0x43, 0xd1, 0xef, 0x48, 0xe9, 0xd5, 0xeb, 0xee, 0xd8, 0x24, 0x2c, 0xfe, 0x01, + 0x19, 0xd7, 0x05, 0xe8, 0x2c, 0xcb, 0x01, 0x1b, 0xf7, 0xe1, 0x0a, 0xea, 0x4f, + 0x27, 0xdc, 0xca, 0x1d, 0x41, 0xdb, 0x01, 0x5d, 0xd5, 0xda, 0x14, 0xfd, 0xf5, + 0xe0, 0xdf, 0x13, 0x08, 0x38, 0x4b, 0xef, 0xd3, 0xc7, 0x14, 0x00, 0x24, 0xe4, + 0xb3, 0x38, 0x3e, 0xe7, 0x11, 0x1e, 0x20, 0x13, 0x15, 0xd7, 0x06, 0xf1, 0xb7, + 0xfc, 0xda, 0xd8, 0x02, 0x09, 0xc7, 0xfa, 0xc2, 0xfe, 0x1b, 0xfd, 0xe3, 0xba, + 0x15, 0xf6, 0x02, 0x08, 0x03, 0x7f, 0x01, 0xf7, 0x1c, 0xc2, 0x05, 0xe8, 0xfe, + 0xf9, 0x0e, 0xd1, 0x50, 0xe4, 0xe1, 0x02, 0xc8, 0x3d, 0xec, 0x56, 0x0b, 0x16, + 0x09, 0x19, 0x19, 0x33, 0x10, 0x0f, 0xee, 0xcb, 0xe9, 0xd5, 0x07, 0xe3, 0x3b, + 0xef, 0x05, 0x1f, 0x2f, 0x19, 0x44, 0x2d, 0xee, 0x25, 0x06, 0x0e, 0x00, 0x11, + 0x1a, 0x46, 0x07, 0x26, 0x1b, 0x1f, 0xbe, 0xf2, 0x25, 0xcb, 0xe2, 0xee, 0xeb, + 0xe2, 0x08, 0x0b, 0x17, 0xfc, 0xe5, 0xc6, 0xfe, 0xd3, 0x1b, 0xc2, 0x19, 0x19, + 0x14, 0x3a, 0x10, 0x35, 0x1a, 0x7a, 0xfe, 0x1d, 0xfe, 0xfb, 0x09, 0x0f, 0xca, + 0x25, 0x49, 0x2c, 0xb0, 0xf9, 0xd3, 0xcb, 0xdb, 0x19, 0x4e, 0xd5, 0xed, 0xe0, + 0xec, 0x4a, 0xfe, 0xee, 0xcf, 0xec, 0x03, 0xf6, 0x2b, 0xcc, 0x18, 0x1a, 0xe6, + 0xf2, 0x09, 0xdc, 0xcf, 0xe2, 0x07, 0x01, 0xf6, 0xe7, 0x00, 0xdb, 0xb4, 0xc0, + 0x19, 0xdf, 0x07, 0x59, 0xd0, 0x43, 0xea, 0xc8, 0xd2, 0x81, 0xf3, 0xec, 0x08, + 0xed, 0x0f, 0xd9, 0xe4, 0xf5, 0xd7, 0xcd, 0x3d, 0x0d, 0xe6, 0x60, 0xf6, 0xd7, + 0x60, 0xf6, 0x04, 0x0b, 0xfb, 0xfb, 0x17, 0xf5, 0xec, 0xef, 0xe6, 0x10, 0xe0, + 0xc2, 0x00, 0x2a, 0xd4, 0xfe, 0x11, 0x20, 0xd9, 0xe8, 0xf5, 0x0c, 0xde, 0x22, + 0x05, 0x36, 0xb1, 0xd5, 0x0e, 0xcd, 0x1d, 0xda, 0x02, 0xfc, 0x03, 0xdd, 0x51, + 0xdd, 0x0a, 0xf9, 0xe9, 0x0e, 0xf9, 0xf3, 0xcd, 0xcc, 0xf4, 0x24, 0x1a, 0x08, + 0xf2, 0x23, 0xeb, 0xed, 0xce, 0xff, 0xdf, 0x0f, 0xf3, 0xc4, 0xeb, 0x12, 0xef, + 0x1b, 0x47, 0xca, 0xc6, 0xd0, 0x01, 0xfd, 0x32, 0xea, 0x1e, 0xfc, 0xba, 0xdd, + 0x14, 0x0f, 0xe3, 0xef, 0xe8, 0xca, 0x19, 0xfb, 0xdd, 0x12, 0x15, 0xf6, 0x02, + 0x1f, 0x20, 0x0e, 0xe5, 0x0e, 0x03, 0xf7, 0xe9, 0x06, 0xf4, 0xde, 0x22, 0xee, + 0x50, 0x50, 0x14, 0xef, 0x16, 0xd7, 0xce, 0x15, 0xf3, 0xfe, 0x2d, 0xe2, 0xf8, + 0xdf, 0x1d, 0xfa, 0x0a, 0x5d, 0xf1, 0x0c, 0x1f, 0x3e, 0xfe, 0x4b, 0x00, 0xc0, + 0xbf, 0x02, 0x04, 0x10, 0x1f, 0x37, 0xd9, 0x2a, 0x08, 0xe4, 0xfb, 0x27, 0x1b, + 0xe9, 0xdc, 0xde, 0x33, 0xf7, 0x10, 0xd9, 0xf0, 0xff, 0x50, 0x27, 0xf1, 0x1e, + 0x24, 0x40, 0xd2, 0x06, 0x17, 0x11, 0x17, 0xf3, 0xdf, 0x11, 0xe6, 0x18, 0x29, + 0xff, 0xe3, 0xd2, 0xd6, 0xcd, 0xf4, 0x0a, 0xf1, 0x0d, 0x6d, 0x08, 0x11, 0xfc, + 0x07, 0xd6, 0xc8, 0x25, 0xbe, 0x04, 0x02, 0x1c, 0xf5, 0x01, 0x2f, 0x0a, 0x0e, + 0xd9, 0xf4, 0xdf, 0x1d, 0xe6, 0xd2, 0x02, 0xda, 0x2c, 0xc4, 0x00, 0xed, 0x21, + 0xeb, 0xcf, 0x2a, 0xf4, 0xb5, 0xfc, 0xb4, 0xc9, 0x03, 0xeb, 0xf4, 0xdd, 0x04, + 0xf4, 0x07, 0xdd, 0x10, 0xf8, 0xea, 0xdd, 0xf5, 0x06, 0xad, 0xce, 0xd6, 0xf7, + 0x1a, 0x21, 0xdc, 0x3d, 0xd7, 0x29, 0xf8, 0xed, 0x1b, 0x0d, 0xc7, 0x08, 0xcf, + 0xc4, 0x2a, 0xe3, 0x2c, 0xec, 0x27, 0x1f, 0xbe, 0x28, 0xd8, 0xe0, 0xab, 0xb5, + 0xf0, 0xd1, 0xd0, 0xeb, 0x41, 0xeb, 0x11, 0x06, 0xd8, 0xb9, 0xd4, 0x37, 0xce, + 0x09, 0x1b, 0x07, 0xf0, 0x0b, 0xde, 0xe4, 0xf4, 0x04, 0xd9, 0x2d, 0x1d, 0xf0, + 0xf9, 0x03, 0xf1, 0xb5, 0xe2, 0xd1, 0xf2, 0x38, 0xf0, 0x04, 0xc8, 0xb4, 0xf8, + 0x18, 0xc7, 0x56, 0xfe, 0x0a, 0xe3, 0x16, 0xfd, 0x26, 0xfd, 0xeb, 0xdf, 0x09, + 0xf5, 0xdc, 0x15, 0x04, 0xd6, 0xd1, 0x22, 0x18, 0x81, 0x0c, 0xdd, 0xb7, 0x05, + 0xda, 0xec, 0x25, 0xed, 0x12, 0x18, 0x56, 0xc9, 0xab, 0xd2, 0x06, 0xe2, 0xeb, + 0xe5, 0xb3, 0xc6, 0xec, 0xf3, 0x22, 0xaa, 0xfb, 0x09, 0x10, 0xe8, 0xd9, 0xfe, + 0xdc, 0x03, 0x45, 0xed, 0x18, 0x0f, 0xab, 0xfd, 0xdf, 0xeb, 0xe1, 0x19, 0xb3, + 0xd1, 0xfc, 0xd5, 0x3f, 0x1a, 0x04, 0x9e, 0xfc, 0x1c, 0x28, 0xb4, 0xd7, 0xf4, + 0xe2, 0xcc, 0xf3, 0x48, 0x24, 0xcb, 0x41, 0xf1, 0x02, 0xf1, 0xbf, 0x07, 0xf3, + 0x5c, 0xff, 0xcb, 0xd0, 0xe8, 0xc6, 0x65, 0xf3, 0xb2, 0x27, 0x2a, 0xe7, 0xc4, + 0xd0, 0x0d, 0x93, 0x06, 0xdc, 0xe7, 0x0d, 0x30, 0x34, 0xf8, 0x03, 0x23, 0xf5, + 0x07, 0xc1, 0xfa, 0x2f, 0xe8, 0x05, 0x10, 0xd0, 0x36, 0x31, 0xe6, 0xfa, 0x9a, + 0x99, 0xd7, 0x01, 0x0b, 0x23, 0xee, 0xea, 0x1f, 0x02, 0xd3, 0x40, 0xb5, 0xb6, + 0x9f, 0xfb, 0xd8, 0x11, 0xce, 0x01, 0xf9, 0xe4, 0xf3, 0xcb, 0xb2, 0xfb, 0xd6, + 0xf0, 0x1b, 0x25, 0xe4, 0x14, 0xea, 0xa6, 0x2b, 0xee, 0xe5, 0x08, 0xff, 0x54, + 0x13, 0xc7, 0xd9, 0xda, 0x31, 0xeb, 0x18, 0x0a, 0x01, 0xca, 0x0d, 0x57, 0x2d, + 0x05, 0x02, 0xe8, 0x06, 0xfc, 0xee, 0x22, 0xcc, 0xfd, 0x5e, 0x18, 0xfe, 0xf8, + 0xef, 0x3a, 0x9d, 0x09, 0x1e, 0xd5, 0xa7, 0xce, 0x4d, 0x0e, 0xf7, 0xd0, 0xfc, + 0xd0, 0xcf, 0xb5, 0xf6, 0x3d, 0x15, 0x18, 0xe1, 0x9a, 0xe1, 0xdc, 0x09, 0x15, + 0x21, 0x4e, 0xf5, 0x50, 0x30, 0xce, 0xc2, 0x11, 0xe2, 0xe1, 0x2e, 0xe1, 0x2d, + 0xd7, 0x11, 0xd4, 0xf3, 0x3f, 0x17, 0xa1, 0xc1, 0xce, 0xf4, 0x47, 0xdc, 0x4e, + 0xf6, 0xf3, 0x30, 0x61, 0xd6, 0xc4, 0x11, 0xe2, 0xe7, 0x9e, 0x07, 0xee, 0xda, + 0x4c, 0x41, 0xb8, 0x22, 0x47, 0xa9, 0xea, 0x10, 0xc4, 0x59, 0x91, 0xed, 0x8e, + 0x38, 0xe5, 0x5a, 0x22, 0xe6, 0x3b, 0x7f, 0x34, 0xeb, 0xbf, 0x08, 0xb4, 0x05, + 0x46, 0xa8, 0xe8, 0xc5, 0x1d, 0x23, 0xed, 0xcc, 0x4f, 0xf0, 0x11, 0x20, 0x20, + 0x33, 0xeb, 0xf6, 0x77, 0xf6, 0x0d, 0xa0, 0xfa, 0x8d, 0x49, 0xcc, 0x15, 0x09, + 0x0a, 0x35, 0xdc, 0xb3, 0x4e, 0xdc, 0x31, 0x0b, 0xd6, 0xb0, 0x0c, 0xff, 0x64, + 0xf9, 0xc8, 0xe8, 0x3c, 0xea, 0x46, 0x11, 0x26, 0xf6, 0x9a, 0x1f, 0xe5, 0x36, + 0x32, 0xf5, 0x0f, 0x4f, 0xdb, 0x0d, 0xd2, 0x0e, 0xff, 0x2b, 0xda, 0xca, 0xa8, + 0x26, 0xeb, 0xdd, 0x05, 0x1b, 0xa0, 0x07, 0x8a, 0x38, 0x27, 0x3a, 0x18, 0x01, + 0xbe, 0xbe, 0x3e, 0xd9, 0x01, 0xc6, 0x44, 0xb4, 0xdf, 0x1f, 0x16, 0xb9, 0x21, + 0xfb, 0xd8, 0xf2, 0xa3, 0xd5, 0xf5, 0xf2, 0x06, 0xc5, 0xc5, 0xf7, 0x3f, 0xd3, + 0x41, 0xf8, 0xd1, 0xf9, 0xe0, 0xbf, 0x0e, 0xdb, 0x94, 0xe5, 0x05, 0x03, 0xfe, + 0xd2, 0x3b, 0xf0, 0x01, 0xcc, 0x04, 0x98, 0x15, 0x09, 0xae, 0xa4, 0x22, 0x2b, + 0xab, 0x03, 0x21, 0x2c, 0x30, 0x38, 0x44, 0xee, 0x12, 0xf9, 0xfe, 0x15, 0xb1, + 0x49, 0x5d, 0x01, 0x9c, 0x31, 0x91, 0x3d, 0xeb, 0x1d, 0xa9, 0xe0, 0xe7, 0xcf, + 0xde, 0x26, 0xcf, 0xef, 0x14, 0x0f, 0xbc, 0x0d, 0xe9, 0x96, 0xe0, 0xec, 0xe8, + 0xc7, 0x1c, 0x06, 0xe1, 0xc2, 0xe0, 0xff, 0xdc, 0xfc, 0xf3, 0xe2, 0xe2, 0x01, + 0x21, 0xd3, 0x3b, 0xf3, 0x18, 0x19, 0xff, 0xe4, 0xcf, 0xbf, 0xe9, 0xd0, 0x39, + 0xe2, 0x12, 0xe6, 0xf2, 0xf3, 0xf9, 0xe8, 0xe2, 0xf5, 0xf6, 0x29, 0x9b, 0xa9, + 0x74, 0xb8, 0xef, 0xb4, 0xef, 0xc4, 0xfe, 0x35, 0x27, 0x0a, 0x05, 0xf9, 0x03, + 0x15, 0x15, 0xd9, 0x12, 0x29, 0xf6, 0xeb, 0x2d, 0x0c, 0x16, 0xf7, 0xee, 0xc2, + 0xb9, 0x1d, 0xd5, 0xef, 0x46, 0xf1, 0x0f, 0xe0, 0x07, 0xcf, 0xc6, 0x1d, 0xec, + 0x07, 0x11, 0x26, 0xf4, 0xde, 0xc1, 0xf0, 0xea, 0x1a, 0xda, 0xe5, 0x3b, 0x34, + 0xd4, 0xd6, 0x0a, 0xf9, 0xc6, 0xe0, 0x0b, 0xdf, 0x1b, 0xb4, 0xfa, 0xf0, 0xf7, + 0x0a, 0x0e, 0xcc, 0xcd, 0x01, 0xd6, 0x9f, 0xbf, 0xdc, 0xe0, 0xee, 0xe8, 0xf7, + 0xd9, 0x50, 0x25, 0x13, 0xfb, 0xe9, 0xb0, 0xe5, 0xfb, 0x4a, 0xd3, 0x02, 0xad, + 0x34, 0xc4, 0xf8, 0xf9, 0xe3, 0x5f, 0xfa, 0x01, 0xf0, 0xff, 0xf7, 0x0e, 0xf2, + 0xca, 0xe6, 0xfb, 0x0f, 0x08, 0xf2, 0xfb, 0x11, 0xe2, 0x15, 0xcc, 0xd5, 0x19, + 0x08, 0xad, 0xeb, 0x1a, 0xe5, 0x14, 0xd4, 0xf0, 0xf3, 0x0a, 0x1f, 0x1a, 0xf0, + 0xf7, 0x17, 0x19, 0xda, 0x1e, 0xf4, 0x20, 0x07, 0xdb, 0xe0, 0xb4, 0xef, 0x3c, + 0x03, 0xe2, 0xf0, 0xca, 0x44, 0xfa, 0xea, 0xf2, 0xec, 0xef, 0xfa, 0x14, 0xc5, + 0x3e, 0x1b, 0x2f, 0xfc, 0x07, 0xe3, 0x05, 0x24, 0xf3, 0xec, 0x10, 0x7f, 0xfe, + 0xed, 0x28, 0xee, 0x98, 0x1e, 0xe1, 0xb4, 0xee, 0x0d, 0xbe, 0x04, 0x3a, 0xcf, + 0xdb, 0xa5, 0xda, 0xd9, 0xed, 0x2a, 0x31, 0x00, 0xfe, 0xfb, 0xf9, 0xe7, 0xfa, + 0xa4, 0xc6, 0xe2, 0x02, 0xea, 0xfc, 0xeb, 0x14, 0xed, 0x11, 0x28, 0xd6, 0xd7, + 0xed, 0xef, 0xf1, 0xef, 0xc9, 0xe4, 0xf6, 0xe5, 0x47, 0x21, 0x0e, 0xcf, 0xa0, + 0x40, 0xce, 0xe1, 0x3c, 0xe9, 0xd9, 0xbd, 0x13, 0x14, 0x01, 0xe0, 0xc7, 0xef, + 0x39, 0xf1, 0x06, 0x09, 0x32, 0x30, 0x95, 0x10, 0xf4, 0x45, 0xd0, 0x1c, 0xe1, + 0xaa, 0x2f, 0x18, 0xeb, 0xc9, 0xf3, 0xa4, 0x1f, 0xd4, 0xda, 0x0e, 0xd0, 0x3a, + 0xfc, 0xf6, 0xa3, 0x20, 0xe2, 0xfa, 0x09, 0x5b, 0x17, 0x26, 0x25, 0x08, 0xf7, + 0xed, 0x2d, 0x18, 0xc9, 0xfb, 0xc0, 0xe0, 0x09, 0xdb, 0x02, 0x0f, 0xf1, 0xdd, + 0xbd, 0xba, 0xd8, 0xbd, 0x12, 0xca, 0xbb, 0xcf, 0xf5, 0x3a, 0x34, 0xf9, 0xfe, + 0xd7, 0x10, 0xfa, 0x0c, 0xfa, 0xe5, 0x23, 0x04, 0xf7, 0xf1, 0x0f, 0xde, 0xcf, + 0x90, 0x31, 0x05, 0x4b, 0xfa, 0xe6, 0xef, 0xf4, 0xd9, 0x01, 0x03, 0x39, 0x02, + 0xa8, 0xe7, 0xf5, 0x13, 0x36, 0xd9, 0xff, 0x90, 0xbe, 0xf0, 0x02, 0x45, 0xb4, + 0xc2, 0x22, 0x28, 0x9f, 0xed, 0xf5, 0x13, 0x15, 0xfd, 0x18, 0xeb, 0x3b, 0x22, + 0x00, 0xfa, 0xdd, 0xe4, 0xcc, 0xd1, 0x25, 0x28, 0xf2, 0xb8, 0xde, 0x16, 0x25, + 0x0f, 0x0e, 0xe5, 0xcd, 0xf1, 0x1e, 0x29, 0xe1, 0xfb, 0x2b, 0xb6, 0xe4, 0x02, + 0x00, 0xe3, 0x29, 0xe1, 0xda, 0x4d, 0xf2, 0xf7, 0x03, 0xc3, 0xed, 0xc8, 0x28, + 0xf8, 0xdd, 0xfe, 0x45, 0xf2, 0xb0, 0xe7, 0x31, 0xd0, 0xf7, 0xf5, 0xdd, 0x2e, + 0x18, 0xc7, 0x03, 0xeb, 0xbb, 0xd4, 0xb9, 0x2c, 0xd6, 0xef, 0xea, 0x29, 0xf2, + 0xfb, 0x0f, 0xa6, 0xcd, 0x32, 0xe9, 0xf5, 0xed, 0x2c, 0xe3, 0xe6, 0x10, 0xb0, + 0xd0, 0x49, 0xef, 0xfb, 0xab, 0xeb, 0xf7, 0xfd, 0x31, 0xef, 0xdf, 0xec, 0x08, + 0xd9, 0x35, 0x81, 0xc6, 0x24, 0xf0, 0x5a, 0xb0, 0x30, 0x3d, 0xe9, 0xbc, 0xdc, + 0xd8, 0x1b, 0xf2, 0xcc, 0x1c, 0xaf, 0x98, 0x09, 0xac, 0x38, 0xda, 0x05, 0x0a, + 0x3b, 0xcf, 0x28, 0xff, 0x35, 0xdc, 0x07, 0x20, 0x27, 0x57, 0xe3, 0xc4, 0x08, + 0x16, 0x0d, 0x30, 0x81, 0xab, 0x15, 0xe1, 0x10, 0x27, 0xa8, 0xd1, 0xcd, 0x42, + 0x0a, 0xf0, 0xed, 0x0d, 0x08, 0xc7, 0x30, 0xe3, 0x38, 0x0b, 0x24, 0xe6, 0x26, + 0x30, 0x59, 0x1b, 0xac, 0xf4, 0xc6, 0xb0, 0xdd, 0x52, 0x15, 0xb3, 0x2f, 0x8b, + 0x0a, 0xb8, 0xc2, 0x53, 0x1f, 0xae, 0x05, 0xf7, 0x45, 0x9e, 0xb9, 0xb4, 0x2d, + 0xe0, 0x10, 0xe3, 0x07, 0x1e, 0xef, 0xd1, 0x39, 0x9b, 0x34, 0xe6, 0x17, 0x5c, + 0xec, 0xc4, 0xe4, 0xf8, 0x42, 0xf9, 0xdd, 0x2a, 0x10, 0xb8, 0xa4, 0x24, 0xf8, + 0x00, 0x53, 0xd0, 0x0e, 0xdc, 0x9b, 0x26, 0x7d, 0xfa, 0x1f, 0x3d, 0xe7, 0xeb, + 0xc5, 0xf1, 0xc3, 0x0d, 0xeb, 0xc6, 0x27, 0x11, 0x4b, 0xd0, 0x13, 0xf3, 0xc5, + 0x05, 0x35, 0x2f, 0x06, 0xcc, 0xb9, 0x2a, 0xc4, 0x24, 0xef, 0x39, 0xf7, 0xa9, + 0xcf, 0xdf, 0xb0, 0xfd, 0xa3, 0x16, 0x23, 0x16, 0x00, 0xe5, 0xbd, 0xc8, 0xed, + 0xdf, 0x84, 0x03, 0xc2, 0x03, 0x27, 0xee, 0xf5, 0xf0, 0xde, 0x2a, 0x16, 0x01, + 0xba, 0xd6, 0xe0, 0x08, 0xf6, 0x10, 0xd0, 0x13, 0xeb, 0x31, 0x17, 0x2b, 0xc1, + 0x20, 0xfa, 0xeb, 0xf1, 0x21, 0x11, 0xe4, 0xc4, 0xf8, 0xfd, 0xf3, 0x46, 0x25, + 0x17, 0xfd, 0xe0, 0xfb, 0x00, 0xd9, 0xdb, 0xa4, 0xdc, 0x02, 0xae, 0xfa, 0xe0, + 0xd8, 0xe2, 0xf0, 0x11, 0xf2, 0x1d, 0x2f, 0x44, 0x0d, 0x28, 0x14, 0xb4, 0x06, + 0xe0, 0xe2, 0x36, 0x41, 0xf0, 0xc9, 0xf5, 0xd5, 0x47, 0x54, 0xda, 0xdd, 0x8a, + 0x04, 0xed, 0xae, 0x08, 0x64, 0xba, 0x60, 0xfc, 0x11, 0xe2, 0x05, 0x01, 0x6b, + 0x07, 0xf5, 0xc9, 0x14, 0xd5, 0xfd, 0x18, 0xf0, 0x2f, 0x06, 0xf9, 0x19, 0xf2, + 0x2c, 0x52, 0xa9, 0x76, 0xe0, 0xd4, 0xae, 0xc2, 0xdb, 0xd4, 0xef, 0xb9, 0xee, + 0x44, 0x1c, 0x13, 0xf2, 0xdc, 0xfb, 0xfc, 0xb2, 0xed, 0xed, 0xf4, 0x0a, 0xbd, + 0xee, 0xfa, 0xdd, 0xf6, 0xec, 0xfb, 0xda, 0xb2, 0xf9, 0x0e, 0xf1, 0x2c, 0x1d, + 0x08, 0xde, 0xcd, 0xf0, 0x0d, 0x0a, 0xfe, 0xbc, 0xdd, 0xfa, 0x30, 0x18, 0xd7, + 0x08, 0xcc, 0xd3, 0xf7, 0x03, 0x09, 0x15, 0x00, 0xfe, 0x0e, 0xd0, 0xed, 0x35, + 0x0c, 0xb6, 0xf3, 0xbb, 0x3d, 0xec, 0xf5, 0x23, 0xfe, 0x26, 0x5c, 0xed, 0x06, + 0xd1, 0xaf, 0xe7, 0x21, 0x37, 0xde, 0xd9, 0x28, 0x7f, 0x0d, 0x17, 0x16, 0x13, + 0xa0, 0xfc, 0xf2, 0xd5, 0x26, 0xbb, 0xdc, 0x19, 0x1d, 0x3f, 0x43, 0xd7, 0xed, + 0xfa, 0xcd, 0x0f, 0x94, 0x22, 0xfd, 0x1c, 0xfd, 0xe2, 0xf6, 0xde, 0x03, 0x04, + 0x20, 0xcd, 0xc7, 0x9d, 0x29, 0x0b, 0xf5, 0xec, 0xfc, 0x48, 0xfb, 0x70, 0xef, + 0xbc, 0xd8, 0x13, 0xc8, 0x48, 0xfc, 0xdf, 0x31, 0xeb, 0x42, 0xcd, 0xee, 0xcf, + 0x28, 0x1f, 0xf7, 0xaa, 0x0f, 0xd6, 0xd9, 0xd0, 0xfa, 0xda, 0xb7, 0xfc, 0x01, + 0xbb, 0x22, 0xe5, 0xe2, 0x1e, 0xf0, 0x00, 0x0d, 0x06, 0xc9, 0xd7, 0xea, 0xef, + 0x20, 0x02, 0xbd, 0x0e, 0xec, 0x19, 0xed, 0x12, 0xff, 0xdb, 0x00, 0x40, 0xed, + 0xec, 0xb7, 0xd5, 0xd5, 0x02, 0xd2, 0xdc, 0x17, 0xcb, 0x0c, 0xed, 0xe7, 0x01, + 0x0c, 0xe0, 0xd5, 0xf0, 0x23, 0xdb, 0xe0, 0xfc, 0x0f, 0xf6, 0x25, 0x21, 0xfd, + 0xf3, 0x45, 0x05, 0x19, 0x10, 0x12, 0xcb, 0xf6, 0x2d, 0x99, 0xdf, 0x36, 0xfd, + 0xb5, 0xee, 0xe3, 0xdf, 0x41, 0xf3, 0x03, 0xea, 0xd0, 0x03, 0xdb, 0x20, 0x1f, + 0x30, 0xf8, 0x3b, 0x15, 0x08, 0xc0, 0xe1, 0xff, 0xf2, 0xf0, 0x0b, 0xf0, 0x19, + 0x71, 0x0d, 0xe8, 0xcb, 0xd2, 0xf1, 0x27, 0xed, 0xeb, 0x12, 0xd6, 0xfd, 0x5a, + 0xf4, 0x37, 0x17, 0xd6, 0xb9, 0x23, 0xdc, 0x02, 0xad, 0x0d, 0xf7, 0xcb, 0xc4, + 0xb8, 0x3e, 0x15, 0xf8, 0xec, 0xfd, 0x06, 0xd1, 0xa0, 0xe0, 0x4c, 0x34, 0xef, + 0xb7, 0xef, 0xdc, 0x27, 0xbd, 0x01, 0xc3, 0x3e, 0xf1, 0xda, 0xd7, 0xa1, 0xde, + 0xfe, 0x39, 0xee, 0xaa, 0x09, 0xdd, 0xf4, 0xc8, 0x00, 0xaa, 0xc7, 0xc3, 0x19, + 0x08, 0x33, 0xf0, 0xe5, 0x24, 0x3b, 0x14, 0xf1, 0xc2, 0xcc, 0xcd, 0xea, 0xe0, + 0x44, 0xdd, 0xca, 0xbd, 0xf3, 0xd1, 0x01, 0xfe, 0x45, 0x26, 0x0c, 0xe3, 0x10, + 0x2d, 0x0e, 0x24, 0xd0, 0xd7, 0x32, 0xcf, 0x25, 0xf3, 0x2b, 0xe1, 0x04, 0xfe, + 0xf7, 0x2b, 0xdb, 0x02, 0x37, 0x11, 0xce, 0xcb, 0x39, 0x12, 0xbc, 0xf1, 0x0d, + 0x1e, 0xf8, 0x04, 0x49, 0x00, 0xd7, 0xe3, 0xd6, 0xf8, 0xe5, 0xf2, 0x38, 0x16, + 0x11, 0xde, 0xd4, 0xee, 0x29, 0xee, 0x14, 0x1a, 0xfc, 0x1f, 0xc2, 0xfc, 0x51, + 0xaf, 0xe2, 0x1f, 0xbf, 0xf5, 0xdf, 0x23, 0xcd, 0xc7, 0x05, 0xce, 0xd3, 0xf8, + 0x0e, 0xfa, 0x56, 0xef, 0xcf, 0x4d, 0xfb, 0xa6, 0xd2, 0x08, 0xe2, 0xe6, 0xde, + 0x2c, 0xe8, 0xc7, 0x27, 0xa8, 0xf1, 0xd2, 0xe6, 0x15, 0x0d, 0xf9, 0xfc, 0xd8, + 0x49, 0x2c, 0x2a, 0xd5, 0x0d, 0xf6, 0x13, 0x1c, 0x14, 0xe3, 0x15, 0x0a, 0x06, + 0xf1, 0x2e, 0x08, 0xfd, 0x2b, 0xf2, 0x81, 0x02, 0xcd, 0x3e, 0xd5, 0xe3, 0xb0, + 0xd3, 0x22, 0x13, 0x09, 0xd5, 0xc8, 0x25, 0xe0, 0x20, 0x21, 0xde, 0xf8, 0xf1, + 0xc1, 0x0b, 0xf8, 0xbd, 0xd7, 0x0b, 0x2e, 0xeb, 0xe5, 0xeb, 0xa5, 0xee, 0x01, + 0x17, 0xe7, 0xe7, 0xbd, 0xcf, 0xdd, 0xff, 0x19, 0xea, 0xec, 0xe7, 0xf3, 0x35, + 0xd0, 0x11, 0xb8, 0xae, 0x19, 0xef, 0x4e, 0xd7, 0xaf, 0xde, 0xf9, 0xa7, 0x14, + 0xf3, 0xed, 0xe8, 0x14, 0xeb, 0xd1, 0xad, 0xce, 0xff, 0xd3, 0xff, 0x2d, 0x56, + 0xbe, 0xee, 0xba, 0xc1, 0xae, 0x44, 0xe9, 0xe5, 0xc0, 0x21, 0xf2, 0xc6, 0xf7, + 0xce, 0x02, 0xfb, 0xa6, 0x47, 0x1f, 0x30, 0x05, 0x03, 0xf6, 0xd9, 0xdf, 0xc0, + 0xdb, 0x11, 0xf3, 0xa8, 0xd9, 0x12, 0xcc, 0x93, 0xe3, 0x37, 0xff, 0xd1, 0xe0, + 0xeb, 0xdf, 0xdb, 0x11, 0xcf, 0xdf, 0x36, 0xe9, 0xb7, 0x00, 0xf7, 0x1b, 0xad, + 0xd6, 0xe6, 0x24, 0x31, 0x19, 0x06, 0x03, 0xcd, 0xe7, 0x01, 0x19, 0xf6, 0xf9, + 0xf9, 0x2b, 0xfc, 0xed, 0x18, 0xb6, 0x5a, 0xe3, 0x0c, 0xd8, 0x07, 0x32, 0x15, + 0x1b, 0xf5, 0xc1, 0xe0, 0x37, 0xcd, 0x25, 0xd2, 0xcb, 0x43, 0x4d, 0xd6, 0x0f, + 0x17, 0xcc, 0xe4, 0x1f, 0xcd, 0x9a, 0x3e, 0x1b, 0x0a, 0x30, 0xed, 0xcd, 0x2a, + 0x44, 0xc7, 0xfa, 0xf9, 0x0f, 0xd0, 0xe3, 0xf5, 0x8b, 0xf6, 0xa7, 0xc4, 0x9f, + 0xdf, 0xe4, 0x12, 0x22, 0xd2, 0x26, 0x12, 0xfa, 0x19, 0xdc, 0xb9, 0x1b, 0x2b, + 0x09, 0x09, 0x57, 0x93, 0x95, 0x02, 0xea, 0xef, 0x16, 0xf3, 0x3e, 0x04, 0xf1, + 0xe3, 0xf2, 0x32, 0xc4, 0x43, 0x29, 0xd1, 0x33, 0xfa, 0xcd, 0x05, 0x4d, 0x24, + 0xe0, 0xd1, 0x1e, 0x28, 0x14, 0x50, 0xfb, 0x1e, 0x0e, 0xe7, 0x09, 0xc4, 0x0c, + 0xed, 0x08, 0x09, 0xbc, 0xf7, 0xe4, 0x00, 0xf4, 0xeb, 0x0e, 0x08, 0xf2, 0xfd, + 0x05, 0x07, 0x19, 0xba, 0x3e, 0xcc, 0xcb, 0x40, 0xea, 0x01, 0xf4, 0xb8, 0xee, + 0x21, 0xa5, 0xf6, 0x25, 0xf8, 0xe0, 0xeb, 0xe9, 0x34, 0xf3, 0x0f, 0xb2, 0x1e, + 0xca, 0xf1, 0xb1, 0xd4, 0xed, 0x04, 0x1c, 0xff, 0xe0, 0x2f, 0xa0, 0xe4, 0x03, + 0xa0, 0xf3, 0xd8, 0xf3, 0xfe, 0x23, 0xcf, 0xe7, 0x1a, 0x07, 0x0a, 0xdb, 0x81, + 0x75, 0x3f, 0xf1, 0x3f, 0x00, 0x0d, 0x0e, 0xaf, 0xf7, 0x2e, 0xfc, 0x01, 0x01, + 0xe5, 0x30, 0x21, 0xfd, 0xd3, 0xd8, 0xf0, 0xfc, 0x27, 0x00, 0x04, 0xfc, 0x3b, + 0xef, 0x10, 0xe8, 0x16, 0xfd, 0x15, 0xef, 0x07, 0x03, 0x06, 0x18, 0xe2, 0xd4, + 0xf1, 0x2d, 0x0f, 0xe1, 0xd6, 0xc2, 0xeb, 0xf7, 0xae, 0xcd, 0xfa, 0xf1, 0x11, + 0xed, 0x00, 0xf3, 0xd2, 0xe0, 0xf8, 0xbe, 0x00, 0x15, 0x23, 0x03, 0x1d, 0xbb, + 0xeb, 0x03, 0x05, 0x12, 0x26, 0x0e, 0xdc, 0xef, 0xce, 0xe4, 0xe3, 0x06, 0xef, + 0x35, 0x3c, 0x11, 0xeb, 0xfc, 0x0c, 0xf9, 0xde, 0xec, 0x3f, 0xf2, 0x1a, 0xc1, + 0xed, 0x06, 0x2d, 0xef, 0xc8, 0xe2, 0xf3, 0xb4, 0xf6, 0x23, 0x03, 0xdd, 0xd0, + 0x28, 0x10, 0xca, 0xed, 0xe9, 0x1d, 0x0a, 0xed, 0xd9, 0xfe, 0xd7, 0xe6, 0x21, + 0x02, 0xca, 0xda, 0xe2, 0xed, 0x07, 0x3a, 0xf5, 0xd3, 0xe7, 0xd9, 0xed, 0xcf, + 0xca, 0x0b, 0x07, 0xee, 0xfe, 0xe6, 0xf2, 0xff, 0xfb, 0x08, 0x0b, 0xe9, 0xf2, + 0xf5, 0xda, 0x02, 0xce, 0x33, 0xf4, 0xd1, 0xd7, 0xe1, 0x1b, 0x43, 0xfb, 0xfd, + 0xb3, 0xec, 0x19, 0xe5, 0xe1, 0xfc, 0x02, 0xf4, 0x1a, 0xbb, 0x28, 0x06, 0xcc, + 0x41, 0x22, 0xd2, 0xf5, 0xf4, 0x0a, 0x02, 0x7f, 0x16, 0xb8, 0xbd, 0xe6, 0xea, + 0xf0, 0x0e, 0xf5, 0xf8, 0x01, 0xc0, 0x15, 0xd1, 0xfb, 0xd3, 0xed, 0x13, 0xce, + 0xd2, 0xe8, 0x07, 0xf6, 0x00, 0x2c, 0xe3, 0x09, 0xf6, 0xf4, 0x09, 0x11, 0x1e, + 0x0d, 0x09, 0x35, 0xf5, 0x18, 0x13, 0xd2, 0xc0, 0xd4, 0x0e, 0xf1, 0x00, 0x17, + 0x2d, 0xce, 0xf2, 0x37, 0x33, 0xfe, 0x0f, 0x99, 0xe5, 0xe9, 0x10, 0xd6, 0x05, + 0xf9, 0xd5, 0xd8, 0xc6, 0xce, 0x07, 0xd1, 0xbc, 0x15, 0xf9, 0x0c, 0x1c, 0x2a, + 0xf1, 0x3d, 0xb9, 0x12, 0x76, 0xba, 0xf4, 0xe8, 0x27, 0x19, 0x1d, 0xf4, 0x15, + 0x37, 0x10, 0x06, 0xf3, 0xc3, 0x06, 0xfb, 0x39, 0xdb, 0xee, 0x11, 0xeb, 0x18, + 0xf9, 0xe4, 0xe7, 0x55, 0xec, 0xff, 0xd4, 0x14, 0xe4, 0xd3, 0xfa, 0xea, 0xdf, + 0x0d, 0xbd, 0xe4, 0xf2, 0x3b, 0x00, 0x06, 0xc7, 0x33, 0xbc, 0xde, 0xf8, 0xe6, + 0x01, 0xe6, 0xd7, 0xd7, 0xd8, 0x3c, 0xd7, 0xf8, 0xd0, 0xd5, 0xe7, 0xf3, 0xfe, + 0x16, 0xfc, 0xfa, 0xf4, 0x02, 0xd3, 0xfd, 0x37, 0x04, 0xc2, 0x0d, 0xde, 0xed, + 0x11, 0x24, 0x0d, 0x1c, 0xf7, 0x01, 0xfd, 0xed, 0xda, 0xd6, 0x3a, 0xb1, 0xda, + 0x04, 0xf9, 0xeb, 0xd8, 0xf0, 0xe5, 0x00, 0xe4, 0x0a, 0x3b, 0x05, 0xdc, 0xc9, + 0x40, 0xae, 0xdf, 0x12, 0x04, 0x52, 0xf8, 0x3c, 0x29, 0xfe, 0xe3, 0x28, 0xff, + 0x03, 0x10, 0xe4, 0x0e, 0x14, 0xec, 0x0c, 0xd0, 0xc5, 0x09, 0xfe, 0xb9, 0xf8, + 0xf6, 0x19, 0xdf, 0x29, 0x0d, 0xf4, 0x31, 0xf0, 0xfa, 0x32, 0x0e, 0xd0, 0xd4, + 0xf6, 0xfb, 0xf3, 0x2a, 0x08, 0xfe, 0xc4, 0x0e, 0x32, 0xc7, 0xd4, 0xf3, 0x0a, + 0xdc, 0xf6, 0xec, 0x10, 0x7f, 0xfa, 0x11, 0xd2, 0xe0, 0x3f, 0x1b, 0xb4, 0x2b, + 0x01, 0xd5, 0xeb, 0xe1, 0xef, 0x0c, 0xc1, 0xd0, 0xd3, 0xfe, 0xe8, 0xee, 0x29, + 0x11, 0x05, 0xe0, 0x17, 0xc7, 0xf0, 0xe3, 0xe9, 0xd6, 0x05, 0xeb, 0xeb, 0xa2, + 0xdc, 0xfd, 0x04, 0x18, 0x03, 0xe8, 0xd1, 0x3a, 0xd0, 0x08, 0xea, 0x11, 0x1b, + 0x1e, 0x1c, 0x23, 0xf2, 0xf5, 0x00, 0xf2, 0x1d, 0xf0, 0x01, 0xf5, 0xf0, 0xe2, + 0xfe, 0xfc, 0xf7, 0x0b, 0x03, 0xf3, 0x28, 0x04, 0xfc, 0xb4, 0xf6, 0xf5, 0x1f, + 0xe3, 0xd9, 0x23, 0x11, 0xb0, 0xe3, 0xe8, 0xe0, 0xe3, 0x0e, 0x23, 0xf0, 0x07, + 0x08, 0xc8, 0x0b, 0x1c, 0xe1, 0xd8, 0x0f, 0x1d, 0xf1, 0xf0, 0x24, 0xdb, 0x4d, + 0x06, 0x1e, 0x1e, 0xd5, 0x0d, 0x01, 0x0b, 0x03, 0xff, 0xc7, 0xf9, 0x25, 0x04, + 0xd5, 0x20, 0x0c, 0x0c, 0xee, 0x26, 0xfc, 0x23, 0x11, 0xfc, 0xd3, 0x06, 0x3c, + 0xc4, 0xaf, 0xed, 0xd5, 0xfc, 0xe7, 0x2e, 0xea, 0xf1, 0xf9, 0xfb, 0x03, 0x30, + 0xfb, 0xe4, 0xf7, 0xe3, 0x0e, 0xfd, 0xe0, 0xf9, 0x07, 0xf7, 0xcc, 0xfc, 0xe3, + 0xe6, 0xd4, 0xe8, 0x1c, 0xff, 0xb3, 0x28, 0xf5, 0xe6, 0xfc, 0x08, 0xd8, 0xe2, + 0x0c, 0x0c, 0x4c, 0x10, 0x19, 0x0a, 0xc7, 0x12, 0x14, 0x04, 0x22, 0x0d, 0xdb, + 0xe0, 0xe5, 0x26, 0xe5, 0x0e, 0x1b, 0xed, 0x16, 0xc3, 0xd1, 0x7f, 0x07, 0xc1, + 0x02, 0x0c, 0x13, 0x2d, 0x11, 0xcc, 0x15, 0xf3, 0x02, 0xed, 0xc4, 0x10, 0xce, + 0xc8, 0x1a, 0xeb, 0xf7, 0x19, 0x25, 0xe5, 0x12, 0x20, 0xfe, 0x22, 0xfa, 0xb5, + 0xd6, 0xed, 0x1b, 0x0b, 0xd7, 0xfb, 0xb1, 0xdc, 0xff, 0xef, 0x40, 0x2f, 0xf9, + 0xf0, 0xd1, 0xd7, 0xe6, 0xe9, 0xf6, 0xe1, 0xeb, 0xe2, 0xea, 0xf0, 0xe0, 0xce, + 0xbf, 0x0d, 0xdd, 0xd2, 0x07, 0x09, 0xd0, 0xa1, 0x18, 0x11, 0xdf, 0x0f, 0xcc, + 0x2f, 0xe1, 0x3e, 0xf2, 0xfe, 0xbd, 0x05, 0x00, 0xbc, 0xba, 0xb9, 0xf4, 0x03, + 0xd4, 0xc6, 0x01, 0xfa, 0xfb, 0x27, 0xfd, 0xef, 0x25, 0xe2, 0x03, 0xf7, 0x30, + 0x06, 0xc4, 0x94, 0xf7, 0xe2, 0x0c, 0xeb, 0xd9, 0xf5, 0x14, 0xc6, 0x0b, 0xff, + 0x0b, 0x2b, 0xf3, 0x11, 0x24, 0xe5, 0xd8, 0xf6, 0x04, 0x2d, 0x19, 0x1a, 0x0e, + 0x18, 0xcd, 0xf8, 0x11, 0x0f, 0x08, 0x2e, 0xdb, 0xe1, 0x3d, 0x05, 0xbd, 0xde, + 0x13, 0xf4, 0xd4, 0x0e, 0xd6, 0xe1, 0xcd, 0xfd, 0xde, 0x3a, 0xd0, 0x34, 0xf2, + 0xe1, 0xd8, 0x34, 0xc4, 0xdd, 0x11, 0xd2, 0xff, 0xda, 0xf6, 0xec, 0xd1, 0xbd, + 0xe4, 0xdd, 0xfc, 0x22, 0x13, 0x1f, 0x38, 0xd0, 0x24, 0x0f, 0xfe, 0x1a, 0xdf, + 0xde, 0x2b, 0x35, 0xe8, 0x34, 0x1e, 0x13, 0xf2, 0xfb, 0xac, 0xf1, 0xe6, 0x3d, + 0xe7, 0x20, 0xf6, 0x14, 0x0f, 0xe8, 0xfe, 0x26, 0x21, 0xf2, 0xc9, 0x20, 0xc4, + 0x2f, 0xc4, 0x33, 0xc9, 0xed, 0xfa, 0xcf, 0x10, 0xe1, 0xd0, 0xa9, 0xcd, 0xe1, + 0xfb, 0xf3, 0xfc, 0x4e, 0xcc, 0x2f, 0x19, 0x10, 0x84, 0x18, 0xdf, 0x44, 0x19, + 0xf7, 0xb5, 0xc7, 0xdb, 0xca, 0xef, 0x0d, 0x08, 0xf7, 0x81, 0xb1, 0xef, 0xd4, + 0x3c, 0xab, 0xc6, 0xbc, 0xef, 0xfd, 0x0c, 0x1e, 0xd6, 0x0a, 0xfa, 0x4f, 0x09, + 0xec, 0x39, 0x2c, 0x25, 0xe0, 0xca, 0xf2, 0xff, 0xd1, 0xf8, 0xf7, 0x2e, 0xfd, + 0x13, 0x14, 0x09, 0xef, 0x04, 0x01, 0xa9, 0x39, 0x1b, 0xd1, 0x14, 0xdb, 0xc2, + 0x08, 0x01, 0x40, 0xd3, 0xff, 0x2b, 0x09, 0xb2, 0xeb, 0x03, 0x01, 0x0c, 0x2b, + 0x25, 0xf3, 0xe1, 0xe5, 0xe2, 0x71, 0xf0, 0xfc, 0x0d, 0x04, 0xe7, 0xaf, 0x11, + 0xb7, 0x16, 0xf0, 0xf1, 0x40, 0xaf, 0xe5, 0xf0, 0x0d, 0xf7, 0xd3, 0xff, 0x2b, + 0xa6, 0x2c, 0xc8, 0x1b, 0xff, 0xb5, 0x03, 0xe1, 0x10, 0xd2, 0xf8, 0x00, 0x15, + 0xe0, 0xfd, 0xed, 0x5a, 0xeb, 0x16, 0xed, 0x0b, 0xc2, 0xf6, 0x03, 0x0a, 0xf1, + 0xd5, 0x01, 0x24, 0x0e, 0xbe, 0xfa, 0xf1, 0x01, 0x02, 0x28, 0x19, 0xee, 0x1d, + 0x15, 0x0e, 0xf2, 0x12, 0xa8, 0x01, 0xee, 0xff, 0x34, 0x11, 0xf0, 0x2f, 0x27, + 0xee, 0xf6, 0xeb, 0xfb, 0x09, 0xcb, 0x21, 0x1c, 0x2b, 0x29, 0x10, 0x1e, 0x06, + 0x07, 0x20, 0x3c, 0xfa, 0xd9, 0xb6, 0x04, 0x42, 0x30, 0xdd, 0x2d, 0xe8, 0xf6, + 0xcd, 0xfb, 0x0a, 0x1d, 0xf2, 0x5f, 0xe6, 0x05, 0x2c, 0x0d, 0xdc, 0x28, 0xec, + 0xe6, 0x08, 0xf9, 0x28, 0xca, 0x1b, 0x0e, 0xdd, 0x12, 0xc1, 0xdf, 0x06, 0xe8, + 0xeb, 0x3e, 0x25, 0xea, 0xf7, 0xbd, 0xf5, 0xdb, 0xdf, 0xdc, 0x4a, 0x27, 0xff, + 0xff, 0x08, 0x19, 0x90, 0x1c, 0xe5, 0x3d, 0xe6, 0xf8, 0xf8, 0xcc, 0x0e, 0xd7, + 0xf3, 0x1e, 0xd7, 0xae, 0xd1, 0x14, 0xd2, 0xfa, 0xa2, 0xe6, 0x25, 0x41, 0x39, + 0xff, 0x17, 0xef, 0x0e, 0x19, 0xac, 0x11, 0xd1, 0x08, 0x08, 0xc5, 0xf3, 0x27, + 0xbb, 0xfd, 0xe9, 0xd5, 0x8e, 0xdf, 0x15, 0xcf, 0xe0, 0xd9, 0xfd, 0x10, 0xe6, + 0x28, 0xee, 0x1a, 0xe9, 0xed, 0x81, 0xca, 0x0d, 0xba, 0x0a, 0xc4, 0xd5, 0xe4, + 0xe9, 0xd0, 0xdc, 0xf7, 0xa9, 0xe7, 0xbc, 0x40, 0x0b, 0x09, 0xe4, 0xf6, 0xb2, + 0x12, 0xf0, 0x69, 0x44, 0x06, 0xef, 0x11, 0x16, 0x54, 0x2f, 0xe8, 0xb4, 0x9d, + 0x25, 0xdb, 0x0e, 0x0f, 0xee, 0x17, 0x18, 0x14, 0xbc, 0xfc, 0x0b, 0x27, 0xd5, + 0xef, 0xbb, 0x19, 0xd9, 0x01, 0x07, 0xf4, 0x13, 0x45, 0xb3, 0x0d, 0x0b, 0xb2, + 0xbb, 0x25, 0x0a, 0x25, 0x00, 0xe2, 0x13, 0xfb, 0xff, 0xb8, 0xe4, 0xf5, 0xdd, + 0xbb, 0xff, 0x3a, 0xcb, 0xd6, 0xf5, 0x09, 0x41, 0x10, 0xd5, 0xef, 0xca, 0xf2, + 0x31, 0x90, 0x0e, 0x28, 0xed, 0x00, 0xd8, 0x3f, 0xc5, 0xe5, 0xf8, 0x42, 0x3a, + 0x30, 0x2a, 0xee, 0xff, 0xd0, 0x2f, 0x0d, 0xb1, 0xe2, 0x07, 0xe3, 0x3a, 0xdb, + 0xa2, 0xe7, 0x3d, 0xf5, 0xcf, 0xf7, 0xec, 0x08, 0x3d, 0x29, 0x0d, 0x04, 0xe8, + 0x8a, 0xe8, 0xd4, 0x40, 0xdc, 0xf6, 0xeb, 0xc9, 0xd0, 0xdf, 0xeb, 0xec, 0xf9, + 0xff, 0xcb, 0x43, 0xef, 0xe3, 0x25, 0x03, 0x19, 0x01, 0x01, 0xd3, 0x21, 0x36, + 0x1f, 0x2d, 0x08, 0x2d, 0xce, 0xff, 0xf3, 0xe3, 0x08, 0xeb, 0xf1, 0x02, 0x35, + 0x19, 0x62, 0x26, 0xd6, 0xd3, 0x18, 0x37, 0xd9, 0xc5, 0x36, 0x32, 0xf1, 0xb8, + 0x59, 0xe3, 0x48, 0xf7, 0xdf, 0xd6, 0xea, 0xd4, 0x30, 0xfb, 0x33, 0x5f, 0xbc, + 0xc1, 0xf6, 0xe5, 0xb5, 0x31, 0x02, 0x1f, 0x24, 0xee, 0xe8, 0xe5, 0x6a, 0x9b, + 0x02, 0xdd, 0x2f, 0xf5, 0x21, 0x2d, 0x1e, 0xc9, 0x2c, 0x15, 0x08, 0xc5, 0xbe, + 0xd5, 0x2d, 0xfc, 0xe3, 0x8b, 0x13, 0xd0, 0xee, 0x0d, 0x1e, 0x66, 0xec, 0x10, + 0xe8, 0x1e, 0x2e, 0xeb, 0xdd, 0x45, 0xca, 0xc1, 0xfe, 0xcc, 0xfe, 0xb7, 0xbd, + 0xc9, 0xc3, 0x1f, 0xc2, 0xb1, 0x14, 0xae, 0x31, 0xe1, 0xd1, 0x30, 0x07, 0xf3, + 0xa8, 0x3e, 0x93, 0x45, 0x2c, 0xed, 0x8f, 0xd1, 0xb8, 0xd0, 0x1a, 0x27, 0xc4, + 0xa3, 0xdd, 0x0d, 0x7f, 0x2b, 0x07, 0xde, 0xf9, 0x3b, 0x2f, 0xc2, 0xfd, 0xa0, + 0xcb, 0xbb, 0x3a, 0xf7, 0xe7, 0xe0, 0x03, 0x04, 0x06, 0xbc, 0xbc, 0xbf, 0x11, + 0x05, 0xda, 0xd6, 0x4e, 0xb7, 0x35, 0xd2, 0x68, 0x1b, 0x39, 0xe1, 0xd0, 0x0d, + 0x11, 0x26, 0xcf, 0xeb, 0xef, 0xc7, 0xfd, 0x19, 0xdf, 0xca, 0x43, 0xd1, 0xa5, + 0x2c, 0x55, 0x0b, 0x17, 0x31, 0xd7, 0xc9, 0xe7, 0xf3, 0xe2, 0xfe, 0xc4, 0xdd, + 0x5c, 0xd5, 0xfe, 0xc6, 0xce, 0x5a, 0x06, 0xbc, 0xa7, 0x55, 0xf4, 0xbf, 0xf0, + 0x44, 0x29, 0xe6, 0x2c, 0xd2, 0xa4, 0x27, 0xbb, 0x24, 0xc4, 0xd1, 0xd9, 0xaa, + 0xb7, 0xbc, 0xaf, 0xe1, 0x30, 0xa9, 0x9b, 0x13, 0xf1, 0x54, 0x45, 0x21, 0xe8, + 0x0d, 0xf0, 0xf3, 0xc5, 0x56, 0x01, 0xf4, 0xee, 0xfa, 0x11, 0x0d, 0x1b, 0xb8, + 0xe2, 0xc1, 0xf7, 0xc7, 0xb0, 0xd0, 0x23, 0xfa, 0xec, 0xe2, 0xfb, 0x23, 0xd3, + 0x02, 0x44, 0x2f, 0x4b, 0x95, 0x0c, 0x03, 0x41, 0xed, 0x35, 0x14, 0xfb, 0x45, + 0xd4, 0xf0, 0xf0, 0xf2, 0x13, 0xc5, 0x25, 0xb4, 0xdb, 0x1b, 0xc2, 0xda, 0xf0, + 0x18, 0xd7, 0xdc, 0xcb, 0xac, 0xe2, 0xc8, 0xfe, 0xff, 0x14, 0xee, 0xb4, 0x12, + 0xf0, 0xd8, 0xd3, 0xc6, 0xd2, 0xbd, 0x9f, 0xbb, 0x6b, 0xe9, 0x39, 0xbf, 0x14, + 0xe5, 0xed, 0x0d, 0xcd, 0xfb, 0xee, 0x57, 0x94, 0xbf, 0x0f, 0x0a, 0xcf, 0x00, + 0xf1, 0xdb, 0x0e, 0x2b, 0x05, 0xc0, 0xeb, 0x07, 0xe6, 0x5e, 0x56, 0x11, 0xd9, + 0x29, 0x1a, 0x17, 0x0f, 0x3a, 0x04, 0xb4, 0x22, 0x06, 0xf9, 0x0c, 0xe8, 0x33, + 0xe1, 0x8c, 0x30, 0xf4, 0xcf, 0x50, 0x32, 0xa6, 0xb1, 0x2c, 0xb1, 0x0a, 0xc0, + 0x2f, 0xe4, 0x08, 0xbf, 0xea, 0xff, 0xda, 0xf5, 0x81, 0xc7, 0x0f, 0xeb, 0xe2, + 0x53, 0x56, 0xd8, 0xb2, 0xe0, 0xdf, 0x2d, 0x20, 0xf2, 0xec, 0xf0, 0x22, 0xe6, + 0x3d, 0x0d, 0x2c, 0x34, 0x05, 0x0c, 0x1b, 0xe7, 0x35, 0x25, 0x41, 0x3e, 0xeb, + 0x08, 0x21, 0xc5, 0x22, 0xd8, 0x1a, 0xc0, 0xce, 0x9e, 0x05, 0xc4, 0xf4, 0xa5, + 0x23, 0x40, 0x0f, 0xce, 0xc4, 0xf2, 0x49, 0x01, 0xd8, 0x07, 0x27, 0x36, 0xcf, + 0x15, 0xf7, 0x02, 0xbf, 0x96, 0xe5, 0xd7, 0x17, 0x59, 0x49, 0x1f, 0x97, 0xe7, + 0xdb, 0xd3, 0xea, 0xdb, 0xf7, 0x0a, 0x09, 0x0e, 0xa9, 0xc6, 0x0c, 0xb9, 0xcc, + 0x31, 0xd1, 0xd5, 0xc9, 0x01, 0x6d, 0x2d, 0xc6, 0xed, 0xc3, 0xa5, 0xca, 0xdc, + 0xdd, 0x97, 0xc1, 0xf8, 0x28, 0xc5, 0x06, 0x1b, 0x3b, 0xdd, 0xc0, 0xf3, 0xc4, + 0x2e, 0xf7, 0xf1, 0xeb, 0x20, 0xe8, 0xfe, 0xb6, 0x6b, 0xcf, 0x2c, 0x03, 0xb4, + 0xdb, 0x54, 0x05, 0xe3, 0xae, 0x1b, 0x32, 0xc8, 0x0d, 0xa1, 0x15, 0xdf, 0x32, + 0x29, 0x17, 0xfc, 0xf5, 0x0b, 0x18, 0x2a, 0x1f, 0x13, 0xbe, 0x09, 0xf5, 0xb8, + 0xac, 0xf2, 0x55, 0xd9, 0xbd, 0xca, 0x27, 0x4d, 0xdd, 0xc3, 0x1c, 0xdb, 0x09, + 0xe9, 0xd4, 0x0a, 0xae, 0xf3, 0x61, 0x19, 0xb7, 0xff, 0x00, 0xec, 0xfe, 0xf7, + 0xbe, 0xf8, 0x61, 0xda, 0xf8, 0x27, 0x2c, 0xd4, 0xfc, 0xf5, 0x42, 0xde, 0xdc, + 0x47, 0x65, 0x40, 0xbc, 0xf6, 0xdb, 0xf3, 0xc6, 0xa4, 0x00, 0xea, 0x21, 0x00, + 0x15, 0x48, 0x09, 0xbf, 0x2f, 0xec, 0xd9, 0xb9, 0xde, 0x9e, 0x28, 0xe1, 0xec, + 0x5d, 0xea, 0x27, 0x35, 0xc3, 0x46, 0xfd, 0xef, 0x1d, 0xf2, 0x9c, 0xd4, 0xf0, + 0x04, 0xe1, 0xcf, 0xb5, 0xd8, 0xf9, 0xef, 0xed, 0xf8, 0x21, 0xdc, 0x17, 0xd8, + 0x20, 0xf0, 0xeb, 0xbc, 0x06, 0x0d, 0xe6, 0xe6, 0xc2, 0x0c, 0x03, 0xc8, 0xf6, + 0xcb, 0xc3, 0xf8, 0xfd, 0x14, 0x17, 0xf3, 0x11, 0x13, 0xfe, 0xea, 0xf8, 0xd9, + 0xcd, 0xfa, 0x22, 0xf6, 0x03, 0x25, 0x02, 0x14, 0x20, 0x02, 0xfe, 0xad, 0xe2, + 0x3c, 0x07, 0xfb, 0x40, 0x13, 0xef, 0xea, 0x08, 0x1a, 0x1f, 0x36, 0xe6, 0xe0, + 0xde, 0xf9, 0xfa, 0xcd, 0x04, 0xce, 0x1c, 0xe3, 0xf3, 0x1d, 0x31, 0xdf, 0x15, + 0xe7, 0xfd, 0xcd, 0x03, 0xf2, 0xfb, 0xa8, 0xf4, 0x0b, 0x26, 0xff, 0x23, 0xb5, + 0x9d, 0xee, 0xf6, 0xeb, 0x23, 0xcd, 0xe8, 0xeb, 0xfe, 0x1b, 0xde, 0x00, 0xe0, + 0x28, 0x00, 0xca, 0x22, 0xdf, 0xfa, 0x05, 0xe5, 0x3e, 0xf9, 0xfc, 0x2b, 0xe4, + 0xf5, 0xee, 0xed, 0xdf, 0xb5, 0xd2, 0x00, 0xe0, 0xd6, 0x03, 0xfb, 0xe0, 0xe1, + 0xf7, 0xc2, 0xc2, 0x1b, 0xcd, 0xcd, 0xb8, 0x07, 0xe6, 0x00, 0xf1, 0x02, 0xd2, + 0xea, 0x3b, 0x04, 0x08, 0xba, 0xe2, 0xc1, 0xb9, 0xc0, 0xf8, 0x19, 0x65, 0x2c, + 0xd9, 0xf2, 0xfe, 0xd2, 0xdd, 0xd4, 0x17, 0x2e, 0x2c, 0x0a, 0x59, 0x4c, 0x14, + 0xf3, 0xd7, 0x40, 0xc7, 0x36, 0x3c, 0x01, 0xdd, 0x24, 0xf6, 0x1d, 0xdd, 0x31, + 0xf9, 0xdb, 0xd7, 0xfa, 0xd9, 0xf9, 0xf7, 0xbb, 0x25, 0x1a, 0xea, 0x21, 0xe4, + 0xf3, 0xfb, 0xef, 0x81, 0xf6, 0x55, 0xd7, 0xf4, 0x4d, 0xf2, 0x09, 0x1e, 0x36, + 0xfa, 0xec, 0xdc, 0xdd, 0xe6, 0xe1, 0x11, 0xca, 0x18, 0xe0, 0xff, 0xf0, 0xd0, + 0xe1, 0x12, 0xaa, 0xba, 0x22, 0x34, 0x0c, 0x05, 0x1a, 0x00, 0xd2, 0xec, 0x2b, + 0x37, 0xe8, 0xdd, 0x0b, 0x1f, 0xb9, 0xdd, 0xd3, 0x08, 0x22, 0xd7, 0x4e, 0xeb, + 0x14, 0x26, 0x0e, 0xfc, 0xdc, 0xe7, 0x2b, 0xf2, 0x3c, 0x12, 0xdd, 0xf9, 0xe9, + 0xf7, 0xdb, 0xff, 0xee, 0xda, 0xe5, 0x15, 0xe7, 0xe4, 0xdf, 0x0f, 0x0a, 0x1b, + 0xf2, 0x04, 0x04, 0xfa, 0x0d, 0xeb, 0xe7, 0xd2, 0x31, 0xfa, 0xf1, 0xca, 0x15, + 0xf7, 0xf8, 0xf2, 0xf4, 0x19, 0x10, 0x38, 0xef, 0x14, 0xf4, 0xe6, 0x10, 0x04, + 0xeb, 0x10, 0xdc, 0xfb, 0x07, 0xf1, 0x0f, 0xd7, 0xf4, 0xeb, 0xfd, 0x02, 0x7f, + 0x26, 0xe8, 0xf3, 0xcf, 0x21, 0x0d, 0xf9, 0xeb, 0xe4, 0xd5, 0x14, 0xda, 0xe0, + 0xe9, 0xf8, 0xcf, 0x04, 0xd1, 0xc8, 0xe4, 0xe5, 0x29, 0x5c, 0xcc, 0x19, 0xf9, + 0xe0, 0x0d, 0x09, 0x04, 0x2e, 0x0b, 0x04, 0xfd, 0xda, 0x09, 0xf0, 0xcd, 0x1f, + 0xd7, 0xdb, 0x05, 0x1d, 0xe0, 0x0f, 0x02, 0x04, 0xf7, 0xee, 0xde, 0xd5, 0x0f, + 0x05, 0xeb, 0xe1, 0xed, 0x13, 0xdc, 0x10, 0xe9, 0x14, 0xd1, 0xf8, 0xfe, 0xed, + 0xf3, 0xec, 0xfb, 0xfd, 0xd6, 0x19, 0x21, 0x04, 0xfc, 0xe2, 0xf2, 0xeb, 0xd0, + 0xf9, 0x23, 0x02, 0x38, 0x05, 0x0d, 0xfe, 0xf6, 0xde, 0xca, 0xc3, 0x28, 0x0a, + 0xfa, 0xed, 0x07, 0xdb, 0xf3, 0x12, 0x30, 0x2a, 0xf9, 0xe1, 0xe6, 0x09, 0xd5, + 0xff, 0x30, 0x09, 0x3e, 0xfa, 0xfe, 0x2d, 0xf0, 0xf8, 0xfd, 0xda, 0x27, 0xfd, + 0xf1, 0xc7, 0xff, 0xd6, 0xe9, 0x02, 0xf2, 0xfc, 0xfa, 0x08, 0xde, 0xd4, 0x00, + 0xe4, 0xc7, 0x2d, 0xf4, 0x16, 0x05, 0x01, 0xf9, 0xd4, 0x01, 0x07, 0xcd, 0xf0, + 0x32, 0xde, 0xc8, 0xfe, 0x08, 0x16, 0xe2, 0x1e, 0xfd, 0xf6, 0xeb, 0x00, 0x13, + 0x31, 0xfa, 0x08, 0x14, 0xb7, 0x13, 0xff, 0x1b, 0xcf, 0x16, 0x0d, 0xe6, 0x08, + 0xf7, 0xf6, 0xc8, 0x24, 0xdf, 0xf0, 0x0a, 0x01, 0xfc, 0xf3, 0x04, 0xdc, 0xc0, + 0xc3, 0xe8, 0x14, 0x23, 0xd2, 0xe4, 0xe7, 0x08, 0xc6, 0xfe, 0xe8, 0x0d, 0xea, + 0x07, 0x03, 0xdb, 0x03, 0xf4, 0xf9, 0xb8, 0x1d, 0xea, 0x35, 0xc7, 0x41, 0x27, + 0xcf, 0xea, 0xf3, 0xd4, 0xd5, 0x22, 0xd4, 0xe5, 0x07, 0xb6, 0xe7, 0xe6, 0xe9, + 0xd7, 0x04, 0xbd, 0xf7, 0xed, 0xf9, 0xcf, 0x00, 0xc9, 0x18, 0x3b, 0xf5, 0xd5, + 0x43, 0xea, 0x37, 0x02, 0xe4, 0xf8, 0xd2, 0x17, 0x07, 0xfe, 0x0d, 0xe4, 0x0e, + 0xa1, 0xff, 0x3b, 0xf9, 0xf3, 0xdd, 0x2f, 0x1e, 0x7f, 0x00, 0xdd, 0xf1, 0xb5, + 0x17, 0xd3, 0x5b, 0xdd, 0xc9, 0xe5, 0x33, 0x0b, 0xe2, 0x31, 0xa1, 0x09, 0xf5, + 0xb7, 0xf7, 0xd5, 0x9f, 0x4a, 0x3e, 0xd0, 0xd4, 0xe6, 0xb9, 0xef, 0xed, 0xd0, + 0x61, 0xf2, 0x34, 0x2f, 0x0a, 0xff, 0x19, 0xf1, 0x36, 0xc0, 0xf0, 0xce, 0x6c, + 0x08, 0xb9, 0xce, 0xd8, 0xbb, 0x63, 0xe2, 0x20, 0x3f, 0x24, 0xcb, 0xdb, 0xd2, + 0xf9, 0x0a, 0xea, 0xdf, 0x2d, 0xca, 0x13, 0x14, 0xb0, 0xea, 0xff, 0x22, 0xcf, + 0x06, 0x07, 0xf7, 0xef, 0x32, 0xf3, 0x0b, 0x0d, 0xa1, 0x98, 0xfb, 0xd9, 0x29, + 0xec, 0x40, 0x01, 0x20, 0xc8, 0xfe, 0xf1, 0x2b, 0x07, 0xff, 0x06, 0xe6, 0x05, + 0xce, 0x1d, 0x56, 0xe1, 0xe1, 0x00, 0x13, 0xe0, 0xfd, 0x0e, 0xff, 0xfc, 0x51, + 0x0b, 0x25, 0x01, 0xef, 0x39, 0x34, 0x38, 0xe6, 0xf3, 0xdc, 0xf3, 0x42, 0xe3, + 0x13, 0x04, 0x07, 0xef, 0xd1, 0xea, 0xfe, 0xe1, 0xd0, 0xd8, 0xf4, 0x2f, 0xee, + 0xef, 0xeb, 0x14, 0xfe, 0xf2, 0x0d, 0xb1, 0x17, 0x00, 0x24, 0xad, 0xb8, 0xb8, + 0x0f, 0xd9, 0x09, 0xf6, 0xbf, 0x19, 0xf4, 0x0e, 0xf4, 0x2a, 0x1a, 0xfe, 0x22, + 0xf5, 0xfa, 0x3b, 0x22, 0xb9, 0x67, 0x10, 0x10, 0xc4, 0x0b, 0x00, 0xcf, 0x45, + 0xdd, 0xbc, 0x4c, 0xf2, 0x43, 0xb9, 0x07, 0xe2, 0xc9, 0xf9, 0x0b, 0xf0, 0xee, + 0xd4, 0xe0, 0xe7, 0x2b, 0xe2, 0xc6, 0xd8, 0xeb, 0xc7, 0x1d, 0xd9, 0xf9, 0x00, + 0x15, 0xfe, 0xdf, 0x06, 0xd8, 0x04, 0x05, 0xeb, 0x1c, 0xdb, 0xcf, 0x35, 0xe2, + 0x0a, 0xf4, 0xf7, 0x09, 0x13, 0xfd, 0xfe, 0xe0, 0xe9, 0xf8, 0xfd, 0xc0, 0xdd, + 0xf4, 0x1a, 0xff, 0xf1, 0xcf, 0x15, 0x34, 0xf5, 0xea, 0x14, 0x11, 0x04, 0xf9, + 0xeb, 0x0d, 0xe2, 0xc8, 0x0c, 0x09, 0x04, 0xc5, 0xe4, 0xfd, 0x0b, 0x15, 0x2f, + 0xf5, 0x11, 0x18, 0x08, 0x7f, 0x01, 0x05, 0xfc, 0xf9, 0xf9, 0x0d, 0x0b, 0xe1, + 0xd0, 0xef, 0x14, 0x23, 0xf6, 0x0d, 0xba, 0xe8, 0x0f, 0xd8, 0xe3, 0x09, 0xd9, + 0x06, 0x3d, 0x08, 0x05, 0xfa, 0xf7, 0x02, 0xf5, 0xd1, 0x4e, 0xf1, 0x14, 0xfd, + 0xc8, 0xec, 0xe5, 0xf3, 0x15, 0xd2, 0xd8, 0xda, 0x08, 0xeb, 0xe9, 0xdf, 0xdf, + 0xec, 0xf2, 0x09, 0x04, 0x07, 0x1f, 0xec, 0x0c, 0xcf, 0x10, 0x06, 0xf7, 0xfb, + 0xe8, 0xcb, 0xff, 0x15, 0xc3, 0xf4, 0xe6, 0xf3, 0xf5, 0xef, 0xea, 0x0c, 0x19, + 0xe9, 0x1f, 0xed, 0xc9, 0xef, 0xde, 0xec, 0x07, 0x27, 0xd5, 0x08, 0xec, 0xec, + 0xe8, 0xcc, 0xe0, 0xfc, 0xca, 0xf4, 0xc4, 0xf2, 0xdd, 0x13, 0x20, 0x20, 0x2a, + 0xf4, 0xea, 0xfb, 0xe8, 0x19, 0x16, 0xfc, 0xe2, 0x1d, 0xea, 0xfb, 0x35, 0x14, + 0x14, 0xbe, 0x0a, 0x2c, 0x0f, 0xe1, 0xe5, 0xf8, 0xcd, 0xf4, 0x03, 0xff, 0xeb, + 0x09, 0x09, 0xbd, 0xdf, 0xf9, 0xea, 0xf2, 0x0b, 0x06, 0xf1, 0xf8, 0xec, 0xf7, + 0xf3, 0xe5, 0xf3, 0xf6, 0xf8, 0x25, 0xe9, 0xe9, 0xc7, 0x1a, 0x05, 0x05, 0x0e, + 0x0c, 0x05, 0xec, 0x19, 0xfa, 0x28, 0xe2, 0x06, 0x13, 0xe1, 0x18, 0xe9, 0x06, + 0xf9, 0xfe, 0x09, 0x06, 0x00, 0xe9, 0xef, 0xf1, 0xf8, 0xf5, 0xed, 0x2c, 0x15, + 0xef, 0xdd, 0x08, 0xcd, 0xd0, 0xdf, 0xfc, 0xf5, 0xf9, 0xdc, 0xdc, 0xdb, 0xff, + 0xe0, 0x2e, 0xed, 0x02, 0xfb, 0xfd, 0xeb, 0xf5, 0xe3, 0x2d, 0xc6, 0xd6, 0x1b, + 0xe9, 0xfb, 0x16, 0x09, 0x0b, 0xc1, 0xea, 0xe6, 0x09, 0xff, 0xf5, 0xfc, 0x34, + 0xf6, 0x1c, 0xfd, 0x0a, 0x02, 0x04, 0x12, 0xf5, 0x12, 0xe0, 0xf5, 0xc2, 0xf2, + 0xf0, 0x0d, 0x0f, 0xf7, 0xe8, 0xec, 0x2e, 0x34, 0xe2, 0xe1, 0x18, 0xfd, 0xba, + 0x08, 0x14, 0xf2, 0xea, 0x15, 0x1d, 0xda, 0x0c, 0x1a, 0xfe, 0xe6, 0x0b, 0x01, + 0x32, 0x25, 0x22, 0xec, 0xca, 0x11, 0xed, 0x22, 0xde, 0xf9, 0xf8, 0x0f, 0xd1, + 0x03, 0xfc, 0x04, 0xf5, 0x0d, 0xb3, 0xe6, 0x2e, 0xe9, 0xf0, 0x22, 0x15, 0x52, + 0x14, 0xf0, 0xe6, 0x27, 0xfb, 0x19, 0xe9, 0x28, 0xe6, 0xff, 0xba, 0xf5, 0x07, + 0x04, 0xbd, 0x07, 0xe1, 0x05, 0xea, 0x08, 0xec, 0xda, 0xb9, 0x32, 0xe7, 0xec, + 0x0e, 0x05, 0xad, 0xef, 0xf0, 0xe7, 0xe9, 0x27, 0xd6, 0xe4, 0x26, 0x05, 0x07, + 0xc4, 0xd5, 0xf7, 0xfd, 0xcb, 0xf4, 0x21, 0xe6, 0x0c, 0x25, 0x0b, 0xcc, 0x1f, + 0xc1, 0x2d, 0x04, 0x1e, 0x49, 0x1f, 0x3c, 0x19, 0x00, 0xe5, 0xaa, 0xcf, 0xd5, + 0xc9, 0x03, 0xd6, 0xcf, 0xe4, 0xf0, 0x05, 0x2f, 0x07, 0xf1, 0xc5, 0x2a, 0x25, + 0xfd, 0x30, 0x42, 0xf2, 0x01, 0xfd, 0xe1, 0x0c, 0xf7, 0x1e, 0x7f, 0x04, 0x16, + 0xc3, 0xde, 0xd8, 0x00, 0xc9, 0xe0, 0x35, 0xfc, 0xf0, 0x06, 0x31, 0xec, 0x0d, + 0xd6, 0xe0, 0xd1, 0x2c, 0xcd, 0xc8, 0xf9, 0xf9, 0xfd, 0xe9, 0xf4, 0x0d, 0xc5, + 0xe2, 0x29, 0xce, 0xdf, 0xe4, 0xf3, 0x07, 0x1c, 0x0b, 0xf6, 0x13, 0xe3, 0x06, + 0x00, 0x36, 0x09, 0xd7, 0xce, 0xdc, 0x19, 0xff, 0x14, 0xe2, 0x09, 0xdd, 0x09, + 0xf6, 0xc6, 0xf7, 0x9f, 0x0b, 0xeb, 0xd4, 0x0a, 0x22, 0x28, 0xd8, 0xcc, 0xcf, + 0xdc, 0xd6, 0xc1, 0x02, 0xf8, 0xdd, 0x0c, 0xef, 0x40, 0xd9, 0xd1, 0xc9, 0x07, + 0xee, 0xea, 0xda, 0xac, 0xeb, 0x37, 0xe1, 0xd7, 0x07, 0xc3, 0x1f, 0xfe, 0x12, + 0xe6, 0xe1, 0xf7, 0x1d, 0xb7, 0x29, 0x18, 0xd1, 0x3f, 0x00, 0xb6, 0x1a, 0xd5, + 0xf4, 0x0d, 0xeb, 0xab, 0xe4, 0xe1, 0x14, 0xf1, 0xdd, 0xcb, 0xf2, 0x0e, 0x03, + 0xe6, 0xd5, 0x21, 0x4e, 0xe0, 0xcc, 0x07, 0x20, 0xce, 0x12, 0xb1, 0xe5, 0xd8, + 0x13, 0xb8, 0x0c, 0xeb, 0xda, 0xfb, 0x0a, 0xd5, 0xe8, 0x66, 0x28, 0xfb, 0xee, + 0x94, 0x35, 0xc4, 0x24, 0xc8, 0x29, 0x12, 0x0c, 0xf3, 0xee, 0x28, 0x96, 0x03, + 0x22, 0xf2, 0xf2, 0xe3, 0x95, 0xf2, 0x7f, 0xf6, 0xeb, 0x03, 0x29, 0xe9, 0xd7, + 0xe4, 0x33, 0xeb, 0x49, 0xfd, 0xdc, 0xc5, 0x1b, 0xf0, 0x2c, 0x87, 0xf4, 0x04, + 0x10, 0xe9, 0xf5, 0xc8, 0xef, 0x06, 0x13, 0xfe, 0x26, 0xf0, 0x32, 0x11, 0xf0, + 0x05, 0x21, 0xfc, 0xe8, 0xcf, 0xf8, 0x9c, 0x31, 0xf4, 0xc6, 0xf0, 0x13, 0x0e, + 0xe8, 0xe0, 0x2e, 0x32, 0xfe, 0xf6, 0x17, 0xce, 0xe9, 0xcd, 0x06, 0x06, 0xcf, + 0x33, 0x09, 0x1d, 0x07, 0xd9, 0xcb, 0xcc, 0xd9, 0x4d, 0xf5, 0xd1, 0xba, 0xe7, + 0xc2, 0xe1, 0x03, 0x20, 0x0a, 0x0e, 0xc4, 0x00, 0xb1, 0x5a, 0xf0, 0x3e, 0xcf, + 0x26, 0x0a, 0x33, 0x0e, 0xee, 0xfe, 0xbb, 0xe0, 0x21, 0xd9, 0xa1, 0xb4, 0x58, + 0xc8, 0xd4, 0xff, 0xed, 0xaf, 0x1a, 0x0f, 0xca, 0xd2, 0xfd, 0x09, 0xc4, 0x1b, + 0x97, 0xdf, 0xf3, 0x32, 0xe3, 0xc2, 0xf1, 0x1d, 0xf1, 0xc3, 0xf4, 0x9d, 0x00, + 0xeb, 0x0b, 0x0f, 0x03, 0x17, 0xc4, 0x09, 0xe5, 0x14, 0xfb, 0x1a, 0xc8, 0xfe, + 0x11, 0xb6, 0x21, 0xeb, 0x19, 0xb6, 0x0c, 0xfd, 0xca, 0xc8, 0xde, 0x00, 0xa4, + 0xc4, 0xe6, 0xeb, 0x03, 0x0b, 0x10, 0xe5, 0xf6, 0xc6, 0xd0, 0xb9, 0xd2, 0xd0, + 0x23, 0xb3, 0xa0, 0xdf, 0x32, 0xd7, 0x17, 0x95, 0xe2, 0x01, 0x06, 0xa7, 0xec, + 0xa0, 0x33, 0x0f, 0xca, 0xfc, 0xc1, 0xd9, 0xa2, 0x14, 0xf4, 0xc9, 0xff, 0x21, + 0x03, 0x84, 0xf7, 0xfd, 0x2d, 0xc4, 0x08, 0xce, 0xa9, 0xf7, 0x35, 0xcc, 0x24, + 0x44, 0xe4, 0xbf, 0xbb, 0xe6, 0x22, 0x0a, 0xf3, 0xe2, 0xdb, 0x1d, 0xea, 0xd9, + 0xac, 0xff, 0x25, 0xfb, 0x3c, 0x05, 0xe8, 0xb0, 0xf0, 0x01, 0x05, 0x01, 0x31, + 0x1f, 0x34, 0xab, 0xde, 0x8d, 0x18, 0xe8, 0xb9, 0xe2, 0x01, 0x24, 0x06, 0xde, + 0xef, 0xf4, 0xa2, 0xc0, 0xec, 0x2d, 0xf4, 0xa5, 0xda, 0x0a, 0x37, 0x0f, 0x18, + 0x18, 0xbc, 0xe5, 0xed, 0x0b, 0xf5, 0xed, 0xf3, 0x28, 0x11, 0x3e, 0x2f, 0x99, + 0xd0, 0x00, 0xb7, 0x18, 0xb9, 0x3b, 0x31, 0x16, 0xf2, 0xb3, 0x5f, 0xf9, 0x06, + 0x18, 0xd3, 0xfb, 0x81, 0xae, 0xcf, 0xe0, 0xe5, 0xe4, 0xee, 0x09, 0x24, 0xac, + 0xf9, 0xcf, 0xa3, 0x53, 0xe2, 0x1d, 0x4e, 0xb9, 0xc1, 0xcb, 0x41, 0xdf, 0x09, + 0x22, 0xf1, 0xe7, 0xe6, 0x20, 0xdb, 0x49, 0xbf, 0x00, 0xee, 0xd5, 0xd2, 0xdf, + 0x2a, 0xe9, 0x3b, 0xd1, 0xdf, 0xf8, 0xdb, 0x05, 0x31, 0xef, 0xd4, 0x0d, 0x03, + 0x2f, 0x1f, 0xd4, 0xa2, 0xfc, 0xf2, 0x2b, 0x0d, 0x22, 0x1b, 0x07, 0xf0, 0x3f, + 0xf5, 0x13, 0x07, 0x01, 0xd4, 0x41, 0xd0, 0xc4, 0xfa, 0x1d, 0x26, 0xe8, 0xa7, + 0x0c, 0x0e, 0xc6, 0x0b, 0x3a, 0x55, 0x13, 0x2f, 0x10, 0x60, 0xf7, 0x11, 0xcf, + 0x12, 0xf2, 0x0d, 0x2c, 0xf9, 0xd8, 0x15, 0x21, 0xf5, 0x00, 0x0e, 0xd1, 0xcc, + 0xfb, 0xaa, 0xe6, 0xd3, 0x33, 0x5b, 0x24, 0xfc, 0xc2, 0xcc, 0x31, 0xda, 0x40, + 0x57, 0xf2, 0xfb, 0xf6, 0xdd, 0x27, 0x32, 0xc9, 0x44, 0xdc, 0xd4, 0xe3, 0xed, + 0xc3, 0x32, 0xd2, 0xd2, 0x42, 0x10, 0x27, 0x0a, 0xd7, 0x10, 0x37, 0xe4, 0x3b, + 0x44, 0xd1, 0xd6, 0xe3, 0xdd, 0xf8, 0xcf, 0x0f, 0x02, 0xed, 0xca, 0xb0, 0xf4, + 0xd8, 0xd4, 0xf8, 0x11, 0x0c, 0xfc, 0x19, 0xd2, 0xe7, 0xdc, 0xed, 0x14, 0xfc, + 0xda, 0xb0, 0xc6, 0x03, 0xce, 0xb3, 0x26, 0x0e, 0x21, 0xfa, 0xe4, 0xeb, 0x07, + 0xb6, 0x2d, 0xa3, 0xcc, 0x33, 0x14, 0xe1, 0x12, 0xb9, 0xfb, 0xe9, 0x27, 0xbb, + 0x3d, 0x06, 0xbe, 0xe3, 0x03, 0xf8, 0xe1, 0xf5, 0x2d, 0x07, 0x56, 0x1b, 0x05, + 0x1d, 0xc8, 0x01, 0xfc, 0xcf, 0xf6, 0xb4, 0x24, 0xea, 0x0d, 0xd6, 0xfe, 0xf0, + 0xf0, 0xef, 0xd2, 0xe4, 0xe2, 0x1c, 0x06, 0xfd, 0xd1, 0x24, 0xf5, 0x81, 0x09, + 0xee, 0xd9, 0x33, 0x03, 0xeb, 0x13, 0xe7, 0x22, 0xe9, 0x21, 0xbf, 0xee, 0x1c, + 0xe3, 0xd8, 0x0d, 0xe0, 0xcb, 0xac, 0xbf, 0xe2, 0xfc, 0xba, 0x2f, 0x35, 0x17, + 0xf2, 0xce, 0x11, 0xd8, 0xed, 0xf6, 0xd6, 0x0e, 0xfb, 0xe8, 0xe8, 0xf6, 0xb8, + 0xe4, 0xfd, 0xf0, 0xe2, 0xf5, 0xc7, 0x14, 0xe3, 0x03, 0xc0, 0xe4, 0x11, 0xef, + 0xf2, 0xe1, 0xf6, 0xe6, 0xef, 0xed, 0x22, 0x18, 0xe0, 0xf5, 0x34, 0x1b, 0x1b, + 0xb7, 0x0c, 0xfe, 0x2d, 0x0e, 0xad, 0xc8, 0xd6, 0xc9, 0x0c, 0x06, 0xe6, 0xf3, + 0x14, 0xc6, 0xf9, 0xc0, 0x1b, 0xd3, 0x23, 0x22, 0xe9, 0x15, 0xf1, 0xff, 0xee, + 0x18, 0x14, 0xcb, 0xe6, 0xd6, 0xea, 0x08, 0xf0, 0x39, 0xe7, 0x06, 0x2e, 0x13, + 0x0f, 0x0c, 0xd4, 0xc9, 0xe5, 0xdf, 0x0f, 0x0e, 0xf4, 0x0c, 0xf5, 0xff, 0x1e, + 0x27, 0xf0, 0x0a, 0xa0, 0xfe, 0xd7, 0x29, 0xd4, 0xea, 0x18, 0xfb, 0x00, 0xb8, + 0xb0, 0xf6, 0x93, 0x0c, 0xde, 0x25, 0x08, 0x0d, 0xe9, 0xdd, 0x30, 0xc3, 0xff, + 0x1c, 0xae, 0xdc, 0xee, 0x1c, 0x03, 0x15, 0xea, 0x1d, 0xf1, 0x15, 0x1e, 0xf5, + 0x9c, 0x12, 0xec, 0x12, 0xd9, 0xea, 0x13, 0xfe, 0xea, 0x20, 0xf9, 0x0b, 0x6e, + 0x08, 0xe7, 0x11, 0xc1, 0x0d, 0xdd, 0x1a, 0x1a, 0xd7, 0x2a, 0xfe, 0xe0, 0x2e, + 0xdb, 0xdf, 0xea, 0xfc, 0xe6, 0xb0, 0xdf, 0xbb, 0x07, 0xeb, 0xac, 0x09, 0xf1, + 0x3c, 0x07, 0xe2, 0xcd, 0x0c, 0xed, 0x02, 0xee, 0x01, 0x93, 0x44, 0xda, 0x06, + 0xe3, 0x12, 0x05, 0xf1, 0x49, 0x1a, 0xe0, 0xfd, 0x02, 0xd8, 0xed, 0xfe, 0x36, + 0xda, 0xd0, 0x15, 0x24, 0x01, 0x0b, 0x07, 0x44, 0x23, 0x31, 0xef, 0x46, 0x24, + 0x9e, 0xe4, 0xd1, 0xf9, 0xb6, 0x34, 0x3f, 0xf3, 0xe7, 0xe9, 0x9d, 0xf3, 0xd7, + 0xcf, 0xf0, 0x36, 0xe4, 0x1c, 0x0b, 0xc9, 0xe4, 0x04, 0x28, 0xf3, 0x22, 0xf7, + 0xe3, 0xe1, 0x15, 0xef, 0xab, 0x0d, 0xbd, 0x99, 0xb1, 0xdc, 0xc6, 0xd1, 0x16, + 0xf8, 0x41, 0x13, 0x2a, 0x2e, 0xce, 0xe0, 0x32, 0x34, 0x04, 0xdf, 0xff, 0x1f, + 0xba, 0xe6, 0xfc, 0xc5, 0x22, 0x08, 0xe8, 0xff, 0xf4, 0xcf, 0x04, 0x16, 0xe8, + 0x32, 0xe5, 0x34, 0xe7, 0xcc, 0xd4, 0xdf, 0x1c, 0xf4, 0xf5, 0xf4, 0x0f, 0x36, + 0xb1, 0xd5, 0xd5, 0xcd, 0xfa, 0xec, 0x12, 0xef, 0xa2, 0xfc, 0xdd, 0xd6, 0xf3, + 0x06, 0xd0, 0xaf, 0xd2, 0xfc, 0xf4, 0x21, 0x08, 0xd3, 0x3c, 0xbb, 0xfe, 0x3c, + 0x3b, 0xf6, 0xfc, 0xc7, 0x0a, 0xe2, 0xbf, 0xcb, 0x03, 0xf9, 0x29, 0x9f, 0xf6, + 0xfc, 0x3e, 0x00, 0x10, 0x44, 0x29, 0x2f, 0xc8, 0xf5, 0xc2, 0x2f, 0xe5, 0x0c, + 0x20, 0xff, 0x14, 0xe4, 0xff, 0xc3, 0x07, 0xf1, 0xda, 0x2b, 0x02, 0xb9, 0xe9, + 0xfe, 0xd8, 0x01, 0x96, 0x19, 0x02, 0x06, 0xc9, 0xd4, 0xe8, 0xfc, 0x17, 0xb7, + 0xd7, 0x22, 0x18, 0x0a, 0x1b, 0x47, 0xff, 0x23, 0x0a, 0x2c, 0x14, 0x0f, 0x32, + 0xea, 0x0c, 0xa1, 0x1d, 0xf5, 0xff, 0xf3, 0x11, 0x2d, 0xf5, 0x2f, 0x29, 0xcf, + 0x11, 0x20, 0x81, 0xd2, 0x81, 0x13, 0xad, 0xd2, 0xf8, 0x60, 0x1f, 0x12, 0xbc, + 0xe3, 0xad, 0x2c, 0x22, 0x9e, 0xfd, 0xc5, 0x12, 0xc0, 0xd5, 0x03, 0xea, 0xc8, + 0xc5, 0xe7, 0xd6, 0xdf, 0x33, 0x06, 0x3f, 0x28, 0x21, 0xfb, 0xce, 0x2f, 0xcf, + 0xc3, 0xc8, 0xe7, 0xd1, 0xef, 0xc6, 0xff, 0xdb, 0x38, 0xeb, 0x02, 0x1c, 0x01, + 0x12, 0x1a, 0x0e, 0x25, 0xe8, 0xf0, 0xfb, 0x97, 0xf6, 0xb5, 0xc0, 0xf4, 0xff, + 0xfd, 0xe2, 0xf3, 0xd2, 0xbe, 0xfe, 0x49, 0xe8, 0x2c, 0xf3, 0xe4, 0x16, 0xd7, + 0x02, 0x0f, 0x46, 0x1f, 0xf4, 0x01, 0xc4, 0x0d, 0xd5, 0xed, 0xec, 0xe3, 0xc7, + 0xec, 0xb8, 0xe9, 0x70, 0xd5, 0x10, 0x1c, 0x15, 0xcf, 0x21, 0xb1, 0x45, 0xf6, + 0xe9, 0xd2, 0xf8, 0xa8, 0xfd, 0xec, 0x16, 0x81, 0xd6, 0xe4, 0xfd, 0xf2, 0x1b, + 0x01, 0x0d, 0xf6, 0xb9, 0x12, 0x00, 0x33, 0x29, 0xac, 0xd6, 0xcd, 0x11, 0xfb, + 0xfc, 0xe7, 0xd8, 0xf1, 0x40, 0x29, 0x38, 0xee, 0x12, 0x34, 0xe3, 0xd7, 0x28, + 0xf0, 0xf1, 0x06, 0x23, 0xd4, 0xe0, 0xbe, 0x13, 0x10, 0xf4, 0x29, 0xd8, 0xe9, + 0xe3, 0xe6, 0xf6, 0xe2, 0x17, 0x29, 0x06, 0xc4, 0x1a, 0x45, 0xd4, 0x15, 0x17, + 0x63, 0x3d, 0xff, 0xcd, 0x16, 0x17, 0x2b, 0x14, 0x39, 0x09, 0xd5, 0xf4, 0xfb, + 0xff, 0xeb, 0xed, 0xd1, 0xd1, 0x07, 0xf9, 0xdc, 0xac, 0xef, 0x00, 0xd4, 0xc9, + 0x11, 0x22, 0xf0, 0xe3, 0x00, 0xe1, 0x19, 0xd7, 0xf3, 0x67, 0xa5, 0xc7, 0xd4, + 0x0a, 0x10, 0x06, 0xe4, 0x87, 0xe5, 0xe6, 0x1b, 0xda, 0xe3, 0xe5, 0xe1, 0xe7, + 0xcf, 0xf9, 0x03, 0xf3, 0x1a, 0xc5, 0xfc, 0x23, 0x1f, 0x05, 0x15, 0xca, 0xd3, + 0xcb, 0x62, 0xb0, 0x5f, 0x17, 0xd5, 0x1f, 0xc6, 0xfe, 0xcc, 0x31, 0xd2, 0x0b, + 0x20, 0x01, 0xe2, 0xf7, 0x25, 0xc9, 0xad, 0xfa, 0xb7, 0xd7, 0x5d, 0xfe, 0xc1, + 0x04, 0xe6, 0xea, 0xda, 0xad, 0x1b, 0xf4, 0xe7, 0xdc, 0xfb, 0x1a, 0xf3, 0x2e, + 0x1e, 0x23, 0x1c, 0xea, 0xeb, 0xe6, 0xce, 0xef, 0xf1, 0xfa, 0xc9, 0x21, 0x27, + 0xf0, 0xfe, 0x08, 0xe3, 0xc7, 0xfd, 0x20, 0x2c, 0x1b, 0x07, 0xc3, 0xe0, 0xce, + 0xe6, 0x04, 0xd4, 0xef, 0xf4, 0xb1, 0x46, 0xf7, 0x06, 0xd3, 0x34, 0x0b, 0x49, + 0xcd, 0xea, 0xea, 0x1e, 0xd5, 0x1b, 0xc9, 0x02, 0xe7, 0x01, 0xed, 0x2b, 0xdd, + 0x06, 0xb6, 0xe2, 0x0a, 0x2f, 0x0c, 0x25, 0x20, 0xda, 0x24, 0xf2, 0xfc, 0x01, + 0x17, 0xf5, 0xf4, 0x3c, 0xfd, 0x18, 0xd6, 0xe2, 0x34, 0xf4, 0xdf, 0xf0, 0x31, + 0xea, 0xf7, 0x20, 0xf4, 0x81, 0x0d, 0xe9, 0x12, 0xf5, 0xb4, 0xd8, 0xaf, 0xbc, + 0xd2, 0x12, 0x1e, 0xf0, 0xa6, 0xd0, 0xea, 0x01, 0x1b, 0xf1, 0x3a, 0xd7, 0xf8, + 0x3e, 0x93, 0xee, 0xbd, 0x1e, 0xcb, 0x14, 0xf4, 0x03, 0xeb, 0x00, 0xb8, 0xee, + 0x04, 0xe5, 0x2d, 0xb8, 0x0c, 0xaf, 0x26, 0xdc, 0x31, 0xb6, 0xf4, 0x1f, 0x31, + 0xa7, 0xeb, 0x22, 0xf6, 0xfc, 0xfc, 0xc0, 0x24, 0xec, 0xf6, 0xe6, 0x1e, 0xb4, + 0xef, 0x18, 0xe7, 0xf1, 0xfb, 0xcf, 0xdf, 0xcd, 0x0b, 0xee, 0x26, 0x10, 0xd1, + 0x11, 0xf3, 0x0f, 0x1c, 0x42, 0xed, 0x34, 0xf8, 0xf7, 0xff, 0xdc, 0xf4, 0x2e, + 0x23, 0x18, 0xf4, 0xc1, 0x18, 0x19, 0xfc, 0xbb, 0xad, 0x10, 0x02, 0xfd, 0xe8, + 0x09, 0xf2, 0x2b, 0x07, 0x2d, 0xd8, 0x23, 0x2e, 0x31, 0x0a, 0x1a, 0x1f, 0x10, + 0x20, 0x10, 0xa5, 0xf8, 0xdd, 0x32, 0xf0, 0xda, 0xb7, 0x20, 0x13, 0x0e, 0xfc, + 0xfb, 0xc6, 0x00, 0x0d, 0xc9, 0xbf, 0x95, 0xe5, 0x03, 0xd4, 0xf3, 0xf2, 0xf2, + 0x3c, 0xf5, 0x99, 0xbc, 0x0b, 0xf1, 0x1a, 0xd2, 0x1d, 0xba, 0xbb, 0xdf, 0xf6, + 0xbd, 0x2e, 0x29, 0x20, 0x01, 0x0b, 0xeb, 0xa8, 0xed, 0x40, 0xe6, 0x23, 0xc6, + 0x0c, 0x3a, 0xf8, 0xff, 0xf4, 0xed, 0x05, 0xea, 0x0e, 0xfb, 0xbf, 0xeb, 0xd7, + 0xf0, 0x09, 0xea, 0x26, 0x11, 0xd9, 0xfc, 0xc0, 0x14, 0xfc, 0xff, 0xf9, 0xd8, + 0x03, 0xb8, 0xf1, 0xf4, 0xf2, 0xfc, 0xd3, 0xd0, 0xf7, 0xed, 0xf1, 0x28, 0xfc, + 0x22, 0x07, 0x36, 0xef, 0x07, 0x04, 0x0b, 0xec, 0x01, 0xee, 0x25, 0xe5, 0xf0, + 0x1f, 0x01, 0xea, 0x10, 0x1d, 0x0e, 0xde, 0xed, 0x24, 0x11, 0x06, 0xd7, 0xdd, + 0x01, 0xc2, 0x48, 0x28, 0x4f, 0xe3, 0x3c, 0xd7, 0xe4, 0xe1, 0xcd, 0xf9, 0xf4, + 0xe9, 0xc2, 0xf5, 0x07, 0xef, 0x05, 0x1d, 0x0e, 0xdf, 0x04, 0xd9, 0xf0, 0x17, + 0x01, 0xeb, 0xe8, 0xd0, 0x2f, 0x2c, 0x52, 0xf9, 0xc3, 0xfe, 0xf7, 0xf5, 0x3a, + 0xb5, 0xed, 0xd1, 0x0a, 0xec, 0xfa, 0xd4, 0xfd, 0x35, 0x14, 0xf3, 0xba, 0xe5, + 0xff, 0x29, 0xe8, 0x45, 0xf7, 0x09, 0xe5, 0xcf, 0xd9, 0xd7, 0x01, 0xf2, 0xf6, + 0xf6, 0x1d, 0xd2, 0xfe, 0xeb, 0xdd, 0xdb, 0x1b, 0x2b, 0xe4, 0xd9, 0x43, 0xed, + 0xd6, 0x0f, 0xc2, 0x1d, 0x21, 0xc1, 0xd5, 0x0d, 0x28, 0x27, 0xee, 0xce, 0xbb, + 0xe4, 0x36, 0xe8, 0xd1, 0xe3, 0xf4, 0x7f, 0xd4, 0xf5, 0x0a, 0xf9, 0xc0, 0xef, + 0xe3, 0xff, 0xe5, 0x11, 0xf3, 0x3f, 0x2b, 0x03, 0xe3, 0xcd, 0x2a, 0xe9, 0xfb, + 0xfe, 0xfb, 0xeb, 0x34, 0xdf, 0x2f, 0xe7, 0xd3, 0xe7, 0xe9, 0x16, 0x1f, 0xd6, + 0xc2, 0xeb, 0x0b, 0x1f, 0x02, 0xf8, 0xea, 0xfa, 0xd9, 0xf6, 0xf4, 0xf3, 0xaa, + 0x10, 0xc6, 0xd2, 0x25, 0xf4, 0x02, 0x31, 0xf5, 0x04, 0xcd, 0xd9, 0xf2, 0xed, + 0xf5, 0x19, 0x30, 0x13, 0x11, 0x14, 0xed, 0x1c, 0x1d, 0xf7, 0xbc, 0xcc, 0x24, + 0x3b, 0x0d, 0xd4, 0xf6, 0xf5, 0xe4, 0xe0, 0xf5, 0x0c, 0xe0, 0xcf, 0xf4, 0x0d, + 0xb7, 0xe2, 0x00, 0xfd, 0x10, 0x13, 0x43, 0x22, 0x2d, 0x36, 0x0f, 0x06, 0x08, + 0xca, 0xd9, 0xf0, 0x2e, 0x04, 0xbd, 0xe5, 0xbd, 0x0e, 0xde, 0x02, 0xee, 0xdc, + 0xc6, 0x0e, 0xe5, 0xcd, 0xff, 0xf6, 0x13, 0x0f, 0xf8, 0xf0, 0xf5, 0xf0, 0xea, + 0x27, 0xa5, 0xe1, 0xf9, 0x0c, 0xd7, 0x07, 0xab, 0xe0, 0x36, 0x12, 0xdb, 0x32, + 0xf6, 0x16, 0xf6, 0x10, 0xfd, 0x12, 0xd1, 0xfb, 0xf4, 0xf9, 0xdb, 0xe4, 0xcf, + 0x02, 0x09, 0x3b, 0xe7, 0x15, 0xfe, 0x19, 0x7f, 0x29, 0xfa, 0xfd, 0xcd, 0x13, + 0xea, 0x0b, 0xdf, 0x17, 0xfa, 0x18, 0x03, 0xeb, 0xed, 0x01, 0xc6, 0x15, 0xd0, + 0xb5, 0x16, 0xbe, 0x1c, 0x1a, 0x0f, 0x0b, 0x07, 0xe8, 0x19, 0x07, 0x12, 0x3d, + 0xf0, 0xf1, 0xf2, 0xb5, 0xc3, 0xe3, 0xfa, 0xff, 0xd8, 0xd3, 0xb4, 0x00, 0xc5, + 0xd3, 0xea, 0xc4, 0xd5, 0xfd, 0xe3, 0x44, 0x0d, 0x1e, 0xee, 0xf7, 0xbc, 0xdd, + 0xe5, 0xde, 0xda, 0x12, 0xd3, 0xc9, 0x05, 0xc3, 0xed, 0xd5, 0xf5, 0xbf, 0xc8, + 0x01, 0x0a, 0x00, 0x25, 0x28, 0x03, 0xc6, 0x00, 0xe4, 0xd3, 0xf2, 0xfd, 0xf3, + 0x0c, 0xfb, 0x0f, 0x17, 0xb0, 0xdc, 0x02, 0xb7, 0xef, 0xd3, 0xf7, 0xce, 0xf6, + 0x27, 0x23, 0x0d, 0x11, 0xcc, 0xfb, 0xf9, 0xf2, 0x22, 0xd8, 0xc4, 0x33, 0xf0, + 0x14, 0x42, 0x05, 0xe4, 0xed, 0xf7, 0x1e, 0xbe, 0xc2, 0xea, 0x11, 0xeb, 0xdf, + 0x0c, 0xf9, 0xc6, 0x07, 0x13, 0xb1, 0xd6, 0xf9, 0xb8, 0xd1, 0xf5, 0xd2, 0xcf, + 0x02, 0xba, 0x10, 0x02, 0xe4, 0x16, 0xeb, 0xd0, 0x3f, 0xda, 0xec, 0xe1, 0x1a, + 0x39, 0x1a, 0x06, 0x2e, 0x17, 0xdb, 0x09, 0xf8, 0xe9, 0xf7, 0x18, 0x12, 0xb1, + 0x0a, 0xf2, 0xef, 0xfd, 0xe6, 0x24, 0xfd, 0x1b, 0xe1, 0x07, 0xb9, 0xf8, 0xf2, + 0xcb, 0x49, 0xec, 0xe2, 0x04, 0x1d, 0xd1, 0xd5, 0xe8, 0x09, 0xec, 0xe0, 0xb8, + 0xc8, 0xfc, 0xf4, 0xf5, 0x08, 0xe9, 0xfb, 0xf5, 0x13, 0xad, 0x14, 0xdb, 0x01, + 0x09, 0xbe, 0x10, 0xe8, 0x19, 0xfc, 0xec, 0x1e, 0xbe, 0xb1, 0x2d, 0xbb, 0x01, + 0xf8, 0x0a, 0x4c, 0x1e, 0x17, 0xec, 0xf0, 0xc8, 0x1f, 0x18, 0x9b, 0xe9, 0xf1, + 0x0c, 0xf2, 0xca, 0xa2, 0xd0, 0xef, 0xee, 0xcb, 0xee, 0x09, 0xff, 0xce, 0xf0, + 0xff, 0x1e, 0xd0, 0x0b, 0xd2, 0xe4, 0xa4, 0xd8, 0xfc, 0xd8, 0xe3, 0x36, 0xfc, + 0x12, 0x2d, 0x22, 0x74, 0x14, 0xed, 0xdb, 0xbc, 0x08, 0xd3, 0x2a, 0xd0, 0x96, + 0x17, 0xf2, 0x26, 0xfd, 0x05, 0xd3, 0xd7, 0x56, 0xbc, 0xdc, 0x14, 0xe4, 0xf7, + 0x6c, 0x05, 0x21, 0x30, 0x25, 0x11, 0x00, 0xb5, 0x50, 0xcb, 0x05, 0xea, 0xf1, + 0x27, 0x32, 0xf7, 0x22, 0xc5, 0xd5, 0xcd, 0xf0, 0xed, 0x37, 0xc3, 0x1b, 0xe7, + 0x48, 0xee, 0xc9, 0xf3, 0xf4, 0xdb, 0xc7, 0xbc, 0xfe, 0xdd, 0xe9, 0x87, 0x01, + 0xf6, 0x1d, 0xf0, 0xba, 0xe4, 0xf6, 0xcd, 0x21, 0xf6, 0xbf, 0x1f, 0xf4, 0x0b, + 0xe4, 0xc1, 0xe7, 0xdd, 0x45, 0x03, 0x06, 0x09, 0x04, 0x1e, 0x1a, 0x0a, 0x19, + 0xcc, 0x93, 0x06, 0xc6, 0x1c, 0xbe, 0xef, 0xa5, 0x19, 0x2e, 0x41, 0x3a, 0xf2, + 0xcb, 0xf3, 0xc5, 0x17, 0x36, 0x4d, 0xbf, 0xdc, 0x02, 0x04, 0xfb, 0xe5, 0x36, + 0xf9, 0xdd, 0x0a, 0x9b, 0xa5, 0xb4, 0x57, 0xce, 0xea, 0xfe, 0xd4, 0x4c, 0xd3, + 0xce, 0x0d, 0xdb, 0xf7, 0xf0, 0x97, 0x3a, 0xbc, 0xe0, 0xab, 0xe8, 0x1d, 0xe1, + 0xfa, 0xea, 0xec, 0xe0, 0x1d, 0xa9, 0xe8, 0xcd, 0xc8, 0x11, 0x01, 0x0d, 0x28, + 0x0f, 0xbc, 0x20, 0xec, 0x13, 0x01, 0xfd, 0x44, 0xd3, 0x24, 0xe6, 0x26, 0xb3, + 0x04, 0x23, 0x11, 0x0b, 0xca, 0x04, 0xc4, 0x08, 0x02, 0xe7, 0x7f, 0x25, 0x26, + 0xf1, 0xc7, 0xe2, 0xf1, 0x0c, 0xe6, 0xac, 0x38, 0xbe, 0xd0, 0xda, 0xe7, 0xbd, + 0x13, 0xc4, 0x03, 0x14, 0x12, 0x9c, 0xc5, 0xdf, 0xea, 0xfe, 0xdc, 0xcc, 0xc2, + 0x96, 0x2a, 0xe3, 0x28, 0xbe, 0xba, 0x38, 0xc1, 0x95, 0x2e, 0x1f, 0xda, 0xaf, + 0x08, 0x39, 0xa8, 0x51, 0x11, 0xe6, 0x28, 0x16, 0x32, 0xe9, 0x2b, 0xeb, 0xdd, + 0x17, 0x39, 0xd1, 0x3e, 0x07, 0x3c, 0x05, 0xbe, 0xfe, 0x32, 0xb0, 0x0f, 0xda, + 0xee, 0x26, 0xd4, 0x14, 0xeb, 0xf6, 0x06, 0x2f, 0x19, 0xdd, 0xe7, 0xbe, 0x2a, + 0xd3, 0xcb, 0xff, 0x35, 0xf0, 0xb4, 0x23, 0x05, 0xd5, 0xaa, 0x2a, 0x16, 0xfe, + 0xd1, 0xd7, 0x29, 0xa9, 0x17, 0xfa, 0x2b, 0x02, 0xbf, 0x3a, 0xaa, 0xe4, 0x0d, + 0xed, 0xdc, 0xcc, 0xee, 0x2b, 0xd3, 0xcf, 0xd4, 0xfe, 0xcc, 0xe4, 0x10, 0xbb, + 0x30, 0xc2, 0xe9, 0xd3, 0x2e, 0xaf, 0x10, 0xf5, 0xef, 0x30, 0xf3, 0x01, 0xfb, + 0xa9, 0xe8, 0x05, 0x50, 0x10, 0xe2, 0xe2, 0x30, 0x19, 0xed, 0x67, 0xea, 0x1f, + 0x3b, 0x5b, 0x10, 0xf8, 0x04, 0x57, 0x0e, 0x01, 0x81, 0xd6, 0x2e, 0xe4, 0xe8, + 0x9a, 0xfc, 0xa1, 0xe1, 0x3f, 0xc7, 0xfe, 0x2d, 0x50, 0x40, 0x2a, 0x54, 0xcf, + 0xd6, 0xac, 0xec, 0x12, 0xfc, 0x23, 0x0b, 0xb0, 0xee, 0xee, 0x07, 0x17, 0xee, + 0xd3, 0xdb, 0xf3, 0x04, 0xbf, 0xef, 0xf9, 0xc2, 0x2b, 0x0b, 0x0f, 0x4e, 0x44, + 0x97, 0x35, 0x26, 0x03, 0xe2, 0x03, 0x33, 0xd1, 0xd7, 0x2f, 0x2b, 0x06, 0x1a, + 0xf5, 0xe7, 0xe7, 0xf0, 0xfe, 0xfb, 0x1b, 0xcf, 0x44, 0xd0, 0x16, 0x9f, 0xb7, + 0xd2, 0xd1, 0xe4, 0xa8, 0xf0, 0xe8, 0xed, 0xd6, 0xb5, 0xb0, 0xb8, 0x96, 0xd8, + 0xc8, 0x02, 0x9d, 0xeb, 0x27, 0x08, 0xf1, 0xeb, 0xe9, 0xbf, 0xbf, 0x2e, 0xe8, + 0xae, 0xc7, 0xd6, 0xbe, 0xd8, 0xd5, 0xf8, 0x27, 0xb1, 0xdf, 0xd3, 0xfb, 0xca, + 0x20, 0xee, 0xf6, 0xa2, 0xe6, 0xf3, 0x4b, 0xd9, 0xb9, 0x23, 0x47, 0x19, 0x50, + 0xc3, 0xd7, 0xbe, 0x28, 0xf1, 0xf7, 0xf9, 0xd9, 0x0c, 0xc2, 0xe2, 0x21, 0xd3, + 0xf2, 0xde, 0x0b, 0xad, 0xbd, 0x17, 0xd8, 0xfa, 0xb8, 0xe5, 0x25, 0xd2, 0xe5, + 0xb1, 0xe7, 0x24, 0xbd, 0x4b, 0xa7, 0x08, 0x25, 0x11, 0xbc, 0xce, 0x0e, 0xb8, + 0xcf, 0xda, 0x05, 0xff, 0xd1, 0x48, 0xd8, 0xca, 0xf2, 0x9c, 0xfe, 0x14, 0x16, + 0xcb, 0x0e, 0x2c, 0xf3, 0xcc, 0x57, 0xb2, 0xf9, 0xf5, 0xd0, 0x1a, 0xc7, 0x1c, + 0x0c, 0x34, 0x05, 0x0a, 0xd9, 0xbe, 0x44, 0x05, 0x23, 0x35, 0xeb, 0x00, 0xa4, + 0x07, 0xb5, 0xd1, 0xda, 0x2b, 0x1c, 0x16, 0x27, 0xec, 0xf9, 0xcf, 0x33, 0xa7, + 0x1b, 0xee, 0xbc, 0x14, 0x25, 0xcb, 0xa0, 0xfe, 0xf0, 0xe4, 0xa3, 0xed, 0xf7, + 0xfd, 0x05, 0x2e, 0xe6, 0xe6, 0xb4, 0x40, 0xb2, 0xc5, 0xc6, 0xde, 0xad, 0xfd, + 0xac, 0xd6, 0xe5, 0xce, 0xbc, 0xee, 0x39, 0x4f, 0x10, 0xda, 0x3c, 0xae, 0xea, + 0x12, 0x21, 0xca, 0x1d, 0x97, 0xfc, 0xc9, 0xe7, 0xe9, 0xf3, 0x7d, 0xec, 0x11, + 0x59, 0x53, 0x06, 0x2b, 0x4c, 0xbc, 0x06, 0xf3, 0x09, 0xd9, 0xd5, 0xbd, 0x0e, + 0xf0, 0x02, 0x21, 0xda, 0x17, 0x13, 0xb9, 0xfa, 0xfe, 0x20, 0x01, 0xf9, 0xf3, + 0x08, 0xbf, 0xaf, 0x16, 0xf6, 0x2d, 0x4e, 0xfb, 0x1b, 0x47, 0xea, 0x13, 0x35, + 0x03, 0x11, 0x03, 0xe5, 0x15, 0xf7, 0xfe, 0xc6, 0xe2, 0x2f, 0xd5, 0x04, 0xcb, + 0x1e, 0x3a, 0x0e, 0x23, 0xe2, 0x48, 0xf6, 0x1f, 0xe0, 0xfd, 0xc6, 0x48, 0xd1, + 0x45, 0xf4, 0x2b, 0x35, 0x41, 0xc9, 0x51, 0xf6, 0xbd, 0xb4, 0xf9, 0xda, 0xae, + 0x20, 0xeb, 0xbe, 0xe0, 0x81, 0x28, 0xaf, 0x0f, 0xd6, 0x16, 0xf6, 0xf9, 0xc8, + 0xf5, 0xfc, 0xe9, 0xb6, 0xe2, 0xdd, 0xfa, 0x15, 0xdc, 0xcc, 0xe2, 0xc1, 0xd5, + 0x2c, 0xde, 0x1d, 0xb2, 0xe6, 0xf7, 0xf7, 0xf2, 0xfe, 0xff, 0xa6, 0xb1, 0x0d, + 0x08, 0xf8, 0xb8, 0x03, 0xcc, 0x0f, 0x10, 0x17, 0x1b, 0xcd, 0xec, 0x46, 0xd9, + 0xe5, 0xed, 0xd6, 0xf2, 0xe2, 0xf4, 0xe4, 0xdf, 0xda, 0xe8, 0xee, 0xb9, 0xe3, + 0xf9, 0x2c, 0xe7, 0x2d, 0xf9, 0xec, 0x14, 0xe2, 0xd5, 0xeb, 0x17, 0x50, 0x11, + 0xee, 0xfb, 0x25, 0xc0, 0xf2, 0xfe, 0x1f, 0xe2, 0xf1, 0xc7, 0xf3, 0x02, 0xeb, + 0xd2, 0xfe, 0x14, 0x2b, 0x56, 0x20, 0x29, 0x29, 0xca, 0xf2, 0xb3, 0x5e, 0xf3, + 0xcb, 0xdc, 0xf5, 0x4f, 0xf2, 0x4b, 0xe3, 0xd1, 0xe5, 0xbe, 0xce, 0xef, 0x0a, + 0x34, 0x5a, 0xd7, 0x00, 0x08, 0xeb, 0xe0, 0x07, 0xf6, 0x30, 0xe8, 0x11, 0xe1, + 0xc7, 0x07, 0xf1, 0xf6, 0xb4, 0x81, 0xe1, 0xeb, 0x1d, 0xde, 0xdd, 0xdc, 0xf5, + 0xfa, 0xaa, 0x09, 0xdf, 0x09, 0x30, 0xc3, 0xdc, 0xe3, 0xee, 0xf2, 0xfe, 0x17, + 0xe7, 0xbf, 0x3b, 0xfb, 0xe3, 0xff, 0xda, 0xf8, 0x15, 0x94, 0x0e, 0xf5, 0x02, + 0xed, 0x02, 0xee, 0xf2, 0xc6, 0xcc, 0xfd, 0xfc, 0x2d, 0xf9, 0x51, 0x46, 0xc6, + 0xcc, 0xce, 0xc7, 0x23, 0xa1, 0x06, 0xb9, 0xfe, 0xee, 0x13, 0x4e, 0x49, 0x01, + 0xea, 0xc5, 0x3c, 0xc4, 0x25, 0xf0, 0x5e, 0xf6, 0x18, 0x12, 0x34, 0xe7, 0xf2, + 0x0b, 0xc9, 0xdc, 0x33, 0xb5, 0xc1, 0xb2, 0x26, 0xdc, 0x15, 0xd6, 0xf9, 0xe3, + 0x42, 0xe7, 0xe6, 0x12, 0xf7, 0xef, 0xcb, 0x39, 0xdb, 0xb5, 0xf7, 0x18, 0xfb, + 0x0a, 0xae, 0xda, 0xfc, 0xdd, 0x04, 0xc3, 0xff, 0x10, 0xdb, 0x02, 0x06, 0x11, + 0x04, 0x1a, 0xfe, 0x13, 0x07, 0x57, 0x07, 0x25, 0xb6, 0xc2, 0xe5, 0xf1, 0x5a, + 0xa1, 0x35, 0x2a, 0xde, 0x2e, 0xd6, 0xe9, 0xc4, 0x03, 0xdf, 0xc2, 0x1a, 0x2f, + 0x23, 0xc8, 0xa8, 0xf6, 0xd6, 0xb6, 0xa1, 0x09, 0x1c, 0xa9, 0xb7, 0xe3, 0xed, + 0xf8, 0x03, 0xb1, 0x40, 0x02, 0xe7, 0xc1, 0x9c, 0xc5, 0xda, 0xf5, 0xed, 0xe4, + 0x04, 0x36, 0xf0, 0xe0, 0xd5, 0x07, 0xf3, 0x08, 0x5c, 0xa4, 0x07, 0x37, 0xc8, + 0xcd, 0x12, 0x1c, 0x3c, 0xf9, 0xed, 0xe5, 0x0d, 0xea, 0x15, 0xdc, 0x15, 0xf6, + 0xf2, 0x37, 0x15, 0x1a, 0x27, 0xd1, 0x2a, 0xfa, 0xe2, 0xba, 0x22, 0xd6, 0x19, + 0xd0, 0xd0, 0x0e, 0x08, 0x0e, 0x02, 0x30, 0x04, 0xee, 0xff, 0x33, 0xc2, 0xdd, + 0xea, 0xca, 0xe9, 0xdf, 0x06, 0xca, 0xe5, 0xfb, 0x39, 0x0e, 0xb8, 0xc2, 0x02, + 0x0c, 0x05, 0xe7, 0x37, 0xd8, 0x1b, 0xe6, 0x07, 0x02, 0xff, 0x03, 0x09, 0xec, + 0xf3, 0x01, 0xdb, 0xde, 0xf4, 0x50, 0xee, 0x21, 0xf4, 0xdc, 0x9f, 0xf1, 0xf7, + 0xf4, 0xc6, 0xd2, 0xf1, 0x30, 0x42, 0xed, 0x25, 0x2f, 0xf5, 0x08, 0x27, 0xc1, + 0xdb, 0x22, 0x23, 0xd6, 0x27, 0xeb, 0x0f, 0xf1, 0x28, 0x06, 0x20, 0x21, 0x55, + 0xf9, 0xed, 0x20, 0xbb, 0xf4, 0x29, 0x16, 0xea, 0xfc, 0xed, 0x0f, 0x0d, 0xce, + 0xfa, 0xf3, 0x38, 0x09, 0xca, 0x56, 0x7f, 0xf4, 0x26, 0x27, 0xef, 0x04, 0xf6, + 0xf5, 0xe3, 0xea, 0x16, 0xf5, 0x00, 0x35, 0x16, 0xc9, 0xff, 0x36, 0xfe, 0xbe, + 0xfc, 0x37, 0xef, 0xd5, 0xf8, 0x0a, 0x20, 0x1a, 0xfa, 0xd6, 0x01, 0x3e, 0x3f, + 0xc8, 0x16, 0x27, 0xdc, 0xc9, 0xdd, 0xb1, 0x38, 0x17, 0x0f, 0xde, 0xf7, 0xc0, + 0xfe, 0x09, 0xcb, 0xf3, 0x13, 0x21, 0x19, 0x46, 0xf5, 0x1b, 0xf4, 0x2b, 0xe7, + 0xb6, 0x0f, 0xec, 0x59, 0xec, 0xfa, 0x12, 0x1d, 0x09, 0xee, 0xee, 0x25, 0xef, + 0x07, 0xf1, 0xfa, 0xcf, 0xfc, 0x32, 0x2a, 0xf6, 0xf7, 0xe4, 0xf6, 0xac, 0xff, + 0x27, 0x03, 0xc8, 0xf2, 0xb3, 0xc7, 0xdf, 0xe5, 0xec, 0xde, 0x2c, 0x03, 0xf8, + 0xda, 0x00, 0xde, 0x23, 0xfb, 0xf8, 0xb7, 0x04, 0xdc, 0xfa, 0xe3, 0xe9, 0x29, + 0x16, 0x1c, 0x05, 0xd2, 0xbe, 0xcb, 0x10, 0xd4, 0x41, 0x2f, 0xdf, 0xc5, 0x2d, + 0xfc, 0x29, 0x1d, 0xa5, 0x21, 0x2b, 0xde, 0x12, 0x10, 0xbd, 0x0d, 0xf9, 0xb9, + 0x0d, 0xf2, 0x2c, 0xf1, 0x50, 0x36, 0x36, 0xe9, 0xb0, 0x48, 0x23, 0xef, 0xfe, + 0x1c, 0xf3, 0xe5, 0x0e, 0x46, 0x0d, 0x12, 0xfd, 0xe1, 0x0d, 0xef, 0x32, 0x1d, + 0xe7, 0x00, 0x23, 0x0c, 0xca, 0x25, 0x24, 0x00, 0xf5, 0xad, 0xcb, 0x0b, 0x09, + 0x1e, 0xd0, 0xfb, 0xd3, 0xdc, 0xee, 0xed, 0x36, 0xe3, 0xdb, 0x02, 0x6f, 0xda, + 0xc7, 0xd0, 0xd2, 0xd8, 0xa1, 0xc1, 0x04, 0x5d, 0xbd, 0x0d, 0x35, 0xf5, 0x09, + 0x59, 0xad, 0xe0, 0x00, 0xe7, 0xa3, 0x13, 0xa0, 0xfc, 0x27, 0xf1, 0x10, 0x06, + 0xd1, 0x22, 0x21, 0x43, 0x0e, 0xd8, 0xbc, 0x1d, 0xad, 0x05, 0xc2, 0xe7, 0x23, + 0xed, 0xfd, 0x0c, 0x0c, 0x08, 0xf9, 0x2f, 0x3b, 0x10, 0xf1, 0xd3, 0x10, 0xfa, + 0xe0, 0xe4, 0xb0, 0xc4, 0xf1, 0xd5, 0xd5, 0x2f, 0x14, 0xca, 0xf3, 0xea, 0xd9, + 0xde, 0xe6, 0x01, 0xec, 0xee, 0x0b, 0x1f, 0x28, 0x81, 0xfe, 0x02, 0xc0, 0xcc, + 0xce, 0xb1, 0xfd, 0x04, 0xdd, 0x18, 0xfa, 0x26, 0xe3, 0xe9, 0xca, 0xdc, 0xc6, + 0xef, 0xf6, 0x12, 0x08, 0xf0, 0x5f, 0xe6, 0xfd, 0xf8, 0x15, 0x2e, 0x0b, 0xcb, + 0x1b, 0x14, 0x43, 0x17, 0x58, 0xee, 0xb7, 0x5d, 0xd6, 0x15, 0x05, 0xa4, 0x10, + 0xe1, 0xd6, 0x12, 0x24, 0x2c, 0x33, 0x29, 0xce, 0xf4, 0x01, 0xb1, 0x48, 0xf2, + 0x29, 0x14, 0xc3, 0x1f, 0xf2, 0xd1, 0xd4, 0x46, 0xd3, 0x16, 0xef, 0xfe, 0xed, + 0xe5, 0x1d, 0x07, 0x2f, 0x29, 0xf0, 0x17, 0x18, 0xd0, 0x18, 0xdd, 0x53, 0xcb, + 0x0b, 0xd4, 0x09, 0x54, 0x08, 0xf4, 0x30, 0xd8, 0x3f, 0x44, 0x2c, 0xf2, 0x08, + 0x2c, 0x15, 0xe7, 0xe0, 0xdd, 0xe8, 0xcc, 0xce, 0xea, 0x2c, 0x06, 0xd3, 0x25, + 0x09, 0x2e, 0xb9, 0xa7, 0xe9, 0xcf, 0x11, 0xc5, 0xe9, 0x17, 0xc0, 0x01, 0xe2, + 0xe8, 0xe4, 0xef, 0xee, 0xd5, 0x55, 0x20, 0xf6, 0x17, 0xad, 0x15, 0xdc, 0x81, + 0xed, 0xcc, 0xe2, 0x20, 0x1c, 0xd0, 0xe6, 0x22, 0x02, 0x95, 0xf4, 0xd7, 0xd6, + 0x38, 0x2f, 0x0f, 0xc5, 0xa9, 0x0b, 0xd6, 0xef, 0x02, 0xde, 0x98, 0xaa, 0x29, + 0x4c, 0x2a, 0x3c, 0xca, 0x5f, 0x39, 0x06, 0x2e, 0xc6, 0xde, 0xf0, 0x0d, 0x9d, + 0xe1, 0x16, 0xe7, 0x1e, 0xdc, 0xd3, 0xf9, 0x09, 0xb4, 0x31, 0x9a, 0x87, 0xfe, + 0xb5, 0xc2, 0xeb, 0x0f, 0xe7, 0xf6, 0x47, 0x23, 0x12, 0xc0, 0xc9, 0x23, 0x17, + 0xec, 0xd6, 0xb1, 0xca, 0xee, 0x2c, 0xed, 0xf2, 0xc9, 0xf4, 0x1b, 0xc7, 0xcb, + 0xd4, 0xff, 0xe8, 0x08, 0xfc, 0xe9, 0x62, 0xe2, 0xe6, 0x0e, 0xf2, 0xbc, 0xe2, + 0xc1, 0xd9, 0x16, 0x12, 0x43, 0xb9, 0xee, 0xc0, 0xef, 0xfc, 0x37, 0xf5, 0xf0, + 0xca, 0xe9, 0x63, 0x18, 0xe9, 0x12, 0xcd, 0x0b, 0xdc, 0xf1, 0xc3, 0x05, 0x25, + 0x31, 0x10, 0x99, 0xcb, 0x24, 0xff, 0x4a, 0x0d, 0x2b, 0x02, 0xf9, 0x3e, 0x03, + 0x0b, 0x62, 0xdb, 0xf5, 0xd8, 0xf1, 0xd1, 0xf8, 0xe2, 0xdb, 0xf4, 0x21, 0xe6, + 0xac, 0x18, 0xdf, 0x21, 0xf4, 0x1b, 0xcd, 0xa9, 0x10, 0x6e, 0xe9, 0xfb, 0x17, + 0xd2, 0xf4, 0x0d, 0xf8, 0xf9, 0x30, 0x0a, 0x96, 0x00, 0xf9, 0xbf, 0xcf, 0xf4, + 0x3f, 0xf5, 0xec, 0x1d, 0x16, 0xa9, 0x0c, 0xe2, 0xb5, 0xf3, 0x1f, 0x3f, 0xf5, + 0x11, 0xf3, 0x17, 0x04, 0x0c, 0xd2, 0x9d, 0xb4, 0xdd, 0xec, 0xc4, 0x37, 0x13, + 0x06, 0x0c, 0xba, 0x2a, 0x15, 0xf7, 0xd4, 0xd0, 0xe6, 0x10, 0x19, 0xfa, 0x6d, + 0x49, 0xd8, 0xde, 0xcd, 0x00, 0xf9, 0xbf, 0xf6, 0xd5, 0x16, 0xb5, 0xbd, 0xde, + 0x21, 0xcb, 0x43, 0xf7, 0x1e, 0xdf, 0x2f, 0x0f, 0x23, 0xa7, 0x55, 0xe7, 0xf5, + 0xe4, 0xe0, 0x0e, 0xba, 0x41, 0xdb, 0xfc, 0xe8, 0x05, 0xcc, 0x0f, 0xb6, 0xf5, + 0xe3, 0xad, 0xeb, 0xf3, 0xba, 0x19, 0xfe, 0xe2, 0xf8, 0xaa, 0xd1, 0xfd, 0x9f, + 0xb3, 0x1f, 0xbb, 0xdf, 0xd2, 0x0b, 0x00, 0x2f, 0xd6, 0x03, 0xf4, 0xf1, 0x14, + 0xf6, 0x47, 0xfa, 0xca, 0xff, 0x08, 0xe2, 0xdc, 0x49, 0x44, 0x37, 0x2d, 0xfd, + 0xdc, 0xf8, 0xe3, 0x00, 0xd3, 0x78, 0xee, 0xf5, 0xe9, 0x07, 0xda, 0xd4, 0x34, + 0xca, 0xdc, 0x2a, 0x04, 0xe2, 0x08, 0x2e, 0x0c, 0xbb, 0x0c, 0xdf, 0x8b, 0xf6, + 0xe1, 0xf8, 0xfa, 0xdb, 0xe2, 0xfa, 0xc4, 0x09, 0x17, 0xf5, 0xed, 0xcd, 0x1b, + 0xda, 0x0b, 0x2c, 0x0c, 0xee, 0xf4, 0x09, 0xc9, 0xc9, 0xd8, 0xe3, 0x34, 0x49, + 0xef, 0x04, 0xc7, 0xfc, 0xf4, 0x01, 0xe0, 0xc6, 0x27, 0xdf, 0xf2, 0xe6, 0xf8, + 0x58, 0xd8, 0xf1, 0xb7, 0x14, 0xbd, 0x07, 0xfd, 0xd1, 0x8d, 0xdc, 0x25, 0x06, + 0xd5, 0xf1, 0xbb, 0xcd, 0x20, 0xb1, 0xd7, 0xec, 0x9d, 0x09, 0xdd, 0x07, 0xf5, + 0xfe, 0x35, 0xea, 0x6b, 0x3f, 0xce, 0xca, 0xf3, 0xd1, 0xe4, 0x19, 0x03, 0x0f, + 0x0e, 0xda, 0xdf, 0xe2, 0x18, 0xd2, 0x2f, 0x49, 0xe1, 0xe3, 0xa7, 0xf4, 0x11, + 0x03, 0xf1, 0xe2, 0x25, 0xf5, 0x03, 0xf3, 0xe2, 0xfe, 0xf9, 0x01, 0xed, 0xe6, + 0x2b, 0x02, 0xc0, 0xe4, 0xe0, 0x21, 0xda, 0xb7, 0xe0, 0x18, 0xe2, 0x01, 0xfe, + 0x0b, 0xe9, 0x3d, 0x8f, 0xaf, 0xf9, 0x0d, 0xdc, 0xf6, 0xff, 0xc5, 0xc7, 0xe7, + 0xe0, 0x15, 0xba, 0xd2, 0x16, 0xe4, 0x02, 0x1e, 0xf5, 0x0c, 0x56, 0xe0, 0x27, + 0x4b, 0xc0, 0x13, 0x05, 0x08, 0x2e, 0x02, 0x06, 0x19, 0xff, 0x21, 0x2b, 0xf6, + 0xfe, 0x38, 0xff, 0x7f, 0xda, 0xc2, 0x43, 0x07, 0xdf, 0xdb, 0xb6, 0x03, 0x0a, + 0xd3, 0x1e, 0xe6, 0xeb, 0xe6, 0xdf, 0xd7, 0x05, 0xda, 0xe2, 0x2e, 0xf9, 0xe6, + 0x24, 0x28, 0xfa, 0xfd, 0x09, 0x0a, 0xfb, 0xe3, 0x18, 0x0f, 0xcf, 0x15, 0x13, + 0xe5, 0xf2, 0x00, 0xef, 0xee, 0xd6, 0x0b, 0xd7, 0xf1, 0xfc, 0xf5, 0x1c, 0xcf, + 0x10, 0xfa, 0x2c, 0xcf, 0x35, 0x0a, 0xe6, 0xf8, 0xe7, 0x0f, 0xd6, 0xd6, 0x39, + 0xe4, 0xfb, 0x04, 0x1c, 0x1f, 0xc3, 0x1f, 0x23, 0x07, 0xee, 0x1e, 0x21, 0x20, + 0xec, 0xf9, 0xfb, 0x0d, 0xf5, 0xef, 0xdf, 0x26, 0x07, 0x00, 0xc8, 0x26, 0x2e, + 0x00, 0x0e, 0xb5, 0xe3, 0x4a, 0xdb, 0xfd, 0xb0, 0x2a, 0x0b, 0xe7, 0x23, 0xee, + 0xf9, 0xe5, 0xfe, 0x0c, 0xd3, 0xc1, 0xf5, 0xe7, 0xf7, 0x00, 0xf1, 0xde, 0x1d, + 0xec, 0x05, 0xd0, 0x0c, 0xde, 0x28, 0x04, 0x26, 0xee, 0xe4, 0xfd, 0xfb, 0x0e, + 0xe4, 0xfd, 0x14, 0x0d, 0x0d, 0x27, 0x29, 0xfa, 0xfd, 0xda, 0x0b, 0xe2, 0x12, + 0x04, 0x28, 0xeb, 0xee, 0xf7, 0xbf, 0xfa, 0xc2, 0x1c, 0xf8, 0xd8, 0xc5, 0xfd, + 0xe8, 0x12, 0xef, 0xfe, 0xe9, 0x0a, 0x11, 0x1b, 0xf2, 0xe2, 0xc4, 0xaa, 0xd5, + 0xce, 0x23, 0xf2, 0xe4, 0x1f, 0xcf, 0x07, 0x06, 0x17, 0x28, 0xd6, 0x24, 0x1b, + 0xc5, 0x07, 0x05, 0xf2, 0x52, 0x41, 0xe6, 0x7f, 0xfb, 0xd9, 0xec, 0xfb, 0x1b, + 0xe5, 0xf3, 0x02, 0xdc, 0x1b, 0x16, 0x16, 0x03, 0xf5, 0x12, 0x0c, 0xee, 0xef, + 0x05, 0x0f, 0xed, 0x21, 0xc2, 0xfb, 0x31, 0x04, 0xe4, 0xfb, 0xe7, 0xbd, 0x37, + 0xff, 0x07, 0x21, 0xd8, 0x0d, 0x39, 0x0a, 0xf3, 0x02, 0xe7, 0x0c, 0x13, 0xd0, + 0x0e, 0x1f, 0x15, 0xff, 0x06, 0xfc, 0x22, 0xfa, 0x1d, 0x08, 0xc5, 0xeb, 0xfa, + 0xe1, 0xd3, 0xfa, 0xf2, 0xf2, 0xd7, 0x2b, 0xf8, 0x13, 0xe6, 0xfe, 0xd2, 0xfc, + 0xe9, 0x11, 0x4e, 0x14, 0xe8, 0x36, 0xed, 0xdb, 0x12, 0x14, 0x23, 0x0f, 0xb5, + 0xdf, 0x3f, 0x0c, 0xee, 0xf3, 0xcb, 0xcb, 0xec, 0x2f, 0xad, 0x18, 0xeb, 0xc3, + 0xfd, 0x64, 0x08, 0x20, 0x2c, 0x27, 0xfb, 0xcf, 0xd3, 0xfe, 0x49, 0xeb, 0xcc, + 0xe9, 0xc6, 0x27, 0xfc, 0xac, 0xe0, 0xe0, 0xb7, 0x4c, 0xd0, 0xdd, 0xfa, 0x43, + 0xee, 0xa0, 0xa1, 0xb5, 0x0c, 0xd5, 0xd7, 0xa6, 0x06, 0xe8, 0xf4, 0xce, 0x1e, + 0xd5, 0xfb, 0xc5, 0x0f, 0xb3, 0xc2, 0x1a, 0x08, 0xb8, 0xff, 0x44, 0x23, 0x0c, + 0x14, 0xe9, 0x2d, 0xe7, 0x97, 0xd7, 0x2b, 0xe7, 0xac, 0xdc, 0xcb, 0x94, 0xee, + 0x0b, 0x1e, 0x00, 0x50, 0x26, 0x17, 0xf1, 0x2c, 0x38, 0xda, 0x0a, 0x6f, 0xd8, + 0xc9, 0x10, 0x26, 0xe3, 0x0d, 0x19, 0x1a, 0xf1, 0x15, 0xe6, 0xf9, 0xdd, 0xee, + 0xab, 0x20, 0xee, 0xfc, 0xde, 0xdd, 0x16, 0x23, 0x1f, 0x9f, 0x25, 0x2e, 0xe6, + 0x21, 0x0d, 0xc9, 0xfa, 0xcf, 0xe3, 0x01, 0xcf, 0x24, 0x71, 0xa5, 0xf5, 0x2e, + 0xdf, 0x35, 0x17, 0x30, 0xe3, 0xeb, 0x1e, 0x29, 0x16, 0xfb, 0x23, 0xe5, 0x20, + 0xf8, 0x1e, 0xf4, 0xb1, 0xe9, 0xbc, 0x08, 0x20, 0x00, 0x17, 0xcf, 0x03, 0x20, + 0xde, 0xbb, 0xd4, 0xf4, 0xc3, 0xe7, 0x2b, 0xe1, 0xb0, 0x38, 0x01, 0xdf, 0x9d, + 0x73, 0x16, 0x17, 0xc2, 0xe8, 0x47, 0x15, 0xfb, 0xc7, 0x07, 0xfb, 0x49, 0xd3, + 0x09, 0xbb, 0xaa, 0x38, 0x29, 0xef, 0xe6, 0xc9, 0xbf, 0x0c, 0x4b, 0xe0, 0x09, + 0x52, 0x15, 0x0a, 0x94, 0x89, 0xa6, 0xd5, 0xe4, 0xf6, 0x18, 0x04, 0xe1, 0x2a, + 0xda, 0xe6, 0xb4, 0xd1, 0x0b, 0x59, 0xf7, 0xb6, 0xc2, 0x91, 0xec, 0xaf, 0xbb, + 0x3b, 0xcb, 0x22, 0xfc, 0xf8, 0x18, 0xc4, 0xbd, 0x12, 0x81, 0xc0, 0xcd, 0xdf, + 0x09, 0xaa, 0x0d, 0x50, 0xe7, 0xe3, 0x10, 0x28, 0x25, 0x9f, 0xd7, 0xbc, 0xac, + 0x02, 0x3b, 0x00, 0xcd, 0x21, 0xee, 0xf3, 0xdc, 0x16, 0x10, 0xbb, 0x25, 0xae, + 0xe1, 0x22, 0xca, 0xfa, 0x95, 0xf1, 0xd6, 0x38, 0xd7, 0x9e, 0xd8, 0xc9, 0xe8, + 0xd9, 0x10, 0xd9, 0xdb, 0xd7, 0xeb, 0xa2, 0x59, 0x39, 0xd7, 0x08, 0xd7, 0xf1, + 0x9e, 0xef, 0x0c, 0xc6, 0xda, 0x17, 0xef, 0xd9, 0xec, 0xc0, 0x03, 0x09, 0x1e, + 0xea, 0xef, 0x63, 0xfb, 0xdd, 0x89, 0xdf, 0xaa, 0xf6, 0xec, 0x0a, 0x2e, 0x31, + 0xee, 0x2e, 0x90, 0xe8, 0x17, 0xd5, 0x52, 0xde, 0x29, 0xac, 0x0b, 0xfa, 0xf1, + 0xff, 0xb3, 0xb0, 0x01, 0xdf, 0x0f, 0x53, 0xa4, 0xea, 0xd0, 0xe0, 0xb0, 0xc7, + 0x22, 0xf4, 0x1b, 0x7f, 0xbd, 0xe5, 0xe4, 0x93, 0x16, 0xca, 0xf8, 0xb6, 0xee, + 0x01, 0x04, 0x07, 0xf7, 0x07, 0xfc, 0xe4, 0xd1, 0x00, 0xf8, 0xc2, 0xca, 0xfa, + 0x33, 0x03, 0xec, 0xd3, 0xd6, 0x03, 0x0c, 0xce, 0x0a, 0x15, 0xb8, 0xf1, 0x05, + 0xe9, 0x32, 0x95, 0xf0, 0x0c, 0xd8, 0x10, 0x00, 0xcd, 0xe0, 0xbe, 0xf9, 0x11, + 0xac, 0xba, 0xfc, 0x75, 0xe7, 0x27, 0xa8, 0x36, 0xbb, 0xf4, 0x35, 0x32, 0xfc, + 0xb4, 0xdc, 0x0b, 0x1c, 0x50, 0x0e, 0xad, 0xd4, 0xc1, 0xc7, 0xde, 0x05, 0xdc, + 0x41, 0x0e, 0xae, 0xfa, 0x09, 0xf0, 0x96, 0xe0, 0xc1, 0xd7, 0xc6, 0x00, 0x9d, + 0x05, 0xff, 0xec, 0x14, 0xce, 0xe4, 0x09, 0x17, 0x02, 0x04, 0xeb, 0x58, 0xee, + 0x0c, 0x15, 0x19, 0xd7, 0xb1, 0xcd, 0xea, 0x89, 0x8a, 0x12, 0xf5, 0x3c, 0x02, + 0x5b, 0xf8, 0xca, 0x06, 0xa6, 0xc5, 0xec, 0x11, 0xcd, 0x30, 0xe0, 0x04, 0x1e, + 0xf9, 0xc4, 0xe1, 0xae, 0xbe, 0x12, 0x1c, 0x03, 0xfc, 0xf0, 0xa2, 0x3a, 0xae, + 0x0c, 0x6e, 0x0a, 0xe1, 0xe5, 0xeb, 0xba, 0x31, 0xbe, 0x42, 0x27, 0xd5, 0x00, + 0xaa, 0xcc, 0x28, 0xcd, 0x05, 0x09, 0xd3, 0xd0, 0xf4, 0x07, 0xbe, 0x14, 0xf3, + 0x10, 0xf2, 0x18, 0x35, 0x1f, 0x42, 0xe0, 0xf1, 0xeb, 0xd2, 0x24, 0xfc, 0x01, + 0xc7, 0x47, 0x9e, 0x04, 0x17, 0x03, 0xf4, 0xab, 0xe6, 0x96, 0x78, 0xbb, 0xbd, + 0x16, 0xb3, 0x03, 0xca, 0xda, 0x07, 0x09, 0xc9, 0x13, 0xf7, 0x00, 0x14, 0xb8, + 0xc7, 0xee, 0x02, 0x1f, 0x1e, 0xc6, 0x88, 0xe2, 0x3c, 0xd9, 0xf9, 0xb5, 0xfe, + 0x9e, 0x04, 0xe4, 0x01, 0xf4, 0x46, 0x55, 0x0d, 0xe3, 0x22, 0x45, 0xf7, 0xb7, + 0xae, 0x0b, 0x49, 0xe7, 0x43, 0x24, 0x49, 0x3a, 0xd8, 0xd7, 0x49, 0x11, 0x06, + 0x15, 0x12, 0xec, 0x02, 0x4e, 0x61, 0x45, 0xf9, 0xe9, 0x1a, 0x0f, 0x0b, 0x98, + 0xf8, 0x4f, 0x22, 0x2d, 0x1b, 0xc7, 0xf4, 0x21, 0xa2, 0xe0, 0x7f, 0xda, 0xdc, + 0xa3, 0x2b, 0x33, 0xf9, 0x10, 0x1d, 0xe4, 0xc4, 0xd6, 0xb1, 0xd7, 0x05, 0xd7, + 0xa4, 0x1e, 0x42, 0xcc, 0xf2, 0xc6, 0xd4, 0xf3, 0xc2, 0x39, 0x91, 0x21, 0xf9, + 0xd4, 0x24, 0xe1, 0x16, 0xc4, 0xf3, 0xd4, 0xbc, 0xfe, 0x15, 0x11, 0x99, 0xee, + 0xd1, 0x0c, 0x17, 0xe0, 0x29, 0xe0, 0x2e, 0x5f, 0x4f, 0x27, 0xe7, 0x06, 0x36, + 0xcd, 0x41, 0xe4, 0x97, 0x18, 0x31, 0xf7, 0x23, 0x0a, 0x05, 0xfd, 0x9e, 0x17, + 0x27, 0x15, 0x03, 0x0d, 0x19, 0x1a, 0xe6, 0xf1, 0x0e, 0x2b, 0xce, 0xda, 0xc7, + 0xc2, 0xf8, 0xdc, 0xc0, 0xaa, 0x35, 0xb9, 0xba, 0xe4, 0xc2, 0x16, 0x1c, 0x38, + 0xc2, 0xc1, 0x09, 0x23, 0xf5, 0x0a, 0x0d, 0xf3, 0x0b, 0x05, 0x49, 0xdf, 0x05, + 0x0b, 0x22, 0x1d, 0x3f, 0xdd, 0x39, 0x61, 0xc8, 0xc5, 0x70, 0x18, 0xdb, 0x26, + 0x24, 0x8f, 0xbb, 0x5e, 0x47, 0x19, 0x0e, 0xbf, 0xe0, 0x1d, 0xc8, 0xdf, 0x1f, + 0xaf, 0x40, 0x3d, 0x42, 0x46, 0xfb, 0xb2, 0xfb, 0xe5, 0x90, 0x26, 0xe0, 0x19, + 0x3b, 0x13, 0x32, 0x15, 0x54, 0x15, 0xe5, 0xa6, 0x9d, 0xd3, 0xab, 0xc2, 0xf8, + 0xb4, 0x25, 0x10, 0x3a, 0xce, 0x23, 0xf4, 0xa1, 0xcf, 0xff, 0x0f, 0xf8, 0x10, + 0xd8, 0x72, 0x0e, 0xe5, 0xde, 0xd6, 0x0a, 0x32, 0xb8, 0x11, 0xec, 0x9f, 0x19, + 0x12, 0x07, 0xc1, 0x2a, 0xf6, 0x33, 0xc8, 0xfc, 0x0f, 0xf6, 0xf8, 0x19, 0x13, + 0x12, 0xfa, 0x01, 0xce, 0x26, 0xdb, 0x11, 0x1e, 0xbe, 0xe5, 0xd6, 0xdb, 0xfb, + 0xf8, 0x2b, 0x2a, 0x32, 0x34, 0xf4, 0xc5, 0x43, 0x18, 0x06, 0xcb, 0xd5, 0x13, + 0xe1, 0x1b, 0xff, 0x2d, 0x17, 0x0c, 0xee, 0xc0, 0xe0, 0x9c, 0xbe, 0x1d, 0x0c, + 0xff, 0x25, 0x52, 0xed, 0xf3, 0x3d, 0xec, 0xd3, 0x35, 0xe2, 0x0f, 0xcb, 0x52, + 0x0f, 0x1b, 0xd5, 0xee, 0x12, 0x41, 0xdf, 0xf7, 0x1d, 0xdc, 0xd9, 0xd5, 0xf8, + 0xfa, 0xfc, 0xe2, 0x26, 0xf8, 0xd1, 0x3b, 0xd1, 0xf0, 0x18, 0xe9, 0x2f, 0x37, + 0x07, 0xd8, 0xe2, 0xd9, 0x99, 0xdc, 0xf1, 0xec, 0xfc, 0xe3, 0x1b, 0xb5, 0x0c, + 0x2c, 0x34, 0xfb, 0x38, 0x26, 0xe6, 0xa7, 0xd8, 0xbd, 0xd9, 0xe8, 0xe6, 0x21, + 0x08, 0xfd, 0x18, 0x44, 0xf1, 0x0a, 0xae, 0xfd, 0xd6, 0x45, 0x0b, 0xcf, 0x12, + 0xf8, 0xdd, 0xf1, 0x28, 0xd5, 0x0c, 0xec, 0x19, 0x3d, 0xe7, 0xec, 0xf2, 0xf6, + 0xb0, 0x53, 0x1a, 0xe4, 0x20, 0x21, 0x35, 0xf0, 0xd6, 0xcb, 0x15, 0xdc, 0xd7, + 0xff, 0xf9, 0xe1, 0x9e, 0xf6, 0xbd, 0x08, 0xfe, 0xdb, 0xed, 0xd9, 0x10, 0x37, + 0xf1, 0xbf, 0xf6, 0x9a, 0xf0, 0xeb, 0x3a, 0xf8, 0x04, 0xc5, 0xe2, 0xb9, 0x05, + 0x2f, 0x29, 0x11, 0x1f, 0x15, 0xe8, 0x19, 0x0f, 0xd2, 0x18, 0xde, 0x7f, 0x03, + 0x0d, 0xf8, 0xdb, 0xe7, 0xe1, 0xe6, 0xd8, 0x08, 0xcc, 0xd9, 0x29, 0xef, 0xb4, + 0x03, 0x48, 0x29, 0x00, 0x05, 0x0c, 0xf0, 0x26, 0xfa, 0xfd, 0xcf, 0x0f, 0x19, + 0xeb, 0xb6, 0xdd, 0xd6, 0x27, 0x53, 0x13, 0xfa, 0x0a, 0xf4, 0xf8, 0x0b, 0x5f, + 0xfb, 0xcc, 0xe7, 0xb3, 0x21, 0xf9, 0x68, 0x08, 0x63, 0xb5, 0x2d, 0xd1, 0xea, + 0x22, 0xdd, 0x1b, 0x03, 0xe3, 0xcf, 0xa6, 0xe9, 0xd7, 0x1e, 0x0a, 0x1e, 0x3f, + 0xb8, 0x08, 0xca, 0xdb, 0x14, 0x06, 0x3b, 0x64, 0x27, 0x21, 0xcd, 0xb9, 0xf1, + 0x1f, 0xc4, 0x08, 0x05, 0xcf, 0xce, 0xbb, 0xf8, 0x8d, 0xb9, 0xec, 0x5b, 0x56, + 0x6f, 0x0b, 0xe0, 0xcd, 0x21, 0xb8, 0xe0, 0x10, 0xf8, 0xc7, 0x39, 0xea, 0x56, + 0xde, 0x36, 0xb3, 0xf7, 0xeb, 0xde, 0xde, 0x1d, 0xf2, 0x39, 0xd1, 0xb7, 0xf6, + 0xaa, 0x50, 0x01, 0xc8, 0x20, 0xcf, 0xd5, 0x98, 0xca, 0x08, 0xa1, 0xf0, 0x1a, + 0xc5, 0x1b, 0xdc, 0xde, 0x10, 0xce, 0x09, 0x05, 0xba, 0xa8, 0xf2, 0xdf, 0xd9, + 0xed, 0xc2, 0x1d, 0x17, 0xf3, 0xff, 0xca, 0x56, 0x5c, 0xf9, 0x14, 0x95, 0xdc, + 0x14, 0x02, 0x5f, 0x01, 0xc3, 0xf4, 0x42, 0xb1, 0x44, 0xc4, 0x9b, 0xb2, 0xfd, + 0xff, 0x01, 0x2c, 0x01, 0xbc, 0xb7, 0xa1, 0xd1, 0xee, 0x16, 0x2b, 0xe6, 0x50, + 0xef, 0xc8, 0x3b, 0xaa, 0xbb, 0x15, 0xfd, 0xde, 0xfc, 0xe0, 0xee, 0x0a, 0xed, + 0xf2, 0x44, 0x06, 0xab, 0x11, 0xee, 0xe8, 0x05, 0xdb, 0xeb, 0x27, 0xf9, 0xa9, + 0xd3, 0x08, 0xf7, 0x60, 0x3b, 0xf8, 0xe2, 0xe4, 0x07, 0xf4, 0xf7, 0x08, 0xf4, + 0x0c, 0x49, 0x1f, 0xb9, 0xef, 0xd0, 0xc4, 0x6f, 0x05, 0xc1, 0xbc, 0x0f, 0xc0, + 0xbe, 0x33, 0x3f, 0x81, 0xbf, 0xcf, 0xe3, 0x34, 0xd1, 0xfb, 0x2f, 0xe9, 0x28, + 0xe0, 0xf9, 0xba, 0x2c, 0x18, 0xe3, 0x23, 0xfc, 0xf2, 0xa8, 0x16, 0x90, 0x29, + 0xcd, 0x66, 0x0d, 0xd8, 0x21, 0xeb, 0xb5, 0xed, 0x1b, 0xad, 0xfa, 0x33, 0x1b, + 0x3b, 0x9c, 0xbd, 0x0e, 0x9f, 0x11, 0x06, 0xd0, 0xd8, 0xa2, 0x0d, 0xb3, 0x92, + 0xc8, 0x08, 0x22, 0xc4, 0x0a, 0xf9, 0x12, 0xe6, 0x25, 0xd3, 0x2b, 0xeb, 0xea, + 0xfa, 0xbe, 0x09, 0xf6, 0x30, 0x0f, 0xf3, 0x05, 0x18, 0x04, 0xee, 0xef, 0xee, + 0xbc, 0xf1, 0xc4, 0xe0, 0x0c, 0xf5, 0xfe, 0xf5, 0xee, 0xed, 0x05, 0xcd, 0x3e, + 0xd5, 0xd3, 0x15, 0xf1, 0xd7, 0x18, 0xb1, 0x0b, 0xe8, 0xff, 0xc4, 0x37, 0x10, + 0xd7, 0xba, 0xf2, 0x0d, 0xbb, 0xe8, 0x03, 0x36, 0x2e, 0x0d, 0xf0, 0xf3, 0x05, + 0xd8, 0xd1, 0xf0, 0x0f, 0xe4, 0x03, 0xc8, 0xf3, 0x06, 0xe8, 0xf3, 0x06, 0xf8, + 0x0a, 0xdf, 0xc8, 0xf9, 0xfb, 0xd3, 0xd6, 0xfa, 0xf0, 0xd4, 0x16, 0xcd, 0xf8, + 0x2d, 0xfd, 0xe0, 0xfa, 0xab, 0x14, 0xe6, 0x1e, 0xd6, 0x12, 0x32, 0xef, 0x04, + 0xf9, 0xd7, 0xec, 0xce, 0xf7, 0xc8, 0xfa, 0x01, 0x1e, 0x0b, 0x0e, 0xfc, 0xd5, + 0xe5, 0xf4, 0xd5, 0x0e, 0x06, 0xf4, 0xeb, 0xe2, 0xb8, 0xe4, 0xee, 0x0c, 0xd4, + 0xfe, 0xd0, 0xff, 0xe8, 0x10, 0x13, 0xc4, 0xad, 0xed, 0xf7, 0xea, 0xfc, 0xf2, + 0xf8, 0xfa, 0xf4, 0xd7, 0xf4, 0xea, 0xed, 0x22, 0x2c, 0xf8, 0xe9, 0xe5, 0x2e, + 0xda, 0x7f, 0x03, 0xf3, 0xef, 0xf3, 0xc2, 0xe4, 0x39, 0xf3, 0x07, 0x11, 0xc4, + 0xe0, 0xdd, 0x11, 0xe3, 0xf7, 0xe7, 0xf0, 0x1d, 0xf7, 0x11, 0xfb, 0x07, 0x1a, + 0x11, 0x05, 0x07, 0xf3, 0xd5, 0xdc, 0x2c, 0xfe, 0xe6, 0x23, 0xcb, 0x15, 0x09, + 0xc0, 0xc2, 0xdb, 0xe7, 0x1c, 0xea, 0xe0, 0x34, 0xfc, 0x11, 0x04, 0xfd, 0xf2, + 0x0e, 0xaa, 0xce, 0x10, 0x19, 0xe6, 0xff, 0xd4, 0xe1, 0xca, 0xdc, 0xcf, 0x2c, + 0xbc, 0x0d, 0xfe, 0xf6, 0xf1, 0x05, 0xfe, 0xed, 0x35, 0xd6, 0x13, 0x48, 0xdd, + 0x27, 0x0b, 0xdc, 0xfd, 0x0a, 0x23, 0x26, 0xfa, 0xfb, 0x13, 0xe9, 0xd2, 0x18, + 0xe4, 0x4f, 0xbb, 0xcc, 0x21, 0xe6, 0xf3, 0x22, 0x01, 0x04, 0x37, 0x04, 0x09, + 0x51, 0xc9, 0xb5, 0xe3, 0x0b, 0x30, 0xf2, 0x13, 0xf4, 0xe8, 0x13, 0x01, 0xc4, + 0xfe, 0xfc, 0x43, 0x52, 0xcf, 0x20, 0xde, 0xfd, 0xc4, 0xc4, 0xf6, 0xb3, 0x3a, + 0xd9, 0xd7, 0xea, 0xf0, 0xef, 0xed, 0x0b, 0x1c, 0xcf, 0x7f, 0x43, 0x30, 0x25, + 0x3e, 0xce, 0x11, 0xf7, 0xda, 0xce, 0xf5, 0x0d, 0x15, 0x10, 0x0e, 0x1f, 0xfe, + 0x45, 0xd3, 0x26, 0xfb, 0x1f, 0xfc, 0x29, 0x31, 0xf3, 0x17, 0xf9, 0xe4, 0xce, + 0x37, 0x15, 0x07, 0xf0, 0xe2, 0x2e, 0x0a, 0x4f, 0xc7, 0x51, 0xcf, 0xe9, 0xc3, + 0xe2, 0xea, 0x12, 0xea, 0x27, 0xb1, 0xe6, 0x30, 0xe6, 0xd8, 0x09, 0xd9, 0xf5, + 0x07, 0x13, 0xf7, 0xf8, 0xfc, 0xc7, 0x19, 0xf8, 0xe6, 0xd2, 0x00, 0xe0, 0x33, + 0x09, 0x05, 0x13, 0xfa, 0x00, 0xfc, 0x06, 0xad, 0xcc, 0xf8, 0x38, 0x05, 0x05, + 0x35, 0xed, 0x1a, 0x1c, 0xea, 0x15, 0xec, 0xec, 0x04, 0xee, 0xca, 0x17, 0xe9, + 0xf6, 0x3f, 0xf6, 0xde, 0xd5, 0x25, 0x1a, 0x0c, 0x1a, 0xea, 0xd7, 0xd7, 0xdd, + 0x23, 0xf8, 0xaf, 0x07, 0xfa, 0xbb, 0x29, 0x35, 0xd5, 0x02, 0xd0, 0x02, 0xff, + 0xd2, 0x14, 0xc5, 0x4d, 0x1e, 0xe7, 0xe0, 0x1d, 0xc0, 0xfd, 0xd3, 0xcd, 0x4d, + 0x23, 0xca, 0x49, 0x07, 0xff, 0x6f, 0x06, 0x39, 0xdf, 0x17, 0x1d, 0xc5, 0x04, + 0xf1, 0xee, 0xe4, 0xee, 0xfd, 0x05, 0xe9, 0x19, 0x26, 0x17, 0x13, 0xc5, 0xf9, + 0x2c, 0x06, 0x26, 0xea, 0x0c, 0xea, 0x13, 0xb3, 0xb2, 0xdb, 0x0e, 0x09, 0x19, + 0xf7, 0xff, 0x0a, 0xe9, 0x30, 0xdf, 0x20, 0xca, 0xd9, 0xf8, 0x02, 0x0d, 0xd1, + 0xec, 0xf0, 0x11, 0xf3, 0xf8, 0xd6, 0xe6, 0xf6, 0xd4, 0x08, 0x0a, 0xfa, 0xdb, + 0x00, 0x59, 0xdf, 0xef, 0x0a, 0xf8, 0x00, 0xee, 0xea, 0xfe, 0xc0, 0xed, 0x01, + 0xd9, 0x1e, 0x0e, 0x41, 0x20, 0x23, 0x18, 0xfb, 0x1f, 0xf1, 0x11, 0xf4, 0xf2, + 0x34, 0xed, 0xdf, 0xf4, 0xe0, 0xfc, 0xde, 0xff, 0x26, 0xd6, 0xc3, 0x14, 0xdf, + 0xfa, 0xcc, 0xda, 0xdd, 0x12, 0xee, 0x03, 0x02, 0xd0, 0xdb, 0x2d, 0xdb, 0xda, + 0xf3, 0xf8, 0xd4, 0x27, 0xbc, 0xdf, 0x06, 0xf6, 0xff, 0x1b, 0x00, 0xd2, 0x06, + 0x10, 0xfd, 0xfd, 0xeb, 0xff, 0xe9, 0xe5, 0xdd, 0x03, 0xdc, 0x06, 0x3f, 0x45, + 0xfe, 0x08, 0x20, 0x24, 0x2f, 0x1e, 0xf3, 0xf3, 0xc2, 0x20, 0xd0, 0xfc, 0xed, + 0xbf, 0x03, 0xfb, 0xee, 0x04, 0x18, 0xd9, 0xd2, 0x1b, 0xe2, 0xdd, 0xfe, 0xdb, + 0x21, 0x2a, 0xe6, 0xf7, 0x07, 0xd4, 0x04, 0xe3, 0x27, 0x27, 0xdc, 0x03, 0xc8, + 0xed, 0xe0, 0x1b, 0xf7, 0x34, 0xc8, 0xe5, 0xc3, 0x1d, 0xfb, 0x08, 0xeb, 0xd5, + 0xe6, 0x21, 0x11, 0x21, 0xed, 0x2a, 0xc7, 0xd8, 0xe1, 0xfe, 0x0a, 0xe5, 0xb9, + 0x10, 0xff, 0x23, 0x1b, 0xb1, 0xf4, 0xe3, 0xf2, 0x11, 0xe7, 0xd4, 0x0d, 0xfe, + 0x00, 0x21, 0xd6, 0xdd, 0x03, 0xe5, 0xf0, 0x11, 0xf7, 0xed, 0xe1, 0xfc, 0x0c, + 0x09, 0xa9, 0xdf, 0xed, 0xdc, 0xf2, 0xb8, 0xfc, 0xf2, 0x06, 0x3a, 0x32, 0x1f, + 0xfb, 0xac, 0xe0, 0xec, 0x01, 0x2f, 0xdd, 0xcd, 0x0e, 0xcc, 0x16, 0x2f, 0x20, + 0x2e, 0x03, 0xf4, 0x1f, 0xdf, 0xbf, 0xd8, 0x14, 0x0a, 0x0b, 0xe4, 0xf8, 0xec, + 0xd7, 0xe2, 0xe0, 0xe6, 0xfa, 0xf6, 0xcd, 0xf9, 0xd5, 0xcc, 0xe2, 0xfd, 0x16, + 0xf9, 0xea, 0x0c, 0xc6, 0xcc, 0x26, 0xd3, 0xec, 0xea, 0xed, 0x08, 0xe2, 0xee, + 0xe4, 0x00, 0xe2, 0xfa, 0xe1, 0x0e, 0x0d, 0xfe, 0x29, 0xc9, 0x1d, 0x1d, 0x0d, + 0xfb, 0x26, 0xfd, 0x0e, 0x22, 0xf4, 0xe8, 0xc3, 0x5d, 0xe4, 0xff, 0x7f, 0x2f, + 0x20, 0xee, 0xc8, 0xe7, 0xf7, 0xcc, 0x0b, 0xe3, 0x0f, 0xa5, 0xd0, 0xcd, 0x08, + 0xe6, 0xff, 0xc7, 0x01, 0x12, 0xe8, 0xe2, 0xd6, 0xf2, 0xfc, 0xf2, 0x06, 0xf1, + 0xa2, 0xfa, 0xc7, 0xd5, 0xdd, 0xc9, 0xcb, 0xe5, 0xe5, 0xd2, 0xfb, 0xf0, 0x00, + 0xe0, 0xfc, 0x04, 0xf4, 0xd6, 0x40, 0x1a, 0xa2, 0xee, 0xe7, 0x15, 0xd4, 0x16, + 0xdd, 0xf8, 0x00, 0xd0, 0xe2, 0x3c, 0xec, 0xe4, 0xe3, 0xde, 0xf4, 0x04, 0xc3, + 0xd7, 0x11, 0x28, 0xed, 0xd2, 0xa6, 0xe1, 0x21, 0xe7, 0xf3, 0x3a, 0x07, 0x1e, + 0x72, 0x38, 0x09, 0xea, 0xf0, 0xf4, 0x08, 0xf2, 0xd4, 0x01, 0xcf, 0x1a, 0xd1, + 0xfb, 0x3e, 0xc6, 0xf1, 0x30, 0xe4, 0xeb, 0x38, 0xb3, 0xf7, 0x18, 0xd7, 0xe6, + 0xf6, 0x19, 0xfe, 0x04, 0xc5, 0x2f, 0xf6, 0xf2, 0xe5, 0xe4, 0xca, 0x08, 0xfd, + 0x5f, 0xbf, 0x09, 0xb3, 0xfc, 0xea, 0xcf, 0xc7, 0xe0, 0xac, 0x2f, 0x1c, 0x36, + 0x20, 0xf6, 0xb2, 0xc2, 0xa2, 0x0d, 0x05, 0xdf, 0xc3, 0x1f, 0xc9, 0xf3, 0xfa, + 0xb7, 0x3b, 0x05, 0x19, 0xb1, 0xf2, 0xe6, 0xf5, 0x07, 0x1d, 0xeb, 0xc0, 0xa6, + 0xb5, 0xea, 0xd9, 0xf7, 0xf0, 0xf9, 0x05, 0xf6, 0xff, 0x2d, 0xf2, 0xc9, 0x02, + 0xd3, 0x03, 0xbb, 0xb2, 0xe2, 0xe0, 0x38, 0x40, 0xcd, 0xf7, 0xda, 0x20, 0xd4, + 0x26, 0x0d, 0x32, 0xb4, 0x13, 0xbb, 0x19, 0x6f, 0xf6, 0xe7, 0xbf, 0xe1, 0x19, + 0xaf, 0x14, 0xc5, 0x3c, 0xfd, 0xdd, 0xf7, 0xef, 0xcc, 0x08, 0xce, 0xd4, 0xf5, + 0x04, 0xc2, 0xc9, 0x02, 0xaa, 0xc3, 0xb3, 0xc6, 0x19, 0xfe, 0x0f, 0x28, 0xe4, + 0x81, 0x13, 0x17, 0xf8, 0xbd, 0x14, 0x08, 0x2d, 0xfb, 0x3d, 0xf7, 0x07, 0x0f, + 0x12, 0xe5, 0xda, 0xcb, 0x41, 0xda, 0x2b, 0xf4, 0x19, 0xcd, 0x2d, 0x38, 0x10, + 0x19, 0x2a, 0x16, 0xd1, 0xdd, 0xda, 0xd7, 0x23, 0x13, 0x0c, 0xe6, 0xda, 0x93, + 0xe3, 0xc2, 0xcd, 0xe1, 0xe4, 0xe8, 0xe8, 0x07, 0xf6, 0x19, 0x0c, 0xd1, 0x14, + 0x09, 0xd8, 0xc4, 0x20, 0x0d, 0xc6, 0x0b, 0xcf, 0x00, 0x00, 0xfc, 0xea, 0xde, + 0xaa, 0x0f, 0x0d, 0x19, 0x95, 0xe7, 0x44, 0xb3, 0x2c, 0xcc, 0x38, 0x39, 0xdc, + 0xc1, 0xe0, 0x1f, 0xd7, 0xd0, 0x07, 0xbc, 0x30, 0x3f, 0x0a, 0xde, 0xea, 0xe7, + 0xf1, 0xc2, 0xf2, 0x1c, 0xb2, 0xee, 0xee, 0xb0, 0xea, 0xdc, 0xcf, 0x95, 0x17, + 0xe8, 0x4f, 0xce, 0x49, 0xb9, 0xdd, 0x0f, 0xe9, 0x02, 0x32, 0xa9, 0xf0, 0xe8, + 0x19, 0x32, 0x10, 0xfa, 0x09, 0xbd, 0xd4, 0x01, 0x1d, 0xf8, 0x23, 0xec, 0xde, + 0xae, 0xe8, 0xd3, 0x14, 0xe4, 0x31, 0xfd, 0x56, 0xeb, 0xb9, 0x03, 0x06, 0xeb, + 0x32, 0xd8, 0xe5, 0x1f, 0x35, 0x53, 0xfe, 0xda, 0x0c, 0xb1, 0xdb, 0xc1, 0xcd, + 0x53, 0xe6, 0x16, 0xfb, 0xf3, 0xd7, 0xde, 0x01, 0xc8, 0xef, 0x23, 0x2e, 0xda, + 0xdf, 0xc0, 0xc9, 0xe4, 0xf0, 0xe1, 0xcb, 0xe7, 0x7f, 0xf5, 0xe8, 0xe2, 0x14, + 0x17, 0x2f, 0xe1, 0xda, 0xcb, 0xa2, 0x2d, 0x0b, 0xfb, 0xee, 0x10, 0x20, 0xf6, + 0x0f, 0x15, 0xfd, 0x11, 0xd4, 0x50, 0xec, 0xfb, 0xf7, 0xd8, 0xb3, 0xe6, 0xe2, + 0xbe, 0x3a, 0x32, 0xf1, 0xf2, 0x36, 0xc3, 0xaa, 0x27, 0xf9, 0x31, 0x41, 0xf6, + 0xd7, 0x0d, 0x07, 0xc8, 0xee, 0xfc, 0x13, 0x00, 0xeb, 0x1c, 0xe5, 0x08, 0x1f, + 0x17, 0xf7, 0xf1, 0xee, 0xe2, 0x1a, 0xf9, 0xcc, 0xec, 0x95, 0x26, 0xee, 0x03, + 0xf1, 0xbf, 0x0e, 0x1c, 0x46, 0xf6, 0x16, 0x1c, 0xf6, 0xd4, 0x1a, 0xfa, 0xef, + 0x0d, 0x44, 0xe4, 0x3e, 0x6d, 0x3f, 0x1c, 0x43, 0xd8, 0xfd, 0x3a, 0xcb, 0xe8, + 0x06, 0xfc, 0xf6, 0x07, 0x3f, 0xfa, 0xef, 0xc1, 0xb7, 0xfd, 0x0b, 0x3c, 0x0f, + 0xe1, 0x0b, 0xe1, 0xef, 0x9b, 0xd3, 0x95, 0x1d, 0xf3, 0xf5, 0xf1, 0xff, 0x16, + 0x02, 0xf4, 0x15, 0xf5, 0xa6, 0xd5, 0xf6, 0x03, 0x1c, 0x3a, 0xfd, 0xe0, 0x05, + 0xff, 0x0e, 0xda, 0xce, 0xc0, 0xdd, 0xcd, 0xe2, 0xdf, 0xba, 0x14, 0xc7, 0xf9, + 0xf8, 0x12, 0xfd, 0xe3, 0x31, 0xe5, 0x8e, 0xfb, 0x07, 0xf0, 0xf9, 0xf3, 0xd5, + 0xd5, 0x08, 0xa6, 0x01, 0x11, 0x33, 0x23, 0x24, 0x45, 0x4e, 0x3a, 0x0d, 0x20, + 0xd7, 0x1e, 0x39, 0x19, 0xd7, 0xfd, 0xa0, 0xc6, 0xe5, 0xe7, 0xd3, 0xba, 0x11, + 0xfc, 0x2a, 0xfe, 0x19, 0xf0, 0xcb, 0xce, 0xe1, 0xdd, 0x35, 0x0c, 0x3c, 0xf2, + 0xf9, 0x07, 0x17, 0xc1, 0xf9, 0xd5, 0x06, 0x11, 0x87, 0xf1, 0x0d, 0x0d, 0xee, + 0xf1, 0xdb, 0xa5, 0x12, 0xe6, 0xd2, 0x29, 0x37, 0xd9, 0xe4, 0xcb, 0x38, 0xc4, + 0x2a, 0x14, 0xbf, 0xc2, 0x2b, 0x0e, 0xe6, 0xda, 0xd7, 0xce, 0xf6, 0xf7, 0x39, + 0x1d, 0xfb, 0x01, 0xfe, 0xe9, 0xb2, 0xde, 0x99, 0xfb, 0x38, 0x24, 0xbc, 0xe9, + 0xd6, 0xc8, 0x1f, 0xbb, 0x55, 0xfc, 0xe2, 0xdc, 0x33, 0xde, 0x01, 0x08, 0x0e, + 0x19, 0xe9, 0x20, 0x33, 0xfb, 0x9b, 0xdd, 0x0c, 0xbb, 0xf2, 0xc6, 0x1d, 0xbc, + 0x16, 0x1a, 0xd9, 0xc6, 0x81, 0x35, 0xfd, 0xe8, 0x1e, 0x25, 0xbb, 0x27, 0xd0, + 0x16, 0xe4, 0xd9, 0x39, 0xad, 0xa0, 0xd3, 0xe1, 0x20, 0xfa, 0x01, 0xee, 0x08, + 0xdb, 0xdc, 0x6a, 0x2f, 0xc1, 0x43, 0xf0, 0x01, 0x07, 0xb1, 0xc6, 0xa7, 0x32, + 0x02, 0xcf, 0x20, 0x06, 0x48, 0x28, 0x11, 0xc4, 0xec, 0x6b, 0xd0, 0x14, 0xee, + 0x6a, 0x26, 0xd7, 0xf2, 0x46, 0xff, 0x29, 0xa5, 0xdf, 0xe1, 0xdc, 0xd6, 0x11, + 0xd8, 0x08, 0xe9, 0xf2, 0x0e, 0xdc, 0x89, 0xdf, 0xe6, 0x14, 0xec, 0x3a, 0x10, + 0x3e, 0xed, 0xe2, 0x20, 0x3e, 0x13, 0xf9, 0xba, 0xfe, 0xd7, 0xca, 0xf2, 0x44, + 0x1f, 0x04, 0x14, 0xc1, 0xfb, 0x0b, 0xf2, 0x66, 0xc8, 0xf8, 0x45, 0x0b, 0x36, + 0x1b, 0xd1, 0x28, 0x1c, 0x00, 0x0b, 0x14, 0xb5, 0xfa, 0xd3, 0xf6, 0x2a, 0xd4, + 0xcc, 0xc9, 0xaf, 0xd8, 0xca, 0x06, 0x26, 0x02, 0xd1, 0xde, 0xc5, 0x02, 0xc0, + 0xf0, 0x1d, 0x32, 0x31, 0xd4, 0x2f, 0xf9, 0xf3, 0xe2, 0x1f, 0x97, 0xb8, 0x1d, + 0xc4, 0x2d, 0xfe, 0xbe, 0xfa, 0xce, 0xd8, 0x15, 0xea, 0xbd, 0xda, 0x56, 0xd7, + 0x09, 0xca, 0x23, 0x14, 0xbf, 0x5c, 0x52, 0x1b, 0x3b, 0xe4, 0x19, 0xf1, 0xec, + 0x15, 0xfb, 0xa7, 0xb7, 0xe2, 0xdf, 0xd8, 0xe8, 0x23, 0x2a, 0x1d, 0x04, 0x1b, + 0x20, 0xf0, 0xf3, 0x83, 0x2e, 0xdb, 0xf6, 0x99, 0xfd, 0x33, 0x09, 0xf1, 0x3b, + 0xfd, 0x20, 0xd7, 0x96, 0x04, 0x01, 0x2b, 0xd1, 0x0b, 0x32, 0x4b, 0x29, 0x20, + 0xfa, 0x0e, 0xcd, 0xdd, 0x4c, 0xae, 0x00, 0xaf, 0x0b, 0xf5, 0xe5, 0x03, 0xdb, + 0x99, 0xc5, 0xe6, 0xf5, 0x81, 0xe7, 0x0b, 0x11, 0xc2, 0x1f, 0xf6, 0xfb, 0x2f, + 0x47, 0x40, 0xff, 0x1f, 0xfe, 0xdc, 0xc6, 0xc5, 0xed, 0x04, 0x1e, 0x27, 0x12, + 0xc3, 0x2f, 0x1d, 0x23, 0xfe, 0xed, 0x41, 0x3f, 0xfb, 0x09, 0xf8, 0xf1, 0xf4, + 0xff, 0xc7, 0xc5, 0x1b, 0xdb, 0x01, 0x8c, 0x0e, 0xf2, 0x36, 0xf3, 0xfc, 0xcd, + 0xd2, 0xfb, 0x0a, 0x15, 0x46, 0x25, 0x03, 0xfe, 0xeb, 0xca, 0xba, 0x11, 0x19, + 0xec, 0xba, 0x04, 0xba, 0x25, 0xef, 0x1c, 0xfb, 0x09, 0x0e, 0x22, 0x1e, 0xda, + 0x01, 0xf9, 0x36, 0xec, 0x24, 0xbd, 0xed, 0x10, 0xee, 0x19, 0xb7, 0xa8, 0xf2, + 0xe0, 0x9a, 0x12, 0xdb, 0xb9, 0xf9, 0xbd, 0xc8, 0x10, 0x24, 0x06, 0x8f, 0xeb, + 0x0c, 0x19, 0xd9, 0x0a, 0x8f, 0xd7, 0xc1, 0x0a, 0xd9, 0x43, 0x0d, 0xb6, 0x03, + 0xe5, 0x09, 0x2e, 0xfd, 0xdc, 0xd1, 0xf9, 0xa1, 0xd7, 0x10, 0xc0, 0xf8, 0x0f, + 0xe2, 0x15, 0x30, 0x15, 0x25, 0xed, 0xf7, 0x1e, 0x2a, 0xb3, 0xdb, 0x48, 0x21, + 0x01, 0xf0, 0x04, 0xc1, 0x05, 0xfd, 0x20, 0xd4, 0xe4, 0x04, 0xc3, 0x01, 0xde, + 0xe2, 0xe0, 0x03, 0xef, 0xd2, 0x22, 0x0d, 0x29, 0xfb, 0xca, 0xf1, 0xe5, 0x11, + 0x07, 0xe3, 0xe3, 0xe9, 0x3a, 0xad, 0x06, 0x13, 0xfc, 0xca, 0x39, 0xd0, 0xf2, + 0xf4, 0x0f, 0x0f, 0x1d, 0xd4, 0xf5, 0xd4, 0x1c, 0xc5, 0x2f, 0x0f, 0xdd, 0x01, + 0x0b, 0xc7, 0xfd, 0xfe, 0x20, 0x24, 0x24, 0x2d, 0xe8, 0x13, 0x1f, 0x1a, 0xfa, + 0xfc, 0x11, 0xe9, 0x25, 0x07, 0x05, 0xf9, 0xea, 0x11, 0xd4, 0xac, 0x17, 0x07, + 0x26, 0x04, 0xf9, 0xc0, 0xe1, 0xf9, 0x00, 0xc3, 0x04, 0xc1, 0xfb, 0x25, 0xe3, + 0xf6, 0x1b, 0xf0, 0x12, 0xf1, 0xf8, 0xd0, 0xf1, 0x1b, 0xe2, 0x08, 0x32, 0xf1, + 0x15, 0xf2, 0xb8, 0xe4, 0xe3, 0x12, 0xef, 0xd2, 0xd9, 0xdc, 0xf4, 0xbe, 0x1d, + 0x08, 0x19, 0x13, 0xdc, 0xd0, 0x20, 0xf5, 0xdc, 0xd9, 0x29, 0xeb, 0xee, 0xc8, + 0x1b, 0xb3, 0x0b, 0x0c, 0xda, 0xd8, 0x20, 0xfa, 0xc8, 0xeb, 0x0e, 0x1d, 0xe8, + 0xd8, 0xd0, 0x20, 0x2b, 0xf4, 0x31, 0x19, 0x22, 0xce, 0x1d, 0x23, 0xed, 0xe7, + 0x1a, 0xcb, 0xd6, 0xe0, 0xea, 0x09, 0x0b, 0xbd, 0xf3, 0x09, 0xd0, 0x07, 0xd5, + 0x16, 0xf1, 0xfa, 0xfa, 0x09, 0xce, 0xf0, 0x1b, 0xe9, 0x43, 0xf8, 0xe5, 0xfd, + 0x05, 0xdd, 0x31, 0xfa, 0x0d, 0x16, 0x08, 0xfa, 0xd0, 0x06, 0x49, 0xcd, 0xf3, + 0xd1, 0x06, 0xf4, 0xf5, 0xf2, 0x25, 0xef, 0x03, 0x32, 0x45, 0x96, 0x22, 0x24, + 0x08, 0xe8, 0x37, 0xb6, 0x06, 0x1f, 0xda, 0xf3, 0xd8, 0xc9, 0x0d, 0xd5, 0xcb, + 0xac, 0xdd, 0x01, 0x09, 0x09, 0x12, 0x19, 0xba, 0xfa, 0x09, 0xd8, 0x11, 0x04, + 0x16, 0xec, 0x25, 0xf0, 0xe2, 0x30, 0x04, 0xeb, 0x0b, 0xfc, 0xd8, 0xec, 0x05, + 0x10, 0xf4, 0x01, 0x0f, 0x08, 0x06, 0xfd, 0xf6, 0x7f, 0x10, 0xf2, 0xf8, 0xd9, + 0x0e, 0x04, 0x1b, 0x1c, 0xfa, 0x1e, 0xc6, 0xf0, 0xa6, 0x0f, 0x2d, 0xdb, 0xc3, + 0x5c, 0xb3, 0xf0, 0xcd, 0x31, 0x68, 0x04, 0xee, 0x1b, 0xe0, 0x01, 0xfc, 0x16, + 0xe6, 0xf7, 0xf8, 0x2d, 0xaa, 0xfa, 0xe2, 0x07, 0x02, 0xc3, 0xdf, 0xd1, 0xe6, + 0x23, 0xe4, 0x01, 0x00, 0x36, 0xa5, 0x03, 0xdc, 0xd2, 0xc5, 0xda, 0xe0, 0xca, + 0xf3, 0xba, 0xee, 0xf9, 0xec, 0x41, 0x55, 0x38, 0x00, 0x01, 0x9b, 0x17, 0xbd, + 0x41, 0x08, 0xde, 0xbc, 0x26, 0x31, 0xef, 0xf9, 0xda, 0x0b, 0x32, 0xcf, 0xd9, + 0x08, 0xd6, 0x0e, 0x56, 0x21, 0x2d, 0x28, 0xec, 0x01, 0x0a, 0xc1, 0x71, 0xf6, + 0x23, 0xf7, 0xe3, 0x04, 0xe2, 0xf7, 0x23, 0x81, 0xd4, 0x0b, 0xf5, 0x0e, 0x33, + 0xae, 0xed, 0x0e, 0xe5, 0xfd, 0x2d, 0x2f, 0x26, 0xb3, 0xe8, 0xd0, 0xf6, 0xd2, + 0xf9, 0xc8, 0xe5, 0xec, 0x12, 0xd3, 0xe9, 0x09, 0xf0, 0x16, 0x02, 0x9f, 0xee, + 0x05, 0xe2, 0x08, 0x03, 0xbe, 0xce, 0xc6, 0x61, 0x0b, 0x0e, 0x0e, 0x07, 0x13, + 0x2b, 0x13, 0xdf, 0xe8, 0x9d, 0x07, 0xb8, 0x0d, 0x9b, 0xec, 0xbe, 0xd4, 0x51, + 0x21, 0x15, 0xb9, 0xec, 0x08, 0xa3, 0xfc, 0x54, 0x2b, 0xed, 0xed, 0x0f, 0xec, + 0x13, 0xfe, 0x03, 0xe9, 0xdb, 0x3a, 0xaf, 0xad, 0xde, 0x42, 0xfb, 0xff, 0xe6, + 0x07, 0x48, 0xf8, 0xeb, 0xdb, 0xd1, 0x20, 0xe8, 0xaf, 0x3e, 0xad, 0xe4, 0xed, + 0xe8, 0xf1, 0xea, 0xf8, 0x06, 0xfe, 0xb4, 0x2b, 0xb9, 0xe6, 0x06, 0xf8, 0xd6, + 0xd7, 0xf7, 0xf4, 0xf0, 0x11, 0x0a, 0xf5, 0x1c, 0xe4, 0xd4, 0xde, 0x9a, 0x1e, + 0xf5, 0x30, 0xca, 0x26, 0xec, 0xd1, 0x07, 0x05, 0xdf, 0xb8, 0x0f, 0xd5, 0xc2, + 0x1d, 0x26, 0xe2, 0xc9, 0xbc, 0xc9, 0x89, 0xe3, 0xb5, 0xfb, 0x16, 0x98, 0xdb, + 0xc8, 0xd1, 0xf0, 0x06, 0x97, 0x27, 0x0d, 0x0b, 0x1d, 0xfb, 0xfd, 0x1f, 0x11, + 0x44, 0xd7, 0xce, 0x00, 0x39, 0xe4, 0xf3, 0x15, 0x13, 0xf8, 0x1c, 0xd7, 0x0b, + 0xf0, 0xf2, 0x25, 0x0b, 0xe6, 0x07, 0xf1, 0xe6, 0xf3, 0x02, 0x00, 0x25, 0xe5, + 0xfd, 0x23, 0x14, 0xd3, 0x0a, 0xe5, 0x05, 0x13, 0x43, 0xe3, 0xee, 0xe2, 0xe6, + 0xf5, 0xf9, 0xfd, 0x24, 0xd2, 0x20, 0x29, 0xde, 0x0b, 0xfa, 0x10, 0xd8, 0xe4, + 0xfa, 0xd3, 0x05, 0xf3, 0x24, 0xdc, 0x02, 0xe8, 0xe8, 0xf0, 0xf0, 0x2c, 0xdb, + 0xd9, 0x1c, 0xf2, 0xfc, 0xf0, 0x08, 0x17, 0xf4, 0xe0, 0xeb, 0x0f, 0xe9, 0xff, + 0x0a, 0xfb, 0xf7, 0xe7, 0x05, 0x0e, 0x10, 0x05, 0x2c, 0x06, 0xd9, 0x08, 0x02, + 0x0c, 0x35, 0x08, 0x17, 0xf6, 0xf8, 0x08, 0x17, 0xdf, 0xef, 0xfb, 0x0d, 0xb6, + 0xc1, 0x01, 0x35, 0xf5, 0xd2, 0xfe, 0xe2, 0x1c, 0xfb, 0xe1, 0xe7, 0x16, 0x0b, + 0x0b, 0xeb, 0x1a, 0x15, 0xd0, 0x00, 0xdd, 0x24, 0xf4, 0xf8, 0xed, 0x29, 0xf5, + 0x19, 0x09, 0x0e, 0xe8, 0xef, 0x1d, 0xf1, 0xdd, 0xe3, 0xd1, 0x6b, 0xf1, 0xf4, + 0x09, 0xf5, 0x1d, 0x57, 0xd9, 0x7f, 0x04, 0x15, 0xf9, 0x0a, 0xdb, 0xd4, 0xea, + 0xc7, 0xf6, 0x07, 0x06, 0xde, 0xfe, 0xed, 0x12, 0xf2, 0x6f, 0x14, 0xf6, 0xca, + 0x05, 0xdf, 0x1e, 0x17, 0x07, 0xe7, 0xf8, 0xd6, 0xf3, 0xed, 0x11, 0xd2, 0x22, + 0x1a, 0x1f, 0xf2, 0xf3, 0xe2, 0x0f, 0x11, 0xea, 0xfa, 0x6f, 0xeb, 0xec, 0xf5, + 0xee, 0x02, 0xd7, 0xfe, 0xc7, 0x19, 0xf1, 0x0e, 0x03, 0x05, 0xfc, 0xd7, 0xc6, + 0xf5, 0x07, 0x44, 0xf7, 0x02, 0x0e, 0xfc, 0x17, 0xe2, 0xf0, 0x1b, 0xf9, 0xf5, + 0xe6, 0xf8, 0xea, 0xf2, 0x0d, 0x19, 0x04, 0x1a, 0xed, 0x0f, 0xe8, 0xdc, 0xd9, + 0xfc, 0x0c, 0xf6, 0xf7, 0x19, 0x5d, 0xf0, 0x1d, 0x4e, 0x1f, 0x18, 0xe4, 0xd5, + 0x14, 0xf9, 0xf7, 0xf1, 0xab, 0x6b, 0xd7, 0x0c, 0xfe, 0xfa, 0xc0, 0x9d, 0xca, + 0x07, 0xd8, 0x1f, 0xf3, 0xfa, 0x09, 0xba, 0xdd, 0x09, 0x1e, 0x18, 0x0d, 0xf4, + 0x30, 0x39, 0xef, 0xf6, 0xf8, 0xd6, 0x2b, 0xd5, 0xf6, 0xb8, 0xdb, 0x0e, 0xd2, + 0xf6, 0x4a, 0xf9, 0x19, 0x06, 0xf1, 0xaa, 0xee, 0xc6, 0xdc, 0x21, 0x13, 0x5b, + 0x3d, 0x23, 0xc4, 0x30, 0x1f, 0x3d, 0x41, 0x06, 0xea, 0xe2, 0x17, 0x20, 0xd6, + 0xef, 0x81, 0x13, 0x1d, 0x1b, 0x01, 0xce, 0xf7, 0xf1, 0x43, 0x2d, 0x00, 0xe6, + 0x1d, 0xc3, 0xed, 0x07, 0xd3, 0x0b, 0x2d, 0xef, 0xed, 0x1b, 0xe7, 0x30, 0xc8, + 0xd3, 0xf2, 0x08, 0x03, 0xb7, 0xec, 0xdc, 0x1c, 0xb0, 0xcc, 0x56, 0x22, 0x48, + 0xaa, 0x07, 0xe5, 0xe2, 0x0a, 0x07, 0xf8, 0xbe, 0x3c, 0xe1, 0x25, 0xc4, 0x34, + 0xef, 0xa6, 0x1e, 0xfd, 0xba, 0xaf, 0x05, 0xda, 0x3b, 0xef, 0xba, 0x02, 0xd8, + 0x14, 0x31, 0x15, 0x00, 0x08, 0xba, 0xf6, 0xe7, 0xff, 0x32, 0x31, 0xd4, 0x1b, + 0xf0, 0x08, 0x1f, 0x9c, 0xf9, 0x1c, 0xde, 0xdf, 0x0d, 0xe0, 0xe8, 0x47, 0xd8, + 0x22, 0x04, 0x09, 0xec, 0xfc, 0x0b, 0x14, 0xc8, 0xed, 0xe8, 0xd2, 0xb2, 0xa9, + 0x15, 0xea, 0xf0, 0x13, 0xfd, 0xff, 0xf0, 0xda, 0xf9, 0xf2, 0x0f, 0x10, 0xfc, + 0x11, 0xf5, 0x16, 0x3f, 0x01, 0x01, 0x19, 0x22, 0x38, 0x02, 0xbb, 0xf6, 0x13, + 0x4a, 0x23, 0x17, 0x11, 0x40, 0xd2, 0xcb, 0x19, 0x0b, 0xfb, 0xf0, 0xef, 0x30, + 0x1d, 0x1b, 0xca, 0xde, 0x22, 0xeb, 0x02, 0x17, 0xc0, 0xb0, 0x21, 0x07, 0x2f, + 0x00, 0xe5, 0xb2, 0xed, 0x83, 0x20, 0xdb, 0x41, 0x04, 0x0a, 0xee, 0xc8, 0xe7, + 0x09, 0xf8, 0xf4, 0x10, 0x30, 0xda, 0x0a, 0x14, 0xfa, 0xbf, 0xf9, 0xce, 0x15, + 0xf1, 0xfc, 0xbd, 0x1e, 0x17, 0xf4, 0xe0, 0xe6, 0xcd, 0xfd, 0x29, 0x25, 0x02, + 0xcd, 0xc7, 0xb6, 0xe5, 0x06, 0x01, 0xd6, 0x1c, 0xfd, 0xfa, 0x18, 0xfd, 0xc8, + 0xc3, 0x17, 0xe2, 0x1f, 0xc8, 0xe7, 0x36, 0xc4, 0xef, 0xf2, 0xd4, 0xd2, 0x14, + 0x21, 0x06, 0x07, 0xfc, 0x06, 0x04, 0xf0, 0xc5, 0x11, 0xc6, 0x19, 0x09, 0x30, + 0xf9, 0x12, 0xfe, 0xf4, 0xfd, 0xf7, 0xf5, 0x13, 0x1c, 0xfe, 0xd4, 0xd8, 0x08, + 0x28, 0x23, 0xf5, 0x05, 0x13, 0xfb, 0x01, 0x6a, 0x1c, 0xe0, 0xea, 0xfb, 0x23, + 0xf9, 0x0a, 0x04, 0x3d, 0xf2, 0x19, 0x0a, 0xcf, 0x0b, 0x00, 0xd5, 0x12, 0xdd, + 0x12, 0x2c, 0xe1, 0x18, 0x29, 0x02, 0x1b, 0x08, 0x08, 0xee, 0xda, 0xd6, 0x1c, + 0xf6, 0x1d, 0xb8, 0xaa, 0xd9, 0xf3, 0x0e, 0xf6, 0xef, 0xd1, 0xf6, 0xf4, 0xb5, + 0xfd, 0xd9, 0xdd, 0xf8, 0x38, 0x0b, 0xeb, 0xe5, 0xfe, 0x00, 0xf9, 0xcb, 0xec, + 0x0c, 0xf0, 0xf2, 0x0f, 0xf9, 0xcd, 0xd1, 0x31, 0xd0, 0xcc, 0xe7, 0x2a, 0xd4, + 0xee, 0xf4, 0xaa, 0xe9, 0x06, 0xe7, 0xea, 0xee, 0xe8, 0xff, 0xf3, 0xe3, 0xf8, + 0x10, 0xc8, 0xed, 0x01, 0xd0, 0xee, 0x02, 0xe7, 0x03, 0xc1, 0xe4, 0xd3, 0xba, + 0x1c, 0x25, 0x49, 0xe4, 0xf1, 0xdf, 0xf6, 0xbd, 0x49, 0x0b, 0xbb, 0x03, 0xe9, + 0xfb, 0x4b, 0x1b, 0xf4, 0x7f, 0xe0, 0x27, 0xd2, 0x04, 0x0d, 0x08, 0xcc, 0xbf, + 0xf9, 0xed, 0xee, 0xed, 0x54, 0xc1, 0xf3, 0x04, 0xb5, 0xce, 0xe7, 0xc5, 0xf6, + 0xea, 0xcd, 0x09, 0x0f, 0xfe, 0x37, 0xdd, 0x0e, 0x0b, 0xf8, 0x09, 0xbf, 0xf8, + 0xcc, 0xe7, 0xf8, 0x43, 0xfe, 0x0d, 0xfb, 0xe7, 0xdf, 0xf5, 0x3a, 0xc6, 0x29, + 0x29, 0xfc, 0x31, 0xf3, 0xf0, 0x10, 0xd9, 0xd8, 0x05, 0xcb, 0x02, 0xee, 0x08, + 0x1d, 0x53, 0x06, 0x1c, 0xe3, 0xe4, 0xed, 0xd8, 0xcf, 0xeb, 0x3b, 0xeb, 0x3b, + 0x0b, 0xdb, 0x46, 0xc8, 0x05, 0x2a, 0xe5, 0x04, 0x0f, 0x99, 0x43, 0xba, 0x3a, + 0xfd, 0xf5, 0xd5, 0xee, 0x44, 0x30, 0xe8, 0x18, 0xf6, 0xe3, 0xf1, 0xf6, 0x25, + 0xe3, 0x0e, 0x43, 0x35, 0xfd, 0xc0, 0x0c, 0xf8, 0x59, 0xe3, 0x00, 0xf7, 0x11, + 0xcd, 0x1b, 0xd1, 0xef, 0x34, 0xd4, 0x93, 0x07, 0x2f, 0xf0, 0xe6, 0xda, 0xc7, + 0xf4, 0xc7, 0xd2, 0xeb, 0x15, 0xef, 0xf1, 0xe1, 0x5e, 0xce, 0x29, 0x12, 0x3f, + 0xde, 0xef, 0x2a, 0x19, 0x25, 0xe6, 0xf8, 0x07, 0x0a, 0x54, 0x3f, 0xf4, 0xf3, + 0xcf, 0xeb, 0xed, 0xd3, 0x1d, 0xc7, 0xcf, 0x24, 0xe6, 0xdb, 0x17, 0x0d, 0x56, + 0xd4, 0xc6, 0xeb, 0x23, 0xaf, 0xb2, 0x19, 0xea, 0x3e, 0x31, 0xe7, 0x17, 0x05, + 0xcb, 0xcf, 0x5d, 0x05, 0x05, 0x32, 0xfc, 0xeb, 0xd2, 0x0c, 0xd5, 0xf6, 0x15, + 0xda, 0xd4, 0x15, 0xd9, 0xba, 0xcd, 0x07, 0xd1, 0xf7, 0x30, 0xe0, 0x12, 0x1c, + 0xd5, 0xcf, 0xc1, 0x2a, 0xe1, 0x00, 0x9f, 0xb1, 0x10, 0xf2, 0xf6, 0x27, 0x03, + 0x7f, 0x10, 0x1f, 0x2e, 0x0b, 0xea, 0x22, 0xd4, 0xc9, 0xa9, 0xdb, 0x0b, 0x13, + 0xad, 0xa9, 0xe8, 0x30, 0x15, 0xda, 0xf3, 0xe8, 0xd0, 0x19, 0xfc, 0x03, 0xf1, + 0xe2, 0xbb, 0x08, 0xd0, 0x3b, 0x27, 0x22, 0xd9, 0x0d, 0x4e, 0xee, 0xe6, 0x16, + 0x1e, 0x14, 0xb4, 0xe9, 0xde, 0xf9, 0x27, 0x01, 0x0e, 0xf2, 0xf2, 0xf1, 0xe6, + 0x00, 0xc4, 0xd9, 0xe8, 0x33, 0xf0, 0x34, 0x10, 0xd0, 0x02, 0xf1, 0xeb, 0x28, + 0x26, 0xff, 0x49, 0xe5, 0x01, 0x37, 0x4e, 0x29, 0xf8, 0xc1, 0xe3, 0x22, 0xb9, + 0x1f, 0x02, 0xfd, 0x0e, 0xb7, 0xd6, 0xc7, 0xf9, 0xcd, 0xcd, 0x1a, 0x17, 0xe6, + 0xee, 0x05, 0xd1, 0xe5, 0xed, 0xf9, 0xe1, 0x32, 0x27, 0xe6, 0xf0, 0xd0, 0x31, + 0xe1, 0xea, 0xd4, 0x30, 0x06, 0x43, 0xec, 0xf6, 0xf3, 0x22, 0xf2, 0xf6, 0xd0, + 0xda, 0xfd, 0x0f, 0xad, 0x01, 0xda, 0x0a, 0xc3, 0x10, 0xf8, 0x9f, 0xfe, 0xe4, + 0xf4, 0xb0, 0x2f, 0x13, 0xd7, 0x8b, 0x13, 0xf6, 0xce, 0xd9, 0x05, 0x9e, 0x13, + 0xfb, 0x12, 0xfe, 0x9b, 0xf2, 0xf5, 0xbc, 0x18, 0xf5, 0x10, 0xd1, 0x18, 0xd8, + 0x0a, 0x49, 0xea, 0xd2, 0x0d, 0x02, 0xfd, 0xf7, 0xe1, 0x19, 0xee, 0xb4, 0x14, + 0xe1, 0xf5, 0xb3, 0xcc, 0xe2, 0xf2, 0x15, 0x52, 0xdd, 0xd9, 0x10, 0x22, 0x41, + 0x44, 0x01, 0x21, 0xb8, 0x1c, 0xdc, 0xd9, 0xd9, 0x0e, 0x0f, 0x30, 0xd1, 0xd2, + 0xe8, 0xc4, 0xdf, 0xed, 0xec, 0xc6, 0x36, 0xdb, 0xfb, 0x0f, 0x10, 0x2e, 0xbd, + 0xb5, 0x22, 0x23, 0xf8, 0x22, 0x0d, 0xde, 0xc7, 0xe6, 0xed, 0xfb, 0xe1, 0x4a, + 0x9a, 0x24, 0xd0, 0xf6, 0xe6, 0x30, 0xdc, 0xce, 0xca, 0xe5, 0xfb, 0xe9, 0xfc, + 0x24, 0xd1, 0x0b, 0xe2, 0xce, 0x07, 0xdb, 0xae, 0x34, 0x08, 0xd3, 0x2c, 0xb5, + 0xfc, 0xfa, 0xf4, 0x05, 0xfe, 0x15, 0x2b, 0xfb, 0xe8, 0x2f, 0x30, 0xa3, 0x04, + 0xad, 0x0c, 0xe7, 0xe3, 0x04, 0xea, 0x41, 0x3c, 0xfc, 0xe0, 0x9e, 0xb8, 0xf8, + 0x54, 0xdd, 0xed, 0xfd, 0xcb, 0x2b, 0x4b, 0xf8, 0x00, 0xc6, 0xe7, 0xff, 0x24, + 0x1f, 0xee, 0xc2, 0x53, 0xf0, 0x0a, 0xf7, 0xcd, 0x27, 0x1e, 0x06, 0xe4, 0x12, + 0xcc, 0xb4, 0x2e, 0x08, 0xfd, 0xfa, 0x1a, 0xf1, 0x03, 0xeb, 0xbe, 0x0b, 0xc1, + 0xea, 0x81, 0x29, 0xe9, 0xb9, 0xc0, 0xde, 0x23, 0xf7, 0xdd, 0xe8, 0xd2, 0xdc, + 0x1c, 0xec, 0xd1, 0x04, 0xe0, 0x1f, 0xf7, 0x0c, 0x26, 0xe5, 0x01, 0xe6, 0xe9, + 0x08, 0xce, 0x1f, 0xee, 0xbd, 0x06, 0x13, 0x08, 0xf0, 0xf7, 0xf3, 0x26, 0x1f, + 0x12, 0x14, 0xbe, 0x44, 0xfe, 0xdc, 0x55, 0x47, 0x24, 0x0d, 0xd7, 0xdb, 0xc0, + 0xd0, 0x1f, 0x28, 0x03, 0x92, 0xde, 0xe7, 0x15, 0xf4, 0x32, 0xaf, 0x3a, 0x2c, + 0x13, 0xd1, 0x18, 0x24, 0xb8, 0x5a, 0x47, 0x33, 0x01, 0xca, 0x19, 0xeb, 0x05, + 0xda, 0xb7, 0x81, 0xf4, 0xde, 0xde, 0x06, 0x3d, 0x90, 0xeb, 0x1a, 0xe7, 0xde, + 0xe2, 0xd0, 0x0f, 0x0a, 0x08, 0xeb, 0x21, 0xad, 0x06, 0x0e, 0xae, 0x00, 0x18, + 0x1e, 0x2f, 0x4b, 0xc0, 0xda, 0xf3, 0x42, 0x27, 0x41, 0x36, 0x55, 0xce, 0x1a, + 0xce, 0xc7, 0x12, 0x4f, 0xc9, 0x22, 0xae, 0x17, 0x2d, 0x09, 0xea, 0xc5, 0xb0, + 0xd4, 0xe8, 0x17, 0x2e, 0xdd, 0x34, 0x40, 0xdb, 0x06, 0xea, 0x13, 0xa4, 0x27, + 0xf1, 0x02, 0x34, 0xdb, 0x14, 0xfe, 0xfd, 0x26, 0x3c, 0x15, 0xc6, 0x12, 0xa2, + 0xb5, 0x03, 0x2a, 0xf0, 0xd8, 0xc1, 0xf6, 0xfa, 0x26, 0xaa, 0xc9, 0xdd, 0x21, + 0x39, 0x55, 0x32, 0x2c, 0xcb, 0x20, 0xcc, 0x02, 0x25, 0xa9, 0xed, 0x05, 0x50, + 0xc6, 0x48, 0x37, 0x14, 0xbf, 0xa6, 0x39, 0x1f, 0x44, 0xed, 0x2d, 0x0d, 0xde, + 0x1f, 0x37, 0x99, 0x99, 0x09, 0x15, 0xeb, 0x12, 0xe2, 0xfe, 0xdc, 0x91, 0xc7, + 0xe4, 0x05, 0xd9, 0xf0, 0xf1, 0xe7, 0xe3, 0x1d, 0x14, 0x10, 0xca, 0xcc, 0xaf, + 0xe1, 0x04, 0x43, 0xdc, 0xe2, 0xfc, 0x31, 0xd3, 0xe3, 0x21, 0x13, 0xd9, 0xd9, + 0xa0, 0x46, 0x16, 0x21, 0x24, 0x10, 0x1e, 0xe2, 0x06, 0x19, 0xeb, 0xdc, 0xde, + 0xc6, 0x2e, 0xba, 0xfc, 0x2b, 0xce, 0x16, 0xd2, 0x10, 0xe2, 0xb8, 0xde, 0x20, + 0xc3, 0xf5, 0x29, 0xb5, 0xea, 0x08, 0xf5, 0xd9, 0xb2, 0xca, 0x1c, 0x15, 0xf0, + 0x4c, 0xd5, 0xc1, 0x01, 0x08, 0xf8, 0xe5, 0xab, 0x19, 0xc5, 0xc8, 0xa9, 0xeb, + 0xfd, 0xeb, 0x11, 0x04, 0xd2, 0xa0, 0x25, 0x18, 0xbb, 0xb3, 0x26, 0xef, 0x01, + 0xd6, 0x4a, 0xfd, 0x0c, 0x33, 0x26, 0x12, 0x12, 0xdb, 0xf2, 0x03, 0xfa, 0xc4, + 0x33, 0x3f, 0x0b, 0x12, 0xe6, 0xa1, 0x57, 0x3a, 0x39, 0x06, 0xff, 0x3d, 0xfa, + 0x1f, 0xd1, 0x05, 0x1f, 0x00, 0x0e, 0xf7, 0xf5, 0x14, 0x17, 0xf1, 0xc9, 0xe4, + 0xff, 0x05, 0xec, 0xd3, 0xb1, 0xdc, 0x12, 0xe0, 0xfa, 0xe4, 0xf3, 0x2f, 0xec, + 0xfd, 0xfe, 0xde, 0xe0, 0xe7, 0xf0, 0x01, 0x17, 0xf3, 0x07, 0x12, 0xb1, 0xee, + 0xd4, 0x12, 0x05, 0xd6, 0x3f, 0xdd, 0xbd, 0xbb, 0xfb, 0xd7, 0x00, 0x24, 0x0b, + 0x36, 0xed, 0xee, 0x20, 0x4d, 0xf2, 0xf1, 0xeb, 0x26, 0xf0, 0xe9, 0xac, 0xd7, + 0xe7, 0x2d, 0x2a, 0xe7, 0xcf, 0xf3, 0xc3, 0xd0, 0x1c, 0xe4, 0xec, 0xff, 0x06, + 0xd3, 0xc4, 0x1e, 0xee, 0xfb, 0x08, 0xb9, 0xde, 0xd6, 0xfe, 0x18, 0x28, 0x00, + 0xd5, 0xc6, 0xe0, 0xd4, 0x32, 0x3d, 0xd9, 0x0f, 0xf9, 0xe9, 0xfd, 0xe7, 0xe5, + 0xf2, 0xe7, 0xf7, 0xd9, 0x2d, 0xcd, 0x0f, 0x07, 0x21, 0xdb, 0xce, 0xcf, 0xc5, + 0x05, 0xe1, 0xcd, 0x19, 0xb6, 0xf1, 0xed, 0x12, 0xf6, 0x0e, 0xff, 0xd8, 0xa4, + 0x1d, 0x42, 0xf0, 0xb1, 0xce, 0x02, 0xef, 0xf7, 0xba, 0x0f, 0x01, 0xd2, 0x02, + 0x31, 0xd7, 0xf1, 0xd8, 0x00, 0xfc, 0x45, 0x1a, 0xc2, 0xb8, 0x08, 0xec, 0x07, + 0x0e, 0xb7, 0x0f, 0xc6, 0xd6, 0x3a, 0xad, 0xeb, 0xca, 0xda, 0x0e, 0x2b, 0xc1, + 0x02, 0xfc, 0xef, 0x3f, 0x31, 0xe8, 0x04, 0x15, 0xef, 0xff, 0x25, 0x00, 0x04, + 0x01, 0xc9, 0xdd, 0xff, 0xe4, 0x0c, 0xd8, 0xbc, 0xd9, 0xe0, 0xc4, 0xe8, 0x1e, + 0xd9, 0x34, 0x0d, 0x25, 0xe5, 0x3b, 0xc9, 0x02, 0x1d, 0xf9, 0xce, 0x17, 0xf6, + 0x06, 0x04, 0xe1, 0xea, 0x0d, 0xcf, 0xd2, 0x15, 0xf4, 0xd2, 0x34, 0x09, 0xe0, + 0x7f, 0xa7, 0x22, 0x58, 0xdb, 0xef, 0xfd, 0xf0, 0x3a, 0x3b, 0xf5, 0x52, 0x30, + 0x18, 0xff, 0xfa, 0xa1, 0x06, 0xdc, 0x7b, 0x0a, 0x08, 0x1d, 0xef, 0x13, 0xfe, + 0xdf, 0x18, 0x67, 0x1c, 0xdd, 0xe9, 0xd9, 0xf1, 0xb0, 0xdd, 0x09, 0x14, 0x09, + 0xe0, 0x03, 0x12, 0xf5, 0xd6, 0x37, 0xe3, 0x06, 0xe0, 0xde, 0x4a, 0xcd, 0x0e, + 0xee, 0xf1, 0x1f, 0xfc, 0xf3, 0xf0, 0xd2, 0xf2, 0xfb, 0xfc, 0xd6, 0xe7, 0x34, + 0x0b, 0xfc, 0xf1, 0xd0, 0x09, 0xda, 0xef, 0x27, 0xac, 0xb8, 0x57, 0xdf, 0x00, + 0xb1, 0xf4, 0xca, 0xe3, 0x7e, 0x1d, 0x07, 0x09, 0x1d, 0xcd, 0x45, 0xcb, 0xfa, + 0xf1, 0xd3, 0xd7, 0xc8, 0xef, 0xdc, 0xf2, 0xe5, 0x01, 0x06, 0xf2, 0x12, 0xf5, + 0xda, 0x32, 0xbb, 0x15, 0xb5, 0x04, 0xb4, 0xca, 0xf2, 0x0b, 0x0c, 0x24, 0x62, + 0xdf, 0xe5, 0x95, 0x16, 0x04, 0x46, 0xe1, 0x00, 0xee, 0x4d, 0xcc, 0xdc, 0x4e, + 0xda, 0xcd, 0xc9, 0xe9, 0x0b, 0x51, 0x0e, 0x30, 0xfa, 0xf5, 0xe2, 0x0f, 0xb8, + 0xa7, 0xba, 0xe5, 0xee, 0xd0, 0xd7, 0xc3, 0xd0, 0xf6, 0x36, 0x00, 0x25, 0x48, + 0x1b, 0xc6, 0xe6, 0xb0, 0xba, 0xfb, 0x2e, 0xe9, 0xf2, 0xc6, 0x30, 0xc2, 0xef, + 0xf4, 0xde, 0x75, 0x0c, 0x06, 0x2f, 0x1c, 0x2f, 0x18, 0x03, 0xe6, 0xfa, 0x0b, + 0xf5, 0x13, 0xda, 0x51, 0xf7, 0xf0, 0x16, 0xe9, 0xe3, 0xee, 0xe3, 0xc0, 0xce, + 0x11, 0x13, 0x39, 0xf5, 0xf0, 0xd8, 0x02, 0x35, 0x11, 0xe1, 0x04, 0x1c, 0x24, + 0xda, 0xf5, 0xf8, 0x10, 0xd4, 0xd6, 0xf3, 0xe1, 0x09, 0xf7, 0xff, 0xdd, 0x02, + 0xe1, 0xdb, 0xf3, 0x0b, 0x15, 0x1d, 0xea, 0x2f, 0x08, 0xb0, 0x38, 0x0f, 0xfe, + 0xd3, 0x19, 0xde, 0x27, 0x02, 0x09, 0xd9, 0xe8, 0x7f, 0xfd, 0x04, 0xfd, 0xeb, + 0xc6, 0xff, 0xf7, 0xe0, 0xc9, 0x1d, 0xa1, 0x0c, 0x17, 0xd9, 0xdd, 0xa3, 0xdb, + 0xe1, 0x10, 0x28, 0xed, 0x07, 0xe5, 0x06, 0xf0, 0xf9, 0xd8, 0xb9, 0xc3, 0xfc, + 0x25, 0xf0, 0xfc, 0xfe, 0xe5, 0x03, 0x0f, 0xf3, 0xd9, 0xb5, 0xe5, 0xeb, 0xf3, + 0xdc, 0x2d, 0xd2, 0xc8, 0xcf, 0xef, 0xdd, 0xe5, 0xf8, 0x0a, 0x1f, 0xfc, 0xd0, + 0x11, 0xdc, 0xcb, 0x31, 0x01, 0xdf, 0xfb, 0xee, 0x2a, 0xe1, 0xf5, 0x37, 0xdd, + 0x0d, 0xcd, 0x10, 0xcc, 0xf8, 0x01, 0xff, 0xdd, 0xfc, 0xd6, 0x20, 0x43, 0xd2, + 0xec, 0x11, 0xf8, 0x03, 0xdc, 0x15, 0xfc, 0xf2, 0xca, 0xf9, 0x07, 0x08, 0xe0, + 0xfd, 0x23, 0x2b, 0x22, 0xe1, 0xcb, 0xe6, 0x10, 0x03, 0x46, 0x24, 0x00, 0xf9, + 0xdf, 0xfe, 0x27, 0x0b, 0x1e, 0xc0, 0x0e, 0x15, 0x06, 0xd3, 0x11, 0xd2, 0xd0, + 0x0d, 0xda, 0xda, 0x29, 0xc3, 0x0f, 0x5c, 0x13, 0x03, 0xf7, 0xd3, 0x14, 0xf7, + 0xf6, 0x12, 0x11, 0x13, 0x05, 0xda, 0xf3, 0xe6, 0xf0, 0xde, 0xc3, 0xcd, 0xd4, + 0xfc, 0xe5, 0xda, 0xe2, 0xe2, 0xe5, 0x1e, 0xfc, 0xfc, 0xf3, 0x08, 0xe4, 0xf2, + 0xec, 0x07, 0x01, 0xff, 0xec, 0xf5, 0x0a, 0x00, 0xe5, 0xe9, 0xe6, 0xf6, 0xfc, + 0xef, 0xe2, 0xde, 0xdd, 0xee, 0xfe, 0x06, 0xf0, 0xc2, 0xe4, 0x04, 0xf6, 0xe2, + 0x0f, 0xef, 0x09, 0xf0, 0x0b, 0xe4, 0xde, 0xde, 0x13, 0xe9, 0xd8, 0xd2, 0xf8, + 0xf6, 0xef, 0x12, 0x24, 0x7f, 0xf7, 0xc4, 0xf7, 0xd5, 0x1b, 0x02, 0x43, 0x07, + 0x04, 0x11, 0x05, 0xf9, 0x17, 0x1a, 0x4a, 0x01, 0x2d, 0xc1, 0xbf, 0xdb, 0xf7, + 0xf4, 0x05, 0x18, 0x27, 0xda, 0x22, 0x07, 0xec, 0xe5, 0x0c, 0x04, 0xb4, 0x01, + 0xba, 0xf4, 0xe8, 0x26, 0xf6, 0xee, 0xfa, 0x0e, 0xf9, 0xf6, 0xfc, 0xf8, 0xe0, + 0xd1, 0x0c, 0x08, 0xd8, 0xfa, 0x06, 0x17, 0xd8, 0x1b, 0xf9, 0x41, 0xec, 0x1f, + 0xd8, 0x04, 0xe9, 0x00, 0x35, 0xf8, 0x0f, 0x15, 0xc8, 0xf9, 0xd4, 0xfa, 0xdd, + 0x15, 0xdd, 0x0f, 0x33, 0x06, 0x19, 0xdc, 0xfd, 0xd3, 0xb3, 0xca, 0xbc, 0xfc, + 0x01, 0xb4, 0xed, 0xc6, 0x2f, 0xd8, 0x37, 0xe7, 0xe8, 0xf8, 0xeb, 0xe5, 0xde, + 0xd4, 0xe6, 0xde, 0xc3, 0xd8, 0xf4, 0xf0, 0x0c, 0xc0, 0x1c, 0xe8, 0xc0, 0x0d, + 0x16, 0x03, 0xf0, 0xd6, 0x19, 0x0c, 0xf6, 0x38, 0x3b, 0x1c, 0x0c, 0xfb, 0xa6, + 0xee, 0xdb, 0x10, 0xa1, 0x0b, 0x17, 0xe6, 0x19, 0x15, 0xb9, 0xfa, 0x03, 0xc5, + 0xf6, 0xe5, 0xe0, 0xdb, 0x4e, 0x05, 0x2e, 0xf9, 0xda, 0xf9, 0x1f, 0x26, 0xf6, + 0xcd, 0x28, 0x33, 0xee, 0x17, 0xb9, 0xe4, 0x29, 0x08, 0x16, 0xe5, 0x09, 0xca, + 0x18, 0xf5, 0xfe, 0x00, 0xfb, 0xe2, 0xef, 0x0f, 0x06, 0x19, 0xed, 0xf2, 0xf1, + 0xa6, 0x10, 0x57, 0xf1, 0xdc, 0xe2, 0x43, 0x2b, 0x24, 0xf0, 0xe7, 0x06, 0x11, + 0x23, 0xc8, 0x21, 0x0f, 0xf7, 0xd7, 0xf4, 0xd5, 0xca, 0xf5, 0xff, 0xf0, 0xf0, + 0xd2, 0xd9, 0x13, 0x0c, 0x15, 0x06, 0xdb, 0x09, 0xd1, 0x00, 0x37, 0x08, 0x0d, + 0xce, 0x16, 0xc4, 0xd5, 0xe4, 0xd9, 0xe9, 0x04, 0xaf, 0xc5, 0xde, 0xe4, 0x26, + 0xdd, 0x39, 0x08, 0xd6, 0xc9, 0x09, 0x1a, 0xe5, 0xc4, 0x3c, 0xfc, 0x2a, 0x1b, + 0xee, 0x0b, 0x0b, 0x9c, 0x2d, 0xcf, 0xad, 0xc5, 0x1e, 0xb5, 0xfa, 0x05, 0xe6, + 0x7f, 0xf2, 0xfa, 0x08, 0xd9, 0x0e, 0x03, 0x3c, 0xdf, 0xbb, 0x16, 0xe1, 0x42, + 0xfa, 0x11, 0x95, 0xb9, 0x3d, 0xbd, 0xe4, 0xd2, 0x01, 0xfe, 0xbc, 0xed, 0x0b, + 0xd3, 0x04, 0xc1, 0xd4, 0xf7, 0x2d, 0xe4, 0x08, 0xbe, 0xe5, 0x05, 0xea, 0xee, + 0xe5, 0x1a, 0xf0, 0x59, 0x03, 0xc8, 0xd6, 0x18, 0xe2, 0xe9, 0x07, 0x18, 0x1a, + 0x20, 0x24, 0xfc, 0x06, 0x1a, 0xfe, 0x03, 0xa1, 0xc7, 0xd5, 0xe3, 0x08, 0x06, + 0xf2, 0xcc, 0xb1, 0xef, 0xdf, 0x1e, 0xe3, 0x1e, 0xbb, 0xc5, 0xf1, 0x14, 0xe2, + 0xe2, 0x0e, 0x1a, 0x00, 0xb9, 0x09, 0xfe, 0xac, 0x13, 0x0e, 0xcc, 0xc6, 0xf5, + 0x34, 0xea, 0x2f, 0x5c, 0x19, 0xeb, 0x33, 0xbd, 0x9d, 0x12, 0x9a, 0x19, 0xa4, + 0xd7, 0xd3, 0xea, 0xd2, 0x1a, 0xde, 0x16, 0x1d, 0x18, 0xf0, 0x98, 0x40, 0xe9, + 0x00, 0xd8, 0xe0, 0x13, 0x03, 0x08, 0xe2, 0xf3, 0xcd, 0x1c, 0xe8, 0xcd, 0x38, + 0xfb, 0x34, 0x18, 0xf4, 0x12, 0x13, 0xfc, 0xc3, 0xf6, 0x0b, 0xfe, 0xd4, 0xee, + 0x10, 0xf8, 0xd6, 0x6f, 0x21, 0x05, 0xff, 0x07, 0xd6, 0xe0, 0x90, 0xf7, 0x2a, + 0x2b, 0xa2, 0xef, 0xdf, 0x0a, 0x06, 0x1b, 0x2a, 0x08, 0x4a, 0xc4, 0x11, 0xfa, + 0xf4, 0xae, 0x01, 0xb5, 0xf5, 0xf9, 0x26, 0x54, 0x0d, 0x43, 0x55, 0xc5, 0xe9, + 0xff, 0xe1, 0xc1, 0xf3, 0x22, 0x2b, 0xc4, 0x15, 0xe8, 0x57, 0xee, 0xfa, 0xeb, + 0xfc, 0xda, 0xd8, 0xc1, 0x0d, 0xf0, 0x1b, 0xfc, 0x0d, 0xd9, 0x2c, 0x3d, 0x12, + 0x1c, 0x1c, 0xd2, 0x3d, 0xfa, 0xf6, 0x1b, 0xf0, 0x0f, 0x40, 0x9b, 0xa7, 0xf9, + 0xb2, 0xe1, 0xf8, 0xf2, 0xf4, 0x14, 0xd6, 0xe7, 0x0f, 0xc9, 0x00, 0xe2, 0x08, + 0xdb, 0x7f, 0xb8, 0xe5, 0xe4, 0xab, 0x24, 0xfb, 0xee, 0xf5, 0xe3, 0x36, 0x2a, + 0xad, 0xfc, 0xf9, 0xbe, 0xe3, 0x01, 0xd3, 0xdb, 0xe1, 0x60, 0x0a, 0xbf, 0x0a, + 0xc0, 0xac, 0xe0, 0xd0, 0x41, 0xd6, 0x0b, 0xdc, 0x3e, 0x09, 0xf7, 0xc5, 0xe1, + 0xe6, 0xff, 0xe3, 0x22, 0xca, 0xdf, 0x24, 0xfa, 0x60, 0xe1, 0xb6, 0x97, 0xeb, + 0xe2, 0x2a, 0x39, 0x21, 0xc6, 0xdf, 0x3c, 0x1f, 0x3b, 0x16, 0xf9, 0x1f, 0x9a, + 0xda, 0xda, 0xbf, 0x4e, 0xd7, 0x03, 0x1f, 0xdd, 0xeb, 0x03, 0x33, 0x19, 0xed, + 0xfd, 0xe5, 0xcb, 0x14, 0xde, 0xf5, 0x17, 0x00, 0x59, 0xc3, 0xd7, 0xe7, 0xf0, + 0xb1, 0xce, 0x42, 0x35, 0xe5, 0xc0, 0xf1, 0x58, 0xf3, 0xd5, 0xe7, 0x13, 0xd6, + 0x0c, 0x24, 0x05, 0xcb, 0x00, 0xb6, 0xec, 0xff, 0x1e, 0x39, 0xf1, 0x1a, 0xb9, + 0xf8, 0x01, 0xff, 0xe2, 0x68, 0xde, 0x28, 0xcf, 0xcc, 0xe7, 0xd6, 0x0d, 0xa9, + 0x20, 0xf1, 0xe3, 0xeb, 0xec, 0xf0, 0xd2, 0x13, 0xf8, 0x08, 0x0c, 0xf2, 0xe5, + 0x1e, 0xc6, 0x06, 0x1f, 0xc0, 0xfd, 0xac, 0xfa, 0xb6, 0xf9, 0xff, 0xd1, 0xf0, + 0xe8, 0xbc, 0xed, 0x23, 0xa5, 0xd9, 0x0b, 0xfe, 0xf8, 0xac, 0x5c, 0xca, 0xd9, + 0xe0, 0xcf, 0x81, 0xf5, 0xfb, 0x26, 0x0b, 0x09, 0x10, 0x2d, 0x9b, 0x20, 0x01, + 0xfb, 0x0c, 0x09, 0x0d, 0xd0, 0x0c, 0x24, 0x11, 0x10, 0xb5, 0x07, 0xd3, 0xe4, + 0x17, 0x16, 0xd6, 0xdc, 0xfe, 0xcb, 0xb6, 0xc8, 0xf8, 0xde, 0xe8, 0x3c, 0xd9, + 0x47, 0xfd, 0xa0, 0x22, 0xd5, 0xde, 0xea, 0xc2, 0xea, 0xe7, 0x43, 0xde, 0x09, + 0xab, 0xd6, 0xcd, 0x1c, 0xf9, 0xc0, 0xcc, 0x03, 0xfe, 0x31, 0x18, 0x22, 0xe5, + 0xdc, 0xfb, 0xd8, 0xbb, 0xfa, 0x9d, 0x06, 0x32, 0x09, 0x0d, 0xaa, 0x1a, 0x01, + 0xbe, 0xd0, 0xcf, 0xea, 0x0e, 0x16, 0x21, 0x13, 0xef, 0xd4, 0xdc, 0x49, 0x0e, + 0xef, 0xd1, 0x1e, 0x13, 0x42, 0x2f, 0x28, 0xc9, 0xbe, 0xe5, 0x11, 0x3d, 0xf5, + 0xf0, 0xca, 0x16, 0x1c, 0xd8, 0x18, 0xfd, 0xd2, 0x19, 0xe3, 0xea, 0xbf, 0xdd, + 0xcb, 0x87, 0xff, 0x1e, 0xb7, 0xe6, 0x25, 0xcc, 0xe5, 0xf9, 0xe5, 0xe9, 0xac, + 0xfa, 0x50, 0xfa, 0xea, 0x04, 0x06, 0xa1, 0xc9, 0x07, 0x0b, 0xf3, 0xde, 0xa0, + 0xdd, 0xe8, 0x90, 0x96, 0x0b, 0xeb, 0x0d, 0x21, 0x07, 0x2f, 0x99, 0xeb, 0x9b, + 0x0a, 0x0d, 0xe4, 0xf8, 0x4e, 0xe2, 0xdf, 0x15, 0xe0, 0xe4, 0xd7, 0xc3, 0xf5, + 0xd9, 0x1e, 0xd3, 0x07, 0xfe, 0xd7, 0xf5, 0xcf, 0x29, 0x34, 0x20, 0x20, 0xd9, + 0xcd, 0x14, 0xfe, 0xe5, 0x2f, 0x1b, 0x08, 0x3f, 0x9d, 0xc4, 0x03, 0x04, 0x09, + 0xf5, 0xcb, 0xd2, 0xfa, 0xfa, 0xcf, 0x01, 0xc5, 0x07, 0x06, 0x03, 0xfa, 0xdd, + 0xc0, 0xda, 0xf1, 0xc6, 0xef, 0xf1, 0x14, 0xf6, 0xcd, 0x48, 0x9d, 0xb3, 0xb4, + 0xac, 0xff, 0xe6, 0xed, 0x04, 0xf3, 0xf8, 0xdd, 0xe7, 0x08, 0xe3, 0x37, 0xf5, + 0xd9, 0xfe, 0x08, 0xd8, 0x01, 0xf1, 0xc6, 0xd8, 0xd4, 0x38, 0x15, 0x1b, 0xe1, + 0x9c, 0x04, 0xe6, 0xe1, 0xfd, 0x03, 0xcd, 0x86, 0x0e, 0x0c, 0xe4, 0x81, 0x04, + 0xf4, 0xfc, 0xd7, 0x26, 0x37, 0x0a, 0xae, 0x0e, 0xe5, 0x33, 0xfa, 0xd8, 0xeb, + 0x01, 0xc0, 0x50, 0xf8, 0xf5, 0x24, 0x1e, 0x28, 0x06, 0xc3, 0x13, 0xf8, 0xae, + 0x03, 0xfb, 0xce, 0xbc, 0x2c, 0x17, 0x0a, 0xf3, 0xcf, 0xee, 0x1a, 0xb0, 0x1f, + 0xba, 0xbc, 0xee, 0xae, 0x00, 0x05, 0xbe, 0xd6, 0xf5, 0x12, 0xe8, 0xb5, 0x2c, + 0xd4, 0xf2, 0x20, 0x2a, 0xfd, 0x1b, 0x30, 0xf7, 0xaf, 0xc2, 0xde, 0xcb, 0x30, + 0x20, 0xdc, 0x0f, 0xfe, 0xeb, 0x1e, 0xca, 0xc7, 0xf3, 0x22, 0xce, 0xeb, 0xf1, + 0x14, 0xfb, 0xe5, 0xfe, 0xd4, 0xcd, 0xd5, 0xfb, 0xea, 0xc6, 0xd8, 0xde, 0xe3, + 0x33, 0x29, 0x61, 0x32, 0x1e, 0xfb, 0x2d, 0xcb, 0xc5, 0xef, 0x06, 0xe9, 0xeb, + 0x0d, 0x20, 0x38, 0xfb, 0xdc, 0xdd, 0xbd, 0xe7, 0xd3, 0xec, 0xcb, 0x5a, 0xe0, + 0x4e, 0x2f, 0x22, 0xc6, 0x06, 0xca, 0xe3, 0x09, 0x2c, 0x3d, 0x17, 0x08, 0xef, + 0xe6, 0xed, 0xd1, 0x33, 0x1f, 0x28, 0xd6, 0xb9, 0x88, 0xe9, 0x1b, 0xe5, 0xe1, + 0xd3, 0x6e, 0x0c, 0x09, 0xb9, 0x1e, 0xcc, 0xf1, 0x40, 0xce, 0x33, 0x0e, 0xff, + 0x2a, 0x18, 0x13, 0xf0, 0xe5, 0xa6, 0xd9, 0xe1, 0x2b, 0x11, 0xec, 0x1b, 0x23, + 0x0a, 0x18, 0xdf, 0x13, 0xfc, 0x41, 0xcc, 0x00, 0xc6, 0xf4, 0x25, 0xf3, 0x21, + 0x36, 0x04, 0x51, 0xfe, 0xbb, 0xf4, 0xf7, 0x05, 0x46, 0x0b, 0xea, 0x3d, 0xf6, + 0xaf, 0x03, 0x4b, 0xe8, 0x13, 0xf7, 0x14, 0x10, 0xf8, 0x08, 0xd0, 0xb7, 0x05, + 0xcd, 0x13, 0xda, 0x9f, 0xe8, 0x14, 0xc8, 0x02, 0x09, 0xc1, 0x2e, 0xa6, 0x07, + 0x13, 0xfd, 0xdd, 0xde, 0x43, 0x17, 0x45, 0xe4, 0xe5, 0xed, 0x1b, 0xfe, 0xf1, + 0xed, 0xf8, 0x15, 0x4d, 0x0d, 0x0e, 0x37, 0x1d, 0x09, 0xfc, 0xc5, 0xb8, 0xe9, + 0xf0, 0xef, 0xf7, 0x0a, 0x19, 0x22, 0x14, 0x11, 0x44, 0xd7, 0xe3, 0x03, 0xe6, + 0x26, 0x00, 0xb2, 0x0a, 0xe2, 0xec, 0xe4, 0x3e, 0x24, 0xe4, 0x30, 0xbe, 0x12, + 0xf4, 0x02, 0xfd, 0x1b, 0x05, 0xda, 0xde, 0x02, 0xe1, 0x33, 0xfb, 0x0f, 0xe0, + 0x03, 0x18, 0xed, 0xe6, 0xe1, 0x10, 0x2d, 0xc9, 0x19, 0xee, 0x13, 0x3b, 0xef, + 0xda, 0xe7, 0xb5, 0xc1, 0xdb, 0xee, 0xfa, 0x03, 0x2c, 0x57, 0xec, 0x02, 0x18, + 0xf3, 0xf2, 0xfe, 0x2d, 0xeb, 0x02, 0xf7, 0x1f, 0xeb, 0xef, 0x43, 0xe7, 0x2c, + 0x00, 0xa3, 0x2f, 0xf9, 0xd2, 0xec, 0xc6, 0xbe, 0x11, 0xc9, 0xce, 0xf2, 0xf2, + 0xe5, 0xf8, 0x24, 0x09, 0x25, 0x02, 0x30, 0x68, 0x2f, 0x1c, 0x1e, 0x10, 0xf9, + 0x10, 0xe5, 0xdf, 0xc2, 0xdf, 0xf3, 0x2d, 0xf5, 0xbf, 0xdd, 0x1d, 0x02, 0x06, + 0x03, 0xd1, 0x20, 0x2f, 0x2b, 0xeb, 0xda, 0x20, 0xe0, 0x40, 0x17, 0xe7, 0x47, + 0x0a, 0xf5, 0xe0, 0x1f, 0x00, 0x13, 0x23, 0x0c, 0x06, 0x46, 0xc7, 0xf7, 0x22, + 0x2b, 0xfa, 0xe5, 0x15, 0xf8, 0xe5, 0xe8, 0x43, 0x29, 0x07, 0x0d, 0xe5, 0xee, + 0x04, 0xfc, 0xd2, 0xae, 0x7f, 0xd0, 0x07, 0xe5, 0xfb, 0xf5, 0xe4, 0x1b, 0xfd, + 0xd6, 0xc3, 0xd2, 0xe4, 0xb9, 0xdc, 0xe1, 0xf4, 0x25, 0xf2, 0xf1, 0xcd, 0xee, + 0x16, 0x14, 0x01, 0x33, 0x33, 0x04, 0xf5, 0xd0, 0xfc, 0xf0, 0x1e, 0x10, 0xfc, + 0xda, 0x30, 0xe7, 0x06, 0xc5, 0xdc, 0xdd, 0xf2, 0x18, 0xe4, 0x6d, 0xe7, 0x19, + 0xe7, 0x04, 0xf7, 0x1f, 0xde, 0x0d, 0xd5, 0x0b, 0xc8, 0xbf, 0x00, 0x0e, 0xcb, + 0xff, 0xd4, 0x18, 0x9e, 0xcb, 0xf1, 0xf7, 0xed, 0xfc, 0x2f, 0x56, 0xcb, 0xec, + 0x4f, 0x1b, 0x2b, 0xcc, 0xee, 0xdc, 0x24, 0xdb, 0x1d, 0xbe, 0x32, 0xfc, 0x3d, + 0x61, 0xf4, 0xcc, 0x05, 0xe6, 0xf7, 0xc7, 0xfc, 0xd4, 0xf4, 0x91, 0xec, 0xeb, + 0x1f, 0xdd, 0xfa, 0x37, 0x0b, 0xba, 0xd9, 0x20, 0xca, 0x41, 0x5a, 0x31, 0x02, + 0xf4, 0x14, 0xae, 0x45, 0x0d, 0xf0, 0x1c, 0xb2, 0x03, 0xff, 0x17, 0xe6, 0x17, + 0xd8, 0xc2, 0xe9, 0xc3, 0xc0, 0x78, 0xcb, 0x0a, 0x40, 0xe9, 0x43, 0xbb, 0xe2, + 0xe0, 0x15, 0x2e, 0xd6, 0x21, 0xb0, 0xc6, 0xe0, 0xba, 0x20, 0x02, 0xe2, 0x00, + 0xcf, 0xce, 0xef, 0x1d, 0x35, 0x10, 0xf7, 0xd9, 0xd6, 0xed, 0xe6, 0x2a, 0x1e, + 0xe8, 0x1f, 0x0c, 0x19, 0xc5, 0x0e, 0xe9, 0x0f, 0xe0, 0x22, 0xb9, 0xc9, 0x03, + 0xf2, 0xe5, 0xde, 0xb8, 0xd0, 0xfb, 0xf9, 0xcf, 0x16, 0xf5, 0xf7, 0xe0, 0xe3, + 0x17, 0xf1, 0xe2, 0x50, 0x15, 0x3c, 0xec, 0xfb, 0xdb, 0xe7, 0x2d, 0xbc, 0xe6, + 0xbf, 0x19, 0xed, 0xe7, 0x61, 0xb8, 0x71, 0xd1, 0x08, 0x03, 0xdb, 0x05, 0x40, + 0x4c, 0x01, 0xf1, 0x09, 0xef, 0x3a, 0x02, 0x2a, 0x37, 0xc0, 0x55, 0xd1, 0x8c, + 0x14, 0x09, 0xfd, 0xea, 0x22, 0xee, 0x0b, 0x23, 0xec, 0xa9, 0x81, 0xff, 0xd3, + 0xf2, 0xe3, 0xcd, 0xc2, 0x09, 0x13, 0xdb, 0xbb, 0x0f, 0x16, 0x04, 0xa7, 0x15, + 0x4e, 0xe9, 0x16, 0xd2, 0xe4, 0xd2, 0xe2, 0xe2, 0x2c, 0xbc, 0x1b, 0xf6, 0xfc, + 0xd9, 0x60, 0x86, 0x1c, 0x29, 0xc4, 0x40, 0xe6, 0xf1, 0x25, 0xc9, 0x44, 0x20, + 0x2e, 0xd4, 0x05, 0xc8, 0x0b, 0x30, 0x1e, 0xda, 0xe7, 0xdc, 0xeb, 0xe3, 0xef, + 0xa9, 0xe0, 0x2f, 0xbc, 0xb7, 0xaf, 0x50, 0xd6, 0x59, 0xf5, 0xf0, 0x0c, 0x11, + 0xbb, 0xf8, 0xd1, 0x1c, 0x0b, 0xee, 0x28, 0xa3, 0x28, 0x21, 0xc1, 0xb9, 0xc0, + 0xe0, 0xed, 0xaa, 0xf0, 0xf9, 0xca, 0xc7, 0x0f, 0x07, 0xc4, 0x04, 0x36, 0xdf, + 0xeb, 0xf4, 0xf6, 0xde, 0xf9, 0x2a, 0x18, 0xed, 0xf0, 0x07, 0xed, 0x25, 0xdf, + 0x0f, 0xf5, 0x81, 0xd1, 0x13, 0x19, 0x15, 0xdc, 0xfe, 0xf7, 0xfe, 0x30, 0x1d, + 0xdb, 0x1f, 0x17, 0x3a, 0xeb, 0xf6, 0xd0, 0x37, 0x0c, 0xed, 0xd9, 0xb3, 0x26, + 0xfb, 0xd5, 0xfb, 0xb5, 0x07, 0xe9, 0xea, 0xe0, 0xe1, 0xc8, 0xe0, 0xd9, 0xe4, + 0xcf, 0xe2, 0xda, 0xe0, 0x04, 0xbe, 0xac, 0x1a, 0x02, 0xd6, 0x04, 0xe0, 0x18, + 0xd7, 0xff, 0x27, 0x0b, 0x24, 0x98, 0x2c, 0xfc, 0xd1, 0xd5, 0x48, 0xfb, 0x0b, + 0x02, 0xec, 0xd8, 0xfa, 0xe3, 0x9c, 0xf4, 0xfd, 0xcf, 0x5b, 0x11, 0xf2, 0xdc, + 0x03, 0xd7, 0xf9, 0xa7, 0x0d, 0xf7, 0xb8, 0xc3, 0x0f, 0xe7, 0x28, 0xa5, 0xee, + 0xf1, 0x10, 0x43, 0xde, 0x04, 0xe9, 0x10, 0x02, 0x00, 0xc7, 0x2a, 0x3d, 0xe4, + 0xac, 0xdb, 0x0a, 0xdb, 0xd8, 0xee, 0x21, 0x2c, 0x0e, 0x21, 0x2e, 0xdd, 0x30, + 0x1b, 0xde, 0x11, 0xe7, 0x46, 0xfc, 0x0f, 0x2e, 0xe8, 0x31, 0x59, 0x09, 0xe3, + 0xaa, 0x50, 0xd5, 0xd2, 0x1a, 0xfd, 0xfe, 0x29, 0xc4, 0xdc, 0xc7, 0xf5, 0xdb, + 0xa6, 0xdd, 0x25, 0xee, 0xf9, 0xb3, 0x12, 0xf9, 0xf4, 0x31, 0x13, 0x03, 0x20, + 0xff, 0xca, 0x01, 0xbe, 0xef, 0xca, 0xb9, 0xc9, 0xd4, 0x04, 0xb9, 0xd8, 0x25, + 0xb0, 0xf5, 0xbb, 0xa4, 0xd9, 0xc3, 0xfd, 0xa6, 0x16, 0x2f, 0xeb, 0xe2, 0x01, + 0x1f, 0x06, 0xf7, 0xe5, 0xbf, 0xcc, 0xbf, 0xf4, 0x0e, 0xf4, 0x25, 0x45, 0x1a, + 0xf8, 0x06, 0xd0, 0x18, 0xea, 0x03, 0xd3, 0x32, 0xf8, 0xe5, 0x24, 0x3e, 0x23, + 0xdb, 0xf2, 0xea, 0xd1, 0x04, 0x1b, 0x18, 0xe5, 0x06, 0x5f, 0xab, 0x34, 0xb9, + 0x42, 0xe8, 0xfc, 0x20, 0x20, 0x1e, 0x16, 0xed, 0x34, 0xdc, 0x27, 0x08, 0x0f, + 0xf3, 0xf2, 0xf6, 0xdd, 0xd9, 0x15, 0xd1, 0xd4, 0xb5, 0x00, 0xc4, 0xc9, 0xdb, + 0xc9, 0xd1, 0xfe, 0xdd, 0xa8, 0xe5, 0x2c, 0xcd, 0xce, 0x22, 0xdd, 0xf6, 0xe4, + 0x21, 0xda, 0x28, 0x0c, 0x93, 0xef, 0xf5, 0x4a, 0x31, 0x9e, 0xca, 0x2b, 0x13, + 0x02, 0xef, 0xeb, 0xca, 0x07, 0xc8, 0xe7, 0x5f, 0xfd, 0x7d, 0xef, 0x20, 0x45, + 0x20, 0xc6, 0x15, 0x8c, 0xd7, 0xf8, 0xcf, 0x13, 0xd2, 0x0d, 0x28, 0x46, 0x58, + 0xeb, 0x34, 0x59, 0x11, 0xb7, 0xc8, 0xe4, 0x47, 0x45, 0xf1, 0xf7, 0x34, 0x07, + 0xd3, 0x0f, 0x75, 0xdb, 0x34, 0xfb, 0xd2, 0xb7, 0x23, 0xe2, 0xf8, 0x40, 0xd6, + 0x11, 0x03, 0xd0, 0xe5, 0xac, 0xb5, 0xde, 0x36, 0x15, 0xf1, 0xd2, 0x36, 0xea, + 0xcd, 0x45, 0x59, 0xf6, 0x1e, 0xca, 0x0e, 0xf2, 0x2c, 0x25, 0xde, 0xd7, 0x66, + 0x33, 0x23, 0xd5, 0x9b, 0x1c, 0xd4, 0xab, 0x13, 0xea, 0x03, 0xb2, 0x59, 0x01, + 0x19, 0x08, 0x16, 0x64, 0xd3, 0x33, 0xd5, 0x95, 0xd5, 0x3c, 0xca, 0xdc, 0xe8, + 0x19, 0x08, 0xcb, 0xe1, 0x81, 0xdb, 0xe2, 0xde, 0x19, 0x12, 0xd6, 0x1f, 0xcf, + 0x14, 0xfb, 0xd8, 0x30, 0xf8, 0x0d, 0x3d, 0xdb, 0xbb, 0x14, 0xdc, 0x0e, 0xbe, + 0xf0, 0xe7, 0x12, 0x4d, 0xd2, 0x20, 0xb5, 0x4c, 0xb1, 0xd6, 0x4b, 0x95, 0xe1, + 0x0a, 0xa9, 0x06, 0x15, 0xf7, 0x8b, 0xb8, 0x06, 0xce, 0xc9, 0xe1, 0xdf, 0x8d, + 0x0b, 0xd4, 0xcc, 0xf8, 0xa2, 0xdb, 0x96, 0xfe, 0x45, 0x11, 0x28, 0xed, 0x1e, + 0x94, 0x07, 0x21, 0xe5, 0x2d, 0x2e, 0xc2, 0x0a, 0xf2, 0xf9, 0x0c, 0xe6, 0xe1, + 0x12, 0xd5, 0xd6, 0x4c, 0xe1, 0x30, 0x04, 0xda, 0xfb, 0x34, 0x11, 0x3d, 0xf7, + 0x02, 0xb2, 0x62, 0x13, 0xdf, 0xf5, 0x03, 0xea, 0x02, 0x89, 0xc5, 0x16, 0x1e, + 0x12, 0xd4, 0xe4, 0x20, 0xd9, 0xf1, 0xa7, 0x02, 0x51, 0xcd, 0xd9, 0xc9, 0x97, + 0x07, 0xe2, 0xab, 0xc5, 0x53, 0x45, 0xe5, 0xdf, 0xb2, 0xbc, 0xc9, 0xf5, 0x3f, + 0xae, 0xc4, 0x1f, 0xb8, 0x27, 0x05, 0xb6, 0xc4, 0xf8, 0x26, 0xd1, 0x01, 0x0e, + 0xc4, 0xfd, 0xa2, 0x05, 0x9e, 0xbf, 0x33, 0x21, 0xfa, 0xe9, 0x09, 0x07, 0x9c, + 0xf1, 0x20, 0xe2, 0x2e, 0xcb, 0xd8, 0x85, 0x1e, 0xea, 0x34, 0xf6, 0xcf, 0xd2, + 0x38, 0xf7, 0xd8, 0x2b, 0xea, 0xe9, 0x02, 0xc3, 0xc4, 0x93, 0x09, 0xa4, 0xf6, + 0x1c, 0xe2, 0xe7, 0xea, 0xbd, 0x2f, 0xfa, 0x16, 0xca, 0xcb, 0xe0, 0xc7, 0xf2, + 0x22, 0x43, 0xbe, 0x00, 0xb9, 0xf5, 0xf5, 0xf8, 0x05, 0x7d, 0x20, 0x19, 0xed, + 0xc6, 0x03, 0xf2, 0x32, 0x18, 0xc0, 0x1c, 0x93, 0x1c, 0x0f, 0x04, 0x27, 0x81, + 0xdc, 0xcf, 0xbb, 0x00, 0xda, 0xbb, 0xe6, 0xac, 0xe9, 0x36, 0x05, 0x12, 0xfd, + 0x1e, 0xf1, 0xb4, 0xa2, 0x33, 0x10, 0xbf, 0x1f, 0xe8, 0x18, 0xc9, 0x29, 0x07, + 0x0b, 0x2e, 0xfa, 0xa7, 0x02, 0xd8, 0xca, 0xf3, 0xf0, 0xe3, 0x1e, 0xfd, 0xd8, + 0xf0, 0xe5, 0x04, 0x9b, 0xec, 0x11, 0xe5, 0xfa, 0x0e, 0x93, 0xe6, 0xdb, 0x06, + 0xe8, 0xf1, 0xe3, 0x36, 0xd8, 0xe5, 0x0b, 0x02, 0xb4, 0xeb, 0x06, 0xdb, 0x0e, + 0xf0, 0xd9, 0xb6, 0xb9, 0xcc, 0xbe, 0x09, 0x42, 0x13, 0xfd, 0x3e, 0x08, 0xf2, + 0xf1, 0x8f, 0xb2, 0xe7, 0xd1, 0xa4, 0xd8, 0x35, 0xf5, 0xef, 0xf7, 0xc9, 0xef, + 0x95, 0xc2, 0x03, 0xf0, 0xce, 0x2b, 0x20, 0xed, 0x2d, 0xfe, 0xe5, 0x4f, 0xb2, + 0xd0, 0xd9, 0xdc, 0x06, 0xe7, 0x0c, 0x22, 0x08, 0xf0, 0x2d, 0xf4, 0xbd, 0x23, + 0x24, 0x4b, 0xec, 0xe0, 0xde, 0xeb, 0xf2, 0x24, 0xcd, 0xf8, 0x23, 0xfa, 0x13, + 0xf8, 0xeb, 0x49, 0x06, 0xed, 0xca, 0xde, 0xb3, 0x65, 0x3c, 0xe1, 0x27, 0xf7, + 0x32, 0xd0, 0x21, 0x8b, 0x20, 0xec, 0xf4, 0x2e, 0xf3, 0xf6, 0x02, 0xc4, 0x23, + 0x06, 0x2d, 0x3a, 0xdc, 0x1e, 0xcd, 0x0c, 0xeb, 0xa6, 0xf9, 0xe1, 0x12, 0x2a, + 0x37, 0x57, 0x0b, 0xdc, 0xa2, 0xc4, 0x01, 0xbc, 0x4b, 0x45, 0x3d, 0x4f, 0x0a, + 0x5b, 0x26, 0x40, 0x33, 0x3a, 0x95, 0xa6, 0xda, 0x5f, 0xd6, 0xd9, 0xe3, 0xe5, + 0x37, 0xbe, 0xe4, 0x00, 0xe5, 0xba, 0x07, 0x53, 0x1d, 0x27, 0x1d, 0x0b, 0x38, + 0xcf, 0xc4, 0xf5, 0x21, 0x4e, 0xf2, 0x52, 0xdf, 0xf2, 0xc2, 0xf1, 0x14, 0x17, + 0xba, 0xb3, 0x95, 0x00, 0xee, 0xd2, 0xd6, 0x1f, 0x18, 0x03, 0x88, 0x25, 0xdb, + 0xf5, 0x13, 0x00, 0x2e, 0x04, 0xb3, 0x1e, 0xee, 0xd1, 0x12, 0x17, 0xd8, 0x2d, + 0xbf, 0xfe, 0x37, 0xf1, 0xe5, 0x1b, 0xeb, 0xe4, 0xe4, 0x59, 0xf7, 0x7b, 0x0d, + 0xd9, 0x9a, 0x18, 0x22, 0xdb, 0xb8, 0xf1, 0xe4, 0x32, 0xd8, 0xdd, 0xc0, 0xf5, + 0xef, 0xc6, 0x44, 0xca, 0x02, 0x4a, 0xf0, 0x11, 0x0e, 0x90, 0xf8, 0xf5, 0x08, + 0xfe, 0xad, 0xd5, 0x17, 0xe6, 0xd0, 0x8b, 0x65, 0xf9, 0xde, 0xfc, 0x32, 0x0f, + 0xc1, 0xd0, 0xb6, 0xd6, 0x21, 0x12, 0x13, 0xcc, 0xeb, 0x10, 0x2a, 0x4e, 0xd6, + 0x4c, 0x18, 0xbc, 0xe3, 0x2a, 0x06, 0xbe, 0xe8, 0xbb, 0x0c, 0xfe, 0xef, 0xc0, + 0xf4, 0xc0, 0xdc, 0x36, 0x14, 0x35, 0x10, 0x7f, 0xf2, 0x13, 0x15, 0xe1, 0x33, + 0x26, 0xd7, 0xf2, 0x30, 0xfd, 0xe0, 0x61, 0xd5, 0xc0, 0xea, 0x35, 0xb9, 0x9d, + 0x3f, 0x15, 0x14, 0xe7, 0xd6, 0xc1, 0x08, 0xc2, 0xd7, 0xeb, 0xd5, 0xe1, 0x2a, + 0xfe, 0xab, 0xf8, 0xee, 0xf8, 0x06, 0x24, 0xe8, 0x27, 0x0c, 0x26, 0x08, 0x0f, + 0xaf, 0x04, 0xbe, 0xf3, 0xe2, 0xdd, 0xdd, 0x58, 0xc8, 0x33, 0xf1, 0xeb, 0x1a, + 0xbc, 0x4c, 0xd9, 0xc7, 0xf7, 0xd0, 0xfb, 0xc6, 0xcf, 0x2d, 0xf9, 0xe4, 0xe9, + 0xe2, 0x40, 0xf3, 0x3e, 0xe6, 0xe5, 0x19, 0xda, 0x1c, 0x05, 0x00, 0xf7, 0xba, + 0x08, 0xf7, 0xd4, 0xd4, 0x5b, 0xf1, 0x25, 0xca, 0x0a, 0xd5, 0x00, 0xe6, 0xe9, + 0x13, 0x00, 0xa5, 0x38, 0xf8, 0xe1, 0x1c, 0xe0, 0x02, 0x42, 0x6a, 0xce, 0x08, + 0xe2, 0x30, 0x33, 0xf9, 0xdd, 0xe2, 0xcf, 0xf0, 0x51, 0x22, 0x0e, 0x29, 0x62, + 0xb8, 0xcb, 0x14, 0xd1, 0x98, 0xff, 0xd0, 0xb7, 0xc0, 0xdc, 0x0b, 0xfb, 0x52, + 0x47, 0xf8, 0x05, 0xe3, 0xd5, 0x19, 0x14, 0xf1, 0xeb, 0x04, 0x2f, 0xc7, 0x58, + 0xc6, 0xc3, 0xb7, 0xeb, 0xa0, 0x22, 0xd2, 0xe7, 0xb0, 0xe7, 0x0f, 0xfb, 0xbb, + 0x15, 0x29, 0xc9, 0xd5, 0x00, 0xf0, 0x16, 0xeb, 0xfe, 0x37, 0xdd, 0xf1, 0xc8, + 0xee, 0xdb, 0xfc, 0xe0, 0xbe, 0xfa, 0x05, 0xf3, 0xf8, 0xe0, 0x13, 0xf6, 0xd6, + 0x19, 0x30, 0xd0, 0xe9, 0x33, 0xd3, 0xe3, 0xb9, 0xc4, 0x45, 0xf5, 0xa5, 0x55, + 0xfe, 0xca, 0x02, 0xc2, 0x10, 0xd4, 0x15, 0x1e, 0xe0, 0xe6, 0x07, 0xed, 0x73, + 0x06, 0xf5, 0x1d, 0xda, 0x81, 0xd9, 0xfb, 0xfe, 0xf9, 0x16, 0x28, 0xde, 0x10, + 0xf0, 0xce, 0xf8, 0x2e, 0xe2, 0x34, 0x2d, 0x1c, 0x0a, 0xf4, 0x29, 0x1d, 0xe6, + 0x98, 0xc6, 0xb8, 0x38, 0x14, 0x11, 0xe7, 0xf9, 0x01, 0x2a, 0xee, 0x5e, 0xf9, + 0xfd, 0xf7, 0xc8, 0xfe, 0xf0, 0xbf, 0x2f, 0x9d, 0xc0, 0x1b, 0xd7, 0x1f, 0xd1, + 0xd7, 0xa3, 0xa9, 0x14, 0xdd, 0xe7, 0xe4, 0x03, 0x28, 0x52, 0x34, 0x1f, 0xbc, + 0xdd, 0xfb, 0x26, 0xc3, 0xef, 0x22, 0x4f, 0x24, 0xb3, 0xaf, 0x04, 0x01, 0x04, + 0x08, 0x22, 0xce, 0xf0, 0x24, 0x3d, 0xc0, 0xa1, 0x06, 0x01, 0x16, 0x18, 0x5a, + 0xdb, 0x42, 0x10, 0xc9, 0xf3, 0xf5, 0xfb, 0xfc, 0x00, 0x0c, 0xff, 0x05, 0xf0, + 0x1e, 0xdd, 0xd4, 0x53, 0xca, 0x09, 0xf7, 0x1c, 0xb1, 0x18, 0xbc, 0x13, 0x1b, + 0x02, 0x14, 0x52, 0x24, 0xf7, 0x36, 0xb4, 0x15, 0xde, 0x1d, 0xfe, 0xf7, 0x40, + 0xe9, 0xd4, 0x25, 0x47, 0x13, 0x39, 0x46, 0x37, 0xb0, 0xfc, 0x34, 0xf1, 0x0d, + 0x04, 0x1e, 0x77, 0xcd, 0x34, 0xbe, 0x03, 0xf1, 0x1a, 0x1f, 0xc3, 0xdc, 0x96, + 0xf2, 0x21, 0xef, 0x9f, 0xe6, 0xf9, 0xfd, 0x26, 0xf8, 0x07, 0xc9, 0xf2, 0xe3, + 0xbe, 0xb7, 0x27, 0xb8, 0x39, 0xfc, 0x50, 0x16, 0xe6, 0xd8, 0xf2, 0xcc, 0xb0, + 0x48, 0x26, 0xcc, 0xf7, 0xd5, 0x4f, 0xe4, 0xc5, 0x03, 0x1b, 0xfa, 0xa1, 0xd6, + 0x09, 0x1e, 0x0e, 0xfd, 0xb4, 0x1a, 0xce, 0xce, 0x0a, 0x37, 0x12, 0xce, 0xd9, + 0xd2, 0xfc, 0x30, 0xaf, 0x05, 0x19, 0x1c, 0x46, 0xdc, 0xc9, 0x3c, 0x13, 0xed, + 0x05, 0xe6, 0x08, 0x7f, 0x56, 0xc7, 0xeb, 0x98, 0x05, 0x3e, 0xf8, 0xe9, 0x32, + 0xfd, 0xb8, 0x31, 0xd7, 0xe9, 0x18, 0x1f, 0x2f, 0xf3, 0xc5, 0xe7, 0x07, 0xc7, + 0x2e, 0x8a, 0x12, 0xd9, 0x2e, 0xf7, 0x14, 0x36, 0xe5, 0x10, 0x37, 0xd0, 0x0b, + 0xe0, 0xb6, 0xfc, 0xd7, 0x07, 0xad, 0xe6, 0x05, 0xf0, 0xcc, 0x1f, 0xe7, 0x4d, + 0xef, 0x17, 0xe0, 0xee, 0xef, 0xe9, 0xa6, 0x13, 0xc9, 0xaf, 0xf6, 0x21, 0xce, + 0x2e, 0x30, 0x1a, 0xba, 0xfb, 0x57, 0x01, 0x8c, 0xe0, 0x13, 0x09, 0x20, 0xe1, + 0x3b, 0xfb, 0xec, 0xf7, 0x27, 0xe8, 0x16, 0xc1, 0xe7, 0x0f, 0xb2, 0xd8, 0x16, + 0x0f, 0x3d, 0xe6, 0x49, 0xe4, 0x0c, 0x3a, 0x0e, 0xcf, 0x34, 0xf4, 0x2c, 0xf8, + 0xdd, 0x08, 0xd5, 0xf6, 0xf0, 0xdc, 0xfa, 0xe5, 0x17, 0xce, 0x4f, 0xb6, 0xdc, + 0x36, 0xde, 0x20, 0x32, 0xe4, 0xc0, 0x0d, 0x39, 0xf6, 0xf3, 0x0d, 0x14, 0xf9, + 0x0b, 0x2d, 0x5d, 0x42, 0xd1, 0x45, 0x14, 0xc7, 0x0c, 0xae, 0xeb, 0xbb, 0x32, + 0x0b, 0x04, 0xf5, 0x9c, 0xf2, 0xef, 0xc0, 0x4b, 0xf1, 0xb3, 0x2e, 0x13, 0x35, + 0xf4, 0xf3, 0x12, 0xfc, 0xcd, 0xed, 0xf4, 0xac, 0xd1, 0x04, 0xe9, 0xa9, 0x07, + 0xda, 0x50, 0xc7, 0xd4, 0x1e, 0xe8, 0xeb, 0x1e, 0x08, 0x4c, 0xe7, 0x57, 0xec, + 0xff, 0x04, 0xd6, 0x15, 0xcc, 0x56, 0x00, 0x0b, 0xeb, 0xe5, 0x50, 0x09, 0x16, + 0xf2, 0xd9, 0xdc, 0xf0, 0xee, 0x37, 0x26, 0x06, 0x0c, 0x20, 0xec, 0x1c, 0x0f, + 0x3c, 0xdc, 0xe6, 0x25, 0xdb, 0x04, 0x0d, 0x1c, 0x43, 0xf3, 0x23, 0x1b, 0x3a, + 0x11, 0x25, 0x02, 0xa6, 0x07, 0x06, 0xfb, 0xc9, 0xed, 0x59, 0x05, 0x1c, 0x03, + 0xde, 0x03, 0x45, 0x0d, 0xd0, 0x01, 0x33, 0x22, 0x0c, 0xfb, 0xc2, 0xf1, 0xd8, + 0xc3, 0xf0, 0x4b, 0xc3, 0x05, 0x20, 0x41, 0xcf, 0xde, 0xd7, 0x17, 0x12, 0x34, + 0xff, 0xfb, 0xe2, 0x10, 0xeb, 0xdb, 0xcd, 0x07, 0xdb, 0xed, 0xd9, 0x1e, 0x4a, + 0x2b, 0xf4, 0xab, 0xfd, 0x31, 0x04, 0xed, 0x02, 0x1c, 0xc5, 0x7e, 0xde, 0xb9, + 0x16, 0xb1, 0x05, 0x0a, 0xf2, 0xc6, 0x20, 0x1b, 0x14, 0xce, 0x4d, 0xe7, 0xf2, + 0x1b, 0xe0, 0xf8, 0x03, 0x15, 0x07, 0x19, 0x14, 0xfb, 0xeb, 0xb9, 0xbc, 0x25, + 0x0c, 0xd1, 0xfc, 0xe4, 0x34, 0xd0, 0x81, 0x0c, 0xe7, 0x07, 0x04, 0xd3, 0x34, + 0xe2, 0xc1, 0xdc, 0xd7, 0xd6, 0xe3, 0x34, 0x9d, 0xd9, 0xbc, 0x26, 0xb0, 0xbb, + 0x25, 0xdd, 0xe6, 0xdb, 0xf2, 0xe7, 0x00, 0x23, 0x06, 0x4c, 0xd9, 0x04, 0xc9, + 0x3b, 0x19, 0x0c, 0x06, 0x23, 0x1e, 0xf7, 0xe8, 0xf1, 0x32, 0x34, 0xe3, 0xd2, + 0xe5, 0xf5, 0x24, 0xf3, 0x31, 0x18, 0xef, 0xf4, 0x10, 0x0d, 0xc3, 0xed, 0x0d, + 0x3d, 0x0d, 0xfb, 0xc0, 0xda, 0x2a, 0xde, 0xee, 0x2d, 0x15, 0xfc, 0x03, 0xef, + 0x01, 0xe0, 0x2c, 0xee, 0xe4, 0x4b, 0x35, 0xcb, 0x2d, 0x1f, 0xb8, 0xdd, 0xc8, + 0xdc, 0x24, 0xdd, 0x16, 0x02, 0xd0, 0xe1, 0xd1, 0xbf, 0xea, 0x35, 0xe6, 0x8d, + 0x1b, 0xef, 0x5e, 0x0e, 0xd0, 0xe0, 0x16, 0x66, 0x18, 0x81, 0xce, 0x2c, 0x30, + 0xbd, 0xc9, 0x1a, 0x44, 0x0c, 0xfd, 0xdc, 0x04, 0xc4, 0xfa, 0xfd, 0x1b, 0x2f, + 0x04, 0xee, 0x0c, 0x0d, 0x04, 0xd4, 0x21, 0x2b, 0xd7, 0xb5, 0x33, 0x11, 0xc7, + 0xe2, 0xb2, 0x03, 0xf7, 0x00, 0x05, 0xd8, 0x5f, 0xb2, 0x27, 0x81, 0xdb, 0xa8, + 0xe5, 0xdf, 0x32, 0xf3, 0xb8, 0x13, 0xf7, 0xf2, 0xf3, 0x0f, 0x24, 0xb3, 0x1e, + 0x2e, 0xc0, 0xdc, 0xdf, 0xff, 0x36, 0x89, 0x3e, 0x30, 0xf5, 0xe2, 0x21, 0xf0, + 0x2b, 0x19, 0x10, 0xfa, 0x05, 0x3a, 0x06, 0xff, 0x1c, 0xb4, 0xff, 0xcd, 0xd9, + 0xe6, 0xf1, 0x37, 0x04, 0x19, 0xfe, 0xf2, 0xfa, 0xfb, 0x5a, 0x9d, 0xd3, 0x1e, + 0xa7, 0xb0, 0x27, 0xb0, 0xd9, 0x47, 0x3b, 0xfb, 0xf6, 0xcc, 0xf8, 0xd5, 0xdc, + 0xd9, 0xc2, 0xee, 0xc0, 0x0d, 0xf7, 0xd9, 0xc7, 0x1f, 0xd5, 0xee, 0xfd, 0xe4, + 0xea, 0x01, 0xef, 0x23, 0xfa, 0xee, 0xcf, 0xee, 0xab, 0xbb, 0x1a, 0x21, 0xdf, + 0x3f, 0x06, 0xd3, 0xd8, 0xf8, 0x2f, 0x99, 0xad, 0x06, 0xb8, 0xd7, 0x0b, 0x23, + 0x19, 0x1a, 0xc5, 0x28, 0xa5, 0x54, 0x4a, 0x14, 0x53, 0x9a, 0xd2, 0x12, 0xda, + 0x13, 0x3b, 0xf2, 0x2d, 0x0c, 0xca, 0x13, 0xe7, 0xd2, 0x07, 0xe8, 0xde, 0xb1, + 0x43, 0xcd, 0x37, 0xd6, 0xfe, 0xe9, 0xf7, 0xc0, 0x56, 0xfe, 0xc6, 0xdd, 0xf9, + 0x0b, 0xd8, 0x12, 0xe6, 0x02, 0x2b, 0x8c, 0x41, 0xb1, 0xd6, 0xaf, 0xf9, 0x26, + 0xd5, 0xc9, 0xff, 0xd8, 0x37, 0xcc, 0xf4, 0x03, 0x22, 0x40, 0x08, 0xcb, 0xcd, + 0xb1, 0xb6, 0x1c, 0xe4, 0xe1, 0xaf, 0xf8, 0xf8, 0xc2, 0xd5, 0xec, 0x29, 0xf1, + 0xe3, 0x27, 0xef, 0xf9, 0xc7, 0x08, 0x1f, 0xf0, 0xb3, 0x0a, 0x28, 0x4a, 0xea, + 0xb9, 0x08, 0x13, 0xff, 0x03, 0x52, 0x1c, 0xfb, 0x0a, 0xec, 0x02, 0x05, 0xcb, + 0x0c, 0xe0, 0x08, 0xf2, 0xf3, 0xd6, 0xe1, 0x2e, 0xf8, 0xc6, 0x0a, 0xf7, 0xc3, + 0x4a, 0x2f, 0xdd, 0x0a, 0xef, 0x1b, 0xfd, 0x10, 0xd7, 0xd1, 0xcb, 0x11, 0xfa, + 0x41, 0xc4, 0xdc, 0xf3, 0xfb, 0x3a, 0xee, 0xde, 0x12, 0x22, 0xef, 0x04, 0x24, + 0xb7, 0xd5, 0xe1, 0x07, 0x10, 0x1f, 0xb2, 0xc4, 0xd5, 0xc0, 0x30, 0xdf, 0xe9, + 0x28, 0x14, 0xe1, 0x02, 0x24, 0x27, 0x08, 0x25, 0x2f, 0x23, 0x05, 0x24, 0x00, + 0x26, 0xac, 0xb8, 0x02, 0xd5, 0x3d, 0xf0, 0x35, 0xd8, 0xe9, 0xeb, 0x6d, 0xe1, + 0xee, 0xf5, 0xfa, 0x4c, 0x27, 0x0d, 0x1d, 0xf2, 0xfb, 0xd6, 0x17, 0xf1, 0x1d, + 0xc9, 0x1a, 0x08, 0x30, 0x29, 0x17, 0xda, 0x18, 0x28, 0xea, 0x12, 0xf2, 0xf7, + 0x10, 0x3f, 0xe2, 0xe2, 0xe7, 0xfc, 0xcf, 0x1d, 0x1a, 0x07, 0xe3, 0x0e, 0xd8, + 0x1a, 0xde, 0x11, 0xf9, 0x0d, 0xa7, 0x1e, 0x37, 0x04, 0x4e, 0xcb, 0xe9, 0x28, + 0xee, 0xc5, 0xd4, 0xe9, 0xe6, 0x16, 0x16, 0x0e, 0xe8, 0x51, 0x07, 0xe6, 0xf5, + 0x00, 0xbd, 0xce, 0xc7, 0xb8, 0xed, 0x0b, 0xe2, 0x0e, 0xc0, 0x1a, 0xfc, 0xc4, + 0xc1, 0x0f, 0xe9, 0x0d, 0xcc, 0xd3, 0x28, 0x0c, 0x7f, 0xb2, 0x00, 0x22, 0xcb, + 0xe1, 0x26, 0xdb, 0x14, 0xec, 0x11, 0x27, 0x06, 0xb4, 0xff, 0xbf, 0x0b, 0x27, + 0xcb, 0xf5, 0xf8, 0x02, 0x23, 0x06, 0xc7, 0xcb, 0xfa, 0xef, 0x9a, 0x03, 0x13, + 0xce, 0x04, 0x09, 0x13, 0xe5, 0x24, 0x2a, 0x32, 0x10, 0xb8, 0xeb, 0xff, 0xe2, + 0x24, 0x14, 0xfb, 0xa5, 0xfe, 0x26, 0xc7, 0x9c, 0xe2, 0x6e, 0xd6, 0xe5, 0xd1, + 0x1d, 0xee, 0xd1, 0xf2, 0x02, 0xa7, 0x81, 0x7b, 0xe1, 0x13, 0x20, 0x1d, 0xc7, + 0x2f, 0xcf, 0x9a, 0x4f, 0xb3, 0x53, 0xc7, 0xcb, 0x05, 0x77, 0xc2, 0xa3, 0x67, + 0x98, 0x32, 0xc4, 0xe4, 0x19, 0xf6, 0x46, 0x39, 0x8d, 0xc1, 0x26, 0x37, 0xc2, + 0xf2, 0x53, 0xc6, 0x1f, 0x74, 0xf2, 0x0f, 0xc0, 0x5e, 0xf5, 0xcd, 0x49, 0x01, + 0x13, 0xfa, 0xd3, 0xe4, 0xce, 0xd8, 0xea, 0x1e, 0x21, 0xd2, 0xf9, 0x07, 0xaa, + 0x16, 0x2d, 0x25, 0xe7, 0x47, 0x0e, 0x0f, 0x24, 0xb3, 0xd6, 0xc4, 0x4b, 0x61, + 0xc4, 0xf4, 0xda, 0x06, 0xca, 0xc8, 0x15, 0x3d, 0x40, 0xfd, 0x1b, 0xdc, 0x9b, + 0x20, 0x07, 0xfc, 0x37, 0xc9, 0xc0, 0xa2, 0x95, 0xad, 0x41, 0x36, 0xd9, 0xac, + 0xfe, 0x13, 0xe5, 0x45, 0x2b, 0x1e, 0xec, 0x4c, 0x33, 0xdd, 0xf3, 0xd7, 0x1f, + 0xde, 0xf2, 0x2e, 0xf1, 0x12, 0xc3, 0xdf, 0xcf, 0x01, 0xda, 0xbd, 0xc5, 0x1a, + 0x29, 0x1b, 0x33, 0xec, 0xc3, 0xd7, 0xbe, 0x52, 0xe3, 0x25, 0x35, 0x16, 0x0a, + 0x3f, 0xae, 0x31, 0xd1, 0xef, 0xc5, 0xb7, 0xfa, 0x2e, 0x15, 0xbf, 0x3c, 0xb7, + 0x10, 0xba, 0xdc, 0x4a, 0x52, 0x68, 0x15, 0x50, 0x53, 0x2d, 0x95, 0x04, 0x0a, + 0x1f, 0x67, 0x2d, 0xbd, 0x28, 0xc6, 0xe9, 0x1d, 0xf1, 0xf8, 0xf2, 0xfd, 0x2c, + 0xec, 0xbf, 0x2d, 0xd4, 0xde, 0xdb, 0x5f, 0xdf, 0xff, 0xea, 0x15, 0xe6, 0xd6, + 0x15, 0x07, 0xf3, 0xed, 0xf1, 0xe4, 0xf0, 0x37, 0xd7, 0x90, 0xb8, 0xd3, 0x4a, + 0xd6, 0x14, 0x3b, 0xea, 0xf9, 0x32, 0x07, 0xe0, 0x15, 0x10, 0x2a, 0x16, 0xbb, + 0x10, 0xc8, 0x08, 0xca, 0x11, 0xfb, 0xb2, 0x17, 0xf1, 0x13, 0x18, 0xfe, 0xc9, + 0xe5, 0xa5, 0x2b, 0x05, 0x07, 0xef, 0x07, 0x13, 0xcd, 0x4e, 0xdc, 0x32, 0xef, + 0x1f, 0x24, 0x0d, 0x37, 0xfc, 0xf2, 0xbe, 0xea, 0xfa, 0x27, 0xa7, 0xd4, 0xe9, + 0xc8, 0x01, 0x0c, 0xf0, 0xc9, 0xeb, 0xcf, 0x51, 0x26, 0xd9, 0x0f, 0xfc, 0xcf, + 0xf2, 0x16, 0x0a, 0x0c, 0x1a, 0xe9, 0xef, 0x48, 0xf0, 0x56, 0xf0, 0xd8, 0xb2, + 0xfa, 0xa6, 0x2c, 0xb9, 0xb1, 0x15, 0x00, 0xd3, 0xf7, 0xf8, 0x27, 0xe3, 0xfd, + 0x1d, 0xff, 0xb6, 0x40, 0xef, 0x2a, 0xca, 0xdd, 0x02, 0x98, 0x12, 0x34, 0x1a, + 0x30, 0xcb, 0xf9, 0x3a, 0xd8, 0x30, 0xfb, 0x97, 0x2d, 0xb0, 0x1a, 0xa4, 0xc1, + 0xcc, 0x0c, 0xf0, 0x1b, 0x3e, 0xf1, 0x05, 0xff, 0xdb, 0x11, 0xac, 0xcd, 0xad, + 0x05, 0x0c, 0x0b, 0xf5, 0x12, 0x15, 0xf9, 0x32, 0xf0, 0xbc, 0xa9, 0x32, 0x0d, + 0xe9, 0xfc, 0xcc, 0xeb, 0x36, 0x7a, 0xf6, 0xc4, 0xff, 0xff, 0x24, 0xb2, 0xcc, + 0x47, 0xd5, 0x04, 0xe1, 0x7f, 0x21, 0xea, 0x16, 0xe2, 0x3e, 0x22, 0xcb, 0xf4, + 0xc9, 0x32, 0x36, 0xf4, 0xe8, 0x54, 0x34, 0x22, 0x3f, 0x26, 0xe2, 0xc4, 0xf8, + 0xcd, 0x29, 0xdc, 0x0f, 0xc8, 0xec, 0xc5, 0x29, 0x66, 0xe1, 0xf5, 0x54, 0xd0, + 0x00, 0x2a, 0xe2, 0x99, 0xc6, 0x11, 0xf8, 0x28, 0xf5, 0xdc, 0x2f, 0x06, 0x06, + 0x1c, 0x12, 0xd8, 0x3e, 0xba, 0xd9, 0x2f, 0x4c, 0xb6, 0x0d, 0x00, 0x25, 0x38, + 0x31, 0xe2, 0xdc, 0xd9, 0x3d, 0x65, 0x00, 0x40, 0x2f, 0xd2, 0x5d, 0xb4, 0xd7, + 0x45, 0x2b, 0x51, 0x39, 0x03, 0xf6, 0x2a, 0x06, 0x98, 0x07, 0xf5, 0x0f, 0xf5, + 0x69, 0x31, 0x2a, 0x06, 0x01, 0x38, 0xc3, 0xe0, 0xf9, 0x07, 0xfa, 0xd7, 0x15, + 0x10, 0x20, 0xf2, 0xf0, 0xc8, 0x02, 0xf2, 0x59, 0xd7, 0xcb, 0x10, 0xf9, 0x2a, + 0x1a, 0x09, 0xfc, 0xce, 0x2c, 0xe9, 0xc3, 0xd4, 0xe0, 0xb6, 0x02, 0xe4, 0xdb, + 0x29, 0xff, 0xc0, 0x3e, 0xc2, 0xfd, 0xf4, 0xeb, 0xfa, 0xf9, 0x11, 0x3b, 0x06, + 0xb6, 0x2c, 0x1d, 0xa9, 0x0c, 0xe0, 0x25, 0x00, 0xf0, 0xef, 0x29, 0xdd, 0xe1, + 0xdc, 0x17, 0xda, 0xf9, 0xe9, 0x3d, 0xff, 0x0a, 0xbe, 0xe4, 0x1e, 0x03, 0xd8, + 0x3e, 0x21, 0xb8, 0x01, 0x41, 0x0c, 0xb8, 0xe7, 0x42, 0x82, 0x28, 0x2a, 0xd4, + 0xe4, 0xee, 0xe1, 0xd4, 0x3e, 0xc5, 0xd5, 0xca, 0x41, 0x34, 0xdb, 0x20, 0x05, + 0x1b, 0x3b, 0x20, 0xd4, 0x1d, 0xa4, 0xe4, 0x00, 0xac, 0x67, 0xc5, 0xe4, 0x35, + 0x36, 0x04, 0x37, 0x13, 0xf0, 0xcc, 0xbb, 0xd5, 0xe2, 0x42, 0xac, 0x16, 0xfd, + 0xca, 0xfe, 0xc8, 0x42, 0x38, 0x29, 0x3a, 0xb5, 0xbc, 0xd6, 0x9a, 0x34, 0x08, + 0xd7, 0x9a, 0x36, 0x2e, 0x0e, 0x33, 0xb8, 0xfc, 0xda, 0x94, 0x06, 0xb7, 0xaa, + 0x33, 0xf2, 0xec, 0x9d, 0x10, 0xb7, 0x29, 0xc4, 0x73, 0x26, 0x4c, 0x09, 0x79, + 0x01, 0xfd, 0x34, 0xe3, 0xdd, 0xe5, 0x9f, 0xd2, 0x1d, 0x25, 0xa3, 0xfe, 0xf7, + 0xf2, 0x16, 0xf4, 0x33, 0x23, 0xf3, 0xca, 0x0d, 0x20, 0xe5, 0x37, 0xf2, 0xe6, + 0x38, 0x39, 0xf4, 0xf7, 0xf2, 0x53, 0xfe, 0xd5, 0xe9, 0x33, 0x17, 0xdb, 0x06, + 0xf4, 0xe9, 0xec, 0xca, 0x83, 0xb4, 0xf8, 0x15, 0x4f, 0x7a, 0xea, 0x0f, 0xfc, + 0xe5, 0x95, 0x36, 0x37, 0xe1, 0xf4, 0x51, 0xde, 0x0d, 0x04, 0x27, 0x3e, 0x32, + 0x10, 0xf2, 0xf1, 0xa1, 0xa8, 0x1f, 0xe4, 0x15, 0xee, 0xd7, 0x2b, 0xd0, 0xdd, + 0xd9, 0xdc, 0x08, 0xe6, 0xc2, 0xe8, 0xae, 0xe9, 0xd0, 0x04, 0xc3, 0xeb, 0x32, + 0x8f, 0x02, 0xa4, 0x2f, 0x97, 0xed, 0xd0, 0x00, 0xc1, 0xdd, 0x00, 0xf5, 0x1e, + 0x34, 0xed, 0x22, 0xfd, 0x0e, 0xe2, 0x48, 0x81, 0x15, 0x42, 0x3e, 0xe0, 0x59, + 0xe6, 0xf7, 0x5f, 0xe5, 0xcf, 0xaf, 0x3f, 0xfb, 0xfc, 0x17, 0x34, 0x1d, 0xe4, + 0x06, 0xb6, 0xe9, 0x20, 0xeb, 0xbc, 0xe5, 0xdb, 0xbd, 0xc4, 0x3f, 0xce, 0xe6, + 0x88, 0x20, 0xd3, 0xf3, 0xcf, 0x1c, 0xba, 0xe9, 0x13, 0xd3, 0xc3, 0xfd, 0xf1, + 0xdd, 0x53, 0xe6, 0x43, 0xf7, 0xaa, 0xdd, 0xde, 0xf9, 0xfb, 0xe6, 0xd9, 0xc3, + 0x16, 0xb1, 0xdd, 0xe3, 0x11, 0x36, 0xf4, 0xf9, 0xb7, 0xbd, 0xaa, 0x2f, 0xa0, + 0xd8, 0xfc, 0x1e, 0xb7, 0x47, 0x00, 0x32, 0x10, 0x16, 0xf4, 0x6e, 0x16, 0xce, + 0xde, 0x00, 0xea, 0xdf, 0x25, 0x32, 0xfa, 0x2e, 0x57, 0x2b, 0x0d, 0xb2, 0xde, + 0xf6, 0xd6, 0x4b, 0xe4, 0x22, 0xe5, 0x11, 0xd8, 0xdd, 0xcc, 0xd3, 0xc2, 0xc7, + 0x30, 0xc8, 0x22, 0xac, 0xe5, 0xd5, 0xf8, 0xf7, 0xf9, 0x24, 0xab, 0x24, 0xdc, + 0x15, 0xf2, 0xb3, 0x02, 0x19, 0xfa, 0x31, 0xc5, 0xd1, 0xf3, 0xea, 0xd6, 0xca, + 0x05, 0xe8, 0xdf, 0xe4, 0x09, 0x1a, 0xd4, 0xe4, 0x7f, 0x49, 0xb3, 0xdf, 0xaa, + 0xf2, 0x07, 0xdb, 0x16, 0x21, 0x21, 0x1e, 0xfb, 0xd9, 0xda, 0x0b, 0x15, 0xab, + 0x1d, 0xf7, 0x33, 0x37, 0xe3, 0x07, 0xd3, 0xe6, 0xb3, 0xf1, 0x19, 0xfe, 0xf0, + 0xd3, 0xba, 0xff, 0xe1, 0xfd, 0xcc, 0x26, 0xdd, 0x3c, 0x31, 0xef, 0xd8, 0xbe, + 0x36, 0xf3, 0xd5, 0xd5, 0xe8, 0xf5, 0x09, 0x28, 0x43, 0x1b, 0x10, 0xbd, 0x9a, + 0xdb, 0x2c, 0xdf, 0xc5, 0xe0, 0xc7, 0x1f, 0xda, 0x00, 0xd1, 0x0b, 0xba, 0xfd, + 0x0c, 0x2f, 0xc0, 0xf5, 0xf1, 0x09, 0xef, 0x06, 0x1c, 0xee, 0xfa, 0xf9, 0xf5, + 0xea, 0x9a, 0xec, 0x30, 0xf6, 0x0c, 0xbe, 0xe4, 0x06, 0xed, 0x62, 0xa9, 0xd2, + 0xc8, 0xf0, 0xfb, 0x4a, 0xf9, 0xee, 0x4d, 0xca, 0xd0, 0xdf, 0x04, 0xf5, 0x06, + 0x17, 0x3e, 0x69, 0x0b, 0x3d, 0x46, 0x9f, 0xef, 0x05, 0xb3, 0xe6, 0xc9, 0xaa, + 0x19, 0xd9, 0x1d, 0xc8, 0x0d, 0x0e, 0xd0, 0x56, 0x2a, 0xef, 0x3b, 0x6a, 0x45, + 0xad, 0x9b, 0x0d, 0xcb, 0x39, 0xd5, 0x2b, 0xf2, 0xe9, 0x20, 0xfc, 0x19, 0xd9, + 0xb7, 0xd6, 0xf0, 0xd4, 0x0a, 0xfc, 0x14, 0x11, 0xfe, 0xdb, 0x02, 0x0b, 0x11, + 0x01, 0xea, 0xa8, 0x15, 0xc9, 0x9f, 0xf0, 0xdf, 0xdf, 0xdb, 0x06, 0xee, 0xda, + 0xe1, 0xf9, 0xc2, 0x13, 0xff, 0x1b, 0x27, 0xe8, 0xf7, 0xe2, 0xf2, 0xc0, 0x13, + 0xb3, 0xf7, 0xd5, 0xdb, 0x41, 0xf4, 0xd6, 0xe5, 0xf9, 0xa2, 0xf3, 0x1a, 0x61, + 0xd6, 0x18, 0xf2, 0xf7, 0x05, 0xec, 0xdf, 0xe1, 0x44, 0xe6, 0x1d, 0x2e, 0xdf, + 0x1a, 0x42, 0xf3, 0xe0, 0x11, 0x02, 0xf0, 0xec, 0x55, 0xef, 0x01, 0xe9, 0xcd, + 0xfc, 0x0a, 0x28, 0x32, 0x38, 0x28, 0x4e, 0x57, 0x13, 0xd5, 0xf2, 0xd2, 0xda, + 0x00, 0xe6, 0x28, 0x03, 0xf3, 0xbd, 0x4c, 0x54, 0xd6, 0x01, 0xf9, 0x2e, 0x54, + 0xde, 0x25, 0x05, 0xe3, 0xbc, 0x0e, 0xa7, 0xa6, 0xd2, 0xf2, 0xc8, 0x0a, 0xcc, + 0xf1, 0xd8, 0x0f, 0x07, 0xf2, 0xf6, 0x4b, 0xf5, 0xb6, 0x08, 0xd4, 0xf9, 0x23, + 0xd4, 0xc6, 0x11, 0xd3, 0x78, 0x06, 0x3a, 0x03, 0xfc, 0x25, 0xee, 0x2b, 0xd0, + 0x27, 0x37, 0x04, 0x4c, 0xc7, 0xe2, 0xe9, 0xc3, 0xd3, 0xd4, 0xf0, 0xed, 0xe4, + 0x12, 0x45, 0xdb, 0x01, 0xf1, 0xf7, 0xd3, 0x43, 0x04, 0x3c, 0x1c, 0xfd, 0x40, + 0x10, 0x84, 0x4e, 0xe4, 0x1b, 0x03, 0x15, 0xae, 0xde, 0x05, 0xfb, 0x00, 0x26, + 0xd5, 0xc3, 0x20, 0x32, 0x21, 0xf1, 0xd9, 0xb2, 0x23, 0xf8, 0xf8, 0xf7, 0xe7, + 0x2b, 0xf4, 0xc8, 0xfe, 0x78, 0x22, 0x72, 0xdc, 0xf0, 0x2d, 0x1d, 0xc1, 0x22, + 0x10, 0x60, 0x45, 0x45, 0xc1, 0x60, 0xcc, 0x81, 0x16, 0xd3, 0xc6, 0xcd, 0xfe, + 0xc7, 0xcd, 0x07, 0xe8, 0xbf, 0xfb, 0xfb, 0xd5, 0x0b, 0x1f, 0xeb, 0x1c, 0x24, + 0xef, 0x19, 0xde, 0xc6, 0xbf, 0x00, 0xc9, 0x08, 0x11, 0xed, 0xf0, 0xf8, 0xf3, + 0xd3, 0x2f, 0xe9, 0xe8, 0xc0, 0xdf, 0xf4, 0x30, 0xe6, 0x1d, 0xff, 0xe6, 0xed, + 0x2d, 0xb2, 0xb9, 0xfd, 0xd0, 0x95, 0x2b, 0xd2, 0x38, 0x1f, 0xc2, 0x0f, 0x14, + 0xb8, 0x09, 0x07, 0xff, 0x02, 0xe7, 0xe2, 0xcc, 0x29, 0x12, 0xf1, 0x09, 0x01, + 0xc4, 0x01, 0xb7, 0xd6, 0xc5, 0xdf, 0xd8, 0xff, 0x12, 0x14, 0x1f, 0xb9, 0x1b, + 0x1b, 0x53, 0xc4, 0x02, 0xee, 0xd9, 0xcf, 0xeb, 0xc2, 0xd9, 0x0a, 0x35, 0x09, + 0xf2, 0x0e, 0x04, 0x65, 0xee, 0xad, 0x10, 0x05, 0x2c, 0x14, 0x19, 0xf3, 0x12, + 0xb7, 0x1e, 0x24, 0xe7, 0xc9, 0x24, 0xec, 0xf7, 0x24, 0x07, 0x2d, 0xce, 0x3c, + 0xf0, 0xef, 0x1b, 0xe6, 0x05, 0xb0, 0xf7, 0xe9, 0x13, 0xdb, 0xea, 0xdb, 0xff, + 0x06, 0xd8, 0x25, 0x2c, 0xc5, 0x03, 0xe0, 0xec, 0xef, 0x02, 0x04, 0xdd, 0xd7, + 0x02, 0xd3, 0xed, 0x0b, 0x1e, 0x01, 0xe7, 0xdf, 0xcb, 0xf9, 0xba, 0x02, 0xde, + 0x3b, 0x14, 0xee, 0x28, 0x2f, 0xf6, 0x1b, 0x0b, 0x20, 0x30, 0xfe, 0xf8, 0xed, + 0x1b, 0x04, 0x02, 0xef, 0xc3, 0xf5, 0x06, 0xe3, 0xe8, 0xe8, 0x24, 0x19, 0x1a, + 0xc7, 0x0c, 0x83, 0xe1, 0x7f, 0xe3, 0xc4, 0xf0, 0x00, 0xfc, 0xff, 0xfa, 0x0a, + 0xf9, 0xf7, 0x12, 0x09, 0x2f, 0xf1, 0xef, 0x6b, 0xd0, 0x1c, 0x3a, 0x02, 0xc1, + 0xde, 0x05, 0x23, 0xe8, 0xf2, 0xc9, 0xf2, 0xf0, 0x30, 0xf8, 0x02, 0xae, 0xac, + 0xcc, 0xc9, 0x20, 0x02, 0x14, 0xec, 0xd9, 0xb3, 0xf7, 0xcb, 0x03, 0x09, 0xd3, + 0x13, 0x93, 0xe0, 0xa5, 0xf1, 0xe2, 0xe1, 0xe1, 0x02, 0xd0, 0xeb, 0x05, 0x1e, + 0xdb, 0xc0, 0xf7, 0x3f, 0x2e, 0xbc, 0xfb, 0x33, 0xf7, 0x1f, 0x48, 0x11, 0x18, + 0x2a, 0x31, 0x3a, 0x01, 0x2f, 0xd6, 0xce, 0x05, 0xfd, 0xc2, 0x40, 0xf5, 0xef, + 0x06, 0x9d, 0x1a, 0xe2, 0xae, 0xe4, 0x0a, 0xb7, 0xd3, 0x07, 0x33, 0x01, 0x16, + 0x0d, 0xeb, 0xe7, 0xfc, 0x09, 0xda, 0xd9, 0xc5, 0x01, 0xfa, 0xce, 0xf3, 0xe2, + 0xd5, 0xe7, 0xc1, 0xdc, 0x1f, 0x1d, 0xc3, 0xfa, 0xc0, 0xe8, 0xf4, 0xe3, 0xba, + 0xe5, 0xe5, 0x06, 0x06, 0x3b, 0xff, 0x18, 0xac, 0xdc, 0x25, 0xd5, 0xe3, 0x32, + 0xc3, 0xb8, 0x13, 0x28, 0xed, 0x1f, 0xc9, 0xf2, 0xe7, 0x0a, 0xfa, 0xbc, 0x66, + 0xfa, 0xf6, 0xeb, 0xfa, 0xca, 0xe0, 0x17, 0x1d, 0xf7, 0x11, 0xfc, 0xf6, 0xd4, + 0x08, 0xde, 0xe6, 0x38, 0x0d, 0x25, 0xa9, 0xd9, 0xe0, 0x2f, 0x0b, 0xd0, 0x08, + 0xd6, 0xfa, 0x1f, 0x3e, 0xcf, 0xed, 0xfd, 0xaf, 0xb7, 0xc0, 0xf6, 0xf3, 0x0f, + 0x44, 0x8b, 0xd8, 0xf3, 0xc8, 0xf4, 0x1e, 0xf2, 0xe3, 0x97, 0xac, 0x0c, 0x15, + 0xee, 0x16, 0xed, 0xef, 0xe5, 0x15, 0xdb, 0x4c, 0xad, 0xdc, 0x20, 0xbe, 0xcb, + 0xf2, 0xb7, 0x00, 0x1f, 0xd7, 0xc2, 0x0e, 0xb1, 0x2a, 0x24, 0xdb, 0x2f, 0xd6, + 0x09, 0xe7, 0xe5, 0xf5, 0x36, 0x2d, 0xc0, 0xea, 0x38, 0x28, 0x15, 0x0a, 0xb5, + 0x26, 0x05, 0x05, 0x8b, 0xef, 0xf8, 0x1d, 0xfb, 0xdb, 0xef, 0x08, 0xec, 0x29, + 0xe5, 0x0c, 0x56, 0xbf, 0xf7, 0xfd, 0x08, 0xf6, 0x50, 0xed, 0x00, 0x0b, 0xc9, + 0xe0, 0x0f, 0xf2, 0xdc, 0xef, 0x1c, 0xb0, 0xe6, 0xc6, 0x00, 0x1e, 0xbf, 0x44, + 0xe4, 0xed, 0x07, 0x09, 0xfa, 0x01, 0xfd, 0xf6, 0x25, 0xe1, 0xdf, 0x72, 0xbb, + 0xfb, 0xb5, 0xe9, 0xb8, 0xbb, 0xb6, 0x7f, 0xdd, 0xe6, 0x0a, 0xda, 0x72, 0xd2, + 0x18, 0xc4, 0xc2, 0x03, 0x12, 0x09, 0xee, 0x16, 0x8b, 0x15, 0x11, 0x16, 0xfe, + 0xe7, 0xef, 0x26, 0x32, 0xdd, 0x08, 0xf9, 0x08, 0x2a, 0xb3, 0xd9, 0x5f, 0xe4, + 0x0f, 0xe6, 0xbc, 0x41, 0x1b, 0x02, 0xd9, 0xf0, 0x00, 0x45, 0xed, 0xe6, 0x16, + 0xc5, 0x12, 0x20, 0xf9, 0x08, 0x19, 0x2b, 0xd1, 0x02, 0xda, 0xf6, 0x1a, 0xff, + 0x08, 0x03, 0xdb, 0xed, 0xf9, 0xc9, 0x1b, 0xe3, 0x13, 0x17, 0x13, 0x3b, 0x2d, + 0x1d, 0xe5, 0xfb, 0xfd, 0xef, 0x28, 0x06, 0xc8, 0xc2, 0xd3, 0xcc, 0xaa, 0xd6, + 0xf8, 0xf8, 0x37, 0xf0, 0xf5, 0xd9, 0xf4, 0xf7, 0x10, 0xc7, 0xd4, 0xef, 0x02, + 0xe7, 0xf6, 0xda, 0xf8, 0xeb, 0x21, 0xc3, 0x37, 0x02, 0xbf, 0x03, 0xc7, 0xd9, + 0xd7, 0x0a, 0xfd, 0x30, 0x2b, 0x0d, 0x28, 0x18, 0x03, 0xd0, 0xcb, 0xbb, 0x36, + 0xe4, 0xed, 0xba, 0x2d, 0xf8, 0x14, 0x13, 0xaa, 0xbf, 0x22, 0xe8, 0xea, 0x11, + 0x12, 0xe6, 0xcc, 0x0b, 0xef, 0x9b, 0x15, 0xbd, 0xfa, 0xd5, 0xf2, 0xef, 0xd9, + 0xef, 0x1a, 0xec, 0x31, 0xc2, 0xd0, 0xd8, 0xf1, 0xcf, 0x2f, 0xdf, 0xf8, 0xdc, + 0xbc, 0xb8, 0xde, 0xe2, 0xfa, 0x3c, 0xf7, 0xc5, 0xcd, 0xfc, 0x0b, 0x14, 0x1e, + 0xff, 0x01, 0xfe, 0xfc, 0xe0, 0xdf, 0x07, 0x0a, 0xda, 0xf4, 0xea, 0x0e, 0xfd, + 0x3e, 0xf0, 0xce, 0x9d, 0xe5, 0xdf, 0x23, 0xc7, 0xf5, 0xec, 0x0e, 0xec, 0xea, + 0x19, 0x31, 0xb2, 0x2d, 0xfe, 0xd6, 0xe9, 0x0a, 0x00, 0xe5, 0x7f, 0x15, 0xc3, + 0xd7, 0xc7, 0xb9, 0x03, 0xf5, 0xd6, 0x30, 0xfe, 0xd1, 0x07, 0xb8, 0x4e, 0xc6, + 0xf3, 0xfe, 0xd6, 0xf8, 0x0f, 0x2f, 0xf2, 0xf0, 0x2b, 0x07, 0xe5, 0xe1, 0xd5, + 0xf7, 0xf0, 0x1b, 0xd7, 0x21, 0x42, 0xc0, 0x40, 0x13, 0xb3, 0xd1, 0xd9, 0x43, + 0x0e, 0x04, 0xfd, 0x32, 0xd6, 0x18, 0x09, 0x11, 0xda, 0x21, 0x94, 0xe3, 0xf5, + 0x16, 0xb2, 0xe0, 0xf9, 0x93, 0xf9, 0xcd, 0xfb, 0x0d, 0xc9, 0xef, 0xfa, 0x04, + 0x2c, 0x06, 0x07, 0xdd, 0x42, 0xcc, 0x15, 0x11, 0xca, 0x18, 0x2e, 0xf2, 0x4d, + 0x19, 0x1b, 0x44, 0x33, 0x30, 0xf8, 0x03, 0xd9, 0x2f, 0xdb, 0x37, 0xdb, 0x06, + 0x16, 0x0b, 0xcc, 0x09, 0xba, 0xd4, 0x6e, 0xee, 0xe8, 0x05, 0xcc, 0x21, 0xe8, + 0xec, 0xd8, 0xc5, 0xf6, 0xb0, 0x18, 0xb1, 0x24, 0xfa, 0x22, 0xc4, 0x02, 0x3a, + 0x2a, 0x26, 0xa3, 0xf8, 0x26, 0xb7, 0x07, 0xee, 0x03, 0x0d, 0x10, 0xe2, 0x38, + 0x02, 0xf9, 0xdf, 0x2e, 0x3c, 0xae, 0x37, 0x19, 0xd8, 0x00, 0x20, 0xd3, 0xdb, + 0xe0, 0x38, 0x04, 0x4b, 0x01, 0x3a, 0x60, 0xe7, 0xe2, 0xd7, 0xc4, 0xf5, 0xb8, + 0x35, 0x25, 0xc9, 0x57, 0xf3, 0x3b, 0x3b, 0xd4, 0x23, 0xd3, 0x0d, 0x09, 0x00, + 0xec, 0x00, 0x63, 0xec, 0x2e, 0x21, 0x1e, 0x81, 0xed, 0xd2, 0xc5, 0x12, 0xf9, + 0x2f, 0xf6, 0x04, 0xd6, 0xf5, 0x29, 0x0b, 0xcc, 0x09, 0x90, 0x32, 0xc8, 0x27, + 0xf6, 0xd7, 0xe6, 0xe2, 0xee, 0x1c, 0x2f, 0x0e, 0xfe, 0x03, 0xbf, 0xbb, 0x1d, + 0x27, 0x6c, 0x25, 0x10, 0x27, 0xee, 0x59, 0xc5, 0xd1, 0xd1, 0x2a, 0x50, 0xd0, + 0xe6, 0xd9, 0x33, 0xd1, 0xed, 0x1c, 0xe2, 0xea, 0x57, 0x14, 0xe3, 0xe8, 0x08, + 0x00, 0x52, 0xe8, 0x06, 0xdf, 0xb6, 0xee, 0xe0, 0x3d, 0x04, 0xdc, 0xf2, 0x0a, + 0x0a, 0xd8, 0xb9, 0xfd, 0x9a, 0xe3, 0x0a, 0x19, 0x0f, 0x1b, 0xf5, 0xd2, 0xc6, + 0x13, 0xff, 0xee, 0xb7, 0x25, 0x0e, 0x46, 0xfc, 0xe4, 0xe5, 0xdc, 0xf2, 0xd2, + 0x51, 0x2a, 0xf8, 0xf3, 0xc8, 0xc2, 0xe8, 0xe4, 0x53, 0x43, 0x15, 0x30, 0xd6, + 0x43, 0xf7, 0xd4, 0x24, 0xfa, 0x18, 0xe1, 0x23, 0xc3, 0xb5, 0x2e, 0x65, 0x4c, + 0x2a, 0x01, 0xf1, 0xce, 0xd0, 0x92, 0xab, 0xbf, 0xc5, 0x30, 0xe2, 0xa8, 0xe7, + 0x0d, 0x26, 0xba, 0x09, 0x0a, 0x4c, 0x03, 0xf9, 0xab, 0x1c, 0x05, 0x33, 0x0f, + 0x90, 0x32, 0x0d, 0xe1, 0x10, 0xa1, 0x47, 0xbf, 0x0b, 0xc5, 0xe0, 0x22, 0xd2, + 0xe7, 0xd3, 0xf1, 0xdc, 0x02, 0x25, 0x13, 0xc9, 0xf5, 0x89, 0xb2, 0x87, 0x06, + 0xce, 0xed, 0xa9, 0xd8, 0x45, 0x21, 0x20, 0xd2, 0xec, 0xfe, 0xcf, 0x2d, 0xa7, + 0xfb, 0x1a, 0x25, 0xb8, 0xe0, 0x08, 0xbb, 0xed, 0x0d, 0x1d, 0xf4, 0x91, 0xb7, + 0x55, 0xe8, 0xe6, 0x1a, 0xf9, 0x36, 0xb0, 0xba, 0xe0, 0x3b, 0xd2, 0x3b, 0xfd, + 0x03, 0xce, 0x51, 0x29, 0xf5, 0xd7, 0x30, 0x32, 0x19, 0xa2, 0xee, 0xf7, 0x5e, + 0x39, 0x25, 0xda, 0xd7, 0x26, 0x1e, 0xf0, 0x0b, 0xf5, 0xdb, 0xd9, 0x16, 0xbf, + 0x3d, 0xf9, 0xc4, 0xaa, 0xdc, 0x1f, 0x35, 0x06, 0x09, 0xca, 0xad, 0xf1, 0xdf, + 0xd6, 0x27, 0x13, 0xa2, 0xe3, 0x0c, 0xe1, 0x3c, 0x1f, 0xd3, 0x27, 0xcb, 0xf7, + 0x36, 0xef, 0x02, 0xdb, 0x0d, 0x07, 0x1b, 0xcb, 0xf1, 0xd6, 0x0c, 0x34, 0xe3, + 0xd4, 0x02, 0xf6, 0x21, 0xcd, 0xcb, 0xfd, 0xc5, 0x04, 0xda, 0x13, 0xa0, 0xa9, + 0x13, 0xca, 0x1c, 0x23, 0x23, 0x27, 0xe5, 0x5a, 0xd1, 0xef, 0x43, 0x04, 0xd3, + 0xe6, 0x45, 0xf3, 0x44, 0xbb, 0x00, 0xf1, 0x39, 0xcc, 0xba, 0xf8, 0x1d, 0x06, + 0x30, 0xf6, 0xd0, 0xb2, 0x0c, 0xdc, 0xdf, 0x1d, 0xd0, 0x45, 0xb2, 0xde, 0xe0, + 0x00, 0xd5, 0x7f, 0xfe, 0xe5, 0x1e, 0x58, 0x2e, 0x01, 0xf1, 0x1d, 0xd5, 0xeb, + 0xc6, 0x09, 0x0f, 0x14, 0xd5, 0x12, 0xe8, 0xb8, 0xda, 0x1b, 0xd5, 0x1f, 0xe7, + 0x39, 0xda, 0xd3, 0x18, 0xf6, 0xfb, 0x1f, 0x11, 0xfe, 0xff, 0x67, 0xdc, 0xe0, + 0x41, 0xf4, 0xe8, 0xe8, 0xf2, 0xed, 0x27, 0xdc, 0xa9, 0xf1, 0xc3, 0x9a, 0xb5, + 0xd7, 0xe3, 0xf5, 0xfb, 0x28, 0xb9, 0xf5, 0xd7, 0x12, 0x25, 0xd7, 0xe5, 0xf6, + 0x4c, 0x29, 0xfd, 0xdc, 0xc3, 0xe6, 0x3c, 0x12, 0x09, 0xe9, 0xfe, 0xf8, 0x05, + 0x4f, 0xbb, 0x25, 0x02, 0xd8, 0xb3, 0xd6, 0xbe, 0x1e, 0xd6, 0xdb, 0xf2, 0xe7, + 0x23, 0x04, 0x13, 0xe7, 0x09, 0x3a, 0xfa, 0xa8, 0x1e, 0xf9, 0x0b, 0x2e, 0xdb, + 0xc1, 0xe0, 0x06, 0xb5, 0xc3, 0x01, 0xf7, 0x34, 0xe6, 0xb9, 0x01, 0xf1, 0x02, + 0xe2, 0x13, 0xc7, 0x05, 0x08, 0x02, 0x4c, 0x54, 0x1d, 0xf6, 0x04, 0x25, 0x29, + 0xb1, 0xe6, 0xe9, 0xd9, 0x06, 0x26, 0xe9, 0xed, 0xfc, 0xdf, 0x2a, 0xb2, 0x0a, + 0xc9, 0x1c, 0x2a, 0xf9, 0x17, 0xf3, 0x08, 0xe9, 0xff, 0xe8, 0xba, 0x17, 0x08, + 0x09, 0xea, 0x1f, 0x07, 0xf3, 0x13, 0xea, 0xe4, 0xd7, 0x29, 0xf3, 0xe8, 0xce, + 0xf6, 0x16, 0xda, 0xfb, 0x07, 0xb7, 0x08, 0xd3, 0xe4, 0x36, 0xc7, 0xc4, 0x34, + 0x23, 0x36, 0x00, 0xe8, 0xf4, 0xbd, 0xfa, 0xf7, 0x98, 0xdd, 0xe9, 0xf9, 0x2b, + 0xb2, 0x37, 0xfe, 0xcd, 0x0b, 0x0f, 0xe8, 0x03, 0xb2, 0xdb, 0x15, 0xb7, 0xf7, + 0xc6, 0xeb, 0xf9, 0xc5, 0xf3, 0xe2, 0x23, 0x35, 0xb9, 0xb6, 0xcc, 0xfd, 0xb0, + 0x18, 0xb9, 0x1e, 0xf2, 0xf2, 0xeb, 0xe8, 0x33, 0xde, 0x02, 0xe1, 0x1e, 0xce, + 0x30, 0xfb, 0x7f, 0xec, 0xfd, 0xb4, 0x0b, 0x15, 0x1a, 0x59, 0xe6, 0xe1, 0xe3, + 0x25, 0x01, 0x07, 0x3c, 0x15, 0xae, 0xf5, 0xe9, 0x35, 0x19, 0xe8, 0xfe, 0x06, + 0x0f, 0x27, 0x0e, 0xdc, 0x17, 0x1c, 0x37, 0xaa, 0x3c, 0xe7, 0x37, 0x07, 0x18, + 0xc3, 0xc8, 0xf1, 0x53, 0xcc, 0xdc, 0xb3, 0xe0, 0xe2, 0x2d, 0xe9, 0xe4, 0xdd, + 0xf7, 0x13, 0x27, 0xc9, 0x52, 0x03, 0x0a, 0x9f, 0x06, 0x2e, 0x40, 0xf0, 0x03, + 0x22, 0x46, 0xf3, 0x0d, 0xb4, 0xfb, 0xf7, 0xd1, 0xbd, 0xd8, 0x11, 0xf8, 0xc5, + 0xcd, 0xfa, 0xf8, 0xc6, 0xbe, 0xb5, 0xc9, 0x27, 0xbb, 0xb6, 0xfe, 0x0b, 0x95, + 0xd1, 0xbf, 0xb2, 0xc4, 0x0b, 0xc8, 0x3d, 0x15, 0x2d, 0x04, 0x2e, 0xe9, 0xfd, + 0xd3, 0xc1, 0xfa, 0xe6, 0x17, 0x03, 0xc8, 0xc0, 0xeb, 0x14, 0xb3, 0x13, 0x19, + 0xda, 0x1e, 0x09, 0xa8, 0xd0, 0xf3, 0xc9, 0x23, 0xbf, 0x3f, 0xf2, 0xac, 0x26, + 0xfc, 0x17, 0xbd, 0xf9, 0xf8, 0x32, 0xe6, 0x4b, 0xd9, 0xc4, 0x58, 0xff, 0xe5, + 0xe0, 0xec, 0x19, 0xe7, 0xff, 0xf1, 0x0f, 0x99, 0xe8, 0x1c, 0xe9, 0x1c, 0x4d, + 0x27, 0xe7, 0xbd, 0xdb, 0x0b, 0x49, 0x3b, 0xf6, 0x11, 0x1a, 0x20, 0xe2, 0x0a, + 0xc8, 0xc1, 0xcf, 0xe7, 0x0a, 0x20, 0xc9, 0x9e, 0xe3, 0xe3, 0x55, 0xcc, 0x00, + 0x15, 0xfb, 0x4d, 0xc4, 0x1c, 0xfe, 0x93, 0xaa, 0xe3, 0x0e, 0xce, 0xdc, 0x1a, + 0x57, 0x16, 0x2c, 0x15, 0x45, 0xd0, 0x17, 0x17, 0xe8, 0xe6, 0x4b, 0xc4, 0x36, + 0xf7, 0x51, 0x0a, 0x32, 0x07, 0x28, 0xcb, 0xba, 0xe2, 0xea, 0x09, 0x08, 0xe1, + 0x1d, 0x41, 0xb9, 0x14, 0x7b, 0xc1, 0xd4, 0x06, 0xfd, 0x07, 0x3c, 0x11, 0x4a, + 0xf1, 0xe2, 0x29, 0xf9, 0xf1, 0xb7, 0xe3, 0x1e, 0xf9, 0x03, 0xce, 0x18, 0x27, + 0xf9, 0xd9, 0x05, 0x07, 0x6c, 0xfc, 0xbe, 0x17, 0xcf, 0xfd, 0xf1, 0xd3, 0xf4, + 0xf7, 0xc9, 0xdf, 0xaa, 0x3d, 0xfb, 0x25, 0x04, 0x2b, 0xe5, 0xf9, 0x1e, 0xfe, + 0xfa, 0x53, 0xeb, 0xca, 0xfb, 0xf3, 0xfd, 0xc8, 0x2d, 0xb8, 0x16, 0x11, 0x56, + 0x0c, 0xe0, 0xfb, 0xd2, 0x26, 0x14, 0x33, 0x5d, 0x13, 0xfd, 0x35, 0x29, 0xaa, + 0x39, 0xed, 0x14, 0x27, 0xd3, 0xf1, 0x17, 0x11, 0x39, 0xeb, 0x1d, 0xdc, 0x37, + 0x0c, 0xe0, 0xeb, 0x04, 0x0a, 0xb2, 0x06, 0x25, 0x32, 0xfe, 0x24, 0xe2, 0xf3, + 0xd2, 0xeb, 0xf6, 0x01, 0x3a, 0xe2, 0xed, 0x5b, 0xbf, 0x0f, 0x2b, 0xde, 0x00, + 0x7f, 0x56, 0x0b, 0xc4, 0xcb, 0x1a, 0x21, 0x1f, 0xd8, 0xc0, 0x25, 0xde, 0xce, + 0x1e, 0xe0, 0xd0, 0x45, 0xf6, 0x1c, 0x14, 0x32, 0x1e, 0x3a, 0x2d, 0xcf, 0xdc, + 0xa6, 0xab, 0xb4, 0x3b, 0xe0, 0xef, 0xaf, 0x0e, 0xce, 0x0b, 0xc9, 0x28, 0x2b, + 0xc7, 0x0a, 0x2a, 0xde, 0xc4, 0xc7, 0xba, 0x81, 0x29, 0xf2, 0x19, 0xd9, 0xdf, + 0x36, 0xee, 0xb1, 0xf7, 0xbf, 0xc7, 0x01, 0xe8, 0x2a, 0x92, 0xf3, 0x10, 0xe8, + 0x0a, 0x0a, 0xea, 0xb5, 0xe5, 0xc9, 0x38, 0x34, 0xde, 0xe6, 0x12, 0xcb, 0xeb, + 0x14, 0xc9, 0x3d, 0xc6, 0xb6, 0xc0, 0xca, 0xd9, 0x4e, 0xc3, 0xb0, 0x41, 0xca, + 0x0c, 0xaa, 0xd2, 0xc8, 0xec, 0xe0, 0xea, 0xd4, 0x1c, 0xf4, 0x3c, 0xff, 0x0a, + 0xe5, 0x2f, 0x3e, 0xce, 0xdd, 0x1a, 0x08, 0x24, 0xfc, 0x1b, 0x2f, 0xac, 0x00, + 0x10, 0xfe, 0x3b, 0xed, 0xee, 0xe4, 0x18, 0xde, 0xde, 0x25, 0x33, 0x5d, 0xf8, + 0x3f, 0xec, 0xfd, 0xdd, 0x0a, 0xeb, 0x07, 0xdd, 0xe9, 0x2a, 0x3a, 0x02, 0xe1, + 0x09, 0x00, 0xbe, 0x1f, 0xdd, 0x0f, 0x33, 0x49, 0x13, 0xf5, 0xec, 0xbd, 0x11, + 0xb5, 0xf0, 0xd5, 0x03, 0xca, 0xde, 0xd6, 0x73, 0xf9, 0x09, 0xdb, 0xf0, 0x28, + 0x4b, 0xfe, 0xf1, 0xf1, 0xfc, 0xa9, 0x07, 0xf3, 0x06, 0x25, 0xc6, 0x60, 0xca, + 0x29, 0xfe, 0x05, 0xf2, 0xd1, 0xe7, 0x00, 0x2c, 0x31, 0xf7, 0x0c, 0x30, 0xe3, + 0x0d, 0xe2, 0x07, 0xdf, 0xae, 0xd9, 0xc1, 0xf3, 0x1a, 0xf2, 0xd4, 0x0e, 0xc3, + 0x16, 0xf2, 0x44, 0x22, 0x00, 0xe5, 0x24, 0xef, 0xa2, 0x62, 0x13, 0x07, 0x44, + 0xdf, 0xb3, 0x03, 0xfa, 0x23, 0xfe, 0xf6, 0xd8, 0xaa, 0xf1, 0x12, 0x18, 0xee, + 0x1f, 0xd8, 0x5a, 0x14, 0x3a, 0x38, 0xe2, 0xf5, 0x22, 0xc9, 0xc5, 0x6c, 0x15, + 0x76, 0xea, 0xf6, 0x52, 0xe6, 0x12, 0x3a, 0x06, 0x27, 0x7b, 0x09, 0xde, 0x68, + 0xf0, 0xef, 0xe4, 0xc7, 0xc3, 0xd1, 0x2e, 0xdb, 0xeb, 0x47, 0xb8, 0xcc, 0xf3, + 0x0a, 0xeb, 0x19, 0x0e, 0x27, 0xed, 0x19, 0xde, 0x21, 0xdc, 0xf3, 0xcd, 0xe2, + 0xf9, 0x02, 0xe8, 0x27, 0xfe, 0x06, 0x03, 0xd2, 0x37, 0xa2, 0xde, 0xdc, 0xda, + 0x5c, 0xc7, 0xbd, 0xf4, 0x06, 0x05, 0xf5, 0xf0, 0x06, 0xab, 0x08, 0xda, 0x3f, + 0xf8, 0x17, 0x37, 0xfd, 0x25, 0xe2, 0x3c, 0xf6, 0x22, 0x16, 0x11, 0xce, 0xf8, + 0xdb, 0xc2, 0x1d, 0x16, 0x0e, 0xe5, 0xd9, 0x00, 0x32, 0xca, 0x3a, 0xa5, 0x0c, + 0x06, 0x02, 0xb2, 0x2d, 0xdb, 0x0d, 0xde, 0x24, 0xf5, 0x59, 0x0e, 0xaf, 0xe2, + 0xf3, 0xfa, 0xb3, 0xd8, 0x03, 0x3d, 0x1a, 0x1a, 0x16, 0xea, 0xf5, 0xe5, 0xfe, + 0xda, 0x3a, 0xf7, 0x15, 0xe1, 0xfe, 0xf4, 0x0f, 0xde, 0xbb, 0xf5, 0xef, 0xfe, + 0xdb, 0x32, 0xe0, 0xd7, 0xfa, 0x3f, 0xf9, 0xf9, 0xf7, 0xf5, 0xe0, 0x14, 0x35, + 0xc8, 0xe1, 0xcf, 0x15, 0x0e, 0x3a, 0xed, 0x13, 0x3b, 0xeb, 0xc2, 0x34, 0xec, + 0xa9, 0x9d, 0x01, 0x9f, 0x0b, 0xaa, 0x3d, 0x1a, 0x13, 0x0f, 0xea, 0x31, 0x02, + 0xde, 0x0b, 0x1c, 0x37, 0xf9, 0xf5, 0xbd, 0xf4, 0x04, 0xe5, 0x08, 0xf5, 0xcd, + 0xe7, 0xe3, 0x10, 0x0e, 0x13, 0x27, 0x07, 0x14, 0xd9, 0xad, 0xd5, 0xbf, 0xc5, + 0x2b, 0x1f, 0xf9, 0x24, 0x08, 0x34, 0x03, 0x14, 0x02, 0x91, 0x13, 0x0c, 0x55, + 0x1d, 0xeb, 0x09, 0x16, 0xe6, 0xf2, 0x23, 0xd3, 0x3b, 0xcd, 0xeb, 0xeb, 0xc8, + 0xf2, 0xc0, 0xf9, 0xb6, 0xe9, 0xfd, 0xe3, 0x1e, 0x18, 0x33, 0x1f, 0xf6, 0xe9, + 0xc0, 0xf3, 0xf7, 0xee, 0x29, 0xdc, 0x94, 0x5e, 0xf4, 0xeb, 0xf6, 0xf8, 0xd0, + 0xde, 0x00, 0x17, 0xfd, 0x0b, 0x56, 0xfe, 0x01, 0xae, 0x2c, 0xf9, 0x0d, 0xa4, + 0xcf, 0x07, 0x2a, 0x0e, 0x19, 0x20, 0x81, 0x08, 0xc5, 0xdf, 0x21, 0xde, 0xe6, + 0xe0, 0x24, 0xd9, 0x21, 0x1b, 0xc6, 0x28, 0x0e, 0x00, 0x13, 0x0b, 0xf6, 0x2b, + 0x13, 0x13, 0xad, 0x2e, 0x63, 0xfc, 0xfe, 0x09, 0x18, 0xaf, 0x3b, 0xdb, 0x0a, + 0xd9, 0xdc, 0x0f, 0x19, 0xc1, 0xe4, 0x02, 0x23, 0x74, 0x05, 0xdd, 0xf5, 0x43, + 0x08, 0xdd, 0xf4, 0xeb, 0x01, 0x09, 0xfb, 0xc3, 0x2f, 0xc1, 0xc9, 0x35, 0x18, + 0x28, 0xf3, 0xe4, 0xd1, 0x1c, 0xfe, 0xed, 0xae, 0xbf, 0xd5, 0xf5, 0x34, 0x23, + 0xcf, 0x08, 0x14, 0x3b, 0xd5, 0xa0, 0x3c, 0xec, 0xc8, 0xf1, 0x3a, 0xbd, 0xe4, + 0xfd, 0x1d, 0xed, 0x27, 0x13, 0xb1, 0x0c, 0xdd, 0xd5, 0xdf, 0x00, 0xe9, 0xec, + 0xcb, 0xf7, 0x3c, 0x44, 0x06, 0xea, 0xa6, 0xe2, 0x0a, 0x08, 0xd2, 0x01, 0xe1, + 0xf6, 0xc9, 0x1a, 0x43, 0xdb, 0x45, 0xb9, 0x2c, 0x1a, 0xe4, 0x1c, 0xe1, 0xfe, + 0xe8, 0xd2, 0x03, 0xb6, 0xbc, 0x43, 0x16, 0xfe, 0xad, 0xf0, 0xdc, 0xf7, 0xfe, + 0x0b, 0x33, 0xc9, 0xaa, 0xb9, 0x15, 0xfb, 0xda, 0x99, 0x2a, 0xea, 0x02, 0x3c, + 0x2a, 0x62, 0x03, 0x08, 0x1a, 0x20, 0xdd, 0x2c, 0xde, 0x05, 0x39, 0xb3, 0xc8, + 0xba, 0xc9, 0x03, 0x07, 0xd8, 0x00, 0x06, 0xc5, 0x3c, 0x16, 0xf4, 0xb5, 0xf0, + 0xc5, 0xe2, 0xe7, 0xfe, 0x05, 0x0c, 0x0b, 0x1f, 0xd6, 0xdb, 0xd1, 0xf7, 0xe5, + 0xfb, 0xb1, 0xcc, 0x1a, 0xcf, 0xa7, 0x34, 0xfa, 0xc1, 0x30, 0xa1, 0xe2, 0x16, + 0xdf, 0xed, 0x2a, 0x1a, 0x9f, 0x0e, 0xf7, 0x0d, 0xd9, 0xf6, 0x02, 0x0f, 0xb1, + 0xe8, 0xb1, 0x10, 0x14, 0xee, 0x04, 0xec, 0x9c, 0xb2, 0xa5, 0xd1, 0xde, 0x11, + 0x1a, 0x46, 0xfb, 0xa3, 0x4c, 0x10, 0xef, 0x16, 0xeb, 0x06, 0x14, 0x19, 0x48, + 0x1c, 0xe5, 0xf9, 0xe1, 0x14, 0x04, 0x20, 0xbf, 0xc0, 0xa2, 0x07, 0xd0, 0x01, + 0xd9, 0xf8, 0x93, 0xe3, 0xe7, 0xd9, 0x1b, 0xa3, 0xf9, 0xc0, 0xc0, 0xc7, 0xe2, + 0xd1, 0xff, 0x4c, 0xee, 0xfc, 0x31, 0xef, 0x3a, 0xef, 0xd5, 0xd7, 0xce, 0xf3, + 0xe5, 0xba, 0xe8, 0x15, 0x15, 0x7f, 0xf8, 0x07, 0x38, 0x17, 0x10, 0x3d, 0x0f, + 0x1b, 0xe3, 0xd3, 0xcc, 0xc5, 0x41, 0x3f, 0x35, 0xed, 0xd1, 0xe2, 0xc6, 0x1d, + 0xcf, 0xdf, 0xd4, 0xbf, 0xf9, 0xe7, 0x10, 0x0b, 0x07, 0xce, 0x19, 0xca, 0xfb, + 0xee, 0xfb, 0xf8, 0xc8, 0x10, 0xcf, 0xfa, 0xba, 0xd1, 0xe7, 0xd7, 0xdb, 0xce, + 0xcd, 0x03, 0xff, 0xd2, 0x33, 0xed, 0x25, 0x06, 0x30, 0xf0, 0x01, 0xe8, 0x25, + 0x10, 0x00, 0x15, 0x2c, 0xe8, 0x0e, 0xdd, 0x03, 0x0e, 0xd6, 0xc7, 0xd7, 0x16, + 0xf5, 0x34, 0x54, 0x12, 0xc1, 0xfe, 0x4c, 0xe8, 0x08, 0x19, 0x01, 0xf9, 0x9e, + 0x0a, 0xb7, 0xbc, 0x02, 0xcc, 0xed, 0x15, 0xea, 0xc7, 0x32, 0x33, 0x1c, 0xf9, + 0xbf, 0xbb, 0x20, 0x1e, 0x08, 0xe7, 0xea, 0x22, 0x02, 0xfc, 0x0a, 0xc1, 0xd0, + 0xec, 0x07, 0x0c, 0x38, 0xed, 0xfe, 0xd3, 0xe5, 0x13, 0xb9, 0xd5, 0xeb, 0xd2, + 0xf8, 0xdc, 0x1f, 0xbf, 0xf3, 0xf9, 0x18, 0x13, 0x09, 0xe6, 0xea, 0x14, 0x81, + 0xfc, 0xea, 0xcf, 0xfc, 0xdd, 0x08, 0xcd, 0x1f, 0x05, 0xb6, 0xce, 0x23, 0x23, + 0xce, 0xc6, 0x0e, 0xb6, 0xf3, 0xdf, 0xe9, 0x16, 0x18, 0xcc, 0x13, 0x19, 0x19, + 0xef, 0x19, 0x2a, 0xfb, 0xcc, 0x18, 0xb9, 0xca, 0xd9, 0xe2, 0x56, 0xc9, 0xc5, + 0x0b, 0x12, 0xcf, 0x12, 0xfc, 0x21, 0x5b, 0xb9, 0x0e, 0x13, 0x19, 0xeb, 0x01, + 0x0f, 0x47, 0x25, 0xed, 0xe1, 0x12, 0xf9, 0xfe, 0xf6, 0x27, 0xe9, 0x05, 0xb8, + 0xae, 0xec, 0x2d, 0x00, 0xf7, 0xde, 0xf2, 0xe7, 0xfe, 0x04, 0xc7, 0xda, 0x1e, + 0xef, 0x32, 0x9c, 0xe2, 0x15, 0xbe, 0xcc, 0x26, 0xe0, 0x02, 0xfd, 0x0c, 0xe9, + 0xf5, 0xf9, 0xfe, 0xf8, 0xe4, 0xf1, 0xd7, 0x02, 0xcf, 0x28, 0x20, 0x12, 0xde, + 0x39, 0xfa, 0xda, 0x06, 0xed, 0xc8, 0xeb, 0x03, 0x27, 0x1a, 0x1b, 0xf8, 0xf6, + 0xd6, 0xb2, 0xfc, 0xd8, 0xb5, 0xf3, 0xeb, 0xf6, 0x00, 0x18, 0x45, 0x13, 0xfd, + 0x62, 0xfb, 0xd0, 0xf0, 0xa6, 0x35, 0xdc, 0x75, 0xac, 0x9c, 0xe9, 0xd5, 0xea, + 0xbe, 0xbe, 0xf8, 0x1a, 0x05, 0x85, 0x0a, 0x1e, 0x01, 0xda, 0xd3, 0x81, 0xe1, + 0xcc, 0xd4, 0xdf, 0xd1, 0xfb, 0x13, 0xd6, 0xde, 0x1f, 0xa0, 0xd6, 0x1e, 0xe9, + 0x3d, 0xd4, 0x13, 0xce, 0x41, 0x2f, 0x40, 0xdd, 0x03, 0x61, 0xa5, 0x34, 0xc8, + 0x16, 0xdb, 0xc6, 0xbe, 0xaf, 0xe3, 0x52, 0x6e, 0xdb, 0xec, 0x49, 0xe0, 0xfb, + 0x24, 0xf9, 0x24, 0xe8, 0x29, 0xc6, 0xb9, 0x03, 0x26, 0x2c, 0xda, 0x01, 0xe9, + 0xa7, 0xde, 0x05, 0xbf, 0xa8, 0x1f, 0xbd, 0xb3, 0x84, 0xe2, 0x1f, 0x29, 0x12, + 0xcd, 0xe7, 0x1f, 0x05, 0x4f, 0x1a, 0x2a, 0xe2, 0x92, 0xc0, 0xfc, 0x1e, 0xf7, + 0xbd, 0xa7, 0xe0, 0xc1, 0xe2, 0xc9, 0x88, 0x19, 0xcf, 0xc5, 0xfa, 0x12, 0xad, + 0xd8, 0x0e, 0x20, 0x98, 0x9e, 0x04, 0x17, 0xc1, 0xf6, 0x02, 0x60, 0xf2, 0xdc, + 0x09, 0x42, 0x29, 0x26, 0x0a, 0x8a, 0xec, 0xe9, 0x12, 0x03, 0xb2, 0xb4, 0xf6, + 0x10, 0xf3, 0x87, 0x12, 0xfd, 0xda, 0xde, 0xf2, 0xdd, 0xa8, 0x44, 0x5d, 0xff, + 0x69, 0x40, 0xc0, 0x86, 0x0b, 0x4a, 0x5d, 0xef, 0x04, 0x14, 0xf9, 0x9b, 0x11, + 0xa1, 0xde, 0x3d, 0xe7, 0x5a, 0xf9, 0xbb, 0xce, 0xf9, 0xa2, 0xf8, 0x2c, 0x05, + 0xd4, 0xf7, 0x1d, 0xdf, 0xdf, 0xda, 0x34, 0xd8, 0xf5, 0xcb, 0x0a, 0xe0, 0xe0, + 0xc6, 0xdf, 0xe4, 0xd1, 0xd8, 0xf8, 0x28, 0xea, 0x01, 0xfc, 0x4b, 0xcb, 0x46, + 0xc1, 0xf7, 0x1f, 0xe7, 0xe9, 0x21, 0x09, 0xd5, 0x18, 0xdf, 0xe1, 0xfc, 0xdb, + 0xfd, 0x3e, 0xa1, 0xa8, 0xed, 0x2f, 0x4e, 0x4a, 0xba, 0xe1, 0x50, 0xff, 0x56, + 0xcb, 0xcd, 0x10, 0xe4, 0xe5, 0x77, 0x68, 0xfa, 0xd6, 0xb3, 0xd2, 0xba, 0xcb, + 0x55, 0x15, 0xf4, 0x26, 0x0c, 0x28, 0x3b, 0xdc, 0xe7, 0x2b, 0xe1, 0x06, 0xe9, + 0x83, 0x24, 0xf6, 0x0f, 0x11, 0x18, 0xf0, 0x04, 0xf7, 0x15, 0xd7, 0xe4, 0xdf, + 0x15, 0xf5, 0x81, 0xcd, 0x02, 0x45, 0x0a, 0xfc, 0xb1, 0xf3, 0xd4, 0x0b, 0xc4, + 0xdf, 0x09, 0xca, 0x05, 0xc7, 0xe9, 0x0f, 0xf7, 0xeb, 0xda, 0x7c, 0x12, 0xf6, + 0xc8, 0x04, 0xdf, 0xd3, 0x8d, 0x23, 0x64, 0x22, 0xff, 0x45, 0x23, 0xf1, 0xfa, + 0xf0, 0x15, 0xa7, 0xf2, 0xba, 0xe4, 0xbb, 0x2f, 0x85, 0x96, 0xef, 0x07, 0xa8, + 0x9c, 0xf2, 0x4a, 0xe0, 0xd3, 0xdb, 0xe6, 0x8d, 0xc0, 0xb8, 0xd2, 0xf0, 0x09, + 0xbf, 0x3b, 0xeb, 0x12, 0x56, 0xa5, 0x9f, 0x46, 0xef, 0xd6, 0x26, 0x1f, 0xf4, + 0xd8, 0xb5, 0x24, 0xdf, 0xa7, 0x02, 0xc6, 0x01, 0x4c, 0x3b, 0xef, 0xdf, 0x07, + 0xad, 0x19, 0x42, 0x0a, 0x02, 0xb1, 0xce, 0x56, 0xec, 0x0b, 0xd7, 0x4f, 0xb6, + 0xbd, 0x06, 0xf9, 0xb4, 0x21, 0x4e, 0xfd, 0x04, 0xd5, 0x46, 0x38, 0x91, 0x11, + 0xbe, 0x3d, 0x08, 0xc8, 0xee, 0x2f, 0xfd, 0x1a, 0xac, 0xcd, 0xfe, 0x29, 0x0f, + 0xda, 0xf8, 0x96, 0x21, 0xfd, 0xd9, 0x33, 0x19, 0xc1, 0x57, 0xf8, 0x10, 0xd3, + 0xe9, 0xdc, 0xfc, 0x0c, 0xf0, 0xcd, 0x19, 0xc6, 0xd7, 0x1c, 0x01, 0xe9, 0x4b, + 0xba, 0xf6, 0xb2, 0xe7, 0xf4, 0xbc, 0xfc, 0x14, 0xf3, 0xc9, 0x06, 0xf8, 0x26, + 0x26, 0x04, 0xe9, 0x52, 0xdc, 0x18, 0x11, 0xd4, 0x52, 0xf6, 0xf6, 0xf0, 0x51, + 0xde, 0xde, 0x1e, 0xdd, 0xf5, 0x40, 0xb0, 0x00, 0x03, 0xea, 0x17, 0xe3, 0x09, + 0xfd, 0x0b, 0xf0, 0x3e, 0xa3, 0xba, 0x12, 0x3f, 0x15, 0xf0, 0xef, 0x17, 0xb0, + 0x1f, 0xf3, 0xa9, 0x5f, 0xe0, 0x57, 0x06, 0x03, 0x12, 0xa0, 0x15, 0x1b, 0xe3, + 0xf0, 0xdb, 0x57, 0x0b, 0x44, 0x48, 0xd8, 0x05, 0xd6, 0xfb, 0x4e, 0xdf, 0x09, + 0xbf, 0xde, 0x27, 0x05, 0x21, 0xe0, 0xd5, 0xcf, 0x24, 0x08, 0xe4, 0xc1, 0xfc, + 0xf2, 0x33, 0xe1, 0xec, 0x15, 0x09, 0x03, 0xf4, 0x05, 0xf0, 0x11, 0xf8, 0x9b, + 0xea, 0xcc, 0xfb, 0xa7, 0xf9, 0x07, 0xdf, 0xe3, 0xa2, 0x00, 0x0c, 0xc1, 0x1e, + 0x18, 0xd4, 0xea, 0x02, 0x3f, 0xef, 0x17, 0x03, 0x24, 0x1d, 0x44, 0x15, 0xc3, + 0xe0, 0x03, 0x08, 0x10, 0xf8, 0x09, 0x16, 0x21, 0x14, 0x29, 0x02, 0xc8, 0x09, + 0x17, 0x33, 0xfe, 0x62, 0x25, 0xfc, 0xfb, 0xc3, 0x48, 0x5d, 0x1d, 0xeb, 0x00, + 0x1c, 0xd0, 0x18, 0xa5, 0x18, 0xd3, 0x2e, 0x1e, 0xc0, 0xee, 0x12, 0xee, 0x57, + 0xf6, 0xf2, 0x0e, 0xe1, 0x07, 0xb0, 0xea, 0xe9, 0x2a, 0x11, 0x3d, 0xf0, 0xf3, + 0xd4, 0xe8, 0x08, 0xd2, 0xf2, 0xe9, 0x00, 0x0b, 0xf4, 0xa2, 0xbe, 0xf9, 0xbf, + 0x5d, 0x3c, 0xb9, 0xe1, 0xc6, 0xf5, 0x00, 0xd5, 0x13, 0x05, 0x05, 0x10, 0xff, + 0xe4, 0x1d, 0xb4, 0xfa, 0xd6, 0xe9, 0xec, 0x0a, 0xf8, 0x01, 0xec, 0xe4, 0xec, + 0x3c, 0xd0, 0xcd, 0xf5, 0xc0, 0xcc, 0xda, 0xcf, 0xf5, 0x3f, 0xe0, 0xe4, 0xc0, + 0x08, 0x27, 0x53, 0xdf, 0x08, 0xa9, 0x24, 0x0c, 0xb7, 0x2c, 0x21, 0x7f, 0xd0, + 0xe2, 0x28, 0xe9, 0xbc, 0x1b, 0xca, 0xec, 0x1f, 0x00, 0x0e, 0x17, 0xfe, 0x1b, + 0x05, 0xf0, 0x5d, 0xf1, 0x0e, 0x24, 0x09, 0xe8, 0xf6, 0x13, 0x05, 0xc3, 0x2a, + 0x09, 0xc5, 0xe5, 0x26, 0xeb, 0xdc, 0xfa, 0x05, 0x09, 0xe8, 0xf3, 0xca, 0xf2, + 0x01, 0xed, 0xdf, 0xb6, 0x04, 0xdd, 0xe3, 0xb2, 0xf2, 0xbf, 0xfa, 0x4a, 0x28, + 0x01, 0x0e, 0xb4, 0x01, 0x13, 0xc6, 0x3a, 0x05, 0xe8, 0xf4, 0x02, 0x0d, 0x16, + 0x08, 0xea, 0xdd, 0xfe, 0x13, 0xe1, 0xfd, 0x38, 0xef, 0x00, 0xdb, 0x1a, 0x1f, + 0xe9, 0xe5, 0xcf, 0xe4, 0xf4, 0xfa, 0x32, 0xc5, 0x04, 0x1c, 0x0b, 0x50, 0xeb, + 0xff, 0x2c, 0xe6, 0xde, 0xf7, 0xfa, 0xa5, 0xb8, 0xc4, 0xc9, 0xe8, 0x06, 0x02, + 0xfb, 0xb5, 0xfb, 0xee, 0x1a, 0x13, 0xf7, 0xd2, 0xea, 0x2c, 0xec, 0xe4, 0x07, + 0xf4, 0x2c, 0xc1, 0x2b, 0x04, 0x13, 0x24, 0x06, 0xdd, 0xfe, 0x8f, 0xe1, 0x43, + 0xb9, 0xdf, 0xbd, 0x47, 0xac, 0x2e, 0xe2, 0x16, 0xe2, 0xfb, 0xc1, 0x48, 0x08, + 0xf2, 0x61, 0xd4, 0xf0, 0xe4, 0x4b, 0x0a, 0xd2, 0xe1, 0x3a, 0x24, 0x2f, 0xa9, + 0xea, 0xfc, 0xcd, 0x32, 0xf7, 0x03, 0x1a, 0x6a, 0xbb, 0x28, 0xea, 0xa3, 0xe4, + 0xb8, 0xbf, 0x1b, 0xce, 0xfe, 0xd1, 0xc3, 0x21, 0x0d, 0x9e, 0xf3, 0xdb, 0xdc, + 0x1b, 0xf6, 0xdf, 0xc2, 0xbf, 0x12, 0x30, 0x63, 0xc4, 0xe6, 0xf8, 0x05, 0xcc, + 0x16, 0xf7, 0x0a, 0xe4, 0xca, 0xea, 0xea, 0x0a, 0xe8, 0x2e, 0x1c, 0xc1, 0xfc, + 0xac, 0x20, 0x02, 0xfb, 0x42, 0x0b, 0xf7, 0xe2, 0xf9, 0xe1, 0xe5, 0xcb, 0xb4, + 0xb3, 0x02, 0x17, 0xd2, 0xd9, 0xca, 0xe9, 0xbe, 0xfa, 0x17, 0xd3, 0xda, 0x48, + 0xfa, 0xd1, 0x07, 0xbd, 0x10, 0x19, 0xa5, 0xe8, 0x0b, 0x3c, 0x3a, 0x0f, 0xf0, + 0xe4, 0xe2, 0x0e, 0x9e, 0xc5, 0xd5, 0xba, 0x77, 0xd6, 0xc4, 0x4d, 0x06, 0xd2, + 0xf1, 0x03, 0x5b, 0xce, 0x00, 0x35, 0x2a, 0x08, 0xf1, 0x87, 0xbb, 0x3a, 0xb3, + 0x08, 0x0c, 0xa5, 0xcf, 0x2a, 0xe4, 0x4c, 0x04, 0x41, 0xd7, 0xd7, 0xd2, 0x13, + 0xee, 0xe6, 0x9d, 0xdc, 0x09, 0xf1, 0xec, 0xd8, 0x34, 0xfe, 0x56, 0x07, 0xaf, + 0xd6, 0x37, 0xd9, 0xdf, 0x4c, 0xb6, 0x16, 0x1a, 0xa6, 0x07, 0xc7, 0x9d, 0xe6, + 0x07, 0xf8, 0x31, 0xee, 0x3a, 0xd1, 0x38, 0xb7, 0xac, 0xc2, 0x19, 0xeb, 0xba, + 0x05, 0x54, 0xe1, 0xbe, 0xf1, 0x3a, 0xc1, 0xfb, 0xe8, 0x5b, 0xd2, 0xa6, 0x30, + 0xd9, 0x81, 0xa0, 0x07, 0x1b, 0x00, 0x01, 0x6e, 0xcc, 0x24, 0x0f, 0xf4, 0x16, + 0x0b, 0xd4, 0xd1, 0x3c, 0xcc, 0xb5, 0xd6, 0xa9, 0x2c, 0xf3, 0xea, 0xe3, 0xfd, + 0xf9, 0x81, 0x21, 0x4d, 0x3e, 0xd5, 0xfe, 0xb7, 0x0f, 0xc1, 0x1c, 0x1d, 0x16, + 0xf7, 0x03, 0xf9, 0xfe, 0xd6, 0xf3, 0x11, 0xab, 0xd3, 0xfb, 0x58, 0xf3, 0xae, + 0xcc, 0xde, 0xfb, 0xc4, 0xb8, 0x0b, 0x05, 0xde, 0x30, 0x1f, 0xc9, 0x83, 0x0d, + 0xd7, 0xec, 0x03, 0x18, 0x15, 0xf6, 0x0e, 0x4a, 0xcc, 0x14, 0x31, 0xac, 0x25, + 0x2a, 0x1e, 0xb5, 0xd8, 0x6d, 0xd2, 0x1c, 0xec, 0xdb, 0xc8, 0xc7, 0xec, 0x1d, + 0xbe, 0xf1, 0x10, 0xeb, 0x0b, 0xc6, 0xca, 0xed, 0xe4, 0xdc, 0xbc, 0x09, 0x58, + 0xe2, 0xed, 0xc8, 0xdb, 0xd2, 0xec, 0xf6, 0x15, 0xeb, 0xda, 0xd4, 0x2e, 0xf0, + 0xc7, 0xdb, 0xff, 0x3b, 0xb3, 0x60, 0x15, 0xdb, 0xff, 0x06, 0x05, 0x1d, 0x00, + 0xae, 0xe6, 0xcb, 0x09, 0x50, 0x1e, 0xec, 0x36, 0x08, 0xcc, 0xa3, 0xf3, 0x54, + 0x06, 0x54, 0xeb, 0xc4, 0xf0, 0x43, 0xc1, 0xfd, 0xe5, 0xf0, 0xd5, 0xdb, 0xe4, + 0xe3, 0xfd, 0x44, 0x1c, 0x0f, 0xf0, 0xe0, 0x03, 0x2a, 0x65, 0xe3, 0xc8, 0xe9, + 0xfd, 0xef, 0xdb, 0x42, 0x05, 0x06, 0xe2, 0xd1, 0xa9, 0xdc, 0x10, 0x9d, 0x38, + 0x0d, 0x1f, 0xc0, 0x0d, 0xf1, 0xd7, 0x31, 0xc9, 0x21, 0x87, 0xf7, 0xed, 0xf7, + 0xa1, 0x08, 0xf3, 0xbf, 0xcf, 0x2a, 0xd6, 0xe9, 0xfd, 0x03, 0xf9, 0xdc, 0x22, + 0x00, 0xff, 0x15, 0xeb, 0x09, 0xfb, 0x2a, 0x29, 0xf7, 0x09, 0xfa, 0xb5, 0xf0, + 0x13, 0xe6, 0xf8, 0x46, 0x07, 0x29, 0x8d, 0xfd, 0xfe, 0x0a, 0x1b, 0x18, 0xf3, + 0xa4, 0xec, 0xc3, 0x26, 0xa0, 0xe4, 0xd8, 0x0a, 0xd8, 0xf0, 0x96, 0x86, 0x2d, + 0xc9, 0x02, 0x21, 0xf4, 0x2e, 0x40, 0x1f, 0x0e, 0x3e, 0xd7, 0x51, 0x3f, 0x0d, + 0xc9, 0x9c, 0xb7, 0x27, 0xd8, 0x23, 0x02, 0xc7, 0x0f, 0xd5, 0x90, 0x38, 0xc9, + 0x1e, 0x02, 0xaa, 0x3c, 0xbe, 0x88, 0x29, 0xdd, 0x39, 0xe7, 0x98, 0x09, 0xd9, + 0x84, 0x38, 0xe9, 0x4b, 0xb3, 0xbb, 0x2e, 0x29, 0xfd, 0x1a, 0x1f, 0x08, 0xe4, + 0x3d, 0x1e, 0xfb, 0xc2, 0x32, 0x13, 0x4b, 0x40, 0xdd, 0xfc, 0xe4, 0xff, 0xf7, + 0x28, 0xde, 0xbb, 0xf3, 0x09, 0xe5, 0x06, 0xc9, 0x34, 0xe5, 0x93, 0xde, 0xd8, + 0x2e, 0xb4, 0xfe, 0xc6, 0x41, 0xa6, 0xdc, 0xfc, 0x0c, 0x2d, 0x33, 0xd4, 0x62, + 0xe7, 0xc8, 0xcc, 0x4a, 0x28, 0xc7, 0x31, 0x93, 0x1b, 0x4c, 0x33, 0x2d, 0x3f, + 0xc1, 0x58, 0xe2, 0xcc, 0xef, 0xf1, 0xf9, 0xce, 0x09, 0x24, 0xb9, 0x09, 0xd9, + 0x23, 0xef, 0xfc, 0xd1, 0x15, 0x41, 0xfd, 0x21, 0xe6, 0x49, 0xbd, 0xd0, 0xd8, + 0xcc, 0x2c, 0xd1, 0xfe, 0xb8, 0xca, 0xd4, 0xec, 0xdb, 0x14, 0xd5, 0x61, 0xfa, + 0xbc, 0x27, 0xf8, 0x91, 0xa3, 0x3f, 0x23, 0x48, 0xcd, 0x1d, 0xf3, 0x2c, 0xfc, + 0xaa, 0xb0, 0xf0, 0x0b, 0xd9, 0xe5, 0x0c, 0xb8, 0x0f, 0xdb, 0x95, 0xf6, 0xef, + 0x1e, 0xda, 0xe5, 0xf4, 0x6f, 0x42, 0xf2, 0x35, 0xba, 0x11, 0xc9, 0x0b, 0xf2, + 0xb7, 0x16, 0xbd, 0xa0, 0x24, 0x36, 0xe5, 0x3d, 0xe7, 0xfb, 0xa0, 0xd6, 0x05, + 0xb7, 0xd8, 0x16, 0xf2, 0x1d, 0xac, 0x81, 0x04, 0xb5, 0xdd, 0xe9, 0x21, 0x99, + 0x3c, 0x16, 0xf6, 0x1a, 0xa6, 0xb8, 0x4c, 0xd1, 0x24, 0xd9, 0xeb, 0xe8, 0x03, + 0xc1, 0xe4, 0xe4, 0xab, 0x92, 0xf5, 0x11, 0xd6, 0x45, 0x35, 0xf4, 0x05, 0xe5, + 0xe5, 0xe2, 0xc4, 0x5a, 0xf9, 0xf3, 0xe7, 0xd6, 0xd0, 0x0a, 0xb0, 0x23, 0xdf, + 0x3d, 0xea, 0x29, 0xde, 0x0d, 0xb3, 0x12, 0x0a, 0xee, 0xb1, 0x36, 0x3a, 0xb6, + 0x07, 0x1b, 0xf4, 0xc1, 0x08, 0x2f, 0xc7, 0x03, 0xf6, 0xf1, 0xf8, 0x16, 0x36, + 0xe1, 0x1a, 0x02, 0x08, 0xfd, 0xe9, 0x9b, 0xd2, 0xb8, 0xfc, 0x32, 0xb2, 0xe2, + 0x37, 0xd9, 0xaf, 0x05, 0xfb, 0x52, 0x1c, 0x09, 0x03, 0xe1, 0x2e, 0xd7, 0x2c, + 0x22, 0xf6, 0x04, 0x03, 0x11, 0x26, 0xd9, 0x1e, 0xb1, 0xe4, 0xa7, 0x33, 0xf2, + 0x1a, 0x10, 0xf8, 0xe1, 0x29, 0x0b, 0xe2, 0x1b, 0xf8, 0x1c, 0xd3, 0xc9, 0x17, + 0xec, 0x00, 0x61, 0xbf, 0x01, 0x3c, 0x9c, 0x06, 0x54, 0x10, 0xd4, 0xe9, 0xa2, + 0x3f, 0xba, 0xd3, 0xe5, 0xaa, 0x05, 0x03, 0x50, 0x07, 0x38, 0x17, 0xf9, 0x44, + 0x03, 0xc5, 0xfd, 0xc3, 0xb4, 0xdc, 0xf5, 0x0c, 0x07, 0xf5, 0xcd, 0x31, 0x44, + 0x62, 0x08, 0xbe, 0xa5, 0x34, 0x2a, 0xe7, 0xfa, 0x07, 0xca, 0xd8, 0xad, 0xce, + 0x00, 0xee, 0xdb, 0x1f, 0xb7, 0x38, 0xde, 0xc2, 0x3c, 0xf3, 0xeb, 0xb7, 0x99, + 0xb2, 0x1b, 0x0f, 0xd8, 0x14, 0x17, 0x15, 0x46, 0x19, 0x29, 0x25, 0xae, 0x3a, + 0xce, 0x41, 0x43, 0xdb, 0xd7, 0x1a, 0x1b, 0x91, 0x17, 0xa4, 0x0b, 0xeb, 0x0d, + 0xde, 0xe8, 0xde, 0x81, 0xfd, 0xf2, 0x14, 0xc3, 0xa7, 0x0b, 0xc9, 0xe9, 0x30, + 0xbb, 0x23, 0xef, 0xf0, 0xe4, 0x12, 0xc9, 0xcf, 0xfb, 0x1b, 0xcb, 0xe9, 0xad, + 0xf5, 0x56, 0x03, 0x4d, 0xdb, 0xe6, 0x15, 0x07, 0x5f, 0x34, 0xfa, 0xcb, 0xf5, + 0x2d, 0xd9, 0xc9, 0x19, 0xfe, 0x23, 0xfa, 0xda, 0xdd, 0xd3, 0xac, 0xca, 0x31, + 0xd6, 0x08, 0x1d, 0xef, 0xfe, 0x18, 0xef, 0xfd, 0xee, 0xe9, 0x32, 0x4f, 0xee, + 0x02, 0xf1, 0xf3, 0xb3, 0x61, 0x0b, 0xe7, 0xbe, 0xe6, 0xa2, 0xc3, 0xdd, 0x09, + 0xe6, 0x01, 0xaf, 0xc0, 0x2b, 0xca, 0xf1, 0x3a, 0x2d, 0x2e, 0x31, 0x0c, 0xd1, + 0x88, 0xdf, 0xb5, 0xf1, 0x17, 0x23, 0xf2, 0x3b, 0x08, 0x60, 0xee, 0xd5, 0xfe, + 0x12, 0x18, 0xdc, 0x02, 0x02, 0xa9, 0xdd, 0xde, 0xca, 0xed, 0xd3, 0x11, 0x14, + 0x0f, 0x46, 0xfe, 0x02, 0xc3, 0x1c, 0x18, 0xcd, 0xdc, 0xdd, 0x58, 0xd7, 0xee, + 0x43, 0x1d, 0xce, 0xd9, 0x09, 0xf5, 0x09, 0xe4, 0x58, 0x13, 0xd2, 0x08, 0xe1, + 0xda, 0xee, 0x36, 0xa1, 0xf3, 0x00, 0x43, 0xa5, 0x06, 0xf9, 0x0b, 0xf3, 0xda, + 0x8e, 0xd5, 0xe8, 0xd7, 0xd2, 0x2b, 0x21, 0x00, 0xc0, 0x17, 0xd1, 0x09, 0xd3, + 0xda, 0xfc, 0xba, 0x15, 0x08, 0xee, 0xd8, 0xd6, 0xc4, 0xab, 0x43, 0x03, 0xfa, + 0x10, 0x22, 0xe4, 0xf5, 0xe6, 0x18, 0x18, 0x3a, 0xd2, 0xf4, 0x08, 0xfa, 0xd4, + 0x0d, 0xdc, 0xd9, 0x23, 0xa7, 0xe9, 0x3c, 0xff, 0x1d, 0xf2, 0xef, 0x39, 0x07, + 0x17, 0xc2, 0x30, 0x2f, 0xf3, 0xca, 0x55, 0x15, 0xff, 0xff, 0x99, 0x2d, 0xe0, + 0x44, 0x0d, 0x6e, 0xc6, 0xf1, 0x20, 0x0f, 0xc1, 0xf1, 0x0a, 0xf5, 0xec, 0x11, + 0x24, 0xf8, 0xe8, 0x02, 0xd2, 0xe6, 0x12, 0x1e, 0xff, 0xc9, 0x17, 0xcf, 0xd7, + 0x07, 0xd8, 0x0d, 0x04, 0x0d, 0x2a, 0xfe, 0x09, 0x3b, 0xcd, 0x56, 0x26, 0xcd, + 0x03, 0x2a, 0x0f, 0xdc, 0x3c, 0x01, 0xaa, 0xd8, 0x3f, 0x37, 0x01, 0xde, 0xf3, + 0xe8, 0xdd, 0xf8, 0xe3, 0x01, 0x39, 0xe9, 0xbc, 0x16, 0xfa, 0xe1, 0xd3, 0xf4, + 0xd1, 0x15, 0x22, 0x17, 0xdd, 0x0f, 0xef, 0xd4, 0xd2, 0x15, 0x81, 0xd2, 0x19, + 0xe6, 0xd6, 0x1d, 0x06, 0x08, 0xb7, 0xe2, 0xde, 0xed, 0xe0, 0x0e, 0xed, 0x09, + 0x38, 0xcb, 0xef, 0xea, 0x2f, 0xd9, 0xdf, 0xfb, 0x05, 0xe3, 0x11, 0xce, 0xe7, + 0xf4, 0x15, 0x45, 0xf5, 0xf4, 0x09, 0x16, 0xcc, 0x44, 0xce, 0x1b, 0xe5, 0x0e, + 0xfa, 0xc1, 0x2d, 0x44, 0xed, 0xe6, 0x27, 0xfe, 0x00, 0x23, 0xdb, 0x1a, 0xc1, + 0x2d, 0xad, 0xbe, 0x2b, 0x22, 0xe7, 0x07, 0xe1, 0xd8, 0xf6, 0xe7, 0x53, 0xbb, + 0xd1, 0x85, 0xe7, 0xdd, 0x32, 0xe2, 0xf3, 0xe0, 0x05, 0x09, 0xfa, 0xd7, 0xf4, + 0x15, 0x3b, 0xea, 0x16, 0x0f, 0xe8, 0xd4, 0x44, 0xf8, 0xb0, 0xe4, 0xe9, 0xe4, + 0xe1, 0xb7, 0x52, 0xb5, 0x65, 0x03, 0x11, 0xab, 0xbe, 0x3f, 0xc8, 0x21, 0xf7, + 0x09, 0x0f, 0x31, 0xf4, 0x47, 0xfc, 0xfb, 0xdb, 0x81, 0x2a, 0x37, 0xd4, 0xc4, + 0x08, 0xb7, 0xff, 0xfc, 0x27, 0x1c, 0xf0, 0x00, 0x07, 0x16, 0x07, 0xaf, 0xe4, + 0xda, 0x26, 0xcc, 0xf1, 0xd8, 0x37, 0x35, 0x18, 0x36, 0x0c, 0x0b, 0x4e, 0xfc, + 0xd7, 0x97, 0x15, 0xed, 0xdf, 0xf1, 0x00, 0xe7, 0x2b, 0xde, 0xf3, 0xb5, 0xc6, + 0x33, 0xd5, 0xf2, 0x0e, 0x1f, 0xf0, 0xcd, 0xbf, 0x40, 0xbe, 0x07, 0xd4, 0x8c, + 0xd4, 0xbe, 0x92, 0xdb, 0x3e, 0x1b, 0xfb, 0xd4, 0x1a, 0xe1, 0x0d, 0x0d, 0x1b, + 0xe6, 0x9f, 0xd9, 0xc0, 0xb9, 0x09, 0xd8, 0xa6, 0xdd, 0xfd, 0xf8, 0x0d, 0x01, + 0x3d, 0xb7, 0xe6, 0xe1, 0xca, 0xe0, 0x01, 0xe4, 0xa9, 0x0f, 0x18, 0x1d, 0xc2, + 0xf0, 0x08, 0x16, 0x11, 0x06, 0x14, 0xb4, 0x9a, 0xb5, 0xc1, 0x90, 0xc7, 0x00, + 0xfc, 0x0b, 0xd5, 0x95, 0xe6, 0x24, 0xf3, 0xfb, 0x01, 0xac, 0xc0, 0x13, 0xe2, + 0xff, 0xd0, 0xd2, 0x1a, 0x1c, 0xb5, 0x4d, 0x3b, 0xeb, 0x1f, 0xf0, 0xf8, 0xb5, + 0xcb, 0xff, 0xd9, 0x19, 0xd4, 0xf6, 0x16, 0x14, 0xdb, 0xfe, 0x26, 0xdb, 0x97, + 0x44, 0x21, 0x3a, 0xec, 0xda, 0xe3, 0x08, 0xa7, 0x4e, 0xd7, 0xf2, 0x34, 0xcb, + 0x40, 0xd0, 0x75, 0x1b, 0xf4, 0x2b, 0x26, 0xf3, 0x2c, 0xc8, 0xe5, 0xd6, 0x71, + 0x1d, 0xf3, 0xb9, 0x64, 0xc1, 0xee, 0x25, 0x27, 0xc0, 0x0c, 0x19, 0xf1, 0x11, + 0x61, 0x01, 0xea, 0x0c, 0xf7, 0xa1, 0x1a, 0x18, 0xe4, 0xc7, 0xf5, 0x23, 0xf5, + 0x3a, 0xfe, 0x87, 0xfb, 0x9f, 0x09, 0xd2, 0x24, 0x24, 0x27, 0xf5, 0xa1, 0x17, + 0x36, 0x0c, 0xe9, 0xf0, 0x28, 0xec, 0xe2, 0xe1, 0xb5, 0xcb, 0x07, 0xf7, 0xe0, + 0x15, 0x1c, 0xea, 0xde, 0x00, 0x0a, 0x20, 0xe8, 0xe8, 0x42, 0xde, 0xea, 0x01, + 0xff, 0xf1, 0x31, 0x2c, 0x2f, 0x11, 0xe7, 0xf1, 0xfd, 0xd4, 0xed, 0x03, 0xf1, + 0xdd, 0xf6, 0xcf, 0xca, 0x01, 0x40, 0xf4, 0xff, 0xe4, 0xe0, 0x0b, 0x3d, 0xe8, + 0x2c, 0xca, 0xf4, 0xe0, 0xf6, 0x55, 0xef, 0x27, 0xff, 0xd2, 0xd6, 0x5f, 0x07, + 0xe4, 0xfa, 0xf1, 0x32, 0xf4, 0x36, 0xca, 0xea, 0x26, 0x1a, 0x13, 0x26, 0x19, + 0xde, 0x10, 0x13, 0xe2, 0xc0, 0x00, 0xc2, 0xd2, 0x03, 0x02, 0x3e, 0xed, 0x02, + 0x54, 0xcd, 0x10, 0x06, 0x18, 0xd4, 0x60, 0x05, 0x2f, 0x07, 0xd7, 0xd7, 0x14, + 0x28, 0xf8, 0xf5, 0xec, 0xd3, 0x03, 0xe5, 0xf9, 0x4f, 0x04, 0x17, 0xec, 0x55, + 0x00, 0x13, 0x04, 0xea, 0x27, 0xf4, 0xb2, 0x07, 0xf2, 0xd7, 0x32, 0xfa, 0x31, + 0x48, 0x09, 0xfa, 0x40, 0xca, 0xff, 0xf9, 0x44, 0xf6, 0x26, 0x11, 0x11, 0xd5, + 0x20, 0xd1, 0xcf, 0x7f, 0x39, 0x25, 0x2c, 0x2c, 0xc4, 0x1c, 0x20, 0xd9, 0xa5, + 0x11, 0x0b, 0xcb, 0xfa, 0xed, 0xd9, 0xe5, 0x13, 0xd0, 0xcf, 0x26, 0xe4, 0xf7, + 0xd7, 0x16, 0x51, 0xc4, 0xea, 0xec, 0x0a, 0xfe, 0x1a, 0x11, 0x15, 0x18, 0x27, + 0x6a, 0xf1, 0x29, 0xed, 0xfd, 0xe2, 0xe3, 0xe6, 0x16, 0x1b, 0x17, 0x2a, 0x13, + 0x16, 0x01, 0xd9, 0xd2, 0x07, 0xe4, 0x04, 0xd6, 0x4a, 0xfd, 0x24, 0x09, 0xde, + 0x33, 0xb7, 0xfe, 0xc1, 0x02, 0xdc, 0x25, 0xf1, 0xe0, 0x5d, 0x19, 0xf6, 0xee, + 0xe6, 0xc8, 0x31, 0xe1, 0xe5, 0xed, 0x00, 0xf9, 0xf2, 0xf8, 0xc7, 0x02, 0x02, + 0xc1, 0xd9, 0xdd, 0x37, 0xc9, 0xbe, 0xe8, 0xf9, 0x2b, 0xe3, 0xdf, 0x14, 0xa8, + 0x31, 0xc8, 0xcf, 0xfd, 0xec, 0x2a, 0xf6, 0xb3, 0x96, 0xdb, 0xc9, 0xd5, 0x01, + 0xee, 0xec, 0x02, 0x3a, 0x03, 0xb3, 0x56, 0x21, 0xcf, 0xd3, 0x28, 0x2d, 0xb4, + 0xd0, 0x0b, 0xd6, 0xf1, 0xac, 0xf8, 0xdb, 0x12, 0x40, 0x19, 0x9e, 0xfa, 0x27, + 0xe5, 0x1d, 0xf5, 0xeb, 0xea, 0xbe, 0xb9, 0xc6, 0xde, 0xd7, 0xf9, 0xd9, 0xe4, + 0x35, 0xca, 0xce, 0x2a, 0x56, 0xbe, 0x0d, 0x06, 0xff, 0xcc, 0xe7, 0xba, 0x17, + 0x22, 0xea, 0xc2, 0x3d, 0x15, 0xe4, 0x2c, 0x0b, 0x0c, 0xf4, 0xf8, 0x56, 0x43, + 0x4c, 0xfd, 0xf4, 0xb6, 0xd5, 0xf9, 0xd5, 0x05, 0x1c, 0xdf, 0xfe, 0x00, 0x35, + 0xec, 0xe6, 0xa9, 0x06, 0x17, 0xdc, 0xcf, 0x06, 0xf1, 0x42, 0x25, 0xd2, 0xc6, + 0x1a, 0xfc, 0xe6, 0xf0, 0xd5, 0xdd, 0xde, 0xf2, 0xd3, 0xfe, 0x06, 0x81, 0x23, + 0x20, 0x3a, 0x1f, 0x24, 0xe7, 0x17, 0x09, 0x21, 0xff, 0xb7, 0xeb, 0xb4, 0xc7, + 0xf0, 0xb0, 0xb3, 0xfa, 0x0c, 0xc3, 0x22, 0xf4, 0x1b, 0xdd, 0xd3, 0x17, 0x3b, + 0x33, 0xa2, 0xd1, 0x18, 0x1f, 0x2a, 0xce, 0x0d, 0xbe, 0xc4, 0x0f, 0x3f, 0xff, + 0xe9, 0xdc, 0xaf, 0x01, 0xec, 0xeb, 0xf1, 0xc8, 0xc1, 0x22, 0xc8, 0x2d, 0xa7, + 0xc6, 0xbe, 0x44, 0xd5, 0xea, 0x1a, 0x1d, 0x0d, 0x1e, 0x0f, 0x21, 0x03, 0x45, + 0xd5, 0x39, 0xfa, 0x0e, 0xf4, 0xdf, 0xf9, 0x0d, 0xdf, 0x17, 0x23, 0x8a, 0x14, + 0x20, 0xcc, 0x08, 0x09, 0xe1, 0x25, 0xe3, 0xb9, 0x1e, 0xf4, 0x1e, 0xcf, 0xe2, + 0xef, 0xca, 0xf0, 0x2d, 0x1c, 0x00, 0xf9, 0xdd, 0x88, 0x1f, 0x0c, 0xdd, 0x2e, + 0x03, 0xd2, 0x05, 0x0a, 0xe4, 0x35, 0x0a, 0x2b, 0xbb, 0xb6, 0x09, 0xbc, 0xe5, + 0xfd, 0xeb, 0xd3, 0xe6, 0xdc, 0x08, 0xd8, 0x39, 0x1d, 0xf0, 0x3b, 0xe1, 0x04, + 0xfa, 0x0a, 0xf5, 0xe4, 0x13, 0xd6, 0x2e, 0x08, 0x05, 0x18, 0xa6, 0xd3, 0xd9, + 0x3f, 0x31, 0xb7, 0x08, 0x8e, 0x10, 0x21, 0xda, 0x1d, 0xe8, 0xe7, 0xf2, 0x1a, + 0x06, 0xba, 0xd7, 0x09, 0x01, 0xcd, 0xf7, 0xb1, 0xe6, 0x01, 0xfe, 0xf6, 0xe8, + 0xe0, 0xc5, 0xd5, 0xdc, 0xbc, 0xff, 0xb1, 0x1e, 0x2c, 0xd5, 0xf6, 0xed, 0x42, + 0xb0, 0x07, 0x08, 0x1c, 0xe9, 0x30, 0xf3, 0xde, 0xcf, 0x16, 0x2d, 0xf1, 0x28, + 0xe1, 0xd2, 0x20, 0x1c, 0xe8, 0xfb, 0x17, 0xe1, 0x23, 0xe5, 0xd1, 0xfc, 0xee, + 0x0e, 0x20, 0x0e, 0x15, 0x11, 0xc7, 0x1a, 0x00, 0x17, 0xc6, 0x24, 0xd6, 0x05, + 0x1f, 0x08, 0xfc, 0x08, 0xef, 0xf7, 0xf4, 0xc6, 0xd1, 0xe1, 0x29, 0xe6, 0xed, + 0x0b, 0xb6, 0x19, 0xf5, 0xea, 0x2a, 0x25, 0xfc, 0xa5, 0xd9, 0x1f, 0x3f, 0x30, + 0x00, 0x01, 0x29, 0xdb, 0x06, 0xf3, 0x24, 0xa9, 0x21, 0x1f, 0x16, 0x13, 0x03, + 0x1d, 0x2c, 0x04, 0xea, 0xf7, 0xe3, 0xee, 0x43, 0x20, 0x40, 0xfc, 0x38, 0xcd, + 0x5c, 0xfb, 0x36, 0xd6, 0xd5, 0x30, 0xbd, 0xeb, 0xe3, 0x0a, 0xd4, 0xec, 0xef, + 0xfb, 0xd2, 0xf5, 0x08, 0xe8, 0x0a, 0xfb, 0xe1, 0x32, 0x81, 0x2f, 0xc8, 0x38, + 0xf4, 0x1a, 0xd2, 0xac, 0xd2, 0x02, 0x1c, 0xd1, 0xef, 0xf9, 0xad, 0xe8, 0xee, + 0xf3, 0x13, 0xff, 0x16, 0xa1, 0xa7, 0xd4, 0xf2, 0xee, 0x21, 0x00, 0x19, 0x30, + 0x40, 0xd8, 0x0f, 0x19, 0x16, 0x4d, 0x3a, 0x1c, 0xb3, 0xea, 0x00, 0xff, 0x88, + 0xfd, 0xfe, 0xc6, 0x38, 0x02, 0xe9, 0x06, 0xfe, 0x2a, 0x3a, 0x11, 0x10, 0xf4, + 0x11, 0xef, 0xf7, 0xea, 0xf9, 0x28, 0xd1, 0x17, 0xdb, 0xbe, 0x07, 0x46, 0xe6, + 0x94, 0x02, 0xe8, 0x12, 0x06, 0x09, 0x06, 0xf5, 0xbd, 0xb4, 0xda, 0xd2, 0x32, + 0xd9, 0x2a, 0xa1, 0x3a, 0x3c, 0xe1, 0xe2, 0x26, 0x2a, 0x12, 0xc2, 0xeb, 0x01, + 0xbe, 0xf6, 0x1f, 0x5d, 0x36, 0xff, 0x04, 0x09, 0xcb, 0x19, 0x23, 0x10, 0xfc, + 0xc8, 0xce, 0x10, 0x18, 0x0c, 0x08, 0xc7, 0xe6, 0x0f, 0xe5, 0xd1, 0xf0, 0xda, + 0xd5, 0xe0, 0xc2, 0x24, 0xda, 0xe2, 0x0a, 0xf9, 0xec, 0x4d, 0x8c, 0xdf, 0xde, + 0xfe, 0x1a, 0xf0, 0xc1, 0xc3, 0xcd, 0x2b, 0xe9, 0x0e, 0xc9, 0xa6, 0x35, 0xee, + 0x2c, 0xe2, 0x4d, 0xfd, 0x1e, 0xfc, 0xf7, 0xc9, 0x4d, 0x27, 0xaf, 0xde, 0xd3, + 0xb2, 0xd9, 0xfb, 0xef, 0x27, 0xfd, 0x0f, 0x1a, 0xef, 0x96, 0xc4, 0x23, 0xf1, + 0xdc, 0x0c, 0x07, 0x0f, 0xeb, 0x34, 0xf7, 0x2a, 0x17, 0xf5, 0xdf, 0x09, 0x9f, + 0xdb, 0xf2, 0xb5, 0xe4, 0xf0, 0x1e, 0x3e, 0xe4, 0x4b, 0x15, 0x0b, 0xb3, 0x11, + 0xdb, 0xf4, 0xef, 0x50, 0x1f, 0x3f, 0x24, 0x46, 0xda, 0xdf, 0x0b, 0x30, 0x82, + 0xf8, 0xbd, 0xff, 0xdb, 0xdd, 0x15, 0xe8, 0x3f, 0xba, 0x3c, 0xc9, 0x3e, 0x19, + 0xb7, 0xcc, 0xee, 0xf3, 0xf2, 0xb9, 0x36, 0x25, 0x1e, 0x2c, 0x0c, 0xbf, 0x07, + 0xf1, 0xc7, 0x12, 0xfb, 0xda, 0x49, 0x2d, 0xb1, 0xbf, 0xe7, 0xce, 0x0e, 0xf9, + 0x2f, 0xe4, 0x09, 0x1c, 0xe3, 0xd2, 0x47, 0xc7, 0xf0, 0xe3, 0x3a, 0xab, 0xd1, + 0xf2, 0xf3, 0xf2, 0xb5, 0x21, 0xe5, 0xe0, 0xde, 0x13, 0xfc, 0xb6, 0x04, 0xf0, + 0xd5, 0x99, 0xe3, 0xfb, 0xbb, 0x04, 0xe3, 0xfa, 0xc8, 0xf2, 0x15, 0xdd, 0xc8, + 0xb1, 0x28, 0x0b, 0xad, 0x1d, 0x21, 0xe9, 0x23, 0xd4, 0xd0, 0xe8, 0xc0, 0xc8, + 0xe5, 0x12, 0x11, 0x14, 0xda, 0x09, 0xf8, 0xcc, 0x0f, 0xe2, 0x22, 0xcc, 0xfd, + 0x03, 0xb1, 0x9e, 0xde, 0xbc, 0x3a, 0x14, 0x2d, 0xe1, 0xe5, 0xc6, 0xd9, 0x9b, + 0xec, 0x05, 0xa3, 0x20, 0x30, 0xc1, 0xfc, 0x26, 0xe3, 0x3f, 0x1e, 0xff, 0xe3, + 0x0d, 0x50, 0x01, 0x9e, 0xd6, 0xff, 0xae, 0x18, 0x01, 0x2b, 0x49, 0x0b, 0x5d, + 0x0b, 0xf0, 0xed, 0x06, 0x2f, 0x4c, 0x3d, 0x0d, 0xd2, 0xd4, 0x7f, 0xfc, 0xf1, + 0x49, 0x10, 0xe1, 0xf6, 0xf4, 0x92, 0x2e, 0xdf, 0xed, 0x1a, 0x01, 0x17, 0x08, + 0xe2, 0xee, 0x49, 0x10, 0x8f, 0x0b, 0xde, 0x2c, 0xe8, 0x1b, 0x07, 0xbf, 0xce, + 0xc3, 0xee, 0xfa, 0x2b, 0xe7, 0xd4, 0x25, 0x05, 0xd0, 0x1d, 0xbd, 0xb1, 0xbd, + 0xfa, 0x0d, 0xd8, 0xff, 0xe2, 0x14, 0xfc, 0xf8, 0x16, 0xca, 0xf9, 0x33, 0xef, + 0x17, 0xd3, 0x2a, 0xed, 0xa4, 0x50, 0xda, 0x3b, 0x51, 0xe0, 0x5f, 0xf8, 0x03, + 0x35, 0xb8, 0xdc, 0xc5, 0xe4, 0x1c, 0x10, 0x9e, 0xe2, 0xe2, 0xba, 0xd7, 0xdb, + 0x42, 0xb5, 0xe3, 0xd4, 0xf1, 0x07, 0xeb, 0xfe, 0xe7, 0xfa, 0xa1, 0xfa, 0x38, + 0x1a, 0xc8, 0xe9, 0x41, 0xed, 0xe6, 0x9a, 0xac, 0xf1, 0x26, 0xff, 0x25, 0xc5, + 0xf4, 0xe8, 0xb6, 0xfe, 0x4e, 0xff, 0x24, 0xda, 0x21, 0xfb, 0xa5, 0x22, 0xf2, + 0xbc, 0xd2, 0xef, 0x02, 0xfd, 0xf1, 0xb2, 0xf0, 0x6a, 0xbd, 0x10, 0xe5, 0x53, + 0xe6, 0x3a, 0x18, 0x8b, 0xfb, 0x0e, 0x32, 0x24, 0xe9, 0x7f, 0x0e, 0xd2, 0x1f, + 0x32, 0xc6, 0xf0, 0xb3, 0xa1, 0xf7, 0x14, 0x3f, 0x13, 0xdf, 0xb5, 0xe9, 0xb8, + 0xc8, 0xe6, 0xe4, 0x09, 0xf6, 0x2d, 0x29, 0xf3, 0x67, 0x10, 0x0e, 0xdd, 0x27, + 0x1e, 0x0d, 0xc3, 0xd7, 0x0b, 0x38, 0x55, 0xc8, 0xee, 0xb1, 0xce, 0xf7, 0xd0, + 0xe2, 0xf4, 0xc2, 0xee, 0xd2, 0xe1, 0xf0, 0x39, 0x91, 0x4a, 0xfa, 0x9c, 0xfe, + 0x33, 0xcc, 0x15, 0xba, 0xe4, 0x9d, 0x00, 0x1e, 0xe6, 0xe8, 0x74, 0x25, 0x50, + 0xdd, 0xd3, 0x58, 0xf8, 0xed, 0xf2, 0xda, 0x67, 0xc5, 0xf9, 0x30, 0x21, 0xf7, + 0xfa, 0xdf, 0x75, 0x1d, 0xf3, 0xf9, 0xb1, 0xb3, 0xc8, 0x52, 0x2c, 0x95, 0xdb, + 0xfd, 0xe0, 0xb7, 0xde, 0x52, 0xf1, 0x50, 0xf3, 0xf9, 0xe1, 0xec, 0x1d, 0x12, + 0xe4, 0xbd, 0x23, 0x0b, 0xf0, 0xbb, 0x49, 0x38, 0xd0, 0xcc, 0x20, 0xff, 0x14, + 0xf9, 0xe3, 0xd8, 0xcb, 0xf8, 0xf7, 0xf9, 0xe9, 0xe4, 0xdb, 0xd0, 0xcc, 0xea, + 0x3c, 0x1c, 0xf2, 0xbc, 0x26, 0xf6, 0x06, 0xe3, 0x00, 0x0c, 0xf4, 0xff, 0xfb, + 0x15, 0xf8, 0x01, 0x2c, 0x05, 0xbb, 0xc6, 0x07, 0xc6, 0xf5, 0x3b, 0x2d, 0x1a, + 0xf2, 0x2f, 0xcd, 0xc9, 0xfa, 0xf3, 0x03, 0x35, 0xe8, 0x19, 0xde, 0xcc, 0xef, + 0x31, 0xf1, 0xee, 0x2e, 0x5e, 0xc9, 0x05, 0x7b, 0x1c, 0xb9, 0xbc, 0x09, 0x4a, + 0x30, 0x08, 0x01, 0xea, 0xd6, 0xe7, 0xb6, 0xcb, 0x0a, 0xd8, 0xe0, 0x0c, 0x11, + 0x09, 0x0c, 0x22, 0xe1, 0xe9, 0x13, 0xc4, 0x01, 0x18, 0xe3, 0xd0, 0xf3, 0x28, + 0x0b, 0xc1, 0xc2, 0xd4, 0xff, 0xf0, 0x16, 0x5f, 0x33, 0x16, 0xcb, 0xd4, 0xb7, + 0xde, 0xd2, 0x16, 0xde, 0xf2, 0xfe, 0xb4, 0xdf, 0xb2, 0x1b, 0xb6, 0x9e, 0xf7, + 0xfe, 0xbf, 0xaf, 0x21, 0xae, 0x2a, 0x23, 0xdb, 0xe7, 0xe9, 0x1b, 0xcd, 0x1d, + 0x17, 0xae, 0xdb, 0x32, 0x42, 0xb9, 0xc8, 0xf2, 0x0a, 0xfc, 0xe1, 0xb2, 0xd7, + 0xd6, 0xe5, 0xeb, 0x4b, 0xd0, 0x45, 0xcb, 0xa7, 0x12, 0xd0, 0x31, 0xe4, 0x8b, + 0x03, 0x38, 0x00, 0xbd, 0x28, 0xea, 0xf4, 0xf3, 0x2c, 0xfa, 0xad, 0x27, 0xf4, + 0xdd, 0x63, 0xdc, 0xf3, 0xd7, 0xd1, 0x7f, 0xfa, 0x34, 0x1b, 0x23, 0xbc, 0xf7, + 0xe0, 0x20, 0x26, 0x24, 0xd2, 0xa3, 0x16, 0xe7, 0xf0, 0xd2, 0xf9, 0xa7, 0xbe, + 0xd7, 0xec, 0x12, 0x07, 0x13, 0x00, 0x0f, 0xdc, 0x50, 0x10, 0xf3, 0xad, 0x38, + 0x93, 0x13, 0xf5, 0x01, 0xb5, 0xbd, 0xe4, 0xd3, 0x0a, 0xe2, 0x28, 0x3e, 0x2d, + 0x20, 0x1c, 0xea, 0xd8, 0xb6, 0x53, 0xe6, 0xca, 0x0b, 0xf1, 0x0e, 0xa9, 0x1e, + 0x07, 0x2f, 0x4f, 0xf1, 0xe0, 0xc3, 0xc6, 0xce, 0x01, 0x09, 0xd0, 0x0d, 0x18, + 0x25, 0x30, 0x17, 0x9d, 0x33, 0x60, 0xfa, 0x07, 0x40, 0xd6, 0x0a, 0x0a, 0x21, + 0xfe, 0xb5, 0x0d, 0x12, 0xe5, 0xe2, 0xce, 0xdf, 0x01, 0xdf, 0xd0, 0x0c, 0x27, + 0x22, 0x28, 0x21, 0x2c, 0xf2, 0x51, 0x2d, 0x1b, 0xc3, 0x2c, 0xb5, 0x07, 0xd1, + 0xd4, 0x30, 0xee, 0xd9, 0x24, 0xf5, 0x13, 0xe2, 0xc9, 0x14, 0x10, 0x19, 0xbc, + 0x00, 0xfd, 0xd1, 0xe4, 0xd8, 0x13, 0xb3, 0xdc, 0xef, 0xcd, 0xe1, 0x40, 0x1c, + 0xd7, 0xdf, 0x17, 0x1c, 0xf5, 0xe4, 0xf0, 0xcc, 0xe8, 0xd4, 0x11, 0xdd, 0xbb, + 0x34, 0xf3, 0x38, 0x09, 0x3f, 0x1a, 0xef, 0xf8, 0xee, 0xd2, 0x35, 0xe9, 0x22, + 0xd1, 0xd0, 0x36, 0x07, 0xfe, 0x1b, 0xfe, 0xd1, 0x06, 0xee, 0xd8, 0x9c, 0xee, + 0xe9, 0x24, 0x27, 0x09, 0xd1, 0x02, 0xcc, 0x34, 0xf7, 0x7f, 0x2f, 0x02, 0x09, + 0xc1, 0xea, 0xd3, 0x1c, 0x3c, 0xe8, 0xe6, 0x09, 0xda, 0xf9, 0xda, 0xe1, 0xf3, + 0x38, 0x20, 0xb9, 0x0d, 0x14, 0xeb, 0xef, 0xfd, 0xb3, 0xe6, 0x07, 0x1a, 0xff, + 0xf0, 0x1a, 0x2f, 0xc3, 0x12, 0x31, 0xf0, 0xed, 0x3c, 0xd1, 0x03, 0x2b, 0xb3, + 0x18, 0xc0, 0x9b, 0xed, 0x23, 0x1d, 0xd9, 0xc2, 0x07, 0xf9, 0x28, 0x15, 0x08, + 0x1a, 0xc5, 0x04, 0xc6, 0x19, 0xe5, 0x0c, 0x4c, 0x05, 0x09, 0xda, 0xff, 0x02, + 0x2f, 0xe9, 0x0a, 0xdf, 0xa0, 0x03, 0x21, 0x31, 0x11, 0xff, 0x07, 0x4d, 0xd7, + 0x07, 0x46, 0xdc, 0xcf, 0x08, 0xe9, 0xf8, 0xef, 0xa3, 0x38, 0x02, 0x28, 0x1b, + 0x27, 0x95, 0xe5, 0x1d, 0x99, 0x94, 0xc4, 0x23, 0xeb, 0x0e, 0xb9, 0xaf, 0xcd, + 0x39, 0xfe, 0xfb, 0xeb, 0x01, 0x2e, 0xea, 0xd9, 0xf6, 0xf3, 0x0a, 0x19, 0xc4, + 0x21, 0x2e, 0xe4, 0x03, 0xdf, 0xfc, 0xec, 0xe9, 0xc3, 0x02, 0x2b, 0x4b, 0x0b, + 0xca, 0x0a, 0x4a, 0xbe, 0x14, 0x0a, 0xe9, 0x37, 0xa3, 0xbb, 0xb6, 0x3a, 0xd7, + 0x27, 0xb0, 0x05, 0xfe, 0xff, 0xe4, 0x0f, 0x8f, 0xf8, 0x19, 0x9e, 0xcc, 0xe9, + 0x46, 0xf8, 0xb9, 0xf7, 0xc5, 0xab, 0xfa, 0x09, 0x60, 0x24, 0xc8, 0x15, 0xa0, + 0x25, 0x07, 0xc6, 0xd3, 0xda, 0xf1, 0x3a, 0x2b, 0xd7, 0xe4, 0x18, 0xee, 0x54, + 0x1a, 0x03, 0x16, 0x18, 0xb6, 0xfb, 0xd9, 0x3f, 0x00, 0x09, 0x28, 0xe3, 0xdf, + 0xc9, 0x2c, 0x85, 0xf3, 0xf6, 0x16, 0xdc, 0xee, 0x0d, 0xfa, 0x2f, 0xf4, 0xde, + 0x1d, 0xd9, 0xd9, 0x36, 0x23, 0xd5, 0xec, 0x0f, 0x05, 0x00, 0x30, 0x3a, 0xdc, + 0x20, 0xcd, 0xb6, 0x45, 0x99, 0xca, 0x0c, 0x4a, 0x31, 0x12, 0xd8, 0xfa, 0xfd, + 0x17, 0x82, 0xbd, 0x06, 0xe3, 0x25, 0xbc, 0x37, 0xdc, 0xdf, 0xc2, 0xcb, 0x34, + 0xe4, 0xf9, 0xb7, 0xf4, 0x0d, 0x9b, 0xe3, 0xd2, 0x81, 0xd9, 0x46, 0xce, 0xae, + 0xb0, 0x68, 0xe0, 0x06, 0xec, 0xfd, 0x0e, 0x37, 0x0a, 0x24, 0x18, 0x0d, 0x13, + 0xa7, 0xdb, 0x02, 0x86, 0xb0, 0x25, 0xed, 0xcf, 0x01, 0xf5, 0xd2, 0xd5, 0xf1, + 0xf1, 0xf6, 0xc6, 0xd9, 0xda, 0xc8, 0x11, 0x28, 0x22, 0xae, 0xf9, 0x07, 0xe1, + 0xdb, 0xfc, 0x0b, 0x88, 0xd0, 0x02, 0xca, 0xe7, 0xfc, 0xd1, 0xb1, 0x10, 0x03, + 0x48, 0x08, 0xfd, 0x44, 0x35, 0x0b, 0xd7, 0x23, 0xf6, 0x19, 0xfe, 0x01, 0xf3, + 0x2e, 0xd5, 0x30, 0x45, 0x3e, 0x48, 0xb6, 0x19, 0x09, 0xf7, 0x07, 0x14, 0x20, + 0xfd, 0xd6, 0xd9, 0x23, 0x0f, 0x11, 0x02, 0x3f, 0xc6, 0xec, 0x24, 0x07, 0xe2, + 0xd9, 0xeb, 0xfd, 0xf9, 0xd4, 0x12, 0x14, 0x1d, 0x29, 0x1e, 0x29, 0x0b, 0xad, + 0x1e, 0x2d, 0x0a, 0xd6, 0xd7, 0xfb, 0x33, 0x30, 0xd0, 0xc7, 0xf3, 0x3f, 0xf4, + 0xf0, 0xe1, 0x46, 0x16, 0x55, 0xf9, 0x3e, 0xc9, 0x19, 0x1c, 0xec, 0xf2, 0xeb, + 0x9a, 0xc4, 0xf1, 0x05, 0xce, 0xe6, 0xea, 0xf5, 0xd0, 0x08, 0x25, 0x22, 0xdf, + 0xf7, 0xcd, 0xb2, 0x02, 0xfc, 0xce, 0xc8, 0xd1, 0xa6, 0x33, 0x02, 0x07, 0x21, + 0xf2, 0xb1, 0xd8, 0xef, 0xe0, 0xc2, 0xd6, 0xf7, 0xfd, 0xce, 0xc4, 0x08, 0xce, + 0x2d, 0x0e, 0x98, 0xff, 0xcb, 0xf3, 0xda, 0x40, 0x15, 0xf3, 0x10, 0xf7, 0xe1, + 0xc4, 0xe0, 0xc8, 0x10, 0xf3, 0xfc, 0x27, 0xc2, 0x1a, 0xc3, 0x18, 0xdf, 0xce, + 0xa5, 0xd0, 0x42, 0x24, 0xd5, 0x0f, 0xe6, 0xf8, 0xf8, 0xf1, 0x15, 0xf1, 0xbb, + 0x1b, 0xc1, 0x05, 0xfb, 0x41, 0xba, 0xf0, 0xce, 0x01, 0x43, 0xe6, 0xf2, 0x2d, + 0xea, 0xba, 0xde, 0xd4, 0x09, 0x04, 0xfc, 0xff, 0xdd, 0xcd, 0x21, 0x09, 0xfd, + 0x2b, 0xfa, 0xf5, 0xf7, 0x2b, 0xfe, 0x13, 0xd6, 0x07, 0x86, 0x33, 0xe8, 0x13, + 0x0f, 0x03, 0xcf, 0xa3, 0xc1, 0x0d, 0x08, 0x2b, 0xd6, 0xe0, 0xce, 0x0a, 0xf5, + 0xf3, 0x04, 0xdf, 0xb0, 0xe9, 0xf4, 0x13, 0xfb, 0xa8, 0xd9, 0xd9, 0xfe, 0x0f, + 0xbe, 0xc9, 0x25, 0x35, 0x03, 0xcf, 0xe3, 0xe0, 0xf0, 0x56, 0x0e, 0xf1, 0x2b, + 0x1e, 0xf0, 0x07, 0xf0, 0x15, 0x9e, 0xc6, 0xf2, 0xfc, 0x1e, 0xa6, 0xb1, 0xed, + 0x2a, 0x25, 0x22, 0x32, 0x13, 0xbf, 0xc3, 0x0d, 0x18, 0xd3, 0xf6, 0x02, 0x02, + 0xe3, 0x22, 0x76, 0xfd, 0xdd, 0xdd, 0xed, 0xde, 0xe4, 0xd9, 0xa0, 0x26, 0xdb, + 0xbd, 0xf1, 0x1a, 0xae, 0xf7, 0xd3, 0xc0, 0xf1, 0xc7, 0xf3, 0xc9, 0xfe, 0x31, + 0x84, 0xb1, 0xc5, 0x46, 0xf4, 0xfc, 0x49, 0xf5, 0xcf, 0x16, 0xe8, 0xef, 0xe1, + 0x0a, 0xfd, 0xcd, 0xd1, 0xff, 0xf3, 0xf1, 0xf7, 0xf5, 0xec, 0xc5, 0x11, 0xd7, + 0xd4, 0x15, 0x13, 0xae, 0xe5, 0xe7, 0x34, 0xdb, 0x0f, 0x1b, 0x23, 0x9b, 0xc9, + 0xbf, 0xdd, 0x7f, 0xfa, 0x00, 0x04, 0xbc, 0xa6, 0xcb, 0xf2, 0x0e, 0xbc, 0xec, + 0x96, 0xeb, 0xf9, 0xe8, 0xe0, 0x1d, 0x97, 0xfa, 0xf0, 0xfc, 0xf3, 0x19, 0xd1, + 0x1c, 0x1b, 0xd9, 0xf0, 0xb2, 0x1f, 0xd0, 0x1e, 0x2b, 0xfc, 0x00, 0xe1, 0x0d, + 0x19, 0xf1, 0xf9, 0x08, 0xeb, 0xcd, 0xca, 0xed, 0xbf, 0xdb, 0x08, 0x2f, 0x0e, + 0xeb, 0x9f, 0xc9, 0xc4, 0x1c, 0x0b, 0xce, 0xbf, 0x28, 0x09, 0x0d, 0x3e, 0x29, + 0xc5, 0x18, 0x30, 0xf1, 0x4b, 0xed, 0xff, 0xe2, 0xec, 0xf0, 0x09, 0xd4, 0x6c, + 0x39, 0xcd, 0x21, 0xd3, 0x5b, 0x0f, 0x0c, 0xd1, 0xf2, 0x2d, 0xe3, 0x0d, 0xdd, + 0x07, 0xb1, 0x33, 0xe5, 0xb9, 0x1b, 0xc7, 0x04, 0x10, 0xf4, 0xc2, 0x4d, 0x16, + 0x98, 0xe1, 0x1c, 0xe4, 0x31, 0xfb, 0xe0, 0x00, 0x07, 0x43, 0x0e, 0xe2, 0xde, + 0xd4, 0xb1, 0x14, 0xec, 0x7f, 0xdc, 0xf2, 0xee, 0xc4, 0xd4, 0x53, 0x19, 0xe3, + 0xfb, 0xf1, 0xdb, 0xb4, 0x06, 0xb9, 0xc3, 0x16, 0x06, 0xfb, 0x00, 0xd0, 0xc9, + 0xee, 0x04, 0x50, 0x42, 0xaa, 0xbd, 0xbb, 0xe1, 0xde, 0x1c, 0xfc, 0xe2, 0xcf, + 0xb4, 0x0f, 0xeb, 0xff, 0x88, 0x4f, 0x0f, 0x9c, 0xd3, 0xe2, 0xd7, 0xdb, 0x18, + 0x1d, 0xfc, 0xef, 0xca, 0x31, 0xfc, 0x1b, 0x1b, 0xa6, 0xdd, 0xfd, 0xfc, 0x0b, + 0x4a, 0x0f, 0x1c, 0xda, 0x8d, 0x3b, 0x1b, 0xe7, 0x0d, 0xde, 0xd1, 0x15, 0x11, + 0xcf, 0x0b, 0x29, 0x19, 0x03, 0x31, 0xf0, 0x5a, 0xf0, 0xc4, 0xdd, 0x3e, 0x25, + 0xfd, 0xd3, 0xdc, 0xe8, 0xda, 0xb8, 0xc7, 0xff, 0xe6, 0xf2, 0xc7, 0x07, 0xd5, + 0x1f, 0xfa, 0xc4, 0x36, 0xb4, 0x2f, 0xe1, 0xd5, 0xfb, 0x15, 0x1b, 0x08, 0xee, + 0xda, 0xd2, 0xec, 0xbc, 0x0f, 0x1a, 0xc3, 0xeb, 0xec, 0xfa, 0x0f, 0xc9, 0x3c, + 0x5b, 0x00, 0x33, 0xfd, 0x01, 0x1d, 0xcc, 0xe2, 0x3b, 0x43, 0xcd, 0x56, 0x39, + 0x09, 0x0e, 0xc3, 0xd1, 0xfd, 0xbb, 0x30, 0xdb, 0x53, 0x1a, 0xb4, 0x2f, 0x11, + 0xfc, 0x13, 0x2f, 0xeb, 0xc8, 0xd3, 0x26, 0xf7, 0x24, 0x1f, 0xd0, 0xe5, 0xdc, + 0x36, 0xec, 0xd1, 0x2f, 0xc8, 0x28, 0xe4, 0xd1, 0x52, 0x24, 0x24, 0xe5, 0xf2, + 0x0b, 0xc4, 0xf5, 0xcf, 0x38, 0xdc, 0x2a, 0x26, 0xe6, 0xdc, 0xc0, 0xec, 0xd8, + 0xda, 0xf7, 0xd1, 0xf7, 0xfb, 0x06, 0xf7, 0xd7, 0x19, 0x2b, 0xf4, 0xff, 0xf8, + 0x19, 0xd2, 0xe4, 0xba, 0x1b, 0xd7, 0x1b, 0x22, 0xfc, 0x53, 0xef, 0xee, 0x21, + 0x9d, 0xe3, 0xf0, 0x14, 0xe7, 0xa4, 0x0e, 0x0a, 0xd5, 0x23, 0x1a, 0x2b, 0xe5, + 0x1a, 0x14, 0x0b, 0xf1, 0xe7, 0xe6, 0xdd, 0x09, 0x0f, 0x03, 0xeb, 0x09, 0x18, + 0x19, 0x31, 0xae, 0xf0, 0x29, 0x09, 0x0a, 0xe2, 0xe5, 0xe3, 0xcc, 0xfb, 0x02, + 0x03, 0xa9, 0xee, 0x18, 0xf0, 0xfe, 0xca, 0xed, 0xd2, 0xfb, 0xf4, 0xe2, 0xf7, + 0x05, 0x07, 0xdc, 0xf0, 0xf1, 0xe5, 0x11, 0x26, 0xc3, 0xaf, 0x0f, 0xf6, 0x0f, + 0x25, 0xc2, 0xd8, 0x10, 0x11, 0x1f, 0x19, 0x05, 0xfa, 0xfb, 0xd2, 0xe9, 0xf8, + 0xcc, 0xb5, 0xf3, 0xdb, 0xc8, 0x4a, 0xe7, 0xf7, 0x1b, 0x1a, 0x2c, 0xfa, 0xcd, + 0x00, 0x23, 0x33, 0xce, 0xb3, 0x13, 0xa8, 0x01, 0xc5, 0x0d, 0x32, 0xee, 0xe2, + 0xef, 0x25, 0xcd, 0xe8, 0xf3, 0x18, 0xe0, 0xf0, 0x2a, 0xde, 0x7f, 0x4a, 0xac, + 0x1a, 0x04, 0x17, 0x01, 0xe8, 0xdb, 0xdc, 0x2a, 0xf0, 0xe4, 0x11, 0x01, 0x2c, + 0x09, 0x16, 0x0f, 0xda, 0x40, 0xd8, 0x1d, 0x12, 0x0c, 0x10, 0x3a, 0xe6, 0xef, + 0x22, 0xd6, 0xad, 0xda, 0x53, 0x0b, 0x20, 0x26, 0x15, 0xb9, 0x1b, 0xe0, 0x37, + 0x09, 0xd2, 0xf3, 0xf9, 0xd7, 0xc4, 0x16, 0xcf, 0xdc, 0x16, 0xec, 0x1c, 0x23, + 0xc5, 0xe9, 0xe5, 0xca, 0x20, 0xb9, 0x10, 0xe7, 0x10, 0x51, 0x0f, 0xdd, 0x4f, + 0x21, 0x16, 0x28, 0xc1, 0xb8, 0xe3, 0x06, 0xe0, 0x12, 0x0a, 0xb5, 0x0c, 0x39, + 0x27, 0xe2, 0x02, 0x00, 0xbb, 0x4b, 0x0b, 0xaa, 0xc7, 0xf6, 0x47, 0x2d, 0xdf, + 0x0d, 0xfd, 0xf8, 0xba, 0xf0, 0xe9, 0x08, 0xdd, 0x00, 0xe4, 0xf2, 0xf6, 0xec, + 0x04, 0xc0, 0x36, 0x19, 0xd0, 0x03, 0xf9, 0xaf, 0xbc, 0xf0, 0xda, 0x21, 0xe7, + 0xc9, 0xba, 0x4f, 0xa7, 0xcc, 0xf8, 0x2f, 0xe5, 0x71, 0xe8, 0x0a, 0x38, 0xc5, + 0x15, 0xdb, 0x0f, 0x10, 0xff, 0x30, 0x02, 0xe3, 0x35, 0x0e, 0xf5, 0x24, 0xfa, + 0x32, 0xc9, 0x49, 0xf0, 0xf7, 0x1a, 0xf5, 0x0a, 0xd3, 0xb4, 0xe9, 0x0a, 0xcc, + 0x0e, 0xc0, 0xd7, 0xf4, 0x0e, 0x35, 0x1b, 0xcd, 0xf0, 0xc6, 0x01, 0x26, 0xba, + 0x10, 0xe3, 0x4b, 0x39, 0x2e, 0xbe, 0xfc, 0xd3, 0xfb, 0xf0, 0x10, 0x3a, 0xbf, + 0x09, 0xc3, 0xb3, 0xd0, 0xcb, 0xf6, 0x42, 0x06, 0x0a, 0xea, 0xca, 0x1c, 0x19, + 0x35, 0x2c, 0xdf, 0xed, 0x0e, 0x09, 0xfe, 0x08, 0x03, 0xde, 0xbb, 0xe3, 0xe6, + 0xc6, 0x2e, 0xff, 0xe2, 0xe7, 0x0c, 0x1f, 0xce, 0xf2, 0x05, 0xbc, 0xdc, 0xfe, + 0xed, 0x1b, 0x24, 0xa3, 0xe9, 0xd6, 0x0f, 0x20, 0x7f, 0x01, 0xed, 0x03, 0x3e, + 0xd9, 0xdd, 0x0a, 0xf8, 0x3e, 0xe6, 0xd5, 0xf6, 0xfc, 0xe4, 0xc9, 0xf3, 0xdd, + 0xba, 0x04, 0x1a, 0x04, 0x30, 0x26, 0xe1, 0xda, 0x49, 0xe1, 0xab, 0xfa, 0x22, + 0xe6, 0xc6, 0x0e, 0xe3, 0xd8, 0x1a, 0x1b, 0xd4, 0xd7, 0xfa, 0x20, 0xee, 0xf5, + 0xf9, 0x16, 0x0b, 0xdd, 0xd2, 0x12, 0xff, 0x51, 0xec, 0xf7, 0xdd, 0xb1, 0xec, + 0xe2, 0xfe, 0xfb, 0xd3, 0x38, 0xd2, 0xfc, 0xb7, 0xee, 0x0d, 0xf0, 0xe7, 0xed, + 0xce, 0x1b, 0x2e, 0x2a, 0x24, 0xe3, 0xeb, 0x30, 0x03, 0x0e, 0xd0, 0x04, 0xdd, + 0x3b, 0xdf, 0x49, 0x1d, 0xe5, 0x05, 0xeb, 0x07, 0xcb, 0x24, 0x23, 0xc2, 0xed, + 0xf4, 0xeb, 0xc6, 0xb7, 0x5c, 0xf0, 0xe7, 0x69, 0xf7, 0x05, 0x16, 0xc1, 0xdb, + 0xfa, 0x2b, 0xe1, 0x19, 0xe2, 0xa7, 0x0a, 0xb7, 0xf0, 0x40, 0xd2, 0xc1, 0xb8, + 0x2f, 0xc3, 0xeb, 0xcd, 0xf9, 0xe2, 0xfd, 0x0f, 0x0a, 0xe3, 0x18, 0x19, 0xa5, + 0x0d, 0xed, 0xf0, 0xcc, 0xe8, 0xed, 0xf3, 0x2a, 0x09, 0xb1, 0xf7, 0xd9, 0x3d, + 0xf6, 0x42, 0xff, 0x31, 0xdf, 0x09, 0xd0, 0x1b, 0xb8, 0xd6, 0xeb, 0x48, 0xfd, + 0x00, 0xb7, 0x05, 0xf7, 0x12, 0x01, 0x1a, 0x05, 0xcc, 0xf3, 0xe6, 0xeb, 0xcf, + 0x1f, 0xc5, 0x23, 0x00, 0x33, 0xbd, 0xf7, 0xd9, 0xb7, 0x18, 0xec, 0xa7, 0xee, + 0xf4, 0xb4, 0xf2, 0x01, 0xc7, 0x1e, 0x1b, 0xf2, 0xc7, 0x0a, 0x07, 0x17, 0x1c, + 0xbf, 0xc8, 0x32, 0x1a, 0x1c, 0xe7, 0x96, 0xf6, 0xfd, 0x34, 0x0e, 0xf8, 0xf2, + 0x10, 0x14, 0xdb, 0x02, 0x2c, 0xed, 0xef, 0x18, 0xe4, 0x16, 0xdd, 0xd9, 0xea, + 0xf2, 0x1c, 0x24, 0x13, 0x07, 0x17, 0xe1, 0x1d, 0xe9, 0xd2, 0xbe, 0xe6, 0xfe, + 0x30, 0x3e, 0x1a, 0x2f, 0x0a, 0x06, 0xdb, 0x01, 0xe0, 0x16, 0xb3, 0x1a, 0x1f, + 0xd4, 0x05, 0xea, 0xfd, 0xcb, 0x13, 0x08, 0xb8, 0x2a, 0xb6, 0xf8, 0xeb, 0x29, + 0x22, 0x3b, 0x2e, 0xf2, 0xe7, 0x10, 0xea, 0xd3, 0xf2, 0xf5, 0x14, 0x17, 0x03, + 0x29, 0x17, 0xe5, 0xfb, 0xf1, 0xc7, 0xd3, 0xb9, 0x10, 0x06, 0xcf, 0x96, 0xeb, + 0x13, 0x02, 0xd7, 0x42, 0xfd, 0xb8, 0xf0, 0xf3, 0xf9, 0x07, 0xc3, 0xe9, 0xf4, + 0x1a, 0xd5, 0xf0, 0xbf, 0x24, 0xd6, 0x17, 0xe4, 0xd6, 0x0e, 0x0d, 0xe8, 0x0e, + 0x0a, 0x44, 0xef, 0xad, 0x0f, 0xeb, 0x3b, 0xd2, 0x33, 0x32, 0xc8, 0xf5, 0x2c, + 0x47, 0xcb, 0x1c, 0x2a, 0xee, 0x31, 0x81, 0xd0, 0xe2, 0xdb, 0x10, 0xdb, 0x31, + 0xfd, 0xe6, 0x16, 0xc6, 0x40, 0xdb, 0x26, 0xf4, 0xfe, 0x2e, 0xe8, 0xc0, 0xf7, + 0x1a, 0xbb, 0xd5, 0x0f, 0x35, 0xfd, 0xf8, 0xee, 0xbc, 0x06, 0xd0, 0x0e, 0xd5, + 0xc6, 0xf9, 0xbe, 0xf5, 0xbe, 0xc8, 0xf0, 0x11, 0xfc, 0xe6, 0x01, 0xf9, 0xe7, + 0x1e, 0x27, 0xdb, 0xdb, 0xdd, 0x10, 0x1c, 0xee, 0x0f, 0x06, 0xdc, 0x2b, 0x1d, + 0xfc, 0x35, 0xf8, 0x43, 0x07, 0x05, 0xc2, 0x17, 0x36, 0xe8, 0x12, 0x13, 0x08, + 0xfd, 0xf0, 0xb3, 0xcf, 0x4f, 0xe5, 0xea, 0x2e, 0xfd, 0xfa, 0xe7, 0x26, 0x1f, + 0xee, 0xe7, 0x2f, 0xe0, 0x0c, 0x1c, 0x29, 0x11, 0x16, 0x25, 0xe4, 0x1e, 0x14, + 0x00, 0xfe, 0xd5, 0xf7, 0xe3, 0xe7, 0x13, 0xc0, 0xf5, 0xc0, 0x24, 0x0a, 0xed, + 0xf9, 0xe0, 0xc6, 0xe5, 0x10, 0x0e, 0xe6, 0xda, 0x16, 0x1b, 0x11, 0xf9, 0xf5, + 0xf1, 0xd2, 0xe8, 0xd3, 0x02, 0xd6, 0xde, 0x07, 0x1f, 0x07, 0xdc, 0xc8, 0x00, + 0x07, 0xe9, 0x40, 0x16, 0xef, 0xfa, 0xfa, 0xe3, 0x0d, 0xef, 0xdc, 0x2e, 0x03, + 0xf5, 0xc9, 0xc5, 0xda, 0xbb, 0xea, 0xb0, 0xd3, 0xfd, 0x0e, 0x02, 0x05, 0xf2, + 0xdf, 0x18, 0x94, 0xe5, 0xf1, 0xea, 0x0a, 0x08, 0x3e, 0xdf, 0xe5, 0xd2, 0x1a, + 0xb9, 0xea, 0xe4, 0x25, 0x33, 0x24, 0x2c, 0x05, 0x14, 0x7f, 0xef, 0xef, 0x2d, + 0xf1, 0xe5, 0x15, 0xdf, 0xf7, 0xa0, 0x2f, 0xf4, 0xfb, 0x10, 0x0d, 0xd4, 0x00, + 0x07, 0xde, 0x33, 0xed, 0x14, 0xff, 0xfa, 0xe2, 0x51, 0xea, 0xa5, 0x2c, 0x16, + 0x0c, 0x1d, 0x01, 0xcf, 0xdd, 0xf6, 0xef, 0x1f, 0x12, 0x5a, 0x19, 0xc4, 0xee, + 0x07, 0xdf, 0xc3, 0x6a, 0xed, 0xdf, 0x49, 0x30, 0x2d, 0x08, 0x02, 0x0b, 0xf1, + 0xdd, 0xfc, 0x15, 0xd0, 0xbd, 0x03, 0x1c, 0xef, 0xdd, 0xe7, 0xba, 0x47, 0x45, + 0xb9, 0xbe, 0xd6, 0x2e, 0xcc, 0xab, 0xbc, 0x06, 0xe8, 0x07, 0xdf, 0x0f, 0xd9, + 0x07, 0x06, 0x1a, 0xb2, 0xe2, 0x25, 0xfd, 0xfa, 0x0d, 0x16, 0x04, 0xfa, 0x2b, + 0xda, 0x1a, 0x0e, 0xb7, 0xc5, 0xef, 0xbd, 0xe0, 0x85, 0xdb, 0x03, 0xf3, 0xd5, + 0xf7, 0x91, 0xc6, 0xad, 0x0e, 0xc6, 0xed, 0xea, 0x0f, 0xfb, 0xd1, 0xaf, 0x03, + 0x24, 0x26, 0x3e, 0xe2, 0x55, 0xe7, 0xd2, 0xe7, 0xbb, 0x01, 0xc2, 0x42, 0x23, + 0xe0, 0x24, 0x11, 0xb8, 0x55, 0xf8, 0x9d, 0xf4, 0xe4, 0x2d, 0x04, 0x8b, 0x29, + 0xca, 0xff, 0x1c, 0xfe, 0xd3, 0x3f, 0x30, 0x07, 0x4b, 0xfe, 0x2e, 0xb9, 0xff, + 0x2a, 0x59, 0x4e, 0xed, 0xcb, 0x01, 0xcc, 0x09, 0x2e, 0x42, 0x1c, 0xaf, 0x46, + 0xc9, 0xee, 0x9f, 0xc6, 0xbb, 0xeb, 0xbd, 0x11, 0x3e, 0xef, 0xef, 0x36, 0xa7, + 0xde, 0xc4, 0xc8, 0xee, 0x8d, 0xbc, 0x3b, 0xdd, 0x49, 0xe1, 0xb5, 0xc0, 0xe2, + 0xe3, 0x29, 0xd1, 0xfe, 0x1a, 0x03, 0x95, 0xe6, 0xe6, 0xca, 0xfd, 0xe6, 0x1b, + 0xf1, 0x14, 0x12, 0xed, 0xf0, 0x00, 0xc6, 0x2f, 0x02, 0xb7, 0x26, 0xf7, 0x9d, + 0x27, 0x91, 0xf7, 0x54, 0x38, 0xba, 0xea, 0xf8, 0xfc, 0xd9, 0xab, 0x37, 0x07, + 0x8e, 0xf2, 0x31, 0x0c, 0x1e, 0xd6, 0x0a, 0x09, 0xef, 0x81, 0x1c, 0xbc, 0x08, + 0x13, 0xe6, 0xf8, 0xb2, 0xdd, 0x11, 0x51, 0xe4, 0x50, 0xcc, 0xa9, 0x35, 0xf8, + 0x3c, 0x97, 0xd4, 0xce, 0xea, 0xf6, 0xe2, 0xd4, 0x58, 0xf4, 0xb6, 0x42, 0xe5, + 0x33, 0x4a, 0xfc, 0xdd, 0x35, 0x2a, 0xa3, 0x28, 0xe9, 0x5a, 0xa5, 0xe0, 0xf2, + 0xe5, 0x06, 0x23, 0x2e, 0x59, 0xdc, 0x3a, 0xec, 0x26, 0x2f, 0x32, 0xc9, 0xec, + 0xc4, 0x08, 0x0c, 0xcd, 0xe6, 0x5d, 0x39, 0x95, 0xd7, 0xc7, 0x34, 0x29, 0xcb, + 0xf3, 0xe6, 0xfc, 0x0c, 0xf2, 0xd6, 0xd8, 0x3f, 0x2b, 0x1e, 0x15, 0xf4, 0x0c, + 0x51, 0x05, 0x2b, 0x26, 0xd3, 0x08, 0x28, 0x07, 0xf5, 0xff, 0x24, 0x42, 0x0a, + 0xb4, 0x1e, 0xab, 0x2a, 0x18, 0x53, 0x94, 0xd3, 0xf6, 0xfa, 0x59, 0x47, 0xbb, + 0xd7, 0xd5, 0xbb, 0x53, 0xfd, 0xf3, 0xd7, 0xf8, 0xe0, 0x09, 0x37, 0x03, 0xc4, + 0x41, 0x5b, 0xc4, 0xdf, 0xef, 0xbf, 0x35, 0xbf, 0x29, 0xb8, 0xec, 0xac, 0xf9, + 0x9c, 0xc6, 0x29, 0xf4, 0xb1, 0xd4, 0x14, 0x79, 0x56, 0xdf, 0xf2, 0x2e, 0xfe, + 0x6c, 0xc2, 0xdc, 0xc7, 0x2e, 0x08, 0xca, 0xbf, 0x02, 0xc3, 0x2f, 0xdf, 0x1f, + 0xf1, 0xa6, 0xfb, 0xf7, 0x25, 0x04, 0x72, 0xe5, 0x00, 0x1c, 0xe0, 0x32, 0xd1, + 0x6b, 0xe4, 0xb7, 0xbe, 0x06, 0x52, 0xc4, 0x5a, 0x4c, 0x15, 0x15, 0xd5, 0xe0, + 0x35, 0x8c, 0x30, 0xcd, 0xc5, 0xfb, 0xdb, 0xd0, 0x2e, 0xc6, 0x23, 0x32, 0x06, + 0xd5, 0xbc, 0xad, 0x13, 0xc6, 0x41, 0x29, 0xe2, 0x29, 0xe3, 0x25, 0x00, 0x24, + 0x01, 0x3a, 0xe9, 0xdf, 0xd8, 0x16, 0x37, 0xcf, 0xff, 0x03, 0xe9, 0x06, 0x20, + 0xe2, 0x3c, 0xd1, 0xcc, 0x26, 0xe8, 0xc2, 0xd6, 0x0d, 0x35, 0x08, 0xae, 0x13, + 0x47, 0x1b, 0xe6, 0x46, 0x49, 0x34, 0x36, 0x9a, 0xf9, 0x56, 0xdb, 0xc1, 0x36, + 0x3a, 0xd6, 0xcd, 0xca, 0xad, 0xb7, 0xa3, 0x2c, 0xa3, 0xe2, 0x0a, 0xe8, 0xf4, + 0x38, 0x47, 0xca, 0xf7, 0x0e, 0xb1, 0x15, 0x2a, 0xe8, 0xe5, 0x65, 0x3a, 0x01, + 0x54, 0x4a, 0x2d, 0xfc, 0x33, 0x23, 0x07, 0x81, 0xc3, 0xa2, 0xda, 0x05, 0x08, + 0x02, 0x57, 0x0d, 0xe4, 0xd4, 0xc8, 0xce, 0x2b, 0xc2, 0x38, 0x04, 0xd4, 0xdf, + 0xbb, 0x07, 0x0b, 0xce, 0xb6, 0xf5, 0x01, 0xd6, 0x4a, 0x01, 0x41, 0x4b, 0xd3, + 0xf4, 0x3d, 0x3f, 0x0d, 0x1c, 0xeb, 0xe6, 0x68, 0x07, 0x04, 0x19, 0x9b, 0xbb, + 0xfb, 0xfc, 0xd0, 0x03, 0x01, 0xbd, 0xf3, 0xa3, 0xcf, 0xc5, 0x2c, 0x15, 0xf3, + 0x6c, 0x34, 0xfa, 0xed, 0x17, 0x0f, 0x1b, 0xe7, 0xe1, 0x11, 0x34, 0xad, 0xfd, + 0x90, 0x00, 0x12, 0x50, 0x06, 0xf0, 0xa3, 0x12, 0xbf, 0xbe, 0x00, 0x20, 0x49, + 0xed, 0xe7, 0xde, 0x07, 0xd0, 0x12, 0x1b, 0xba, 0xab, 0x26, 0x34, 0xaa, 0x27, + 0xb2, 0x37, 0x02, 0xf8, 0x07, 0x07, 0xf3, 0x02, 0xf8, 0xd5, 0x27, 0xdb, 0x2b, + 0xc8, 0x2a, 0xd4, 0x36, 0x0d, 0xd6, 0xe5, 0x37, 0xec, 0x6b, 0x2a, 0x0f, 0xb4, + 0x58, 0xdc, 0xc7, 0x30, 0xea, 0xc5, 0x06, 0xcb, 0x22, 0x16, 0xd2, 0xf7, 0x14, + 0xff, 0xe5, 0x3b, 0x01, 0xee, 0x2e, 0xcf, 0x06, 0xcd, 0x7f, 0x11, 0xf8, 0xc6, + 0x04, 0x3e, 0xd8, 0x22, 0xd0, 0x02, 0xe1, 0xa0, 0xcf, 0x2f, 0xbb, 0x3f, 0x2c, + 0xe8, 0x34, 0x17, 0xbc, 0x21, 0xf6, 0xc7, 0x49, 0xf2, 0x0d, 0xb5, 0xed, 0xbb, + 0xce, 0x00, 0xbf, 0xb1, 0xfb, 0xc5, 0x53, 0x06, 0x13, 0xb2, 0xfb, 0x06, 0xd7, + 0xee, 0x5a, 0x0f, 0xeb, 0xa8, 0xe7, 0xfd, 0x0f, 0x16, 0xf1, 0xe1, 0x37, 0x9f, + 0x38, 0xed, 0xf0, 0xd3, 0x24, 0x2f, 0xaa, 0xef, 0xf8, 0x01, 0xfe, 0x47, 0xfb, + 0x27, 0x0a, 0xdf, 0xa2, 0xf7, 0xd2, 0x20, 0xac, 0x2e, 0x0e, 0xea, 0xc7, 0xfb, + 0xcf, 0x43, 0xed, 0x93, 0xc5, 0x00, 0x22, 0x2d, 0x57, 0x61, 0x02, 0xfc, 0xda, + 0x23, 0xec, 0xf1, 0x13, 0x44, 0xef, 0x2b, 0xeb, 0x12, 0x73, 0xcd, 0xe4, 0x00, + 0xe9, 0x5d, 0xe6, 0xcb, 0xc5, 0xd6, 0xec, 0xe4, 0x20, 0xec, 0xb0, 0x52, 0xb4, + 0xb7, 0xd1, 0xd1, 0xc8, 0xb7, 0x14, 0xd9, 0xba, 0xfe, 0xbc, 0x14, 0x1c, 0xe1, + 0xa5, 0xf1, 0xb1, 0xe0, 0xd8, 0xe7, 0xbe, 0xfc, 0xf2, 0xcf, 0x09, 0x27, 0xdd, + 0x02, 0xe4, 0x12, 0x4d, 0xcd, 0x21, 0x12, 0xac, 0xe8, 0x06, 0xee, 0xce, 0x46, + 0xdc, 0xde, 0x0f, 0xf4, 0xf2, 0xf1, 0xba, 0xd1, 0xe6, 0x36, 0xda, 0x3c, 0xfb, + 0xdb, 0xc9, 0x00, 0xdd, 0xfe, 0xc3, 0xe7, 0xa6, 0xc5, 0xba, 0x22, 0xee, 0xe3, + 0xa6, 0x43, 0x00, 0xdd, 0xd8, 0xe4, 0x24, 0x13, 0xfc, 0x0d, 0x09, 0xde, 0xcd, + 0xca, 0xfe, 0xff, 0x07, 0xe7, 0xd6, 0xaa, 0x06, 0xdd, 0xd9, 0x34, 0xcc, 0x1a, + 0x45, 0xd9, 0xe9, 0xec, 0xef, 0xfb, 0xdd, 0xee, 0xf6, 0x1d, 0x08, 0xfc, 0xdd, + 0xd4, 0x25, 0xaa, 0x0c, 0xee, 0x03, 0xaf, 0x02, 0x52, 0xcf, 0x01, 0xb8, 0xed, + 0xb6, 0x17, 0x4a, 0x1e, 0x25, 0x13, 0xba, 0xc9, 0xfa, 0xec, 0x0c, 0x16, 0xcf, + 0xcc, 0xe4, 0x02, 0xf8, 0xf0, 0x45, 0xea, 0x04, 0xee, 0xeb, 0x09, 0x3b, 0x35, + 0xc5, 0x06, 0xc0, 0x0b, 0xd1, 0xd2, 0xf7, 0x28, 0x10, 0x14, 0x2c, 0xe6, 0x19, + 0xd1, 0xf6, 0xec, 0x17, 0xd3, 0xda, 0x44, 0x47, 0x00, 0xdc, 0x15, 0x0e, 0xf5, + 0xdd, 0xdd, 0xed, 0x55, 0xa2, 0x06, 0xf5, 0xff, 0x07, 0x3f, 0xc8, 0xbb, 0xf7, + 0xe9, 0xe9, 0xcd, 0xba, 0x04, 0xd7, 0x00, 0x25, 0x15, 0x23, 0x77, 0x06, 0xbd, + 0x50, 0xc3, 0xd9, 0xcf, 0x30, 0xe2, 0xaf, 0xc0, 0x2b, 0xbd, 0x17, 0x05, 0xe9, + 0x51, 0xfe, 0x08, 0x26, 0x25, 0xdf, 0xe7, 0xfc, 0xb6, 0x02, 0xd8, 0x0c, 0xd3, + 0xe1, 0xf5, 0x20, 0xd7, 0x40, 0x11, 0x02, 0x14, 0xe9, 0xe2, 0xbe, 0xe6, 0x1e, + 0x14, 0xdc, 0xfa, 0x03, 0x27, 0xcb, 0xf9, 0x21, 0x08, 0x17, 0x1b, 0x04, 0x26, + 0xf4, 0xf1, 0xd6, 0xc2, 0xca, 0xfa, 0xfe, 0x2d, 0xf7, 0xdd, 0xd9, 0xe4, 0x3a, + 0x00, 0x35, 0x0f, 0xfc, 0xf4, 0x18, 0x08, 0xdf, 0x1d, 0x10, 0x48, 0xb3, 0xdf, + 0x1e, 0x0d, 0x00, 0x19, 0xb3, 0x3f, 0x7f, 0x1f, 0xc2, 0x1c, 0xc9, 0xd4, 0x36, + 0xf1, 0xd1, 0xeb, 0x03, 0xe6, 0x18, 0x18, 0xe7, 0xe2, 0xe6, 0xf8, 0xdd, 0x0a, + 0x23, 0xf0, 0xc5, 0x1c, 0xf0, 0x10, 0xcd, 0xf0, 0x9f, 0xc2, 0xd8, 0x1d, 0xe4, + 0x20, 0xfa, 0x1f, 0xf2, 0xcc, 0x0a, 0xc7, 0x00, 0xf5, 0x07, 0x19, 0x1a, 0x64, + 0xdb, 0xe7, 0xf3, 0xc1, 0x14, 0xe5, 0xd3, 0xe7, 0x17, 0xf4, 0xbb, 0x17, 0xcd, + 0x2d, 0x1d, 0x27, 0xb0, 0x16, 0xe3, 0xf7, 0xe2, 0xfa, 0x42, 0x20, 0x24, 0xe6, + 0xdb, 0xd9, 0x12, 0x0d, 0xee, 0xe6, 0xff, 0x28, 0x07, 0x44, 0xfc, 0xd5, 0xff, + 0x05, 0xe5, 0xd4, 0xfb, 0xc1, 0xd3, 0xf8, 0x2c, 0x0a, 0x22, 0x0e, 0xe5, 0x1d, + 0x09, 0x25, 0xf7, 0x20, 0x26, 0x2f, 0x24, 0xda, 0x1e, 0xff, 0xb1, 0x10, 0x47, + 0x46, 0xe1, 0x25, 0xd3, 0xf6, 0xfe, 0x2c, 0xc8, 0x45, 0x20, 0xd1, 0x13, 0xdf, + 0xf9, 0x04, 0xd2, 0x2a, 0xfb, 0xf1, 0x15, 0xf4, 0xd5, 0xdb, 0x08, 0x03, 0xff, + 0x1a, 0x1a, 0x0c, 0xf7, 0xd5, 0xf6, 0xfd, 0xe1, 0xaa, 0xfc, 0x45, 0x4a, 0x14, + 0xea, 0xfc, 0x07, 0xf2, 0x28, 0xfa, 0x24, 0x1e, 0xc3, 0xda, 0x3d, 0xf6, 0x01, + 0xfd, 0x1f, 0x04, 0xe3, 0x2a, 0xda, 0xfc, 0xfb, 0xdd, 0xe1, 0xf6, 0xda, 0xe5, + 0x14, 0xf8, 0xf1, 0x2e, 0x08, 0x1f, 0xfc, 0xf8, 0xff, 0xe5, 0xf5, 0x35, 0xf2, + 0x16, 0xf4, 0xfb, 0xe3, 0xf9, 0xfb, 0xf8, 0xf9, 0xe3, 0xdc, 0xfc, 0xf6, 0x13, + 0x11, 0x11, 0x7f, 0xfc, 0x16, 0xee, 0xe8, 0x21, 0x06, 0x4c, 0xec, 0x10, 0xf8, + 0xff, 0xfd, 0xff, 0x27, 0xb0, 0x17, 0x5d, 0xdd, 0xe5, 0xc0, 0xf1, 0xed, 0x38, + 0xd8, 0x04, 0xf7, 0x03, 0xd6, 0x09, 0xe9, 0x0d, 0x41, 0xea, 0x01, 0xea, 0xf4, + 0x21, 0x26, 0xe2, 0x1a, 0x00, 0x05, 0xf3, 0xe3, 0xc2, 0x0c, 0xef, 0x0c, 0xf6, + 0xd3, 0xce, 0x06, 0x08, 0x0b, 0xd2, 0x01, 0xf1, 0xf5, 0xfe, 0x38, 0x06, 0x2d, + 0x16, 0x0c, 0xf9, 0x05, 0xd4, 0x08, 0xc8, 0x24, 0xe1, 0x2a, 0xdd, 0x0c, 0x23, + 0x1c, 0x38, 0x04, 0xce, 0x0e, 0x11, 0x16, 0xf1, 0xf3, 0xd7, 0xdf, 0x0e, 0xb8, + 0xd9, 0xdb, 0x2d, 0x1e, 0x07, 0xdf, 0x06, 0xf8, 0xf7, 0x8a, 0xbe, 0xe2, 0xf6, + 0xfd, 0x09, 0xf2, 0x01, 0xc0, 0xee, 0xc7, 0x1b, 0xf3, 0x03, 0xfa, 0x97, 0xbc, + 0xd7, 0xe4, 0xb7, 0x0a, 0x0f, 0xd4, 0xc2, 0x45, 0x01, 0x07, 0x11, 0xd5, 0x03, + 0xde, 0xfa, 0xdd, 0xe2, 0xd6, 0xae, 0x41, 0xc1, 0x22, 0x0e, 0x2b, 0x81, 0xa2, + 0xf9, 0xfa, 0xed, 0x3a, 0xce, 0xe7, 0x21, 0x01, 0xf6, 0x17, 0xec, 0x17, 0x5e, + 0xb2, 0x0e, 0xe7, 0x33, 0xf7, 0xec, 0x05, 0x27, 0x08, 0x0d, 0x0e, 0xf6, 0xdb, + 0x82, 0x00, 0xd4, 0xe3, 0xed, 0xf5, 0xe8, 0x01, 0xba, 0xe6, 0xe2, 0xed, 0x17, + 0x3e, 0x1a, 0xc9, 0x46, 0xe6, 0xf1, 0x07, 0xe9, 0x04, 0x05, 0x20, 0xf7, 0x3a, + 0xf0, 0xad, 0xd4, 0xfe, 0x39, 0xd7, 0xf1, 0xdc, 0x60, 0xd8, 0xe4, 0xdf, 0x3e, + 0x01, 0xbc, 0xfa, 0x3f, 0xba, 0x58, 0x0b, 0x42, 0x42, 0xe6, 0x06, 0x0d, 0xf6, + 0x08, 0x0b, 0xd3, 0x25, 0xbe, 0x1d, 0x3e, 0xcc, 0xcd, 0xc2, 0xfe, 0xfd, 0xeb, + 0xf4, 0xff, 0xf7, 0xd6, 0xf1, 0xf6, 0xc5, 0x08, 0x39, 0xb5, 0x04, 0xae, 0xff, + 0x59, 0x32, 0x31, 0xc6, 0xc1, 0xd2, 0xd6, 0xa2, 0xa3, 0xf7, 0x17, 0xde, 0x1e, + 0x51, 0xca, 0x99, 0xa1, 0xd7, 0x2b, 0x1e, 0x14, 0xba, 0xf5, 0x08, 0xca, 0x1a, + 0x0e, 0x36, 0x07, 0x11, 0xa4, 0x07, 0xb8, 0xd5, 0x27, 0x3a, 0x9e, 0xfa, 0xd4, + 0x0e, 0xec, 0xf6, 0x01, 0x23, 0x02, 0xf6, 0x2f, 0xe5, 0x3a, 0xbd, 0x26, 0xf5, + 0xd9, 0x2e, 0xdc, 0xc8, 0xe6, 0xd0, 0xc4, 0x07, 0xfe, 0x14, 0xc2, 0xeb, 0x1b, + 0xbf, 0xc1, 0xc5, 0x4f, 0x27, 0xeb, 0xcb, 0xed, 0xfb, 0x35, 0x11, 0x07, 0x4d, + 0xbc, 0x38, 0x14, 0x2b, 0x1e, 0xff, 0xfe, 0xdf, 0xb2, 0xfb, 0xf9, 0x1d, 0xed, + 0xe8, 0xec, 0x0d, 0x10, 0xfe, 0xe0, 0x29, 0xe5, 0xe1, 0x1d, 0x8c, 0x20, 0x41, + 0xe8, 0xdd, 0xd5, 0xed, 0x0f, 0xd9, 0x62, 0xd9, 0x5e, 0x63, 0x8b, 0x0c, 0x08, + 0x04, 0xf1, 0x31, 0xbd, 0x2e, 0xf0, 0x95, 0x3e, 0xe6, 0xfd, 0x04, 0x21, 0xe9, + 0x0e, 0x30, 0xe1, 0x0f, 0x47, 0x43, 0xed, 0xbc, 0xd4, 0x95, 0x99, 0x81, 0x78, + 0x1f, 0x04, 0x08, 0xc6, 0x0e, 0x09, 0xe2, 0x31, 0xec, 0x1a, 0xc9, 0x2c, 0xf9, + 0x17, 0x2f, 0xd8, 0xd9, 0xa0, 0xff, 0x32, 0x00, 0x26, 0xf5, 0xce, 0x25, 0xe3, + 0xe5, 0xbd, 0x0d, 0x74, 0xaf, 0xb5, 0xfd, 0x67, 0xc7, 0xc8, 0x4c, 0xa4, 0xfa, + 0xf6, 0xd2, 0x03, 0xf0, 0xc5, 0xf2, 0x2d, 0x2a, 0xb3, 0xd4, 0x26, 0xcd, 0x21, + 0x32, 0xe0, 0xfc, 0xb7, 0x96, 0x13, 0xfb, 0x1f, 0xdf, 0xb2, 0xd4, 0x0c, 0xf6, + 0x33, 0x26, 0xf7, 0xd7, 0xf0, 0x02, 0xc2, 0x52, 0x90, 0xe5, 0x16, 0xc0, 0x0e, + 0x09, 0x5f, 0x1b, 0x38, 0x2b, 0xd9, 0xba, 0xe4, 0xdc, 0xcb, 0x26, 0xdc, 0xfb, + 0xdb, 0xef, 0x27, 0xce, 0x01, 0xaf, 0xbd, 0x05, 0xf6, 0xd9, 0xcf, 0xea, 0x14, + 0xe6, 0xf9, 0x48, 0xc2, 0x40, 0xff, 0xf8, 0xc0, 0x24, 0x51, 0xda, 0x23, 0xc6, + 0xe5, 0xe9, 0xdc, 0x07, 0xa0, 0xdf, 0xa0, 0x13, 0xca, 0x23, 0x5b, 0xcb, 0xf5, + 0x0a, 0x04, 0x45, 0xbe, 0x29, 0xf5, 0x21, 0xb8, 0x20, 0x21, 0xfc, 0x14, 0x2b, + 0xf7, 0xee, 0x1c, 0xe6, 0x06, 0x2e, 0x29, 0x07, 0xf4, 0xf3, 0xd1, 0xe0, 0x21, + 0x28, 0xea, 0xe9, 0x1d, 0xd3, 0xc0, 0xed, 0xe1, 0x99, 0x42, 0x2a, 0x23, 0x92, + 0x2e, 0xe1, 0x04, 0xef, 0xec, 0x9e, 0x1b, 0xd7, 0xb8, 0x10, 0xe6, 0xed, 0x09, + 0xdd, 0xe5, 0x16, 0xf4, 0x10, 0xf5, 0xd2, 0x2b, 0x21, 0xae, 0xf2, 0x42, 0x2a, + 0x41, 0x42, 0xfb, 0xfb, 0x0a, 0xff, 0xbe, 0xfc, 0x1f, 0x29, 0xdb, 0x4e, 0x1d, + 0x08, 0xed, 0x01, 0x17, 0xa3, 0xd3, 0xd8, 0x0d, 0xe8, 0xf8, 0x78, 0xdb, 0xff, + 0x09, 0x31, 0xe5, 0x05, 0xec, 0x09, 0xc7, 0xc6, 0xeb, 0xd1, 0x05, 0x10, 0xef, + 0x16, 0xbb, 0xe1, 0xc3, 0xbe, 0x06, 0xb4, 0xd9, 0x02, 0xa0, 0xe5, 0xfe, 0x05, + 0x0e, 0xc7, 0xcc, 0x41, 0x29, 0x25, 0xfe, 0xf1, 0x24, 0xe7, 0xa9, 0x44, 0x00, + 0x12, 0x00, 0xb7, 0x25, 0xbf, 0x1d, 0x0f, 0x10, 0x4d, 0x8d, 0xe8, 0xfb, 0x0f, + 0xb0, 0x1f, 0xfe, 0x3a, 0xef, 0x16, 0x11, 0xcc, 0x03, 0xdb, 0xfe, 0x5b, 0xff, + 0x03, 0xb0, 0xed, 0xba, 0xf7, 0xc6, 0x2e, 0x1e, 0x1a, 0xe4, 0x27, 0xe3, 0xe2, + 0x0f, 0x0c, 0xb9, 0xa3, 0x01, 0xd3, 0xfb, 0x31, 0xc9, 0xfd, 0xcc, 0xbe, 0xed, + 0x0f, 0xe9, 0xe6, 0x10, 0xd3, 0x01, 0x00, 0x19, 0xcb, 0xfd, 0xac, 0xf9, 0xdb, + 0xd0, 0x9e, 0x3a, 0xde, 0x12, 0xcf, 0x0b, 0xb2, 0x0a, 0x15, 0xf2, 0xfc, 0x39, + 0x19, 0xe5, 0xf0, 0xf9, 0xcb, 0x4b, 0xd5, 0x02, 0x29, 0xce, 0xec, 0xfc, 0x20, + 0x1f, 0x13, 0xe8, 0xea, 0x41, 0xdb, 0x45, 0x4e, 0xe2, 0xb3, 0xf2, 0xd4, 0xad, + 0x0a, 0xfe, 0xe5, 0x06, 0x1a, 0x20, 0xce, 0xc0, 0x49, 0xf9, 0xfe, 0xdc, 0xcf, + 0xca, 0x00, 0xce, 0x40, 0x43, 0x1f, 0xb9, 0x30, 0xd7, 0xce, 0xa4, 0x0b, 0x0a, + 0x23, 0x12, 0x03, 0x16, 0xce, 0xdd, 0x10, 0xb1, 0x2f, 0xdc, 0x06, 0xd8, 0x1d, + 0xe4, 0x15, 0xfd, 0xc8, 0xe4, 0x09, 0xff, 0x13, 0xd3, 0x05, 0x40, 0xe7, 0x1c, + 0x39, 0xde, 0xe5, 0x50, 0xf1, 0xea, 0xfe, 0x0f, 0xc4, 0x35, 0x7f, 0xc6, 0x26, + 0x25, 0xb1, 0x01, 0xf3, 0x20, 0xbe, 0x44, 0xa8, 0x1b, 0xef, 0x0f, 0xc1, 0x00, + 0xf0, 0x2d, 0x02, 0xfe, 0x3b, 0x27, 0x03, 0x08, 0xfa, 0x38, 0x01, 0xd3, 0xfa, + 0xea, 0x32, 0xfa, 0xe3, 0x33, 0x0a, 0x0b, 0x59, 0x13, 0xb3, 0x17, 0xf6, 0x23, + 0xe8, 0x3c, 0x1b, 0xd6, 0xfe, 0x1e, 0x00, 0x05, 0xca, 0x12, 0xdd, 0x1e, 0xe0, + 0xfd, 0xc8, 0x12, 0xde, 0xc5, 0x09, 0xb3, 0xfc, 0xc4, 0x24, 0xbe, 0xc0, 0xfd, + 0xed, 0x13, 0xec, 0x0f, 0xa3, 0xbb, 0xe6, 0xeb, 0xd0, 0xf1, 0xe8, 0x26, 0x99, + 0x01, 0xca, 0xd7, 0xe6, 0xc8, 0xc4, 0xce, 0x3b, 0xee, 0xf8, 0x1b, 0x9a, 0x26, + 0xb1, 0x1a, 0xf5, 0xe5, 0x3e, 0x28, 0xe8, 0x10, 0xf0, 0x2a, 0xe0, 0xfa, 0x3e, + 0x2a, 0xd7, 0xde, 0x1d, 0x1b, 0x26, 0x0b, 0xcc, 0x4c, 0xef, 0x0c, 0xe6, 0xc1, + 0xdf, 0x06, 0xf6, 0x87, 0xbe, 0xd3, 0xc3, 0x28, 0x2f, 0x06, 0xb9, 0x5a, 0xff, + 0xa4, 0xe3, 0x06, 0x2d, 0x0f, 0x20, 0x9e, 0xb0, 0xbe, 0x1e, 0x20, 0xdb, 0xd3, + 0xda, 0x86, 0xd4, 0xe8, 0xed, 0x17, 0xef, 0xc9, 0xda, 0xbc, 0xbe, 0x06, 0xb1, + 0x24, 0xf1, 0x21, 0x01, 0xf3, 0xf0, 0x1c, 0x06, 0x19, 0x18, 0xef, 0xfc, 0x9e, + 0x0a, 0xd0, 0xdc, 0x78, 0x00, 0xfb, 0xe4, 0x05, 0xbc, 0x4a, 0x2c, 0xff, 0x81, + 0xf2, 0x32, 0x19, 0x05, 0xa6, 0x33, 0xf6, 0xda, 0xbe, 0xfd, 0xe8, 0xdd, 0x01, + 0x0f, 0xcb, 0xdc, 0x48, 0x52, 0x09, 0x7f, 0xf6, 0xa2, 0x02, 0xf7, 0x23, 0x03, + 0x4b, 0xf0, 0x44, 0x27, 0xaa, 0x01, 0xfb, 0xf5, 0xec, 0xfa, 0xea, 0xd6, 0xb1, + 0xc4, 0xde, 0xe0, 0x15, 0xf7, 0x0b, 0x05, 0xf0, 0xd7, 0x09, 0xef, 0xd1, 0x03, + 0xf5, 0x26, 0xd6, 0x18, 0xf1, 0xec, 0xd7, 0xea, 0xed, 0xf0, 0x18, 0x2b, 0x07, + 0xf5, 0xe6, 0xf3, 0x21, 0xe8, 0x31, 0xeb, 0xcd, 0xc8, 0xe7, 0x17, 0x2b, 0xff, + 0xd1, 0xed, 0xd5, 0xc2, 0x19, 0xe8, 0xff, 0xc2, 0x24, 0xf6, 0x2f, 0xf9, 0xcb, + 0x78, 0x01, 0xdd, 0xdc, 0xec, 0x10, 0x07, 0xec, 0x0f, 0x3f, 0xfd, 0x19, 0xd3, + 0xc7, 0xf3, 0xad, 0xae, 0x3c, 0xb8, 0x0a, 0xe5, 0xf7, 0xf2, 0x03, 0x08, 0x00, + 0xc9, 0x04, 0x4d, 0x29, 0xe2, 0x27, 0x0d, 0x08, 0xd4, 0xf6, 0x10, 0xc5, 0xf8, + 0xa3, 0xcf, 0x9d, 0x46, 0x0a, 0x25, 0x0a, 0xd2, 0xec, 0xd0, 0x18, 0x13, 0xf5, + 0xb7, 0x0b, 0xfd, 0x2a, 0x00, 0x37, 0x30, 0xc0, 0xf6, 0x12, 0xf3, 0xb1, 0x2c, + 0x14, 0x09, 0x30, 0xd9, 0xd9, 0xc4, 0xf5, 0x01, 0xc1, 0x2e, 0x2e, 0x04, 0xc6, + 0xf0, 0xab, 0xda, 0xce, 0xd8, 0x1e, 0xea, 0x3c, 0x1a, 0xd5, 0xe0, 0x01, 0xc1, + 0x1f, 0xe8, 0x04, 0x12, 0xe8, 0x10, 0xc6, 0x03, 0xe1, 0xda, 0xb6, 0xe8, 0xcb, + 0x8e, 0x43, 0xfb, 0xf3, 0x36, 0xd5, 0xd0, 0x53, 0xeb, 0xfa, 0xee, 0xd3, 0x39, + 0xd5, 0xf7, 0xa6, 0xba, 0x37, 0xd6, 0x10, 0x06, 0xbe, 0xbb, 0xc8, 0xb4, 0x15, + 0x02, 0xe4, 0x1c, 0xe7, 0xd9, 0x01, 0x2a, 0x0c, 0x16, 0x1c, 0x01, 0x11, 0xca, + 0xd6, 0xf8, 0x4a, 0xc1, 0xf5, 0x04, 0x09, 0xc3, 0xf0, 0x14, 0xca, 0xda, 0xf7, + 0xf6, 0x17, 0xfd, 0xde, 0x33, 0x39, 0xd8, 0x98, 0x0a, 0xe9, 0x2f, 0xf6, 0xe0, + 0x13, 0xd0, 0xfb, 0x01, 0xff, 0xd9, 0xea, 0xe6, 0xf9, 0x05, 0x37, 0xf5, 0x4c, + 0x06, 0xf7, 0x22, 0x06, 0xd9, 0x22, 0x18, 0x46, 0xfb, 0xe5, 0xfb, 0xde, 0xfc, + 0xc2, 0xee, 0x11, 0xec, 0xce, 0x0b, 0x2a, 0x09, 0x08, 0x3b, 0xd1, 0xe7, 0x1f, + 0x09, 0xe2, 0xfd, 0x0a, 0x15, 0xc7, 0xff, 0xca, 0x17, 0xab, 0xde, 0xdb, 0xfb, + 0xf6, 0x29, 0xd7, 0x21, 0xea, 0xc2, 0x08, 0x0f, 0xed, 0x1b, 0xf1, 0x0b, 0xfa, + 0x07, 0xde, 0xfc, 0xe1, 0x2c, 0x35, 0xf1, 0xe2, 0xc9, 0xf6, 0xd7, 0x1d, 0xad, + 0xea, 0x48, 0xfe, 0xe1, 0x05, 0x14, 0xf1, 0x0e, 0x1c, 0x0e, 0xb0, 0x3b, 0xf3, + 0x2a, 0x03, 0xef, 0x22, 0x3e, 0x0c, 0xdf, 0xba, 0x32, 0xca, 0xfe, 0xdf, 0x21, + 0x3d, 0x3e, 0x04, 0x09, 0x43, 0xf0, 0x3b, 0xc6, 0x4c, 0x81, 0x28, 0xfe, 0x09, + 0x3e, 0x1e, 0xe6, 0x21, 0xb3, 0x2b, 0xac, 0x1a, 0x09, 0xe3, 0x09, 0xe5, 0xf7, + 0xd8, 0xfb, 0xe4, 0xd3, 0xde, 0x15, 0x09, 0xe5, 0xb5, 0xc8, 0xe8, 0x20, 0xb2, + 0xe4, 0xf6, 0xeb, 0x23, 0xff, 0xd4, 0xcb, 0xdc, 0xeb, 0x1b, 0x8f, 0xf8, 0xf2, + 0x29, 0x41, 0x06, 0xc8, 0xe5, 0xcc, 0xff, 0x07, 0xf9, 0x33, 0xbe, 0xce, 0xf2, + 0x09, 0x9a, 0xd7, 0x08, 0x2a, 0x40, 0x1c, 0xef, 0x0c, 0xc8, 0xf3, 0xdb, 0xe9, + 0x2a, 0xd4, 0x1b, 0xb1, 0xd2, 0x3b, 0x33, 0xea, 0xfd, 0xf5, 0x0c, 0xd5, 0xe2, + 0x1c, 0x04, 0xef, 0xde, 0x0c, 0xf5, 0xad, 0x1f, 0xb0, 0xf9, 0xfc, 0xe4, 0xcf, + 0x0e, 0xaf, 0xe4, 0xe3, 0x16, 0xbe, 0xe7, 0xf1, 0xf8, 0xc8, 0x1f, 0xd8, 0xe9, + 0xbd, 0xb4, 0xb9, 0xe3, 0xbe, 0x17, 0x17, 0x28, 0xef, 0x03, 0xd9, 0xc5, 0xf6, + 0xf0, 0xff, 0x1b, 0xf2, 0xc3, 0xcc, 0xd8, 0xe6, 0x19, 0xaa, 0x06, 0xf0, 0x16, + 0xce, 0x0f, 0xd8, 0x18, 0xe9, 0x13, 0xfa, 0xf9, 0xb2, 0xb0, 0x24, 0x05, 0xe5, + 0xcd, 0x2d, 0xee, 0xd1, 0x13, 0x0d, 0xe8, 0xd2, 0xee, 0xdf, 0xf6, 0x65, 0xf9, + 0xc5, 0xa1, 0xe8, 0xce, 0xdd, 0xec, 0xdd, 0x1b, 0x15, 0x9b, 0x03, 0xcf, 0x33, + 0xce, 0x1e, 0xe2, 0x00, 0xe6, 0x03, 0xe0, 0xe5, 0x18, 0x1d, 0x01, 0x09, 0xe4, + 0xdb, 0xeb, 0x2c, 0x2b, 0xca, 0xc1, 0xe1, 0xdb, 0x01, 0xfa, 0xde, 0xc8, 0xe5, + 0x06, 0xd7, 0xda, 0xd7, 0x1e, 0xce, 0x37, 0x03, 0x13, 0xe3, 0xe6, 0x81, 0xe8, + 0x01, 0x19, 0xdb, 0x0f, 0xe8, 0xfe, 0xe5, 0xe6, 0xd6, 0x07, 0x85, 0xf8, 0x0c, + 0x1f, 0xd7, 0x25, 0x0b, 0xdd, 0x37, 0xd3, 0x17, 0x56, 0xd3, 0x03, 0x0a, 0x03, + 0xe8, 0x13, 0xbb, 0xff, 0xdc, 0x14, 0x0e, 0xe5, 0xae, 0x41, 0x16, 0x6c, 0x09, + 0xc6, 0xf8, 0xf8, 0x0d, 0xd8, 0xba, 0xdd, 0xf7, 0xfd, 0x18, 0x44, 0x8c, 0x3d, + 0xe3, 0x31, 0xd7, 0x1a, 0xef, 0x4e, 0x42, 0xc5, 0x1e, 0xcd, 0xe0, 0xfa, 0x03, + 0x2d, 0x4b, 0x0b, 0xfe, 0x2f, 0xea, 0x03, 0xfa, 0x0d, 0xe9, 0x1c, 0xe6, 0x0b, + 0x19, 0xe2, 0xf1, 0x15, 0xe2, 0x00, 0x33, 0xba, 0x33, 0xc4, 0xd5, 0xc2, 0x1b, + 0xd2, 0xee, 0xed, 0x1e, 0x13, 0xf9, 0xf1, 0xed, 0xee, 0x05, 0x13, 0x10, 0x15, + 0x5f, 0xcd, 0xe0, 0xdb, 0xd4, 0x28, 0xf9, 0x1e, 0xcc, 0xea, 0x23, 0x17, 0xcc, + 0x1f, 0xd7, 0x2e, 0xa8, 0x46, 0xec, 0xd0, 0xda, 0x12, 0xe2, 0xf1, 0x09, 0x2f, + 0xe6, 0x2f, 0xd9, 0xc4, 0xf0, 0xd8, 0x11, 0xbc, 0x0f, 0xf5, 0x34, 0x1d, 0x96, + 0x10, 0x01, 0xc4, 0xe9, 0x38, 0xe1, 0x2c, 0xf8, 0xcc, 0x0b, 0x33, 0xc6, 0xe5, + 0xf1, 0x23, 0x2f, 0x06, 0xdf, 0xb1, 0xb8, 0x13, 0x09, 0x11, 0xce, 0xc9, 0x4b, + 0x18, 0xce, 0x35, 0xfc, 0x3a, 0x12, 0xc3, 0x0d, 0x53, 0xc8, 0x0c, 0xd2, 0x2d, + 0xfd, 0xa1, 0xc3, 0xed, 0x35, 0x14, 0x0a, 0xfe, 0xf3, 0xdc, 0xb8, 0xcc, 0x1d, + 0x01, 0x0e, 0x3a, 0xe5, 0xd1, 0x12, 0x81, 0xdf, 0x09, 0xbd, 0x0c, 0xf0, 0x19, + 0x06, 0xe2, 0x11, 0xad, 0x07, 0xf1, 0x0e, 0xc3, 0x2b, 0x15, 0x1a, 0x31, 0xf1, + 0x13, 0xec, 0x10, 0x07, 0xde, 0x25, 0x1e, 0x1a, 0xe5, 0xd2, 0x25, 0xf4, 0x04, + 0x26, 0x20, 0x19, 0xff, 0x1a, 0x35, 0x26, 0xeb, 0x00, 0x00, 0x49, 0xca, 0xee, + 0xd0, 0xf0, 0xde, 0x27, 0x12, 0x0b, 0x0b, 0xf7, 0x12, 0x13, 0x05, 0xf3, 0x03, + 0x05, 0x3d, 0x12, 0xfe, 0xff, 0xd4, 0xfa, 0xf1, 0x3f, 0xfb, 0x17, 0x2e, 0x12, + 0xfb, 0x1a, 0xe7, 0x41, 0xc9, 0x01, 0xe1, 0xb8, 0x1d, 0x29, 0x37, 0xdd, 0xe9, + 0xda, 0xa9, 0x38, 0xbf, 0xef, 0xdb, 0xe7, 0xcd, 0xe5, 0x21, 0x1d, 0xc5, 0x08, + 0x33, 0xc3, 0xed, 0x19, 0x0c, 0x09, 0xf4, 0xcb, 0xef, 0xf2, 0x2c, 0x11, 0xfc, + 0xe0, 0x36, 0xdf, 0x29, 0x3f, 0xe5, 0x3b, 0xc7, 0xb6, 0xc8, 0xf9, 0x1c, 0xd5, + 0xfe, 0xed, 0xdb, 0xdb, 0xa4, 0xe1, 0xea, 0x0b, 0xf8, 0x1a, 0x4e, 0x19, 0xc7, + 0xec, 0x4e, 0xa6, 0x8f, 0xe1, 0xf8, 0xff, 0xe0, 0xe2, 0xd6, 0xdb, 0x04, 0x2e, + 0x42, 0x15, 0x16, 0xe0, 0xc3, 0xf3, 0x08, 0xd0, 0xfe, 0x11, 0x20, 0x52, 0xe5, + 0x1e, 0xe4, 0xd0, 0xf8, 0xf2, 0x17, 0xc6, 0x35, 0xaf, 0xcf, 0x1b, 0xfa, 0xc7, + 0xc7, 0xff, 0x13, 0x00, 0x2a, 0x4a, 0xd0, 0x3a, 0xd7, 0x38, 0xd0, 0xc4, 0x65, + 0xd6, 0x17, 0x2c, 0xe2, 0xfd, 0xfd, 0xf4, 0x3b, 0xe0, 0xf2, 0xba, 0x04, 0xe5, + 0x21, 0xad, 0x4f, 0x03, 0xf5, 0x1f, 0xa6, 0xb8, 0xe6, 0xd0, 0x37, 0xf5, 0xe4, + 0xd0, 0xf5, 0xfe, 0x03, 0x11, 0x4c, 0xea, 0xf5, 0x1c, 0xc0, 0xd2, 0xd9, 0x1c, + 0x13, 0xd2, 0xf3, 0x05, 0x12, 0xfa, 0x18, 0xd7, 0xcd, 0xbf, 0xda, 0xc6, 0xb4, + 0x1d, 0xfe, 0x37, 0x12, 0x8f, 0xbc, 0x5b, 0xe7, 0xc8, 0x20, 0xfc, 0xcf, 0xfb, + 0xfe, 0x32, 0x1d, 0x5e, 0x15, 0xea, 0xbe, 0xc8, 0xd3, 0x81, 0xc4, 0x04, 0xea, + 0xdd, 0xca, 0x32, 0x1d, 0x37, 0xb8, 0x00, 0x25, 0xe3, 0x0d, 0xf5, 0x3b, 0x16, + 0x04, 0x0a, 0x06, 0x28, 0xb1, 0x07, 0x18, 0xcd, 0x4c, 0xf2, 0xf6, 0x07, 0xc4, + 0x19, 0x22, 0xe0, 0x28, 0xd2, 0x2d, 0xf4, 0x1a, 0x0c, 0xf4, 0x44, 0x04, 0x2b, + 0x42, 0x03, 0x15, 0xb2, 0x96, 0x27, 0x17, 0x0b, 0x21, 0xe8, 0xab, 0x41, 0xd9, + 0x15, 0xd4, 0xdf, 0xf9, 0x30, 0x10, 0xb7, 0xe0, 0xe0, 0x09, 0x35, 0x00, 0x19, + 0xf7, 0xb7, 0xcb, 0x05, 0x1b, 0x0e, 0xf2, 0xd0, 0xde, 0x2f, 0x0e, 0x19, 0xd1, + 0x17, 0x1d, 0xe0, 0xeb, 0xf6, 0xc0, 0x6a, 0x10, 0xf8, 0xd2, 0x02, 0x04, 0xdb, + 0xe0, 0x07, 0x37, 0xe7, 0x1d, 0x02, 0x07, 0xec, 0xcf, 0xe7, 0xf5, 0xef, 0xbc, + 0xf4, 0x3f, 0xa6, 0x12, 0xff, 0x1b, 0x08, 0xb5, 0xf5, 0xd3, 0xbe, 0xf6, 0xda, + 0xd5, 0xda, 0x01, 0xef, 0xcf, 0x1a, 0x3e, 0xe6, 0xb7, 0xdc, 0xfe, 0xdf, 0xd4, + 0xee, 0x16, 0x21, 0xcb, 0x19, 0x27, 0x27, 0xe0, 0xf1, 0x06, 0x2c, 0x20, 0xcc, + 0x9d, 0xb4, 0x09, 0xf5, 0x1e, 0xd2, 0x09, 0x13, 0xfa, 0xca, 0x56, 0xe5, 0xd6, + 0xde, 0xfe, 0x12, 0xe5, 0x3c, 0xe4, 0xed, 0xfa, 0xfb, 0x21, 0xdc, 0x1a, 0x06, + 0xf7, 0x3f, 0xa3, 0xfa, 0x62, 0xe4, 0xed, 0x29, 0x11, 0x35, 0x0f, 0x78, 0xd0, + 0xf6, 0xf2, 0x51, 0x2e, 0xbb, 0xa3, 0xc6, 0x81, 0xec, 0x13, 0x4a, 0xcf, 0xe7, + 0x2a, 0xfa, 0xe6, 0x16, 0xcb, 0xf2, 0x95, 0x04, 0xde, 0xd3, 0x37, 0xcf, 0x9b, + 0x14, 0xf1, 0xfd, 0xfc, 0x12, 0x16, 0x16, 0xed, 0x22, 0xd3, 0xd5, 0xba, 0xd7, + 0xec, 0xe1, 0xdf, 0x2b, 0xd2, 0xc2, 0x08, 0xd7, 0xdd, 0xab, 0xd7, 0xe4, 0x0a, + 0xf4, 0xc5, 0xb2, 0x19, 0xdf, 0xe9, 0x24, 0xc2, 0xc2, 0xfd, 0xcb, 0xbd, 0xe7, + 0xaf, 0x8d, 0xad, 0x19, 0x27, 0x04, 0xe0, 0xea, 0x2f, 0xf4, 0xe8, 0x40, 0x2e, + 0xde, 0x2c, 0xcd, 0xfa, 0x53, 0x23, 0xdf, 0x5f, 0xdd, 0xe1, 0xb5, 0xea, 0x01, + 0x1f, 0xac, 0xff, 0xfe, 0x27, 0xdb, 0x1d, 0xc3, 0x90, 0xf1, 0xe3, 0xaa, 0x01, + 0x04, 0xe5, 0x07, 0xb7, 0xbf, 0xc4, 0xc9, 0x11, 0xc9, 0xb5, 0xe0, 0x1e, 0xdf, + 0x14, 0x03, 0x1a, 0xcc, 0x28, 0x02, 0xee, 0x1b, 0x13, 0xed, 0xef, 0x58, 0xa8, + 0x09, 0x10, 0x15, 0xed, 0x00, 0x66, 0x06, 0xeb, 0xe9, 0xe5, 0xed, 0xfe, 0x28, + 0xd9, 0xaa, 0xe9, 0x99, 0x46, 0x17, 0xd1, 0xe6, 0x0a, 0xdf, 0xdc, 0xbe, 0x32, + 0xb5, 0xfa, 0xf6, 0xf2, 0xd0, 0xf7, 0xca, 0x03, 0xe6, 0xfc, 0x07, 0xcf, 0xef, + 0x93, 0xe5, 0x05, 0xf1, 0xe1, 0xdc, 0x10, 0x15, 0x25, 0x18, 0x17, 0xba, 0xb1, + 0xeb, 0x9d, 0xdc, 0x04, 0xbe, 0x27, 0x2d, 0xf2, 0x15, 0xdb, 0x25, 0xe6, 0xe4, + 0xe9, 0x1e, 0x27, 0xe9, 0xff, 0x26, 0x39, 0xca, 0x12, 0xa0, 0xd3, 0xcc, 0xfc, + 0x1c, 0x9d, 0xc0, 0xd0, 0xfc, 0xe0, 0xd2, 0x11, 0x23, 0xf6, 0x3b, 0xfe, 0xfc, + 0x3a, 0x25, 0x48, 0xd5, 0xdf, 0xc5, 0x29, 0x0e, 0xfd, 0x5b, 0xe1, 0x09, 0x4d, + 0x19, 0x31, 0xc9, 0xb1, 0xfd, 0x12, 0x32, 0xb5, 0x00, 0xf4, 0x43, 0x2c, 0xfb, + 0x1b, 0xeb, 0xd8, 0xe8, 0x11, 0xb6, 0x2b, 0xff, 0xef, 0x26, 0xcd, 0x5c, 0xf6, + 0xe9, 0xf0, 0xf3, 0xfd, 0xea, 0x00, 0xc3, 0xce, 0x1f, 0x44, 0xcf, 0xe0, 0xd2, + 0x12, 0xc1, 0x16, 0xdd, 0xe7, 0x9e, 0x3a, 0x10, 0x05, 0xfe, 0x0d, 0x04, 0xaf, + 0xdc, 0xc1, 0xc5, 0xd2, 0xdc, 0xa0, 0xd9, 0x00, 0x01, 0x71, 0xe2, 0x15, 0x1c, + 0xd3, 0x11, 0xcb, 0x0b, 0xd5, 0x86, 0x14, 0xa7, 0x0c, 0xe3, 0x3b, 0xb9, 0xb5, + 0xd7, 0x34, 0xdf, 0x37, 0xf3, 0xf6, 0xf2, 0xe1, 0x38, 0x35, 0x01, 0x00, 0xe9, + 0xad, 0xe8, 0x07, 0x2a, 0x96, 0x23, 0x2e, 0xff, 0xe0, 0xd9, 0x26, 0xeb, 0xe2, + 0x58, 0xcb, 0xe7, 0x01, 0xc8, 0x13, 0x1f, 0xca, 0xe5, 0xde, 0xfc, 0x0a, 0xe4, + 0x04, 0xd2, 0xef, 0x20, 0xd7, 0x03, 0x0a, 0xff, 0x27, 0x19, 0xf0, 0xc6, 0x01, + 0x19, 0xfa, 0xbb, 0xde, 0x13, 0xf0, 0xfd, 0x03, 0x9c, 0x07, 0xdd, 0xc3, 0x27, + 0xe1, 0xb6, 0xb4, 0xe7, 0xde, 0xe4, 0x81, 0x07, 0xef, 0x12, 0xe3, 0x19, 0x27, + 0x17, 0xca, 0xbb, 0x08, 0xc7, 0xd6, 0x20, 0x99, 0xf1, 0xe6, 0x1f, 0xcd, 0x03, + 0x05, 0x43, 0x17, 0xcc, 0x08, 0xec, 0xc3, 0x23, 0x28, 0x15, 0x07, 0xd7, 0x21, + 0xf2, 0xfc, 0x02, 0xf2, 0xc3, 0xe7, 0x20, 0x1c, 0xde, 0xa1, 0x0b, 0xcb, 0x1c, + 0xed, 0x8b, 0xcb, 0xd6, 0x23, 0x18, 0xe6, 0xfe, 0xde, 0x2a, 0xfd, 0xca, 0x2b, + 0x28, 0xf4, 0xf9, 0xd2, 0xc1, 0xe1, 0x14, 0xc8, 0x17, 0x01, 0xe4, 0xdf, 0x28, + 0x25, 0x0c, 0xfe, 0xf8, 0x15, 0x39, 0xfe, 0xd4, 0xeb, 0x1d, 0xf0, 0xeb, 0x16, + 0x92, 0x45, 0xf6, 0xbc, 0x35, 0x0c, 0xff, 0x29, 0x41, 0xf4, 0xe4, 0x46, 0x2a, + 0x0a, 0xfe, 0xc6, 0xe7, 0xe6, 0xa9, 0x0e, 0x0a, 0x01, 0x12, 0x4f, 0x21, 0xe6, + 0x14, 0xab, 0x09, 0xe0, 0xd5, 0xba, 0xfc, 0xf4, 0x02, 0xf4, 0x2b, 0x39, 0xef, + 0x1c, 0xb6, 0xed, 0xe6, 0x0c, 0x03, 0xda, 0xd4, 0xe9, 0xf7, 0x48, 0xf2, 0xe5, + 0x2f, 0xc5, 0xad, 0x31, 0xcc, 0xfd, 0xb3, 0xf2, 0xc4, 0x39, 0xee, 0x0a, 0xfe, + 0xe9, 0x1e, 0xec, 0x14, 0x14, 0xe3, 0xfb, 0x02, 0xfc, 0xf1, 0xf9, 0xb5, 0xd0, + 0xc4, 0x08, 0xe1, 0xf4, 0x15, 0xec, 0xc1, 0xd8, 0x0d, 0xff, 0x2f, 0xf9, 0x18, + 0xc1, 0xcc, 0x5d, 0xa1, 0xf2, 0x29, 0xf7, 0xf7, 0x30, 0xe3, 0x21, 0xe1, 0x11, + 0x1e, 0x89, 0xf2, 0xfd, 0xdc, 0x27, 0xd1, 0x17, 0xee, 0xcd, 0x7d, 0x12, 0xc2, + 0x14, 0xb5, 0xdf, 0x1f, 0xcd, 0x42, 0xcc, 0x0f, 0xd2, 0x13, 0x63, 0x13, 0x40, + 0xef, 0x16, 0x12, 0x04, 0x4e, 0xc5, 0xd4, 0x0c, 0x14, 0x1e, 0xda, 0xa1, 0x48, + 0xcc, 0xfd, 0x1a, 0xac, 0x18, 0xe6, 0xfc, 0x3b, 0x31, 0x0f, 0x7f, 0xf8, 0xf4, + 0x87, 0x14, 0xb8, 0xe1, 0x14, 0xec, 0xa9, 0x31, 0x20, 0x45, 0x06, 0xed, 0xf0, + 0xda, 0xe5, 0xe4, 0xcc, 0xdb, 0xff, 0xe7, 0xd3, 0x12, 0xf6, 0xe7, 0x06, 0x16, + 0xf2, 0xb6, 0xdf, 0x0b, 0x2b, 0x15, 0xe5, 0xca, 0x0f, 0x1d, 0xd2, 0x41, 0x07, + 0xea, 0xd8, 0x16, 0x0a, 0xaf, 0xad, 0xee, 0x02, 0x01, 0x04, 0x60, 0xe9, 0x31, + 0x5d, 0x04, 0x0e, 0xcb, 0xc3, 0xaa, 0x0b, 0xda, 0xbe, 0x16, 0x12, 0xed, 0xf5, + 0x1d, 0xd4, 0xd6, 0x29, 0x21, 0xfa, 0x99, 0x16, 0x06, 0xaa, 0x15, 0xd4, 0x1c, + 0x10, 0xec, 0xe9, 0xe7, 0x14, 0xe9, 0xf0, 0x34, 0xbe, 0xf5, 0x53, 0xf5, 0x08, + 0xe4, 0xd2, 0xe3, 0x1b, 0xec, 0xf7, 0xb4, 0xf2, 0x0b, 0x15, 0xcb, 0xaf, 0xe8, + 0xc3, 0xe1, 0x1d, 0x24, 0xe9, 0x23, 0xfc, 0xce, 0xd0, 0xd1, 0xac, 0x20, 0x0a, + 0x09, 0xda, 0xd3, 0xf3, 0x25, 0x12, 0xee, 0xd1, 0xc6, 0x11, 0xac, 0xf2, 0x1c, + 0xe6, 0xec, 0xf4, 0x1a, 0xc0, 0xb3, 0x08, 0x0a, 0x2b, 0x30, 0x63, 0xdb, 0xfa, + 0xd3, 0x19, 0xdd, 0xf6, 0x58, 0xcf, 0xe9, 0x25, 0xee, 0xe5, 0xcd, 0x11, 0x08, + 0xe3, 0xdc, 0xec, 0x43, 0xdc, 0x04, 0xfd, 0x11, 0xbd, 0x16, 0xda, 0xea, 0xf8, + 0xdc, 0xee, 0xe9, 0xe3, 0x42, 0xb7, 0x32, 0xc9, 0xc1, 0x4b, 0xff, 0x16, 0x1c, + 0x1d, 0x99, 0xbd, 0x5c, 0x30, 0xd3, 0x0f, 0xe4, 0x74, 0xc7, 0x02, 0x0f, 0xc7, + 0x2d, 0xec, 0x2a, 0xe2, 0x0d, 0x1d, 0xec, 0x0e, 0xe8, 0xdb, 0x22, 0xc9, 0xb3, + 0xd1, 0xfe, 0xe2, 0xe9, 0x20, 0xda, 0xd4, 0x19, 0x21, 0xa4, 0xf1, 0xe1, 0x39, + 0x2f, 0x05, 0x23, 0xe4, 0xf4, 0x01, 0x12, 0x00, 0xec, 0x25, 0x1e, 0xa8, 0xf6, + 0xf8, 0xff, 0x0e, 0xd5, 0xc0, 0xcb, 0xc1, 0x33, 0x22, 0xc4, 0x1f, 0x0e, 0x05, + 0xed, 0xe1, 0x01, 0xe0, 0x11, 0xeb, 0x0a, 0xe0, 0x32, 0xd0, 0x70, 0xaf, 0x1b, + 0xf1, 0x07, 0x10, 0xf6, 0x02, 0xed, 0x3e, 0xd6, 0xa9, 0x11, 0xee, 0x1e, 0xe0, + 0xd1, 0xbc, 0xe8, 0x01, 0xe2, 0x1c, 0x3e, 0xa3, 0xd6, 0x8a, 0x0d, 0xdd, 0xe1, + 0x30, 0xed, 0x04, 0x15, 0xff, 0x24, 0xff, 0x1b, 0x81, 0xcd, 0xd5, 0x19, 0xe1, + 0x14, 0x33, 0x29, 0xdb, 0xdc, 0x38, 0xce, 0xf7, 0xd6, 0xd9, 0x23, 0xbb, 0x01, + 0xd4, 0xfc, 0xda, 0x48, 0xde, 0xd8, 0x37, 0xd4, 0x2b, 0xcd, 0x36, 0xe9, 0x14, + 0xf7, 0xfc, 0xcc, 0xe4, 0x25, 0xe8, 0xf3, 0x22, 0x3b, 0x0a, 0xc5, 0xce, 0xfb, + 0xef, 0x1c, 0x06, 0x19, 0x19, 0x0d, 0xfd, 0xe0, 0xf4, 0xed, 0x01, 0xef, 0x30, + 0xfe, 0xed, 0xe5, 0xfa, 0xe8, 0x1b, 0x0d, 0x2f, 0x04, 0xcd, 0xda, 0xca, 0xd8, + 0xed, 0x1a, 0x1a, 0x0f, 0x00, 0x04, 0xef, 0x7f, 0xff, 0xd3, 0xf8, 0xf4, 0x14, + 0xf0, 0x1f, 0xec, 0xcf, 0xff, 0xe9, 0x03, 0xa9, 0x17, 0x98, 0x24, 0x46, 0xcf, + 0xed, 0x14, 0xc9, 0x00, 0xd0, 0xd5, 0x36, 0xec, 0x3d, 0xd0, 0xff, 0xdd, 0x0d, + 0x30, 0x01, 0xd8, 0xd2, 0xbe, 0xee, 0xe6, 0x0a, 0xe7, 0xfb, 0x17, 0x1a, 0xe4, + 0xe6, 0x03, 0xb3, 0x25, 0x10, 0x27, 0xe3, 0x11, 0xd1, 0xc3, 0xc8, 0xda, 0xe5, + 0xf0, 0x0c, 0xf1, 0x13, 0xb3, 0xeb, 0xd5, 0xce, 0xb0, 0x18, 0x16, 0xe5, 0xf1, + 0xfa, 0xcf, 0xd0, 0xd1, 0xe4, 0xd5, 0xeb, 0xea, 0x14, 0x09, 0x29, 0xbf, 0x30, + 0xd5, 0xd7, 0x2a, 0x1a, 0xed, 0x1e, 0xe7, 0x19, 0x31, 0x2f, 0xce, 0xbe, 0xd9, + 0xeb, 0xf9, 0xd1, 0x0e, 0xe5, 0xdf, 0xfb, 0xc7, 0x02, 0xea, 0xf6, 0x29, 0x11, + 0xdd, 0x03, 0xdf, 0x21, 0x12, 0xf6, 0xe9, 0xf3, 0xfb, 0x16, 0x2d, 0xdd, 0xf8, + 0xdf, 0xe8, 0xd3, 0xfe, 0x24, 0xd1, 0xf7, 0xbf, 0xe5, 0xff, 0x1f, 0x27, 0xe1, + 0x00, 0xff, 0xd5, 0xb0, 0x1b, 0x17, 0xdc, 0xef, 0x1f, 0xd2, 0xf4, 0x0c, 0xf0, + 0xaf, 0xda, 0xf4, 0x0e, 0x22, 0x1f, 0x05, 0xe5, 0x19, 0x19, 0x22, 0x00, 0x13, + 0xde, 0x1c, 0xe8, 0x41, 0x17, 0xee, 0x48, 0xe4, 0xf3, 0xf1, 0xad, 0x1a, 0x1a, + 0xeb, 0x41, 0x35, 0x14, 0x0f, 0xd6, 0xe6, 0xde, 0xd2, 0x39, 0xc9, 0xf7, 0x0b, + 0xe4, 0xf0, 0x00, 0xd7, 0x09, 0xf1, 0xff, 0xca, 0xfa, 0xfb, 0x19, 0x0e, 0xf1, + 0x09, 0x24, 0xce, 0xe4, 0x1c, 0x10, 0xfb, 0xf7, 0xf0, 0xf2, 0x2b, 0xd7, 0xfc, + 0xe8, 0xe4, 0x07, 0xfe, 0xdc, 0xe8, 0x19, 0xef, 0xed, 0xff, 0x0d, 0xe1, 0xf7, + 0xd6, 0xf9, 0xed, 0x1b, 0x17, 0x0d, 0xf6, 0xeb, 0xf5, 0x0d, 0x0b, 0xe1, 0x0f, + 0xf8, 0xfc, 0xf7, 0xf7, 0xef, 0xdf, 0x12, 0x1b, 0x03, 0x06, 0xf8, 0x03, 0xf0, + 0xe0, 0xf2, 0xe7, 0x3b, 0xc8, 0x05, 0xef, 0x0c, 0xf8, 0x15, 0xe0, 0x2e, 0xe1, + 0xb6, 0xfa, 0xf0, 0x20, 0x08, 0xe2, 0xe5, 0x02, 0xe3, 0x0a, 0x00, 0x18, 0xd1, + 0x14, 0xe5, 0x00, 0x17, 0x13, 0xfa, 0x1b, 0xee, 0x19, 0xfd, 0xd9, 0xf5, 0xcc, + 0x03, 0xe6, 0x0b, 0xe2, 0x16, 0x1a, 0x15, 0xea, 0x0f, 0xdd, 0xd3, 0xf0, 0xf4, + 0x00, 0xc5, 0x04, 0x0b, 0x0e, 0xde, 0xdc, 0x1e, 0xe8, 0xe9, 0x43, 0x00, 0x11, + 0x0b, 0x25, 0xe0, 0xfc, 0x1f, 0xd7, 0x7f, 0xf7, 0x06, 0x15, 0x0c, 0x24, 0x41, + 0xf1, 0x1c, 0xf1, 0xfb, 0xe5, 0xcc, 0xcf, 0xf7, 0xd7, 0xe6, 0x05, 0xee, 0xee, + 0x2e, 0x1b, 0x1b, 0x0a, 0x28, 0x20, 0x0d, 0x06, 0xf5, 0x0a, 0x13, 0xed, 0x00, + 0x23, 0xc6, 0xd9, 0xf8, 0x1d, 0xe1, 0x11, 0xcc, 0xe9, 0xe3, 0xfe, 0x18, 0x0a, + 0xdf, 0xfb, 0xdc, 0x02, 0xed, 0xe8, 0x00, 0x19, 0x23, 0xda, 0x14, 0x0c, 0xe9, + 0x3e, 0xf1, 0x1c, 0x05, 0x1c, 0xdd, 0xf3, 0x19, 0x11, 0x05, 0x02, 0x04, 0xf0, + 0x02, 0xf7, 0xf9, 0xf4, 0x03, 0x00, 0xe2, 0xf7, 0x16, 0x07, 0x37, 0xdd, 0x09, + 0xfe, 0x1e, 0x27, 0xef, 0x14, 0xfa, 0xdf, 0xf0, 0xd4, 0xe5, 0x08, 0xeb, 0x26, + 0x33, 0x36, 0xe7, 0x18, 0xfa, 0xfc, 0x10, 0x13, 0x0c, 0xf5, 0xe5, 0xfb, 0xfe, + 0x1b, 0xc4, 0xe8, 0x04, 0xd1, 0x0e, 0x33, 0xee, 0x15, 0x0b, 0x12, 0xf3, 0xe8, + 0xd1, 0x00, 0x01, 0xe6, 0xd8, 0xd7, 0x01, 0xe5, 0x13, 0xfe, 0xf7, 0x0f, 0xee, + 0x18, 0x06, 0x07, 0xe8, 0xdf, 0x12, 0x17, 0xd3, 0xff, 0xfe, 0xe7, 0x15, 0x13, + 0xd1, 0xa8, 0xd0, 0xf2, 0x0a, 0xce, 0xfe, 0xfb, 0xf9, 0xd8, 0xcd, 0xf2, 0xf1, + 0x25, 0x0e, 0x1d, 0xc9, 0xeb, 0x2b, 0xf9, 0xf5, 0xf2, 0xf7, 0x32, 0xf9, 0x2b, + 0xef, 0x2b, 0x04, 0xf7, 0x21, 0x11, 0x1e, 0xf5, 0x3c, 0xfc, 0xc9, 0xb8, 0x3b, + 0x03, 0xb9, 0xb2, 0xec, 0xe8, 0xe9, 0x04, 0x18, 0xdf, 0xde, 0xc2, 0x26, 0x0e, + 0x0e, 0xf7, 0xd8, 0x40, 0x0d, 0xf1, 0x4e, 0xf2, 0xe9, 0xef, 0xf1, 0x13, 0x1d, + 0xf9, 0xe0, 0x1a, 0x10, 0x18, 0x12, 0xdd, 0x35, 0x35, 0xf9, 0x02, 0xde, 0xd2, + 0x2a, 0xf9, 0xdf, 0x01, 0xd5, 0xf3, 0xf5, 0x05, 0x08, 0xe5, 0x9e, 0x19, 0x0a, + 0x0c, 0x44, 0xeb, 0x32, 0xf1, 0x06, 0x51, 0xd6, 0xdd, 0xea, 0xf1, 0xd5, 0xd8, + 0xed, 0xfe, 0x7f, 0xd2, 0x07, 0x03, 0xd6, 0x14, 0x13, 0xd7, 0x0c, 0xdd, 0xe0, + 0xff, 0xaf, 0x1a, 0xfc, 0xd5, 0xca, 0xd0, 0xe7, 0xf3, 0xf6, 0xeb, 0xea, 0x10, + 0xf0, 0xfe, 0x10, 0xfb, 0xe9, 0x1a, 0xf8, 0xde, 0x0b, 0xf9, 0xb3, 0xc6, 0xf4, + 0xe8, 0x10, 0x1c, 0xd5, 0xee, 0xcf, 0x09, 0x01, 0xfc, 0xe9, 0xf0, 0xcd, 0x20, + 0xe5, 0x04, 0x0c, 0x04, 0x11, 0xec, 0xc2, 0x10, 0x1f, 0x17, 0xd1, 0xd6, 0x08, + 0x22, 0xf3, 0xf0, 0x34, 0x1e, 0x13, 0xfd, 0xdd, 0x18, 0xfb, 0x1f, 0xe0, 0x06, + 0x0c, 0xf3, 0x05, 0x03, 0xf3, 0x0e, 0x17, 0xfe, 0xde, 0x02, 0xea, 0x0e, 0xf0, + 0x22, 0xdc, 0xef, 0xc5, 0xeb, 0xf9, 0x0a, 0xf1, 0x05, 0xe9, 0x18, 0x12, 0xf2, + 0xf7, 0xea, 0x12, 0x2a, 0x33, 0xe0, 0xfd, 0xf1, 0x08, 0x24, 0xf7, 0xe5, 0xde, + 0xe1, 0x11, 0x35, 0x16, 0x16, 0x13, 0xf9, 0x1b, 0xda, 0xbb, 0xfd, 0xfe, 0xdf, + 0x0f, 0x0a, 0x40, 0xf8, 0xed, 0xea, 0xbb, 0xbe, 0xec, 0x05, 0xd7, 0x0f, 0x1b, + 0x24, 0xd5, 0x2b, 0xf2, 0x1b, 0xe4, 0xdc, 0x5e, 0xeb, 0xdb, 0x48, 0x3e, 0x0d, + 0xad, 0x26, 0xdc, 0xf2, 0xc6, 0xb5, 0x22, 0xa5, 0xc5, 0x2d, 0xc9, 0xcb, 0xe9, + 0x2e, 0x1f, 0xba, 0x81, 0xc7, 0xcd, 0xbb, 0x0c, 0xe5, 0xd6, 0xdd, 0xf5, 0xe7, + 0x17, 0x05, 0x0d, 0xf6, 0xd8, 0xf1, 0xc0, 0xff, 0xfc, 0xf2, 0xe5, 0xeb, 0xda, + 0x03, 0x0a, 0xfb, 0x48, 0xf9, 0xa7, 0xf5, 0xe7, 0xe8, 0x31, 0xd6, 0xd2, 0x2c, + 0xba, 0x4c, 0x19, 0xb7, 0x4d, 0x08, 0x0e, 0x1c, 0xce, 0xd6, 0xa6, 0xbe, 0xc2, + 0x07, 0xed, 0x32, 0xd7, 0xfc, 0xc9, 0xa6, 0x40, 0x1c, 0x05, 0xdb, 0x40, 0xd7, + 0x0a, 0x2a, 0xaf, 0x04, 0xf8, 0xff, 0x22, 0x27, 0xa1, 0xd8, 0xeb, 0xe4, 0xf0, + 0x04, 0xa8, 0xb2, 0x3d, 0xe3, 0x12, 0xe0, 0xb5, 0x2c, 0x0d, 0xe9, 0x30, 0xb4, + 0x26, 0x1d, 0xcc, 0x0c, 0xf8, 0xe2, 0x04, 0xa9, 0xee, 0xc3, 0xb6, 0xe7, 0xfa, + 0x3d, 0xb4, 0xe7, 0xcb, 0x35, 0x02, 0xde, 0x34, 0x3c, 0xea, 0xe6, 0x0a, 0xcc, + 0xfa, 0x00, 0x44, 0x03, 0xf6, 0xf2, 0xfb, 0xec, 0xce, 0x1a, 0x45, 0x35, 0xc4, + 0xd4, 0x26, 0xdf, 0xfe, 0xeb, 0x20, 0xe8, 0xfb, 0xd5, 0xc4, 0x3a, 0xf4, 0xfc, + 0x09, 0xe8, 0x3d, 0xe7, 0xd4, 0x22, 0xc2, 0xde, 0x16, 0xf8, 0x38, 0xf8, 0x1d, + 0x36, 0x31, 0x35, 0xfc, 0xc6, 0xfa, 0xda, 0x0e, 0xcf, 0xe8, 0xe4, 0xb9, 0xed, + 0xfa, 0x37, 0x18, 0x05, 0xbb, 0xd8, 0xee, 0x14, 0x0b, 0xe5, 0xec, 0xcc, 0xc9, + 0xf6, 0xd6, 0x08, 0xfc, 0x09, 0x2a, 0x08, 0xfd, 0xcd, 0xa2, 0x13, 0x36, 0x32, + 0x31, 0xf5, 0x0a, 0xef, 0xfb, 0x09, 0x17, 0x03, 0xd8, 0x2a, 0x05, 0xe7, 0x2a, + 0xdd, 0xef, 0xe8, 0xab, 0x0d, 0xd4, 0xcb, 0x29, 0x0d, 0xf9, 0xbf, 0x85, 0xfb, + 0x2a, 0xf8, 0x44, 0xdb, 0xa1, 0x24, 0xe2, 0xfe, 0xe0, 0x3a, 0x09, 0xf0, 0x08, + 0xa1, 0xf9, 0x2c, 0x10, 0xdc, 0xf0, 0xec, 0xe8, 0xf8, 0x54, 0x01, 0x1e, 0xb0, + 0x44, 0xf9, 0x0a, 0x3a, 0x29, 0xea, 0xe3, 0xee, 0x5f, 0x22, 0x5b, 0xfe, 0xdd, + 0x89, 0x0c, 0xb2, 0xda, 0x96, 0x99, 0xf4, 0xec, 0x05, 0xc8, 0xf9, 0xdf, 0xf8, + 0xd0, 0x0e, 0xca, 0x9d, 0x38, 0x0b, 0x20, 0x35, 0xf5, 0xf9, 0x2b, 0xcb, 0xef, + 0x26, 0xe3, 0xea, 0x45, 0x23, 0xa2, 0xb7, 0xe1, 0x1c, 0x1d, 0xe1, 0xda, 0x33, + 0xc6, 0x09, 0x1b, 0x4c, 0xc7, 0xd1, 0xb7, 0xf3, 0xa5, 0x36, 0x5a, 0xef, 0x05, + 0xfb, 0x9f, 0xbf, 0x5f, 0x17, 0x84, 0xde, 0xf7, 0xf3, 0x4f, 0xc6, 0x31, 0x25, + 0x27, 0xe3, 0x04, 0xe3, 0x15, 0xa5, 0xeb, 0xbe, 0xe7, 0x0b, 0x3d, 0xcc, 0xe3, + 0x18, 0xb5, 0x21, 0x5f, 0x09, 0xf8, 0xd2, 0xc6, 0xc4, 0x29, 0x18, 0xc2, 0x3c, + 0x32, 0x26, 0xe6, 0x18, 0x36, 0xf5, 0x31, 0xcd, 0xe0, 0x21, 0x6b, 0xef, 0x5c, + 0xca, 0xfd, 0xca, 0x28, 0xc4, 0x01, 0xf7, 0x40, 0xe1, 0xe7, 0xee, 0xdd, 0x11, + 0xc6, 0x08, 0x8d, 0xbe, 0xb8, 0x57, 0x3b, 0xc2, 0xf9, 0xe1, 0xec, 0x3d, 0x32, + 0xa9, 0xc1, 0x2f, 0x3c, 0x10, 0xc5, 0x0b, 0x0d, 0x0c, 0x08, 0xbe, 0xda, 0xf1, + 0xff, 0xcd, 0x00, 0x44, 0x03, 0x59, 0xae, 0x0d, 0x18, 0xdf, 0xf3, 0x7f, 0xf1, + 0x02, 0x5d, 0x05, 0xf9, 0xea, 0xfa, 0x91, 0x1e, 0x0d, 0xf9, 0xf3, 0x33, 0x46, + 0xfc, 0xfc, 0x5a, 0xcc, 0x42, 0x39, 0xe7, 0xc3, 0xb9, 0xec, 0xce, 0x9a, 0x38, + 0xb5, 0xea, 0xc2, 0xc8, 0x24, 0x2c, 0xcc, 0x14, 0xac, 0xe2, 0xc8, 0x33, 0xb5, + 0xf2, 0xa0, 0xee, 0xdd, 0x2a, 0x97, 0xef, 0x22, 0xda, 0x5d, 0x2d, 0x4e, 0x07, + 0xdb, 0xc6, 0xb9, 0xe9, 0xa7, 0x00, 0xf4, 0xc4, 0xd4, 0xb6, 0xef, 0xdd, 0xe8, + 0xef, 0xee, 0x9d, 0xeb, 0xde, 0xec, 0xc9, 0xe7, 0xf7, 0xcb, 0xb8, 0xc2, 0x0f, + 0xfc, 0xec, 0xfa, 0xda, 0x89, 0x05, 0x3e, 0xc0, 0x29, 0xf7, 0x14, 0xe2, 0xf1, + 0xda, 0xd3, 0xe5, 0xdd, 0x0a, 0xf6, 0x16, 0x03, 0xeb, 0xed, 0x39, 0x34, 0xb8, + 0xe7, 0xf2, 0x1f, 0xb9, 0xed, 0xb5, 0xe4, 0x18, 0x35, 0xf8, 0x1b, 0xd6, 0x20, + 0x48, 0x2f, 0x06, 0xaa, 0xd7, 0x1d, 0xd8, 0x06, 0x09, 0xca, 0xdf, 0x1d, 0x28, + 0x07, 0x11, 0xf5, 0x0c, 0xf5, 0x8a, 0xe9, 0x19, 0xc6, 0xcd, 0xf6, 0xc1, 0xe9, + 0x0a, 0xfd, 0x38, 0xe2, 0xde, 0x08, 0xd1, 0xd2, 0xe7, 0x10, 0xfd, 0x16, 0xdf, + 0x50, 0x81, 0x1f, 0xd4, 0x03, 0xbe, 0x50, 0x12, 0xd1, 0xe4, 0xdd, 0xe3, 0x1a, + 0x1a, 0xe0, 0xd1, 0xdb, 0xe1, 0xbe, 0x05, 0xf5, 0x9c, 0x10, 0x02, 0x0c, 0x1a, + 0xd4, 0x27, 0xf3, 0xd2, 0x32, 0x88, 0x0e, 0x23, 0x14, 0x58, 0xfa, 0xf8, 0xf3, + 0xe2, 0x32, 0xe1, 0xdd, 0xe5, 0x00, 0xb8, 0x24, 0xee, 0x39, 0xab, 0xf8, 0xd4, + 0xf4, 0x57, 0xd8, 0xc5, 0xf7, 0x49, 0x2f, 0x4a, 0xe5, 0xf7, 0xea, 0xfa, 0xec, + 0x39, 0x27, 0xc6, 0xc8, 0x1f, 0xeb, 0xd5, 0x53, 0xf7, 0x60, 0xe4, 0xe3, 0x39, + 0xbc, 0xd1, 0xab, 0x1f, 0x1e, 0x0d, 0xd7, 0x1c, 0x51, 0xc6, 0xc3, 0x21, 0xc2, + 0xd0, 0x14, 0xbd, 0xc8, 0xb0, 0xc4, 0x0e, 0xeb, 0x4b, 0x0b, 0xf0, 0xe7, 0xee, + 0xe9, 0x63, 0xda, 0xe8, 0x2a, 0xf8, 0xd6, 0xde, 0x19, 0x22, 0xe0, 0xb8, 0xfd, + 0xee, 0xd4, 0xfb, 0xda, 0x47, 0xc7, 0x50, 0x14, 0xe2, 0xd7, 0x18, 0x05, 0xd4, + 0xfd, 0x9f, 0x06, 0xee, 0xf1, 0xe1, 0xce, 0x40, 0x2f, 0xff, 0x0c, 0x19, 0xf1, + 0x29, 0xbb, 0xc6, 0xd7, 0xee, 0xb4, 0xe9, 0xc1, 0xe2, 0xfd, 0x08, 0xb4, 0x32, + 0xdd, 0x16, 0xe1, 0x21, 0x97, 0xd0, 0xf6, 0x03, 0xe0, 0xbc, 0xd7, 0x96, 0x48, + 0xe0, 0xfb, 0xd8, 0xe4, 0xe2, 0x06, 0xd6, 0x11, 0xe7, 0xd5, 0x92, 0x32, 0xfc, + 0xef, 0xd4, 0xe6, 0x42, 0x19, 0xce, 0x09, 0x16, 0xcb, 0xae, 0x0a, 0xe2, 0x33, + 0x0d, 0xa2, 0x33, 0x00, 0xe0, 0x0e, 0xd0, 0x4c, 0x15, 0xe7, 0x3f, 0xdb, 0x1a, + 0x33, 0x38, 0xc8, 0xfb, 0xc1, 0xfa, 0x04, 0x17, 0x27, 0x3f, 0x12, 0xb4, 0x18, + 0xf4, 0x05, 0xe8, 0x0b, 0x1c, 0xa8, 0xe7, 0xde, 0x04, 0xb8, 0xf0, 0x00, 0xc5, + 0x10, 0xd7, 0xd3, 0xb8, 0x28, 0x37, 0xf7, 0x2f, 0xde, 0x05, 0xa7, 0xe8, 0xa9, + 0x15, 0xf2, 0x06, 0xb7, 0xf3, 0xc3, 0xc1, 0x21, 0x0e, 0x0b, 0x2a, 0xeb, 0x05, + 0xfe, 0x11, 0xd0, 0xf5, 0x00, 0xc7, 0x30, 0xe4, 0x15, 0x2c, 0x00, 0x0f, 0x95, + 0xd8, 0x1e, 0xe8, 0x26, 0x13, 0xd8, 0xcf, 0xde, 0xcc, 0x3e, 0xcd, 0x9d, 0x15, + 0x4d, 0x54, 0x3f, 0xac, 0xed, 0x3f, 0xce, 0xb0, 0x21, 0x47, 0xdd, 0x31, 0x81, + 0xf0, 0x1e, 0x07, 0xc9, 0x29, 0x04, 0xd3, 0x3f, 0xff, 0xef, 0xb1, 0x1a, 0x05, + 0xfb, 0x32, 0xf2, 0xfe, 0xe2, 0x1b, 0x08, 0xaf, 0xb6, 0xa9, 0xeb, 0xba, 0x16, + 0x41, 0xbc, 0xaf, 0xdb, 0xdf, 0x16, 0x1c, 0x32, 0x2d, 0x19, 0xd4, 0xc4, 0x4c, + 0xb9, 0xba, 0xdf, 0x30, 0xc1, 0x93, 0xce, 0x03, 0xac, 0xdb, 0xef, 0xff, 0xf1, + 0x4a, 0x49, 0xca, 0xfc, 0xeb, 0xbd, 0x09, 0x20, 0x2f, 0x06, 0x3f, 0xfd, 0x3b, + 0x1c, 0x29, 0xf4, 0x11, 0x16, 0x0b, 0xd8, 0xef, 0x32, 0x08, 0xfa, 0x4d, 0xe1, + 0x3a, 0xbc, 0x50, 0xeb, 0x38, 0x07, 0xf2, 0x13, 0xbb, 0xd2, 0xac, 0x4f, 0x5f, + 0x09, 0x26, 0xfa, 0xee, 0xea, 0x3c, 0xda, 0x0f, 0x54, 0xe7, 0x07, 0x09, 0xed, + 0xda, 0x33, 0x20, 0x2c, 0x33, 0xcd, 0xf4, 0x3f, 0xbe, 0xf3, 0xbe, 0xa8, 0xc1, + 0xbb, 0x12, 0xfe, 0x00, 0x02, 0xc0, 0x25, 0x0a, 0xda, 0xa8, 0xdc, 0x24, 0x0a, + 0xc7, 0xef, 0xd1, 0xf2, 0xed, 0xc1, 0x0d, 0xe2, 0x8d, 0x02, 0xeb, 0x07, 0xf7, + 0xde, 0xf1, 0xcd, 0x20, 0x26, 0x1e, 0xd2, 0xf9, 0xa7, 0xb7, 0xef, 0x01, 0xce, + 0xb8, 0xaf, 0xbc, 0xd8, 0xf5, 0x4d, 0xe3, 0xd0, 0xa3, 0xc6, 0x1e, 0x02, 0xd4, + 0x00, 0x10, 0xde, 0xd5, 0xed, 0xfe, 0xdb, 0xd5, 0xfa, 0x0d, 0x23, 0x54, 0xf9, + 0xfe, 0xd0, 0xdb, 0xa8, 0x1f, 0x0a, 0xa1, 0x04, 0xef, 0x4e, 0x03, 0x19, 0xf2, + 0xec, 0xbd, 0x20, 0xbb, 0xe6, 0xf7, 0x1b, 0xbe, 0xe9, 0x14, 0xf9, 0xdc, 0xf2, + 0xe5, 0xf7, 0xf1, 0xe8, 0xb8, 0xe9, 0xe3, 0xee, 0xf4, 0x28, 0x0b, 0x9f, 0xe3, + 0xff, 0x22, 0xd2, 0x98, 0x81, 0x16, 0xed, 0xf3, 0x9f, 0x15, 0xfd, 0x11, 0x1a, + 0xda, 0xea, 0xb5, 0xf2, 0x9d, 0x08, 0x37, 0xb9, 0x22, 0xbc, 0x11, 0x21, 0xee, + 0x1a, 0x2c, 0xca, 0x01, 0xdd, 0xfe, 0xd8, 0xf6, 0xa5, 0x05, 0xc7, 0x9b, 0xf7, + 0xe2, 0xa9, 0xd6, 0x11, 0xc0, 0xf7, 0x11, 0xfa, 0x1e, 0xde, 0xc9, 0x27, 0x13, + 0xf4, 0xee, 0x1c, 0xbd, 0x06, 0xf5, 0xde, 0x27, 0xbf, 0x11, 0xcf, 0xc7, 0x53, + 0x1c, 0x17, 0xe1, 0xf4, 0xfa, 0x35, 0xce, 0xe0, 0x06, 0xeb, 0x27, 0xed, 0xc1, + 0xdc, 0x18, 0xf4, 0xa7, 0xde, 0x12, 0xd9, 0x09, 0xe0, 0x28, 0xcf, 0xdc, 0x11, + 0x12, 0x03, 0x2f, 0x30, 0xcf, 0xfa, 0x11, 0xc7, 0xe5, 0x40, 0x07, 0xeb, 0x37, + 0xde, 0xc0, 0x26, 0x10, 0xca, 0x3d, 0xe3, 0xe8, 0xe9, 0xf1, 0x04, 0xe2, 0xe9, + 0x09, 0x30, 0x20, 0x15, 0x11, 0xc7, 0xed, 0xe0, 0x06, 0x1c, 0xdf, 0x1d, 0xea, + 0xd7, 0x18, 0x01, 0xd8, 0x99, 0xf3, 0x05, 0x19, 0x0e, 0x1b, 0x3e, 0xbf, 0x29, + 0x6e, 0xcc, 0x0b, 0x2a, 0xf6, 0xa3, 0xee, 0x8f, 0x18, 0xbb, 0xfe, 0xb0, 0xce, + 0x28, 0xbf, 0x1e, 0x01, 0x0e, 0xeb, 0x24, 0xef, 0xfb, 0xb4, 0x11, 0x67, 0xd6, + 0xec, 0xa1, 0x01, 0x90, 0x41, 0x4f, 0xc0, 0x0a, 0x1f, 0xab, 0xe4, 0xf2, 0xdc, + 0xec, 0x09, 0x12, 0x97, 0x04, 0x22, 0xf2, 0x2d, 0x20, 0x15, 0x9f, 0xc4, 0x15, + 0x2f, 0xf5, 0x11, 0xfe, 0x1e, 0x05, 0x4e, 0x08, 0x0c, 0x19, 0x38, 0xf1, 0xce, + 0x1c, 0x20, 0xc2, 0xb7, 0xd2, 0xdc, 0xf6, 0x13, 0xfb, 0xaa, 0xde, 0x24, 0x2b, + 0x04, 0xb0, 0xc4, 0x23, 0x9b, 0xb3, 0xe6, 0x8d, 0xc3, 0xd6, 0xd7, 0x37, 0x2a, + 0xd2, 0x37, 0xda, 0x81, 0xea, 0x25, 0x2b, 0xce, 0x08, 0x07, 0xf0, 0x3a, 0xe3, + 0x1e, 0xa9, 0xe7, 0xf1, 0xed, 0x1a, 0xa8, 0x21, 0xe2, 0xe9, 0xd4, 0xc2, 0xd5, + 0x15, 0x45, 0xdf, 0x38, 0xcf, 0x3b, 0x1f, 0xe4, 0x24, 0x43, 0xe4, 0x07, 0xcc, + 0xca, 0xfe, 0xe8, 0x10, 0x30, 0xc0, 0xc0, 0x31, 0x9c, 0xf9, 0xdf, 0xd5, 0xd2, + 0x07, 0x2f, 0xfc, 0xff, 0x0e, 0xe0, 0x06, 0x20, 0xb3, 0x19, 0xf9, 0x20, 0xae, + 0xe3, 0xfa, 0xd5, 0x0b, 0x25, 0x2d, 0xc6, 0xe9, 0x06, 0x36, 0xce, 0xf6, 0x17, + 0xf5, 0xde, 0x25, 0xee, 0x25, 0xd1, 0xe4, 0xe1, 0x33, 0xfa, 0xeb, 0x05, 0x55, + 0xce, 0x0c, 0xf8, 0xb5, 0xeb, 0x00, 0x65, 0x0b, 0x0b, 0x32, 0xab, 0x02, 0xab, + 0x0f, 0xfb, 0xd6, 0xf3, 0xba, 0xd8, 0xf7, 0x25, 0xb2, 0x46, 0x3b, 0xff, 0xc6, + 0xbd, 0x0b, 0x16, 0xce, 0xf2, 0xed, 0xb2, 0xf4, 0xf3, 0xf9, 0xe8, 0xe9, 0xb5, + 0xe1, 0x9d, 0xff, 0xf0, 0xed, 0xd2, 0x18, 0xfd, 0xeb, 0xc7, 0xf6, 0x3f, 0x0c, + 0xdc, 0xe8, 0x0d, 0x2b, 0xd0, 0x64, 0x15, 0x10, 0xcf, 0x05, 0xdc, 0xe0, 0xcf, + 0xda, 0xdd, 0x24, 0xd2, 0x40, 0x07, 0xb1, 0x41, 0x02, 0xe4, 0xca, 0x07, 0x23, + 0x2f, 0xbf, 0xf0, 0xcb, 0xc0, 0x00, 0xba, 0xee, 0xe2, 0xc7, 0x14, 0xca, 0x3f, + 0xf5, 0xba, 0xdd, 0xf2, 0xfc, 0x28, 0xa4, 0x09, 0xbc, 0xe5, 0x2c, 0x22, 0x57, + 0x25, 0x40, 0x20, 0xab, 0xdf, 0x01, 0x2d, 0x08, 0xa4, 0xde, 0x1a, 0x0f, 0xe9, + 0xc3, 0x1a, 0x41, 0xc1, 0xe4, 0xb9, 0xeb, 0x0d, 0xd7, 0xb6, 0x04, 0x08, 0x47, + 0xed, 0x0d, 0x32, 0x2a, 0x25, 0xe3, 0x10, 0xe2, 0xb9, 0xb3, 0xd2, 0x0d, 0x3a, + 0x2c, 0xe4, 0xef, 0x39, 0x9c, 0xcb, 0xbe, 0xf1, 0x23, 0x60, 0x02, 0x4a, 0xd1, + 0xbe, 0xd9, 0xa9, 0x2a, 0x1e, 0x0f, 0xb4, 0x02, 0x03, 0xdf, 0xd2, 0x23, 0xa7, + 0xcf, 0x1e, 0x32, 0x16, 0x09, 0xfe, 0x1d, 0xe6, 0x19, 0xd7, 0xb9, 0xd1, 0xc4, + 0x51, 0xbc, 0x13, 0x16, 0xf4, 0x4e, 0xf0, 0xcb, 0xff, 0xeb, 0xdd, 0x03, 0xf4, + 0x12, 0x25, 0x40, 0xde, 0x47, 0xf7, 0xe1, 0xdf, 0x45, 0xf6, 0x26, 0xa7, 0xeb, + 0xe6, 0xee, 0x0a, 0xed, 0xed, 0xfb, 0x32, 0xc4, 0x45, 0x33, 0xd2, 0x26, 0xeb, + 0x1e, 0x09, 0x2a, 0xde, 0x3f, 0xcc, 0x44, 0xe5, 0x27, 0xb6, 0x50, 0xb2, 0x03, + 0xf4, 0x16, 0xc7, 0xc2, 0xdc, 0xd3, 0x05, 0x35, 0x14, 0x4e, 0xd6, 0xd5, 0x4f, + 0x0d, 0xcd, 0x1b, 0xfe, 0x68, 0xe5, 0xce, 0x0c, 0x1b, 0xe4, 0xea, 0xc0, 0xfd, + 0xcb, 0x79, 0x0a, 0x9b, 0x40, 0xe2, 0xfd, 0xa4, 0xbc, 0xc3, 0x21, 0x51, 0x48, + 0xa2, 0x06, 0x91, 0x00, 0xe1, 0xfa, 0x37, 0x09, 0xdc, 0x3d, 0x00, 0xcd, 0x7f, + 0xf7, 0x43, 0x1c, 0xe4, 0x1c, 0xfc, 0x4a, 0x21, 0xb2, 0xdb, 0x04, 0x21, 0xcf, + 0x00, 0xa6, 0xe4, 0x29, 0x17, 0x2a, 0xde, 0x22, 0x47, 0xf1, 0x17, 0xe5, 0x03, + 0xd3, 0xc5, 0xce, 0xfc, 0xd9, 0xe8, 0xd8, 0xf1, 0xc2, 0x2f, 0x08, 0x47, 0xf3, + 0xc4, 0x04, 0xea, 0xd3, 0xb4, 0x33, 0xe2, 0xee, 0xc5, 0xe5, 0x19, 0xf2, 0xff, + 0xc1, 0xfb, 0xd7, 0x1e, 0xe7, 0xd2, 0x03, 0xd8, 0xd9, 0xea, 0xb0, 0xfa, 0x1f, + 0x43, 0xe8, 0xe1, 0x2e, 0x15, 0x24, 0xe5, 0xc4, 0x1b, 0xd9, 0x0d, 0x1b, 0xe3, + 0xeb, 0x0c, 0xcc, 0xe1, 0x46, 0xfc, 0xde, 0x0e, 0x0a, 0x0b, 0xd2, 0x10, 0xda, + 0x0f, 0xec, 0x0a, 0xf9, 0xe1, 0xdf, 0x14, 0xea, 0x22, 0x45, 0xf0, 0x22, 0x15, + 0xc6, 0x04, 0xfd, 0x0c, 0x2e, 0x01, 0xdc, 0x05, 0xba, 0xf3, 0xe3, 0x04, 0x1c, + 0xde, 0xf7, 0xd8, 0x13, 0xfa, 0xd6, 0xec, 0x1b, 0x15, 0xfa, 0xcf, 0xe6, 0xdd, + 0x22, 0x03, 0xf4, 0xd7, 0x1f, 0xf3, 0xe2, 0xfe, 0x02, 0x2e, 0xf7, 0xdb, 0xf6, + 0xf9, 0xfb, 0x17, 0xed, 0x1a, 0xf0, 0xed, 0xc6, 0xf7, 0x18, 0xad, 0x29, 0xfb, + 0x04, 0xf0, 0x35, 0x0b, 0xd0, 0x0d, 0x02, 0x17, 0x09, 0xf6, 0xfd, 0x0d, 0xac, + 0xdf, 0x18, 0xd5, 0xcf, 0xd9, 0xce, 0x3d, 0xf8, 0xeb, 0xff, 0x12, 0xb1, 0x15, + 0x01, 0xf9, 0x1a, 0x10, 0xeb, 0xf5, 0x1f, 0x05, 0x0e, 0xfd, 0xfd, 0x12, 0x09, + 0x27, 0xcd, 0x11, 0x0d, 0x35, 0xa3, 0xda, 0xc4, 0xde, 0xee, 0x03, 0xf7, 0x1b, + 0x26, 0x0d, 0x18, 0x2c, 0x06, 0xb9, 0xef, 0x2b, 0xe6, 0x0a, 0xee, 0x0c, 0xed, + 0x79, 0xe3, 0x16, 0x47, 0xf1, 0xfe, 0xde, 0xf2, 0xe5, 0x05, 0xd4, 0xde, 0xec, + 0x44, 0xc9, 0xd1, 0x2f, 0x07, 0xf6, 0x17, 0x1b, 0xd9, 0xdd, 0xed, 0x3a, 0x35, + 0x2a, 0x3e, 0x08, 0x08, 0xaa, 0xef, 0xeb, 0xa6, 0x7f, 0xf1, 0x57, 0x26, 0x29, + 0xe0, 0x0e, 0x33, 0xcf, 0x29, 0xdf, 0xd8, 0xed, 0x18, 0xf2, 0x07, 0x08, 0x28, + 0xd4, 0xde, 0xd7, 0xd4, 0x0b, 0xc2, 0xcf, 0xf3, 0x2e, 0x0b, 0xb3, 0x95, 0x1f, + 0x1f, 0x23, 0x02, 0x0c, 0x19, 0xf5, 0xe6, 0xfd, 0xb9, 0x12, 0xe6, 0x13, 0x13, + 0x35, 0x38, 0x20, 0x1a, 0xe6, 0xf4, 0x32, 0x50, 0xc3, 0x04, 0xb5, 0xdf, 0xe1, + 0xf4, 0xf5, 0xdb, 0x42, 0xfb, 0xeb, 0xf2, 0xb8, 0x20, 0xe7, 0x25, 0x06, 0xee, + 0x33, 0x12, 0xdd, 0x01, 0xef, 0x0f, 0x1f, 0xf2, 0xcc, 0xf9, 0x10, 0xe7, 0xc3, + 0x9e, 0xe1, 0x19, 0x2a, 0xf5, 0x0c, 0xde, 0xc8, 0xda, 0xf4, 0xb0, 0xec, 0x09, + 0x1a, 0x02, 0xab, 0x5e, 0xce, 0x0e, 0x2d, 0xfb, 0xee, 0x1b, 0xf2, 0x3d, 0x51, + 0xde, 0xbf, 0x24, 0xe0, 0x3a, 0xa9, 0x27, 0xaa, 0xce, 0xb3, 0xf7, 0xcd, 0xf8, + 0xa7, 0xf6, 0xf3, 0xe1, 0x1e, 0x3a, 0x36, 0xc2, 0xb4, 0xfb, 0x41, 0x51, 0x0e, + 0x17, 0x27, 0x00, 0x14, 0xf0, 0xe2, 0xc9, 0xcc, 0xf6, 0xcd, 0xf0, 0xcb, 0x2f, + 0xb6, 0x06, 0x29, 0xe6, 0xba, 0xf5, 0xed, 0xe1, 0xdb, 0x49, 0xfa, 0xfd, 0xfe, + 0x03, 0xff, 0x07, 0xf9, 0x33, 0xc7, 0xfd, 0x1c, 0x4c, 0x93, 0x0b, 0xeb, 0xbd, + 0xda, 0xf3, 0x1a, 0xfb, 0x3d, 0x13, 0x2d, 0x3a, 0x2e, 0x3b, 0xc7, 0x9b, 0x1b, + 0xe5, 0xec, 0x0c, 0x11, 0xdf, 0xee, 0xef, 0xce, 0x20, 0x18, 0x3e, 0xe9, 0xf9, + 0x22, 0x15, 0x04, 0xfe, 0x09, 0x00, 0x10, 0xfe, 0xf1, 0x2e, 0xf6, 0xbe, 0x3c, + 0xb7, 0xd6, 0xe2, 0x08, 0x24, 0x36, 0xf3, 0x05, 0x17, 0x47, 0xdd, 0xf9, 0xf0, + 0xff, 0xf3, 0x4a, 0xea, 0xee, 0xe1, 0x03, 0x26, 0x95, 0xc4, 0x3c, 0x44, 0x2c, + 0xd3, 0xeb, 0xb8, 0x67, 0x0d, 0x25, 0x3d, 0xbc, 0x19, 0x3e, 0xfa, 0xdb, 0xd8, + 0x7f, 0x25, 0xa0, 0x28, 0x13, 0x34, 0xef, 0xd3, 0x23, 0xec, 0xbf, 0xc4, 0x09, + 0xcf, 0x3f, 0xca, 0x02, 0xf4, 0xc1, 0xde, 0xb7, 0xfd, 0xb9, 0x0e, 0xfd, 0xf8, + 0x09, 0xdd, 0xfb, 0xb3, 0xe8, 0x2d, 0x29, 0x27, 0xf3, 0xf6, 0xfc, 0xec, 0x13, + 0x08, 0xfe, 0xf1, 0x17, 0x06, 0xc5, 0x11, 0xf5, 0xf2, 0x1d, 0x25, 0xe0, 0xd6, + 0x01, 0x00, 0x1b, 0xbc, 0x05, 0x2f, 0xbf, 0x16, 0x16, 0x2e, 0xc6, 0xfa, 0xb4, + 0x5a, 0x43, 0xaa, 0xdd, 0xf2, 0xf2, 0xd6, 0xa1, 0xef, 0x0d, 0xcc, 0xca, 0xe0, + 0x57, 0xec, 0x9d, 0xd2, 0x3c, 0xd4, 0xf2, 0xc6, 0xfc, 0xbe, 0xb2, 0x11, 0xbc, + 0xdc, 0xef, 0x3b, 0xe1, 0x23, 0xc6, 0x0c, 0xd9, 0x15, 0x05, 0xf1, 0x54, 0x34, + 0xf9, 0xaa, 0xf3, 0xf4, 0x98, 0xda, 0x21, 0x22, 0xdd, 0xf7, 0x17, 0x11, 0x4b, + 0xed, 0x05, 0xf0, 0xf4, 0x41, 0xd1, 0xa8, 0x0f, 0x08, 0x1b, 0x16, 0x04, 0x9c, + 0xff, 0x18, 0xf1, 0xbe, 0x3d, 0x0b, 0xcd, 0xbf, 0xa7, 0xe2, 0x2c, 0xec, 0x0d, + 0xf5, 0xc9, 0xf3, 0x00, 0x07, 0x0b, 0xd1, 0x9f, 0x42, 0x21, 0xcf, 0xed, 0xfa, + 0xf7, 0x14, 0x0a, 0xcf, 0xc6, 0x31, 0x0e, 0xd1, 0xd0, 0x4d, 0xbb, 0xe9, 0xe0, + 0x3d, 0xd4, 0xcb, 0x21, 0xfa, 0xd9, 0x2f, 0xb4, 0xd3, 0xe5, 0x14, 0x03, 0xa4, + 0xda, 0x17, 0x18, 0x3a, 0xf1, 0xfc, 0xb6, 0x2b, 0x21, 0xde, 0x1b, 0xaf, 0xf0, + 0xe3, 0xd0, 0xdb, 0xf2, 0x15, 0xce, 0x24, 0x19, 0xc4, 0xf7, 0x0d, 0x11, 0xf7, + 0xff, 0xfa, 0xc8, 0xa5, 0x19, 0xde, 0xe8, 0xd6, 0x05, 0x0a, 0x1d, 0x12, 0xfd, + 0xed, 0xc5, 0x2a, 0xc1, 0xc6, 0xbc, 0xc8, 0x04, 0x81, 0x4c, 0x2a, 0xe9, 0xac, + 0xfa, 0x25, 0x40, 0xeb, 0xf2, 0xf4, 0xce, 0x1a, 0xd1, 0xcb, 0xee, 0xe0, 0xc3, + 0x1e, 0xd5, 0xca, 0x0d, 0xf6, 0x3b, 0x3b, 0xf5, 0x1f, 0xe2, 0x2e, 0x35, 0x3a, + 0x3c, 0xb7, 0xd6, 0x0a, 0xd3, 0xe4, 0x47, 0x13, 0x38, 0x09, 0xde, 0xd3, 0x0b, + 0x05, 0xe7, 0xe7, 0x25, 0x17, 0x27, 0x19, 0x17, 0xce, 0xf3, 0x22, 0xbd, 0xec, + 0xee, 0xca, 0x5a, 0xf8, 0xeb, 0x22, 0xeb, 0xe3, 0x34, 0xf9, 0x18, 0xcc, 0xbd, + 0x0b, 0x01, 0xfa, 0x15, 0xce, 0x08, 0x39, 0xaf, 0xe9, 0x2a, 0x22, 0x3d, 0xe7, + 0xd4, 0x23, 0xdc, 0xdd, 0x12, 0xdc, 0x28, 0xbd, 0xde, 0x09, 0xdd, 0xee, 0x52, + 0xff, 0x21, 0xc0, 0xcb, 0xd7, 0x34, 0xfa, 0xee, 0xf3, 0x2e, 0x0a, 0x1e, 0x0a, + 0xd5, 0x2b, 0xcd, 0xe6, 0x16, 0x34, 0x04, 0xf2, 0x36, 0xed, 0x1b, 0xce, 0xd2, + 0x42, 0x04, 0xd9, 0xe2, 0x71, 0xd2, 0x00, 0xf0, 0xfb, 0xd7, 0x2a, 0x40, 0x11, + 0xe0, 0x1e, 0xfe, 0x01, 0x09, 0x34, 0xb8, 0x26, 0xc1, 0xfc, 0x9d, 0x00, 0xf0, + 0xeb, 0x11, 0x04, 0xd9, 0x9b, 0x21, 0xf3, 0x02, 0xd6, 0x06, 0xeb, 0x3c, 0xea, + 0xbb, 0xfc, 0xde, 0x12, 0x0a, 0x0c, 0x62, 0xde, 0xe3, 0xe2, 0xda, 0x19, 0xfc, + 0xe0, 0xe7, 0x40, 0xe1, 0xd2, 0x8d, 0xa4, 0xf4, 0xe3, 0x02, 0xe0, 0xd1, 0x39, + 0xd0, 0x1d, 0xed, 0xca, 0xe0, 0x11, 0x87, 0xe2, 0xd1, 0xd9, 0xb5, 0xea, 0xa3, + 0x35, 0xfe, 0x12, 0xef, 0x09, 0x37, 0x33, 0xeb, 0xf5, 0xf7, 0xe2, 0xcc, 0xf5, + 0x2b, 0xc1, 0xfa, 0xd2, 0xe6, 0x02, 0xf7, 0xc8, 0xe9, 0x7f, 0xc4, 0x5f, 0x2c, + 0x0e, 0xfc, 0x2f, 0xea, 0xad, 0x1c, 0xdd, 0xf8, 0xd1, 0xfa, 0x09, 0xb0, 0xae, + 0xd9, 0xc6, 0xde, 0x04, 0xfc, 0xe4, 0x0d, 0xef, 0xce, 0x1b, 0x11, 0x21, 0xfa, + 0xca, 0x4b, 0x1e, 0x10, 0xf1, 0x1d, 0x3c, 0xbf, 0xd1, 0xe5, 0xd6, 0x0d, 0x18, + 0xdc, 0x13, 0x10, 0xee, 0x4f, 0x0b, 0x07, 0xf3, 0x08, 0xde, 0x30, 0xd4, 0x3a, + 0x4c, 0x19, 0xac, 0xfb, 0xe1, 0x2b, 0x23, 0xde, 0x1d, 0x1d, 0x27, 0x12, 0xe4, + 0x0e, 0xe8, 0x61, 0xcb, 0xa1, 0x03, 0xe6, 0x97, 0x44, 0xab, 0x07, 0xb4, 0xef, + 0xda, 0xdc, 0x0a, 0xe7, 0xec, 0xd8, 0x1e, 0xb6, 0x2f, 0xdf, 0x13, 0xcd, 0x37, + 0x03, 0x0c, 0x1e, 0xde, 0x9a, 0x0e, 0x11, 0x2b, 0xf5, 0xdd, 0xe0, 0xd2, 0x1d, + 0xbd, 0x01, 0x0e, 0xfd, 0xdc, 0xf5, 0x0a, 0xca, 0x33, 0xe1, 0x0b, 0xf1, 0xf8, + 0x2e, 0xa5, 0x1d, 0xe7, 0x4c, 0x01, 0x33, 0x18, 0x2a, 0xc9, 0xe8, 0x04, 0xd8, + 0x1f, 0xde, 0x00, 0x44, 0xbd, 0xd9, 0xc7, 0x11, 0xf0, 0xd6, 0x32, 0xcf, 0x13, + 0x9a, 0xdd, 0xd9, 0xc7, 0xf4, 0xf2, 0xbb, 0xc5, 0xf0, 0x01, 0x00, 0x81, 0xe7, + 0x27, 0xf4, 0x10, 0x08, 0x6a, 0xee, 0xb7, 0x13, 0x58, 0x5f, 0xd8, 0x16, 0xff, + 0x43, 0xe9, 0x31, 0x13, 0x51, 0xfc, 0xed, 0x01, 0x35, 0xb7, 0x02, 0x00, 0xf8, + 0xf1, 0x0f, 0x2a, 0xf7, 0xe7, 0xc8, 0xa8, 0xeb, 0xa8, 0x2c, 0x21, 0xf4, 0x2d, + 0x15, 0x41, 0x14, 0x28, 0x18, 0xf4, 0x0f, 0x21, 0xfe, 0xd7, 0x27, 0x43, 0xf2, + 0xa3, 0xe5, 0x52, 0xf4, 0xfd, 0xc4, 0x59, 0x0a, 0xbf, 0xe2, 0xcd, 0x39, 0x15, + 0x08, 0x10, 0x09, 0x97, 0x97, 0x23, 0x40, 0x28, 0x4a, 0x0e, 0xed, 0x1d, 0x32, + 0xf4, 0xc6, 0xe6, 0xae, 0xf1, 0x45, 0x4b, 0xd0, 0xfe, 0x33, 0x35, 0x1c, 0xda, + 0xaf, 0x17, 0x03, 0x37, 0x2c, 0x02, 0x1c, 0xda, 0x27, 0xf2, 0x36, 0xed, 0x2a, + 0x2a, 0x14, 0xcf, 0xee, 0x0d, 0xd7, 0x06, 0xe2, 0x05, 0x52, 0xee, 0x14, 0xe1, + 0xf3, 0xad, 0xea, 0xe3, 0xe7, 0xfd, 0xf1, 0xea, 0xeb, 0xc4, 0x1a, 0xff, 0x0e, + 0xdc, 0xce, 0xf2, 0xfd, 0xaf, 0xb1, 0xb1, 0xaf, 0x2e, 0xb9, 0x14, 0x31, 0x31, + 0xbd, 0xcb, 0xda, 0xc1, 0x37, 0xfd, 0x64, 0xe2, 0xba, 0xfb, 0x27, 0xef, 0x15, + 0xd0, 0x1d, 0xee, 0x0f, 0xc3, 0xea, 0x30, 0x31, 0xfb, 0xd5, 0x12, 0x0c, 0xf2, + 0x3a, 0x89, 0x30, 0x91, 0xc2, 0xda, 0xc1, 0x0b, 0xe1, 0x31, 0x4c, 0x30, 0xde, + 0xe8, 0x0a, 0x11, 0x0d, 0xeb, 0xef, 0x00, 0x05, 0xd9, 0xbf, 0x08, 0x39, 0x36, + 0xed, 0xbe, 0xc9, 0x1e, 0xf0, 0x3b, 0x44, 0xfa, 0xa4, 0x8f, 0xc7, 0xd1, 0xd5, + 0x0c, 0xe0, 0x14, 0xcf, 0x24, 0xcb, 0x1b, 0xf7, 0xd9, 0xdf, 0x10, 0xfa, 0xa9, + 0xa7, 0x03, 0xfd, 0xd4, 0x0b, 0xca, 0xd5, 0xe4, 0xb6, 0x23, 0xca, 0xed, 0x04, + 0xf1, 0x38, 0xf9, 0x01, 0xac, 0x4c, 0x0e, 0xd7, 0xcf, 0xad, 0xe4, 0x20, 0x0a, + 0xf8, 0xfc, 0x2f, 0xcc, 0xff, 0xdd, 0xe1, 0x81, 0x04, 0xac, 0xd6, 0xe6, 0xbd, + 0x2e, 0x47, 0xf1, 0x1f, 0x3a, 0xd0, 0x0f, 0xb9, 0x17, 0xac, 0x04, 0xcb, 0x20, + 0x32, 0x88, 0x20, 0x00, 0x34, 0xe4, 0xdc, 0xc6, 0x37, 0x0c, 0x22, 0x02, 0x1e, + 0xd6, 0xe0, 0x02, 0x06, 0xa2, 0xe9, 0xec, 0xe5, 0x03, 0xee, 0xe6, 0xca, 0x01, + 0xd1, 0xb8, 0x0d, 0x26, 0x2a, 0x12, 0xbc, 0xdb, 0xf3, 0xcb, 0xc2, 0x21, 0xcf, + 0x3c, 0xfc, 0x04, 0xc9, 0xc5, 0x13, 0xcd, 0x04, 0x2a, 0xe8, 0xee, 0xaf, 0xec, + 0x1b, 0xf9, 0xc1, 0x05, 0x33, 0x1f, 0x1f, 0x24, 0xdb, 0xb4, 0xea, 0x12, 0x54, + 0xf7, 0xee, 0x24, 0xe3, 0xe0, 0x09, 0xbe, 0xd5, 0x15, 0xdc, 0x2d, 0xea, 0x36, + 0x1e, 0xda, 0xdf, 0x21, 0x07, 0xbd, 0x31, 0xeb, 0xc3, 0xe6, 0xb1, 0xd9, 0x24, + 0xdc, 0x19, 0x0c, 0xa8, 0xff, 0x0a, 0x13, 0xf0, 0xbe, 0xea, 0xde, 0xba, 0xea, + 0x19, 0x2c, 0xe0, 0xdb, 0x48, 0x10, 0xfc, 0x05, 0x1a, 0x0f, 0xb9, 0x2c, 0x0d, + 0xd3, 0xb5, 0xea, 0xd3, 0x04, 0xdd, 0xdc, 0x1e, 0xd8, 0x19, 0xa7, 0x0b, 0xde, + 0x1a, 0xdd, 0x2d, 0xdc, 0xe8, 0x10, 0xf7, 0x19, 0xfb, 0xf6, 0xdb, 0xca, 0xd4, + 0x19, 0xe1, 0x2b, 0xd3, 0xd9, 0xe6, 0xc7, 0xf3, 0xec, 0xfa, 0x15, 0x06, 0xc2, + 0xf9, 0x0a, 0xb0, 0xf0, 0x16, 0xdd, 0xf6, 0xd7, 0x0c, 0x26, 0xfc, 0x31, 0x05, + 0x36, 0xff, 0x35, 0x07, 0x07, 0x2d, 0xef, 0x02, 0xfb, 0xa0, 0xf2, 0xea, 0x0b, + 0x20, 0x32, 0x13, 0x0f, 0x27, 0xb3, 0xf3, 0xbb, 0xe7, 0x14, 0xdc, 0x0b, 0x02, + 0x1d, 0xe2, 0xf7, 0xea, 0xff, 0xf6, 0x0f, 0xde, 0xed, 0xf3, 0x21, 0x0b, 0xee, + 0x18, 0xf3, 0x33, 0xf7, 0x25, 0xf0, 0xf8, 0xd3, 0xc5, 0xe0, 0xeb, 0xc9, 0xea, + 0xe2, 0x08, 0x10, 0xcd, 0xfc, 0xf1, 0x0e, 0x02, 0x15, 0xcd, 0xf9, 0x18, 0x14, + 0x08, 0x1f, 0x01, 0xfe, 0xcb, 0xf8, 0xed, 0xef, 0x05, 0x07, 0xf7, 0xdd, 0x07, + 0x17, 0xd0, 0x16, 0x20, 0x22, 0x06, 0x0d, 0x05, 0x7f, 0xfd, 0xdc, 0xf4, 0x18, + 0x16, 0x0c, 0xd8, 0x14, 0x05, 0x01, 0x17, 0xc5, 0xcf, 0xf1, 0xd9, 0x02, 0xed, + 0x04, 0x0d, 0x22, 0x1e, 0xf6, 0xbb, 0xfd, 0xed, 0x0a, 0xf8, 0xde, 0xde, 0xd8, + 0x34, 0xf4, 0xfc, 0xf9, 0xcc, 0xcf, 0xf2, 0xea, 0x41, 0x47, 0xd9, 0xd6, 0xe9, + 0xf5, 0xe9, 0xc9, 0x07, 0x09, 0xfc, 0xf6, 0xd6, 0x0a, 0xeb, 0xed, 0xf7, 0xf2, + 0xfc, 0xed, 0xf6, 0xfd, 0xe3, 0xf2, 0x25, 0x0d, 0xd9, 0xd7, 0xf3, 0x14, 0xe5, + 0x4d, 0x0a, 0xeb, 0xf8, 0xeb, 0x19, 0xd2, 0xbb, 0xe7, 0xcb, 0xfa, 0xf4, 0xd7, + 0xf4, 0x17, 0xb7, 0x0e, 0xe8, 0xf0, 0x13, 0xda, 0xf3, 0x0c, 0x0e, 0x0b, 0xe5, + 0xea, 0xf9, 0x0c, 0x58, 0x03, 0xfb, 0x0b, 0xf6, 0xeb, 0x0d, 0xf9, 0xde, 0x29, + 0xda, 0x18, 0xfc, 0xdb, 0xdb, 0xc8, 0x0c, 0x37, 0x1f, 0xf9, 0x14, 0x13, 0xdf, + 0x12, 0x22, 0xff, 0x17, 0xe9, 0xe1, 0xf6, 0x0d, 0x0a, 0xe5, 0xef, 0xd3, 0xd6, + 0xf2, 0xd6, 0xfb, 0xf7, 0xe1, 0x07, 0xff, 0x42, 0xdc, 0x2d, 0xb0, 0x07, 0xfb, + 0xf3, 0x12, 0x05, 0x0f, 0xdf, 0x0e, 0xdc, 0xf2, 0x00, 0xc8, 0xdf, 0x02, 0x0e, + 0x08, 0x22, 0x18, 0x13, 0x2b, 0xd9, 0x00, 0x0b, 0xc2, 0x12, 0xdf, 0xfe, 0x4a, + 0x3c, 0xcc, 0x47, 0x12, 0x20, 0xde, 0x1a, 0xca, 0xed, 0xed, 0x30, 0x0c, 0x04, + 0x38, 0x0f, 0xeb, 0x19, 0xb5, 0x20, 0x22, 0x07, 0xec, 0x09, 0xd4, 0xb4, 0xf3, + 0x11, 0xf6, 0xbb, 0xd9, 0x05, 0xf4, 0x0a, 0xed, 0x33, 0xc1, 0xe8, 0x43, 0xd4, + 0x07, 0xfc, 0xdc, 0x2e, 0x0f, 0x1d, 0x2e, 0xd2, 0xe5, 0xff, 0x1a, 0xc1, 0xea, + 0x26, 0x29, 0xb8, 0x17, 0xbe, 0x08, 0xdc, 0xe9, 0xd7, 0xeb, 0xe1, 0x31, 0xdf, + 0xef, 0x01, 0xd8, 0xa1, 0x3b, 0x20, 0x06, 0x9b, 0xf5, 0xfd, 0xee, 0x2e, 0xd7, + 0xec, 0x18, 0x25, 0x32, 0x7f, 0x0b, 0x08, 0xeb, 0xa0, 0x0d, 0xfd, 0x33, 0xfb, + 0xce, 0xdf, 0x0a, 0xf9, 0x00, 0x18, 0xd8, 0xe7, 0x25, 0xd8, 0xd5, 0x09, 0xeb, + 0x17, 0x74, 0x10, 0xed, 0x00, 0x12, 0x0c, 0xdf, 0xb9, 0x4b, 0x08, 0x16, 0xe1, + 0xf3, 0xdf, 0x1e, 0x05, 0xf9, 0xd4, 0xc7, 0xcf, 0xd9, 0xe1, 0xc5, 0xbb, 0xe0, + 0xce, 0xf5, 0x1d, 0xe5, 0x11, 0x06, 0xe1, 0x07, 0xf6, 0x26, 0xcd, 0x03, 0xc7, + 0x15, 0xd9, 0x23, 0xe8, 0xd0, 0x05, 0xf9, 0xf3, 0xc9, 0xe1, 0xe0, 0x05, 0xe6, + 0x11, 0xf3, 0xde, 0xe2, 0xfa, 0xc4, 0xfb, 0x05, 0x13, 0x01, 0x1c, 0xe9, 0x08, + 0xd8, 0xdd, 0xb9, 0x19, 0xb5, 0xea, 0xa8, 0x03, 0xde, 0xf2, 0x09, 0x45, 0x39, + 0x0f, 0xf1, 0xda, 0xe2, 0x13, 0x37, 0x16, 0xe2, 0x3f, 0xf7, 0xdf, 0x32, 0xe9, + 0x07, 0x4c, 0xeb, 0x40, 0xac, 0xe5, 0xb0, 0xfe, 0xc2, 0xe0, 0xf4, 0xd7, 0xc1, + 0x23, 0xf5, 0xdf, 0xe7, 0x0f, 0xff, 0xe3, 0x34, 0xbf, 0xd1, 0xdc, 0xfe, 0x0c, + 0xd1, 0xf0, 0xea, 0xd6, 0xbd, 0xf8, 0xc3, 0xcc, 0xc5, 0xf0, 0xf3, 0xdb, 0x03, + 0x17, 0x1d, 0x0d, 0x28, 0xe8, 0x16, 0xd3, 0x16, 0xcc, 0xf5, 0x17, 0xec, 0x36, + 0xe4, 0x2e, 0x07, 0xdc, 0xe2, 0xd3, 0x0a, 0xd7, 0x0a, 0x1f, 0xc0, 0x19, 0x16, + 0xeb, 0xd4, 0xd9, 0xfe, 0xd9, 0xd9, 0xb6, 0xf9, 0xf6, 0xdd, 0xd1, 0xe4, 0x25, + 0xc0, 0xf9, 0xda, 0x10, 0xe5, 0x25, 0x15, 0xb5, 0x1d, 0x9c, 0x10, 0x05, 0xd1, + 0xd2, 0x8d, 0xee, 0xde, 0xa7, 0xb7, 0x49, 0xe9, 0x26, 0x9c, 0x03, 0xec, 0x22, + 0xf9, 0xe3, 0x30, 0x04, 0x29, 0x10, 0xcd, 0xe2, 0xce, 0xf6, 0x18, 0xfd, 0xe5, + 0x21, 0x0b, 0x19, 0xf7, 0x19, 0xe7, 0xd1, 0xf2, 0xfc, 0xf8, 0x10, 0xbf, 0xdb, + 0x0f, 0xd7, 0x4b, 0x0c, 0x30, 0x1a, 0x49, 0xf7, 0xd0, 0xc8, 0x14, 0x2b, 0x13, + 0xa6, 0xe6, 0xf0, 0xcf, 0x09, 0x22, 0x30, 0xf5, 0x41, 0xc9, 0x06, 0xf7, 0x1f, + 0xe9, 0xf0, 0x04, 0x0d, 0xde, 0xed, 0x10, 0x1b, 0xc2, 0x29, 0xc0, 0xd3, 0x2a, + 0xcf, 0xfb, 0xc8, 0x17, 0xf9, 0xa6, 0x11, 0x06, 0xf5, 0x0d, 0xd3, 0xd1, 0xf9, + 0xc0, 0xa7, 0xe3, 0xff, 0xec, 0x15, 0xe0, 0xed, 0xba, 0xcf, 0xfe, 0xf9, 0xea, + 0x01, 0x43, 0x01, 0x08, 0xfd, 0x2a, 0xc0, 0x42, 0x15, 0xc7, 0xfb, 0xfa, 0xf7, + 0xcd, 0x24, 0xff, 0xf4, 0xc3, 0xde, 0xef, 0xe5, 0x03, 0x06, 0x15, 0xeb, 0xf5, + 0x27, 0xe3, 0xd7, 0x09, 0x10, 0x07, 0xe9, 0x1f, 0xdf, 0xdb, 0x24, 0x1f, 0xeb, + 0xcb, 0xf8, 0xc3, 0xda, 0x1f, 0x19, 0x0c, 0xe2, 0x6a, 0xce, 0xfa, 0xf9, 0xb8, + 0x18, 0xf7, 0xf7, 0xe6, 0xd0, 0x1d, 0xac, 0x2a, 0xfd, 0xf7, 0x0c, 0xf2, 0x18, + 0xb3, 0xc5, 0x33, 0xd9, 0x43, 0xfb, 0xf0, 0x46, 0xc7, 0xb7, 0x0a, 0xde, 0xf8, + 0x08, 0xed, 0x15, 0xd9, 0xd3, 0x15, 0x24, 0x34, 0x0a, 0x36, 0x03, 0xb4, 0xce, + 0x87, 0xc0, 0x7f, 0xc1, 0xec, 0xf6, 0xec, 0x16, 0x14, 0x01, 0x23, 0x00, 0xe3, + 0xcd, 0x94, 0xee, 0xe3, 0xec, 0xf9, 0x08, 0xf6, 0x0e, 0xf3, 0xec, 0x0f, 0xba, + 0xb5, 0x07, 0x08, 0xfb, 0xd1, 0xc8, 0x0d, 0xb5, 0xe7, 0xfb, 0x13, 0xb6, 0xfb, + 0x10, 0xf7, 0xbb, 0xdb, 0xdb, 0xe2, 0x09, 0x29, 0x4e, 0x36, 0x2a, 0xe4, 0xe1, + 0x27, 0xde, 0xe8, 0xdb, 0x01, 0x15, 0x03, 0xf1, 0x20, 0xef, 0xc2, 0xd8, 0xca, + 0xac, 0x0c, 0x34, 0x2d, 0xc9, 0xb3, 0xf2, 0xc4, 0x21, 0xf3, 0x04, 0x81, 0xa7, + 0xea, 0x45, 0xd3, 0x3b, 0x09, 0x28, 0xf4, 0xad, 0xf1, 0xfc, 0x13, 0xed, 0xaa, + 0xba, 0x10, 0xea, 0x37, 0x22, 0x24, 0xd3, 0xe1, 0x0d, 0xfa, 0x09, 0xec, 0x29, + 0x13, 0x10, 0x03, 0x28, 0xfa, 0x28, 0xda, 0xdb, 0xde, 0x6c, 0x60, 0xc2, 0x0a, + 0xf0, 0x37, 0x5f, 0x01, 0x00, 0xf8, 0xbe, 0xbf, 0xc6, 0x41, 0x01, 0xcd, 0xfd, + 0x3e, 0x0d, 0xfe, 0x05, 0xef, 0xed, 0x23, 0x09, 0xee, 0x45, 0xf2, 0xbe, 0x34, + 0x2d, 0x03, 0x6f, 0xb7, 0xd3, 0xf2, 0xf6, 0x01, 0xbe, 0x11, 0x0f, 0xcb, 0x38, + 0x09, 0x0c, 0xd9, 0xc3, 0x1d, 0xe3, 0xfc, 0xa9, 0xb3, 0x2a, 0xe5, 0xa6, 0xb2, + 0x2a, 0xff, 0xf3, 0x26, 0x09, 0xed, 0xb8, 0x0d, 0xa8, 0x13, 0xe5, 0xba, 0x4d, + 0x2d, 0x38, 0xf7, 0xbe, 0xc3, 0x28, 0x3a, 0x27, 0xdf, 0xe3, 0xca, 0xb2, 0x0d, + 0x05, 0xbb, 0xd9, 0xda, 0xfe, 0xb6, 0xbc, 0xaa, 0xff, 0x1c, 0xf1, 0xf3, 0x00, + 0x03, 0x1b, 0x13, 0x16, 0xe4, 0x1a, 0xf5, 0xd7, 0x2b, 0xf4, 0x28, 0x35, 0xfe, + 0xdb, 0xcd, 0xc6, 0xf7, 0xde, 0xf8, 0xd3, 0xfc, 0x07, 0x17, 0x00, 0xdf, 0x03, + 0x03, 0x17, 0xe3, 0xb0, 0x22, 0x00, 0xd2, 0xc9, 0x30, 0x18, 0x04, 0xf2, 0x0e, + 0x0e, 0x06, 0xc8, 0xe9, 0xd7, 0xe4, 0x3b, 0x06, 0x02, 0xf6, 0x1f, 0x02, 0xfd, + 0x07, 0x11, 0xc0, 0x49, 0xd8, 0xd6, 0xbb, 0x22, 0xaf, 0x51, 0xeb, 0x05, 0xaf, + 0xe0, 0xeb, 0x07, 0x14, 0x36, 0x2d, 0xaf, 0xf8, 0xf7, 0x1b, 0xec, 0xf0, 0x23, + 0xf4, 0xed, 0xdb, 0xf4, 0x0b, 0x5d, 0x0d, 0xb5, 0xcd, 0x09, 0xfb, 0xf9, 0xde, + 0x03, 0xe3, 0xf7, 0x4a, 0x5f, 0xb3, 0xda, 0x13, 0xfd, 0xbb, 0xee, 0xe6, 0x19, + 0xe7, 0x56, 0x9d, 0x30, 0xd9, 0x2e, 0x2b, 0xb6, 0xf5, 0xca, 0x30, 0x8a, 0xc4, + 0xf8, 0xfd, 0xc8, 0xf5, 0x20, 0xf5, 0x35, 0x14, 0xfa, 0x08, 0x06, 0xd7, 0xc3, + 0xfb, 0xff, 0xd3, 0xd6, 0xb8, 0x31, 0x0c, 0x46, 0x29, 0xe6, 0x07, 0xe5, 0x0d, + 0x25, 0xaa, 0xf4, 0xa7, 0x3a, 0xe9, 0xd1, 0x39, 0xcc, 0x48, 0xfc, 0x92, 0x27, + 0xa8, 0x3a, 0x32, 0xe9, 0x09, 0xc4, 0x16, 0x18, 0xea, 0xea, 0xb6, 0xa8, 0x2b, + 0x1f, 0xea, 0x01, 0x0d, 0xb8, 0xe1, 0x15, 0x59, 0xb0, 0x2d, 0xc3, 0xfd, 0x66, + 0xdc, 0x05, 0x1e, 0xd1, 0xcf, 0x26, 0xdc, 0x00, 0x42, 0x29, 0x16, 0x19, 0xc7, + 0x27, 0xe9, 0x89, 0xc5, 0x12, 0x49, 0xcc, 0x21, 0xfd, 0xef, 0xac, 0x4f, 0xeb, + 0x07, 0xf5, 0x22, 0x1a, 0x8a, 0x28, 0xac, 0x26, 0xa4, 0x2b, 0x55, 0xf3, 0x15, + 0xa8, 0xf6, 0x18, 0x3d, 0x33, 0x10, 0x0c, 0xea, 0x12, 0xca, 0xc9, 0xec, 0xa4, + 0xb9, 0xfb, 0xce, 0x31, 0x35, 0xf0, 0x02, 0x19, 0x32, 0x95, 0x09, 0xbb, 0xc4, + 0x2c, 0xf8, 0x1c, 0xd9, 0x0a, 0xcf, 0x8c, 0xf2, 0x15, 0x8d, 0xcb, 0xa3, 0x08, + 0x28, 0xdd, 0x1b, 0x08, 0xd7, 0xb1, 0x48, 0x07, 0x0b, 0xe5, 0xe8, 0xf0, 0x40, + 0x0e, 0x07, 0xec, 0xde, 0xc6, 0xce, 0xb4, 0xe6, 0x15, 0x21, 0x0b, 0xa7, 0xf6, + 0xf0, 0xf1, 0x11, 0x36, 0xda, 0x94, 0x0f, 0xeb, 0x1e, 0x54, 0xd9, 0x9d, 0xc2, + 0x0f, 0x22, 0xce, 0x00, 0xe5, 0x5a, 0x18, 0xb8, 0x01, 0x4c, 0xc6, 0xf8, 0xe5, + 0x99, 0x28, 0x04, 0xf4, 0xf4, 0x16, 0x25, 0xdd, 0x0d, 0x3e, 0xb0, 0x01, 0xfe, + 0xb6, 0xfe, 0xe7, 0x04, 0xbd, 0x26, 0xb5, 0x4b, 0xb0, 0xe9, 0xf0, 0xfe, 0x03, + 0x3d, 0xe6, 0xf3, 0x1e, 0x6e, 0x13, 0x4d, 0x4c, 0xc5, 0xb5, 0x81, 0xa0, 0xec, + 0xc0, 0xcf, 0x0b, 0x01, 0x1a, 0xcc, 0x1d, 0xac, 0x2d, 0xd1, 0x15, 0x05, 0x0a, + 0xff, 0x2b, 0xf0, 0xb9, 0xf6, 0xbf, 0x45, 0x00, 0xb5, 0x43, 0x1a, 0xd5, 0xe0, + 0x0e, 0x10, 0xe5, 0xc9, 0xed, 0xde, 0x2e, 0xd0, 0xe8, 0x2f, 0x08, 0xd4, 0xdf, + 0xc7, 0xf8, 0xf6, 0xb3, 0x22, 0xf9, 0xec, 0xe6, 0x14, 0xd8, 0x14, 0xee, 0xc1, + 0x00, 0x12, 0xe4, 0x12, 0x00, 0xec, 0xe1, 0xac, 0xcb, 0x0c, 0xd2, 0xe9, 0x11, + 0x2e, 0xd7, 0x18, 0xd1, 0x2b, 0x3a, 0x32, 0xee, 0x08, 0x00, 0xb2, 0x8a, 0x15, + 0xe6, 0xab, 0xf8, 0xfd, 0x93, 0xe3, 0xf6, 0xeb, 0xd8, 0x1f, 0xd7, 0x29, 0xfe, + 0x40, 0x57, 0xec, 0xa2, 0xe2, 0x0d, 0x0e, 0xe9, 0xf7, 0x1f, 0x92, 0xdd, 0xaf, + 0xec, 0x13, 0x10, 0xc9, 0xe6, 0x24, 0xcf, 0xeb, 0x0a, 0xfa, 0x25, 0xbc, 0xe0, + 0x8a, 0x18, 0x89, 0x05, 0xbd, 0x20, 0x13, 0xf3, 0x06, 0x19, 0xc4, 0xdd, 0xd3, + 0x2d, 0xd1, 0xd3, 0x33, 0x07, 0xf5, 0x26, 0x2a, 0x16, 0x05, 0xeb, 0x48, 0x3f, + 0x34, 0xe7, 0xff, 0xfa, 0x81, 0xdb, 0xe9, 0xf3, 0xc0, 0x25, 0x0c, 0xb5, 0xe8, + 0x00, 0x47, 0xf6, 0x42, 0xf8, 0xd7, 0xd1, 0xf7, 0xf8, 0x20, 0x07, 0x17, 0xf9, + 0x1b, 0x9e, 0xf2, 0x3a, 0xdc, 0x0e, 0x29, 0xb0, 0x1a, 0x04, 0x99, 0x43, 0x0a, + 0x07, 0xff, 0x52, 0x02, 0x14, 0x04, 0xac, 0xe7, 0xcf, 0x04, 0x07, 0xf3, 0xf4, + 0x26, 0x07, 0xe4, 0x47, 0xd6, 0xd7, 0x01, 0xd1, 0x17, 0x18, 0x37, 0xfc, 0xfc, + 0xd5, 0xf3, 0x08, 0xfc, 0x37, 0x28, 0xce, 0xfd, 0x24, 0xde, 0xf0, 0xe3, 0x1f, + 0xa0, 0xf0, 0x07, 0xfb, 0xdc, 0xfd, 0xd4, 0xf1, 0x2e, 0xe5, 0x1c, 0xd8, 0x19, + 0xe1, 0xe5, 0x5f, 0xe5, 0xc9, 0xf2, 0x25, 0xc1, 0x34, 0x42, 0xc4, 0xf1, 0xf7, + 0xe6, 0xf5, 0xcb, 0xf3, 0x2d, 0x00, 0xe6, 0xda, 0xff, 0xac, 0x37, 0xfa, 0xd7, + 0xc0, 0xf0, 0x2a, 0xd6, 0xc3, 0xdf, 0xc3, 0x30, 0xed, 0xb0, 0xff, 0xe5, 0xf9, + 0x07, 0xf3, 0xd8, 0x1c, 0x41, 0x17, 0xda, 0xf8, 0x03, 0xf0, 0x0c, 0xce, 0x14, + 0x08, 0x06, 0xf4, 0x11, 0xde, 0x14, 0xfc, 0x19, 0x28, 0xd8, 0x04, 0x4b, 0x27, + 0x21, 0xb7, 0xee, 0xdf, 0x02, 0xf7, 0x16, 0xf1, 0xd5, 0x12, 0xea, 0xf3, 0x1f, + 0x0a, 0xd0, 0x39, 0x53, 0xf6, 0xef, 0xed, 0x1a, 0x1e, 0xea, 0xd0, 0x1f, 0xd7, + 0xf9, 0xfd, 0x1b, 0xf4, 0xfb, 0x08, 0xd5, 0x1c, 0x25, 0x33, 0xd9, 0xf7, 0x16, + 0x07, 0xf5, 0x01, 0x29, 0x3e, 0x1a, 0x10, 0x05, 0xde, 0x14, 0xe2, 0xe2, 0x1f, + 0x03, 0x0b, 0xe9, 0xed, 0x0d, 0xfd, 0xf1, 0x09, 0x05, 0x06, 0xd7, 0xcb, 0xb7, + 0x00, 0xdc, 0xff, 0xde, 0x04, 0xc1, 0x2e, 0x13, 0xf0, 0x09, 0x19, 0x0c, 0x2a, + 0x1b, 0xf2, 0x26, 0xbc, 0xe5, 0x31, 0xc5, 0x00, 0xb8, 0xfa, 0x2b, 0xf1, 0xfb, + 0xda, 0xfd, 0xc5, 0x22, 0x12, 0x03, 0xf9, 0x20, 0xd2, 0xf2, 0x3b, 0xad, 0x16, + 0xe4, 0xed, 0xee, 0x24, 0xfb, 0x0d, 0xe9, 0x04, 0x0f, 0xd4, 0xfa, 0xf0, 0xe9, + 0xe9, 0xf7, 0xf9, 0xfd, 0xdf, 0x7f, 0x0c, 0x0b, 0x0a, 0xdf, 0xdc, 0x01, 0xfa, + 0xef, 0xf6, 0x08, 0xd7, 0x42, 0x10, 0xf6, 0x6a, 0x12, 0xf9, 0xef, 0xf3, 0x0f, + 0x01, 0xe5, 0xe8, 0x0a, 0x08, 0xd8, 0xb0, 0x23, 0xd9, 0xdd, 0x03, 0xee, 0xf1, + 0xed, 0xe1, 0x24, 0x52, 0xf3, 0x7d, 0x20, 0xe8, 0x9e, 0xe7, 0x07, 0xed, 0x73, + 0xe9, 0x1e, 0x0a, 0x08, 0xe1, 0xf3, 0x17, 0xe1, 0x07, 0xf9, 0xdd, 0xff, 0x17, + 0x0e, 0xd6, 0xf4, 0xfd, 0xf9, 0xed, 0xbb, 0xd0, 0xf7, 0xcd, 0xea, 0xdb, 0xe9, + 0x19, 0xcf, 0xbd, 0x35, 0x13, 0x07, 0x27, 0x2b, 0x03, 0xca, 0x0c, 0xfb, 0xc7, + 0x01, 0x07, 0x02, 0x24, 0x27, 0x1e, 0x22, 0x38, 0xf2, 0x1c, 0x2b, 0xa3, 0xc8, + 0x14, 0xfe, 0xfa, 0x01, 0xec, 0xde, 0xff, 0xeb, 0xda, 0xca, 0xdd, 0x25, 0xd1, + 0xb0, 0xf7, 0x14, 0xd1, 0x94, 0xba, 0x3d, 0xb9, 0x1c, 0xcc, 0xbe, 0x2d, 0xfb, + 0x2f, 0x08, 0xff, 0xee, 0xaf, 0x97, 0xfd, 0xa5, 0x10, 0x48, 0x25, 0x37, 0xd8, + 0x2d, 0xff, 0xc9, 0xff, 0xf1, 0x4c, 0xf1, 0x8f, 0xf0, 0xcb, 0xc3, 0x81, 0xf9, + 0x1e, 0x49, 0x33, 0x13, 0x14, 0xf1, 0xa2, 0x5e, 0xf7, 0x3a, 0xf9, 0xdc, 0xe9, + 0x0e, 0x49, 0x6f, 0xed, 0xd0, 0xe4, 0x0a, 0xb5, 0xde, 0xd6, 0xd4, 0xe7, 0xc4, + 0xf4, 0xee, 0x08, 0xee, 0x05, 0xe8, 0xb7, 0x5c, 0x9e, 0x3b, 0xbe, 0xcd, 0x31, + 0xdf, 0x42, 0x1a, 0xfb, 0xed, 0xe5, 0xda, 0xf6, 0xab, 0xc9, 0xe3, 0xbc, 0x13, + 0xf3, 0xc8, 0xed, 0x28, 0x2a, 0xc4, 0xeb, 0xe3, 0xc4, 0xf4, 0x2a, 0x22, 0x0b, + 0x13, 0xd5, 0xcc, 0xf5, 0xb1, 0x33, 0x10, 0xee, 0xb5, 0xc4, 0xdd, 0x02, 0xcf, + 0x1e, 0xc4, 0xc7, 0xe7, 0x15, 0xa1, 0x37, 0xcf, 0x01, 0x94, 0xa6, 0xdc, 0x28, + 0xec, 0x02, 0x3e, 0x09, 0x0c, 0xae, 0x0a, 0x40, 0x03, 0x32, 0xd2, 0x8f, 0xcb, + 0x99, 0xc8, 0x3d, 0xe7, 0xec, 0x36, 0xb6, 0xf0, 0xf8, 0xcc, 0xae, 0x0e, 0xec, + 0x0b, 0xed, 0x32, 0xe3, 0x0a, 0xb7, 0xc8, 0xba, 0x45, 0x30, 0x03, 0xc5, 0x1c, + 0xf9, 0x42, 0xbf, 0x44, 0x50, 0x28, 0x0a, 0xd4, 0x9f, 0xb0, 0xe6, 0x17, 0x04, + 0x06, 0x06, 0x32, 0xc8, 0x14, 0x46, 0xe2, 0x25, 0xee, 0x95, 0xeb, 0xe2, 0xe0, + 0x06, 0xf1, 0x09, 0xf6, 0xdf, 0x12, 0x1d, 0xd8, 0xbd, 0x16, 0x35, 0xc3, 0x3f, + 0x10, 0x12, 0xc5, 0xe0, 0xeb, 0x11, 0xfc, 0x20, 0xb1, 0xc6, 0xb6, 0xdd, 0xfd, + 0x34, 0x11, 0x11, 0x22, 0x1b, 0xe8, 0xdc, 0x0d, 0xdc, 0x45, 0xe4, 0xbb, 0x1e, + 0xfe, 0xeb, 0xed, 0xfb, 0x3a, 0x1a, 0x25, 0xa9, 0xfb, 0x66, 0xc6, 0xec, 0xba, + 0xcb, 0xc9, 0x28, 0x08, 0xc5, 0x21, 0xb8, 0x2f, 0x06, 0xb7, 0x16, 0xd5, 0xb3, + 0xce, 0xad, 0xc5, 0xa9, 0xbe, 0x9e, 0x9b, 0x0c, 0x39, 0x20, 0xe8, 0xcf, 0xc8, + 0xd9, 0xf0, 0x26, 0xb6, 0xc9, 0xf3, 0xf2, 0xdc, 0xec, 0xca, 0x1f, 0xf2, 0x13, + 0xaa, 0x32, 0x11, 0xf7, 0xd1, 0xb6, 0x10, 0xa5, 0xf4, 0xf6, 0x3e, 0x0c, 0xed, + 0xd6, 0xe8, 0x92, 0xf9, 0xfa, 0x1d, 0x56, 0xbe, 0xf1, 0xc6, 0x12, 0xe9, 0xf1, + 0x21, 0xcd, 0x07, 0xa3, 0xe0, 0xd5, 0x07, 0xe9, 0xfd, 0xc5, 0x2d, 0xfb, 0xa3, + 0xe5, 0xdd, 0xd0, 0x15, 0xdc, 0x10, 0x0f, 0x81, 0x13, 0xcb, 0x31, 0xa5, 0x1d, + 0xee, 0xbc, 0xb7, 0xeb, 0xd1, 0xb4, 0xcd, 0xcc, 0x9d, 0xe8, 0xf3, 0xf5, 0x2a, + 0x30, 0xe7, 0xdc, 0xe2, 0xcc, 0xef, 0x10, 0x11, 0xba, 0x08, 0xd6, 0xd2, 0xd1, + 0x9d, 0x1f, 0x1f, 0xdc, 0xe1, 0xf4, 0xb0, 0x0d, 0xf1, 0x99, 0x9c, 0x24, 0xfb, + 0x0a, 0xdc, 0xee, 0xa9, 0xd5, 0xd8, 0xcd, 0xf4, 0x19, 0xef, 0x1e, 0x2d, 0x17, + 0xed, 0xe7, 0xf1, 0x36, 0x55, 0x22, 0xba, 0xa3, 0xe1, 0xc3, 0xda, 0xfc, 0xbb, + 0x07, 0xe3, 0xa1, 0xed, 0xc3, 0xfb, 0xe2, 0xe6, 0xff, 0xa0, 0xef, 0x02, 0xb2, + 0xd9, 0xee, 0x60, 0x15, 0x39, 0x15, 0xec, 0xfc, 0xfd, 0x2e, 0xf4, 0xa9, 0x10, + 0xf0, 0x18, 0x17, 0xa3, 0xce, 0xe1, 0xdf, 0xc0, 0xaa, 0x2c, 0x52, 0xb3, 0xf4, + 0xeb, 0x44, 0x8e, 0x17, 0xa8, 0xed, 0xef, 0x06, 0xd6, 0xe8, 0x3f, 0xd0, 0xf2, + 0xb4, 0xc9, 0xe2, 0xab, 0x03, 0x25, 0x39, 0x07, 0x35, 0xe0, 0xa3, 0xdf, 0xba, + 0x04, 0x59, 0xb2, 0xc4, 0x9a, 0x06, 0x14, 0xde, 0xf2, 0x4d, 0xf3, 0x43, 0x01, + 0xcc, 0xaa, 0x3a, 0x11, 0x43, 0xa9, 0xb0, 0x35, 0x26, 0xfc, 0xf6, 0x92, 0x0b, + 0x2a, 0x19, 0xde, 0x0d, 0xd2, 0xea, 0xf0, 0xfd, 0x09, 0xd2, 0x6c, 0xb6, 0xb9, + 0x09, 0x9b, 0xee, 0x15, 0xdf, 0x81, 0x37, 0x1a, 0xf8, 0x44, 0x16, 0xf3, 0x35, + 0xc9, 0xdf, 0xe9, 0x1a, 0x17, 0x1a, 0x2c, 0x27, 0xa9, 0x27, 0x10, 0x03, 0xd1, + 0x2f, 0x1c, 0x99, 0xe1, 0x03, 0x08, 0xcb, 0xbc, 0xef, 0x05, 0xf9, 0xac, 0x9a, + 0x19, 0xac, 0x36, 0x99, 0x3c, 0xf9, 0xbc, 0xec, 0xd2, 0x09, 0x45, 0xc0, 0x09, + 0x59, 0xbf, 0xf9, 0xcc, 0xde, 0xd4, 0x27, 0x3f, 0xd0, 0xe5, 0x15, 0xcb, 0xca, + 0x00, 0xd3, 0xed, 0x16, 0x2f, 0x28, 0xe8, 0x50, 0xbf, 0x94, 0xc9, 0xb9, 0xc0, + 0x92, 0x8a, 0xdb, 0x3e, 0xbe, 0xf3, 0x07, 0xf7, 0x16, 0x96, 0x09, 0x29, 0xe8, + 0xca, 0x54, 0x26, 0xf4, 0x08, 0x18, 0x2c, 0x08, 0x01, 0xef, 0xcf, 0x5b, 0x41, + 0x18, 0x22, 0x3a, 0xf8, 0xc2, 0xc7, 0x0d, 0x07, 0x17, 0x1d, 0x57, 0x9d, 0xfb, + 0xb3, 0xdf, 0x8d, 0xfb, 0x01, 0xf7, 0xf6, 0xb9, 0x31, 0xf3, 0xf6, 0x1f, 0x42, + 0x04, 0x93, 0xb8, 0xd5, 0xfe, 0x9e, 0x02, 0xc4, 0x4d, 0x47, 0x27, 0xc5, 0xfa, + 0x5a, 0x2b, 0xa8, 0x9e, 0x18, 0xf0, 0xe1, 0x20, 0x03, 0x9c, 0x1d, 0xb4, 0xa8, + 0x2a, 0xce, 0xac, 0xe2, 0xdf, 0x05, 0xc3, 0x52, 0xec, 0x46, 0xe0, 0xc7, 0x5e, + 0xd4, 0x16, 0xd7, 0x61, 0xdc, 0x0d, 0x0b, 0x2b, 0xf9, 0xa1, 0xa1, 0x2a, 0x21, + 0x03, 0x13, 0xc9, 0x05, 0x3c, 0xfa, 0xd1, 0x05, 0x35, 0x11, 0x4f, 0xf1, 0x1c, + 0xf1, 0xee, 0x10, 0xe0, 0xd9, 0xa9, 0xda, 0x0d, 0xa3, 0x08, 0x07, 0x1a, 0x3b, + 0x50, 0xd6, 0x8c, 0x51, 0x30, 0xe3, 0xf8, 0x32, 0xc9, 0xfc, 0x02, 0xbe, 0x1d, + 0x4e, 0xd0, 0x5b, 0x05, 0xf5, 0xfd, 0x0a, 0xfd, 0xec, 0xdc, 0x37, 0xe4, 0x1f, + 0xda, 0x3a, 0x32, 0xbd, 0xa6, 0xd1, 0x02, 0xe8, 0x82, 0xd9, 0xfd, 0xe7, 0x56, + 0x02, 0x1b, 0xbf, 0x7c, 0xc5, 0xba, 0xfb, 0xde, 0x1c, 0x1e, 0x03, 0x36, 0x58, + 0x21, 0x86, 0xef, 0x31, 0xf4, 0xdb, 0xef, 0xb1, 0xcc, 0xec, 0xd9, 0xde, 0xf6, + 0x21, 0x00, 0x31, 0xd7, 0xf4, 0x89, 0x0a, 0xe7, 0x23, 0xea, 0xc3, 0x26, 0xbf, + 0x06, 0xfa, 0x01, 0x96, 0xe2, 0x19, 0xba, 0x3a, 0x23, 0xb4, 0xc1, 0x19, 0xb6, + 0xb1, 0x00, 0x45, 0x5a, 0x4a, 0xe5, 0xf0, 0x93, 0xe0, 0xd8, 0xff, 0x30, 0xd6, + 0x17, 0x01, 0xe0, 0xe0, 0xd7, 0x24, 0xab, 0x89, 0xa9, 0xbc, 0xf5, 0x11, 0x07, + 0xca, 0xd2, 0xb1, 0xb0, 0xbd, 0x52, 0x21, 0xd2, 0xfb, 0xa0, 0xd2, 0xce, 0xd3, + 0x09, 0xdf, 0xc9, 0x9b, 0x10, 0xde, 0x3a, 0x23, 0xcd, 0xf4, 0xcd, 0xe6, 0x11, + 0xce, 0xd8, 0x1a, 0xa2, 0x19, 0x18, 0xb9, 0x0c, 0xc3, 0xe9, 0xf8, 0x18, 0xf3, + 0xd8, 0xe4, 0xce, 0xb4, 0x12, 0xd9, 0x3c, 0xb1, 0xc6, 0xef, 0x02, 0xe9, 0x74, + 0x15, 0xe3, 0xda, 0x35, 0xc8, 0x2e, 0xea, 0xad, 0xae, 0xe9, 0xc5, 0xd6, 0xda, + 0xee, 0xb9, 0x04, 0x39, 0xc2, 0x1a, 0x25, 0x15, 0xf1, 0x57, 0x31, 0x9e, 0x84, + 0xee, 0xb3, 0x81, 0x31, 0xf2, 0xf4, 0xdc, 0x28, 0xf6, 0xd3, 0xe9, 0xf8, 0x15, + 0xf7, 0xcb, 0x06, 0x87, 0xe6, 0xb7, 0xd5, 0x64, 0xeb, 0xfd, 0xbf, 0xb1, 0xd4, + 0xdb, 0x46, 0x1c, 0xe6, 0x38, 0xc6, 0x52, 0x2e, 0xe1, 0xdb, 0x92, 0xef, 0xe9, + 0xea, 0xe7, 0xe0, 0xcb, 0x4b, 0x3d, 0x4c, 0xa0, 0xc0, 0xa1, 0x16, 0x31, 0xe4, + 0xc6, 0xef, 0x00, 0xa6, 0xce, 0x1f, 0xf0, 0x18, 0x9b, 0xd4, 0xf7, 0xf5, 0xf6, + 0x49, 0xae, 0xd7, 0x3d, 0xa3, 0x46, 0x5c, 0x3e, 0x6f, 0x9d, 0xd0, 0x24, 0x5b, + 0xc3, 0x9d, 0xec, 0xf6, 0x08, 0x86, 0xc5, 0xee, 0xc2, 0x0a, 0xf7, 0xf6, 0xdf, + 0xfd, 0xdd, 0xfb, 0x14, 0xb5, 0x22, 0xbd, 0xf6, 0xd3, 0xe9, 0xc3, 0xe8, 0x10, + 0x04, 0x0d, 0x11, 0xf2, 0x1c, 0xde, 0x17, 0xe0, 0x23, 0x08, 0xdf, 0xf7, 0x07, + 0xe0, 0xee, 0x21, 0xda, 0x2b, 0x0b, 0xe2, 0xee, 0x08, 0xfc, 0x28, 0xd0, 0x2b, + 0xfd, 0x07, 0x28, 0x03, 0x07, 0xeb, 0xf7, 0x05, 0x0f, 0x15, 0x21, 0xf9, 0xcb, + 0x46, 0xcf, 0x17, 0xd4, 0xe5, 0xcb, 0xfa, 0x30, 0x1c, 0xf0, 0x01, 0x02, 0xd0, + 0x20, 0xd7, 0xe2, 0x31, 0xe5, 0xeb, 0x2b, 0xf2, 0xf8, 0x27, 0x21, 0x1d, 0xf5, + 0x1c, 0x0e, 0x13, 0x08, 0x30, 0xcc, 0xe6, 0xcf, 0x16, 0xbd, 0xd3, 0xef, 0xfe, + 0x03, 0xe7, 0x7f, 0xdc, 0xf3, 0xd9, 0x1d, 0xd2, 0x2f, 0xf9, 0xde, 0x17, 0x26, + 0xd2, 0xed, 0x7e, 0xff, 0xcf, 0xd7, 0xf2, 0x2b, 0x38, 0x02, 0x34, 0x14, 0x18, + 0xbc, 0x3d, 0xda, 0xe2, 0xee, 0xda, 0xf8, 0xfd, 0xbf, 0xed, 0x0d, 0xf9, 0x19, + 0xe5, 0x01, 0x3a, 0x10, 0xbd, 0xda, 0xfe, 0xf2, 0x0e, 0x0d, 0xce, 0xf9, 0xc9, + 0x1e, 0xcf, 0xd4, 0xfd, 0xee, 0x65, 0xf8, 0x01, 0x40, 0x15, 0xe7, 0x52, 0xe7, + 0xe8, 0xe3, 0xef, 0x18, 0x13, 0xd1, 0xf1, 0xd2, 0xec, 0x18, 0xe9, 0x03, 0x0d, + 0x23, 0xf8, 0xf8, 0xe1, 0x3e, 0x12, 0xbb, 0xe5, 0xf9, 0x0b, 0x38, 0x2c, 0xf1, + 0xf7, 0x09, 0x27, 0xe7, 0x22, 0x01, 0xe2, 0xc7, 0xf9, 0xe0, 0xec, 0xfb, 0xf5, + 0x02, 0x02, 0xe2, 0xd1, 0x00, 0xf7, 0x22, 0xf0, 0x05, 0x00, 0x3c, 0x2a, 0xdb, + 0x43, 0x07, 0x48, 0x05, 0x0b, 0xd8, 0x37, 0x0d, 0x1c, 0xbe, 0x3f, 0x55, 0xf5, + 0x05, 0x31, 0xc5, 0xca, 0x03, 0x02, 0xcf, 0xf0, 0x15, 0x01, 0x20, 0x26, 0x0e, + 0x00, 0xd0, 0xc1, 0xcd, 0xf2, 0x09, 0xf8, 0xfa, 0x15, 0xf4, 0x0b, 0xd3, 0xed, + 0xd7, 0xd9, 0x0f, 0xf5, 0xde, 0xfb, 0xe7, 0xeb, 0x1d, 0x27, 0x30, 0x03, 0xd2, + 0xd9, 0xf7, 0x00, 0x11, 0x20, 0xf4, 0x26, 0xa6, 0x2d, 0xc0, 0xed, 0xf5, 0xb9, + 0x06, 0x19, 0x04, 0xc1, 0xfd, 0xce, 0x23, 0xcd, 0x27, 0x13, 0xaf, 0xd2, 0xda, + 0xe9, 0xdc, 0x17, 0x1b, 0x10, 0x38, 0x24, 0xcf, 0x42, 0xcf, 0xf6, 0x0d, 0x22, + 0xf7, 0x0a, 0xfa, 0xc1, 0x1d, 0xbf, 0x20, 0xaa, 0xe1, 0x1b, 0xc9, 0xd9, 0xbf, + 0xe0, 0xc0, 0xbb, 0x37, 0x2a, 0xcf, 0xf4, 0x0a, 0x33, 0xe5, 0x0d, 0xe7, 0x13, + 0x11, 0x1a, 0xf3, 0x13, 0xe8, 0xfc, 0x4a, 0xe8, 0x07, 0xf8, 0x3c, 0xbc, 0x04, + 0x73, 0xc6, 0xb6, 0x17, 0xf8, 0x95, 0xba, 0x02, 0x63, 0x3f, 0xf3, 0x48, 0x0f, + 0xcc, 0x23, 0x53, 0xf4, 0xe0, 0xaf, 0x0d, 0x2a, 0x3b, 0xd8, 0xd9, 0x7f, 0x29, + 0xdd, 0xe2, 0x28, 0x36, 0xea, 0x1d, 0xd3, 0xfc, 0xf9, 0xf1, 0x11, 0xea, 0xba, + 0x13, 0x4b, 0xef, 0xd1, 0x85, 0xe5, 0x09, 0x29, 0x04, 0x04, 0x1f, 0x41, 0xe6, + 0xf3, 0xf1, 0xc8, 0xd0, 0xfd, 0xce, 0x1e, 0xda, 0xfd, 0x09, 0xcf, 0xea, 0xf4, + 0xea, 0x16, 0xf5, 0xf9, 0xe4, 0x18, 0x1a, 0x02, 0x26, 0xef, 0x14, 0xf8, 0xd0, + 0xec, 0xc7, 0xd5, 0xb9, 0x08, 0x28, 0x5f, 0xed, 0x13, 0x2e, 0x92, 0xc1, 0xd9, + 0xbf, 0x02, 0x01, 0xf0, 0xe7, 0xfc, 0xab, 0x2b, 0xef, 0xfb, 0x03, 0xfd, 0xbe, + 0xe8, 0xff, 0xe3, 0x1c, 0xe0, 0xe2, 0xdc, 0x09, 0xf0, 0x60, 0xe1, 0xcc, 0x1a, + 0x43, 0x0e, 0xe8, 0xc6, 0x1f, 0xf5, 0x06, 0x28, 0xc6, 0x2c, 0x46, 0x5a, 0x0d, + 0xeb, 0x24, 0xfc, 0xcc, 0x0a, 0xd6, 0x19, 0x25, 0x4a, 0xd4, 0x1c, 0xf9, 0xf3, + 0xfa, 0x02, 0xd6, 0x0c, 0xe5, 0x2d, 0xf8, 0x22, 0xf9, 0xd4, 0xdb, 0xe3, 0x06, + 0xd6, 0x2b, 0xf3, 0xc8, 0x65, 0x22, 0x09, 0xc2, 0xb5, 0xd2, 0x35, 0xa1, 0xfd, + 0x19, 0x33, 0xe0, 0x56, 0xbd, 0x29, 0xe1, 0xe3, 0xb2, 0xdb, 0x25, 0xff, 0xe6, + 0xbc, 0xc5, 0xdc, 0xc8, 0xf1, 0xf1, 0x19, 0xea, 0xc5, 0xcd, 0xa8, 0xdc, 0xe2, + 0xeb, 0x0e, 0x44, 0x2c, 0xbe, 0xe9, 0x11, 0xf7, 0xba, 0x0a, 0x45, 0xe9, 0xe6, + 0x0a, 0x1c, 0xac, 0x10, 0xec, 0x23, 0x05, 0xd9, 0xd1, 0x13, 0x3b, 0xfe, 0xe5, + 0xe3, 0x05, 0xfe, 0xeb, 0xb3, 0xff, 0xd0, 0x16, 0xf9, 0xf6, 0x2c, 0x00, 0xfe, + 0xf3, 0x07, 0xca, 0x47, 0x0a, 0xda, 0xc1, 0xcd, 0x30, 0xf4, 0xf9, 0xfc, 0x00, + 0xa0, 0x26, 0x13, 0xda, 0xcb, 0x17, 0xb2, 0xee, 0x9a, 0xc4, 0xd3, 0x09, 0x45, + 0xc4, 0xab, 0xb2, 0x11, 0xf0, 0xee, 0x04, 0xfe, 0x21, 0xf2, 0x17, 0x36, 0x15, + 0xf3, 0x22, 0x0a, 0xe1, 0x0c, 0xea, 0xc0, 0xf0, 0xd7, 0x29, 0xee, 0xef, 0x18, + 0x0a, 0x92, 0x2e, 0xff, 0x0d, 0xf8, 0x14, 0xc1, 0x20, 0x99, 0xc0, 0xd9, 0xe8, + 0x04, 0xb2, 0xd4, 0x2e, 0x04, 0xcb, 0x09, 0x02, 0x1f, 0xdf, 0xc7, 0xf2, 0x1b, + 0x2d, 0x56, 0x16, 0xf5, 0x07, 0xf1, 0x2f, 0xea, 0xf3, 0xf7, 0x13, 0xb7, 0x1d, + 0x23, 0xdc, 0x38, 0xcb, 0xe5, 0xfb, 0x2a, 0x30, 0x32, 0x35, 0xe4, 0x20, 0x10, + 0xa7, 0x21, 0x0d, 0x02, 0xf1, 0x0c, 0xd2, 0x22, 0x0e, 0x02, 0x43, 0xea, 0xed, + 0xd1, 0xec, 0x7f, 0x00, 0xcd, 0x08, 0xef, 0x30, 0x04, 0xcd, 0xdb, 0xd5, 0x20, + 0x07, 0xdb, 0x00, 0xdf, 0x2e, 0xe6, 0xfb, 0xc3, 0xf7, 0xa6, 0xf4, 0x25, 0x24, + 0x17, 0x08, 0x50, 0x32, 0xe7, 0xfc, 0x15, 0x2b, 0xf8, 0x05, 0xc5, 0xb0, 0xd6, + 0xf0, 0xfe, 0x0d, 0xcb, 0xc2, 0xda, 0xef, 0xb8, 0x29, 0x15, 0x43, 0xc5, 0x21, + 0x20, 0x07, 0x04, 0xbe, 0xc4, 0x29, 0xc0, 0xd6, 0xac, 0xd6, 0xdc, 0x03, 0xe0, + 0xcc, 0xc0, 0xf7, 0xd0, 0x19, 0xc2, 0xd4, 0xc6, 0x2d, 0xee, 0xda, 0xd6, 0xa4, + 0xeb, 0xa2, 0xf3, 0x11, 0xa3, 0xf9, 0xc4, 0x3c, 0x3c, 0x0f, 0xc8, 0xcf, 0xe0, + 0x18, 0xe0, 0x33, 0xe5, 0xc8, 0xea, 0xf0, 0x16, 0xff, 0xd7, 0x0c, 0x1d, 0x11, + 0xf6, 0x12, 0x13, 0xf4, 0xf6, 0xac, 0xf8, 0xe7, 0x01, 0xd7, 0xf3, 0xfd, 0xdb, + 0xf8, 0xf5, 0xde, 0xd9, 0xd0, 0xfb, 0xfc, 0xf1, 0x2e, 0x02, 0x2c, 0xeb, 0xc7, + 0x0c, 0x0e, 0xfc, 0xda, 0x26, 0xd5, 0xf0, 0xd4, 0x14, 0xb9, 0x0d, 0xe6, 0x2a, + 0x03, 0xfa, 0x06, 0xd8, 0x7f, 0xff, 0xc7, 0x12, 0x21, 0xdc, 0x27, 0xe5, 0xeb, + 0x3e, 0xcb, 0x16, 0xd8, 0xd7, 0x33, 0xec, 0x1a, 0xf6, 0xec, 0xf3, 0x29, 0xd9, + 0xd2, 0xea, 0x16, 0xc0, 0x26, 0xf1, 0xdf, 0x0c, 0xdd, 0x41, 0xf2, 0xc8, 0xcd, + 0x09, 0xd6, 0x0f, 0xfb, 0x36, 0x1b, 0xeb, 0x02, 0x2f, 0xb7, 0x1a, 0xdb, 0xdc, + 0x2b, 0xfe, 0xdb, 0xe8, 0xd1, 0xca, 0x16, 0xff, 0x18, 0xf4, 0xf5, 0xd1, 0xdc, + 0xf8, 0xed, 0xda, 0x34, 0x02, 0xe9, 0x15, 0x1c, 0xc3, 0x16, 0x2c, 0x0f, 0xbd, + 0x13, 0x06, 0xfa, 0xe2, 0xda, 0xa4, 0xed, 0x18, 0xe4, 0xf6, 0xfb, 0xd6, 0x18, + 0x16, 0x02, 0xf9, 0xcb, 0xca, 0xf9, 0xfe, 0xf7, 0xe9, 0xd3, 0xe7, 0x3a, 0xe8, + 0xda, 0xf6, 0xf5, 0xe9, 0xdd, 0x32, 0xe0, 0xee, 0x2b, 0x1f, 0xea, 0xff, 0x1e, + 0xdb, 0xda, 0x09, 0x15, 0x2d, 0x0f, 0x0b, 0xfe, 0xf8, 0x1d, 0x07, 0x05, 0xf6, + 0x1b, 0xef, 0xbf, 0x22, 0x11, 0xd7, 0xee, 0xed, 0x0f, 0xb6, 0xdc, 0xfb, 0x33, + 0xea, 0x02, 0xe3, 0x16, 0xc6, 0x24, 0x02, 0xfa, 0x12, 0xfd, 0xc1, 0xf7, 0x1a, + 0xf6, 0xfb, 0xd3, 0x09, 0x25, 0xd9, 0x2f, 0xe8, 0xf9, 0x0a, 0xf0, 0xf6, 0x31, + 0x3d, 0x22, 0x31, 0xef, 0xdd, 0x12, 0x09, 0x02, 0xf5, 0xfd, 0xde, 0x11, 0x23, + 0x2c, 0x0d, 0xb9, 0x06, 0xf8, 0xe9, 0x1b, 0xe5, 0x04, 0x1b, 0xe7, 0x0f, 0xe4, + 0x06, 0xf9, 0x2e, 0x19, 0xd6, 0x20, 0x1c, 0xb9, 0xf7, 0xc0, 0x08, 0xe2, 0xdb, + 0xf6, 0x00, 0xed, 0xf9, 0x34, 0xec, 0xe7, 0xc5, 0x2c, 0x0d, 0x1d, 0xb8, 0xdc, + 0x19, 0xd3, 0x30, 0x08, 0x3a, 0xf4, 0x12, 0xd3, 0x12, 0x03, 0xdc, 0xb1, 0x06, + 0x18, 0x3a, 0x1f, 0xc5, 0xea, 0x19, 0xf1, 0xea, 0xfe, 0xef, 0xd1, 0xcf, 0x22, + 0xe8, 0x24, 0x28, 0xc9, 0x40, 0x02, 0x1e, 0x0f, 0xcb, 0x0c, 0x28, 0x35, 0xca, + 0xad, 0xe5, 0x35, 0x0d, 0x1b, 0xe6, 0x0c, 0x11, 0xe0, 0x28, 0x35, 0x13, 0x09, + 0xdd, 0x05, 0x3e, 0xf9, 0x0c, 0xd9, 0xdc, 0x0a, 0xb2, 0x11, 0xc7, 0xf7, 0x28, + 0xd4, 0xdc, 0xed, 0xd3, 0x18, 0xed, 0x14, 0x39, 0x0c, 0x1f, 0xfc, 0xf0, 0x1d, + 0xf5, 0xa4, 0x3a, 0x37, 0x3e, 0x26, 0xd4, 0x28, 0xe6, 0xdf, 0x5f, 0x15, 0x11, + 0xf5, 0x20, 0x0d, 0xf1, 0x01, 0x05, 0x03, 0x19, 0x1e, 0x06, 0x48, 0xef, 0xe4, + 0x21, 0xde, 0xfe, 0xdc, 0xe4, 0xc2, 0x0d, 0xd7, 0xe1, 0x0c, 0xca, 0x13, 0x2d, + 0x0d, 0xf1, 0xed, 0xba, 0xe6, 0xae, 0xf5, 0x29, 0x00, 0xcc, 0xfa, 0x07, 0x46, + 0x15, 0xd8, 0xd0, 0xd9, 0xec, 0xe4, 0xca, 0xde, 0xf9, 0xd1, 0xef, 0xc9, 0xe2, + 0x0e, 0xd2, 0xfe, 0x04, 0x1a, 0x18, 0xf3, 0x2e, 0xfa, 0x15, 0x67, 0xfd, 0xc3, + 0xf4, 0xc7, 0xec, 0xdd, 0x19, 0x0c, 0xd9, 0xfd, 0xd6, 0xd8, 0x45, 0xe3, 0xe1, + 0xed, 0xe6, 0xf7, 0xd9, 0xda, 0xea, 0x1c, 0x41, 0x13, 0x25, 0x0e, 0x02, 0xfa, + 0xc3, 0xde, 0x68, 0x00, 0xfa, 0x01, 0x1e, 0xc5, 0xf9, 0x14, 0x11, 0xda, 0xf5, + 0xec, 0xf9, 0xc8, 0xf7, 0xf4, 0xd4, 0x18, 0xf3, 0xd8, 0xe8, 0x0e, 0x0e, 0x02, + 0xea, 0x07, 0x3d, 0xb8, 0x2f, 0xd5, 0xfd, 0xe3, 0xf4, 0x66, 0x28, 0xfa, 0x20, + 0x03, 0x1f, 0xf1, 0xd4, 0xcc, 0xd4, 0x13, 0xd5, 0x7f, 0x0a, 0xee, 0x02, 0x18, + 0x2c, 0x00, 0xea, 0x3e, 0x18, 0x09, 0xf6, 0x06, 0x46, 0xfe, 0xed, 0xb6, 0xff, + 0xec, 0xe5, 0xc6, 0x26, 0x07, 0x1f, 0xff, 0xfe, 0x04, 0x21, 0x0a, 0x01, 0xe7, + 0xc5, 0xf5, 0x2d, 0xe8, 0x1a, 0x1e, 0xe6, 0xd7, 0xfa, 0xe5, 0xee, 0x01, 0x1e, + 0xbd, 0x15, 0x08, 0x4d, 0xdd, 0x01, 0x0d, 0x17, 0xbf, 0x0b, 0xe5, 0x1a, 0xbb, + 0xc3, 0xb7, 0xd6, 0x0e, 0xf1, 0xed, 0x15, 0x39, 0x21, 0x2b, 0x27, 0x0e, 0x04, + 0xd5, 0xe0, 0xf8, 0xeb, 0xb0, 0xd5, 0xde, 0x10, 0x08, 0xcb, 0xf7, 0x15, 0xe5, + 0x1c, 0xa3, 0xdb, 0x31, 0xcb, 0xdb, 0x4e, 0x30, 0xea, 0x18, 0x41, 0xdc, 0x09, + 0xcf, 0x0e, 0xf9, 0x04, 0xc4, 0xc8, 0xe1, 0x08, 0x46, 0x05, 0xd3, 0xec, 0xb9, + 0xd8, 0x00, 0x58, 0xeb, 0x3a, 0xb3, 0xc8, 0xf1, 0x0d, 0x08, 0x1f, 0x06, 0xdb, + 0xf6, 0xf8, 0xcd, 0x24, 0xd9, 0x1a, 0x18, 0x0a, 0xe5, 0xe4, 0x2d, 0x13, 0xee, + 0x18, 0xaf, 0xba, 0xd1, 0x0c, 0xea, 0x0f, 0x17, 0xec, 0xbc, 0x7e, 0x2e, 0x08, + 0xc5, 0xe4, 0xeb, 0xd9, 0xf4, 0xc8, 0xea, 0xca, 0xc8, 0xe6, 0x33, 0x81, 0x13, + 0x06, 0xf5, 0xf0, 0xf9, 0x3c, 0xe8, 0xd3, 0xde, 0xc6, 0x00, 0x2e, 0xf2, 0xe4, + 0x27, 0xe0, 0xb9, 0xf3, 0xff, 0x2d, 0xd7, 0xf5, 0x1a, 0xcb, 0xe9, 0xf8, 0x43, + 0x03, 0x05, 0x08, 0xce, 0xfd, 0xf7, 0xd0, 0x0c, 0xfb, 0xe5, 0xd4, 0xaa, 0x19, + 0xd2, 0xd7, 0x11, 0xed, 0xce, 0xf3, 0xe6, 0xe0, 0xf7, 0xc7, 0xde, 0xb2, 0x0e, + 0xc4, 0x08, 0x38, 0xf3, 0xe7, 0xe8, 0xf8, 0xef, 0xec, 0x0a, 0x41, 0x00, 0x01, + 0xec, 0xec, 0xe3, 0x03, 0x31, 0xaa, 0x1d, 0x1c, 0xff, 0x2d, 0xb8, 0x3c, 0xb1, + 0xdf, 0xfb, 0xd1, 0x28, 0xf1, 0xe3, 0xf4, 0xe4, 0x2e, 0xcf, 0xe2, 0xba, 0x11, + 0x26, 0xbf, 0x01, 0xb1, 0xd2, 0xc2, 0x0e, 0x88, 0xed, 0x14, 0x0a, 0xdf, 0x48, + 0xba, 0x16, 0xbc, 0xe2, 0x18, 0xb9, 0xf5, 0xe2, 0xd2, 0x06, 0x14, 0xec, 0x8c, + 0xdf, 0x1b, 0x13, 0xd7, 0xcf, 0xf7, 0xd9, 0xc2, 0xd3, 0xdb, 0xff, 0xf2, 0x46, + 0xe1, 0xe3, 0xcd, 0xa2, 0xf0, 0xef, 0x24, 0xf8, 0x14, 0xe0, 0x12, 0x07, 0xbd, + 0xf8, 0x16, 0xf6, 0x0f, 0xa7, 0x0c, 0xb7, 0xab, 0xe3, 0xd8, 0x9c, 0xed, 0x08, + 0x20, 0x16, 0x1b, 0x27, 0x19, 0xb7, 0x02, 0xda, 0xd1, 0xf6, 0xb3, 0x25, 0xaa, + 0xe2, 0x13, 0x1d, 0xfe, 0xf1, 0xc0, 0xdc, 0xc6, 0xf9, 0x17, 0xd4, 0xf8, 0xe4, + 0xfb, 0xdb, 0xa6, 0xed, 0xf6, 0x03, 0x2f, 0xd5, 0xe1, 0xb3, 0xb3, 0x13, 0xec, + 0x06, 0xde, 0xee, 0x06, 0xbe, 0x1f, 0x08, 0x1a, 0x23, 0x04, 0xd1, 0xb8, 0x07, + 0xb8, 0xe3, 0x13, 0x0f, 0x18, 0x05, 0xc0, 0xd5, 0xf8, 0x35, 0xa4, 0x22, 0xe3, + 0xf2, 0x0d, 0x0f, 0xd4, 0xfc, 0xb2, 0xd6, 0xdc, 0xeb, 0xd1, 0x1e, 0x30, 0xb9, + 0xcf, 0xff, 0x0f, 0xe6, 0x0a, 0xc7, 0xea, 0x0a, 0x37, 0x8f, 0x21, 0x1e, 0xaf, + 0x29, 0x1d, 0xe6, 0xda, 0x26, 0x14, 0x1d, 0x66, 0xe9, 0xab, 0xcc, 0xed, 0xa5, + 0xd6, 0x2c, 0xff, 0xf6, 0x04, 0xcc, 0xda, 0xf3, 0x1f, 0xdc, 0x00, 0x35, 0xce, + 0xde, 0xb5, 0x15, 0xf3, 0xbb, 0x01, 0xce, 0xea, 0xcd, 0xdc, 0xff, 0x00, 0x09, + 0xc2, 0x04, 0xee, 0xcb, 0x37, 0xf0, 0xf5, 0xaa, 0xac, 0xef, 0xc8, 0xbe, 0x10, + 0xfe, 0xdd, 0x37, 0x1f, 0x23, 0xdf, 0xee, 0x98, 0xf6, 0x0b, 0x02, 0xeb, 0xff, + 0xea, 0x10, 0xcd, 0xf6, 0xc6, 0x18, 0xc7, 0xd2, 0x33, 0x35, 0xff, 0x22, 0x03, + 0x9b, 0x51, 0xc3, 0x00, 0x76, 0xc6, 0xf6, 0xbe, 0xd2, 0x27, 0xf4, 0xf8, 0x28, + 0x09, 0x22, 0x16, 0xea, 0xb1, 0x02, 0xe6, 0x7f, 0x2e, 0xe4, 0xfa, 0x0e, 0x07, + 0xf1, 0xc0, 0xe0, 0xec, 0xff, 0xef, 0xd8, 0x17, 0x9f, 0xd0, 0xdf, 0xf8, 0xef, + 0xec, 0xd1, 0x10, 0xf4, 0xfd, 0xf6, 0x13, 0xd4, 0xe3, 0x66, 0xea, 0xfe, 0x3b, + 0xfe, 0xfc, 0x19, 0x20, 0x22, 0x08, 0xc4, 0xf9, 0x0b, 0xdc, 0x02, 0xd6, 0xe9, + 0x29, 0x19, 0xdc, 0xe5, 0xf4, 0x58, 0xef, 0x24, 0xd3, 0xdf, 0xb7, 0x36, 0xf5, + 0x22, 0xc4, 0xde, 0xce, 0xd7, 0x39, 0x20, 0x06, 0x08, 0xf4, 0xc7, 0x30, 0xfa, + 0xe6, 0xe6, 0xc7, 0x08, 0xfb, 0x22, 0xb9, 0x0d, 0x1b, 0x1a, 0x17, 0xe4, 0x18, + 0xcd, 0xe0, 0x11, 0xe6, 0x1d, 0xf5, 0xcc, 0xc0, 0xea, 0xd8, 0x32, 0xf0, 0xe7, + 0x5a, 0xf5, 0xc9, 0xff, 0xee, 0xca, 0x32, 0xec, 0xf8, 0x2c, 0x0c, 0xd3, 0xd7, + 0x30, 0x0c, 0xe5, 0xd7, 0xf5, 0x18, 0xe6, 0xe7, 0x27, 0x0a, 0x10, 0xcb, 0x0c, + 0xe7, 0xef, 0x15, 0xe5, 0xea, 0xff, 0x13, 0xeb, 0xd3, 0x14, 0x14, 0x01, 0x0f, + 0x0f, 0x07, 0xe1, 0xfc, 0x93, 0xcc, 0x0c, 0x32, 0xea, 0x1c, 0x06, 0x16, 0xd7, + 0xec, 0x13, 0xe3, 0x7f, 0x27, 0xe9, 0x32, 0x0f, 0xfa, 0x51, 0x1b, 0xba, 0xfb, + 0x2d, 0x03, 0x16, 0xfd, 0x05, 0xd8, 0x10, 0x0d, 0xbc, 0x0f, 0x18, 0x01, 0xe1, + 0xea, 0xe5, 0x2a, 0xe9, 0xe2, 0xec, 0xf8, 0xf6, 0x57, 0xf2, 0xf2, 0x05, 0x06, + 0xf6, 0xde, 0x1c, 0xe6, 0x03, 0xfa, 0xec, 0xcb, 0x0e, 0x19, 0x1a, 0x23, 0x01, + 0xda, 0xfe, 0xe4, 0xbf, 0x14, 0x00, 0xf3, 0x0c, 0x42, 0x11, 0x00, 0x0a, 0x2f, + 0xf3, 0xbf, 0x09, 0xd8, 0x19, 0xf6, 0xe4, 0xe2, 0x15, 0x55, 0xdd, 0xeb, 0xcc, + 0x14, 0xd3, 0x22, 0xee, 0xd7, 0xf6, 0x05, 0xed, 0x05, 0x02, 0xea, 0x02, 0xc3, + 0xe8, 0xee, 0x07, 0x0c, 0x10, 0xda, 0xfb, 0xe9, 0x05, 0xf0, 0xd0, 0xe7, 0xd2, + 0x05, 0xfc, 0xdc, 0xf0, 0xec, 0xff, 0xe9, 0xec, 0xc0, 0xc8, 0xe1, 0xf0, 0xf9, + 0xe0, 0xfd, 0x1e, 0xd6, 0xbe, 0xf4, 0xfa, 0xdd, 0xc6, 0x1d, 0xfe, 0xff, 0x06, + 0xda, 0x0b, 0xf9, 0xdf, 0xf2, 0xfb, 0xf3, 0xfe, 0xe7, 0x09, 0x00, 0x1a, 0x23, + 0xfd, 0xe3, 0x33, 0xfd, 0xf9, 0x10, 0x01, 0x1b, 0xdf, 0xf0, 0xcb, 0x09, 0x16, + 0x13, 0xd4, 0x0b, 0xd1, 0xec, 0xeb, 0xef, 0x13, 0x12, 0xbe, 0x20, 0xd2, 0xf0, + 0xce, 0xfe, 0xf1, 0xd3, 0x0e, 0x2c, 0xd4, 0x0e, 0xf5, 0x25, 0xd3, 0xf6, 0xeb, + 0xee, 0xc9, 0x14, 0xea, 0xd7, 0xe1, 0xea, 0x09, 0x3b, 0xfc, 0xca, 0x17, 0xd3, + 0xf1, 0x20, 0xaf, 0xf1, 0x1c, 0xbf, 0xe1, 0xe5, 0x04, 0xc2, 0xf5, 0x1a, 0xe9, + 0xf0, 0xd9, 0xf5, 0x11, 0xfd, 0xe5, 0xf2, 0x16, 0x07, 0x12, 0x33, 0xb6, 0x31, + 0xc7, 0xef, 0xdb, 0x0a, 0x18, 0xc5, 0xfd, 0xea, 0xf7, 0x11, 0x07, 0xe8, 0xfb, + 0xf4, 0xfd, 0x07, 0xd5, 0x0f, 0xbe, 0x12, 0x19, 0xfd, 0xf9, 0xd7, 0xd0, 0x05, + 0x26, 0xd1, 0xf5, 0xe4, 0xe0, 0xf2, 0x1a, 0xf6, 0xdb, 0xe5, 0xd9, 0x2c, 0x14, + 0x1a, 0x2f, 0xed, 0xd2, 0x2a, 0x2e, 0x13, 0xf9, 0xe1, 0xa3, 0xf8, 0xe3, 0xe6, + 0xdf, 0xcc, 0xe5, 0x0d, 0x03, 0xd9, 0xf2, 0xf3, 0x1c, 0x2e, 0xf5, 0x1c, 0x21, + 0xd5, 0xe2, 0x21, 0xdb, 0x0b, 0x02, 0xef, 0x03, 0xff, 0xf2, 0xde, 0xdc, 0xe5, + 0xd7, 0x02, 0xe1, 0xf1, 0x04, 0xf5, 0x05, 0xd5, 0xf1, 0x09, 0xe4, 0xcf, 0xfc, + 0xf8, 0x05, 0xd0, 0xdc, 0x15, 0xea, 0x28, 0x2b, 0x1c, 0x0c, 0xe5, 0xee, 0xb8, + 0xf3, 0x11, 0xf1, 0xf7, 0xe7, 0x03, 0xc0, 0x0a, 0xd5, 0x1f, 0xcf, 0x18, 0xf1, + 0xea, 0x02, 0xd1, 0xe8, 0xd6, 0xfe, 0xfd, 0xee, 0x02, 0x31, 0x0f, 0xc3, 0xeb, + 0x08, 0xcf, 0xfd, 0xd1, 0xf0, 0x0a, 0x1c, 0x15, 0xf6, 0xae, 0xc3, 0x07, 0x49, + 0xe6, 0xe0, 0x03, 0xde, 0xbc, 0xf7, 0xd6, 0xf4, 0x81, 0x3f, 0xee, 0xd5, 0x96, + 0xe3, 0x14, 0x74, 0xf7, 0x02, 0x04, 0xf3, 0xda, 0x1b, 0x3c, 0x27, 0x10, 0xf0, + 0x4a, 0xc6, 0x98, 0x51, 0xfa, 0x0f, 0x27, 0x11, 0xb0, 0xa0, 0x07, 0xef, 0x4f, + 0xef, 0x1c, 0xdf, 0xde, 0xcf, 0xf2, 0x43, 0xd7, 0xe9, 0x92, 0x0e, 0xe5, 0xf7, + 0xe3, 0x93, 0xbb, 0xd7, 0xe8, 0xda, 0x10, 0x15, 0x09, 0xf3, 0xdb, 0x05, 0xe3, + 0xe2, 0xd3, 0x63, 0x89, 0x01, 0xc9, 0x3b, 0x24, 0xcc, 0x47, 0x06, 0x06, 0x2c, + 0x0c, 0xe4, 0xe2, 0x8f, 0x04, 0x05, 0x1e, 0xc2, 0xdd, 0xf8, 0x60, 0x0b, 0x06, + 0x23, 0x30, 0xed, 0x2d, 0x26, 0x1f, 0x0d, 0xca, 0x33, 0x35, 0x2f, 0xed, 0x4a, + 0x07, 0xef, 0x09, 0xd3, 0x9e, 0xc6, 0x35, 0xd9, 0xde, 0x00, 0x13, 0x58, 0x0b, + 0xfb, 0xe3, 0x0b, 0x08, 0x06, 0xd1, 0x33, 0xea, 0xaf, 0xe6, 0xd5, 0x67, 0xe3, + 0xb9, 0xf7, 0x1f, 0x0e, 0xf2, 0xbf, 0x58, 0x06, 0xff, 0xa3, 0xc6, 0xf4, 0x42, + 0xc8, 0xfd, 0x28, 0x1d, 0x09, 0x22, 0x21, 0xe8, 0xd7, 0xf2, 0x0c, 0x8b, 0xa0, + 0x0b, 0x00, 0xbf, 0xe4, 0xce, 0xf6, 0x65, 0xf3, 0xfc, 0x25, 0x18, 0xf4, 0x02, + 0xd4, 0x10, 0x02, 0x34, 0xd3, 0xf6, 0xbb, 0x1e, 0x02, 0x0c, 0x1f, 0x16, 0x9a, + 0x5c, 0xc0, 0xd1, 0xd0, 0x04, 0xf9, 0xfc, 0x9d, 0xa5, 0xf2, 0x08, 0x3e, 0xc8, + 0xce, 0x0e, 0x0f, 0xcb, 0xc8, 0xfa, 0x3e, 0xe2, 0xbe, 0x0f, 0x51, 0xdb, 0x3b, + 0x07, 0xf4, 0xdf, 0x25, 0x1b, 0x15, 0x1b, 0x07, 0xf0, 0x28, 0x07, 0x81, 0xef, + 0xfe, 0xe5, 0xa1, 0x29, 0xc6, 0xdc, 0x0a, 0xf2, 0x00, 0xb1, 0xd8, 0x15, 0x04, + 0x50, 0x45, 0x1b, 0xf9, 0xf4, 0xe8, 0x07, 0xc3, 0xce, 0x3c, 0xde, 0x47, 0x10, + 0x01, 0x2f, 0x23, 0xf7, 0xd4, 0xd4, 0xd8, 0xfe, 0x45, 0xea, 0x23, 0x1b, 0x10, + 0xd2, 0x24, 0xdc, 0x0c, 0x00, 0x25, 0xfb, 0xa3, 0xe4, 0xf6, 0xcf, 0x5e, 0xfd, + 0x13, 0xd1, 0xf4, 0xe7, 0xe6, 0xc1, 0xb9, 0xc4, 0xc6, 0x1c, 0x8e, 0x09, 0x3a, + 0xda, 0x03, 0xf4, 0xe5, 0x35, 0xfc, 0x08, 0xee, 0x81, 0xf1, 0x20, 0x11, 0xf2, + 0xcd, 0xb2, 0x2a, 0x28, 0x31, 0x25, 0xb4, 0xf6, 0x21, 0xd2, 0xf9, 0xa5, 0xf7, + 0xb8, 0xf2, 0x12, 0x02, 0x29, 0x3b, 0x08, 0xc4, 0xbb, 0xe3, 0xce, 0x16, 0xc9, + 0x20, 0xd7, 0x47, 0x0c, 0xa6, 0x10, 0x18, 0xfb, 0x4f, 0xc0, 0xc1, 0x17, 0xd8, + 0xb9, 0xf4, 0xd9, 0xcf, 0x07, 0x2a, 0x2e, 0x10, 0xfc, 0x22, 0x4f, 0x94, 0x2b, + 0x15, 0x1b, 0xbe, 0xb0, 0xa6, 0x37, 0xf1, 0x19, 0xdb, 0xe3, 0xe4, 0xfc, 0x26, + 0xee, 0xe0, 0x2b, 0xdd, 0xba, 0x1e, 0x06, 0x05, 0xbe, 0xe6, 0xc5, 0x1f, 0xd0, + 0xce, 0xb5, 0xd0, 0xfd, 0xbf, 0x9d, 0xcd, 0x1f, 0xe8, 0x5f, 0xd7, 0xb1, 0xf6, + 0x0d, 0xb5, 0x4c, 0x0b, 0xd2, 0xf5, 0x1f, 0x04, 0xe6, 0x12, 0xcf, 0xbb, 0xe6, + 0xf3, 0xcb, 0x3d, 0x24, 0xc1, 0xe6, 0x97, 0xa3, 0xf4, 0x3b, 0xd3, 0x13, 0x34, + 0xbc, 0x23, 0x2b, 0x19, 0xb2, 0x45, 0xc4, 0xb7, 0xe7, 0x3b, 0xf0, 0xf0, 0x02, + 0xab, 0xc8, 0x95, 0x32, 0x14, 0x0a, 0x4e, 0xba, 0x4b, 0x2a, 0x9c, 0xf4, 0xe1, + 0xfe, 0xe9, 0x2d, 0xe9, 0x3c, 0xed, 0x03, 0xf8, 0x11, 0xf5, 0xed, 0x0b, 0x1a, + 0x16, 0x06, 0x25, 0xb1, 0xb5, 0xdc, 0x3e, 0xea, 0x38, 0x40, 0xa5, 0xfe, 0xd6, + 0x48, 0x0f, 0x9e, 0xd1, 0xc4, 0x3b, 0x0b, 0xb1, 0xe6, 0x1b, 0x0a, 0xc0, 0xdd, + 0x0e, 0xaa, 0x66, 0x02, 0x11, 0xfb, 0xff, 0x0a, 0xc2, 0xb3, 0xf6, 0xfa, 0xe7, + 0x67, 0x0a, 0x08, 0x22, 0xf5, 0x41, 0x0d, 0xc3, 0xda, 0x0b, 0x14, 0x3c, 0xf2, + 0xcc, 0xf6, 0x33, 0xe7, 0x50, 0xfa, 0xa4, 0x2a, 0x16, 0x27, 0x2a, 0x9c, 0x33, + 0xd2, 0xbf, 0xcf, 0x02, 0xf6, 0xba, 0xf5, 0xcf, 0x1e, 0xf0, 0xd7, 0xb0, 0xe2, + 0x81, 0xf9, 0x02, 0xb9, 0x02, 0xe5, 0xe9, 0xf7, 0xd2, 0xf2, 0xe2, 0x06, 0xfc, + 0xe0, 0x03, 0x0a, 0x30, 0xd9, 0xef, 0x24, 0xc4, 0xf0, 0xbc, 0xf9, 0xdb, 0x0c, + 0xd5, 0x09, 0x03, 0x43, 0xbc, 0x4e, 0xf7, 0x08, 0x00, 0x15, 0xec, 0x19, 0xc9, + 0xe6, 0xc0, 0xd4, 0x03, 0x00, 0xe0, 0xd0, 0xa1, 0x16, 0xeb, 0x0f, 0x2e, 0xfe, + 0x02, 0x04, 0xcf, 0x07, 0xda, 0x32, 0x0d, 0xf8, 0xbe, 0x1a, 0x34, 0x15, 0x35, + 0xea, 0xe9, 0xff, 0xdd, 0xe5, 0x2a, 0xc9, 0xfe, 0x19, 0xf8, 0xbe, 0xd2, 0x25, + 0xea, 0xe2, 0xf5, 0x26, 0xe0, 0xb6, 0xfb, 0xe4, 0xd0, 0x22, 0x37, 0x22, 0x8f, + 0x11, 0xe6, 0xe1, 0x1a, 0x0a, 0xbf, 0xd8, 0xe3, 0xd1, 0xee, 0xd8, 0x32, 0x4a, + 0xb1, 0xce, 0xec, 0xde, 0xee, 0xcc, 0x25, 0x07, 0xf4, 0x33, 0x02, 0xf9, 0x33, + 0x23, 0xd0, 0xf6, 0xd1, 0x08, 0xdd, 0xe4, 0xd9, 0xbe, 0xe1, 0x2d, 0xc3, 0xed, + 0x03, 0xbc, 0x3b, 0xc3, 0xd0, 0x44, 0x08, 0x14, 0xcb, 0xca, 0xa6, 0xb1, 0xe9, + 0xa6, 0xf5, 0x41, 0x39, 0xf4, 0x01, 0xed, 0x4f, 0x1d, 0xed, 0xc5, 0x40, 0x2c, + 0x29, 0xd1, 0x45, 0x0a, 0xe1, 0x32, 0x50, 0xf5, 0x31, 0x10, 0x05, 0xdd, 0xfc, + 0xbc, 0x20, 0x2c, 0x0e, 0xdb, 0xf7, 0xfc, 0xf6, 0xa9, 0xcb, 0xff, 0xf1, 0xc8, + 0xd6, 0xec, 0xb1, 0xd8, 0xbb, 0x3d, 0xf9, 0xec, 0x03, 0xe1, 0x12, 0xbb, 0xeb, + 0x1d, 0x1e, 0xea, 0xed, 0xf1, 0x0e, 0x11, 0xe5, 0x05, 0xf1, 0xf7, 0x13, 0x29, + 0xcb, 0x0e, 0xc0, 0xec, 0xf7, 0x09, 0x01, 0xb4, 0x00, 0x3e, 0xc2, 0x23, 0xeb, + 0x1f, 0xbe, 0xaf, 0x0f, 0xbe, 0x09, 0xc2, 0xf5, 0xe6, 0x9e, 0x04, 0xbe, 0xd1, + 0xea, 0xd6, 0x28, 0xaa, 0x06, 0xd8, 0x03, 0xe8, 0xf6, 0xc6, 0x24, 0x10, 0xe0, + 0xe1, 0x17, 0xdd, 0xe0, 0x0c, 0x0a, 0xf9, 0xf8, 0xd3, 0x4a, 0x13, 0xd1, 0x0b, + 0x24, 0x17, 0xd3, 0x04, 0xd9, 0x10, 0x37, 0xc2, 0x67, 0xf6, 0xf4, 0xeb, 0x0c, + 0x1d, 0x24, 0x12, 0x1f, 0x09, 0x42, 0xff, 0x32, 0xe7, 0xca, 0x2a, 0x04, 0x40, + 0x30, 0xe8, 0xfb, 0xc2, 0xfc, 0xe7, 0x0b, 0xf8, 0x2c, 0xed, 0x0a, 0x13, 0x4e, + 0xc5, 0x2d, 0x30, 0xe7, 0x26, 0xcb, 0x09, 0x53, 0xfc, 0xf2, 0xd4, 0xd7, 0x0a, + 0xee, 0x05, 0x12, 0x25, 0xff, 0x0d, 0xd3, 0xd9, 0x17, 0x0f, 0xf8, 0x1f, 0x26, + 0x06, 0x02, 0x0f, 0x20, 0x09, 0x33, 0x10, 0x12, 0x09, 0xfd, 0xf6, 0xde, 0x7f, + 0x12, 0xf4, 0x0f, 0xc0, 0x05, 0xce, 0x0e, 0x05, 0xf7, 0xd9, 0x14, 0xe3, 0x07, + 0xa0, 0x2e, 0x23, 0x43, 0xfd, 0xf8, 0xdb, 0xfd, 0xec, 0xdb, 0xaf, 0xe6, 0x23, + 0x0b, 0xd6, 0x09, 0xe3, 0x14, 0x13, 0x07, 0xe5, 0xd3, 0x43, 0x13, 0x18, 0xff, + 0xec, 0x00, 0xe9, 0xf8, 0xc7, 0xeb, 0xe2, 0xfd, 0x09, 0x35, 0x22, 0x36, 0x18, + 0xf0, 0x1b, 0x0c, 0x02, 0xf3, 0xa8, 0xdb, 0xe1, 0xfd, 0x06, 0xdf, 0x12, 0xc3, + 0xf1, 0xf0, 0xbe, 0x0c, 0x2b, 0x3b, 0x38, 0x33, 0x5f, 0x7c, 0xf6, 0x08, 0xf8, + 0xee, 0xb7, 0x03, 0x26, 0x5e, 0xf6, 0xfa, 0xd8, 0x18, 0x07, 0x03, 0xfe, 0x1e, + 0xee, 0x38, 0xb0, 0x0c, 0x2c, 0xc6, 0x22, 0xe0, 0x05, 0x11, 0x01, 0xff, 0x03, + 0x0f, 0x08, 0x19, 0xfa, 0x03, 0xb2, 0xd7, 0x40, 0x2c, 0x0c, 0x0b, 0x24, 0x08, + 0xb3, 0x36, 0xd4, 0xbe, 0xeb, 0xe2, 0x1e, 0xfc, 0xf7, 0xe6, 0x08, 0xfa, 0xed, + 0xcf, 0x09, 0xb3, 0x30, 0xf4, 0xfb, 0x16, 0xf7, 0x1c, 0xfd, 0x2a, 0xd5, 0xff, + 0xf5, 0xf7, 0xee, 0x25, 0x04, 0x08, 0x05, 0xdc, 0xe3, 0xef, 0xc4, 0x1a, 0x02, + 0xd2, 0xf6, 0x4c, 0xb3, 0xf7, 0xc8, 0xf3, 0x36, 0xff, 0xe7, 0x33, 0xd2, 0xf9, + 0xf6, 0x0c, 0x88, 0x09, 0xb3, 0xe2, 0xc7, 0xe7, 0xf8, 0x27, 0xda, 0xbc, 0xf1, + 0xac, 0xf9, 0x0f, 0xc5, 0xba, 0xe3, 0xb1, 0x04, 0xfb, 0xfc, 0x40, 0x2e, 0xde, + 0xb6, 0xdc, 0xbb, 0x25, 0x2b, 0x0f, 0x1c, 0x21, 0xf3, 0x31, 0x15, 0xf2, 0x25, + 0xf1, 0xe0, 0xc5, 0x22, 0xc3, 0xed, 0xdc, 0x4d, 0xdb, 0xf3, 0xd3, 0x55, 0x38, + 0xf3, 0xd7, 0xac, 0xf3, 0x04, 0xa4, 0x3c, 0xd2, 0xee, 0xe1, 0xd7, 0xfc, 0xde, + 0xdb, 0xe8, 0xd6, 0x0a, 0xb3, 0x65, 0x0d, 0x2e, 0xca, 0xfe, 0xe9, 0xca, 0xc4, + 0x81, 0x16, 0x47, 0xb6, 0x5d, 0xcf, 0xac, 0x39, 0xff, 0x38, 0xdb, 0x49, 0xcd, + 0xe0, 0x34, 0x07, 0x4e, 0xc1, 0x0c, 0x1f, 0xb6, 0xaa, 0x1e, 0x2d, 0x0e, 0x29, + 0xed, 0x30, 0xdc, 0xba, 0xc7, 0xf4, 0x2f, 0x6e, 0xbe, 0x31, 0xf8, 0xdd, 0xb8, + 0x05, 0xfc, 0xee, 0xe8, 0xda, 0x0b, 0xb7, 0xf7, 0x02, 0x0f, 0x85, 0x9f, 0x3d, + 0xd2, 0x3d, 0xff, 0xd1, 0xc0, 0x27, 0xe5, 0x0f, 0xff, 0xfc, 0xcf, 0x10, 0x4b, + 0xf5, 0xf5, 0x08, 0x2b, 0xeb, 0xe5, 0xd9, 0xd2, 0xc4, 0xd4, 0xf0, 0xd8, 0xfc, + 0xac, 0xe6, 0xe6, 0xc7, 0x15, 0xf1, 0xfc, 0xc3, 0x09, 0x15, 0xc9, 0xe2, 0x00, + 0x44, 0x41, 0xbf, 0x49, 0x21, 0x17, 0xdb, 0x83, 0xa3, 0xc2, 0xfb, 0x26, 0x1a, + 0xf4, 0x26, 0x20, 0xd1, 0xa7, 0x1f, 0xe6, 0x06, 0x99, 0x07, 0x16, 0x4d, 0xb1, + 0x3e, 0xc7, 0x2b, 0x30, 0xdc, 0xed, 0xed, 0xf7, 0xd9, 0xe8, 0x1c, 0xdf, 0x17, + 0xaf, 0xfb, 0xdf, 0xfb, 0xe0, 0x18, 0xe3, 0x39, 0x15, 0xf9, 0x3d, 0xaf, 0x3e, + 0x10, 0xb6, 0x3b, 0xf3, 0xee, 0xcf, 0xfa, 0xe4, 0xd2, 0xf4, 0x02, 0xf4, 0x15, + 0x24, 0xf2, 0xea, 0xfb, 0x12, 0x4e, 0xe3, 0xfd, 0xff, 0x26, 0x13, 0x38, 0xe9, + 0xe0, 0x06, 0x26, 0xf2, 0xff, 0xde, 0xef, 0xe4, 0x3d, 0xe6, 0xe6, 0xd3, 0xf1, + 0x05, 0xcd, 0xc8, 0xe4, 0xc2, 0xe0, 0x00, 0xea, 0xe2, 0x11, 0xfc, 0xd7, 0xe7, + 0xcd, 0xe8, 0xb5, 0xc6, 0x06, 0xf3, 0xbc, 0xda, 0xd6, 0xce, 0x05, 0xfa, 0xf0, + 0xe1, 0xfd, 0xe6, 0x35, 0x49, 0xfc, 0x00, 0xf8, 0xed, 0x1e, 0x24, 0x81, 0x2d, + 0x11, 0xe6, 0xfe, 0xdc, 0xba, 0xb8, 0xf7, 0x26, 0x04, 0x12, 0x1e, 0x24, 0x6f, + 0x0b, 0xf9, 0xcd, 0xd4, 0x0c, 0xce, 0x15, 0xc6, 0xe8, 0xb3, 0x05, 0x0f, 0xac, + 0x2a, 0xbd, 0xf5, 0x2f, 0xdf, 0xd3, 0x00, 0xed, 0xd2, 0x12, 0xed, 0x19, 0x36, + 0x1a, 0xf3, 0xe6, 0x02, 0x21, 0x10, 0xfe, 0xdb, 0xa6, 0xdc, 0xd2, 0x10, 0x6b, + 0xd7, 0xde, 0xce, 0xfd, 0xc2, 0x12, 0xd2, 0xfd, 0xe4, 0xd0, 0xe2, 0xfb, 0x11, + 0xdc, 0xc0, 0xda, 0xd4, 0xf8, 0x0e, 0x05, 0xdd, 0xf9, 0xee, 0x2e, 0x22, 0xe6, + 0xc2, 0xd9, 0x0b, 0xf6, 0xe0, 0x21, 0xf9, 0xdf, 0x32, 0x0c, 0x14, 0xbc, 0xc3, + 0x17, 0xf2, 0xe0, 0xe9, 0xf4, 0xf7, 0x0c, 0xdd, 0x3b, 0xbc, 0xdb, 0x1b, 0xdf, + 0xfb, 0xd9, 0x06, 0xcb, 0xde, 0x1a, 0x35, 0x21, 0x16, 0xe7, 0xd7, 0x19, 0xfb, + 0x2b, 0xc1, 0xd2, 0x0f, 0x2c, 0x02, 0x22, 0x09, 0xf0, 0xcd, 0xd8, 0x1f, 0xaf, + 0xf2, 0xd1, 0x04, 0x05, 0xbc, 0xd2, 0xea, 0x30, 0xeb, 0xee, 0xe8, 0xef, 0xd7, + 0xce, 0xbe, 0xff, 0xbe, 0xa8, 0xbc, 0xdc, 0xfd, 0xea, 0x07, 0x00, 0xe2, 0xee, + 0x27, 0xe6, 0xe7, 0x01, 0xf8, 0x07, 0xf3, 0x07, 0x01, 0xf7, 0xec, 0xe8, 0xf9, + 0xee, 0xfe, 0x14, 0x01, 0xdd, 0x2d, 0x31, 0x25, 0xf1, 0xfe, 0x22, 0xf7, 0xcf, + 0x09, 0xcf, 0xfe, 0xfb, 0xdd, 0xcc, 0x3d, 0x2f, 0xed, 0xf1, 0xe5, 0xaa, 0xed, + 0xe2, 0xea, 0xca, 0x00, 0xf8, 0xf6, 0xe7, 0xf6, 0x0c, 0x0b, 0xd0, 0x18, 0x01, + 0x1f, 0xb3, 0x1f, 0xf0, 0x07, 0xad, 0xf1, 0xca, 0xc4, 0xec, 0xf5, 0x36, 0xa4, + 0x15, 0xd1, 0xf5, 0xae, 0xcb, 0x21, 0x81, 0xfd, 0xcc, 0xd0, 0x00, 0xbf, 0xe2, + 0x0c, 0x27, 0x64, 0x22, 0x49, 0x21, 0xbd, 0xfd, 0xdb, 0xd9, 0xa7, 0x04, 0x04, + 0xe3, 0x30, 0xf4, 0xfb, 0x2b, 0xc6, 0xef, 0xfe, 0x1c, 0xe4, 0xdd, 0x01, 0x43, + 0xef, 0x4b, 0x72, 0x5c, 0x33, 0x37, 0xe5, 0xe4, 0x01, 0xea, 0xb0, 0x0b, 0x43, + 0xde, 0x06, 0xe4, 0x30, 0x5c, 0xea, 0xcd, 0xe5, 0x1e, 0x13, 0xe9, 0x0a, 0x2e, + 0xcf, 0xd9, 0x35, 0x13, 0xb7, 0xf3, 0x1f, 0xeb, 0xc5, 0x1c, 0x09, 0x13, 0x02, + 0x20, 0x13, 0x9e, 0x20, 0xe2, 0xba, 0x0d, 0xf8, 0xdf, 0x45, 0xeb, 0x1c, 0xf6, + 0x03, 0xec, 0xe5, 0x5e, 0xbb, 0x2a, 0xd3, 0xc1, 0xce, 0xb5, 0xe7, 0xff, 0xfc, + 0xf6, 0x1c, 0xb6, 0x11, 0xa6, 0xe6, 0x1b, 0xfa, 0x32, 0x24, 0xee, 0xca, 0xdd, + 0xe6, 0x17, 0x9a, 0xef, 0xea, 0xd8, 0x47, 0xf0, 0x14, 0x37, 0xd5, 0xff, 0x8a, + 0xe8, 0x03, 0xf6, 0x8e, 0x14, 0xec, 0xc4, 0x3e, 0xfc, 0xd4, 0x11, 0xd9, 0x96, + 0x9f, 0x11, 0xf3, 0x14, 0xa6, 0xdd, 0x1a, 0xfd, 0xa8, 0xcf, 0xdd, 0x18, 0xf4, + 0xd0, 0x5c, 0xf3, 0x25, 0x02, 0x2b, 0x3a, 0x44, 0xe0, 0xce, 0xf1, 0x09, 0xbe, + 0xe2, 0x1f, 0xa3, 0x11, 0xf9, 0xe7, 0x45, 0xcd, 0xeb, 0xda, 0xe0, 0xd0, 0xd6, + 0x3c, 0xf9, 0x63, 0xc2, 0x46, 0x30, 0xd3, 0xf9, 0xfa, 0xec, 0x97, 0x3f, 0x36, + 0x1b, 0xe7, 0x0f, 0xed, 0x0d, 0xe3, 0x18, 0x42, 0xcb, 0x0d, 0x37, 0x13, 0x13, + 0x49, 0xd2, 0x01, 0xcf, 0xd6, 0x27, 0xfc, 0x0e, 0xec, 0xb7, 0x1a, 0xc6, 0xf3, + 0x15, 0x60, 0x08, 0xf9, 0xe8, 0x3b, 0xc3, 0x34, 0xfc, 0x02, 0xa8, 0xcf, 0x26, + 0x37, 0xed, 0xee, 0xfc, 0xce, 0x15, 0x63, 0xb6, 0x3e, 0x09, 0xfb, 0xec, 0xfd, + 0x00, 0xc1, 0xf3, 0x08, 0x9e, 0xe7, 0xcc, 0xcf, 0xed, 0xf4, 0xd5, 0xf8, 0x11, + 0xdd, 0x12, 0xe8, 0xfc, 0xeb, 0x05, 0x03, 0x12, 0xf8, 0x12, 0xf8, 0xdb, 0x0c, + 0xda, 0x1a, 0xe8, 0x23, 0xd9, 0x16, 0x21, 0xde, 0xe0, 0x33, 0x00, 0xd5, 0x0d, + 0xeb, 0xfd, 0xfd, 0xd2, 0x23, 0xf9, 0xda, 0xcd, 0xd8, 0x1e, 0xdf, 0x13, 0x51, + 0xe8, 0xf1, 0x0b, 0x1e, 0x1e, 0xf7, 0x19, 0xff, 0xd8, 0xde, 0xdb, 0x1b, 0xe5, + 0xf4, 0xce, 0x0a, 0xfc, 0x0b, 0x00, 0xdd, 0xf0, 0xde, 0xcd, 0xbb, 0xec, 0xc4, + 0xe0, 0x25, 0xe0, 0x13, 0xef, 0xef, 0xd6, 0xe4, 0xeb, 0x0d, 0x0c, 0x15, 0xeb, + 0x0b, 0xd8, 0x20, 0x12, 0x03, 0x81, 0x01, 0x07, 0x18, 0xfb, 0xb5, 0xb6, 0xaf, + 0xb7, 0xd8, 0x0f, 0x00, 0x17, 0xde, 0xd1, 0x24, 0x16, 0xfc, 0xfa, 0x0e, 0xed, + 0xea, 0xe3, 0x09, 0x06, 0xd1, 0xe3, 0x38, 0x11, 0x03, 0xe6, 0xcd, 0x0a, 0x0d, + 0xd9, 0xeb, 0xbb, 0xe4, 0xd5, 0xb5, 0x14, 0x0d, 0x09, 0xf3, 0x22, 0x04, 0x03, + 0xe3, 0x03, 0xce, 0xdf, 0x1a, 0xc7, 0xdf, 0xdd, 0x1c, 0x1e, 0x0b, 0x01, 0xf4, + 0x0d, 0xff, 0x18, 0xf3, 0x1a, 0xff, 0x53, 0xff, 0x19, 0xfb, 0x2f, 0xf4, 0xca, + 0xea, 0x40, 0x1b, 0xf3, 0x09, 0xf9, 0xbc, 0x01, 0xec, 0xe7, 0xdf, 0x01, 0xb4, + 0x2c, 0xf4, 0xd6, 0xf8, 0x05, 0xca, 0xf9, 0xe3, 0xef, 0xdc, 0xfe, 0xf4, 0xf3, + 0xee, 0xfc, 0x05, 0x2f, 0xbf, 0xd4, 0x0e, 0xed, 0x0e, 0xfb, 0xe5, 0xf0, 0xe3, + 0xe3, 0x05, 0x0b, 0xec, 0xde, 0x13, 0xd6, 0xd3, 0xe1, 0xf6, 0xd4, 0xee, 0x22, + 0x27, 0x14, 0xf3, 0x1b, 0xec, 0xd0, 0xfd, 0xc9, 0xe9, 0x03, 0xee, 0x13, 0x0c, + 0x2d, 0xeb, 0x03, 0x9d, 0x1a, 0xed, 0x39, 0xf7, 0xde, 0xaa, 0xd2, 0xfc, 0x4f, + 0xd4, 0xf6, 0xba, 0xf9, 0xe9, 0xd3, 0xea, 0x17, 0x93, 0x2d, 0xfe, 0xf9, 0x00, + 0x00, 0x08, 0xb7, 0xfb, 0x8d, 0x2c, 0x40, 0xc1, 0x42, 0x1f, 0xbb, 0xd3, 0x41, + 0xfb, 0x13, 0xe6, 0xa8, 0x53, 0x05, 0x24, 0x1b, 0x1a, 0xf7, 0x0c, 0x2d, 0xab, + 0x23, 0xeb, 0xee, 0x42, 0x26, 0xb0, 0x05, 0x1a, 0xf0, 0xa8, 0xf2, 0x38, 0xd0, + 0xff, 0xef, 0x21, 0x41, 0x1f, 0x2a, 0x2a, 0xeb, 0xfe, 0x23, 0x0a, 0x43, 0xff, + 0x29, 0xe1, 0xad, 0xcd, 0xf8, 0x14, 0xcc, 0xd3, 0xc2, 0xf5, 0xfa, 0xb1, 0x18, + 0xa3, 0xe6, 0x49, 0x15, 0x0d, 0xf9, 0xd1, 0xf1, 0x10, 0x14, 0xea, 0xc7, 0x55, + 0xf4, 0x22, 0xcf, 0x07, 0xc4, 0xee, 0x27, 0xc0, 0x22, 0x1c, 0xf9, 0xf7, 0xda, + 0x0f, 0xd6, 0x27, 0x35, 0x10, 0xe7, 0x01, 0x33, 0xb5, 0xf5, 0x31, 0xd5, 0xef, + 0xcd, 0xe3, 0x1a, 0xa8, 0x13, 0x23, 0x3f, 0xbb, 0xe0, 0xf7, 0xda, 0xe9, 0xf8, + 0xf6, 0x00, 0x15, 0x09, 0xba, 0x27, 0xf4, 0x81, 0xe1, 0x17, 0x06, 0x0a, 0x3f, + 0xde, 0xcd, 0x07, 0xd7, 0xdc, 0xc5, 0x44, 0xe3, 0xb8, 0xd9, 0xfc, 0xf1, 0xc5, + 0xc8, 0xec, 0xdb, 0x1a, 0xc6, 0xf7, 0x31, 0xde, 0xe3, 0xe6, 0xc7, 0x9a, 0x32, + 0xb3, 0xb4, 0x2a, 0xdc, 0xe1, 0xe5, 0x15, 0xd8, 0xe2, 0xfd, 0x46, 0xfd, 0xe0, + 0x0b, 0x0d, 0x24, 0x0f, 0x0d, 0xfb, 0xc2, 0xfe, 0xa2, 0xd2, 0x0d, 0xea, 0x09, + 0x3e, 0xd6, 0xf5, 0x21, 0xb0, 0x31, 0xd3, 0x23, 0x06, 0x20, 0x06, 0xdc, 0x35, + 0x23, 0x29, 0xf3, 0xa9, 0xa8, 0xe8, 0xc8, 0x00, 0xfa, 0xf5, 0x0b, 0xd8, 0x1b, + 0x01, 0xd5, 0xec, 0xe3, 0xa4, 0xc7, 0xb6, 0xdd, 0x14, 0x3c, 0xde, 0xde, 0x14, + 0xe1, 0x30, 0xd1, 0x1b, 0xd8, 0x3c, 0x13, 0xaf, 0xbc, 0xe7, 0xd4, 0x0b, 0x01, + 0x08, 0xd5, 0x2d, 0x27, 0xfc, 0xcd, 0xef, 0x04, 0xfb, 0xcf, 0xf3, 0x16, 0x40, + 0x4a, 0xac, 0x06, 0xce, 0x18, 0xfe, 0x13, 0xc2, 0xce, 0x28, 0xef, 0xc3, 0xf0, + 0x1f, 0xd6, 0x05, 0xd7, 0x04, 0xf5, 0x0c, 0xe1, 0xe9, 0xca, 0x06, 0x18, 0xc4, + 0x11, 0x08, 0x3b, 0x18, 0xf6, 0xd7, 0xdd, 0x0a, 0xa7, 0xb7, 0xfa, 0xf4, 0x41, + 0x11, 0x28, 0x33, 0x17, 0x9f, 0x2e, 0x17, 0xde, 0x06, 0x0d, 0xa9, 0x30, 0xdd, + 0x24, 0xe5, 0xe2, 0xe2, 0x1e, 0xd6, 0x20, 0x2c, 0x0a, 0xf8, 0xd9, 0xd7, 0x14, + 0xda, 0xff, 0xd6, 0x19, 0xf0, 0x13, 0x36, 0x2b, 0xfc, 0xb6, 0xc4, 0x2b, 0xbf, + 0xf4, 0xe0, 0xa2, 0x05, 0x8b, 0x3c, 0xf6, 0xeb, 0xe3, 0xdc, 0x24, 0xba, 0xe3, + 0x3a, 0x1f, 0x07, 0xf8, 0x34, 0x14, 0xd2, 0xdd, 0x47, 0x3d, 0xad, 0xc9, 0x06, + 0x14, 0x16, 0xf3, 0xe8, 0xcb, 0xe9, 0xec, 0xe1, 0xec, 0x0c, 0x14, 0xd1, 0xd2, + 0x0c, 0xfa, 0xeb, 0xd4, 0xfc, 0xdf, 0x43, 0x2a, 0xdc, 0x02, 0xe1, 0xc2, 0x0a, + 0xe2, 0xfa, 0xec, 0x3a, 0xf7, 0x0b, 0xbd, 0x1d, 0x18, 0x26, 0xe8, 0x08, 0x1f, + 0xda, 0xdd, 0x0b, 0xf3, 0x13, 0x15, 0xd2, 0x1a, 0x81, 0xe7, 0x07, 0xfe, 0xb2, + 0xb3, 0x39, 0x0a, 0xda, 0xee, 0xd6, 0xf3, 0xf6, 0xde, 0xb5, 0x22, 0xe4, 0x1b, + 0xe9, 0x2d, 0x07, 0x02, 0x20, 0x1f, 0xdd, 0xe9, 0xde, 0x21, 0xfa, 0xee, 0xda, + 0x39, 0xf8, 0xdc, 0xf9, 0x01, 0xfe, 0x13, 0x12, 0x0f, 0x22, 0xd1, 0xfa, 0xf4, + 0xfa, 0xca, 0xf8, 0x18, 0xfb, 0x28, 0x11, 0x0a, 0x15, 0xe4, 0xce, 0x0e, 0x23, + 0x08, 0x04, 0x09, 0xd6, 0x07, 0x06, 0x01, 0x27, 0xdd, 0xf6, 0xef, 0xbf, 0x44, + 0xd2, 0xf1, 0xd9, 0x0a, 0xde, 0x11, 0x42, 0x16, 0xf7, 0xf0, 0xe3, 0x0d, 0x00, + 0x08, 0xbe, 0xca, 0x2b, 0xf3, 0x50, 0xe6, 0xd4, 0x1d, 0x1a, 0xf3, 0x10, 0x2e, + 0xf8, 0xc1, 0x20, 0xc4, 0xf4, 0xa7, 0xe8, 0xbb, 0x03, 0xf1, 0x08, 0xc2, 0x35, + 0xde, 0xd5, 0xe1, 0x6b, 0x1e, 0xbf, 0x1d, 0xb3, 0xc3, 0x2e, 0x3c, 0x81, 0x22, + 0x1e, 0xb4, 0x15, 0xc1, 0xeb, 0xc7, 0xc5, 0xfb, 0xc7, 0xaa, 0xb5, 0x20, 0xf4, + 0xb1, 0x2e, 0xbe, 0xfa, 0x27, 0xe2, 0x28, 0xef, 0x5c, 0xd9, 0xf6, 0xf6, 0x41, + 0xd1, 0xd0, 0x20, 0x26, 0x41, 0x03, 0xd4, 0x11, 0xbf, 0xfe, 0x49, 0x01, 0xc8, + 0xc1, 0xd8, 0x35, 0xaf, 0xac, 0x17, 0xdf, 0xbf, 0xcd, 0x00, 0xba, 0xbc, 0xb2, + 0xec, 0xb8, 0xc1, 0x4e, 0xc9, 0xe6, 0xf1, 0xb3, 0xb3, 0xd9, 0x04, 0xf1, 0xdf, + 0x52, 0x24, 0xf2, 0x24, 0x00, 0xe6, 0xf3, 0xe4, 0xc5, 0xa1, 0xac, 0xb7, 0x31, + 0xc2, 0x3c, 0xf0, 0xfd, 0x27, 0xee, 0xc9, 0xe6, 0xc3, 0xad, 0xd8, 0xb7, 0x37, + 0x06, 0x96, 0xfb, 0x53, 0xc5, 0x1e, 0x0f, 0x13, 0xbd, 0x9f, 0xed, 0xf5, 0x49, + 0x33, 0x13, 0xca, 0x52, 0x58, 0x39, 0x16, 0x02, 0xd0, 0x2a, 0x11, 0x0f, 0xd0, + 0x21, 0xbe, 0xe5, 0xe0, 0x03, 0x03, 0xe5, 0x37, 0xed, 0xda, 0x16, 0x5a, 0xd9, + 0xfe, 0xfe, 0xd0, 0x0a, 0xec, 0x0f, 0xff, 0xf8, 0x22, 0xe9, 0xf5, 0xf7, 0xe3, + 0xfd, 0x09, 0xef, 0xc8, 0x03, 0xfa, 0x01, 0x2e, 0xf7, 0x1b, 0x1c, 0xfd, 0xec, + 0xe7, 0xcd, 0xec, 0x0e, 0x46, 0xe6, 0xf9, 0xc6, 0xb0, 0x15, 0x50, 0xdf, 0xf0, + 0xe4, 0x12, 0x01, 0xe2, 0xc8, 0x0b, 0x12, 0x0e, 0x10, 0x0b, 0x21, 0x2b, 0xee, + 0x14, 0xd3, 0x12, 0xe3, 0xc7, 0xaf, 0xf0, 0xe8, 0xa4, 0xc4, 0xeb, 0x99, 0x15, + 0x32, 0x2c, 0xd3, 0xe5, 0xb4, 0xaf, 0x28, 0xce, 0xd1, 0xec, 0xb7, 0xd9, 0x4e, + 0xe4, 0xed, 0x5e, 0xc2, 0x2e, 0xd6, 0xdc, 0xf6, 0xe1, 0x30, 0xd1, 0xf6, 0xf0, + 0xc0, 0x00, 0xd1, 0x03, 0xde, 0xeb, 0x15, 0xef, 0xde, 0xc7, 0xfc, 0xd7, 0x35, + 0xef, 0xbd, 0xce, 0xda, 0xc0, 0xf7, 0x1c, 0x0c, 0xde, 0xe7, 0xbe, 0x09, 0xeb, + 0xbe, 0x12, 0xc9, 0x05, 0xe7, 0xe5, 0x0b, 0x1a, 0x23, 0x18, 0xf4, 0x0c, 0x09, + 0xf7, 0x1f, 0xc0, 0x2f, 0xfb, 0x16, 0xbf, 0x05, 0xe8, 0xe1, 0xf9, 0xea, 0x24, + 0xe9, 0x11, 0x3b, 0xfa, 0xeb, 0xcf, 0xe6, 0xdc, 0xd6, 0x1c, 0x1f, 0x03, 0xb8, + 0x0d, 0x0e, 0x01, 0x37, 0x08, 0x0a, 0x45, 0x2b, 0xf3, 0xe4, 0xf9, 0x1a, 0x0e, + 0x0d, 0xf6, 0x1b, 0xe8, 0xc5, 0x03, 0x14, 0x30, 0xe3, 0x45, 0xbd, 0x0a, 0xf8, + 0xb5, 0xee, 0x12, 0xe2, 0x17, 0x21, 0x32, 0x24, 0x32, 0x2e, 0x35, 0xf0, 0xe5, + 0x12, 0xd2, 0xe9, 0x11, 0x1e, 0x06, 0xf9, 0x21, 0x16, 0x36, 0x12, 0x0e, 0x05, + 0xe1, 0xb1, 0x2e, 0xe9, 0xe9, 0xe1, 0x01, 0x03, 0xe1, 0xfc, 0xf6, 0x29, 0x2d, + 0x12, 0x03, 0xfb, 0x37, 0x0e, 0x06, 0x30, 0xbd, 0x03, 0x40, 0xd9, 0x00, 0xe7, + 0x09, 0xfd, 0xef, 0xe6, 0xec, 0x2a, 0xf8, 0xfa, 0xfe, 0x09, 0xfd, 0x29, 0xd1, + 0xe5, 0x4a, 0xc9, 0xfc, 0xdd, 0xfe, 0x2f, 0x0e, 0xdd, 0x21, 0xda, 0x11, 0xee, + 0xc7, 0xfd, 0xfe, 0xcf, 0x02, 0xe3, 0x0b, 0xed, 0xf0, 0x6f, 0xf3, 0xf5, 0x11, + 0xf5, 0xbd, 0xf0, 0xeb, 0x08, 0x00, 0x08, 0xe8, 0x25, 0xfb, 0x08, 0x26, 0x17, + 0x06, 0xe6, 0xd7, 0x12, 0xf6, 0xc3, 0x05, 0xf9, 0x1d, 0xc8, 0xc5, 0xdb, 0xe5, + 0xc0, 0x18, 0x27, 0x10, 0xfc, 0xd7, 0x3a, 0x1f, 0x21, 0xf7, 0x01, 0x0c, 0xcd, + 0xed, 0x2e, 0xd3, 0xef, 0xda, 0xd9, 0x0a, 0xe8, 0xf6, 0x07, 0x00, 0x11, 0x12, + 0x01, 0xf2, 0xe7, 0xf5, 0x0e, 0xeb, 0x0a, 0x0f, 0x2f, 0xd4, 0xcb, 0x00, 0xf4, + 0xeb, 0xea, 0xec, 0xf1, 0x24, 0x0d, 0xdd, 0x1b, 0x00, 0xff, 0x11, 0x08, 0x0d, + 0xcd, 0x06, 0xf3, 0xc7, 0xde, 0xf4, 0x02, 0x23, 0x0e, 0x7f, 0xf3, 0x32, 0x11, + 0x12, 0x02, 0x2d, 0xd9, 0x48, 0xce, 0xe2, 0xc9, 0x14, 0xe5, 0xd7, 0x28, 0x20, + 0x1a, 0xc1, 0x36, 0xe7, 0x30, 0x38, 0xec, 0x0d, 0x4c, 0x3a, 0x24, 0xd2, 0xb1, + 0x3d, 0x19, 0xbb, 0xd3, 0xca, 0xdb, 0x03, 0xe3, 0xd7, 0x0e, 0xe0, 0xc3, 0xb5, + 0xe3, 0x3e, 0xe0, 0x0f, 0xd2, 0xec, 0xb8, 0xae, 0x2c, 0xf4, 0xec, 0xcd, 0x14, + 0xee, 0xe2, 0x52, 0xdf, 0x64, 0xf3, 0xef, 0x1e, 0xb3, 0x9c, 0x08, 0x02, 0xf2, + 0x1c, 0xd6, 0x20, 0x17, 0x2b, 0x20, 0xdc, 0xed, 0xfc, 0xf7, 0xc4, 0x21, 0xd2, + 0x47, 0x2a, 0x0b, 0x00, 0x09, 0x3d, 0x3e, 0xf3, 0x32, 0xc6, 0x0b, 0xc0, 0xf9, + 0x1c, 0x00, 0x14, 0xfb, 0xfe, 0x46, 0x1f, 0xcd, 0xdf, 0x40, 0xe5, 0x0d, 0xdd, + 0x24, 0xd8, 0xf7, 0xf3, 0xf4, 0x1e, 0x0c, 0xd4, 0x2c, 0x07, 0x92, 0xd9, 0x1a, + 0xda, 0x42, 0xd2, 0x33, 0x0c, 0xe6, 0xed, 0xf6, 0xe1, 0xca, 0x27, 0x11, 0xe2, + 0xf4, 0x81, 0x26, 0x08, 0xf4, 0x40, 0xcb, 0xb6, 0xf1, 0xf7, 0x22, 0xd2, 0xce, + 0xda, 0xe7, 0xd3, 0xf3, 0xdd, 0x43, 0x36, 0xff, 0x20, 0x10, 0x18, 0x06, 0xbf, + 0x07, 0x1c, 0x0e, 0x07, 0x03, 0x2a, 0xf0, 0xec, 0xc8, 0xf8, 0xb7, 0xe3, 0xe2, + 0x14, 0xde, 0xaf, 0xda, 0x3f, 0x0f, 0xfb, 0x11, 0x2a, 0xbd, 0xe7, 0x12, 0x04, + 0xf5, 0x24, 0x17, 0xf3, 0x05, 0x22, 0x3c, 0x1b, 0xe2, 0xfb, 0xb4, 0x38, 0x04, + 0x0a, 0x1c, 0x09, 0xf0, 0x34, 0xf7, 0xf5, 0x10, 0x32, 0xe9, 0xbc, 0x36, 0xc7, + 0xef, 0x1b, 0xff, 0x29, 0xf6, 0xfc, 0xfa, 0xd8, 0x0c, 0xae, 0x9a, 0x1b, 0x06, + 0x03, 0xbf, 0x09, 0x3a, 0xde, 0x16, 0x1f, 0xca, 0x0b, 0xd6, 0x21, 0xcb, 0xb2, + 0xc4, 0x1e, 0x05, 0xc8, 0xc7, 0xdf, 0xfb, 0x0c, 0xc7, 0xef, 0x11, 0xe3, 0xdc, + 0xe4, 0x0b, 0xe1, 0xf6, 0xe2, 0xce, 0xad, 0xea, 0x1c, 0xf2, 0xe8, 0xe8, 0xde, + 0xf2, 0xe8, 0xd7, 0xfe, 0xfc, 0x23, 0xc6, 0x47, 0x06, 0xdd, 0xde, 0x64, 0x0e, + 0xda, 0xfe, 0xd5, 0x21, 0x19, 0x06, 0xf7, 0xe9, 0xe6, 0xf9, 0x1e, 0xbc, 0xea, + 0x11, 0xe1, 0x0b, 0xd0, 0x20, 0x12, 0x39, 0xf1, 0x08, 0xed, 0xcb, 0x38, 0x0c, + 0xe3, 0xe5, 0xbf, 0x39, 0x00, 0xdd, 0xcc, 0xa3, 0x0f, 0xf4, 0x29, 0x1f, 0xd4, + 0x3d, 0x25, 0xe3, 0x62, 0xf2, 0xc1, 0x02, 0x97, 0x2a, 0xfd, 0xe1, 0xc8, 0xea, + 0x36, 0x0f, 0xf4, 0xc1, 0xfb, 0x26, 0xd4, 0x2d, 0xe2, 0x09, 0xe0, 0xfa, 0xae, + 0xff, 0xf7, 0x31, 0x08, 0x1b, 0x5e, 0x0b, 0xe1, 0xd1, 0x2b, 0xd2, 0xfa, 0xec, + 0xbc, 0xed, 0x44, 0xd7, 0xcf, 0x7f, 0xd8, 0xca, 0xe9, 0x0f, 0x53, 0x44, 0x3c, + 0x15, 0x24, 0x07, 0xd1, 0x1e, 0x9f, 0xd1, 0xca, 0xe6, 0xec, 0xba, 0xea, 0xbc, + 0xc7, 0xef, 0x0c, 0xf9, 0xe8, 0x1f, 0xf4, 0xf7, 0x47, 0xbb, 0xa3, 0xe9, 0xd4, + 0xda, 0xde, 0xe0, 0x01, 0xd8, 0x1c, 0x0b, 0x21, 0x26, 0xe0, 0x32, 0x26, 0x4f, + 0xe4, 0x4e, 0xf8, 0x01, 0xed, 0xef, 0xfa, 0xf9, 0x27, 0x1c, 0xe2, 0xfb, 0xd4, + 0xfd, 0xf7, 0x01, 0xdd, 0x95, 0x02, 0xea, 0xf1, 0x2e, 0x37, 0x16, 0x0b, 0x4a, + 0x17, 0x4b, 0xcb, 0x21, 0x2e, 0x26, 0x16, 0x0a, 0x14, 0x1b, 0xf9, 0x13, 0xb9, + 0xee, 0x3a, 0x46, 0xfe, 0x16, 0xf1, 0xa4, 0x45, 0xf1, 0x24, 0xf4, 0x11, 0x1e, + 0x2f, 0x03, 0xe9, 0x34, 0x52, 0xfa, 0xb4, 0x10, 0xec, 0x47, 0x2a, 0xd4, 0xd9, + 0x08, 0x70, 0x36, 0xd7, 0x22, 0xd1, 0xaa, 0xf0, 0x00, 0xbd, 0xdd, 0xee, 0xb1, + 0x05, 0x1a, 0x00, 0xd0, 0xbb, 0xbc, 0xf5, 0x07, 0xe6, 0xfc, 0x2a, 0xeb, 0xe0, + 0x01, 0xa0, 0xfd, 0xda, 0xde, 0xf4, 0xff, 0xeb, 0xe1, 0x14, 0x1c, 0xf3, 0xf0, + 0x02, 0xe4, 0xe5, 0xef, 0xe6, 0x06, 0x05, 0x17, 0x0f, 0x20, 0xc9, 0x01, 0xd6, + 0x1e, 0xf0, 0xc9, 0xb3, 0x2d, 0x00, 0x03, 0xb6, 0xd5, 0x17, 0x0a, 0xa5, 0x13, + 0xfd, 0x44, 0x17, 0xbc, 0xec, 0xd8, 0xf2, 0xe4, 0x05, 0x2b, 0xe8, 0xcf, 0xea, + 0x2f, 0xf2, 0xde, 0xf4, 0x0a, 0xe6, 0x00, 0x04, 0xde, 0xf2, 0x9e, 0xd3, 0x12, + 0x09, 0xf6, 0x16, 0x11, 0x38, 0xd5, 0x30, 0xf0, 0x3d, 0x0d, 0xef, 0x45, 0xd8, + 0x1c, 0xe7, 0x07, 0xc8, 0x13, 0xed, 0x17, 0xe9, 0x16, 0x47, 0x22, 0xf6, 0x81, + 0x45, 0x07, 0xf8, 0xab, 0x2f, 0xd8, 0xb9, 0xfd, 0xfb, 0xeb, 0xcb, 0xcb, 0xf9, + 0x3a, 0x2c, 0xe6, 0x0c, 0x93, 0xec, 0x1d, 0x12, 0x06, 0xd9, 0x15, 0xf6, 0x16, + 0x91, 0xf7, 0xd0, 0xdf, 0x2b, 0x1a, 0x30, 0xef, 0xc5, 0x05, 0x28, 0xbb, 0xc5, + 0x9d, 0xfd, 0xce, 0xe4, 0x13, 0xc7, 0x0e, 0xd5, 0xcb, 0xeb, 0xd1, 0xdb, 0x3f, + 0x25, 0x02, 0x01, 0xa2, 0x47, 0xe0, 0xf6, 0x3d, 0xd3, 0x1a, 0x30, 0x1a, 0x25, + 0xdf, 0xc6, 0x0d, 0xfd, 0x2d, 0xde, 0xdb, 0xd4, 0x43, 0xc5, 0x35, 0xee, 0xf4, + 0x13, 0xd0, 0xe2, 0xb8, 0x05, 0x2f, 0xe4, 0xaa, 0x17, 0x36, 0xe3, 0x4e, 0x2e, + 0x09, 0x01, 0xef, 0x06, 0xb2, 0xeb, 0x04, 0x2e, 0x12, 0x02, 0x16, 0xf0, 0x0f, + 0xda, 0x14, 0xfa, 0xd2, 0xba, 0xe9, 0x02, 0x2e, 0x17, 0xeb, 0xcb, 0x8d, 0x06, + 0xd3, 0xa7, 0x17, 0x15, 0x1a, 0x0f, 0xcf, 0x23, 0x3d, 0xff, 0x33, 0xd4, 0x21, + 0xfe, 0xbe, 0xf8, 0xf0, 0xd0, 0xbf, 0xab, 0x11, 0xe0, 0x18, 0xb1, 0x41, 0xb5, + 0x26, 0x1e, 0xff, 0x07, 0x37, 0xec, 0xbc, 0x96, 0x19, 0x0c, 0x1b, 0xf0, 0x48, + 0x2f, 0xc6, 0xd2, 0xd8, 0xbc, 0xf9, 0x11, 0xbb, 0xff, 0xe7, 0xe7, 0x1f, 0x3d, + 0x24, 0xff, 0x16, 0x54, 0x0c, 0xdf, 0x1b, 0xd3, 0xba, 0xf6, 0x43, 0x01, 0xd8, + 0x4f, 0x23, 0x02, 0x00, 0x41, 0xab, 0xdb, 0xbe, 0x12, 0xf7, 0xfe, 0xcc, 0xdb, + 0xaf, 0x2c, 0xf3, 0x10, 0xea, 0x96, 0x18, 0x00, 0xf4, 0xf0, 0x06, 0xbc, 0x00, + 0xac, 0xe3, 0x3d, 0xa3, 0xbb, 0xba, 0xf5, 0xd5, 0x19, 0xe6, 0xa6, 0xff, 0x56, + 0xf8, 0x07, 0x26, 0xeb, 0x11, 0xed, 0xb1, 0xcb, 0xc9, 0x07, 0x27, 0x69, 0xaa, + 0xef, 0x06, 0x4b, 0xf1, 0xe6, 0xe4, 0x21, 0xa4, 0xe1, 0xda, 0xe7, 0xe2, 0xb9, + 0x30, 0x0c, 0x0a, 0x44, 0x2c, 0xdc, 0xf3, 0xe8, 0xe3, 0xe0, 0x1a, 0xcb, 0xa4, + 0xfd, 0x07, 0xdf, 0xd8, 0x11, 0xe1, 0x08, 0x2b, 0xcc, 0x15, 0x13, 0xd0, 0xc0, + 0xf3, 0x22, 0x59, 0xd2, 0x33, 0xf5, 0x1d, 0xd9, 0xfc, 0xd6, 0x30, 0x1a, 0xf5, + 0xd5, 0x19, 0x1c, 0x11, 0xd7, 0x20, 0x3f, 0xd9, 0xdb, 0x18, 0xf7, 0xae, 0xfd, + 0x15, 0x54, 0x06, 0x27, 0xc8, 0xe6, 0xa4, 0xc4, 0x3f, 0x03, 0x4f, 0xda, 0xaf, + 0xd1, 0xad, 0xf7, 0x31, 0x37, 0x1b, 0xa6, 0xe6, 0x32, 0x2e, 0x04, 0x15, 0x1a, + 0x0f, 0xb8, 0xc0, 0x37, 0xbc, 0x81, 0x09, 0xe5, 0x1b, 0x51, 0x94, 0x10, 0x19, + 0x1b, 0xf5, 0xea, 0xc5, 0xee, 0x00, 0xe5, 0xcd, 0x01, 0xfe, 0x11, 0x9b, 0xa2, + 0x05, 0xd7, 0xab, 0xe7, 0xfd, 0xb6, 0xd9, 0xec, 0xe3, 0x3d, 0xbb, 0x1f, 0x10, + 0x1e, 0xe7, 0xdd, 0xeb, 0x4d, 0x21, 0xd2, 0x35, 0x9d, 0x53, 0x41, 0x23, 0x1c, + 0xe5, 0xc6, 0xf7, 0x15, 0xd4, 0x3d, 0x1a, 0x0d, 0xec, 0xba, 0x23, 0xfc, 0x02, + 0x38, 0xa1, 0x04, 0xf5, 0x99, 0xff, 0x49, 0xbc, 0xab, 0xba, 0xad, 0xe3, 0xb7, + 0x19, 0xcf, 0xf7, 0x0e, 0x25, 0x68, 0x13, 0xbe, 0xcb, 0xd7, 0x1b, 0xd5, 0x29, + 0xfe, 0x0c, 0x42, 0x1d, 0x61, 0x0b, 0xfa, 0x08, 0xf0, 0xde, 0xff, 0xf3, 0xbd, + 0x29, 0x9d, 0xb1, 0xf6, 0x50, 0x07, 0x55, 0xf8, 0x1e, 0xe2, 0xfe, 0x19, 0xfc, + 0xc5, 0xde, 0xdc, 0x0d, 0xfb, 0x17, 0x13, 0xf6, 0xf3, 0xf4, 0xfe, 0xe8, 0x0e, + 0xc7, 0xee, 0xb8, 0xd1, 0x5a, 0xd4, 0x1a, 0xbe, 0xe9, 0x1e, 0xb2, 0x15, 0xa6, + 0xc0, 0x06, 0xd4, 0x0f, 0xcd, 0xec, 0x0d, 0xd9, 0x03, 0xd9, 0xc9, 0xd2, 0x05, + 0xdf, 0x23, 0xd2, 0xbe, 0x66, 0xec, 0xf7, 0xbf, 0x02, 0xd8, 0xdc, 0x60, 0xf3, + 0x27, 0x28, 0xe5, 0xf7, 0xfa, 0xca, 0xbe, 0x2f, 0x0d, 0xcc, 0xd8, 0x0a, 0xff, + 0x18, 0x11, 0xfa, 0x01, 0xe9, 0x2e, 0xd6, 0x03, 0x4b, 0xe4, 0x20, 0x0c, 0xe3, + 0xca, 0xb2, 0x12, 0x34, 0x13, 0x42, 0x49, 0x0e, 0xd3, 0xc5, 0xee, 0xfe, 0x16, + 0x09, 0x03, 0x39, 0x1d, 0xcf, 0xcc, 0xff, 0x0b, 0xb9, 0xf8, 0x10, 0xf4, 0x34, + 0xd7, 0xe5, 0x05, 0x06, 0xd7, 0x02, 0xd0, 0xe7, 0xe0, 0xb6, 0xc2, 0xbc, 0xca, + 0xd3, 0xcd, 0x1a, 0xdc, 0xeb, 0x28, 0x2c, 0x1a, 0x07, 0x16, 0x86, 0xd9, 0x01, + 0x02, 0xeb, 0xc1, 0xcc, 0x58, 0xd1, 0x17, 0x06, 0xe0, 0x6d, 0xdd, 0x05, 0x19, + 0x2e, 0x04, 0x0d, 0x3d, 0xe6, 0xd9, 0xfe, 0x02, 0x0f, 0xf0, 0x10, 0xfb, 0xff, + 0x13, 0xc1, 0xe7, 0xe8, 0x01, 0xc0, 0xfa, 0x01, 0xed, 0x34, 0x16, 0xf2, 0xe1, + 0xea, 0x03, 0x14, 0xe4, 0xed, 0x25, 0x12, 0x11, 0xee, 0x01, 0x18, 0x0d, 0xdd, + 0xfe, 0xb7, 0x1c, 0x04, 0x14, 0xfc, 0x00, 0xcd, 0x24, 0x08, 0x0e, 0xfc, 0x0b, + 0xdc, 0x23, 0xf9, 0xba, 0x5b, 0x31, 0x28, 0xc0, 0x1b, 0xdd, 0x31, 0x20, 0x09, + 0xea, 0xf5, 0x7e, 0xca, 0xcb, 0x0d, 0xb8, 0xf5, 0x09, 0xf8, 0xad, 0xec, 0x0f, + 0xd3, 0xfd, 0x0d, 0xe7, 0xc7, 0x82, 0xe6, 0xd9, 0x03, 0x05, 0x26, 0xe0, 0xe0, + 0xde, 0xfd, 0xde, 0x05, 0x81, 0xea, 0xd9, 0xfc, 0x0e, 0xeb, 0xcd, 0x12, 0xf4, + 0xc1, 0x0a, 0xdd, 0xdc, 0xea, 0xef, 0xdb, 0xe2, 0x07, 0xe8, 0xe4, 0xaa, 0xd4, + 0x2b, 0xb1, 0xce, 0x04, 0xfd, 0xf3, 0xe7, 0xd6, 0x4e, 0x83, 0xd1, 0x89, 0xa6, + 0x2f, 0x00, 0x06, 0xc9, 0x36, 0x1f, 0x35, 0x28, 0xee, 0xdf, 0x1a, 0x11, 0x2e, + 0xb4, 0xc7, 0x23, 0x37, 0xf9, 0x2f, 0x0d, 0xdb, 0xe8, 0x11, 0x3a, 0xc2, 0x91, + 0x48, 0x34, 0x38, 0x13, 0x07, 0xe8, 0xa5, 0xcf, 0x27, 0x52, 0x8d, 0x0a, 0x04, + 0x3a, 0x17, 0x3d, 0x5c, 0xf6, 0xff, 0xe0, 0xd9, 0x4c, 0x20, 0x05, 0xb0, 0xe9, + 0xc6, 0x2b, 0x0c, 0xd7, 0x1d, 0xec, 0xb5, 0x7a, 0xd0, 0xa0, 0xd4, 0x49, 0x34, + 0x3d, 0x1b, 0x6e, 0x5f, 0x63, 0xff, 0xe3, 0x11, 0xa6, 0xff, 0x3e, 0x99, 0xcb, + 0xff, 0x88, 0xa1, 0x3b, 0xe1, 0xca, 0xa6, 0x2c, 0x3f, 0x3d, 0xf3, 0xb4, 0xb5, + 0x32, 0x53, 0xb2, 0xf2, 0x2a, 0x39, 0x11, 0xdc, 0x32, 0xdd, 0x5c, 0x60, 0x10, + 0xfe, 0xdb, 0x01, 0x18, 0xbf, 0x94, 0x34, 0xb2, 0xaf, 0xa2, 0xf4, 0x05, 0x2e, + 0x19, 0x09, 0xc8, 0x3f, 0x01, 0xfa, 0xfa, 0xe1, 0x17, 0x0f, 0x3c, 0xc6, 0xe6, + 0xf5, 0xb7, 0xf8, 0xe7, 0xed, 0x0d, 0xf5, 0xec, 0x1c, 0x27, 0xf6, 0x19, 0xec, + 0xd3, 0xc5, 0xc6, 0x9a, 0x11, 0x03, 0x58, 0x08, 0x09, 0x54, 0xd9, 0x36, 0xb7, + 0x26, 0xe7, 0x41, 0xf9, 0xfe, 0xf9, 0x20, 0x3e, 0x33, 0xb1, 0x01, 0xd2, 0x0f, + 0xf8, 0x36, 0x27, 0xbd, 0xe8, 0x06, 0x3b, 0x24, 0xf8, 0xf1, 0xa7, 0x52, 0x2b, + 0x25, 0xe7, 0x49, 0x2b, 0x01, 0xcf, 0xd9, 0x1b, 0x1b, 0xa1, 0xf1, 0x41, 0x24, + 0xcc, 0xcf, 0xaf, 0x4d, 0xcc, 0x58, 0x04, 0xd3, 0xbf, 0xde, 0x13, 0xca, 0x41, + 0x06, 0xfb, 0x33, 0xd7, 0xd3, 0xdc, 0xe2, 0x00, 0x12, 0xbb, 0xbd, 0xd9, 0x5a, + 0xf0, 0xcf, 0xf6, 0x12, 0x28, 0x02, 0x13, 0xd3, 0x9e, 0xff, 0xf4, 0x7f, 0x0c, + 0xf1, 0xb5, 0x09, 0xd4, 0x10, 0x8c, 0xff, 0x12, 0x23, 0x4a, 0x9f, 0xae, 0xed, + 0x17, 0xec, 0xd4, 0xf2, 0xd5, 0xa6, 0x2b, 0xe8, 0xcb, 0xde, 0x4d, 0xec, 0xf9, + 0xae, 0xaf, 0x0f, 0xa6, 0xcf, 0x08, 0x96, 0xd1, 0xb9, 0xa5, 0x1b, 0x1f, 0xf2, + 0xe6, 0x36, 0xf5, 0x97, 0xfc, 0x19, 0x34, 0xe0, 0xeb, 0x02, 0x40, 0xde, 0xf5, + 0x2d, 0xb7, 0xce, 0xae, 0xb9, 0x1a, 0x05, 0x5d, 0x64, 0xdb, 0xf2, 0x67, 0x27, + 0xf6, 0x1f, 0xa5, 0xb9, 0xe4, 0xf3, 0xc6, 0x6b, 0x8d, 0x12, 0xf6, 0x48, 0xed, + 0xf4, 0xfe, 0xc7, 0x32, 0xe4, 0x96, 0x27, 0xde, 0xcc, 0x44, 0x16, 0xe7, 0xeb, + 0xef, 0xbb, 0x23, 0x4f, 0x36, 0x0b, 0xf4, 0xbb, 0xcb, 0x05, 0xdf, 0x0f, 0x24, + 0xc1, 0x3c, 0xc8, 0xb4, 0xb9, 0xcf, 0xf5, 0x36, 0xa9, 0x05, 0x51, 0x29, 0xef, + 0xc9, 0x15, 0xdc, 0x99, 0xe0, 0xbf, 0xf1, 0x21, 0x3f, 0xfb, 0xe0, 0xfe, 0x3e, + 0x31, 0xf2, 0xef, 0xcd, 0xc7, 0xa6, 0xc3, 0xfa, 0xce, 0x2d, 0xae, 0xcd, 0xe9, + 0xce, 0x15, 0x1b, 0x2b, 0x29, 0xbc, 0xf1, 0xfa, 0xe6, 0x0b, 0x3e, 0xc8, 0x27, + 0x2c, 0xe7, 0xc0, 0xe1, 0x2c, 0x5b, 0x59, 0x0f, 0xca, 0xca, 0x23, 0x9b, 0xc2, + 0x34, 0x6c, 0x12, 0x0c, 0xc1, 0xe7, 0xf4, 0x27, 0x0c, 0x02, 0xbb, 0xf8, 0x06, + 0xda, 0xe5, 0xd3, 0xe6, 0xb5, 0x4a, 0x2e, 0x18, 0xf9, 0xea, 0x20, 0x22, 0x33, + 0xdd, 0xec, 0xdc, 0xd2, 0x04, 0xd7, 0xed, 0xf0, 0xbb, 0x9e, 0xbc, 0x0d, 0xea, + 0xe5, 0xc9, 0xcd, 0xec, 0x1e, 0x99, 0xa0, 0xe0, 0xfd, 0x1b, 0xa4, 0x3a, 0xfe, + 0xd7, 0xea, 0xa6, 0x3c, 0x8f, 0x1b, 0x18, 0x42, 0xf8, 0xf8, 0x05, 0x25, 0x52, + 0x2b, 0x06, 0xe8, 0x69, 0xf5, 0xc4, 0xd8, 0x0e, 0x05, 0x03, 0xf6, 0x58, 0x40, + 0xd6, 0x46, 0x02, 0x5d, 0x81, 0xdb, 0x99, 0xf2, 0xd2, 0xd7, 0xd1, 0x0b, 0x0d, + 0xc5, 0xc6, 0x05, 0x0b, 0x52, 0xfe, 0xb9, 0x1d, 0x28, 0xbe, 0x33, 0x36, 0xff, + 0xf5, 0xab, 0x53, 0xed, 0x62, 0xfd, 0xb1, 0x54, 0x26, 0xf5, 0x32, 0xd0, 0xba, + 0x02, 0xfa, 0x96, 0x37, 0x03, 0xcf, 0x19, 0xa7, 0x16, 0x3c, 0xe3, 0x8e, 0x8f, + 0xe4, 0xf4, 0xba, 0xaf, 0x95, 0xed, 0x29, 0xbb, 0xb7, 0x3d, 0x29, 0xfa, 0xba, + 0x0a, 0xf8, 0x24, 0x02, 0x43, 0xb6, 0x38, 0xd9, 0x22, 0x0c, 0x23, 0x45, 0xf4, + 0x0b, 0x04, 0x3d, 0x13, 0xfb, 0x42, 0x59, 0xd7, 0xd4, 0x59, 0x0c, 0xe4, 0x49, + 0x34, 0xae, 0x35, 0x28, 0xb7, 0xb7, 0x43, 0xd8, 0x1a, 0x83, 0x38, 0x35, 0xf9, + 0x48, 0x3d, 0xc7, 0x54, 0x66, 0x0c, 0xc9, 0xb5, 0xae, 0xe9, 0xb9, 0xe7, 0x2c, + 0x3e, 0xdf, 0xef, 0xde, 0x93, 0xa7, 0xf7, 0xdb, 0x44, 0xad, 0xfa, 0x04, 0xfc, + 0x1d, 0x18, 0x24, 0x1f, 0xb9, 0x01, 0xb2, 0xe8, 0xe2, 0x9c, 0xd3, 0xb0, 0xe2, + 0x03, 0x35, 0xe4, 0x3d, 0xe5, 0x1e, 0x2c, 0xad, 0x2e, 0x1e, 0xba, 0xb1, 0x0d, + 0xa6, 0xe9, 0x0e, 0xe9, 0x06, 0x85, 0xfa, 0x11, 0x32, 0xeb, 0x18, 0x47, 0xdf, + 0x98, 0x29, 0x22, 0xcb, 0x05, 0xdb, 0xe4, 0x1f, 0xf5, 0x3c, 0x6c, 0xf2, 0x14, + 0x18, 0x1b, 0x5a, 0xe8, 0xd8, 0xc9, 0xf6, 0xeb, 0x1b, 0xc3, 0x07, 0xd6, 0xac, + 0xb9, 0x11, 0xc4, 0x20, 0xd4, 0x1a, 0x28, 0xc2, 0x25, 0x53, 0x37, 0x10, 0xdf, + 0x08, 0xf3, 0x1a, 0xcd, 0x01, 0x38, 0x50, 0x47, 0xe0, 0x17, 0xc8, 0xd5, 0xef, + 0x9c, 0x3c, 0xf4, 0x17, 0x8d, 0xb8, 0x04, 0xa8, 0xea, 0x29, 0xf5, 0x5c, 0xe2, + 0x20, 0xf2, 0x23, 0x7f, 0x36, 0x13, 0xb1, 0xe9, 0x32, 0x05, 0xca, 0xf4, 0x02, + 0xfe, 0x11, 0x0d, 0xf1, 0x31, 0x9c, 0xdb, 0x13, 0x4d, 0x1a, 0x01, 0xf2, 0x18, + 0xf9, 0xbe, 0xcf, 0x61, 0xf2, 0x3f, 0x3f, 0x29, 0x0d, 0x28, 0x15, 0x92, 0x0e, + 0xea, 0xe4, 0x18, 0xd5, 0x15, 0xc7, 0x8d, 0x07, 0x3e, 0xb4, 0xc5, 0xdb, 0x03, + 0x00, 0xc9, 0xbd, 0x0b, 0xaf, 0xde, 0xf7, 0x0c, 0xdd, 0x09, 0x0a, 0xb6, 0xf6, + 0x1c, 0xc8, 0x11, 0x1e, 0xf9, 0xd4, 0xbd, 0xfe, 0xe7, 0x27, 0xe4, 0xe4, 0xf0, + 0xde, 0x2a, 0xcd, 0xdd, 0x0d, 0xd7, 0x10, 0xd3, 0x0c, 0x0b, 0xe6, 0x1b, 0xce, + 0xf0, 0x0a, 0x2a, 0xe7, 0x7a, 0xeb, 0xea, 0x18, 0xe7, 0x0f, 0xcd, 0xec, 0xba, + 0x14, 0xb7, 0xe4, 0x23, 0x0b, 0x1c, 0x40, 0x85, 0xdd, 0x9a, 0xe6, 0xd8, 0xbc, + 0x0c, 0xed, 0x20, 0xff, 0xfd, 0x9f, 0x37, 0x09, 0x41, 0x39, 0xed, 0xab, 0x1e, + 0x0f, 0xfb, 0xe8, 0x33, 0xc7, 0xc8, 0x04, 0xd0, 0x00, 0x04, 0xff, 0xfd, 0x07, + 0x16, 0x11, 0xdd, 0x05, 0x0d, 0xe3, 0xca, 0xe1, 0x06, 0x09, 0xda, 0x28, 0x06, + 0xfe, 0xeb, 0x31, 0x51, 0xc6, 0xf4, 0x0e, 0xfa, 0xce, 0x07, 0xfe, 0xe0, 0x30, + 0x42, 0xea, 0x18, 0xf4, 0xe2, 0xd1, 0xf2, 0xce, 0x39, 0xa3, 0xc2, 0x0f, 0x9e, + 0x37, 0xb0, 0x81, 0xe8, 0x1e, 0x04, 0xce, 0x1e, 0xc3, 0x45, 0x11, 0x54, 0x08, + 0xcf, 0xe3, 0xf7, 0xb3, 0x44, 0x1c, 0xc3, 0xf2, 0x23, 0x11, 0xfb, 0x26, 0x0c, + 0xf4, 0x00, 0xef, 0xf3, 0x00, 0xb9, 0xf4, 0xed, 0x17, 0xd7, 0x1c, 0xd1, 0xe7, + 0xed, 0xbf, 0x3f, 0xe3, 0xca, 0x23, 0x15, 0x0d, 0x08, 0xa7, 0xf8, 0x33, 0xf3, + 0x41, 0x0a, 0xbc, 0x05, 0xd9, 0x35, 0xd8, 0xba, 0xda, 0xea, 0xfe, 0xd3, 0x0c, + 0x1a, 0xd8, 0xb9, 0x24, 0xfc, 0x0c, 0x11, 0x0d, 0x24, 0xdb, 0x13, 0x4b, 0x0d, + 0xc3, 0xd9, 0xf3, 0xc9, 0x11, 0xeb, 0x10, 0xd2, 0xdb, 0xe1, 0xc7, 0x63, 0x16, + 0x08, 0x0a, 0xd0, 0xf3, 0x06, 0xb6, 0x22, 0xf2, 0x05, 0xa3, 0xdb, 0xfc, 0xfb, + 0x08, 0xff, 0xd3, 0xf8, 0xc8, 0x0f, 0x20, 0xc2, 0xed, 0xec, 0x1c, 0xdf, 0x29, + 0xdf, 0x12, 0xdf, 0xd6, 0xec, 0x56, 0xc7, 0xf3, 0x11, 0xae, 0xf6, 0xf6, 0x1a, + 0xd5, 0xcd, 0xdd, 0x04, 0xdb, 0x0d, 0xde, 0xd5, 0xf7, 0x4c, 0xd7, 0xec, 0x0b, + 0x25, 0xf9, 0x11, 0xfa, 0x1d, 0xf7, 0x3e, 0xfb, 0xc5, 0xdd, 0x23, 0xb2, 0x26, + 0xc6, 0xe6, 0x14, 0xd0, 0x1d, 0x25, 0x14, 0x2f, 0x21, 0xc0, 0x26, 0xe6, 0xce, + 0x1a, 0xd6, 0xf8, 0x00, 0x02, 0x08, 0x0d, 0xee, 0x17, 0xff, 0xbf, 0xeb, 0x3b, + 0xf5, 0x1c, 0xe0, 0xe6, 0x2d, 0x05, 0xb6, 0xe2, 0xef, 0x3a, 0xfa, 0x29, 0x70, + 0xda, 0xc2, 0xc1, 0xd5, 0x0a, 0x43, 0x15, 0xfe, 0xeb, 0x0c, 0xc5, 0xca, 0x2d, + 0xf8, 0x05, 0xf3, 0xf2, 0xfb, 0x3d, 0xf9, 0x35, 0x03, 0xee, 0xb6, 0x23, 0xd5, + 0xbb, 0xb8, 0xfc, 0xfc, 0xbd, 0xcd, 0x10, 0xb4, 0x0c, 0xfe, 0x1b, 0xf8, 0x12, + 0x12, 0xad, 0xfc, 0xa1, 0xbd, 0x16, 0x39, 0xee, 0xd5, 0xd2, 0xf7, 0xef, 0xd9, + 0xd3, 0xfd, 0x38, 0xf5, 0xde, 0x0f, 0x4c, 0xfd, 0x38, 0x38, 0xdb, 0x1a, 0x2d, + 0xce, 0xff, 0xed, 0x20, 0xe9, 0x1f, 0x23, 0xd3, 0xf8, 0x0c, 0x02, 0xb8, 0xc2, + 0xe6, 0x30, 0x2c, 0x0d, 0xe3, 0x01, 0x0c, 0x23, 0x3a, 0xe4, 0x07, 0x17, 0x31, + 0xe5, 0x17, 0xe8, 0x04, 0xe2, 0x9d, 0xd2, 0xe7, 0x27, 0xf0, 0x11, 0xdd, 0xe5, + 0xda, 0xc4, 0xe9, 0x17, 0xf1, 0x05, 0x17, 0x16, 0x32, 0xb1, 0x2c, 0x1e, 0x18, + 0xbf, 0xf6, 0xe4, 0x22, 0x08, 0xdc, 0x01, 0x1f, 0x7f, 0x02, 0xf2, 0x07, 0xd0, + 0xd7, 0x24, 0x06, 0xff, 0xf2, 0x37, 0x97, 0xe5, 0x0c, 0x0b, 0xf3, 0xcb, 0xd3, + 0xf3, 0xdb, 0x1c, 0x08, 0xe6, 0xfd, 0xda, 0x11, 0xda, 0x18, 0xe3, 0xd8, 0xfb, + 0xfa, 0x13, 0x09, 0x13, 0xfb, 0xe4, 0x12, 0x0a, 0xe0, 0xf7, 0xd3, 0xd3, 0x23, + 0xb8, 0x10, 0xa3, 0xe6, 0xc0, 0xe6, 0xde, 0xed, 0xdf, 0x05, 0xca, 0x16, 0xd2, + 0xe1, 0xfe, 0xd2, 0x30, 0xd7, 0x1b, 0xb6, 0x1a, 0x2a, 0xf5, 0xdc, 0x41, 0xd7, + 0x8a, 0x17, 0x2b, 0xd9, 0xec, 0xba, 0x1d, 0xa5, 0x06, 0x9b, 0x2c, 0x21, 0x18, + 0x9b, 0x1d, 0x1c, 0xc0, 0xe3, 0xce, 0x27, 0x16, 0xa4, 0x4a, 0xe3, 0x97, 0x9b, + 0x0b, 0xf8, 0x16, 0x3b, 0x26, 0x0a, 0xe6, 0xf5, 0x3d, 0x73, 0x2d, 0xfe, 0x00, + 0xc7, 0x41, 0xe6, 0xf7, 0x08, 0x03, 0x07, 0x28, 0x0d, 0xb5, 0xa9, 0xb0, 0xac, + 0x3b, 0xac, 0xd0, 0x32, 0xc8, 0xf9, 0x29, 0xf2, 0x07, 0xd3, 0xc4, 0xf3, 0xf3, + 0xfc, 0x20, 0xea, 0x12, 0xae, 0x84, 0xb1, 0x38, 0xe0, 0x66, 0xb4, 0xc5, 0xc0, + 0xf7, 0xc8, 0xb1, 0x2b, 0xb5, 0xb6, 0xf2, 0x09, 0x04, 0x2d, 0xdd, 0x81, 0xc4, + 0x13, 0xda, 0xf4, 0x06, 0xd5, 0x24, 0x1a, 0x20, 0x07, 0xd6, 0xea, 0xc0, 0xc2, + 0x06, 0xbb, 0xb1, 0xee, 0xdf, 0xff, 0x23, 0xcf, 0xb4, 0xb2, 0xfe, 0xf5, 0x13, + 0x1b, 0xea, 0x23, 0xc5, 0x05, 0x18, 0xa3, 0x00, 0x13, 0xe7, 0x33, 0x03, 0xff, + 0xa7, 0xf4, 0x16, 0x37, 0x68, 0x06, 0xa3, 0xec, 0x0f, 0x1c, 0x53, 0x28, 0xbc, + 0xd2, 0x0f, 0x28, 0x01, 0xe1, 0xdf, 0x7f, 0xb6, 0x26, 0xaf, 0x09, 0xff, 0xe6, + 0xcc, 0xa6, 0xef, 0xfb, 0x23, 0xc4, 0x4d, 0x16, 0xc0, 0x27, 0xdf, 0x93, 0x15, + 0xab, 0x9d, 0xcc, 0xcb, 0x1d, 0xb4, 0xe3, 0xfc, 0xf1, 0xdd, 0x10, 0xce, 0x9e, + 0x12, 0xf5, 0xdc, 0x38, 0xf2, 0x20, 0x4d, 0xac, 0xea, 0xe0, 0x24, 0xaf, 0x31, + 0xe6, 0xb1, 0x25, 0xc7, 0x1d, 0xf8, 0x04, 0xf9, 0x2c, 0xf9, 0xbd, 0xc8, 0xc0, + 0x53, 0x4c, 0xdf, 0x60, 0x05, 0xf3, 0xf3, 0x15, 0xd4, 0x12, 0xbc, 0xdc, 0x35, + 0x00, 0x08, 0xee, 0xb4, 0x20, 0xc2, 0x43, 0xe6, 0x11, 0xf9, 0x24, 0xcc, 0xdd, + 0x1c, 0x19, 0xef, 0x9e, 0x04, 0xfe, 0xf6, 0xc1, 0xd1, 0xf3, 0xf9, 0xe3, 0xf8, + 0x19, 0x39, 0xea, 0x38, 0x07, 0x28, 0x1a, 0x20, 0xca, 0xcf, 0xe8, 0xc2, 0xb4, + 0xe3, 0x33, 0xc8, 0xdd, 0xfb, 0x0a, 0x10, 0x33, 0x0c, 0xc8, 0x51, 0xd7, 0x11, + 0xcd, 0xc7, 0x0a, 0xf7, 0x3f, 0x26, 0x03, 0xf3, 0xec, 0x10, 0x16, 0xce, 0xee, + 0xf0, 0x03, 0x1f, 0xee, 0xe7, 0x0e, 0x43, 0xe9, 0xfb, 0xfe, 0xef, 0xc0, 0xc7, + 0x04, 0x06, 0x11, 0x18, 0xc4, 0xbd, 0x09, 0x06, 0xf4, 0x11, 0xdd, 0xde, 0x32, + 0x95, 0xa5, 0x07, 0x11, 0xe1, 0x03, 0x39, 0xea, 0x27, 0xef, 0xcf, 0x00, 0xc8, + 0xf0, 0x12, 0xf1, 0xf1, 0xe1, 0x2f, 0xbd, 0x59, 0x13, 0xc2, 0x0a, 0x24, 0xa8, + 0x36, 0x08, 0x3a, 0xde, 0xbb, 0xea, 0x24, 0x46, 0xfc, 0xd5, 0x12, 0xdb, 0xdd, + 0xe6, 0x21, 0xea, 0x00, 0xac, 0x25, 0x07, 0xfc, 0x0f, 0xec, 0xbe, 0xf0, 0x22, + 0xec, 0x0a, 0x3b, 0x1c, 0x30, 0x02, 0x2f, 0x4d, 0x19, 0xf6, 0xe8, 0x25, 0x24, + 0xe7, 0xc0, 0x1c, 0xa5, 0x27, 0x96, 0x1f, 0xd7, 0xf9, 0x2d, 0x16, 0x41, 0x22, + 0xe5, 0xdd, 0xf0, 0xec, 0x27, 0x09, 0x20, 0xf6, 0x14, 0x38, 0xdf, 0xc5, 0xf7, + 0x19, 0x25, 0x14, 0xd7, 0x28, 0xbf, 0xd5, 0xcb, 0x05, 0x50, 0xff, 0xed, 0x13, + 0xfe, 0xb7, 0xc9, 0xbc, 0x25, 0xd1, 0xeb, 0xd1, 0x55, 0xba, 0xef, 0x15, 0x51, + 0x03, 0xe7, 0xea, 0xb7, 0x09, 0xe9, 0x22, 0x37, 0xe2, 0x39, 0xd2, 0xe8, 0xe7, + 0x15, 0xac, 0x2f, 0xfa, 0x01, 0xdb, 0x49, 0xe4, 0xea, 0xda, 0xc9, 0xce, 0xfb, + 0xe1, 0x10, 0xe9, 0x14, 0xc3, 0x13, 0xd4, 0x46, 0xaa, 0x65, 0xe7, 0xb5, 0xf1, + 0xef, 0xfa, 0x37, 0x10, 0x02, 0xba, 0xee, 0xd4, 0xed, 0x33, 0x81, 0xcd, 0xb6, + 0x47, 0x0c, 0x10, 0xd2, 0x54, 0xe7, 0x0e, 0xe0, 0xe4, 0xf5, 0x02, 0x00, 0x0f, + 0xd7, 0xb5, 0x14, 0xff, 0xef, 0xdf, 0xfd, 0x03, 0xe9, 0x3d, 0xe1, 0xd3, 0x7f, + 0xfc, 0xeb, 0xf8, 0x9a, 0xe3, 0xf0, 0x2a, 0xef, 0xf2, 0xfe, 0x43, 0xde, 0xec, + 0xfb, 0xd2, 0xff, 0xe4, 0x1c, 0x04, 0xe6, 0x0a, 0x16, 0xec, 0xc7, 0x9d, 0xfc, + 0x0e, 0x2c, 0xcd, 0xc3, 0xed, 0xf1, 0x15, 0xf5, 0x05, 0xef, 0x27, 0x21, 0xef, + 0xda, 0xfc, 0x1d, 0x26, 0x28, 0x15, 0xff, 0x0d, 0xdf, 0x1e, 0x06, 0xe2, 0xba, + 0x28, 0xec, 0x04, 0xee, 0x04, 0x21, 0xff, 0x01, 0x1d, 0x15, 0xd3, 0x26, 0xf5, + 0xdf, 0x37, 0x06, 0xf2, 0x1a, 0xe7, 0x45, 0xf9, 0xfa, 0x2a, 0x25, 0xd8, 0x12, + 0xd3, 0x07, 0x1c, 0xe1, 0xfb, 0x00, 0xee, 0xdd, 0x27, 0x1f, 0xd9, 0xed, 0x14, + 0xf5, 0x1a, 0xcd, 0x3c, 0xfa, 0x1b, 0x00, 0xe2, 0xf4, 0xe2, 0x10, 0xdd, 0x17, + 0xd3, 0x15, 0xcd, 0x3d, 0x5c, 0xc4, 0x04, 0x03, 0xde, 0xed, 0xef, 0xeb, 0xe4, + 0xf7, 0x15, 0xbf, 0xe8, 0xee, 0xec, 0x05, 0x0a, 0xe1, 0x24, 0x26, 0xde, 0x09, + 0xfb, 0x2a, 0xf0, 0x29, 0xde, 0x09, 0xea, 0xf5, 0xdc, 0xf0, 0xfd, 0xfd, 0xbd, + 0xfa, 0xe1, 0x30, 0xc5, 0x08, 0xc6, 0xf5, 0xca, 0xfd, 0xea, 0xd4, 0xde, 0xe7, + 0xe7, 0x0a, 0xdf, 0xf1, 0xe4, 0xe9, 0x01, 0x04, 0xf9, 0xd8, 0x3c, 0xe6, 0xe3, + 0xeb, 0xe4, 0x22, 0xec, 0xdf, 0x15, 0x24, 0x07, 0x23, 0xff, 0x18, 0xf7, 0x0a, + 0xb7, 0xe5, 0x28, 0xe6, 0x0f, 0x0b, 0x06, 0xf8, 0xdc, 0x00, 0x20, 0xf4, 0xcb, + 0x06, 0xf6, 0xfe, 0xfb, 0xd3, 0xc2, 0x0b, 0x47, 0x05, 0x0c, 0x22, 0x07, 0x06, + 0xec, 0x1f, 0xe1, 0xfc, 0x08, 0xdf, 0xb6, 0xf1, 0x0b, 0x05, 0xf6, 0x38, 0x00, + 0xeb, 0x07, 0xcd, 0x19, 0x29, 0xda, 0xed, 0xfa, 0xfe, 0x39, 0xa8, 0xc1, 0x19, + 0xd9, 0xdf, 0x23, 0xec, 0x2a, 0xfc, 0x0a, 0x00, 0xc1, 0x26, 0xb7, 0xfe, 0xbd, + 0xf6, 0x48, 0x0a, 0xd6, 0xe3, 0xd5, 0xe0, 0x1a, 0xf3, 0x0e, 0x00, 0x19, 0x22, + 0xf8, 0xcf, 0x22, 0x04, 0xbf, 0xeb, 0x08, 0xee, 0xbb, 0xfd, 0xf6, 0xd9, 0x30, + 0x26, 0xd0, 0xe7, 0x01, 0x07, 0xee, 0x1f, 0x07, 0xf8, 0xb1, 0x41, 0x00, 0x17, + 0xb9, 0xd2, 0xeb, 0xce, 0x0b, 0xea, 0xe5, 0xf0, 0xd7, 0x1d, 0x10, 0xe8, 0x23, + 0x02, 0xdb, 0x25, 0x06, 0xdf, 0xe0, 0xf9, 0xec, 0xf1, 0xe1, 0xee, 0xfd, 0xea, + 0xde, 0xfe, 0x03, 0xd1, 0xe5, 0xd9, 0xfb, 0xed, 0x01, 0xe2, 0x1a, 0x02, 0x1a, + 0x31, 0xc8, 0x1b, 0x3c, 0xf5, 0xe2, 0xfd, 0x0d, 0x31, 0xec, 0x30, 0xb9, 0x3f, + 0xc8, 0xe7, 0x0a, 0x0f, 0xee, 0xea, 0xfd, 0xfd, 0x04, 0x01, 0x05, 0x27, 0xff, + 0xee, 0x00, 0xef, 0xd1, 0xc1, 0xde, 0x11, 0xf2, 0xe0, 0x0a, 0xbe, 0xed, 0x20, + 0x09, 0x08, 0xed, 0xd4, 0xc7, 0x08, 0x05, 0xcc, 0x00, 0xcf, 0xd3, 0x0d, 0x07, + 0x24, 0xc8, 0x0e, 0xe8, 0x4e, 0x41, 0xf1, 0xdf, 0xd8, 0xc5, 0x30, 0xfc, 0x12, + 0xf4, 0xfd, 0xdd, 0x23, 0x34, 0xf1, 0x18, 0xef, 0x20, 0x01, 0x01, 0x10, 0x04, + 0x03, 0x14, 0xf8, 0x0b, 0xcf, 0xfd, 0x35, 0xff, 0xf3, 0x0c, 0x0a, 0xc0, 0xb9, + 0xf9, 0x2d, 0x0f, 0xe0, 0x24, 0xef, 0x26, 0xae, 0xde, 0xdc, 0xf4, 0x1a, 0xe3, + 0x25, 0xfb, 0xd5, 0x1b, 0x22, 0xf7, 0x17, 0x1c, 0xb8, 0x40, 0xb7, 0xf0, 0xe1, + 0x09, 0x1c, 0xc3, 0xdf, 0xd1, 0xc9, 0xd6, 0xf2, 0xf6, 0x07, 0xd6, 0x0c, 0xd7, + 0xbb, 0xe5, 0xbd, 0xd6, 0xdf, 0xf9, 0x04, 0x17, 0xe2, 0xda, 0x1a, 0x45, 0x1c, + 0xd6, 0xe7, 0x0c, 0xdd, 0x14, 0x1a, 0xcf, 0x0f, 0xd1, 0xe3, 0xef, 0xd8, 0x27, + 0x16, 0xe3, 0xd1, 0xc9, 0x0e, 0xf9, 0xfb, 0xd9, 0x81, 0x13, 0xeb, 0x01, 0xe5, + 0x26, 0xee, 0x7f, 0xcf, 0xc3, 0xe0, 0xc1, 0x20, 0xd6, 0x01, 0xdf, 0x27, 0xfb, + 0xe9, 0x10, 0xb8, 0xfa, 0xda, 0x15, 0xb8, 0xe7, 0xc9, 0xeb, 0xbf, 0x03, 0xea, + 0xed, 0x11, 0xe5, 0x0f, 0xc5, 0xee, 0xe6, 0xa5, 0x03, 0x0a, 0x0e, 0x11, 0x24, + 0xdd, 0x11, 0xdc, 0x1c, 0xe1, 0xc5, 0x19, 0xf0, 0xd7, 0xdb, 0xdc, 0xc4, 0xec, + 0x10, 0x60, 0x3d, 0x25, 0x06, 0xf2, 0xee, 0x05, 0x23, 0xf3, 0xf4, 0xfb, 0xfb, + 0xb8, 0xfb, 0x02, 0xd3, 0x16, 0xae, 0xca, 0xfe, 0xa2, 0xfd, 0x16, 0xd2, 0xbe, + 0xec, 0xe6, 0xb0, 0xb9, 0xe5, 0x03, 0x07, 0x14, 0xa9, 0x25, 0xee, 0xc6, 0x1e, + 0xf5, 0xb1, 0xc5, 0xdb, 0xfb, 0xd5, 0x49, 0xda, 0x2e, 0xf1, 0xe7, 0x08, 0xe0, + 0xe4, 0xc2, 0xbf, 0xdd, 0x0a, 0xd5, 0xf1, 0xe3, 0xc1, 0x01, 0x42, 0xdc, 0xe4, + 0xfd, 0xfa, 0xd6, 0xd7, 0xcb, 0x37, 0xc3, 0xf1, 0xd8, 0x07, 0xbc, 0x21, 0xf8, + 0xc8, 0xc7, 0xf2, 0x38, 0xe6, 0xc4, 0xc3, 0x0a, 0xff, 0xb9, 0xf4, 0xc5, 0xda, + 0xc4, 0xf9, 0x3d, 0x00, 0x0d, 0x1c, 0x06, 0xfa, 0x35, 0x2e, 0xe8, 0xec, 0x05, + 0x04, 0x15, 0x26, 0xc0, 0xde, 0x23, 0xda, 0x23, 0xd7, 0x12, 0xa9, 0xf5, 0x36, + 0xfb, 0xc1, 0xe6, 0xaa, 0xf4, 0xfb, 0x1b, 0xd3, 0x1b, 0xea, 0xd0, 0xc7, 0x03, + 0xd4, 0x30, 0x0c, 0x0d, 0xed, 0x16, 0xf5, 0xd2, 0xc2, 0xf8, 0xe7, 0xd1, 0xa7, + 0xef, 0x07, 0xe4, 0xf5, 0x25, 0x2e, 0xd1, 0x58, 0xef, 0x15, 0xfe, 0x1d, 0xe7, + 0x14, 0xfe, 0x05, 0xda, 0xfc, 0x1a, 0x09, 0x95, 0xca, 0xe8, 0x0d, 0xce, 0x06, + 0x1a, 0x13, 0x1c, 0x05, 0x0c, 0x28, 0x02, 0x39, 0xe6, 0xc0, 0xe1, 0x02, 0xbf, + 0x36, 0x30, 0xf9, 0x1c, 0xc5, 0xa8, 0xff, 0xd0, 0x2d, 0xff, 0xf1, 0x0e, 0xf1, + 0x05, 0xfb, 0xd4, 0xf4, 0x24, 0x09, 0xec, 0x18, 0xf2, 0xfa, 0xe8, 0x11, 0xbb, + 0x41, 0xce, 0xbb, 0xd5, 0xf1, 0x01, 0x34, 0x16, 0xc3, 0xec, 0xfb, 0xbd, 0x61, + 0xd6, 0x20, 0xdb, 0xd9, 0xf9, 0xb1, 0xff, 0x03, 0x4a, 0x14, 0x31, 0xe8, 0xe5, + 0x14, 0xd0, 0xe6, 0xb3, 0x8c, 0x5e, 0xc3, 0x0e, 0xc4, 0xfd, 0x98, 0xf8, 0xfe, + 0x42, 0xa4, 0x1e, 0x16, 0xee, 0x15, 0xc9, 0xee, 0xe6, 0x31, 0x1e, 0xea, 0x53, + 0x2e, 0x81, 0x1b, 0xb6, 0xe6, 0x14, 0x28, 0xe4, 0x4f, 0x1f, 0x28, 0x11, 0xd6, + 0xd5, 0x5e, 0x39, 0x07, 0x1d, 0xdc, 0xb5, 0xea, 0xfe, 0x2b, 0x35, 0x54, 0xc3, + 0xba, 0x32, 0xec, 0xe9, 0xc3, 0x29, 0x13, 0xcc, 0xc4, 0xf8, 0x37, 0xbf, 0x85, + 0xb4, 0xcd, 0x23, 0xf4, 0xa4, 0xeb, 0xdc, 0x20, 0x48, 0x0b, 0xce, 0x03, 0x0d, + 0xf7, 0xdb, 0x93, 0x0d, 0xfd, 0xaf, 0x1c, 0x32, 0x24, 0x07, 0x0e, 0xb5, 0x3e, + 0x2a, 0xdc, 0x43, 0xe9, 0xe7, 0x1a, 0x1b, 0xe4, 0x28, 0x12, 0xf3, 0x28, 0xd1, + 0xc6, 0xfa, 0x18, 0xe8, 0x21, 0xef, 0x88, 0xea, 0xe8, 0xe2, 0x9b, 0xca, 0xdb, + 0x57, 0x0d, 0x07, 0x94, 0xf2, 0x2e, 0x9e, 0xda, 0xb6, 0x2c, 0x2d, 0xf6, 0xfa, + 0xba, 0x3f, 0xd9, 0x6c, 0x23, 0x06, 0x2d, 0xff, 0xfe, 0x27, 0x11, 0x1f, 0x13, + 0x1a, 0xd2, 0x1f, 0x99, 0xd9, 0xb0, 0xe7, 0xe4, 0xb2, 0x2c, 0xb0, 0xce, 0xcf, + 0x4a, 0x41, 0xbf, 0xb8, 0xd5, 0x93, 0xed, 0x55, 0xbe, 0x05, 0xed, 0xf1, 0x2b, + 0x27, 0x49, 0xcf, 0x05, 0x07, 0xd6, 0x21, 0x1b, 0xf3, 0xcc, 0x0c, 0xa9, 0x26, + 0x32, 0xd0, 0x1d, 0xc6, 0x18, 0x0c, 0x15, 0x08, 0xba, 0x19, 0xb9, 0xe7, 0xe4, + 0x42, 0x35, 0x11, 0xe2, 0xea, 0x05, 0xe9, 0x10, 0xb0, 0xd3, 0xe8, 0x25, 0x28, + 0xbf, 0xc5, 0xe9, 0x09, 0xd5, 0xed, 0x0d, 0x98, 0x22, 0xf0, 0x50, 0x0a, 0x26, + 0x33, 0x0e, 0xff, 0xca, 0xe0, 0x17, 0xd6, 0xe9, 0xf0, 0x1e, 0x02, 0x1d, 0xd1, + 0xfd, 0xe3, 0x1c, 0xfe, 0xe2, 0x42, 0xb2, 0x2f, 0x48, 0x07, 0xec, 0xb1, 0xb7, + 0x00, 0x88, 0x23, 0xd5, 0x21, 0xa2, 0x18, 0xd8, 0x81, 0xef, 0x0b, 0xf8, 0x01, + 0x25, 0x14, 0x3d, 0xc3, 0x00, 0x03, 0x0f, 0x42, 0xa1, 0x3a, 0xc3, 0x3b, 0xb8, + 0x4e, 0xdb, 0xf4, 0xf4, 0xfe, 0xea, 0x1b, 0x23, 0xc1, 0x23, 0x1a, 0x3b, 0xcc, + 0x22, 0x1d, 0x0c, 0x8c, 0xdd, 0xf5, 0xca, 0xed, 0xf8, 0xef, 0xf3, 0x1c, 0x2a, + 0xd3, 0xc0, 0xc9, 0xdc, 0xeb, 0x11, 0xeb, 0xe7, 0xc5, 0xcb, 0x02, 0xff, 0xfe, + 0xb9, 0xe3, 0xf3, 0x22, 0x4f, 0x10, 0xfb, 0x37, 0x0e, 0x2d, 0x1f, 0xc7, 0x1e, + 0xce, 0x1d, 0xfd, 0x12, 0x86, 0x39, 0xcd, 0xc5, 0x33, 0xce, 0xc3, 0x45, 0x11, + 0x24, 0x9f, 0x1b, 0xd0, 0x24, 0xf6, 0x22, 0xb7, 0x30, 0xc7, 0xb8, 0x2a, 0xef, + 0x02, 0x3d, 0x5c, 0x15, 0x60, 0xf2, 0xc6, 0xe3, 0xd5, 0x05, 0xc2, 0x0e, 0xe2, + 0xb2, 0xc6, 0x2e, 0xf4, 0xef, 0x0f, 0x98, 0xc4, 0xce, 0x1f, 0xe6, 0xd2, 0xaa, + 0xf2, 0x46, 0xc6, 0xe5, 0x62, 0x3f, 0xcc, 0x4f, 0xe9, 0xdf, 0x16, 0xed, 0x53, + 0xb6, 0xf3, 0xde, 0xc3, 0x89, 0x32, 0xc7, 0xe5, 0x04, 0x09, 0x2c, 0x07, 0xc0, + 0xe0, 0x4a, 0x31, 0x41, 0xdc, 0xb2, 0xbe, 0xc4, 0x3f, 0xf1, 0x09, 0xb0, 0x0f, + 0x42, 0x0c, 0x15, 0x26, 0xd6, 0xad, 0x29, 0xcc, 0x98, 0xb1, 0xe9, 0xd6, 0xf7, + 0xa8, 0xe4, 0xe4, 0x0a, 0xd2, 0x1c, 0xdf, 0xbe, 0xa9, 0xeb, 0x09, 0xdf, 0x2e, + 0x13, 0x31, 0x0a, 0x37, 0xad, 0x3c, 0xcb, 0xf3, 0x37, 0xe9, 0xe8, 0x3d, 0xae, + 0x14, 0xf2, 0xef, 0xe6, 0x18, 0x00, 0xc6, 0xc3, 0xe3, 0xf3, 0xcd, 0xb0, 0xee, + 0x28, 0x19, 0x4b, 0xb1, 0xd4, 0x2b, 0x0a, 0xe5, 0x05, 0x05, 0xee, 0xfb, 0xfa, + 0x23, 0xeb, 0x01, 0xf1, 0xe5, 0x1c, 0xe5, 0xd1, 0xb9, 0xeb, 0x18, 0xe1, 0x02, + 0xe6, 0x24, 0x24, 0xd6, 0xf3, 0x0b, 0x27, 0xfa, 0xe6, 0xce, 0xfe, 0xe9, 0xf3, + 0xe3, 0x06, 0x0d, 0x0d, 0xf4, 0x3f, 0xf6, 0xdc, 0x27, 0xd2, 0xf7, 0xd8, 0x01, + 0xe9, 0x05, 0x15, 0xf6, 0x17, 0xfd, 0x1d, 0x08, 0xcd, 0xf5, 0xfb, 0x06, 0x0d, + 0x08, 0xe0, 0x37, 0x20, 0x0b, 0x16, 0xfc, 0x29, 0x09, 0xdc, 0x16, 0xdc, 0x14, + 0x1a, 0x51, 0xc2, 0x58, 0x05, 0x16, 0xf9, 0x11, 0xee, 0x14, 0xd7, 0x22, 0x19, + 0xd3, 0xfc, 0xf3, 0x00, 0x44, 0xe5, 0xff, 0xea, 0xe5, 0x13, 0xd3, 0xee, 0xe9, + 0x0e, 0xf6, 0xdc, 0x49, 0xe1, 0xf9, 0x12, 0xe3, 0xcb, 0x04, 0xe0, 0xe1, 0x15, + 0xe9, 0xeb, 0x08, 0x01, 0x02, 0xda, 0x04, 0xf5, 0x13, 0xfd, 0xec, 0x1c, 0xdb, + 0x16, 0xed, 0xf8, 0xcc, 0x0f, 0xd2, 0x3d, 0x0e, 0xd6, 0x1d, 0x1b, 0x13, 0x19, + 0x13, 0x03, 0xf3, 0x1c, 0x24, 0x25, 0x4d, 0xc2, 0xc8, 0x00, 0xbf, 0x27, 0x18, + 0x15, 0x28, 0x02, 0x1a, 0x06, 0xe9, 0xde, 0x0e, 0x2a, 0xfe, 0x03, 0x10, 0x36, + 0xe4, 0xd6, 0xec, 0x0f, 0x0e, 0xf7, 0xd1, 0xe5, 0x12, 0xf5, 0xcf, 0x46, 0x12, + 0xd2, 0xd6, 0x10, 0x01, 0x7f, 0x0b, 0xd1, 0x22, 0xd6, 0xf7, 0xe4, 0xdf, 0xe6, + 0xf4, 0xda, 0xd5, 0xf3, 0x2f, 0xe2, 0x18, 0x09, 0xd2, 0xdb, 0xe2, 0x1c, 0xf5, + 0xd7, 0x1c, 0xed, 0xe2, 0xff, 0xb5, 0x38, 0xd7, 0xf6, 0xbc, 0x2b, 0x06, 0xc5, + 0xea, 0x14, 0xf3, 0xb7, 0xfa, 0xfe, 0x20, 0x12, 0xe8, 0x27, 0xd1, 0xf4, 0xdc, + 0xf3, 0xf1, 0xfb, 0x37, 0x29, 0xfc, 0x0d, 0xc5, 0xfc, 0xcd, 0x1d, 0xff, 0xc4, + 0xd4, 0xc5, 0x25, 0xf9, 0x16, 0x0a, 0x18, 0xfc, 0x08, 0x03, 0xd9, 0xf3, 0xe1, + 0xfc, 0xea, 0x06, 0x19, 0xe5, 0x05, 0xfe, 0x01, 0xe6, 0xfc, 0x1f, 0x24, 0xd9, + 0x10, 0xfc, 0xfc, 0xe5, 0xd8, 0x30, 0x10, 0xcc, 0x04, 0xd7, 0xe5, 0xad, 0x0a, + 0xf4, 0xfc, 0x21, 0xb5, 0x16, 0x03, 0x30, 0x1f, 0x3f, 0xfa, 0xe1, 0x3b, 0xf2, + 0xc1, 0xe1, 0xe1, 0x0c, 0x15, 0xe7, 0xee, 0x19, 0xfd, 0x38, 0xef, 0xfc, 0xf4, + 0xf0, 0x0e, 0xf8, 0x2d, 0xdb, 0xc9, 0xeb, 0x18, 0x48, 0x1d, 0x14, 0xd6, 0x2e, + 0xd9, 0x27, 0xaf, 0x2a, 0xe6, 0xe1, 0xe8, 0x07, 0x2d, 0xff, 0xe7, 0xd8, 0xcf, + 0xc6, 0x09, 0x29, 0xd9, 0x0d, 0xd2, 0xe3, 0x3f, 0xbe, 0x09, 0xf5, 0x0d, 0x02, + 0xea, 0x14, 0xfc, 0xe9, 0x01, 0xb3, 0x04, 0x1d, 0xf1, 0xfc, 0xe0, 0x36, 0x39, + 0xff, 0xa9, 0xfc, 0xdb, 0x04, 0x09, 0x23, 0xf0, 0x28, 0xca, 0xd6, 0xed, 0x08, + 0xf0, 0x97, 0xf3, 0xec, 0xf4, 0x50, 0x0e, 0x56, 0xff, 0xe5, 0x20, 0xf7, 0xcb, + 0xf0, 0x13, 0xf4, 0xfa, 0x0f, 0x23, 0x7f, 0x0f, 0x04, 0xe0, 0x2e, 0xff, 0xd5, + 0xbd, 0x09, 0xe6, 0x11, 0x27, 0xfc, 0xb6, 0xfd, 0xa8, 0xd8, 0xe8, 0xf1, 0x08, + 0xc1, 0xdb, 0x1a, 0x00, 0xf1, 0x2c, 0xc1, 0xf5, 0xad, 0x10, 0x05, 0xe9, 0x07, + 0xed, 0xca, 0xdb, 0xd8, 0x13, 0xd9, 0x0c, 0x09, 0xe2, 0xe6, 0xd4, 0x25, 0x17, + 0xff, 0x17, 0xf0, 0x50, 0xfb, 0x04, 0x18, 0xdd, 0xef, 0x21, 0xd0, 0xfc, 0xe9, + 0xe3, 0xfe, 0xc1, 0xf0, 0x24, 0xfd, 0x0f, 0x05, 0x08, 0xef, 0xf7, 0x1c, 0xd4, + 0xce, 0xff, 0xb1, 0xdf, 0x16, 0x05, 0xf0, 0xd8, 0xe3, 0xf6, 0xe9, 0x1a, 0x1a, + 0xf8, 0xfd, 0xe5, 0xc1, 0x1d, 0x03, 0x0a, 0xd0, 0xf6, 0xf6, 0x16, 0x27, 0xe8, + 0x04, 0x3c, 0xd3, 0xba, 0xc8, 0x35, 0x29, 0x14, 0x17, 0x03, 0xeb, 0xca, 0x44, + 0xee, 0xe4, 0xb4, 0x0e, 0x16, 0x16, 0x0b, 0xfc, 0xd5, 0x04, 0xea, 0x19, 0xdd, + 0xe5, 0x11, 0x23, 0x18, 0x36, 0xe9, 0xb7, 0xfd, 0x2f, 0x1e, 0x8c, 0xbf, 0x4b, + 0x17, 0xba, 0xe8, 0xef, 0x0f, 0xaf, 0xc8, 0x11, 0xdf, 0x13, 0x98, 0x29, 0x20, + 0x12, 0x4c, 0xe9, 0x9c, 0x28, 0x18, 0xc9, 0x24, 0xf5, 0xf5, 0xe3, 0x9b, 0x21, + 0x19, 0xe1, 0xd0, 0xb5, 0xf7, 0x41, 0x0a, 0xef, 0x88, 0xd0, 0xe5, 0xc1, 0xf0, + 0xfc, 0xca, 0xc6, 0x06, 0xf0, 0xea, 0x21, 0xf2, 0x1e, 0xd5, 0xc3, 0xf6, 0xfb, + 0x09, 0x01, 0x9a, 0x13, 0x04, 0xb0, 0xbb, 0x0b, 0x18, 0x05, 0xa0, 0x01, 0xcc, + 0xe3, 0x45, 0x81, 0xae, 0x28, 0x98, 0xe3, 0x8a, 0x1c, 0x6b, 0xe6, 0xca, 0xf9, + 0x1d, 0xe7, 0x08, 0x1a, 0xcd, 0xda, 0x58, 0x4c, 0x0f, 0xa9, 0xf1, 0x16, 0x08, + 0xa6, 0x47, 0x05, 0xd5, 0x17, 0xfc, 0x39, 0x31, 0xe1, 0x5f, 0x12, 0x5f, 0x00, + 0xf0, 0xac, 0xe5, 0x29, 0xbc, 0xec, 0xf2, 0x11, 0x07, 0x33, 0x0e, 0x19, 0x1e, + 0xbb, 0x29, 0xfc, 0xc4, 0xb3, 0x41, 0x59, 0x15, 0xe4, 0x64, 0x57, 0xf0, 0xb7, + 0xeb, 0xef, 0x00, 0xad, 0xc7, 0x19, 0xdb, 0xed, 0x15, 0xdc, 0xfa, 0xeb, 0xde, + 0x26, 0xd2, 0x0c, 0x8b, 0xf0, 0x3b, 0x04, 0xed, 0xee, 0x1d, 0xe9, 0xe6, 0x23, + 0xe3, 0x34, 0x34, 0x07, 0x4f, 0x3e, 0x08, 0xa5, 0xa9, 0x3f, 0xe6, 0x0a, 0xeb, + 0xd6, 0xd6, 0xf0, 0xe4, 0x09, 0x97, 0xec, 0x41, 0xd5, 0x04, 0xe0, 0xf3, 0x04, + 0xfe, 0x10, 0xc9, 0x07, 0x86, 0xfc, 0x55, 0xc4, 0xe6, 0xf9, 0x1a, 0x57, 0x4e, + 0xd5, 0xd5, 0xd6, 0xe8, 0x07, 0x1a, 0xe4, 0x01, 0xb0, 0xe2, 0x83, 0xff, 0xee, + 0xb2, 0xf4, 0x2f, 0xc0, 0x17, 0x52, 0x39, 0x0b, 0x0a, 0x08, 0x24, 0xe5, 0xfc, + 0x20, 0x35, 0x81, 0x2c, 0x4d, 0x3a, 0x33, 0x2c, 0x15, 0x14, 0x93, 0xb8, 0x29, + 0xff, 0x08, 0x50, 0xd8, 0xc2, 0xb6, 0xd6, 0x3b, 0xc6, 0x13, 0xe4, 0x12, 0xfb, + 0xcf, 0x29, 0x33, 0x11, 0x10, 0xf2, 0x1f, 0x1a, 0xe6, 0xb2, 0x0c, 0x0e, 0x1f, + 0x0a, 0x1a, 0x14, 0xde, 0x03, 0xec, 0xed, 0x28, 0xe4, 0xbe, 0x0d, 0xaf, 0x1a, + 0x10, 0xe5, 0xe7, 0x03, 0xfd, 0xb7, 0xe6, 0xd5, 0xff, 0x0a, 0x15, 0x06, 0xca, + 0xe3, 0x07, 0xe9, 0xc3, 0xae, 0xe5, 0x11, 0x31, 0x1a, 0xfd, 0x38, 0x09, 0xe4, + 0x02, 0xe3, 0xec, 0xd6, 0x1f, 0xae, 0xed, 0xe3, 0x00, 0xc9, 0xfe, 0xd1, 0xf5, + 0x00, 0xf7, 0xf1, 0x04, 0x14, 0x05, 0xed, 0x3a, 0xfd, 0xf1, 0xea, 0xec, 0x31, + 0x41, 0x1f, 0x21, 0xf7, 0xbc, 0x3e, 0xea, 0x39, 0x01, 0x05, 0x09, 0x0e, 0xd9, + 0x22, 0xfb, 0xef, 0x04, 0x42, 0x22, 0x02, 0xc5, 0xc7, 0x1a, 0x1a, 0x0a, 0xed, + 0xfd, 0x14, 0xf7, 0xf2, 0x0d, 0xf4, 0xc3, 0x1f, 0x27, 0xe7, 0xd9, 0xdd, 0x04, + 0x20, 0x02, 0x7f, 0xb3, 0xc0, 0xcf, 0xe2, 0xd1, 0x0c, 0x07, 0xe0, 0x6d, 0x12, + 0x28, 0xf5, 0x1c, 0x18, 0x1f, 0xf6, 0xfe, 0xb9, 0xf2, 0xfa, 0xda, 0xa9, 0xeb, + 0xd9, 0xe3, 0x1d, 0x08, 0xd0, 0xcc, 0x1c, 0xd7, 0x30, 0xea, 0x09, 0xed, 0xe5, + 0x04, 0x1d, 0x14, 0xdb, 0x1c, 0x1d, 0xf8, 0xfd, 0xe0, 0x14, 0x05, 0xcd, 0xd4, + 0xdb, 0xbc, 0x02, 0xf2, 0xf2, 0x00, 0xd5, 0xf4, 0x07, 0x29, 0xe4, 0xfc, 0x01, + 0x35, 0xd8, 0xd3, 0xd4, 0xeb, 0x3e, 0xee, 0xd5, 0x0a, 0xd1, 0x0c, 0x0a, 0x10, + 0x2c, 0xf1, 0x0d, 0xeb, 0xdc, 0xff, 0xe9, 0xd2, 0x02, 0x14, 0xf0, 0xae, 0x22, + 0x06, 0xd6, 0xf4, 0x30, 0xc5, 0xd4, 0xcc, 0x19, 0x05, 0x18, 0xe0, 0xc6, 0x15, + 0x0e, 0xea, 0xf9, 0x11, 0x3b, 0xe8, 0x60, 0x15, 0xfe, 0xec, 0xfb, 0x24, 0xe1, + 0xf8, 0x1a, 0x14, 0x12, 0xea, 0x23, 0xce, 0xe0, 0xe3, 0x0e, 0x32, 0x51, 0x05, + 0x26, 0x06, 0x06, 0x4c, 0xde, 0xeb, 0xf0, 0xdf, 0xf1, 0x02, 0x1f, 0x3a, 0x1b, + 0x3d, 0xd7, 0xcc, 0x0c, 0xd4, 0xe3, 0xef, 0x08, 0xed, 0xaa, 0x15, 0xb3, 0x19, + 0xe6, 0xbb, 0x2b, 0x1d, 0xde, 0x2d, 0x01, 0xbd, 0xe5, 0xfa, 0x10, 0xba, 0x1a, + 0xec, 0xe9, 0xb5, 0x17, 0x1f, 0xd5, 0x19, 0xd8, 0x3a, 0x1c, 0xe0, 0xb8, 0x07, + 0xe4, 0x14, 0x38, 0xeb, 0x06, 0xfe, 0xc5, 0xee, 0xf8, 0xa6, 0x08, 0xff, 0xf2, + 0x00, 0xd4, 0xe2, 0x2c, 0xfe, 0x28, 0x2a, 0x17, 0xa0, 0x05, 0xe9, 0xf9, 0xb6, + 0x15, 0xef, 0x06, 0x27, 0xfa, 0x17, 0xda, 0xe1, 0x18, 0xd0, 0xb8, 0x58, 0xaf, + 0xf6, 0xdd, 0xf6, 0x2f, 0x05, 0x0f, 0xe1, 0x38, 0xfd, 0x06, 0xd2, 0x05, 0xb4, + 0x00, 0xd6, 0x02, 0x01, 0x27, 0x8b, 0x06, 0xdb, 0xfa, 0x10, 0x4c, 0xe8, 0x02, + 0xa1, 0x16, 0xf8, 0xe8, 0xdd, 0xf4, 0xa5, 0xcd, 0xab, 0xf8, 0xf7, 0x09, 0xc2, + 0x18, 0x2f, 0x10, 0xd6, 0xd3, 0x40, 0xea, 0x33, 0xd2, 0xec, 0x08, 0xf4, 0x01, + 0x03, 0xe3, 0x1f, 0xc5, 0xe5, 0x7f, 0xd7, 0xe1, 0x16, 0x0c, 0x0d, 0xb1, 0xf3, + 0x3e, 0xed, 0xc9, 0xd8, 0xf9, 0x72, 0x08, 0x9a, 0xea, 0xf9, 0x2f, 0x4d, 0xd7, + 0xc5, 0x0a, 0xe2, 0xe2, 0xb8, 0x54, 0xd2, 0xe0, 0x16, 0x0b, 0xeb, 0x13, 0xe0, + 0x2a, 0xbe, 0xce, 0x33, 0x8c, 0xfc, 0xdc, 0x60, 0xdf, 0xe0, 0xed, 0xe5, 0x2b, + 0xd9, 0xbd, 0xd3, 0x2a, 0x26, 0xb1, 0xab, 0x12, 0x9a, 0xc0, 0xd3, 0xb0, 0x12, + 0xd4, 0x17, 0xc6, 0xed, 0xa6, 0xe5, 0x06, 0x09, 0x2a, 0xf5, 0xa9, 0xfc, 0xe1, + 0x5b, 0xd2, 0xfa, 0xed, 0x23, 0x1f, 0xed, 0xb1, 0x11, 0xec, 0x0c, 0x01, 0x01, + 0xcb, 0x25, 0xd8, 0x13, 0x15, 0xf2, 0x1c, 0xee, 0xd4, 0xd8, 0xf6, 0xfe, 0x3d, + 0xde, 0x01, 0xca, 0xc7, 0xe7, 0x9a, 0xd4, 0x15, 0x0d, 0xf9, 0x17, 0xd7, 0xfa, + 0xe6, 0xc0, 0xcc, 0x36, 0x23, 0xeb, 0xf8, 0xe5, 0xd2, 0x1c, 0xd8, 0xdf, 0xb2, + 0xeb, 0xf4, 0xea, 0x1e, 0xfb, 0xdd, 0xfc, 0xf2, 0x1f, 0xe0, 0xfb, 0xd0, 0x26, + 0xef, 0xa5, 0xeb, 0xd2, 0xfb, 0x07, 0x19, 0xfd, 0xee, 0x16, 0x06, 0xd2, 0xee, + 0x0f, 0x21, 0xea, 0x04, 0x20, 0x4b, 0xf0, 0x17, 0x0f, 0x19, 0xfe, 0x3d, 0xdf, + 0xdd, 0xd5, 0xe7, 0x14, 0x00, 0x06, 0x02, 0x11, 0x0d, 0x0e, 0x02, 0xf6, 0xe7, + 0x4a, 0xf0, 0xff, 0xff, 0xb2, 0x28, 0x22, 0x1b, 0xd0, 0x25, 0xd7, 0x03, 0xf9, + 0xfb, 0x0c, 0x05, 0xdf, 0x14, 0x1a, 0x17, 0x34, 0xef, 0x0c, 0x22, 0xf5, 0x0d, + 0xf5, 0x0e, 0x09, 0xdd, 0xfc, 0x42, 0xf7, 0x07, 0xfb, 0xdf, 0xe0, 0xd7, 0x08, + 0xcd, 0xf6, 0xcb, 0xe1, 0xdc, 0x18, 0xf0, 0xee, 0x07, 0x1d, 0x26, 0xd6, 0x10, + 0xf3, 0xf0, 0xd8, 0xf5, 0xf1, 0xc8, 0x23, 0xf4, 0xc1, 0xd4, 0xed, 0x07, 0xcf, + 0x4c, 0x1b, 0x21, 0x34, 0xf3, 0xe3, 0xf4, 0x22, 0xeb, 0xfd, 0x01, 0xcb, 0xfc, + 0xd0, 0xeb, 0x0a, 0x07, 0x20, 0x00, 0x1a, 0xcc, 0x23, 0x31, 0xfa, 0xe6, 0xc3, + 0xf0, 0x08, 0x15, 0xdf, 0xed, 0xf3, 0xf4, 0xf6, 0x17, 0xf9, 0x16, 0xd6, 0xd2, + 0x11, 0x31, 0xdb, 0xfe, 0x1d, 0x13, 0xdf, 0x09, 0x1f, 0x00, 0x7f, 0x20, 0xe1, + 0xff, 0xdd, 0xba, 0xfd, 0xe7, 0xe4, 0xf2, 0x00, 0xda, 0xdf, 0x1e, 0xbd, 0x04, + 0xd1, 0xfd, 0xd1, 0x05, 0xf0, 0xfa, 0xd3, 0xd2, 0xec, 0xcb, 0x28, 0xf4, 0xf9, + 0xf1, 0x08, 0xbb, 0xea, 0x0d, 0x0f, 0x27, 0x10, 0xce, 0x23, 0xe1, 0xec, 0x38, + 0x1a, 0x17, 0xcc, 0x12, 0x17, 0xe2, 0xf4, 0x33, 0xdf, 0xcf, 0x37, 0x1a, 0x0b, + 0xda, 0x12, 0xcb, 0xf4, 0xe4, 0x9a, 0x06, 0xf7, 0x28, 0x00, 0x0b, 0xc4, 0x12, + 0xfd, 0xe0, 0xf9, 0xdc, 0xce, 0xda, 0x12, 0x04, 0x24, 0xfb, 0x18, 0x14, 0x20, + 0xff, 0x13, 0xf2, 0x16, 0xdb, 0xfc, 0xf2, 0x02, 0x2b, 0x00, 0xe4, 0xef, 0x22, + 0xf5, 0xe7, 0x13, 0xf6, 0xe5, 0x19, 0xdf, 0x14, 0x1e, 0xd5, 0xf3, 0xf4, 0xcc, + 0xe0, 0x01, 0xf4, 0xe6, 0xeb, 0x1f, 0x06, 0xed, 0xcf, 0xcd, 0x36, 0xf1, 0x03, + 0x24, 0x0d, 0xf4, 0x2f, 0xda, 0xf5, 0xee, 0xfc, 0xe1, 0xe0, 0xff, 0xf5, 0xd7, + 0xd6, 0xdd, 0x17, 0x17, 0xde, 0xf8, 0x02, 0xce, 0x1a, 0x7f, 0x15, 0xda, 0x03, + 0xd1, 0xf4, 0xe4, 0x35, 0xf9, 0xf1, 0xf1, 0x04, 0xf3, 0xbe, 0x10, 0xf3, 0xfd, + 0x0c, 0xd5, 0xdb, 0x15, 0x0e, 0xfa, 0xd5, 0x0b, 0x13, 0xf8, 0x00, 0xef, 0xf5, + 0xfc, 0x2a, 0x05, 0xf9, 0xfe, 0xdf, 0xd9, 0x14, 0x00, 0x4b, 0x1b, 0x01, 0xd0, + 0xf0, 0xf7, 0x07, 0xfe, 0xe5, 0x04, 0x0d, 0xec, 0xf2, 0xf1, 0xd9, 0xf7, 0x02, + 0xcb, 0xf7, 0x1a, 0xe5, 0xe3, 0xdf, 0xca, 0xf2, 0xf8, 0xf6, 0xe2, 0xe4, 0x22, + 0xfd, 0xf8, 0xe5, 0xe6, 0xed, 0xfe, 0x00, 0xf0, 0xc0, 0x00, 0xc7, 0x1d, 0xe3, + 0xd6, 0xfe, 0xf1, 0xef, 0xda, 0x12, 0xf6, 0x08, 0x00, 0xf0, 0xe3, 0xdb, 0x06, + 0xf3, 0xf7, 0x14, 0x3b, 0x0c, 0xfa, 0x00, 0xff, 0xd6, 0xe8, 0x4b, 0xd7, 0xec, + 0x33, 0x04, 0x0d, 0x40, 0xe7, 0x00, 0xfb, 0x00, 0x05, 0xee, 0x1f, 0x38, 0x21, + 0xb8, 0xf3, 0x1b, 0xfa, 0x13, 0xe2, 0xd8, 0xe1, 0x0b, 0xfc, 0xe8, 0xea, 0x00, + 0xe1, 0xf7, 0x0d, 0xe0, 0x22, 0xd3, 0xee, 0xf2, 0xce, 0xee, 0x32, 0xf5, 0xfe, + 0xcd, 0x10, 0x01, 0x15, 0xea, 0x2b, 0xef, 0x1c, 0xd9, 0xfa, 0x0e, 0x22, 0x13, + 0xf1, 0xf8, 0xfb, 0xff, 0x2a, 0xfd, 0x03, 0x2e, 0x19, 0xca, 0x05, 0xfc, 0x13, + 0x1f, 0x16, 0xea, 0x0b, 0x2c, 0xfd, 0xdf, 0x11, 0xf5, 0xc7, 0x12, 0x06, 0xd3, + 0x07, 0x2b, 0x13, 0xf2, 0x05, 0xf4, 0x0a, 0x0a, 0x18, 0x03, 0xf9, 0xeb, 0xdb, + 0x0f, 0xd2, 0xff, 0xd5, 0xda, 0xf6, 0xd5, 0xda, 0xf4, 0xc7, 0xf7, 0xb9, 0xf0, + 0x10, 0xca, 0x45, 0xf1, 0xf8, 0x1e, 0xe3, 0xbd, 0xe8, 0x0f, 0x10, 0x2b, 0xd3, + 0x0a, 0x18, 0xe1, 0x25, 0xbd, 0x23, 0xd8, 0xd1, 0x11, 0x20, 0xef, 0xee, 0x0d, + 0x11, 0xdb, 0x1e, 0xfb, 0x52, 0x15, 0xdb, 0xf5, 0x10, 0xd2, 0xf2, 0x02, 0x2b, + 0xf3, 0xf2, 0x46, 0x07, 0x00, 0xbe, 0x10, 0xf2, 0xef, 0x15, 0xe8, 0x07, 0x05, + 0x25, 0x10, 0x33, 0x32, 0xd7, 0xb5, 0xe8, 0x24, 0xf5, 0xf4, 0xf1, 0xdd, 0x08, + 0xc4, 0x0b, 0xd0, 0x20, 0xdb, 0xcf, 0xf8, 0x0c, 0x30, 0x07, 0xbd, 0x06, 0x04, + 0x15, 0x1f, 0xd8, 0x2e, 0xf6, 0xb7, 0xe4, 0xec, 0xef, 0xb1, 0x0b, 0xec, 0xf5, + 0xcc, 0xf3, 0x43, 0x2c, 0x07, 0xdc, 0x42, 0x24, 0xe7, 0xff, 0xdc, 0xed, 0x12, + 0xc2, 0xb6, 0x21, 0xda, 0xf7, 0xf2, 0xe7, 0x00, 0xd9, 0xf2, 0x1b, 0x25, 0x07, + 0x2a, 0x37, 0xd4, 0xe1, 0xf1, 0xeb, 0xc4, 0x1d, 0x0e, 0xd2, 0xd3, 0xe7, 0x26, + 0x1c, 0xe9, 0x33, 0xdb, 0xa6, 0x32, 0x02, 0x07, 0xe8, 0xf9, 0xf8, 0x0f, 0xde, + 0xe0, 0x27, 0x14, 0x20, 0x10, 0xe0, 0xf3, 0xe2, 0x06, 0xcd, 0x24, 0xc0, 0xf2, + 0x10, 0x4b, 0x7f, 0xe0, 0xad, 0xef, 0x01, 0xb3, 0xc6, 0xf7, 0x17, 0xdd, 0x52, + 0xd8, 0xdb, 0x4c, 0xfc, 0x2b, 0x0d, 0xbc, 0xf9, 0xe2, 0x00, 0x18, 0xbb, 0x04, + 0x30, 0x0e, 0x1a, 0xdb, 0x17, 0xd1, 0xd8, 0x01, 0xf1, 0xf6, 0xfa, 0x23, 0x20, + 0xfe, 0xdd, 0x0d, 0xef, 0xce, 0x09, 0xdc, 0xda, 0xe4, 0x5c, 0xc6, 0x11, 0x03, + 0xdc, 0xf6, 0x2b, 0x40, 0xf3, 0x0b, 0x1d, 0x19, 0xa7, 0x05, 0xc5, 0x09, 0xc8, + 0xed, 0x28, 0x07, 0xe8, 0x0c, 0x0a, 0x24, 0x13, 0xec, 0xb4, 0x09, 0xfd, 0xec, + 0x25, 0x1a, 0xe2, 0xe1, 0xfe, 0x26, 0xa1, 0xcd, 0x15, 0xe6, 0x1d, 0xdf, 0xeb, + 0x9e, 0xe7, 0x0f, 0x05, 0x9c, 0x33, 0x36, 0xcb, 0x39, 0xd2, 0x0e, 0x4c, 0xa6, + 0xe5, 0xbd, 0xd1, 0x07, 0xc9, 0xef, 0xaa, 0xdd, 0xec, 0x02, 0x09, 0xe5, 0xed, + 0xf7, 0xd3, 0xfb, 0xd1, 0xa8, 0xb0, 0xdb, 0xf3, 0xed, 0x0a, 0x81, 0x49, 0x00, + 0xb3, 0xc6, 0xc3, 0xd5, 0xfa, 0xfc, 0xe1, 0xbd, 0x48, 0xd9, 0xfd, 0xc3, 0x09, + 0xe4, 0x24, 0x26, 0xd9, 0xd4, 0xfc, 0x03, 0x51, 0x2f, 0x07, 0xe5, 0x9d, 0x02, + 0xc5, 0xd1, 0x07, 0xf8, 0x31, 0xea, 0xf6, 0xeb, 0x05, 0x01, 0x0c, 0x21, 0xa9, + 0xea, 0xf1, 0xb1, 0xfb, 0x60, 0xf4, 0x0b, 0x40, 0xb0, 0x4f, 0x33, 0xba, 0xcf, + 0x13, 0x03, 0xea, 0xd5, 0x3d, 0xd0, 0x3d, 0x06, 0x99, 0xf2, 0x04, 0xf1, 0xe2, + 0x94, 0xee, 0xf2, 0xa5, 0xac, 0x33, 0x19, 0xcc, 0x84, 0x30, 0xd4, 0xa8, 0x34, + 0x81, 0x26, 0x0a, 0xb8, 0xde, 0xfa, 0x32, 0x02, 0xd8, 0xfb, 0x39, 0x49, 0xd7, + 0x0e, 0x24, 0xda, 0xda, 0xed, 0x3d, 0x93, 0xbe, 0x0b, 0xdb, 0x39, 0xd9, 0xfb, + 0xe3, 0x27, 0xe3, 0xba, 0xe9, 0x36, 0xf3, 0xea, 0xde, 0xb9, 0x20, 0x21, 0x84, + 0xf9, 0x2c, 0x0a, 0xff, 0xed, 0x27, 0xef, 0x1a, 0x08, 0xe1, 0xe0, 0xfb, 0xe1, + 0x0a, 0x13, 0xe2, 0x20, 0xfa, 0xae, 0xf9, 0xe1, 0xf4, 0x96, 0x30, 0x11, 0xb3, + 0xdf, 0x49, 0x42, 0xd9, 0xbc, 0xbc, 0xcf, 0xf4, 0xe3, 0xff, 0x02, 0x57, 0x17, + 0xf6, 0xc5, 0x35, 0xe4, 0xf1, 0x03, 0xc1, 0xd4, 0x26, 0xa5, 0x05, 0xcd, 0x31, + 0xab, 0xf8, 0x14, 0x18, 0xa6, 0xe4, 0x3b, 0x94, 0xf5, 0xe7, 0xc3, 0xb1, 0x0e, + 0xc6, 0xd4, 0xd2, 0x33, 0x02, 0x60, 0xf0, 0xe2, 0xc8, 0x08, 0x20, 0x93, 0xe8, + 0xc0, 0x20, 0xfd, 0x46, 0xcc, 0x3d, 0x0b, 0xf9, 0xe6, 0xae, 0xf5, 0xff, 0xff, + 0xd6, 0xdd, 0x10, 0xd0, 0xd3, 0x01, 0xe0, 0x11, 0xf9, 0x09, 0x0e, 0xc3, 0xbe, + 0x0f, 0xea, 0xde, 0xc9, 0x02, 0x02, 0x0b, 0xeb, 0xfa, 0xed, 0xf6, 0x15, 0x04, + 0x14, 0xf7, 0x11, 0x10, 0xde, 0x2b, 0x0f, 0xe0, 0xc8, 0xed, 0xec, 0x2b, 0x24, + 0x10, 0xd1, 0xf0, 0xfd, 0xeb, 0xef, 0x06, 0xcc, 0x15, 0xf5, 0xf3, 0xf0, 0x27, + 0xe4, 0xf9, 0xc0, 0x04, 0xcd, 0x01, 0xf6, 0x10, 0x20, 0xea, 0x81, 0x15, 0xdd, + 0xef, 0xd3, 0x11, 0xe5, 0xbd, 0x0e, 0xd5, 0x2d, 0x1e, 0x1d, 0x0b, 0x0d, 0x13, + 0xf1, 0xe9, 0x05, 0x00, 0x0b, 0xe7, 0x01, 0xdf, 0xfc, 0x01, 0xe6, 0xe7, 0xee, + 0x11, 0x14, 0xc4, 0xf2, 0xde, 0xfd, 0xe1, 0x12, 0x0a, 0x12, 0xf1, 0xe5, 0xe4, + 0x17, 0xee, 0x12, 0x14, 0x0c, 0x02, 0xf9, 0xf8, 0x35, 0x07, 0x0a, 0x03, 0x04, + 0x10, 0x0d, 0x07, 0xd7, 0x03, 0x0f, 0x0d, 0x2c, 0x0a, 0xdf, 0x0e, 0xd5, 0xf7, + 0xc9, 0x14, 0xd7, 0xd5, 0x14, 0xea, 0x00, 0xee, 0x12, 0xf4, 0x2e, 0x08, 0x15, + 0xf5, 0x18, 0x18, 0xdd, 0x25, 0x12, 0xea, 0xe8, 0xf2, 0xad, 0x1c, 0x12, 0xe6, + 0x01, 0xeb, 0xf0, 0xfa, 0xee, 0x1a, 0x22, 0xed, 0x22, 0x29, 0xfe, 0x0e, 0x23, + 0xd2, 0xfd, 0x15, 0x07, 0xfc, 0xf1, 0x3c, 0xde, 0xd6, 0x09, 0xbb, 0xcf, 0xef, + 0xc1, 0x1e, 0x19, 0x09, 0x1d, 0xfd, 0xf3, 0xec, 0x14, 0xf1, 0xe8, 0xf9, 0x22, + 0xf7, 0xe5, 0x0a, 0x02, 0x13, 0xee, 0x26, 0x03, 0x0f, 0xef, 0xdb, 0xe9, 0x46, + 0xed, 0x0c, 0xf0, 0xfb, 0xd4, 0xdb, 0xfd, 0xe3, 0x13, 0x14, 0xc9, 0x07, 0xea, + 0xea, 0xda, 0xcc, 0x08, 0x2e, 0xdc, 0xde, 0xe6, 0x21, 0xc5, 0xf1, 0x0c, 0x38, + 0xde, 0xf3, 0x0e, 0x01, 0xc3, 0xe9, 0xfd, 0x0b, 0xf7, 0x39, 0xe2, 0x17, 0xdf, + 0x0e, 0x1b, 0xda, 0x08, 0xeb, 0xdf, 0x0b, 0x03, 0xd0, 0x35, 0x43, 0xa9, 0x00, + 0xb6, 0xba, 0x9e, 0xa9, 0xa4, 0xe3, 0x01, 0x1a, 0xdf, 0x12, 0x10, 0xba, 0xb0, + 0xd2, 0xf7, 0x69, 0xfa, 0xfe, 0xdc, 0xb0, 0x00, 0x01, 0x05, 0xe5, 0x3d, 0xaa, + 0xe7, 0xa4, 0xf0, 0xc5, 0xeb, 0xa0, 0xc0, 0xa6, 0xc9, 0xbf, 0x17, 0x74, 0xe7, + 0x08, 0x11, 0x1c, 0x1f, 0x2b, 0xed, 0x39, 0x01, 0x00, 0x9b, 0xfb, 0xd8, 0xfa, + 0x21, 0xc9, 0x14, 0x2e, 0x0e, 0x17, 0x9a, 0x08, 0xd3, 0xfc, 0x00, 0xcf, 0xff, + 0xc5, 0xba, 0xf6, 0x1a, 0xfd, 0x2f, 0xd8, 0x36, 0x4d, 0xcd, 0xf6, 0x11, 0x06, + 0x65, 0xe2, 0x1b, 0xc3, 0x0f, 0xc7, 0xdd, 0xde, 0xd2, 0xcf, 0xeb, 0xcc, 0xfb, + 0xb7, 0x56, 0xc6, 0x12, 0xdd, 0xec, 0xdc, 0xfb, 0x04, 0x20, 0xc0, 0xcc, 0x17, + 0xd3, 0xf4, 0xe4, 0x0d, 0x21, 0xde, 0xc5, 0xb5, 0x0d, 0x3e, 0x1d, 0x06, 0xe9, + 0x23, 0xfa, 0xc0, 0xd2, 0xf2, 0x69, 0xff, 0x05, 0xda, 0x11, 0xe5, 0xb9, 0x21, + 0xd5, 0x97, 0x25, 0xe4, 0x0e, 0xfc, 0x05, 0x1c, 0xc0, 0xef, 0xed, 0xa8, 0xf9, + 0xe5, 0xed, 0x44, 0x0d, 0x26, 0xff, 0x29, 0x1c, 0x41, 0xc3, 0xd1, 0xff, 0xe3, + 0xe7, 0x9a, 0xc9, 0x34, 0x29, 0x5e, 0xbd, 0xdc, 0xc4, 0xf2, 0xe4, 0xeb, 0xf9, + 0x7f, 0x3b, 0xf1, 0x63, 0x19, 0xdd, 0xea, 0xda, 0x34, 0xe5, 0xf0, 0xf9, 0xc2, + 0x1d, 0xcc, 0x1f, 0xd8, 0xd0, 0x40, 0xfe, 0x26, 0xd2, 0xad, 0x32, 0xb3, 0xdc, + 0xa5, 0xe1, 0x14, 0x11, 0x76, 0x5f, 0xe7, 0x13, 0xde, 0xdf, 0x2e, 0x32, 0x05, + 0xe3, 0x27, 0xf5, 0xfc, 0xee, 0x1a, 0x3d, 0xb4, 0x1f, 0xd4, 0xf2, 0xd9, 0x2e, + 0xe1, 0x00, 0x1e, 0x05, 0x2c, 0xd4, 0xc4, 0x09, 0x25, 0xea, 0xa1, 0xc8, 0x29, + 0xd5, 0x1f, 0xcb, 0x0f, 0x2e, 0xf1, 0xee, 0xe5, 0x3b, 0xed, 0xd7, 0x22, 0xfe, + 0xdb, 0x32, 0xd7, 0xd6, 0xff, 0x09, 0x02, 0x18, 0xf2, 0x01, 0x05, 0x01, 0xe2, + 0xd4, 0xdb, 0xf4, 0x10, 0xaf, 0xfc, 0xe8, 0x22, 0xe0, 0x0f, 0xe0, 0xff, 0x36, + 0x04, 0xf5, 0xd2, 0xd1, 0xa9, 0x12, 0xde, 0x0e, 0x0d, 0xe2, 0xfe, 0xdf, 0xf5, + 0xf5, 0xd3, 0x1a, 0x13, 0x0a, 0x2f, 0x03, 0xeb, 0xe2, 0xdb, 0x11, 0xfd, 0xf7, + 0xd8, 0x0f, 0x02, 0xbf, 0xc8, 0x1e, 0xe2, 0x0e, 0x05, 0xd1, 0x23, 0x02, 0x22, + 0x11, 0xff, 0x92, 0x27, 0x2b, 0xd3, 0x07, 0xb1, 0xfd, 0xd1, 0xd1, 0x32, 0xeb, + 0x2c, 0xfe, 0xd2, 0xea, 0xf7, 0xe1, 0x21, 0x0e, 0xde, 0x0a, 0x02, 0xf9, 0xc4, + 0x0c, 0xfc, 0x0a, 0x20, 0x01, 0xbf, 0xc9, 0xee, 0x09, 0xd3, 0x05, 0xff, 0xcb, + 0xf4, 0x15, 0xe8, 0x1b, 0x0a, 0xd3, 0xf0, 0xef, 0xb1, 0x33, 0xba, 0x4f, 0xd8, + 0xfa, 0x06, 0xcd, 0x13, 0x00, 0xe5, 0x31, 0xd6, 0x25, 0xec, 0xfe, 0xb0, 0xd6, + 0xf5, 0x11, 0x1a, 0xd9, 0x03, 0xe6, 0x0c, 0x4c, 0xf4, 0xe9, 0xf4, 0xd6, 0xbb, + 0xfa, 0xf8, 0xde, 0x9f, 0x1a, 0xb7, 0xef, 0xe2, 0x17, 0x0d, 0x0f, 0x2c, 0xf0, + 0x07, 0xbc, 0x36, 0xf9, 0x32, 0x04, 0xfe, 0x07, 0xe3, 0xe9, 0xc0, 0xf7, 0xde, + 0x2d, 0xe0, 0xed, 0x18, 0xd6, 0x38, 0xf6, 0xe3, 0xdd, 0xe0, 0xfc, 0xc1, 0x7f, + 0x13, 0xe0, 0x25, 0x2e, 0x13, 0xed, 0xde, 0xe5, 0xe5, 0x17, 0xe3, 0xc9, 0x3c, + 0xde, 0x0c, 0xf2, 0xa5, 0xda, 0xdd, 0x3c, 0xec, 0xdb, 0x0c, 0x27, 0xed, 0xef, + 0xd2, 0x36, 0xd1, 0xf5, 0xc2, 0xab, 0x0c, 0x0a, 0xc2, 0x28, 0xdc, 0xcf, 0x10, + 0xc6, 0xd9, 0xca, 0xe6, 0xdf, 0x16, 0x10, 0xe4, 0xfe, 0x1e, 0xe5, 0x4f, 0x02, + 0x15, 0xfe, 0x00, 0xd7, 0x0e, 0x07, 0xef, 0xd4, 0xef, 0xf1, 0xf2, 0x21, 0x2f, + 0xc6, 0xfc, 0x39, 0x16, 0x32, 0x9a, 0xcd, 0x07, 0x1e, 0x04, 0x23, 0xf5, 0xfa, + 0x12, 0x34, 0x21, 0xfa, 0x05, 0x30, 0x24, 0x33, 0xf2, 0xf9, 0xfd, 0xd5, 0xff, + 0x46, 0xd2, 0x18, 0x1a, 0xc3, 0x32, 0x15, 0xdc, 0x03, 0xd7, 0x32, 0xf2, 0xe7, + 0xd7, 0x16, 0xf0, 0xf0, 0x03, 0xe9, 0xdd, 0x25, 0xf4, 0xf8, 0xfa, 0x13, 0xe3, + 0x41, 0x1b, 0xc4, 0xe1, 0x18, 0x14, 0xe9, 0xe7, 0xe2, 0xff, 0x2d, 0xf6, 0xea, + 0xd4, 0xdc, 0x23, 0xea, 0xea, 0x29, 0x14, 0x0e, 0xec, 0x0b, 0xec, 0x00, 0xf7, + 0x08, 0xdc, 0x1a, 0xef, 0xe4, 0xf2, 0x20, 0xcb, 0xc3, 0xf6, 0x3d, 0x14, 0xe2, + 0xc5, 0xf7, 0xf7, 0xd2, 0xe6, 0x0b, 0x1a, 0xf9, 0x26, 0x20, 0x1f, 0x0f, 0xd4, + 0xf3, 0x0e, 0xd6, 0x4d, 0x01, 0x07, 0x1a, 0xf1, 0xe1, 0xe0, 0x1e, 0xea, 0xea, + 0x1d, 0xfe, 0xed, 0x1e, 0xf0, 0x00, 0x00, 0xff, 0x0d, 0xb3, 0x02, 0x4b, 0x0a, + 0xf3, 0x1c, 0x38, 0xfb, 0xee, 0x5d, 0x0c, 0xe6, 0xdf, 0x02, 0xed, 0x1f, 0xfe, + 0xea, 0x7f, 0xe5, 0xf7, 0x01, 0x02, 0x22, 0x60, 0xdd, 0xee, 0xcf, 0x11, 0xfc, + 0xee, 0xf1, 0x14, 0xc7, 0xe4, 0xf8, 0x3b, 0x09, 0xe6, 0xf7, 0xdc, 0xf9, 0x27, + 0x06, 0x10, 0x25, 0xf8, 0xe6, 0x12, 0xe5, 0xe1, 0x1b, 0xd3, 0xd3, 0xea, 0x04, + 0x12, 0x02, 0xe1, 0xe4, 0xf3, 0x4a, 0x13, 0xf1, 0xb4, 0x0c, 0xf7, 0x53, 0xd0, + 0xcd, 0xe5, 0x2c, 0x09, 0x06, 0xdf, 0xf1, 0x0d, 0x1f, 0xfc, 0xdd, 0xdf, 0x07, + 0x1f, 0x41, 0x23, 0xff, 0x1f, 0x22, 0x15, 0x06, 0x0f, 0x02, 0xd7, 0x11, 0x1f, + 0xea, 0x24, 0xef, 0xe9, 0x0a, 0x0d, 0x1c, 0xd9, 0xeb, 0xe1, 0x2b, 0x00, 0x08, + 0xd9, 0xd1, 0xfa, 0xdc, 0x06, 0x14, 0x0b, 0x03, 0x40, 0x3c, 0xdc, 0xf4, 0xc3, + 0xeb, 0xfa, 0xeb, 0x07, 0xd8, 0x18, 0x09, 0xfa, 0x6d, 0xe2, 0xff, 0x06, 0xfa, + 0x16, 0xec, 0xd4, 0xf8, 0xdc, 0xd7, 0x30, 0x08, 0xe1, 0x37, 0x08, 0xca, 0xe1, + 0xc7, 0x0a, 0xd0, 0x10, 0xed, 0x10, 0x09, 0xd4, 0xed, 0x4e, 0xea, 0x1b, 0x2b, + 0xd3, 0x14, 0xe0, 0xfd, 0x0a, 0x12, 0xeb, 0xd1, 0xe8, 0x2f, 0xc6, 0xd8, 0xfe, + 0xec, 0xf6, 0xca, 0xfa, 0xc1, 0xfd, 0xc9, 0x22, 0xdb, 0xdb, 0xe4, 0x09, 0x22, + 0xfb, 0xb7, 0xb5, 0xdd, 0xf9, 0x03, 0xda, 0x1f, 0x00, 0x24, 0xf5, 0xd6, 0x05, + 0x0e, 0x07, 0x16, 0x01, 0x3e, 0xbe, 0x44, 0x18, 0x00, 0xe0, 0xdb, 0x4e, 0x0b, + 0xe6, 0xf2, 0xd9, 0xd1, 0x1e, 0x00, 0x95, 0x0e, 0xd4, 0xf3, 0xd9, 0x10, 0xf9, + 0xf8, 0x0f, 0x51, 0xa0, 0xb9, 0x4f, 0xc9, 0xd9, 0x05, 0xf5, 0xde, 0xc4, 0x27, + 0x37, 0x26, 0x06, 0xef, 0xf0, 0x13, 0xd2, 0xc9, 0x35, 0xe0, 0x19, 0x00, 0xf8, + 0x81, 0xf0, 0xf1, 0xf5, 0xd6, 0x33, 0xf4, 0x19, 0x0e, 0xf9, 0xc5, 0x25, 0xe8, + 0x0f, 0x0e, 0xee, 0xd0, 0x92, 0xe2, 0xf5, 0x01, 0xf0, 0x01, 0x10, 0x0c, 0x0a, + 0xeb, 0xd1, 0xc0, 0x04, 0x25, 0x22, 0xc9, 0xbd, 0xf8, 0xff, 0x17, 0xe9, 0x2d, + 0x1c, 0xcd, 0xd5, 0x2d, 0xae, 0x0d, 0x05, 0xf6, 0x1b, 0x0f, 0xf7, 0xeb, 0xf9, + 0xe6, 0xe2, 0x1d, 0x0c, 0xc3, 0x0f, 0x1f, 0xb7, 0xf7, 0xcb, 0x22, 0x26, 0xfe, + 0x16, 0x30, 0xbe, 0x18, 0xbd, 0x24, 0x2c, 0xe0, 0x00, 0xdf, 0xa5, 0xe1, 0x28, + 0x1a, 0x09, 0xf0, 0xef, 0xc9, 0x13, 0x3c, 0x06, 0xd6, 0x4c, 0xe1, 0x04, 0xfc, + 0x12, 0xf0, 0xda, 0xcd, 0x15, 0x0a, 0x67, 0xf1, 0x1e, 0xe9, 0xf7, 0x0c, 0x20, + 0xf4, 0x3f, 0x11, 0xfd, 0x38, 0x07, 0x0b, 0xf0, 0xde, 0xff, 0x21, 0x15, 0x14, + 0x02, 0x15, 0xcd, 0x70, 0xba, 0x08, 0xdd, 0xf5, 0xe5, 0xd9, 0xe7, 0x4b, 0x61, + 0x0e, 0x15, 0x0a, 0xe7, 0x34, 0xe6, 0xd0, 0xc0, 0xf4, 0x28, 0x2e, 0x22, 0xfd, + 0x07, 0xf8, 0xfe, 0xed, 0x24, 0x33, 0x03, 0x05, 0xd3, 0xd8, 0xd7, 0xd8, 0x3a, + 0x1e, 0xfd, 0x58, 0x16, 0x9e, 0xc8, 0x1f, 0xb8, 0xc0, 0xfa, 0x1f, 0x33, 0x0c, + 0xf5, 0xb7, 0x17, 0x25, 0x30, 0x21, 0xb6, 0xdd, 0x0f, 0x42, 0x0f, 0xdb, 0x22, + 0xc1, 0x91, 0xd3, 0x5c, 0x16, 0xc6, 0xdf, 0x01, 0x15, 0x0e, 0x42, 0xed, 0x1c, + 0x01, 0x7a, 0xbe, 0x28, 0x32, 0x1a, 0x04, 0xda, 0xff, 0xc1, 0x1e, 0xc2, 0x0c, + 0x3a, 0xdd, 0xe7, 0x38, 0xc3, 0x9a, 0x0a, 0x02, 0xf0, 0xfd, 0xf9, 0xce, 0xbb, + 0x8e, 0x27, 0xdf, 0x23, 0x38, 0x1e, 0xf5, 0x06, 0xfc, 0xdb, 0x43, 0xfe, 0xdf, + 0x35, 0x03, 0xf4, 0x14, 0x1c, 0xc8, 0xe1, 0xf0, 0xf1, 0xe0, 0xc3, 0xdd, 0xba, + 0xc9, 0xf3, 0x0e, 0xda, 0x07, 0xfc, 0x2c, 0xf7, 0x2c, 0x1c, 0xeb, 0x4e, 0xfd, + 0xef, 0xb4, 0x0a, 0xd2, 0x07, 0xb7, 0xe3, 0xcf, 0x0a, 0x07, 0xf9, 0x18, 0xa4, + 0xeb, 0x30, 0xaf, 0xf0, 0x0b, 0xfc, 0x3e, 0xf2, 0x24, 0x0b, 0xac, 0xb8, 0xfe, + 0xdc, 0xd9, 0x05, 0xd5, 0x16, 0x33, 0xe2, 0xf3, 0x15, 0xca, 0xd5, 0xc7, 0x10, + 0x0d, 0xd4, 0x16, 0x19, 0xab, 0x3e, 0xc0, 0xa5, 0xd3, 0xac, 0xed, 0x20, 0xf1, + 0xbf, 0x05, 0xf3, 0xc7, 0x44, 0x38, 0x33, 0x4f, 0xdd, 0xd4, 0x61, 0xff, 0x39, + 0xdd, 0x0d, 0x15, 0xfc, 0x58, 0x13, 0xe7, 0xc9, 0xfb, 0x1c, 0x0a, 0xcc, 0x74, + 0x99, 0xec, 0x00, 0xec, 0x01, 0xe0, 0xfb, 0xfb, 0xe5, 0xce, 0x24, 0xb5, 0x42, + 0x46, 0x02, 0xe5, 0xf9, 0x13, 0x1b, 0xd3, 0x00, 0x0a, 0xe9, 0xbd, 0xfe, 0x00, + 0x32, 0x1c, 0xc1, 0x2a, 0x0d, 0x0c, 0x07, 0xbb, 0xe1, 0xdd, 0x17, 0xd3, 0x06, + 0x02, 0x24, 0xc8, 0xbc, 0xd5, 0x45, 0xbe, 0x81, 0x53, 0xdf, 0x13, 0x11, 0x43, + 0x01, 0x00, 0xc8, 0xcb, 0xb1, 0xea, 0x1b, 0xcd, 0x24, 0x1b, 0xd9, 0xd0, 0x25, + 0xfe, 0xeb, 0xc7, 0x07, 0xe3, 0xf9, 0x9e, 0xda, 0x26, 0x04, 0xca, 0x05, 0xfc, + 0x12, 0x10, 0xdd, 0x1d, 0x26, 0xe1, 0xd8, 0x74, 0xe5, 0x92, 0x7f, 0x06, 0x08, + 0x0c, 0xc5, 0xfd, 0xee, 0xfc, 0xe1, 0xf7, 0xba, 0x2f, 0x25, 0xf7, 0xe6, 0xd9, + 0xe9, 0xee, 0x00, 0x58, 0xea, 0x2a, 0xec, 0xab, 0xdc, 0xb5, 0x29, 0x25, 0xfa, + 0xe5, 0x06, 0x25, 0xff, 0x24, 0x0e, 0x06, 0xf8, 0x16, 0x77, 0xbb, 0xf5, 0xe6, + 0xcb, 0xf0, 0xdf, 0x07, 0xea, 0x07, 0xd1, 0x2e, 0x15, 0xdf, 0xfd, 0x16, 0xed, + 0x33, 0x14, 0xfe, 0xe4, 0xc2, 0xe4, 0x10, 0x07, 0x24, 0xd8, 0xe7, 0x2d, 0x09, + 0x1e, 0xdc, 0xf8, 0xc0, 0x42, 0x17, 0x0e, 0x3a, 0x09, 0xde, 0xc9, 0xf0, 0xf0, + 0xd3, 0x00, 0x1e, 0xb5, 0xb6, 0xdb, 0x3d, 0x06, 0x0c, 0xe7, 0x43, 0x23, 0x06, + 0x19, 0xe4, 0x0c, 0xf8, 0x2a, 0xd2, 0x28, 0xe6, 0xf1, 0x31, 0xff, 0x16, 0xf9, + 0xb1, 0x20, 0x4e, 0xe1, 0x17, 0xfc, 0xe8, 0x2b, 0xfd, 0xeb, 0xf3, 0xf1, 0xea, + 0xd2, 0x16, 0x1d, 0x0b, 0x6c, 0x1a, 0xed, 0x03, 0x23, 0x11, 0xe8, 0xe8, 0x15, + 0x09, 0x25, 0xd3, 0x0e, 0xfa, 0xe1, 0xfa, 0xf3, 0x12, 0x04, 0x10, 0xca, 0x07, + 0x03, 0xce, 0xfb, 0xd5, 0x16, 0x06, 0x08, 0xd2, 0xea, 0xc3, 0xf8, 0x0d, 0xf7, + 0xea, 0xe6, 0x04, 0xc5, 0x09, 0xd8, 0x1c, 0xbb, 0x1c, 0x0f, 0x14, 0xc9, 0xf0, + 0xef, 0xd2, 0x1b, 0x07, 0x17, 0x31, 0x56, 0xee, 0x38, 0xf6, 0x10, 0xfb, 0x9f, + 0x11, 0xec, 0xf5, 0x1b, 0xf7, 0x27, 0x0e, 0x09, 0x32, 0xf7, 0xc1, 0xf8, 0x07, + 0xf7, 0xf3, 0xa3, 0xec, 0xc5, 0x71, 0xe1, 0x04, 0xeb, 0x3e, 0xf5, 0x03, 0x1a, + 0xe1, 0xec, 0x1a, 0xb9, 0xf6, 0x24, 0x21, 0xd6, 0xd7, 0x47, 0xb9, 0xe1, 0xef, + 0xed, 0x15, 0x10, 0xe0, 0xf0, 0xb4, 0x06, 0x36, 0x8f, 0xed, 0x16, 0xc6, 0x14, + 0xc2, 0xf8, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x15, + 0x1a, 0x00, 0x00, 0xf7, 0xf1, 0xff, 0xff, 0xaa, 0x0e, 0x00, 0x00, 0xcc, 0x66, + 0x00, 0x00, 0x67, 0xed, 0xff, 0xff, 0x7e, 0x1d, 0x00, 0x00, 0x14, 0x05, 0x00, + 0x00, 0xd9, 0xd3, 0xff, 0xff, 0xe0, 0x30, 0x00, 0x00, 0x3b, 0x29, 0x00, 0x00, + 0x40, 0x3e, 0x00, 0x00, 0x99, 0xfa, 0xff, 0xff, 0x83, 0x1b, 0x00, 0x00, 0x78, + 0xe4, 0xff, 0xff, 0xf8, 0x23, 0x00, 0x00, 0x0e, 0x25, 0x00, 0x00, 0x33, 0x06, + 0x00, 0x00, 0xfe, 0x32, 0x00, 0x00, 0x27, 0xe5, 0xff, 0xff, 0xba, 0x0d, 0x00, + 0x00, 0xc4, 0x51, 0x00, 0x00, 0x07, 0xf0, 0xff, 0xff, 0x40, 0xf2, 0xff, 0xff, + 0x2a, 0x57, 0x00, 0x00, 0xd1, 0x01, 0x00, 0x00, 0x11, 0x0e, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0x51, 0x29, 0x00, 0x00, 0x53, 0x29, 0x00, 0x00, 0xcf, 0x38, + 0x00, 0x00, 0x78, 0x5f, 0x00, 0x00, 0x90, 0x13, 0x00, 0x00, 0xee, 0x08, 0x00, + 0x00, 0xec, 0xec, 0xff, 0xff, 0x2c, 0x3d, 0x00, 0x00, 0x53, 0x34, 0x00, 0x00, + 0xd2, 0x08, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0xa9, 0xe5, 0xff, 0xff, 0x91, + 0x0c, 0x00, 0x00, 0xc7, 0x02, 0x00, 0x00, 0xdc, 0x12, 0x00, 0x00, 0x67, 0xd1, + 0xff, 0xff, 0x8b, 0xfc, 0xff, 0xff, 0x6e, 0x13, 0x00, 0x00, 0x3e, 0xe7, 0xff, + 0xff, 0x34, 0x53, 0x00, 0x00, 0x05, 0x3a, 0x00, 0x00, 0x5c, 0x1a, 0x00, 0x00, + 0xdd, 0x16, 0x00, 0x00, 0x31, 0x52, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x4a, + 0x15, 0x00, 0x00, 0x26, 0x2f, 0x00, 0x00, 0xcb, 0x12, 0x00, 0x00, 0xd0, 0x1a, + 0x00, 0x00, 0xda, 0x19, 0x00, 0x00, 0x2e, 0x57, 0x00, 0x00, 0x3d, 0x04, 0x00, + 0x00, 0x9d, 0x28, 0x00, 0x00, 0x94, 0x09, 0x00, 0x00, 0x7f, 0xfa, 0xff, 0xff, + 0x11, 0x22, 0x00, 0x00, 0x06, 0x0a, 0x00, 0x00, 0xce, 0x4b, 0x00, 0x00, 0xff, + 0x16, 0x00, 0x00, 0xf2, 0x41, 0x00, 0x00, 0xca, 0x1c, 0x00, 0x00, 0x57, 0x28, + 0x00, 0x00, 0x6d, 0x27, 0x00, 0x00, 0x4a, 0x0a, 0x00, 0x00, 0xbf, 0x50, 0x00, + 0x00, 0x55, 0x3d, 0x00, 0x00, 0x59, 0x57, 0x00, 0x00, 0x44, 0x4c, 0x00, 0x00, + 0x32, 0x22, 0x00, 0x00, 0x88, 0x02, 0x00, 0x00, 0x73, 0xde, 0xff, 0xff, 0xbe, + 0x37, 0x00, 0x00, 0xca, 0x18, 0x00, 0x00, 0x3c, 0xfb, 0xff, 0xff, 0x0b, 0x42, + 0x00, 0x00, 0x68, 0x72, 0x00, 0x00, 0xff, 0xe9, 0xff, 0xff, 0x03, 0x0d, 0x00, + 0x00, 0x40, 0x22, 0x00, 0x00, 0x79, 0x2e, 0x00, 0x00, 0x3f, 0xe5, 0xff, 0xff, + 0x63, 0x33, 0x00, 0x00, 0x2c, 0x5f, 0x00, 0x00, 0x94, 0x2e, 0x00, 0x00, 0x71, + 0x01, 0x00, 0x00, 0x4e, 0x38, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x9e, 0x2e, + 0x00, 0x00, 0xc4, 0xdd, 0xff, 0xff, 0x1b, 0x0c, 0x00, 0x00, 0x23, 0x28, 0x00, + 0x00, 0xee, 0x1c, 0x00, 0x00, 0x8b, 0x2e, 0x00, 0x00, 0xff, 0xf7, 0xff, 0xff, + 0xab, 0x0b, 0x00, 0x00, 0x96, 0x3a, 0x00, 0x00, 0xdf, 0x2b, 0x00, 0x00, 0xc2, + 0x4e, 0x00, 0x00, 0x6f, 0x09, 0x00, 0x00, 0xc3, 0x6a, 0x00, 0x00, 0x61, 0x19, + 0x00, 0x00, 0x2c, 0xdc, 0xff, 0xff, 0xfb, 0x25, 0x00, 0x00, 0x67, 0x66, 0x00, + 0x00, 0x65, 0xf6, 0xff, 0xff, 0xf5, 0x6e, 0x00, 0x00, 0xb6, 0x17, 0x00, 0x00, + 0xc3, 0x08, 0x00, 0x00, 0x81, 0xf3, 0xff, 0xff, 0x6b, 0xe9, 0xff, 0xff, 0x36, + 0x38, 0x00, 0x00, 0xbb, 0x0e, 0x00, 0x00, 0x35, 0xcf, 0xff, 0xff, 0xdb, 0xd7, + 0xff, 0xff, 0xcd, 0xfb, 0xff, 0xff, 0x2f, 0x11, 0x00, 0x00, 0xfd, 0xfe, 0xff, + 0xff, 0x5d, 0x13, 0x00, 0x00, 0x45, 0x1c, 0x00, 0x00, 0xd6, 0x22, 0x00, 0x00, + 0xb2, 0x0a, 0x00, 0x00, 0x82, 0x17, 0x00, 0x00, 0x9a, 0x52, 0x00, 0x00, 0xe0, + 0xe2, 0xff, 0xff, 0x20, 0x02, 0x00, 0x00, 0x25, 0xfd, 0xff, 0xff, 0xb1, 0x2f, + 0x00, 0x00, 0xa0, 0x3b, 0x00, 0x00, 0xae, 0x26, 0x00, 0x00, 0xb5, 0x3e, 0x00, + 0x00, 0xb9, 0xfb, 0xff, 0xff, 0x2c, 0x40, 0x00, 0x00, 0x64, 0x39, 0x00, 0x00, + 0xeb, 0x46, 0x00, 0x00, 0x2a, 0x1c, 0x00, 0x00, 0xd9, 0x0a, 0x00, 0x00, 0xf0, + 0x40, 0x00, 0x00, 0x55, 0xda, 0xff, 0xff, 0xa7, 0x1e, 0x00, 0x00, 0xa3, 0xf6, + 0xff, 0xff, 0x68, 0x31, 0x00, 0x00, 0x23, 0x29, 0x00, 0x00, 0x0f, 0x25, 0x00, + 0x00, 0x55, 0xfd, 0xff, 0xff, 0x83, 0x1c, 0x00, 0x00, 0xc6, 0x87, 0x00, 0x00, + 0x65, 0xf8, 0xff, 0xff, 0x13, 0xfe, 0xff, 0xff, 0x56, 0x13, 0x00, 0x00, 0xfc, + 0x17, 0x00, 0x00, 0x4e, 0x10, 0x00, 0x00, 0xfd, 0x15, 0x00, 0x00, 0x93, 0xd1, + 0xff, 0xff, 0x13, 0x12, 0x00, 0x00, 0x9d, 0x14, 0x00, 0x00, 0xf3, 0xde, 0xff, + 0xff, 0x83, 0x37, 0x00, 0x00, 0x9f, 0xf9, 0xff, 0xff, 0xbb, 0xed, 0xff, 0xff, + 0x05, 0x2e, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x23, 0x5c, 0x00, 0x00, 0xb8, + 0xf8, 0xff, 0xff, 0xd8, 0x08, 0x00, 0x00, 0x05, 0x44, 0x00, 0x00, 0xc2, 0x5b, + 0x00, 0x00, 0xe8, 0x0a, 0x00, 0x00, 0xe8, 0x47, 0x00, 0x00, 0x1e, 0x1b, 0x00, + 0x00, 0xcd, 0xff, 0xff, 0xff, 0x0e, 0x1c, 0x00, 0x00, 0x4c, 0x40, 0x00, 0x00, + 0x5b, 0x28, 0x00, 0x00, 0x17, 0x3a, 0x00, 0x00, 0x1b, 0x01, 0x00, 0x00, 0x53, + 0x77, 0x00, 0x00, 0xf4, 0x42, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x00, 0x5e, 0xed, + 0xff, 0xff, 0x78, 0x17, 0x00, 0x00, 0x32, 0x26, 0x00, 0x00, 0x50, 0x1a, 0x00, + 0x00, 0x91, 0xfb, 0xff, 0xff, 0xb9, 0x4f, 0x00, 0x00, 0xd8, 0x05, 0x00, 0x00, + 0x64, 0x38, 0x00, 0x00, 0x17, 0x2f, 0x00, 0x00, 0x81, 0x1e, 0x00, 0x00, 0xf4, + 0x17, 0x00, 0x00, 0x27, 0x26, 0x00, 0x00, 0xea, 0xed, 0xff, 0xff, 0x1a, 0x3b, + 0x00, 0x00, 0x87, 0x7b, 0x00, 0x00, 0xcd, 0x22, 0x00, 0x00, 0xb0, 0x53, 0x00, + 0x00, 0x7a, 0xda, 0xff, 0xff, 0x7f, 0x0c, 0x00, 0x00, 0x01, 0x43, 0x00, 0x00, + 0x2e, 0x07, 0x00, 0x00, 0x89, 0xf3, 0xff, 0xff, 0xdf, 0x2b, 0x00, 0x00, 0xb1, + 0x61, 0x00, 0x00, 0xe0, 0x1c, 0x00, 0x00, 0x95, 0x4d, 0x00, 0x00, 0x02, 0x01, + 0x00, 0x00, 0x9e, 0x40, 0x00, 0x00, 0x44, 0x4a, 0x00, 0x00, 0xa2, 0xcb, 0xff, + 0xff, 0x9d, 0x16, 0x00, 0x00, 0xca, 0x47, 0x00, 0x00, 0x33, 0x0e, 0x00, 0x00, + 0x2e, 0x50, 0x00, 0x00, 0xf9, 0x28, 0x00, 0x00, 0x40, 0x17, 0x00, 0x00, 0x03, + 0x57, 0x00, 0x00, 0xfe, 0xe3, 0xff, 0xff, 0xa8, 0x2f, 0x00, 0x00, 0xe9, 0x00, + 0x00, 0x00, 0xa6, 0x07, 0x00, 0x00, 0x78, 0x10, 0x00, 0x00, 0xd3, 0x45, 0x00, + 0x00, 0xd3, 0xce, 0xff, 0xff, 0x0f, 0x2d, 0x00, 0x00, 0x83, 0xf4, 0xff, 0xff, + 0xba, 0x2a, 0x00, 0x00, 0xec, 0x15, 0x00, 0x00, 0x94, 0x5d, 0x00, 0x00, 0x83, + 0x0e, 0x00, 0x00, 0xe6, 0x1c, 0x00, 0x00, 0x98, 0x39, 0x00, 0x00, 0x9c, 0x3a, + 0x00, 0x00, 0x7e, 0x05, 0x00, 0x00, 0x17, 0x46, 0x00, 0x00, 0xa8, 0xf9, 0xff, + 0xff, 0x40, 0x0d, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00, 0x1a, 0x07, 0x00, 0x00, + 0x32, 0x23, 0x00, 0x00, 0x3f, 0x0c, 0x00, 0x00, 0xd5, 0x08, 0x00, 0x00, 0x3c, + 0x01, 0x00, 0x00, 0xe3, 0x75, 0x00, 0x00, 0xa3, 0x1f, 0x00, 0x00, 0xa1, 0x27, + 0x00, 0x00, 0xd0, 0x23, 0x00, 0x00, 0xeb, 0xdc, 0xff, 0xff, 0x99, 0x05, 0x00, + 0x00, 0x27, 0x0e, 0x00, 0x00, 0xd7, 0xf2, 0xff, 0xff, 0xce, 0xfc, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xf1, 0x25, 0xba, 0xa3, 0xe0, + 0xeb, 0xbd, 0x28, 0xce, 0x20, 0xc9, 0xfb, 0x37, 0x28, 0x43, 0xea, 0x70, 0xa9, + 0xe0, 0x2c, 0xe1, 0x9e, 0x5f, 0xc9, 0x52, 0xd2, 0x28, 0x21, 0xcb, 0xef, 0xc2, + 0x08, 0x13, 0xc5, 0x29, 0xfa, 0x40, 0xfa, 0x0d, 0xfd, 0xdb, 0x16, 0x50, 0x43, + 0xb5, 0xf1, 0x5d, 0xdc, 0x2d, 0x42, 0x0d, 0xd9, 0x94, 0x22, 0xae, 0x1f, 0x31, + 0x13, 0xcc, 0xcf, 0xc2, 0xa6, 0x81, 0xc5, 0xaa, 0x17, 0xaf, 0xef, 0xd4, 0x0c, + 0xab, 0xb2, 0xa8, 0x12, 0x36, 0xa5, 0x3c, 0xd4, 0xbf, 0xbb, 0xca, 0x0f, 0xaf, + 0x14, 0xb6, 0xdb, 0xb0, 0xcb, 0xb1, 0x8b, 0x31, 0xd0, 0x19, 0xcd, 0xab, 0x47, + 0x16, 0xb8, 0x29, 0xa8, 0xfa, 0x82, 0x59, 0xa5, 0xad, 0xb2, 0xa6, 0xde, 0xbf, + 0xbd, 0x17, 0xcf, 0xb9, 0x1a, 0xcd, 0x17, 0xc4, 0xe2, 0xd0, 0xe2, 0x2f, 0xc8, + 0xbf, 0x3e, 0xd4, 0xbe, 0xae, 0xe6, 0x03, 0x1b, 0x2e, 0x47, 0xa0, 0xe2, 0xb4, + 0xc4, 0x28, 0xb1, 0xb7, 0xe4, 0x18, 0x00, 0xcb, 0x18, 0x3a, 0xea, 0x01, 0x22, + 0xe1, 0xb8, 0xd9, 0xfd, 0xbb, 0xd3, 0xd5, 0xc7, 0xde, 0xc1, 0xf8, 0xab, 0xab, + 0x44, 0xb7, 0x08, 0xd9, 0xd2, 0xc9, 0xfe, 0xa4, 0x1a, 0xd8, 0xc5, 0x22, 0x9a, + 0x48, 0xd6, 0x30, 0x38, 0x1e, 0x38, 0xb8, 0xeb, 0x1f, 0x10, 0xd8, 0xbe, 0x15, + 0xde, 0x24, 0x0d, 0x14, 0xa7, 0x97, 0xab, 0x26, 0xeb, 0xe7, 0x9b, 0xd4, 0xb2, + 0xf3, 0xc8, 0x5d, 0x33, 0x0f, 0xce, 0xc5, 0xce, 0xaa, 0x50, 0xbc, 0x1e, 0x11, + 0xbe, 0xde, 0xe2, 0xc6, 0xee, 0xba, 0xf4, 0xe9, 0x0e, 0x97, 0x30, 0x3f, 0x01, + 0xd8, 0x5c, 0x0f, 0xec, 0x22, 0xe0, 0x3e, 0xbb, 0xd8, 0x39, 0xc1, 0xb3, 0x02, + 0x15, 0xd0, 0x17, 0xf9, 0x32, 0xc6, 0xcf, 0xb2, 0xbc, 0x20, 0xbb, 0xd3, 0xc7, + 0x2c, 0xb9, 0xd7, 0x2f, 0x1c, 0xe4, 0x4d, 0x65, 0x2e, 0x08, 0x32, 0xd8, 0x38, + 0xe1, 0x52, 0x19, 0xc4, 0xf2, 0xb8, 0x16, 0x91, 0x5a, 0x27, 0xca, 0x20, 0x74, + 0xa5, 0x22, 0xb3, 0x2e, 0xdd, 0xe5, 0x2c, 0x14, 0x42, 0xf7, 0xe5, 0x40, 0xc0, + 0xf9, 0xb8, 0x07, 0xee, 0x0f, 0x1e, 0xed, 0xa3, 0xc8, 0x3b, 0x0d, 0xa4, 0x0f, + 0xe8, 0xb8, 0xfd, 0x16, 0x64, 0xd9, 0x46, 0xe3, 0xce, 0xe9, 0x2d, 0x48, 0x34, + 0x4f, 0x78, 0x3a, 0x56, 0xe2, 0x55, 0x0d, 0x40, 0xf9, 0x4e, 0x5f, 0x68, 0xea, + 0xb9, 0x63, 0xc9, 0x30, 0x50, 0x57, 0x30, 0xfb, 0x4d, 0xf6, 0x55, 0x2c, 0x56, + 0x35, 0x5e, 0x78, 0xd3, 0x37, 0xe9, 0x3f, 0x64, 0xb0, 0xe5, 0x49, 0xdb, 0x55, + 0x10, 0x7f, 0x9a, 0x61, 0x47, 0x4e, 0x52, 0x27, 0x44, 0x45, 0xdf, 0x2e, 0x46, + 0xe4, 0x53, 0xe4, 0x2c, 0x28, 0x2f, 0x2b, 0xd6, 0x3e, 0x37, 0xbb, 0x28, 0x43, + 0x59, 0x18, 0xe8, 0xd4, 0xe8, 0xd0, 0x5f, 0x0a, 0x47, 0x43, 0xe5, 0x4f, 0x62, + 0x22, 0xf4, 0x00, 0x32, 0xee, 0xb8, 0x27, 0xfd, 0xde, 0x3f, 0x3b, 0x43, 0x05, + 0x4b, 0x38, 0x3c, 0x31, 0x29, 0x40, 0x10, 0x3c, 0x65, 0x9d, 0x38, 0xe0, 0x23, + 0x1e, 0x38, 0xfe, 0x52, 0xed, 0x31, 0x44, 0xd8, 0x6c, 0xb0, 0x33, 0xd4, 0xd4, + 0xf7, 0xca, 0x4f, 0x10, 0xd6, 0xf2, 0x2c, 0x3d, 0xee, 0x1f, 0xe7, 0x00, 0xf0, + 0x58, 0x6d, 0x5d, 0xc1, 0x1b, 0x0d, 0x6a, 0x27, 0x55, 0x05, 0x43, 0xa8, 0xdd, + 0xe8, 0x2a, 0x46, 0x44, 0x53, 0xb4, 0x29, 0xcc, 0xdb, 0x46, 0x26, 0x27, 0x52, + 0x0e, 0x45, 0xfd, 0x17, 0xe1, 0x6b, 0xe1, 0xb5, 0x01, 0x2b, 0x99, 0xf9, 0x23, + 0xe7, 0x34, 0xcb, 0x39, 0x2d, 0xc2, 0x43, 0x5a, 0x0e, 0xeb, 0x3b, 0xe4, 0x19, + 0xd4, 0x4c, 0x30, 0x6b, 0x3e, 0xdc, 0x46, 0x39, 0x38, 0xce, 0x47, 0x2c, 0xc6, + 0xda, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x8b, + 0x3f, 0x00, 0x00, 0x49, 0xbd, 0xff, 0xff, 0xee, 0xfe, 0xff, 0xff, 0x04, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0xd8, 0x56, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x54, 0x4f, 0x43, 0x4f, + 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x78, 0x54, 0xff, 0xff, 0xf0, 0x08, + 0x00, 0x00, 0xe4, 0x08, 0x00, 0x00, 0xd8, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x78, 0x08, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, + 0xc0, 0x07, 0x00, 0x00, 0x78, 0x07, 0x00, 0x00, 0x34, 0x07, 0x00, 0x00, 0xec, + 0x06, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x1c, 0x06, + 0x00, 0x00, 0xd4, 0x05, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x48, 0x05, 0x00, + 0x00, 0x04, 0x05, 0x00, 0x00, 0xbc, 0x04, 0x00, 0x00, 0x78, 0x04, 0x00, 0x00, + 0x30, 0x04, 0x00, 0x00, 0xec, 0x03, 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x60, + 0x03, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x8c, 0x02, + 0x00, 0x00, 0x48, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xbc, 0x01, 0x00, + 0x00, 0x74, 0x01, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0x84, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x66, + 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xce, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x42, 0xf8, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x11, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x8a, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x10, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3c, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x07, + 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x82, 0xf9, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd0, 0xf9, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xc2, 0xf9, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x5e, 0xf9, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x2e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, + 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x54, 0xfa, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x46, 0xfa, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe2, 0xf9, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, + 0x00, 0x8a, 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd8, + 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0xca, 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x66, 0xfa, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x0e, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x5c, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x25, 0x00, + 0x00, 0x00, 0x4e, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xea, 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x00, 0x92, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0xe0, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0xd2, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x02, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x6e, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x53, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x19, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x16, 0xfc, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x52, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x56, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xf2, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, + 0x00, 0x17, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x9a, 0xfc, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe8, 0xfc, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0xda, 0xfc, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x76, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x1e, 0xfd, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6c, 0xfd, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, + 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x5e, 0xfd, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xfa, 0xfc, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x46, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0xa2, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf0, 0xfd, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x43, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0xe2, + 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7e, 0xfd, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x44, 0x00, + 0x00, 0x00, 0x26, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x74, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x66, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, + 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0xaa, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0xf8, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x86, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3b, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x0d, 0x00, + 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x2e, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x7c, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x39, 0x00, 0x00, 0x00, 0x6e, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x37, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xb2, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x0c, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x08, + 0x00, 0x0c, 0x00, 0x10, 0x00, 0x07, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x00, 0x1a, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x07, 0x00, + 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, + 0x00, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x22, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x57, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x59, 0x00, + 0x00, 0x00, 0xb4, 0x2f, 0x01, 0x00, 0x1c, 0x29, 0x01, 0x00, 0x88, 0x22, 0x01, + 0x00, 0x04, 0x1c, 0x01, 0x00, 0x8c, 0x15, 0x01, 0x00, 0x04, 0x0f, 0x01, 0x00, + 0x8c, 0x02, 0x01, 0x00, 0x04, 0xf6, 0x00, 0x00, 0x8c, 0xe9, 0x00, 0x00, 0xa4, + 0xe8, 0x00, 0x00, 0x6c, 0xe7, 0x00, 0x00, 0x24, 0xe6, 0x00, 0x00, 0x2c, 0xe4, + 0x00, 0x00, 0x24, 0xe2, 0x00, 0x00, 0x2c, 0xe0, 0x00, 0x00, 0x24, 0xde, 0x00, + 0x00, 0xac, 0xda, 0x00, 0x00, 0x24, 0xd7, 0x00, 0x00, 0xac, 0xd3, 0x00, 0x00, + 0x24, 0xd0, 0x00, 0x00, 0xac, 0xc9, 0x00, 0x00, 0x24, 0xc3, 0x00, 0x00, 0xac, + 0xbc, 0x00, 0x00, 0x24, 0xb6, 0x00, 0x00, 0xac, 0xaf, 0x00, 0x00, 0x24, 0xa9, + 0x00, 0x00, 0xac, 0xa2, 0x00, 0x00, 0x0c, 0xa2, 0x00, 0x00, 0x74, 0xa1, 0x00, + 0x00, 0xf0, 0xa0, 0x00, 0x00, 0x5c, 0xa0, 0x00, 0x00, 0xd0, 0x9f, 0x00, 0x00, + 0x78, 0x9f, 0x00, 0x00, 0xa4, 0x9e, 0x00, 0x00, 0x0c, 0x9e, 0x00, 0x00, 0x68, + 0x9d, 0x00, 0x00, 0xe8, 0x96, 0x00, 0x00, 0x70, 0x90, 0x00, 0x00, 0xcc, 0x8f, + 0x00, 0x00, 0x28, 0x8f, 0x00, 0x00, 0xa8, 0x88, 0x00, 0x00, 0x30, 0x82, 0x00, + 0x00, 0x8c, 0x81, 0x00, 0x00, 0xe8, 0x80, 0x00, 0x00, 0x68, 0x7a, 0x00, 0x00, + 0xf0, 0x6d, 0x00, 0x00, 0x4c, 0x6d, 0x00, 0x00, 0xa8, 0x6c, 0x00, 0x00, 0x28, + 0x60, 0x00, 0x00, 0xb0, 0x53, 0x00, 0x00, 0x0c, 0x53, 0x00, 0x00, 0x68, 0x52, + 0x00, 0x00, 0x88, 0x51, 0x00, 0x00, 0x50, 0x50, 0x00, 0x00, 0xac, 0x4f, 0x00, + 0x00, 0x08, 0x4f, 0x00, 0x00, 0xc8, 0x4d, 0x00, 0x00, 0xd0, 0x4b, 0x00, 0x00, + 0x2c, 0x4b, 0x00, 0x00, 0x88, 0x4a, 0x00, 0x00, 0x88, 0x48, 0x00, 0x00, 0x90, + 0x46, 0x00, 0x00, 0xec, 0x45, 0x00, 0x00, 0x48, 0x45, 0x00, 0x00, 0x48, 0x43, + 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0x2c, 0x3f, 0x00, 0x00, 0x88, 0x3e, 0x00, + 0x00, 0x08, 0x3b, 0x00, 0x00, 0x90, 0x37, 0x00, 0x00, 0xec, 0x36, 0x00, 0x00, + 0x48, 0x36, 0x00, 0x00, 0xc8, 0x32, 0x00, 0x00, 0x50, 0x2c, 0x00, 0x00, 0xac, + 0x2b, 0x00, 0x00, 0x08, 0x2b, 0x00, 0x00, 0x88, 0x24, 0x00, 0x00, 0x10, 0x1e, + 0x00, 0x00, 0x6c, 0x1d, 0x00, 0x00, 0xc8, 0x1c, 0x00, 0x00, 0x48, 0x16, 0x00, + 0x00, 0xd0, 0x0f, 0x00, 0x00, 0x2c, 0x0f, 0x00, 0x00, 0x88, 0x0e, 0x00, 0x00, + 0x08, 0x08, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x52, 0xd8, 0xfe, 0xff, 0x00, 0x00, + 0x00, 0x09, 0x54, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0xec, 0x5e, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x81, 0x80, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf, 0x05, 0x00, 0x00, 0x00, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0xc2, 0xd8, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x09, 0x5c, 0x00, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x44, 0xdf, 0xfe, 0xff, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3b, 0x21, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x50, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x52, + 0x65, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x32, 0xd9, 0xfe, + 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xcc, 0x5f, 0xff, 0xff, 0x30, + 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, + 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x39, + 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, + 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0xd2, 0xd9, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x02, 0x64, 0x06, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x54, + 0xe0, 0xfe, 0xff, 0x10, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x09, 0xc1, 0x56, 0x38, 0x70, 0xbe, + 0x8a, 0x38, 0xc6, 0x5e, 0x5c, 0x38, 0x6b, 0x13, 0x7e, 0x38, 0x35, 0xee, 0x4e, + 0x38, 0x92, 0x3c, 0xb2, 0x38, 0x73, 0x8f, 0x83, 0x38, 0x0e, 0x10, 0x96, 0x38, + 0x30, 0xad, 0x59, 0x38, 0x3a, 0xfb, 0x97, 0x38, 0x7d, 0xae, 0x8d, 0x38, 0x37, + 0x9b, 0x8a, 0x38, 0x06, 0xbc, 0x4d, 0x38, 0x17, 0x10, 0x7e, 0x38, 0x6a, 0xf4, + 0x80, 0x38, 0x76, 0x67, 0x2f, 0x38, 0xcc, 0x91, 0x68, 0x38, 0x9a, 0x18, 0x55, + 0x38, 0x1b, 0x65, 0x30, 0x38, 0x52, 0xad, 0x97, 0x38, 0x99, 0x46, 0x80, 0x38, + 0x7e, 0x0e, 0x81, 0x38, 0x50, 0xe4, 0x69, 0x38, 0xc7, 0x6b, 0x51, 0x38, 0x9b, + 0x88, 0x39, 0x38, 0xf3, 0xa1, 0xc5, 0x38, 0x62, 0xe9, 0x42, 0x38, 0x89, 0xe8, + 0xad, 0x38, 0x8e, 0xc1, 0xc0, 0x38, 0x2c, 0xf5, 0x85, 0x38, 0x94, 0xee, 0x7c, + 0x38, 0x4c, 0xde, 0x9f, 0x38, 0xea, 0xa8, 0x98, 0x38, 0xe4, 0x06, 0x5e, 0x38, + 0x83, 0x3e, 0x92, 0x38, 0x1b, 0x6c, 0x4d, 0x38, 0x38, 0xee, 0x8d, 0x38, 0xe2, + 0xb2, 0x82, 0x38, 0x8e, 0xc1, 0x55, 0x38, 0xc9, 0x3b, 0x9d, 0x38, 0xf6, 0x00, + 0x9a, 0x38, 0x65, 0x1f, 0x9f, 0x38, 0x38, 0xc2, 0x5a, 0x38, 0x8c, 0x70, 0x7b, + 0x38, 0xa7, 0x22, 0x53, 0x38, 0xe2, 0xe7, 0x55, 0x38, 0xfc, 0xcf, 0x8c, 0x38, + 0xed, 0x8b, 0x7a, 0x38, 0x13, 0xa5, 0x86, 0x38, 0x7f, 0xf3, 0x87, 0x38, 0x76, + 0x25, 0x69, 0x38, 0x2e, 0x32, 0x80, 0x38, 0x72, 0x5e, 0x95, 0x38, 0x7a, 0x2c, + 0x85, 0x38, 0xc3, 0x7d, 0x94, 0x38, 0x50, 0x99, 0x97, 0x38, 0x0a, 0x98, 0x80, + 0x38, 0x47, 0xa5, 0x4c, 0x38, 0x61, 0x07, 0x7c, 0x38, 0x4b, 0x39, 0x82, 0x38, + 0xc3, 0x09, 0x6f, 0x38, 0x41, 0xb8, 0x78, 0x38, 0x5f, 0x0e, 0x51, 0x38, 0x23, + 0xc2, 0x86, 0x38, 0x30, 0xc3, 0x98, 0x38, 0xa8, 0x15, 0x80, 0x38, 0xea, 0xe4, + 0x8b, 0x38, 0x8b, 0x83, 0x86, 0x38, 0x03, 0xff, 0x52, 0x38, 0x19, 0xcf, 0x84, + 0x38, 0x30, 0xfe, 0xad, 0x38, 0xd5, 0x13, 0x56, 0x38, 0x41, 0x60, 0x7f, 0x38, + 0x73, 0xa4, 0x81, 0x38, 0xd9, 0x0d, 0xbc, 0x38, 0xf5, 0xae, 0xa6, 0x38, 0x59, + 0xa6, 0x7f, 0x38, 0x04, 0xb7, 0x91, 0x38, 0xb0, 0x51, 0x88, 0x38, 0xdf, 0x68, + 0x85, 0x38, 0x73, 0xfc, 0x88, 0x38, 0x3e, 0xf8, 0x79, 0x38, 0xf6, 0x38, 0x97, + 0x38, 0x69, 0x3e, 0x97, 0x38, 0x50, 0xf3, 0x7a, 0x38, 0x91, 0x57, 0x5d, 0x38, + 0x06, 0x22, 0x63, 0x38, 0xaf, 0x51, 0x7c, 0x38, 0x6e, 0x68, 0xa1, 0x38, 0x08, + 0x2a, 0xa3, 0x38, 0x5b, 0x07, 0xb2, 0x38, 0x36, 0x72, 0x95, 0x38, 0x02, 0xcf, + 0x6e, 0x38, 0x17, 0x6b, 0x84, 0x38, 0x7f, 0x72, 0x78, 0x38, 0xc7, 0x37, 0x78, + 0x38, 0xb3, 0xd1, 0x61, 0x38, 0x69, 0xc3, 0x96, 0x38, 0x8e, 0x04, 0x50, 0x38, + 0x4b, 0x1c, 0x89, 0x38, 0x7d, 0x9d, 0x7f, 0x38, 0xb0, 0x7d, 0x5f, 0x38, 0xe8, + 0x6b, 0x70, 0x38, 0xd3, 0x12, 0x65, 0x38, 0x5b, 0x57, 0x91, 0x38, 0x35, 0x42, + 0x6d, 0x38, 0x3d, 0xa2, 0x89, 0x38, 0xa9, 0xdb, 0x56, 0x38, 0x8e, 0x11, 0x5f, + 0x38, 0x0b, 0x42, 0x4b, 0x38, 0xe7, 0x81, 0xc2, 0x38, 0x9e, 0xfc, 0x61, 0x38, + 0x95, 0xd3, 0xb9, 0x38, 0x15, 0x9f, 0x93, 0x38, 0x07, 0x4e, 0x39, 0x38, 0x9e, + 0xa7, 0x70, 0x38, 0x4d, 0xd4, 0x61, 0x38, 0xc6, 0x72, 0x70, 0x38, 0x04, 0xf0, + 0xa8, 0x38, 0x59, 0x15, 0xd0, 0x38, 0x9c, 0x9a, 0xbf, 0x38, 0x39, 0x42, 0x84, + 0x38, 0xfa, 0x8a, 0x8d, 0x38, 0x36, 0x1c, 0x3a, 0x38, 0xfc, 0x64, 0x61, 0x38, + 0x61, 0xb6, 0x73, 0x38, 0x3d, 0x27, 0x75, 0x38, 0xd9, 0xc4, 0x97, 0x38, 0x36, + 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, + 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, + 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x39, 0x5f, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, + 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x46, 0xe0, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x02, 0x6c, 0x06, 0x00, + 0x00, 0x11, 0x00, 0x00, 0x00, 0x24, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xa2, 0xd9, 0xfe, 0xff, 0x14, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x8f, + 0xcb, 0x23, 0x39, 0x92, 0x83, 0xcf, 0x38, 0x7c, 0x0d, 0xdd, 0x38, 0xbc, 0x8b, + 0x0a, 0x39, 0x18, 0x12, 0x7a, 0x39, 0x9b, 0x70, 0x06, 0x39, 0x6a, 0xc6, 0xff, + 0x38, 0x8b, 0x50, 0x1d, 0x39, 0x18, 0xe3, 0xe4, 0x38, 0xf7, 0x10, 0xdb, 0x38, + 0x6c, 0xc8, 0x1a, 0x39, 0x79, 0x8f, 0x3f, 0x39, 0xb3, 0x01, 0xe1, 0x38, 0xde, + 0x9f, 0xd4, 0x38, 0xdb, 0x07, 0x55, 0x39, 0xea, 0x41, 0x30, 0x39, 0xf5, 0xa0, + 0x3a, 0x39, 0x4b, 0x1f, 0x00, 0x39, 0x59, 0xf8, 0xe1, 0x38, 0xea, 0x98, 0xae, + 0x38, 0x56, 0x25, 0x36, 0x39, 0x43, 0x8e, 0xda, 0x38, 0xa3, 0x92, 0x53, 0x39, + 0xd0, 0x31, 0x66, 0x39, 0x14, 0x14, 0x51, 0x39, 0xa9, 0xf9, 0x2a, 0x39, 0x56, + 0x7e, 0xd5, 0x38, 0x7a, 0x79, 0x55, 0x39, 0xfc, 0xb2, 0x3a, 0x39, 0x8e, 0x31, + 0x95, 0x39, 0x4d, 0x04, 0x49, 0x39, 0x61, 0xaf, 0x20, 0x39, 0xa4, 0xb7, 0x04, + 0x39, 0x80, 0x50, 0x2a, 0x39, 0xff, 0xd1, 0x1a, 0x39, 0x4b, 0xe2, 0x3b, 0x39, + 0x02, 0xbb, 0x21, 0x39, 0x92, 0x95, 0x02, 0x39, 0xba, 0x20, 0x04, 0x39, 0x61, + 0x09, 0x6b, 0x39, 0x8b, 0x71, 0xca, 0x38, 0x98, 0x2e, 0x08, 0x39, 0xf6, 0xa6, + 0xe1, 0x38, 0x29, 0x2a, 0x43, 0x39, 0x0f, 0x60, 0x36, 0x39, 0xe2, 0x80, 0x08, + 0x39, 0xa7, 0x75, 0xf3, 0x38, 0xd4, 0x07, 0x09, 0x39, 0x68, 0x6f, 0x6c, 0x39, + 0xe4, 0x93, 0x7f, 0x39, 0xa9, 0x4c, 0x04, 0x39, 0x53, 0x42, 0x4a, 0x39, 0xe4, + 0x10, 0x1f, 0x39, 0x80, 0x86, 0xe8, 0x38, 0x73, 0xef, 0x04, 0x39, 0xf8, 0xa4, + 0x05, 0x39, 0x28, 0x51, 0x15, 0x39, 0x1e, 0x0c, 0x23, 0x39, 0x8c, 0x98, 0xa8, + 0x39, 0x05, 0x83, 0x7a, 0x39, 0xd1, 0x6b, 0x1a, 0x39, 0x17, 0x32, 0x8c, 0x39, + 0xb9, 0xa8, 0x18, 0x39, 0x00, 0x47, 0x03, 0x39, 0x0b, 0x94, 0x23, 0x39, 0xb5, + 0xd3, 0x5c, 0x39, 0x92, 0xba, 0xd8, 0x38, 0x4b, 0x61, 0x18, 0x39, 0x41, 0x3f, + 0x6f, 0x39, 0x84, 0x04, 0xac, 0x38, 0x30, 0x2b, 0x48, 0x39, 0xa4, 0x34, 0x23, + 0x39, 0x8b, 0x5e, 0xe8, 0x38, 0x2a, 0x30, 0xe6, 0x38, 0xf0, 0x4c, 0x09, 0x39, + 0x29, 0xe9, 0xac, 0x39, 0x2a, 0xdf, 0x08, 0x39, 0xed, 0x3c, 0x30, 0x39, 0x8f, + 0x37, 0xf1, 0x38, 0x94, 0xf6, 0xd6, 0x38, 0x8e, 0x51, 0xee, 0x38, 0x39, 0x4a, + 0x0f, 0x39, 0x83, 0xca, 0x44, 0x39, 0x70, 0x12, 0xf0, 0x38, 0x93, 0x9a, 0x34, + 0x39, 0x77, 0xfc, 0xdc, 0x38, 0x3b, 0xaa, 0xf1, 0x38, 0x86, 0x48, 0x16, 0x39, + 0x52, 0xb3, 0x3c, 0x39, 0xd2, 0x02, 0x37, 0x39, 0xba, 0x0a, 0xe7, 0x38, 0xe5, + 0x71, 0xfc, 0x38, 0x2d, 0x79, 0x05, 0x39, 0xb7, 0x1e, 0xb7, 0x38, 0x7f, 0x1e, + 0x97, 0x39, 0x91, 0xcc, 0xd1, 0x38, 0x2b, 0x81, 0x36, 0x39, 0xb6, 0x3f, 0x4a, + 0x39, 0x2f, 0x77, 0xe9, 0x38, 0xfc, 0x08, 0xe2, 0x38, 0xdb, 0xac, 0x41, 0x39, + 0x6e, 0x60, 0xe8, 0x38, 0x32, 0x5a, 0x0a, 0x39, 0x8c, 0x3a, 0xd8, 0x38, 0x97, + 0x15, 0xd5, 0x38, 0x4d, 0x54, 0xf7, 0x38, 0xc6, 0x45, 0x3a, 0x39, 0xcf, 0x4c, + 0x24, 0x39, 0xf7, 0x4e, 0x00, 0x39, 0x9b, 0xa0, 0x3f, 0x39, 0x7c, 0x4c, 0xeb, + 0x38, 0x34, 0x60, 0x40, 0x39, 0xd8, 0xdc, 0xe2, 0x38, 0x21, 0x86, 0xce, 0x38, + 0x5f, 0x05, 0x0d, 0x39, 0x79, 0x9f, 0x01, 0x39, 0x15, 0xa6, 0x19, 0x39, 0x70, + 0x6d, 0x1a, 0x39, 0x0e, 0xe6, 0x4b, 0x39, 0x22, 0x44, 0x35, 0x39, 0x7a, 0x72, + 0x45, 0x39, 0x75, 0x03, 0xb3, 0x38, 0xdf, 0x93, 0xe4, 0x38, 0xcf, 0x69, 0xd4, + 0x38, 0x56, 0xa3, 0x02, 0x39, 0x29, 0x15, 0xd1, 0x38, 0xf9, 0x55, 0xf6, 0x38, + 0xea, 0x4f, 0x0f, 0x39, 0x39, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x39, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x62, 0x69, 0x61, 0x73, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc2, 0xe6, + 0xfe, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, + 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x5c, 0x6d, 0xff, 0xff, + 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, + 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x39, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, + 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x62, 0xe7, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, + 0x00, 0x2b, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xfc, 0x6d, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x38, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, + 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0xe8, 0xfe, 0xff, 0x00, 0x00, 0x00, + 0x02, 0x64, 0x06, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x84, 0xee, 0xfe, 0xff, 0x10, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, + 0x87, 0x53, 0x38, 0x9e, 0xa2, 0x7d, 0x38, 0x7f, 0xbe, 0x75, 0x38, 0xa1, 0x24, + 0x71, 0x38, 0x94, 0x4d, 0xb1, 0x38, 0x29, 0xe9, 0xae, 0x38, 0x71, 0x40, 0x73, + 0x38, 0x2d, 0x97, 0x66, 0x38, 0x02, 0xf5, 0x6a, 0x38, 0xdf, 0xd8, 0x99, 0x38, + 0x88, 0x06, 0x87, 0x38, 0xd1, 0xe2, 0x82, 0x38, 0x30, 0xc7, 0x82, 0x38, 0x47, + 0x1e, 0x87, 0x38, 0xc7, 0x7d, 0x50, 0x38, 0xac, 0x3f, 0x59, 0x38, 0xf9, 0xac, + 0x8c, 0x38, 0x30, 0xa1, 0x91, 0x38, 0x5b, 0x15, 0x7f, 0x38, 0xff, 0xfa, 0x54, + 0x38, 0x85, 0x90, 0x8c, 0x38, 0x37, 0x35, 0x7e, 0x38, 0xfa, 0xe0, 0x88, 0x38, + 0x18, 0x32, 0x87, 0x38, 0x52, 0x6e, 0x92, 0x38, 0xf0, 0xb0, 0x7e, 0x38, 0x18, + 0xd4, 0x73, 0x38, 0x67, 0x2d, 0x95, 0x38, 0x44, 0x40, 0x83, 0x38, 0x8c, 0xae, + 0x83, 0x38, 0x22, 0xa0, 0x86, 0x38, 0x1a, 0xad, 0x94, 0x38, 0xed, 0xfd, 0x8f, + 0x38, 0xa1, 0x1d, 0x65, 0x38, 0xff, 0x45, 0x67, 0x38, 0x24, 0x9b, 0x85, 0x38, + 0xfb, 0x5f, 0xb1, 0x38, 0xee, 0xe4, 0x8e, 0x38, 0x3f, 0xd4, 0x83, 0x38, 0x67, + 0x1c, 0x70, 0x38, 0xab, 0xef, 0x8a, 0x38, 0x9e, 0x4b, 0x83, 0x38, 0x4d, 0x92, + 0x5c, 0x38, 0xd9, 0x84, 0x7a, 0x38, 0x41, 0xde, 0x51, 0x38, 0x2d, 0x3c, 0x75, + 0x38, 0x6d, 0x6f, 0x96, 0x38, 0xb5, 0x6d, 0x95, 0x38, 0xdc, 0xf4, 0x31, 0x38, + 0x74, 0x9c, 0x2c, 0x38, 0xb6, 0x91, 0x8b, 0x38, 0xa3, 0xac, 0x32, 0x38, 0x8e, + 0xf8, 0x80, 0x38, 0x33, 0x35, 0x66, 0x38, 0x91, 0x5c, 0x41, 0x38, 0x70, 0x7b, + 0x88, 0x38, 0xa8, 0x31, 0x85, 0x38, 0x4a, 0xf1, 0x50, 0x38, 0x20, 0x68, 0x86, + 0x38, 0x2f, 0x82, 0x80, 0x38, 0x08, 0x63, 0x43, 0x38, 0x62, 0x65, 0x70, 0x38, + 0x5b, 0x58, 0x84, 0x38, 0x3c, 0x49, 0x97, 0x38, 0x98, 0x68, 0x60, 0x38, 0xd0, + 0xe8, 0x83, 0x38, 0x62, 0xca, 0x4b, 0x38, 0xc5, 0xaf, 0x81, 0x38, 0x0f, 0x62, + 0x73, 0x38, 0xff, 0xbd, 0x7f, 0x38, 0xc6, 0x43, 0x9f, 0x38, 0x96, 0x2d, 0x93, + 0x38, 0x40, 0x9d, 0x8f, 0x38, 0x54, 0xaa, 0xac, 0x38, 0x20, 0x51, 0xb0, 0x38, + 0x8e, 0xa3, 0x84, 0x38, 0xaa, 0x0f, 0xb8, 0x38, 0xad, 0x3d, 0x5f, 0x38, 0x45, + 0x6d, 0x83, 0x38, 0x4d, 0x6c, 0x6a, 0x38, 0xea, 0xc4, 0x87, 0x38, 0xa7, 0x52, + 0xac, 0x38, 0x12, 0xef, 0x95, 0x38, 0xeb, 0x1b, 0x8b, 0x38, 0xf0, 0xe9, 0xaf, + 0x38, 0xb3, 0xf3, 0x81, 0x38, 0xe4, 0xa8, 0x3e, 0x38, 0xde, 0x8f, 0x5d, 0x38, + 0xaa, 0xd3, 0x44, 0x38, 0x61, 0x96, 0x87, 0x38, 0x40, 0x35, 0x7a, 0x38, 0xf3, + 0x84, 0x90, 0x38, 0x05, 0x94, 0x79, 0x38, 0x90, 0x70, 0x93, 0x38, 0xa9, 0x54, + 0x6c, 0x38, 0x5d, 0x5e, 0x81, 0x38, 0xd6, 0x95, 0xa7, 0x38, 0xc0, 0xd9, 0x8d, + 0x38, 0xb8, 0xd5, 0x62, 0x38, 0x94, 0x3e, 0x6c, 0x38, 0x0c, 0xf8, 0xa4, 0x38, + 0xd5, 0x76, 0x54, 0x38, 0xe6, 0xe2, 0x93, 0x38, 0x74, 0x27, 0x3d, 0x38, 0x9e, + 0xcb, 0x93, 0x38, 0xeb, 0x8c, 0x5d, 0x38, 0x6f, 0x7d, 0x94, 0x38, 0x2e, 0x42, + 0xb9, 0x38, 0x94, 0x65, 0x55, 0x38, 0x1a, 0xe5, 0x66, 0x38, 0x17, 0x0f, 0x55, + 0x38, 0xbe, 0x91, 0x84, 0x38, 0x1b, 0xc5, 0x89, 0x38, 0x72, 0x38, 0x85, 0x38, + 0x87, 0xcc, 0x8f, 0x38, 0x96, 0x71, 0x83, 0x38, 0xbd, 0x04, 0x6f, 0x38, 0x33, + 0x99, 0x3c, 0x38, 0x73, 0x9d, 0x7d, 0x38, 0x8f, 0x0d, 0x4b, 0x38, 0xa4, 0x6f, + 0x73, 0x38, 0xca, 0xbf, 0x69, 0x38, 0x64, 0x33, 0x7e, 0x38, 0x55, 0x02, 0x81, + 0x38, 0xe5, 0xd2, 0x96, 0x38, 0x27, 0x00, 0x5d, 0x38, 0xd2, 0x15, 0x7b, 0x38, + 0xbf, 0xea, 0x81, 0x38, 0x36, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x38, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x43, + 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x76, 0xee, 0xfe, 0xff, 0x00, 0x00, + 0x00, 0x02, 0x6c, 0x06, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x24, 0x06, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0xd2, 0xe7, 0xfe, 0xff, 0x14, 0x04, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x6c, 0xe2, 0x0b, 0x39, 0xc3, 0x54, 0x4b, 0x39, 0x78, + 0x29, 0x00, 0x39, 0x17, 0x23, 0xcd, 0x38, 0xa2, 0x60, 0x0c, 0x39, 0xf0, 0xcc, + 0x5e, 0x39, 0x9b, 0x41, 0x5d, 0x39, 0x8d, 0xb7, 0x25, 0x39, 0x5c, 0xc1, 0xdf, + 0x38, 0x54, 0x8d, 0x01, 0x39, 0x37, 0x5d, 0xf5, 0x38, 0xa0, 0xf1, 0x70, 0x39, + 0x3e, 0xb2, 0xfd, 0x38, 0x98, 0x3f, 0xe4, 0x38, 0x65, 0x48, 0xd0, 0x38, 0x3e, + 0x60, 0xdd, 0x38, 0xcd, 0x65, 0x7b, 0x39, 0xed, 0xa9, 0x21, 0x39, 0x7c, 0x44, + 0x8c, 0x39, 0x68, 0xf2, 0xf6, 0x38, 0xa0, 0x2a, 0x85, 0x39, 0xd6, 0x79, 0xf1, + 0x38, 0xc9, 0x1a, 0x1f, 0x39, 0x70, 0xb3, 0x08, 0x39, 0xa4, 0x37, 0xdd, 0x38, + 0x6e, 0xfb, 0x15, 0x39, 0x6c, 0xa5, 0x39, 0x39, 0x82, 0xd6, 0x00, 0x39, 0xd5, + 0x9a, 0x0b, 0x39, 0xef, 0xa1, 0x14, 0x39, 0x02, 0xd1, 0x81, 0x39, 0x00, 0x71, + 0x57, 0x39, 0x77, 0xd6, 0x30, 0x39, 0xb3, 0xe9, 0x1e, 0x39, 0x08, 0x37, 0xbf, + 0x38, 0x7f, 0x9e, 0x1a, 0x39, 0x5c, 0xb7, 0xf5, 0x38, 0x1d, 0xb5, 0x22, 0x39, + 0x92, 0x15, 0xf4, 0x38, 0xaa, 0x0e, 0x04, 0x39, 0xa1, 0x4e, 0x02, 0x39, 0x83, + 0xd2, 0x54, 0x39, 0xad, 0x3c, 0x25, 0x39, 0x70, 0x88, 0x09, 0x39, 0x65, 0x13, + 0xc3, 0x38, 0x18, 0x02, 0xf0, 0x38, 0xc2, 0xa6, 0x36, 0x39, 0xeb, 0x6f, 0x6a, + 0x39, 0xfa, 0x9a, 0xe6, 0x38, 0x03, 0xd5, 0x20, 0x39, 0xef, 0x8b, 0x13, 0x39, + 0x3e, 0xdb, 0xfb, 0x38, 0xca, 0xc2, 0x1b, 0x39, 0x9a, 0x7a, 0xe7, 0x38, 0x9b, + 0x14, 0x00, 0x39, 0x5f, 0x15, 0x27, 0x39, 0x39, 0xd9, 0x30, 0x39, 0x4c, 0xbf, + 0x86, 0x39, 0xe9, 0x2f, 0x29, 0x39, 0xcc, 0xda, 0xda, 0x38, 0xf4, 0x7f, 0x7a, + 0x39, 0x3a, 0x7d, 0x1a, 0x39, 0xe4, 0xb2, 0xf3, 0x38, 0xb8, 0x92, 0x3a, 0x39, + 0x03, 0x6d, 0x1a, 0x39, 0x35, 0x9d, 0x4e, 0x39, 0xb0, 0xf5, 0xef, 0x38, 0x15, + 0xc7, 0xce, 0x38, 0x91, 0x19, 0x50, 0x39, 0xbc, 0x6d, 0x0a, 0x39, 0x06, 0xfe, + 0x22, 0x39, 0x61, 0xea, 0x30, 0x39, 0xe8, 0x52, 0x26, 0x39, 0xfd, 0xea, 0xd6, + 0x38, 0x17, 0xba, 0x33, 0x39, 0xd8, 0x54, 0x12, 0x39, 0x0f, 0x2a, 0x18, 0x39, + 0x14, 0x44, 0x04, 0x39, 0xf2, 0x1f, 0x2a, 0x39, 0x3f, 0x04, 0x99, 0x39, 0xc7, + 0xa3, 0x09, 0x39, 0x83, 0x12, 0xe8, 0x38, 0x05, 0x9a, 0x6f, 0x39, 0x21, 0xbe, + 0x02, 0x39, 0x81, 0xf9, 0x26, 0x39, 0xf0, 0x4d, 0xec, 0x38, 0x17, 0x0e, 0x21, + 0x39, 0xc4, 0x6f, 0x63, 0x39, 0x3e, 0xa9, 0x36, 0x39, 0x3b, 0x91, 0x35, 0x39, + 0xe8, 0x6e, 0x95, 0x39, 0xe8, 0xd4, 0xfd, 0x38, 0xbf, 0xfb, 0x43, 0x39, 0xfd, + 0xd8, 0xce, 0x38, 0x0f, 0x5e, 0xea, 0x38, 0x8c, 0x83, 0xdf, 0x38, 0xc4, 0x46, + 0x5a, 0x39, 0x57, 0x2e, 0x27, 0x39, 0xad, 0x75, 0x20, 0x39, 0xdd, 0xcf, 0x24, + 0x39, 0x79, 0xcb, 0xd9, 0x38, 0x8c, 0xf2, 0xf7, 0x38, 0x00, 0xbe, 0xeb, 0x38, + 0xe8, 0x7c, 0x32, 0x39, 0xbd, 0xe0, 0xd3, 0x38, 0x73, 0xd3, 0xf3, 0x38, 0xb9, + 0x02, 0x2a, 0x39, 0x3b, 0xd8, 0x30, 0x39, 0x18, 0xb2, 0x09, 0x39, 0xc7, 0x6b, + 0x62, 0x39, 0xbf, 0x36, 0x06, 0x39, 0xe1, 0x87, 0x3c, 0x39, 0xde, 0xa6, 0x27, + 0x39, 0x44, 0x9f, 0x63, 0x39, 0xa9, 0x3e, 0x2c, 0x39, 0x1b, 0xd6, 0xfb, 0x38, + 0xd8, 0x3c, 0xdb, 0x38, 0xcd, 0xf0, 0xed, 0x38, 0xa1, 0xb9, 0x82, 0x39, 0xd9, + 0x5d, 0xd8, 0x38, 0xf4, 0x20, 0xef, 0x38, 0x68, 0x24, 0x71, 0x39, 0x7a, 0x10, + 0xe4, 0x38, 0x0b, 0x9c, 0x88, 0x39, 0x8f, 0xcb, 0x35, 0x39, 0x82, 0xaa, 0xfb, + 0x38, 0xce, 0x66, 0x02, 0x39, 0xde, 0x38, 0x17, 0x39, 0x39, 0x00, 0x00, 0x00, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, + 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x38, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, + 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, + 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0xf2, 0xf4, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, + 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x8c, 0x7b, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, + 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x38, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, + 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x92, 0xf5, 0xfe, 0xff, 0x00, 0x00, + 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x2c, 0x7c, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, + 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x37, 0x5f, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x32, 0xf6, + 0xfe, 0xff, 0x00, 0x00, 0x00, 0x02, 0x64, 0x06, 0x00, 0x00, 0x53, 0x00, 0x00, + 0x00, 0x20, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb4, 0xfc, 0xfe, 0xff, + 0x10, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0xaa, 0x0c, 0x61, 0x38, 0xf0, 0x53, 0xb3, 0x38, 0x35, + 0xea, 0x8d, 0x38, 0xa4, 0xc2, 0x86, 0x38, 0xe8, 0x92, 0x60, 0x38, 0xc0, 0x2c, + 0x5c, 0x38, 0x67, 0xa0, 0x62, 0x38, 0xa1, 0xb3, 0xb4, 0x38, 0x5c, 0x07, 0x60, + 0x38, 0x30, 0xdc, 0x5f, 0x38, 0x2a, 0xa0, 0xd1, 0x38, 0xc9, 0x14, 0x9e, 0x38, + 0x9d, 0xac, 0x58, 0x38, 0xf3, 0x95, 0x8a, 0x38, 0x83, 0x03, 0x8d, 0x38, 0x78, + 0x46, 0x86, 0x38, 0x80, 0xea, 0x5d, 0x38, 0xe1, 0x99, 0x9a, 0x38, 0x4b, 0xe2, + 0x96, 0x38, 0xa9, 0xeb, 0x83, 0x38, 0x6b, 0x80, 0x8f, 0x38, 0x18, 0xf4, 0x80, + 0x38, 0x65, 0xfb, 0x67, 0x38, 0x1b, 0xd7, 0x8e, 0x38, 0xc4, 0x6c, 0x96, 0x38, + 0x92, 0x70, 0x98, 0x38, 0x9e, 0x46, 0x47, 0x38, 0xaa, 0xde, 0x7c, 0x38, 0x5f, + 0xc7, 0x4b, 0x38, 0xff, 0xa2, 0x83, 0x38, 0x4b, 0xa4, 0x82, 0x38, 0x61, 0xee, + 0x9b, 0x38, 0x47, 0xdb, 0x66, 0x38, 0xb4, 0x48, 0x85, 0x38, 0xe1, 0x54, 0x6e, + 0x38, 0x47, 0xba, 0xb8, 0x38, 0x65, 0x8b, 0x85, 0x38, 0xaa, 0x65, 0x41, 0x38, + 0x33, 0x6d, 0x88, 0x38, 0xfc, 0xe2, 0x72, 0x38, 0x92, 0x90, 0xae, 0x38, 0x60, + 0x60, 0x9e, 0x38, 0x9a, 0xa0, 0x77, 0x38, 0x67, 0x07, 0x78, 0x38, 0x6a, 0x34, + 0x83, 0x38, 0xba, 0xe1, 0x6b, 0x38, 0x1d, 0x9b, 0x78, 0x38, 0xd7, 0x8f, 0x8b, + 0x38, 0x0f, 0xc0, 0x8a, 0x38, 0xbb, 0xcc, 0x85, 0x38, 0x85, 0xf7, 0x50, 0x38, + 0x48, 0xc2, 0x8c, 0x38, 0x4a, 0x58, 0x56, 0x38, 0x73, 0x66, 0x5a, 0x38, 0x6d, + 0x58, 0x63, 0x38, 0x49, 0x9b, 0x6a, 0x38, 0xd9, 0x6a, 0x5b, 0x38, 0x61, 0xbc, + 0x58, 0x38, 0xe4, 0x43, 0x55, 0x38, 0x4c, 0x13, 0x9a, 0x38, 0xe5, 0xe5, 0x94, + 0x38, 0x92, 0xf8, 0x3a, 0x38, 0xa9, 0x4e, 0x66, 0x38, 0x46, 0xdf, 0x69, 0x38, + 0xc3, 0xbc, 0x92, 0x38, 0xee, 0xc7, 0x84, 0x38, 0x63, 0x4c, 0x9c, 0x38, 0xfc, + 0x62, 0x60, 0x38, 0xfb, 0x60, 0x85, 0x38, 0xeb, 0x7f, 0x7b, 0x38, 0xb0, 0xbc, + 0xa1, 0x38, 0x0d, 0x46, 0x8c, 0x38, 0xc8, 0xf9, 0x88, 0x38, 0x81, 0x37, 0x81, + 0x38, 0xf2, 0x93, 0x95, 0x38, 0x38, 0xc8, 0x98, 0x38, 0x1f, 0x9a, 0x9b, 0x38, + 0xfb, 0x1e, 0x80, 0x38, 0xce, 0x84, 0x81, 0x38, 0x1d, 0x96, 0x7d, 0x38, 0xbb, + 0x15, 0xb2, 0x38, 0x39, 0x9f, 0x84, 0x38, 0xeb, 0xbe, 0x7a, 0x38, 0xc4, 0x6f, + 0x87, 0x38, 0x37, 0x62, 0x93, 0x38, 0xc1, 0x53, 0x99, 0x38, 0xa2, 0xe3, 0x3f, + 0x38, 0x67, 0xdf, 0x43, 0x38, 0x7f, 0xd2, 0x64, 0x38, 0x7c, 0x06, 0x7f, 0x38, + 0x0c, 0xe0, 0x6c, 0x38, 0x30, 0x77, 0x90, 0x38, 0x49, 0xd7, 0x57, 0x38, 0x65, + 0x1d, 0x7a, 0x38, 0x36, 0x38, 0xb0, 0x38, 0xb9, 0x08, 0x86, 0x38, 0x9d, 0x25, + 0x47, 0x38, 0xd6, 0x87, 0x69, 0x38, 0x73, 0x64, 0xce, 0x38, 0x14, 0xae, 0x5b, + 0x38, 0x65, 0xe5, 0x99, 0x38, 0xb0, 0xec, 0x5e, 0x38, 0xf2, 0x88, 0x9f, 0x38, + 0x3c, 0x3b, 0x8a, 0x38, 0xd1, 0xf0, 0x82, 0x38, 0x3e, 0xe0, 0x7b, 0x38, 0xc9, + 0xd2, 0x6f, 0x38, 0xa4, 0x9f, 0x95, 0x38, 0x0e, 0x3b, 0x5b, 0x38, 0x15, 0x3c, + 0x6d, 0x38, 0xd3, 0xed, 0x5a, 0x38, 0xa0, 0x9e, 0x96, 0x38, 0x49, 0x50, 0xcc, + 0x38, 0x1e, 0xe4, 0x48, 0x38, 0xda, 0x56, 0x3a, 0x38, 0x41, 0x0d, 0x57, 0x38, + 0xc9, 0x68, 0xc0, 0x38, 0x86, 0x69, 0x4a, 0x38, 0x97, 0x84, 0x6f, 0x38, 0xb3, + 0x7c, 0x9d, 0x38, 0x24, 0x1c, 0x6f, 0x38, 0x62, 0xb0, 0x8e, 0x38, 0x61, 0xaf, + 0x72, 0x38, 0x03, 0x03, 0x83, 0x38, 0xf3, 0x9f, 0x5b, 0x38, 0x6f, 0xbe, 0x89, + 0x38, 0x82, 0x3b, 0x9c, 0x38, 0x9f, 0x52, 0x8a, 0x38, 0x36, 0x00, 0x00, 0x00, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, + 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x37, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, + 0x69, 0x73, 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, 0x69, + 0x61, 0x73, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xa6, + 0xfc, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x02, 0x6c, 0x06, 0x00, 0x00, 0x4e, 0x00, + 0x00, 0x00, 0x24, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0xf6, 0xfe, + 0xff, 0x14, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xa1, 0x0c, 0xe5, 0x38, + 0xb5, 0x80, 0x28, 0x39, 0x9e, 0xce, 0x25, 0x39, 0xeb, 0xb3, 0x62, 0x39, 0x74, + 0x53, 0x38, 0x39, 0x9f, 0x2b, 0xb8, 0x38, 0xb9, 0x9e, 0x07, 0x39, 0xdb, 0x1c, + 0x63, 0x39, 0x9e, 0x9d, 0x0f, 0x39, 0xbd, 0x02, 0x0c, 0x39, 0xc0, 0xda, 0x50, + 0x39, 0x0c, 0x9f, 0x4e, 0x39, 0xfb, 0xe3, 0x85, 0x39, 0x9b, 0x35, 0xd1, 0x39, + 0xde, 0x77, 0x12, 0x39, 0x61, 0x64, 0x33, 0x39, 0xeb, 0xba, 0x62, 0x39, 0xa4, + 0x8c, 0x63, 0x39, 0x4c, 0xd0, 0x39, 0x39, 0xb5, 0x69, 0x9b, 0x39, 0xb9, 0x55, + 0x80, 0x39, 0x97, 0x96, 0x52, 0x39, 0xd6, 0x78, 0x74, 0x39, 0xa2, 0x2d, 0x09, + 0x39, 0x67, 0xac, 0xc4, 0x38, 0x1d, 0x5f, 0x21, 0x39, 0x02, 0x83, 0x13, 0x39, + 0xdb, 0x4b, 0x4a, 0x39, 0xcf, 0x1b, 0x20, 0x39, 0xb4, 0x50, 0x70, 0x39, 0xf7, + 0xd3, 0xe9, 0x38, 0xe2, 0x48, 0x15, 0x39, 0x93, 0x55, 0x04, 0x39, 0xfc, 0xb9, + 0x34, 0x39, 0xda, 0x08, 0x2d, 0x39, 0xb3, 0x09, 0x5f, 0x39, 0x25, 0x87, 0x07, + 0x39, 0x7c, 0x80, 0x37, 0x39, 0xfd, 0x85, 0x24, 0x39, 0x0b, 0x4b, 0x0d, 0x39, + 0xae, 0xfa, 0x17, 0x39, 0x80, 0x0e, 0x44, 0x39, 0xa4, 0x0e, 0x12, 0x39, 0xa1, + 0xb3, 0x12, 0x39, 0xd2, 0x44, 0x1c, 0x39, 0x15, 0x69, 0xd7, 0x38, 0x18, 0x08, + 0x25, 0x39, 0x73, 0x4a, 0x6f, 0x39, 0x70, 0xe3, 0x78, 0x39, 0xbe, 0x9e, 0x31, + 0x39, 0x1b, 0x13, 0x1b, 0x39, 0x3f, 0xf2, 0x41, 0x39, 0xc3, 0xb6, 0x1c, 0x39, + 0xfe, 0x9d, 0x13, 0x39, 0x61, 0x1b, 0x0d, 0x39, 0x23, 0x75, 0x06, 0x39, 0x7b, + 0xa1, 0x3c, 0x39, 0xde, 0x43, 0x7c, 0x39, 0xeb, 0x1b, 0x22, 0x39, 0x76, 0xff, + 0x30, 0x39, 0x24, 0x23, 0x53, 0x39, 0x8b, 0x71, 0x03, 0x39, 0x3b, 0x12, 0x84, + 0x39, 0x9b, 0x1d, 0x9a, 0x39, 0x1e, 0xe6, 0x02, 0x39, 0x2c, 0xbe, 0xdd, 0x38, + 0x55, 0xdd, 0x7b, 0x39, 0xc8, 0xdf, 0x05, 0x39, 0x61, 0x65, 0x25, 0x39, 0x23, + 0xbb, 0x43, 0x39, 0x18, 0x72, 0xe3, 0x38, 0x4d, 0x09, 0x6e, 0x39, 0x91, 0xf0, + 0x36, 0x39, 0x9b, 0x10, 0x1e, 0x39, 0x54, 0xa5, 0x8f, 0x39, 0x8c, 0x4f, 0xbb, + 0x39, 0xf5, 0xd3, 0x1a, 0x39, 0xe7, 0x86, 0xc7, 0x38, 0x0f, 0x4e, 0x11, 0x39, + 0xab, 0xce, 0x17, 0x39, 0xc4, 0xb5, 0x56, 0x39, 0x18, 0xfb, 0x76, 0x39, 0x06, + 0x4d, 0x46, 0x39, 0x1f, 0x49, 0x09, 0x39, 0xd0, 0x09, 0xf7, 0x38, 0xbc, 0x92, + 0x38, 0x39, 0x5c, 0x55, 0x63, 0x39, 0x49, 0xda, 0x43, 0x39, 0xf9, 0xcd, 0x0a, + 0x39, 0xfd, 0xf5, 0xc2, 0x39, 0x49, 0xd8, 0x45, 0x39, 0xf9, 0x91, 0x0d, 0x39, + 0x59, 0x18, 0x15, 0x39, 0xc5, 0x1a, 0x12, 0x39, 0xa6, 0xfe, 0x1d, 0x39, 0x1d, + 0x58, 0x35, 0x39, 0x24, 0x78, 0x42, 0x39, 0x59, 0x85, 0x63, 0x39, 0xd1, 0x0f, + 0x00, 0x39, 0xfa, 0x4c, 0x6a, 0x39, 0xf8, 0x36, 0x27, 0x39, 0x8e, 0xea, 0x21, + 0x39, 0x6e, 0xdc, 0x77, 0x39, 0x21, 0x26, 0xf4, 0x38, 0x3f, 0xff, 0x00, 0x39, + 0x2c, 0x94, 0x14, 0x39, 0x12, 0x2e, 0x36, 0x39, 0x00, 0xd5, 0xd7, 0x38, 0xbd, + 0xa6, 0x18, 0x39, 0xb5, 0xda, 0x5d, 0x39, 0xcd, 0x8e, 0x94, 0x39, 0x64, 0x41, + 0xa4, 0x39, 0xcf, 0x85, 0x10, 0x39, 0x15, 0x89, 0x8f, 0x39, 0x7a, 0x67, 0x1f, + 0x39, 0x30, 0x0c, 0x8e, 0x39, 0x2d, 0x18, 0x1b, 0x39, 0x5e, 0x4b, 0x6d, 0x39, + 0xda, 0x52, 0x25, 0x39, 0x27, 0x75, 0x70, 0x39, 0xea, 0x56, 0x39, 0x39, 0x05, + 0x83, 0xce, 0x38, 0x68, 0x65, 0xea, 0x38, 0x05, 0xd0, 0xe0, 0x38, 0xf6, 0xf8, + 0x67, 0x39, 0x3c, 0x43, 0x41, 0x39, 0xa0, 0x45, 0x4d, 0x39, 0xa9, 0x70, 0xda, + 0x38, 0x39, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x37, 0x5f, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x22, 0x03, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x44, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xbc, 0x89, 0xff, 0xff, 0x30, 0x00, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x37, 0x5f, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, + 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc2, + 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x31, 0x00, + 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x5c, 0x8a, 0xff, + 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, + 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, + 0x5f, 0x36, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, + 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x62, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x64, 0x06, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0xe4, 0x0a, 0xff, 0xff, 0x10, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x30, 0x0b, 0xba, 0x38, + 0x07, 0xe6, 0x99, 0x38, 0x5b, 0xb2, 0x0d, 0x39, 0x9a, 0xf2, 0xbe, 0x38, 0x1f, + 0x1d, 0x99, 0x38, 0x8b, 0x74, 0xed, 0x38, 0xaf, 0x9e, 0x6d, 0x38, 0xcb, 0xd4, + 0x9e, 0x38, 0xde, 0xf6, 0xda, 0x38, 0x9a, 0xb8, 0xa7, 0x38, 0x2e, 0x44, 0x99, + 0x38, 0x6a, 0x0c, 0xd5, 0x38, 0x30, 0x65, 0x86, 0x38, 0xcb, 0xe2, 0x38, 0x38, + 0x20, 0xca, 0x7d, 0x38, 0xa1, 0x51, 0x8b, 0x38, 0x0e, 0xc5, 0x88, 0x38, 0x3e, + 0x33, 0x95, 0x38, 0xa2, 0x88, 0xbb, 0x38, 0xcf, 0xaf, 0x7e, 0x38, 0x6a, 0x0d, + 0xae, 0x38, 0xf3, 0x33, 0x86, 0x38, 0x67, 0xd4, 0xc5, 0x38, 0x0f, 0x0f, 0xcc, + 0x38, 0xa6, 0xfb, 0xd7, 0x38, 0x6e, 0xf4, 0x8e, 0x38, 0x61, 0x41, 0xa3, 0x38, + 0xf7, 0xbe, 0xb4, 0x38, 0xb1, 0xe2, 0x9b, 0x38, 0x70, 0x32, 0xca, 0x38, 0xe1, + 0xfb, 0xac, 0x38, 0xff, 0xc4, 0x93, 0x38, 0x49, 0x65, 0xb3, 0x38, 0x95, 0xae, + 0x8b, 0x38, 0x1e, 0x8a, 0x86, 0x38, 0xcf, 0x20, 0x83, 0x38, 0x64, 0x37, 0x9c, + 0x38, 0x8a, 0xb5, 0x35, 0x38, 0xe5, 0xbe, 0xa6, 0x38, 0x35, 0x13, 0xbe, 0x38, + 0x70, 0x9c, 0xc5, 0x38, 0xa9, 0xf2, 0xa6, 0x38, 0x45, 0x16, 0x95, 0x38, 0x29, + 0xe0, 0xaa, 0x38, 0x64, 0xfa, 0xc7, 0x38, 0xa3, 0x66, 0x49, 0x38, 0xe7, 0x2d, + 0xa4, 0x38, 0xd4, 0x74, 0xa8, 0x38, 0xb8, 0xb8, 0x63, 0x38, 0x26, 0x53, 0x72, + 0x38, 0x06, 0x28, 0xc2, 0x38, 0x06, 0xe0, 0xb0, 0x38, 0xa7, 0x1d, 0xa6, 0x38, + 0x05, 0x41, 0xaa, 0x38, 0xc2, 0x93, 0x95, 0x38, 0x38, 0xc1, 0x97, 0x38, 0xb0, + 0xa8, 0xb6, 0x38, 0x7a, 0x24, 0xa5, 0x38, 0xeb, 0xed, 0x83, 0x38, 0xd6, 0x54, + 0x48, 0x38, 0x6f, 0x32, 0x94, 0x38, 0x54, 0x98, 0x8a, 0x38, 0x88, 0x4d, 0x83, + 0x38, 0xb0, 0xe4, 0x96, 0x38, 0xf9, 0xf6, 0xa9, 0x38, 0xe1, 0x67, 0xa6, 0x38, + 0x06, 0x46, 0x78, 0x38, 0xed, 0xd5, 0xea, 0x38, 0x05, 0x1f, 0x94, 0x38, 0x91, + 0xe5, 0x91, 0x38, 0xf6, 0x2e, 0x98, 0x38, 0x94, 0x63, 0x5d, 0x38, 0xf9, 0x4f, + 0xa4, 0x38, 0x4b, 0x46, 0x9e, 0x38, 0x19, 0xcf, 0x98, 0x38, 0x3e, 0x3b, 0x4b, + 0x38, 0x38, 0xc9, 0x79, 0x38, 0x24, 0xbb, 0x88, 0x38, 0xda, 0x39, 0x87, 0x38, + 0xd0, 0xe6, 0x84, 0x38, 0x05, 0x05, 0xa9, 0x38, 0x1a, 0xae, 0x9d, 0x38, 0xc1, + 0x65, 0xbe, 0x38, 0xf1, 0xc2, 0x98, 0x38, 0x20, 0x08, 0x93, 0x38, 0x15, 0xb5, + 0x9c, 0x38, 0xba, 0x98, 0x63, 0x38, 0x98, 0xf0, 0x97, 0x38, 0x04, 0xe0, 0x90, + 0x38, 0xc7, 0x9e, 0x74, 0x38, 0xfe, 0x4c, 0xb7, 0x38, 0x50, 0xeb, 0x7f, 0x38, + 0x2a, 0xe3, 0xa6, 0x38, 0x14, 0xed, 0x73, 0x38, 0x62, 0x8f, 0xcd, 0x38, 0xee, + 0x19, 0x78, 0x38, 0x3a, 0xd7, 0x6c, 0x38, 0x61, 0x01, 0xbd, 0x38, 0x56, 0xda, + 0x97, 0x38, 0xd0, 0xa5, 0xa5, 0x38, 0x1b, 0xb8, 0xc4, 0x38, 0xbb, 0x0b, 0xcc, + 0x38, 0x9d, 0xe2, 0xa7, 0x38, 0xef, 0xaf, 0xb6, 0x38, 0x9e, 0x37, 0xae, 0x38, + 0x6a, 0x46, 0x72, 0x38, 0xfb, 0x4c, 0x88, 0x38, 0x7a, 0xea, 0x96, 0x38, 0x2e, + 0xf7, 0x98, 0x38, 0x08, 0x3a, 0xa5, 0x38, 0xe1, 0xdf, 0xb4, 0x38, 0xcf, 0x6f, + 0x4d, 0x38, 0x9b, 0xe7, 0x91, 0x38, 0xd6, 0x8a, 0x94, 0x38, 0x71, 0x6f, 0x88, + 0x38, 0xa5, 0x79, 0x9d, 0x38, 0xf7, 0xe3, 0xa4, 0x38, 0x3d, 0xe7, 0x6e, 0x38, + 0xea, 0xa0, 0x8c, 0x38, 0x66, 0x7f, 0x3d, 0x38, 0x0e, 0x6e, 0x93, 0x38, 0xd3, + 0x64, 0x6d, 0x38, 0xc9, 0xb9, 0x9b, 0x38, 0xde, 0x7c, 0xdc, 0x38, 0xc9, 0xa5, + 0xcf, 0x38, 0xc7, 0xca, 0x7d, 0x38, 0x79, 0x75, 0xa0, 0x38, 0x5e, 0xab, 0x95, + 0x38, 0x36, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x36, 0x5f, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x76, + 0x32, 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0xd6, 0x0a, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x6c, + 0x03, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x24, 0x03, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x32, 0x04, 0xff, 0xff, 0x14, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe4, 0xe1, 0xd9, 0x38, + 0x59, 0x7e, 0xcd, 0x38, 0x89, 0x65, 0xac, 0x38, 0x2d, 0x36, 0xbb, 0x38, 0xa1, + 0x1e, 0x8e, 0x38, 0xbb, 0x08, 0x92, 0x38, 0x77, 0xc7, 0xf3, 0x38, 0xb3, 0xfb, + 0xbc, 0x38, 0x7f, 0x6a, 0xba, 0x38, 0xff, 0xe1, 0x05, 0x39, 0x24, 0xf5, 0xb9, + 0x38, 0x71, 0xb3, 0xcb, 0x38, 0xbe, 0x56, 0xce, 0x38, 0x18, 0xb7, 0xc0, 0x38, + 0xd2, 0x9d, 0xbd, 0x38, 0x74, 0x16, 0x37, 0x39, 0x46, 0x11, 0xb2, 0x38, 0xbd, + 0x56, 0x6c, 0x39, 0xdb, 0x35, 0xb7, 0x38, 0xe8, 0x93, 0xd7, 0x38, 0x53, 0xc4, + 0xab, 0x38, 0xb6, 0xa6, 0xc4, 0x38, 0xb5, 0xd1, 0x09, 0x39, 0xdd, 0x60, 0xa5, + 0x38, 0x77, 0x4e, 0xed, 0x38, 0x35, 0x67, 0xb4, 0x38, 0x85, 0x14, 0xe0, 0x38, + 0x6b, 0x21, 0xc0, 0x38, 0xfd, 0x90, 0xbf, 0x38, 0xd6, 0x8b, 0xe1, 0x38, 0x76, + 0x9c, 0xaa, 0x38, 0x06, 0x37, 0xc2, 0x38, 0x18, 0x19, 0xac, 0x38, 0xbc, 0x40, + 0xb5, 0x38, 0x54, 0x25, 0x3a, 0x39, 0x03, 0xd8, 0x01, 0x39, 0x1a, 0xdc, 0xe0, + 0x38, 0xdb, 0x58, 0xe6, 0x38, 0x8f, 0xb3, 0x98, 0x38, 0xe6, 0xda, 0x9c, 0x38, + 0x80, 0xed, 0xb5, 0x38, 0x71, 0x6c, 0xfd, 0x38, 0x0f, 0xc1, 0xf6, 0x38, 0x20, + 0x63, 0xde, 0x38, 0x89, 0x1f, 0xab, 0x38, 0xc7, 0xcd, 0xdd, 0x38, 0x5c, 0xf0, + 0x9f, 0x38, 0x1a, 0x54, 0xe4, 0x38, 0x2d, 0x39, 0xba, 0x38, 0x20, 0x55, 0xd1, + 0x38, 0xcf, 0x66, 0x87, 0x38, 0xe1, 0xb7, 0xe6, 0x38, 0x9a, 0x6d, 0x1a, 0x39, + 0xfc, 0x97, 0x11, 0x39, 0x28, 0x62, 0xaf, 0x38, 0x0b, 0xcf, 0xc5, 0x38, 0x61, + 0xbc, 0x23, 0x39, 0x0c, 0x7b, 0xc5, 0x38, 0xfc, 0xfa, 0x94, 0x38, 0x39, 0x7c, + 0x96, 0x38, 0x2a, 0x7e, 0x8e, 0x38, 0x5e, 0x2d, 0xd6, 0x38, 0xa1, 0xd1, 0xcc, + 0x38, 0x43, 0x1a, 0x24, 0x39, 0x39, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, + 0x5f, 0x36, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, + 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x62, 0x69, 0x61, + 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x52, + 0x0e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x2c, 0x00, + 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xec, 0x94, 0xff, + 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, + 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, + 0x5f, 0x36, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, + 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, + 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x8c, 0x95, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, + 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x35, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, + 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x92, 0x0f, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x02, 0x64, 0x03, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x20, 0x03, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x16, 0xff, 0xff, 0x10, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xd3, 0x57, 0x81, 0x38, 0x47, + 0x8c, 0xbc, 0x38, 0x50, 0xdf, 0xd4, 0x38, 0xe8, 0xc0, 0xf7, 0x38, 0xa1, 0x2a, + 0xaa, 0x38, 0x11, 0x80, 0x8b, 0x38, 0xdc, 0xc8, 0xb0, 0x38, 0xbc, 0xd0, 0xa3, + 0x38, 0x79, 0xa4, 0xd5, 0x38, 0xb0, 0x8f, 0xc2, 0x38, 0x83, 0xa4, 0xbf, 0x38, + 0xf4, 0xa6, 0xa9, 0x38, 0x77, 0x21, 0xc2, 0x38, 0x2f, 0xca, 0x6f, 0x38, 0x06, + 0x11, 0xfe, 0x38, 0xe8, 0xd1, 0x57, 0x38, 0x97, 0xa2, 0xc2, 0x38, 0x6b, 0x93, + 0x59, 0x38, 0x7a, 0x86, 0x7d, 0x38, 0x15, 0xc0, 0xe4, 0x38, 0x70, 0xa8, 0xb4, + 0x38, 0x14, 0x02, 0xa1, 0x38, 0x58, 0x71, 0xb0, 0x38, 0xfd, 0x49, 0xb5, 0x38, + 0x91, 0x89, 0x81, 0x38, 0x3a, 0x10, 0x6c, 0x38, 0x68, 0x77, 0xea, 0x38, 0x45, + 0xdc, 0xa9, 0x38, 0x91, 0x2c, 0xd9, 0x38, 0x22, 0x65, 0xa5, 0x38, 0x4c, 0x00, + 0xc3, 0x38, 0x82, 0x95, 0xa6, 0x38, 0xdf, 0xb7, 0x91, 0x38, 0x4f, 0xb4, 0xa3, + 0x38, 0xcf, 0x1e, 0x9a, 0x38, 0x15, 0xe8, 0x8d, 0x38, 0xd5, 0xfc, 0xa2, 0x38, + 0x68, 0xb5, 0x62, 0x38, 0x51, 0x04, 0x82, 0x38, 0x4a, 0x25, 0xd2, 0x38, 0x8b, + 0xd1, 0xc4, 0x38, 0x02, 0x61, 0xb0, 0x38, 0x5f, 0x34, 0x8b, 0x38, 0xf3, 0xd3, + 0xb3, 0x38, 0x6d, 0x60, 0xb8, 0x38, 0x7f, 0xeb, 0xa8, 0x38, 0x85, 0x4d, 0x8d, + 0x38, 0x56, 0x3a, 0x6c, 0x38, 0x9d, 0xee, 0x94, 0x38, 0x9c, 0x0c, 0x3d, 0x38, + 0xc0, 0x96, 0xae, 0x38, 0x52, 0xab, 0xd5, 0x38, 0xe1, 0xa7, 0x18, 0x38, 0x47, + 0xfe, 0x55, 0x38, 0x36, 0xac, 0xb0, 0x38, 0xd8, 0xdf, 0xa3, 0x38, 0xc1, 0x94, + 0x9c, 0x38, 0x24, 0xd7, 0xb0, 0x38, 0x40, 0x4a, 0xad, 0x38, 0x0f, 0x31, 0xa7, + 0x38, 0x7c, 0xb9, 0xbf, 0x38, 0xd0, 0x06, 0xc6, 0x38, 0x53, 0x4e, 0x5f, 0x38, + 0x94, 0x25, 0x5d, 0x38, 0x36, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x35, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x43, + 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x13, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x02, 0x6c, 0x03, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x24, 0x03, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x62, 0x0c, 0xff, 0xff, 0x14, 0x02, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa7, + 0x20, 0xfc, 0x38, 0x89, 0x62, 0x69, 0x39, 0xfc, 0x00, 0x35, 0x39, 0xca, 0x7e, + 0x39, 0x39, 0x08, 0x4e, 0x66, 0x39, 0xf3, 0x61, 0xd8, 0x38, 0x94, 0xb7, 0x05, + 0x39, 0x40, 0x49, 0x97, 0x38, 0x31, 0xdd, 0x9c, 0x39, 0x72, 0x72, 0xb2, 0x39, + 0x74, 0xe6, 0xd4, 0x39, 0x53, 0x96, 0x64, 0x39, 0x38, 0xbe, 0x5f, 0x39, 0x6a, + 0x5f, 0xbe, 0x38, 0x01, 0x21, 0x21, 0x39, 0x8f, 0xf1, 0x40, 0x39, 0xa2, 0x39, + 0x0f, 0x39, 0xc1, 0x47, 0xe9, 0x38, 0x86, 0x92, 0x22, 0x39, 0x34, 0xfb, 0xec, + 0x38, 0xdf, 0x67, 0xe0, 0x38, 0x53, 0x3a, 0x11, 0x39, 0x1a, 0xf8, 0xd1, 0x39, + 0xb5, 0x00, 0x19, 0x39, 0x26, 0x8e, 0x05, 0x39, 0x43, 0x28, 0xac, 0x39, 0xdb, + 0xee, 0x8a, 0x39, 0x85, 0x31, 0xe1, 0x38, 0x0f, 0x1e, 0x11, 0x39, 0xe7, 0xea, + 0x2f, 0x39, 0x42, 0x73, 0x05, 0x39, 0xec, 0x15, 0x2f, 0x39, 0x12, 0x09, 0xd2, + 0x38, 0xd2, 0x2e, 0x09, 0x39, 0x1e, 0x05, 0x22, 0x39, 0xaa, 0x44, 0xaf, 0x38, + 0x02, 0xe1, 0x86, 0x39, 0x59, 0x42, 0x92, 0x39, 0xe4, 0x90, 0x09, 0x39, 0x3c, + 0xde, 0x04, 0x39, 0xaa, 0xf2, 0x32, 0x39, 0xc0, 0x84, 0x2a, 0x39, 0x1d, 0xd5, + 0x76, 0x39, 0x1a, 0x13, 0x24, 0x39, 0x4f, 0xbd, 0xbc, 0x38, 0xe0, 0x06, 0xa8, + 0x38, 0xd5, 0x4b, 0x8f, 0x39, 0xe1, 0xed, 0xc7, 0x38, 0xfd, 0xea, 0x80, 0x39, + 0x77, 0xf5, 0x5b, 0x39, 0x00, 0xa6, 0x37, 0x39, 0xf3, 0x36, 0x55, 0x39, 0x77, + 0x6e, 0xa1, 0x39, 0x2b, 0x10, 0x07, 0x39, 0xd0, 0xf0, 0xdb, 0x38, 0x62, 0xd5, + 0xff, 0x38, 0xcd, 0xfc, 0x53, 0x39, 0x5c, 0xc1, 0x16, 0x39, 0xd3, 0xbe, 0xe9, + 0x38, 0x77, 0xc2, 0xf2, 0x38, 0x71, 0x2a, 0x98, 0x39, 0xe4, 0x4e, 0xd0, 0x38, + 0x4b, 0x79, 0x0a, 0x39, 0x56, 0x9a, 0x8e, 0x39, 0x39, 0x00, 0x00, 0x00, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x35, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, + 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, + 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x82, 0x16, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, + 0x00, 0x57, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1c, 0x9d, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x35, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, + 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x09, 0x84, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xbc, 0x9d, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, + 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, + 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x34, 0x5f, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xc2, 0x17, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x02, 0x64, 0x03, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, + 0x20, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x44, 0x1e, 0xff, 0xff, 0x10, + 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa9, 0xbb, + 0xd0, 0x38, 0x3a, 0x81, 0x84, 0x38, 0x12, 0x86, 0xf8, 0x38, 0xd8, 0xe1, 0xd0, + 0x38, 0xb4, 0x0a, 0xa1, 0x38, 0x93, 0x51, 0xb6, 0x38, 0x65, 0xd7, 0xf0, 0x38, + 0x98, 0x9a, 0xc6, 0x38, 0xbf, 0x4e, 0x88, 0x38, 0xc6, 0xa5, 0xd3, 0x38, 0x59, + 0xc6, 0x60, 0x38, 0xd2, 0xdc, 0xf0, 0x38, 0x70, 0x7e, 0x87, 0x38, 0xa3, 0xd3, + 0xcf, 0x38, 0x54, 0xfb, 0x02, 0x39, 0xdb, 0x90, 0x45, 0x39, 0x8b, 0x00, 0xcc, + 0x38, 0x3b, 0xd8, 0xc4, 0x38, 0x73, 0xed, 0xd3, 0x38, 0xcb, 0xb7, 0x8d, 0x38, + 0x3e, 0xc5, 0x2d, 0x39, 0xe9, 0xaf, 0x9f, 0x38, 0x61, 0x00, 0xa6, 0x38, 0xa9, + 0xf7, 0x12, 0x39, 0x70, 0x6d, 0x0c, 0x39, 0x18, 0x81, 0x2a, 0x38, 0x9d, 0x17, + 0x83, 0x38, 0x0b, 0x0d, 0x22, 0x39, 0x83, 0x52, 0x07, 0x39, 0x26, 0x7c, 0xc5, + 0x38, 0xb5, 0x04, 0xd0, 0x38, 0x42, 0xcc, 0x12, 0x39, 0x01, 0x47, 0x00, 0x39, + 0x5e, 0x12, 0x74, 0x38, 0x62, 0x92, 0xb3, 0x38, 0x20, 0xfd, 0x27, 0x39, 0xd0, + 0x51, 0x6e, 0x38, 0x79, 0x0f, 0x77, 0x38, 0x3e, 0x76, 0xb4, 0x38, 0x32, 0x98, + 0x88, 0x38, 0x30, 0x5d, 0xa8, 0x38, 0x11, 0x95, 0xd5, 0x38, 0xb0, 0x91, 0x9f, + 0x38, 0xad, 0x1f, 0xd7, 0x38, 0xec, 0x9d, 0x1b, 0x39, 0xcb, 0x15, 0x1d, 0x39, + 0x27, 0x48, 0x4a, 0x38, 0x09, 0xb3, 0xb5, 0x38, 0x98, 0x7f, 0x02, 0x39, 0x47, + 0x95, 0x53, 0x39, 0xf1, 0x99, 0x47, 0x39, 0x73, 0x76, 0xd8, 0x38, 0x71, 0x7a, + 0xd5, 0x38, 0x67, 0x79, 0x4e, 0x39, 0x42, 0xf0, 0x01, 0x39, 0x59, 0xbe, 0xe5, + 0x38, 0x0a, 0xec, 0x9f, 0x38, 0x87, 0x6a, 0x20, 0x39, 0x6a, 0x06, 0xdc, 0x38, + 0x40, 0x5d, 0xfa, 0x38, 0x95, 0x1d, 0x92, 0x38, 0xd3, 0xcd, 0x3e, 0x39, 0xa1, + 0x43, 0x0d, 0x39, 0x6b, 0x23, 0x97, 0x38, 0x36, 0x00, 0x00, 0x00, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, + 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, + 0x32, 0x64, 0x5f, 0x34, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, + 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x36, 0x1b, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x02, 0xec, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0xa4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x92, 0x14, 0xff, 0xff, 0x14, + 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xc5, 0xba, 0x8c, 0x38, 0x92, 0x4d, 0xa9, + 0x38, 0x52, 0x02, 0x82, 0x38, 0xfc, 0xa9, 0xaf, 0x38, 0xff, 0x9a, 0x46, 0x39, + 0x14, 0xa1, 0xcb, 0x38, 0x60, 0xad, 0x95, 0x38, 0xb6, 0xdd, 0x96, 0x38, 0x69, + 0x54, 0x96, 0x38, 0xca, 0x22, 0x68, 0x38, 0x68, 0x2c, 0xac, 0x38, 0xe7, 0x85, + 0x95, 0x38, 0x41, 0x03, 0xd5, 0x38, 0xd5, 0x13, 0x28, 0x39, 0xa9, 0xae, 0xde, + 0x38, 0x26, 0x06, 0xa4, 0x38, 0xa7, 0x7b, 0x9a, 0x38, 0x0e, 0x89, 0x8f, 0x38, + 0x4c, 0x4a, 0xf2, 0x38, 0x6d, 0x8f, 0x9d, 0x38, 0x03, 0xb2, 0xef, 0x38, 0x3e, + 0x97, 0xd8, 0x38, 0x80, 0xfe, 0x4b, 0x38, 0xed, 0x28, 0xad, 0x38, 0x04, 0xbb, + 0x2a, 0x39, 0x49, 0x6b, 0xbb, 0x38, 0x82, 0x54, 0xa2, 0x38, 0xbd, 0xee, 0x90, + 0x38, 0x46, 0xb5, 0xea, 0x38, 0xd2, 0x63, 0xa7, 0x38, 0x11, 0x03, 0xda, 0x38, + 0x48, 0x20, 0x22, 0x39, 0x39, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x34, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x62, 0x69, 0x61, 0x73, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x32, 0x1d, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, + 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xcc, 0xa3, 0xff, 0xff, + 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, + 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x34, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, + 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0xd2, 0x1d, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, + 0x00, 0x35, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x6c, 0xa4, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x33, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, + 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x72, 0x1e, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x02, 0xe4, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xf4, 0x24, 0xff, 0xff, 0x10, 0x01, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x3e, 0x8f, + 0xd5, 0x38, 0xe1, 0xa8, 0x15, 0x39, 0x06, 0x19, 0xf5, 0x38, 0x79, 0x80, 0xc5, + 0x38, 0x35, 0x5e, 0x4f, 0x38, 0x3f, 0x44, 0x8d, 0x38, 0x0a, 0xa0, 0xb7, 0x38, + 0xb2, 0xf2, 0xa7, 0x38, 0x34, 0xb7, 0xf3, 0x38, 0xb4, 0xd4, 0xb8, 0x38, 0x08, + 0x3d, 0x0e, 0x39, 0xea, 0xad, 0xa8, 0x38, 0x47, 0xf9, 0x00, 0x39, 0xbf, 0x4e, + 0x04, 0x39, 0xdb, 0x31, 0xa0, 0x38, 0xed, 0x1d, 0xbd, 0x38, 0x41, 0x75, 0xc6, + 0x38, 0x76, 0x6a, 0xe9, 0x38, 0xe5, 0x13, 0x0f, 0x39, 0x14, 0xa9, 0xed, 0x38, + 0xd2, 0x34, 0x26, 0x39, 0xc4, 0x70, 0xc7, 0x38, 0x27, 0xd1, 0xb3, 0x38, 0xb7, + 0x3f, 0xfd, 0x38, 0x58, 0x20, 0x1e, 0x39, 0xd6, 0xeb, 0x47, 0x39, 0x15, 0x4c, + 0x22, 0x39, 0xa1, 0xd0, 0x04, 0x39, 0xa2, 0x9e, 0x8c, 0x38, 0x2c, 0x4b, 0xbe, + 0x38, 0xd9, 0xb7, 0xe5, 0x38, 0x2a, 0xdd, 0xbf, 0x38, 0x36, 0x00, 0x00, 0x00, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, + 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x33, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, + 0x69, 0x73, 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, 0x69, + 0x61, 0x73, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x66, + 0x20, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xec, 0x01, 0x00, 0x00, 0x22, 0x00, + 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc2, 0x19, 0xff, + 0xff, 0x14, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xe1, 0x95, 0x47, 0x39, 0x5c, + 0xa6, 0x6d, 0x39, 0x76, 0xe7, 0x2c, 0x39, 0x44, 0x2e, 0x74, 0x39, 0x27, 0x35, + 0x9d, 0x39, 0x0c, 0xe8, 0x14, 0x3a, 0x59, 0x1e, 0xd8, 0x38, 0x9b, 0xf8, 0x30, + 0x39, 0xfc, 0xec, 0x33, 0x39, 0xcd, 0x64, 0xd1, 0x39, 0x39, 0xe6, 0x05, 0x3a, + 0x72, 0xd9, 0x25, 0x39, 0x42, 0xa7, 0x87, 0x38, 0xd6, 0xfc, 0xa1, 0x39, 0xe1, + 0x80, 0x50, 0x39, 0xe2, 0x17, 0x4b, 0x38, 0x07, 0xb7, 0x2c, 0x39, 0xa1, 0x48, + 0xd2, 0x38, 0x3d, 0xfc, 0x06, 0x3a, 0xae, 0x9c, 0x16, 0x3a, 0x53, 0xec, 0x07, + 0x39, 0x9c, 0xa6, 0x10, 0x3a, 0x59, 0x92, 0x9c, 0x38, 0xd0, 0xc6, 0x1f, 0x39, + 0x61, 0x0a, 0x16, 0x39, 0xb9, 0x19, 0x35, 0x3a, 0x4d, 0x18, 0x3b, 0x39, 0x21, + 0x5f, 0x9e, 0x38, 0x70, 0x69, 0xfb, 0x38, 0x85, 0x13, 0x29, 0x39, 0xca, 0x56, + 0x1f, 0x39, 0x98, 0x9d, 0x8a, 0x39, 0x39, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, + 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, + 0x64, 0x5f, 0x33, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, + 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x62, 0x69, + 0x61, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x62, 0x22, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xfc, 0xa8, + 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, + 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, + 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, + 0x64, 0x5f, 0x33, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, + 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x02, 0x23, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, + 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x9c, 0xa9, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, + 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x32, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xa2, 0x23, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x02, 0xe4, 0x01, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0xa0, 0x01, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x24, 0x2a, 0xff, 0xff, 0x10, 0x01, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0xa9, 0x23, 0x8e, 0x39, 0xb2, 0x18, 0xc6, 0x38, 0x94, 0x74, 0x1a, 0x39, 0x67, + 0xb0, 0x1d, 0x39, 0xcd, 0x82, 0xf5, 0x38, 0xb3, 0x69, 0x1d, 0x38, 0x67, 0xcc, + 0x03, 0x39, 0x74, 0xc8, 0x29, 0x39, 0xaf, 0x8a, 0xb9, 0x38, 0x18, 0x9b, 0xa7, + 0x38, 0xb5, 0x00, 0x2d, 0x38, 0x4f, 0x24, 0xfe, 0x38, 0xce, 0xc8, 0x1c, 0x39, + 0xe2, 0x95, 0xfb, 0x38, 0xc4, 0x61, 0x72, 0x39, 0x18, 0x6d, 0x8d, 0x39, 0x57, + 0x16, 0x24, 0x39, 0x92, 0xe1, 0x3c, 0x39, 0x03, 0x6a, 0x5a, 0x38, 0x21, 0x2c, + 0x9b, 0x38, 0xa9, 0x0d, 0x05, 0x39, 0xd1, 0x14, 0x3f, 0x38, 0x2a, 0xa9, 0x11, + 0x39, 0xf1, 0xe3, 0x25, 0x39, 0xd4, 0x0c, 0x05, 0x39, 0x8c, 0x1e, 0xdc, 0x37, + 0xfa, 0xf1, 0x07, 0x39, 0x33, 0x53, 0x34, 0x39, 0x97, 0x2f, 0x6a, 0x39, 0xd0, + 0x60, 0xe8, 0x38, 0x00, 0x42, 0x4d, 0x39, 0xf1, 0xd0, 0xb5, 0x38, 0x36, 0x00, + 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, + 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x32, 0x5f, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, + 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x96, 0x25, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x2c, 0x01, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf2, + 0x1e, 0xff, 0xff, 0x94, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x27, + 0xf0, 0xac, 0x38, 0x4d, 0xb4, 0x95, 0x38, 0x20, 0x35, 0xf3, 0x38, 0xed, 0x7a, + 0xc5, 0x38, 0x08, 0x25, 0x10, 0x39, 0xff, 0xdf, 0xec, 0x38, 0x1b, 0x9b, 0xf9, + 0x38, 0xce, 0x25, 0x84, 0x38, 0x67, 0xff, 0xf7, 0x38, 0xf1, 0x99, 0x5b, 0x39, + 0x59, 0xbf, 0x93, 0x38, 0x9e, 0x8e, 0xf4, 0x38, 0xf9, 0x05, 0xb2, 0x38, 0xa0, + 0x01, 0xad, 0x38, 0x04, 0x3f, 0x24, 0x39, 0xef, 0x8a, 0x32, 0x39, 0x39, 0x00, + 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, + 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x32, 0x5f, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, + 0x73, 0x65, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0xd2, 0x26, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x84, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x6c, 0xad, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, + 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x32, 0x5f, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x72, 0x27, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x44, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0xae, 0xff, 0xff, 0x30, 0x00, + 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, + 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x5f, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, + 0x75, 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x12, 0x28, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x24, 0x01, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x94, 0x2e, + 0xff, 0xff, 0x90, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x58, 0x91, 0xaa, 0x39, 0x89, 0x15, + 0x5a, 0x39, 0x0c, 0xe3, 0xcb, 0x39, 0x37, 0x66, 0x33, 0x39, 0xb6, 0xee, 0x95, + 0x39, 0x82, 0xd1, 0x97, 0x39, 0xc1, 0x33, 0x41, 0x39, 0x27, 0x74, 0x53, 0x39, + 0xfc, 0x35, 0xb0, 0x39, 0x97, 0x5a, 0x4c, 0x39, 0x7b, 0xb4, 0x9e, 0x39, 0x95, + 0xda, 0x45, 0x39, 0xfc, 0x96, 0x95, 0x39, 0x36, 0x8b, 0x2b, 0x39, 0x2f, 0x32, + 0x48, 0x39, 0x51, 0x8f, 0x86, 0x39, 0x36, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, + 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, + 0x64, 0x5f, 0x31, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, + 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x46, 0x29, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x02, 0xcc, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x84, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa2, 0x22, 0xff, 0xff, 0x54, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xfa, 0x50, 0xd3, 0x38, 0x62, + 0x8a, 0x18, 0x39, 0x74, 0x24, 0x61, 0x3b, 0x22, 0x48, 0x8f, 0x38, 0xec, 0xd9, + 0xb4, 0x39, 0x0a, 0xb5, 0x82, 0x38, 0x1c, 0xef, 0x35, 0x39, 0xd6, 0x72, 0xf6, + 0x3b, 0x39, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x5f, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x22, 0x2a, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x44, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xbc, 0xb0, 0xff, 0xff, 0x30, 0x00, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x5f, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, + 0x36, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc2, + 0x2a, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x27, 0x00, + 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x5c, 0xb1, 0xff, + 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x72, + 0x98, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x25, 0xda, 0x97, 0x40, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, + 0x5f, 0x31, 0x33, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, + 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x62, 0x2b, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x64, 0x0c, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0xe4, 0x31, 0xff, 0xff, 0x10, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1f, 0x37, 0xa6, 0x37, 0xa1, 0xb4, 0x00, + 0x38, 0x98, 0x9f, 0xe0, 0x37, 0x43, 0x01, 0x4f, 0x37, 0x0f, 0xa8, 0xe7, 0x37, + 0x6d, 0x06, 0x84, 0x37, 0x96, 0x2b, 0x92, 0x37, 0x4d, 0xf5, 0xe0, 0x37, 0x9e, + 0xa2, 0xa7, 0x37, 0xa0, 0x06, 0xcc, 0x37, 0xe4, 0x70, 0xa6, 0x37, 0x4d, 0x9c, + 0x85, 0x37, 0xbd, 0x71, 0xd4, 0x37, 0xfe, 0x3d, 0x8b, 0x37, 0xd5, 0xe9, 0x87, + 0x37, 0x0a, 0x83, 0xa1, 0x37, 0xae, 0x42, 0xae, 0x37, 0xc5, 0xda, 0x82, 0x37, + 0xad, 0xbd, 0x6b, 0x37, 0xa5, 0x09, 0xbe, 0x37, 0xb8, 0xf0, 0x5c, 0x37, 0x78, + 0xb8, 0x95, 0x37, 0x6a, 0xbe, 0xc1, 0x37, 0xc7, 0xbc, 0x96, 0x37, 0x14, 0xb4, + 0xe4, 0x37, 0xf2, 0x48, 0x92, 0x37, 0x46, 0xc4, 0x06, 0x38, 0x59, 0x42, 0xc5, + 0x37, 0x7c, 0x19, 0x66, 0x37, 0x30, 0xe4, 0x8a, 0x37, 0x5b, 0x24, 0xa4, 0x37, + 0x78, 0x26, 0xba, 0x37, 0xca, 0xbf, 0xd9, 0x37, 0xf5, 0xb8, 0x9c, 0x37, 0xee, + 0xa0, 0x96, 0x37, 0xb5, 0xa5, 0x8f, 0x37, 0x58, 0xa9, 0x9e, 0x37, 0xc0, 0x9e, + 0x79, 0x37, 0x56, 0xde, 0xac, 0x37, 0x89, 0xa8, 0x94, 0x37, 0xcc, 0xeb, 0xc6, + 0x37, 0xd2, 0x26, 0xa3, 0x37, 0x3b, 0x10, 0xc7, 0x37, 0x7c, 0x49, 0xba, 0x37, + 0xbb, 0x07, 0x5a, 0x37, 0xe4, 0x03, 0x6f, 0x37, 0xee, 0x71, 0x93, 0x37, 0x74, + 0x4a, 0x89, 0x37, 0x3d, 0x2f, 0xd1, 0x37, 0x38, 0x2e, 0xca, 0x37, 0xa3, 0x44, + 0xa3, 0x37, 0x4d, 0xbe, 0x6d, 0x37, 0x27, 0x53, 0x88, 0x37, 0x87, 0x38, 0x1c, + 0x38, 0x53, 0x4c, 0x8e, 0x37, 0x3f, 0x6a, 0xbe, 0x37, 0x6a, 0x06, 0xc9, 0x37, + 0xf6, 0xa8, 0x96, 0x37, 0x07, 0x79, 0x87, 0x37, 0xa5, 0x0f, 0xa6, 0x37, 0xc0, + 0x65, 0xa6, 0x37, 0x4d, 0xf4, 0x9a, 0x37, 0xa1, 0x4f, 0xc2, 0x37, 0x49, 0xa7, + 0x8f, 0x37, 0x46, 0x94, 0x68, 0x37, 0xd8, 0x90, 0xa0, 0x37, 0x00, 0x2c, 0x76, + 0x37, 0xe0, 0xdc, 0x92, 0x37, 0x02, 0x50, 0x92, 0x37, 0xb5, 0x1f, 0xab, 0x37, + 0x77, 0x9c, 0xae, 0x37, 0x4f, 0x20, 0x8f, 0x37, 0x30, 0xd6, 0x43, 0x37, 0xbc, + 0xb3, 0x9f, 0x37, 0x08, 0x44, 0x7e, 0x37, 0x8b, 0x1a, 0x79, 0x37, 0x2f, 0xb3, + 0xf9, 0x37, 0x19, 0x9a, 0xa3, 0x37, 0x64, 0xa1, 0x87, 0x37, 0x39, 0xb2, 0x4f, + 0x37, 0x24, 0x04, 0x19, 0x38, 0x06, 0x87, 0x81, 0x37, 0x8b, 0xfb, 0x4f, 0x37, + 0xbc, 0x34, 0x93, 0x37, 0xff, 0x66, 0xd9, 0x37, 0xfc, 0x08, 0x66, 0x37, 0x44, + 0xf8, 0x87, 0x37, 0xfd, 0xf8, 0xec, 0x37, 0x74, 0x22, 0x93, 0x37, 0x8b, 0x02, + 0x99, 0x37, 0x05, 0x49, 0xc1, 0x37, 0x7d, 0x68, 0x7d, 0x37, 0x7e, 0x66, 0x99, + 0x37, 0xff, 0xdd, 0xa3, 0x37, 0xc7, 0x00, 0x5b, 0x37, 0x1b, 0x9c, 0xe9, 0x37, + 0xbe, 0x3f, 0xc6, 0x37, 0x12, 0x48, 0xad, 0x37, 0x61, 0x61, 0xe4, 0x37, 0x61, + 0xd1, 0x81, 0x37, 0x4f, 0xd5, 0x80, 0x37, 0x5b, 0x9b, 0x7c, 0x37, 0xc3, 0x4c, + 0x7c, 0x37, 0xad, 0xdd, 0xa6, 0x37, 0x0f, 0x98, 0xcf, 0x37, 0x6f, 0xb3, 0x83, + 0x37, 0xff, 0xdd, 0x7e, 0x37, 0x8f, 0x15, 0x7e, 0x37, 0x39, 0xbb, 0xb7, 0x37, + 0xc2, 0xa7, 0xa1, 0x37, 0x33, 0xa7, 0xc9, 0x37, 0x5e, 0x0a, 0x7d, 0x37, 0xb5, + 0x3e, 0x45, 0x37, 0xbb, 0x10, 0xe8, 0x37, 0xc9, 0xc0, 0x86, 0x37, 0xb3, 0x01, + 0xc6, 0x37, 0x1a, 0xfe, 0xd6, 0x37, 0x12, 0x88, 0x8b, 0x37, 0x5b, 0x0c, 0xf5, + 0x37, 0xeb, 0x77, 0x7b, 0x37, 0xb1, 0x5b, 0xa6, 0x37, 0x80, 0xb2, 0x6e, 0x37, + 0x2c, 0x7e, 0x78, 0x37, 0xea, 0xc5, 0xa0, 0x37, 0x8c, 0xee, 0xa6, 0x37, 0xf1, + 0x74, 0x7a, 0x37, 0x47, 0xd0, 0x72, 0x37, 0x7a, 0xca, 0xb8, 0x37, 0x4f, 0x17, + 0xb1, 0x37, 0xe8, 0xee, 0xe9, 0x37, 0x0c, 0xb2, 0xf3, 0x37, 0x43, 0xcd, 0xbe, + 0x37, 0x4e, 0xe2, 0xa2, 0x37, 0xcc, 0x69, 0x77, 0x37, 0x63, 0xbf, 0xae, 0x37, + 0xcf, 0xf5, 0x49, 0x37, 0x15, 0x5a, 0xbd, 0x37, 0x87, 0xe5, 0xb5, 0x37, 0x0e, + 0x9c, 0x78, 0x37, 0x58, 0x6c, 0x92, 0x37, 0x82, 0xbe, 0xb3, 0x37, 0xbe, 0xbd, + 0x92, 0x37, 0xd5, 0xe0, 0x97, 0x37, 0xcb, 0xee, 0xa7, 0x37, 0x6e, 0xab, 0xa0, + 0x37, 0x21, 0x07, 0x9d, 0x37, 0xa1, 0x64, 0xac, 0x37, 0x56, 0xbc, 0xa9, 0x37, + 0xb5, 0x8d, 0xb8, 0x37, 0xed, 0x81, 0x87, 0x37, 0x95, 0xbf, 0xaa, 0x37, 0xc1, + 0xd9, 0x93, 0x37, 0xaa, 0x1d, 0x79, 0x37, 0x89, 0xa7, 0x66, 0x37, 0x52, 0x2f, + 0xb7, 0x37, 0x72, 0xb9, 0xa3, 0x37, 0x1d, 0xa3, 0x91, 0x37, 0xe2, 0x52, 0xef, + 0x37, 0xb0, 0x2b, 0x95, 0x37, 0xed, 0x68, 0x97, 0x37, 0x15, 0xd7, 0x76, 0x37, + 0x53, 0xba, 0x95, 0x37, 0x24, 0x50, 0x0a, 0x38, 0xbd, 0xc8, 0x9b, 0x37, 0xcd, + 0x2e, 0x92, 0x37, 0x41, 0x93, 0x8c, 0x37, 0x7d, 0xa0, 0x6e, 0x37, 0x05, 0x97, + 0x97, 0x37, 0x11, 0xc1, 0x5d, 0x37, 0x40, 0x3d, 0xf4, 0x37, 0x88, 0x74, 0x9c, + 0x37, 0x6d, 0x48, 0x6e, 0x37, 0xf1, 0x0a, 0xd1, 0x37, 0x6b, 0x91, 0x87, 0x37, + 0x1d, 0x90, 0x96, 0x37, 0x8a, 0x5c, 0x97, 0x37, 0xcd, 0x78, 0x4c, 0x38, 0xb6, + 0xc4, 0x18, 0x38, 0xe7, 0xee, 0xaa, 0x37, 0x76, 0xff, 0x9c, 0x37, 0x3e, 0xe5, + 0x75, 0x37, 0x5e, 0x91, 0x8d, 0x37, 0xe8, 0x93, 0x94, 0x37, 0x67, 0xa9, 0xa1, + 0x37, 0x38, 0x67, 0xbc, 0x37, 0x0f, 0x70, 0xae, 0x37, 0x56, 0xb9, 0xe5, 0x37, + 0xb9, 0x85, 0x8f, 0x37, 0x9e, 0xfe, 0x89, 0x37, 0xeb, 0x2d, 0x98, 0x37, 0xad, + 0x33, 0x9e, 0x37, 0x15, 0x54, 0xbd, 0x37, 0xac, 0x25, 0x78, 0x37, 0xa2, 0x99, + 0xa2, 0x37, 0x0f, 0x39, 0xb8, 0x37, 0x1d, 0x29, 0x70, 0x37, 0x49, 0x30, 0x88, + 0x37, 0x29, 0x56, 0xc4, 0x37, 0x5c, 0xc7, 0x73, 0x37, 0x5a, 0x86, 0x28, 0x37, + 0xb9, 0x1a, 0x89, 0x37, 0x19, 0x6d, 0x34, 0x37, 0x86, 0xf1, 0xb0, 0x37, 0xc2, + 0xbb, 0xb5, 0x37, 0xb9, 0xcc, 0x9e, 0x37, 0x53, 0xfc, 0xc1, 0x37, 0x15, 0x65, + 0xd7, 0x37, 0x36, 0x53, 0x84, 0x37, 0x11, 0x3c, 0x5f, 0x37, 0x21, 0xdf, 0xad, + 0x37, 0xaa, 0xa4, 0xb3, 0x37, 0xf0, 0x1d, 0xc0, 0x37, 0x89, 0x4d, 0x9d, 0x37, + 0x0b, 0x3f, 0x90, 0x37, 0xc7, 0x60, 0x0d, 0x38, 0x17, 0xd5, 0x62, 0x37, 0x79, + 0xf9, 0x64, 0x37, 0x05, 0xa7, 0x9d, 0x37, 0xa4, 0x54, 0xb6, 0x37, 0xd5, 0xd7, + 0x9a, 0x37, 0x6d, 0x6c, 0xa5, 0x37, 0xbc, 0x04, 0x84, 0x37, 0x26, 0xd0, 0xc6, + 0x37, 0x27, 0x4f, 0xd9, 0x37, 0xe4, 0x88, 0x97, 0x37, 0xa0, 0xb0, 0x90, 0x37, + 0xd0, 0x8a, 0x70, 0x37, 0x37, 0x89, 0x65, 0x37, 0xd0, 0xed, 0x84, 0x37, 0x51, + 0x5b, 0x81, 0x37, 0xa1, 0xcb, 0xcf, 0x37, 0x50, 0x99, 0x89, 0x37, 0x06, 0x12, + 0x98, 0x37, 0xb9, 0x3c, 0x46, 0x37, 0x79, 0x62, 0xc0, 0x37, 0x77, 0x44, 0xfd, + 0x37, 0xe2, 0x7a, 0xc5, 0x37, 0xcd, 0xd7, 0x74, 0x37, 0xfe, 0x0e, 0x80, 0x37, + 0xc2, 0x16, 0xbe, 0x37, 0xd8, 0x0f, 0x0f, 0x38, 0x06, 0x17, 0xd0, 0x37, 0x17, + 0xb5, 0x7e, 0x37, 0xda, 0x09, 0x0d, 0x38, 0x12, 0xbe, 0x6c, 0x37, 0xae, 0x7e, + 0xfe, 0x37, 0xc7, 0xb0, 0xe0, 0x37, 0x2b, 0xdd, 0xaf, 0x37, 0x8a, 0xa2, 0x86, + 0x37, 0x71, 0x66, 0x13, 0x38, 0x3e, 0x15, 0x8b, 0x37, 0xd1, 0x60, 0xa3, 0x37, + 0xd0, 0xe7, 0xf9, 0x37, 0xf3, 0xcf, 0xcb, 0x37, 0xc5, 0x4b, 0xa0, 0x37, 0x35, + 0xae, 0xcb, 0x37, 0x37, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, + 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, + 0x33, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x43, + 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xd6, 0x37, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x02, 0x6c, 0x0c, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x24, 0x0c, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x32, 0x31, 0xff, 0xff, 0x14, 0x08, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0xb0, 0xe5, 0x90, 0x39, 0xc1, 0x92, 0x2e, 0x39, 0x18, 0xad, 0xa1, 0x39, 0x8b, + 0xcb, 0x3b, 0x39, 0x27, 0xd9, 0x0f, 0x39, 0xb2, 0x7b, 0x51, 0x39, 0x41, 0xb1, + 0x05, 0x39, 0x4f, 0x04, 0x77, 0x39, 0xf3, 0x6c, 0x0f, 0x39, 0x3d, 0xfc, 0x77, + 0x39, 0x70, 0x73, 0x25, 0x39, 0x99, 0xd2, 0x12, 0x39, 0x26, 0xc1, 0x33, 0x39, + 0x8f, 0x0b, 0x33, 0x39, 0xae, 0xe1, 0x81, 0x39, 0xe4, 0xf5, 0x62, 0x39, 0x63, + 0x50, 0x20, 0x39, 0x76, 0x82, 0x10, 0x39, 0xc6, 0x80, 0x65, 0x39, 0xf6, 0x7d, + 0x54, 0x39, 0x0f, 0x03, 0x79, 0x39, 0x9b, 0xef, 0x4c, 0x39, 0xa1, 0x12, 0x48, + 0x39, 0x23, 0x63, 0x51, 0x39, 0x52, 0xcf, 0x62, 0x39, 0x3c, 0xff, 0x24, 0x39, + 0x9a, 0xbd, 0x33, 0x39, 0x89, 0x8e, 0x5a, 0x39, 0x53, 0x05, 0x71, 0x39, 0xe1, + 0x35, 0x06, 0x39, 0x36, 0x71, 0x1b, 0x39, 0x3b, 0x22, 0x09, 0x39, 0x4e, 0x59, + 0x17, 0x39, 0x51, 0x6c, 0x31, 0x39, 0xd2, 0x94, 0x46, 0x39, 0x15, 0x9a, 0x4c, + 0x39, 0x68, 0x27, 0x85, 0x39, 0x57, 0x9e, 0x40, 0x39, 0xdd, 0x3e, 0x9e, 0x39, + 0x05, 0x2d, 0x87, 0x39, 0x9b, 0xb1, 0x55, 0x39, 0x79, 0x55, 0x42, 0x39, 0x5e, + 0x90, 0x21, 0x39, 0xa1, 0x2a, 0x2d, 0x39, 0xb0, 0xa2, 0x36, 0x39, 0x06, 0x7a, + 0x40, 0x39, 0x00, 0x86, 0x4d, 0x39, 0x12, 0xab, 0x82, 0x39, 0x90, 0xf3, 0x3f, + 0x39, 0xe0, 0x70, 0x2c, 0x39, 0x5b, 0x73, 0x27, 0x39, 0x54, 0x38, 0x23, 0x39, + 0xf7, 0xd0, 0xff, 0x38, 0xbb, 0x29, 0x5e, 0x39, 0x1b, 0xd5, 0x83, 0x39, 0x4d, + 0xff, 0x25, 0x39, 0x21, 0xa7, 0x28, 0x39, 0x92, 0x5f, 0x2c, 0x39, 0x55, 0x77, + 0x76, 0x39, 0xc4, 0x8a, 0x09, 0x39, 0x5f, 0xdc, 0x3d, 0x39, 0xed, 0xe2, 0x8c, + 0x39, 0xde, 0x2b, 0x44, 0x39, 0x36, 0x74, 0x9c, 0x39, 0xf6, 0xe6, 0x7d, 0x39, + 0x15, 0xad, 0x6c, 0x39, 0x94, 0x7b, 0x23, 0x39, 0x21, 0xda, 0x65, 0x39, 0xf0, + 0xe6, 0x51, 0x39, 0xb0, 0xcd, 0x54, 0x39, 0x93, 0x79, 0x19, 0x39, 0x8c, 0x13, + 0x6c, 0x39, 0x9b, 0x9e, 0x26, 0x39, 0x2e, 0xd8, 0x37, 0x39, 0x2c, 0x02, 0x4e, + 0x39, 0xe1, 0x82, 0x3b, 0x39, 0x80, 0x97, 0x14, 0x39, 0xb0, 0x36, 0x47, 0x39, + 0x4b, 0x5c, 0x84, 0x39, 0xac, 0xcb, 0x38, 0x39, 0xad, 0xc9, 0x78, 0x39, 0x77, + 0x79, 0x25, 0x39, 0x58, 0x48, 0x7a, 0x39, 0xb6, 0x02, 0x31, 0x39, 0x6a, 0xcd, + 0x0b, 0x39, 0xde, 0xf4, 0x50, 0x39, 0xd2, 0x52, 0x83, 0x39, 0x30, 0x2e, 0x34, + 0x39, 0x35, 0x7c, 0x59, 0x39, 0x2c, 0x59, 0x2f, 0x39, 0x3b, 0x14, 0x19, 0x39, + 0xc2, 0x49, 0x26, 0x39, 0xea, 0xbf, 0x4c, 0x39, 0x64, 0xb8, 0x97, 0x39, 0xf3, + 0xb8, 0x52, 0x39, 0xed, 0xde, 0x44, 0x39, 0xb5, 0xb9, 0x58, 0x39, 0x58, 0x74, + 0x62, 0x39, 0x6f, 0x38, 0x1a, 0x39, 0x82, 0x10, 0x2f, 0x39, 0xf7, 0xa6, 0x60, + 0x39, 0xd3, 0xbd, 0x6f, 0x39, 0x12, 0xb3, 0x3b, 0x39, 0xf1, 0x46, 0x42, 0x39, + 0x72, 0xd8, 0x2c, 0x39, 0xd3, 0x91, 0x4e, 0x39, 0xaa, 0x80, 0x26, 0x39, 0x1b, + 0x95, 0xff, 0x38, 0xf0, 0xa8, 0x69, 0x39, 0xcf, 0x29, 0x86, 0x39, 0xd1, 0x23, + 0x1a, 0x39, 0xb6, 0x2f, 0x3a, 0x39, 0xa5, 0x55, 0x1e, 0x39, 0x17, 0xcf, 0x45, + 0x39, 0x15, 0x57, 0xea, 0x38, 0xcf, 0xbb, 0x17, 0x39, 0x52, 0xc3, 0x44, 0x39, + 0x2d, 0x44, 0x66, 0x39, 0x13, 0x22, 0x9e, 0x39, 0xa2, 0x1f, 0x2b, 0x39, 0x6d, + 0xac, 0x57, 0x39, 0x06, 0xa5, 0x84, 0x39, 0x9f, 0x2c, 0x0f, 0x39, 0x2a, 0xab, + 0x35, 0x39, 0x8c, 0x72, 0x49, 0x39, 0x73, 0x53, 0x4c, 0x39, 0xc6, 0x1a, 0x90, + 0x39, 0xf9, 0xa3, 0x6c, 0x39, 0xa7, 0xa9, 0xac, 0x39, 0x5d, 0x07, 0x1c, 0x39, + 0x75, 0x46, 0x21, 0x39, 0x4d, 0xad, 0x4a, 0x39, 0x23, 0x7f, 0x52, 0x39, 0x94, + 0x97, 0x4b, 0x39, 0xab, 0x86, 0x17, 0x39, 0x15, 0xa4, 0x05, 0x39, 0xe3, 0xce, + 0x1b, 0x39, 0xbb, 0xe3, 0xd9, 0x38, 0x55, 0x62, 0x1e, 0x39, 0x8e, 0x3c, 0x6c, + 0x39, 0x92, 0xd5, 0x4d, 0x39, 0x33, 0x73, 0x81, 0x39, 0x98, 0xce, 0xb0, 0x39, + 0x57, 0xe4, 0x25, 0x39, 0x59, 0x1f, 0x67, 0x39, 0x09, 0x6b, 0x77, 0x39, 0xbe, + 0xcc, 0x52, 0x39, 0x30, 0x00, 0x5a, 0x39, 0x24, 0x7f, 0x5c, 0x39, 0x62, 0x99, + 0x6e, 0x39, 0xa7, 0xc8, 0x44, 0x39, 0xd3, 0x1c, 0xf9, 0x38, 0xad, 0xa2, 0x8b, + 0x39, 0x0b, 0xe0, 0x61, 0x39, 0x64, 0xf5, 0x25, 0x39, 0x56, 0x0a, 0x53, 0x39, + 0x35, 0x4a, 0x47, 0x39, 0x0f, 0x33, 0x3c, 0x39, 0xc0, 0xb1, 0x34, 0x39, 0x24, + 0x11, 0x6c, 0x39, 0x32, 0x70, 0x3c, 0x39, 0xfe, 0x33, 0x36, 0x39, 0xe7, 0xbc, + 0xeb, 0x38, 0xba, 0xd8, 0x17, 0x39, 0x27, 0x6b, 0x5f, 0x39, 0xef, 0x82, 0x2d, + 0x39, 0x34, 0x5c, 0x6a, 0x39, 0x8c, 0x54, 0x3b, 0x39, 0x44, 0x16, 0x3c, 0x39, + 0x08, 0x5b, 0x78, 0x39, 0x20, 0xb4, 0xc1, 0x39, 0x49, 0xb8, 0x08, 0x39, 0x08, + 0xe9, 0x63, 0x39, 0x4d, 0x7b, 0x49, 0x39, 0x0a, 0x6c, 0x2c, 0x39, 0x15, 0x27, + 0x86, 0x39, 0x71, 0xda, 0x74, 0x39, 0xb1, 0x10, 0x18, 0x39, 0xa4, 0x45, 0x94, + 0x39, 0x61, 0x87, 0x71, 0x39, 0x8c, 0x1c, 0x64, 0x39, 0x7a, 0x1e, 0x7b, 0x39, + 0x7e, 0xb6, 0x36, 0x39, 0x2f, 0x59, 0x14, 0x39, 0xd5, 0x70, 0x1a, 0x39, 0x12, + 0xa8, 0xc2, 0x39, 0xe5, 0x23, 0x80, 0x39, 0x73, 0xd2, 0x95, 0x39, 0xe4, 0xe4, + 0x2c, 0x39, 0xc7, 0x98, 0x50, 0x39, 0xe2, 0x0d, 0x62, 0x39, 0xef, 0xd1, 0x22, + 0x39, 0xc5, 0xb5, 0x05, 0x39, 0x7b, 0x81, 0x3b, 0x39, 0xe7, 0xc4, 0x00, 0x39, + 0x93, 0xcf, 0x24, 0x39, 0xa4, 0x08, 0x18, 0x39, 0xa9, 0xa7, 0x5f, 0x39, 0x70, + 0xad, 0x8b, 0x39, 0x8c, 0xa8, 0x7c, 0x39, 0x9e, 0x62, 0x85, 0x39, 0x26, 0x5a, + 0x54, 0x39, 0xfc, 0x19, 0x0d, 0x39, 0x66, 0x93, 0x06, 0x39, 0x5c, 0x72, 0x7e, + 0x39, 0xde, 0x33, 0xf3, 0x38, 0x1e, 0x7d, 0x42, 0x39, 0x73, 0xfb, 0x46, 0x39, + 0x9a, 0x5f, 0x96, 0x39, 0x9c, 0xf5, 0x80, 0x39, 0x92, 0x05, 0x2a, 0x39, 0x64, + 0x49, 0x2e, 0x39, 0xcf, 0xb0, 0x3c, 0x39, 0x6e, 0x23, 0x41, 0x39, 0x46, 0xda, + 0x63, 0x39, 0xde, 0x7d, 0x7f, 0x39, 0x2c, 0x55, 0x5c, 0x39, 0xc0, 0x05, 0x29, + 0x39, 0xdf, 0xf3, 0x44, 0x39, 0xba, 0x41, 0x06, 0x39, 0xe5, 0x32, 0x7a, 0x39, + 0xee, 0xf3, 0x67, 0x39, 0x0c, 0x2d, 0x49, 0x39, 0xf7, 0x67, 0x7f, 0x39, 0x86, + 0x07, 0x3b, 0x39, 0x94, 0x91, 0x50, 0x39, 0x8a, 0xc6, 0x32, 0x39, 0x20, 0x3b, + 0x17, 0x39, 0x77, 0xba, 0x46, 0x39, 0x53, 0xe6, 0x58, 0x39, 0x2a, 0x2e, 0x9f, + 0x39, 0x08, 0x04, 0x5a, 0x39, 0x02, 0xc9, 0x2c, 0x39, 0x9e, 0x69, 0x6e, 0x39, + 0x42, 0xac, 0x92, 0x39, 0xb7, 0xa2, 0x17, 0x39, 0x1b, 0x22, 0x7f, 0x39, 0x59, + 0x99, 0x24, 0x39, 0x8c, 0xee, 0x42, 0x39, 0x79, 0xb6, 0x2a, 0x39, 0x41, 0xef, + 0x78, 0x39, 0xad, 0x11, 0x25, 0x39, 0x55, 0x23, 0x07, 0x39, 0x13, 0xd7, 0x38, + 0x39, 0x6e, 0xff, 0x5f, 0x39, 0x80, 0x41, 0x7f, 0x39, 0x58, 0xd1, 0x52, 0x39, + 0x4a, 0x08, 0x74, 0x39, 0x7a, 0xa0, 0x64, 0x39, 0xc1, 0x91, 0x66, 0x39, 0xbe, + 0x37, 0x6e, 0x39, 0xb9, 0xa4, 0x32, 0x39, 0x67, 0x88, 0x00, 0x39, 0xb8, 0xeb, + 0x56, 0x39, 0xec, 0x29, 0x15, 0x39, 0xec, 0x57, 0x40, 0x39, 0x3a, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, + 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x33, 0x5f, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, + 0x73, 0x65, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x52, 0x44, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, + 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0xec, 0xca, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, + 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x33, 0x5f, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xf2, 0x44, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x44, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xcb, 0xff, 0xff, 0x30, 0x00, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x31, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x32, 0x5f, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, + 0x75, 0x36, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x92, + 0x45, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x64, 0x0c, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x4c, 0xff, + 0xff, 0x10, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x5e, 0xab, 0x58, 0x38, 0x1b, 0x09, 0x10, 0x38, 0x76, 0x32, 0x30, + 0x38, 0xb8, 0xde, 0x27, 0x38, 0xe2, 0x95, 0x9b, 0x38, 0xac, 0xeb, 0x28, 0x38, + 0x59, 0xcd, 0x7f, 0x38, 0xfb, 0xe1, 0x81, 0x38, 0x42, 0x88, 0x30, 0x38, 0x21, + 0x9e, 0x49, 0x38, 0x15, 0x51, 0x46, 0x38, 0x57, 0xbd, 0x3e, 0x38, 0x2f, 0xbe, + 0x17, 0x38, 0xdc, 0x57, 0x53, 0x38, 0xae, 0xf1, 0xa4, 0x38, 0x12, 0xd3, 0x64, + 0x38, 0x91, 0x27, 0x7a, 0x38, 0xf3, 0x6c, 0x14, 0x38, 0x97, 0x6f, 0x4a, 0x38, + 0x8b, 0xcb, 0x48, 0x38, 0x08, 0xfb, 0x82, 0x38, 0x3f, 0x07, 0x44, 0x38, 0xdb, + 0xb2, 0x3a, 0x38, 0x27, 0xbd, 0x26, 0x38, 0xde, 0xeb, 0x56, 0x38, 0x6a, 0x0a, + 0x7d, 0x38, 0x79, 0x0c, 0x58, 0x38, 0x98, 0x0d, 0x79, 0x38, 0x22, 0x01, 0x2f, + 0x38, 0xaa, 0x72, 0x46, 0x38, 0x91, 0x50, 0x07, 0x38, 0xea, 0xe2, 0x68, 0x38, + 0x14, 0x55, 0x53, 0x38, 0x32, 0xe4, 0x4b, 0x38, 0x9b, 0x92, 0x0f, 0x38, 0xf7, + 0xef, 0x3c, 0x38, 0x62, 0x4e, 0xa8, 0x38, 0x67, 0x90, 0x3c, 0x38, 0x05, 0xdf, + 0x14, 0x38, 0x3a, 0x8e, 0x7d, 0x38, 0x32, 0x6c, 0x7f, 0x38, 0x05, 0x40, 0x4b, + 0x38, 0x85, 0x4e, 0x46, 0x38, 0xbe, 0x73, 0x26, 0x38, 0xf9, 0x5d, 0x36, 0x38, + 0x8a, 0x30, 0x3d, 0x38, 0x3c, 0x9b, 0x2c, 0x38, 0x6a, 0x3b, 0x2c, 0x38, 0xe1, + 0x38, 0x89, 0x38, 0xdf, 0x1e, 0x5c, 0x38, 0x11, 0x07, 0x4f, 0x38, 0x08, 0x26, + 0x15, 0x38, 0x92, 0x27, 0x75, 0x38, 0xcf, 0x76, 0x3a, 0x38, 0x14, 0x13, 0x55, + 0x38, 0x64, 0x30, 0x53, 0x38, 0x4d, 0x19, 0x75, 0x38, 0xea, 0x65, 0x3d, 0x38, + 0xe5, 0x0c, 0x1d, 0x38, 0xc0, 0xb7, 0x4a, 0x38, 0x9f, 0xc4, 0x1c, 0x38, 0x38, + 0xae, 0x72, 0x38, 0x00, 0xba, 0x11, 0x38, 0xc9, 0xb0, 0x54, 0x38, 0x51, 0xb9, + 0x83, 0x38, 0x30, 0xf6, 0x57, 0x38, 0x2f, 0x3b, 0x4f, 0x38, 0xe4, 0x2f, 0x58, + 0x38, 0x59, 0xec, 0x16, 0x38, 0xf4, 0x06, 0x4a, 0x38, 0x8e, 0x81, 0x41, 0x38, + 0x30, 0x10, 0x40, 0x38, 0xb3, 0xfd, 0x95, 0x38, 0xa9, 0xfa, 0x49, 0x38, 0xcd, + 0x4f, 0x45, 0x38, 0x48, 0x3e, 0x22, 0x38, 0x5b, 0xb5, 0x5e, 0x38, 0x80, 0x22, + 0x44, 0x38, 0x02, 0x38, 0x78, 0x38, 0xfc, 0x94, 0xef, 0x38, 0xc1, 0xab, 0x95, + 0x38, 0xfc, 0x35, 0x17, 0x38, 0xcd, 0xd4, 0x6d, 0x38, 0xa0, 0xed, 0xe6, 0x37, + 0x17, 0xfc, 0x26, 0x38, 0x9a, 0x2a, 0xdd, 0x37, 0x00, 0x2a, 0x6e, 0x38, 0xc3, + 0xcf, 0x97, 0x38, 0x4b, 0x50, 0x1a, 0x38, 0x34, 0xe2, 0x78, 0x38, 0x65, 0x83, + 0x76, 0x38, 0xff, 0xf5, 0x8f, 0x38, 0x00, 0x75, 0x4c, 0x38, 0xed, 0x8f, 0x8a, + 0x38, 0xa4, 0x3f, 0x6c, 0x38, 0x32, 0x37, 0x66, 0x38, 0xb9, 0xa6, 0x40, 0x38, + 0x6f, 0x8b, 0x40, 0x38, 0xea, 0x25, 0x5f, 0x38, 0x8c, 0xbb, 0x52, 0x38, 0x1e, + 0x92, 0x4d, 0x38, 0x64, 0xda, 0x51, 0x38, 0xb2, 0xc2, 0x16, 0x38, 0xa6, 0x8a, + 0x2f, 0x38, 0x8b, 0x23, 0x58, 0x38, 0x9d, 0x86, 0x4c, 0x38, 0x39, 0xd1, 0x24, + 0x38, 0x59, 0x2d, 0x2d, 0x38, 0xdd, 0x33, 0x92, 0x38, 0x39, 0xe8, 0x28, 0x38, + 0xc6, 0x34, 0x57, 0x38, 0x16, 0xd8, 0x2d, 0x38, 0x44, 0x45, 0x63, 0x38, 0x12, + 0x10, 0x9b, 0x38, 0xf7, 0x0b, 0x05, 0x38, 0xae, 0x23, 0x35, 0x38, 0xd5, 0xd1, + 0x96, 0x38, 0xfd, 0xf5, 0x81, 0x38, 0x0b, 0x99, 0x71, 0x38, 0xd5, 0xae, 0x7e, + 0x38, 0xb0, 0x03, 0x50, 0x38, 0xff, 0x6c, 0x70, 0x38, 0xbd, 0xeb, 0x23, 0x38, + 0xce, 0xd1, 0x33, 0x38, 0x27, 0xe9, 0x3f, 0x38, 0x94, 0xc7, 0x39, 0x38, 0x1c, + 0x36, 0x22, 0x38, 0xb0, 0x96, 0x37, 0x38, 0x2e, 0x1b, 0x24, 0x38, 0xa6, 0x99, + 0x53, 0x38, 0x89, 0x1b, 0x3e, 0x38, 0x4d, 0x3d, 0x65, 0x38, 0x82, 0xda, 0x30, + 0x38, 0x7f, 0xe9, 0x47, 0x38, 0xe8, 0xd4, 0xa1, 0x38, 0xc1, 0x4b, 0x2f, 0x38, + 0x68, 0x9d, 0x48, 0x38, 0x62, 0xfb, 0x09, 0x38, 0xa7, 0x96, 0xff, 0x37, 0xb3, + 0x52, 0x43, 0x38, 0x3f, 0x5f, 0x2a, 0x38, 0x08, 0x03, 0x76, 0x38, 0x11, 0x90, + 0x2d, 0x38, 0xed, 0x50, 0x4f, 0x38, 0x46, 0xf5, 0x75, 0x38, 0x73, 0xd3, 0x8e, + 0x38, 0x4a, 0x4a, 0x84, 0x38, 0xaf, 0xdc, 0x82, 0x38, 0x77, 0xda, 0x24, 0x38, + 0x5e, 0x8b, 0x45, 0x38, 0x6e, 0x38, 0x4a, 0x38, 0x12, 0x5b, 0x3c, 0x38, 0x7c, + 0x27, 0x68, 0x38, 0x77, 0x4e, 0x0f, 0x38, 0xb6, 0x1d, 0x5c, 0x38, 0xa2, 0x68, + 0x9c, 0x38, 0x32, 0x4e, 0x5c, 0x38, 0xa4, 0xeb, 0x6b, 0x38, 0xfa, 0x00, 0x69, + 0x38, 0xe1, 0xb9, 0x5a, 0x38, 0xe2, 0xa4, 0x57, 0x38, 0xb3, 0x7c, 0x4e, 0x38, + 0xef, 0x33, 0x32, 0x38, 0x6b, 0x57, 0x08, 0x38, 0x25, 0xf4, 0x2b, 0x38, 0x26, + 0x3a, 0x74, 0x38, 0xc7, 0x13, 0x74, 0x38, 0x1f, 0x16, 0x82, 0x38, 0x27, 0x5f, + 0x21, 0x38, 0xbe, 0x7b, 0x7d, 0x38, 0x7b, 0x58, 0x98, 0x38, 0xe7, 0x8b, 0x95, + 0x38, 0x4f, 0xd2, 0x3c, 0x38, 0xdb, 0x19, 0x3f, 0x38, 0x06, 0xed, 0x7d, 0x38, + 0x75, 0x64, 0x2a, 0x38, 0xcf, 0x6a, 0x56, 0x38, 0x32, 0x2a, 0x39, 0x38, 0xb3, + 0xd9, 0x4d, 0x38, 0x8f, 0xe5, 0x79, 0x38, 0x20, 0xf9, 0x4a, 0x38, 0x9b, 0x1b, + 0x4f, 0x38, 0xa1, 0xbf, 0x9e, 0x38, 0xa5, 0x73, 0x3a, 0x38, 0x33, 0xe8, 0x34, + 0x38, 0xbb, 0x0b, 0x3b, 0x38, 0x8b, 0xbd, 0x42, 0x38, 0xc6, 0x6b, 0x38, 0x38, + 0x80, 0x3c, 0x52, 0x38, 0x18, 0xd2, 0x8b, 0x38, 0x2e, 0x63, 0x40, 0x38, 0x07, + 0x07, 0x3d, 0x38, 0xb8, 0x65, 0x5a, 0x38, 0xa2, 0x62, 0x11, 0x38, 0x44, 0x30, + 0x4b, 0x38, 0x7c, 0xf0, 0x4c, 0x38, 0x5b, 0xf6, 0x3d, 0x38, 0x2f, 0x0b, 0x84, + 0x38, 0xc7, 0xb6, 0x77, 0x38, 0x7c, 0x0e, 0x82, 0x38, 0x3e, 0x69, 0x6a, 0x38, + 0x80, 0x1a, 0x62, 0x38, 0x55, 0x09, 0x7f, 0x38, 0x05, 0x5b, 0x89, 0x38, 0xbf, + 0xa8, 0x10, 0x38, 0xac, 0x94, 0x86, 0x38, 0x84, 0xe1, 0x39, 0x38, 0xcd, 0xe1, + 0x6c, 0x38, 0x44, 0xc8, 0x6d, 0x38, 0xb5, 0x9e, 0x32, 0x38, 0xb0, 0x68, 0x71, + 0x38, 0x58, 0x21, 0x1f, 0x38, 0x68, 0x40, 0x4a, 0x38, 0xb5, 0x63, 0x7e, 0x38, + 0x51, 0x7d, 0x25, 0x38, 0x76, 0x9f, 0x4e, 0x38, 0xc6, 0x16, 0x7e, 0x38, 0x82, + 0x8f, 0x41, 0x38, 0xbe, 0x2b, 0x58, 0x38, 0xe2, 0x0c, 0x5e, 0x38, 0xff, 0xba, + 0x83, 0x38, 0xf0, 0x81, 0x99, 0x38, 0x97, 0x78, 0x4f, 0x38, 0x44, 0x39, 0x51, + 0x38, 0x49, 0xee, 0x6f, 0x38, 0x32, 0xce, 0x0c, 0x38, 0x67, 0x24, 0x2f, 0x38, + 0xde, 0xb2, 0x52, 0x38, 0xad, 0x9c, 0x36, 0x38, 0x03, 0x36, 0x23, 0x38, 0x55, + 0x22, 0x60, 0x38, 0x68, 0xd0, 0x87, 0x38, 0x77, 0x81, 0x41, 0x38, 0x0b, 0xc1, + 0x4c, 0x38, 0x41, 0xfd, 0x7a, 0x38, 0x32, 0x30, 0x24, 0x38, 0x0c, 0xca, 0x24, + 0x38, 0xb9, 0xa1, 0x48, 0x38, 0x92, 0x65, 0x73, 0x38, 0x20, 0x5f, 0x55, 0x38, + 0xdb, 0xe4, 0x2a, 0x38, 0x86, 0x64, 0x13, 0x38, 0x71, 0x46, 0x5a, 0x38, 0x3e, + 0x8c, 0x96, 0x38, 0x09, 0xa2, 0x35, 0x38, 0x49, 0x97, 0x71, 0x38, 0x38, 0xd5, + 0x4b, 0x38, 0xd9, 0xfc, 0x5a, 0x38, 0x7a, 0xbd, 0x73, 0x38, 0xba, 0x91, 0x8a, + 0x38, 0xcc, 0x88, 0x54, 0x38, 0xaa, 0xbe, 0x3f, 0x38, 0x39, 0xe4, 0x2d, 0x38, + 0x47, 0x27, 0x4a, 0x38, 0x22, 0xc9, 0x98, 0x38, 0x3c, 0x45, 0x93, 0x38, 0x37, + 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, + 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, + 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x32, 0x5f, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, + 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x06, 0x52, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x6c, 0x06, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x24, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x62, 0x4b, 0xff, 0xff, 0x14, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xaf, + 0xee, 0x04, 0x39, 0x1a, 0x2d, 0xe1, 0x38, 0xcd, 0x5c, 0x4a, 0x39, 0x9e, 0x09, + 0x23, 0x39, 0x24, 0x90, 0x63, 0x39, 0x5e, 0x18, 0xd8, 0x38, 0x4f, 0x1f, 0x02, + 0x39, 0x8f, 0x4d, 0x25, 0x39, 0xb8, 0x22, 0xe3, 0x38, 0xbb, 0xb9, 0x51, 0x39, + 0x64, 0x85, 0x10, 0x39, 0xfc, 0xae, 0xee, 0x38, 0x6d, 0x49, 0x23, 0x39, 0x77, + 0xdd, 0x05, 0x39, 0xac, 0xbd, 0xfc, 0x38, 0xfc, 0x0d, 0x1b, 0x39, 0x8f, 0xdc, + 0x65, 0x39, 0x40, 0xf4, 0x2c, 0x39, 0x34, 0xb4, 0x0b, 0x39, 0xc5, 0x81, 0x01, + 0x39, 0xbe, 0xfd, 0x06, 0x39, 0x4c, 0xa1, 0xe8, 0x38, 0x53, 0xb2, 0x25, 0x39, + 0xcb, 0x38, 0x0b, 0x39, 0x73, 0x8a, 0xce, 0x38, 0x69, 0xdc, 0x28, 0x39, 0x95, + 0x30, 0x0e, 0x39, 0xee, 0x53, 0xdd, 0x38, 0x1a, 0x2f, 0x33, 0x39, 0xbf, 0x3e, + 0x1e, 0x39, 0x45, 0x1b, 0x1e, 0x39, 0x12, 0x7d, 0x3e, 0x39, 0x16, 0x99, 0x24, + 0x39, 0x2a, 0xbc, 0x36, 0x39, 0xa1, 0x90, 0x05, 0x39, 0xbe, 0x5a, 0x33, 0x39, + 0x74, 0x39, 0x2d, 0x39, 0x1b, 0xc8, 0xbe, 0x38, 0x73, 0xbe, 0xda, 0x38, 0xff, + 0x96, 0x5e, 0x39, 0xb8, 0xdb, 0xc5, 0x38, 0x08, 0x9c, 0x74, 0x39, 0x5c, 0x88, + 0x46, 0x39, 0x2f, 0x30, 0x12, 0x39, 0xe2, 0x1a, 0xff, 0x38, 0xf5, 0x05, 0x12, + 0x39, 0xd8, 0x56, 0xed, 0x38, 0xee, 0xd7, 0x53, 0x39, 0xf4, 0x60, 0xfa, 0x38, + 0x44, 0x47, 0xfc, 0x38, 0x65, 0x71, 0xf3, 0x38, 0x7d, 0x30, 0xdc, 0x38, 0x8c, + 0xb8, 0x2e, 0x39, 0x7a, 0x16, 0x40, 0x39, 0x1f, 0x90, 0x29, 0x39, 0xf5, 0x2a, + 0x39, 0x39, 0x15, 0x22, 0xde, 0x38, 0x49, 0x46, 0x28, 0x39, 0x24, 0x4d, 0xc1, + 0x38, 0x9a, 0x81, 0x05, 0x39, 0xb0, 0xfd, 0x31, 0x39, 0x87, 0x96, 0x35, 0x39, + 0xfd, 0x04, 0x14, 0x39, 0x56, 0x18, 0xce, 0x38, 0xe7, 0x38, 0x04, 0x39, 0x89, + 0x3d, 0x2d, 0x39, 0xad, 0x29, 0xe1, 0x38, 0x89, 0x83, 0x17, 0x39, 0xa7, 0x0c, + 0x16, 0x39, 0x41, 0x56, 0x4d, 0x39, 0x04, 0x5a, 0x0f, 0x39, 0x6d, 0x76, 0xd5, + 0x38, 0x6a, 0xbd, 0x03, 0x39, 0x8e, 0x29, 0xdd, 0x38, 0xa9, 0x07, 0x09, 0x39, + 0x75, 0x72, 0x02, 0x39, 0x9b, 0x42, 0xb7, 0x38, 0x42, 0x41, 0x03, 0x39, 0xbc, + 0xb7, 0x1e, 0x39, 0x2c, 0xaa, 0xf1, 0x38, 0xaf, 0xed, 0x1f, 0x39, 0x8c, 0xe9, + 0x3d, 0x39, 0x4f, 0xae, 0x02, 0x39, 0xb3, 0x70, 0x19, 0x39, 0x78, 0xa2, 0x37, + 0x39, 0xcf, 0xbf, 0x24, 0x39, 0x11, 0x48, 0x2a, 0x39, 0x88, 0xc4, 0x09, 0x39, + 0xb8, 0x9c, 0x61, 0x39, 0x2a, 0xbb, 0x2d, 0x39, 0x4d, 0x46, 0xb3, 0x38, 0x2c, + 0xb1, 0x2f, 0x39, 0x3b, 0xb2, 0x5c, 0x39, 0x68, 0x02, 0x0b, 0x39, 0xac, 0x5f, + 0x0e, 0x39, 0x97, 0x49, 0x52, 0x39, 0x5b, 0x3c, 0xf5, 0x38, 0x9c, 0x54, 0x14, + 0x39, 0xa5, 0x79, 0x19, 0x39, 0x05, 0x86, 0xf3, 0x38, 0x98, 0xb5, 0x4e, 0x39, + 0xeb, 0x2d, 0x65, 0x39, 0x64, 0xe8, 0x74, 0x39, 0x2c, 0xf8, 0xf9, 0x38, 0x76, + 0x51, 0x20, 0x39, 0x6d, 0xf2, 0xf9, 0x38, 0x23, 0xa2, 0x4d, 0x39, 0xb9, 0xfe, + 0x14, 0x39, 0xcc, 0x69, 0x09, 0x39, 0xa2, 0x12, 0x85, 0x39, 0x09, 0x0a, 0x39, + 0x39, 0xc0, 0xa2, 0xf4, 0x38, 0x3e, 0x22, 0x19, 0x39, 0xa1, 0x25, 0x0e, 0x39, + 0x1b, 0xf8, 0x13, 0x39, 0x19, 0x29, 0x16, 0x39, 0xa0, 0x37, 0x5e, 0x39, 0x24, + 0x0b, 0x1c, 0x39, 0x9d, 0x0b, 0xce, 0x38, 0x1b, 0x8f, 0xe9, 0x38, 0xd7, 0x0e, + 0x26, 0x39, 0x18, 0x13, 0xc2, 0x38, 0x5a, 0xb2, 0x07, 0x39, 0xe5, 0xa3, 0x74, + 0x39, 0x15, 0x8b, 0x99, 0x38, 0x37, 0xae, 0xfe, 0x38, 0x85, 0x31, 0x53, 0x39, + 0x73, 0x9b, 0x49, 0x39, 0x3a, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x31, 0x32, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, + 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x62, 0x69, 0x61, + 0x73, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x82, 0x58, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, + 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0xdf, 0xff, 0xff, + 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, + 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x31, 0x32, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, + 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x22, 0x59, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, + 0x00, 0x26, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xbc, 0xdf, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x31, 0x31, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, + 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc2, 0x59, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x02, 0x64, 0x06, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x44, 0x60, 0xff, 0xff, 0x10, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x69, + 0x47, 0x9f, 0x38, 0x5b, 0xf0, 0x8b, 0x38, 0xaa, 0xcd, 0x9a, 0x38, 0x40, 0x1d, + 0x5d, 0x38, 0x15, 0xe3, 0x78, 0x38, 0xdb, 0x22, 0x2f, 0x38, 0xb7, 0xfc, 0x7c, + 0x38, 0x05, 0xdd, 0x4b, 0x38, 0x70, 0xd6, 0x56, 0x38, 0xfd, 0x3d, 0x4a, 0x38, + 0x70, 0xb2, 0x4d, 0x38, 0x21, 0xe6, 0x7e, 0x38, 0x51, 0xa8, 0x8b, 0x38, 0x00, + 0x8f, 0x43, 0x38, 0x02, 0xd3, 0x73, 0x38, 0x4c, 0x13, 0x44, 0x38, 0x1e, 0x6c, + 0xa3, 0x38, 0xa9, 0x97, 0x88, 0x38, 0x5b, 0x0c, 0x3e, 0x38, 0xf6, 0x0a, 0x6a, + 0x38, 0x1a, 0x32, 0x71, 0x38, 0x05, 0xfb, 0x42, 0x38, 0x7d, 0x9d, 0x57, 0x38, + 0x1e, 0x05, 0x7c, 0x38, 0x9b, 0x6e, 0x9b, 0x38, 0xe5, 0x57, 0x55, 0x38, 0x15, + 0xcd, 0x74, 0x38, 0x79, 0xb9, 0x82, 0x38, 0x9a, 0x43, 0x30, 0x38, 0xa6, 0xd0, + 0x75, 0x38, 0xba, 0x21, 0x79, 0x38, 0x85, 0x96, 0x5f, 0x38, 0x89, 0xcb, 0x5d, + 0x38, 0xee, 0xb0, 0x90, 0x38, 0x39, 0xf4, 0x8c, 0x38, 0x98, 0xf8, 0x3a, 0x38, + 0x85, 0x5f, 0x65, 0x38, 0x93, 0x54, 0x39, 0x38, 0xf6, 0xa8, 0x77, 0x38, 0xb8, + 0xa7, 0x58, 0x38, 0x38, 0x90, 0x54, 0x38, 0x66, 0x29, 0x8a, 0x38, 0xbb, 0xbe, + 0x59, 0x38, 0x69, 0x3f, 0x85, 0x38, 0x96, 0x0d, 0xaa, 0x38, 0x2b, 0x8d, 0x98, + 0x38, 0x0b, 0x19, 0x57, 0x38, 0x14, 0x47, 0x7c, 0x38, 0xe1, 0x06, 0x91, 0x38, + 0xaa, 0x54, 0x72, 0x38, 0xaa, 0x43, 0x4b, 0x38, 0x24, 0x3a, 0x55, 0x38, 0xad, + 0xc2, 0x45, 0x38, 0x38, 0xd2, 0x6c, 0x38, 0x21, 0x95, 0x43, 0x38, 0xd6, 0x2d, + 0x5f, 0x38, 0x6b, 0x28, 0xaa, 0x38, 0x59, 0xf8, 0x56, 0x38, 0x3d, 0xa1, 0x72, + 0x38, 0xcf, 0x5e, 0x46, 0x38, 0x98, 0x72, 0x64, 0x38, 0x59, 0xb0, 0x82, 0x38, + 0x93, 0x97, 0x89, 0x38, 0x94, 0x0b, 0x71, 0x38, 0x68, 0x1e, 0x9e, 0x38, 0x4f, + 0x79, 0x6b, 0x38, 0x64, 0x7c, 0x71, 0x38, 0x5c, 0x15, 0x69, 0x38, 0x5c, 0x37, + 0x82, 0x38, 0xbb, 0x01, 0x5e, 0x38, 0x38, 0x98, 0x3c, 0x38, 0x40, 0xc6, 0x59, + 0x38, 0xa7, 0x14, 0x57, 0x38, 0xa7, 0xad, 0x8f, 0x38, 0x1a, 0xc8, 0x51, 0x38, + 0x30, 0x3a, 0x6b, 0x38, 0x18, 0xbd, 0x2f, 0x38, 0x27, 0x7e, 0x34, 0x38, 0x24, + 0xe2, 0x84, 0x38, 0x5c, 0x2c, 0x74, 0x38, 0xfd, 0xc7, 0xc2, 0x38, 0xe7, 0xfd, + 0xb9, 0x38, 0x1a, 0x1c, 0x75, 0x38, 0x07, 0x09, 0x86, 0x38, 0x1b, 0x05, 0x4b, + 0x38, 0x4f, 0xc3, 0x5a, 0x38, 0xbc, 0x2c, 0x36, 0x38, 0x17, 0x0d, 0x45, 0x38, + 0xb3, 0x8a, 0x92, 0x38, 0x30, 0x8f, 0x94, 0x38, 0x79, 0xf2, 0x53, 0x38, 0x2c, + 0x41, 0x95, 0x38, 0x57, 0x91, 0x8f, 0x38, 0x46, 0x02, 0x4b, 0x38, 0xd0, 0xaa, + 0x2d, 0x38, 0xe4, 0x49, 0x5a, 0x38, 0xf2, 0xaa, 0x37, 0x38, 0x02, 0x5e, 0x5a, + 0x38, 0x30, 0x54, 0x40, 0x38, 0x44, 0xbc, 0xb3, 0x38, 0xe7, 0x64, 0x79, 0x38, + 0xe5, 0x9f, 0x78, 0x38, 0x9c, 0x06, 0x88, 0x38, 0x2d, 0x40, 0x77, 0x38, 0x82, + 0x16, 0x2f, 0x38, 0xce, 0xd7, 0x8c, 0x38, 0x11, 0x5a, 0x54, 0x38, 0xa5, 0x49, + 0x8a, 0x38, 0xa3, 0x55, 0x6f, 0x38, 0x39, 0xb9, 0x4d, 0x38, 0xcb, 0x17, 0x85, + 0x38, 0x20, 0xec, 0x5f, 0x38, 0xe8, 0x9c, 0x7f, 0x38, 0x12, 0xe5, 0x55, 0x38, + 0xcc, 0xb5, 0x6b, 0x38, 0xc3, 0xa4, 0x6c, 0x38, 0x2e, 0x80, 0x87, 0x38, 0xb6, + 0x54, 0x47, 0x38, 0xfd, 0x78, 0x88, 0x38, 0xca, 0x4d, 0x62, 0x38, 0x88, 0x90, + 0x74, 0x38, 0xf6, 0xe1, 0x42, 0x38, 0x0b, 0x9f, 0x55, 0x38, 0xfb, 0xe5, 0x94, + 0x38, 0x2c, 0x57, 0x49, 0x38, 0x58, 0xdf, 0x76, 0x38, 0x7f, 0x56, 0x9a, 0x38, + 0x80, 0x6d, 0x6d, 0x38, 0x37, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x31, 0x31, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x36, 0x60, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x02, 0x6c, 0x06, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x24, 0x06, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x92, 0x59, 0xff, 0xff, 0x14, 0x04, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0xa6, 0x5d, 0x16, 0x39, 0x80, 0xca, 0x26, 0x39, 0x1d, + 0x38, 0x4e, 0x39, 0x85, 0x11, 0x0e, 0x39, 0x7a, 0xb2, 0xf1, 0x38, 0xe4, 0x71, + 0xf9, 0x38, 0xf8, 0xbb, 0x22, 0x39, 0x83, 0xfe, 0x50, 0x39, 0xa7, 0x56, 0x2a, + 0x39, 0x64, 0xa7, 0x64, 0x39, 0xc3, 0x88, 0x5f, 0x39, 0xe8, 0x19, 0x12, 0x39, + 0x73, 0xa6, 0x46, 0x39, 0x32, 0xc1, 0x7c, 0x39, 0xfc, 0x05, 0x25, 0x39, 0x2c, + 0x83, 0xdd, 0x38, 0x09, 0x83, 0x3f, 0x39, 0x1a, 0xee, 0xf2, 0x38, 0xca, 0x53, + 0xff, 0x38, 0x98, 0xc7, 0x8a, 0x38, 0x3c, 0x4e, 0x0a, 0x39, 0xbb, 0xe2, 0x2a, + 0x39, 0x73, 0x31, 0xa6, 0x38, 0xba, 0x18, 0x16, 0x39, 0x16, 0x5c, 0x26, 0x39, + 0x16, 0x0f, 0x23, 0x39, 0x9d, 0x2c, 0x7a, 0x39, 0xed, 0x6f, 0x80, 0x39, 0xfd, + 0xae, 0x61, 0x39, 0xb5, 0xd3, 0x56, 0x39, 0x52, 0xe0, 0xaa, 0x38, 0x71, 0x4c, + 0x34, 0x39, 0x86, 0x28, 0x3a, 0x39, 0xff, 0xb9, 0x3d, 0x39, 0x86, 0x87, 0xff, + 0x38, 0x5b, 0xb7, 0x33, 0x39, 0x6e, 0x8a, 0xdc, 0x38, 0xd8, 0xfa, 0x17, 0x39, + 0xfa, 0x05, 0x9b, 0x39, 0x54, 0x55, 0x03, 0x39, 0x2e, 0x3e, 0x38, 0x39, 0x55, + 0xe2, 0x58, 0x39, 0x6b, 0x3d, 0x7a, 0x39, 0xa9, 0xf1, 0x01, 0x39, 0xc4, 0x32, + 0xd8, 0x38, 0x2f, 0xa2, 0xe2, 0x38, 0x64, 0x41, 0x24, 0x39, 0x74, 0x1a, 0x21, + 0x39, 0x02, 0x5f, 0x36, 0x39, 0x27, 0x2b, 0x03, 0x39, 0xfc, 0xdf, 0xf0, 0x38, + 0x63, 0xa1, 0x31, 0x39, 0x45, 0x79, 0x16, 0x39, 0xd8, 0x1d, 0x39, 0x39, 0x72, + 0x33, 0x1b, 0x39, 0xe9, 0x8d, 0x85, 0x39, 0xcd, 0xf4, 0x07, 0x39, 0x30, 0x96, + 0x60, 0x39, 0x2d, 0x4a, 0x36, 0x39, 0x73, 0xac, 0x17, 0x39, 0x8f, 0x96, 0x04, + 0x39, 0xe0, 0xe9, 0x14, 0x39, 0x02, 0xd8, 0x74, 0x39, 0xd3, 0x31, 0x3b, 0x39, + 0xc6, 0x17, 0x61, 0x39, 0x47, 0xbf, 0x00, 0x39, 0x3b, 0x76, 0xf1, 0x38, 0x1b, + 0x81, 0xeb, 0x38, 0xd8, 0xf2, 0xf8, 0x38, 0xbd, 0xd6, 0x2a, 0x39, 0x99, 0x29, + 0x23, 0x39, 0xa7, 0x7a, 0x10, 0x39, 0x7d, 0x22, 0x30, 0x39, 0x9b, 0xd2, 0xf2, + 0x38, 0xfd, 0x0b, 0x16, 0x39, 0x88, 0xd2, 0x14, 0x39, 0x0c, 0x47, 0x46, 0x39, + 0x25, 0x27, 0x35, 0x39, 0xed, 0xda, 0x4c, 0x39, 0x61, 0xa7, 0x3d, 0x39, 0x47, + 0xde, 0xfb, 0x38, 0x92, 0x79, 0xf0, 0x38, 0x33, 0x22, 0x1d, 0x39, 0xe0, 0x77, + 0xb5, 0x38, 0xcc, 0x41, 0x13, 0x39, 0x32, 0xe3, 0x24, 0x39, 0xef, 0xfb, 0x3c, + 0x39, 0x18, 0x5d, 0x89, 0x39, 0xed, 0xb6, 0x31, 0x39, 0x80, 0xf8, 0xdc, 0x38, + 0xde, 0xc0, 0x61, 0x39, 0xab, 0x1b, 0x1d, 0x39, 0xd7, 0xde, 0x3a, 0x39, 0x2b, + 0xa0, 0x80, 0x39, 0x9b, 0xbf, 0x6f, 0x39, 0xa3, 0x07, 0x82, 0x39, 0x11, 0xa3, + 0x68, 0x39, 0x0d, 0x4d, 0x28, 0x39, 0x37, 0xf5, 0xe5, 0x38, 0xe2, 0x07, 0x1d, + 0x39, 0x22, 0xe9, 0x2b, 0x39, 0x64, 0x6d, 0xdc, 0x38, 0xe7, 0xfb, 0x96, 0x38, + 0xa9, 0x83, 0x2e, 0x39, 0xce, 0x74, 0x31, 0x39, 0xa4, 0xab, 0x71, 0x39, 0xf6, + 0xbc, 0x3b, 0x39, 0xb8, 0x99, 0x7f, 0x39, 0xa7, 0xd0, 0x18, 0x39, 0x3b, 0x6e, + 0x5f, 0x39, 0x35, 0x63, 0xd0, 0x38, 0x92, 0xbf, 0xf0, 0x38, 0x99, 0x14, 0x40, + 0x39, 0x36, 0xed, 0x0d, 0x39, 0x67, 0x31, 0x17, 0x39, 0x3e, 0x94, 0x28, 0x39, + 0x57, 0x94, 0x17, 0x39, 0x1e, 0x64, 0x11, 0x39, 0x73, 0x4a, 0x72, 0x39, 0xa7, + 0xf6, 0x39, 0x39, 0x73, 0xd8, 0x35, 0x39, 0xc5, 0x95, 0x1a, 0x39, 0x01, 0xa4, + 0x07, 0x39, 0x15, 0x2b, 0x2f, 0x39, 0xcf, 0xa3, 0x5c, 0x39, 0x98, 0xfc, 0x71, + 0x39, 0x66, 0xc2, 0x88, 0x39, 0xc0, 0xba, 0x55, 0x39, 0x3a, 0x00, 0x00, 0x00, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, + 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x31, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, + 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, + 0x65, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0xb2, 0x66, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x84, 0x00, + 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x4c, 0xed, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, + 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x31, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, + 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x52, 0x67, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0xec, 0xed, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x31, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, + 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x30, 0x5f, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, + 0x36, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xf2, 0x67, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x64, 0x06, 0x00, 0x00, 0x46, 0x00, 0x00, + 0x00, 0x20, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x74, 0x6e, 0xff, 0xff, + 0x10, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x0f, 0xdb, 0x81, 0x38, 0x9a, 0x27, 0x6e, 0x38, 0xf4, + 0x34, 0x6d, 0x38, 0xd5, 0x59, 0x5c, 0x38, 0xfa, 0x44, 0x57, 0x38, 0x7d, 0xe6, + 0x46, 0x38, 0xc9, 0xad, 0x3f, 0x38, 0xcc, 0x17, 0x2a, 0x38, 0xc3, 0x1f, 0x69, + 0x38, 0x5a, 0x69, 0x85, 0x38, 0xa7, 0xd6, 0xad, 0x38, 0xd1, 0x8d, 0x8a, 0x38, + 0x68, 0xae, 0x66, 0x38, 0xeb, 0xdf, 0x6a, 0x38, 0x20, 0x8b, 0x56, 0x38, 0x3c, + 0x9c, 0x91, 0x38, 0x20, 0xc1, 0x8e, 0x38, 0x56, 0x75, 0x5d, 0x38, 0xb0, 0x8a, + 0x82, 0x38, 0xd1, 0xe7, 0x87, 0x38, 0xa7, 0xbf, 0x82, 0x38, 0x8b, 0xf8, 0xa1, + 0x38, 0x6e, 0x1e, 0x6c, 0x38, 0xbb, 0x19, 0x7f, 0x38, 0x32, 0xb7, 0x7a, 0x38, + 0xb2, 0x5a, 0x75, 0x38, 0x36, 0x30, 0xaa, 0x38, 0x09, 0x83, 0x67, 0x38, 0x76, + 0x02, 0x91, 0x38, 0x95, 0x5a, 0x7b, 0x38, 0xc1, 0xa1, 0x55, 0x38, 0x6a, 0x3e, + 0x3d, 0x38, 0x67, 0xf7, 0x6f, 0x38, 0x32, 0x6e, 0x40, 0x38, 0x0f, 0x3a, 0x86, + 0x38, 0xb5, 0xd7, 0x7d, 0x38, 0x6c, 0xfd, 0xa5, 0x38, 0x24, 0xfa, 0x7b, 0x38, + 0x47, 0x81, 0x70, 0x38, 0xad, 0x65, 0x65, 0x38, 0xa2, 0xce, 0x83, 0x38, 0x27, + 0xa2, 0x62, 0x38, 0x6d, 0x47, 0x6b, 0x38, 0x82, 0x04, 0x3a, 0x38, 0x52, 0x8e, + 0x69, 0x38, 0xfc, 0x53, 0x45, 0x38, 0x77, 0x70, 0x61, 0x38, 0xc8, 0xc8, 0x95, + 0x38, 0x9b, 0x83, 0x5f, 0x38, 0x95, 0xb5, 0x9d, 0x38, 0x71, 0x60, 0x6c, 0x38, + 0x49, 0x40, 0xa6, 0x38, 0x6a, 0x26, 0x80, 0x38, 0x89, 0x76, 0x4b, 0x38, 0x7a, + 0xdd, 0x87, 0x38, 0x01, 0x7e, 0x90, 0x38, 0x12, 0xd1, 0x73, 0x38, 0x62, 0x7a, + 0x8e, 0x38, 0xf4, 0xd6, 0x6a, 0x38, 0x8b, 0xd9, 0x4a, 0x38, 0x41, 0x51, 0x3c, + 0x38, 0xf6, 0x05, 0x3a, 0x38, 0xa1, 0x01, 0x81, 0x38, 0x43, 0x13, 0x72, 0x38, + 0x92, 0x81, 0x94, 0x38, 0x70, 0x8b, 0x6d, 0x38, 0x18, 0xc6, 0x71, 0x38, 0x80, + 0xd6, 0xa2, 0x38, 0x1f, 0xdb, 0xae, 0x38, 0xb3, 0x44, 0xd1, 0x38, 0xde, 0x33, + 0x3f, 0x38, 0x51, 0xf0, 0x3c, 0x38, 0xbe, 0x68, 0x6d, 0x38, 0xf0, 0xc2, 0x30, + 0x38, 0x8b, 0x96, 0x84, 0x38, 0xcf, 0x4e, 0x6d, 0x38, 0x39, 0xcb, 0x4c, 0x38, + 0x64, 0xf9, 0x32, 0x38, 0x90, 0x6f, 0x3f, 0x38, 0xa0, 0xd9, 0x65, 0x38, 0x2d, + 0x33, 0x74, 0x38, 0x8f, 0x61, 0x5b, 0x38, 0xc8, 0xcb, 0x80, 0x38, 0x9e, 0x5d, + 0x4b, 0x38, 0xb8, 0x83, 0x97, 0x38, 0x2a, 0x05, 0x96, 0x38, 0xfc, 0x2b, 0x6a, + 0x38, 0xb6, 0x3f, 0x36, 0x38, 0x50, 0x70, 0x6a, 0x38, 0x52, 0xfe, 0x64, 0x38, + 0xd2, 0x09, 0x6d, 0x38, 0x2a, 0x53, 0x9e, 0x38, 0x4c, 0x99, 0x8c, 0x38, 0xac, + 0x4d, 0x94, 0x38, 0x6f, 0x65, 0xa6, 0x38, 0xe0, 0xc6, 0x83, 0x38, 0x24, 0xb7, + 0x8a, 0x38, 0x5e, 0x02, 0x74, 0x38, 0xdb, 0xbe, 0x4d, 0x38, 0x1b, 0x8b, 0x43, + 0x38, 0xa1, 0x86, 0x2b, 0x38, 0x67, 0x24, 0x89, 0x38, 0xd5, 0x4c, 0x40, 0x38, + 0x30, 0xf2, 0x4b, 0x38, 0x8c, 0xf6, 0x63, 0x38, 0x3d, 0x68, 0x78, 0x38, 0x64, + 0x47, 0x98, 0x38, 0xde, 0xaa, 0x66, 0x38, 0x2f, 0x29, 0x6a, 0x38, 0xa3, 0x0e, + 0x50, 0x38, 0x4a, 0xd1, 0x53, 0x38, 0xa1, 0xd8, 0x62, 0x38, 0xfc, 0x95, 0x84, + 0x38, 0x64, 0x6e, 0x9d, 0x38, 0x4f, 0xa2, 0x8d, 0x38, 0x03, 0xbe, 0x80, 0x38, + 0xa1, 0x5f, 0x55, 0x38, 0x43, 0x55, 0x71, 0x38, 0xb5, 0xef, 0x5b, 0x38, 0x94, + 0x43, 0x5e, 0x38, 0x31, 0x5b, 0x77, 0x38, 0x32, 0xe8, 0x61, 0x38, 0x0c, 0x74, + 0x53, 0x38, 0x7a, 0xe4, 0x5f, 0x38, 0x62, 0xdf, 0x51, 0x38, 0x23, 0x25, 0x99, + 0x38, 0x17, 0xd0, 0x64, 0x38, 0x62, 0xd0, 0x68, 0x38, 0x37, 0x00, 0x00, 0x00, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, + 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x30, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x77, 0x69, 0x73, 0x65, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, + 0x69, 0x61, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x66, + 0x6e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x6c, 0x06, 0x00, 0x00, 0x16, 0x00, + 0x00, 0x00, 0x24, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc2, 0x67, 0xff, + 0xff, 0x14, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x8d, 0xb4, 0x0a, 0x39, + 0x7e, 0xcb, 0x12, 0x39, 0x18, 0x65, 0x2f, 0x39, 0x96, 0xaa, 0x18, 0x39, 0x5e, + 0xca, 0x1c, 0x39, 0x2f, 0x14, 0x37, 0x39, 0x40, 0x9c, 0x08, 0x39, 0x42, 0x07, + 0x23, 0x39, 0x7b, 0xbd, 0x1c, 0x39, 0x0f, 0xa2, 0xf1, 0x38, 0xeb, 0x75, 0x25, + 0x39, 0xb6, 0x10, 0x4c, 0x39, 0x1e, 0x2c, 0x31, 0x39, 0x98, 0xa3, 0x48, 0x39, + 0xfa, 0x46, 0x7a, 0x39, 0xaa, 0xdf, 0xd6, 0x38, 0xff, 0xec, 0x4e, 0x39, 0x8f, + 0xac, 0x3e, 0x39, 0x94, 0x6b, 0x02, 0x39, 0xfd, 0xcc, 0xf7, 0x38, 0x71, 0x65, + 0x42, 0x39, 0x9a, 0x8d, 0x17, 0x39, 0x2a, 0x92, 0xb3, 0x38, 0x2a, 0x7d, 0x27, + 0x39, 0x7d, 0x6a, 0x6f, 0x39, 0xd8, 0xce, 0xda, 0x38, 0x2a, 0x54, 0x0b, 0x39, + 0x05, 0x96, 0x05, 0x39, 0xef, 0x61, 0x2b, 0x39, 0xe2, 0x57, 0x75, 0x39, 0x3b, + 0x78, 0x2c, 0x39, 0xbe, 0x24, 0xb6, 0x38, 0x8b, 0xca, 0x46, 0x39, 0x11, 0x3f, + 0x42, 0x39, 0x03, 0x1c, 0x14, 0x39, 0x3f, 0x96, 0x8c, 0x39, 0x53, 0xac, 0x00, + 0x39, 0x20, 0x71, 0x35, 0x39, 0x29, 0x32, 0x53, 0x39, 0x8e, 0x91, 0xfc, 0x38, + 0xb9, 0xf3, 0x29, 0x39, 0x2f, 0xed, 0xde, 0x38, 0x52, 0x28, 0x5a, 0x39, 0xb4, + 0x10, 0x82, 0x39, 0xd9, 0xdb, 0x42, 0x39, 0x26, 0xb8, 0xd0, 0x38, 0xd1, 0x22, + 0x22, 0x39, 0x73, 0xda, 0x13, 0x39, 0x23, 0x11, 0x55, 0x39, 0x4d, 0xd7, 0xce, + 0x38, 0x7c, 0x2d, 0x29, 0x39, 0xa2, 0x76, 0x3a, 0x39, 0x30, 0x7f, 0x45, 0x39, + 0x36, 0x9d, 0x29, 0x39, 0x49, 0x0c, 0xd5, 0x38, 0x70, 0x44, 0x30, 0x39, 0x4f, + 0x38, 0xec, 0x38, 0x3f, 0x3d, 0xb5, 0x38, 0xbf, 0x25, 0x33, 0x39, 0x12, 0xd7, + 0xbd, 0x38, 0xc6, 0x3e, 0xd0, 0x38, 0x9e, 0xdd, 0x25, 0x39, 0x5d, 0x82, 0x93, + 0x39, 0x3c, 0x1b, 0x19, 0x39, 0xe8, 0xcc, 0xf0, 0x38, 0x73, 0x56, 0x38, 0x39, + 0xbe, 0x5c, 0xf0, 0x38, 0x7f, 0x48, 0x30, 0x39, 0x02, 0xed, 0x57, 0x39, 0x6d, + 0x10, 0x1d, 0x39, 0x94, 0xbf, 0x21, 0x39, 0x89, 0x6e, 0x5e, 0x39, 0x52, 0x37, + 0x01, 0x39, 0x36, 0x31, 0xb7, 0x38, 0x09, 0xc4, 0xec, 0x38, 0x1d, 0xcd, 0x17, + 0x39, 0xb8, 0xd1, 0xd2, 0x38, 0x14, 0x86, 0x03, 0x39, 0x0f, 0xd3, 0xc9, 0x38, + 0x0a, 0x46, 0x03, 0x39, 0xa7, 0xb6, 0x1f, 0x39, 0x91, 0x21, 0xfc, 0x38, 0x47, + 0x19, 0x61, 0x39, 0x33, 0x5a, 0x0f, 0x39, 0x3e, 0x5c, 0xb4, 0x38, 0xb6, 0x11, + 0x22, 0x39, 0xf3, 0x79, 0x61, 0x39, 0xd8, 0x00, 0x6c, 0x39, 0x67, 0xe8, 0x30, + 0x39, 0x41, 0xd7, 0x8a, 0x39, 0xff, 0x16, 0x1f, 0x39, 0x75, 0x6b, 0x28, 0x39, + 0xe4, 0x57, 0x40, 0x39, 0x82, 0xef, 0xdb, 0x38, 0x8c, 0x69, 0xa0, 0x39, 0xc2, + 0xb9, 0x40, 0x39, 0x04, 0xc8, 0x83, 0x39, 0xce, 0xdd, 0x0e, 0x39, 0x4d, 0xa8, + 0xee, 0x38, 0xea, 0xbf, 0x24, 0x39, 0xfe, 0x8e, 0x10, 0x39, 0x17, 0x94, 0xe9, + 0x38, 0x38, 0x42, 0xaa, 0x38, 0x87, 0x5e, 0x37, 0x39, 0xa7, 0xe2, 0xd0, 0x38, + 0xa6, 0x2c, 0x21, 0x39, 0xd0, 0xeb, 0x41, 0x39, 0x59, 0x17, 0x5a, 0x39, 0x15, + 0xe7, 0x8c, 0x39, 0xf4, 0xde, 0x67, 0x39, 0x58, 0x8c, 0x2d, 0x39, 0x5c, 0x8e, + 0x1b, 0x39, 0x9a, 0xe9, 0xe6, 0x38, 0xa4, 0xe6, 0x29, 0x39, 0x3c, 0x34, 0x0a, + 0x39, 0x7c, 0x46, 0xcb, 0x38, 0xe7, 0x15, 0x28, 0x39, 0xa1, 0x03, 0x35, 0x39, + 0xa3, 0x8a, 0x20, 0x39, 0x05, 0xe8, 0xf2, 0x38, 0x61, 0xcf, 0xbb, 0x38, 0xc6, + 0x8a, 0x13, 0x39, 0x4d, 0xb1, 0x41, 0x39, 0x3f, 0x33, 0x38, 0x39, 0xac, 0x8c, + 0x5d, 0x39, 0xa1, 0x08, 0xc6, 0x38, 0x12, 0x0e, 0x39, 0x39, 0x79, 0x73, 0x3a, + 0x39, 0x3a, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x30, 0x5f, + 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, + 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe2, 0x74, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x44, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7c, 0xfb, 0xff, 0xff, 0x30, 0x00, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x31, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x30, 0x5f, + 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, + 0x75, 0x36, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x82, + 0x75, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x78, 0x00, 0x00, 0x00, 0x59, 0x00, + 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0xfc, 0xff, + 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc1, 0xc0, + 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, + 0x5f, 0x30, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x36, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x16, 0x76, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0xc0, + 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x72, 0x6f, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x8c, 0x89, 0x06, 0x39, 0x3a, 0xd9, 0x5a, 0x39, 0xb1, 0xe4, + 0xc7, 0x37, 0x81, 0xa6, 0xd6, 0x37, 0x69, 0xc0, 0xbd, 0x38, 0xcd, 0xb7, 0x99, + 0x39, 0xeb, 0x2f, 0x15, 0x39, 0x7f, 0xee, 0x0e, 0x37, 0x2c, 0x00, 0x00, 0x00, + 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, + 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x30, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, + 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0xe6, 0x76, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x44, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x4c, 0x6f, 0x67, 0x69, 0x74, 0x73, 0x2f, 0x53, 0x70, 0x61, 0x74, 0x69, 0x61, + 0x6c, 0x53, 0x71, 0x75, 0x65, 0x65, 0x7a, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x70, + 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3a, 0x77, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x09, 0x74, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd4, 0xfd, 0xff, 0xff, 0x30, + 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x1b, 0x4d, 0x3c, + 0x01, 0x00, 0x00, 0x00, 0xce, 0xb0, 0xcc, 0x3f, 0x01, 0x00, 0x00, 0x00, 0xe2, + 0xeb, 0xcb, 0xbf, 0x21, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4c, 0x6f, 0x67, 0x69, 0x74, 0x73, 0x2f, + 0x53, 0x70, 0x61, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x71, 0x75, 0x65, 0x65, 0x7a, + 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0xc2, 0x77, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x74, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x44, 0x7e, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0xe5, 0xd6, 0xbf, 0x3a, 0x4a, 0xd6, 0xb6, 0x3a, 0x2d, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x4c, 0x6f, 0x67, 0x69, 0x74, 0x73, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, + 0x5f, 0x31, 0x63, 0x5f, 0x31, 0x78, 0x31, 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x52, 0x78, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x70, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0xd4, 0x7e, 0xff, 0xff, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xef, + 0x7a, 0xe4, 0x37, 0x28, 0xc2, 0xd9, 0x37, 0x2c, 0x00, 0x00, 0x00, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4c, 0x6f, 0x67, + 0x69, 0x74, 0x73, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x63, + 0x5f, 0x31, 0x78, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x5f, 0x62, + 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0xd2, 0x78, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x78, 0x00, 0x00, + 0x00, 0x4b, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x6c, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x73, 0x1b, 0x4d, + 0x3c, 0x01, 0x00, 0x00, 0x00, 0xce, 0xb0, 0xcc, 0x3f, 0x01, 0x00, 0x00, 0x00, + 0xe2, 0xeb, 0xcb, 0xbf, 0x28, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4c, 0x6f, 0x67, 0x69, 0x74, 0x73, + 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x63, 0x5f, 0x31, 0x78, + 0x31, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x66, 0x79, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x09, 0x80, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x98, 0x72, 0x98, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x25, 0xda, 0x97, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x4d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x4c, 0x6f, + 0x67, 0x69, 0x74, 0x73, 0x2f, 0x41, 0x76, 0x67, 0x50, 0x6f, 0x6f, 0x6c, 0x5f, + 0x31, 0x61, 0x2f, 0x41, 0x76, 0x67, 0x50, 0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x7a, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x09, 0x58, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0x80, 0xff, 0xff, 0x10, 0x04, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x30, 0x9c, 0x0e, 0x3b, 0xed, 0x44, 0x38, 0x3b, 0xef, 0x56, 0x12, 0x3b, 0xe5, + 0xb8, 0x28, 0x3b, 0x2f, 0x6a, 0x09, 0x3b, 0x71, 0xb8, 0x6c, 0x3b, 0x85, 0xba, + 0x2e, 0x3b, 0x52, 0x4d, 0x47, 0x3b, 0x02, 0x8d, 0x10, 0x3b, 0xa9, 0xd9, 0x49, + 0x3b, 0xbe, 0x2b, 0x3c, 0x3b, 0x25, 0x16, 0x38, 0x3b, 0xdc, 0x9e, 0x08, 0x3b, + 0xaf, 0xb6, 0x28, 0x3b, 0x9d, 0x44, 0x2b, 0x3b, 0x68, 0xf5, 0xe8, 0x3a, 0xd1, + 0x70, 0x1a, 0x3b, 0x56, 0x82, 0x0d, 0x3b, 0x47, 0x46, 0xea, 0x3a, 0x30, 0x72, + 0x49, 0x3b, 0xc3, 0x5d, 0x2a, 0x3b, 0x3f, 0x67, 0x2b, 0x3b, 0x9d, 0x51, 0x1b, + 0x3b, 0x92, 0x11, 0x0b, 0x3b, 0x6e, 0x69, 0xf6, 0x3a, 0x8b, 0x3d, 0x83, 0x3b, + 0xfb, 0x6e, 0x01, 0x3b, 0xd5, 0xf8, 0x66, 0x3b, 0x88, 0x00, 0x80, 0x3b, 0x9e, + 0xe9, 0x31, 0x3b, 0x6e, 0xf6, 0x27, 0x3b, 0x3d, 0x53, 0x54, 0x3b, 0x57, 0xc0, + 0x4a, 0x3b, 0x93, 0x70, 0x13, 0x3b, 0x06, 0x3b, 0x42, 0x3b, 0xca, 0x69, 0x08, + 0x3b, 0x62, 0x80, 0x3c, 0x3b, 0x94, 0x95, 0x2d, 0x3b, 0x88, 0xf2, 0x0d, 0x3b, + 0x67, 0xd3, 0x50, 0x3b, 0x47, 0x89, 0x4c, 0x3b, 0xb2, 0x55, 0x53, 0x3b, 0xf9, + 0x44, 0x11, 0x3b, 0xbd, 0xf8, 0x26, 0x3b, 0x03, 0x35, 0x0c, 0x3b, 0xfc, 0x0b, + 0x0e, 0x3b, 0x3a, 0x04, 0x3b, 0x3b, 0xeb, 0x60, 0x26, 0x3b, 0x3d, 0xd3, 0x32, + 0x3b, 0x65, 0x8f, 0x34, 0x3b, 0xe0, 0xd2, 0x1a, 0x3b, 0xa5, 0x42, 0x2a, 0x3b, + 0x6f, 0x61, 0x46, 0x3b, 0x12, 0xdf, 0x30, 0x3b, 0x07, 0x37, 0x45, 0x3b, 0x9e, + 0x57, 0x49, 0x3b, 0xed, 0xc9, 0x2a, 0x3b, 0xc1, 0xe5, 0x07, 0x3b, 0xe6, 0x5c, + 0x27, 0x3b, 0x18, 0xf4, 0x2c, 0x3b, 0x7b, 0xbc, 0x1e, 0x3b, 0x5b, 0x2a, 0x25, + 0x3b, 0x8b, 0xd3, 0x0a, 0x3b, 0xd6, 0xf9, 0x32, 0x3b, 0x3b, 0xe3, 0x4a, 0x3b, + 0xc3, 0x1c, 0x2a, 0x3b, 0x06, 0xcc, 0x39, 0x3b, 0xb5, 0xa6, 0x32, 0x3b, 0x58, + 0x1d, 0x0c, 0x3b, 0x0d, 0x63, 0x30, 0x3b, 0x98, 0x15, 0x67, 0x3b, 0x2b, 0x29, + 0x0e, 0x3b, 0xeb, 0x95, 0x29, 0x3b, 0x68, 0x2e, 0x2c, 0x3b, 0x64, 0xc2, 0x79, + 0x3b, 0x5d, 0x60, 0x5d, 0x3b, 0x77, 0xc4, 0x29, 0x3b, 0x11, 0x87, 0x41, 0x3b, + 0x7e, 0x0c, 0x35, 0x3b, 0x48, 0x2f, 0x31, 0x3b, 0x48, 0xef, 0x35, 0x3b, 0xd9, + 0xfe, 0x25, 0x3b, 0xa7, 0xd7, 0x48, 0x3b, 0xe3, 0xde, 0x48, 0x3b, 0x93, 0xa5, + 0x26, 0x3b, 0x26, 0xfc, 0x12, 0x3b, 0x98, 0xd4, 0x16, 0x3b, 0x3e, 0x8e, 0x27, + 0x3b, 0xb2, 0x5e, 0x56, 0x3b, 0xd3, 0xb3, 0x58, 0x3b, 0xc5, 0x71, 0x6c, 0x3b, + 0xb0, 0x7b, 0x46, 0x3b, 0x77, 0x95, 0x1e, 0x3b, 0x3a, 0xde, 0x2f, 0x3b, 0x08, + 0xfc, 0x24, 0x3b, 0x0a, 0xd5, 0x24, 0x3b, 0x41, 0xf5, 0x15, 0x3b, 0x87, 0x3b, + 0x48, 0x3b, 0x06, 0x23, 0x0a, 0x3b, 0x94, 0x19, 0x36, 0x3b, 0x95, 0xbe, 0x29, + 0x3b, 0x77, 0x69, 0x14, 0x3b, 0xa8, 0xa7, 0x1f, 0x3b, 0x80, 0x1e, 0x18, 0x3b, + 0x05, 0x08, 0x41, 0x3b, 0xf7, 0x8d, 0x1d, 0x3b, 0x79, 0xcb, 0x36, 0x3b, 0xde, + 0xad, 0x0e, 0x3b, 0xa8, 0x21, 0x14, 0x3b, 0xdb, 0xf9, 0x06, 0x3b, 0x43, 0x2a, + 0x81, 0x3b, 0xc1, 0x11, 0x16, 0x3b, 0x01, 0xcd, 0x76, 0x3b, 0x47, 0x0f, 0x44, + 0x3b, 0xa1, 0x1b, 0xf6, 0x3a, 0x4f, 0xcf, 0x1f, 0x3b, 0xfb, 0xf6, 0x15, 0x3b, + 0x37, 0xac, 0x1f, 0x3b, 0xc5, 0x5e, 0x60, 0x3b, 0x2d, 0x2e, 0x8a, 0x3b, 0x57, + 0x79, 0x7e, 0x3b, 0xf3, 0xa7, 0x2f, 0x3b, 0x94, 0xfc, 0x3b, 0x3b, 0x78, 0x2d, + 0xf7, 0x3a, 0x0f, 0xad, 0x15, 0x3b, 0x1c, 0xd7, 0x21, 0x3b, 0x0e, 0xcc, 0x22, + 0x3b, 0x70, 0x91, 0x49, 0x3b, 0x2b, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, + 0x64, 0x5f, 0x39, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, + 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x76, 0x80, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x09, 0x68, 0x06, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x24, 0x06, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd2, 0x79, 0xff, 0xff, 0x14, 0x04, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x5a, 0x8a, 0xd9, 0x3b, 0x5f, 0xcd, 0x89, 0x3b, + 0xf4, 0xca, 0x92, 0x3b, 0x96, 0x01, 0xb8, 0x3b, 0x04, 0x10, 0x26, 0x3c, 0x8e, + 0x8d, 0xb2, 0x3b, 0xc2, 0xd9, 0xa9, 0x3b, 0xf9, 0xee, 0xd0, 0x3b, 0xce, 0xfe, + 0x97, 0x3b, 0x44, 0x79, 0x91, 0x3b, 0x2f, 0x92, 0xcd, 0x3b, 0x8d, 0x6a, 0xfe, + 0x3b, 0x21, 0x6b, 0x95, 0x3b, 0x29, 0x32, 0x8d, 0x3b, 0x37, 0x77, 0x0d, 0x3c, + 0x8a, 0x17, 0xea, 0x3b, 0xc5, 0xdd, 0xf7, 0x3b, 0x8f, 0x29, 0xaa, 0x3b, 0xeb, + 0x0e, 0x96, 0x3b, 0x17, 0xe3, 0x67, 0x3b, 0x96, 0xe9, 0xf1, 0x3b, 0x78, 0x22, + 0x91, 0x3b, 0x60, 0x7f, 0x0c, 0x3c, 0x14, 0xdd, 0x18, 0x3c, 0x55, 0xd7, 0x0a, + 0x3c, 0x94, 0x13, 0xe3, 0x3b, 0xe5, 0xc5, 0x8d, 0x3b, 0xab, 0xc2, 0x0d, 0x3c, + 0xb7, 0xf5, 0xf7, 0x3b, 0xd0, 0x25, 0x46, 0x3c, 0xdb, 0x7c, 0x05, 0x3c, 0xec, + 0x68, 0xd5, 0x3b, 0xe5, 0x43, 0xb0, 0x3b, 0xea, 0x32, 0xe2, 0x3b, 0xe6, 0x9e, + 0xcd, 0x3b, 0x8b, 0x88, 0xf9, 0x3b, 0x5e, 0xcc, 0xd6, 0x3b, 0xa6, 0x6e, 0xad, + 0x3b, 0x77, 0x7b, 0xaf, 0x3b, 0x3a, 0x14, 0x1c, 0x3c, 0x66, 0x6f, 0x86, 0x3b, + 0xe2, 0xdd, 0xb4, 0x3b, 0xdf, 0xd8, 0x95, 0x3b, 0xff, 0x99, 0x01, 0x3c, 0x94, + 0x37, 0xf2, 0x3b, 0x2c, 0x4b, 0xb5, 0x3b, 0x21, 0xac, 0xa1, 0x3b, 0x65, 0xfe, + 0xb5, 0x3b, 0xfb, 0x01, 0x1d, 0x3c, 0x35, 0xb8, 0x29, 0x3c, 0xd0, 0xb5, 0xaf, + 0x3b, 0x0b, 0x50, 0x06, 0x3c, 0x6f, 0x42, 0xd3, 0x3b, 0x51, 0x69, 0x9a, 0x3b, + 0x05, 0x8e, 0xb0, 0x3b, 0x19, 0x7f, 0xb1, 0x3b, 0xc9, 0x4f, 0xc6, 0x3b, 0x17, + 0x8c, 0xd8, 0x3b, 0x99, 0xea, 0x5f, 0x3c, 0x01, 0x5b, 0x26, 0x3c, 0x31, 0x17, + 0xcd, 0x3b, 0x86, 0x32, 0x3a, 0x3c, 0x16, 0xc0, 0xca, 0x3b, 0x4c, 0x5a, 0xae, + 0x3b, 0x9e, 0x40, 0xd9, 0x3b, 0x96, 0xa4, 0x12, 0x3c, 0xe5, 0xeb, 0x8f, 0x3b, + 0x37, 0x61, 0xca, 0x3b, 0x01, 0xe0, 0x1e, 0x3c, 0xff, 0x75, 0x64, 0x3b, 0xae, + 0xec, 0x04, 0x3c, 0xe9, 0xc1, 0xd8, 0x3b, 0xc8, 0x4e, 0x9a, 0x3b, 0xfc, 0xdb, + 0x98, 0x3b, 0x2e, 0x5a, 0xb6, 0x3b, 0xaa, 0xa5, 0x65, 0x3c, 0x63, 0xc8, 0xb5, + 0x3b, 0xeb, 0x10, 0xea, 0x3b, 0xe5, 0x2e, 0xa0, 0x3b, 0xbe, 0xbf, 0x8e, 0x3b, + 0x28, 0x42, 0x9e, 0x3b, 0x94, 0x4e, 0xbe, 0x3b, 0x7b, 0xae, 0x02, 0x3c, 0x3e, + 0x6c, 0x9f, 0x3b, 0x4b, 0xdd, 0xef, 0x3b, 0xa7, 0xbf, 0x92, 0x3b, 0x0b, 0x7b, + 0xa0, 0x3b, 0x52, 0x98, 0xc7, 0x3b, 0x29, 0x9e, 0xfa, 0x3b, 0xbf, 0x0f, 0xf3, + 0x3b, 0x1f, 0x6d, 0x99, 0x3b, 0xa2, 0xa3, 0xa7, 0x3b, 0xf0, 0x44, 0xb1, 0x3b, + 0xcb, 0x34, 0x73, 0x3b, 0x80, 0xb4, 0x48, 0x3c, 0xd8, 0x51, 0x8b, 0x3b, 0x8d, + 0x63, 0xf2, 0x3b, 0x4f, 0x4e, 0x06, 0x3c, 0x25, 0x09, 0x9b, 0x3b, 0xf7, 0x19, + 0x96, 0x3b, 0xc9, 0x9c, 0x00, 0x3c, 0x09, 0x50, 0x9a, 0x3b, 0xca, 0xbf, 0xb7, + 0x3b, 0xe1, 0x96, 0x8f, 0x3b, 0x56, 0x80, 0x8d, 0x3b, 0xfb, 0x3d, 0xa4, 0x3b, + 0xab, 0x64, 0xf7, 0x3b, 0x02, 0x36, 0xda, 0x3b, 0xe0, 0x68, 0xaa, 0x3b, 0x4d, + 0x81, 0xfe, 0x3b, 0xca, 0x40, 0x9c, 0x3b, 0xc5, 0x7f, 0xff, 0x3b, 0xa7, 0xa6, + 0x96, 0x3b, 0x12, 0x25, 0x89, 0x3b, 0x22, 0x4b, 0xbb, 0x3b, 0xcd, 0x27, 0xac, + 0x3b, 0x94, 0x10, 0xcc, 0x3b, 0x58, 0x19, 0xcd, 0x3b, 0xc5, 0x66, 0x07, 0x3c, + 0x7d, 0xbe, 0xf0, 0x3b, 0x05, 0x1e, 0x03, 0x3c, 0x97, 0xc0, 0x6d, 0x3b, 0x32, + 0xca, 0x97, 0x3b, 0x43, 0x0e, 0x8d, 0x3b, 0xee, 0x80, 0xad, 0x3b, 0x0d, 0xd8, + 0x8a, 0x3b, 0x17, 0x95, 0xa3, 0x3b, 0x22, 0x56, 0xbe, 0x3b, 0x35, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x39, 0x5f, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, + 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, + 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xfa, + 0x86, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x58, 0x06, 0x00, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7c, 0x8d, 0xff, + 0xff, 0x10, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x25, 0x78, 0x0c, 0x3b, 0xfd, 0x6d, 0x28, 0x3b, + 0x80, 0x30, 0x23, 0x3b, 0x53, 0x22, 0x20, 0x3b, 0x08, 0x7b, 0x6b, 0x3b, 0xaa, + 0x4d, 0x68, 0x3b, 0xcb, 0x88, 0x21, 0x3b, 0x64, 0x20, 0x19, 0x3b, 0xb3, 0x06, + 0x1c, 0x3b, 0x08, 0x54, 0x4c, 0x3b, 0xad, 0x54, 0x33, 0x3b, 0x3e, 0xd5, 0x2d, + 0x3b, 0x8c, 0xb0, 0x2d, 0x3b, 0x36, 0x74, 0x33, 0x3b, 0x86, 0x73, 0x0a, 0x3b, + 0x48, 0x44, 0x10, 0x3b, 0xba, 0xd5, 0x3a, 0x3b, 0x14, 0x6a, 0x41, 0x3b, 0x2e, + 0x64, 0x29, 0x3b, 0xad, 0x6e, 0x0d, 0x3b, 0xf0, 0xaf, 0x3a, 0x3b, 0x56, 0xcf, + 0x28, 0x3b, 0xcc, 0xca, 0x35, 0x3b, 0x87, 0x8e, 0x33, 0x3b, 0x84, 0x7a, 0x42, + 0x3b, 0x7f, 0x21, 0x29, 0x3b, 0xd8, 0xea, 0x21, 0x3b, 0x4c, 0x20, 0x46, 0x3b, + 0x5a, 0x51, 0x2e, 0x3b, 0xd2, 0xe3, 0x2e, 0x3b, 0xad, 0xcc, 0x32, 0x3b, 0xe6, + 0x75, 0x45, 0x3b, 0x3e, 0x3d, 0x3f, 0x3b, 0xad, 0x25, 0x18, 0x3b, 0x7b, 0x94, + 0x19, 0x3b, 0x0c, 0x72, 0x31, 0x3b, 0x79, 0x93, 0x6b, 0x3b, 0x0c, 0xc8, 0x3d, + 0x3b, 0xe3, 0x15, 0x2f, 0x3b, 0xdc, 0x72, 0x1f, 0x3b, 0x4f, 0x86, 0x38, 0x3b, + 0x6e, 0x60, 0x2e, 0x3b, 0x27, 0x79, 0x12, 0x3b, 0x38, 0x5c, 0x26, 0x3b, 0x97, + 0x5d, 0x0b, 0x3b, 0xf6, 0xd9, 0x22, 0x3b, 0xfd, 0xcb, 0x47, 0x3b, 0xb4, 0x75, + 0x46, 0x3b, 0x34, 0x59, 0xec, 0x3a, 0xca, 0x3f, 0xe5, 0x3a, 0x85, 0x5d, 0x39, + 0x3b, 0x48, 0x4d, 0xed, 0x3a, 0x1c, 0x4a, 0x2b, 0x3b, 0x54, 0xdf, 0x18, 0x3b, + 0x78, 0x67, 0x00, 0x3b, 0xf0, 0x43, 0x35, 0x3b, 0xf3, 0xe5, 0x30, 0x3b, 0x3b, + 0xc0, 0x0a, 0x3b, 0x4a, 0x82, 0x32, 0x3b, 0xe6, 0xac, 0x2a, 0x3b, 0xc3, 0xbf, + 0x01, 0x3b, 0x53, 0xa3, 0x1f, 0x3b, 0x59, 0xc5, 0x2f, 0x3b, 0x43, 0xed, 0x48, + 0x3b, 0x75, 0x05, 0x15, 0x3b, 0x34, 0x31, 0x2f, 0x3b, 0x65, 0x54, 0x07, 0x3b, + 0x71, 0x3d, 0x2c, 0x3b, 0x1e, 0x9f, 0x21, 0x3b, 0x2b, 0xd4, 0x29, 0x3b, 0x03, + 0x86, 0x53, 0x3b, 0x8b, 0x78, 0x43, 0x3b, 0xd9, 0xbc, 0x3e, 0x3b, 0x37, 0x52, + 0x65, 0x3b, 0xbe, 0x2b, 0x6a, 0x3b, 0x39, 0x29, 0x30, 0x3b, 0xce, 0x74, 0x74, + 0x3b, 0xf5, 0x3e, 0x14, 0x3b, 0x20, 0x8d, 0x2e, 0x3b, 0xeb, 0xab, 0x1b, 0x3b, + 0x86, 0x51, 0x34, 0x3b, 0xc5, 0xdd, 0x64, 0x3b, 0x83, 0x21, 0x47, 0x3b, 0x14, + 0xc1, 0x38, 0x3b, 0xb2, 0xa2, 0x69, 0x3b, 0xaa, 0x97, 0x2c, 0x3b, 0x4f, 0x38, + 0xfd, 0x3a, 0x89, 0x21, 0x13, 0x3b, 0x8f, 0xb4, 0x02, 0x3b, 0xb8, 0x13, 0x34, + 0x3b, 0x5c, 0x27, 0x26, 0x3b, 0x92, 0xf0, 0x3f, 0x3b, 0x4b, 0xbc, 0x25, 0x3b, + 0x7f, 0xd1, 0x43, 0x3b, 0x38, 0xf0, 0x1c, 0x3b, 0x53, 0xd1, 0x2b, 0x3b, 0x00, + 0x93, 0x5e, 0x3b, 0x33, 0x65, 0x3c, 0x3b, 0xec, 0xa1, 0x16, 0x3b, 0x8e, 0xe1, + 0x1c, 0x3b, 0x70, 0x19, 0x5b, 0x3b, 0xe9, 0x16, 0x0d, 0x3b, 0x59, 0x69, 0x44, + 0x3b, 0x66, 0x38, 0xfb, 0x3a, 0x6d, 0x4a, 0x44, 0x3b, 0x94, 0x1f, 0x13, 0x3b, + 0x97, 0x36, 0x45, 0x3b, 0xe5, 0x0b, 0x76, 0x3b, 0x74, 0xb5, 0x0d, 0x3b, 0x23, + 0x54, 0x19, 0x3b, 0x05, 0x7c, 0x0d, 0x3b, 0x90, 0x11, 0x30, 0x3b, 0xc7, 0xf9, + 0x36, 0x3b, 0xf7, 0xee, 0x30, 0x3b, 0xa3, 0xfb, 0x3e, 0x3b, 0xdb, 0x92, 0x2e, + 0x3b, 0x25, 0xb9, 0x1e, 0x3b, 0x77, 0x7b, 0xfa, 0x3a, 0x8e, 0x6a, 0x28, 0x3b, + 0x01, 0xd7, 0x06, 0x3b, 0x23, 0xa8, 0x21, 0x3b, 0x5c, 0x39, 0x1b, 0x3b, 0x20, + 0xce, 0x28, 0x3b, 0x19, 0x57, 0x2b, 0x3b, 0x18, 0x50, 0x48, 0x3b, 0x1a, 0xc2, + 0x12, 0x3b, 0x7d, 0xbc, 0x26, 0x3b, 0xc6, 0x8b, 0x2c, 0x3b, 0x2b, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x38, 0x5f, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, + 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x6e, 0x8d, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x68, 0x06, 0x00, 0x00, 0x47, + 0x00, 0x00, 0x00, 0x24, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xca, 0x86, + 0xff, 0xff, 0x14, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb7, 0xc8, 0xb9, + 0x3b, 0x49, 0x06, 0x07, 0x3c, 0x13, 0x37, 0xaa, 0x3b, 0x4d, 0x39, 0x88, 0x3b, + 0x57, 0x70, 0xba, 0x3b, 0x17, 0xf4, 0x13, 0x3c, 0x91, 0xed, 0x12, 0x3c, 0xc7, + 0x17, 0xdc, 0x3b, 0x67, 0x96, 0x94, 0x3b, 0xb3, 0x0f, 0xac, 0x3b, 0xe6, 0xef, + 0xa2, 0x3b, 0x74, 0x00, 0x20, 0x3c, 0x5d, 0x78, 0xa8, 0x3b, 0x3b, 0x92, 0x97, + 0x3b, 0x13, 0x50, 0x8a, 0x3b, 0xe9, 0x01, 0x93, 0x3b, 0x9a, 0xf1, 0x26, 0x3c, + 0xaf, 0xb5, 0xd6, 0x3b, 0xf4, 0x4a, 0x3a, 0x3c, 0xf9, 0xfc, 0xa3, 0x3b, 0x9c, + 0xdc, 0x30, 0x3c, 0xe8, 0x5a, 0xa0, 0x3b, 0x93, 0x4f, 0xd3, 0x3b, 0x50, 0x8e, + 0xb5, 0x3b, 0xf3, 0xe6, 0x92, 0x3b, 0xee, 0x31, 0xc7, 0x3b, 0xb3, 0x8f, 0xf6, + 0x3b, 0xe5, 0x1c, 0xab, 0x3b, 0xa2, 0x69, 0xb9, 0x3b, 0x11, 0x67, 0xc5, 0x3b, + 0x97, 0x69, 0x2c, 0x3c, 0x0a, 0x11, 0x0f, 0x3c, 0xd6, 0xdc, 0xea, 0x3b, 0x62, + 0x0e, 0xd3, 0x3b, 0x16, 0xf5, 0x7d, 0x3b, 0x81, 0x5a, 0xcd, 0x3b, 0xc3, 0x2b, + 0xa3, 0x3b, 0x8a, 0x18, 0xd8, 0x3b, 0x53, 0x16, 0xa2, 0x3b, 0x79, 0x63, 0xaf, + 0x3b, 0x6d, 0x10, 0xad, 0x3b, 0xcb, 0x53, 0x0d, 0x3c, 0x96, 0x74, 0xdb, 0x3b, + 0x34, 0xa9, 0xb6, 0x3b, 0xe1, 0x8a, 0x81, 0x3b, 0x64, 0x61, 0x9f, 0x3b, 0x79, + 0x95, 0xf2, 0x3b, 0x52, 0xae, 0x1b, 0x3c, 0xea, 0x22, 0x99, 0x3b, 0xe8, 0x9a, + 0xd5, 0x3b, 0xd9, 0xf5, 0xc3, 0x3b, 0x97, 0x3f, 0xa7, 0x3b, 0xb4, 0xde, 0xce, + 0x3b, 0x6a, 0xb7, 0x99, 0x3b, 0x5d, 0x1b, 0xaa, 0x3b, 0x62, 0xe8, 0xdd, 0x3b, + 0x80, 0xe0, 0xea, 0x3b, 0x11, 0xf6, 0x32, 0x3c, 0xa1, 0xb3, 0xe0, 0x3b, 0x4b, + 0x55, 0x91, 0x3b, 0xf8, 0x58, 0x26, 0x3c, 0x51, 0x2e, 0xcd, 0x3b, 0xcb, 0xd4, + 0xa1, 0x3b, 0xdc, 0xca, 0xf7, 0x3b, 0xc8, 0x18, 0xcd, 0x3b, 0x65, 0x34, 0x09, + 0x3c, 0x27, 0x59, 0x9f, 0x3b, 0x34, 0x50, 0x89, 0x3b, 0xfa, 0x30, 0x0a, 0x3c, + 0xbd, 0xd9, 0xb7, 0x3b, 0x60, 0x79, 0xd8, 0x3b, 0x48, 0xf7, 0xea, 0x3b, 0x1c, + 0xe6, 0xdc, 0x3b, 0x0c, 0xb8, 0x8e, 0x3b, 0x26, 0xb3, 0xee, 0x3b, 0xae, 0x58, + 0xc2, 0x3b, 0xdb, 0x17, 0xca, 0x3b, 0x6b, 0xaa, 0xaf, 0x3b, 0x6d, 0xf2, 0xe1, + 0x3b, 0xa3, 0x39, 0x4b, 0x3c, 0x84, 0xcd, 0xb6, 0x3b, 0x4b, 0x1c, 0x9a, 0x3b, + 0x47, 0x1c, 0x1f, 0x3c, 0x83, 0xa4, 0xad, 0x3b, 0x5f, 0xc3, 0xdd, 0x3b, 0xc1, + 0xeb, 0x9c, 0x3b, 0xb6, 0xe6, 0xd5, 0x3b, 0x38, 0x08, 0x17, 0x3c, 0xc6, 0x98, + 0xf2, 0x3b, 0xe2, 0x24, 0xf1, 0x3b, 0x4c, 0x77, 0x46, 0x3c, 0x62, 0x8f, 0xa8, + 0x3b, 0x2d, 0x25, 0x02, 0x3c, 0x18, 0x5c, 0x89, 0x3b, 0x76, 0xa2, 0x9b, 0x3b, + 0x5b, 0x6d, 0x94, 0x3b, 0xfe, 0xf2, 0x10, 0x3c, 0x8b, 0x09, 0xde, 0x3b, 0x4a, + 0x1c, 0xd5, 0x3b, 0x11, 0xe4, 0xda, 0x3b, 0x1e, 0xa1, 0x90, 0x3b, 0x11, 0xa7, + 0xa4, 0x3b, 0x2c, 0x8c, 0x9c, 0x3b, 0xe4, 0x0d, 0xed, 0x3b, 0x3d, 0xb3, 0x8c, + 0x3b, 0x6a, 0xea, 0xa1, 0x3b, 0x9e, 0xcb, 0xe1, 0x3b, 0x2e, 0xdf, 0xea, 0x3b, + 0x87, 0xe0, 0xb6, 0x3b, 0x92, 0x5b, 0x16, 0x3c, 0xb6, 0x40, 0xb2, 0x3b, 0x77, + 0x64, 0xfa, 0x3b, 0x9f, 0xa9, 0xde, 0x3b, 0xc3, 0x27, 0x17, 0x3c, 0x38, 0xc3, + 0xe4, 0x3b, 0x2e, 0x3c, 0xa7, 0x3b, 0x67, 0x96, 0x91, 0x3b, 0xe8, 0x01, 0x9e, + 0x3b, 0x8a, 0x9e, 0x2d, 0x3c, 0x52, 0xae, 0x8f, 0x3b, 0xe2, 0xcb, 0x9e, 0x3b, + 0x2d, 0x22, 0x20, 0x3c, 0xf1, 0x72, 0x97, 0x3b, 0x3e, 0x6f, 0x35, 0x3c, 0x5a, + 0x72, 0xf1, 0x3b, 0x3a, 0x1f, 0xa7, 0x3b, 0x8a, 0x30, 0xad, 0x3b, 0x86, 0xd7, + 0xc8, 0x3b, 0x35, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, + 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x38, + 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, + 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0xf2, 0x93, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x58, + 0x06, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x74, 0x9a, 0xff, 0xff, 0x10, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x69, 0x72, 0x15, + 0x3b, 0x7b, 0x2b, 0x6e, 0x3b, 0x0e, 0x7b, 0x3c, 0x3b, 0x82, 0xfa, 0x32, 0x3b, + 0x8e, 0x21, 0x15, 0x3b, 0xb7, 0x35, 0x12, 0x3b, 0x84, 0x7e, 0x16, 0x3b, 0x91, + 0xfe, 0x6f, 0x3b, 0xe3, 0xc4, 0x14, 0x3b, 0x38, 0xa8, 0x14, 0x3b, 0x5c, 0x34, + 0x8b, 0x3b, 0x9b, 0xf3, 0x51, 0x3b, 0xa0, 0xe2, 0x0f, 0x3b, 0x26, 0x0f, 0x38, + 0x3b, 0xaa, 0x48, 0x3b, 0x3b, 0x97, 0x55, 0x32, 0x3b, 0xb9, 0x5d, 0x13, 0x3b, + 0x5e, 0x54, 0x4d, 0x3b, 0x8b, 0x64, 0x48, 0x3b, 0xfc, 0x34, 0x2f, 0x3b, 0x8e, + 0x96, 0x3e, 0x3b, 0x2f, 0x44, 0x2b, 0x3b, 0xf1, 0x0c, 0x1a, 0x3b, 0xaf, 0xb5, + 0x3d, 0x3b, 0x74, 0xc8, 0x47, 0x3b, 0x81, 0x75, 0x4a, 0x3b, 0xe5, 0x54, 0x04, + 0x3b, 0xdd, 0xeb, 0x27, 0x3b, 0x65, 0x52, 0x07, 0x3b, 0x7a, 0xd4, 0x2e, 0x3b, + 0x34, 0x82, 0x2d, 0x3b, 0x98, 0x18, 0x4f, 0x3b, 0x9d, 0x4d, 0x19, 0x3b, 0x8f, + 0x04, 0x31, 0x3b, 0x5d, 0x44, 0x1e, 0x3b, 0x66, 0x57, 0x75, 0x3b, 0x22, 0x5d, + 0x31, 0x3b, 0x83, 0x6d, 0x00, 0x3b, 0x07, 0x31, 0x35, 0x3b, 0xbb, 0x4a, 0x21, + 0x3b, 0x02, 0xd8, 0x67, 0x3b, 0xff, 0x57, 0x52, 0x3b, 0xa6, 0x70, 0x24, 0x3b, + 0xea, 0xb4, 0x24, 0x3b, 0x9d, 0x41, 0x2e, 0x3b, 0xe5, 0xa3, 0x1c, 0x3b, 0x01, + 0x17, 0x25, 0x3b, 0x09, 0x5b, 0x39, 0x3b, 0x14, 0x47, 0x38, 0x3b, 0xe8, 0xb3, + 0x31, 0x3b, 0x5e, 0xc4, 0x0a, 0x3b, 0x07, 0xf2, 0x3a, 0x3b, 0xa1, 0x56, 0x0e, + 0x3b, 0x08, 0x08, 0x11, 0x3b, 0xb8, 0xf8, 0x16, 0x3b, 0x1e, 0xcb, 0x1b, 0x3b, + 0xf4, 0xb4, 0x11, 0x3b, 0x18, 0xed, 0x0f, 0x3b, 0x15, 0x9f, 0x0d, 0x3b, 0xa1, + 0xa1, 0x4c, 0x3b, 0x54, 0xc1, 0x45, 0x3b, 0x22, 0x52, 0xf8, 0x3a, 0x3c, 0xf0, + 0x18, 0x3b, 0x44, 0x4e, 0x1b, 0x3b, 0xb3, 0xe2, 0x42, 0x3b, 0x88, 0x59, 0x30, + 0x3b, 0x73, 0x95, 0x4f, 0x3b, 0xbb, 0x01, 0x15, 0x3b, 0xcd, 0x24, 0x31, 0x3b, + 0xf2, 0x02, 0x27, 0x3b, 0x99, 0xce, 0x56, 0x3b, 0x09, 0x4d, 0x3a, 0x3b, 0xbe, + 0xeb, 0x35, 0x3b, 0xb7, 0x9d, 0x2b, 0x3b, 0x7d, 0xa8, 0x46, 0x3b, 0xea, 0xe9, + 0x4a, 0x3b, 0xb1, 0xa8, 0x4e, 0x3b, 0x25, 0x29, 0x2a, 0x3b, 0x61, 0x04, 0x2c, + 0x3b, 0xaf, 0x65, 0x28, 0x3b, 0xdc, 0x84, 0x6c, 0x3b, 0x77, 0x23, 0x30, 0x3b, + 0xc8, 0x82, 0x26, 0x3b, 0x70, 0xe0, 0x33, 0x3b, 0x71, 0xbe, 0x43, 0x3b, 0x3c, + 0xa3, 0x4b, 0x3b, 0x53, 0xda, 0xfe, 0x3a, 0x5a, 0x12, 0x02, 0x3b, 0xc8, 0xf3, + 0x17, 0x3b, 0x4e, 0x5a, 0x29, 0x3b, 0xc8, 0x4c, 0x1d, 0x3b, 0x4b, 0xde, 0x3f, + 0x3b, 0xf6, 0x54, 0x0f, 0x3b, 0x85, 0x17, 0x26, 0x3b, 0xa8, 0x0a, 0x6a, 0x3b, + 0x96, 0x03, 0x32, 0x3b, 0xfa, 0x3e, 0x04, 0x3b, 0x34, 0x14, 0x1b, 0x3b, 0xb4, + 0x0e, 0x89, 0x3b, 0x99, 0xe1, 0x11, 0x3b, 0xaa, 0x64, 0x4c, 0x3b, 0x2d, 0x09, + 0x14, 0x3b, 0xe1, 0xe1, 0x53, 0x3b, 0xac, 0x96, 0x37, 0x3b, 0xd6, 0xe7, 0x2d, + 0x3b, 0xe9, 0x42, 0x27, 0x3b, 0xf9, 0x41, 0x1f, 0x3b, 0x05, 0xb8, 0x46, 0x3b, + 0x37, 0x95, 0x11, 0x3b, 0xe6, 0x89, 0x1d, 0x3b, 0xee, 0x61, 0x11, 0x3b, 0xac, + 0x0a, 0x48, 0x3b, 0x50, 0xad, 0x87, 0x3b, 0x7c, 0x67, 0x05, 0x3b, 0x59, 0x7b, + 0xf7, 0x3a, 0xcd, 0xce, 0x0e, 0x3b, 0x2b, 0x8b, 0x7f, 0x3b, 0x13, 0x6a, 0x06, + 0x3b, 0x0c, 0x0e, 0x1f, 0x3b, 0x9d, 0x29, 0x51, 0x3b, 0xb0, 0xc8, 0x1e, 0x3b, + 0x42, 0x82, 0x3d, 0x3b, 0x76, 0x28, 0x21, 0x3b, 0x00, 0x00, 0x2e, 0x3b, 0x37, + 0xd8, 0x11, 0x3b, 0xeb, 0xf0, 0x36, 0x3b, 0x08, 0x7f, 0x4f, 0x3b, 0xbb, 0xb5, + 0x37, 0x3b, 0x2b, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, + 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x37, + 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x77, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x66, 0x9a, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x68, 0x06, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x24, 0x06, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0xc2, 0x93, 0xff, 0xff, 0x14, 0x04, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x63, 0x1a, 0x98, 0x3b, 0xf0, 0xca, 0xdf, 0x3b, 0x6a, 0x36, 0xdc, + 0x3b, 0x7a, 0x8b, 0x16, 0x3c, 0xd6, 0xce, 0xf4, 0x3b, 0xef, 0x99, 0x74, 0x3b, + 0xcd, 0x1e, 0xb4, 0x3b, 0x29, 0xd1, 0x16, 0x3c, 0x55, 0xbd, 0xbe, 0x3b, 0xa3, + 0xf3, 0xb9, 0x3b, 0x43, 0xb1, 0x0a, 0x3c, 0x9e, 0x35, 0x09, 0x3c, 0xc9, 0xd2, + 0x31, 0x3c, 0x99, 0xed, 0x8a, 0x3c, 0x32, 0x87, 0xc2, 0x3b, 0x50, 0x41, 0xee, + 0x3b, 0x20, 0x90, 0x16, 0x3c, 0x65, 0x1b, 0x17, 0x3c, 0xa5, 0xc8, 0xf6, 0x3b, + 0x64, 0x68, 0x4e, 0x3c, 0xda, 0x71, 0x2a, 0x3c, 0x00, 0xd8, 0x0b, 0x3c, 0x3e, + 0x58, 0x22, 0x3c, 0x9b, 0x30, 0xb6, 0x3b, 0x7c, 0x9a, 0x82, 0x3b, 0x52, 0x52, + 0xd6, 0x3b, 0xfe, 0xe9, 0xc3, 0x3b, 0x5f, 0x56, 0x06, 0x3c, 0xef, 0xa4, 0xd4, + 0x3b, 0x97, 0x95, 0x1f, 0x3c, 0xc2, 0x46, 0x9b, 0x3b, 0xcc, 0x44, 0xc6, 0x3b, + 0xa7, 0xc1, 0xaf, 0x3b, 0x02, 0x07, 0xf0, 0x3b, 0xc1, 0xcf, 0xe5, 0x3b, 0x71, + 0x1c, 0x14, 0x3c, 0x7d, 0xff, 0xb3, 0x3b, 0xa4, 0xb6, 0xf3, 0x3b, 0xf4, 0x81, + 0xda, 0x3b, 0xab, 0xa7, 0xbb, 0x3b, 0xef, 0xd8, 0xc9, 0x3b, 0xa1, 0x31, 0x02, + 0x3c, 0x71, 0xfb, 0xc1, 0x3b, 0x91, 0xd6, 0xc2, 0x3b, 0x67, 0x8b, 0xcf, 0x3b, + 0xc8, 0x0b, 0x8f, 0x3b, 0xbf, 0x2e, 0xdb, 0x3b, 0x70, 0xe7, 0x1e, 0x3c, 0x08, + 0x47, 0x25, 0x3c, 0xd4, 0xe6, 0xeb, 0x3b, 0x60, 0xf5, 0xcd, 0x3b, 0xde, 0xca, + 0x00, 0x3c, 0xbb, 0x22, 0xd0, 0x3b, 0xd5, 0x0d, 0xc4, 0x3b, 0x5c, 0x68, 0xbb, + 0x3b, 0x92, 0x93, 0xb2, 0x3b, 0x77, 0x86, 0xfa, 0x3b, 0x11, 0x85, 0x27, 0x3c, + 0x14, 0x4d, 0xd7, 0x3b, 0x49, 0x13, 0xeb, 0x3b, 0x56, 0x35, 0x0c, 0x3c, 0xcc, + 0x92, 0xae, 0x3b, 0x36, 0x68, 0x2f, 0x3c, 0x52, 0xaf, 0x4c, 0x3c, 0xa0, 0xd9, + 0xad, 0x3b, 0x49, 0x40, 0x93, 0x3b, 0xfa, 0x40, 0x27, 0x3c, 0x35, 0xcd, 0xb1, + 0x3b, 0xa4, 0xaa, 0xdb, 0x3b, 0x45, 0xfa, 0x01, 0x3c, 0xc4, 0x09, 0x97, 0x3b, + 0x2d, 0x12, 0x1e, 0x3c, 0x80, 0xf7, 0xf2, 0x3b, 0x0e, 0xee, 0xd1, 0x3b, 0x93, + 0xc7, 0x3e, 0x3c, 0xa5, 0xc5, 0x78, 0x3c, 0x81, 0xa1, 0xcd, 0x3b, 0x95, 0x7f, + 0x84, 0x3b, 0xac, 0xfb, 0xc0, 0x3b, 0x7b, 0x9e, 0xc9, 0x3b, 0xb4, 0x94, 0x0e, + 0x3c, 0xbe, 0x02, 0x24, 0x3c, 0x26, 0xaf, 0x03, 0x3c, 0x1d, 0x55, 0xb6, 0x3b, + 0x84, 0x0c, 0xa4, 0x3b, 0xe1, 0x22, 0xf5, 0x3b, 0xaf, 0xf6, 0x16, 0x3c, 0xf4, + 0x0e, 0x02, 0x3c, 0x8f, 0x59, 0xb8, 0x3b, 0x5a, 0x77, 0x81, 0x3c, 0xa0, 0x61, + 0x03, 0x3c, 0xdf, 0x05, 0xbc, 0x3b, 0x56, 0x04, 0xc6, 0x3b, 0x8d, 0x0b, 0xc2, + 0x3b, 0x34, 0xd6, 0xd1, 0x3b, 0x06, 0xd9, 0xf0, 0x3b, 0xc8, 0x23, 0x01, 0x3c, + 0x8d, 0x16, 0x17, 0x3c, 0x01, 0x15, 0xaa, 0x3b, 0x1e, 0x97, 0x1b, 0x3c, 0x01, + 0x15, 0xde, 0x3b, 0x84, 0x0b, 0xd7, 0x3b, 0x61, 0x98, 0x24, 0x3c, 0x52, 0x21, + 0xa2, 0x3b, 0x00, 0x53, 0xab, 0x3b, 0xca, 0x54, 0xc5, 0x3b, 0x2f, 0xf5, 0xf1, + 0x3b, 0x72, 0x53, 0x8f, 0x3b, 0x73, 0xbd, 0xca, 0x3b, 0x3c, 0x53, 0x13, 0x3c, + 0xa8, 0x4d, 0x45, 0x3c, 0xd9, 0x26, 0x5a, 0x3c, 0xb7, 0xf1, 0xbf, 0x3b, 0x0f, + 0xa2, 0x3e, 0x3c, 0x6e, 0xb5, 0xd3, 0x3b, 0x30, 0xa8, 0x3c, 0x3c, 0x1c, 0xfc, + 0xcd, 0x3b, 0x0c, 0x94, 0x1d, 0x3c, 0x09, 0x92, 0xdb, 0x3b, 0xcc, 0xad, 0x1f, + 0x3c, 0x6e, 0x27, 0xf6, 0x3b, 0x01, 0x23, 0x89, 0x3b, 0x57, 0xa7, 0x9b, 0x3b, + 0x23, 0x4a, 0x95, 0x3b, 0x53, 0x0b, 0x1a, 0x3c, 0xa6, 0x56, 0x00, 0x3c, 0x3c, + 0x50, 0x08, 0x3c, 0xd0, 0x0e, 0x91, 0x3b, 0x35, 0x00, 0x00, 0x00, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x37, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, + 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, + 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xea, 0xa0, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x58, 0x06, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x20, + 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6c, 0xa7, 0xff, 0xff, 0x10, 0x04, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0xdb, 0x16, 0x77, 0x3b, 0x81, 0x65, 0x4c, 0x3b, 0xe0, 0x30, 0xbc, + 0x3b, 0x34, 0x9a, 0x7d, 0x3b, 0xad, 0x5a, 0x4b, 0x3b, 0x64, 0xaf, 0x9d, 0x3b, + 0x60, 0xcb, 0x1d, 0x3b, 0x9d, 0xf2, 0x52, 0x3b, 0xef, 0x67, 0x91, 0x3b, 0x2c, + 0xc1, 0x5e, 0x3b, 0x8d, 0x8e, 0x4b, 0x3b, 0x3e, 0x7a, 0x8d, 0x3b, 0x64, 0x7e, + 0x32, 0x3b, 0x35, 0x8d, 0xf5, 0x3a, 0x39, 0x88, 0x28, 0x3b, 0x69, 0x08, 0x39, + 0x3b, 0xb7, 0xa5, 0x35, 0x3b, 0x0e, 0x28, 0x46, 0x3b, 0x77, 0x11, 0x79, 0x3b, + 0xbf, 0x20, 0x29, 0x3b, 0xd0, 0x29, 0x67, 0x3b, 0xff, 0x3c, 0x32, 0x3b, 0x0c, + 0x5f, 0x83, 0x3b, 0x00, 0x82, 0x87, 0x3b, 0x1c, 0x6d, 0x8f, 0x3b, 0xa2, 0xdc, + 0x3d, 0x3b, 0xd5, 0xd2, 0x58, 0x3b, 0xa0, 0x0d, 0x70, 0x3b, 0x13, 0x09, 0x4f, + 0x3b, 0x7e, 0x45, 0x86, 0x3b, 0x87, 0xbe, 0x65, 0x3b, 0xa3, 0x41, 0x44, 0x3b, + 0x85, 0x42, 0x6e, 0x3b, 0xdd, 0x83, 0x39, 0x3b, 0x70, 0xaf, 0x32, 0x3b, 0x93, + 0x27, 0x2e, 0x3b, 0x90, 0x79, 0x4f, 0x3b, 0x1b, 0x55, 0xf1, 0x3a, 0x88, 0x75, + 0x5d, 0x3b, 0x82, 0x71, 0x7c, 0x3b, 0xe2, 0x39, 0x83, 0x3b, 0x48, 0xba, 0x5d, + 0x3b, 0x93, 0x01, 0x46, 0x3b, 0xb6, 0xf1, 0x62, 0x3b, 0x46, 0xcc, 0x84, 0x3b, + 0x28, 0xbe, 0x05, 0x3b, 0xf6, 0x0c, 0x5a, 0x3b, 0x29, 0xbb, 0x5f, 0x3b, 0xaa, + 0x38, 0x17, 0x3b, 0x37, 0xeb, 0x20, 0x3b, 0x94, 0xee, 0x80, 0x3b, 0x88, 0xe9, + 0x6a, 0x3b, 0x62, 0x9f, 0x5c, 0x3b, 0x5b, 0x1e, 0x62, 0x3b, 0x3d, 0xa8, 0x46, + 0x3b, 0x9e, 0x8c, 0x49, 0x3b, 0x0a, 0x98, 0x72, 0x3b, 0x72, 0x54, 0x5b, 0x3b, + 0xfc, 0x37, 0x2f, 0x3b, 0x56, 0x08, 0x05, 0x3b, 0xfb, 0xd2, 0x44, 0x3b, 0x4f, + 0x12, 0x38, 0x3b, 0xf8, 0x62, 0x2e, 0x3b, 0xba, 0x67, 0x48, 0x3b, 0x02, 0xbc, + 0x61, 0x3b, 0xf7, 0x01, 0x5d, 0x3b, 0x80, 0xde, 0x24, 0x3b, 0x0f, 0xf2, 0x9b, + 0x3b, 0x33, 0xb9, 0x44, 0x3b, 0xe4, 0xc4, 0x41, 0x3b, 0x5e, 0x1e, 0x4a, 0x3b, + 0x20, 0x04, 0x13, 0x3b, 0x37, 0x3a, 0x5a, 0x3b, 0x5c, 0x35, 0x52, 0x3b, 0x0d, + 0xf3, 0x4a, 0x3b, 0x57, 0xf5, 0x06, 0x3b, 0x9f, 0xdf, 0x25, 0x3b, 0x8c, 0x98, + 0x35, 0x3b, 0xd5, 0x98, 0x33, 0x3b, 0x8c, 0x82, 0x30, 0x3b, 0xaa, 0x7a, 0x60, + 0x3b, 0x3a, 0x6b, 0x51, 0x3b, 0x24, 0xdf, 0x7c, 0x3b, 0xe8, 0xe2, 0x4a, 0x3b, + 0xca, 0x46, 0x43, 0x3b, 0x7f, 0x20, 0x50, 0x3b, 0x6b, 0x23, 0x17, 0x3b, 0x89, + 0xcb, 0x49, 0x3b, 0x85, 0x69, 0x40, 0x3b, 0x70, 0x71, 0x22, 0x3b, 0x41, 0x72, + 0x73, 0x3b, 0x43, 0xf2, 0x29, 0x3b, 0xb4, 0xa5, 0x5d, 0x3b, 0x6f, 0xfb, 0x21, + 0x3b, 0x37, 0x81, 0x88, 0x3b, 0x38, 0xc1, 0x24, 0x3b, 0xec, 0x46, 0x1d, 0x3b, + 0xd5, 0x05, 0x7b, 0x3b, 0xfa, 0xad, 0x49, 0x3b, 0x38, 0x00, 0x5c, 0x3b, 0x42, + 0xa2, 0x82, 0x3b, 0xca, 0x7f, 0x87, 0x3b, 0xf8, 0xf8, 0x5e, 0x3b, 0xa9, 0xa1, + 0x72, 0x3b, 0xdd, 0x61, 0x67, 0x3b, 0xc2, 0xe2, 0x20, 0x3b, 0x3d, 0x06, 0x35, + 0x3b, 0x6a, 0x6f, 0x48, 0x3b, 0x49, 0x28, 0x4b, 0x3b, 0x13, 0x71, 0x5b, 0x3b, + 0x57, 0x39, 0x70, 0x3b, 0x3f, 0x6c, 0x08, 0x3b, 0x99, 0xc7, 0x41, 0x3b, 0x64, + 0x48, 0x45, 0x3b, 0x02, 0x34, 0x35, 0x3b, 0x8f, 0x25, 0x51, 0x3b, 0xc4, 0xfe, + 0x5a, 0x3b, 0x8e, 0xa5, 0x1e, 0x3b, 0xb6, 0xc5, 0x3a, 0x3b, 0x33, 0xad, 0xfb, + 0x3a, 0x2b, 0xce, 0x43, 0x3b, 0xf4, 0xa4, 0x1d, 0x3b, 0xbf, 0xd2, 0x4e, 0x3b, + 0xeb, 0x6a, 0x92, 0x3b, 0x17, 0xe4, 0x89, 0x3b, 0xa8, 0x88, 0x28, 0x3b, 0x04, + 0x1c, 0x55, 0x3b, 0x98, 0xc7, 0x46, 0x3b, 0x2b, 0x00, 0x00, 0x00, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x36, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, + 0x73, 0x65, 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, + 0x61, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x5e, 0xa7, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x09, 0x68, 0x03, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, + 0x24, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xba, 0xa0, 0xff, 0xff, 0x14, + 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x01, 0xb0, 0x90, 0x3b, 0xe7, 0x75, 0x88, 0x3b, 0xda, 0xf6, 0x64, + 0x3b, 0xf3, 0xa3, 0x78, 0x3b, 0xae, 0xc0, 0x3c, 0x3b, 0x98, 0xf3, 0x41, 0x3b, + 0x75, 0xe2, 0xa1, 0x3b, 0x49, 0xfe, 0x7a, 0x3b, 0x71, 0x95, 0x77, 0x3b, 0x26, + 0xd0, 0xb1, 0x3b, 0x93, 0xf9, 0x76, 0x3b, 0x29, 0x45, 0x87, 0x3b, 0x9a, 0x05, + 0x89, 0x3b, 0x2c, 0xf3, 0x7f, 0x3b, 0x9b, 0xd5, 0x7b, 0x3b, 0xd2, 0x29, 0xf3, + 0x3b, 0xf1, 0x7e, 0x6c, 0x3b, 0x99, 0xf1, 0x1c, 0x3c, 0x86, 0x53, 0x73, 0x3b, + 0x38, 0x28, 0x8f, 0x3b, 0xbe, 0x20, 0x64, 0x3b, 0xb5, 0x96, 0x82, 0x3b, 0x84, + 0x0a, 0xb7, 0x3b, 0xa5, 0xa4, 0x5b, 0x3b, 0x1b, 0x96, 0x9d, 0x3b, 0x12, 0x99, + 0x6f, 0x3b, 0xa0, 0xcd, 0x94, 0x3b, 0x62, 0x2c, 0x7f, 0x3b, 0x90, 0x6c, 0x7e, + 0x3b, 0xdc, 0xc6, 0x95, 0x3b, 0xcd, 0x97, 0x62, 0x3b, 0x8a, 0xf8, 0x80, 0x3b, + 0x53, 0x91, 0x64, 0x3b, 0xf9, 0xb9, 0x70, 0x3b, 0x93, 0x39, 0xf7, 0x3b, 0xe4, + 0x72, 0xac, 0x3b, 0x29, 0x52, 0x95, 0x3b, 0x01, 0xf7, 0x98, 0x3b, 0x7a, 0xce, + 0x4a, 0x3b, 0xb9, 0x52, 0x50, 0x3b, 0x6e, 0x9f, 0x71, 0x3b, 0x03, 0x4a, 0xa8, + 0x3b, 0x34, 0xdc, 0xa3, 0x3b, 0xd3, 0xad, 0x93, 0x3b, 0xe2, 0x45, 0x63, 0x3b, + 0xa6, 0x4a, 0x93, 0x3b, 0x3a, 0x6b, 0x54, 0x3b, 0xd9, 0x9f, 0x97, 0x3b, 0xef, + 0x53, 0x77, 0x3b, 0x87, 0x02, 0x8b, 0x3b, 0x8b, 0xd4, 0x33, 0x3b, 0x1b, 0x36, + 0x99, 0x3b, 0x90, 0x19, 0xcd, 0x3b, 0xda, 0x5d, 0xc1, 0x3b, 0x5d, 0xee, 0x68, + 0x3b, 0x7d, 0x5b, 0x83, 0x3b, 0x30, 0x76, 0xd9, 0x3b, 0xb6, 0x23, 0x83, 0x3b, + 0x57, 0xdd, 0x45, 0x3b, 0xfc, 0xdc, 0x47, 0x3b, 0x90, 0x3f, 0x3d, 0x3b, 0x20, + 0x3a, 0x8e, 0x3b, 0x35, 0x03, 0x88, 0x3b, 0xe1, 0xf2, 0xd9, 0x3b, 0x35, 0x00, + 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, + 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x36, 0x5f, 0x64, 0x65, 0x70, + 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, + 0x69, 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, + 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xe2, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x58, 0x03, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0xb1, + 0xff, 0xff, 0x10, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0xa4, 0xc8, 0x2b, 0x3b, 0x4e, 0x6a, 0x7a, 0x3b, 0x4b, 0x5c, 0x8d, 0x3b, + 0x1a, 0x86, 0xa4, 0x3b, 0x9d, 0x00, 0x62, 0x3b, 0x17, 0x46, 0x39, 0x3b, 0xc4, + 0xca, 0x6a, 0x3b, 0x39, 0x91, 0x59, 0x3b, 0x38, 0xdf, 0x8d, 0x3b, 0x6b, 0x33, + 0x81, 0x3b, 0x7e, 0x86, 0x7e, 0x3b, 0xbc, 0x51, 0x61, 0x3b, 0x39, 0xea, 0x80, + 0x3b, 0x43, 0x3c, 0x1f, 0x3b, 0x4e, 0xb7, 0xa8, 0x3b, 0x64, 0x51, 0x0f, 0x3b, + 0xf8, 0x3f, 0x81, 0x3b, 0xe5, 0x7b, 0x10, 0x3b, 0x4d, 0x5b, 0x28, 0x3b, 0x8e, + 0xe7, 0x97, 0x3b, 0xb4, 0xef, 0x6f, 0x3b, 0xc2, 0xd6, 0x55, 0x3b, 0x89, 0x56, + 0x6a, 0x3b, 0x44, 0xc6, 0x70, 0x3b, 0xb4, 0x0a, 0x2c, 0x3b, 0xc6, 0xc2, 0x1c, + 0x3b, 0x4b, 0xb3, 0x9b, 0x3b, 0x8c, 0x98, 0x61, 0x3b, 0x98, 0x37, 0x90, 0x3b, + 0x51, 0xaa, 0x5b, 0x3b, 0x32, 0x7e, 0x81, 0x3b, 0x90, 0x3e, 0x5d, 0x3b, 0x34, + 0x88, 0x41, 0x3b, 0x78, 0x6b, 0x59, 0x3b, 0xeb, 0xb0, 0x4c, 0x3b, 0x3c, 0x78, + 0x3c, 0x3b, 0xcb, 0x77, 0x58, 0x3b, 0x77, 0x8c, 0x16, 0x3b, 0xbb, 0xad, 0x2c, + 0x3b, 0xc3, 0x8c, 0x8b, 0x3b, 0x26, 0xb3, 0x82, 0x3b, 0xd6, 0x40, 0x6a, 0x3b, + 0x8e, 0xe1, 0x38, 0x3b, 0x7e, 0xd5, 0x6e, 0x3b, 0x10, 0xe0, 0x74, 0x3b, 0xc5, + 0x58, 0x60, 0x3b, 0xf5, 0xaa, 0x3b, 0x3b, 0xbd, 0xde, 0x1c, 0x3b, 0xe8, 0xcc, + 0x45, 0x3b, 0xbf, 0x14, 0xfb, 0x3a, 0x37, 0xe0, 0x67, 0x3b, 0xc4, 0xe3, 0x8d, + 0x3b, 0xf7, 0xbe, 0xca, 0x3a, 0xdb, 0x1a, 0x0e, 0x3b, 0xb8, 0xa4, 0x6a, 0x3b, + 0x4b, 0xa5, 0x59, 0x3b, 0x90, 0xf5, 0x4f, 0x3b, 0xbc, 0xdd, 0x6a, 0x3b, 0x9d, + 0x26, 0x66, 0x3b, 0x28, 0x0d, 0x5e, 0x3b, 0x58, 0xa2, 0x7e, 0x3b, 0x86, 0x80, + 0x83, 0x3b, 0x03, 0x4a, 0x14, 0x3b, 0xf4, 0xda, 0x12, 0x3b, 0x2b, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x35, 0x5f, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, + 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x56, 0xae, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x68, 0x03, 0x00, 0x00, 0x4d, + 0x00, 0x00, 0x00, 0x24, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb2, 0xa7, + 0xff, 0xff, 0x14, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0xaf, 0x6d, 0xa7, 0x3b, 0x6f, 0xfb, 0x1a, 0x3c, + 0x4f, 0x65, 0xf0, 0x3b, 0x64, 0x5c, 0xf6, 0x3b, 0xd1, 0xef, 0x18, 0x3c, 0x0b, + 0xb1, 0x8f, 0x3b, 0xd0, 0x97, 0xb1, 0x3b, 0x49, 0xed, 0x48, 0x3b, 0xc5, 0x55, + 0x50, 0x3c, 0xff, 0xff, 0x6c, 0x3c, 0x09, 0x61, 0x8d, 0x3c, 0xd3, 0xcb, 0x17, + 0x3c, 0x51, 0x94, 0x14, 0x3c, 0xb9, 0xd6, 0x7c, 0x3b, 0xd5, 0xff, 0xd5, 0x3b, + 0x69, 0x20, 0x00, 0x3c, 0x8b, 0x38, 0xbe, 0x3b, 0xa6, 0xe9, 0x9a, 0x3b, 0x9a, + 0xea, 0xd7, 0x3b, 0xd0, 0x5e, 0x9d, 0x3b, 0xfa, 0x04, 0x95, 0x3b, 0x76, 0xe1, + 0xc0, 0x3b, 0xc1, 0x6e, 0x8b, 0x3c, 0xf0, 0x34, 0xcb, 0x3b, 0xca, 0x60, 0xb1, + 0x3b, 0x79, 0xa5, 0x64, 0x3c, 0x3b, 0x85, 0x38, 0x3c, 0xe2, 0x8a, 0x95, 0x3b, + 0xec, 0xbb, 0xc0, 0x3b, 0xfb, 0xa3, 0xe9, 0x3b, 0x14, 0x3d, 0xb1, 0x3b, 0x1d, + 0x89, 0xe8, 0x3b, 0x06, 0x7a, 0x8b, 0x3b, 0x2f, 0x32, 0xb6, 0x3b, 0xcc, 0x2e, + 0xd7, 0x3b, 0x32, 0xc7, 0x68, 0x3b, 0xd7, 0x22, 0x33, 0x3c, 0x1e, 0x40, 0x42, + 0x3c, 0x6e, 0xb4, 0xb6, 0x3b, 0x28, 0x77, 0xb0, 0x3b, 0x49, 0xaa, 0xed, 0x3b, + 0x4f, 0x78, 0xe2, 0x3b, 0x85, 0xe9, 0x23, 0x3c, 0x5e, 0xe9, 0xd9, 0x3b, 0x6d, + 0xab, 0x7a, 0x3b, 0x21, 0x29, 0x5f, 0x3b, 0xb7, 0x50, 0x3e, 0x3c, 0xf7, 0xc3, + 0x84, 0x3b, 0x18, 0x38, 0x2b, 0x3c, 0x01, 0x11, 0x12, 0x3c, 0x78, 0xe8, 0xf3, + 0x3b, 0x7d, 0x96, 0x0d, 0x3c, 0xb6, 0x66, 0x56, 0x3c, 0x79, 0x61, 0xb3, 0x3b, + 0xea, 0x0d, 0x92, 0x3b, 0xb3, 0xe3, 0xa9, 0x3b, 0xe0, 0xc5, 0x0c, 0x3c, 0xce, + 0x38, 0xc8, 0x3b, 0xb8, 0x38, 0x9b, 0x3b, 0x23, 0x35, 0xa1, 0x3b, 0x5e, 0x18, + 0x4a, 0x3c, 0x63, 0x54, 0x8a, 0x3b, 0x17, 0xe9, 0xb7, 0x3b, 0xfa, 0x64, 0x3d, + 0x3c, 0x35, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x35, 0x5f, + 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, + 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0xda, 0xb1, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x58, 0x03, + 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x5c, 0xb8, 0xff, 0xff, 0x10, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x9e, 0x9c, 0x8a, 0x3b, 0xa1, 0xfb, 0x2f, 0x3b, 0x08, + 0x09, 0xa5, 0x3b, 0xf9, 0xb5, 0x8a, 0x3b, 0x37, 0xe2, 0x55, 0x3b, 0x57, 0x24, + 0x72, 0x3b, 0x09, 0xef, 0x9f, 0x3b, 0xa9, 0xe2, 0x83, 0x3b, 0x95, 0x08, 0x35, + 0x3b, 0x15, 0x8c, 0x8c, 0x3b, 0xb7, 0x43, 0x15, 0x3b, 0xa3, 0xf2, 0x9f, 0x3b, + 0xed, 0xf3, 0x33, 0x3b, 0x8a, 0x02, 0x8a, 0x3b, 0xcc, 0xf5, 0xad, 0x3b, 0x31, + 0x32, 0x03, 0x3c, 0x5c, 0x78, 0x87, 0x3b, 0x97, 0xb7, 0x82, 0x3b, 0xae, 0xbb, + 0x8c, 0x3b, 0x1a, 0x38, 0x3c, 0x3b, 0xf6, 0xc9, 0xe6, 0x3b, 0xa1, 0x15, 0x54, + 0x3b, 0x80, 0x78, 0x5c, 0x3b, 0xec, 0x30, 0xc3, 0x3b, 0x58, 0x81, 0xba, 0x3b, + 0x74, 0x73, 0xe2, 0x3a, 0x5c, 0x1b, 0x2e, 0x3b, 0x52, 0x39, 0xd7, 0x3b, 0x96, + 0xb9, 0xb3, 0x3b, 0x71, 0x24, 0x83, 0x3b, 0x20, 0x23, 0x8a, 0x3b, 0x48, 0xf7, + 0xc2, 0x3b, 0x4d, 0x5e, 0xaa, 0x3b, 0x32, 0x14, 0x22, 0x3b, 0x6a, 0x7e, 0x6e, + 0x3b, 0x2e, 0x1c, 0xdf, 0x3b, 0x54, 0x42, 0x1e, 0x3b, 0x46, 0x10, 0x24, 0x3b, + 0x0a, 0xad, 0x6f, 0x3b, 0x22, 0x6a, 0x35, 0x3b, 0xc4, 0x9b, 0x5f, 0x3b, 0xfd, + 0xd4, 0x8d, 0x3b, 0x7e, 0xed, 0x53, 0x3b, 0x09, 0xdb, 0x8e, 0x3b, 0xbd, 0xad, + 0xce, 0x3b, 0xf2, 0xa0, 0xd0, 0x3b, 0xea, 0x53, 0x06, 0x3b, 0xc8, 0x51, 0x71, + 0x3b, 0x76, 0x51, 0xad, 0x3b, 0x21, 0x81, 0x0c, 0x3c, 0x3a, 0x8c, 0x04, 0x3c, + 0xa8, 0xbe, 0x8f, 0x3b, 0x4f, 0xc3, 0x8d, 0x3b, 0x9e, 0x1c, 0x09, 0x3c, 0x17, + 0x93, 0xac, 0x3b, 0x67, 0x90, 0x98, 0x3b, 0x7d, 0x65, 0x54, 0x3b, 0x7b, 0x0d, + 0xd5, 0x3b, 0x42, 0x1c, 0x92, 0x3b, 0xec, 0x41, 0xa6, 0x3b, 0x4a, 0x0f, 0x42, + 0x3b, 0x5c, 0x69, 0xfd, 0x3b, 0xd2, 0x9d, 0xbb, 0x3b, 0x0a, 0xbb, 0x48, 0x3b, + 0x2b, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, + 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x34, 0x5f, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x77, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x4e, 0xb5, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0xe8, 0x01, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0xaa, 0xae, 0xff, 0xff, 0x14, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0e, + 0xe8, 0x3a, 0x3b, 0x06, 0xdb, 0x60, 0x3b, 0x15, 0xab, 0x2c, 0x3b, 0xc2, 0x4d, + 0x69, 0x3b, 0xed, 0xe2, 0x03, 0x3c, 0xf7, 0x38, 0x87, 0x3b, 0x43, 0xca, 0x46, + 0x3b, 0x75, 0x5e, 0x48, 0x3b, 0x1b, 0xa8, 0x47, 0x3b, 0x1a, 0x27, 0x1a, 0x3b, + 0xfa, 0xaa, 0x64, 0x3b, 0xd7, 0x95, 0x46, 0x3b, 0x29, 0x74, 0x8d, 0x3b, 0x56, + 0x3a, 0xdf, 0x3b, 0xfc, 0xdf, 0x93, 0x3b, 0x2a, 0xd8, 0x59, 0x3b, 0x3a, 0x2c, + 0x4d, 0x3b, 0x06, 0xa2, 0x3e, 0x3b, 0x56, 0xe5, 0xa0, 0x3b, 0x7c, 0x42, 0x51, + 0x3b, 0x36, 0x2c, 0x9f, 0x3b, 0x6f, 0xd4, 0x8f, 0x3b, 0x01, 0x77, 0x07, 0x3b, + 0x5a, 0xfa, 0x65, 0x3b, 0x61, 0xc0, 0xe2, 0x3b, 0x7d, 0xea, 0x78, 0x3b, 0x3d, + 0x98, 0x57, 0x3b, 0x13, 0x7d, 0x40, 0x3b, 0x60, 0xdc, 0x9b, 0x3b, 0x92, 0x50, + 0x5e, 0x3b, 0x09, 0xc6, 0x90, 0x3b, 0xe0, 0x52, 0xd7, 0x3b, 0x35, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x34, 0x5f, 0x64, 0x65, 0x70, 0x74, + 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, + 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, + 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x52, + 0xb7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0xd8, 0x01, 0x00, 0x00, 0x21, 0x00, + 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd4, 0xbd, 0xff, + 0xff, 0x10, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x1f, 0xd1, 0x8d, 0x3b, 0x4a, 0xc4, 0xc6, 0x3b, 0x9e, + 0xc2, 0xa2, 0x3b, 0x50, 0x27, 0x83, 0x3b, 0x8f, 0xb4, 0x09, 0x3b, 0xa4, 0x9e, + 0x3b, 0x3b, 0x8d, 0xe0, 0x73, 0x3b, 0x54, 0x0e, 0x5f, 0x3b, 0xa8, 0xd7, 0xa1, + 0x3b, 0x7f, 0x7a, 0x75, 0x3b, 0x0e, 0xe9, 0xbc, 0x3b, 0xfa, 0x06, 0x60, 0x3b, + 0x12, 0x4b, 0xab, 0x3b, 0x95, 0xb8, 0xaf, 0x3b, 0x37, 0xc2, 0x54, 0x3b, 0xbe, + 0x2b, 0x7b, 0x3b, 0xdd, 0xc9, 0x83, 0x3b, 0xb2, 0x00, 0x9b, 0x3b, 0x6c, 0x06, + 0xbe, 0x3b, 0x47, 0xd2, 0x9d, 0x3b, 0x27, 0xbe, 0xdc, 0x3b, 0xe2, 0x70, 0x84, + 0x3b, 0xc7, 0xd1, 0x6e, 0x3b, 0x4f, 0x2c, 0xa8, 0x3b, 0xf4, 0x02, 0xd2, 0x3b, + 0x9c, 0xc2, 0x04, 0x3c, 0x0b, 0x8d, 0xd7, 0x3b, 0x16, 0x65, 0xb0, 0x3b, 0xaf, + 0xc2, 0x3a, 0x3b, 0xd6, 0xbb, 0x7c, 0x3b, 0x16, 0x8c, 0x98, 0x3b, 0xbb, 0xd1, + 0x7e, 0x3b, 0x2b, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, + 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x33, + 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x77, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x46, 0xb9, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0xe8, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0xa2, 0xb2, 0xff, 0xff, 0x14, 0x01, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x87, 0x89, 0x04, 0x3c, 0x79, 0xd0, 0x1d, 0x3c, 0x68, 0xa3, 0xe5, 0x3b, + 0xb9, 0x26, 0x22, 0x3c, 0x98, 0xca, 0x50, 0x3c, 0x30, 0xc4, 0xc5, 0x3c, 0x27, + 0x84, 0x8f, 0x3b, 0x2d, 0x0a, 0xeb, 0x3b, 0xbe, 0xf6, 0xee, 0x3b, 0xf0, 0x0c, + 0x8b, 0x3c, 0xc4, 0xd5, 0xb1, 0x3c, 0xcb, 0x44, 0xdc, 0x3b, 0x23, 0x2a, 0x34, + 0x3b, 0xcc, 0x23, 0x57, 0x3c, 0x95, 0x75, 0x0a, 0x3c, 0xdc, 0xdd, 0x06, 0x3b, + 0x15, 0x63, 0xe5, 0x3b, 0x3b, 0xa4, 0x8b, 0x3b, 0x01, 0x47, 0xb3, 0x3c, 0x17, + 0x08, 0xc8, 0x3c, 0xde, 0x85, 0xb4, 0x3b, 0x47, 0x1d, 0xc0, 0x3c, 0x5e, 0xf2, + 0x4f, 0x3b, 0x0c, 0x34, 0xd4, 0x3b, 0xc9, 0x45, 0xc7, 0x3b, 0x2a, 0x86, 0xf0, + 0x3c, 0x46, 0x7c, 0xf8, 0x3b, 0x57, 0x56, 0x52, 0x3b, 0x04, 0xf4, 0xa6, 0x3b, + 0xec, 0x8d, 0xe0, 0x3b, 0x44, 0x9f, 0xd3, 0x3b, 0x4d, 0x19, 0x38, 0x3c, 0x35, + 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, + 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x33, 0x5f, 0x64, 0x65, + 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, + 0x77, 0x69, 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, + 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x4a, 0xbb, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0xd8, 0x01, 0x00, 0x00, + 0x3d, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xcc, + 0xc1, 0xff, 0xff, 0x10, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x5c, 0xc7, 0x3c, 0x3c, 0x66, 0x8c, 0x83, + 0x3b, 0xd4, 0x22, 0xcd, 0x3b, 0x48, 0x6e, 0xd1, 0x3b, 0xdc, 0x08, 0xa3, 0x3b, + 0x61, 0x10, 0xd1, 0x3a, 0x79, 0x0b, 0xaf, 0x3b, 0x3a, 0x7e, 0xe1, 0x3b, 0x30, + 0x6c, 0x76, 0x3b, 0xfb, 0x99, 0x5e, 0x3b, 0xf0, 0xc4, 0xe5, 0x3a, 0x1c, 0xc4, + 0xa8, 0x3b, 0xb1, 0x3a, 0xd0, 0x3b, 0x88, 0x11, 0xa7, 0x3b, 0xec, 0xf4, 0x20, + 0x3c, 0xe3, 0xd4, 0x3b, 0x3c, 0xab, 0xed, 0xd9, 0x3b, 0x95, 0xdb, 0xfa, 0x3b, + 0x66, 0x0a, 0x11, 0x3b, 0x9b, 0x16, 0x4e, 0x3b, 0x24, 0xb6, 0xb0, 0x3b, 0xa5, + 0xc7, 0xfd, 0x3a, 0xac, 0x74, 0xc1, 0x3b, 0xbc, 0x52, 0xdc, 0x3b, 0x0a, 0xb5, + 0xb0, 0x3b, 0x49, 0x2c, 0x92, 0x3a, 0x60, 0x8d, 0xb4, 0x3b, 0x7f, 0x7e, 0xef, + 0x3b, 0x9a, 0x83, 0x1b, 0x3c, 0x4a, 0x50, 0x9a, 0x3b, 0xd4, 0x4d, 0x08, 0x3c, + 0x80, 0x79, 0x71, 0x3b, 0x2b, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, + 0x5f, 0x32, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, + 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3e, 0xbd, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x09, 0x28, 0x01, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x9a, 0xb6, 0xff, 0xff, 0x94, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0xf3, 0xae, 0x65, 0x3b, 0x76, 0xd3, 0x46, 0x3b, + 0x47, 0x81, 0xa1, 0x3b, 0xa1, 0x23, 0x83, 0x3b, 0x2e, 0x71, 0xbf, 0x3b, 0xbf, + 0x4c, 0x9d, 0x3b, 0x00, 0xc1, 0xa5, 0x3b, 0x36, 0x82, 0x2f, 0x3b, 0x9a, 0xaf, + 0xa4, 0x3b, 0x3a, 0xd4, 0x11, 0x3c, 0x22, 0x3a, 0x44, 0x3b, 0xb5, 0x66, 0xa2, + 0x3b, 0xef, 0x6f, 0x6c, 0x3b, 0x28, 0xc6, 0x65, 0x3b, 0xb1, 0x23, 0xda, 0x3b, + 0x85, 0x20, 0xed, 0x3b, 0x35, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, + 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, + 0x5f, 0x32, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, + 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x82, 0xbe, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x09, 0x18, 0x01, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0xc5, 0xff, 0xff, 0x90, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x09, 0x89, 0x62, 0x3c, 0x4d, 0xd2, 0x10, 0x3c, 0xc6, 0x64, 0x87, 0x3c, 0xc1, + 0x43, 0xee, 0x3b, 0x0a, 0x21, 0x47, 0x3c, 0x41, 0xa2, 0x49, 0x3c, 0x5e, 0x4c, + 0x00, 0x3c, 0x22, 0x6b, 0x0c, 0x3c, 0xb3, 0x07, 0x6a, 0x3c, 0x28, 0xb4, 0x07, + 0x3c, 0xb3, 0xc7, 0x52, 0x3c, 0x27, 0x63, 0x03, 0x3c, 0x87, 0xac, 0x46, 0x3c, + 0xe4, 0xd4, 0xe3, 0x3b, 0x53, 0xf1, 0x04, 0x3c, 0x58, 0xb6, 0x32, 0x3c, 0x2b, + 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, + 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x5f, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0xb6, 0xbf, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0xc8, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x12, 0xb9, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0xc6, 0x53, 0x8c, 0x3b, 0xca, 0x97, 0xca, 0x3b, 0x35, 0x82, 0x15, 0x3e, + 0xcd, 0x4b, 0x3e, 0x3b, 0x6d, 0x31, 0x70, 0x3c, 0x71, 0x98, 0x2d, 0x3b, 0x91, + 0xa1, 0xf1, 0x3b, 0x42, 0xa8, 0xa3, 0x3e, 0x35, 0x00, 0x00, 0x00, 0x4d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, + 0x76, 0x32, 0x64, 0x5f, 0x31, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, + 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, + 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x9a, 0xc0, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x58, 0x0c, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1c, + 0x0c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0xc7, 0xff, 0xff, 0x0c, 0x08, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x35, 0xc1, 0x5c, 0x3a, 0xe5, + 0xef, 0xaa, 0x3a, 0xfb, 0x29, 0x95, 0x3a, 0xd6, 0x76, 0x09, 0x3a, 0x9a, 0xd5, + 0x99, 0x3a, 0x88, 0x58, 0x2f, 0x3a, 0xe3, 0x21, 0x42, 0x3a, 0xe5, 0x62, 0x95, + 0x3a, 0xfa, 0xa3, 0x5e, 0x3a, 0x66, 0x7c, 0x87, 0x3a, 0xef, 0x0d, 0x5d, 0x3a, + 0x96, 0x73, 0x31, 0x3a, 0x87, 0x13, 0x8d, 0x3a, 0x55, 0xee, 0x38, 0x3a, 0x8f, + 0x82, 0x34, 0x3a, 0x09, 0x82, 0x56, 0x3a, 0x8f, 0x70, 0x67, 0x3a, 0x8d, 0xca, + 0x2d, 0x3a, 0xf5, 0x8b, 0x1c, 0x3a, 0xcf, 0x64, 0x7c, 0x3a, 0xda, 0xb7, 0x12, + 0x3a, 0xff, 0xd8, 0x46, 0x3a, 0x72, 0xa8, 0x80, 0x3a, 0xb8, 0x32, 0x48, 0x3a, + 0x95, 0xdf, 0x97, 0x3a, 0xe1, 0x48, 0x42, 0x3a, 0xad, 0xfc, 0xb2, 0x3a, 0x0f, + 0xfe, 0x82, 0x3a, 0xec, 0xcc, 0x18, 0x3a, 0x0f, 0x77, 0x38, 0x3a, 0x48, 0x00, + 0x5a, 0x3a, 0x17, 0x3b, 0x77, 0x3a, 0x5c, 0x99, 0x90, 0x3a, 0xa5, 0x25, 0x50, + 0x3a, 0xbc, 0x0d, 0x48, 0x3a, 0x14, 0xc8, 0x3e, 0x3a, 0xe9, 0xb8, 0x52, 0x3a, + 0x6b, 0xc3, 0x25, 0x3a, 0x4a, 0x97, 0x65, 0x3a, 0xd6, 0x6f, 0x45, 0x3a, 0x95, + 0x18, 0x84, 0x3a, 0x8e, 0xaf, 0x58, 0x3a, 0xc7, 0x30, 0x84, 0x3a, 0x99, 0x69, + 0x77, 0x3a, 0x22, 0xc9, 0x10, 0x3a, 0x95, 0xb8, 0x1e, 0x3a, 0x50, 0xd3, 0x43, + 0x3a, 0xe2, 0x56, 0x36, 0x3a, 0x5e, 0xe9, 0x8a, 0x3a, 0xb1, 0x42, 0x86, 0x3a, + 0x28, 0xd7, 0x58, 0x3a, 0x5f, 0xe0, 0x1d, 0x3a, 0x70, 0x0e, 0x35, 0x3a, 0x13, + 0x7b, 0xcf, 0x3a, 0x5e, 0xfd, 0x3c, 0x3a, 0x1c, 0xe5, 0x7c, 0x3a, 0x42, 0x7e, + 0x85, 0x3a, 0x67, 0x18, 0x48, 0x3a, 0xbd, 0xec, 0x33, 0x3a, 0xc7, 0x8c, 0x5c, + 0x3a, 0x23, 0xff, 0x5c, 0x3a, 0x76, 0xcc, 0x4d, 0x3a, 0xe1, 0x08, 0x81, 0x3a, + 0x2d, 0xca, 0x3e, 0x3a, 0x76, 0x72, 0x1a, 0x3a, 0x5e, 0x40, 0x55, 0x3a, 0x38, + 0x79, 0x23, 0x3a, 0x59, 0x0d, 0x43, 0x3a, 0x43, 0x52, 0x42, 0x3a, 0x1c, 0x46, + 0x63, 0x3a, 0xce, 0xe7, 0x67, 0x3a, 0xe9, 0x16, 0x3e, 0x3a, 0x3c, 0x0c, 0x02, + 0x3a, 0xb6, 0x1a, 0x54, 0x3a, 0x2d, 0xd9, 0x28, 0x3a, 0xa0, 0x6b, 0x25, 0x3a, + 0xfd, 0xd0, 0xa5, 0x3a, 0xa9, 0x48, 0x59, 0x3a, 0x58, 0x22, 0x34, 0x3a, 0x5a, + 0xec, 0x09, 0x3a, 0x80, 0x39, 0xcb, 0x3a, 0x54, 0x07, 0x2c, 0x3a, 0x0a, 0x1d, + 0x0a, 0x3a, 0x0a, 0x82, 0x43, 0x3a, 0x65, 0x5e, 0x90, 0x3a, 0xf7, 0xc1, 0x18, + 0x3a, 0xba, 0x95, 0x34, 0x3a, 0x58, 0x5d, 0x9d, 0x3a, 0xc2, 0x69, 0x43, 0x3a, + 0x61, 0x37, 0x4b, 0x3a, 0x7d, 0x5a, 0x80, 0x3a, 0x63, 0x47, 0x28, 0x3a, 0x1f, + 0xbc, 0x4b, 0x3a, 0xd7, 0xa2, 0x59, 0x3a, 0x84, 0x6e, 0x11, 0x3a, 0xaa, 0x21, + 0x9b, 0x3a, 0x54, 0xa6, 0x83, 0x3a, 0xb7, 0x23, 0x66, 0x3a, 0xaa, 0xa8, 0x97, + 0x3a, 0x14, 0x6a, 0x2c, 0x3a, 0x4d, 0x1b, 0x2b, 0x3a, 0x2a, 0xbf, 0x27, 0x3a, + 0xf9, 0x8a, 0x27, 0x3a, 0x6a, 0x9e, 0x5d, 0x3a, 0xfa, 0xda, 0x89, 0x3a, 0x4f, + 0xea, 0x2e, 0x3a, 0x6b, 0x3f, 0x29, 0x3a, 0x51, 0xba, 0x28, 0x3a, 0xa8, 0x04, + 0x74, 0x3a, 0xcd, 0xb2, 0x56, 0x3a, 0x08, 0xe9, 0x85, 0x3a, 0xe2, 0x08, 0x28, + 0x3a, 0xa4, 0xfb, 0x02, 0x3a, 0x1c, 0x1b, 0x9a, 0x3a, 0x0b, 0xf8, 0x32, 0x3a, + 0x21, 0x7d, 0x83, 0x3a, 0xbd, 0xc4, 0x8e, 0x3a, 0xb8, 0x50, 0x39, 0x3a, 0x34, + 0xba, 0xa2, 0x3a, 0xa2, 0xfd, 0x26, 0x3a, 0xc7, 0xf1, 0x5c, 0x3a, 0x89, 0x82, + 0x1e, 0x3a, 0xc9, 0x03, 0x25, 0x3a, 0xda, 0x86, 0x55, 0x3a, 0xd2, 0xb4, 0x5d, + 0x3a, 0xa8, 0x51, 0x26, 0x3a, 0x4f, 0x3e, 0x21, 0x3a, 0xea, 0x6c, 0x75, 0x3a, + 0xf4, 0x32, 0x6b, 0x3a, 0xa6, 0x58, 0x9b, 0x3a, 0x3c, 0xd4, 0xa1, 0x3a, 0x9c, + 0x68, 0x7d, 0x3a, 0x8f, 0x54, 0x58, 0x3a, 0x41, 0x4c, 0x24, 0x3a, 0x2f, 0x16, + 0x68, 0x3a, 0x3b, 0x1d, 0x06, 0x3a, 0xa3, 0x7b, 0x7b, 0x3a, 0xd7, 0x94, 0x71, + 0x3a, 0xa1, 0x17, 0x25, 0x3a, 0xe4, 0x77, 0x42, 0x3a, 0x05, 0xb9, 0x6e, 0x3a, + 0x00, 0xe4, 0x42, 0x3a, 0x9b, 0xb6, 0x49, 0x3a, 0x25, 0x09, 0x5f, 0x3a, 0xae, + 0x63, 0x55, 0x3a, 0x78, 0x8d, 0x50, 0x3a, 0xa5, 0xf5, 0x64, 0x3a, 0x22, 0x6e, + 0x61, 0x3a, 0x34, 0x1c, 0x75, 0x3a, 0x8f, 0xf8, 0x33, 0x3a, 0x71, 0xc6, 0x62, + 0x3a, 0x34, 0x5d, 0x44, 0x3a, 0xb3, 0x6d, 0x25, 0x3a, 0x41, 0x2b, 0x19, 0x3a, + 0xd8, 0x4a, 0x73, 0x3a, 0x4b, 0x72, 0x59, 0x3a, 0xa2, 0x6c, 0x41, 0x3a, 0x0a, + 0xed, 0x9e, 0x3a, 0x05, 0x1e, 0x46, 0x3a, 0x5a, 0x17, 0x49, 0x3a, 0xd4, 0xea, + 0x23, 0x3a, 0x76, 0xdb, 0x46, 0x3a, 0x6f, 0xb2, 0xb7, 0x3a, 0x9b, 0xe6, 0x4e, + 0x3a, 0x28, 0x26, 0x42, 0x3a, 0x92, 0xb3, 0x3a, 0x3a, 0x93, 0x76, 0x1e, 0x3a, + 0x92, 0x54, 0x49, 0x3a, 0x35, 0x42, 0x13, 0x3a, 0xac, 0x30, 0xa2, 0x3a, 0xc4, + 0xca, 0x4f, 0x3a, 0x18, 0x3c, 0x1e, 0x3a, 0x44, 0xd1, 0x8a, 0x3a, 0x22, 0x0d, + 0x34, 0x3a, 0x66, 0xf7, 0x47, 0x3a, 0xe7, 0x06, 0x49, 0x3a, 0x38, 0xc8, 0x07, + 0x3b, 0x41, 0xe5, 0xca, 0x3a, 0x4b, 0x05, 0x63, 0x3a, 0x48, 0x83, 0x50, 0x3a, + 0x3b, 0x4a, 0x23, 0x3a, 0x10, 0x05, 0x3c, 0x3a, 0x70, 0x54, 0x45, 0x3a, 0xfc, + 0xb4, 0x56, 0x3a, 0x16, 0x39, 0x7a, 0x3a, 0xd3, 0xac, 0x67, 0x3a, 0x13, 0x8d, + 0x98, 0x3a, 0x99, 0x9d, 0x3e, 0x3a, 0x2a, 0x46, 0x37, 0x3a, 0xfc, 0x1c, 0x4a, + 0x3a, 0xa1, 0x1c, 0x52, 0x3a, 0xab, 0x73, 0x7b, 0x3a, 0x04, 0xc9, 0x24, 0x3a, + 0x0b, 0xf4, 0x57, 0x3a, 0xc8, 0xab, 0x74, 0x3a, 0x4d, 0x7b, 0x1f, 0x3a, 0x21, + 0xe0, 0x34, 0x3a, 0x37, 0x61, 0x82, 0x3a, 0x63, 0xe2, 0x21, 0x3a, 0x6f, 0xd2, + 0xdf, 0x39, 0x7e, 0x17, 0x36, 0x3a, 0xe5, 0xa0, 0xef, 0x39, 0xc6, 0x00, 0x6b, + 0x3a, 0x5d, 0x5d, 0x71, 0x3a, 0xe6, 0xe7, 0x52, 0x3a, 0x8f, 0xd1, 0x80, 0x3a, + 0x20, 0x09, 0x8f, 0x3a, 0x83, 0xbe, 0x2f, 0x3a, 0xe3, 0x3d, 0x14, 0x3a, 0x58, + 0xec, 0x66, 0x3a, 0xb2, 0x96, 0x6e, 0x3a, 0xc3, 0x27, 0x7f, 0x3a, 0xfa, 0xea, + 0x50, 0x3a, 0xbb, 0x93, 0x3f, 0x3a, 0x88, 0xc4, 0xbb, 0x3a, 0x81, 0xa1, 0x16, + 0x3a, 0xaa, 0x0d, 0x18, 0x3a, 0xd3, 0x61, 0x51, 0x3a, 0x6a, 0x28, 0x72, 0x3a, + 0xa7, 0xa6, 0x4d, 0x3a, 0x01, 0xb4, 0x5b, 0x3a, 0x49, 0x56, 0x2f, 0x3a, 0x39, + 0x06, 0x84, 0x3a, 0x90, 0x4e, 0x90, 0x3a, 0xce, 0x41, 0x49, 0x3a, 0x94, 0x2a, + 0x40, 0x3a, 0x2e, 0xbc, 0x1f, 0x3a, 0x1e, 0x6d, 0x18, 0x3a, 0xd8, 0x8b, 0x30, + 0x3a, 0x48, 0xcd, 0x2b, 0x3a, 0x39, 0xfd, 0x89, 0x3a, 0x9e, 0xbf, 0x36, 0x3a, + 0xf0, 0xf7, 0x49, 0x3a, 0x53, 0xa4, 0x03, 0x3a, 0xc8, 0x82, 0x7f, 0x3a, 0x77, + 0x2f, 0xa8, 0x3a, 0x9a, 0x23, 0x83, 0x3a, 0x4e, 0x97, 0x22, 0x3a, 0xe9, 0x13, + 0x2a, 0x3a, 0x39, 0x76, 0x7c, 0x3a, 0x0b, 0x01, 0xbe, 0x3a, 0x4a, 0x2f, 0x8a, + 0x3a, 0x41, 0x24, 0x29, 0x3a, 0x15, 0x51, 0xbb, 0x3a, 0x38, 0x36, 0x1d, 0x3a, + 0x1f, 0x00, 0xa9, 0x3a, 0x64, 0x35, 0x95, 0x3a, 0xbd, 0x91, 0x69, 0x3a, 0xdf, + 0xcf, 0x32, 0x3a, 0x0e, 0xc4, 0xc3, 0x3a, 0x36, 0xb8, 0x38, 0x3a, 0x95, 0xfc, + 0x58, 0x3a, 0xf0, 0xf3, 0xa5, 0x3a, 0x17, 0x58, 0x87, 0x3a, 0xa1, 0xe4, 0x54, + 0x3a, 0xaf, 0x41, 0x87, 0x3a, 0x2c, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, + 0x64, 0x5f, 0x31, 0x33, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, + 0x65, 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0e, + 0xcd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x68, 0x0c, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x24, 0x0c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6a, 0xc6, 0xff, + 0xff, 0x14, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x71, 0x40, 0x3c, 0xe8, 0xda, 0xe7, + 0x3b, 0xe4, 0xb9, 0x56, 0x3c, 0x54, 0x6a, 0xf9, 0x3b, 0x67, 0x0c, 0xbf, 0x3b, + 0x24, 0x1c, 0x0b, 0x3c, 0x6a, 0x8f, 0xb1, 0x3b, 0xdc, 0x08, 0x24, 0x3c, 0xb2, + 0x7c, 0xbe, 0x3b, 0x80, 0xad, 0x24, 0x3c, 0x51, 0xbd, 0xdb, 0x3b, 0xb3, 0xff, + 0xc2, 0x3b, 0x86, 0xbc, 0xee, 0x3b, 0x59, 0xcb, 0xed, 0x3b, 0xbb, 0x7f, 0x2c, + 0x3c, 0x49, 0xb7, 0x16, 0x3c, 0xc3, 0xea, 0xd4, 0x3b, 0x45, 0xed, 0xbf, 0x3b, + 0x83, 0x67, 0x18, 0x3c, 0xa5, 0x1b, 0x0d, 0x3c, 0x08, 0x5c, 0x25, 0x3c, 0x1d, + 0x17, 0x08, 0x3c, 0x5f, 0xdc, 0x04, 0x3c, 0xd5, 0x0b, 0x0b, 0x3c, 0xac, 0x9d, + 0x16, 0x3c, 0xfb, 0x22, 0xdb, 0x3b, 0xd0, 0xb7, 0xee, 0x3b, 0xa7, 0x22, 0x11, + 0x3c, 0x89, 0x0d, 0x20, 0x3c, 0x8f, 0x3f, 0xb2, 0x3b, 0x5b, 0x72, 0xce, 0x3b, + 0x76, 0x21, 0xb6, 0x3b, 0x9b, 0x02, 0xc9, 0x3b, 0xdb, 0xa3, 0xeb, 0x3b, 0xd3, + 0xde, 0x03, 0x3c, 0x52, 0xde, 0x07, 0x3c, 0x56, 0xd8, 0x30, 0x3c, 0x4b, 0xd2, + 0xff, 0x3b, 0x7d, 0x2b, 0x52, 0x3c, 0xca, 0x87, 0x33, 0x3c, 0xf1, 0xe7, 0x0d, + 0x3c, 0xc2, 0x0c, 0x01, 0x3c, 0xbc, 0x93, 0xd6, 0x3b, 0x9d, 0xfc, 0xe5, 0x3b, + 0x11, 0x90, 0xf2, 0x3b, 0x0f, 0xa2, 0xff, 0x3b, 0xfc, 0x7a, 0x08, 0x3c, 0x34, + 0x8b, 0x2d, 0x3c, 0x7b, 0xef, 0xfe, 0x3b, 0xe9, 0x05, 0xe5, 0x3b, 0x35, 0x65, + 0xde, 0x3b, 0xcf, 0xc6, 0xd8, 0x3b, 0xc4, 0xe0, 0xa9, 0x3b, 0xb6, 0x87, 0x13, + 0x3c, 0x08, 0x17, 0x2f, 0x3c, 0x12, 0x77, 0xdc, 0x3b, 0xf8, 0xfd, 0xdf, 0x3b, + 0xed, 0xee, 0xe4, 0x3b, 0x3e, 0xab, 0x23, 0x3c, 0x4c, 0xac, 0xb6, 0x3b, 0xae, + 0x28, 0xfc, 0x3b, 0x63, 0x1d, 0x3b, 0x3c, 0x21, 0x45, 0x02, 0x3c, 0x58, 0xca, + 0x4f, 0x3c, 0x5f, 0x9b, 0x28, 0x3c, 0xf0, 0x2a, 0x1d, 0x3c, 0x20, 0x20, 0xd9, + 0x3b, 0xda, 0xa2, 0x18, 0x3c, 0x5b, 0x63, 0x0b, 0x3c, 0x97, 0x50, 0x0d, 0x3c, + 0x77, 0xd5, 0xcb, 0x3b, 0xfb, 0xc4, 0x1c, 0x3c, 0xa6, 0x4a, 0xdd, 0x3b, 0x1d, + 0x2b, 0xf4, 0x3b, 0x71, 0xcd, 0x08, 0x3c, 0xd3, 0x09, 0xf9, 0x3b, 0x36, 0x59, + 0xc5, 0x3b, 0x51, 0x4a, 0x04, 0x3c, 0x93, 0xca, 0x2f, 0x3c, 0x80, 0x6e, 0xf5, + 0x3b, 0xed, 0x35, 0x25, 0x3c, 0x52, 0xc5, 0xdb, 0x3b, 0x0a, 0x34, 0x26, 0x3c, + 0x9a, 0x17, 0xeb, 0x3b, 0xd1, 0xac, 0xb9, 0x3b, 0x9b, 0xc2, 0x0a, 0x3c, 0xff, + 0x69, 0x2e, 0x3c, 0x57, 0x4d, 0xef, 0x3b, 0x7b, 0x6c, 0x10, 0x3c, 0x6e, 0xe2, + 0xe8, 0x3b, 0xde, 0x4e, 0xcb, 0x3b, 0xf6, 0xd9, 0xdc, 0x3b, 0x71, 0xf7, 0x07, + 0x3c, 0xe5, 0x80, 0x49, 0x3c, 0xd1, 0xee, 0x0b, 0x3c, 0x09, 0xbc, 0x02, 0x3c, + 0x52, 0xeb, 0x0f, 0x3c, 0x42, 0x61, 0x16, 0x3c, 0xf3, 0xd2, 0xcc, 0x3b, 0xec, + 0x81, 0xe8, 0x3b, 0xe0, 0x2e, 0x15, 0x3c, 0x0e, 0x34, 0x1f, 0x3c, 0xd3, 0x49, + 0xf9, 0x3b, 0x1c, 0x03, 0x01, 0x3c, 0x77, 0x8f, 0xe5, 0x3b, 0xd6, 0x2c, 0x09, + 0x3c, 0xe1, 0x22, 0xdd, 0x3b, 0x04, 0xb9, 0xa9, 0x3b, 0x2f, 0x2a, 0x1b, 0x3c, + 0x87, 0x2f, 0x32, 0x3c, 0x91, 0xb7, 0xcc, 0x3b, 0x5e, 0x47, 0xf7, 0x3b, 0xbf, + 0x49, 0xd2, 0x3b, 0x85, 0x5b, 0x03, 0x3c, 0xd4, 0x9d, 0x9b, 0x3b, 0x6f, 0x85, + 0xc9, 0x3b, 0xb4, 0xa9, 0x02, 0x3c, 0x46, 0xe9, 0x18, 0x3c, 0x41, 0x05, 0x52, + 0x3c, 0x03, 0x46, 0xe3, 0x3b, 0x80, 0x38, 0x0f, 0x3c, 0x2c, 0x2b, 0x30, 0x3c, + 0x43, 0x27, 0xbe, 0x3b, 0x53, 0x47, 0xf1, 0x3b, 0x11, 0xc6, 0x05, 0x3c, 0x6a, + 0xaf, 0x07, 0x3c, 0x8f, 0x63, 0x3f, 0x3c, 0xe3, 0x24, 0x1d, 0x3c, 0x52, 0x51, + 0x65, 0x3c, 0xc7, 0x39, 0xcf, 0x3b, 0x93, 0x31, 0xd6, 0x3b, 0x15, 0x97, 0x06, + 0x3c, 0x6d, 0xc8, 0x0b, 0x3c, 0xa8, 0x32, 0x07, 0x3c, 0xdb, 0x3e, 0xc9, 0x3b, + 0xec, 0x7d, 0xb1, 0x3b, 0xc5, 0xee, 0xce, 0x3b, 0x3a, 0xb1, 0x90, 0x3b, 0x99, + 0x5a, 0xd2, 0x3b, 0x36, 0xe0, 0x1c, 0x3c, 0xd3, 0xaf, 0x08, 0x3c, 0x00, 0xed, + 0x2b, 0x3c, 0x61, 0xd2, 0x6a, 0x3c, 0x43, 0x53, 0xdc, 0x3b, 0xd1, 0x7a, 0x19, + 0x3c, 0x14, 0x4d, 0x24, 0x3c, 0xf6, 0xfb, 0x0b, 0x3c, 0x20, 0xc4, 0x10, 0x3c, + 0x6e, 0x6c, 0x12, 0x3c, 0xdb, 0x71, 0x1e, 0x3c, 0x3f, 0xad, 0x02, 0x3c, 0x24, + 0x6d, 0xa5, 0x3b, 0x0e, 0x74, 0x39, 0x3c, 0xc7, 0xfe, 0x15, 0x3c, 0xe8, 0x69, + 0xdc, 0x3b, 0xdd, 0x24, 0x0c, 0x3c, 0x47, 0x57, 0x04, 0x3c, 0xcf, 0xf3, 0xf9, + 0x3b, 0x13, 0xfc, 0xef, 0x3b, 0x62, 0xc3, 0x1c, 0x3c, 0x02, 0x45, 0xfa, 0x3b, + 0x0d, 0xfd, 0xf1, 0x3b, 0x71, 0x8b, 0x9c, 0x3b, 0xd7, 0xab, 0xc9, 0x3b, 0x28, + 0x5d, 0x14, 0x3c, 0xe5, 0x71, 0xe6, 0x3b, 0x3a, 0xa1, 0x1b, 0x3c, 0x49, 0xcc, + 0xf8, 0x3b, 0x92, 0xcd, 0xf9, 0x3b, 0x73, 0xec, 0x24, 0x3c, 0x9d, 0xa1, 0x80, + 0x3c, 0xc1, 0x94, 0xb5, 0x3b, 0xbf, 0x58, 0x17, 0x3c, 0xe1, 0xcb, 0x05, 0x3c, + 0x7d, 0xff, 0xe4, 0x3b, 0xe8, 0x2b, 0x32, 0x3c, 0x0f, 0x99, 0x22, 0x3c, 0x2b, + 0xf6, 0xc9, 0x3b, 0x7d, 0xec, 0x44, 0x3c, 0xe6, 0x63, 0x20, 0x3c, 0xf5, 0x7a, + 0x17, 0x3c, 0x3d, 0xc2, 0x26, 0x3c, 0x5f, 0xaa, 0xf2, 0x3b, 0x72, 0x06, 0xc5, + 0x3b, 0xdb, 0x1d, 0xcd, 0x3b, 0x9c, 0x43, 0x81, 0x3c, 0xac, 0x2f, 0x2a, 0x3c, + 0x80, 0xfb, 0x46, 0x3c, 0xfe, 0x9f, 0xe5, 0x3b, 0x74, 0x85, 0x0a, 0x3c, 0x38, + 0x1d, 0x16, 0x3c, 0xd1, 0x3e, 0xd8, 0x3b, 0x6a, 0x95, 0xb1, 0x3b, 0xf7, 0x07, + 0xf9, 0x3b, 0x82, 0x05, 0xab, 0x3b, 0xaf, 0xe3, 0xda, 0x3b, 0x7a, 0xeb, 0xc9, + 0x3b, 0x56, 0x85, 0x14, 0x3c, 0x58, 0x82, 0x39, 0x3c, 0xed, 0xc7, 0x27, 0x3c, + 0xfa, 0x26, 0x31, 0x3c, 0xdd, 0x03, 0x0d, 0x3c, 0x82, 0x66, 0xbb, 0x3b, 0xc3, + 0xbb, 0xb2, 0x3b, 0xf1, 0xf7, 0x28, 0x3c, 0x71, 0x80, 0xa1, 0x3b, 0x16, 0x27, + 0x01, 0x3c, 0xfa, 0x22, 0x04, 0x3c, 0xf8, 0xb6, 0x47, 0x3c, 0x33, 0x46, 0x2b, + 0x3c, 0x65, 0xcf, 0xe1, 0x3b, 0x78, 0x79, 0xe7, 0x3b, 0xd3, 0x9a, 0xfa, 0x3b, + 0x87, 0x41, 0x00, 0x3c, 0xf2, 0x4e, 0x17, 0x3c, 0x95, 0xa9, 0x29, 0x3c, 0x8f, + 0x50, 0x12, 0x3c, 0xa3, 0x7b, 0xe0, 0x3b, 0xf2, 0xc9, 0x02, 0x3c, 0x4b, 0x4f, + 0xb2, 0x3b, 0xcc, 0x25, 0x26, 0x3c, 0xfc, 0x07, 0x1a, 0x3c, 0xea, 0x97, 0x05, + 0x3c, 0x0a, 0x9b, 0x29, 0x3c, 0xfe, 0x65, 0xf8, 0x3b, 0xac, 0x80, 0x0a, 0x3c, + 0xaf, 0x6f, 0xed, 0x3b, 0x86, 0xda, 0xc8, 0x3b, 0xd3, 0xf7, 0x03, 0x3c, 0xf3, + 0x08, 0x10, 0x3c, 0x4f, 0x69, 0x53, 0x3c, 0xad, 0xc6, 0x10, 0x3c, 0xf6, 0x7a, + 0xe5, 0x3b, 0x23, 0x52, 0x1e, 0x3c, 0xc8, 0xcc, 0x42, 0x3c, 0x1b, 0x64, 0xc9, + 0x3b, 0xa6, 0x6c, 0x29, 0x3c, 0xaa, 0x9b, 0xda, 0x3b, 0x69, 0x72, 0x01, 0x3c, + 0x59, 0xba, 0xe2, 0x3b, 0xe1, 0x4e, 0x25, 0x3c, 0x79, 0x3b, 0xdb, 0x3b, 0xed, + 0x7a, 0xb3, 0x3b, 0xa5, 0x7d, 0xf5, 0x3b, 0x9f, 0xbf, 0x14, 0x3c, 0x7f, 0x81, + 0x29, 0x3c, 0x04, 0xff, 0x0b, 0x3c, 0x81, 0x0d, 0x22, 0x3c, 0x91, 0xd2, 0x17, + 0x3c, 0xca, 0x1c, 0x19, 0x3c, 0x04, 0x31, 0x1e, 0x3c, 0xc5, 0x42, 0xed, 0x3b, + 0x29, 0xb5, 0xaa, 0x3b, 0x88, 0xb8, 0x0e, 0x3c, 0xad, 0x1b, 0xc6, 0x3b, 0xc5, + 0x74, 0xff, 0x3b, 0x36, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, + 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, + 0x31, 0x33, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, + 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x92, 0xd9, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, + 0x58, 0x0c, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x14, 0xe0, 0xff, 0xff, 0x0c, 0x08, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0xcc, 0xe1, 0x0f, 0x3b, 0x17, 0x4c, 0xbf, 0x3a, 0x04, + 0x03, 0xea, 0x3a, 0xcc, 0xf3, 0xde, 0x3a, 0x10, 0xa3, 0x4e, 0x3b, 0x00, 0x59, + 0xe0, 0x3a, 0x5d, 0xde, 0x29, 0x3b, 0x21, 0x80, 0x2c, 0x3b, 0xf8, 0x74, 0xea, + 0x3a, 0x02, 0xe3, 0x05, 0x3b, 0xd8, 0xb1, 0x03, 0x3b, 0x77, 0x53, 0xfd, 0x3a, + 0x96, 0x88, 0xc9, 0x3a, 0x58, 0x58, 0x0c, 0x3b, 0xfb, 0x10, 0x5b, 0x3b, 0x2a, + 0xf4, 0x17, 0x3b, 0x46, 0x1e, 0x26, 0x3b, 0xb2, 0x20, 0xc5, 0x3a, 0x1a, 0x6e, + 0x06, 0x3b, 0x2a, 0x57, 0x05, 0x3b, 0x67, 0xf5, 0x2d, 0x3b, 0xd0, 0x2c, 0x02, + 0x3b, 0x8a, 0xf5, 0xf7, 0x3a, 0x38, 0x73, 0xdd, 0x3a, 0xa1, 0xb8, 0x0e, 0x3b, + 0xea, 0x08, 0x28, 0x3b, 0x48, 0x78, 0x0f, 0x3b, 0x07, 0x63, 0x25, 0x3b, 0x81, + 0x6d, 0xe8, 0x3a, 0x25, 0xc8, 0x03, 0x3b, 0x00, 0xb7, 0xb3, 0x3a, 0xaf, 0xa6, + 0x1a, 0x3b, 0x7f, 0x56, 0x0c, 0x3b, 0x89, 0x65, 0x07, 0x3b, 0xb5, 0xae, 0xbe, + 0x3a, 0xb4, 0xee, 0xfa, 0x3a, 0x1a, 0x88, 0x5f, 0x3b, 0xc9, 0x6f, 0xfa, 0x3a, + 0x32, 0xb8, 0xc5, 0x3a, 0x72, 0x60, 0x28, 0x3b, 0xd9, 0x9d, 0x29, 0x3b, 0x83, + 0xf8, 0x06, 0x3b, 0x24, 0xb0, 0x03, 0x3b, 0xb8, 0x11, 0xdd, 0x3a, 0xce, 0x34, + 0xf2, 0x3a, 0x77, 0x44, 0xfb, 0x3a, 0x2c, 0x3e, 0xe5, 0x3a, 0xe8, 0xbe, 0xe4, + 0x3a, 0x8b, 0x3f, 0x36, 0x3b, 0x80, 0x2c, 0x12, 0x3b, 0xb1, 0x7a, 0x09, 0x3b, + 0x83, 0x16, 0xc6, 0x3a, 0x47, 0xcc, 0x22, 0x3b, 0xcb, 0xa5, 0xf7, 0x3a, 0xab, + 0x7e, 0x0d, 0x3b, 0x22, 0x3e, 0x0c, 0x3b, 0xcd, 0xc2, 0x22, 0x3b, 0x5a, 0x8b, + 0xfb, 0x3a, 0x20, 0x95, 0xd0, 0x3a, 0x05, 0x9e, 0x06, 0x3b, 0x23, 0x35, 0xd0, + 0x3a, 0xb1, 0x27, 0x21, 0x3b, 0x08, 0x8b, 0xc1, 0x3a, 0x65, 0x3d, 0x0d, 0x3b, + 0x1f, 0xf2, 0x2e, 0x3b, 0x7c, 0x69, 0x0f, 0x3b, 0x4d, 0x9d, 0x09, 0x3b, 0xcd, + 0x8f, 0x0f, 0x3b, 0xe6, 0x71, 0xc8, 0x3a, 0x9e, 0x28, 0x06, 0x3b, 0x08, 0x80, + 0x00, 0x3b, 0x80, 0x15, 0xff, 0x3a, 0xf1, 0x34, 0x47, 0x3b, 0x74, 0x20, 0x06, + 0x3b, 0xfe, 0x06, 0x03, 0x3b, 0xb7, 0x7a, 0xd7, 0x3a, 0x6e, 0xe4, 0x13, 0x3b, + 0xe9, 0x3e, 0x02, 0x3b, 0x31, 0xd5, 0x24, 0x3b, 0xef, 0x18, 0x9f, 0x3b, 0x1c, + 0xc8, 0x46, 0x3b, 0xb3, 0xd3, 0xc8, 0x3a, 0x50, 0xef, 0x1d, 0x3b, 0xcc, 0x59, + 0x99, 0x3a, 0xce, 0xc6, 0xdd, 0x3a, 0x4a, 0xde, 0x92, 0x3a, 0xe4, 0x27, 0x1e, + 0x3b, 0xef, 0x9f, 0x49, 0x3b, 0xa4, 0xf2, 0xcc, 0x3a, 0x36, 0x46, 0x25, 0x3b, + 0x41, 0xb3, 0x23, 0x3b, 0xb6, 0x32, 0x3f, 0x3b, 0xb2, 0xc5, 0x07, 0x3b, 0x26, + 0x07, 0x38, 0x3b, 0x43, 0xe2, 0x1c, 0x3b, 0xa7, 0xe0, 0x18, 0x3b, 0x6e, 0xdd, + 0xff, 0x3a, 0x2f, 0xb9, 0xff, 0x3a, 0x2d, 0x2f, 0x14, 0x3b, 0x8b, 0xf0, 0x0b, + 0x3b, 0x08, 0x83, 0x08, 0x3b, 0x06, 0x5b, 0x0b, 0x3b, 0x94, 0x3a, 0xc8, 0x3a, + 0x24, 0x24, 0xe9, 0x3a, 0x9a, 0x87, 0x0f, 0x3b, 0x64, 0xd1, 0x07, 0x3b, 0xdf, + 0xe5, 0xda, 0x3a, 0x3a, 0x00, 0xe6, 0x3a, 0xe1, 0x2c, 0x42, 0x3b, 0x6c, 0x54, + 0xe0, 0x3a, 0x0b, 0xe9, 0x0e, 0x3b, 0xfd, 0xe2, 0xe6, 0x3a, 0xff, 0xeb, 0x16, + 0x3b, 0x57, 0xf1, 0x4d, 0x3b, 0xe4, 0xb3, 0xb0, 0x3a, 0x63, 0x93, 0xf0, 0x3a, + 0xaf, 0x4e, 0x48, 0x3b, 0xb4, 0x9a, 0x2c, 0x3b, 0xa1, 0x6f, 0x20, 0x3b, 0x19, + 0x20, 0x29, 0x3b, 0x73, 0x22, 0x0a, 0x3b, 0x61, 0xa8, 0x1f, 0x3b, 0x17, 0xb5, + 0xd9, 0x3a, 0xa5, 0xd2, 0xee, 0x3a, 0xa7, 0xe1, 0xfe, 0x3a, 0x10, 0xbd, 0xf6, + 0x3a, 0xdd, 0x6f, 0xd7, 0x3a, 0x21, 0xd4, 0xf3, 0x3a, 0x19, 0xf4, 0xd9, 0x3a, + 0x08, 0x84, 0x0c, 0x3b, 0x92, 0x7c, 0xfc, 0x3a, 0xb5, 0x3a, 0x18, 0x3b, 0x34, + 0xe2, 0xea, 0x3a, 0x0e, 0xc1, 0x04, 0x3b, 0xc4, 0xee, 0x56, 0x3b, 0x9c, 0xd0, + 0xe8, 0x3a, 0x87, 0x38, 0x05, 0x3b, 0xde, 0x41, 0xb7, 0x3a, 0x0b, 0xba, 0xa9, + 0x3a, 0xeb, 0xb4, 0x01, 0x3b, 0x7f, 0x46, 0xe2, 0x3a, 0x03, 0x5e, 0x23, 0x3b, + 0x56, 0x83, 0xe6, 0x3a, 0xbd, 0xab, 0x09, 0x3b, 0xe0, 0x54, 0x23, 0x3b, 0xd5, + 0xb0, 0x3d, 0x3b, 0xaa, 0xb2, 0x2f, 0x3b, 0x18, 0xcd, 0x2d, 0x3b, 0x26, 0xf2, + 0xda, 0x3a, 0x8c, 0x2e, 0x03, 0x3b, 0x79, 0x49, 0x06, 0x3b, 0xf3, 0x28, 0xfa, + 0x3a, 0x38, 0x2a, 0x1a, 0x3b, 0x36, 0x54, 0xbe, 0x3a, 0xbb, 0x2b, 0x12, 0x3b, + 0xf7, 0xba, 0x4f, 0x3b, 0xed, 0x4b, 0x12, 0x3b, 0x7b, 0xaa, 0x1c, 0x3b, 0xa6, + 0xba, 0x1a, 0x3b, 0x6f, 0x3f, 0x11, 0x3b, 0x7e, 0x33, 0x0f, 0x3b, 0xcf, 0x1e, + 0x09, 0x3b, 0xf9, 0xac, 0xec, 0x3a, 0x1a, 0x14, 0xb5, 0x3a, 0x41, 0x60, 0xe4, + 0x3a, 0x9d, 0x2e, 0x22, 0x3b, 0x22, 0x15, 0x22, 0x3b, 0x61, 0xc5, 0x2c, 0x3b, + 0x5f, 0x52, 0xd6, 0x3a, 0x2c, 0x54, 0x28, 0x3b, 0x83, 0x55, 0x4a, 0x3b, 0xce, + 0x9d, 0x46, 0x3b, 0x50, 0xc7, 0xfa, 0x3a, 0x57, 0xce, 0xfd, 0x3a, 0x66, 0x9f, + 0x28, 0x3b, 0x6b, 0x4d, 0xe2, 0x3a, 0xed, 0x62, 0x0e, 0x3b, 0x0a, 0xec, 0xf5, + 0x3a, 0x91, 0xb2, 0x08, 0x3b, 0x71, 0xf2, 0x25, 0x3b, 0x6f, 0xc9, 0x06, 0x3b, + 0x55, 0x88, 0x09, 0x3b, 0x81, 0xd6, 0x52, 0x3b, 0x97, 0xa1, 0xf7, 0x3a, 0x63, + 0x44, 0xf0, 0x3a, 0x94, 0x6b, 0xf8, 0x3a, 0xde, 0x51, 0x01, 0x3b, 0x22, 0xef, + 0xf4, 0x3a, 0x2d, 0x9c, 0x0b, 0x3b, 0x08, 0xb3, 0x39, 0x3b, 0xb9, 0x83, 0xff, + 0x3a, 0x55, 0x0d, 0xfb, 0x3a, 0x8c, 0x07, 0x11, 0x3b, 0xff, 0x16, 0xc1, 0x3a, + 0x0d, 0xee, 0x06, 0x3b, 0xb2, 0x17, 0x08, 0x3b, 0x31, 0x4b, 0xfc, 0x3a, 0xda, + 0x5e, 0x2f, 0x3b, 0x60, 0x7f, 0x24, 0x3b, 0x3d, 0xbb, 0x2c, 0x3b, 0xe3, 0xa9, + 0x1b, 0x3b, 0x99, 0x25, 0x16, 0x3b, 0x32, 0x5c, 0x29, 0x3b, 0xe2, 0x6c, 0x36, + 0x3b, 0x1e, 0x20, 0xc0, 0x3a, 0x74, 0xbd, 0x32, 0x3b, 0x83, 0xdf, 0xf6, 0x3a, + 0xf2, 0x4d, 0x1d, 0x3b, 0xfd, 0xe6, 0x1d, 0x3b, 0xc8, 0x3a, 0xed, 0x3a, 0x85, + 0x4f, 0x20, 0x3b, 0x49, 0x58, 0xd3, 0x3a, 0xc5, 0x4e, 0x06, 0x3b, 0x36, 0xee, + 0x28, 0x3b, 0x6f, 0xca, 0xdb, 0x3a, 0xe4, 0x35, 0x09, 0x3b, 0x1f, 0xbb, 0x28, + 0x3b, 0x4c, 0x89, 0x00, 0x3b, 0x0c, 0x8d, 0x0f, 0x3b, 0x8e, 0x74, 0x13, 0x3b, + 0x5b, 0xf4, 0x2e, 0x3b, 0x93, 0xe0, 0x4b, 0x3b, 0x14, 0xc6, 0x09, 0x3b, 0x07, + 0xf0, 0x0a, 0x3b, 0x3c, 0x54, 0x1f, 0x3b, 0xda, 0x01, 0xbb, 0x3a, 0x59, 0x9c, + 0xe8, 0x3a, 0xc7, 0xea, 0x0b, 0x3b, 0x15, 0x88, 0xf2, 0x3a, 0xbc, 0xc3, 0xd8, + 0x3a, 0xcc, 0xd6, 0x14, 0x3b, 0xca, 0x60, 0x34, 0x3b, 0xf9, 0x7f, 0x00, 0x3b, + 0x31, 0xf8, 0x07, 0x3b, 0x2d, 0xac, 0x26, 0x3b, 0x02, 0x10, 0xda, 0x3a, 0x58, + 0xdc, 0xda, 0x3a, 0x65, 0x3b, 0x05, 0x3b, 0x73, 0xa1, 0x21, 0x3b, 0x2b, 0xb1, + 0x0d, 0x3b, 0xf2, 0xf7, 0xe2, 0x3a, 0x82, 0xc1, 0xc3, 0x3a, 0xc7, 0xf2, 0x10, + 0x3b, 0x42, 0xf2, 0x47, 0x3b, 0x33, 0x3b, 0xf1, 0x3a, 0x76, 0x6e, 0x20, 0x3b, + 0x97, 0x5b, 0x07, 0x3b, 0xe8, 0x6b, 0x11, 0x3b, 0xd3, 0xdb, 0x21, 0x3b, 0x8b, + 0x09, 0x38, 0x3b, 0xd7, 0x22, 0x0d, 0x3b, 0x39, 0xa9, 0xfe, 0x3a, 0x1b, 0xf3, + 0xe6, 0x3a, 0x15, 0x3e, 0x06, 0x3b, 0x21, 0xeb, 0x4a, 0x3b, 0xf3, 0x97, 0x43, + 0x3b, 0x2c, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, + 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x32, + 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x77, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x06, 0xe6, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x09, 0x68, 0x06, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x24, 0x06, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x62, 0xdf, 0xff, 0xff, 0x14, 0x04, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x8d, 0xb0, 0x3b, 0xf3, 0x87, 0x95, 0x3b, + 0xa0, 0x61, 0x06, 0x3c, 0xc6, 0x88, 0xd8, 0x3b, 0xb8, 0x1d, 0x17, 0x3c, 0x2e, + 0x80, 0x8f, 0x3b, 0x95, 0xd1, 0xac, 0x3b, 0x02, 0x8b, 0xdb, 0x3b, 0x0e, 0xd5, + 0x96, 0x3b, 0x56, 0x45, 0x0b, 0x3c, 0x29, 0xf1, 0xbf, 0x3b, 0x33, 0x80, 0x9e, + 0x3b, 0x84, 0xdd, 0xd8, 0x3b, 0x22, 0xca, 0xb1, 0x3b, 0xf4, 0xd5, 0xa7, 0x3b, + 0x93, 0xee, 0xcd, 0x3b, 0x77, 0xa4, 0x18, 0x3c, 0x65, 0xb4, 0xe5, 0x3b, 0x55, + 0x8b, 0xb9, 0x3b, 0x5a, 0x00, 0xac, 0x3b, 0x00, 0x49, 0xb3, 0x3b, 0x1c, 0x7b, + 0x9a, 0x3b, 0xd6, 0x10, 0xdc, 0x3b, 0x6d, 0xe7, 0xb8, 0x3b, 0xf0, 0x27, 0x89, + 0x3b, 0xbb, 0x44, 0xe0, 0x3b, 0x85, 0xd8, 0xbc, 0x3b, 0xbc, 0xf9, 0x92, 0x3b, + 0x8e, 0xfa, 0xed, 0x3b, 0x55, 0x2b, 0xd2, 0x3b, 0x37, 0xfc, 0xd1, 0x3b, 0x1b, + 0xfe, 0xfc, 0x3b, 0x51, 0x9b, 0xda, 0x3b, 0xe7, 0xb1, 0xf2, 0x3b, 0x15, 0x64, + 0xb1, 0x3b, 0x84, 0x34, 0xee, 0x3b, 0x4e, 0x10, 0xe6, 0x3b, 0xc4, 0x61, 0x7d, + 0x3b, 0x78, 0x42, 0x91, 0x3b, 0x45, 0xd0, 0x13, 0x3c, 0xe8, 0x63, 0x83, 0x3b, + 0x9d, 0x6f, 0x22, 0x3c, 0x8d, 0xd6, 0x03, 0x3c, 0xfe, 0x27, 0xc2, 0x3b, 0xda, + 0x67, 0xa9, 0x3b, 0xe9, 0xef, 0xc1, 0x3b, 0xab, 0x9b, 0x9d, 0x3b, 0x64, 0xad, + 0x0c, 0x3c, 0x62, 0x44, 0xa6, 0x3b, 0x53, 0x87, 0xa7, 0x3b, 0x4d, 0xa9, 0xa1, + 0x3b, 0x33, 0x38, 0x92, 0x3b, 0x1a, 0x0d, 0xe8, 0x3b, 0xda, 0x1d, 0xff, 0x3b, + 0x69, 0x33, 0xe1, 0x3b, 0x0d, 0xed, 0xf5, 0x3b, 0xa2, 0x82, 0x93, 0x3b, 0x59, + 0x7d, 0xdf, 0x3b, 0x3a, 0x5d, 0x80, 0x3b, 0x20, 0x50, 0xb1, 0x3b, 0xee, 0x64, + 0xec, 0x3b, 0xeb, 0x2b, 0xf1, 0x3b, 0xa0, 0x96, 0xc4, 0x3b, 0x29, 0xdc, 0x88, + 0x3b, 0x92, 0x9b, 0xaf, 0x3b, 0xb9, 0x15, 0xe6, 0x3b, 0xad, 0x85, 0x95, 0x3b, + 0xb2, 0x3a, 0xc9, 0x3b, 0xcd, 0x48, 0xc7, 0x3b, 0x47, 0x5b, 0x08, 0x3c, 0x8d, + 0x63, 0xbe, 0x3b, 0xa4, 0xc0, 0x8d, 0x3b, 0x91, 0xf7, 0xae, 0x3b, 0x98, 0xdd, + 0x92, 0x3b, 0x2c, 0xfe, 0xb5, 0x3b, 0x03, 0x40, 0xad, 0x3b, 0x76, 0x64, 0x73, + 0x3b, 0xac, 0x52, 0xae, 0x3b, 0x06, 0xcc, 0xd2, 0x3b, 0x01, 0x7b, 0xa0, 0x3b, + 0xac, 0x67, 0xd4, 0x3b, 0x2d, 0x3a, 0xfc, 0x3b, 0x81, 0x8f, 0xad, 0x3b, 0xae, + 0xc9, 0xcb, 0x3b, 0xc7, 0xe3, 0xf3, 0x3b, 0xbf, 0xce, 0xda, 0x3b, 0xb6, 0x27, + 0xe2, 0x3b, 0x05, 0xf9, 0xb6, 0x3b, 0x12, 0xd2, 0x15, 0x3c, 0x93, 0xbc, 0xe6, + 0x3b, 0x5e, 0x19, 0x6e, 0x3b, 0x4e, 0x57, 0xe9, 0x3b, 0x5b, 0x8e, 0x12, 0x3c, + 0x32, 0x9f, 0xb8, 0x3b, 0x10, 0x17, 0xbd, 0x3b, 0xde, 0xa4, 0x0b, 0x3c, 0x14, + 0xda, 0xa2, 0x3b, 0x5f, 0x00, 0xc5, 0x3b, 0x8f, 0xd5, 0xcb, 0x3b, 0xff, 0xb6, + 0xa1, 0x3b, 0x97, 0x44, 0x09, 0x3c, 0x7e, 0x30, 0x18, 0x3c, 0x52, 0xa2, 0x22, + 0x3c, 0xcd, 0xfe, 0xa5, 0x3b, 0x30, 0xec, 0xd4, 0x3b, 0xfc, 0xfa, 0xa5, 0x3b, + 0xab, 0x8d, 0x08, 0x3c, 0x4e, 0xe2, 0xc5, 0x3b, 0x83, 0x80, 0xb6, 0x3b, 0xbf, + 0xbc, 0x30, 0x3c, 0x53, 0xc1, 0xf5, 0x3b, 0x13, 0x74, 0xa2, 0x3b, 0x7a, 0x61, + 0xcb, 0x3b, 0xf9, 0xc9, 0xbc, 0x3b, 0x84, 0x85, 0xc4, 0x3b, 0x95, 0x6e, 0xc7, + 0x3b, 0xf0, 0x90, 0x13, 0x3c, 0xcc, 0x3e, 0xcf, 0x3b, 0xb6, 0xd3, 0x88, 0x3b, + 0x08, 0x19, 0x9b, 0x3b, 0xb5, 0x8b, 0xdc, 0x3b, 0xae, 0xe0, 0x80, 0x3b, 0xdf, + 0x38, 0xb4, 0x3b, 0xd6, 0x74, 0x22, 0x3c, 0xb8, 0xec, 0x4b, 0x3b, 0xb0, 0x1f, + 0xa9, 0x3b, 0xe2, 0x3e, 0x0c, 0x3c, 0x3a, 0xe1, 0x05, 0x3c, 0x36, 0x00, 0x00, + 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, + 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x32, 0x5f, 0x64, 0x65, 0x70, + 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, + 0x69, 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, + 0x65, 0x61, 0x64, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x8a, + 0xec, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x58, 0x06, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0x00, 0x1c, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0xf3, 0xff, + 0xff, 0x0c, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0xd7, 0x8a, 0x53, 0x3b, 0x38, 0xdb, 0x39, 0x3b, 0x26, 0x99, 0x4d, 0x3b, + 0x6c, 0xd5, 0x12, 0x3b, 0xcc, 0x46, 0x25, 0x3b, 0x4b, 0x9a, 0xe8, 0x3a, 0xd1, + 0xff, 0x27, 0x3b, 0xc5, 0x60, 0x07, 0x3b, 0x66, 0xaa, 0x0e, 0x3b, 0x2a, 0x4d, + 0x06, 0x3b, 0x7e, 0x98, 0x08, 0x3b, 0xd2, 0x44, 0x29, 0x3b, 0x8c, 0x7b, 0x39, + 0x3b, 0xf6, 0xdc, 0x01, 0x3b, 0x1f, 0xea, 0x21, 0x3b, 0xd0, 0x34, 0x02, 0x3b, + 0x98, 0x0b, 0x59, 0x3b, 0x6c, 0x69, 0x35, 0x3b, 0x68, 0x68, 0xfc, 0x3a, 0x47, + 0x6b, 0x1b, 0x3b, 0x45, 0x2b, 0x20, 0x3b, 0xb1, 0x7a, 0x01, 0x3b, 0x95, 0x2e, + 0x0f, 0x3b, 0x66, 0x5b, 0x27, 0x3b, 0xe6, 0x6e, 0x4e, 0x3b, 0x5e, 0xac, 0x0d, + 0x3b, 0x30, 0x90, 0x22, 0x3b, 0x54, 0x9e, 0x2d, 0x3b, 0xc8, 0x19, 0xea, 0x3a, + 0x8e, 0x3c, 0x23, 0x3b, 0x65, 0x70, 0x25, 0x3b, 0xf4, 0x79, 0x14, 0x3b, 0x29, + 0x49, 0x13, 0x3b, 0xfc, 0x2a, 0x40, 0x3b, 0x5c, 0x34, 0x3b, 0x3b, 0x2a, 0x52, + 0xf8, 0x3a, 0x6e, 0x51, 0x18, 0x3b, 0x53, 0x24, 0xf6, 0x3a, 0x33, 0x76, 0x24, + 0x3b, 0x60, 0xdf, 0x0f, 0x3b, 0xc5, 0x27, 0x0d, 0x3b, 0xfb, 0x7e, 0x37, 0x3b, + 0xa8, 0x98, 0x10, 0x3b, 0x37, 0xf8, 0x30, 0x3b, 0x0b, 0xda, 0x61, 0x3b, 0x7d, + 0x9b, 0x4a, 0x3b, 0xa1, 0xd6, 0x0e, 0x3b, 0x33, 0x87, 0x27, 0x3b, 0x23, 0x9d, + 0x40, 0x3b, 0x39, 0xec, 0x20, 0x3b, 0xef, 0xfa, 0x06, 0x3b, 0x9c, 0x98, 0x0d, + 0x3b, 0x47, 0x53, 0x03, 0x3b, 0x99, 0x43, 0x1d, 0x3b, 0x08, 0xe1, 0x01, 0x3b, + 0x70, 0x34, 0x14, 0x3b, 0xae, 0xfd, 0x61, 0x3b, 0xeb, 0xc0, 0x0e, 0x3b, 0x12, + 0x1f, 0x21, 0x3b, 0xf5, 0xba, 0x03, 0x3b, 0x19, 0xb4, 0x17, 0x3b, 0x36, 0x92, + 0x2d, 0x3b, 0x4f, 0xbd, 0x36, 0x3b, 0xb0, 0x11, 0x20, 0x3b, 0x62, 0x00, 0x52, + 0x3b, 0x8e, 0x5e, 0x1c, 0x3b, 0x9a, 0x5c, 0x20, 0x3b, 0x2f, 0xc8, 0x1a, 0x3b, + 0x86, 0xf1, 0x2c, 0x3b, 0x26, 0x6d, 0x13, 0x3b, 0x2a, 0x7a, 0xfa, 0x3a, 0xa6, + 0x9d, 0x10, 0x3b, 0xb7, 0xd3, 0x0e, 0x3b, 0xa1, 0xd2, 0x3e, 0x3b, 0xe1, 0x4e, + 0x0b, 0x3b, 0xa4, 0x34, 0x1c, 0x3b, 0x23, 0x67, 0xe9, 0x3a, 0x8c, 0xb7, 0xef, + 0x3a, 0x58, 0x7c, 0x30, 0x3b, 0x75, 0x25, 0x22, 0x3b, 0xce, 0x58, 0x81, 0x3b, + 0x37, 0x05, 0x77, 0x3b, 0xa9, 0xc4, 0x22, 0x3b, 0xfd, 0x03, 0x32, 0x3b, 0x64, + 0xd1, 0x06, 0x3b, 0xb2, 0x45, 0x11, 0x3b, 0x69, 0xf3, 0xf1, 0x3a, 0xb1, 0xda, + 0x02, 0x3b, 0x36, 0xa0, 0x42, 0x3b, 0x2c, 0x4e, 0x45, 0x3b, 0x04, 0xbf, 0x0c, + 0x3b, 0x8e, 0x3a, 0x46, 0x3b, 0x07, 0xad, 0x3e, 0x3b, 0x82, 0xcf, 0x06, 0x3b, + 0xdc, 0xa6, 0xe6, 0x3a, 0x11, 0xf5, 0x10, 0x3b, 0x09, 0xef, 0xf3, 0x3a, 0x6d, + 0x02, 0x11, 0x3b, 0xcf, 0x6f, 0xff, 0x3a, 0x0a, 0xb6, 0x6e, 0x3b, 0x01, 0x9d, + 0x25, 0x3b, 0x2e, 0x1a, 0x25, 0x3b, 0xc7, 0xa8, 0x34, 0x3b, 0x9e, 0x30, 0x24, + 0x3b, 0xe5, 0x89, 0xe8, 0x3a, 0x9e, 0x0e, 0x3b, 0x3b, 0xcf, 0x03, 0x0d, 0x3b, + 0xcf, 0xa9, 0x37, 0x3b, 0xde, 0xee, 0x1e, 0x3b, 0x00, 0x9d, 0x08, 0x3b, 0x9a, + 0xc3, 0x30, 0x3b, 0xcd, 0xb2, 0x14, 0x3b, 0x32, 0xbe, 0x29, 0x3b, 0x1e, 0x0a, + 0x0e, 0x3b, 0xb9, 0x86, 0x1c, 0x3b, 0x69, 0x25, 0x1d, 0x3b, 0x3d, 0xf6, 0x33, + 0x3b, 0x41, 0x5e, 0x04, 0x3b, 0xb0, 0x40, 0x35, 0x3b, 0xa8, 0x47, 0x16, 0x3b, + 0xfa, 0x67, 0x22, 0x3b, 0x0d, 0x6a, 0x01, 0x3b, 0x9d, 0xdb, 0x0d, 0x3b, 0x71, + 0xc1, 0x45, 0x3b, 0xe3, 0xb3, 0x05, 0x3b, 0x50, 0xf0, 0x23, 0x3b, 0xe0, 0xfa, + 0x4c, 0x3b, 0xb7, 0xaa, 0x1d, 0x3b, 0x2c, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, + 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, + 0x32, 0x64, 0x5f, 0x31, 0x31, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, + 0x73, 0x65, 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, + 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xfe, 0xf2, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x64, 0x06, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x5a, 0xec, + 0xff, 0xff, 0x10, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x60, 0xb4, 0xc7, 0x3b, 0xf2, 0x84, 0xdd, + 0x3b, 0x43, 0xf1, 0x08, 0x3c, 0x44, 0xaf, 0xbc, 0x3b, 0x85, 0x80, 0xa0, 0x3b, + 0xa1, 0xa5, 0xa5, 0x3b, 0xa5, 0x21, 0xd8, 0x3b, 0x03, 0xc9, 0x0a, 0x3c, 0x16, + 0x3b, 0xe2, 0x3b, 0x28, 0xd7, 0x17, 0x3c, 0xd1, 0x70, 0x14, 0x3c, 0x68, 0x0a, + 0xc2, 0x3b, 0x88, 0xea, 0x03, 0x3c, 0x4b, 0xd8, 0x27, 0x3c, 0xf2, 0x2b, 0xdb, + 0x3b, 0x1b, 0x19, 0x93, 0x3b, 0x08, 0x5a, 0xfe, 0x3b, 0x1d, 0x52, 0xa1, 0x3b, + 0xa4, 0x8d, 0xa9, 0x3b, 0x15, 0x51, 0x38, 0x3b, 0xe8, 0xaf, 0xb7, 0x3b, 0x20, + 0xf5, 0xe2, 0x3b, 0xad, 0xb9, 0x5c, 0x3b, 0xd7, 0x58, 0xc7, 0x3b, 0x4d, 0xf2, + 0xdc, 0x3b, 0x09, 0x90, 0xd8, 0x3b, 0xa0, 0x21, 0x26, 0x3c, 0xa6, 0x94, 0x2a, + 0x3c, 0x34, 0xde, 0x15, 0x3c, 0x96, 0xa8, 0x0e, 0x3c, 0xec, 0xf1, 0x62, 0x3b, + 0x86, 0x75, 0xef, 0x3b, 0xd2, 0x3d, 0xf7, 0x3b, 0x06, 0xfb, 0xfb, 0x3b, 0xff, + 0xaf, 0xa9, 0x3b, 0x84, 0xaf, 0xee, 0x3b, 0xed, 0x73, 0x92, 0x3b, 0x26, 0xd9, + 0xc9, 0x3b, 0xf0, 0xe3, 0x4d, 0x3c, 0x54, 0x6d, 0xae, 0x3b, 0x95, 0xb2, 0xf4, + 0x3b, 0x4c, 0x06, 0x10, 0x3c, 0xc9, 0x2c, 0x26, 0x3c, 0xf4, 0x94, 0xac, 0x3b, + 0xb6, 0x91, 0x8f, 0x3b, 0xb3, 0x7f, 0x96, 0x3b, 0xd8, 0x26, 0xda, 0x3b, 0x22, + 0xf7, 0xd5, 0x3b, 0x2f, 0x36, 0xf2, 0x3b, 0x4f, 0x35, 0xae, 0x3b, 0xbd, 0xf4, + 0x9f, 0x3b, 0x57, 0xea, 0xeb, 0x3b, 0x0f, 0xd9, 0xc7, 0x3b, 0xa2, 0xdb, 0xf5, + 0x3b, 0x53, 0x20, 0xce, 0x3b, 0x79, 0x60, 0x31, 0x3c, 0x20, 0x91, 0xb4, 0x3b, + 0xbc, 0x23, 0x15, 0x3c, 0x83, 0x1a, 0xf2, 0x3b, 0x09, 0x71, 0xc9, 0x3b, 0xf6, + 0x17, 0xb0, 0x3b, 0x9d, 0xc6, 0xc5, 0x3b, 0x71, 0x97, 0x22, 0x3c, 0x2c, 0x9e, + 0xf8, 0x3b, 0xc9, 0x79, 0x15, 0x3c, 0x0a, 0xfe, 0xaa, 0x3b, 0x83, 0x58, 0xa0, + 0x3b, 0xbc, 0x63, 0x9c, 0x3b, 0x43, 0x51, 0xa5, 0x3b, 0x33, 0xe5, 0xe2, 0x3b, + 0x3f, 0xb3, 0xd8, 0x3b, 0xe6, 0xe2, 0xbf, 0x3b, 0xce, 0xed, 0xe9, 0x3b, 0xdb, + 0x3f, 0xa1, 0x3b, 0xec, 0x47, 0xc7, 0x3b, 0x9d, 0xa7, 0xc5, 0x3b, 0x2e, 0xab, + 0x03, 0x3c, 0xfd, 0x97, 0xf0, 0x3b, 0x61, 0x09, 0x08, 0x3c, 0x4c, 0xe2, 0xfb, + 0x3b, 0x9b, 0x41, 0xa7, 0x3b, 0xbb, 0xb0, 0x9f, 0x3b, 0x6c, 0xb1, 0xd0, 0x3b, + 0x35, 0x03, 0x71, 0x3b, 0x63, 0x93, 0xc3, 0x3b, 0xbe, 0xfd, 0xda, 0x3b, 0x99, + 0xfe, 0xfa, 0x3b, 0xa3, 0x6f, 0x36, 0x3c, 0xf2, 0x06, 0xec, 0x3b, 0x05, 0xbd, + 0x92, 0x3b, 0x13, 0xea, 0x15, 0x3c, 0xbf, 0xa8, 0xd0, 0x3b, 0xf5, 0x2f, 0xf8, + 0x3b, 0xb9, 0xd4, 0x2a, 0x3c, 0x3d, 0x35, 0x1f, 0x3c, 0x24, 0xb2, 0x2c, 0x3c, + 0x49, 0x7c, 0x1a, 0x3c, 0x55, 0x86, 0xdf, 0x3b, 0xd6, 0xb4, 0x98, 0x3b, 0x78, + 0x8e, 0xd0, 0x3b, 0xa1, 0x51, 0xe4, 0x3b, 0xa4, 0x60, 0x92, 0x3b, 0x8e, 0x86, + 0x48, 0x3b, 0xdc, 0xc6, 0xe7, 0x3b, 0x21, 0xaf, 0xeb, 0x3b, 0xfb, 0x7b, 0x20, + 0x3c, 0xf6, 0x56, 0xf9, 0x3b, 0x14, 0xbc, 0x29, 0x3c, 0x1e, 0xf5, 0xca, 0x3b, + 0x33, 0x5f, 0x14, 0x3c, 0xe1, 0x61, 0x8a, 0x3b, 0x37, 0xdf, 0x9f, 0x3b, 0x5b, + 0x1b, 0xff, 0x3b, 0x0b, 0x7f, 0xbc, 0x3b, 0x9d, 0xcd, 0xc8, 0x3b, 0xe2, 0xe4, + 0xdf, 0x3b, 0x03, 0x51, 0xc9, 0x3b, 0xf8, 0x18, 0xc1, 0x3b, 0x70, 0xe5, 0x20, + 0x3c, 0x96, 0xfb, 0xf6, 0x3b, 0x78, 0x83, 0xf1, 0x3b, 0xe9, 0x4e, 0xcd, 0x3b, + 0xd1, 0x25, 0xb4, 0x3b, 0x38, 0xa5, 0xe8, 0x3b, 0xc7, 0x84, 0x12, 0x3c, 0xbd, + 0xb1, 0x20, 0x3c, 0x2f, 0xa2, 0x35, 0x3c, 0x03, 0xee, 0x0d, 0x3c, 0x36, 0x00, + 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, + 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x64, 0x5f, 0x31, 0x31, 0x5f, 0x64, 0x65, + 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, + 0x77, 0x69, 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, + 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x7e, 0xf9, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x64, 0x06, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x28, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x0c, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0xf0, 0x76, 0x2c, 0x3b, 0x4c, 0x26, 0x1e, 0x3b, 0x2a, 0x85, 0x1d, 0x3b, + 0xa7, 0x53, 0x12, 0x3b, 0xce, 0xf3, 0x0e, 0x3b, 0x0f, 0x15, 0x04, 0x3b, 0xce, + 0x92, 0xfe, 0x3a, 0x9b, 0xe7, 0xe1, 0x3a, 0x17, 0xcf, 0x1a, 0x3b, 0xeb, 0x2f, + 0x31, 0x3b, 0x15, 0xe1, 0x66, 0x3b, 0x5a, 0x04, 0x38, 0x3b, 0xd1, 0x2f, 0x19, + 0x3b, 0xb2, 0xf8, 0x1b, 0x3b, 0x63, 0x78, 0x0e, 0x3b, 0x80, 0x63, 0x41, 0x3b, + 0x7e, 0x98, 0x3d, 0x3b, 0xeb, 0x0f, 0x13, 0x3b, 0x31, 0x60, 0x2d, 0x3b, 0xe1, + 0x7f, 0x34, 0x3b, 0x89, 0xa6, 0x2d, 0x3b, 0x18, 0x1e, 0x57, 0x3b, 0x35, 0xcc, + 0x1c, 0x3b, 0x16, 0x67, 0x29, 0x3b, 0xa7, 0x7d, 0x26, 0x3b, 0x3a, 0xee, 0x22, + 0x3b, 0x08, 0x08, 0x62, 0x3b, 0x04, 0xbd, 0x19, 0x3b, 0x44, 0x97, 0x40, 0x3b, + 0x27, 0xea, 0x26, 0x3b, 0x6a, 0xdd, 0x0d, 0x3b, 0xe4, 0x56, 0xfb, 0x3a, 0x4a, + 0x5a, 0x1f, 0x3b, 0x5a, 0x92, 0xff, 0x3a, 0x1c, 0x45, 0x32, 0x3b, 0x3e, 0x91, + 0x28, 0x3b, 0x93, 0x74, 0x5c, 0x3b, 0x1c, 0x54, 0x27, 0x3b, 0xd9, 0xb5, 0x1f, + 0x3b, 0x85, 0x55, 0x18, 0x3b, 0x6f, 0x0e, 0x2f, 0x3b, 0xae, 0x7f, 0x16, 0x3b, + 0x6e, 0x3d, 0x1c, 0x3b, 0xfc, 0x0d, 0xf7, 0x3a, 0x82, 0x18, 0x1b, 0x3b, 0xc5, + 0x09, 0x03, 0x3b, 0xaf, 0xb4, 0x15, 0x3b, 0xa9, 0xee, 0x46, 0x3b, 0x65, 0x6d, + 0x14, 0x3b, 0x29, 0x75, 0x51, 0x3b, 0x0b, 0xf8, 0x1c, 0x3b, 0x61, 0xcd, 0x5c, + 0x3b, 0x05, 0x33, 0x2a, 0x3b, 0xb7, 0x1c, 0x07, 0x3b, 0x26, 0x72, 0x34, 0x3b, + 0x59, 0xe7, 0x3f, 0x3b, 0xd6, 0xe8, 0x21, 0x3b, 0x8a, 0x3a, 0x3d, 0x3b, 0xbe, + 0xf2, 0x1b, 0x3b, 0x76, 0xb4, 0x06, 0x3b, 0xea, 0x1b, 0xfa, 0x3a, 0xeb, 0x0f, + 0xf7, 0x3a, 0x2a, 0x56, 0x2b, 0x3b, 0xca, 0xc0, 0x20, 0x3b, 0x15, 0x3c, 0x45, + 0x3b, 0x98, 0xbe, 0x1d, 0x3b, 0x8c, 0x8d, 0x20, 0x3b, 0xe2, 0x44, 0x58, 0x3b, + 0x05, 0x3b, 0x68, 0x3b, 0x9f, 0xf7, 0x8a, 0x3b, 0xe2, 0xf0, 0xfd, 0x3a, 0x2b, + 0xef, 0xfa, 0x3a, 0x8e, 0xa7, 0x1d, 0x3b, 0xe6, 0xc2, 0xea, 0x3a, 0xf1, 0x17, + 0x30, 0x3b, 0x55, 0x96, 0x1d, 0x3b, 0xf4, 0xfe, 0x07, 0x3b, 0x39, 0xb3, 0xed, + 0x3a, 0x2b, 0x40, 0xfe, 0x3a, 0x84, 0xa2, 0x18, 0x3b, 0xfc, 0x29, 0x22, 0x3b, + 0xc9, 0xae, 0x11, 0x3b, 0xa5, 0x0e, 0x2b, 0x3b, 0x2b, 0x0c, 0x07, 0x3b, 0xf0, + 0x3a, 0x49, 0x3b, 0xdc, 0x3e, 0x47, 0x3b, 0x35, 0x81, 0x1b, 0x3b, 0x9d, 0x0c, + 0xf2, 0x3a, 0x95, 0xae, 0x1b, 0x3b, 0xe2, 0x10, 0x18, 0x3b, 0x85, 0x68, 0x1d, + 0x3b, 0x74, 0x46, 0x52, 0x3b, 0x99, 0xbb, 0x3a, 0x3b, 0x28, 0xf7, 0x44, 0x3b, + 0xb7, 0xfe, 0x5c, 0x3b, 0x21, 0x04, 0x2f, 0x3b, 0x3b, 0x3b, 0x38, 0x3b, 0x92, + 0x09, 0x22, 0x3b, 0xbd, 0xa0, 0x08, 0x3b, 0x60, 0xda, 0x01, 0x3b, 0xcd, 0xce, + 0xe3, 0x3a, 0x59, 0x24, 0x36, 0x3b, 0x0a, 0x66, 0xff, 0x3a, 0xd4, 0x6e, 0x07, + 0x3b, 0xb9, 0x61, 0x17, 0x3b, 0x38, 0xf5, 0x24, 0x3b, 0xd1, 0x3e, 0x4a, 0x3b, + 0x77, 0x2d, 0x19, 0x3b, 0x59, 0x7f, 0x1b, 0x3b, 0xb8, 0x29, 0x0a, 0x3b, 0xfb, + 0xa8, 0x0c, 0x3b, 0xdb, 0xa3, 0x16, 0x3b, 0x33, 0x17, 0x30, 0x3b, 0x9c, 0x16, + 0x51, 0x3b, 0x91, 0x1b, 0x3c, 0x3b, 0x5c, 0xfc, 0x2a, 0x3b, 0x81, 0xb1, 0x0d, + 0x3b, 0x9e, 0x42, 0x20, 0x3b, 0x2e, 0x0d, 0x12, 0x3b, 0xe0, 0x98, 0x13, 0x3b, + 0x8e, 0x42, 0x24, 0x3b, 0x31, 0x04, 0x16, 0x3b, 0x10, 0x6b, 0x0c, 0x3b, 0xb9, + 0xad, 0x14, 0x3b, 0x57, 0x5e, 0x0b, 0x3b, 0x52, 0x65, 0x4b, 0x3b, 0x2f, 0xf2, + 0x17, 0x3b, 0x61, 0x9a, 0x1a, 0x3b, 0x2c, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, + 0x69, 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, + 0x32, 0x64, 0x5f, 0x31, 0x30, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x77, 0x69, + 0x73, 0x65, 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, + 0x61, 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x10, + 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x68, 0x06, + 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x24, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x6a, 0xf9, 0xff, 0xff, 0x14, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xcb, 0x37, 0xb8, 0x3b, 0x43, 0xf6, 0xc2, 0x3b, 0x44, 0xf2, 0xe8, 0x3b, 0x8f, + 0xc2, 0xca, 0x3b, 0xc4, 0x3c, 0xd0, 0x3b, 0xce, 0x26, 0xf3, 0x3b, 0x85, 0x6f, + 0xb5, 0x3b, 0xa4, 0x85, 0xd8, 0x3b, 0xa7, 0x2b, 0xd0, 0x3b, 0x9e, 0x75, 0xa0, + 0x3b, 0x9c, 0xc0, 0xdb, 0x3b, 0x19, 0x83, 0x07, 0x3c, 0x97, 0x4e, 0xeb, 0x3b, + 0xa3, 0x3c, 0x05, 0x3c, 0x22, 0x33, 0x26, 0x3c, 0x87, 0xb0, 0x8e, 0x3b, 0x61, + 0x69, 0x09, 0x3c, 0x2e, 0x3d, 0xfd, 0x3b, 0xe0, 0x36, 0xad, 0x3b, 0x20, 0x8e, + 0xa4, 0x3b, 0x5d, 0x17, 0x01, 0x3c, 0x10, 0x48, 0xc9, 0x3b, 0x1f, 0x7e, 0x6e, + 0x3b, 0x3c, 0x72, 0xde, 0x3b, 0xb7, 0xfc, 0x1e, 0x3c, 0x5b, 0x4d, 0x91, 0x3b, + 0xc7, 0x0b, 0xb9, 0x3b, 0x3f, 0x6b, 0xb1, 0x3b, 0x11, 0x9e, 0xe3, 0x3b, 0x5c, + 0xec, 0x22, 0x3c, 0xae, 0x0f, 0xe5, 0x3b, 0xcc, 0xe8, 0x71, 0x3b, 0x80, 0x02, + 0x04, 0x3c, 0xe1, 0xfd, 0x00, 0x3c, 0x34, 0xb5, 0xc4, 0x3b, 0x8c, 0xb7, 0x3a, + 0x3c, 0xde, 0xe4, 0xaa, 0x3b, 0x3e, 0xfa, 0xf0, 0x3b, 0x4f, 0x3f, 0x0c, 0x3c, + 0xa8, 0xb8, 0xa7, 0x3b, 0xb1, 0xb7, 0xe1, 0x3b, 0x81, 0x09, 0x94, 0x3b, 0xc6, + 0xde, 0x10, 0x3c, 0x2f, 0xbe, 0x2c, 0x3c, 0xfe, 0x65, 0x01, 0x3c, 0x49, 0x9a, + 0x8a, 0x3b, 0x3d, 0x56, 0xd7, 0x3b, 0x21, 0x5e, 0xc4, 0x3b, 0x61, 0x7d, 0x0d, + 0x3c, 0xf9, 0x5a, 0x89, 0x3b, 0x69, 0xb0, 0xe0, 0x3b, 0x8f, 0xa5, 0xf7, 0x3b, + 0x76, 0x26, 0x03, 0x3c, 0xcb, 0x44, 0xe1, 0x3b, 0x28, 0x7a, 0x8d, 0x3b, 0xe5, + 0x1a, 0xea, 0x3b, 0x64, 0xdd, 0x9c, 0x3b, 0x57, 0xb5, 0x70, 0x3b, 0x22, 0xee, + 0xed, 0x3b, 0xa3, 0x21, 0x7c, 0x3b, 0xaf, 0x49, 0x8a, 0x3b, 0x56, 0x4a, 0xdc, + 0x3b, 0x23, 0xe9, 0x43, 0x3c, 0x2c, 0x58, 0xcb, 0x3b, 0x12, 0xe8, 0x9f, 0x3b, + 0xd0, 0xd2, 0xf4, 0x3b, 0x96, 0x9d, 0x9f, 0x3b, 0x48, 0x20, 0xea, 0x3b, 0x63, + 0x63, 0x0f, 0x3c, 0xd0, 0x99, 0xd0, 0x3b, 0x70, 0xd2, 0xd6, 0x3b, 0x67, 0xb5, + 0x13, 0x3c, 0x79, 0x9d, 0xab, 0x3b, 0x5b, 0x4d, 0x73, 0x3b, 0x2e, 0x3a, 0x9d, + 0x3b, 0x6a, 0x9c, 0xc9, 0x3b, 0x44, 0xff, 0x8b, 0x3b, 0x13, 0xae, 0xae, 0x3b, + 0x28, 0x06, 0x86, 0x3b, 0x05, 0x59, 0xae, 0x3b, 0x95, 0x1e, 0xd4, 0x3b, 0x4a, + 0x6e, 0xa7, 0x3b, 0xc9, 0x7a, 0x15, 0x3c, 0xcb, 0x63, 0xbe, 0x3b, 0x82, 0x8a, + 0x6f, 0x3b, 0x86, 0x3f, 0xd7, 0x3b, 0xfb, 0xba, 0x15, 0x3c, 0x8f, 0xb8, 0x1c, + 0x3c, 0xa9, 0xf4, 0xea, 0x3b, 0xe2, 0x65, 0x38, 0x3c, 0x8b, 0x4a, 0xd3, 0x3b, + 0xb7, 0xae, 0xdf, 0x3b, 0xbb, 0x74, 0xff, 0x3b, 0x0c, 0x0d, 0x92, 0x3b, 0x2e, + 0x0c, 0x55, 0x3c, 0xb5, 0xf6, 0xff, 0x3b, 0xa5, 0x05, 0x2f, 0x3c, 0x95, 0xbe, + 0xbd, 0x3b, 0xc3, 0x7b, 0x9e, 0x3b, 0xe2, 0xce, 0xda, 0x3b, 0xe9, 0xfd, 0xbf, + 0x3b, 0x57, 0x1c, 0x9b, 0x3b, 0xf2, 0x1f, 0x62, 0x3b, 0x8b, 0x89, 0xf3, 0x3b, + 0x83, 0xb6, 0x8a, 0x3b, 0x4c, 0x0f, 0xd6, 0x3b, 0x98, 0xc6, 0x00, 0x3c, 0x81, + 0xd3, 0x10, 0x3c, 0xe8, 0x22, 0x3b, 0x3c, 0x0e, 0xfa, 0x19, 0x3c, 0x64, 0x7e, + 0xe6, 0x3b, 0x12, 0x99, 0xce, 0x3b, 0x20, 0x57, 0x99, 0x3b, 0x51, 0xa6, 0xe1, + 0x3b, 0x5f, 0x8d, 0xb7, 0x3b, 0xce, 0xfc, 0x86, 0x3b, 0x17, 0x3d, 0xdf, 0x3b, + 0xd1, 0x68, 0xf0, 0x3b, 0x20, 0x38, 0xd5, 0x3b, 0x13, 0x4e, 0xa1, 0x3b, 0x6d, + 0x6f, 0x79, 0x3b, 0x4f, 0xf4, 0xc3, 0x3b, 0xbd, 0x9f, 0x00, 0x3c, 0x0f, 0xa4, + 0xf4, 0x3b, 0x6a, 0x1f, 0x13, 0x3c, 0xbb, 0x81, 0x83, 0x3b, 0xaf, 0xc6, 0xf5, + 0x3b, 0x5c, 0xa1, 0xf7, 0x3b, 0x36, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, + 0x64, 0x5f, 0x31, 0x30, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, + 0x65, 0x2f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x77, 0x69, 0x73, 0x65, 0x5f, 0x77, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x1a, 0x00, + 0x08, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x09, 0xc4, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x94, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x12, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x03, 0x86, 0x3c, 0x60, 0xfe, 0xd9, 0x3c, 0xcc, 0x1c, 0x47, 0x3b, 0xda, 0xcf, + 0x55, 0x3b, 0xa8, 0x02, 0x3d, 0x3c, 0x15, 0x1e, 0x19, 0x3d, 0xbb, 0x9a, 0x94, + 0x3c, 0x90, 0x5f, 0x8e, 0x3a, 0x21, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x6e, 0x65, 0x74, 0x56, 0x31, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, + 0x64, 0x5f, 0x30, 0x2f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2f, 0x72, + 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd6, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x19, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, + 0xf2, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x0c, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, +}; +const int g_person_detect_model_data_len = 300568; diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detect_model_data.h b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detect_model_data.h new file mode 100644 index 000000000..86471b304 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detect_model_data.h @@ -0,0 +1,27 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This is a standard TensorFlow Lite model file that has been converted into a +// C data array, so it can be easily compiled into a binary for devices that +// don't have a file system. It was created using the command: +// xxd -i person_detect.tflite > person_detect_model_data.cc + +#ifndef TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_PERSON_DETECT_MODEL_DATA_H_ +#define TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_PERSON_DETECT_MODEL_DATA_H_ + +extern const unsigned char g_person_detect_model_data[]; +extern const int g_person_detect_model_data_len; + +#endif // TENSORFLOW_LITE_MICRO_EXAMPLES_PERSON_DETECTION_PERSON_DETECT_MODEL_DATA_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detection.ino b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detection.ino new file mode 100644 index 000000000..caefcf71c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/examples/person_detection/person_detection.ino @@ -0,0 +1,132 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "detection_responder.h" +#include "image_provider.h" +#include "main_functions.h" +#include "model_settings.h" +#include "person_detect_model_data.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_interpreter.h" +#include "tensorflow/lite/micro/micro_mutable_op_resolver.h" +#include "tensorflow/lite/micro/system_setup.h" +#include "tensorflow/lite/schema/schema_generated.h" + +// Globals, used for compatibility with Arduino-style sketches. +namespace { +tflite::ErrorReporter* error_reporter = nullptr; +const tflite::Model* model = nullptr; +tflite::MicroInterpreter* interpreter = nullptr; +TfLiteTensor* input = nullptr; + +// In order to use optimized tensorflow lite kernels, a signed int8_t quantized +// model is preferred over the legacy unsigned model format. This means that +// throughout this project, input images must be converted from unisgned to +// signed format. The easiest and quickest way to convert from unsigned to +// signed 8-bit integers is to subtract 128 from the unsigned value to get a +// signed value. + +// An area of memory to use for input, output, and intermediate arrays. +constexpr int kTensorArenaSize = 136 * 1024; +static uint8_t tensor_arena[kTensorArenaSize]; +} // namespace + +// The name of this function is important for Arduino compatibility. +void setup() { + tflite::InitializeTarget(); + + // Set up logging. Google style is to avoid globals or statics because of + // lifetime uncertainty, but since this has a trivial destructor it's okay. + // NOLINTNEXTLINE(runtime-global-variables) + static tflite::MicroErrorReporter micro_error_reporter; + error_reporter = µ_error_reporter; + + // Map the model into a usable data structure. This doesn't involve any + // copying or parsing, it's a very lightweight operation. + model = tflite::GetModel(g_person_detect_model_data); + if (model->version() != TFLITE_SCHEMA_VERSION) { + TF_LITE_REPORT_ERROR(error_reporter, + "Model provided is schema version %d not equal " + "to supported version %d.", + model->version(), TFLITE_SCHEMA_VERSION); + return; + } + + // Pull in only the operation implementations we need. + // This relies on a complete list of all the ops needed by this graph. + // An easier approach is to just use the AllOpsResolver, but this will + // incur some penalty in code space for op implementations that are not + // needed by this graph. + // + // tflite::AllOpsResolver resolver; + // NOLINTNEXTLINE(runtime-global-variables) + static tflite::MicroMutableOpResolver<5> micro_op_resolver; + micro_op_resolver.AddAveragePool2D(); + micro_op_resolver.AddConv2D(); + micro_op_resolver.AddDepthwiseConv2D(); + micro_op_resolver.AddReshape(); + micro_op_resolver.AddSoftmax(); + + // Build an interpreter to run the model with. + // NOLINTNEXTLINE(runtime-global-variables) + static tflite::MicroInterpreter static_interpreter( + model, micro_op_resolver, tensor_arena, kTensorArenaSize, error_reporter); + interpreter = &static_interpreter; + + // Allocate memory from the tensor_arena for the model's tensors. + TfLiteStatus allocate_status = interpreter->AllocateTensors(); + if (allocate_status != kTfLiteOk) { + TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed"); + return; + } + + // Get information about the memory area to use for the model's input. + input = interpreter->input(0); + + if ((input->dims->size != 4) || (input->dims->data[0] != 1) || + (input->dims->data[1] != kNumRows) || + (input->dims->data[2] != kNumCols) || + (input->dims->data[3] != kNumChannels) || (input->type != kTfLiteInt8)) { + TF_LITE_REPORT_ERROR(error_reporter, + "Bad input tensor parameters in model"); + return; + } +} + +// The name of this function is important for Arduino compatibility. +void loop() { + // Get image from provider. + if (kTfLiteOk != GetImage(error_reporter, input)) { + TF_LITE_REPORT_ERROR(error_reporter, "Image capture failed."); + } + + // Run the model on this input and make sure it succeeds. + if (kTfLiteOk != interpreter->Invoke()) { + TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed."); + } + + TfLiteTensor* output = interpreter->output(0); + + // Process the inference results. + int8_t person_score = output->data.uint8[kPersonIndex]; + int8_t no_person_score = output->data.uint8[kNotAPersonIndex]; + float person_score_f = + (person_score - output->params.zero_point) * output->params.scale; + float no_person_score_f = + (no_person_score - output->params.zero_point) * output->params.scale; + RespondToDetection(error_reporter, person_score_f, no_person_score_f); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/library.json b/lib/libesp32_ml/tf_lite_esp32/library.json new file mode 100644 index 000000000..5c49bb378 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/library.json @@ -0,0 +1,15 @@ +{ + "name": "tf_lite_esp32", + "version": "0.0.1", + "keywords": "tensor flow", + "description": "Tensor flow lite for Arduino-ESP32", + "frameworks": "arduino", + "platforms": "espressif32", + "build": { + "libArchive": true, + "flags": [ + "-I Source/include", + "-I Source/esp-nn/include" + ] + } +} \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/library.properties b/lib/libesp32_ml/tf_lite_esp32/library.properties new file mode 100644 index 000000000..028d14440 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/library.properties @@ -0,0 +1,13 @@ +name=Arduino_TensorFlowLite for ESP32 +version=0.0.1-ALPHA +author=TensorFlow Authors +maintainer=Pete Warden +sentence=Allows you to run machine learning models locally on your device. +paragraph=This library runs TensorFlow machine learning models on microcontrollers, allowing you to build AI/ML applications powered by deep learning and neural networks. With the included examples, you can recognize speech, detect people using a camera, and recognise "magic wand" gestures using an accelerometer. +category=Data Processing +url=https://www.tensorflow.org/lite/microcontrollers/overview +ldflags= +includes=TensorFlowLite.h +precompiled=full +dot_a_linkage=false +depends=Arduino diff --git a/lib/libesp32_ml/tf_lite_esp32/src/TensorFlowLite.h b/lib/libesp32_ml/tf_lite_esp32/src/TensorFlowLite.h new file mode 100644 index 000000000..f549f5233 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/TensorFlowLite.h @@ -0,0 +1,26 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_TOOLS_MAKE_TEMPLATES_TENSORFLOWLITE_H_ +#define TENSORFLOW_LITE_MICRO_TOOLS_MAKE_TEMPLATES_TENSORFLOWLITE_H_ + +// This header is deliberately empty, and is only present because including it +// in a .ino sketch forces the Arduino toolchain to build the rest of the +// library. + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "esp-nn/include/esp_nn.h" + + +#endif // TENSORFLOW_LITE_MICRO_TOOLS_MAKE_TEMPLATES_TENSORFLOWLITE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/.gitignore b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/.gitignore new file mode 100644 index 000000000..08ca72b5b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/.gitignore @@ -0,0 +1,57 @@ +.config +*.o +*.i +*.s +*.orig +*.pyc + +# gtags +GTAGS +GRTAGS +GPATH + +# emacs +.dir-locals.el + +# emacs temp file suffixes +*~ +.#* +\#*# + +# eclipse setting +.settings + +# MacOS directory files +.DS_Store + +# Example project files +examples/**/sdkconfig +examples/**/sdkconfig.old +examples/**/build + +# Test app files +test_app/build +test_app/sdkconfig +test_app/sdkconfig.old + +# Doc build artifacts +docs/_build/ +docs/doxygen-warning-log.txt +docs/sphinx-warning-log.txt +docs/sphinx-warning-log-sanitized.txt +docs/xml/ +docs/xml_in/ +docs/man/ +docs/doxygen_sqlite3.db + +TEST_LOGS + + +# gcov coverage reports +*.gcda +*.gcno +coverage.info +coverage_report/ + +# VS Code Settings +.vscode/ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/.gitlab-ci.yml b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/.gitlab-ci.yml new file mode 100644 index 000000000..6b540bda8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/.gitlab-ci.yml @@ -0,0 +1,55 @@ +stages: + - build + +variables: + BATCH_BUILD: "1" + V: "0" + MAKEFLAGS: "-j8 --no-keep-going" + IDF_PATH: "$CI_PROJECT_DIR/esp-idf" + LOG_PATH: "$CI_PROJECT_DIR" + +.set_git_config: &set_git_config + # Set git config + - git config user.email "test@espressif.com" + - git config user.name "Espressif" + +.add_ssh_key: &add_ssh_key + # Add gitlab ssh key + - mkdir -p ~/.ssh + - chmod 700 ~/.ssh + - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64 + - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa + - chmod 600 ~/.ssh/id_rsa + - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config + +before_script: + # Add gitlab ssh key + - *add_ssh_key + # Set git config + - *set_git_config + +.build_esp32s3: &build_esp32s3 + - idf.py set-target esp32s3 build + +.build_esp32: &build_esp32 + - idf.py set-target esp32 build + +build_demo: + stage: build + image: $CI_DOCKER_REGISTRY/esp32-ci-env:esp-nn + tags: + - build + script: + # Clone IDF + - git clone --recursive --single-branch -b release/v4.4 --reference-if-able /local_references/gitlab/ https://gitlab-ci-token:${BOT_TOKEN}@gitlab.espressif.cn:6688/espressif/esp-idf.git + - cd esp-idf + - ./install.sh + - . ./export.sh + - cd .. + # Build examples now + - cd test_app + # Build esp32s3 + - *build_esp32s3 + # Build esp32 + - *build_esp32 + - cd - diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/LICENSE b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/README.md b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/README.md new file mode 100644 index 000000000..f70f40747 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/README.md @@ -0,0 +1,55 @@ +# ESP-NN + +The library contains optimised NN (Neural Network) functions for various Espressif chipsets. + +* Supported platforms: + * TensorFlow Lite Micro (TFLite Micro). Repo can be found [here](https://github.com/espressif/tflite-micro-esp-examples) + +* Supported ESP chipsets include: + * ESP32-S3 (Assembly versions optimised to benefit from vector instructions of ESP32-S3) + * ESP32 (Generic optimisations) + * ESP32-C3 (Generic optimisations) + +## Performance + +### Kernelwise performance for s8 versions: + + * Kernelwise performance on ESP32-S3 chip + * Numbers are ticks taken for kernel to execute + * Chip config: 240MHz, SPI: QPI 80MHz, Data cache: 64KB + + | Function | ANSI C | ESP32-S3 Opt | Opt Ratio | Data info | Memory | + | ----------------| --------|---------|---------|-------------|-----------| + | elementwise_add | 320397 | 87119 | 3.68 | size = 1615 | External | + | elementwise_mul | 125958 | 44239 | 2.85 | size = 1615 | External | + | convolution | 4663012 | 428675 | 10.88 | input(10,10), filter(64x1x1x64) | External | + | convolution | 301014 | 32433 | 9.28 | input(8,8), filter(16x1x1x16) | External | + | convolution | 2115418 | 1020923 | 2.07 | input(10,10), filter(64x3x3x3) | External | + | depthwise conv | 1190062 | 203278 | 5.85 | input (18, 18), pad(0,0), stride(1,1) filter: 1x3x3x16 | External | + | depthwise conv | 837072 | 182335 | 4.59 | input (12, 12), pad(1,1), stride(1,1) filter: 8x5x5x4 | External | + | max pool | 485714 | 76747 | 6.33 | input(16,16), filter (1x3x3x16) | Internal | + | avg pool | 541462 | 160580 | 3.37 | input(16,16), filter (1x3x3x16) | Internal | + | fully connected | 15853 | 9547 | 1.66 | len: 265, ch = 3 | Internal | + | prelu (relu6) | 19472 | 2734 | 7.12 | size, 1615 | Internal | + + +## Configuration + + * To configure, please use `idf.py menuconfig` and under `ESP-NN` select `NN_OPTIMIZATIONS` + * There are two options presented: + * Optimized versions + * ANSI C + + * Default selection is for `Optimized versions`. For ESP32-S3, assembly versions are automatically selected, whereas for other chipsets (viz., ESP32, ESP32-C3), generic optimisations are selected. + * For debugging purposes, you may want to select `ANSI C` reference versions. + + +## Contributing + +If you encounter an issue with ESP-NN, or wish to submit a feature request, please use the Issues section on the Github. + +For general questions related to this library, please use the esp32.com forum. + +## Copyrights and License + +All original source code in this repository is Copyright (C) 2020-2021 Espressif Systems. This source code is licensed under the Apache License 2.0 as described in the file LICENSE. diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn.h b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn.h new file mode 100644 index 000000000..bd5331194 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn.h @@ -0,0 +1,46 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#if defined(CONFIG_NN_OPTIMIZED) +// select apt optimisations +#ifdef CONFIG_IDF_TARGET_ESP32S3 +#define ARCH_ESP32_S3 1 +#endif +#ifdef CONFIG_IDF_TARGET_ESP32 +#define ARCH_ESP32 1 +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* reference kernels included by default */ +#include "esp_nn_ansi_headers.h" + +#if defined(CONFIG_NN_OPTIMIZED) +#if defined(ARCH_ESP32_S3) +#include "esp_nn_esp32s3.h" +#else // for other platforms use generic optimisations +#include "esp_nn_generic_opt.h" +#endif // #if defined(ARCH_ESP32_S3) +#else +#include "esp_nn_ansi_c.h" +#endif + +#ifdef __cplusplus +} +#endif diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_ansi_c.h b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_ansi_c.h new file mode 100644 index 000000000..8279ebef3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_ansi_c.h @@ -0,0 +1,47 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file Header definitions to include for ANSI C versions. + * These are just typedefs to pick up ANSI versions. + */ + +#pragma once + +#include "esp_nn_defs.h" +#include "esp_nn_ansi_headers.h" + +#define esp_nn_add_elementwise_s8 esp_nn_add_elementwise_s8_ansi +#define esp_nn_mul_elementwise_s8 esp_nn_mul_elementwise_s8_ansi + +#define esp_nn_depthwise_conv_s8 esp_nn_depthwise_conv_s8_ansi + +#define esp_nn_conv_s8 esp_nn_conv_s8_ansi + +#define esp_nn_get_conv_scratch_size esp_nn_get_conv_scratch_size_ansi +#define esp_nn_set_conv_scratch_buf esp_nn_set_conv_scratch_buf_ansi + +#define esp_nn_get_depthwise_conv_scratch_size esp_nn_get_depthwise_conv_scratch_size_ansi +#define esp_nn_set_depthwise_conv_scratch_buf esp_nn_set_depthwise_conv_scratch_buf_ansi + +#define esp_nn_relu6_s8 esp_nn_relu6_s8_ansi + +#define esp_nn_avg_pool_s8 esp_nn_avg_pool_s8_ansi +#define esp_nn_max_pool_s8 esp_nn_max_pool_s8_ansi + +#define esp_nn_fully_connected_s8 esp_nn_fully_connected_s8_ansi + +#define esp_nn_get_softmax_scratch_size esp_nn_get_softmax_scratch_size_ansi +#define esp_nn_set_softmax_scratch_buf esp_nn_set_softmax_scratch_buf_ansi +#define esp_nn_softmax_s8 esp_nn_softmax_s8_ansi diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_ansi_headers.h b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_ansi_headers.h new file mode 100644 index 000000000..52ebb6800 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_ansi_headers.h @@ -0,0 +1,309 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * @file Header definitions to include for esp_nn reference functions + */ + +#include "esp_nn_defs.h" +/************************** Basic math functions ****************************/ + +/** + * @brief elementwise addition + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + * + * shift values are expected to be <= 0 + */ +void esp_nn_add_elementwise_s8_ansi(const int8_t *input1_data, + const int8_t *input2_data, + const int32_t input1_offset, + const int32_t input2_offset, + const int32_t input1_mult, + const int32_t input2_mult, + const int32_t input1_shift, + const int32_t input2_shift, + const int32_t left_shift, + int8_t *output, + const int32_t out_offset, + const int32_t out_mult, + const int32_t out_shift, + const int32_t activation_min, + const int32_t activation_max, + const int32_t size); +/** + * @brief elementwise multiplication + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + * + * output shift is expected to be <= 0 + */ +void esp_nn_mul_elementwise_s8_ansi(const int8_t *input1_data, + const int8_t *input2_data, + const int32_t input1_offset, + const int32_t input2_offset, + int8_t *output, + const int32_t out_offset, + const int32_t out_mult, + const int32_t out_shift, + const int32_t activation_min, + const int32_t activation_max, + const int32_t size); + + +/************************** Convolution functions *****************************/ + +/** + * @brief depthwise convolution per channel + * + * @note inputs type: int8_t, output: int8_t + * Version used in tflite is per channel. + * This version follows the same footsprints. + * Meaning, it has per out_channel shift and multiplier for + * requantization + * + * optimization notes: Though input_offset is int32 type, + * offset values are contained in 8 bits [-128, 127] + */ +void esp_nn_depthwise_conv_s8_ansi(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const dw_conv_params_t *conv_params, + const quant_data_t *quant_data); + +/** + * @brief 2d-convolution channelwise + * + * @note operation: result += (input + offset) * filter + * + * inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + */ +void esp_nn_conv_s8_ansi(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const conv_params_t *conv_params, + const quant_data_t *quant_data); + +int esp_nn_get_conv_scratch_size_ansi(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const conv_params_t *conv_params); +void esp_nn_set_conv_scratch_buf_ansi(const void *buf); + +int esp_nn_get_depthwise_conv_scratch_size_ansi(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const dw_conv_params_t *conv_params); +void esp_nn_set_depthwise_conv_scratch_buf_ansi(const void *buf); + +/************************** Activation functions *****************************/ + +/** + * @brief relu6 + * + * @note inout: int8_t + */ +void esp_nn_relu6_s8_ansi(int8_t *data, uint16_t size); + +/************************** Pooling functions *****************************/ + + +/** + * @brief max_pool + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + */ +void esp_nn_max_pool_s8_ansi(const int8_t *input, + const uint16_t input_wd, + const uint16_t input_ht, + int8_t *output, + const uint16_t output_wd, + const uint16_t output_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t filter_wd, + const uint16_t filter_ht, + const uint16_t pad_wd, + const uint16_t pad_ht, + const int32_t activation_min, + const int32_t activation_max, + const uint16_t channels); + +/** + * @brief avg_pool + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + */ +void esp_nn_avg_pool_s8_ansi(const int8_t *input, + const uint16_t input_wd, + const uint16_t input_ht, + int8_t *output, + const uint16_t output_wd, + const uint16_t output_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t filter_wd, + const uint16_t filter_ht, + const uint16_t pad_wd, + const uint16_t pad_ht, + const int32_t activation_min, + const int32_t activation_max, + const uint16_t channels); + + +/************************** Fully connected functions ***********************/ + +/** + * @brief fully connected + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + */ +void esp_nn_fully_connected_s8_ansi(const int8_t *input_data, + const int32_t input_offset, + const uint16_t row_len, + const int8_t *filter_data, + const int32_t filter_offset, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t out_shift, + const int32_t out_mult, + const int32_t activation_min, + const int32_t activation_max); + +/** + * @brief Get scratch buffer size needed by softmax function + * + * @param width + * @param height + * @return size in bytes + * + * @note buffer must be 4 byte aligned + */ +int32_t esp_nn_get_softmax_scratch_size_ansi(const int32_t width, const int32_t height); + +/* ANSI C function to be hooked up when optimised version needed */ +int32_t esp_nn_get_softmax_scratch_size_opt(const int32_t width, const int32_t height); + +/** + * @brief Set scratch buffer to be used by softmax function + * + * @param buffer this can be NULL if one needs to unset it + * must be aligned to 4 bytes + */ +void esp_nn_set_softmax_scratch_buf_ansi(void *buffer); + +/** + * @brief reference softmax function + * + * @note inputs type: int8_t, output: int8_t + */ +void esp_nn_softmax_s8_ansi(const int8_t *input_data, + const int32_t height, + const int32_t width, + const int32_t mult, + const int32_t shift, + const int32_t diff_min, + int8_t *output_data); + + +//////////////////////////// Generic optimisations ///////////////////////////// + +/************************** Convolution functions *****************************/ + +/** + * @brief 2d-convolution channelwise optimized version + * + * @note operation: result += (input + offset) * filter + * + * inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + */ +void esp_nn_conv_s8_opt(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const conv_params_t *conv_params, + const quant_data_t *quant_data); + +/** + * @brief depthwise convolution per channel optimized version + * + * @note inputs type: int8_t, output: int8_t + * Version used in tflite is per channel. + * This version follows the same footsprints. + * Meaning, it has per out_channel shift and multiplier for + * requantization + * + * optimization notes: Though input_offset is int32 type, + * offset values are contained in 8 bits [-128, 127] + */ +void esp_nn_depthwise_conv_s8_opt(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const dw_conv_params_t *conv_params, + const quant_data_t *quant_data); + +int esp_nn_get_conv_scratch_size_opt(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const conv_params_t *conv_params); +void esp_nn_set_conv_scratch_buf_opt(const void *buf); + +int esp_nn_get_depthwise_conv_scratch_size_opt(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const dw_conv_params_t *conv_params); +void esp_nn_set_depthwise_conv_scratch_buf_opt(const void *buf); + +/* ANSI C function to be hooked up when optimised version needed */ +void esp_nn_set_softmax_scratch_buf_opt(void *buffer); + +/** + * @brief optimised version of softmax function + * + * @note the function uses extra buffer (4 * width bytes) + * hence, scratch buffers must be set before calling this. + */ +void esp_nn_softmax_s8_opt(const int8_t *input_data, + const int32_t height, + const int32_t width, + const int32_t mult, + const int32_t shift, + const int32_t diff_min, + int8_t *output_data); diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_defs.h b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_defs.h new file mode 100644 index 000000000..756d8e6fb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_defs.h @@ -0,0 +1,83 @@ +// Copyright 2022 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +/** + * @brief structure to club data dims + * this structure can be used for input, output and filter + */ +typedef struct data_dims { + int32_t width; + int32_t height; + int32_t channels; + + int32_t extra; // can be used as batch or any other param +} data_dims_t; + +/** + * @brief 2d data structure (width, height) + * + */ +typedef struct data_2d { + int32_t width; + int32_t height; +} data_2d_t; + +/** + * @brief min/max activation + */ +typedef struct act_params { + int32_t min; + int32_t max; +} act_params_t; + +/** + * @brief per channel quant data + * + * @note number of shift and mult elements are equal to output channels + */ +typedef struct quant_data { + int32_t *shift; + int32_t *mult; +} quant_data_t; + +/** + * @brief params specific to convolution 2d + * + */ +typedef struct conv_params { + int32_t in_offset; + int32_t out_offset; + data_2d_t stride; + data_2d_t padding; + data_2d_t dilation; + act_params_t activation; +} conv_params_t; + +/** + * @brief params specific to depthwise convolution 2d + * + */ +typedef struct dw_conv_params { + int32_t in_offset; + int32_t out_offset; + int32_t ch_mult; // channel multiplier. (in_ch * ch_mult = out_ch) + data_2d_t stride; + data_2d_t padding; + data_2d_t dilation; + act_params_t activation; +} dw_conv_params_t; diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_esp32s3.h b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_esp32s3.h new file mode 100644 index 000000000..9f7664549 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_esp32s3.h @@ -0,0 +1,233 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file Header definitions to include for esp_nn optimized functions for + * the ESP32-S3 platform + */ + +#pragma once +#ifdef CONFIG_IDF_TARGET_ESP32S3 +#include "esp_nn_defs.h" +#include "esp_nn_ansi_headers.h" + +/************************** Basic math functions *****************************/ + + +/** + * @brief elementwise addition + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + * + * shift values are expected to be <= 0 + */ +void esp_nn_add_elementwise_s8_esp32s3(const int8_t *input1_data, + const int8_t *input2_data, + const int32_t input1_offset, + const int32_t input2_offset, + const int32_t input1_mult, + const int32_t input2_mult, + const int32_t input1_shift, + const int32_t input2_shift, + const int32_t left_shift, + int8_t *output, + const int32_t out_offset, + const int32_t out_mult, + const int32_t out_shift, + const int32_t activation_min, + const int32_t activation_max, + const int32_t size); + +/** + * @brief elementwise multiplication + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + * + * output shift is expected to be <= 0 + */ +void esp_nn_mul_elementwise_s8_esp32s3(const int8_t *input1_data, + const int8_t *input2_data, + const int32_t input1_offset, + const int32_t input2_offset, + int8_t *output, + const int32_t out_offset, + const int32_t out_mult, + const int32_t out_shift, + const int32_t activation_min, + const int32_t activation_max, + const int32_t size); + + +/************************** Convolution functions *****************************/ + +/** + * @brief depthwise convolution per channel + * + * @note inputs type: int8_t, output: int8_t + * Version used in tflite is per channel. + * This version follows the same footsprints. + * Meaning, it has per out_channel shift and multiplier for + * requantization + * + * optimization notes: Though input_offset is int32 type, + * offset values are contained in 8 bits [-128, 127] + */ +void esp_nn_depthwise_conv_s8_esp32s3(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *output_data, + const dw_conv_params_t *conv_params, + const quant_data_t *quant_data); + +/** + * @brief 2d - convolution channelwise + * + * @note operation: result += (input + offset) * filter + * + * inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + */ +void esp_nn_conv_s8_esp32s3(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *output_data, + const conv_params_t *conv_params, + const quant_data_t *quant_data); + +int esp_nn_get_conv_scratch_size_esp32s3(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const conv_params_t *conv_params); +void esp_nn_set_conv_scratch_buf_esp32s3(const void *buf); + +int esp_nn_get_depthwise_conv_scratch_size_esp32s3(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const dw_conv_params_t *conv_params); +void esp_nn_set_depthwise_conv_scratch_buf_esp32s3(const void *buf); + +/************************** Pooling functions *****************************/ + +/** + * @brief max_pool + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + */ +void esp_nn_max_pool_s8_esp32s3(const int8_t *input, + const uint16_t input_wd, + const uint16_t input_ht, + int8_t *output, + const uint16_t output_wd, + const uint16_t output_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t filter_wd, + const uint16_t filter_ht, + const uint16_t pad_wd, + const uint16_t pad_ht, + const int32_t activation_min, + const int32_t activation_max, + const uint16_t channels); + +/** + * @brief avg_pool + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + */ +void esp_nn_avg_pool_s8_esp32s3(const int8_t *input, + const uint16_t input_wd, + const uint16_t input_ht, + int8_t *output, + const uint16_t output_wd, + const uint16_t output_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t filter_wd, + const uint16_t filter_ht, + const uint16_t pad_wd, + const uint16_t pad_ht, + const int32_t activation_min, + const int32_t activation_max, + const uint16_t channels); + + +/************************** Fully connected functions *****************************/ + +/** + * @brief fully connected + * + * @note inputs type: int8_t, output: int8_t + * input offsets: although int32_t, they are contained in 8 bits [-128, 127] + * + * Current version works only on aligned input. + * row_len and channels should both be multiple of 8. + */ +void esp_nn_fully_connected_s8_esp32s3(const int8_t *input_data, + const int32_t input_offset, + const uint16_t row_len, + const int8_t *filter_data, + const int32_t filter_offset, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t out_shift, + const int32_t out_mult, + const int32_t activation_min, + const int32_t activation_max); + +/** + * @brief relu6 + * + * @note inout: int8_t + */ +void esp_nn_relu6_s8_esp32s3(int8_t *data, uint16_t size); + +/********************** function defines ***************************/ + +#define esp_nn_add_elementwise_s8 esp_nn_add_elementwise_s8_esp32s3 +#define esp_nn_mul_elementwise_s8 esp_nn_mul_elementwise_s8_esp32s3 + +#define esp_nn_depthwise_conv_s8 esp_nn_depthwise_conv_s8_esp32s3 + +#define esp_nn_get_conv_scratch_size esp_nn_get_conv_scratch_size_esp32s3 +#define esp_nn_set_conv_scratch_buf esp_nn_set_conv_scratch_buf_esp32s3 + +#define esp_nn_get_depthwise_conv_scratch_size esp_nn_get_depthwise_conv_scratch_size_esp32s3 +#define esp_nn_set_depthwise_conv_scratch_buf esp_nn_set_depthwise_conv_scratch_buf_esp32s3 + +#define esp_nn_conv_s8 esp_nn_conv_s8_esp32s3 + +#define esp_nn_relu6_s8 esp_nn_relu6_s8_esp32s3 + +#define esp_nn_avg_pool_s8 esp_nn_avg_pool_s8_esp32s3 +#define esp_nn_max_pool_s8 esp_nn_max_pool_s8_esp32s3 + +#define esp_nn_fully_connected_s8 esp_nn_fully_connected_s8_esp32s3 + +#define esp_nn_get_softmax_scratch_size esp_nn_get_softmax_scratch_size_opt +#define esp_nn_set_softmax_scratch_buf esp_nn_set_softmax_scratch_buf_opt +#define esp_nn_softmax_s8 esp_nn_softmax_s8_opt + +#endif // CONFIG_IDF_TARGET_ESP32S3 \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_generic_opt.h b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_generic_opt.h new file mode 100644 index 000000000..136cba5de --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/include/esp_nn_generic_opt.h @@ -0,0 +1,47 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file Header definitions to include for esp_nn generic optimisations + * For functions which not having optimisations, _ansi versions are picked. + */ + +#pragma once + +#include "esp_nn_defs.h" +#include "esp_nn_ansi_headers.h" + +#define esp_nn_add_elementwise_s8 esp_nn_add_elementwise_s8_ansi +#define esp_nn_mul_elementwise_s8 esp_nn_mul_elementwise_s8_ansi + +#define esp_nn_depthwise_conv_s8 esp_nn_depthwise_conv_s8_opt + +#define esp_nn_conv_s8 esp_nn_conv_s8_opt + +#define esp_nn_get_conv_scratch_size esp_nn_get_conv_scratch_size_opt +#define esp_nn_set_conv_scratch_buf esp_nn_set_conv_scratch_buf_opt + +#define esp_nn_get_depthwise_conv_scratch_size esp_nn_get_depthwise_conv_scratch_size_opt +#define esp_nn_set_depthwise_conv_scratch_buf esp_nn_set_depthwise_conv_scratch_buf_opt + +#define esp_nn_relu6_s8 esp_nn_relu6_s8_ansi + +#define esp_nn_avg_pool_s8 esp_nn_avg_pool_s8_ansi +#define esp_nn_max_pool_s8 esp_nn_max_pool_s8_ansi + +#define esp_nn_fully_connected_s8 esp_nn_fully_connected_s8_ansi + +#define esp_nn_get_softmax_scratch_size esp_nn_get_softmax_scratch_size_opt +#define esp_nn_set_softmax_scratch_buf esp_nn_set_softmax_scratch_buf_opt +#define esp_nn_softmax_s8 esp_nn_softmax_s8_opt diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/activation_functions/esp_nn_relu_ansi.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/activation_functions/esp_nn_relu_ansi.c new file mode 100644 index 000000000..3c83bf89b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/activation_functions/esp_nn_relu_ansi.c @@ -0,0 +1,30 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "../common/common_functions.h" + +void esp_nn_relu6_s8_ansi(int8_t *data, uint16_t size) +{ + int32_t i; + + for (i = 0; i < size; i++) { + int32_t ip = data[i]; + + ip = max(ip, 0); + data[i] = min(ip, 6); + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/basic_math/esp_nn_add_ansi.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/basic_math/esp_nn_add_ansi.c new file mode 100644 index 000000000..d7fe34e62 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/basic_math/esp_nn_add_ansi.c @@ -0,0 +1,97 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "../common/common_functions.h" + +void esp_nn_add_elementwise_u8_ansi(const uint8_t *input1_data, + const uint8_t *input2_data, + const int32_t input1_offset, + const int32_t input2_offset, + const int32_t input1_mult, + const int32_t input2_mult, + const int32_t input1_shift, + const int32_t input2_shift, + const int32_t left_shift, + uint8_t *output, + const int32_t out_offset, + const int32_t out_mult, + const int32_t out_shift, + const int32_t activation_min, + const int32_t activation_max, + const int32_t size) +{ + for (int i = 0; i < size; i++) { + int32_t tmp1 = input1_data[i] + input1_offset; + int32_t tmp2 = input2_data[i] + input2_offset; + + tmp1 <<= left_shift; + tmp2 <<= left_shift; + + tmp1 = esp_nn_sat_round_doubling_high_mul(tmp1, input1_mult); + tmp2 = esp_nn_sat_round_doubling_high_mul(tmp2, input2_mult); + + tmp1 = esp_nn_div_by_power_of_two(tmp1, -input1_shift); + tmp2 = esp_nn_div_by_power_of_two(tmp2, -input2_shift); + + int32_t out = tmp1 + tmp2; + out = esp_nn_sat_round_doubling_high_mul(out, out_mult); + out = esp_nn_div_by_power_of_two(out, -out_shift); + out = out + out_offset; + + out = max(activation_min, min(out, activation_max)); + output[i] = (uint8_t) out; + } +} + +void esp_nn_add_elementwise_s8_ansi(const int8_t *input1_data, + const int8_t *input2_data, + const int32_t input1_offset, + const int32_t input2_offset, + const int32_t input1_mult, + const int32_t input2_mult, + const int32_t input1_shift, + const int32_t input2_shift, + const int32_t left_shift, + int8_t *output, + const int32_t out_offset, + const int32_t out_mult, + const int32_t out_shift, + const int32_t activation_min, + const int32_t activation_max, + const int32_t size) +{ + for (int i = 0; i < size; i++) { + int32_t tmp1 = input1_data[i] + input1_offset; + int32_t tmp2 = input2_data[i] + input2_offset; + + tmp1 <<= left_shift; + tmp2 <<= left_shift; + + tmp1 = esp_nn_sat_round_doubling_high_mul(tmp1, input1_mult); + tmp2 = esp_nn_sat_round_doubling_high_mul(tmp2, input2_mult); + + tmp1 = esp_nn_div_by_power_of_two(tmp1, -input1_shift); + tmp2 = esp_nn_div_by_power_of_two(tmp2, -input2_shift); + + int32_t out = tmp1 + tmp2; + out = esp_nn_sat_round_doubling_high_mul(out, out_mult); + out = esp_nn_div_by_power_of_two(out, -out_shift); + out = out + out_offset; + + out = max(activation_min, min(out, activation_max)); + output[i] = (int8_t) out; + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/basic_math/esp_nn_mul_ansi.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/basic_math/esp_nn_mul_ansi.c new file mode 100644 index 000000000..c2eae5e59 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/basic_math/esp_nn_mul_ansi.c @@ -0,0 +1,42 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "../common/common_functions.h" + +void esp_nn_mul_elementwise_s8_ansi(const int8_t *input1_data, + const int8_t *input2_data, + const int32_t input1_offset, + const int32_t input2_offset, + int8_t *output, + const int32_t out_offset, + const int32_t out_mult, + const int32_t out_shift, + const int32_t activation_min, + const int32_t activation_max, + const int32_t size) +{ + for (int i = 0; i < size; i++) { + int32_t tmp1 = input1_data[i] + input1_offset; + int32_t tmp2 = input2_data[i] + input2_offset; + + int32_t out = tmp1 * tmp2; + out = esp_nn_multiply_by_quantized_mult(out, out_mult, out_shift); + out = out + out_offset; + + out = max(activation_min, min(out, activation_max)); + output[i] = (int8_t) out; + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/common/common_functions.h b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/common/common_functions.h new file mode 100644 index 000000000..0a74eca40 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/common/common_functions.h @@ -0,0 +1,255 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include + +/** + * c99 standard still doesn't strictly inline functions + * We need to use attribute as well to do this. + */ +#define __NN_FORCE_INLINE__ __attribute((always_inline)) static inline + +/* min/max macros */ +#ifndef max +#define max(a, b) ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; \ +}) + +#define min(a, b) ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; \ +}) +#endif + +__NN_FORCE_INLINE__ int32_t esp_nn_clz32(uint32_t in) +{ +#if CONFIG_IDF_TARGET_ARCH_XTENSA + __asm__ volatile("nsau %0, %0" : "+r" (in)); + return in; +#elif defined(__GNUC__) + return __builtin_clz(in); +#else + int32_t count = 32; + uint32_t x = in, y = in >> 16; + if (y != 0) { + count -= 16; + x = y; + } + y = x >> 8; + if (y != 0) { + count -= 8; + x = y; + } + y = x >> 4; + if (y != 0) { + count -= 4; + x = y; + } + y = x >> 2; + if (y != 0) { + count -= 2; + x = y; + } + y = x >> 1; + if (y != 0) { + return count - 2; + } + return count - x; +#endif +} + +/** + * Signed saturate a 32 bit value to 8 bits keeping output in 32 bit variable. + */ +__NN_FORCE_INLINE__ int32_t esp_nn_saturate8(int32_t in) +{ +#if CONFIG_IDF_TARGET_ARCH_XTENSA + __asm__ volatile("clamps %0, %0, 7" : "+a"(in)); + return in; +#else + return max(INT8_MIN, min(in, INT8_MAX)); +#endif +} + +__NN_FORCE_INLINE__ int32_t esp_nn_pick_sat_high32_of64(int64_t val64) +{ + int32_t sign = (int32_t) (val64 >> 63); + int32_t to_add = sign & ((1ul << 31) - 1); + return (int32_t) ((int64_t) (val64 + to_add) >> 31); +} + +__NN_FORCE_INLINE__ int32_t esp_nn_sat_round_doubling_high_mul(int32_t in0, int32_t in1) +{ + int32_t result; + int64_t in0_64 = (int64_t) in0; + bool overflow = (in0 == in1) && (in0 == (int32_t) INT32_MIN); + + /* Nudge value */ + int64_t nudge_val = 1 << 30; + if ((in0 < 0) ^ (in1 < 0)) { + nudge_val = 1 - nudge_val; + } + + /* Multiply and add nudge */ + int64_t mult = in0_64 * in1 + nudge_val; + + /* Round and pickup 32 bits */ + result = esp_nn_pick_sat_high32_of64(mult); + + return overflow ? INT32_MAX : result; +} + +/** + * fast version + * this will fail for values closer to INT32_MAX and INT32_MIN by `1 << (exponent - 1)`. + * We can afford to do this because we are at the very last stage of filter. + * Also it is pretty rare condition as our output is going to be 8 bit. + */ +__NN_FORCE_INLINE__ int32_t esp_nn_div_by_power_of_two_fast(int32_t val, int32_t exponent) +{ + int32_t to_add = (1 << (exponent - 1)) - (val < 0); + return (int32_t) ((val + to_add) >> exponent); +} + +__NN_FORCE_INLINE__ int32_t esp_nn_div_by_power_of_two(int32_t val, int32_t exponent) +{ + int32_t result; + + const int32_t mask = (1 << exponent) - 1; + const int32_t remainder = val & mask; + + result = val >> exponent; + int32_t threshold = (mask >> 1) + (result < 0); + + if (remainder > threshold) { + result += 1; + } + return result; +} + +__NN_FORCE_INLINE__ int32_t esp_nn_multiply_by_quantized_mult(int32_t x, int32_t mult, int32_t shift) +{ + int32_t left_shift = shift > 0 ? shift : 0; + int32_t right_shift = shift > 0 ? 0 : -shift; + int32_t result = esp_nn_sat_round_doubling_high_mul(x * (1 << left_shift), mult); + return esp_nn_div_by_power_of_two(result, right_shift); +} + +__NN_FORCE_INLINE__ int32_t esp_nn_multiply_by_quantized_mult_fast(int32_t x, int32_t mult, int32_t shift) +{ + int32_t left_shift = max(shift, 0); + int32_t right_shift = left_shift - shift; + + int64_t nudge_val = 1 << 30; + int64_t in0_64 = (int64_t) (x << left_shift); + + /* Multiply and add nudge */ + int64_t mult_64 = in0_64 * mult + nudge_val; + int32_t result = (int32_t) (mult_64 >> 31); + if (right_shift) { + result = esp_nn_div_by_power_of_two_fast(result, right_shift); + } + return result; +} + +static void esp_nn_aligned_s8_pad_with_value(const int8_t *src, int8_t *dst, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const int32_t pad_val, + const uint16_t pad_wd, + const uint16_t pad_ht) +{ + /* memset with pad_val */ + memset(dst, pad_val, ((input_wd + 2 * pad_wd) * (input_ht + 2 * pad_ht)) * channels); + dst += (pad_wd + input_wd + pad_wd) * channels; + + for (int i = 0; i < input_ht; i++) { + dst += pad_wd * channels; + for (int j = 0; j < input_wd * channels; j++) { + *dst++ = *src++; + } + dst += pad_wd * channels; + } +} + +static void esp_nn_aligned_s8_pad_end_with_value(const int8_t *src, int8_t *dst, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const int32_t pad_val, + const uint16_t pad_wd, + const uint16_t pad_ht) +{ + for (int i = 0; i < input_ht; i++) { + for (int j = 0; j < input_wd * channels; j++) { + *dst++ = *src++; + } + if (pad_wd) { + memset(dst, pad_val, pad_wd * channels); + dst += pad_wd * channels; + } + } + /* pad end `pad_ht` lines at end */ + if (pad_ht) { + memset(dst, pad_val, (input_wd + pad_wd) * pad_ht * channels); + } +} + +/** + * @brief convert 8 bit input data to 16 bit + * + * @param src int8_t source data + * @param dst int16_t dst data + * @param size length of data + * @param offset offset to be added to src data. Range: [-128, 127] + */ +__NN_FORCE_INLINE__ void esp_nn_s8_to_s16_with_offset(const int8_t *src, int16_t *dst, + const int size, const int32_t offset) +{ + int i = 0; + for (; i < size; i += 2) { + dst[i + 0] = src[i + 0] + offset; + dst[i + 1] = src[i + 1] + offset; + } + if(i < size) { + dst[i] = src[i] + offset; + } +} + +/** + * @brief convert 8 bit input data to 16 bit + * + * @param src int8_t source data + * @param dst int16_t dst data + * @param size length of data + */ +__NN_FORCE_INLINE__ void esp_nn_s8_to_s16(const int8_t *src, int16_t *dst, const int size) +{ + int i = 0; + for (; i < size; i += 2) { + dst[i + 0] = src[i + 0]; + dst[i + 1] = src[i + 1]; + } + if(i < size) { + dst[i] = src[i]; + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_ansi.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_ansi.c new file mode 100644 index 000000000..c7a415ba6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_ansi.c @@ -0,0 +1,179 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "../../include/esp_nn_defs.h" + +#include "../common/common_functions.h" + +int esp_nn_get_conv_scratch_size_ansi(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const conv_params_t *conv_params) +{ + return 0; +} + +void esp_nn_set_conv_scratch_buf_ansi(const void *buf) +{ + +} + +/** + * Assumption 1: i/p channels == o/p channels + * Assumption 2: Pointers are valid + * Assumption 3: dialation width = 1 + */ +void esp_nn_conv_u8_ansi(const uint8_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t in_channels, + const int32_t input_offset, + const uint16_t pad_wd, + const uint16_t pad_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint8_t *filter_data, + const uint16_t filter_wd, + const uint16_t filter_ht, + const int32_t filter_offset, + const int32_t *bias, + uint8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t out_shift, + const int32_t out_mult, + const int32_t activation_min, + const int32_t activation_max) +{ + for (int out_y = 0; out_y < out_ht; out_y++) { //height loop + const int16_t base_y = (out_y * stride_ht) - pad_ht; + for (int out_x = 0; out_x < out_wd; out_x++) { //width_loop + const int16_t base_x = (out_x * stride_wd) - pad_wd; + for (int out_ch_idx = 0; out_ch_idx < out_channels; out_ch_idx++) {//channel_loop + int32_t result = 0; + + /* Select filter so as the point doesn't lie outside block */ + int filter_y_start = max(0, -base_y); + int filter_x_start = max(0, -base_x); + int filter_y_end = min(filter_ht, input_ht - base_y); + int filter_x_end = min(filter_wd, input_wd - base_x); + + for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + const int32_t idx_y = base_y + filter_y_idx; + for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t idx_x = base_x + filter_x_idx; + for (int in_ch_idx = 0; in_ch_idx < in_channels; in_ch_idx++) { + int32_t input_index = (idx_y * input_wd + idx_x) * in_channels + in_ch_idx; + int32_t filter_index = ((out_ch_idx * filter_ht + filter_y_idx) + * filter_wd + filter_x_idx) * in_channels + + in_ch_idx; + int32_t input_val = input_data[input_index] + input_offset; + int32_t filter_val = filter_data[filter_index] + filter_offset; + result += input_val * filter_val; + } + } + } + if (bias) { + result += bias[out_ch_idx]; + } + result = esp_nn_multiply_by_quantized_mult(result, out_mult, out_shift); + result += out_offset; + result = max(result, activation_min); + result = min(result, activation_max); + + int out_index = (out_y * out_wd + out_x) * out_channels + out_ch_idx; + out_data[out_index] = (uint8_t) result; + } + } + } +} + +/** + * Assumption 1: i/p channels == o/p channels + * Assumption 2: Pointers are valid + * Assumption 3: dialation width = 1 + */ +void esp_nn_conv_s8_ansi(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const conv_params_t *conv_params, + const quant_data_t *quant_data) +{ + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t in_channels = input_dims->channels; + const int32_t input_offset = conv_params->in_offset; + const int32_t out_offset = conv_params->out_offset; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const uint16_t out_channels = output_dims->channels; + const int32_t *out_shift = quant_data->shift; + const int32_t *out_mult = quant_data->mult; + const int32_t activation_min = conv_params->activation.min; + const int32_t activation_max = conv_params->activation.max; + + int32_t out_ch_idx, out_y, out_x, in_ch_idx, filter_y_idx, filter_x_idx; + + for (out_y = 0; out_y < out_ht; out_y++) { + for (out_x = 0; out_x < out_wd; out_x++) { + for (out_ch_idx = 0; out_ch_idx < out_channels; out_ch_idx++) { + int32_t conv_out = 0; + + const int32_t base_y = stride_ht * out_y - pad_ht; + const int32_t base_x = stride_wd * out_x - pad_wd; + + const int32_t filter_y_start = max(0, -base_y); + const int32_t filter_x_start = max(0, -base_x); + + const int32_t filter_y_end = min(filter_ht, input_ht - base_y); + const int32_t filter_x_end = min(filter_wd, input_wd - base_x); + + for (filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + for (filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t in_row = base_y + filter_y_idx; + const int32_t in_col = base_x + filter_x_idx; + int32_t input_base_offset = (in_row * input_wd + in_col) * in_channels; + int32_t filter_base_offset = out_ch_idx * in_channels * filter_ht * filter_wd + + (filter_y_idx * filter_wd + filter_x_idx) * in_channels; + for (in_ch_idx = 0; in_ch_idx < in_channels; in_ch_idx++) { + conv_out += + (input_data[input_base_offset + in_ch_idx] + input_offset) * + filter_data[filter_base_offset + in_ch_idx]; + } + } + } + if (bias) { + conv_out += bias[out_ch_idx]; + } + conv_out = esp_nn_multiply_by_quantized_mult(conv_out, out_mult[out_ch_idx], out_shift[out_ch_idx]); + conv_out += out_offset; + conv_out = max(conv_out, activation_min); + conv_out = min(conv_out, activation_max); + *out_data++ = (int8_t) conv_out; + } + } + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_esp32s3.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_esp32s3.c new file mode 100644 index 000000000..8918bd861 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_esp32s3.c @@ -0,0 +1,463 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "../../include/esp_nn_defs.h" + +#include "../common/common_functions.h" + +static int16_t *scratch_buffer = NULL; + +extern void esp_nn_conv_s8_mult8_1x1_esp32s3(const int8_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t in_channels, + const int32_t input_offset, + const int8_t *filter_aligned, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max, + void *buffer /* scratch buffer */); + +extern void esp_nn_conv_s16_mult4_1x1_esp32s3(const int16_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t in_channels, + const int16_t *filter_data, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max, + void *buffer /* scratch buffer */); + +extern void esp_nn_conv_s16_mult8_esp32s3(const int16_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t in_channels, + const uint16_t pad_wd, + const uint16_t pad_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const int16_t *filter_data, + const uint16_t filter_wd, + const uint16_t filter_ht, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max); + +extern void esp_nn_aligned_s8_to_s16_with_offset_esp32s3(const int8_t *src, int16_t *dst, + const int size, const int32_t offset); + +extern void esp_nn_s8_to_s16_esp32s3(const int8_t *src, int16_t *dst, const int size); + +static void esp_nn_conv_s8_unrolled(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const conv_params_t *conv_params, + const quant_data_t *quant_data) +{ + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t in_ch = input_dims->channels; + const int32_t input_offset = conv_params->in_offset; + const int32_t out_offset = conv_params->out_offset; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const uint16_t out_ch = output_dims->channels; + const int32_t *out_shift = quant_data->shift; + const int32_t *out_mult = quant_data->mult; + const int32_t activation_min = conv_params->activation.min; + const int32_t activation_max = conv_params->activation.max; + + int32_t out_ch_idx, out_y, out_x, in_ch_idx, filter_y_idx, filter_x_idx; + + for (out_y = 0; out_y < out_ht; out_y++) { + for (out_x = 0; out_x < out_wd; out_x++) { + for (out_ch_idx = 0; out_ch_idx < out_ch; out_ch_idx++) { + int32_t conv_out = 0; + + const int32_t base_y = stride_ht * out_y - pad_ht; + const int32_t base_x = stride_wd * out_x - pad_wd; + + const int32_t filter_y_start = max(0, -base_y); + const int32_t filter_x_start = max(0, -base_x); + + const int32_t filter_y_end = min(filter_ht, input_ht - base_y); + const int32_t filter_x_end = min(filter_wd, input_wd - base_x); + + for (filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + for (filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t in_row = base_y + filter_y_idx; + const int32_t in_col = base_x + filter_x_idx; + int32_t input_base_offset = (in_row * input_wd + in_col) * in_ch; + int32_t filter_base_offset = out_ch_idx * in_ch * filter_ht * filter_wd + + (filter_y_idx * filter_wd + filter_x_idx) * in_ch; + for (in_ch_idx = 0; in_ch_idx < in_ch; in_ch_idx++) { + conv_out += + (input_data[input_base_offset + in_ch_idx] + input_offset) * + filter_data[filter_base_offset + in_ch_idx]; + } + } + } + if (bias) { + conv_out += bias[out_ch_idx]; + } + conv_out = esp_nn_multiply_by_quantized_mult_fast(conv_out, out_mult[out_ch_idx], out_shift[out_ch_idx]); + conv_out += out_offset; + conv_out = max(conv_out, activation_min); + conv_out = min(conv_out, activation_max); + *out_data++ = (int8_t) conv_out; + } + } + } +} + +static void esp_nn_conv_s8_pad_valid(const int8_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t in_channels, + const int32_t input_offset, + const uint16_t stride_wd, + const uint16_t stride_ht, + const int8_t *filter_data, + const uint16_t filter_wd, + const uint16_t filter_ht, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max) +{ + int32_t out_ch_idx, out_y, out_x, in_ch_idx, filter_y_idx, filter_x_idx; + + for (out_y = 0; out_y < out_ht; out_y++) { + for (out_x = 0; out_x < out_wd; out_x++) { + for (out_ch_idx = 0; out_ch_idx < out_channels; out_ch_idx++) { + int32_t conv_out = 0; + + const int32_t base_y = stride_ht * out_y; + const int32_t base_x = stride_wd * out_x; + + for (filter_y_idx = 0; filter_y_idx < filter_ht; filter_y_idx++) { + for (filter_x_idx = 0; filter_x_idx < filter_wd; filter_x_idx++) { + const int32_t in_row = base_y + filter_y_idx; + const int32_t in_col = base_x + filter_x_idx; + int32_t input_base_offset = (in_row * input_wd + in_col) * in_channels; + int32_t filter_base_offset = out_ch_idx * in_channels * filter_ht * filter_wd + + (filter_y_idx * filter_wd + filter_x_idx) * in_channels; + const int8_t *input_data_ptr = input_data + input_base_offset; + const int8_t *filter_data_ptr = filter_data + filter_base_offset; + for (in_ch_idx = 0; in_ch_idx < in_channels; in_ch_idx++) { + conv_out += (*input_data_ptr++ + input_offset) * *filter_data_ptr++; + } + } + } + if (bias) { + conv_out += bias[out_ch_idx]; + } + conv_out = esp_nn_multiply_by_quantized_mult_fast(conv_out, out_mult[out_ch_idx], out_shift[out_ch_idx]); + conv_out += out_offset; + conv_out = max(conv_out, activation_min); + conv_out = min(conv_out, activation_max); + *out_data++ = (int8_t) conv_out; + } + } + } +} + +static void esp_nn_conv_s8_pad_valid_3x3(const int8_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t in_channels, + const int32_t input_offset, + const uint16_t stride_wd, + const uint16_t stride_ht, + const int8_t *filter_data, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max) +{ + int32_t out_ch_idx, out_y, out_x, in_ch_idx, filter_y_idx, filter_x_idx; + + for (out_y = 0; out_y < out_ht; out_y++) { + for (out_x = 0; out_x < out_wd; out_x++) { + const int32_t base_y = stride_ht * out_y; + const int32_t base_x = stride_wd * out_x; + for (out_ch_idx = 0; out_ch_idx < out_channels; out_ch_idx++) { + int32_t conv_out = 0; + for (filter_y_idx = 0; filter_y_idx < 3; filter_y_idx++) { + for (filter_x_idx = 0; filter_x_idx < 3; filter_x_idx++) { + const int32_t in_row = base_y + filter_y_idx; + const int32_t in_col = base_x + filter_x_idx; + int32_t input_base_offset = (in_row * input_wd + in_col) * in_channels; + int32_t filter_base_offset = out_ch_idx * in_channels * 3 * 3 + + (filter_y_idx * 3 + filter_x_idx) * in_channels; + const int8_t *input_data_ptr = input_data + input_base_offset; + const int8_t *filter_data_ptr = filter_data + filter_base_offset; + for (in_ch_idx = 0; in_ch_idx < in_channels; in_ch_idx++) { + conv_out += (*input_data_ptr++ + input_offset) * *filter_data_ptr++; + } + } + } + if (bias) { + conv_out += bias[out_ch_idx]; + } + conv_out = esp_nn_multiply_by_quantized_mult_fast(conv_out, out_mult[out_ch_idx], out_shift[out_ch_idx]); + conv_out += out_offset; + conv_out = max(conv_out, activation_min); + conv_out = min(conv_out, activation_max); + *out_data++ = (int8_t) conv_out; + } + } + } +} + +static void esp_nn_conv_s8_pad_valid_ch3_3x3(const int8_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const int32_t input_offset, + const uint16_t stride_wd, + const uint16_t stride_ht, + const int8_t *filter_data, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max) +{ + int32_t out_ch_idx, out_y, out_x, filter_y_idx; + + /* use scratch_buffer to pre-compute offset factor */ + int16_t *filter_sum = (int16_t *) scratch_buffer; + const int8_t *filter_ptr = filter_data; + for (out_ch_idx = 0; out_ch_idx < out_channels; out_ch_idx++) { + int16_t sum_val = 0; + for (int i = 0; i < 9; i++) { + sum_val += *filter_ptr++; + sum_val += *filter_ptr++; + sum_val += *filter_ptr++; + } + *filter_sum++ = sum_val; + } + + for (out_y = 0; out_y < out_ht; out_y++) { + for (out_x = 0; out_x < out_wd; out_x++) { + const int8_t *filter_data_ptr = filter_data; + const int32_t base_y = stride_ht * out_y; + const int32_t base_x = stride_wd * out_x; + const int8_t *input_base_ptr = input_data + (base_y * input_wd + base_x) * 3; + int16_t *filter_sum = (int16_t *) scratch_buffer; + for (out_ch_idx = 0; out_ch_idx < out_channels; out_ch_idx++) { + int32_t conv_out = 0; + + for (filter_y_idx = 0; filter_y_idx < 3; filter_y_idx++) { + const int8_t *input_data_ptr = input_base_ptr + (filter_y_idx * input_wd) * 3; + conv_out += (*input_data_ptr++) * (*filter_data_ptr++); + conv_out += (*input_data_ptr++) * (*filter_data_ptr++); + conv_out += (*input_data_ptr++) * (*filter_data_ptr++); + + conv_out += (*input_data_ptr++) * (*filter_data_ptr++); + conv_out += (*input_data_ptr++) * (*filter_data_ptr++); + conv_out += (*input_data_ptr++) * (*filter_data_ptr++); + + conv_out += (*input_data_ptr++) * (*filter_data_ptr++); + conv_out += (*input_data_ptr++) * (*filter_data_ptr++); + conv_out += (*input_data_ptr++) * (*filter_data_ptr++); + } + + conv_out += *filter_sum++ * input_offset; + + if (bias) { + conv_out += bias[out_ch_idx]; + } + conv_out = esp_nn_multiply_by_quantized_mult_fast(conv_out, out_mult[out_ch_idx], out_shift[out_ch_idx]); + conv_out += out_offset; + conv_out = max(conv_out, activation_min); + conv_out = min(conv_out, activation_max); + *out_data++ = (int8_t) conv_out; + } + } + } +} + +int esp_nn_get_conv_scratch_size_esp32s3(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const conv_params_t *conv_params) +{ + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t in_ch = input_dims->channels; + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + const uint16_t out_ch = output_dims->channels; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + + int filter_size = filter_wd * filter_ht * in_ch * out_ch; + int input_size = input_wd * input_ht * in_ch; + + int transpose_buf_size = 2 * (8 * in_ch); /* to store intermediate data */ + if (input_wd * input_ht < 8) { + transpose_buf_size = 0; // not using this for leftover + } + int align_buf_size = 32; /* extra buffer for alignment */ + if (in_ch % 8 == 0 && filter_wd == 1 && filter_ht == 1 && + pad_wd == 0 && pad_ht == 0 && stride_wd == 1 && stride_ht == 1) { + return filter_size + transpose_buf_size + align_buf_size; + } + return 2 * (filter_size + input_size) + transpose_buf_size + align_buf_size; +} + +void esp_nn_set_conv_scratch_buf_esp32s3(void *buf) +{ + scratch_buffer = (int16_t *) buf; +} + +void esp_nn_conv_s8_esp32s3(const data_dims_t *input_dims, + const int8_t *input, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const conv_params_t *conv_params, + const quant_data_t *quant_data) +{ + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t channels = input_dims->channels; + const int32_t input_offset = conv_params->in_offset; + const int32_t out_offset = conv_params->out_offset; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const uint16_t out_channels = output_dims->channels; + const int32_t *out_shift = quant_data->shift; + const int32_t *out_mult = quant_data->mult; + const int32_t activation_min = conv_params->activation.min; + const int32_t activation_max = conv_params->activation.max; + + int filter_size = filter_wd * filter_ht * channels * out_channels; + int input_size = input_wd * input_ht * channels; + int align_len = 16 - (filter_size & 15); + int16_t *filter_data16 = scratch_buffer; + int16_t *input_data16 = scratch_buffer + filter_size + align_len; + + if (scratch_buffer == NULL) { + printf("esp_nn_conv error! scratch_buffer not set!\n"); + return; + } + + if (channels % 8 == 0 && filter_wd == 1 && filter_ht == 1 && + pad_wd == 0 && pad_ht == 0 && stride_wd == 1 && stride_ht == 1) { + int8_t *filter_aligned = (int8_t *) scratch_buffer; + int scratch_offset = (int) (filter_aligned + filter_size); + void *scratch_buf = (void *) (scratch_offset + 16 - (scratch_offset & 15)); + memcpy(filter_aligned, filter_data, filter_size); // copy to aligned address + esp_nn_conv_s8_mult8_1x1_esp32s3( + input, input_wd, input_ht, channels, input_offset, filter_aligned, + bias, out_data, out_wd, out_ht, out_channels, out_offset, + out_shift, out_mult, activation_min, activation_max, scratch_buf); + } else if (channels % 4 == 0 && filter_wd == 1 && filter_ht == 1 && + (input_wd * input_ht) % 4 == 0 && /* TODO: remove this check */ + pad_wd == 0 && pad_ht == 0 && stride_wd == 1 && stride_ht == 1) { + int scratch_offset = (int) (input_data16 + input_size); + void *scratch_buf = (void *) (scratch_offset + 16 - (scratch_offset & 15)); + esp_nn_s8_to_s16_esp32s3(filter_data, filter_data16, filter_size); + esp_nn_aligned_s8_to_s16_with_offset_esp32s3(input, input_data16, input_size, input_offset); + esp_nn_conv_s16_mult4_1x1_esp32s3( + input_data16, input_wd, input_ht, channels, filter_data16, + bias, out_data, out_wd, out_ht, out_channels, out_offset, + out_shift, out_mult, activation_min, activation_max, scratch_buf); + } else if (channels % 8 == 0) { + esp_nn_s8_to_s16_esp32s3(filter_data, filter_data16, filter_size); + esp_nn_aligned_s8_to_s16_with_offset_esp32s3(input, input_data16, input_size, input_offset); + esp_nn_conv_s16_mult8_esp32s3( + input_data16, input_wd, input_ht, channels, pad_wd, pad_ht, + stride_wd, stride_ht, filter_data16, filter_wd, filter_ht, bias, + out_data, out_wd, out_ht, out_channels, out_offset, out_shift, + out_mult, activation_min, activation_max); + } else if (pad_wd == 0 && pad_ht == 0) { + if (filter_wd == 3 && filter_ht == 3 && channels == 3) { + esp_nn_conv_s8_pad_valid_ch3_3x3(input, input_wd, input_ht, input_offset, + stride_wd, stride_ht, filter_data, bias, + out_data, out_wd, out_ht, out_channels, out_offset, + out_shift, out_mult, activation_min, activation_max); + } else { + esp_nn_conv_s8_pad_valid(input, input_wd, input_ht, channels, input_offset, + stride_wd, stride_ht, filter_data, filter_wd, filter_ht, bias, + out_data, out_wd, out_ht, out_channels, out_offset, out_shift, + out_mult, activation_min, activation_max); + } + } else { + /* Basic unrolled version */ + esp_nn_conv_s8_unrolled(input_dims, input, filter_dims, filter_data, + bias, output_dims, out_data, conv_params, quant_data); + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_opt.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_opt.c new file mode 100644 index 000000000..80b1e13a5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_conv_opt.c @@ -0,0 +1,179 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "../../include/esp_nn_defs.h" + +#include "../common/common_functions.h" + +int esp_nn_get_conv_scratch_size_opt(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const conv_params_t *conv_params) +{ + return 0; +} + +void esp_nn_set_conv_scratch_buf_opt(const void *buf) +{ + +} + +__attribute__ ((noinline)) +static void esp_nn_conv_s8_1x1(const data_dims_t *input_dims, + const int8_t *input_data, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const conv_params_t *conv_params, + const quant_data_t *quant_data) +{ + const uint16_t input_wd = input_dims->width; + const uint16_t in_channels = input_dims->channels; + const int32_t input_offset = conv_params->in_offset; + const int32_t out_offset = conv_params->out_offset; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const uint16_t out_channels = output_dims->channels; + const int32_t activation_min = conv_params->activation.min; + const int32_t activation_max = conv_params->activation.max; + + for (int32_t in_row = 0; in_row < out_ht * stride_ht; in_row += stride_ht) { + for (int32_t in_col = 0; in_col < out_wd * stride_wd; in_col += stride_wd) { + const int32_t *out_mult = quant_data->mult; + const int32_t *out_shift = quant_data->shift; + const int8_t *filter_ptr = filter_data; + const int8_t *input_base_ptr = input_data + (in_row * input_wd + in_col) * in_channels; + int32_t out_ch_idx = 0; + for (; out_ch_idx < out_channels; out_ch_idx++) { + int32_t conv_out = 0; + + const int8_t *input_ptr = input_base_ptr; + + int32_t in_ch_idx = 0; + for (; in_ch_idx < in_channels - 3; in_ch_idx += 4) { + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + } + for (; in_ch_idx < in_channels; in_ch_idx ++) { + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + } + if (bias) { + conv_out += bias[out_ch_idx]; + } + conv_out = esp_nn_multiply_by_quantized_mult_fast(conv_out, *out_mult++, *out_shift++); + conv_out += out_offset; + conv_out = max(conv_out, activation_min); + conv_out = min(conv_out, activation_max); + *out_data++ = (int8_t) conv_out; + } + } + } +} + +/** + * Assumption 1: i/p channels == o/p channels + * Assumption 2: Pointers are valid + * Assumption 3: dialation width = 1 + */ +void esp_nn_conv_s8_opt(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const conv_params_t *conv_params, + const quant_data_t *quant_data) +{ + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + + if (filter_wd == 1 && filter_ht == 1) { + esp_nn_conv_s8_1x1(input_dims, input_data, filter_data, bias, + output_dims, out_data, conv_params, quant_data); + return; + } + + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t in_channels = input_dims->channels; + const int32_t input_offset = conv_params->in_offset; + const int32_t out_offset = conv_params->out_offset; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const uint16_t out_channels = output_dims->channels; + const int32_t activation_min = conv_params->activation.min; + const int32_t activation_max = conv_params->activation.max; + + int32_t out_ch_idx, out_y, out_x, filter_y_idx, filter_x_idx; + + for (out_y = 0; out_y < out_ht; out_y++) { + for (out_x = 0; out_x < out_wd; out_x++) { + const int32_t *out_shift = quant_data->shift; + const int32_t *out_mult = quant_data->mult; + for (out_ch_idx = 0; out_ch_idx < out_channels; out_ch_idx++) { + int32_t conv_out = 0; + + const int32_t base_y = stride_ht * out_y - pad_ht; + const int32_t base_x = stride_wd * out_x - pad_wd; + + const int32_t filter_y_start = max(0, -base_y); + const int32_t filter_x_start = max(0, -base_x); + + const int32_t filter_y_end = min(filter_ht, input_ht - base_y); + const int32_t filter_x_end = min(filter_wd, input_wd - base_x); + + for (filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + for (filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t in_row = base_y + filter_y_idx; + const int32_t in_col = base_x + filter_x_idx; + + const int8_t *input_ptr = input_data + + (in_row * input_wd + in_col) * in_channels; + const int8_t *filter_ptr = filter_data + + out_ch_idx * in_channels * filter_ht * filter_wd + + (filter_y_idx * filter_wd + filter_x_idx) * in_channels; + int32_t in_ch_idx = 0; + for (; in_ch_idx < in_channels - 3; in_ch_idx += 4) { + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + } + for (; in_ch_idx < in_channels; in_ch_idx ++) { + conv_out += (*input_ptr++ + input_offset) * *filter_ptr++; + } + } + } + if (bias) { + conv_out += bias[out_ch_idx]; + } + conv_out = esp_nn_multiply_by_quantized_mult_fast(conv_out, *out_mult++, *out_shift++); + conv_out += out_offset; + conv_out = max(conv_out, activation_min); + conv_out = min(conv_out, activation_max); + *out_data++ = (int8_t) conv_out; + } + } + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_ansi.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_ansi.c new file mode 100644 index 000000000..7cd3cde1f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_ansi.c @@ -0,0 +1,100 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "../../include/esp_nn_defs.h" +#include "../common/common_functions.h" + +int esp_nn_get_depthwise_conv_scratch_size_ansi(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const dw_conv_params_t *conv_params) +{ + return 0; +} + +void esp_nn_set_depthwise_conv_scratch_buf_ansi(const void *buf) +{ + +} + +void esp_nn_depthwise_conv_s8_ansi(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const dw_conv_params_t *conv_params, + const quant_data_t *quant_data) +{ + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t channels = input_dims->channels; + const int32_t input_offset = conv_params->in_offset; + const int32_t out_offset = conv_params->out_offset; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const int32_t *out_shift = quant_data->shift; + const int32_t *out_mult = quant_data->mult; + const int32_t activation_min = conv_params->activation.min; + const int32_t activation_max = conv_params->activation.max; + const uint16_t ch_mult = conv_params->ch_mult; + + int out_idx = 0; + for (int out_y = 0; out_y < out_ht; out_y++) { //height loop + const int16_t base_y = (out_y * stride_ht) - pad_ht; + for (int out_x = 0; out_x < out_wd; out_x++) { //width_loop + const int16_t base_x = (out_x * stride_wd) - pad_wd; + for (int ch_idx = 0; ch_idx < channels; ch_idx++) {//channel_loop + for (int ch_mult_idx = 0; ch_mult_idx < ch_mult; ch_mult_idx++) { + int32_t result = 0; + const int out_ch_idx = ch_mult_idx + ch_idx * ch_mult; + + /* Select filter so as the point doesn't lie outside block */ + int filter_y_start = max(0, -base_y); + int filter_x_start = max(0, -base_x); + int filter_y_end = min(filter_ht, input_ht - base_y); + int filter_x_end = min(filter_wd, input_wd - base_x); + + for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + const int32_t idx_y = base_y + filter_y_idx; + for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t idx_x = base_x + filter_x_idx; + int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx; + int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels * ch_mult) + out_ch_idx; + int32_t input_val = input_data[input_index] + input_offset; + int32_t filter_val = filter_data[filter_index]; + result += input_val * filter_val; + } + } + if (bias) { + result += bias[out_ch_idx]; + } + result = esp_nn_multiply_by_quantized_mult(result, out_mult[out_ch_idx], out_shift[out_ch_idx]); + result += out_offset; + result = max(result, activation_min); + result = min(result, activation_max); + + out_data[out_idx++] = result; + } + } + } + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_opt.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_opt.c new file mode 100644 index 000000000..d7063f72c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_opt.c @@ -0,0 +1,291 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "../../include/esp_nn_defs.h" +#include "../common/common_functions.h" + +int esp_nn_get_depthwise_conv_scratch_size_opt(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const dw_conv_params_t *conv_params) +{ + return 0; +} + +void esp_nn_set_depthwise_conv_scratch_buf_opt(const void *buf) +{ + +} + +/* common channel multiplier == 1 case */ +__attribute__ ((noinline)) +static void esp_nn_depthwise_conv_s8_ch_mult_1(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const dw_conv_params_t *conv_params, + const quant_data_t *quant_data) +{ + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t channels = input_dims->channels; + const int32_t input_offset = conv_params->in_offset; + const int32_t out_offset = conv_params->out_offset; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const int32_t activation_min = conv_params->activation.min; + const int32_t activation_max = conv_params->activation.max; + + int out_idx = 0; + for (int out_y = 0; out_y < out_ht; out_y++) { //height loop + const int16_t base_y = (out_y * stride_ht) - pad_ht; + for (int out_x = 0; out_x < out_wd; out_x++) { //width_loop + const int16_t base_x = (out_x * stride_wd) - pad_wd; + + const int32_t *out_shift = quant_data->shift; + const int32_t *out_mult = quant_data->mult; + + /* Select filter so as the point doesn't lie outside block */ + int filter_y_start = max(0, -base_y); + int filter_x_start = max(0, -base_x); + int filter_y_end = min(filter_ht, input_ht - base_y); + int filter_x_end = min(filter_wd, input_wd - base_x); + + int ch_idx = 0; + for (; ch_idx < channels - 3; ch_idx += 4) {//channel_loop + int32_t result0 = 0; + int32_t result1 = 0; + int32_t result2 = 0; + int32_t result3 = 0; + + for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + const int32_t idx_y = base_y + filter_y_idx; + for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t idx_x = base_x + filter_x_idx; + int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx; + int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels) + ch_idx; + int32_t input_val0 = input_data[input_index + 0] + input_offset; + int32_t input_val1 = input_data[input_index + 1] + input_offset; + int32_t input_val2 = input_data[input_index + 2] + input_offset; + int32_t input_val3 = input_data[input_index + 3] + input_offset; + int32_t filter_val0 = filter_data[filter_index + 0]; + int32_t filter_val1 = filter_data[filter_index + 1]; + int32_t filter_val2 = filter_data[filter_index + 2]; + int32_t filter_val3 = filter_data[filter_index + 3]; + result0 += input_val0 * filter_val0; + result1 += input_val1 * filter_val1; + result2 += input_val2 * filter_val2; + result3 += input_val3 * filter_val3; + } + } + if (bias) { + result0 += bias[ch_idx + 0]; + result1 += bias[ch_idx + 1]; + result2 += bias[ch_idx + 2]; + result3 += bias[ch_idx + 3]; + } + result0 = esp_nn_multiply_by_quantized_mult_fast(result0, *out_mult++, *out_shift++); + result1 = esp_nn_multiply_by_quantized_mult_fast(result1, *out_mult++, *out_shift++); + result2 = esp_nn_multiply_by_quantized_mult_fast(result2, *out_mult++, *out_shift++); + result3 = esp_nn_multiply_by_quantized_mult_fast(result3, *out_mult++, *out_shift++); + + result0 += out_offset; + result1 += out_offset; + result2 += out_offset; + result3 += out_offset; + + result0 = max(result0, activation_min); + result1 = max(result1, activation_min); + result2 = max(result2, activation_min); + result3 = max(result3, activation_min); + + result0 = min(result0, activation_max); + result1 = min(result1, activation_max); + result2 = min(result2, activation_max); + result3 = min(result3, activation_max); + + out_data[out_idx++] = result0; + out_data[out_idx++] = result1; + out_data[out_idx++] = result2; + out_data[out_idx++] = result3; + } + for (; ch_idx < channels; ch_idx++) {//channel_loop + int32_t result = 0; + + for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + const int32_t idx_y = base_y + filter_y_idx; + for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t idx_x = base_x + filter_x_idx; + int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx; + int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels) + ch_idx; + int32_t input_val = input_data[input_index] + input_offset; + int32_t filter_val = filter_data[filter_index]; + result += input_val * filter_val; + } + } + if (bias) { + result += bias[ch_idx]; + } + result = esp_nn_multiply_by_quantized_mult_fast(result, *out_mult++, *out_shift++); + result += out_offset; + result = max(result, activation_min); + result = min(result, activation_max); + + out_data[out_idx++] = result; + } + } + } +} + +void esp_nn_depthwise_conv_s8_opt(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const dw_conv_params_t *conv_params, + const quant_data_t *quant_data) +{ + const uint16_t ch_mult = conv_params->ch_mult; + if (ch_mult == 1) { + esp_nn_depthwise_conv_s8_ch_mult_1(input_dims, input_data, filter_dims, filter_data, + bias, output_dims, out_data, conv_params, quant_data); + return; + } + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t channels = input_dims->channels; + const int32_t input_offset = conv_params->in_offset; + const int32_t out_offset = conv_params->out_offset; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const int32_t activation_min = conv_params->activation.min; + const int32_t activation_max = conv_params->activation.max; + + int out_idx = 0; + for (int out_y = 0; out_y < out_ht; out_y++) { //height loop + const int16_t base_y = (out_y * stride_ht) - pad_ht; + for (int out_x = 0; out_x < out_wd; out_x++) { //width_loop + const int16_t base_x = (out_x * stride_wd) - pad_wd; + + const int32_t *out_shift = quant_data->shift; + const int32_t *out_mult = quant_data->mult; + + /* Select filter so as the point doesn't lie outside block */ + int filter_y_start = max(0, -base_y); + int filter_x_start = max(0, -base_x); + int filter_y_end = min(filter_ht, input_ht - base_y); + int filter_x_end = min(filter_wd, input_wd - base_x); + + for (int ch_idx = 0; ch_idx < channels; ch_idx++) {//channel_loop + int ch_mult_idx = 0; + for (; ch_mult_idx < ch_mult - 3; ch_mult_idx += 4) { + int32_t result0 = 0; + int32_t result1 = 0; + int32_t result2 = 0; + int32_t result3 = 0; + const int out_ch_idx = ch_idx * ch_mult + ch_mult_idx; + + for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + const int32_t idx_y = base_y + filter_y_idx; + for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t idx_x = base_x + filter_x_idx; + int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx; + int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels * ch_mult) + out_ch_idx; + int32_t input_val = input_data[input_index] + input_offset; + int32_t filter_val0 = filter_data[filter_index + 0]; + int32_t filter_val1 = filter_data[filter_index + 1]; + int32_t filter_val2 = filter_data[filter_index + 2]; + int32_t filter_val3 = filter_data[filter_index + 3]; + result0 += input_val * filter_val0; + result1 += input_val * filter_val1; + result2 += input_val * filter_val2; + result3 += input_val * filter_val3; + } + } + if (bias) { + result0 += bias[out_ch_idx + 0]; + result1 += bias[out_ch_idx + 1]; + result2 += bias[out_ch_idx + 2]; + result3 += bias[out_ch_idx + 3]; + } + result0 = esp_nn_multiply_by_quantized_mult_fast(result0, *out_mult++, *out_shift++); + result1 = esp_nn_multiply_by_quantized_mult_fast(result1, *out_mult++, *out_shift++); + result2 = esp_nn_multiply_by_quantized_mult_fast(result2, *out_mult++, *out_shift++); + result3 = esp_nn_multiply_by_quantized_mult_fast(result3, *out_mult++, *out_shift++); + + result0 += out_offset; + result1 += out_offset; + result2 += out_offset; + result3 += out_offset; + + result0 = max(result0, activation_min); + result1 = max(result1, activation_min); + result2 = max(result2, activation_min); + result3 = max(result3, activation_min); + result0 = min(result0, activation_max); + result1 = min(result1, activation_max); + result2 = min(result2, activation_max); + result3 = min(result3, activation_max); + + out_data[out_idx++] = result0; + out_data[out_idx++] = result1; + out_data[out_idx++] = result2; + out_data[out_idx++] = result3; + } + for (; ch_mult_idx < ch_mult; ch_mult_idx++) { + int32_t result = 0; + const int out_ch_idx = ch_idx * ch_mult + ch_mult_idx; + + for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + const int32_t idx_y = base_y + filter_y_idx; + for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t idx_x = base_x + filter_x_idx; + int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx; + int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels * ch_mult) + out_ch_idx; + int32_t input_val = input_data[input_index] + input_offset; + int32_t filter_val = filter_data[filter_index]; + result += input_val * filter_val; + } + } + if (bias) { + result += bias[out_ch_idx]; + } + result = esp_nn_multiply_by_quantized_mult_fast(result, *out_mult++, *out_shift++); + result += out_offset; + result = max(result, activation_min); + result = min(result, activation_max); + + out_data[out_idx++] = result; + } + } + } + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_s8_esp32s3.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_s8_esp32s3.c new file mode 100644 index 000000000..8840977f6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/convolution/esp_nn_depthwise_conv_s8_esp32s3.c @@ -0,0 +1,543 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "../../include/esp_nn_defs.h" + +#include "../common/common_functions.h" + +static int16_t *scratch_buffer = NULL; + +extern void esp_nn_depthwise_conv_s16_mult8_3x3_esp32s3(const int16_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const uint16_t pad_wd, + const uint16_t pad_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t ch_mult, + const int16_t *filter_data, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max); + +extern void esp_nn_depthwise_conv_s8_mult1_3x3_padded_esp32s3(const int8_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const int32_t input_offset, + const uint16_t stride_wd, + const uint16_t stride_ht, + const int8_t *filter_data, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max); + +extern void esp_nn_depthwise_conv_s16_mult1_3x3_no_pad_esp32s3(const int16_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const uint16_t stride_wd, + const uint16_t stride_ht, + const int16_t *filter_data, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max); + +extern void esp_nn_depthwise_conv_s16_mult8_esp32s3(const int16_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const uint16_t pad_wd, + const uint16_t pad_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t ch_mult, + const int16_t *filter_data, + const uint16_t filter_wd, + const uint16_t filter_ht, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max); + +extern void esp_nn_depthwise_conv_s16_mult4_esp32s3(const int16_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const uint16_t pad_wd, + const uint16_t pad_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t ch_mult, + const int16_t *filter_data, + const uint16_t filter_wd, + const uint16_t filter_ht, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max); + +extern void esp_nn_depthwise_conv_s16_mult1_3x3_esp32s3(const int16_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const uint16_t pad_wd, + const uint16_t pad_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const int16_t *filter_data, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max); + +extern void esp_nn_depthwise_conv_s16_mult1_esp32s3(const int16_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const uint16_t pad_wd, + const uint16_t pad_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const int16_t *filter_data, + const uint16_t filter_wd, + const uint16_t filter_ht, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max); + +extern void esp_nn_s8_to_s16_esp32s3(const int8_t *src, int16_t *dst, const int size); + +extern void esp_nn_aligned_s8_to_s16_with_offset_esp32s3(const int8_t *src, int16_t *dst, + const int size, const int32_t offset); + +static void esp_nn_depthwise_conv_s8_unrolled(const int8_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const int32_t input_offset, + const uint16_t pad_wd, + const uint16_t pad_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t ch_mult, + const int8_t *filter_data, + const uint16_t filter_wd, + const uint16_t filter_ht, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max) +{ + int out_idx = 0; + for (int out_y = 0; out_y < out_ht; out_y++) { //height loop + const int16_t base_y = (out_y * stride_ht) - pad_ht; + for (int out_x = 0; out_x < out_wd; out_x++) { //width_loop + const int16_t base_x = (out_x * stride_wd) - pad_wd; + for (int ch_idx = 0; ch_idx < channels; ch_idx++) {//channel_loop + int ch_mult_idx = 0; + for (; ch_mult_idx < ch_mult - 3; ch_mult_idx += 4) { + int32_t result0 = 0, result1 = 0, result2 = 0, result3 = 0; + const int out_ch_idx = ch_mult_idx + ch_idx * ch_mult; + + /* Select filter so as the point doesn't lie outside block */ + int filter_y_start = max(0, -base_y); + int filter_x_start = max(0, -base_x); + int filter_y_end = min(filter_ht, input_ht - base_y); + int filter_x_end = min(filter_wd, input_wd - base_x); + + for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + const int32_t idx_y = base_y + filter_y_idx; + for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t idx_x = base_x + filter_x_idx; + int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx; + int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels * ch_mult) + out_ch_idx; + int32_t input_val = input_data[input_index] + input_offset; + int32_t filter_val0 = filter_data[filter_index + 0]; + int32_t filter_val1 = filter_data[filter_index + 1]; + int32_t filter_val2 = filter_data[filter_index + 2]; + int32_t filter_val3 = filter_data[filter_index + 3]; + result0 += input_val * filter_val0; + result1 += input_val * filter_val1; + result2 += input_val * filter_val2; + result3 += input_val * filter_val3; + } + } + if (bias) { + result0 += bias[out_ch_idx + 0]; + result1 += bias[out_ch_idx + 1]; + result2 += bias[out_ch_idx + 2]; + result3 += bias[out_ch_idx + 3]; + } + result0 = esp_nn_multiply_by_quantized_mult(result0, + out_mult[out_ch_idx + 0], out_shift[out_ch_idx + 0]); + result1 = esp_nn_multiply_by_quantized_mult(result1, + out_mult[out_ch_idx + 1], out_shift[out_ch_idx + 1]); + result2 = esp_nn_multiply_by_quantized_mult(result2, + out_mult[out_ch_idx + 2], out_shift[out_ch_idx + 2]); + result3 = esp_nn_multiply_by_quantized_mult(result3, + out_mult[out_ch_idx + 3], out_shift[out_ch_idx + 3]); + + result0 += out_offset; + result1 += out_offset; + result2 += out_offset; + result3 += out_offset; + + result0 = max(result0, activation_min); + result1 = max(result1, activation_min); + result2 = max(result2, activation_min); + result3 = max(result3, activation_min); + + result0 = min(result0, activation_max); + result1 = min(result1, activation_max); + result2 = min(result2, activation_max); + result3 = min(result3, activation_max); + + out_data[out_idx++] = result0; + out_data[out_idx++] = result1; + out_data[out_idx++] = result2; + out_data[out_idx++] = result3; + } + + /* left-over */ + for (; ch_mult_idx < ch_mult; ch_mult_idx++) { + int32_t result = 0; + const int out_ch_idx = ch_mult_idx + ch_idx * ch_mult; + + /* Select filter so as the point doesn't lie outside block */ + int filter_y_start = max(0, -base_y); + int filter_x_start = max(0, -base_x); + int filter_y_end = min(filter_ht, input_ht - base_y); + int filter_x_end = min(filter_wd, input_wd - base_x); + + for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + const int32_t idx_y = base_y + filter_y_idx; + for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t idx_x = base_x + filter_x_idx; + int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx; + int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels * ch_mult) + out_ch_idx; + int32_t input_val = input_data[input_index] + input_offset; + int32_t filter_val = filter_data[filter_index]; + result += input_val * filter_val; + } + } + if (bias) { + result += bias[out_ch_idx]; + } + result = esp_nn_multiply_by_quantized_mult(result, out_mult[out_ch_idx], out_shift[out_ch_idx]); + result += out_offset; + result = max(result, activation_min); + result = min(result, activation_max); + + out_data[out_idx++] = result; + } + } + } + } +} + +void esp_nn_depthwise_conv_s8_ch_mult1(const int8_t *input_data, + const uint16_t input_wd, + const uint16_t input_ht, + const uint16_t channels, + const int32_t input_offset, + const uint16_t pad_wd, + const uint16_t pad_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const int8_t *filter_data, + const uint16_t filter_wd, + const uint16_t filter_ht, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_wd, + const uint16_t out_ht, + const int32_t out_offset, + const int32_t *out_shift, + const int32_t *out_mult, + const int32_t activation_min, + const int32_t activation_max) +{ + int out_idx = 0; + for (int out_y = 0; out_y < out_ht; out_y++) { //height loop + const int16_t base_y = (out_y * stride_ht) - pad_ht; + for (int out_x = 0; out_x < out_wd; out_x++) { //width_loop + const int16_t base_x = (out_x * stride_wd) - pad_wd; + for (int ch_idx = 0; ch_idx < channels; ch_idx++) {//channel_loop + int32_t result = 0; + /* Select filter so as the point doesn't lie outside block */ + int filter_y_start = max(0, -base_y); + int filter_x_start = max(0, -base_x); + int filter_y_end = min(filter_ht, input_ht - base_y); + int filter_x_end = min(filter_wd, input_wd - base_x); + + for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) { + const int32_t idx_y = base_y + filter_y_idx; + for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) { + const int32_t idx_x = base_x + filter_x_idx; + int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx; + int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * channels + ch_idx; + int32_t input_val = input_data[input_index] + input_offset; + int32_t filter_val = filter_data[filter_index]; + result += input_val * filter_val; + } + } + if (bias) { + result += bias[ch_idx]; + } + result = esp_nn_multiply_by_quantized_mult(result, out_mult[ch_idx], out_shift[ch_idx]); + result += out_offset; + result = max(result, activation_min); + result = min(result, activation_max); + + out_data[out_idx++] = result; + } + } + } +} + +int esp_nn_get_depthwise_conv_scratch_size_esp32s3(const data_dims_t *input_dims, + const data_dims_t *filter_dims, + const data_dims_t *output_dims, + const dw_conv_params_t *conv_params) +{ + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t channels = input_dims->channels; + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + const uint16_t ch_mult = conv_params->ch_mult; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + + int filter_size = filter_wd * filter_ht * channels * ch_mult; + int pad_width = 0, pad_height = 0; + + if ((ch_mult == 1) && (channels % 8 == 0) && (filter_wd == 3) && (filter_ht == 3)) { + if (channels % 16 == 0) { + if (pad_wd || pad_ht) { + pad_width = pad_wd * 2; + pad_height = pad_ht * 2; + } else { + // check if we need to pad additionally + pad_width = (out_wd * stride_wd + filter_wd - 1) - input_wd; + pad_height = (out_ht * stride_ht + filter_ht - 1) - input_ht; + // printf("in(%d %d %d), out(%d %d), filter (%d %d) stride (%d %d), pad (%d %d)", + // input_wd, input_ht, channels, out_wd, out_ht, filter_wd, filter_ht, + // stride_wd, stride_ht, pad_wd, pad_ht); + } + if (pad_width || pad_height) { + int input_size = (input_wd + pad_width) * (input_ht + pad_height) * channels; + // printf("ask1 %d\n", filter_size + input_size + 16); + return filter_size + input_size + 16; // 16 for alignment + } else { + // printf("ask2 %d\n", filter_size + 16); + return filter_size + 16; // 16 for alignment + } + } else { + int input_size = input_wd * input_ht * channels; + // printf("ask3 %d\n", 2 * (filter_size + input_size) + 16); + return 2 * (filter_size + input_size) + 16; // 16 for alignment + } + } else if (ch_mult % 4 == 0) { + int input_size = input_wd * input_ht * channels; + // printf("ask4 %d\n", 2 * (filter_size + input_size) + 16); + return 2 * (filter_size + input_size) + 16; // 16 for alignment + } + return 32; // just few bytes +} + +void esp_nn_set_depthwise_conv_scratch_buf_esp32s3(void *buf) +{ + scratch_buffer = (int16_t *) buf; +} + +/** + * Assumption 1: i/p channels == o/p channels + * Assumption 2: Pointers are valid + * Assumption 3: dialation width = 1 + */ + + + +void esp_nn_depthwise_conv_s8_esp32s3(const data_dims_t *input_dims, + const int8_t *input_data, + const data_dims_t *filter_dims, + const int8_t *filter_data, + const int32_t *bias, + const data_dims_t *output_dims, + int8_t *out_data, + const dw_conv_params_t *conv_params, + const quant_data_t *quant_data) +{ + const uint16_t input_wd = input_dims->width; + const uint16_t input_ht = input_dims->height; + const uint16_t channels = input_dims->channels; + const int32_t input_offset = conv_params->in_offset; + const int32_t out_offset = conv_params->out_offset; + const uint16_t pad_wd = conv_params->padding.width; + const uint16_t pad_ht = conv_params->padding.height; + const uint16_t stride_wd = conv_params->stride.width; + const uint16_t stride_ht = conv_params->stride.height; + const uint16_t filter_wd = filter_dims->width; + const uint16_t filter_ht = filter_dims->height; + const uint16_t out_wd = output_dims->width; + const uint16_t out_ht = output_dims->height; + const int32_t *out_shift = quant_data->shift; + const int32_t *out_mult = quant_data->mult; + const int32_t activation_min = conv_params->activation.min; + const int32_t activation_max = conv_params->activation.max; + const uint16_t ch_mult = conv_params->ch_mult; + + int filter_size = filter_wd * filter_ht * channels * ch_mult; + int align_len = 16 - (filter_size & 15); + int input_size = input_wd * input_ht * channels; + int16_t *filter_data16 = scratch_buffer; + int16_t *input_data16 = scratch_buffer + filter_size + align_len; + if (scratch_buffer == NULL) { + printf("esp_nn_depthwise_conv error! scratch_buffer not set!\n"); + return; + } + + if ((ch_mult == 1) && (channels % 8 == 0)) { + if ((filter_wd == 3) && (filter_ht == 3)) { + if ((channels % 16 == 0) && (pad_wd == 1) && (pad_ht == 1)) { + /* process in 8 bits */ + int8_t *filter_aligned = (int8_t *) scratch_buffer; + int8_t *input_padded = (int8_t *) scratch_buffer + filter_size + align_len; + memcpy(filter_aligned, filter_data, filter_size); + esp_nn_aligned_s8_pad_with_value(input_data, input_padded, input_wd, input_ht, channels, + -input_offset, pad_wd, pad_ht); + esp_nn_depthwise_conv_s8_mult1_3x3_padded_esp32s3(input_padded, input_wd + 2 * pad_wd, + input_ht + 2 * pad_ht, channels, input_offset, + stride_wd, stride_ht, filter_aligned, bias, + out_data, out_wd, out_ht, out_offset, out_shift, + out_mult, activation_min, activation_max); + } else if ((channels % 16 == 0) && (pad_wd == 0) && (pad_ht == 0)) { + /* process in 8 bits */ + int8_t *filter_aligned = (int8_t *) scratch_buffer; + int8_t *input_padded = (int8_t *) scratch_buffer + filter_size + align_len; + + // check if we need to pad additionally + int pad_right = (out_wd * stride_wd + filter_wd - 1) - input_wd; + int pad_bottom = (out_ht * stride_ht + filter_ht - 1) - input_ht; + if (pad_right || pad_bottom) { // pad right and bottom + esp_nn_aligned_s8_pad_end_with_value(input_data, input_padded, input_wd, input_ht, + channels, -input_offset, pad_right, pad_bottom); + } else { + input_padded = (int8_t *) input_data; + } + memcpy(filter_aligned, filter_data, filter_size); + esp_nn_depthwise_conv_s8_mult1_3x3_padded_esp32s3(input_padded, input_wd + pad_right, + input_ht + pad_bottom, channels, input_offset, + stride_wd, stride_ht, filter_aligned, bias, + out_data, out_wd, out_ht, out_offset, out_shift, + out_mult, activation_min, activation_max); + } else { /* (channels % 8) == 0 */ + esp_nn_s8_to_s16_esp32s3(filter_data, filter_data16, filter_size); + esp_nn_aligned_s8_to_s16_with_offset_esp32s3(input_data, input_data16, input_size, input_offset); + esp_nn_depthwise_conv_s16_mult1_3x3_esp32s3(input_data16, input_wd, input_ht, channels, + pad_wd, pad_ht, stride_wd, stride_ht, filter_data16, + bias, out_data, out_wd, out_ht, out_offset, out_shift, + out_mult, activation_min, activation_max); + } + } else { // all other ch_mult == 1, `channels % 8 == 0` + esp_nn_depthwise_conv_s8_ch_mult1(input_data, input_wd, input_ht, channels, input_offset, + pad_wd, pad_ht, stride_wd, stride_ht, + filter_data, filter_wd, filter_ht, + bias, out_data, out_wd, out_ht, out_offset, out_shift, + out_mult, activation_min, activation_max); + } + } else if (ch_mult % 8 == 0) { + esp_nn_s8_to_s16_esp32s3(filter_data, filter_data16, filter_size); + esp_nn_aligned_s8_to_s16_with_offset_esp32s3(input_data, input_data16, input_size, input_offset); + if (filter_wd == 3 && filter_ht == 3) { + esp_nn_depthwise_conv_s16_mult8_3x3_esp32s3(input_data16, input_wd, input_ht, channels, + pad_wd, pad_ht, stride_wd, stride_ht, ch_mult, + filter_data16, bias, + out_data, out_wd, out_ht, out_offset, out_shift, + out_mult, activation_min, activation_max); + } else { + esp_nn_depthwise_conv_s16_mult8_esp32s3(input_data16, input_wd, input_ht, channels, + pad_wd, pad_ht, stride_wd, stride_ht, ch_mult, + filter_data16, filter_wd, filter_ht, bias, + out_data, out_wd, out_ht, out_offset, out_shift, + out_mult, activation_min, activation_max); + } + } else if (ch_mult % 4 == 0) { + esp_nn_s8_to_s16_esp32s3(filter_data, filter_data16, filter_size); + esp_nn_aligned_s8_to_s16_with_offset_esp32s3(input_data, input_data16, input_size, input_offset); + esp_nn_depthwise_conv_s16_mult4_esp32s3(input_data16, input_wd, input_ht, channels, + pad_wd, pad_ht, stride_wd, stride_ht, ch_mult, + filter_data16, filter_wd, filter_ht, bias, + out_data, out_wd, out_ht, out_offset, out_shift, + out_mult, activation_min, activation_max); + } else { + esp_nn_depthwise_conv_s8_unrolled(input_data, input_wd, input_ht, channels, input_offset, + pad_wd, pad_ht, stride_wd, stride_ht, ch_mult, + filter_data, filter_wd, filter_ht, + bias, out_data, out_wd, out_ht, out_offset, out_shift, + out_mult, activation_min, activation_max); + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/fully_connected/esp_nn_fully_connected_ansi.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/fully_connected/esp_nn_fully_connected_ansi.c new file mode 100644 index 000000000..ddf3cce76 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/fully_connected/esp_nn_fully_connected_ansi.c @@ -0,0 +1,50 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "../common/common_functions.h" + +void esp_nn_fully_connected_s8_ansi(const int8_t *input_data, + const int32_t input_offset, + const uint16_t row_len, + const int8_t *filter_data, + const int32_t filter_offset, + const int32_t *bias, + int8_t *out_data, + const uint16_t out_channels, + const int32_t out_offset, + const int32_t out_shift, + const int32_t out_mult, + const int32_t activation_min, + const int32_t activation_max) +{ + for (int32_t out_c = 0; out_c < out_channels; ++out_c) { + int32_t result = 0; + for (int32_t data_idx = 0; data_idx < row_len; data_idx++) { + int32_t filter_index = row_len * out_c + data_idx; + int32_t input_val = input_data[data_idx]; + int32_t filter_val = filter_data[filter_index]; + result += (filter_val + filter_offset) * (input_val + input_offset); + } + if (bias) { + result += bias[out_c]; + } + result = esp_nn_multiply_by_quantized_mult(result, out_mult, out_shift); + result += out_offset; + result = max(result, activation_min); + result = min(result, activation_max); + out_data[out_c] = (int8_t) result; + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/pooling/esp_nn_avg_pool_ansi.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/pooling/esp_nn_avg_pool_ansi.c new file mode 100644 index 000000000..14ad9c3cc --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/pooling/esp_nn_avg_pool_ansi.c @@ -0,0 +1,72 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "../common/common_functions.h" + +void esp_nn_avg_pool_s8_ansi(const int8_t *input, + const uint16_t input_wd, + const uint16_t input_ht, + int8_t *output, + const uint16_t output_wd, + const uint16_t output_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t filter_wd, + const uint16_t filter_ht, + const uint16_t pad_wd, + const uint16_t pad_ht, + const int32_t activation_min, + const int32_t activation_max, + const uint16_t channels) +{ + int32_t base_y = -pad_ht; + for (int32_t out_y = 0; out_y < output_ht; out_y++, base_y += stride_ht) { + int32_t base_x = -pad_wd; + for (int32_t out_x = 0; out_x < output_wd; out_x++, base_x += stride_wd) { + for (int32_t ch_idx = 0; ch_idx < channels; ch_idx++) { + int32_t result = 0; + int32_t filter_cnt = 0; + /* Make sure filter does not cross the input box */ + int32_t filter_y_start = max(0, -base_y); + int32_t filter_x_start = max(0, -base_x); + + int32_t filter_y_end = min(filter_ht, input_ht - base_y); + int32_t filter_x_end = min(filter_wd, input_wd - base_x); + + for (int32_t filter_y = filter_y_start; filter_y < filter_y_end; filter_y++) { + for (int32_t filter_x = filter_x_start; filter_x < filter_x_end; filter_x++) { + int32_t in_x_idx = base_x + filter_x; + int32_t in_y_idx = base_y + filter_y; + int32_t input_index = (in_y_idx * input_wd + in_x_idx) * channels + ch_idx; + result += input[input_index]; + filter_cnt++; + } + } + + /* Rounded average */ + result = result > 0 ? (result + filter_cnt / 2) / filter_cnt + : (result - filter_cnt / 2) / filter_cnt; + + /* Activation function */ + result = max(result, activation_min); + result = min(result, activation_max); + + int32_t output_index = (out_y * output_wd + out_x) * channels + ch_idx; + output[output_index] = (int8_t) result; + } + } + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/pooling/esp_nn_max_pool_ansi.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/pooling/esp_nn_max_pool_ansi.c new file mode 100644 index 000000000..404cfe850 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/pooling/esp_nn_max_pool_ansi.c @@ -0,0 +1,66 @@ +// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "../common/common_functions.h" + +void esp_nn_max_pool_s8_ansi(const int8_t *input, + const uint16_t input_wd, + const uint16_t input_ht, + int8_t *output, + const uint16_t output_wd, + const uint16_t output_ht, + const uint16_t stride_wd, + const uint16_t stride_ht, + const uint16_t filter_wd, + const uint16_t filter_ht, + const uint16_t pad_wd, + const uint16_t pad_ht, + const int32_t activation_min, + const int32_t activation_max, + const uint16_t channels) +{ + int32_t base_y = -pad_ht; + for (int32_t out_y = 0; out_y < output_ht; out_y++, base_y += stride_ht) { + int32_t base_x = -pad_wd; + for (int32_t out_x = 0; out_x < output_wd; out_x++, base_x += stride_wd) { + /* Make sure filter does not cross the input box */ + int32_t filter_y_start = max(0, -base_y); + int32_t filter_x_start = max(0, -base_x); + int32_t filter_y_end = min(filter_ht, input_ht - base_y); + int32_t filter_x_end = min(filter_wd, input_wd - base_x); + + for (int32_t ch_idx = 0; ch_idx < channels; ch_idx++) { + int8_t result = INT8_MIN; + + for (int32_t filter_y = filter_y_start; filter_y < filter_y_end; filter_y++) { + for (int32_t filter_x = filter_x_start; filter_x < filter_x_end; filter_x++) { + int32_t in_x_idx = base_x + filter_x; + int32_t in_y_idx = base_y + filter_y; + int32_t input_index = (in_y_idx * input_wd + in_x_idx) * channels + ch_idx; + result = max(input[input_index], result); + } + } + + /* Activation function */ + result = max(result, activation_min); + result = min(result, activation_max); + + int32_t output_index = (out_y * output_wd + out_x) * channels + ch_idx; + output[output_index] = result; + } + } + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/esp_nn_softmax_ansi.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/esp_nn_softmax_ansi.c new file mode 100644 index 000000000..d71a8616f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/esp_nn_softmax_ansi.c @@ -0,0 +1,88 @@ +// Copyright 2022 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "softmax_common.h" + +int32_t esp_nn_get_softmax_scratch_size_ansi(const int32_t width, const int32_t height) +{ + (void) width; + (void) height; + return 0; +} + +void esp_nn_set_softmax_scratch_buf_ansi(void *buffer) +{ + (void) buffer; + return; +} + +void esp_nn_softmax_s8_ansi(const int8_t *input_data, + const int32_t height, + const int32_t width, + const int32_t mult, + const int32_t shift, + const int32_t diff_min, + int8_t *output_data) +{ + // The representation chosen for the input to the exp() function is Q5.26. + // We need to leave extra space since values that we skip might be as large as + // -32 before multiplying by input mult, and therefore as large as + // -16 afterwards. Note that exp(-8) is definitely not insignificant to + // accumulation, but exp(-16) definitely is. +#define ACCUM_BITS 12 +#define DIFF_BITS 5 + + const int32_t mask = (1 << shift); + int32_t col = 0; + const int8_t *in_ptr = input_data; + int8_t *out_ptr = output_data; + + for (int row_idx = 0; row_idx < height; row_idx++) { + int8_t max_in_row = in_ptr[0]; + for (col = 1; col < width; col++) { + max_in_row = max(max_in_row, in_ptr[col]); + } + + int32_t input_diff = 0; + int32_t sum_of_exps = 0; + + for (col = 0; col < width; col++) { + input_diff = in_ptr[col] - max_in_row; + if (input_diff >= diff_min) { + const int32_t input_diff_rescaled = SAT_HIGH_MUL(input_diff * mask, mult); + const int32_t exp_raw = esp_nn_exp_on_negative_values(input_diff_rescaled); + sum_of_exps += DIV_POW2(exp_raw, ACCUM_BITS); + } + } + + const int32_t headroom_plus1 = esp_nn_clz32((uint32_t) sum_of_exps); + const int32_t shifted_scale = ONE_OVER_ONE_X((sum_of_exps << headroom_plus1) - (1 << 31)); + const int32_t bits_over_unit = ACCUM_BITS - headroom_plus1 + 31 - sizeof(int8_t) * 8; + + for (col = 0; col < width; col++) { + input_diff = in_ptr[col] - max_in_row; + if (input_diff >= diff_min) { + const int32_t input_diff_rescaled = SAT_HIGH_MUL(input_diff * mask, mult); + const int32_t exp_raw = esp_nn_exp_on_negative_values(input_diff_rescaled); + const int32_t shifted_output = SAT_HIGH_MUL(shifted_scale, exp_raw); + const int32_t result = DIV_POW2(shifted_output, bits_over_unit) - 128; + out_ptr[col] = (int8_t) esp_nn_saturate8(result); + } else { + out_ptr[col] = -128; + } + } + in_ptr += width; + out_ptr += width; + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/esp_nn_softmax_opt.c b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/esp_nn_softmax_opt.c new file mode 100644 index 000000000..93337d32d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/esp_nn_softmax_opt.c @@ -0,0 +1,108 @@ +// Copyright 2022 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "softmax_common.h" +#include + +static int32_t *scratch_buf = NULL; + +/** + * @brief Get scratch buffer size needed by softmax function + * + * @param width + * @param height + * @return size in bytes + * + * @note buffer must be 4 byte aligned + */ +int32_t esp_nn_get_softmax_scratch_size_opt(const int32_t width, const int32_t height) +{ + (void) height; + return width * 4; +} + +/** + * @brief Set scratch buffer to be used by softmax function + * + * @param buffer this can be NULL if one needs to unset it + * must be aligned to 4 bytes + */ +void esp_nn_set_softmax_scratch_buf_opt(void *buffer) +{ + scratch_buf = (int32_t *) buffer; +} + +void esp_nn_softmax_s8_opt(const int8_t *input_data, + const int32_t height, + const int32_t width, + const int32_t mult, + const int32_t shift, + const int32_t diff_min, + int8_t *output_data) +{ + if (scratch_buf == NULL) { + printf("%s error! scratch buffer not set\n", __FUNCTION__); + return; + } + // The representation chosen for the input to the exp() function is Q5.26. + // We need to leave extra space since values that we skip might be as large as + // -32 before multiplying by input mult, and therefore as large as + // -16 afterwards. Note that exp(-8) is definitely not insignificant to + // accumulation, but exp(-16) definitely is. +#define ACCUM_BITS 12 +#define DIFF_BITS 5 + + const int32_t mask = (1 << shift); + int32_t col = 0; + const int8_t *in_ptr = input_data; + int8_t *out_ptr = output_data; + + for (int row_idx = 0; row_idx < height; row_idx++) { + int8_t max_in_row = in_ptr[0]; + for (col = 1; col < width; col++) { + max_in_row = max(max_in_row, in_ptr[col]); + } + + int32_t input_diff = 0; + int32_t sum_of_exps = 0; + + for (col = 0; col < width; col++) { + input_diff = in_ptr[col] - max_in_row; + if (input_diff >= diff_min) { + const int32_t input_diff_rescaled = SAT_HIGH_MUL(input_diff * mask, mult); + const int32_t exp_raw = esp_nn_exp_on_negative_values(input_diff_rescaled); + scratch_buf[col] = exp_raw; // store to avoid duplicate calculation later + sum_of_exps += DIV_POW2(exp_raw, ACCUM_BITS); + } + } + + const int32_t headroom_plus1 = esp_nn_clz32((uint32_t) sum_of_exps); + const int32_t shifted_scale = ONE_OVER_ONE_X((sum_of_exps << headroom_plus1) - (1 << 31)); + const int32_t bits_over_unit = ACCUM_BITS - headroom_plus1 + 31 - sizeof(int8_t) * 8; + + for (col = 0; col < width; col++) { + input_diff = in_ptr[col] - max_in_row; + if (input_diff >= diff_min) { + int32_t exp_raw = scratch_buf[col]; + const int32_t shifted_output = SAT_HIGH_MUL(shifted_scale, exp_raw); + const int32_t result = DIV_POW2(shifted_output, bits_over_unit) - 128; + out_ptr[col] = (int8_t) esp_nn_saturate8(result); + } else { + out_ptr[col] = -128; + } + } + in_ptr += width; + out_ptr += width; + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/softmax_common.h b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/softmax_common.h new file mode 100644 index 000000000..010036224 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/esp-nn/src/softmax/softmax_common.h @@ -0,0 +1,104 @@ +// Copyright 2022 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "../common/common_functions.h" + +#define MASK_IF_ZERO(x) (x) == 0 ? ~0 : 0 +#define MASK_IF_NON_ZERO(x) (x) != 0 ? ~0 : 0 +#define SELECT_USING_MASK(mask, a, b) ((mask) & (a)) ^ (~(mask) & (b)) +#define SAT_HIGH_MUL(x, y) esp_nn_sat_round_doubling_high_mul((x), (y)) +#define DIV_POW2(x,y) esp_nn_div_by_power_of_two((x), (y)) + +__NN_FORCE_INLINE__ int32_t mul_power_of_2(int val, int exp) +{ + const int32_t thresh = ((1 << (31 - exp)) - 1); + int32_t result = val << exp; + result = SELECT_USING_MASK(MASK_IF_NON_ZERO(val > thresh), INT32_MAX, result); + result = SELECT_USING_MASK(MASK_IF_NON_ZERO(val < -thresh), INT32_MIN, result); + return result; +} + +/** + * @brief Calculate `1 / (1 + x)` for x in [0, 1] + * + * @param val input value to calculate `1/(1+x)` for + * @return `int32_t` result + * @note Newton-Raphson division + * + * https://en.wikipedia.org/wiki/Division_algorithm#Newton.E2.80.93Raphson_division + * Refer to that page for the logic behind the 48/17 and 32/17 constants. + * Pseudocode: https://en.wikipedia.org/wiki/Division_algorithm#Pseudocode + */ +__NN_FORCE_INLINE__ int32_t esp_nn_one_over_one_plus_x_for_x_in_0_1(int32_t val) +{ + const int64_t sum = (int64_t) val + INT32_MAX; + const int32_t half_denominator = (int32_t) ((sum + (sum >= 0 ? 1 : -1)) / 2L); + int32_t constant_48_over_17 = 1515870810; + int32_t constant_neg_32_over_17 = -1010580540; + int32_t x = constant_48_over_17 + SAT_HIGH_MUL(half_denominator, constant_neg_32_over_17); + const int32_t fixed_2_one = (1 << 29); + + x += mul_power_of_2(SAT_HIGH_MUL(x, fixed_2_one - SAT_HIGH_MUL(half_denominator, x)), 2); + x += mul_power_of_2(SAT_HIGH_MUL(x, fixed_2_one - SAT_HIGH_MUL(half_denominator, x)), 2); + x += mul_power_of_2(SAT_HIGH_MUL(x, fixed_2_one - SAT_HIGH_MUL(half_denominator, x)), 2); + + return mul_power_of_2(x, 1); +} + +#define ONE_OVER_ONE_X(x) esp_nn_one_over_one_plus_x_for_x_in_0_1((x)) + +/** + * @brief Return exp(x) for x < 0. + * + */ +__NN_FORCE_INLINE__ int32_t esp_nn_exp_on_negative_values(int32_t val) +{ + int32_t shift = 24; + + const int32_t one_quarter = (1 << shift); + int32_t mask = one_quarter - 1; + const int32_t val_mod_minus_quarter = (val & mask) - one_quarter; + const int32_t remainder = val_mod_minus_quarter - val; + + // calculate exponent for x in [-1/4, 0) in `result` + const int32_t x = (val_mod_minus_quarter << 5) + (1 << 28); + const int32_t x2 = SAT_HIGH_MUL(x, x); + const int32_t x3 = SAT_HIGH_MUL(x2, x); + const int32_t x4 = SAT_HIGH_MUL(x2, x2); + const int32_t one_over_3 = 715827883; + const int32_t one_over_8 = 1895147668; + + const int32_t x4_over_4 = DIV_POW2(x4, 2); + const int32_t x4_over_4_plus_x3_over_6_plus_x2_over_2 = DIV_POW2(SAT_HIGH_MUL(x4_over_4 + x3, one_over_3) + x2, 1); + int32_t result = one_over_8 + SAT_HIGH_MUL(one_over_8, x + x4_over_4_plus_x3_over_6_plus_x2_over_2); + +#define SELECT_IF_NON_ZERO(x) { \ + mask = MASK_IF_NON_ZERO(remainder & (1 << shift++)); \ + result = SELECT_USING_MASK(mask, SAT_HIGH_MUL(result, x), result); \ +} + + SELECT_IF_NON_ZERO(1672461947) + SELECT_IF_NON_ZERO(1302514674) + SELECT_IF_NON_ZERO(790015084) + SELECT_IF_NON_ZERO(290630308) + SELECT_IF_NON_ZERO(39332535) + SELECT_IF_NON_ZERO(720401) + SELECT_IF_NON_ZERO(242) + +#undef SELECT_IF_NON_ZERO + + mask = MASK_IF_ZERO(val); + return SELECT_USING_MASK(mask, INT32_MAX, result); +} \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/builtin_op_data.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/builtin_op_data.h new file mode 100644 index 000000000..b9d428451 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/builtin_op_data.h @@ -0,0 +1,22 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +// Compatibility shim for new location of interface definitions. + +#ifndef TENSORFLOW_LITE_BUILTIN_OP_DATA_H_ +#define TENSORFLOW_LITE_BUILTIN_OP_DATA_H_ + +#include "tensorflow/lite/c/builtin_op_data.h" + +#endif // TENSORFLOW_LITE_BUILTIN_OP_DATA_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/builtin_ops.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/builtin_ops.h new file mode 100644 index 000000000..337073080 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/builtin_ops.h @@ -0,0 +1,194 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_BUILTIN_OPS_H_ +#define TENSORFLOW_LITE_BUILTIN_OPS_H_ + +// DO NOT EDIT MANUALLY: This file is automatically generated by +// `schema/builtin_ops_header/generator.cc`. + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// The enum for builtin operators. +// Note: CUSTOM, DELEGATE, and PLACEHOLDER_FOR_GREATER_OP_CODES are 3 special +// ops which are not real built-in ops. +typedef enum { + kTfLiteBuiltinAdd = 0, + kTfLiteBuiltinAveragePool2d = 1, + kTfLiteBuiltinConcatenation = 2, + kTfLiteBuiltinConv2d = 3, + kTfLiteBuiltinDepthwiseConv2d = 4, + kTfLiteBuiltinDepthToSpace = 5, + kTfLiteBuiltinDequantize = 6, + kTfLiteBuiltinEmbeddingLookup = 7, + kTfLiteBuiltinFloor = 8, + kTfLiteBuiltinFullyConnected = 9, + kTfLiteBuiltinHashtableLookup = 10, + kTfLiteBuiltinL2Normalization = 11, + kTfLiteBuiltinL2Pool2d = 12, + kTfLiteBuiltinLocalResponseNormalization = 13, + kTfLiteBuiltinLogistic = 14, + kTfLiteBuiltinLshProjection = 15, + kTfLiteBuiltinLstm = 16, + kTfLiteBuiltinMaxPool2d = 17, + kTfLiteBuiltinMul = 18, + kTfLiteBuiltinRelu = 19, + kTfLiteBuiltinReluN1To1 = 20, + kTfLiteBuiltinRelu6 = 21, + kTfLiteBuiltinReshape = 22, + kTfLiteBuiltinResizeBilinear = 23, + kTfLiteBuiltinRnn = 24, + kTfLiteBuiltinSoftmax = 25, + kTfLiteBuiltinSpaceToDepth = 26, + kTfLiteBuiltinSvdf = 27, + kTfLiteBuiltinTanh = 28, + kTfLiteBuiltinConcatEmbeddings = 29, + kTfLiteBuiltinSkipGram = 30, + kTfLiteBuiltinCall = 31, + kTfLiteBuiltinCustom = 32, + kTfLiteBuiltinEmbeddingLookupSparse = 33, + kTfLiteBuiltinPad = 34, + kTfLiteBuiltinUnidirectionalSequenceRnn = 35, + kTfLiteBuiltinGather = 36, + kTfLiteBuiltinBatchToSpaceNd = 37, + kTfLiteBuiltinSpaceToBatchNd = 38, + kTfLiteBuiltinTranspose = 39, + kTfLiteBuiltinMean = 40, + kTfLiteBuiltinSub = 41, + kTfLiteBuiltinDiv = 42, + kTfLiteBuiltinSqueeze = 43, + kTfLiteBuiltinUnidirectionalSequenceLstm = 44, + kTfLiteBuiltinStridedSlice = 45, + kTfLiteBuiltinBidirectionalSequenceRnn = 46, + kTfLiteBuiltinExp = 47, + kTfLiteBuiltinTopkV2 = 48, + kTfLiteBuiltinSplit = 49, + kTfLiteBuiltinLogSoftmax = 50, + kTfLiteBuiltinDelegate = 51, + kTfLiteBuiltinBidirectionalSequenceLstm = 52, + kTfLiteBuiltinCast = 53, + kTfLiteBuiltinPrelu = 54, + kTfLiteBuiltinMaximum = 55, + kTfLiteBuiltinArgMax = 56, + kTfLiteBuiltinMinimum = 57, + kTfLiteBuiltinLess = 58, + kTfLiteBuiltinNeg = 59, + kTfLiteBuiltinPadv2 = 60, + kTfLiteBuiltinGreater = 61, + kTfLiteBuiltinGreaterEqual = 62, + kTfLiteBuiltinLessEqual = 63, + kTfLiteBuiltinSelect = 64, + kTfLiteBuiltinSlice = 65, + kTfLiteBuiltinSin = 66, + kTfLiteBuiltinTransposeConv = 67, + kTfLiteBuiltinSparseToDense = 68, + kTfLiteBuiltinTile = 69, + kTfLiteBuiltinExpandDims = 70, + kTfLiteBuiltinEqual = 71, + kTfLiteBuiltinNotEqual = 72, + kTfLiteBuiltinLog = 73, + kTfLiteBuiltinSum = 74, + kTfLiteBuiltinSqrt = 75, + kTfLiteBuiltinRsqrt = 76, + kTfLiteBuiltinShape = 77, + kTfLiteBuiltinPow = 78, + kTfLiteBuiltinArgMin = 79, + kTfLiteBuiltinFakeQuant = 80, + kTfLiteBuiltinReduceProd = 81, + kTfLiteBuiltinReduceMax = 82, + kTfLiteBuiltinPack = 83, + kTfLiteBuiltinLogicalOr = 84, + kTfLiteBuiltinOneHot = 85, + kTfLiteBuiltinLogicalAnd = 86, + kTfLiteBuiltinLogicalNot = 87, + kTfLiteBuiltinUnpack = 88, + kTfLiteBuiltinReduceMin = 89, + kTfLiteBuiltinFloorDiv = 90, + kTfLiteBuiltinReduceAny = 91, + kTfLiteBuiltinSquare = 92, + kTfLiteBuiltinZerosLike = 93, + kTfLiteBuiltinFill = 94, + kTfLiteBuiltinFloorMod = 95, + kTfLiteBuiltinRange = 96, + kTfLiteBuiltinResizeNearestNeighbor = 97, + kTfLiteBuiltinLeakyRelu = 98, + kTfLiteBuiltinSquaredDifference = 99, + kTfLiteBuiltinMirrorPad = 100, + kTfLiteBuiltinAbs = 101, + kTfLiteBuiltinSplitV = 102, + kTfLiteBuiltinUnique = 103, + kTfLiteBuiltinCeil = 104, + kTfLiteBuiltinReverseV2 = 105, + kTfLiteBuiltinAddN = 106, + kTfLiteBuiltinGatherNd = 107, + kTfLiteBuiltinCos = 108, + kTfLiteBuiltinWhere = 109, + kTfLiteBuiltinRank = 110, + kTfLiteBuiltinElu = 111, + kTfLiteBuiltinReverseSequence = 112, + kTfLiteBuiltinMatrixDiag = 113, + kTfLiteBuiltinQuantize = 114, + kTfLiteBuiltinMatrixSetDiag = 115, + kTfLiteBuiltinRound = 116, + kTfLiteBuiltinHardSwish = 117, + kTfLiteBuiltinIf = 118, + kTfLiteBuiltinWhile = 119, + kTfLiteBuiltinNonMaxSuppressionV4 = 120, + kTfLiteBuiltinNonMaxSuppressionV5 = 121, + kTfLiteBuiltinScatterNd = 122, + kTfLiteBuiltinSelectV2 = 123, + kTfLiteBuiltinDensify = 124, + kTfLiteBuiltinSegmentSum = 125, + kTfLiteBuiltinBatchMatmul = 126, + kTfLiteBuiltinPlaceholderForGreaterOpCodes = 127, + kTfLiteBuiltinCumsum = 128, + kTfLiteBuiltinCallOnce = 129, + kTfLiteBuiltinBroadcastTo = 130, + kTfLiteBuiltinRfft2d = 131, + kTfLiteBuiltinConv3d = 132, + kTfLiteBuiltinImag = 133, + kTfLiteBuiltinReal = 134, + kTfLiteBuiltinComplexAbs = 135, + kTfLiteBuiltinHashtable = 136, + kTfLiteBuiltinHashtableFind = 137, + kTfLiteBuiltinHashtableImport = 138, + kTfLiteBuiltinHashtableSize = 139, + kTfLiteBuiltinReduceAll = 140, + kTfLiteBuiltinConv3dTranspose = 141, + kTfLiteBuiltinVarHandle = 142, + kTfLiteBuiltinReadVariable = 143, + kTfLiteBuiltinAssignVariable = 144, + kTfLiteBuiltinBroadcastArgs = 145, + kTfLiteBuiltinRandomStandardNormal = 146, + kTfLiteBuiltinBucketize = 147, + kTfLiteBuiltinRandomUniform = 148, + kTfLiteBuiltinMultinomial = 149, + kTfLiteBuiltinGelu = 150, + kTfLiteBuiltinDynamicUpdateSlice = 151, + kTfLiteBuiltinRelu0To1 = 152, + kTfLiteBuiltinUnsortedSegmentProd = 153, + kTfLiteBuiltinUnsortedSegmentMax = 154, + kTfLiteBuiltinUnsortedSegmentSum = 155, + kTfLiteBuiltinAtan2 = 156, + kTfLiteBuiltinUnsortedSegmentMin = 157, + kTfLiteBuiltinSign = 158, +} TfLiteBuiltinOperator; + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus +#endif // TENSORFLOW_LITE_BUILTIN_OPS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/builtin_op_data.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/builtin_op_data.h new file mode 100644 index 000000000..7f160972e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/builtin_op_data.h @@ -0,0 +1,525 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_C_BUILTIN_OP_DATA_H_ +#define TENSORFLOW_LITE_C_BUILTIN_OP_DATA_H_ + +#include + +#include "tensorflow/lite/c/common.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// TfLiteReshapeParams can't have dynamic data so we fix the maximum possible +// number of dimensions. +#define TFLITE_RESHAPE_PARAMS_MAX_DIMENSION_COUNT 8 + +// TODO(aselle): Consider using "if this then that" for testing. + +// Useful placeholder to put in otherwise empty structs to avoid size warnings. +typedef struct { + char dummy; +} EmptyStructPlaceholder; + +// IMPORTANT: All new members of structs must be added at the end to ensure +// backwards compatibility. + +// Possible padding types (for convolutions) +typedef enum { + kTfLitePaddingUnknown = 0, + kTfLitePaddingSame, + kTfLitePaddingValid, +} TfLitePadding; + +typedef enum { + kTfLiteMirrorPaddingUnknown = 0, + kTfLiteMirrorPaddingReflect, + kTfLiteMirrorPaddingSymmetric, +} TfLiteMirrorPaddingMode; + +// TODO(b/130259536): We should move this out of builtin_op_data. +typedef struct { + int width; + int height; + int width_offset; + int height_offset; +} TfLitePaddingValues; + +typedef struct { + TfLiteMirrorPaddingMode mode; +} TfLiteMirrorPaddingParams; + +// Possible fused activation functions. +typedef enum { + kTfLiteActNone = 0, + kTfLiteActRelu, + kTfLiteActReluN1To1, // min(max(-1, x), 1) + kTfLiteActRelu6, // min(max(0, x), 6) + kTfLiteActTanh, + kTfLiteActSignBit, + kTfLiteActSigmoid, +} TfLiteFusedActivation; + +typedef struct { + // Parameters for CONV_2D version 1. + TfLitePadding padding; + int stride_width; + int stride_height; + TfLiteFusedActivation activation; + + // Parameters for CONV_2D version 2. + // Note: Version 2 supports dilation values not equal to 1. + int dilation_width_factor; + int dilation_height_factor; +} TfLiteConvParams; + +typedef struct { + TfLitePadding padding; + int stride_width; + int stride_height; + int stride_depth; + int dilation_width_factor; + int dilation_height_factor; + int dilation_depth_factor; + TfLiteFusedActivation activation; +} TfLiteConv3DParams; + +typedef TfLiteConv3DParams TfLiteConv3DTransposeParams; + +typedef struct { + TfLitePadding padding; + int stride_width; + int stride_height; + int filter_width; + int filter_height; + TfLiteFusedActivation activation; + struct { + TfLitePaddingValues padding; + } computed; +} TfLitePoolParams; + +typedef struct { + // Parameters for DepthwiseConv version 1 or above. + TfLitePadding padding; + int stride_width; + int stride_height; + // `depth_multiplier` is redundant. It's used by CPU kernels in + // TensorFlow 2.0 or below, but ignored in versions above. + // + // The information can be deduced from the shape of input and the shape of + // weights. Since the TFLiteConverter toolchain doesn't support partially + // specified shapes, relying on `depth_multiplier` stops us from supporting + // graphs with dynamic shape tensors. + // + // Note: Some of the delegates (e.g. NNAPI, GPU) are still relying on this + // field. + int depth_multiplier; + TfLiteFusedActivation activation; + // Parameters for DepthwiseConv version 2 or above. + int dilation_width_factor; + int dilation_height_factor; +} TfLiteDepthwiseConvParams; + +typedef struct { + int rank; + TfLiteFusedActivation activation; + + // Parameter for SVDF version 4. + bool asymmetric_quantize_inputs; +} TfLiteSVDFParams; + +typedef struct { + TfLiteFusedActivation activation; + + // Parameter for RNN version 3. + bool asymmetric_quantize_inputs; +} TfLiteRNNParams; + +typedef struct { + bool time_major; + TfLiteFusedActivation activation; + + // Parameter for Sequence RNN version 3. + bool asymmetric_quantize_inputs; +} TfLiteSequenceRNNParams; + +typedef struct { + bool time_major; + TfLiteFusedActivation activation; + bool merge_outputs; + + // Parameter for Bidirectional RNN verison 3. + bool asymmetric_quantize_inputs; +} TfLiteBidirectionalSequenceRNNParams; + +typedef enum { + kTfLiteFullyConnectedWeightsFormatDefault = 0, + kTfLiteFullyConnectedWeightsFormatShuffled4x16Int8 = 1, +} TfLiteFullyConnectedWeightsFormat; + +typedef struct { + // Parameters for FullyConnected version 1 or above. + TfLiteFusedActivation activation; + + // Parameters for FullyConnected version 2 or above. + TfLiteFullyConnectedWeightsFormat weights_format; + + // Parameters for FullyConnected version 5 or above. + // If set to true, then the number of dimensions in the input and the output + // tensors are the same. Furthermore, all but the last dimension of the input + // and output shapes will be equal. + bool keep_num_dims; + + // Parameters for FullyConnected version 7 or above. + // If set to true and the weights are quantized, then non constant inputs + // are quantized at evaluation time with asymmetric quantization. + bool asymmetric_quantize_inputs; +} TfLiteFullyConnectedParams; + +typedef enum { + kTfLiteLshProjectionUnknown = 0, + kTfLiteLshProjectionSparse = 1, + kTfLiteLshProjectionDense = 2, +} TfLiteLSHProjectionType; + +typedef struct { + TfLiteLSHProjectionType type; +} TfLiteLSHProjectionParams; + +typedef struct { + float beta; +} TfLiteSoftmaxParams; + +typedef struct { + int axis; + TfLiteFusedActivation activation; +} TfLiteConcatenationParams; + +typedef struct { + TfLiteFusedActivation activation; + // Parameter added for the version 4. + bool pot_scale_int16; +} TfLiteAddParams; + +typedef struct { + EmptyStructPlaceholder placeholder; +} TfLiteSpaceToBatchNDParams; + +typedef struct { + EmptyStructPlaceholder placeholder; +} TfLiteBatchToSpaceNDParams; + +typedef struct { + bool adj_x; + bool adj_y; + // Parameters for BatchMatMul version 4 or above. + // If set to true and the weights are quantized, then non constant inputs + // are quantized at evaluation time with asymmetric quantization. + bool asymmetric_quantize_inputs; +} TfLiteBatchMatMulParams; + +typedef struct { + TfLiteFusedActivation activation; +} TfLiteMulParams; + +typedef struct { + TfLiteFusedActivation activation; + // Parameter added for the version 5. + bool pot_scale_int16; +} TfLiteSubParams; + +typedef struct { + TfLiteFusedActivation activation; +} TfLiteDivParams; + +typedef struct { + TfLiteFusedActivation activation; +} TfLiteL2NormParams; + +typedef struct { + int radius; + float bias; + float alpha; + float beta; +} TfLiteLocalResponseNormParams; + +typedef enum { + kTfLiteLSTMFullKernel = 0, + kTfLiteLSTMBasicKernel +} TfLiteLSTMKernelType; + +typedef struct { + // Parameters for LSTM version 1. + TfLiteFusedActivation activation; + float cell_clip; + float proj_clip; + + // Parameters for LSTM version 2. + // kTfLiteLSTMBasicKernel is only supported in version 2 or above. + TfLiteLSTMKernelType kernel_type; + + // Parameters for LSTM version 4. + bool asymmetric_quantize_inputs; +} TfLiteLSTMParams; + +typedef struct { + // Parameters needed for the underlying LSTM. + TfLiteFusedActivation activation; + float cell_clip; + float proj_clip; + + // If set to true then the first dimension is time, otherwise batch. + bool time_major; + + // Parameter for unidirectional sequence RNN version 3. + bool asymmetric_quantize_inputs; +} TfLiteUnidirectionalSequenceLSTMParams; + +typedef struct { + // Parameters supported by version 1: + // Parameters inherited for the LSTM kernel. + TfLiteFusedActivation activation; + float cell_clip; + float proj_clip; + + // If true, store the outputs of both directions in the first output. + bool merge_outputs; + + // Parameters supported by version 2: + // If set to true then the first dimension is time, otherwise batch. + bool time_major; + + // Parameters supported by version 4: + // If set to true, then hybrid ops use asymmetric quantization for inputs. + bool asymmetric_quantize_inputs; +} TfLiteBidirectionalSequenceLSTMParams; + +typedef struct { + bool align_corners; + // half_pixel_centers assumes pixels are of half the actual dimensions, and + // yields more accurate resizes. Corresponds to the same argument for the + // original TensorFlow op in TF2.0. + bool half_pixel_centers; +} TfLiteResizeBilinearParams; + +typedef struct { + bool align_corners; + bool half_pixel_centers; +} TfLiteResizeNearestNeighborParams; + +typedef struct { + EmptyStructPlaceholder placeholder; +} TfLitePadParams; + +typedef struct { + EmptyStructPlaceholder placeholder; +} TfLitePadV2Params; + +typedef struct { + // These fields are only used in old models for backward compatibility. + // In the current implementation, we use the 2nd input of the op as the shape, + // and these fields are unused. + int shape[TFLITE_RESHAPE_PARAMS_MAX_DIMENSION_COUNT]; + int num_dimensions; +} TfLiteReshapeParams; + +typedef struct { + int ngram_size; + int max_skip_size; + bool include_all_ngrams; +} TfLiteSkipGramParams; + +typedef struct { + int block_size; +} TfLiteSpaceToDepthParams; + +typedef struct { + int block_size; +} TfLiteDepthToSpaceParams; + +typedef struct { + TfLiteType in_data_type; + TfLiteType out_data_type; +} TfLiteCastParams; + +typedef enum { + kTfLiteCombinerTypeSum = 0, + kTfLiteCombinerTypeMean = 1, + kTfLiteCombinerTypeSqrtn = 2, +} TfLiteCombinerType; + +typedef struct { + TfLiteCombinerType combiner; +} TfLiteEmbeddingLookupSparseParams; + +typedef struct { + int axis; + int batch_dims; +} TfLiteGatherParams; + +typedef struct { + EmptyStructPlaceholder placeholder; +} TfLiteTransposeParams; + +typedef struct { + bool keep_dims; +} TfLiteReducerParams; + +typedef struct { + int num_splits; +} TfLiteSplitParams; + +typedef struct { + int num_splits; +} TfLiteSplitVParams; + +typedef struct { + // TODO(ahentz): We can't have dynamic data in this struct, at least not yet. + // For now we will fix the maximum possible number of dimensions. + int squeeze_dims[8]; + int num_squeeze_dims; +} TfLiteSqueezeParams; + +typedef struct { + int begin_mask; + int end_mask; + int ellipsis_mask; + int new_axis_mask; + int shrink_axis_mask; +} TfLiteStridedSliceParams; + +typedef struct { + TfLiteType output_type; +} TfLiteArgMaxParams; + +typedef struct { + TfLiteType output_type; +} TfLiteArgMinParams; + +typedef struct { + TfLitePadding padding; + int stride_width; + int stride_height; +} TfLiteTransposeConvParams; + +typedef struct { + bool validate_indices; +} TfLiteSparseToDenseParams; + +typedef struct { + TfLiteType out_type; +} TfLiteShapeParams; + +typedef struct { + EmptyStructPlaceholder placeholder; +} TfLiteRankParams; + +typedef struct { + // Parameters supported by version 1: + float min; + float max; + int num_bits; + + // Parameters supported by version 2: + bool narrow_range; +} TfLiteFakeQuantParams; + +typedef struct { + int values_count; + int axis; +} TfLitePackParams; + +typedef struct { + int axis; +} TfLiteOneHotParams; + +typedef struct { + int num; + int axis; +} TfLiteUnpackParams; + +typedef struct { + float alpha; +} TfLiteLeakyReluParams; + +typedef struct { + TfLiteType index_out_type; +} TfLiteUniqueParams; + +typedef struct { + int seq_dim; + int batch_dim; +} TfLiteReverseSequenceParams; + +typedef struct { + EmptyStructPlaceholder placeholder; +} TfLiteMatrixDiagParams; + +typedef struct { + EmptyStructPlaceholder placeholder; +} TfLiteMatrixSetDiagParams; + +typedef struct { + int then_subgraph_index; + int else_subgraph_index; +} TfLiteIfParams; + +typedef struct { + int cond_subgraph_index; + int body_subgraph_index; +} TfLiteWhileParams; + +typedef struct { + bool exclusive; + bool reverse; +} TfLiteCumsumParams; + +typedef struct { + int init_subgraph_index; +} TfLiteCallOnceParams; + +typedef struct { + int table_id; + TfLiteType key_dtype; + TfLiteType value_dtype; +} TfLiteHashtableParams; + +typedef struct { + const char* container; + const char* shared_name; +} TfLiteVarHandleParams; + +typedef struct { + int seed; + int seed2; +} TfLiteRandomParams; + +typedef struct { + int num_boundaries; + // This points to the memory stored in the model (flatbuffer), + // and is not owned. + const float* boundaries; +} TfLiteBucketizeParams; + +typedef struct { + bool approximate; +} TfLiteGeluParams; + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // TENSORFLOW_LITE_C_BUILTIN_OP_DATA_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/c_api_types.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/c_api_types.h new file mode 100644 index 000000000..9d7668e13 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/c_api_types.h @@ -0,0 +1,147 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This file declares types used by the pure C inference API defined in c_api.h, +// some of which are also used in the C++ and C kernel and interpreter APIs. + +#ifndef TENSORFLOW_LITE_C_C_API_TYPES_H_ +#define TENSORFLOW_LITE_C_C_API_TYPES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Define TFL_CAPI_EXPORT macro to export a function properly with a shared +// library. +#ifdef SWIG +#define TFL_CAPI_EXPORT +#elif defined(TFL_STATIC_LIBRARY_BUILD) +#define TFL_CAPI_EXPORT +#else // not definded TFL_STATIC_LIBRARY_BUILD +#if defined(_WIN32) +#ifdef TFL_COMPILE_LIBRARY +#define TFL_CAPI_EXPORT __declspec(dllexport) +#else +#define TFL_CAPI_EXPORT __declspec(dllimport) +#endif // TFL_COMPILE_LIBRARY +#else +#define TFL_CAPI_EXPORT __attribute__((visibility("default"))) +#endif // _WIN32 +#endif // SWIG + +// Note that new error status values may be added in future in order to +// indicate more fine-grained internal states, therefore, applications should +// not rely on status values being members of the enum. +typedef enum TfLiteStatus { + kTfLiteOk = 0, + + // Generally referring to an error in the runtime (i.e. interpreter) + kTfLiteError = 1, + + // Generally referring to an error from a TfLiteDelegate itself. + kTfLiteDelegateError = 2, + + // Generally referring to an error in applying a delegate due to + // incompatibility between runtime and delegate, e.g., this error is returned + // when trying to apply a TF Lite delegate onto a model graph that's already + // immutable. + kTfLiteApplicationError = 3, + + // Generally referring to serialized delegate data not being found. + // See tflite::delegates::Serialization. + kTfLiteDelegateDataNotFound = 4, + + // Generally referring to data-writing issues in delegate serialization. + // See tflite::delegates::Serialization. + kTfLiteDelegateDataWriteError = 5, + + // Generally referring to data-reading issues in delegate serialization. + // See tflite::delegates::Serialization. + kTfLiteDelegateDataReadError = 6, + + // Generally referring to issues when the TF Lite model has ops that cannot be + // resolved at runtime. This could happen when the specific op is not + // registered or built with the TF Lite framework. + kTfLiteUnresolvedOps = 7, + + // Generally referring to invocation cancelled by the user. + // See `interpreter::Cancel`. + // TODO(b/194915839): Implement `interpreter::Cancel`. + // TODO(b/250636993): Cancellation triggered by `SetCancellationFunction` + // should also return this status code. + kTfLiteCancelled = 8, +} TfLiteStatus; + +// Types supported by tensor +typedef enum { + kTfLiteNoType = 0, + kTfLiteFloat32 = 1, + kTfLiteInt32 = 2, + kTfLiteUInt8 = 3, + kTfLiteInt64 = 4, + kTfLiteString = 5, + kTfLiteBool = 6, + kTfLiteInt16 = 7, + kTfLiteComplex64 = 8, + kTfLiteInt8 = 9, + kTfLiteFloat16 = 10, + kTfLiteFloat64 = 11, + kTfLiteComplex128 = 12, + kTfLiteUInt64 = 13, + kTfLiteResource = 14, + kTfLiteVariant = 15, + kTfLiteUInt32 = 16, + kTfLiteUInt16 = 17, + kTfLiteInt4 = 18, +} TfLiteType; + +// Legacy. Will be deprecated in favor of TfLiteAffineQuantization. +// If per-layer quantization is specified this field will still be populated in +// addition to TfLiteAffineQuantization. +// Parameters for asymmetric quantization. Quantized values can be converted +// back to float using: +// real_value = scale * (quantized_value - zero_point) +typedef struct TfLiteQuantizationParams { + float scale; + int32_t zero_point; +} TfLiteQuantizationParams; + +// -------------------------------------------------------------------------- +// Opaque types used by c_api.h, c_api_opaque.h and common.h. + +// TfLiteOpaqueContext is an opaque version of TfLiteContext; +typedef struct TfLiteOpaqueContext TfLiteOpaqueContext; + +// TfLiteOpaqueNode is an opaque version of TfLiteNode; +typedef struct TfLiteOpaqueNode TfLiteOpaqueNode; + +// TfLiteOpaqueTensor is an opaque version of TfLiteTensor; +typedef struct TfLiteOpaqueTensor TfLiteOpaqueTensor; + +// TfLiteOpaqueDelegateStruct: opaque version of TfLiteDelegate; allows +// delegation of nodes to alternative backends. +// +// This is an abstract type that is intended to have the same +// role as TfLiteDelegate from common.h, but without exposing the implementation +// details of how delegates are implemented. +// WARNING: This is an experimental type and subject to change. +typedef struct TfLiteOpaqueDelegateStruct TfLiteOpaqueDelegateStruct; + +#ifdef __cplusplus +} // extern C +#endif +#endif // TENSORFLOW_LITE_C_C_API_TYPES_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/common.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/common.cpp new file mode 100644 index 000000000..4e87300af --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/common.cpp @@ -0,0 +1,321 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/common.h" + +#include "tensorflow/lite/c/c_api_types.h" +#ifdef TF_LITE_TENSORFLOW_PROFILER +#include "tensorflow/lite/tensorflow_profiler_logger.h" +#endif + +#ifndef ARDUINO +#include +#include +#endif // ARDUINO + +extern "C" { + +size_t TfLiteIntArrayGetSizeInBytes(int size) { + static TfLiteIntArray dummy; + + size_t computed_size = sizeof(dummy) + sizeof(dummy.data[0]) * size; +#if defined(_MSC_VER) + // Context for why this is needed is in http://b/189926408#comment21 + computed_size -= sizeof(dummy.data[0]); +#endif + return computed_size; +} + +int TfLiteIntArrayEqual(const TfLiteIntArray* a, const TfLiteIntArray* b) { + if (a == b) return 1; + if (a == nullptr || b == nullptr) return 0; + return TfLiteIntArrayEqualsArray(a, b->size, b->data); +} + +int TfLiteIntArrayEqualsArray(const TfLiteIntArray* a, int b_size, + const int b_data[]) { + if (a == nullptr) return (b_size == 0); + if (a->size != b_size) return 0; + int i = 0; + for (; i < a->size; i++) + if (a->data[i] != b_data[i]) return 0; + return 1; +} + +#ifndef ARDUINO + +TfLiteIntArray* TfLiteIntArrayCreate(int size) { + size_t alloc_size = TfLiteIntArrayGetSizeInBytes(size); + if (alloc_size <= 0) return nullptr; + TfLiteIntArray* ret = (TfLiteIntArray*)malloc(alloc_size); + if (!ret) return ret; + ret->size = size; + return ret; +} + +TfLiteIntArray* TfLiteIntArrayCopy(const TfLiteIntArray* src) { + if (!src) return nullptr; + TfLiteIntArray* ret = TfLiteIntArrayCreate(src->size); + if (ret) { + memcpy(ret->data, src->data, src->size * sizeof(int)); + } + return ret; +} + +void TfLiteIntArrayFree(TfLiteIntArray* a) { free(a); } + +#endif // ARDUINO + +int TfLiteFloatArrayGetSizeInBytes(int size) { + static TfLiteFloatArray dummy; + + int computed_size = sizeof(dummy) + sizeof(dummy.data[0]) * size; +#if defined(_MSC_VER) + // Context for why this is needed is in http://b/189926408#comment21 + computed_size -= sizeof(dummy.data[0]); +#endif + return computed_size; +} + +#ifndef ARDUINO + +TfLiteFloatArray* TfLiteFloatArrayCreate(int size) { + TfLiteFloatArray* ret = + (TfLiteFloatArray*)malloc(TfLiteFloatArrayGetSizeInBytes(size)); + ret->size = size; + return ret; +} + +void TfLiteFloatArrayFree(TfLiteFloatArray* a) { free(a); } + +void TfLiteTensorDataFree(TfLiteTensor* t) { + if (t->allocation_type == kTfLiteDynamic || + t->allocation_type == kTfLitePersistentRo) { + if (t->data.raw) { +#ifdef TF_LITE_TENSORFLOW_PROFILER + tflite::OnTfLiteTensorDealloc(t); +#endif + free(t->data.raw); + } + } + t->data.raw = nullptr; +} + +void TfLiteQuantizationFree(TfLiteQuantization* quantization) { + if (quantization->type == kTfLiteAffineQuantization) { + TfLiteAffineQuantization* q_params = + (TfLiteAffineQuantization*)(quantization->params); + if (q_params->scale) { + TfLiteFloatArrayFree(q_params->scale); + q_params->scale = nullptr; + } + if (q_params->zero_point) { + TfLiteIntArrayFree(q_params->zero_point); + q_params->zero_point = nullptr; + } + free(q_params); + } + quantization->params = nullptr; + quantization->type = kTfLiteNoQuantization; +} + +void TfLiteSparsityFree(TfLiteSparsity* sparsity) { + if (sparsity == nullptr) { + return; + } + + if (sparsity->traversal_order) { + TfLiteIntArrayFree(sparsity->traversal_order); + sparsity->traversal_order = nullptr; + } + + if (sparsity->block_map) { + TfLiteIntArrayFree(sparsity->block_map); + sparsity->block_map = nullptr; + } + + if (sparsity->dim_metadata) { + int i = 0; + for (; i < sparsity->dim_metadata_size; i++) { + TfLiteDimensionMetadata metadata = sparsity->dim_metadata[i]; + if (metadata.format == kTfLiteDimSparseCSR) { + TfLiteIntArrayFree(metadata.array_segments); + metadata.array_segments = nullptr; + TfLiteIntArrayFree(metadata.array_indices); + metadata.array_indices = nullptr; + } + } + free(sparsity->dim_metadata); + sparsity->dim_metadata = nullptr; + } + + free(sparsity); +} + +void TfLiteTensorFree(TfLiteTensor* t) { + TfLiteTensorDataFree(t); + if (t->dims) TfLiteIntArrayFree(t->dims); + t->dims = nullptr; + + if (t->dims_signature) { + TfLiteIntArrayFree((TfLiteIntArray*)t->dims_signature); + } + t->dims_signature = nullptr; + + TfLiteQuantizationFree(&t->quantization); + TfLiteSparsityFree(t->sparsity); + t->sparsity = nullptr; +} + +void TfLiteTensorReset(TfLiteType type, const char* name, TfLiteIntArray* dims, + TfLiteQuantizationParams quantization, char* buffer, + size_t size, TfLiteAllocationType allocation_type, + const void* allocation, bool is_variable, + TfLiteTensor* tensor) { + TfLiteTensorFree(tensor); + tensor->type = type; + tensor->name = name; + tensor->dims = dims; + tensor->params = quantization; + tensor->data.raw = buffer; + tensor->bytes = size; + tensor->allocation_type = allocation_type; + tensor->allocation = allocation; + tensor->is_variable = is_variable; + + tensor->quantization.type = kTfLiteNoQuantization; + tensor->quantization.params = nullptr; +} + +TfLiteStatus TfLiteTensorCopy(const TfLiteTensor* src, TfLiteTensor* dst) { + if (!src || !dst) return kTfLiteOk; + if (src->bytes != dst->bytes) return kTfLiteError; + if (src == dst) return kTfLiteOk; + + dst->type = src->type; + if (dst->dims) TfLiteIntArrayFree(dst->dims); + dst->dims = TfLiteIntArrayCopy(src->dims); + memcpy(dst->data.raw, src->data.raw, src->bytes); + dst->buffer_handle = src->buffer_handle; + dst->data_is_stale = src->data_is_stale; + dst->delegate = src->delegate; + + return kTfLiteOk; +} + +void TfLiteTensorResizeMaybeCopy(size_t num_bytes, TfLiteTensor* tensor, + bool preserve_data) { + if (tensor->allocation_type != kTfLiteDynamic && + tensor->allocation_type != kTfLitePersistentRo) { + return; + } + // TODO(b/145340303): Tensor data should be aligned. + if (!tensor->data.data) { + tensor->data.data = (char*)malloc(num_bytes); +#ifdef TF_LITE_TENSORFLOW_PROFILER + tflite::OnTfLiteTensorAlloc(tensor, num_bytes); +#endif + } else if (num_bytes > tensor->bytes) { +#ifdef TF_LITE_TENSORFLOW_PROFILER + tflite::OnTfLiteTensorDealloc(tensor); +#endif + if (preserve_data) { + tensor->data.data = (char*)realloc(tensor->data.data, num_bytes); + } else { + // Calling free and malloc can be more efficient as it avoids needlessly + // copying the data when it is not required. + free(tensor->data.data); + tensor->data.data = (char*)malloc(num_bytes); + } +#ifdef TF_LITE_TENSORFLOW_PROFILER + tflite::OnTfLiteTensorAlloc(tensor, num_bytes); +#endif + } + tensor->bytes = num_bytes; +} + +void TfLiteTensorRealloc(size_t num_bytes, TfLiteTensor* tensor) { + return TfLiteTensorResizeMaybeCopy(num_bytes, tensor, true); +} +#endif // ARDUINO + +const char* TfLiteTypeGetName(TfLiteType type) { + switch (type) { + case kTfLiteNoType: + return "NOTYPE"; + case kTfLiteFloat32: + return "FLOAT32"; + case kTfLiteUInt16: + return "UINT16"; + case kTfLiteInt16: + return "INT16"; + case kTfLiteInt32: + return "INT32"; + case kTfLiteUInt32: + return "UINT32"; + case kTfLiteUInt8: + return "UINT8"; + case kTfLiteInt8: + return "INT8"; + case kTfLiteInt64: + return "INT64"; + case kTfLiteUInt64: + return "UINT64"; + case kTfLiteBool: + return "BOOL"; + case kTfLiteComplex64: + return "COMPLEX64"; + case kTfLiteComplex128: + return "COMPLEX128"; + case kTfLiteString: + return "STRING"; + case kTfLiteFloat16: + return "FLOAT16"; + case kTfLiteFloat64: + return "FLOAT64"; + case kTfLiteResource: + return "RESOURCE"; + case kTfLiteVariant: + return "VARIANT"; + case kTfLiteInt4: + return "INT4"; + } + return "Unknown type"; +} + +TfLiteDelegate TfLiteDelegateCreate() { return TfLiteDelegate{}; } + +struct TfLiteOpaqueDelegateStruct* TfLiteOpaqueDelegateCreate( + const TfLiteOpaqueDelegateBuilder* opaque_delegate_builder) { + if (!opaque_delegate_builder) return nullptr; + + TfLiteDelegate* result = new TfLiteDelegate{}; + result->opaque_delegate_builder = new TfLiteOpaqueDelegateBuilder{}; + *(result->opaque_delegate_builder) = *opaque_delegate_builder; + + return reinterpret_cast(result); +} + +void TfLiteOpaqueDelegateDelete( + const struct TfLiteOpaqueDelegateStruct* opaque_delegate) { + if (!opaque_delegate) return; + + const TfLiteDelegate* tflite_delegate = + reinterpret_cast(opaque_delegate); + delete tflite_delegate->opaque_delegate_builder; + delete tflite_delegate; +} + +} // extern "C" diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/common.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/common.h new file mode 100644 index 000000000..08909ab08 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/c/common.h @@ -0,0 +1,1110 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This file defines common C types and APIs for implementing operations, +// delegates and other constructs in TensorFlow Lite. The actual operations and +// delegates can be defined using C++, but the interface between the interpreter +// and the operations are C. +// +// Summary of abstractions +// TF_LITE_ENSURE - Self-sufficient error checking +// TfLiteStatus - Status reporting +// TfLiteIntArray - stores tensor shapes (dims), +// TfLiteContext - allows an op to access the tensors +// TfLiteTensor - tensor (a multidimensional array) +// TfLiteNode - a single node or operation +// TfLiteRegistration - the implementation of a conceptual operation. +// TfLiteDelegate - allows delegation of nodes to alternative backends. +// +// Some abstractions in this file are created and managed by Interpreter. +// +// NOTE: The order of values in these structs are "semi-ABI stable". New values +// should be added only to the end of structs and never reordered. + +#ifndef TENSORFLOW_LITE_C_COMMON_H_ +#define TENSORFLOW_LITE_C_COMMON_H_ + +#include +#include +#include + +#include "tensorflow/lite/c/c_api_types.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// The list of external context types known to TF Lite. This list exists solely +// to avoid conflicts and to ensure ops can share the external contexts they +// need. Access to the external contexts is controlled by one of the +// corresponding support files. +typedef enum TfLiteExternalContextType { + kTfLiteEigenContext = 0, // include eigen_support.h to use. + kTfLiteGemmLowpContext = 1, // include gemm_support.h to use. + kTfLiteEdgeTpuContext = 2, // Placeholder for Edge TPU support. + kTfLiteCpuBackendContext = 3, // include cpu_backend_context.h to use. + kTfLiteMaxExternalContexts = 4 +} TfLiteExternalContextType; + +// Forward declare so dependent structs and methods can reference these types +// prior to the struct definitions. +struct TfLiteContext; +struct TfLiteDelegate; +struct TfLiteRegistration; +struct TfLiteOpaqueDelegateStruct; +struct TfLiteOpaqueDelegateBuilder; + +// An external context is a collection of information unrelated to the TF Lite +// framework, but useful to a subset of the ops. TF Lite knows very little +// about the actual contexts, but it keeps a list of them, and is able to +// refresh them if configurations like the number of recommended threads +// change. +typedef struct TfLiteExternalContext { + TfLiteExternalContextType type; + TfLiteStatus (*Refresh)(struct TfLiteContext* context); +} TfLiteExternalContext; + +#define kTfLiteOptionalTensor (-1) + +// Fixed size list of integers. Used for dimensions and inputs/outputs tensor +// indices +typedef struct TfLiteIntArray { + int size; + +#if defined(_MSC_VER) + // Context for why this is needed is in http://b/189926408#comment21 + int data[1]; +#elif (!defined(__clang__) && defined(__GNUC__) && __GNUC__ == 6 && \ + __GNUC_MINOR__ >= 1) || \ + defined(HEXAGON) || \ + (defined(__clang__) && __clang_major__ == 7 && __clang_minor__ == 1) + // gcc 6.1+ have a bug where flexible members aren't properly handled + // https://github.com/google/re2/commit/b94b7cd42e9f02673cd748c1ac1d16db4052514c + int data[0]; +#else + int data[]; +#endif +} TfLiteIntArray; + +// Given the size (number of elements) in a TfLiteIntArray, calculate its size +// in bytes. +size_t TfLiteIntArrayGetSizeInBytes(int size); + +#ifndef ARDUINO +// Create a array of a given `size` (uninitialized entries). +// This returns a pointer, that you must free using TfLiteIntArrayFree(). +TfLiteIntArray* TfLiteIntArrayCreate(int size); +#endif + +// Check if two intarrays are equal. Returns 1 if they are equal, 0 otherwise. +int TfLiteIntArrayEqual(const TfLiteIntArray* a, const TfLiteIntArray* b); + +// Check if an intarray equals an array. Returns 1 if equals, 0 otherwise. +int TfLiteIntArrayEqualsArray(const TfLiteIntArray* a, int b_size, + const int b_data[]); + +#ifndef ARDUINO +// Create a copy of an array passed as `src`. +// You are expected to free memory with TfLiteIntArrayFree +TfLiteIntArray* TfLiteIntArrayCopy(const TfLiteIntArray* src); + +// Free memory of array `a`. +void TfLiteIntArrayFree(TfLiteIntArray* a); +#endif // ARDUINO + +// Fixed size list of floats. Used for per-channel quantization. +typedef struct TfLiteFloatArray { + int size; +#if defined(_MSC_VER) + // Context for why this is needed is in http://b/189926408#comment21 + float data[1]; +#elif (!defined(__clang__) && defined(__GNUC__) && __GNUC__ == 6 && \ + __GNUC_MINOR__ >= 1) || \ + defined(HEXAGON) || \ + (defined(__clang__) && __clang_major__ == 7 && __clang_minor__ == 1) + // gcc 6.1+ have a bug where flexible members aren't properly handled + // https://github.com/google/re2/commit/b94b7cd42e9f02673cd748c1ac1d16db4052514c + float data[0]; +#else + float data[]; +#endif +} TfLiteFloatArray; + +// Given the size (number of elements) in a TfLiteFloatArray, calculate its size +// in bytes. +int TfLiteFloatArrayGetSizeInBytes(int size); + +#ifndef ARDUINO +// Create a array of a given `size` (uninitialized entries). +// This returns a pointer, that you must free using TfLiteFloatArrayFree(). +TfLiteFloatArray* TfLiteFloatArrayCreate(int size); + +// Free memory of array `a`. +void TfLiteFloatArrayFree(TfLiteFloatArray* a); +#endif // ARDUINO + +// Since we must not depend on any libraries, define a minimal subset of +// error macros while avoiding names that have pre-conceived meanings like +// assert and check. + +// Try to make all reporting calls through TF_LITE_KERNEL_LOG rather than +// calling the context->ReportError function directly, so that message strings +// can be stripped out if the binary size needs to be severely optimized. +#ifndef TF_LITE_STRIP_ERROR_STRINGS +#define TF_LITE_KERNEL_LOG(context, ...) \ + do { \ + (context)->ReportError((context), __VA_ARGS__); \ + } while (false) + +#define TF_LITE_MAYBE_KERNEL_LOG(context, ...) \ + do { \ + if ((context) != nullptr) { \ + (context)->ReportError((context), __VA_ARGS__); \ + } \ + } while (false) +#else // TF_LITE_STRIP_ERROR_STRINGS +#define ARGS_UNUSED(...) (void)sizeof(#__VA_ARGS__) +#define TF_LITE_KERNEL_LOG(context, ...) ARGS_UNUSED(__VA_ARGS__) +#define TF_LITE_MAYBE_KERNEL_LOG(context, ...) ARGS_UNUSED(__VA_ARGS__) +#endif // TF_LITE_STRIP_ERROR_STRINGS + +// Check whether value is true, and if not return kTfLiteError from +// the current function (and report the error string msg). +#define TF_LITE_ENSURE_MSG(context, value, msg) \ + do { \ + if (!(value)) { \ + TF_LITE_KERNEL_LOG((context), __FILE__ " " msg); \ + return kTfLiteError; \ + } \ + } while (0) + +// Check whether the value `a` is true, and if not return kTfLiteError from +// the current function, while also reporting the location of the error. +#define TF_LITE_ENSURE(context, a) \ + do { \ + if (!(a)) { \ + TF_LITE_KERNEL_LOG((context), "%s:%d %s was not true.", __FILE__, \ + __LINE__, #a); \ + return kTfLiteError; \ + } \ + } while (0) + +#define TF_LITE_ENSURE_STATUS(a) \ + do { \ + const TfLiteStatus s = (a); \ + if (s != kTfLiteOk) { \ + return s; \ + } \ + } while (0) + +// Check whether the value `a == b` is true, and if not return kTfLiteError from +// the current function, while also reporting the location of the error. +// `a` and `b` may be evaluated more than once, so no side effects or +// extremely expensive computations should be done. +// NOTE: Use TF_LITE_ENSURE_TYPES_EQ if comparing TfLiteTypes. +#define TF_LITE_ENSURE_EQ(context, a, b) \ + do { \ + if ((a) != (b)) { \ + TF_LITE_KERNEL_LOG((context), "%s:%d %s != %s (%d != %d)", __FILE__, \ + __LINE__, #a, #b, (a), (b)); \ + return kTfLiteError; \ + } \ + } while (0) + +#define TF_LITE_ENSURE_TYPES_EQ(context, a, b) \ + do { \ + if ((a) != (b)) { \ + TF_LITE_KERNEL_LOG((context), "%s:%d %s != %s (%s != %s)", __FILE__, \ + __LINE__, #a, #b, TfLiteTypeGetName(a), \ + TfLiteTypeGetName(b)); \ + return kTfLiteError; \ + } \ + } while (0) + +#define TF_LITE_ENSURE_NEAR(context, a, b, epsilon) \ + do { \ + auto delta = ((a) > (b)) ? ((a) - (b)) : ((b) - (a)); \ + if (delta > epsilon) { \ + TF_LITE_KERNEL_LOG((context), "%s:%d %s not near %s (%f != %f)", \ + __FILE__, __LINE__, #a, #b, static_cast(a), \ + static_cast(b)); \ + return kTfLiteError; \ + } \ + } while (0) + +#define TF_LITE_ENSURE_OK(context, status) \ + do { \ + const TfLiteStatus s = (status); \ + if ((s) != kTfLiteOk) { \ + return s; \ + } \ + } while (0) + +// Single-precision complex data type compatible with the C99 definition. +typedef struct TfLiteComplex64 { + float re, im; // real and imaginary parts, respectively. +} TfLiteComplex64; + +// Double-precision complex data type compatible with the C99 definition. +typedef struct TfLiteComplex128 { + double re, im; // real and imaginary parts, respectively. +} TfLiteComplex128; + +// Half precision data type compatible with the C99 definition. +typedef struct TfLiteFloat16 { + uint16_t data; +} TfLiteFloat16; + +// Return the name of a given type, for error reporting purposes. +const char* TfLiteTypeGetName(TfLiteType type); + +// SupportedQuantizationTypes. +typedef enum TfLiteQuantizationType { + // No quantization. + kTfLiteNoQuantization = 0, + // Affine quantization (with support for per-channel quantization). + // Corresponds to TfLiteAffineQuantization. + kTfLiteAffineQuantization = 1, +} TfLiteQuantizationType; + +// Structure specifying the quantization used by the tensor, if-any. +typedef struct TfLiteQuantization { + // The type of quantization held by params. + TfLiteQuantizationType type; + // Holds an optional reference to a quantization param structure. The actual + // type depends on the value of the `type` field (see the comment there for + // the values and corresponding types). + void* params; +} TfLiteQuantization; + +// Parameters for asymmetric quantization across a dimension (i.e per output +// channel quantization). +// quantized_dimension specifies which dimension the scales and zero_points +// correspond to. +// For a particular value in quantized_dimension, quantized values can be +// converted back to float using: +// real_value = scale * (quantized_value - zero_point) +typedef struct TfLiteAffineQuantization { + TfLiteFloatArray* scale; + TfLiteIntArray* zero_point; + int32_t quantized_dimension; +} TfLiteAffineQuantization; + +/* A union of pointers that points to memory for a given tensor. */ +typedef union TfLitePtrUnion { + /* Do not access these members directly, if possible, use + * GetTensorData(tensor) instead, otherwise only access .data, as other + * members are deprecated. */ + int32_t* i32; + uint32_t* u32; + int64_t* i64; + uint64_t* u64; + float* f; + TfLiteFloat16* f16; + double* f64; + char* raw; + const char* raw_const; + uint8_t* uint8; + bool* b; + int16_t* i16; + uint16_t* ui16; + TfLiteComplex64* c64; + TfLiteComplex128* c128; + int8_t* int8; + /* Only use this member. */ + void* data; +} TfLitePtrUnion; + +// Memory allocation strategies. +// * kTfLiteMmapRo: Read-only memory-mapped data, or data externally allocated. +// * kTfLiteArenaRw: Arena allocated with no guarantees about persistence, +// and available during eval. +// * kTfLiteArenaRwPersistent: Arena allocated but persistent across eval, and +// only available during eval. +// * kTfLiteDynamic: Allocated during eval, or for string tensors. +// * kTfLitePersistentRo: Allocated and populated during prepare. This is +// useful for tensors that can be computed during prepare and treated +// as constant inputs for downstream ops (also in prepare). +// * kTfLiteCustom: Custom memory allocation provided by the user. See +// TfLiteCustomAllocation below. +typedef enum TfLiteAllocationType { + kTfLiteMemNone = 0, + kTfLiteMmapRo, + kTfLiteArenaRw, + kTfLiteArenaRwPersistent, + kTfLiteDynamic, + kTfLitePersistentRo, + kTfLiteCustom, +} TfLiteAllocationType; + +// The delegates should use zero or positive integers to represent handles. +// -1 is reserved from unallocated status. +typedef int TfLiteBufferHandle; +enum { + kTfLiteNullBufferHandle = -1, +}; + +// Storage format of each dimension in a sparse tensor. +typedef enum TfLiteDimensionType { + kTfLiteDimDense = 0, + kTfLiteDimSparseCSR, +} TfLiteDimensionType; + +// Metadata to encode each dimension in a sparse tensor. +typedef struct TfLiteDimensionMetadata { + TfLiteDimensionType format; + int dense_size; + TfLiteIntArray* array_segments; + TfLiteIntArray* array_indices; +} TfLiteDimensionMetadata; + +// Parameters used to encode a sparse tensor. For detailed explanation of each +// field please refer to lite/schema/schema.fbs. +typedef struct TfLiteSparsity { + TfLiteIntArray* traversal_order; + TfLiteIntArray* block_map; + TfLiteDimensionMetadata* dim_metadata; + int dim_metadata_size; +} TfLiteSparsity; + +// Defines a custom memory allocation not owned by the runtime. +// `data` should be aligned to kDefaultTensorAlignment defined in +// lite/util.h. (Currently 64 bytes) +// NOTE: See Interpreter.SetCustomAllocationForTensor for details on usage. +typedef struct TfLiteCustomAllocation { + void* data; + size_t bytes; +} TfLiteCustomAllocation; + +// The flags used in `Interpreter::SetCustomAllocationForTensor`. +// Note that this is a bitmask, so the values should be 1, 2, 4, 8, ...etc. +typedef enum TfLiteCustomAllocationFlags { + kTfLiteCustomAllocationFlagsNone = 0, + // Skips checking whether allocation.data points to an aligned buffer as + // expected by the TFLite runtime. + // NOTE: Setting this flag can cause crashes when calling Invoke(). + // Use with caution. + kTfLiteCustomAllocationFlagsSkipAlignCheck = 1, +} TfLiteCustomAllocationFlags; + +// A tensor in the interpreter system which is a wrapper around a buffer of +// data including a dimensionality (or NULL if not currently defined). +#ifndef ARDUINO +typedef struct TfLiteTensor { + // The data type specification for data stored in `data`. This affects + // what member of `data` union should be used. + TfLiteType type; + // A union of data pointers. The appropriate type should be used for a typed + // tensor based on `type`. + TfLitePtrUnion data; + // A pointer to a structure representing the dimensionality interpretation + // that the buffer should have. NOTE: the product of elements of `dims` + // and the element datatype size should be equal to `bytes` below. + TfLiteIntArray* dims; + // Quantization information. + TfLiteQuantizationParams params; + // How memory is mapped + // kTfLiteMmapRo: Memory mapped read only. + // i.e. weights + // kTfLiteArenaRw: Arena allocated read write memory + // (i.e. temporaries, outputs). + TfLiteAllocationType allocation_type; + // The number of bytes required to store the data of this Tensor. I.e. + // (bytes of each element) * dims[0] * ... * dims[n-1]. For example, if + // type is kTfLiteFloat32 and dims = {3, 2} then + // bytes = sizeof(float) * 3 * 2 = 4 * 3 * 2 = 24. + size_t bytes; + + // An opaque pointer to a tflite::MMapAllocation + const void* allocation; + + // Null-terminated name of this tensor. + const char* name; + + // The delegate which knows how to handle `buffer_handle`. + // WARNING: This is an experimental interface that is subject to change. + struct TfLiteDelegate* delegate; + + // An integer buffer handle that can be handled by `delegate`. + // The value is valid only when delegate is not null. + // WARNING: This is an experimental interface that is subject to change. + TfLiteBufferHandle buffer_handle; + + // If the delegate uses its own buffer (e.g. GPU memory), the delegate is + // responsible to set data_is_stale to true. + // `delegate->CopyFromBufferHandle` can be called to copy the data from + // delegate buffer. + // WARNING: This is an // experimental interface that is subject to change. + bool data_is_stale; + + // True if the tensor is a variable. + bool is_variable; + + // Quantization information. Replaces params field above. + TfLiteQuantization quantization; + + // Parameters used to encode a sparse tensor. + // This is optional. The field is NULL if a tensor is dense. + // WARNING: This is an experimental interface that is subject to change. + TfLiteSparsity* sparsity; + + // Optional. Encodes shapes with unknown dimensions with -1. This field is + // only populated when unknown dimensions exist in a read-write tensor (i.e. + // an input or output tensor). (e.g. `dims` contains [1, 1, 1, 3] and + // `dims_signature` contains [1, -1, -1, 3]). Note that this field only + // exists when TF_LITE_STATIC_MEMORY is not defined. + const TfLiteIntArray* dims_signature; +} TfLiteTensor; + +// A structure representing an instance of a node. +// This structure only exhibits the inputs, outputs, user defined data and some +// node properties (like statefulness), not other features like the type. +typedef struct TfLiteNode { + // Inputs to this node expressed as indices into the simulator's tensors. + TfLiteIntArray* inputs; + + // Outputs to this node expressed as indices into the simulator's tensors. + TfLiteIntArray* outputs; + + // intermediate tensors to this node expressed as indices into the simulator's + // tensors. + TfLiteIntArray* intermediates; + + // Temporary tensors uses during the computations. This usually contains no + // tensors, but ops are allowed to change that if they need scratch space of + // any sort. + TfLiteIntArray* temporaries; + + // Opaque data provided by the node implementer through `Registration.init`. + void* user_data; + + // Opaque data provided to the node if the node is a builtin. This is usually + // a structure defined in builtin_op_data.h + void* builtin_data; + + // Custom initial data. This is the opaque data provided in the flatbuffer. + // WARNING: This is an experimental interface that is subject to change. + const void* custom_initial_data; + int custom_initial_data_size; + + // The pointer to the delegate. This is non-null only when the node is + // created by calling `interpreter.ModifyGraphWithDelegate`. + // WARNING: This is an experimental interface that is subject to change. + struct TfLiteDelegate* delegate; + + // Whether this op might have side effect (e.g. stateful op). + bool might_have_side_effect; +} TfLiteNode; +#else // defined(ARDUINO)? +// NOTE: This flag is opt-in only at compile time. +// +// Specific reduced TfLiteTensor struct for TF Micro runtime. This struct +// contains only the minimum fields required to initialize and prepare a micro +// inference graph. The fields in this struct have been ordered from +// largest-to-smallest for optimal struct sizeof. +// +// This struct does not use: +// - allocation +// - buffer_handle +// - data_is_stale +// - delegate +// - dims_signature +// - name +// - sparsity +typedef struct TfLiteTensor { + // TODO(b/155784997): Consider consolidating these quantization fields: + // Quantization information. Replaces params field above. + TfLiteQuantization quantization; + + // Quantization information. + TfLiteQuantizationParams params; + + // A union of data pointers. The appropriate type should be used for a typed + // tensor based on `type`. + TfLitePtrUnion data; + + // A pointer to a structure representing the dimensionality interpretation + // that the buffer should have. NOTE: the product of elements of `dims` + // and the element datatype size should be equal to `bytes` below. + TfLiteIntArray* dims; + + // The number of bytes required to store the data of this Tensor. I.e. + // (bytes of each element) * dims[0] * ... * dims[n-1]. For example, if + // type is kTfLiteFloat32 and dims = {3, 2} then + // bytes = sizeof(float) * 3 * 2 = 4 * 3 * 2 = 24. + size_t bytes; + + // The data type specification for data stored in `data`. This affects + // what member of `data` union should be used. + TfLiteType type; + + // How memory is mapped + // kTfLiteMmapRo: Memory mapped read only. + // i.e. weights + // kTfLiteArenaRw: Arena allocated read write memory + // (i.e. temporaries, outputs). + TfLiteAllocationType allocation_type; + + // True if the tensor is a variable. + bool is_variable; +} TfLiteTensor; + +// Specific reduced TfLiteNode struct for TF Micro runtime. This struct contains +// only the minimum fields required to represent a node. +// +// This struct does not use: +// - delegate +// - intermediates +// - temporaries +typedef struct TfLiteNode { + // Inputs to this node expressed as indices into the simulator's tensors. + TfLiteIntArray* inputs; + + // Outputs to this node expressed as indices into the simulator's tensors. + TfLiteIntArray* outputs; + + // intermediate tensors to this node expressed as indices into the simulator's + // tensors. + TfLiteIntArray* intermediates; + + // Opaque data provided by the node implementer through `Registration.init`. + void* user_data; + + // Opaque data provided to the node if the node is a builtin. This is usually + // a structure defined in builtin_op_data.h + void* builtin_data; + + // Custom initial data. This is the opaque data provided in the flatbuffer. + // WARNING: This is an experimental interface that is subject to change. + const void* custom_initial_data; + int custom_initial_data_size; +} TfLiteNode; +#endif // ARDUINO + +// Light-weight tensor struct for TF Micro runtime. Provides the minimal amount +// of information required for a kernel to run during TfLiteRegistration::Eval. +// TODO(b/160955687): Move this field into TF_LITE_STATIC_MEMORY when TFLM +// builds with this flag by default internally. +typedef struct TfLiteEvalTensor { + // A union of data pointers. The appropriate type should be used for a typed + // tensor based on `type`. + TfLitePtrUnion data; + + // A pointer to a structure representing the dimensionality interpretation + // that the buffer should have. + TfLiteIntArray* dims; + + // The data type specification for data stored in `data`. This affects + // what member of `data` union should be used. + TfLiteType type; +} TfLiteEvalTensor; + +#ifndef ARDUINO +// Free data memory of tensor `t`. +void TfLiteTensorDataFree(TfLiteTensor* t); + +// Free quantization data. +void TfLiteQuantizationFree(TfLiteQuantization* quantization); + +// Free sparsity parameters. +void TfLiteSparsityFree(TfLiteSparsity* sparsity); + +// Free memory of tensor `t`. +void TfLiteTensorFree(TfLiteTensor* t); + +// Set all of a tensor's fields (and free any previously allocated data). +void TfLiteTensorReset(TfLiteType type, const char* name, TfLiteIntArray* dims, + TfLiteQuantizationParams quantization, char* buffer, + size_t size, TfLiteAllocationType allocation_type, + const void* allocation, bool is_variable, + TfLiteTensor* tensor); + +// Copies the contents of 'src' in 'dst'. +// Function does nothing if either 'src' or 'dst' is passed as nullptr and +// return kTfLiteOk. +// Returns kTfLiteError if 'src' and 'dst' doesn't have matching data size. +// Note function copies contents, so it won't create new data pointer +// or change allocation type. +// All Tensor related properties will be copied from 'src' to 'dst' like +// quantization, sparsity, ... +TfLiteStatus TfLiteTensorCopy(const TfLiteTensor* src, TfLiteTensor* dst); + +// Change the size of the memory block owned by `tensor` to `num_bytes`. +// Tensors with allocation types other than kTfLiteDynamic will be ignored. +// `tensor`'s internal data buffer will be assigned a pointer +// which can safely be passed to free or realloc if `num_bytes` is zero. +// Behaviour is undefined if `tensor` is NULL. +// If `preserve_data` is true, tensor data will be unchanged in the range from +// the start of the region up to the minimum of the old and new sizes. +void TfLiteTensorResizeMaybeCopy(size_t num_bytes, TfLiteTensor* tensor, + bool preserve_data); + +// Change the size of the memory block owned by `tensor` to `num_bytes`. +// Tensors with allocation types other than kTfLiteDynamic will be ignored. +// `tensor`'s internal data buffer will be assigned a pointer +// which can safely be passed to free or realloc if `num_bytes` is zero. +// Behaviour is undefined if `tensor` is NULL. +// Tensor data will be unchanged in the range from the start of the region up to +// the minimum of the old and new sizes. +void TfLiteTensorRealloc(size_t num_bytes, TfLiteTensor* tensor); +#endif // ARDUINO + +// WARNING: This is an experimental interface that is subject to change. +// +// Currently, TfLiteDelegateParams has to be allocated in a way that it's +// trivially destructable. It will be stored as `builtin_data` field in +// `TfLiteNode` of the delegate node. +// +// See also the `CreateDelegateParams` function in `interpreter.cc` details. +typedef struct TfLiteDelegateParams { + struct TfLiteDelegate* delegate; + TfLiteIntArray* nodes_to_replace; + TfLiteIntArray* input_tensors; + TfLiteIntArray* output_tensors; +} TfLiteDelegateParams; + +typedef struct TfLiteContext { + // Number of tensors in the context. + size_t tensors_size; + + // The execution plan contains a list of the node indices in execution + // order. execution_plan->size is the current number of nodes. And, + // execution_plan->data[0] is the first node that needs to be run. + // TfLiteDelegates can traverse the current execution plan by iterating + // through each member of this array and using GetNodeAndRegistration() to + // access details about a node. i.e. + // + // TfLiteIntArray* execution_plan; + // TF_LITE_ENSURE_STATUS(context->GetExecutionPlan(context, &execution_plan)); + // for (int exec_index = 0; exec_index < execution_plan->size; exec_index++) { + // int node_index = execution_plan->data[exec_index]; + // TfLiteNode* node; + // TfLiteRegistration* reg; + // context->GetNodeAndRegistration(context, node_index, &node, ®); + // } + // Note: the memory pointed by '`*execution_plan` is OWNED by TfLite runtime. + // Future calls to GetExecutionPlan invalidates earlier outputs. The following + // code snippet shows the issue of such an invocation pattern. After calling + // CheckNode, subsequent access to `plan_1st` is undefined. + // + // void CheckNode(const TfLiteNode* node) { + // ... + // TfLiteIntArray* plan_2nd; + // TF_LITE_ENSURE_STATUS(context->GetExecutionPlan(context, &plan_2nd)); + // ... + // } + // + // TfLiteIntArray* plan_1st; + // TF_LITE_ENSURE_STATUS(context->GetExecutionPlan(context, &plan_1st)); + // for (int exec_index = 0; exec_index < plan_1st->size; exec_index++) { + // int node_index = plan_1st->data[exec_index]; + // TfLiteNode* node; + // TfLiteRegistration* reg; + // context->GetNodeAndRegistration(context, node_index, &node, ®); + // CheckNode(node); + // } + // + // WARNING: This is an experimental interface that is subject to change. + TfLiteStatus (*GetExecutionPlan)(struct TfLiteContext* context, + TfLiteIntArray** execution_plan); + + // An array of tensors in the interpreter context (of length `tensors_size`) + TfLiteTensor* tensors; + + // opaque full context ptr (an opaque c++ data structure) + void* impl_; + + // Request memory pointer be resized. Updates dimensions on the tensor. + // NOTE: ResizeTensor takes ownership of newSize. + TfLiteStatus (*ResizeTensor)(struct TfLiteContext*, TfLiteTensor* tensor, + TfLiteIntArray* new_size); + // Request that an error be reported with format string msg. + void (*ReportError)(struct TfLiteContext*, const char* msg, ...); + + // Add `tensors_to_add` tensors, preserving pre-existing Tensor entries. If + // non-null, the value pointed to by `first_new_tensor_index` will be set to + // the index of the first new tensor. + TfLiteStatus (*AddTensors)(struct TfLiteContext*, int tensors_to_add, + int* first_new_tensor_index); + + // Get a Tensor node by node_index. + // WARNING: This is an experimental interface that is subject to change. + TfLiteStatus (*GetNodeAndRegistration)( + struct TfLiteContext*, int node_index, TfLiteNode** node, + struct TfLiteRegistration** registration); + + // Replace ops with one or more stub delegate operations. This function + // does not take ownership of `nodes_to_replace`. + TfLiteStatus (*ReplaceNodeSubsetsWithDelegateKernels)( + struct TfLiteContext*, struct TfLiteRegistration registration, + const TfLiteIntArray* nodes_to_replace, struct TfLiteDelegate* delegate); + + // Number of threads that are recommended to subsystems like gemmlowp and + // eigen. + int recommended_num_threads; + + // Access external contexts by type. + // WARNING: This is an experimental interface that is subject to change. + TfLiteExternalContext* (*GetExternalContext)(struct TfLiteContext*, + TfLiteExternalContextType); + // Set the value of a external context. Does not take ownership of the + // pointer. + // WARNING: This is an experimental interface that is subject to change. + void (*SetExternalContext)(struct TfLiteContext*, TfLiteExternalContextType, + TfLiteExternalContext*); + + // Flag for allowing float16 precision for FP32 calculation. + // default: false. + // WARNING: This is an experimental API and subject to change. + bool allow_fp32_relax_to_fp16; + + // Pointer to the op-level profiler, if set; nullptr otherwise. + void* profiler; + + // Allocate persistent buffer which has the same life time as the interpreter. + // Returns nullptr on failure. + // The memory is allocated from heap for TFL, and from tail in TFLM. + // This method is only available in Init or Prepare stage. + // WARNING: This is an experimental interface that is subject to change. + void* (*AllocatePersistentBuffer)(struct TfLiteContext* ctx, size_t bytes); + + // Allocate a buffer which will be deallocated right after invoke phase. + // The memory is allocated from heap in TFL, and from volatile arena in TFLM. + // This method is only available in invoke stage. + // NOTE: If possible use RequestScratchBufferInArena method to avoid memory + // allocation during inference time. + // WARNING: This is an experimental interface that is subject to change. + TfLiteStatus (*AllocateBufferForEval)(struct TfLiteContext* ctx, size_t bytes, + void** ptr); + + // Request a scratch buffer in the arena through static memory planning. + // This method is only available in Prepare stage and the buffer is allocated + // by the interpreter between Prepare and Eval stage. In Eval stage, + // GetScratchBuffer API can be used to fetch the address. + // WARNING: This is an experimental interface that is subject to change. + TfLiteStatus (*RequestScratchBufferInArena)(struct TfLiteContext* ctx, + size_t bytes, int* buffer_idx); + + // Get the scratch buffer pointer. + // This method is only available in Eval stage. + // WARNING: This is an experimental interface that is subject to change. + void* (*GetScratchBuffer)(struct TfLiteContext* ctx, int buffer_idx); + + // Resize the memory pointer of the `tensor`. This method behaves the same as + // `ResizeTensor`, except that it makes a copy of the shape array internally + // so the shape array could be deallocated right afterwards. + // WARNING: This is an experimental interface that is subject to change. + TfLiteStatus (*ResizeTensorExplicit)(struct TfLiteContext* ctx, + TfLiteTensor* tensor, int dims, + const int* shape); + + // This method provides a preview of post-delegation partitioning. Each + // TfLiteDelegateParams in the referenced array corresponds to one instance of + // the delegate kernel. + // Example usage: + // + // TfLiteIntArray* nodes_to_replace = ...; + // TfLiteDelegateParams* params_array; + // int num_partitions = 0; + // TF_LITE_ENSURE_STATUS(context->PreviewDelegatePartitioning( + // context, delegate, nodes_to_replace, ¶ms_array, &num_partitions)); + // for (int idx = 0; idx < num_partitions; idx++) { + // const auto& partition_params = params_array[idx]; + // ... + // } + // + // NOTE: The context owns the memory referenced by partition_params_array. It + // will be cleared with another call to PreviewDelegateParitioning, or after + // TfLiteDelegateParams::Prepare returns. + // + // WARNING: This is an experimental interface that is subject to change. + TfLiteStatus (*PreviewDelegatePartitioning)( + struct TfLiteContext* context, const TfLiteIntArray* nodes_to_replace, + TfLiteDelegateParams** partition_params_array, int* num_partitions); + + // Returns a TfLiteTensor struct for a given index. + // WARNING: This is an experimental interface that is subject to change. + // WARNING: This method may not be available on all platforms. + TfLiteTensor* (*GetTensor)(const struct TfLiteContext* context, + int tensor_idx); + + // Returns a TfLiteEvalTensor struct for a given index. + // WARNING: This is an experimental interface that is subject to change. + // WARNING: This method may not be available on all platforms. + TfLiteEvalTensor* (*GetEvalTensor)(const struct TfLiteContext* context, + int tensor_idx); + + // Retrieves named metadata buffer from the TFLite model. + // Returns kTfLiteOk if metadata is successfully obtained from the flatbuffer + // Model: that is, there exists a `metadata` entry with given `name` string. + // (see TFLite's schema.fbs). + // The corresponding `buffer` information is populated in `ptr` & `bytes`. + // The data from `ptr` is valid for the lifetime of the Interpreter. + // + // WARNING: This is an experimental interface that is subject to change. + TfLiteStatus (*GetModelMetadata)(const struct TfLiteContext* context, + const char* name, const char** ptr, + size_t* bytes); +} TfLiteContext; + +// `TfLiteRegistrationExternal` is an external version of `TfLiteRegistration` +// for C API which doesn't use internal types (such as `TfLiteContext`) but only +// uses stable API types (such as `TfLiteOpaqueContext`). The purpose of each +// field is the exactly the same as with `TfLiteRegistration`. +typedef struct TfLiteRegistrationExternal TfLiteRegistrationExternal; + +typedef struct TfLiteRegistration { + // Initializes the op from serialized data. + // Called only *once* for the lifetime of the op, so any one-time allocations + // should be made here (unless they depend on tensor sizes). + // + // If a built-in op: + // `buffer` is the op's params data (TfLiteLSTMParams*). + // `length` is zero. + // If custom op: + // `buffer` is the op's `custom_options`. + // `length` is the size of the buffer. + // + // Returns a type-punned (i.e. void*) opaque data (e.g. a primitive pointer + // or an instance of a struct). + // + // The returned pointer will be stored with the node in the `user_data` field, + // accessible within prepare and invoke functions below. + // NOTE: if the data is already in the desired format, simply implement this + // function to return `nullptr` and implement the free function to be a no-op. + void* (*init)(TfLiteContext* context, const char* buffer, size_t length); + + // The pointer `buffer` is the data previously returned by an init invocation. + void (*free)(TfLiteContext* context, void* buffer); + + // prepare is called when the inputs this node depends on have been resized. + // context->ResizeTensor() can be called to request output tensors to be + // resized. + // Can be called multiple times for the lifetime of the op. + // + // Returns kTfLiteOk on success. + TfLiteStatus (*prepare)(TfLiteContext* context, TfLiteNode* node); + + // Execute the node (should read node->inputs and output to node->outputs). + // Returns kTfLiteOk on success. + TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node); + + // profiling_string is called during summarization of profiling information + // in order to group executions together. Providing a value here will cause a + // given op to appear multiple times is the profiling report. This is + // particularly useful for custom ops that can perform significantly + // different calculations depending on their `user-data`. + const char* (*profiling_string)(const TfLiteContext* context, + const TfLiteNode* node); + + // Builtin codes. If this kernel refers to a builtin this is the code + // of the builtin. This is so we can do marshaling to other frameworks like + // NN API. + // Note: It is the responsibility of the registration binder to set this + // properly. + int32_t builtin_code; + + // Custom op name. If the op is a builtin, this will be null. + // Note: It is the responsibility of the registration binder to set this + // properly. + // WARNING: This is an experimental interface that is subject to change. + const char* custom_name; + + // The version of the op. + // Note: It is the responsibility of the registration binder to set this + // properly. + int version; + + // The external version of `TfLiteRegistration`. Since we can't use internal + // types (such as `TfLiteContext`) for C API to maintain ABI stability. + // C API user will provide `TfLiteRegistrationExternal` to implement custom + // ops. We keep it inside of `TfLiteRegistration` and use it to route + // callbacks properly. + TfLiteRegistrationExternal* registration_external; +} TfLiteRegistration; + +// Old version of `TfLiteRegistration` to maintain binary backward +// compatibility. +// WARNING: This structure is deprecated / not an official part of the API. +// It should be only used for binary backward compatibility. +typedef struct TfLiteRegistration_V1 { + void* (*init)(TfLiteContext* context, const char* buffer, size_t length); + void (*free)(TfLiteContext* context, void* buffer); + TfLiteStatus (*prepare)(TfLiteContext* context, TfLiteNode* node); + TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node); + const char* (*profiling_string)(const TfLiteContext* context, + const TfLiteNode* node); + int32_t builtin_code; + const char* custom_name; + int version; +} TfLiteRegistration_V1; + +// The flags used in `TfLiteDelegate`. Note that this is a bitmask, so the +// values should be 1, 2, 4, 8, ...etc. +typedef enum TfLiteDelegateFlags { + kTfLiteDelegateFlagsNone = 0, + // The flag is set if the delegate can handle dynamic sized tensors. + // For example, the output shape of a `Resize` op with non-constant shape + // can only be inferred when the op is invoked. + // In this case, the Delegate is responsible for calling + // `SetTensorToDynamic` to mark the tensor as a dynamic tensor, and calling + // `ResizeTensor` when invoking the op. + // + // If the delegate isn't capable to handle dynamic tensors, this flag need + // to be set to false. + kTfLiteDelegateFlagsAllowDynamicTensors = 1, + + // This flag can be used by delegates (that allow dynamic tensors) to ensure + // applicable tensor shapes are automatically propagated in the case of tensor + // resizing. + // This means that non-dynamic (allocation_type != kTfLiteDynamic) I/O tensors + // of a delegate kernel will have correct shapes before its Prepare() method + // is called. The runtime leverages TFLite builtin ops in the original + // execution plan to propagate shapes. + // + // A few points to note: + // 1. This requires kTfLiteDelegateFlagsAllowDynamicTensors. If that flag is + // false, this one is redundant since the delegate kernels are re-initialized + // every time tensors are resized. + // 2. Enabling this flag adds some overhead to AllocateTensors(), since extra + // work is required to prepare the original execution plan. + // 3. This flag requires that the original execution plan only have ops with + // valid registrations (and not 'dummy' custom ops like with Flex). + // WARNING: This feature is experimental and subject to change. + kTfLiteDelegateFlagsRequirePropagatedShapes = 2 +} TfLiteDelegateFlags; + +// WARNING: This is an experimental interface that is subject to change. +typedef struct TfLiteDelegate { + // Data that delegate needs to identify itself. This data is owned by the + // delegate. The delegate is owned in the user code, so the delegate is + // responsible for deallocating this when it is destroyed. + void* data_; + + // Invoked by ModifyGraphWithDelegate. This prepare is called, giving the + // delegate a view of the current graph through TfLiteContext*. It typically + // will look at the nodes and call ReplaceNodeSubsetsWithDelegateKernels() + // to ask the TensorFlow lite runtime to create macro-nodes to represent + // delegated subgraphs of the original graph. + TfLiteStatus (*Prepare)(TfLiteContext* context, + struct TfLiteDelegate* delegate); + + // Copy the data from delegate buffer handle into raw memory of the given + // 'tensor'. Note that the delegate is allowed to allocate the raw bytes as + // long as it follows the rules for kTfLiteDynamic tensors, in which case this + // cannot be null. + TfLiteStatus (*CopyFromBufferHandle)(TfLiteContext* context, + struct TfLiteDelegate* delegate, + TfLiteBufferHandle buffer_handle, + TfLiteTensor* tensor); + + // Copy the data from raw memory of the given 'tensor' to delegate buffer + // handle. This can be null if the delegate doesn't use its own buffer. + TfLiteStatus (*CopyToBufferHandle)(TfLiteContext* context, + struct TfLiteDelegate* delegate, + TfLiteBufferHandle buffer_handle, + TfLiteTensor* tensor); + + // Free the Delegate Buffer Handle. Note: This only frees the handle, but + // this doesn't release the underlying resource (e.g. textures). The + // resources are either owned by application layer or the delegate. + // This can be null if the delegate doesn't use its own buffer. + void (*FreeBufferHandle)(TfLiteContext* context, + struct TfLiteDelegate* delegate, + TfLiteBufferHandle* handle); + + // Bitmask flags. See the comments in `TfLiteDelegateFlags`. + int64_t flags; + + // The opaque delegate builder associated with this object. If set then the + // TF Lite runtime will give precedence to this field. E.g. instead of + // invoking 'Prepare' via the function pointer inside the 'TfLiteDelegate' + // object, the runtime will first check if the corresponding function + // pointer inside 'opaque_delegate_builder' is set and if so invoke that. + // + // If this field is non-null, then the 'Prepare' field (of the + // 'TfLiteDelegate') should be null. + struct TfLiteOpaqueDelegateBuilder* opaque_delegate_builder; +} TfLiteDelegate; + +// Build a 'null' delegate, with all the fields properly set to their default +// values. +TfLiteDelegate TfLiteDelegateCreate(void); + +// `TfLiteOpaqueDelegateBuilder` is used for constructing +// `TfLiteOpaqueDelegateStruct`, see `TfLiteOpaqueDelegateCreate` below. Note: +// This struct is not ABI stable. +// +// For forward source compatibility `TfLiteOpaqueDelegateBuilder` objects should +// be brace-initialized, so that all fields (including any that might be added +// in the future) get zero-initialized. The purpose of each field is exactly +// the same as with `TfLiteDelegate`. +// +// WARNING: This is an experimental interface that is subject to change. +typedef struct TfLiteOpaqueDelegateBuilder { + // Data that delegate needs to identify itself. This data is owned by the + // delegate. The delegate is owned in the user code, so the delegate is + // responsible for deallocating this when it is destroyed. + void* data; + // Invoked by ModifyGraphWithDelegate. This prepare is called, giving the + // delegate a view of the current graph through TfLiteContext*. It typically + // will look at the nodes and call ReplaceNodeSubsetsWithDelegateKernels() + // to ask the TensorFlow lite runtime to create macro-nodes to represent + // delegated subgraphs of the original graph. + TfLiteStatus (*Prepare)(TfLiteOpaqueContext* context, // NOLINT + struct TfLiteOpaqueDelegateStruct* delegate, + void* data); + // Copies the data from delegate buffer handle into raw memory of the given + // 'tensor'. Note that the delegate is allowed to allocate the raw bytes as + // long as it follows the rules for kTfLiteDynamic tensors, in which case this + // cannot be null. + TfLiteStatus (*CopyFromBufferHandle)( // NOLINT + TfLiteOpaqueContext* context, struct TfLiteOpaqueDelegateStruct* delegate, + void* data, TfLiteBufferHandle buffer_handle, TfLiteOpaqueTensor* tensor); + // Copies the data from raw memory of the given 'tensor' to delegate buffer + // handle. This can be null if the delegate doesn't use its own buffer. + TfLiteStatus (*CopyToBufferHandle)( // NOLINT + TfLiteOpaqueContext* context, struct TfLiteOpaqueDelegateStruct* delegate, + void* data, TfLiteBufferHandle buffer_handle, TfLiteOpaqueTensor* tensor); + // Frees the Delegate Buffer Handle. Note: This only frees the handle, but + // this doesn't release the underlying resource (e.g. textures). The + // resources are either owned by application layer or the delegate. + // This can be null if the delegate doesn't use its own buffer. + void (*FreeBufferHandle)(TfLiteOpaqueContext* context, // NOLINT + struct TfLiteOpaqueDelegateStruct* delegate, + void* data, TfLiteBufferHandle* handle); + // Bitmask flags. See the comments in `TfLiteDelegateFlags`. + int64_t flags; +} TfLiteOpaqueDelegateBuilder; + +// Creates an opaque delegate and returns its address. The opaque delegate will +// behave according to the provided 'opaque_delegate_builder'. The lifetime of +// the fields within the 'opaque_delegate_builder' must outlive any interaction +// between the runtime and the returned 'TfLiteOpaqueDelegateStruct'. The +// returned address should be passed to 'TfLiteOpaqueDelegateDelete' for +// deletion. If 'opaque_delegate_builder' is a null pointer, then a null +// pointer will be returned. +struct TfLiteOpaqueDelegateStruct* TfLiteOpaqueDelegateCreate( + const TfLiteOpaqueDelegateBuilder* opaque_delegate_builder); + +// Deletes the provided opaque 'delegate'. This function has no effect if the +// 'delegate' is a null pointer. +void TfLiteOpaqueDelegateDelete( + const struct TfLiteOpaqueDelegateStruct* delegate); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus +#endif // TENSORFLOW_LITE_C_COMMON_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/context_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/context_util.h new file mode 100644 index 000000000..ed42cc736 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/context_util.h @@ -0,0 +1,53 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +/// \file +/// This provides a few C++ helpers that are useful for manipulating C +/// structures in C++. +#ifndef TENSORFLOW_LITE_CONTEXT_UTIL_H_ +#define TENSORFLOW_LITE_CONTEXT_UTIL_H_ + +#include + +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +/// Provides a range iterable wrapper for TfLiteIntArray* (C lists) that TfLite +/// C api uses. +// Can't use the google array_view, since we can't depend on even +// absl for embedded device reasons. +class TfLiteIntArrayView { + public: + /// Construct a view of a TfLiteIntArray*. Note, `int_array` should be + /// non-null and this view does not take ownership of it. + explicit TfLiteIntArrayView(const TfLiteIntArray* int_array) + : int_array_(int_array) {} + + TfLiteIntArrayView(const TfLiteIntArrayView&) = default; + TfLiteIntArrayView& operator=(const TfLiteIntArrayView& rhs) = default; + + typedef const int* const_iterator; + const_iterator begin() const { return int_array_->data; } + const_iterator end() const { return &int_array_->data[int_array_->size]; } + size_t size() const { return end() - begin(); } + int operator[](size_t pos) const { return int_array_->data[pos]; } + + private: + const TfLiteIntArray* int_array_; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_CONTEXT_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/error_reporter.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/error_reporter.cpp new file mode 100644 index 000000000..7070eaa57 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/error_reporter.cpp @@ -0,0 +1,38 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/core/api/error_reporter.h" +#include + +namespace tflite { + +int ErrorReporter::Report(const char* format, ...) { + va_list args; + va_start(args, format); + int code = Report(format, args); + va_end(args); + return code; +} + +// TODO(aselle): Make the name of ReportError on context the same, so +// we can use the ensure functions w/o a context and w/ a reporter. +int ErrorReporter::ReportError(void*, const char* format, ...) { + va_list args; + va_start(args, format); + int code = Report(format, args); + va_end(args); + return code; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/error_reporter.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/error_reporter.h new file mode 100644 index 000000000..05839a611 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/error_reporter.h @@ -0,0 +1,59 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_CORE_API_ERROR_REPORTER_H_ +#define TENSORFLOW_LITE_CORE_API_ERROR_REPORTER_H_ + +#include + +namespace tflite { + +/// A functor that reports error to supporting system. Invoked similar to +/// printf. +/// +/// Usage: +/// ErrorReporter foo; +/// foo.Report("test %d", 5); +/// or +/// va_list args; +/// foo.Report("test %d", args); // where args is va_list +/// +/// Subclass ErrorReporter to provide another reporting destination. +/// For example, if you have a GUI program, you might redirect to a buffer +/// that drives a GUI error log box. +class ErrorReporter { + public: + virtual ~ErrorReporter() {} + virtual int Report(const char* format, va_list args) = 0; + int Report(const char* format, ...); + int ReportError(void*, const char* format, ...); +}; + +} // namespace tflite + +// You should not make bare calls to the error reporter, instead use the +// TF_LITE_REPORT_ERROR macro, since this allows message strings to be +// stripped when the binary size has to be optimized. If you are looking to +// reduce binary size, define TF_LITE_STRIP_ERROR_STRINGS when compiling and +// every call will be stubbed out, taking no memory. +#ifndef TF_LITE_STRIP_ERROR_STRINGS +#define TF_LITE_REPORT_ERROR(reporter, ...) \ + do { \ + static_cast(reporter)->Report(__VA_ARGS__); \ + } while (false) +#else // TF_LITE_STRIP_ERROR_STRINGS +#define TF_LITE_REPORT_ERROR(reporter, ...) +#endif // TF_LITE_STRIP_ERROR_STRINGS + +#endif // TENSORFLOW_LITE_CORE_API_ERROR_REPORTER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/flatbuffer_conversions.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/flatbuffer_conversions.cpp new file mode 100644 index 000000000..535e4c8a6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/flatbuffer_conversions.cpp @@ -0,0 +1,2472 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/core/api/flatbuffer_conversions.h" + +#include +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +namespace { + +// Utility class for safely allocating POD data. This is useful for avoiding +// leaks in cases where op params are allocated but fail to propagate to the +// parsed op data (e.g., when model parameters are invalid). +class SafeBuiltinDataAllocator { + public: + class BuiltinDataDeleter { + public: + explicit BuiltinDataDeleter(BuiltinDataAllocator* allocator) + : allocator_(allocator) {} + + void operator()(void* data) { allocator_->Deallocate(data); } + + private: + BuiltinDataAllocator* allocator_; + }; + + template + using BuiltinDataPtr = std::unique_ptr; + + explicit SafeBuiltinDataAllocator(BuiltinDataAllocator* allocator) + : allocator_(allocator) {} + + template + BuiltinDataPtr Allocate() { + return BuiltinDataPtr(allocator_->AllocatePOD(), + BuiltinDataDeleter(allocator_)); + } + + private: + BuiltinDataAllocator* allocator_; +}; + +// All the Parse functions take some pointers as params and this function has +// the common DCHECKs to catch if any of those are nullptr. +void CheckParsePointerParams(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + TFLITE_DCHECK(op != nullptr); + TFLITE_DCHECK(error_reporter != nullptr); + TFLITE_DCHECK(allocator != nullptr); + TFLITE_DCHECK(builtin_data != nullptr); +} + +// Copies the contents from the flatbuffer int vector `flatbuffer` into the +// int array `buffer`. `flat_vector` and `buffer` represent the same +// configuration operation for a given operation. +TfLiteStatus FlatBufferIntVectorToArray( + int max_size_of_buffer, const flatbuffers::Vector* flat_vector, + int* buffer, ErrorReporter* error_reporter, const char* op_name) { + if (!flat_vector) { + TF_LITE_REPORT_ERROR(error_reporter, + "Input array not provided for operation '%s'.\n", + op_name); + return kTfLiteError; + } else { + size_t num_dimensions = flat_vector->size(); + if (num_dimensions > max_size_of_buffer / sizeof(int)) { + TF_LITE_REPORT_ERROR( + error_reporter, + "Found too many dimensions in the input array of operation '%s'.\n", + op_name); + return kTfLiteError; + } else { + for (size_t i = 0; i < num_dimensions; ++i) { + buffer[i] = flat_vector->Get(i); + } + } + } + return kTfLiteOk; +} + +// Converts the flatbuffer activation to what is used at runtime. +TfLiteFusedActivation ConvertActivation(ActivationFunctionType activation) { + switch (activation) { + case ActivationFunctionType_NONE: + return kTfLiteActNone; + case ActivationFunctionType_RELU: + return kTfLiteActRelu; + case ActivationFunctionType_RELU_N1_TO_1: + return kTfLiteActReluN1To1; + case ActivationFunctionType_RELU6: + return kTfLiteActRelu6; + case ActivationFunctionType_TANH: + return kTfLiteActTanh; + case ActivationFunctionType_SIGN_BIT: + return kTfLiteActSignBit; + } + return kTfLiteActNone; +} + +// Converts the flatbuffer padding enum to what is used at runtime. +TfLitePadding ConvertPadding(Padding padding) { + switch (padding) { + case Padding_SAME: + return kTfLitePaddingSame; + case Padding_VALID: + return kTfLitePaddingValid; + } + return kTfLitePaddingUnknown; +} + +// Converts the flatbuffer mirror padding enum to what is used at runtime. +TfLiteMirrorPaddingMode ConvertMirrorPadding(MirrorPadMode padding) { + switch (padding) { + case MirrorPadMode_REFLECT: + return kTfLiteMirrorPaddingReflect; + case MirrorPadMode_SYMMETRIC: + return kTfLiteMirrorPaddingSymmetric; + } + return kTfLiteMirrorPaddingUnknown; +} + +#ifndef ARDUINO +TfLiteStatus ParseOpDataTfLite(const Operator* op, BuiltinOperator op_type, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + auto parseLSHProjectionType = [](LSHProjectionType type) { + switch (type) { + case LSHProjectionType_SPARSE: + return kTfLiteLshProjectionSparse; + case LSHProjectionType_DENSE: + return kTfLiteLshProjectionDense; + default: + return kTfLiteLshProjectionUnknown; + } + }; + auto parseCombinerType = [](CombinerType type) { + switch (type) { + case CombinerType_MEAN: + return kTfLiteCombinerTypeMean; + case CombinerType_SQRTN: + return kTfLiteCombinerTypeSqrtn; + case CombinerType_SUM: + default: + return kTfLiteCombinerTypeSum; + } + }; + + SafeBuiltinDataAllocator safe_allocator(allocator); + *builtin_data = nullptr; + switch (op_type) { + case BuiltinOperator_ABS: { + return ParseAbs(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_ADD: { + return ParseAdd(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_ADD_N: { + return ParseAddN(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_ARG_MAX: { + return ParseArgMax(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_ARG_MIN: { + return ParseArgMin(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_ASSIGN_VARIABLE: { + return ParseAssignVariable(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_AVERAGE_POOL_2D: { + return ParsePool(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_BATCH_MATMUL: { + return ParseBatchMatMul(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_BATCH_TO_SPACE_ND: { + return ParseBatchToSpaceNd(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_BROADCAST_ARGS: { + return ParseBroadcastArgs(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_BROADCAST_TO: { + return ParseBroadcastTo(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_CALL_ONCE: { + return ParseCallOnce(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_CEIL: { + return ParseCeil(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_CONCATENATION: { + return ParseConcatenation(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_CONV_2D: { + return ParseConv2D(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_CUMSUM: { + return ParseCumsum(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_DEPTH_TO_SPACE: { + return ParseDepthToSpace(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_DEPTHWISE_CONV_2D: { + return ParseDepthwiseConv2D(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_DEQUANTIZE: { + return ParseDequantize(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_DIV: { + return ParseDiv(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_ELU: { + return ParseElu(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_EXP: { + return ParseExp(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_EXPAND_DIMS: { + return ParseExpandDims(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_FILL: { + return ParseFill(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_FLOOR: { + return ParseFloor(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_FLOOR_DIV: { + return ParseFloorDiv(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_FLOOR_MOD: { + return ParseFloorMod(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_FULLY_CONNECTED: { + return ParseFullyConnected(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_GATHER_ND: { + return ParseGatherNd(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_GREATER: { + return ParseGreater(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_GREATER_EQUAL: { + return ParseGreaterEqual(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_HARD_SWISH: { + return ParseHardSwish(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_L2_NORMALIZATION: { + return ParseL2Normalization(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_L2_POOL_2D: { + return ParsePool(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LEAKY_RELU: { + return ParseLeakyRelu(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LESS: { + return ParseLess(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LESS_EQUAL: { + return ParseLessEqual(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LOG: { + return ParseLog(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LOGICAL_AND: { + return ParseLogicalAnd(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LOGICAL_NOT: { + return ParseLogicalNot(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LOGICAL_OR: { + return ParseLogicalOr(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LOGISTIC: { + return ParseLogistic(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LOG_SOFTMAX: { + return ParseLogSoftmax(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_LSTM: { + return ParseLSTM(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_MAXIMUM: { + return ParseMaximum(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_MAX_POOL_2D: { + return ParsePool(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_MIRROR_PAD: { + return ParseMirrorPad(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_MEAN: { + return ParseReducer(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_MINIMUM: { + return ParseMinimum(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_MUL: { + return ParseMul(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_NEG: { + return ParseNeg(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_NOT_EQUAL: { + return ParseNotEqual(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_PACK: { + return ParsePack(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_PAD: { + return ParsePad(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_PADV2: { + return ParsePadV2(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_POW: { + return ParsePow(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_PRELU: { + return ParsePrelu(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_QUANTIZE: { + return ParseQuantize(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_READ_VARIABLE: { + return ParseReadVariable(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_REDUCE_ANY: { + return ParseReducer(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_REDUCE_ALL: { + return ParseReducer(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_REDUCE_MAX: { + return ParseReducer(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_REDUCE_MIN: { + return ParseReducer(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_REDUCE_PROD: { + return ParseReducer(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_RELU: { + return ParseRelu(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_RELU6: { + return ParseRelu6(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_RESHAPE: { + return ParseReshape(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_RESIZE_BILINEAR: { + return ParseResizeBilinear(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_RESIZE_NEAREST_NEIGHBOR: { + return ParseResizeNearestNeighbor(op, error_reporter, allocator, + builtin_data); + } + + case BuiltinOperator_ROUND: { + return ParseRound(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_RSQRT: { + return ParseRsqrt(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SELECT_V2: { + return ParseSelectV2(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SHAPE: { + return ParseShape(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SIN: { + return ParseSin(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SOFTMAX: { + return ParseSoftmax(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SPACE_TO_BATCH_ND: { + return ParseSpaceToBatchNd(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SPACE_TO_DEPTH: { + return ParseSpaceToDepth(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SPLIT: { + return ParseSplit(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SPLIT_V: { + return ParseSplitV(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SQRT: { + return ParseSqrt(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SQUARE: { + return ParseSquare(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SQUARED_DIFFERENCE: { + return ParseSquaredDifference(op, error_reporter, allocator, + builtin_data); + } + + case BuiltinOperator_SQUEEZE: { + return ParseSqueeze(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_STRIDED_SLICE: { + return ParseStridedSlice(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SUB: { + return ParseSub(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SUM: { + return ParseReducer(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_SVDF: { + return ParseSvdf(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_TANH: { + return ParseTanh(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_TRANSPOSE_CONV: { + return ParseTransposeConv(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_UNPACK: { + return ParseUnpack(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_VAR_HANDLE: { + return ParseVarHandle(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_ZEROS_LIKE: { + return ParseZerosLike(op, error_reporter, allocator, builtin_data); + } + + case BuiltinOperator_CAST: { + return ParseCast(op, error_reporter, allocator, builtin_data); + } + case BuiltinOperator_LSH_PROJECTION: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* lshParams = + op->builtin_options_as_LSHProjectionOptions()) { + params->type = parseLSHProjectionType(lshParams->type()); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* sequence_rnn_params = + op->builtin_options_as_SequenceRNNOptions()) { + params->activation = + ConvertActivation(sequence_rnn_params->fused_activation_function()); + params->time_major = sequence_rnn_params->time_major(); + params->asymmetric_quantize_inputs = + sequence_rnn_params->asymmetric_quantize_inputs(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN: { + auto params = + safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* bidi_sequence_rnn_params = + op->builtin_options_as_BidirectionalSequenceRNNOptions()) { + params->activation = ConvertActivation( + bidi_sequence_rnn_params->fused_activation_function()); + params->time_major = bidi_sequence_rnn_params->time_major(); + params->merge_outputs = bidi_sequence_rnn_params->merge_outputs(); + params->asymmetric_quantize_inputs = + bidi_sequence_rnn_params->asymmetric_quantize_inputs(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_RNN: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* rnn_params = op->builtin_options_as_RNNOptions()) { + params->activation = + ConvertActivation(rnn_params->fused_activation_function()); + params->asymmetric_quantize_inputs = + rnn_params->asymmetric_quantize_inputs(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_EMBEDDING_LOOKUP_SPARSE: { + auto params = + safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* embedding_params = + op->builtin_options_as_EmbeddingLookupSparseOptions()) { + params->combiner = parseCombinerType(embedding_params->combiner()); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + + case BuiltinOperator_HASHTABLE_LOOKUP: + // no-op. + return kTfLiteOk; + + case BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* schema_params = + op->builtin_options_as_LocalResponseNormalizationOptions()) { + params->radius = schema_params->radius(); + params->bias = schema_params->bias(); + params->alpha = schema_params->alpha(); + params->beta = schema_params->beta(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM: { + return ParseUnidirectionalSequenceLSTM(op, error_reporter, allocator, + builtin_data); + } + case BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM: { + auto params = + safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* bidi_lstm_params = + op->builtin_options_as_BidirectionalSequenceLSTMOptions()) { + params->activation = + ConvertActivation(bidi_lstm_params->fused_activation_function()); + params->cell_clip = bidi_lstm_params->cell_clip(); + params->proj_clip = bidi_lstm_params->proj_clip(); + params->merge_outputs = bidi_lstm_params->merge_outputs(); + params->time_major = bidi_lstm_params->time_major(); + params->asymmetric_quantize_inputs = + bidi_lstm_params->asymmetric_quantize_inputs(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_SKIP_GRAM: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* skip_gram_params = + op->builtin_options_as_SkipGramOptions()) { + params->ngram_size = skip_gram_params->ngram_size(); + params->max_skip_size = skip_gram_params->max_skip_size(); + params->include_all_ngrams = skip_gram_params->include_all_ngrams(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + + case BuiltinOperator_GATHER: { + return ParseGather(op, error_reporter, allocator, builtin_data); + } + case BuiltinOperator_SPARSE_TO_DENSE: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* sparse_to_dense_params = + op->builtin_options_as_SparseToDenseOptions()) { + params->validate_indices = sparse_to_dense_params->validate_indices(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_DELEGATE: { + TF_LITE_REPORT_ERROR(error_reporter, + "DELEGATE op shouldn't exist in model."); + return kTfLiteError; + } + case BuiltinOperator_FAKE_QUANT: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* schema_params = + op->builtin_options_as_FakeQuantOptions()) { + params->min = schema_params->min(); + params->max = schema_params->max(); + params->num_bits = schema_params->num_bits(); + params->narrow_range = schema_params->narrow_range(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_ONE_HOT: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* schema_params = op->builtin_options_as_OneHotOptions()) { + params->axis = schema_params->axis(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_UNIQUE: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + const auto* unique_params = op->builtin_options_as_UniqueOptions(); + if (unique_params != nullptr) { + params->index_out_type = + unique_params->idx_out_type() == tflite::TensorType_INT64 + ? TfLiteType::kTfLiteInt64 + : TfLiteType::kTfLiteInt32; + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_REVERSE_SEQUENCE: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* reverse_seq_params = + op->builtin_options_as_ReverseSequenceOptions()) { + params->seq_dim = reverse_seq_params->seq_dim(); + params->batch_dim = reverse_seq_params->batch_dim(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_IF: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* if_params = op->builtin_options_as_IfOptions()) { + params->then_subgraph_index = if_params->then_subgraph_index(); + params->else_subgraph_index = if_params->else_subgraph_index(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_WHILE: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* while_params = op->builtin_options_as_WhileOptions()) { + params->cond_subgraph_index = while_params->cond_subgraph_index(); + params->body_subgraph_index = while_params->body_subgraph_index(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_CONV_3D: + case BuiltinOperator_CONV_3D_TRANSPOSE: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* conv3d_params = op->builtin_options_as_Conv3DOptions()) { + params->padding = ConvertPadding(conv3d_params->padding()); + params->activation = + ConvertActivation(conv3d_params->fused_activation_function()); + params->stride_depth = conv3d_params->stride_d(); + params->stride_height = conv3d_params->stride_h(); + params->stride_width = conv3d_params->stride_w(); + params->dilation_depth_factor = conv3d_params->dilation_d_factor(); + params->dilation_height_factor = conv3d_params->dilation_h_factor(); + params->dilation_width_factor = conv3d_params->dilation_w_factor(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_HASHTABLE: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* hashtable_params = + op->builtin_options_as_HashtableOptions()) { + params->table_id = hashtable_params->table_id(); + TF_LITE_ENSURE_STATUS(ConvertTensorType( + hashtable_params->key_dtype(), ¶ms->key_dtype, error_reporter)); + TF_LITE_ENSURE_STATUS(ConvertTensorType(hashtable_params->value_dtype(), + ¶ms->value_dtype, + error_reporter)); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_MULTINOMIAL: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* multinomial_params = + op->builtin_options_as_RandomOptions()) { + params->seed = multinomial_params->seed(); + params->seed2 = multinomial_params->seed2(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_RANDOM_STANDARD_NORMAL: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* random_std_normal_params = + op->builtin_options_as_RandomOptions()) { + params->seed = random_std_normal_params->seed(); + params->seed2 = random_std_normal_params->seed2(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_BUCKETIZE: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* bucketize_params = + op->builtin_options_as_BucketizeOptions()) { + const flatbuffers::Vector* boundaries = + bucketize_params->boundaries(); + if (boundaries == nullptr) { + TF_LITE_REPORT_ERROR( + error_reporter, + "boundaries array not provided for operation 'bucketize'.\n"); + return kTfLiteError; + } + params->num_boundaries = boundaries->size(); + if (boundaries->data() == nullptr) { + TF_LITE_REPORT_ERROR(error_reporter, + "boundaries.data() returned nullptr for " + "operation 'bucketize'.\n"); + return kTfLiteError; + } + params->boundaries = boundaries->data(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_RANDOM_UNIFORM: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* random_uniform_params = + op->builtin_options_as_RandomOptions()) { + params->seed = random_uniform_params->seed(); + params->seed2 = random_uniform_params->seed2(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + case BuiltinOperator_GELU: { + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* gelu_params = op->builtin_options_as_GeluOptions()) { + params->approximate = gelu_params->approximate(); + } + *builtin_data = params.release(); + return kTfLiteOk; + } + // Below are the ops with no builtin_data structure. + // TODO(aselle): Implement call in BuiltinOptions, but nullptrs are + // ok for now, since there is no call implementation either. + case BuiltinOperator_CALL: + case BuiltinOperator_COMPLEX_ABS: + case BuiltinOperator_CONCAT_EMBEDDINGS: + case BuiltinOperator_COS: + case BuiltinOperator_CUSTOM: + case BuiltinOperator_DENSIFY: + case BuiltinOperator_DYNAMIC_UPDATE_SLICE: + case BuiltinOperator_EMBEDDING_LOOKUP: + case BuiltinOperator_EQUAL: + case BuiltinOperator_HASHTABLE_FIND: + case BuiltinOperator_HASHTABLE_IMPORT: + case BuiltinOperator_HASHTABLE_SIZE: + case BuiltinOperator_IMAG: + case BuiltinOperator_MATRIX_DIAG: + case BuiltinOperator_MATRIX_SET_DIAG: + case BuiltinOperator_NON_MAX_SUPPRESSION_V4: + case BuiltinOperator_NON_MAX_SUPPRESSION_V5: + case BuiltinOperator_RELU_N1_TO_1: + case BuiltinOperator_RELU_0_TO_1: + case BuiltinOperator_SCATTER_ND: + case BuiltinOperator_SELECT: + case BuiltinOperator_SLICE: + case BuiltinOperator_TILE: + case BuiltinOperator_TOPK_V2: + case BuiltinOperator_TRANSPOSE: + case BuiltinOperator_RANGE: + case BuiltinOperator_RANK: + case BuiltinOperator_REAL: + case BuiltinOperator_RFFT2D: + case BuiltinOperator_SEGMENT_SUM: + case BuiltinOperator_REVERSE_V2: + case BuiltinOperator_UNSORTED_SEGMENT_MAX: + case BuiltinOperator_UNSORTED_SEGMENT_MIN: + case BuiltinOperator_UNSORTED_SEGMENT_PROD: + case BuiltinOperator_UNSORTED_SEGMENT_SUM: + case BuiltinOperator_ATAN2: + case BuiltinOperator_SIGN: + case BuiltinOperator_WHERE: + return kTfLiteOk; + case BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES: + return kTfLiteError; + } + return kTfLiteError; +} // NOLINT[readability/fn_size] +#endif // !defined(ARDUINO) +} // namespace + +TfLiteStatus ConvertTensorType(TensorType tensor_type, TfLiteType* type, + ErrorReporter* error_reporter) { + switch (tensor_type) { + case TensorType_FLOAT16: + *type = kTfLiteFloat16; + return kTfLiteOk; + case TensorType_FLOAT32: + *type = kTfLiteFloat32; + return kTfLiteOk; + case TensorType_FLOAT64: + *type = kTfLiteFloat64; + return kTfLiteOk; + case TensorType_INT16: + *type = kTfLiteInt16; + return kTfLiteOk; + case TensorType_UINT16: + *type = kTfLiteUInt16; + return kTfLiteOk; + case TensorType_INT32: + *type = kTfLiteInt32; + return kTfLiteOk; + case TensorType_UINT32: + *type = kTfLiteUInt32; + return kTfLiteOk; + case TensorType_UINT8: + *type = kTfLiteUInt8; + return kTfLiteOk; + case TensorType_INT8: + *type = kTfLiteInt8; + return kTfLiteOk; + case TensorType_INT64: + *type = kTfLiteInt64; + return kTfLiteOk; + case TensorType_UINT64: + *type = kTfLiteUInt64; + return kTfLiteOk; + case TensorType_STRING: + *type = kTfLiteString; + return kTfLiteOk; + case TensorType_BOOL: + *type = kTfLiteBool; + return kTfLiteOk; + case TensorType_COMPLEX64: + *type = kTfLiteComplex64; + return kTfLiteOk; + case TensorType_COMPLEX128: + *type = kTfLiteComplex128; + return kTfLiteOk; + case TensorType_RESOURCE: + *type = kTfLiteResource; + return kTfLiteOk; + case TensorType_VARIANT: + *type = kTfLiteVariant; + return kTfLiteOk; + case TensorType_INT4: + *type = kTfLiteInt4; + return kTfLiteOk; + default: + *type = kTfLiteNoType; + TF_LITE_REPORT_ERROR(error_reporter, + "Unsupported data type %d in tensor\n", tensor_type); + return kTfLiteError; + } +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseAbs(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseAdd(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const AddOptions* schema_params = op->builtin_options_as_AddOptions(); + + if (schema_params != nullptr) { + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + params->pot_scale_int16 = schema_params->pot_scale_int16(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseAddN(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + return kTfLiteOk; +} + +TfLiteStatus ParseArgMax(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const ArgMaxOptions* schema_params = op->builtin_options_as_ArgMaxOptions(); + + if (schema_params != nullptr) { + TF_LITE_ENSURE_STATUS(ConvertTensorType( + schema_params->output_type(), ¶ms->output_type, error_reporter)); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseArgMin(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const ArgMinOptions* schema_params = op->builtin_options_as_ArgMinOptions(); + + if (schema_params != nullptr) { + TF_LITE_ENSURE_STATUS(ConvertTensorType( + schema_params->output_type(), ¶ms->output_type, error_reporter)); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseAssignVariable(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseBatchMatMul(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* bmm_params = op->builtin_options_as_BatchMatMulOptions()) { + params->adj_x = bmm_params->adj_x(); + params->adj_y = bmm_params->adj_y(); + params->asymmetric_quantize_inputs = + bmm_params->asymmetric_quantize_inputs(); + } + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseBatchToSpaceNd(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseBroadcastArgs(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseBroadcastTo(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseCallOnce(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const CallOnceOptions* schema_params = + op->builtin_options_as_CallOnceOptions(); + + if (schema_params != nullptr) { + params->init_subgraph_index = schema_params->init_subgraph_index(); + + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseCast(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* schema_params = op->builtin_options_as_CastOptions()) { + TF_LITE_ENSURE_STATUS(ConvertTensorType( + schema_params->in_data_type(), ¶ms->in_data_type, error_reporter)); + TF_LITE_ENSURE_STATUS(ConvertTensorType(schema_params->out_data_type(), + ¶ms->out_data_type, + error_reporter)); + } + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseCeil(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseConcatenation(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const ConcatenationOptions* schema_params = + op->builtin_options_as_ConcatenationOptions(); + + if (schema_params != nullptr) { + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + params->axis = schema_params->axis(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseConv2D(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const Conv2DOptions* schema_params = op->builtin_options_as_Conv2DOptions(); + + if (schema_params != nullptr) { + params->padding = ConvertPadding(schema_params->padding()); + params->stride_width = schema_params->stride_w(); + params->stride_height = schema_params->stride_h(); + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + + params->dilation_width_factor = schema_params->dilation_w_factor(); + params->dilation_height_factor = schema_params->dilation_h_factor(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseCumsum(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* cumsum_params = op->builtin_options_as_CumsumOptions()) { + params->exclusive = cumsum_params->exclusive(); + params->reverse = cumsum_params->reverse(); + } + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseCos(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseDepthToSpace(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const auto* schema_params = op->builtin_options_as_DepthToSpaceOptions(); + if (schema_params != nullptr) { + params->block_size = schema_params->block_size(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseDepthwiseConv2D(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const DepthwiseConv2DOptions* schema_params = + op->builtin_options_as_DepthwiseConv2DOptions(); + + if (schema_params != nullptr) { + params->padding = ConvertPadding(schema_params->padding()); + params->stride_width = schema_params->stride_w(); + params->stride_height = schema_params->stride_h(); + params->depth_multiplier = schema_params->depth_multiplier(); + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + + params->dilation_width_factor = schema_params->dilation_w_factor(); + params->dilation_height_factor = schema_params->dilation_h_factor(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseDequantize(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseDiv(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* schema_params = op->builtin_options_as_DivOptions()) { + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + } + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseElu(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseEqual(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseExp(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseExpandDims(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseFill(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseFloor(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseFloorDiv(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseFloorMod(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseFullyConnected(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const FullyConnectedOptions* schema_params = + op->builtin_options_as_FullyConnectedOptions(); + + if (schema_params != nullptr) { + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + params->keep_num_dims = schema_params->keep_num_dims(); + params->asymmetric_quantize_inputs = + schema_params->asymmetric_quantize_inputs(); + + switch (schema_params->weights_format()) { + case FullyConnectedOptionsWeightsFormat_DEFAULT: + params->weights_format = kTfLiteFullyConnectedWeightsFormatDefault; + break; + case FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8: + params->weights_format = + kTfLiteFullyConnectedWeightsFormatShuffled4x16Int8; + break; + default: + TF_LITE_REPORT_ERROR(error_reporter, + "Unhandled fully-connected weights format."); + return kTfLiteError; + } + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseGather(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + params->axis = 0; + params->batch_dims = 0; + if (const auto* gather_params = op->builtin_options_as_GatherOptions()) { + params->axis = gather_params->axis(); + params->batch_dims = gather_params->batch_dims(); + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseGatherNd(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseGreater(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseGreaterEqual(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseHardSwish(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseIf(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const IfOptions* schema_params = op->builtin_options_as_IfOptions(); + + if (schema_params != nullptr) { + params->then_subgraph_index = schema_params->then_subgraph_index(); + params->else_subgraph_index = schema_params->else_subgraph_index(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseL2Normalization(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const L2NormOptions* schema_params = op->builtin_options_as_L2NormOptions(); + + if (schema_params != nullptr) { + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseLeakyRelu(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* leaky_relu_params = + op->builtin_options_as_LeakyReluOptions()) { + params->alpha = leaky_relu_params->alpha(); + } + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseLess(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseLessEqual(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseLog(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseLogicalAnd(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseLogicalNot(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseLogicalOr(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseLogistic(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseLogSoftmax(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseLSTM(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + auto params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* lstm_params = op->builtin_options_as_LSTMOptions()) { + params->activation = + ConvertActivation(lstm_params->fused_activation_function()); + params->cell_clip = lstm_params->cell_clip(); + params->proj_clip = lstm_params->proj_clip(); + switch (lstm_params->kernel_type()) { + case LSTMKernelType_FULL: + params->kernel_type = kTfLiteLSTMFullKernel; + break; + case LSTMKernelType_BASIC: + params->kernel_type = kTfLiteLSTMBasicKernel; + break; + default: + TF_LITE_REPORT_ERROR(error_reporter, "Unhandled LSTM kernel type: %d", + lstm_params->kernel_type()); + return kTfLiteError; + } + params->asymmetric_quantize_inputs = + lstm_params->asymmetric_quantize_inputs(); + } else { + TF_LITE_REPORT_ERROR(error_reporter, "No valid LSTM builtin options exist"); + return kTfLiteError; + } + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseMaximum(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseMinimum(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseMirrorPad(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const MirrorPadOptions* schema_params = + op->builtin_options_as_MirrorPadOptions(); + + if (schema_params != nullptr) { + params->mode = ConvertMirrorPadding(schema_params->mode()); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseMul(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const MulOptions* schema_params = op->builtin_options_as_MulOptions(); + + if (schema_params != nullptr) { + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseNeg(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseNotEqual(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParsePack(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const PackOptions* schema_params = op->builtin_options_as_PackOptions(); + + if (schema_params != nullptr) { + params->values_count = schema_params->values_count(); + params->axis = schema_params->axis(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParsePad(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParsePadV2(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +TfLiteStatus ParsePool(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const Pool2DOptions* schema_params = op->builtin_options_as_Pool2DOptions(); + + if (schema_params != nullptr) { + params->padding = ConvertPadding(schema_params->padding()); + params->stride_width = schema_params->stride_w(); + params->stride_height = schema_params->stride_h(); + params->filter_width = schema_params->filter_width(); + params->filter_height = schema_params->filter_height(); + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParsePow(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParsePrelu(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseQuantize(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseReadVariable(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseReducer(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const ReducerOptions* schema_params = op->builtin_options_as_ReducerOptions(); + + if (schema_params != nullptr) { + params->keep_dims = schema_params->keep_dims(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseRelu(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseRelu6(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseReshape(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const ReshapeOptions* schema_params = op->builtin_options_as_ReshapeOptions(); + + if (schema_params != nullptr) { + const flatbuffers::Vector* new_shape = schema_params->new_shape(); + if (new_shape != nullptr) { + TF_LITE_ENSURE_STATUS( + FlatBufferIntVectorToArray(sizeof(params->shape), new_shape, + params->shape, error_reporter, "reshape")); + params->num_dimensions = new_shape->size(); + } else { + // TODO(b/157480169) TODO(b/147203660): We should either return + // kTfLiteError or fill in some reasonable defaults in the params struct. + // We are not doing so until we better undertand the ramifications of + // changing the legacy behavior. + } + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseResizeBilinear(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const ResizeBilinearOptions* schema_params = + op->builtin_options_as_ResizeBilinearOptions(); + + if (schema_params != nullptr) { + params->align_corners = schema_params->align_corners(); + params->half_pixel_centers = schema_params->half_pixel_centers(); + } else { + params->align_corners = false; + params->half_pixel_centers = false; + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseResizeNearestNeighbor(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const ResizeNearestNeighborOptions* schema_params = + op->builtin_options_as_ResizeNearestNeighborOptions(); + + if (schema_params != nullptr) { + params->align_corners = schema_params->align_corners(); + params->half_pixel_centers = schema_params->half_pixel_centers(); + } else { + params->align_corners = false; + params->half_pixel_centers = false; + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseRound(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseRsqrt(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseSelectV2(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseShape(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const ShapeOptions* schema_params = op->builtin_options_as_ShapeOptions(); + + if (schema_params != nullptr) { + TF_LITE_ENSURE_STATUS(ConvertTensorType(schema_params->out_type(), + ¶ms->out_type, error_reporter)); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseSin(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseSlice(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseSoftmax(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const SoftmaxOptions* schema_params = op->builtin_options_as_SoftmaxOptions(); + + if (schema_params != nullptr) { + params->beta = schema_params->beta(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseSpaceToBatchNd(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseSpaceToDepth(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const auto* schema_params = op->builtin_options_as_SpaceToDepthOptions(); + if (schema_params != nullptr) { + params->block_size = schema_params->block_size(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseSplit(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const SplitOptions* schema_params = op->builtin_options_as_SplitOptions(); + + if (schema_params != nullptr) { + params->num_splits = schema_params->num_splits(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseSplitV(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + SafeBuiltinDataAllocator safe_allocator(allocator); + + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const SplitVOptions* schema_params = op->builtin_options_as_SplitVOptions(); + + if (schema_params != nullptr) { + params->num_splits = schema_params->num_splits(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseUnidirectionalSequenceLSTM(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + SafeBuiltinDataAllocator safe_allocator(allocator); + auto params = + safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + if (const auto* seq_lstm_params = + op->builtin_options_as_UnidirectionalSequenceLSTMOptions()) { + params->activation = + ConvertActivation(seq_lstm_params->fused_activation_function()); + params->cell_clip = seq_lstm_params->cell_clip(); + params->proj_clip = seq_lstm_params->proj_clip(); + params->time_major = seq_lstm_params->time_major(); + params->asymmetric_quantize_inputs = + seq_lstm_params->asymmetric_quantize_inputs(); + } + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseSqueeze(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + SafeBuiltinDataAllocator safe_allocator(allocator); + + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const SqueezeOptions* schema_params = op->builtin_options_as_SqueezeOptions(); + + if (schema_params != nullptr) { + const auto* squeeze_dims = schema_params->squeeze_dims(); + if (squeeze_dims != nullptr) { + TF_LITE_ENSURE_STATUS(FlatBufferIntVectorToArray( + sizeof(params->squeeze_dims), squeeze_dims, params->squeeze_dims, + error_reporter, "squeeze")); + params->num_squeeze_dims = squeeze_dims->size(); + } else { + params->num_squeeze_dims = 0; + } + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseSqrt(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseSquare(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseSquaredDifference(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseStridedSlice(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const StridedSliceOptions* schema_params = + op->builtin_options_as_StridedSliceOptions(); + + if (schema_params != nullptr) { + params->begin_mask = schema_params->begin_mask(); + params->end_mask = schema_params->end_mask(); + params->ellipsis_mask = schema_params->ellipsis_mask(); + params->new_axis_mask = schema_params->new_axis_mask(); + params->shrink_axis_mask = schema_params->shrink_axis_mask(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseSub(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const SubOptions* schema_params = op->builtin_options_as_SubOptions(); + + if (schema_params != nullptr) { + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + params->pot_scale_int16 = schema_params->pot_scale_int16(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseSvdf(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const SVDFOptions* schema_params = op->builtin_options_as_SVDFOptions(); + if (schema_params != nullptr) { + params->rank = schema_params->rank(); + params->activation = + ConvertActivation(schema_params->fused_activation_function()); + params->asymmetric_quantize_inputs = + schema_params->asymmetric_quantize_inputs(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseTanh(const Operator*, ErrorReporter*, BuiltinDataAllocator*, + void**) { + return kTfLiteOk; +} +// +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseTranspose(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseTransposeConv(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + const TransposeConvOptions* transpose_conv_params = + op->builtin_options_as_TransposeConvOptions(); + if (transpose_conv_params != nullptr) { + params->padding = ConvertPadding(transpose_conv_params->padding()); + params->stride_width = transpose_conv_params->stride_w(); + params->stride_height = transpose_conv_params->stride_h(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseUnpack(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const UnpackOptions* schema_params = op->builtin_options_as_UnpackOptions(); + + if (schema_params != nullptr) { + params->num = schema_params->num(); + params->axis = schema_params->axis(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseVarHandle(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const VarHandleOptions* schema_params = + op->builtin_options_as_VarHandleOptions(); + + if (schema_params != nullptr) { + if (schema_params->container()) { + params->container = schema_params->container()->c_str(); + } + if (schema_params->shared_name()) { + params->shared_name = schema_params->shared_name()->c_str(); + } + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +TfLiteStatus ParseWhile(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { + CheckParsePointerParams(op, error_reporter, allocator, builtin_data); + + SafeBuiltinDataAllocator safe_allocator(allocator); + std::unique_ptr + params = safe_allocator.Allocate(); + TF_LITE_ENSURE(error_reporter, params != nullptr); + + const WhileOptions* schema_params = op->builtin_options_as_WhileOptions(); + + if (schema_params != nullptr) { + params->cond_subgraph_index = schema_params->cond_subgraph_index(); + params->body_subgraph_index = schema_params->body_subgraph_index(); + } else { + // TODO(b/157480169): We should either return kTfLiteError or fill in some + // reasonable defaults in the params struct. We are not doing so until we + // better undertand the ramifications of changing the legacy behavior. + } + + *builtin_data = params.release(); + return kTfLiteOk; +} + +// We have this parse function instead of directly returning kTfLiteOk from the +// switch-case in ParseOpData because this function is used as part of the +// selective registration for the OpResolver implementation in micro. +TfLiteStatus ParseZerosLike(const Operator*, ErrorReporter*, + BuiltinDataAllocator*, void**) { + return kTfLiteOk; +} + +TfLiteStatus ParseOpData(const Operator* op, BuiltinOperator op_type, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data) { +// TODO(b/145762662): It would be preferable to have the build graph for TF Lite +// Micro not have the ParseOpData function at all. This would require splitting +// the current file into two separate files, one of which defines the +// ParseOpData function and the other that defines the operator specific parse +// functions (e.g. ParseAdd). +// +// Such a split was attempted but was not worth the effort at the time because +// of the following reasons: +// * We could either duplicate the functions and the SafeBuiltinDataAllocator +// class in the anonymous namespace of this file, or attempt to make a common +// library with these helper functions and class. +// * Making a common library with a separate build target was not feasible as +// it introduced circular dependencies due to the ErrorReporter and a common +// .cc and .h within the same api build target the also cause circular +// dependencies due to the BuiltinDataAllocator class. +// * If all the builtin operators were to have their own parse functions, or we +// were ok with some amount of code duplication, then this split of the .cc +// files would be a lot more feasible. +#ifdef ARDUINO + TF_LITE_REPORT_ERROR( + error_reporter, + "ParseOpData is unsupported on TfLiteMicro, please use the operator " + "specific parse functions (e.g. ParseAdd etc.).\n"); + return kTfLiteError; +#else + return ParseOpDataTfLite(op, op_type, error_reporter, allocator, + builtin_data); +#endif +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/flatbuffer_conversions.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/flatbuffer_conversions.h new file mode 100644 index 000000000..c7653f01f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/flatbuffer_conversions.h @@ -0,0 +1,412 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_CORE_API_FLATBUFFER_CONVERSIONS_H_ +#define TENSORFLOW_LITE_CORE_API_FLATBUFFER_CONVERSIONS_H_ + +// These functions transform codes and data structures that are defined in the +// flatbuffer serialization format into in-memory values that are used by the +// runtime API and interpreter. + +#include +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +// Interface class for builtin data allocations. +class BuiltinDataAllocator { + public: + virtual void* Allocate(size_t size, size_t alignment_hint) = 0; + virtual void Deallocate(void* data) = 0; + + // Allocate a structure, but make sure it is a POD structure that doesn't + // require constructors to run. The reason we do this, is that Interpreter's C + // extension part will take ownership so destructors will not be run during + // deallocation. + template + T* AllocatePOD() { + // TODO(b/154346074): Change this to is_trivially_destructible when all + // platform targets support that properly. + static_assert(std::is_pod::value, "Builtin data structure must be POD."); + void* allocated_memory = this->Allocate(sizeof(T), alignof(T)); + return new (allocated_memory) T(); + } + + virtual ~BuiltinDataAllocator() {} +}; + +// Parse the appropriate data out of the op. +// +// This handles builtin data explicitly as there are flatbuffer schemas. +// If it returns kTfLiteOk, it passes the data out with `builtin_data`. The +// calling function has to pass in an allocator object, and this allocator +// will be called to reserve space for the output data. If the calling +// function's allocator reserves memory on the heap, then it's the calling +// function's responsibility to free it. +// If it returns kTfLiteError, `builtin_data` will be `nullptr`. +TfLiteStatus ParseOpData(const Operator* op, BuiltinOperator op_type, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +// Converts the tensor data type used in the flat buffer to the representation +// used by the runtime. +TfLiteStatus ConvertTensorType(TensorType tensor_type, TfLiteType* type, + ErrorReporter* error_reporter); + +TfLiteStatus ParseAbs(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseAdd(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseAddN(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseArgMax(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseArgMin(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseAssignVariable(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseBatchMatMul(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseBatchToSpaceNd(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseBroadcastArgs(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseBroadcastTo(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseCallOnce(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseCeil(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseCast(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseConcatenation(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseConv2D(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseCos(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseCumsum(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseDepthToSpace(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseDepthwiseConv2D(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseDequantize(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseDiv(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseElu(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseEqual(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseExp(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseExpandDims(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseFill(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseFloor(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseFloorDiv(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseFloorMod(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseFullyConnected(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseGather(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseGatherNd(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseGreater(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseGreaterEqual(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseHardSwish(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseIf(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseL2Normalization(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseLeakyRelu(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseLess(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseLessEqual(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseLog(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseLogicalAnd(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseLogicalNot(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseLogicalOr(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseLogistic(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseLogSoftmax(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseLSTM(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseMaximum(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseMinimum(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseMirrorPad(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseMul(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseNeg(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseNotEqual(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParsePack(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParsePad(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParsePadV2(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParsePool(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParsePow(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParsePrelu(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseQuantize(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseReadVariable(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseReducer(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseRelu(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseRelu6(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseReshape(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseResizeBilinear(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseResizeNearestNeighbor(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseRound(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseRsqrt(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSelectV2(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseShape(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSin(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSlice(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSoftmax(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSpaceToBatchNd(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseSpaceToDepth(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseSplit(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSplitV(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSqueeze(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSqrt(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSquare(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSquaredDifference(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseStridedSlice(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseSub(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseSvdf(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseTanh(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseTranspose(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseTransposeConv(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseUnpack(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseUnidirectionalSequenceLSTM(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseVarHandle(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +TfLiteStatus ParseWhile(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, void** builtin_data); + +TfLiteStatus ParseZerosLike(const Operator* op, ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_CORE_API_FLATBUFFER_CONVERSIONS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/op_resolver.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/op_resolver.cpp new file mode 100644 index 000000000..7a48d6624 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/op_resolver.cpp @@ -0,0 +1,68 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/core/api/op_resolver.h" + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/schema/schema_utils.h" + +namespace tflite { + +TfLiteStatus GetRegistrationFromOpCode( + const OperatorCode* opcode, const OpResolver& op_resolver, + ErrorReporter* error_reporter, const TfLiteRegistration** registration) { + TfLiteStatus status = kTfLiteOk; + *registration = nullptr; + auto builtin_code = GetBuiltinCode(opcode); + int version = opcode->version(); + + if (builtin_code > BuiltinOperator_MAX) { + TF_LITE_REPORT_ERROR( + error_reporter, + "Op builtin_code out of range: %d. Are you using old TFLite binary " + "with newer model?", + builtin_code); + status = kTfLiteError; + } else if (builtin_code != BuiltinOperator_CUSTOM) { + *registration = op_resolver.FindOp(builtin_code, version); + if (*registration == nullptr) { + TF_LITE_REPORT_ERROR( + error_reporter, + "Didn't find op for builtin opcode '%s' version '%d'. " + "An older version of this builtin might be supported. " + "Are you using an old TFLite binary with a newer model?\n", + EnumNameBuiltinOperator(builtin_code), version); + status = kTfLiteError; + } + } else if (!opcode->custom_code()) { + TF_LITE_REPORT_ERROR( + error_reporter, + "Operator with CUSTOM builtin_code has no custom_code.\n"); + status = kTfLiteError; + } else { + const char* name = opcode->custom_code()->c_str(); + *registration = op_resolver.FindOp(name, version); + if (*registration == nullptr) { + // Do not report error for unresolved custom op, we do the final check + // while preparing ops. + status = kTfLiteError; + } + } + return status; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/op_resolver.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/op_resolver.h new file mode 100644 index 000000000..cec1f2dd4 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/op_resolver.h @@ -0,0 +1,140 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_CORE_API_OP_RESOLVER_H_ +#define TENSORFLOW_LITE_CORE_API_OP_RESOLVER_H_ + +#include +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/schema/schema_generated.h" + +// Opaque type similar to TfLiteDelegate / TfLiteOpaqueDelegate. +// This is used for cases (e.g. when using "TF Lite with Google Play Services") +// where the TF Lite runtime might be built using a newer (or older) +// version of the TF Lite sources than the app, and hence might have a +// different definition of the TfLiteDelegate type. TF Lite APIs use +// TfLiteOpaqueDelegate rather than TfLiteDelegate when they want to +// refer to a delegate defined with that potentially different version +// of the TfLiteDelegate type. +struct TfLiteOpaqueDelegateStruct; + +namespace tflite { + +/// Abstract interface that returns TfLiteRegistrations given op codes or custom +/// op names. This is the mechanism that ops being referenced in the flatbuffer +/// model are mapped to executable function pointers (TfLiteRegistrations). +class OpResolver { + public: + /// Finds the op registration for a builtin operator by enum code. + virtual const TfLiteRegistration* FindOp(tflite::BuiltinOperator op, + int version) const = 0; + /// Finds the op registration of a custom operator by op name. + virtual const TfLiteRegistration* FindOp(const char* op, + int version) const = 0; + + // Represents a sequence of delegates. + using TfLiteDelegatePtrVector = + std::vector>; + + // Returns optional delegates for resolving and handling ops in the flatbuffer + // model. This may be used in addition to the standard TfLiteRegistration + // lookup for graph resolution. + // WARNING: This API is deprecated, GetDelegateCreators is preferred. + virtual TfLiteDelegatePtrVector GetDelegates(int num_threads) const { + return {}; + } + + // Represents a function that creates a TfLite delegate instance. + using TfLiteDelegateCreator = + std::function( + int /*num_threads*/)>; + + // Represents a sequence of delegate creator functions. + using TfLiteDelegateCreators = std::vector; + + // Returns a vector of delegate creators to create optional delegates for + // resolving and handling ops in the flatbuffer model. This may be used in + // addition to the standard TfLiteRegistration lookup for graph resolution. + // + // Note that this method is not used (will not be called) if you are using + // TF Lite in Google Play Services; the GetOpaqueDelegateCreators method + // (see below) is used for that case. + virtual TfLiteDelegateCreators GetDelegateCreators() const { return {}; } + + // TODO(b/202712825): it would be nice if we could avoid the need for separate + // "opaque" types & methods for use only with TF Lite in Google Play Services. + + // Represents an opaque delegate instance. + // WARNING: Experimental interface, subject to change. + using TfLiteOpaqueDelegatePtr = + std::unique_ptr; + + // Represents a function that creates an opaque delegate instance. + // WARNING: Experimental interface, subject to change. + using TfLiteOpaqueDelegateCreator = + std::function; + + // Represents a sequence of opaque delegate creator functions. + // WARNING: Experimental interface, subject to change. + using TfLiteOpaqueDelegateCreators = std::vector; + + // Returns a vector of opaque delegate creators to create optional opaque + // delegates for resolving and handling ops in the flatbuffer model. This may + // be used in addition to the standard TfLiteRegistration lookup for graph + // resolution. + // + // Note that this method will be called only if you are using TF Lite in + // Google Play Services; if you are using regular TF Lite, GetDelegateCreators + // (see above) is used instead. + // + // WARNING: Experimental interface, subject to change. + virtual TfLiteOpaqueDelegateCreators GetOpaqueDelegateCreators() const { + return {}; + } + + virtual ~OpResolver() {} + + private: + /// Returns true if this OpResolver may contain any "user defined" ops. + /// By "user defined" ops, we mean any op definitions other than those + /// contained in tflite::ops::builtin::BuiltinOpResolver. + /// + /// If this method returns true, it doesn't necessarily mean that the + /// OpResolver contains a user-defined op, just that the absence of + /// user-defined ops can't be guaranteed. + /// + /// Note that "user-defined" ops are not the same as "custom" ops; + /// BuiltinOpResolver may support certain "custom" ops, in addition to + /// "builtin" ops, and may not support all of the "builtin" op enum values. + virtual bool MayContainUserDefinedOps() const { return true; } + + friend class OpResolverInternal; +}; + +// Handles the logic for converting between an OperatorCode structure extracted +// from a flatbuffer and information about a registered operator +// implementation. +TfLiteStatus GetRegistrationFromOpCode(const OperatorCode* opcode, + const OpResolver& op_resolver, + ErrorReporter* error_reporter, + const TfLiteRegistration** registration); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_CORE_API_OP_RESOLVER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/tensor_utils.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/tensor_utils.cpp new file mode 100644 index 000000000..3aac16b68 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/tensor_utils.cpp @@ -0,0 +1,50 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/core/api/tensor_utils.h" + +#include + +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +TfLiteStatus ResetVariableTensor(TfLiteTensor* tensor) { + if (!tensor->is_variable) { + return kTfLiteOk; + } + // TODO(b/115961645): Implement - If a variable tensor has a buffer, reset it + // to the value of the buffer. + int value = 0; + if (tensor->type == kTfLiteInt8) { + value = tensor->params.zero_point; + } + // TODO(b/139446230): Provide a platform header to better handle these + // specific scenarios. +#if __ANDROID__ || defined(__x86_64__) || defined(__i386__) || \ + defined(__i386) || defined(__x86__) || defined(__X86__) || \ + defined(_X86_) || defined(_M_IX86) || defined(_M_X64) + memset(tensor->data.raw, value, tensor->bytes); +#else + char* raw_ptr = tensor->data.raw; + for (size_t i = 0; i < tensor->bytes; ++i) { + *raw_ptr = value; + raw_ptr++; + } +#endif + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/tensor_utils.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/tensor_utils.h new file mode 100644 index 000000000..9f1cf94a5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/core/api/tensor_utils.h @@ -0,0 +1,28 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_CORE_API_TENSOR_UTILS_H_ +#define TENSORFLOW_LITE_CORE_API_TENSOR_UTILS_H_ + +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +// Resets a variable tensor to the default value. +TfLiteStatus ResetVariableTensor(TfLiteTensor* tensor); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_CORE_API_TENSOR_UTILS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/bits.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/bits.h new file mode 100644 index 000000000..04b3ba6f0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/bits.h @@ -0,0 +1,102 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_BITS_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_BITS_H_ + +#ifdef __cplusplus +#include + +extern "C" { +#endif + +static inline int CountLeadingZeros32Slow(uint64_t n) { + int zeroes = 28; + if (n >> 16) zeroes -= 16, n >>= 16; + if (n >> 8) zeroes -= 8, n >>= 8; + if (n >> 4) zeroes -= 4, n >>= 4; + return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes; +} + +static inline int CountLeadingZeros32(uint32_t n) { +#if defined(_MSC_VER) + unsigned long result = 0; // NOLINT(runtime/int) + if (_BitScanReverse(&result, n)) { + return 31 - result; + } + return 32; +#elif defined(__GNUC__) + + // Handle 0 as a special case because __builtin_clz(0) is undefined. + if (n == 0) { + return 32; + } + return __builtin_clz(n); +#else + return CountLeadingZeros32Slow(n); +#endif +} + +static inline int MostSignificantBit32(uint32_t n) { + return 32 - CountLeadingZeros32(n); +} + +static inline int CountLeadingZeros64Slow(uint64_t n) { + int zeroes = 60; + if (n >> 32) zeroes -= 32, n >>= 32; + if (n >> 16) zeroes -= 16, n >>= 16; + if (n >> 8) zeroes -= 8, n >>= 8; + if (n >> 4) zeroes -= 4, n >>= 4; + return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes; +} + +static inline int CountLeadingZeros64(uint64_t n) { +#if defined(_MSC_VER) && defined(_M_X64) + // MSVC does not have __builtin_clzll. Use _BitScanReverse64. + unsigned long result = 0; // NOLINT(runtime/int) + if (_BitScanReverse64(&result, n)) { + return 63 - result; + } + return 64; +#elif defined(_MSC_VER) + // MSVC does not have __builtin_clzll. Compose two calls to _BitScanReverse + unsigned long result = 0; // NOLINT(runtime/int) + if ((n >> 32) && _BitScanReverse(&result, n >> 32)) { + return 31 - result; + } + if (_BitScanReverse(&result, n)) { + return 63 - result; + } + return 64; +#elif defined(__GNUC__) + + // Handle 0 as a special case because __builtin_clzll(0) is undefined. + if (n == 0) { + return 64; + } + return __builtin_clzll(n); +#else + return CountLeadingZeros64Slow(n); +#endif +} + +static inline int MostSignificantBit64(uint64_t n) { + return 64 - CountLeadingZeros64(n); +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_BITS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft.cpp new file mode 100644 index 000000000..bcdd9cc0d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft.cpp @@ -0,0 +1,52 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/fft.h" + +#include + +#include "tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.h" + +void FftCompute(struct FftState* state, const int16_t* input, + int input_scale_shift) { + const size_t input_size = state->input_size; + const size_t fft_size = state->fft_size; + + int16_t* fft_input = state->input; + // First, scale the input by the given shift. + size_t i; + for (i = 0; i < input_size; ++i) { + fft_input[i] = static_cast(static_cast(input[i]) + << input_scale_shift); + } + // Zero out whatever else remains in the top part of the input. + for (; i < fft_size; ++i) { + fft_input[i] = 0; + } + + // Apply the FFT. + kissfft_fixed16::kiss_fftr( + reinterpret_cast(state->scratch), + state->input, + reinterpret_cast(state->output)); +} + +void FftInit(struct FftState* state) { + // All the initialization is done in FftPopulateState() +} + +void FftReset(struct FftState* state) { + memset(state->input, 0, state->fft_size * sizeof(*state->input)); + memset(state->output, 0, (state->fft_size / 2 + 1) * sizeof(*state->output)); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft.h new file mode 100644 index 000000000..aaffa69de --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft.h @@ -0,0 +1,50 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FFT_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FFT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct complex_int16_t { + int16_t real; + int16_t imag; +}; + +struct FftState { + int16_t* input; + struct complex_int16_t* output; + size_t fft_size; + size_t input_size; + void* scratch; + size_t scratch_size; +}; + +void FftCompute(struct FftState* state, const int16_t* input, + int input_scale_shift); + +void FftInit(struct FftState* state); + +void FftReset(struct FftState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FFT_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft_util.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft_util.cpp new file mode 100644 index 000000000..ed3dc8fbd --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft_util.cpp @@ -0,0 +1,70 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/fft_util.h" + +#include + +#include "tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.h" + +int FftPopulateState(struct FftState* state, size_t input_size) { + state->input_size = input_size; + state->fft_size = 1; + while (state->fft_size < state->input_size) { + state->fft_size <<= 1; + } + + state->input = reinterpret_cast( + malloc(state->fft_size * sizeof(*state->input))); + if (state->input == nullptr) { + fprintf(stderr, "Failed to alloc fft input buffer\n"); + return 0; + } + + state->output = reinterpret_cast( + malloc((state->fft_size / 2 + 1) * sizeof(*state->output) * 2)); + if (state->output == nullptr) { + fprintf(stderr, "Failed to alloc fft output buffer\n"); + return 0; + } + + // Ask kissfft how much memory it wants. + size_t scratch_size = 0; + kissfft_fixed16::kiss_fftr_cfg kfft_cfg = kissfft_fixed16::kiss_fftr_alloc( + state->fft_size, 0, nullptr, &scratch_size); + if (kfft_cfg != nullptr) { + fprintf(stderr, "Kiss memory sizing failed.\n"); + return 0; + } + state->scratch = malloc(scratch_size); + if (state->scratch == nullptr) { + fprintf(stderr, "Failed to alloc fft scratch buffer\n"); + return 0; + } + state->scratch_size = scratch_size; + // Let kissfft configure the scratch space we just allocated + kfft_cfg = kissfft_fixed16::kiss_fftr_alloc(state->fft_size, 0, + state->scratch, &scratch_size); + if (kfft_cfg != state->scratch) { + fprintf(stderr, "Kiss memory preallocation strategy failed.\n"); + return 0; + } + return 1; +} + +void FftFreeStateContents(struct FftState* state) { + free(state->input); + free(state->output); + free(state->scratch); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft_util.h new file mode 100644 index 000000000..6a471301c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/fft_util.h @@ -0,0 +1,34 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FFT_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FFT_UTIL_H_ + +#include "tensorflow/lite/experimental/microfrontend/lib/fft.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Prepares and FFT for the given input size. +int FftPopulateState(struct FftState* state, size_t input_size); + +// Frees any allocated buffers. +void FftFreeStateContents(struct FftState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FFT_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank.c new file mode 100644 index 000000000..80f8738f0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank.c @@ -0,0 +1,134 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/filterbank.h" + +#include + +#include "tensorflow/lite/experimental/microfrontend/lib/bits.h" + +void FilterbankConvertFftComplexToEnergy(struct FilterbankState* state, + struct complex_int16_t* fft_output, + int32_t* energy) { + const int end_index = state->end_index; + int i; + energy += state->start_index; + fft_output += state->start_index; + for (i = state->start_index; i < end_index; ++i) { + const int32_t real = fft_output->real; + const int32_t imag = fft_output->imag; + fft_output++; + const uint32_t mag_squared = (real * real) + (imag * imag); + *energy++ = mag_squared; + } +} + +void FilterbankAccumulateChannels(struct FilterbankState* state, + const int32_t* energy) { + uint64_t* work = state->work; + uint64_t weight_accumulator = 0; + uint64_t unweight_accumulator = 0; + + const int16_t* channel_frequency_starts = state->channel_frequency_starts; + const int16_t* channel_weight_starts = state->channel_weight_starts; + const int16_t* channel_widths = state->channel_widths; + + int num_channels_plus_1 = state->num_channels + 1; + int i; + for (i = 0; i < num_channels_plus_1; ++i) { + const int32_t* magnitudes = energy + *channel_frequency_starts++; + const int16_t* weights = state->weights + *channel_weight_starts; + const int16_t* unweights = state->unweights + *channel_weight_starts++; + const int width = *channel_widths++; + int j; + for (j = 0; j < width; ++j) { + weight_accumulator += *weights++ * ((uint64_t)*magnitudes); + unweight_accumulator += *unweights++ * ((uint64_t)*magnitudes); + ++magnitudes; + } + *work++ = weight_accumulator; + weight_accumulator = unweight_accumulator; + unweight_accumulator = 0; + } +} + +static uint16_t Sqrt32(uint32_t num) { + if (num == 0) { + return 0; + } + uint32_t res = 0; + int max_bit_number = 32 - MostSignificantBit32(num); + max_bit_number |= 1; + uint32_t bit = 1U << (31 - max_bit_number); + int iterations = (31 - max_bit_number) / 2 + 1; + while (iterations--) { + if (num >= res + bit) { + num -= res + bit; + res = (res >> 1U) + bit; + } else { + res >>= 1U; + } + bit >>= 2U; + } + // Do rounding - if we have the bits. + if (num > res && res != 0xFFFF) { + ++res; + } + return res; +} + +static uint32_t Sqrt64(uint64_t num) { + // Take a shortcut and just use 32 bit operations if the upper word is all + // clear. This will cause a slight off by one issue for numbers close to 2^32, + // but it probably isn't going to matter (and gives us a big performance win). + if ((num >> 32) == 0) { + return Sqrt32((uint32_t)num); + } + uint64_t res = 0; + int max_bit_number = 64 - MostSignificantBit64(num); + max_bit_number |= 1; + uint64_t bit = 1ULL << (63 - max_bit_number); + int iterations = (63 - max_bit_number) / 2 + 1; + while (iterations--) { + if (num >= res + bit) { + num -= res + bit; + res = (res >> 1U) + bit; + } else { + res >>= 1U; + } + bit >>= 2U; + } + // Do rounding - if we have the bits. + if (num > res && res != 0xFFFFFFFFLL) { + ++res; + } + return res; +} + +uint32_t* FilterbankSqrt(struct FilterbankState* state, int scale_down_shift) { + const int num_channels = state->num_channels; + const uint64_t* work = state->work + 1; + // Reuse the work buffer since we're fine clobbering it at this point to hold + // the output. + uint32_t* output = (uint32_t*)state->work; + int i; + for (i = 0; i < num_channels; ++i) { + *output++ = Sqrt64(*work++) >> scale_down_shift; + } + return (uint32_t*)state->work; +} + +void FilterbankReset(struct FilterbankState* state) { + memset(state->work, 0, (state->num_channels + 1) * sizeof(*state->work)); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank.h new file mode 100644 index 000000000..1e6d3885f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank.h @@ -0,0 +1,63 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FILTERBANK_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FILTERBANK_H_ + +#include +#include + +#include "tensorflow/lite/experimental/microfrontend/lib/fft.h" + +#define kFilterbankBits 12 + +#ifdef __cplusplus +extern "C" { +#endif + +struct FilterbankState { + int num_channels; + int start_index; + int end_index; + int16_t* channel_frequency_starts; + int16_t* channel_weight_starts; + int16_t* channel_widths; + int16_t* weights; + int16_t* unweights; + uint64_t* work; +}; + +// Converts the relevant complex values of an FFT output into energy (the +// square magnitude). +void FilterbankConvertFftComplexToEnergy(struct FilterbankState* state, + struct complex_int16_t* fft_output, + int32_t* energy); + +// Computes the mel-scale filterbank on the given energy array. Output is cached +// internally - to fetch it, you need to call FilterbankSqrt. +void FilterbankAccumulateChannels(struct FilterbankState* state, + const int32_t* energy); + +// Applies an integer square root to the 64 bit intermediate values of the +// filterbank, and returns a pointer to them. Memory will be invalidated the +// next time FilterbankAccumulateChannels is called. +uint32_t* FilterbankSqrt(struct FilterbankState* state, int scale_down_shift); + +void FilterbankReset(struct FilterbankState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FILTERBANK_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank_util.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank_util.c new file mode 100644 index 000000000..f18ebf547 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank_util.c @@ -0,0 +1,220 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/filterbank_util.h" + +#include +#include +#include + +#define kFilterbankIndexAlignment 4 +#define kFilterbankChannelBlockSize 4 + +void FilterbankFillConfigWithDefaults(struct FilterbankConfig* config) { + config->num_channels = 32; + config->lower_band_limit = 125.0f; + config->upper_band_limit = 7500.0f; + config->output_scale_shift = 7; +} + +static float FreqToMel(float freq) { return 1127.0 * log1p(freq / 700.0); } + +static void CalculateCenterFrequencies(const int num_channels, + const float lower_frequency_limit, + const float upper_frequency_limit, + float* center_frequencies) { + assert(lower_frequency_limit >= 0.0f); + assert(upper_frequency_limit > lower_frequency_limit); + + const float mel_low = FreqToMel(lower_frequency_limit); + const float mel_hi = FreqToMel(upper_frequency_limit); + const float mel_span = mel_hi - mel_low; + const float mel_spacing = mel_span / ((float)num_channels); + int i; + for (i = 0; i < num_channels; ++i) { + center_frequencies[i] = mel_low + (mel_spacing * (i + 1)); + } +} + +static void QuantizeFilterbankWeights(const float float_weight, int16_t* weight, + int16_t* unweight) { + *weight = floor(float_weight * (1 << kFilterbankBits) + 0.5); + *unweight = floor((1.0 - float_weight) * (1 << kFilterbankBits) + 0.5); +} + +int FilterbankPopulateState(const struct FilterbankConfig* config, + struct FilterbankState* state, int sample_rate, + int spectrum_size) { + state->num_channels = config->num_channels; + const int num_channels_plus_1 = config->num_channels + 1; + + // How should we align things to index counts given the byte alignment? + const int index_alignment = + (kFilterbankIndexAlignment < sizeof(int16_t) + ? 1 + : kFilterbankIndexAlignment / sizeof(int16_t)); + + state->channel_frequency_starts = + malloc(num_channels_plus_1 * sizeof(*state->channel_frequency_starts)); + state->channel_weight_starts = + malloc(num_channels_plus_1 * sizeof(*state->channel_weight_starts)); + state->channel_widths = + malloc(num_channels_plus_1 * sizeof(*state->channel_widths)); + state->work = malloc(num_channels_plus_1 * sizeof(*state->work)); + + float* center_mel_freqs = + malloc(num_channels_plus_1 * sizeof(*center_mel_freqs)); + int16_t* actual_channel_starts = + malloc(num_channels_plus_1 * sizeof(*actual_channel_starts)); + int16_t* actual_channel_widths = + malloc(num_channels_plus_1 * sizeof(*actual_channel_widths)); + + if (state->channel_frequency_starts == NULL || + state->channel_weight_starts == NULL || state->channel_widths == NULL || + center_mel_freqs == NULL || actual_channel_starts == NULL || + actual_channel_widths == NULL) { + free(center_mel_freqs); + free(actual_channel_starts); + free(actual_channel_widths); + fprintf(stderr, "Failed to allocate channel buffers\n"); + return 0; + } + + CalculateCenterFrequencies(num_channels_plus_1, config->lower_band_limit, + config->upper_band_limit, center_mel_freqs); + + // Always exclude DC. + const float hz_per_sbin = 0.5 * sample_rate / ((float)spectrum_size - 1); + state->start_index = 1.5 + config->lower_band_limit / hz_per_sbin; + state->end_index = 0; // Initialized to zero here, but actually set below. + + // For each channel, we need to figure out what frequencies belong to it, and + // how much padding we need to add so that we can efficiently multiply the + // weights and unweights for accumulation. To simplify the multiplication + // logic, all channels will have some multiplication to do (even if there are + // no frequencies that accumulate to that channel) - they will be directed to + // a set of zero weights. + int chan_freq_index_start = state->start_index; + int weight_index_start = 0; + int needs_zeros = 0; + + int chan; + for (chan = 0; chan < num_channels_plus_1; ++chan) { + // Keep jumping frequencies until we overshoot the bound on this channel. + int freq_index = chan_freq_index_start; + while (FreqToMel((freq_index)*hz_per_sbin) <= center_mel_freqs[chan]) { + ++freq_index; + } + + const int width = freq_index - chan_freq_index_start; + actual_channel_starts[chan] = chan_freq_index_start; + actual_channel_widths[chan] = width; + + if (width == 0) { + // This channel doesn't actually get anything from the frequencies, it's + // always zero. We need then to insert some 'zero' weights into the + // output, and just redirect this channel to do a single multiplication at + // this point. For simplicity, the zeros are placed at the beginning of + // the weights arrays, so we have to go and update all the other + // weight_starts to reflect this shift (but only once). + state->channel_frequency_starts[chan] = 0; + state->channel_weight_starts[chan] = 0; + state->channel_widths[chan] = kFilterbankChannelBlockSize; + if (!needs_zeros) { + needs_zeros = 1; + int j; + for (j = 0; j < chan; ++j) { + state->channel_weight_starts[j] += kFilterbankChannelBlockSize; + } + weight_index_start += kFilterbankChannelBlockSize; + } + } else { + // How far back do we need to go to ensure that we have the proper + // alignment? + const int aligned_start = + (chan_freq_index_start / index_alignment) * index_alignment; + const int aligned_width = (chan_freq_index_start - aligned_start + width); + const int padded_width = + (((aligned_width - 1) / kFilterbankChannelBlockSize) + 1) * + kFilterbankChannelBlockSize; + + state->channel_frequency_starts[chan] = aligned_start; + state->channel_weight_starts[chan] = weight_index_start; + state->channel_widths[chan] = padded_width; + weight_index_start += padded_width; + } + chan_freq_index_start = freq_index; + } + + // Allocate the two arrays to store the weights - weight_index_start contains + // the index of what would be the next set of weights that we would need to + // add, so that's how many weights we need to allocate. + state->weights = calloc(weight_index_start, sizeof(*state->weights)); + state->unweights = calloc(weight_index_start, sizeof(*state->unweights)); + + // If the alloc failed, we also need to nuke the arrays. + if (state->weights == NULL || state->unweights == NULL) { + free(center_mel_freqs); + free(actual_channel_starts); + free(actual_channel_widths); + fprintf(stderr, "Failed to allocate weights or unweights\n"); + return 0; + } + + // Next pass, compute all the weights. Since everything has been memset to + // zero, we only need to fill in the weights that correspond to some frequency + // for a channel. + const float mel_low = FreqToMel(config->lower_band_limit); + for (chan = 0; chan < num_channels_plus_1; ++chan) { + int frequency = actual_channel_starts[chan]; + const int num_frequencies = actual_channel_widths[chan]; + const int frequency_offset = + frequency - state->channel_frequency_starts[chan]; + const int weight_start = state->channel_weight_starts[chan]; + const float denom_val = (chan == 0) ? mel_low : center_mel_freqs[chan - 1]; + + int j; + for (j = 0; j < num_frequencies; ++j, ++frequency) { + const float weight = + (center_mel_freqs[chan] - FreqToMel(frequency * hz_per_sbin)) / + (center_mel_freqs[chan] - denom_val); + + // Make the float into an integer for the weights (and unweights). + const int weight_index = weight_start + frequency_offset + j; + QuantizeFilterbankWeights(weight, state->weights + weight_index, + state->unweights + weight_index); + } + if (frequency > state->end_index) { + state->end_index = frequency; + } + } + + free(center_mel_freqs); + free(actual_channel_starts); + free(actual_channel_widths); + if (state->end_index >= spectrum_size) { + fprintf(stderr, "Filterbank end_index is above spectrum size.\n"); + return 0; + } + return 1; +} + +void FilterbankFreeStateContents(struct FilterbankState* state) { + free(state->channel_frequency_starts); + free(state->channel_weight_starts); + free(state->channel_widths); + free(state->weights); + free(state->unweights); + free(state->work); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank_util.h new file mode 100644 index 000000000..781d10247 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/filterbank_util.h @@ -0,0 +1,50 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FILTERBANK_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FILTERBANK_UTIL_H_ + +#include "tensorflow/lite/experimental/microfrontend/lib/filterbank.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct FilterbankConfig { + // number of frequency channel buckets for filterbank + int num_channels; + // maximum frequency to include + float upper_band_limit; + // minimum frequency to include + float lower_band_limit; + // unused + int output_scale_shift; +}; + +// Fills the frontendConfig with "sane" defaults. +void FilterbankFillConfigWithDefaults(struct FilterbankConfig* config); + +// Allocates any buffers. +int FilterbankPopulateState(const struct FilterbankConfig* config, + struct FilterbankState* state, int sample_rate, + int spectrum_size); + +// Frees any allocated buffers. +void FilterbankFreeStateContents(struct FilterbankState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FILTERBANK_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend.c new file mode 100644 index 000000000..9de2a8796 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend.c @@ -0,0 +1,72 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/frontend.h" + +#include "tensorflow/lite/experimental/microfrontend/lib/bits.h" + +struct FrontendOutput FrontendProcessSamples(struct FrontendState* state, + const int16_t* samples, + size_t num_samples, + size_t* num_samples_read) { + struct FrontendOutput output; + output.values = NULL; + output.size = 0; + + // Try to apply the window - if it fails, return and wait for more data. + if (!WindowProcessSamples(&state->window, samples, num_samples, + num_samples_read)) { + return output; + } + + // Apply the FFT to the window's output (and scale it so that the fixed point + // FFT can have as much resolution as possible). + int input_shift = + 15 - MostSignificantBit32(state->window.max_abs_output_value); + FftCompute(&state->fft, state->window.output, input_shift); + + // We can re-ruse the fft's output buffer to hold the energy. + int32_t* energy = (int32_t*)state->fft.output; + + FilterbankConvertFftComplexToEnergy(&state->filterbank, state->fft.output, + energy); + + FilterbankAccumulateChannels(&state->filterbank, energy); + uint32_t* scaled_filterbank = FilterbankSqrt(&state->filterbank, input_shift); + + // Apply noise reduction. + NoiseReductionApply(&state->noise_reduction, scaled_filterbank); + + if (state->pcan_gain_control.enable_pcan) { + PcanGainControlApply(&state->pcan_gain_control, scaled_filterbank); + } + + // Apply the log and scale. + int correction_bits = + MostSignificantBit32(state->fft.fft_size) - 1 - (kFilterbankBits / 2); + uint16_t* logged_filterbank = + LogScaleApply(&state->log_scale, scaled_filterbank, + state->filterbank.num_channels, correction_bits); + + output.size = state->filterbank.num_channels; + output.values = logged_filterbank; + return output; +} + +void FrontendReset(struct FrontendState* state) { + WindowReset(&state->window); + FftReset(&state->fft); + FilterbankReset(&state->filterbank); + NoiseReductionReset(&state->noise_reduction); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend.h new file mode 100644 index 000000000..883df5fd3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend.h @@ -0,0 +1,64 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FRONTEND_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FRONTEND_H_ + +#include +#include + +#include "tensorflow/lite/experimental/microfrontend/lib/fft.h" +#include "tensorflow/lite/experimental/microfrontend/lib/filterbank.h" +#include "tensorflow/lite/experimental/microfrontend/lib/log_scale.h" +#include "tensorflow/lite/experimental/microfrontend/lib/noise_reduction.h" +#include "tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.h" +#include "tensorflow/lite/experimental/microfrontend/lib/window.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct FrontendState { + struct WindowState window; + struct FftState fft; + struct FilterbankState filterbank; + struct NoiseReductionState noise_reduction; + struct PcanGainControlState pcan_gain_control; + struct LogScaleState log_scale; +}; + +struct FrontendOutput { + const uint16_t* values; + size_t size; +}; + +// Main entry point to processing frontend samples. Updates num_samples_read to +// contain the number of samples that have been consumed from the input array. +// Returns a struct containing the generated output. If not enough samples were +// added to generate a feature vector, the returned size will be 0 and the +// values pointer will be NULL. Note that the output pointer will be invalidated +// as soon as FrontendProcessSamples is called again, so copy the contents +// elsewhere if you need to use them later. +struct FrontendOutput FrontendProcessSamples(struct FrontendState* state, + const int16_t* samples, + size_t num_samples, + size_t* num_samples_read); + +void FrontendReset(struct FrontendState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FRONTEND_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend_util.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend_util.c new file mode 100644 index 000000000..27224f6d2 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend_util.c @@ -0,0 +1,85 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/frontend_util.h" + +#include +#include + +#include "tensorflow/lite/experimental/microfrontend/lib/bits.h" + +void FrontendFillConfigWithDefaults(struct FrontendConfig* config) { + WindowFillConfigWithDefaults(&config->window); + FilterbankFillConfigWithDefaults(&config->filterbank); + NoiseReductionFillConfigWithDefaults(&config->noise_reduction); + PcanGainControlFillConfigWithDefaults(&config->pcan_gain_control); + LogScaleFillConfigWithDefaults(&config->log_scale); +} + +int FrontendPopulateState(const struct FrontendConfig* config, + struct FrontendState* state, int sample_rate) { + memset(state, 0, sizeof(*state)); + + if (!WindowPopulateState(&config->window, &state->window, sample_rate)) { + fprintf(stderr, "Failed to populate window state\n"); + return 0; + } + + if (!FftPopulateState(&state->fft, state->window.size)) { + fprintf(stderr, "Failed to populate fft state\n"); + return 0; + } + FftInit(&state->fft); + + if (!FilterbankPopulateState(&config->filterbank, &state->filterbank, + sample_rate, state->fft.fft_size / 2 + 1)) { + fprintf(stderr, "Failed to populate filterbank state\n"); + return 0; + } + + if (!NoiseReductionPopulateState(&config->noise_reduction, + &state->noise_reduction, + state->filterbank.num_channels)) { + fprintf(stderr, "Failed to populate noise reduction state\n"); + return 0; + } + + int input_correction_bits = + MostSignificantBit32(state->fft.fft_size) - 1 - (kFilterbankBits / 2); + if (!PcanGainControlPopulateState( + &config->pcan_gain_control, &state->pcan_gain_control, + state->noise_reduction.estimate, state->filterbank.num_channels, + state->noise_reduction.smoothing_bits, input_correction_bits)) { + fprintf(stderr, "Failed to populate pcan gain control state\n"); + return 0; + } + + if (!LogScalePopulateState(&config->log_scale, &state->log_scale)) { + fprintf(stderr, "Failed to populate log scale state\n"); + return 0; + } + + FrontendReset(state); + + // All good, return a true value. + return 1; +} + +void FrontendFreeStateContents(struct FrontendState* state) { + WindowFreeStateContents(&state->window); + FftFreeStateContents(&state->fft); + FilterbankFreeStateContents(&state->filterbank); + NoiseReductionFreeStateContents(&state->noise_reduction); + PcanGainControlFreeStateContents(&state->pcan_gain_control); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend_util.h new file mode 100644 index 000000000..895ce6cd2 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/frontend_util.h @@ -0,0 +1,52 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FRONTEND_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FRONTEND_UTIL_H_ + +#include "tensorflow/lite/experimental/microfrontend/lib/fft_util.h" +#include "tensorflow/lite/experimental/microfrontend/lib/filterbank_util.h" +#include "tensorflow/lite/experimental/microfrontend/lib/frontend.h" +#include "tensorflow/lite/experimental/microfrontend/lib/log_scale_util.h" +#include "tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.h" +#include "tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.h" +#include "tensorflow/lite/experimental/microfrontend/lib/window_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct FrontendConfig { + struct WindowConfig window; + struct FilterbankConfig filterbank; + struct NoiseReductionConfig noise_reduction; + struct PcanGainControlConfig pcan_gain_control; + struct LogScaleConfig log_scale; +}; + +// Fills the frontendConfig with "sane" defaults. +void FrontendFillConfigWithDefaults(struct FrontendConfig* config); + +// Allocates any buffers. +int FrontendPopulateState(const struct FrontendConfig* config, + struct FrontendState* state, int sample_rate); + +// Frees any allocated buffers. +void FrontendFreeStateContents(struct FrontendState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_FRONTEND_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_common.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_common.h new file mode 100644 index 000000000..f704677d2 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_common.h @@ -0,0 +1,48 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_KISS_FFT_COMMON_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_KISS_FFT_COMMON_H_ + +// This header file should be included in all variants of kiss_fft_$type.{h,cc} +// so that their sub-included source files do not mistakenly wrap libc header +// files within their kissfft_$type namespaces. +// E.g, This header avoids kissfft_int16.h containing: +// namespace kiss_fft_int16 { +// #include "third_party/kissfft/kiss_fft.h" +// } +// where kiss_fft_.h contains: +// #include +// +// TRICK: By including the following header files here, their preprocessor +// header guards prevent them being re-defined inside of the kiss_fft_$type +// namespaces declared within the kiss_fft_$type.{h,cc} sources. +// Note that the original kiss_fft*.h files are untouched since they +// may be used in libraries that include them directly. + +#include +#include +#include +#include +#include + +#ifdef FIXED_POINT +#include +#endif + +#ifdef USE_SIMD +#include +#endif +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_KISS_FFT_COMMON_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.cpp new file mode 100644 index 000000000..546306612 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.cpp @@ -0,0 +1,10 @@ +#include + +#include "tensorflow/lite/experimental/microfrontend/lib/kiss_fft_common.h" + +#define FIXED_POINT 16 +namespace kissfft_fixed16 { +#include "third_party/kissfft/kiss_fft.c" +#include "third_party/kissfft/tools/kiss_fftr.c" +} // namespace kissfft_fixed16 +#undef FIXED_POINT diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.h new file mode 100644 index 000000000..380307a46 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.h @@ -0,0 +1,33 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_KISS_FFT_INT16_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_KISS_FFT_INT16_H_ + +#include "tensorflow/lite/experimental/microfrontend/lib/kiss_fft_common.h" + +// Wrap 16-bit kiss fft in its own namespace. Enables us to link an application +// with different kiss fft resultions (16/32 bit interger, float, double) +// without getting a linker error. +#define FIXED_POINT 16 +namespace kissfft_fixed16 { +#include "third_party/kissfft/kiss_fft.h" +#include "third_party/kissfft/tools/kiss_fftr.h" +} // namespace kissfft_fixed16 +#undef FIXED_POINT +#undef kiss_fft_scalar +#undef KISS_FFT_H + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_KISS_FFT_INT16_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_lut.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_lut.c new file mode 100644 index 000000000..f59618e02 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_lut.c @@ -0,0 +1,30 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/log_lut.h" +const uint16_t kLogLut[] +#ifndef _MSC_VER + __attribute__((aligned(4))) +#endif // _MSV_VER + = {0, 224, 442, 654, 861, 1063, 1259, 1450, 1636, 1817, 1992, 2163, + 2329, 2490, 2646, 2797, 2944, 3087, 3224, 3358, 3487, 3611, 3732, 3848, + 3960, 4068, 4172, 4272, 4368, 4460, 4549, 4633, 4714, 4791, 4864, 4934, + 5001, 5063, 5123, 5178, 5231, 5280, 5326, 5368, 5408, 5444, 5477, 5507, + 5533, 5557, 5578, 5595, 5610, 5622, 5631, 5637, 5640, 5641, 5638, 5633, + 5626, 5615, 5602, 5586, 5568, 5547, 5524, 5498, 5470, 5439, 5406, 5370, + 5332, 5291, 5249, 5203, 5156, 5106, 5054, 5000, 4944, 4885, 4825, 4762, + 4697, 4630, 4561, 4490, 4416, 4341, 4264, 4184, 4103, 4020, 3935, 3848, + 3759, 3668, 3575, 3481, 3384, 3286, 3186, 3084, 2981, 2875, 2768, 2659, + 2549, 2437, 2323, 2207, 2090, 1971, 1851, 1729, 1605, 1480, 1353, 1224, + 1094, 963, 830, 695, 559, 421, 282, 142, 0, 0}; diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_lut.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_lut.h new file mode 100644 index 000000000..b2448a322 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_lut.h @@ -0,0 +1,40 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_LOG_LUT_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_LOG_LUT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Number of segments in the log lookup table. The table will be kLogSegments+1 +// in length (with some padding). +#define kLogSegments 128 +#define kLogSegmentsLog2 7 + +// Scale used by lookup table. +#define kLogScale 65536 +#define kLogScaleLog2 16 +#define kLogCoeff 45426 + +extern const uint16_t kLogLut[]; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_LOG_LUT_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale.c new file mode 100644 index 000000000..c27a50a62 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale.c @@ -0,0 +1,83 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/log_scale.h" + +#include "tensorflow/lite/experimental/microfrontend/lib/bits.h" +#include "tensorflow/lite/experimental/microfrontend/lib/log_lut.h" + +#define kuint16max 0x0000FFFF + +// The following functions implement integer logarithms of various sizes. The +// approximation is calculated according to method described in +// www.inti.gob.ar/electronicaeinformatica/instrumentacion/utic/ +// publicaciones/SPL2007/Log10-spl07.pdf +// It first calculates log2 of the input and then converts it to natural +// logarithm. + +static uint32_t Log2FractionPart(const uint32_t x, const uint32_t log2x) { + // Part 1 + int32_t frac = x - (1LL << log2x); + if (log2x < kLogScaleLog2) { + frac <<= kLogScaleLog2 - log2x; + } else { + frac >>= log2x - kLogScaleLog2; + } + // Part 2 + const uint32_t base_seg = frac >> (kLogScaleLog2 - kLogSegmentsLog2); + const uint32_t seg_unit = + (((uint32_t)1) << kLogScaleLog2) >> kLogSegmentsLog2; + + const int32_t c0 = kLogLut[base_seg]; + const int32_t c1 = kLogLut[base_seg + 1]; + const int32_t seg_base = seg_unit * base_seg; + const int32_t rel_pos = ((c1 - c0) * (frac - seg_base)) >> kLogScaleLog2; + return frac + c0 + rel_pos; +} + +static uint32_t Log(const uint32_t x, const uint32_t scale_shift) { + const uint32_t integer = MostSignificantBit32(x) - 1; + const uint32_t fraction = Log2FractionPart(x, integer); + const uint32_t log2 = (integer << kLogScaleLog2) + fraction; + const uint32_t round = kLogScale / 2; + const uint32_t loge = (((uint64_t)kLogCoeff) * log2 + round) >> kLogScaleLog2; + // Finally scale to our output scale + const uint32_t loge_scaled = ((loge << scale_shift) + round) >> kLogScaleLog2; + return loge_scaled; +} + +uint16_t* LogScaleApply(struct LogScaleState* state, uint32_t* signal, + int signal_size, int correction_bits) { + const int scale_shift = state->scale_shift; + uint16_t* output = (uint16_t*)signal; + uint16_t* ret = output; + int i; + for (i = 0; i < signal_size; ++i) { + uint32_t value = *signal++; + if (state->enable_log) { + if (correction_bits < 0) { + value >>= -correction_bits; + } else { + value <<= correction_bits; + } + if (value > 1) { + value = Log(value, scale_shift); + } else { + value = 0; + } + } + *output++ = (value < kuint16max) ? value : kuint16max; + } + return ret; +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale.h new file mode 100644 index 000000000..a383f32f5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale.h @@ -0,0 +1,39 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_LOG_SCALE_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_LOG_SCALE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct LogScaleState { + int enable_log; + int scale_shift; +}; + +// Applies a fixed point logarithm to the signal and converts it to 16 bit. Note +// that the signal array will be modified. +uint16_t* LogScaleApply(struct LogScaleState* state, uint32_t* signal, + int signal_size, int correction_bits); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_LOG_SCALE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale_util.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale_util.c new file mode 100644 index 000000000..0e3dd1d1e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale_util.c @@ -0,0 +1,27 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/log_scale_util.h" + +void LogScaleFillConfigWithDefaults(struct LogScaleConfig* config) { + config->enable_log = 1; + config->scale_shift = 6; +} + +int LogScalePopulateState(const struct LogScaleConfig* config, + struct LogScaleState* state) { + state->enable_log = config->enable_log; + state->scale_shift = config->scale_shift; + return 1; +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale_util.h new file mode 100644 index 000000000..11f7d9eeb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/log_scale_util.h @@ -0,0 +1,45 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_LOG_SCALE_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_LOG_SCALE_UTIL_H_ + +#include +#include + +#include "tensorflow/lite/experimental/microfrontend/lib/log_scale.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct LogScaleConfig { + // set to false (0) to disable this module + int enable_log; + // scale results by 2^(scale_shift) + int scale_shift; +}; + +// Populates the LogScaleConfig with "sane" default values. +void LogScaleFillConfigWithDefaults(struct LogScaleConfig* config); + +// Allocates any buffers. +int LogScalePopulateState(const struct LogScaleConfig* config, + struct LogScaleState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_LOG_SCALE_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction.c new file mode 100644 index 000000000..16b30e66a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction.c @@ -0,0 +1,51 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/noise_reduction.h" + +#include + +void NoiseReductionApply(struct NoiseReductionState* state, uint32_t* signal) { + int i; + for (i = 0; i < state->num_channels; ++i) { + const uint32_t smoothing = + ((i & 1) == 0) ? state->even_smoothing : state->odd_smoothing; + const uint32_t one_minus_smoothing = (1 << kNoiseReductionBits) - smoothing; + + // Update the estimate of the noise. + const uint32_t signal_scaled_up = signal[i] << state->smoothing_bits; + uint32_t estimate = + (((uint64_t)signal_scaled_up * smoothing) + + ((uint64_t)state->estimate[i] * one_minus_smoothing)) >> + kNoiseReductionBits; + state->estimate[i] = estimate; + + // Make sure that we can't get a negative value for the signal - estimate. + if (estimate > signal_scaled_up) { + estimate = signal_scaled_up; + } + + const uint32_t floor = + ((uint64_t)signal[i] * state->min_signal_remaining) >> + kNoiseReductionBits; + const uint32_t subtracted = + (signal_scaled_up - estimate) >> state->smoothing_bits; + const uint32_t output = subtracted > floor ? subtracted : floor; + signal[i] = output; + } +} + +void NoiseReductionReset(struct NoiseReductionState* state) { + memset(state->estimate, 0, sizeof(*state->estimate) * state->num_channels); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction.h new file mode 100644 index 000000000..46d3f52e6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction.h @@ -0,0 +1,46 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_NOISE_REDUCTION_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_NOISE_REDUCTION_H_ + +#define kNoiseReductionBits 14 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct NoiseReductionState { + int smoothing_bits; + uint16_t even_smoothing; + uint16_t odd_smoothing; + uint16_t min_signal_remaining; + int num_channels; + uint32_t* estimate; +}; + +// Removes stationary noise from each channel of the signal using a low pass +// filter. +void NoiseReductionApply(struct NoiseReductionState* state, uint32_t* signal); + +void NoiseReductionReset(struct NoiseReductionState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_NOISE_REDUCTION_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.c new file mode 100644 index 000000000..a6c9234eb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.c @@ -0,0 +1,45 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.h" + +#include + +void NoiseReductionFillConfigWithDefaults(struct NoiseReductionConfig* config) { + config->smoothing_bits = 10; + config->even_smoothing = 0.025; + config->odd_smoothing = 0.06; + config->min_signal_remaining = 0.05; +} + +int NoiseReductionPopulateState(const struct NoiseReductionConfig* config, + struct NoiseReductionState* state, + int num_channels) { + state->smoothing_bits = config->smoothing_bits; + state->odd_smoothing = config->odd_smoothing * (1 << kNoiseReductionBits); + state->even_smoothing = config->even_smoothing * (1 << kNoiseReductionBits); + state->min_signal_remaining = + config->min_signal_remaining * (1 << kNoiseReductionBits); + state->num_channels = num_channels; + state->estimate = calloc(state->num_channels, sizeof(*state->estimate)); + if (state->estimate == NULL) { + fprintf(stderr, "Failed to alloc estimate buffer\n"); + return 0; + } + return 1; +} + +void NoiseReductionFreeStateContents(struct NoiseReductionState* state) { + free(state->estimate); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.h new file mode 100644 index 000000000..fa5553914 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/noise_reduction_util.h @@ -0,0 +1,50 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_NOISE_REDUCTION_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_NOISE_REDUCTION_UTIL_H_ + +#include "tensorflow/lite/experimental/microfrontend/lib/noise_reduction.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct NoiseReductionConfig { + // scale the signal up by 2^(smoothing_bits) before reduction + int smoothing_bits; + // smoothing coefficient for even-numbered channels + float even_smoothing; + // smoothing coefficient for odd-numbered channels + float odd_smoothing; + // fraction of signal to preserve (1.0 disables this module) + float min_signal_remaining; +}; + +// Populates the NoiseReductionConfig with "sane" default values. +void NoiseReductionFillConfigWithDefaults(struct NoiseReductionConfig* config); + +// Allocates any buffers. +int NoiseReductionPopulateState(const struct NoiseReductionConfig* config, + struct NoiseReductionState* state, + int num_channels); + +// Frees any allocated buffers. +void NoiseReductionFreeStateContents(struct NoiseReductionState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_NOISE_REDUCTION_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.c new file mode 100644 index 000000000..22d587674 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.c @@ -0,0 +1,56 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.h" + +#include "tensorflow/lite/experimental/microfrontend/lib/bits.h" + +int16_t WideDynamicFunction(const uint32_t x, const int16_t* lut) { + if (x <= 2) { + return lut[x]; + } + + const int16_t interval = MostSignificantBit32(x); + lut += 4 * interval - 6; + + const int16_t frac = + ((interval < 11) ? (x << (11 - interval)) : (x >> (interval - 11))) & + 0x3FF; + + int32_t result = ((int32_t)lut[2] * frac) >> 5; + result += (int32_t)((uint32_t)lut[1] << 5); + result *= frac; + result = (result + (1 << 14)) >> 15; + result += lut[0]; + return (int16_t)result; +} + +uint32_t PcanShrink(const uint32_t x) { + if (x < (2 << kPcanSnrBits)) { + return (x * x) >> (2 + 2 * kPcanSnrBits - kPcanOutputBits); + } else { + return (x >> (kPcanSnrBits - kPcanOutputBits)) - (1 << kPcanOutputBits); + } +} + +void PcanGainControlApply(struct PcanGainControlState* state, + uint32_t* signal) { + int i; + for (i = 0; i < state->num_channels; ++i) { + const uint32_t gain = + WideDynamicFunction(state->noise_estimate[i], state->gain_lut); + const uint32_t snr = ((uint64_t)signal[i] * gain) >> state->snr_shift; + signal[i] = PcanShrink(snr); + } +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.h new file mode 100644 index 000000000..3f6222beb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.h @@ -0,0 +1,47 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_PCAN_GAIN_CONTROL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_PCAN_GAIN_CONTROL_H_ + +#include +#include + +#define kPcanSnrBits 12 +#define kPcanOutputBits 6 + +#ifdef __cplusplus +extern "C" { +#endif + +// Details at https://research.google/pubs/pub45911.pdf +struct PcanGainControlState { + int enable_pcan; + uint32_t* noise_estimate; + int num_channels; + int16_t* gain_lut; + int32_t snr_shift; +}; + +int16_t WideDynamicFunction(const uint32_t x, const int16_t* lut); + +uint32_t PcanShrink(const uint32_t x); + +void PcanGainControlApply(struct PcanGainControlState* state, uint32_t* signal); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_PCAN_GAIN_CONTROL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.c new file mode 100644 index 000000000..e850d439e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.c @@ -0,0 +1,92 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.h" + +#include +#include + +#define kint16max 0x00007FFF + +void PcanGainControlFillConfigWithDefaults( + struct PcanGainControlConfig* config) { + config->enable_pcan = 0; + config->strength = 0.95; + config->offset = 80.0; + config->gain_bits = 21; +} + +int16_t PcanGainLookupFunction(const struct PcanGainControlConfig* config, + int32_t input_bits, uint32_t x) { + const float x_as_float = ((float)x) / ((uint32_t)1 << input_bits); + const float gain_as_float = + ((uint32_t)1 << config->gain_bits) * + powf(x_as_float + config->offset, -config->strength); + + if (gain_as_float > kint16max) { + return kint16max; + } + return (int16_t)(gain_as_float + 0.5f); +} + +int PcanGainControlPopulateState(const struct PcanGainControlConfig* config, + struct PcanGainControlState* state, + uint32_t* noise_estimate, + const int num_channels, + const uint16_t smoothing_bits, + const int32_t input_correction_bits) { + state->enable_pcan = config->enable_pcan; + if (!state->enable_pcan) { + return 1; + } + state->noise_estimate = noise_estimate; + state->num_channels = num_channels; + state->gain_lut = malloc(kWideDynamicFunctionLUTSize * sizeof(int16_t)); + if (state->gain_lut == NULL) { + fprintf(stderr, "Failed to allocate gain LUT\n"); + return 0; + } + state->snr_shift = config->gain_bits - input_correction_bits - kPcanSnrBits; + + const int32_t input_bits = smoothing_bits - input_correction_bits; + state->gain_lut[0] = PcanGainLookupFunction(config, input_bits, 0); + state->gain_lut[1] = PcanGainLookupFunction(config, input_bits, 1); + state->gain_lut -= 6; + int interval; + for (interval = 2; interval <= kWideDynamicFunctionBits; ++interval) { + const uint32_t x0 = (uint32_t)1 << (interval - 1); + const uint32_t x1 = x0 + (x0 >> 1); + const uint32_t x2 = + (interval == kWideDynamicFunctionBits) ? x0 + (x0 - 1) : 2 * x0; + + const int16_t y0 = PcanGainLookupFunction(config, input_bits, x0); + const int16_t y1 = PcanGainLookupFunction(config, input_bits, x1); + const int16_t y2 = PcanGainLookupFunction(config, input_bits, x2); + + const int32_t diff1 = (int32_t)y1 - y0; + const int32_t diff2 = (int32_t)y2 - y0; + const int32_t a1 = 4 * diff1 - diff2; + const int32_t a2 = diff2 - a1; + + state->gain_lut[4 * interval] = y0; + state->gain_lut[4 * interval + 1] = (int16_t)a1; + state->gain_lut[4 * interval + 2] = (int16_t)a2; + } + state->gain_lut += 6; + return 1; +} + +void PcanGainControlFreeStateContents(struct PcanGainControlState* state) { + free(state->gain_lut); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.h new file mode 100644 index 000000000..d4bfaa2ed --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control_util.h @@ -0,0 +1,57 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_PCAN_GAIN_CONTROL_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_PCAN_GAIN_CONTROL_UTIL_H_ + +#include "tensorflow/lite/experimental/microfrontend/lib/pcan_gain_control.h" + +#define kWideDynamicFunctionBits 32 +#define kWideDynamicFunctionLUTSize (4 * kWideDynamicFunctionBits - 3) + +#ifdef __cplusplus +extern "C" { +#endif + +struct PcanGainControlConfig { + // set to false (0) to disable this module + int enable_pcan; + // gain normalization exponent (0.0 disables, 1.0 full strength) + float strength; + // positive value added in the normalization denominator + float offset; + // number of fractional bits in the gain + int gain_bits; +}; + +void PcanGainControlFillConfigWithDefaults( + struct PcanGainControlConfig* config); + +int16_t PcanGainLookupFunction(const struct PcanGainControlConfig* config, + int32_t input_bits, uint32_t x); + +int PcanGainControlPopulateState(const struct PcanGainControlConfig* config, + struct PcanGainControlState* state, + uint32_t* noise_estimate, + const int num_channels, + const uint16_t smoothing_bits, + const int32_t input_correction_bits); + +void PcanGainControlFreeStateContents(struct PcanGainControlState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_PCAN_GAIN_CONTROL_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window.c new file mode 100644 index 000000000..10da6762c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window.c @@ -0,0 +1,70 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/window.h" + +#include + +int WindowProcessSamples(struct WindowState* state, const int16_t* samples, + size_t num_samples, size_t* num_samples_read) { + const int size = state->size; + + // Copy samples from the samples buffer over to our local input. + size_t max_samples_to_copy = state->size - state->input_used; + if (max_samples_to_copy > num_samples) { + max_samples_to_copy = num_samples; + } + memcpy(state->input + state->input_used, samples, + max_samples_to_copy * sizeof(*samples)); + *num_samples_read = max_samples_to_copy; + state->input_used += max_samples_to_copy; + + if (state->input_used < state->size) { + // We don't have enough samples to compute a window. + return 0; + } + + // Apply the window to the input. + const int16_t* coefficients = state->coefficients; + const int16_t* input = state->input; + int16_t* output = state->output; + int i; + int16_t max_abs_output_value = 0; + for (i = 0; i < size; ++i) { + int16_t new_value = + (((int32_t)*input++) * *coefficients++) >> kFrontendWindowBits; + *output++ = new_value; + if (new_value < 0) { + new_value = -new_value; + } + if (new_value > max_abs_output_value) { + max_abs_output_value = new_value; + } + } + // Shuffle the input down by the step size, and update how much we have used. + memmove(state->input, state->input + state->step, + sizeof(*state->input) * (state->size - state->step)); + state->input_used -= state->step; + state->max_abs_output_value = max_abs_output_value; + + // Indicate that the output buffer is valid for the next stage. + return 1; +} + +void WindowReset(struct WindowState* state) { + memset(state->input, 0, state->size * sizeof(*state->input)); + memset(state->output, 0, state->size * sizeof(*state->output)); + state->input_used = 0; + state->max_abs_output_value = 0; +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window.h new file mode 100644 index 000000000..bad815141 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window.h @@ -0,0 +1,49 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_WINDOW_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_WINDOW_H_ + +#include +#include + +#define kFrontendWindowBits 12 + +#ifdef __cplusplus +extern "C" { +#endif + +struct WindowState { + size_t size; + int16_t* coefficients; + size_t step; + + int16_t* input; + size_t input_used; + int16_t* output; + int16_t max_abs_output_value; +}; + +// Applies a window to the samples coming in, stepping forward at the given +// rate. +int WindowProcessSamples(struct WindowState* state, const int16_t* samples, + size_t num_samples, size_t* num_samples_read); + +void WindowReset(struct WindowState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_WINDOW_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window_util.c b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window_util.c new file mode 100644 index 000000000..eee6e7b56 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window_util.c @@ -0,0 +1,73 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/experimental/microfrontend/lib/window_util.h" + +#include +#include +#include +#include + +// Some platforms don't have M_PI +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +void WindowFillConfigWithDefaults(struct WindowConfig* config) { + config->size_ms = 25; + config->step_size_ms = 10; +} + +int WindowPopulateState(const struct WindowConfig* config, + struct WindowState* state, int sample_rate) { + state->size = config->size_ms * sample_rate / 1000; + state->step = config->step_size_ms * sample_rate / 1000; + + state->coefficients = malloc(state->size * sizeof(*state->coefficients)); + if (state->coefficients == NULL) { + fprintf(stderr, "Failed to allocate window coefficients\n"); + return 0; + } + + // Populate the window values. + const float arg = M_PI * 2.0 / ((float)state->size); + int i; + for (i = 0; i < state->size; ++i) { + float float_value = 0.5 - (0.5 * cos(arg * (i + 0.5))); + // Scale it to fixed point and round it. + state->coefficients[i] = + floor(float_value * (1 << kFrontendWindowBits) + 0.5); + } + + state->input_used = 0; + state->input = malloc(state->size * sizeof(*state->input)); + if (state->input == NULL) { + fprintf(stderr, "Failed to allocate window input\n"); + return 0; + } + + state->output = malloc(state->size * sizeof(*state->output)); + if (state->output == NULL) { + fprintf(stderr, "Failed to allocate window output\n"); + return 0; + } + + return 1; +} + +void WindowFreeStateContents(struct WindowState* state) { + free(state->coefficients); + free(state->input); + free(state->output); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window_util.h new file mode 100644 index 000000000..68e4de9eb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/experimental/microfrontend/lib/window_util.h @@ -0,0 +1,45 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_WINDOW_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_WINDOW_UTIL_H_ + +#include "tensorflow/lite/experimental/microfrontend/lib/window.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct WindowConfig { + // length of window frame in milliseconds + size_t size_ms; + // length of step for next frame in milliseconds + size_t step_size_ms; +}; + +// Populates the WindowConfig with "sane" default values. +void WindowFillConfigWithDefaults(struct WindowConfig* config); + +// Allocates any buffers. +int WindowPopulateState(const struct WindowConfig* config, + struct WindowState* state, int sample_rate); + +// Frees any allocated buffers. +void WindowFreeStateContents(struct WindowState* state); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_WINDOW_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/common.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/common.h new file mode 100644 index 000000000..c59a01b33 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/common.h @@ -0,0 +1,1227 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_COMMON_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_COMMON_H_ + +#include +#ifndef ALLOW_SLOW_GENERIC_DEPTHWISECONV_FALLBACK +#ifdef GEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK +#define ALLOW_SLOW_GENERIC_DEPTHWISECONV_FALLBACK +#endif +#endif + +#include +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/optimized/neon_check.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +constexpr int kReverseShift = -1; + +inline void GetActivationMinMax(FusedActivationFunctionType ac, + float* output_activation_min, + float* output_activation_max) { + switch (ac) { + case FusedActivationFunctionType::kNone: + *output_activation_min = std::numeric_limits::lowest(); + *output_activation_max = std::numeric_limits::max(); + break; + case FusedActivationFunctionType::kRelu: + *output_activation_min = 0.f; + *output_activation_max = std::numeric_limits::max(); + break; + case FusedActivationFunctionType::kRelu1: + *output_activation_min = -1.f; + *output_activation_max = 1.f; + break; + case FusedActivationFunctionType::kRelu6: + *output_activation_min = 0.f; + *output_activation_max = 6.f; + break; + } +} + +template +inline T ActivationFunctionWithMinMax(T x, T output_activation_min, + T output_activation_max) { + using std::max; + using std::min; + return min(max(x, output_activation_min), output_activation_max); +} + +// Legacy function, left for compatibility only. +template +float ActivationFunction(float x) { + float output_activation_min, output_activation_max; + GetActivationMinMax(Ac, &output_activation_min, &output_activation_max); + return ActivationFunctionWithMinMax(x, output_activation_min, + output_activation_max); +} + +inline void BiasAndClamp(float clamp_min, float clamp_max, int bias_size, + const float* bias_data, int array_size, + float* array_data) { + if (bias_size == 0) return; + // Note: see b/132215220: in May 2019 we thought it would be OK to replace + // this with the Eigen one-liner: + // return (array.colwise() + bias).cwiseMin(clamp_max).cwiseMin(clamp_max). + // This turned out to severely regress performance: +4ms (i.e. 8%) on + // MobileNet v2 / 1.0 / 224. So we keep custom NEON code for now. + TFLITE_DCHECK_EQ((array_size % bias_size), 0); +#ifdef USE_NEON + float* array_ptr = array_data; + float* array_end_ptr = array_ptr + array_size; + const auto clamp_min_vec = vdupq_n_f32(clamp_min); + const auto clamp_max_vec = vdupq_n_f32(clamp_max); + for (; array_ptr != array_end_ptr; array_ptr += bias_size) { + int i = 0; + for (; i <= bias_size - 16; i += 16) { + auto b0 = vld1q_f32(bias_data + i); + auto b1 = vld1q_f32(bias_data + i + 4); + auto b2 = vld1q_f32(bias_data + i + 8); + auto b3 = vld1q_f32(bias_data + i + 12); + auto a0 = vld1q_f32(array_ptr + i); + auto a1 = vld1q_f32(array_ptr + i + 4); + auto a2 = vld1q_f32(array_ptr + i + 8); + auto a3 = vld1q_f32(array_ptr + i + 12); + auto x0 = vaddq_f32(a0, b0); + auto x1 = vaddq_f32(a1, b1); + auto x2 = vaddq_f32(a2, b2); + auto x3 = vaddq_f32(a3, b3); + x0 = vmaxq_f32(clamp_min_vec, x0); + x1 = vmaxq_f32(clamp_min_vec, x1); + x2 = vmaxq_f32(clamp_min_vec, x2); + x3 = vmaxq_f32(clamp_min_vec, x3); + x0 = vminq_f32(clamp_max_vec, x0); + x1 = vminq_f32(clamp_max_vec, x1); + x2 = vminq_f32(clamp_max_vec, x2); + x3 = vminq_f32(clamp_max_vec, x3); + vst1q_f32(array_ptr + i, x0); + vst1q_f32(array_ptr + i + 4, x1); + vst1q_f32(array_ptr + i + 8, x2); + vst1q_f32(array_ptr + i + 12, x3); + } + for (; i <= bias_size - 4; i += 4) { + auto b = vld1q_f32(bias_data + i); + auto a = vld1q_f32(array_ptr + i); + auto x = vaddq_f32(a, b); + x = vmaxq_f32(clamp_min_vec, x); + x = vminq_f32(clamp_max_vec, x); + vst1q_f32(array_ptr + i, x); + } + for (; i < bias_size; i++) { + array_ptr[i] = ActivationFunctionWithMinMax(array_ptr[i] + bias_data[i], + clamp_min, clamp_max); + } + } +#else // not NEON + for (int array_offset = 0; array_offset < array_size; + array_offset += bias_size) { + for (int i = 0; i < bias_size; i++) { + array_data[array_offset + i] = ActivationFunctionWithMinMax( + array_data[array_offset + i] + bias_data[i], clamp_min, clamp_max); + } + } +#endif +} + +// Single-rounding MultiplyByQuantizedMultiplier +#if TFLITE_SINGLE_ROUNDING +inline int32_t MultiplyByQuantizedMultiplier(int32_t x, + int32_t quantized_multiplier, + int shift) { + TFLITE_DCHECK(quantized_multiplier >= 0); + TFLITE_DCHECK(shift >= -31 && shift <= 30); + + const int64_t total_shift = 31 - shift; + const int64_t round = static_cast(1) << (total_shift - 1); + int64_t result = x * static_cast(quantized_multiplier) + round; + result = result >> total_shift; + + TFLITE_DCHECK(result >= std::numeric_limits::min() && + result <= std::numeric_limits::max()); + return static_cast(result); +} + +inline int32_t MultiplyByQuantizedMultiplierSmallerThanOneExp( + int32_t x, int32_t quantized_multiplier, int shift) { + TFLITE_DCHECK_LE(shift, 0); + return MultiplyByQuantizedMultiplier(x, quantized_multiplier, shift); +} + +inline int32_t MultiplyByQuantizedMultiplierGreaterThanOne( + int32_t x, int32_t quantized_multiplier, int shift) { + TFLITE_DCHECK_GE(shift, 0); + return MultiplyByQuantizedMultiplier(x, quantized_multiplier, shift); +} + +inline int32_t MultiplyByQuantizedMultiplier(int64_t x, + int32_t quantized_multiplier, + int shift) { + // Inputs: + // - quantized_multiplier has fixed point at bit 31 + // - shift is -31 to +7 (negative for right shift) + // + // Assumptions: The following input ranges are assumed + // - quantize_scale>=0 (the usual range is (1<<30) to (1>>31)-1) + // - scaling is chosen so final scaled result fits in int32_t + // - input x is in the range -(1<<47) <= x < (1<<47) + TFLITE_DCHECK(quantized_multiplier >= 0); + TFLITE_DCHECK(shift >= -31 && shift < 8); + TFLITE_DCHECK(x >= -(static_cast(1) << 47) && + x < (static_cast(1) << 47)); + + const int32_t reduced_multiplier = + (quantized_multiplier < 0x7FFF0000) + ? ((quantized_multiplier + (1 << 15)) >> 16) + : 0x7FFF; + const int64_t total_shift = 15 - shift; + const int64_t round = static_cast(1) << (total_shift - 1); + int64_t result = x * static_cast(reduced_multiplier) + round; + result = result >> total_shift; + + TFLITE_DCHECK(result >= std::numeric_limits::min() && + result <= std::numeric_limits::max()); + return static_cast(result); +} + +#ifdef USE_NEON +inline int32x4x4_t MultiplyByQuantizedMultiplier4Rows( + int32x4x4_t input_val, int32_t quantized_multiplier, int shift) { + TFLITE_DCHECK(quantized_multiplier >= 0); + + const int right_shift = std::min(-1, shift); + const int left_shift = shift - right_shift; + + const int32x4_t multiplier_dup = vdupq_n_s32(quantized_multiplier); + const int32x4_t left_shift_dup = vdupq_n_s32(left_shift); + const int32x4_t right_shift_dup = vdupq_n_s32(right_shift); + + int32x4x4_t result; + result.val[0] = vrshlq_s32( + vqdmulhq_s32(vshlq_s32(input_val.val[0], left_shift_dup), multiplier_dup), + right_shift_dup); + + result.val[1] = vrshlq_s32( + vqdmulhq_s32(vshlq_s32(input_val.val[1], left_shift_dup), multiplier_dup), + right_shift_dup); + + result.val[2] = vrshlq_s32( + vqdmulhq_s32(vshlq_s32(input_val.val[2], left_shift_dup), multiplier_dup), + right_shift_dup); + + result.val[3] = vrshlq_s32( + vqdmulhq_s32(vshlq_s32(input_val.val[3], left_shift_dup), multiplier_dup), + right_shift_dup); + + return result; +} +#endif // USE_NEON +// Double-rounding MultiplyByQuantizedMultiplier +#else +inline int32_t MultiplyByQuantizedMultiplierSmallerThanOneExp( + int32_t x, int32_t quantized_multiplier, int left_shift) { + using gemmlowp::RoundingDivideByPOT; + using gemmlowp::SaturatingRoundingDoublingHighMul; + return RoundingDivideByPOT( + SaturatingRoundingDoublingHighMul(x, quantized_multiplier), -left_shift); +} + +inline int32_t MultiplyByQuantizedMultiplierGreaterThanOne( + int32_t x, int32_t quantized_multiplier, int left_shift) { + using gemmlowp::SaturatingRoundingDoublingHighMul; + return SaturatingRoundingDoublingHighMul(x * (1 << left_shift), + quantized_multiplier); +} + +inline int32_t MultiplyByQuantizedMultiplier(int32_t x, + int32_t quantized_multiplier, + int shift) { + using gemmlowp::RoundingDivideByPOT; + using gemmlowp::SaturatingRoundingDoublingHighMul; + int left_shift = shift > 0 ? shift : 0; + int right_shift = shift > 0 ? 0 : -shift; + return RoundingDivideByPOT(SaturatingRoundingDoublingHighMul( + x * (1 << left_shift), quantized_multiplier), + right_shift); +} + +inline int32_t MultiplyByQuantizedMultiplier(int64_t x, + int32_t quantized_multiplier, + int shift) { + // Inputs: + // - quantized_multiplier has fixed point at bit 31 + // - shift is -31 to +7 (negative for right shift) + // + // Assumptions: The following input ranges are assumed + // - quantize_scale>=0 (the usual range is (1<<30) to (1>>31)-1) + // - scaling is chosen so final scaled result fits in int32_t + // - input x is in the range -(1<<47) <= x < (1<<47) + assert(quantized_multiplier >= 0); + assert(shift >= -31 && shift < 8); + assert(x >= -(static_cast(1) << 47) && + x < (static_cast(1) << 47)); + + int32_t reduced_multiplier = (quantized_multiplier < 0x7FFF0000) + ? ((quantized_multiplier + (1 << 15)) >> 16) + : 0x7FFF; + int total_shift = 15 - shift; + x = (x * (int64_t)reduced_multiplier) + ((int64_t)1 << (total_shift - 1)); + int32_t result = x >> total_shift; + return result; +} + +#ifdef USE_NEON +// Round uses ARM's rounding shift right. +inline int32x4x4_t MultiplyByQuantizedMultiplier4Rows( + int32x4x4_t input_val, int32_t quantized_multiplier, int shift) { + const int left_shift = std::max(shift, 0); + const int right_shift = std::min(shift, 0); + int32x4x4_t result; + + int32x4_t multiplier_dup = vdupq_n_s32(quantized_multiplier); + int32x4_t left_shift_dup = vdupq_n_s32(left_shift); + int32x4_t right_shift_dup = vdupq_n_s32(right_shift); + + result.val[0] = + vrshlq_s32(vqrdmulhq_s32(vshlq_s32(input_val.val[0], left_shift_dup), + multiplier_dup), + right_shift_dup); + + result.val[1] = + vrshlq_s32(vqrdmulhq_s32(vshlq_s32(input_val.val[1], left_shift_dup), + multiplier_dup), + right_shift_dup); + + result.val[2] = + vrshlq_s32(vqrdmulhq_s32(vshlq_s32(input_val.val[2], left_shift_dup), + multiplier_dup), + right_shift_dup); + + result.val[3] = + vrshlq_s32(vqrdmulhq_s32(vshlq_s32(input_val.val[3], left_shift_dup), + multiplier_dup), + right_shift_dup); + + return result; +} +#endif // USE_NEON +#endif // TFLITE_SINGLE_ROUNDING + +template +int CountLeadingZeros(T integer_input) { + static_assert(std::is_unsigned::value, + "Only unsigned integer types handled."); +#if defined(__GNUC__) + return integer_input ? __builtin_clz(integer_input) + : std::numeric_limits::digits; +#else + if (integer_input == 0) { + return std::numeric_limits::digits; + } + + const T one_in_leading_positive = static_cast(1) + << (std::numeric_limits::digits - 1); + int leading_zeros = 0; + while (integer_input < one_in_leading_positive) { + integer_input <<= 1; + ++leading_zeros; + } + return leading_zeros; +#endif +} + +template +inline int CountLeadingSignBits(T integer_input) { + static_assert(std::is_signed::value, "Only signed integer types handled."); +#if defined(__GNUC__) && !defined(__clang__) + return integer_input ? __builtin_clrsb(integer_input) + : std::numeric_limits::digits; +#else + using U = typename std::make_unsigned::type; + return integer_input >= 0 + ? CountLeadingZeros(static_cast(integer_input)) - 1 + : integer_input != std::numeric_limits::min() + ? CountLeadingZeros(2 * static_cast(-integer_input) - 1) + : 0; +#endif +} + +// Use "count leading zeros" helper functions to do a fast Floor(log_2(x)). +template +inline Integer FloorLog2(Integer n) { + static_assert(std::is_integral::value, ""); + static_assert(std::is_signed::value, ""); + static_assert(sizeof(Integer) == 4 || sizeof(Integer) == 8, ""); + TFLITE_CHECK_GT(n, 0); + if (sizeof(Integer) == 4) { + return 30 - CountLeadingSignBits(n); + } else { + return 62 - CountLeadingSignBits(n); + } +} + +// The size of the LUT depends on the type of input. For uint8 and int8 inputs +// we use a 256 entries LUT to map all the values in the (u)int8 range. For +// int16 inputs the high 9 bits are used for indexing and the 7 remaining bits +// are used for interpolation. We thus use a 513-entries LUT for int16 cases, +// 512 for the 9-bit indexing and 1 extra entry to interpolate the last value. +template +constexpr int LUTSize() { + static_assert(std::is_same::value || + std::is_same::value || + std::is_same::value, + "Only LUTs with uint8, int8 or int16 inputs are supported."); + // As per c++11: constexpr methods cannot have more than one return statement. + return (std::is_same::value || std::is_same::value) + ? 256 + : 513; +} + +// Use the same LUT generation code for both uint8_t and int8_t. Int8_t indexes +// will be directly casted to uint8_t, the int8 LUT will thus be ordered as [0, +// 1, ..., 127, -128, ..., -2, -1] instead of [-128, -127, ..., -1, 0, 1, ..., +// 126, 127]. +template +inline typename std::enable_if::value || + std::is_same::value, + void>::type +LUTPopulate(float input_scale, int32_t input_zero_point, float output_scale, + int32_t output_zero_point, float (*transform)(float), T* lut) { + uint8_t* lut_uint8 = reinterpret_cast(lut); + const float inverse_scale = 1 / output_scale; + int32_t maxval = std::numeric_limits::max(); + int32_t minval = std::numeric_limits::min(); + for (int32_t val = minval; val <= maxval; ++val) { + const float dequantized = input_scale * (val - input_zero_point); + const float transformed = transform(dequantized); + const float rescaled = std::round(transformed * inverse_scale); + const int32_t quantized = + static_cast(rescaled + output_zero_point); + lut_uint8[static_cast(static_cast(val))] = static_cast( + static_cast(std::max(std::min(maxval, quantized), minval))); + } +} + +// Keep floating-point type configurable for backward compatibility. float +// should be used for FloatT by default. +template +inline typename std::enable_if::value, void>::type +LUTPopulate(FloatT input_scale, int32_t input_zero_point, FloatT output_scale, + int32_t output_zero_point, FloatT (*transform)(FloatT), T* lut) { + static_assert(std::is_floating_point::value, + "FloatT must be a floating-point type."); + const FloatT input_min = + input_scale * (std::numeric_limits::min() - input_zero_point); + const FloatT input_max = + input_scale * (std::numeric_limits::max() - input_zero_point); + const FloatT output_min = + output_scale * (std::numeric_limits::min() - output_zero_point); + const FloatT output_max = + output_scale * (std::numeric_limits::max() - output_zero_point); + + const int nb_steps = 512; + const FloatT step = (input_max - input_min) / nb_steps; + const FloatT half_step = step / 2; + const FloatT output_scaling_inv = + static_cast(std::numeric_limits::max() - + std::numeric_limits::min() + 1) / + (output_max - output_min); + const FloatT table_min = static_cast(std::numeric_limits::min()); + const FloatT table_max = static_cast(std::numeric_limits::max()); + + for (int i = 0; i < nb_steps; i++) { + const FloatT val = transform(input_min + i * step); + const FloatT val_midpoint = transform(input_min + i * step + half_step); + const FloatT val_next = transform(input_min + (i + 1) * step); + + const FloatT sample_val = TfLiteRound(val * output_scaling_inv); + const FloatT midpoint_interp_val = + TfLiteRound((val_next * output_scaling_inv + + TfLiteRound(val * output_scaling_inv)) / + 2); + const FloatT midpoint_val = TfLiteRound(val_midpoint * output_scaling_inv); + const FloatT midpoint_err = midpoint_interp_val - midpoint_val; + const FloatT bias = TfLiteRound(midpoint_err / 2); + + lut[i] = static_cast(std::min( + std::max(sample_val - bias, table_min), table_max)); + } + + lut[nb_steps] = static_cast(std::min( + std::max(TfLiteRound(transform(input_max) * output_scaling_inv), + table_min), + table_max)); +} + +template +inline typename std::enable_if::value, void>::type +LUTPopulate(float input_scale, int32_t input_zero_point, float output_scale, + int32_t output_zero_point, float (*transform)(float), T* lut) { + LUTPopulate(input_scale, input_zero_point, output_scale, + output_zero_point, transform, lut); +} + +// Deprecated and will be removed in future, please use LUTPopulate instead +template +inline void gen_lut(FloatT (*func)(FloatT), FloatT input_min, FloatT input_max, + FloatT output_min, FloatT output_max, LutOutT* lut) { + static_assert(std::is_same::value, + "Input and output type of the LUT must be the same."); + static_assert(std::is_same::value, + "Only int16_t type LUT are supported."); + static_assert(std::is_same::value, + "Only float type is supported for FloatT."); + using T = LutInT; + + const auto zero_point = [](float min, float max, float scale) { + // Symmetric int16 LUT, we know the zero-point will not overflow an int32_t + // and zero-point from min will be the same as from max. + return static_cast( + static_cast(std::numeric_limits::min()) - min / scale); + }; + + const float scale = static_cast(std::numeric_limits::max() - + std::numeric_limits::min()); + const float input_scale = (input_max - input_min) / scale; + const FloatT output_scale = (output_max - output_min) / scale; + const int32_t input_zero_point = + zero_point(input_min, input_max, input_scale); + const int32_t output_zero_point = + zero_point(output_min, output_max, output_scale); + + return LUTPopulate(input_scale, input_zero_point, output_scale, + output_zero_point, func, lut); +} + +// int16_t -> int16_t table lookup with interpolation +// LUT must have 513 values +inline int16_t LUTLookup(int16_t value, const int16_t* lut) { + // 512 base values, lut[513] is only used to calculate the slope + const uint16_t index = static_cast(256 + (value >> 7)); + assert(index < 512 && "LUT index out of range."); + const int16_t offset = value & 0x7f; + + // Base and slope are Q0.x + const int16_t base = lut[index]; + const int16_t slope = lut[index + 1] - lut[index]; + + // Q0.x * Q0.7 = Q0.(x + 7) + // Round and convert from Q0.(x + 7) to Q0.x + const int delta = (slope * offset + 64) >> 7; + + // Q0.15 + Q0.15 + return static_cast(base + delta); +} + +// int8_t -> int8_t table lookup without interpolation +// LUT must have 256 values +// LUTPopulate has ordered the LUT so that indexing it with an +// int8_t is just done by casting it to an uint8_t. +inline int8_t LUTLookup(int8_t value, const int8_t* lut) { + return lut[static_cast(value)]; +} + +// uint8_t -> uint8_t table lookup without interpolation +// LUT must have 256 values +inline uint8_t LUTLookup(uint8_t value, const uint8_t* lut) { + return lut[value]; +} + +// Table of sigmoid(i/24) at 0.16 format - 256 elements. + +// We use combined sigmoid and tanh look-up table, since +// tanh(x) = 2*sigmoid(2*x) -1. +// Both functions are symmetric, so the LUT table is only needed +// for the absolute value of the input. +static const uint16_t sigmoid_table_uint16[256] = { + 32768, 33451, 34133, 34813, 35493, 36169, 36843, 37513, 38180, 38841, 39498, + 40149, 40794, 41432, 42064, 42688, 43304, 43912, 44511, 45102, 45683, 46255, + 46817, 47369, 47911, 48443, 48964, 49475, 49975, 50464, 50942, 51409, 51865, + 52311, 52745, 53169, 53581, 53983, 54374, 54755, 55125, 55485, 55834, 56174, + 56503, 56823, 57133, 57433, 57724, 58007, 58280, 58544, 58800, 59048, 59288, + 59519, 59743, 59959, 60168, 60370, 60565, 60753, 60935, 61110, 61279, 61441, + 61599, 61750, 61896, 62036, 62172, 62302, 62428, 62549, 62666, 62778, 62886, + 62990, 63090, 63186, 63279, 63368, 63454, 63536, 63615, 63691, 63765, 63835, + 63903, 63968, 64030, 64090, 64148, 64204, 64257, 64308, 64357, 64405, 64450, + 64494, 64536, 64576, 64614, 64652, 64687, 64721, 64754, 64786, 64816, 64845, + 64873, 64900, 64926, 64950, 64974, 64997, 65019, 65039, 65060, 65079, 65097, + 65115, 65132, 65149, 65164, 65179, 65194, 65208, 65221, 65234, 65246, 65258, + 65269, 65280, 65291, 65301, 65310, 65319, 65328, 65337, 65345, 65352, 65360, + 65367, 65374, 65381, 65387, 65393, 65399, 65404, 65410, 65415, 65420, 65425, + 65429, 65433, 65438, 65442, 65445, 65449, 65453, 65456, 65459, 65462, 65465, + 65468, 65471, 65474, 65476, 65479, 65481, 65483, 65485, 65488, 65489, 65491, + 65493, 65495, 65497, 65498, 65500, 65501, 65503, 65504, 65505, 65507, 65508, + 65509, 65510, 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65517, 65518, + 65519, 65520, 65520, 65521, 65522, 65522, 65523, 65523, 65524, 65524, 65525, + 65525, 65526, 65526, 65526, 65527, 65527, 65528, 65528, 65528, 65529, 65529, + 65529, 65529, 65530, 65530, 65530, 65530, 65531, 65531, 65531, 65531, 65531, + 65532, 65532, 65532, 65532, 65532, 65532, 65533, 65533, 65533, 65533, 65533, + 65533, 65533, 65533, 65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, + 65534, 65534, 65535}; + +// TODO(b/77858996): Add these to gemmlowp. +template +IntegerType SaturatingAddNonGemmlowp(IntegerType a, IntegerType b) { + static_assert(std::is_same::value, "unimplemented"); + return a; +} + +template <> +inline std::int32_t SaturatingAddNonGemmlowp(std::int32_t a, std::int32_t b) { + std::int64_t a64 = a; + std::int64_t b64 = b; + std::int64_t sum = a64 + b64; + return static_cast(std::min( + static_cast(std::numeric_limits::max()), + std::max( + static_cast(std::numeric_limits::min()), + sum))); +} + +template +gemmlowp::FixedPoint SaturatingAddNonGemmlowp( + gemmlowp::FixedPoint a, + gemmlowp::FixedPoint b) { + return gemmlowp::FixedPoint::FromRaw( + SaturatingAddNonGemmlowp(a.raw(), b.raw())); +} + +template +IntegerType SaturatingSub(IntegerType a, IntegerType b) { + static_assert(std::is_same::value, "unimplemented"); + return a; +} + +template <> +inline std::int16_t SaturatingSub(std::int16_t a, std::int16_t b) { + std::int32_t a32 = a; + std::int32_t b32 = b; + std::int32_t diff = a32 - b32; + return static_cast( + std::min(static_cast(32767), + std::max(static_cast(-32768), diff))); +} + +template <> +inline std::int32_t SaturatingSub(std::int32_t a, std::int32_t b) { + std::int64_t a64 = a; + std::int64_t b64 = b; + std::int64_t diff = a64 - b64; + return static_cast(std::min( + static_cast(std::numeric_limits::max()), + std::max( + static_cast(std::numeric_limits::min()), + diff))); +} + +template +gemmlowp::FixedPoint SaturatingSub( + gemmlowp::FixedPoint a, + gemmlowp::FixedPoint b) { + return gemmlowp::FixedPoint::FromRaw( + SaturatingSub(a.raw(), b.raw())); +} +// End section to be moved to gemmlowp. + +template +IntegerType SaturatingRoundingMultiplyByPOTParam(IntegerType x, int exponent) { + if (exponent == 0) { + return x; + } + using ScalarIntegerType = + typename gemmlowp::FixedPointRawTypeTraits::ScalarRawType; + const IntegerType min = + gemmlowp::Dup(std::numeric_limits::min()); + const IntegerType max = + gemmlowp::Dup(std::numeric_limits::max()); + const int ScalarIntegerTypeBits = 8 * sizeof(ScalarIntegerType); + + const std::int32_t threshold = + ((1 << (ScalarIntegerTypeBits - 1 - exponent)) - 1); + const IntegerType positive_mask = + gemmlowp::MaskIfGreaterThan(x, gemmlowp::Dup(threshold)); + const IntegerType negative_mask = + gemmlowp::MaskIfLessThan(x, gemmlowp::Dup(-threshold)); + + IntegerType result = gemmlowp::ShiftLeft(x, exponent); + result = gemmlowp::SelectUsingMask(positive_mask, max, result); + result = gemmlowp::SelectUsingMask(negative_mask, min, result); + return result; +} + +// If we want to leave IntegerBits fixed, then multiplication +// by a power of two has to be saturating/rounding, not exact anymore. +template +gemmlowp::FixedPoint +SaturatingRoundingMultiplyByPOTParam( + gemmlowp::FixedPoint a, int exponent) { + return gemmlowp::FixedPoint::FromRaw( + SaturatingRoundingMultiplyByPOTParam(a.raw(), exponent)); +} + +// Convert int32_t multiplier to int16_t with rounding. +inline void DownScaleInt32ToInt16Multiplier(int32_t multiplier_int32_t, + int16_t* multiplier_int16_t) { + TFLITE_DCHECK_GE(multiplier_int32_t, 0); + static constexpr int32_t kRoundingOffset = 1 << 15; + if (multiplier_int32_t >= + std::numeric_limits::max() - kRoundingOffset) { + *multiplier_int16_t = std::numeric_limits::max(); + return; + } + const int32_t result = (multiplier_int32_t + kRoundingOffset) >> 16; + TFLITE_DCHECK_LE(result << 16, multiplier_int32_t + kRoundingOffset); + TFLITE_DCHECK_GT(result << 16, multiplier_int32_t - kRoundingOffset); + *multiplier_int16_t = result; + TFLITE_DCHECK_EQ(*multiplier_int16_t, result); +} + +// Minimum output bits to accommodate log of maximum input range. It actually +// does not matter if one considers, say, [-64,64] or [-64,64). +// +// For example, run this through Octave: +// [0:127; ... +// ceil(log(abs( log(2.^(0:127))+1 ))/log(2)); ... +// ceil(log(abs( log(2.^(0:127))+1 ))/log(2))] +constexpr int min_log_x_output_bits(int input_bits) { + return input_bits > 90 ? 7 + : input_bits > 44 ? 6 + : input_bits > 21 ? 5 + : input_bits > 10 ? 4 + : input_bits > 4 ? 3 + : input_bits > 1 ? 2 + : 1; +} + +// Although currently the name of this function says that it cannot handle +// values less than 1, in practice it can handle as low as 1/x_max, where +// x_max is the largest representable input. In other words, the output range +// is symmetric. +template +inline gemmlowp::FixedPoint +log_x_for_x_greater_than_or_equal_to_1_impl( + gemmlowp::FixedPoint input_val) { + // assert(__builtin_clz(0u) >= std::numeric_limits::digits - 1); + // assert(__builtin_clz(0u) <= std::numeric_limits::digits); + using FixedPoint0 = gemmlowp::FixedPoint; + // The reason for accumulating the result with an extra bit of headroom is + // that z_pow_2_adj * log_2 might be saturated, and adding num_scaled * + // recip_denom will otherwise introduce an error. + static constexpr int kAccumIntegerBits = OutputIntegerBits + 1; + using FixedPointAccum = gemmlowp::FixedPoint; + + const FixedPoint0 log_2 = GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT( + FixedPoint0, 1488522236, std::log(2.0)); + const FixedPoint0 sqrt_sqrt_half = GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT( + FixedPoint0, 1805811301, std::sqrt(std::sqrt(0.5))); + const FixedPoint0 sqrt_half = GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT( + FixedPoint0, 1518500250, std::sqrt(0.5)); + const FixedPoint0 one_quarter = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(FixedPoint0, 536870912, 1.0 / 4.0); + + const FixedPoint0 alpha_n = GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT( + FixedPoint0, 117049297, 11.0 / 240.0 * std::sqrt(std::sqrt(2.0))); + const FixedPoint0 alpha_d = GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT( + FixedPoint0, 127690142, 1.0 / 20.0 * std::sqrt(std::sqrt(2.0))); + const FixedPoint0 alpha_i = GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT( + FixedPoint0, 1057819769, + 2.0 / std::sqrt(std::sqrt(2.0)) - std::sqrt(std::sqrt(2.0))); + const FixedPoint0 alpha_f = GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT( + FixedPoint0, 638450708, 1.0 / 4.0 * std::sqrt(std::sqrt(2.0))); + + const FixedPointAccum shifted_quarter = + gemmlowp::Rescale(one_quarter); + + // Reinterpret the input value as Q0.31, because we will figure out the + // required shift "ourselves" instead of using, say, Rescale. + FixedPoint0 z_a = FixedPoint0::FromRaw(input_val.raw()); + // z_a_pow_2 = input_integer_bits - z_a_headroom; + int z_a_headroom_plus_1 = CountLeadingZeros(static_cast(z_a.raw())); + FixedPoint0 r_a_tmp = + SaturatingRoundingMultiplyByPOTParam(z_a, (z_a_headroom_plus_1 - 1)); + const int32_t r_a_raw = + SaturatingRoundingMultiplyByPOTParam((r_a_tmp * sqrt_half).raw(), 1); + // z_pow_2_adj = max(z_pow_2_a - 0.75, z_pow_2_b - 0.25); + // z_pow_2_adj = max(InputIntegerBits - z_a_headroom_plus_1 + 0.25, + // InputIntegerBits - z_b_headroom - 0.25); + const FixedPointAccum z_a_pow_2_adj = SaturatingAddNonGemmlowp( + FixedPointAccum::FromRaw(SaturatingRoundingMultiplyByPOTParam( + static_cast(InputIntegerBits - z_a_headroom_plus_1), + 31 - kAccumIntegerBits)), + shifted_quarter); + + // z_b is treated like z_a, but premultiplying by sqrt(0.5). + FixedPoint0 z_b = z_a * sqrt_half; + int z_b_headroom = CountLeadingZeros(static_cast(z_b.raw())) - 1; + const int32_t r_b_raw = + SaturatingRoundingMultiplyByPOTParam(z_a.raw(), z_b_headroom); + const FixedPointAccum z_b_pow_2_adj = SaturatingSub( + FixedPointAccum::FromRaw(SaturatingRoundingMultiplyByPOTParam( + static_cast(InputIntegerBits - z_b_headroom), + 31 - kAccumIntegerBits)), + shifted_quarter); + + const FixedPoint0 r = FixedPoint0::FromRaw(std::min(r_a_raw, r_b_raw)); + const FixedPointAccum z_pow_2_adj = FixedPointAccum::FromRaw( + std::max(z_a_pow_2_adj.raw(), z_b_pow_2_adj.raw())); + + const FixedPoint0 p = gemmlowp::RoundingHalfSum(r, sqrt_sqrt_half); + FixedPoint0 q = r - sqrt_sqrt_half; + q = q + q; + + const FixedPoint0 common_sq = q * q; + const FixedPoint0 num = q * r + q * common_sq * alpha_n; + const FixedPoint0 denom_minus_one_0 = + p * (alpha_i + q + alpha_d * common_sq) + alpha_f * q; + const FixedPoint0 recip_denom = + one_over_one_plus_x_for_x_in_0_1(denom_minus_one_0); + + const FixedPointAccum num_scaled = gemmlowp::Rescale(num); + return gemmlowp::Rescale(z_pow_2_adj * log_2 + + num_scaled * recip_denom); +} + +template +inline gemmlowp::FixedPoint +log_x_for_x_greater_than_or_equal_to_1( + gemmlowp::FixedPoint input_val) { + static_assert( + OutputIntegerBits >= min_log_x_output_bits(InputIntegerBits), + "Output integer bits must be sufficient to accommodate logs of inputs."); + return log_x_for_x_greater_than_or_equal_to_1_impl( + input_val); +} + +inline int32_t GetReciprocal(int32_t x, int x_integer_digits, + int* num_bits_over_unit) { + int headroom_plus_one = CountLeadingZeros(static_cast(x)); + // This is the number of bits to the left of the binary point above 1.0. + // Consider x=1.25. In that case shifted_scale=0.8 and + // no later adjustment will be needed. + *num_bits_over_unit = x_integer_digits - headroom_plus_one; + const int32_t shifted_sum_minus_one = + static_cast((static_cast(x) << headroom_plus_one) - + (static_cast(1) << 31)); + + gemmlowp::FixedPoint shifted_scale = + gemmlowp::one_over_one_plus_x_for_x_in_0_1( + gemmlowp::FixedPoint::FromRaw(shifted_sum_minus_one)); + return shifted_scale.raw(); +} + +inline void GetInvSqrtQuantizedMultiplierExp(int32_t input, int reverse_shift, + int32_t* output_inv_sqrt, + int* output_shift) { + TFLITE_DCHECK_GE(input, 0); + if (input <= 1) { + // Handle the input value 1 separately to avoid overflow in that case + // in the general computation below (b/143972021). Also handle 0 as if it + // were a 1. 0 is an invalid input here (divide by zero) and 1 is a valid + // but rare/unrealistic input value. We can expect both to occur in some + // incompletely trained models, but probably not in fully trained models. + *output_inv_sqrt = std::numeric_limits::max(); + *output_shift = 0; + return; + } + TFLITE_DCHECK_GT(input, 1); + *output_shift = 11; + while (input >= (1 << 29)) { + input /= 4; + ++*output_shift; + } + const unsigned max_left_shift_bits = + CountLeadingZeros(static_cast(input)) - 1; + const unsigned max_left_shift_bit_pairs = max_left_shift_bits / 2; + const unsigned left_shift_bit_pairs = max_left_shift_bit_pairs - 1; + *output_shift -= left_shift_bit_pairs; + input <<= 2 * left_shift_bit_pairs; + TFLITE_DCHECK_GE(input, (1 << 27)); + TFLITE_DCHECK_LT(input, (1 << 29)); + using gemmlowp::FixedPoint; + using gemmlowp::Rescale; + using gemmlowp::SaturatingRoundingMultiplyByPOT; + // Using 3 integer bits gives us enough room for the internal arithmetic in + // this Newton-Raphson iteration. + using F3 = FixedPoint; + using F0 = FixedPoint; + const F3 fixedpoint_input = F3::FromRaw(input >> 1); + const F3 fixedpoint_half_input = + SaturatingRoundingMultiplyByPOT<-1>(fixedpoint_input); + const F3 fixedpoint_half_three = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(F3, (1 << 28) + (1 << 27), 1.5); + // Newton-Raphson iteration + // Naive unoptimized starting guess: x = 1 + F3 x = F3::One(); + // Naive unoptimized number of iterations: 5 + for (int i = 0; i < 5; i++) { + const F3 x3 = Rescale<3>(x * x * x); + x = Rescale<3>(fixedpoint_half_three * x - fixedpoint_half_input * x3); + } + const F0 fixedpoint_half_sqrt_2 = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(F0, 1518500250, std::sqrt(2.) / 2.); + x = x * fixedpoint_half_sqrt_2; + *output_inv_sqrt = x.raw(); + if (*output_shift < 0) { + *output_inv_sqrt <<= -*output_shift; + *output_shift = 0; + } + // Convert right shift (right is positive) to left shift. + *output_shift *= reverse_shift; +} + +// DO NOT USE THIS STRUCT FOR NEW FUNCTIONALITY BEYOND IMPLEMENTING +// BROADCASTING. +// +// NdArrayDesc describes the shape and memory layout of an N-dimensional +// rectangular array of numbers. +// +// NdArrayDesc is basically identical to Dims defined in types.h. +// However, as Dims is to be deprecated, this class exists as an adaptor +// to enable simple unoptimized implementations of element-wise broadcasting +// operations. +template +struct NdArrayDesc { + // The "extent" of each dimension. Indices along dimension d must be in the + // half-open interval [0, extents[d]). + int extents[N]; + + // The number of *elements* (not bytes) between consecutive indices of each + // dimension. + int strides[N]; +}; + +// DO NOT USE THIS FUNCTION FOR NEW FUNCTIONALITY BEYOND IMPLEMENTING +// BROADCASTING. +// +// Same as Offset(), except takes as NdArrayDesc instead of Dims. +inline int SubscriptToIndex(const NdArrayDesc<4>& desc, int i0, int i1, int i2, + int i3) { + TFLITE_DCHECK(i0 >= 0 && i0 < desc.extents[0]); + TFLITE_DCHECK(i1 >= 0 && i1 < desc.extents[1]); + TFLITE_DCHECK(i2 >= 0 && i2 < desc.extents[2]); + TFLITE_DCHECK(i3 >= 0 && i3 < desc.extents[3]); + return i0 * desc.strides[0] + i1 * desc.strides[1] + i2 * desc.strides[2] + + i3 * desc.strides[3]; +} + +inline int SubscriptToIndex(const NdArrayDesc<5>& desc, int indexes[5]) { + return indexes[0] * desc.strides[0] + indexes[1] * desc.strides[1] + + indexes[2] * desc.strides[2] + indexes[3] * desc.strides[3] + + indexes[4] * desc.strides[4]; +} + +inline int SubscriptToIndex(const NdArrayDesc<8>& desc, int indexes[8]) { + return indexes[0] * desc.strides[0] + indexes[1] * desc.strides[1] + + indexes[2] * desc.strides[2] + indexes[3] * desc.strides[3] + + indexes[4] * desc.strides[4] + indexes[5] * desc.strides[5] + + indexes[6] * desc.strides[6] + indexes[7] * desc.strides[7]; +} + +// Given the dimensions of the operands for an element-wise binary broadcast, +// adjusts them so that they can be directly iterated over with simple loops. +// Returns the adjusted dims as instances of NdArrayDesc in 'desc0_out' and +// 'desc1_out'. 'desc0_out' and 'desc1_out' cannot be nullptr. +// +// This function assumes that the two input shapes are compatible up to +// broadcasting and the shorter one has already been prepended with 1s to be the +// same length. E.g., if shape0 is (1, 16, 16, 64) and shape1 is (1, 64), +// shape1 must already have been prepended to be (1, 1, 1, 64). Recall that +// Dims refer to shapes in reverse order. In this case, input0_dims will be +// (64, 16, 16, 1) and input1_dims will be (64, 1, 1, 1). +// +// When two shapes are compatible up to broadcasting, for each dimension d, +// the input extents are either equal, or one of them is 1. +// +// This function performs the following for each dimension d: +// - If the extents are equal, then do nothing since the loop that walks over +// both of the input arrays is correct. +// - Otherwise, one (and only one) of the extents must be 1. Say extent0 is 1 +// and extent1 is e1. Then set extent0 to e1 and stride0 *to 0*. This allows +// array0 to be referenced *at any index* in dimension d and still access the +// same slice. +template +inline void NdArrayDescsForElementwiseBroadcast(const Dims& input0_dims, + const Dims& input1_dims, + NdArrayDesc* desc0_out, + NdArrayDesc* desc1_out) { + TFLITE_DCHECK(desc0_out != nullptr); + TFLITE_DCHECK(desc1_out != nullptr); + + // Copy dims to desc. + for (int i = 0; i < N; ++i) { + desc0_out->extents[i] = input0_dims.sizes[i]; + desc0_out->strides[i] = input0_dims.strides[i]; + desc1_out->extents[i] = input1_dims.sizes[i]; + desc1_out->strides[i] = input1_dims.strides[i]; + } + + // Walk over each dimension. If the extents are equal do nothing. + // Otherwise, set the desc with extent 1 to have extent equal to the other and + // stride 0. + for (int i = 0; i < N; ++i) { + const int extent0 = ArraySize(input0_dims, i); + const int extent1 = ArraySize(input1_dims, i); + if (extent0 != extent1) { + if (extent0 == 1) { + desc0_out->strides[i] = 0; + desc0_out->extents[i] = extent1; + } else { + TFLITE_DCHECK_EQ(extent1, 1); + desc1_out->strides[i] = 0; + desc1_out->extents[i] = extent0; + } + } + } +} + +// Copies dims to desc, calculating strides. +template +inline void CopyDimsToDesc(const RuntimeShape& input_shape, + NdArrayDesc* desc_out) { + int desc_stride = 1; + for (int i = N - 1; i >= 0; --i) { + desc_out->extents[i] = input_shape.Dims(i); + desc_out->strides[i] = desc_stride; + desc_stride *= input_shape.Dims(i); + } +} + +template +inline void NdArrayDescsForElementwiseBroadcast( + const RuntimeShape& input0_shape, const RuntimeShape& input1_shape, + NdArrayDesc* desc0_out, NdArrayDesc* desc1_out) { + TFLITE_DCHECK(desc0_out != nullptr); + TFLITE_DCHECK(desc1_out != nullptr); + + auto extended_input0_shape = RuntimeShape::ExtendedShape(N, input0_shape); + auto extended_input1_shape = RuntimeShape::ExtendedShape(N, input1_shape); + + // Copy dims to desc, calculating strides. + CopyDimsToDesc(extended_input0_shape, desc0_out); + CopyDimsToDesc(extended_input1_shape, desc1_out); + + // Walk over each dimension. If the extents are equal do nothing. + // Otherwise, set the desc with extent 1 to have extent equal to the other and + // stride 0. + for (int i = 0; i < N; ++i) { + const int extent0 = extended_input0_shape.Dims(i); + const int extent1 = extended_input1_shape.Dims(i); + if (extent0 != extent1) { + if (extent0 == 1) { + desc0_out->strides[i] = 0; + desc0_out->extents[i] = extent1; + } else { + TFLITE_DCHECK_EQ(extent1, 1); + desc1_out->strides[i] = 0; + desc1_out->extents[i] = extent0; + } + } + } +} + +template +inline void NdArrayDescsForElementwiseBroadcast( + const RuntimeShape& input0_shape, const RuntimeShape& input1_shape, + const RuntimeShape& input2_shape, NdArrayDesc* desc0_out, + NdArrayDesc* desc1_out, NdArrayDesc* desc2_out) { + TFLITE_DCHECK(desc0_out != nullptr); + TFLITE_DCHECK(desc1_out != nullptr); + TFLITE_DCHECK(desc2_out != nullptr); + + auto extended_input0_shape = RuntimeShape::ExtendedShape(N, input0_shape); + auto extended_input1_shape = RuntimeShape::ExtendedShape(N, input1_shape); + auto extended_input2_shape = RuntimeShape::ExtendedShape(N, input2_shape); + + // Copy dims to desc, calculating strides. + CopyDimsToDesc(extended_input0_shape, desc0_out); + CopyDimsToDesc(extended_input1_shape, desc1_out); + CopyDimsToDesc(extended_input2_shape, desc2_out); + + // Walk over each dimension. If the extents are equal do nothing. + // Otherwise, set the desc with extent 1 to have extent equal to the other and + // stride 0. + for (int i = 0; i < N; ++i) { + const int extent0 = extended_input0_shape.Dims(i); + const int extent1 = extended_input1_shape.Dims(i); + const int extent2 = extended_input2_shape.Dims(i); + + int extent = extent0; + if (extent1 != 1) extent = extent1; + if (extent2 != 1) extent = extent2; + + TFLITE_DCHECK(extent0 == 1 || extent0 == extent); + TFLITE_DCHECK(extent1 == 1 || extent1 == extent); + TFLITE_DCHECK(extent2 == 1 || extent2 == extent); + + if (!(extent0 == extent1 && extent1 == extent2)) { + if (extent0 == 1) { + desc0_out->strides[i] = 0; + desc0_out->extents[i] = extent; + } + if (extent1 == 1) { + desc1_out->strides[i] = 0; + desc1_out->extents[i] = extent; + } + if (extent2 == 1) { + desc2_out->strides[i] = 0; + desc2_out->extents[i] = extent; + } + } + } +} + +// Detailed implementation of NDOpsHelper, the indexes must be a zero array. +// This implementation is equivalent to N nested loops. Ex, if N=4, it can be +// re-writen as: +// for (int b = 0; b < output.extents[0]; ++b) { +// for (int y = 0; y < output.extents[1]; ++y) { +// for (int x = 0; x < output.extents[2]; ++x) { +// for (int c = 0; c < output.extents[3]; ++c) { +// calc({b,y,x,c}); +// } +// } +// } +// } +template +typename std::enable_if::type NDOpsHelperImpl( + const NdArrayDesc& output, const Calc& calc, int indexes[N]) { + for (indexes[DIM] = 0; indexes[DIM] < output.extents[DIM]; ++indexes[DIM]) { + NDOpsHelperImpl(output, calc, indexes); + } +} + +template +typename std::enable_if::type NDOpsHelperImpl( + const NdArrayDesc& output, const Calc& calc, int indexes[N]) { + for (indexes[DIM] = 0; indexes[DIM] < output.extents[DIM]; ++indexes[DIM]) { + calc(indexes); + } +} + +// Execute the calc function in the innermost iteration based on the shape of +// the output. The calc function should take a single argument of type int[N]. +template +inline void NDOpsHelper(const NdArrayDesc& output, const Calc& calc) { + int indexes[N] = {0}; + NDOpsHelperImpl(output, calc, indexes); +} +// Copied from gemmlowp::RoundDown when we dropped direct dependency on +// gemmlowp. +// +// Returns the runtime argument rounded down to the nearest multiple of +// the fixed Modulus. +template +Integer RoundDown(Integer i) { + return i - (i % Modulus); +} + +// Copied from gemmlowp::RoundUp when we dropped direct dependency on +// gemmlowp. +// +// Returns the runtime argument rounded up to the nearest multiple of +// the fixed Modulus. +template +Integer RoundUp(Integer i) { + return RoundDown(i + Modulus - 1); +} + +// Copied from gemmlowp::CeilQuotient when we dropped direct dependency on +// gemmlowp. +// +// Returns the quotient a / b rounded up ('ceil') to the nearest integer. +template +Integer CeilQuotient(Integer a, Integer b) { + return (a + b - 1) / b; +} + +// This function is a copy of gemmlowp::HowManyThreads, copied when we dropped +// the direct dependency of internal/optimized/ on gemmlowp. +// +// It computes a reasonable number of threads to use for a GEMM of shape +// (rows, cols, depth). +// +// TODO(b/131910176): get rid of this function by switching each call site +// to its own more sensible logic for its own workload. +template +inline int LegacyHowManyThreads(int max_num_threads, int rows, int cols, + int depth) { + // Early-exit in the default case where multi-threading is disabled. + if (max_num_threads == 1) { + return 1; + } + + // Ensure that each thread has KernelRows rows to process, if at all possible. + int thread_count = std::min(max_num_threads, rows / KernelRows); + + // Limit the number of threads according to the overall size of the problem. + if (thread_count > 1) { + // Empirically determined value. + static constexpr std::uint64_t min_cubic_size_per_thread = 64 * 1024; + + // We can only multiply two out of three sizes without risking overflow + const std::uint64_t cubic_size = + std::uint64_t(rows) * std::uint64_t(cols) * std::uint64_t(depth); + + thread_count = std::min( + thread_count, static_cast(cubic_size / min_cubic_size_per_thread)); + } + + if (thread_count < 1) { + thread_count = 1; + } + + assert(thread_count > 0 && thread_count <= max_num_threads); + return thread_count; +} + +template +void optimized_ops_preload_l1_stream(const T* ptr) { +#ifdef __GNUC__ + // builtin offered by GCC-compatible compilers including clang + __builtin_prefetch(ptr, /* 0 means read */ 0, /* 0 means no locality */ 0); +#else + (void)ptr; +#endif +} + +template +void optimized_ops_preload_l1_keep(const T* ptr) { +#ifdef __GNUC__ + // builtin offered by GCC-compatible compilers including clang + __builtin_prefetch(ptr, /* 0 means read */ 0, /* 3 means high locality */ 3); +#else + (void)ptr; +#endif +} + +template +void optimized_ops_prefetch_write_l1_keep(const T* ptr) { +#ifdef __GNUC__ + // builtin offered by GCC-compatible compilers including clang + __builtin_prefetch(ptr, /* 1 means write */ 1, /* 3 means high locality */ 3); +#else + (void)ptr; +#endif +} + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_COMMON_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/compatibility.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/compatibility.h new file mode 100644 index 000000000..0d7f9d635 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/compatibility.h @@ -0,0 +1,122 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_COMPATIBILITY_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_COMPATIBILITY_H_ + +#include + +#include "tensorflow/lite/kernels/op_macros.h" + +#ifndef TFLITE_DCHECK +#define TFLITE_DCHECK(condition) (condition) ? (void)0 : TFLITE_ASSERT_FALSE +#endif + +#ifndef TFLITE_DCHECK_EQ +#define TFLITE_DCHECK_EQ(x, y) ((x) == (y)) ? (void)0 : TFLITE_ASSERT_FALSE +#endif + +#ifndef TFLITE_DCHECK_NE +#define TFLITE_DCHECK_NE(x, y) ((x) != (y)) ? (void)0 : TFLITE_ASSERT_FALSE +#endif + +#ifndef TFLITE_DCHECK_GE +#define TFLITE_DCHECK_GE(x, y) ((x) >= (y)) ? (void)0 : TFLITE_ASSERT_FALSE +#endif + +#ifndef TFLITE_DCHECK_GT +#define TFLITE_DCHECK_GT(x, y) ((x) > (y)) ? (void)0 : TFLITE_ASSERT_FALSE +#endif + +#ifndef TFLITE_DCHECK_LE +#define TFLITE_DCHECK_LE(x, y) ((x) <= (y)) ? (void)0 : TFLITE_ASSERT_FALSE +#endif + +#ifndef TFLITE_DCHECK_LT +#define TFLITE_DCHECK_LT(x, y) ((x) < (y)) ? (void)0 : TFLITE_ASSERT_FALSE +#endif + +// TODO(ahentz): Clean up: We should stick to the DCHECK versions. +#ifndef TFLITE_CHECK +#define TFLITE_CHECK(condition) (condition) ? (void)0 : TFLITE_ABORT +#endif + +#ifndef TFLITE_CHECK_EQ +#define TFLITE_CHECK_EQ(x, y) ((x) == (y)) ? (void)0 : TFLITE_ABORT +#endif + +#ifndef TFLITE_CHECK_NE +#define TFLITE_CHECK_NE(x, y) ((x) != (y)) ? (void)0 : TFLITE_ABORT +#endif + +#ifndef TFLITE_CHECK_GE +#define TFLITE_CHECK_GE(x, y) ((x) >= (y)) ? (void)0 : TFLITE_ABORT +#endif + +#ifndef TFLITE_CHECK_GT +#define TFLITE_CHECK_GT(x, y) ((x) > (y)) ? (void)0 : TFLITE_ABORT +#endif + +#ifndef TFLITE_CHECK_LE +#define TFLITE_CHECK_LE(x, y) ((x) <= (y)) ? (void)0 : TFLITE_ABORT +#endif + +#ifndef TFLITE_CHECK_LT +#define TFLITE_CHECK_LT(x, y) ((x) < (y)) ? (void)0 : TFLITE_ABORT +#endif + +#ifndef ARDUINO +// TODO(b/162019032): Consider removing these type-aliases. +using int8 = std::int8_t; +using uint8 = std::uint8_t; +using int16 = std::int16_t; +using uint16 = std::uint16_t; +using int32 = std::int32_t; +using uint32 = std::uint32_t; +#endif // !defined(ARDUINO) + +// Allow for cross-compiler usage of function signatures - currently used for +// specifying named RUY profiler regions in templated methods. +#if defined(_MSC_VER) +#define TFLITE_PRETTY_FUNCTION __FUNCSIG__ +#elif defined(__GNUC__) +#define TFLITE_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#else +#define TFLITE_PRETTY_FUNCTION __func__ +#endif + +// TFLITE_DEPRECATED() +// +// Duplicated from absl/base/macros.h to avoid pulling in that library. +// Marks a deprecated class, struct, enum, function, method and variable +// declarations. The macro argument is used as a custom diagnostic message (e.g. +// suggestion of a better alternative). +// +// Example: +// +// class TFLITE_DEPRECATED("Use Bar instead") Foo {...}; +// TFLITE_DEPRECATED("Use Baz instead") void Bar() {...} +// +// Every usage of a deprecated entity will trigger a warning when compiled with +// clang's `-Wdeprecated-declarations` option. This option is turned off by +// default, but the warnings will be reported by clang-tidy. +#if defined(__clang__) && __cplusplus >= 201103L +#define TFLITE_DEPRECATED(message) __attribute__((deprecated(message))) +#endif + +#ifndef TFLITE_DEPRECATED +#define TFLITE_DEPRECATED(message) +#endif + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_COMPATIBILITY_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/cppmath.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/cppmath.h new file mode 100644 index 000000000..5cd5b7df6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/cppmath.h @@ -0,0 +1,40 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_CPPMATH_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_CPPMATH_H_ + +#include + +namespace tflite { + +#if defined(ARDUINO) || \ + (defined(__ANDROID__) && !defined(__NDK_MAJOR__)) || defined(__ZEPHYR__) +#define TF_LITE_GLOBAL_STD_PREFIX +#else +#define TF_LITE_GLOBAL_STD_PREFIX std +#endif + +#define DECLARE_STD_GLOBAL_SWITCH1(tf_name, std_name) \ + template \ + inline T tf_name(const T x) { \ + return TF_LITE_GLOBAL_STD_PREFIX::std_name(x); \ + } + +DECLARE_STD_GLOBAL_SWITCH1(TfLiteRound, round); +DECLARE_STD_GLOBAL_SWITCH1(TfLiteExpm1, expm1); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_CPPMATH_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/max.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/max.h new file mode 100644 index 000000000..c18100272 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/max.h @@ -0,0 +1,35 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_MAX_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_MAX_H_ + +#include + +namespace tflite { + +#if defined(TF_LITE_USE_GLOBAL_MAX) || defined(__ZEPHYR__) +inline float TfLiteMax(const float& x, const float& y) { + return std::max(x, y); +} +#else +template +inline T TfLiteMax(const T& x, const T& y) { + return std::fmax(x, y); +} +#endif + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_MAX_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/min.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/min.h new file mode 100644 index 000000000..62035dccd --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/min.h @@ -0,0 +1,35 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_MIN_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_MIN_H_ + +#include + +namespace tflite { + +#if defined(TF_LITE_USE_GLOBAL_MIN) || defined(__ZEPHYR__) +inline float TfLiteMin(const float& x, const float& y) { + return std::min(x, y); +} +#else +template +inline T TfLiteMin(const T& x, const T& y) { + return std::fmin(x, y); +} +#endif + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_MIN_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/optimized/neon_check.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/optimized/neon_check.h new file mode 100644 index 000000000..7df1129d5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/optimized/neon_check.h @@ -0,0 +1,20 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_OPTIMIZED_NEON_CHECK_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_OPTIMIZED_NEON_CHECK_H_ + +// TFLM does not need to utilize any Neon optimizations. + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_OPTIMIZED_NEON_CHECK_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor.h new file mode 100644 index 000000000..4d71c9678 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor.h @@ -0,0 +1,122 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_PORTABLE_TENSOR_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_PORTABLE_TENSOR_H_ + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +inline RuntimeShape GetTensorShape(std::vector data) { + return RuntimeShape(data.size(), data.data()); +} + +// A list of tensors in a format that can be used by kernels like split and +// concatenation. +template +class VectorOfTensors { + public: + // Build with the tensors in 'tensor_list'. + VectorOfTensors(const TfLiteContext& context, + const TfLiteIntArray& tensor_list) { + int num_tensors = tensor_list.size; + + all_data_.reserve(num_tensors); + all_shape_.reserve(num_tensors); + all_shape_ptr_.reserve(num_tensors); + + for (int i = 0; i < num_tensors; ++i) { + TfLiteTensor* t = &context.tensors[tensor_list.data[i]]; + all_data_.push_back(GetTensorData(t)); + all_shape_.push_back(GetTensorShape(t)); + } + + // Taking the pointer from inside a std::vector is only OK if the vector is + // never modified, so we populate all_shape in the previous loop and then we + // are free to grab iterators here. + for (int i = 0; i < num_tensors; ++i) { + all_shape_ptr_.push_back(&all_shape_[i]); + } + } + // Return a pointer to the data pointers of all tensors in the list. For + // example: + // float* const* f = v.data(); + // f[0][1] is the second element of the first tensor. + T* const* data() const { return all_data_.data(); } + + // Return a pointer the shape pointers of all tensors in the list. For + // example: + // const RuntimeShape* const* d = v.dims(); + // dims[1] are the dimensions of the second tensor in the list. + const RuntimeShape* const* shapes() const { return all_shape_ptr_.data(); } + + private: + std::vector all_data_; + std::vector all_shape_; + std::vector all_shape_ptr_; +}; + +// A list of quantized tensors in a format that can be used by kernels like +// split and concatenation. +class VectorOfQuantizedTensors : public VectorOfTensors { + public: + // Build with the tensors in 'tensor_list'. + VectorOfQuantizedTensors(const TfLiteContext& context, + const TfLiteIntArray& tensor_list) + : VectorOfTensors(context, tensor_list) { + for (int i = 0; i < tensor_list.size; ++i) { + TfLiteTensor* t = &context.tensors[tensor_list.data[i]]; + zero_point_.push_back(t->params.zero_point); + scale_.push_back(t->params.scale); + } + } + + const float* scale() const { return scale_.data(); } + const int32_t* zero_point() const { return zero_point_.data(); } + + private: + std::vector zero_point_; + std::vector scale_; +}; + +// Writes randomly accessed values from `input` sequentially into `output`. +template +class SequentialTensorWriter { + public: + SequentialTensorWriter(const TfLiteTensor* input, TfLiteTensor* output) { + input_data_ = GetTensorData(input); + output_ptr_ = GetTensorData(output); + } + SequentialTensorWriter(const T* input_data, T* output_data) + : input_data_(input_data), output_ptr_(output_data) {} + + void Write(int position) { *output_ptr_++ = input_data_[position]; } + void WriteN(int position, int len) { + memcpy(output_ptr_, &input_data_[position], sizeof(T) * len); + output_ptr_ += len; + } + + private: + const T* input_data_; + T* output_ptr_; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_PORTABLE_TENSOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor_utils.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor_utils.cpp new file mode 100644 index 000000000..4904a6a3a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor_utils.cpp @@ -0,0 +1,86 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_TENSOR_UTILS_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_TENSOR_UTILS_H_ + +#include "tensorflow/lite/kernels/internal/portable_tensor_utils.h" + +#include +#include +#include + +#include "tensorflow/lite/c/builtin_op_data.h" + +#if defined(_MSC_VER) +#define __restrict__ __restrict +#endif + +namespace tflite { + +// Not all backends support CpuBackendContext usage, so forward declare to avoid +// pulling in its implementation. Use of CpuBackendContext in method +// implementations is purely optional. +class CpuBackendContext; + +namespace tensor_utils { + +// Apply Rectified Linear to elements of a vector. +void ApplyReluToVector(const float* __restrict__ vector, int v_size, + float* __restrict__ result) { + for (int v = 0; v < v_size; v++) { + result[v] = std::max(0.0f, vector[v]); + } +} + +// Apply Rectified Linear 1 (cap to [-1;1]) to elements of a vector +void ApplyRelu1ToVector(const float* __restrict__ vector, int v_size, + float* __restrict__ result) { + for (int v = 0; v < v_size; v++) { + result[v] = std::max(-1.0f, std::min(vector[v], 1.0f)); + } +} + +// Apply Rectified Linear 6 (cap to [0;6]) to elements of a vector +void ApplyRelu6ToVector(const float* __restrict__ vector, int v_size, + float* __restrict__ result) { + for (int v = 0; v < v_size; v++) { + result[v] = std::max(0.0f, std::min(vector[v], 6.0f)); + } +} + +// Apply signbit to elements of a vector +void ApplySignbitToVector(const float* __restrict__ vector, int v_size, + float* __restrict__ result) { + for (int v = 0; v < v_size; v++) { + result[v] = std::signbit(vector[v]); + } +} + +void UnpackDenseInt4IntoInt8(const int8_t* src_buffer, int num_elements, + int8_t* dst_buffer) { + for (int i = 0; i < num_elements; i += 2) { + // Shift left first so that sign is properly extended when shifted right + dst_buffer[i] = static_cast(src_buffer[i / 2] << 4) >> 4; + // Break early if the tensor has odd length and the higher nibble should be + // ignored. + if (i + 1 == num_elements) break; + dst_buffer[i + 1] = static_cast(src_buffer[i / 2]) >> 4; + } +} + +} // namespace tensor_utils +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_TENSOR_UTILS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor_utils.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor_utils.h new file mode 100644 index 000000000..266d0b4ff --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/portable_tensor_utils.h @@ -0,0 +1,623 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_PORTABLE_TENSOR_UTILS_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_PORTABLE_TENSOR_UTILS_H_ + +#include +#include +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +#if defined(_MSC_VER) +#define __restrict__ __restrict +#endif + +namespace tflite { + +// Not all backends support CpuBackendContext usage, so forward declare to avoid +// pulling in its implementation. Use of CpuBackendContext in method +// implementations is purely optional. +class CpuBackendContext; + +namespace tensor_utils { + +// Multiplies a matrix with a scalar and reduce the result on each row to a +// scalar. +// Parameters: +// - matrix: matrix of size n_row * n_col +// - scalar: the scalar that is multiplied to each element in the matrix +// - n_row: the row count of the matrix +// - n_col: the column count of the matrix +// - output: the 32bit output +// Note: We do not need saturation because the int8 * int8 is safe from overflow +// in (2^31-1) / (2^14) = 131072, which is bigger than the n_row. Non-zero +// initial output value is not exceptionally large. +void MatrixScalarMultiplyAccumulate(const int8_t* matrix, int32_t scalar, + int32_t n_row, int32_t n_col, + int32_t* output); + +// Add another vector for each batch in the batch vector. +template +void VectorBatchVectorAdd(const T* vector, int v_size, int n_batch, + T* batch_vector) { + for (int b = 0; b < n_batch; b++) { + for (int i = 0; i < v_size; ++i) { + batch_vector[i] += vector[i]; + } + batch_vector += v_size; + } +} + +// Cwise product of two vectors. +template +inline void VectorVectorCwiseProduct(const T* vector1, const T* vector2, + int v_size, T* result) { + for (int v = 0; v < v_size; v++) { + *result++ = *vector1++ * *vector2++; + } +} + +// Cwise product of a vector and a batch-vector. +template +inline void VectorBatchVectorCwiseProduct(const T* vector, int v_size, + const T* batch_vector, int n_batch, + T* result) { + for (int b = 0; b < n_batch; b++) { + VectorVectorCwiseProduct(vector, batch_vector, v_size, result); + // Update the pointers. + result += v_size; + batch_vector += v_size; + } +} + +// Cwise product and accumulate of two vectors. Since it's a MAC operation, the +// assumption here is that result array is initialized to valid values. +template +inline void VectorVectorCwiseProductAccumulate(const T* __restrict__ vector1, + const T* __restrict__ vector2, + int v_size, + T* __restrict__ result) { + for (int v = 0; v < v_size; v++) { + *result++ += *vector1++ * *vector2++; + } +} + +// Cwise product and accumulate of a vector and a batch-vector. Since it's a MAC +// operation, the assumption here is that result array is initialized to valid +// values. +template +inline void VectorBatchVectorCwiseProductAccumulate(const T* vector, int v_size, + const T* batch_vector, + int n_batch, T* result) { + for (int b = 0; b < n_batch; b++) { + VectorVectorCwiseProductAccumulate(vector, batch_vector, v_size, result); + // Update the pointers. + result += v_size; + batch_vector += v_size; + } +} + +// Batch vector initialization with another vector. +template +void VectorBatchVectorAssign(const T* vector, int v_size, int n_batch, + T* batch_vector) { + for (int b = 0; b < n_batch; b++) { + std::copy_n(vector, v_size, batch_vector + b * v_size); + } +} + +// Checks if all entries of vector are zero for float. +bool IsZeroVector(const float* vector, int v_size); + +// Checks if all entries of vector are zero for int8. +bool IsZeroVector(const int8_t* vector, int v_size); + +// Quantizes a buffer of floating point values using a symmetric quantization +// (i.e. linear quantization without an offset) to 8-bit signed integers. +// It also outputs the range (min, max) of the floating point buffer, and the +// scaling factor used to quantize the values. +void SymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float* min_value, + float* max_value, float* scaling_factor); + +// Quantizes a buffer of floating point values using a symmetric quantization +// (i.e. linear quantization without an offset) to 8-bit signed integers. +// It uses the range (min, max) provided to the function to calculate the +// appropriate scaling factor to quantize the values. +void SymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float min_value, + float max_value, float* scaling_factor); + +void AsymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float* scaling_factor, + int32_t* offset); + +// Helper function to quantize floats. +// float_data_ptr input float vectors +// n_batch number of input vectors +// n_data size of a single input vector +// quantized_data_ptr (out) vector with quantized data +// scaling_factors (out) scaling factors (one per vector) +// zero_points (out) zero points (one per vector) +// do_asymmetric controls if the quantization should be asymmetric. +inline void BatchQuantizeFloats(const float* float_data_ptr, int n_batch, + int n_data, int8_t* quantized_data_ptr, + float* scaling_factors, int32_t* zero_points, + bool do_asymmetric) { + for (int b = 0; b < n_batch; ++b) { + const int offset = b * n_data; + if (do_asymmetric) { + tensor_utils::AsymmetricQuantizeFloats( + float_data_ptr + offset, n_data, quantized_data_ptr + offset, + &scaling_factors[b], &zero_points[b]); + } else { + float unused_min, unused_max; + tensor_utils::SymmetricQuantizeFloats( + float_data_ptr + offset, n_data, quantized_data_ptr + offset, + &unused_min, &unused_max, &scaling_factors[b]); + } + } +} + +// Multiplies a matrix by a "batched" vector (i.e. a matrix with a batch +// dimension composed by input vectors independent from each other). The result +// of the multiplication is accumulated to the passed result buffer. +// More specifically, for a matrix M of shape [n, i] and a batched-vector +// of shape [i, batch] it will first compute the product of shape [n, batch]. +// This product will be accumulated to the result buffer. +void MatrixBatchVectorMultiplyAccumulate(const float* matrix, int m_rows, + int m_cols, const float* vector, + int n_batch, float* result); + +// Same as the function above, but the matrix is a sparse tensor with block +// pattern 1x4. +// This function assumes that m_cols is a multiple of the block size (4 in this +// case) so that there's no incomplete block. +void SparseMatrixBatchVectorMultiplyAccumulate1x4( + const float* __restrict__ matrix, const int32_t* __restrict__ segments, + const int32_t* __restrict__ indices, int m_rows, int m_cols, + const float* __restrict__ vector, int n_batch, float* __restrict__ result); + +// Same as the function above, but the matrix is stored in block compressed +// sparse row format with block pattern 1x16 which consists of two arrays: +// 1. A matrix array stores non-zero blocks of the matrix in row major. +// 2. A ledger array stores nrows groups, one group per row. Each group starts +// with an integer representing the number of non-zero blocks for the +// corresponding row and follows with column indexes of the first element +// of each non-zero block. +// This function assumes that +// 1. m_cols is a multiple of 16 so that all blocks are full blocks. +// 2. m_cols < 254 * 16 so that block index can be represented by uint8. +void SparseMatrixBatchVectorMultiplyAccumulate( + const float* __restrict__ matrix, const uint8_t* __restrict__ ledger, + int m_rows, int m_cols, const float* __restrict__ vector, int n_batch, + float* __restrict__ result); + +// Same as the function above, but for values quantized using symmetric +// quantization (e.g. by calling SymmetricQuantizeFloats). +// The passed scaling factors is a buffer of the quantization scaling factors +// that will be used to dequentize the products into the final result buffer. +// These scaling factors are the multiplication of the matrix scaling factor +// by the vector's scaling factor, one per batch (i.e. this allows quantizing +// each batch in the batch-vector matrix independently). +void MatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, + const float* __restrict__ scaling_factors, int n_batch, + float* __restrict__ result); + +// Same as the function above except that vector values +// are quantized with asymmetric quantization per-batch and the matrix +// is quantized per row. +void MatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, + const float* __restrict__ scaling_factors, int n_batch, + float* __restrict__ result, const float* __restrict__ per_channel_scale, + const int32_t* __restrict__ input_offset); + +// Same as the function above, but the matrix is a sparse tensor with block +// pattern 1x16. +// This function assumes that m_cols is a multiple of the block size (16 in this +// case) so that there's no incomplete block. Also, it assumes all offsets of +// input, output and filter are zero. +void SparseMatrixBatchVectorMultiplyAccumulate1x16( + const int8_t* __restrict__ matrix, const int32_t* __restrict__ segments, + const int32_t* __restrict__ indices, int m_rows, int m_cols, + const int8_t* __restrict__ vector, const int32_t* __restrict__ bias_vector, + int n_batch, const int32_t input_offset, const int32_t output_multiplier, + const int32_t output_shift, const int32_t output_offset, + const int32_t output_activation_min, const int32_t output_activation_max, + int8_t* __restrict__ result); + +// Same as the function above, but the matrix is stored in block compressed +// sparse row format with block pattern 1x16 which consists of two arrays: +// 1. A matrix array stores non-zero blocks of the matrix in row major. +// 2. A ledger array stores nrows groups, one group per row. Each group starts +// with an integer representing the number of non-zero blocks for the +// corresponding row followed by column index of the first element of +// each non-zero block. +// This function assumes that +// 1. m_cols is a multiple of 16 so that all blocks are full blocks. +// 2. m_cols < 254 * 16 so that block index can be represented by uint8. +void SparseMatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const uint8_t* __restrict__ ledger, + const int m_rows, const int m_cols, const int8_t* __restrict__ vectors, + const float* __restrict__ scaling_factors, int n_batch, + float* __restrict__ result); + +// Same as the above 8, 8, 8 integer matmul except for the presence of zero +// point and non-accumulative. +// TODO(b/148688698): remove this function by folding zero point calculation in +// prepare() function. +void MatrixBatchVectorMultiply(const int8_t* input, int32_t input_zeropoint, + const int8_t* input_to_gate_weights, + int32_t input_to_gate_effective_scale_a, + int32_t input_to_gate_effective_scale_b, + int32_t n_batch, int32_t n_input, int32_t n_cell, + int8_t* gate_output, int8_t gate_output_zp); + +// Same as above but has 16 bit and 8 bit input and 8 bit output. +// Used in projection when hidden is 16bit. +void MatrixBatchVectorMultiply(const int16_t* hidden, + const int8_t* hidden_to_output_weights, + int32_t proj_effective_scale_a, + int32_t proj_effective_scale_b, + const int32_t* gate_bias, int32_t n_batch, + int32_t n_hidden, int32_t n_output, + int32_t output_zp, int8_t* proj_output); + +// Apply Layer Normalization (https://arxiv.org/abs/1607.06450) to a Quantized +// vector. +// Parameters: +// - input: batch vector of size n_batch * n_input; 16 bit. +// - layer_norm_weights: the quantized layer normalization weights. +// - bias: the bias for the layer normalization. +// - layer_norm_scale_a: multiplier for scale factor. +// - layer_norm_scale_b: shift for scale factor. +// - variance_limit: the guard to make sure the inverse does not overflow. +// - n_batch: the number of batches. +// - n_input: the size for input and output. +// - output: the 16 bit output +void ApplyLayerNorm(const int16_t* input, const int16_t* layer_norm_weights, + const int32_t* bias, int32_t layer_norm_scale_a, + int32_t layer_norm_scale_b, int32_t variance_limit, + int n_batch, int n_input, int16_t* output); + +// Same as above but the internal calculation is done in float. +void ApplyLayerNormFloat(const int16_t* input, + const int16_t* layer_norm_weights, + int32_t layer_norm_scale_a, int32_t layer_norm_scale_b, + const int32_t* bias, int n_batch, int n_input, + int16_t* output); + +// Apply Sigmoid to a quantized vector. +// Parameters: +// - input: batch vector of size n_batch * n_input; 16 bit. +// - n_batch: the number of batches. +// - n_input: the size for input and output. +// - output: the 16 bit output +// The input is in Q3.12 format and the output is in Q0.15 format. +void ApplySigmoid(const int16_t* input, int32_t n_batch, int32_t n_input, + int16_t* output); + +// Same as above but the internal calcualtion is float. +void ApplySigmoidFloat(const int16_t* input, int32_t n_batch, int32_t n_input, + int16_t* output); + +// Apply Tanh to a quantized vector. +// Parameters: +// - integer_bits: the integer bits of the input. +// Currently supports 0, 1, 2, 3, 4, 5, 6. +// - input: batch vector of size n_batch * n_input; 16 bit. +// - n_batch: the number of batches. +// - n_input: the size for input and output. +// - output: the 16 bit output +// The input is in Qm.15-m format and the output is in Q0.15 format. +void ApplyTanh(int32_t intger_bits, const int16_t* input, int32_t n_batch, + int32_t n_input, int16_t* output); + +// Apply Tanh to a quantized vector. Tbe internal calculation is in float. +// - Input has 2^(integer_bits) as scale. +// - Output has Q0.15 as scale. +void ApplyTanhFloat(const int16_t* input, int32_t n_batch, int32_t n_input, + int32_t integer_bits, int16_t* output); + +// Element-wise multiplication of two quantized vectors. +// Parameters: +// - input_1: batch vector of size n_batch * n_input; 16 bit. +// - input_2: batch vector of size n_batch * n_input; 16 bit. +// - n_batch: the number of batches. +// - n_input: the size for input and output. +// - shift: the shift needed to produce the output. +// - output: the 16 bit output of size n_batch * n_input. +// Output does not need to be initialized. +void CwiseMul(const int16_t* input_1, const int16_t* input_2, int n_batch, + int n_input, int shift, int16_t* output); + +// Element-wise multiplication of two quantized vectors. +// Parameters: +// - input_1: batch vector of size n_batch * n_input; 16 bit. +// - input_2: batch vector of size n_batch * n_input; 16 bit. +// - n_batch: the number of batches. +// - n_input: the size for input and output. +// - shift: the shift needed to produce the output. +// - output: the 8 bit output of size n_batch * n_input. +// Output does not need to be initialized. +void CwiseMul(const int16_t* input_1, const int16_t* input_2, int n_batch, + int n_input, int shift, int8_t* output); + +// Element-wise multiplication of two quantized vectors with rescaling. +// Parameters: +// - input_1: batch vector of size n_batch * n_input; 16 bit. +// - input_2: batch vector of size n_batch * n_input; 16 bit. +// - multiplier: the multiplier part of scale. +// - shift: the shift part of scale. +// - n_batch: the number of batches. +// - n_input: the size for input and output. +// - output: the 8 bit output of size n_batch * n_input. +// - output_zp: the zero point of output. +// Output does not need to be initialized. +// Multiplier ("m") and shift ("s") are connected to scale ("s") with s = m * +// 2^(s - 31). +void CwiseMul(const int16_t* input_1, const int16_t* input_2, + int32_t multiplier, int32_t shift, int32_t n_batch, + int32_t n_input, int32_t output_zp, int8_t* output); + +// Element-wise saturating addition of two quantized vectors without rescaling. +// Parameters: +// - input_1: batch vector of size n_batch * n_input; 16 bit. +// - input_2: batch vector of size n_batch * n_input; 16 bit. +// - n_batch: the number of batches. +// - n_input: the size for input and output. +// - output: the 8 bit output of size n_batch * n_input. +// Output does not need to be initialized. +void CwiseAdd(const int16_t* input_1, const int16_t* input_2, int n_batch, + int n_input, int16_t* output); + +// Element-wise in-place clipping of a vector. Overloaded for float, int16_t, +// int8_t. Parameters: +// - vector: vector of size v_size. +// - v_size: the size of the vector. +// - clipping_value: the value used for clipping. +void CwiseClipping(float* vector, const int v_size, const float clipping_value); +void CwiseClipping(int16_t* vector, const int v_size, + const int16_t clipping_value); +void CwiseClipping(int8_t* vector, const int v_size, + const int8_t clipping_value); + +// Dot product of two vectors. +float VectorVectorDotProduct(const float* vector1, const float* vector2, + int v_size); + +// Dot product of two batch vectors of size n_batch * v_size: +// vector1 = [x_1_1, x_1_2, ..., x_1_vsize, +// x_2_1, x_2_2, ..., x_2_vsize, +// ... +// x_nbatch_1,..., x_nbatch_vsize] +// vector2 = [y_1_1, y_1_2, ..., y_1_vsize, +// y_2_1, y_2_2, ..., y_2_vsize, +// ... +// y_nbatch_1,..., y_nbatch_vsize] +// Then result will be a vector of n_batch size starting from 'result': +// [x_1_1 * y_1_1 + x_1_2 * y_1_2 + ... + x_1_vsize * y_1_vsize, +// x_2_1 * y_2_1 + x_2_2 * y_2_2 + ... + x_2_vsize * y_2_vsize, +// ... +// x_nbatch_1 * y_nbatch_1 + ... + x_nbatch_vsize * y_nbatch_vsize] +template +inline void BatchVectorBatchVectorDotProduct(const T* vector1, const T* vector2, + int v_size, int n_batch, + T* result) { + for (int b = 0; b < n_batch; b++) { + result[b] = VectorVectorDotProduct(vector1, vector2, v_size); + vector1 += v_size; + vector2 += v_size; + } +} + +// Same as above but input is 16bit and output is 32bit. +void BatchVectorBatchVectorDotProduct(const int16_t* vector1, + const int16_t* vector2, int v_size, + int n_batch, int32_t* result); + +// Same as above, but inputs are 16bit integer and output is 16bit integer. +void VectorBatchVectorCwiseProductAccumulate(const int16_t* vector, int v_size, + const int16_t* batch_vector, + int n_batch, int32_t multiplier, + int shift, int16_t* result); + +// Compute "1.0f - elements of vector" (used in CIFG). +void Sub1Vector(const float* vector, int v_size, float* result); + +// Compute "1.0f - elements of vector" (used in CIFG) for int16 input. +// "vector" has range [0, 32767] because it is the output of sigmoid function. +void Sub1Vector(const int16_t* vector, int v_size, int16_t* result); + +// Reduce-sum on a float input vector: +// input_vector: float pointer to input vector. +// output_vector: float pointer to vector. +// output_size: output vector size. +// reduction_size: number of consecutive elements from input vector which are +// added to get one element of output. +void ReductionSumVector(const float* input_vector, float* output_vector, + int output_size, int reduction_size); + +// Same as above but input/output is 32 bit integer. +void ReductionSumVector(const int32_t* input_vector, int32_t* output_vector, + int output_size, int reduction_size); + +// Same as above but input is 8 bit integer. +void ReductionSumVector(const int8_t* input_vector, int32_t* output_vector, + int output_size, int reduction_size); + +// Multiply all elements of vector with a scalar. +void VectorScalarMultiply(const int8_t* vector, int v_size, float scale, + float* result); + +// Layer norm for each batch. +void MeanStddevNormalization(const float* input_vector, float* output_vector, + int v_size, int n_batch); + +// Saturate Add with rescale on both inputs. +void TwoGateSaturatingAdd(const int8_t* input, int8_t input_zp, + const int8_t* recurrent, int8_t recurrent_zp, + int32_t input_effective_scale_a, + int32_t input_effective_scale_b, + int32_t recurrent_effective_scale_a, + int32_t recurrent_effective_scale_b, int32_t n_batch, + int32_t n_cell, int16_t* output); + +// Same as the function above, but provide a scratch buffer for the +// int8 x int8 -> int32 and a CpuBackendContext for the accumulator +// computation. +void MatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, + const float* __restrict__ scaling_factors, int n_batch, + int32_t* __restrict__ scratch, float* __restrict__ result, + CpuBackendContext* __restrict__ context); + +// Same as the function above except that can make use of cached row sums. +void MatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, const float* scaling_factors, + int n_batch, float* __restrict__ result, const float* per_channel_scale, + const int32_t* input_offset, int32_t* scratch, int32_t* row_sums, + bool* compute_row_sums, CpuBackendContext* context); + +// Same as the function above, but provides separate scaling factor for the +// matrix and the vectors. The scaling factors are multiplied in the +// scaling_factor_scratch buffer. +inline void MatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, const float matrix_scaling_factor, + const float* vector_scaling_factors, int n_batch, + float* __restrict__ result, const float* per_channel_scale, + const int32_t* input_offset, int32_t* scratch, int32_t* row_sums, + bool* compute_row_sums, float* scaling_factor_scratch, + CpuBackendContext* context) { + for (int b = 0; b < n_batch; ++b) { + scaling_factor_scratch[b] = + vector_scaling_factors[b] * matrix_scaling_factor; + } + MatrixBatchVectorMultiplyAccumulate(matrix, m_rows, m_cols, vectors, + scaling_factor_scratch, n_batch, result, + per_channel_scale, input_offset, scratch, + row_sums, compute_row_sums, context); +} + +// Multiplies a matrix by a "batched" vector (i.e. a matrix with a batch +// dimension composed by input vectors independent from each other). The result +// of the multiplication is accumulated to the passed result buffer. +// More specifically, for a matrix M of shape [n, i] and a batched-vector +// of shape [i, batch] it will first compute the product of shape [n, batch]. +// This product will be accumulated to the result buffer, +// Parameters: +// - input: batch vector of size n_batch * n_input +// - bias: vector of size b_input +// - input_to_gate_weights: matrix of size n_input * n_output +// - multiplier: scalar +// - shift: scalar +// - n_batch: the batch size +// - n_input: the input size +// - n_output: the output size +// - output_zp: the zero point of the output. +// - scratch: batch vector of size n_batch * n_output +// - output: the 16 bit output +// Notes: +// - this is used for gate matmul: for non-cifg it is for input, forget, +// cell, output gates; for cifg, it is for forget, cell, output gates. +// - multiplier and shift combined gives the scale. +// - assumes input zero point is 0. +// - scratch is created for optimization purpose only. +// TODO(b/152066492): this can be removed if some future optimization +// work makes it unnecessary. +void MatrixBatchVectorMultiplyAccumulate( + const int8_t* input, const int32_t* bias, + const int8_t* input_to_gate_weights, int32_t multiplier, int32_t shift, + int32_t n_batch, int32_t n_input, int32_t n_output, int32_t output_zp, + int32_t* scratch, int16_t* output, CpuBackendContext* context); + +// Multiplies a matrix by a "batched" vector (i.e. a matrix with a batch +// dimension composed by input vectors independent from each other). The result +// of the multiplication is accumulated to the passed result buffer. +// More specifically, for a matrix M of shape [n, i] and a batched-vector +// of shape [i, batch] it will first compute the product of shape [n, batch]. +// This product will be accumulated to the result buffer, +// Parameters: +// - input: batch vector of size n_batch * n_input +// - bias: vector of size b_input +// - input_to_gate_weights: matrix of size n_input * n_output +// - multiplier: scalar +// - shift: scalar +// - n_batch: the batch size +// - n_input: the input size +// - n_output: the output size +// - output_zp: the zero point of the output. +// - scratch: batch vector of size n_batch * n_output +// - output: the 8 bit output +// Notes: +// - this is used for projection matmul. +// - multiplier and shift combined gives the scale. +// - assumes input zero point is 0. +// - scratch is created for optimization purpose only. +// TODO(b/152066492): this can be removed if some future optimization +// work makes it unnecessary. +void MatrixBatchVectorMultiplyAccumulate( + const int8_t* input, const int32_t* bias, + const int8_t* input_to_gate_weights, int32_t multiplier, int32_t shift, + int32_t n_batch, int32_t n_input, int32_t n_output, int32_t output_zp, + int32_t* scratch, int8_t* output, CpuBackendContext* context); + +// Apply Rectified Linear to elements of a vector. +void ApplyReluToVector(const float* __restrict__ vector, int v_size, + float* __restrict__ result); + +// Apply Rectified Linear 1 (cap to [-1;1]) to elements of a vector +void ApplyRelu1ToVector(const float* __restrict__ vector, int v_size, + float* __restrict__ result); + +// Apply Rectified Linear 6 (cap to [0;6]) to elements of a vector +void ApplyRelu6ToVector(const float* __restrict__ vector, int v_size, + float* __restrict__ result); + +// Apply signbit to elements of a vector +void ApplySignbitToVector(const float* __restrict__ vector, int v_size, + float* __restrict__ result); + +// Unpack or inflate `src_buffer` by taking each element and splitting it as +// two elements into `dst_buffer`. +// Parameters: +// src_buffer : Densely packed buffer containing int4 values +// num_elements : Number of elements stored in the buffer. Note that this can +// be smaller than the size of `src_buffer` by 1 if it's odd, +// in which case the last nibble in `src_buffer` is ignored. +// This should be equal to the size of `dst_buffer`. +// dst_buffer : Buffer to unpack into. Should be allocated by the caller. +// Size should be at least `num_elements`. +// Notes: +// For example, given `src_buffer = {0x12, 0x34};`, calling this function +// will return `dst_buffer = {0x02, 0x01, 0x04, 0x03}`. +void UnpackDenseInt4IntoInt8(const int8_t* src_buffer, int num_elements, + int8_t* dst_buffer); + +} // namespace tensor_utils + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_PORTABLE_TENSOR_UTILS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/quantization_util.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/quantization_util.cpp new file mode 100644 index 000000000..62045d67a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/quantization_util.cpp @@ -0,0 +1,416 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/quantization_util.h" + +#include +#include +#include + +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" + +namespace tflite { + +namespace { +// These constants are used to manipulate the binary representation of doubles. +// Double-precision binary64 floating point format is: +// Bit | 63 | 62-52 | 51-0 | +// | Sign | Exponent | Fraction | +// To avoid 64-bit integers as much as possible, I break this into high and +// low 32-bit chunks. High is: +// Bit | 31 | 30-20 | 19-0 | +// | Sign | Exponent | High Fraction | +// Low is: +// Bit | 31-0 | +// | Low Fraction | +// We then access the components through logical bit-wise operations to +// extract the parts needed, with the positions and masks derived from the +// layout shown above. +constexpr uint64_t kSignMask = 0x8000000000000000LL; +constexpr uint64_t kExponentMask = 0x7ff0000000000000LL; +constexpr int32_t kExponentShift = 52; +constexpr int32_t kExponentBias = 1023; +constexpr uint32_t kExponentIsBadNum = 0x7ff; +constexpr uint64_t kFractionMask = 0x000fffffffc00000LL; +constexpr uint32_t kFractionShift = 22; +constexpr uint32_t kFractionRoundingMask = 0x003fffff; +constexpr uint32_t kFractionRoundingThreshold = 0x00200000; +} // namespace + +void QuantizeMultiplier(double double_multiplier, int32_t* quantized_multiplier, + int* shift) { +#if TFLITE_SINGLE_ROUNDING + // Single-rounding MultiplyByQuantizedMultiplier only supports positive + // multipliers. + // TFLITE_DCHECK(double_multiplier >= 0); +#endif + if (double_multiplier == 0.) { + *quantized_multiplier = 0; + *shift = 0; + return; + } +#ifdef TFLITE_EMULATE_FLOAT + // If we're trying to avoid the use of floating-point instructions (for + // example on microcontrollers) then use an alternative implementation + // that only requires integer and bitwise operations. To enable this, you + // need to set the define during the build process for your platform. + int64_t q_fixed = IntegerFrExp(double_multiplier, shift); +#else // TFLITE_EMULATE_FLOAT + const double q = std::frexp(double_multiplier, shift); + auto q_fixed = static_cast(TfLiteRound(q * (1LL << 31))); +#endif // TFLITE_EMULATE_FLOAT + TFLITE_CHECK(q_fixed <= (1LL << 31)); + if (q_fixed == (1LL << 31)) { + q_fixed /= 2; + ++*shift; + } + TFLITE_CHECK_LE(q_fixed, std::numeric_limits::max()); + // A shift amount smaller than -31 would cause all bits to be shifted out + // and thus all results would be zero. We implement that instead with + // q_fixed==0, so as to avoid hitting issues with right-shift + // operations with shift amounts greater than 31. Note that this happens + // roughly when abs(double_multiplier) < 2^-31 and the present handling means + // that we're effectively flushing tiny double_multiplier's to zero. + // We could conceivably handle values in the range (roughly) [32, 63] + // as 'denormals' i.e. (shift==0, q_fixed < 2^30). In that point of view + // the present handling is just doing 'flush denormals to zero'. We could + // reconsider and actually generate nonzero denormals if a need arises. + if (*shift < -31) { + *shift = 0; + q_fixed = 0; + } +#if TFLITE_SINGLE_ROUNDING + // Single-rounding MultiplyByQuantizedMultiplier doesn't support a shift > 30, + // saturate it. + if (*shift > 30) { + *shift = 30; + q_fixed = (1LL << 31) - 1; + } +#endif + *quantized_multiplier = static_cast(q_fixed); +} + +void QuantizeMultiplierGreaterThanOne(double double_multiplier, + int32_t* quantized_multiplier, + int* left_shift) { + TFLITE_CHECK_GT(double_multiplier, 1.); + QuantizeMultiplier(double_multiplier, quantized_multiplier, left_shift); + TFLITE_CHECK_GE(*left_shift, 0); +} + +void QuantizeMultiplierSmallerThanOneExp(double double_multiplier, + int32_t* quantized_multiplier, + int* left_shift) { + TFLITE_CHECK_LT(double_multiplier, 1.); + TFLITE_CHECK_GT(double_multiplier, 0.); + int shift; + QuantizeMultiplier(double_multiplier, quantized_multiplier, &shift); + TFLITE_CHECK_LE(shift, 0); + *left_shift = shift; +} + +int64_t IntegerFrExp(double input, int* shift) { + // Make sure our assumptions about the double layout hold. + TFLITE_CHECK_EQ(8, sizeof(double)); + + // We want to access the bits of the input double value directly, which is + // tricky to do safely, so use a union to handle the casting. + union { + double double_value; + uint64_t double_as_uint; + } cast_union; + cast_union.double_value = input; + const uint64_t u = cast_union.double_as_uint; + + // If the bitfield is all zeros apart from the sign bit, this is a normalized + // zero value, so return standard values for this special case. + if ((u & ~kSignMask) == 0) { + *shift = 0; + return 0; + } + + // Deal with NaNs and Infs, which are always indicated with a fixed pattern in + // the exponent, and distinguished by whether the fractions are zero or + // non-zero. + const uint32_t exponent_part = ((u & kExponentMask) >> kExponentShift); + if (exponent_part == kExponentIsBadNum) { + *shift = std::numeric_limits::max(); + if (u & kFractionMask) { + // NaN, so just return zero (with the exponent set to INT_MAX). + return 0; + } else { + // Infinity, so return +/- INT_MAX. + if (u & kSignMask) { + return std::numeric_limits::min(); + } else { + return std::numeric_limits::max(); + } + } + } + + // The shift is fairly easy to extract from the high bits of the double value, + // just by masking it out and applying a bias. The std::frexp() implementation + // always returns values between 0.5 and 1.0 though, whereas the exponent + // assumes 1.0 to 2.0 is the standard range, so I add on one to match that + // interface. + *shift = (exponent_part - kExponentBias) + 1; + + // There's an implicit high bit in the double format definition, so make sure + // we include that at the top, and then reconstruct the rest of the fractional + // value from the remaining fragments. + int64_t fraction = 0x40000000 + ((u & kFractionMask) >> kFractionShift); + + // We're cutting off some bits at the bottom, so to exactly match the standard + // frexp implementation here we'll apply rounding by adding one to the least + // significant bit of the result if the discarded portion is over half of the + // maximum. + if ((u & kFractionRoundingMask) > kFractionRoundingThreshold) { + fraction += 1; + } + // Negate the fraction if the sign bit was set. + if (u & kSignMask) { + fraction *= -1; + } + + return fraction; +} + +double DoubleFromFractionAndShift(int64_t fraction, int shift) { + union { + double double_value; + uint64_t double_as_uint; + } result; + + // Detect NaNs and infinities. + if (shift == std::numeric_limits::max()) { + if (fraction == 0) { + return std::numeric_limits::quiet_NaN(); + } else if (fraction > 0) { + return std::numeric_limits::infinity(); + } else { + return -std::numeric_limits::infinity(); + } + } + + // Return a normalized zero for a zero fraction. + if (fraction == 0) { + result.double_as_uint = 0; + return result.double_value; + } + + bool is_negative = (fraction < 0); + int64_t encoded_fraction = is_negative ? -fraction : fraction; + int64_t encoded_shift = (shift - 1); + while (encoded_fraction < 0x40000000) { + encoded_fraction *= 2; + encoded_shift -= 1; + } + while (encoded_fraction > 0x80000000) { + encoded_fraction /= 2; + encoded_shift += 1; + } + encoded_fraction -= 0x40000000; + if (encoded_shift < -1022) { + encoded_shift = -1023; + } else if (encoded_shift > 1022) { + encoded_shift = 1023; + } + encoded_shift += kExponentBias; + uint64_t encoded_sign = is_negative ? kSignMask : 0; + result.double_as_uint = encoded_sign | (encoded_shift << kExponentShift) | + (encoded_fraction << kFractionShift); + return result.double_value; +} + +double IntegerDoubleMultiply(double a, double b) { + int a_shift; + const int64_t a_fraction = IntegerFrExp(a, &a_shift); + int b_shift; + const int64_t b_fraction = IntegerFrExp(b, &b_shift); + // Detect NaNs and infinities. + if (a_shift == std::numeric_limits::max() || + (b_shift == std::numeric_limits::max())) { + return std::numeric_limits::quiet_NaN(); + } + const int result_shift = a_shift + b_shift + 1; + const int64_t result_fraction = (a_fraction * b_fraction) >> 32; + return DoubleFromFractionAndShift(result_fraction, result_shift); +} + +int IntegerDoubleCompare(double a, double b) { + int a_shift; + const int64_t a_fraction = IntegerFrExp(a, &a_shift); + int b_shift; + const int64_t b_fraction = IntegerFrExp(b, &b_shift); + + // Detect NaNs and infinities. + if (a_shift == std::numeric_limits::max() || + (b_shift == std::numeric_limits::max())) { + return 1; + } + + if ((a_fraction == 0) && (b_fraction < 0)) { + return 1; + } else if ((a_fraction < 0) && (b_fraction == 0)) { + return -1; + } else if (a_shift < b_shift) { + return -1; + } else if (a_shift > b_shift) { + return 1; + } else if (a_fraction < b_fraction) { + return -1; + } else if (a_fraction > b_fraction) { + return 1; + } else { + return 0; + } +} + +void PreprocessSoftmaxScaling(double beta, double input_scale, + int input_integer_bits, + int32_t* quantized_multiplier, int* left_shift) { + // If the overall multiplier (input and beta) is large, then exp() of an + // input difference of 1 scaled by this will be large. In other words, we + // can cap the multiplier and know that, when it is used, the output will be + // (round to) zero wherever the input is not at the maximum value. + + // If the overall scale is less than one, and input_integer_bits=0, then the + // result is double equivalent of Q0.31 (actually with more precision). Thus + // this generates a Q(input_integer_bits).(31-input_integer_bits) + // representation. +#if TFLITE_SINGLE_ROUNDING + const double max_real_multiplier = (1LL << 30) - 1.0; +#else + const double max_real_multiplier = (1LL << 31) - 1.0; +#endif + +#ifdef TFLITE_EMULATE_FLOAT + const double input_beta = IntegerDoubleMultiply(beta, input_scale); + int shift; + int64_t fraction = IntegerFrExp(input_beta, &shift); + shift += (31 - input_integer_bits); + double input_beta_real_multiplier = + DoubleFromFractionAndShift(fraction, shift); + if (IntegerDoubleCompare(input_beta_real_multiplier, max_real_multiplier) > + 0) { + input_beta_real_multiplier = max_real_multiplier; + } +#else // TFLITE_EMULATE_FLOAT + const double input_beta_real_multiplier = + std::min(beta * input_scale * (1 << (31 - input_integer_bits)), + max_real_multiplier); +#endif // TFLITE_EMULATE_FLOAT + + QuantizeMultiplierGreaterThanOne(input_beta_real_multiplier, + quantized_multiplier, left_shift); +} + +void PreprocessLogSoftmaxScalingExp(double beta, double input_scale, + int input_integer_bits, + int32_t* quantized_multiplier, + int* left_shift, + int32_t* reverse_scaling_divisor, + int* reverse_scaling_left_shift) { + PreprocessSoftmaxScaling(beta, input_scale, input_integer_bits, + quantized_multiplier, left_shift); + + // Also calculate what amounts to the inverse scaling factor for the input. + const double real_reverse_scaling_divisor = + (1 << (31 - *left_shift)) / static_cast(*quantized_multiplier); + tflite::QuantizeMultiplierSmallerThanOneExp(real_reverse_scaling_divisor, + reverse_scaling_divisor, + reverse_scaling_left_shift); +} + +int CalculateInputRadius(int input_integer_bits, int input_left_shift, + int total_signed_bits) { +#ifdef TFLITE_EMULATE_FLOAT + int64_t result = (1 << input_integer_bits) - 1; + result <<= (total_signed_bits - input_integer_bits); + result >>= input_left_shift; + return result; +#else // TFLITE_EMULATE_FLOAT + const double max_input_rescaled = + 1.0 * ((1 << input_integer_bits) - 1) * + (1LL << (total_signed_bits - input_integer_bits)) / + (1LL << input_left_shift); + // Tighten bound using floor. Suppose that we could use the exact value. + // After scaling the difference, the result would be at the maximum. Thus we + // must ensure that our value has lower magnitude. + return static_cast(std::floor(max_input_rescaled)); +#endif // TFLITE_EMULATE_FLOAT +} + +void NudgeQuantizationRange(const float min, const float max, + const int quant_min, const int quant_max, + float* nudged_min, float* nudged_max, + float* nudged_scale) { + // This code originates from tensorflow/core/kernels/fake_quant_ops_functor.h. + const float quant_min_float = static_cast(quant_min); + const float quant_max_float = static_cast(quant_max); + *nudged_scale = (max - min) / (quant_max_float - quant_min_float); + const float zero_point_from_min = quant_min_float - min / *nudged_scale; + uint16_t nudged_zero_point; + if (zero_point_from_min < quant_min_float) { + nudged_zero_point = static_cast(quant_min); + } else if (zero_point_from_min > quant_max_float) { + nudged_zero_point = static_cast(quant_max); + } else { + nudged_zero_point = static_cast(TfLiteRound(zero_point_from_min)); + } + *nudged_min = (quant_min_float - nudged_zero_point) * (*nudged_scale); + *nudged_max = (quant_max_float - nudged_zero_point) * (*nudged_scale); +} + +void FakeQuantizeArray(const float nudged_scale, const float nudged_min, + const float nudged_max, const float* input_data, + float* output_data, const float size) { + // This code originates from tensorflow/core/kernels/fake_quant_ops_functor.h. + const float inv_nudged_scale = 1.0f / nudged_scale; + + for (int i = 0; i < size; i++) { + const float src_val = input_data[i]; + const float clamped = std::min(nudged_max, std::max(nudged_min, src_val)); + const float clamped_shifted = clamped - nudged_min; + const float dst_val = + TfLiteRound(clamped_shifted * inv_nudged_scale) * nudged_scale + + nudged_min; + output_data[i] = dst_val; + } +} + +bool CheckedLog2(const float x, int* log2_result) { + // Using TfLiteRound instead of std::round and std::log instead of + // std::log2 to work around these functions being missing in a toolchain + // used in some TensorFlow tests as of May 2018. + const float x_log2 = std::log(x) * (1.0f / std::log(2.0f)); + const float x_log2_rounded = TfLiteRound(x_log2); + const float x_log2_fracpart = x_log2 - x_log2_rounded; + + *log2_result = static_cast(x_log2_rounded); + return std::abs(x_log2_fracpart) < 1e-3f; +} + +void QuantizeMultiplierArray(const double* effective_scales, size_t size, + int32_t* effective_scale_significand, + int* effective_shift) { + for (size_t i = 0; i < size; ++i) { + QuantizeMultiplier(effective_scales[i], &effective_scale_significand[i], + &effective_shift[i]); + } +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/quantization_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/quantization_util.h new file mode 100644 index 000000000..0ee914b06 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/quantization_util.h @@ -0,0 +1,292 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_QUANTIZATION_UTIL_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_QUANTIZATION_UTIL_H_ + +#include +#include +#include + +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +// Given the min and max values of a float array, return +// reasonable quantization parameters to use for this array. +template +QuantizationParams ChooseQuantizationParams(double rmin, double rmax, + bool narrow_range) { + const T qmin = std::numeric_limits::min() + (narrow_range ? 1 : 0); + const T qmax = std::numeric_limits::max(); + const double qmin_double = qmin; + const double qmax_double = qmax; + // 0 should always be a representable value. Let's assume that the initial + // min,max range contains 0. + TFLITE_CHECK_LE(rmin, 0.); + TFLITE_CHECK_GE(rmax, 0.); + if (rmin == rmax) { + // Special case where the min,max range is a point. Should be {0}. + TFLITE_CHECK_EQ(rmin, 0.); + TFLITE_CHECK_EQ(rmax, 0.); + QuantizationParams quantization_params; + quantization_params.zero_point = 0; + quantization_params.scale = 0.; + return quantization_params; + } + + // General case. + // + // First determine the scale. + const double scale = (rmax - rmin) / (qmax_double - qmin_double); + + // Zero-point computation. + // First the initial floating-point computation. The zero-point can be + // determined from solving an affine equation for any known pair + // (real value, corresponding quantized value). + // We know two such pairs: (rmin, qmin) and (rmax, qmax). + // The arithmetic error on the zero point computed from either pair + // will be roughly machine_epsilon * (sum of absolute values of terms) + // so we want to use the variant that adds the smaller terms. + const double zero_point_from_min = qmin_double - rmin / scale; + const double zero_point_from_max = qmax_double - rmax / scale; + const double zero_point_from_min_error = + std::abs(qmin_double) + std::abs(rmin / scale); + const double zero_point_from_max_error = + std::abs(qmax_double) + std::abs(rmax / scale); + + const double zero_point_double = + zero_point_from_min_error < zero_point_from_max_error + ? zero_point_from_min + : zero_point_from_max; + + // Now we need to nudge the zero point to be an integer + // (our zero points are integer, and this is motivated by the requirement + // to be able to represent the real value "0" exactly as a quantized value, + // which is required in multiple places, for example in Im2col with SAME + // padding). + T nudged_zero_point = 0; + if (zero_point_double < qmin_double) { + nudged_zero_point = qmin; + } else if (zero_point_double > qmax_double) { + nudged_zero_point = qmax; + } else { + nudged_zero_point = static_cast(round(zero_point_double)); + } + // The zero point should always be in the range of quantized value, + // [qmin, qmax]. + TFLITE_CHECK_GE(nudged_zero_point, qmin); + TFLITE_CHECK_LE(nudged_zero_point, qmax); + + // Finally, store the result nudged quantization params. + QuantizationParams quantization_params; + quantization_params.zero_point = nudged_zero_point; + quantization_params.scale = scale; + return quantization_params; +} + +template +QuantizationParams ChooseQuantizationParams(double rmin, double rmax) { + return ChooseQuantizationParams(rmin, rmax, false); +} + +// Converts a floating-point number to an integer. For all inputs x where +// static_cast(x) is legal according to the C++ standard, the result +// is identical to that cast (i.e. the result is x with its fractional part +// truncated whenever that is representable as IntOut). +// +// static_cast would cause undefined behavior for the following cases, which +// have well-defined behavior for this function: +// +// 1. If x is NaN, the result is zero. +// +// 2. If the truncated form of x is above the representable range of IntOut, +// the result is std::numeric_limits::max(). +// +// 3. If the truncated form of x is below the representable range of IntOut, +// the result is std::numeric_limits::min(). +// +// Note that cases #2 and #3 cover infinities as well as finite numbers. +// +// The range of FloatIn must include the range of IntOut, otherwise +// the results are undefined. +// TODO(sfeuz): Replace by absl::SafeCast once available. +template +IntOut SafeCast(FloatIn x) { + static_assert(!std::numeric_limits::is_integer, + "FloatIn is integer"); + static_assert(std::numeric_limits::is_integer, + "IntOut is not integer"); + static_assert(std::numeric_limits::radix == 2, "IntOut is base 2"); + + // Special case NaN, for which the logic below doesn't work. + if (std::isnan(x)) { + return 0; + } + + // Negative values all clip to zero for unsigned results. + if (!std::numeric_limits::is_signed && x < 0) { + return 0; + } + + // Handle infinities. + if (std::isinf(x)) { + return x < 0 ? std::numeric_limits::min() + : std::numeric_limits::max(); + } + + // Set exp such that x == f * 2^exp for some f with |f| in [0.5, 1.0), + // unless x is zero in which case exp == 0. Note that this implies that the + // magnitude of x is strictly less than 2^exp. + int exp = 0; + std::frexp(x, &exp); + + // Let N be the number of non-sign bits in the representation of IntOut. If + // the magnitude of x is strictly less than 2^N, the truncated version of x + // is representable as IntOut. The only representable integer for which this + // is not the case is kMin for signed types (i.e. -2^N), but that is covered + // by the fall-through below. + if (exp <= std::numeric_limits::digits) { + return x; + } + + // Handle numbers with magnitude >= 2^N. + return x < 0 ? std::numeric_limits::min() + : std::numeric_limits::max(); +} + +// Decompose a double multiplier into a Q0.31 int32 representation of its +// significand, and shift representation of NEGATIVE its exponent --- +// this is intended as a RIGHT-shift. +// +// Restricted to the case where the multiplier < 1 (and non-negative). +void QuantizeMultiplierSmallerThanOneExp(double double_multiplier, + int32_t* quantized_multiplier, + int* left_shift); + +// Decompose a double multiplier into a Q0.31 int32 representation of its +// significand, and shift representation of its exponent. +// +// Restricted to the case where the multiplier > 1. +void QuantizeMultiplierGreaterThanOne(double double_multiplier, + int32_t* quantized_multiplier, + int* left_shift); + +// Decompose a double multiplier into a Q0.31 int32 representation of its +// significand, and shift representation of its exponent. +// +// Handles an arbitrary positive multiplier. The 'shift' output-value is +// basically the 'floating-point exponent' of the multiplier: +// Negative for a right-shift (when the multiplier is <1), positive for a +// left-shift (when the multiplier is >1) +void QuantizeMultiplier(double double_multiplier, int32_t* quantized_multiplier, + int* shift); + +// Splits a double input value into a returned fraction, and a shift value from +// the exponent, using only bitwise and integer operations to support +// microcontrollers and other environments without floating-point support. +// +// This is designed to be a replacement for how std::frexp() is used within the +// QuantizeMultiplier() function, and so has a different signature than the +// standard version, returning a 64-bit integer rather than a double. This +// result has a maximum value of 1<<31, with the fraction expressed as a +// proportion of that maximum. +// +// std::frexp() returns NaNs and infinities unmodified, but since we're +// returning integers that can't represent those values, instead we return +// a shift of std::numeric_limits::max() for all bad numbers, with an int64 +// result of 0 for NaNs, std:numeric_limits::max() for +INFINITY, and +// std::numeric_limits::min() for -INFINITY. Denormalized inputs will +// result in return values that end up truncating some bits at the end, +// reflecting the loss of precision inherent in denormalization. +int64_t IntegerFrExp(double input, int* shift); + +// Converts an integer fraction in the format produced by IntegerFrExp (where +// 0x40000000 is 1.0) and an exponent shift (between -1022 and +1022) into an +// IEEE binary64 double format result. The implementation uses only integer and +// bitwise operators, so no floating point hardware support or emulation is +// needed. This is here so quantized operations can run non-time-critical +// preparation calculations on microcontrollers and other platforms without +// float support. +double DoubleFromFractionAndShift(int64_t fraction, int shift); + +// Performs a multiplication of two numbers in double format, using only integer +// and bitwise instructions. This is aimed at supporting housekeeping functions +// for quantized operations on microcontrollers without floating-point hardware. +double IntegerDoubleMultiply(double a, double b); + +// Returns -1 if a is less than b, 0 if a and b are equal, and +1 if a is +// greater than b. It is implemented using only integer and logical instructions +// so that it can be easily run on microcontrollers for quantized operations. +int IntegerDoubleCompare(double a, double b); + +// This first creates a multiplier in a double equivalent of +// Q(input_integer_bits).(31-input_integer_bits) representation, with extra +// precision in the double's fractional bits. It then splits the result into +// significand and exponent. +void PreprocessSoftmaxScaling(double beta, double input_scale, + int input_integer_bits, + int32_t* quantized_multiplier, int* left_shift); +// Like PreprocessSoftmaxScaling, but inverse scaling factors also calculated. +void PreprocessLogSoftmaxScalingExp(double beta, double input_scale, + int input_integer_bits, + int32_t* quantized_multiplier, + int* left_shift, + int32_t* reverse_scaling_divisor, + int* reverse_scaling_left_shift); +// Calculate the largest input that will result in a within-bounds intermediate +// result within MultiplyByQuantizedMultiplierGreaterThanOne. In other words, +// it must not overflow before we reduce the value by multiplication by the +// input multiplier. The negative radius is used as the minimum difference in +// Softmax. +int CalculateInputRadius(int input_integer_bits, int input_left_shift, + int total_signed_bits = 31); + +// Nudges a min/max quantization range to ensure zero is zero. +// Gymnastics with nudged zero point is to ensure that real zero maps to +// an integer, which is required for e.g. zero-padding in convolutional layers. +// Outputs nudged_min, nudged_max, nudged_scale. +void NudgeQuantizationRange(const float min, const float max, + const int quant_min, const int quant_max, + float* nudged_min, float* nudged_max, + float* nudged_scale); + +// Fake quantizes (quantizes and dequantizes) input_data using the scale, +// nudged_min, and nudged_max from NudgeQuantizationRange. This matches the code +// in TensorFlow's FakeQuantizeWithMinMaxVarsFunctor. +void FakeQuantizeArray(const float nudged_scale, const float nudged_min, + const float nudged_max, const float* input_data, + float* output_data, const float size); + +// If x is approximately a power of two (with any positive or negative +// exponent), stores that exponent (i.e. log2(x)) in *log2_result, otherwise +// returns false. +bool CheckedLog2(const float x, int* log2_result); + +// Decomposes an array of double multipliers into a Q0.31 int32 representation +// of its significand, and shift representation of its exponent. +// +// Handles an arbitrary multiplier. The 'shift' output-value is +// basically the 'floating-point exponent' of the multiplier: +// Negative for a right-shift (when the multiplier is <1), positive for a +// left-shift (when the multiplier is >1) +void QuantizeMultiplierArray(const double* effective_scales, size_t size, + int32_t* effective_scale_significand, + int* effective_shift); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_QUANTIZATION_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/add.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/add.h new file mode 100644 index 000000000..ae1f47a83 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/add.h @@ -0,0 +1,400 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ADD_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ADD_H_ + +#include +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { + +namespace reference_ops { + +template +inline void Add(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const T* input1_data, + const RuntimeShape& input2_shape, const T* input2_data, + const RuntimeShape& output_shape, T* output_data) { + T activation_min, activation_max; + GetActivationParams(params, &activation_min, &activation_max); + + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = ActivationFunctionWithMinMax( + input1_data[i] + input2_data[i], activation_min, activation_max); + } +} + +// Element-wise add that can often be used for inner loop of broadcast add as +// well as the non-broadcast add. + +// This function is used for 8-bit as well as for 16-bit, but the accumulator +// is 32-bit for both cases. The overflow does not happen due to the +// choice of the shift (20 or 15, accordingly - see add.cc for more comments). +template +inline void AddElementwise(int size, const ArithmeticParams& params, + const T* input1_data, const T* input2_data, + T* output_data) { + TFLITE_DCHECK_GT(params.input1_offset, -std::numeric_limits::max()); + TFLITE_DCHECK_GT(params.input2_offset, -std::numeric_limits::max()); + TFLITE_DCHECK_LT(params.input1_offset, std::numeric_limits::max()); + TFLITE_DCHECK_LT(params.input2_offset, std::numeric_limits::max()); + + for (int i = 0; i < size; ++i) { + const int32_t input1_val = params.input1_offset + input1_data[i]; + const int32_t input2_val = params.input2_offset + input2_data[i]; + const int32_t shifted_input1_val = input1_val * (1 << params.left_shift); + const int32_t shifted_input2_val = input2_val * (1 << params.left_shift); + const int32_t scaled_input1_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input1_val, params.input1_multiplier, params.input1_shift); + const int32_t scaled_input2_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input2_val, params.input2_multiplier, params.input2_shift); + const int32_t raw_sum = scaled_input1_val + scaled_input2_val; + const int32_t raw_output = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + raw_sum, params.output_multiplier, params.output_shift) + + params.output_offset; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + output_data[i] = static_cast(clamped_output); + } +} + +// Scalar-broadcast add that can be used for inner loop of more general +// broadcast add, so that, for example, scalar-broadcast with batch will still +// be fast. +inline void AddScalarBroadcast(int size, const ArithmeticParams& params, + uint8_t input1_data, const uint8_t* input2_data, + uint8_t* output_data) { + TFLITE_DCHECK_GT(params.input1_offset, -256); + TFLITE_DCHECK_GT(params.input2_offset, -256); + TFLITE_DCHECK_LT(params.input1_offset, 256); + TFLITE_DCHECK_LT(params.input2_offset, 256); + + const int32_t input1_val = params.input1_offset + input1_data; + const int32_t shifted_input1_val = input1_val * (1 << params.left_shift); + const int32_t scaled_input1_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input1_val, params.input1_multiplier, params.input1_shift); + for (int i = 0; i < size; ++i) { + const int32_t input2_val = params.input2_offset + input2_data[i]; + const int32_t shifted_input2_val = input2_val * (1 << params.left_shift); + const int32_t scaled_input2_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input2_val, params.input2_multiplier, params.input2_shift); + const int32_t raw_sum = scaled_input1_val + scaled_input2_val; + const int32_t raw_output = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + raw_sum, params.output_multiplier, params.output_shift) + + params.output_offset; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + output_data[i] = static_cast(clamped_output); + } +} + +inline void Add(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const uint8_t* input1_data, + const RuntimeShape& input2_shape, const uint8_t* input2_data, + const RuntimeShape& output_shape, uint8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + TFLITE_DCHECK_GT(params.input1_offset, -256); + TFLITE_DCHECK_GT(params.input2_offset, -256); + TFLITE_DCHECK_LT(params.input1_offset, 256); + TFLITE_DCHECK_LT(params.input2_offset, 256); + AddElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +inline void AddGeneralParamScale(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const int16_t* input1_data, + const RuntimeShape& input2_shape, + const int16_t* input2_data, + const RuntimeShape& output_shape, + int16_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + int max_value = std::numeric_limits::max(); + + TFLITE_DCHECK_GT(params.input1_offset, -max_value); + TFLITE_DCHECK_GT(params.input2_offset, -max_value); + TFLITE_DCHECK_LT(params.input1_offset, max_value); + TFLITE_DCHECK_LT(params.input2_offset, max_value); + AddElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +inline void Add(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const int16_t* input1_data, + const RuntimeShape& input2_shape, const int16_t* input2_data, + const RuntimeShape& output_shape, int16_t* output_data, + bool pot_scale = true) { + if (!pot_scale) { + AddGeneralParamScale(params, input1_shape, input1_data, input2_shape, + input2_data, output_shape, output_data); + return; + } + + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + + const int input1_shift = params.input1_shift; + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + const int16_t output_activation_min = params.quantized_activation_min; + const int16_t output_activation_max = params.quantized_activation_max; + + TFLITE_DCHECK(input1_shift == 0 || params.input2_shift == 0); + TFLITE_DCHECK_LE(input1_shift, 0); + TFLITE_DCHECK_LE(params.input2_shift, 0); + const int16_t* not_shift_input = + input1_shift == 0 ? input1_data : input2_data; + const int16_t* shift_input = input1_shift == 0 ? input2_data : input1_data; + const int input_right_shift = + input1_shift == 0 ? -params.input2_shift : -input1_shift; + + for (int i = 0; i < flat_size; i++) { + // F0 uses 0 integer bits, range [-1, 1]. + using F0 = gemmlowp::FixedPoint; + + F0 input_ready_scaled = F0::FromRaw(not_shift_input[i]); + F0 scaled_input = F0::FromRaw( + gemmlowp::RoundingDivideByPOT(shift_input[i], input_right_shift)); + F0 result = gemmlowp::SaturatingAdd(scaled_input, input_ready_scaled); + const int16_t raw_output = result.raw(); + const int16_t clamped_output = std::min( + output_activation_max, std::max(output_activation_min, raw_output)); + output_data[i] = clamped_output; + } +} + +template +inline typename std::enable_if::value, void>::type +BroadcastAdd4DSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const T* input1_data, + const RuntimeShape& input2_shape, const T* input2_data, + const RuntimeShape& output_shape, T* output_data) { + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + const RuntimeShape extended_output_shape = + RuntimeShape::ExtendedShape(4, output_shape); + + T activation_min, activation_max; + GetActivationParams(params, &activation_min, &activation_max); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + for (int b = 0; b < extended_output_shape.Dims(0); ++b) { + for (int y = 0; y < extended_output_shape.Dims(1); ++y) { + for (int x = 0; x < extended_output_shape.Dims(2); ++x) { + for (int c = 0; c < extended_output_shape.Dims(3); ++c) { + output_data[Offset(extended_output_shape, b, y, x, c)] = + ActivationFunctionWithMinMax( + input1_data[SubscriptToIndex(desc1, b, y, x, c)] + + input2_data[SubscriptToIndex(desc2, b, y, x, c)], + activation_min, activation_max); + } + } + } + } +} + +// This function is used for 8-bit as well as for 16-bit, but the accumulator +// is 32-bit for both cases. The overflow does not happen due to the +// choice of the shift (20 or 15, accordingly - see add.cc for more comments). +template +inline typename std::enable_if::value, void>::type +BroadcastAdd4DSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const T* input1_data, + const RuntimeShape& input2_shape, const T* input2_data, + const RuntimeShape& output_shape, T* output_data) { + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + const RuntimeShape extended_output_shape = + RuntimeShape::ExtendedShape(4, output_shape); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + for (int b = 0; b < extended_output_shape.Dims(0); ++b) { + for (int y = 0; y < extended_output_shape.Dims(1); ++y) { + for (int x = 0; x < extended_output_shape.Dims(2); ++x) { + for (int c = 0; c < extended_output_shape.Dims(3); ++c) { + const int32_t input1_val = + params.input1_offset + + input1_data[SubscriptToIndex(desc1, b, y, x, c)]; + const int32_t input2_val = + params.input2_offset + + input2_data[SubscriptToIndex(desc2, b, y, x, c)]; + const int32_t shifted_input1_val = + input1_val * (1 << params.left_shift); + const int32_t shifted_input2_val = + input2_val * (1 << params.left_shift); + const int32_t scaled_input1_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input1_val, params.input1_multiplier, + params.input1_shift); + const int32_t scaled_input2_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input2_val, params.input2_multiplier, + params.input2_shift); + const int32_t raw_sum = scaled_input1_val + scaled_input2_val; + const int32_t raw_output = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + raw_sum, params.output_multiplier, params.output_shift) + + params.output_offset; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + output_data[Offset(extended_output_shape, b, y, x, c)] = + static_cast(clamped_output); + } + } + } + } +} + +inline void BroadcastAddFivefold(const ArithmeticParams& unswitched_params, + const RuntimeShape& unswitched_input1_shape, + const uint8_t* unswitched_input1_data, + const RuntimeShape& unswitched_input2_shape, + const uint8_t* unswitched_input2_data, + const RuntimeShape& output_shape, + uint8_t* output_data) { + ArithmeticParams switched_params = unswitched_params; + switched_params.input1_offset = unswitched_params.input2_offset; + switched_params.input1_multiplier = unswitched_params.input2_multiplier; + switched_params.input1_shift = unswitched_params.input2_shift; + switched_params.input2_offset = unswitched_params.input1_offset; + switched_params.input2_multiplier = unswitched_params.input1_multiplier; + switched_params.input2_shift = unswitched_params.input1_shift; + + const bool use_unswitched = + unswitched_params.broadcast_category == + tflite::BroadcastableOpCategory::kFirstInputBroadcastsFast; + + const ArithmeticParams& params = + use_unswitched ? unswitched_params : switched_params; + const uint8_t* input1_data = + use_unswitched ? unswitched_input1_data : unswitched_input2_data; + const uint8_t* input2_data = + use_unswitched ? unswitched_input2_data : unswitched_input1_data; + + // Fivefold nested loops. The second input resets its position for each + // iteration of the second loop. The first input resets its position at the + // beginning of the fourth loop. The innermost loop is an elementwise add of + // sections of the arrays. + uint8_t* output_data_ptr = output_data; + const uint8_t* input1_data_ptr = input1_data; + const uint8_t* input2_data_reset = input2_data; + // In the fivefold pattern, y0, y2 and y4 are not broadcast, and so shared + // between input shapes. y3 for input 1 is always broadcast, and so the + // dimension there is 1, whereas optionally y1 might be broadcast for input 2. + // Put another way, + // input1.shape.FlatSize = y0 * y1 * y2 * y4, + // input2.shape.FlatSize = y0 * y2 * y3 * y4. + int y0 = params.broadcast_shape[0]; + int y1 = params.broadcast_shape[1]; + int y2 = params.broadcast_shape[2]; + int y3 = params.broadcast_shape[3]; + int y4 = params.broadcast_shape[4]; + if (y4 > 1) { + // General fivefold pattern, with y4 > 1 so there is a non-broadcast inner + // dimension. + for (int i0 = 0; i0 < y0; ++i0) { + const uint8_t* input2_data_ptr; + for (int i1 = 0; i1 < y1; ++i1) { + input2_data_ptr = input2_data_reset; + for (int i2 = 0; i2 < y2; ++i2) { + for (int i3 = 0; i3 < y3; ++i3) { + AddElementwise(y4, params, input1_data_ptr, input2_data_ptr, + output_data_ptr); + input2_data_ptr += y4; + output_data_ptr += y4; + } + // We have broadcast y4 of input1 data y3 times, and now move on. + input1_data_ptr += y4; + } + } + // We have broadcast y2*y3*y4 of input2 data y1 times, and now move on. + input2_data_reset = input2_data_ptr; + } + } else { + // Special case of y4 == 1, in which the innermost loop is a single element + // and can be combined with the next (y3) as an inner broadcast. + // + // Note that this handles the case of pure scalar broadcast when + // y0 == y1 == y2 == 1. With low overhead it handles cases such as scalar + // broadcast with batch (as y2 > 1). + // + // NOTE The process is the same as the above general case except simplified + // for y4 == 1 and the loop over y3 is contained within the + // AddScalarBroadcast function. + for (int i0 = 0; i0 < y0; ++i0) { + const uint8_t* input2_data_ptr; + for (int i1 = 0; i1 < y1; ++i1) { + input2_data_ptr = input2_data_reset; + for (int i2 = 0; i2 < y2; ++i2) { + AddScalarBroadcast(y3, params, *input1_data_ptr, input2_data_ptr, + output_data_ptr); + input2_data_ptr += y3; + output_data_ptr += y3; + input1_data_ptr += 1; + } + } + input2_data_reset = input2_data_ptr; + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ADD_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/add_n.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/add_n.h new file mode 100644 index 000000000..b6b5882d8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/add_n.h @@ -0,0 +1,86 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ADD_N_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ADD_N_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_ops { + +// T is expected to be either float or int. +template +inline void AddN(const RuntimeShape& input_shape, const size_t num_inputs, + const T* const* input_data, T* output_data) { + // All inputs and output should have the same shape, this is checked during + // Prepare stage. + const size_t size = input_shape.FlatSize(); + for (size_t i = 0; i < size; ++i) { + T x = 0; + for (size_t j = 0; j < num_inputs; ++j) { + x += input_data[j][i]; + } + output_data[i] = x; + } +} + +inline void AddN(const ArithmeticParams& params, + const RuntimeShape& input_shape, const size_t num_inputs, + const int8_t* const* input_data, int8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + // Input offset is negative input zero point. Activation tensors are + // asymmetric quantized so they span the full int8 range. + // All inputs should have same zero-point and scale, this is checked during + // Prepare stage. + TFLITE_DCHECK_GE(-params.input1_offset, std::numeric_limits::min()); + TFLITE_DCHECK_LE(-params.input1_offset, std::numeric_limits::max()); + + // All inputs and output should have the same shape, this is checked during + // Prepare stage. + const size_t size = input_shape.FlatSize(); + for (size_t i = 0; i < size; ++i) { + // accumulate in scaled_x before clamping to avoid overflow + const int32_t x = params.input1_offset; // x = 0 + const int32_t shifted_x = x * (1 << params.left_shift); + int32_t scaled_x = MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_x, params.input1_multiplier, params.input1_shift); + + for (size_t j = 0; j < num_inputs; ++j) { + const int32_t y = params.input1_offset + input_data[j][i]; + const int32_t shifted_y = y * (1 << params.left_shift); + int32_t scaled_y = MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_y, params.input1_multiplier, params.input1_shift); + scaled_x += scaled_y; + } + + const int32_t raw_output = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + scaled_x, params.output_multiplier, params.output_shift) + + params.output_offset; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + output_data[i] = static_cast(clamped_output); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ADD_N_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/arg_min_max.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/arg_min_max.h new file mode 100644 index 000000000..8154fbf71 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/arg_min_max.h @@ -0,0 +1,88 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ARG_MIN_MAX_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ARG_MIN_MAX_H_ + +#include + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +template +std::function GetComparefunction(bool is_arg_max) { + if (is_arg_max) { + return std::greater(); + } else { + return std::less(); + } +} + +template +void ArgMinMax(const RuntimeShape& input1_shape, const T1* input1_data, + const T3* input2_data, const RuntimeShape& output_shape, + T2* output_data, const Cmp& cmp) { + TFLITE_DCHECK_GT(input1_shape.DimensionsCount(), 0); + TFLITE_DCHECK_EQ(input1_shape.DimensionsCount() - 1, + output_shape.DimensionsCount()); + int axis = input2_data[0]; + if (axis < 0) { + axis += input1_shape.DimensionsCount(); + } + const int axis_size = input1_shape.Dims(axis); + + int outer_size = 1; + for (int i = 0; i < axis; ++i) { + TFLITE_DCHECK_EQ(input1_shape.Dims(i), output_shape.Dims(i)); + outer_size *= input1_shape.Dims(i); + } + + int inner_size = 1; + const int dims_count = input1_shape.DimensionsCount(); + for (int i = axis + 1; i < dims_count; ++i) { + TFLITE_DCHECK_EQ(input1_shape.Dims(i), output_shape.Dims(i - 1)); + inner_size *= input1_shape.Dims(i); + } + for (int outer = 0; outer < outer_size; ++outer) { + for (int inner = 0; inner < inner_size; ++inner) { + auto min_max_value = input1_data[outer * axis_size * inner_size + inner]; + T2 min_max_index = 0; + for (int i = 1; i < axis_size; ++i) { + const auto& curr_value = + input1_data[(outer * axis_size + i) * inner_size + inner]; + if (cmp(curr_value, min_max_value)) { + min_max_value = curr_value; + min_max_index = static_cast(i); + } + } + output_data[outer * inner_size + inner] = min_max_index; + } + } +} + +template +void ArgMinMax(const RuntimeShape& input1_shape, const T1* input1_data, + const T3* input2_data, const RuntimeShape& output_shape, + T2* output_data, const bool is_arg_max) { + ArgMinMax(input1_shape, input1_data, input2_data, output_shape, output_data, + GetComparefunction(is_arg_max)); +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ARG_MIN_MAX_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/batch_matmul.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/batch_matmul.h new file mode 100644 index 000000000..767ad6ab0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/batch_matmul.h @@ -0,0 +1,275 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BATCH_MATMUL_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BATCH_MATMUL_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/portable_tensor_utils.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { +namespace batch_matmul { + +// Determine which dimension is the broadcast dimension. +inline int broadcast_dim(int lhs_dim, int rhs_dim) { + if (lhs_dim == rhs_dim) return lhs_dim; + if (lhs_dim == 1) return rhs_dim; + TFLITE_DCHECK_EQ(rhs_dim, 1); + return lhs_dim; +} + +// Compute the "extent" for iterating on this dimension. +// If we are broadcasting, then don't advance (i.e return 0). +inline int extent(const RuntimeShape& shape, int x) { + if (shape.Dims(x) == 1) { + return 0; + } + int prod = 1; + for (int i = x + 1; i < shape.DimensionsCount(); ++i) { + prod *= shape.Dims(i); + } + return prod; +} + +} // namespace batch_matmul + +template +inline void BatchMatMul(const RuntimeShape& lhs_shape, const Ta* lhs_data, + const RuntimeShape& rhs_shape, const Tb* rhs_data, + const RuntimeShape& output_shape, Tout* output_data) { + const RuntimeShape extended_lhs_shape = + RuntimeShape::ExtendedShape(5, lhs_shape); + const RuntimeShape extended_rhs_shape = + RuntimeShape::ExtendedShape(5, rhs_shape); + + const int batch_dim0 = batch_matmul::broadcast_dim( + extended_lhs_shape.Dims(0), extended_rhs_shape.Dims(0)); + const int batch_dim1 = batch_matmul::broadcast_dim( + extended_lhs_shape.Dims(1), extended_rhs_shape.Dims(1)); + const int batch_dim2 = batch_matmul::broadcast_dim( + extended_lhs_shape.Dims(2), extended_rhs_shape.Dims(2)); + + const int lhs_ext0 = batch_matmul::extent(extended_lhs_shape, 0); + const int lhs_ext1 = batch_matmul::extent(extended_lhs_shape, 1); + const int lhs_ext2 = batch_matmul::extent(extended_lhs_shape, 2); + const int rhs_ext0 = batch_matmul::extent(extended_rhs_shape, 0); + const int rhs_ext1 = batch_matmul::extent(extended_rhs_shape, 1); + const int rhs_ext2 = batch_matmul::extent(extended_rhs_shape, 2); + + // Set params for each matrix multiply. + const int lhs_rows = extended_lhs_shape.Dims(3); + const int rhs_cols = extended_rhs_shape.Dims(4); + const int accum_depth = extended_lhs_shape.Dims(4); + + for (int b0 = 0; b0 < batch_dim0; ++b0) { + const Ta* lhs_ptr0 = lhs_data + (b0 * lhs_ext0); + const Tb* rhs_ptr0 = rhs_data + (b0 * rhs_ext0); + for (int b1 = 0; b1 < batch_dim1; ++b1) { + const Ta* lhs_ptr1 = lhs_ptr0 + b1 * lhs_ext1; + const Tb* rhs_ptr1 = rhs_ptr0 + b1 * rhs_ext1; + for (int b2 = 0; b2 < batch_dim2; ++b2) { + const Ta* lhs_ptr2 = lhs_ptr1 + b2 * lhs_ext2; + const Tb* rhs_ptr2 = rhs_ptr1 + b2 * rhs_ext2; + Tout* out_ptr = output_data + ((b0 * batch_dim1 * batch_dim2) + + b1 * batch_dim2 + b2) * + lhs_rows * rhs_cols; + for (int j = 0; j < rhs_cols; ++j) { + for (int i = 0; i < lhs_rows; ++i) { + Tout total = 0; + for (int k = 0; k < accum_depth; ++k) { + total += static_cast(lhs_ptr2[accum_depth * i + k]) * + static_cast(rhs_ptr2[j * accum_depth + k]); + } + int idx = lhs_rows * j + i; + out_ptr[idx] = total; + } + } + } + } + } +} + +inline void BatchMatMul(const RuntimeShape& lhs_shape, const int8_t* lhs_data, + const RuntimeShape& rhs_shape, const int8_t* rhs_data, + const float* scaling_factors, + const int32_t* input_offset, int32_t* row_sums, + const RuntimeShape& output_shape, float* output_data, + bool* compute_row_sums) { + const RuntimeShape extended_lhs_shape = + RuntimeShape::ExtendedShape(5, lhs_shape); + const RuntimeShape extended_rhs_shape = + RuntimeShape::ExtendedShape(5, rhs_shape); + + const int batch_dim0 = batch_matmul::broadcast_dim( + extended_lhs_shape.Dims(0), extended_rhs_shape.Dims(0)); + const int batch_dim1 = batch_matmul::broadcast_dim( + extended_lhs_shape.Dims(1), extended_rhs_shape.Dims(1)); + const int batch_dim2 = batch_matmul::broadcast_dim( + extended_lhs_shape.Dims(2), extended_rhs_shape.Dims(2)); + + const int lhs_ext0 = batch_matmul::extent(extended_lhs_shape, 0); + const int lhs_ext1 = batch_matmul::extent(extended_lhs_shape, 1); + const int lhs_ext2 = batch_matmul::extent(extended_lhs_shape, 2); + const int rhs_ext0 = batch_matmul::extent(extended_rhs_shape, 0); + const int rhs_ext1 = batch_matmul::extent(extended_rhs_shape, 1); + const int rhs_ext2 = batch_matmul::extent(extended_rhs_shape, 2); + + // Set params for each matrix multiply. + const int lhs_rows = extended_lhs_shape.Dims(3); + const int rhs_cols = extended_rhs_shape.Dims(4); + const int accum_depth = extended_lhs_shape.Dims(4); + + const int ioff_ext0 = rhs_ext0 == 0 ? 0 : rhs_cols; + const int ioff_ext1 = rhs_ext1 == 0 ? 0 : rhs_cols; + const int ioff_ext2 = rhs_ext2 == 0 ? 0 : rhs_cols; + const int woff_ext0 = lhs_ext0 == 0 ? 0 : lhs_rows; + const int woff_ext1 = lhs_ext1 == 0 ? 0 : lhs_rows; + const int woff_ext2 = lhs_ext2 == 0 ? 0 : lhs_rows; + + if (!compute_row_sums || *compute_row_sums) { + int num_weights_matrices = 1; + for (int i = 1; i < extended_lhs_shape.DimensionsCount() - 2; ++i) { + num_weights_matrices *= extended_lhs_shape.Dims(i); + } + tensor_utils::ReductionSumVector( + lhs_data, row_sums, num_weights_matrices * lhs_rows, accum_depth); + if (compute_row_sums) { + *compute_row_sums = false; + } + } + + for (int b0 = 0; b0 < batch_dim0; ++b0) { + const int8_t* lhs_ptr0 = lhs_data + (b0 * lhs_ext0); + const int8_t* rhs_ptr0 = rhs_data + (b0 * rhs_ext0); + const int32_t* ioff_ptr0 = input_offset + (b0 * ioff_ext0); + const float* scale_ptr0 = scaling_factors + (b0 * ioff_ext0); + const int32_t* woff_ptr0 = row_sums + (b0 * woff_ext0); + for (int b1 = 0; b1 < batch_dim1; ++b1) { + const int8_t* lhs_ptr1 = lhs_ptr0 + b1 * lhs_ext1; + const int8_t* rhs_ptr1 = rhs_ptr0 + b1 * rhs_ext1; + const int32_t* ioff_ptr1 = ioff_ptr0 + (b1 * ioff_ext1); + const float* scale_ptr1 = scale_ptr0 + (b1 * ioff_ext1); + const int32_t* woff_ptr1 = woff_ptr0 + (b1 * woff_ext1); + for (int b2 = 0; b2 < batch_dim2; ++b2) { + const int8_t* lhs_ptr2 = lhs_ptr1 + b2 * lhs_ext2; + const int8_t* rhs_ptr2 = rhs_ptr1 + b2 * rhs_ext2; + const int32_t* ioff_ptr2 = ioff_ptr1 + (b2 * ioff_ext2); + const float* scale_ptr2 = scale_ptr1 + (b2 * ioff_ext2); + const int32_t* woff_ptr2 = woff_ptr1 + (b2 * woff_ext2); + float* out_ptr = output_data + ((b0 * batch_dim1 * batch_dim2) + + b1 * batch_dim2 + b2) * + lhs_rows * rhs_cols; + for (int j = 0; j < rhs_cols; ++j) { + const float batch_scaling_factor = scale_ptr2[j]; + const float batch_offset = static_cast(ioff_ptr2[j]); + for (int i = 0; i < lhs_rows; ++i) { + int32_t total = 0; + for (int k = 0; k < accum_depth; ++k) { + total += + lhs_ptr2[accum_depth * i + k] * rhs_ptr2[j * accum_depth + k]; + } + int32_t row_sum = woff_ptr2[i]; + total -= row_sum * batch_offset; + int idx = lhs_rows * j + i; + out_ptr[idx] += batch_scaling_factor * total; + } + } + } + } + } +} + +template +inline void BatchMatMul(const FullyConnectedParams& params, + const RuntimeShape& lhs_shape, const T* lhs_data, + const RuntimeShape& rhs_shape, const T* rhs_data, + const RuntimeShape& output_shape, T* output_data) { + const RuntimeShape extended_lhs_shape = + RuntimeShape::ExtendedShape(5, lhs_shape); + const RuntimeShape extended_rhs_shape = + RuntimeShape::ExtendedShape(5, rhs_shape); + + const int batch_dim0 = batch_matmul::broadcast_dim( + extended_lhs_shape.Dims(0), extended_rhs_shape.Dims(0)); + const int batch_dim1 = batch_matmul::broadcast_dim( + extended_lhs_shape.Dims(1), extended_rhs_shape.Dims(1)); + const int batch_dim2 = batch_matmul::broadcast_dim( + extended_lhs_shape.Dims(2), extended_rhs_shape.Dims(2)); + + const int lhs_ext0 = batch_matmul::extent(extended_lhs_shape, 0); + const int lhs_ext1 = batch_matmul::extent(extended_lhs_shape, 1); + const int lhs_ext2 = batch_matmul::extent(extended_lhs_shape, 2); + const int rhs_ext0 = batch_matmul::extent(extended_rhs_shape, 0); + const int rhs_ext1 = batch_matmul::extent(extended_rhs_shape, 1); + const int rhs_ext2 = batch_matmul::extent(extended_rhs_shape, 2); + + // Set params for each matrix multiply. + const int lhs_rows = extended_lhs_shape.Dims(3); + const int rhs_cols = extended_rhs_shape.Dims(4); + const int accum_depth = extended_lhs_shape.Dims(4); + + const int32_t input_offset = params.input_offset; + const int32_t filter_offset = params.weights_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_multiplier = params.output_multiplier; + const int output_shift = params.output_shift; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + + for (int b0 = 0; b0 < batch_dim0; ++b0) { + const T* lhs_ptr0 = lhs_data + (b0 * lhs_ext0); + const T* rhs_ptr0 = rhs_data + (b0 * rhs_ext0); + for (int b1 = 0; b1 < batch_dim1; ++b1) { + const T* lhs_ptr1 = lhs_ptr0 + b1 * lhs_ext1; + const T* rhs_ptr1 = rhs_ptr0 + b1 * rhs_ext1; + for (int b2 = 0; b2 < batch_dim2; ++b2) { + const T* lhs_ptr2 = lhs_ptr1 + b2 * lhs_ext2; + const T* rhs_ptr2 = rhs_ptr1 + b2 * rhs_ext2; + T* out_ptr = output_data + + ((b0 * batch_dim1 * batch_dim2) + b1 * batch_dim2 + b2) * + lhs_rows * rhs_cols; + + for (int j = 0; j < rhs_cols; ++j) { + for (int i = 0; i < lhs_rows; ++i) { + AccumT total = 0; + for (int k = 0; k < accum_depth; ++k) { + AccumT lhs_val = lhs_ptr2[accum_depth * i + k]; + AccumT rhs_val = rhs_ptr2[accum_depth * j + k]; + total += (lhs_val + filter_offset) * (rhs_val + input_offset); + } + int32_t total_scaled = MultiplyByQuantizedMultiplier( + total, output_multiplier, output_shift); + total_scaled += output_offset; + total_scaled = std::max(total_scaled, output_activation_min); + total_scaled = std::min(total_scaled, output_activation_max); + const int idx = lhs_rows * j + i; + out_ptr[idx] = static_cast(total_scaled); + } + } + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BATCH_MATMUL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h new file mode 100644 index 000000000..54c526077 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h @@ -0,0 +1,101 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BATCH_TO_SPACE_ND_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BATCH_TO_SPACE_ND_H_ + +#include + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +// TODO(b/135760455): Move this method anonymous namespace in a cc file. +inline RuntimeShape ExtendShapeBatchToSpace(const RuntimeShape& shape) { + if (shape.DimensionsCount() == 4) { + return shape; + } + RuntimeShape new_shape(4, 1); + new_shape.SetDim(0, shape.Dims(0)); + new_shape.SetDim(1, shape.Dims(1)); + new_shape.SetDim(3, shape.Dims(2)); + return new_shape; +} + +template +inline void BatchToSpaceND(const RuntimeShape& unextended_input1_shape, + const T* input1_data, + const RuntimeShape& unextended_input2_shape, + const int32_t* block_shape_data, + const RuntimeShape& unextended_input3_shape, + const int32_t* crops_data, + const RuntimeShape& unextended_output_shape, + T* output_data) { + ruy::profiler::ScopeLabel label("BatchToSpaceND"); + TFLITE_DCHECK_GE(unextended_input1_shape.DimensionsCount(), 3); + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(unextended_input1_shape.DimensionsCount(), + unextended_output_shape.DimensionsCount()); + + const RuntimeShape input1_shape = + ExtendShapeBatchToSpace(unextended_input1_shape); + const RuntimeShape output_shape = + ExtendShapeBatchToSpace(unextended_output_shape); + + const int output_width = output_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_batch_size = output_shape.Dims(0); + + const int depth = input1_shape.Dims(3); + const int input_width = input1_shape.Dims(2); + const int input_height = input1_shape.Dims(1); + const int input_batch_size = input1_shape.Dims(0); + + const int block_shape_height = block_shape_data[0]; + const int block_shape_width = + unextended_input1_shape.DimensionsCount() == 4 ? block_shape_data[1] : 1; + const int crops_top = crops_data[0]; + const int crops_left = + unextended_input1_shape.DimensionsCount() == 4 ? crops_data[2] : 0; + for (int in_batch = 0; in_batch < input_batch_size; ++in_batch) { + const int out_batch = in_batch % output_batch_size; + const int spatial_offset = in_batch / output_batch_size; + for (int in_h = 0; in_h < input_height; ++in_h) { + const int out_h = in_h * block_shape_height + + spatial_offset / block_shape_width - crops_top; + if (out_h < 0 || out_h >= output_height) { + continue; + } + for (int in_w = 0; in_w < input_width; ++in_w) { + const int out_w = in_w * block_shape_width + + spatial_offset % block_shape_width - crops_left; + + if (out_w < 0 || out_w >= output_width) { + continue; + } + T* out = output_data + Offset(output_shape, out_batch, out_h, out_w, 0); + const T* in = + input1_data + Offset(input1_shape, in_batch, in_h, in_w, 0); + memcpy(out, in, depth * sizeof(T)); + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BATCH_TO_SPACE_ND_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/binary_function.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/binary_function.h new file mode 100644 index 000000000..0b124af87 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/binary_function.h @@ -0,0 +1,91 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BINARY_FUNCTION_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BINARY_FUNCTION_H_ + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +// Also appears to duplicate MinimumMaximum. +// +// R: Result type. T1: Input 1 type. T2: Input 2 type. +template +inline void BroadcastBinaryFunction4DSlow( + const RuntimeShape& unextended_input1_shape, const T1* input1_data, + const RuntimeShape& unextended_input2_shape, const T2* input2_data, + const RuntimeShape& unextended_output_shape, R* output_data, + R (*func)(T1, T2)) { + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, + unextended_input2_shape, &desc1, &desc2); + + const int* dims_data = + reinterpret_cast(output_shape.DimsDataUpTo5D()); + for (int b = 0; b < output_shape.Dims(0); ++b) { + int out_idx_b = b * dims_data[1]; + int in_idx1_b = desc1.strides[0] * b; + int in_idx2_b = desc2.strides[0] * b; + for (int y = 0; y < output_shape.Dims(1); ++y) { + int out_idx_y = (out_idx_b + y) * dims_data[2]; + int in_idx1_y = in_idx1_b + desc1.strides[1] * y; + int in_idx2_y = in_idx2_b + desc2.strides[1] * y; + for (int x = 0; x < output_shape.Dims(2); ++x) { + int out_idx_x = (out_idx_y + x) * dims_data[3]; + int in1_idx = in_idx1_y + desc1.strides[2] * x; + int in2_idx = in_idx2_y + desc2.strides[2] * x; + for (int c = 0; c < output_shape.Dims(3); ++c) { + auto out_idx = out_idx_x + c; + auto in1_val = input1_data[in1_idx]; + auto in2_val = input2_data[in2_idx]; + output_data[out_idx] = func(in1_val, in2_val); + in1_idx += desc1.strides[3]; + in2_idx += desc2.strides[3]; + } + } + } + } +} + +// R: Result type. T1: Input 1 type. T2: Input 2 type. +template +inline void BinaryFunction(const RuntimeShape& input1_shape, + const T1* input1_data, + const RuntimeShape& input2_shape, + const T2* input2_data, + const RuntimeShape& output_shape, R* output_data, + R (*func)(T1, T2)) { + const int flat_size = + MatchingFlatSize(input1_shape, input2_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = func(input1_data[i], input2_data[i]); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BINARY_FUNCTION_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/broadcast_args.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/broadcast_args.h new file mode 100644 index 000000000..d93c316d1 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/broadcast_args.h @@ -0,0 +1,56 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BROADCAST_ARGS_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BROADCAST_ARGS_H_ + +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +void BroadcastArgs(const RuntimeShape& input1_shape, const T* input1_data, + const RuntimeShape& input2_shape, const T* input2_data, + const RuntimeShape& output_shape, T* output_data) { + // Gets data at the backward index i of the shape tensor. Returns 1 if the + // index is out of range. + auto get_shape_data = [](const RuntimeShape& shape, const T* data, + int backward_idx) -> T { + int forward_idx = shape.FlatSize() - 1 - backward_idx; + if (forward_idx < 0) return 1; + return data[forward_idx]; + }; + + int output_num_elements = output_shape.FlatSize(); + for (int i = 0; i < output_num_elements; ++i) { + int backward_i = output_num_elements - 1 - i; + int shape1_i = get_shape_data(input1_shape, input1_data, i); + int shape2_i = get_shape_data(input2_shape, input2_data, i); + if (shape1_i == 1) { + output_data[backward_i] = shape2_i; + } else if (shape2_i == 1) { + output_data[backward_i] = shape1_i; + } else { + TFLITE_CHECK_EQ(shape1_i, shape2_i); + output_data[backward_i] = shape1_i; + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BROADCAST_ARGS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/broadcast_to.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/broadcast_to.h new file mode 100644 index 000000000..f106b2b52 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/broadcast_to.h @@ -0,0 +1,97 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BROADCAST_TO_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BROADCAST_TO_H_ + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/kernel_util.h" + +namespace tflite { +namespace reference_ops { +template +void BroadcastImpl(const NdArrayDesc& input_desc, const char* input_data, + const NdArrayDesc& output_desc, char* output_data, + int indexes[N], int dim, const int last_broadcasting_dim, + const int type_size) { + // Copy data from input to output. + if (dim == last_broadcasting_dim) { + int copy_size = output_desc.strides[dim] * type_size; + const char* data_src = + input_data + SubscriptToIndex(input_desc, indexes) * type_size; + char* data_dst = + output_data + SubscriptToIndex(output_desc, indexes) * type_size; + for (int i = 0; i < output_desc.extents[dim]; ++i, data_dst += copy_size) { + memcpy(data_dst, data_src, copy_size); + } + return; + } + + // Recursive call to find the next broadcasting. + for (indexes[dim] = 0; indexes[dim] < input_desc.extents[dim]; + ++indexes[dim]) { + BroadcastImpl(input_desc, input_data, output_desc, output_data, indexes, + dim + 1, last_broadcasting_dim, type_size); + } + + // Duplicate data in output tensor. + indexes[dim] = 0; + if (input_desc.extents[dim] != output_desc.extents[dim]) { + int copy_size = output_desc.strides[dim] * type_size; + char* data_src = + output_data + SubscriptToIndex(output_desc, indexes) * type_size; + char* data_dst = data_src + copy_size; + for (int i = 1; i < output_desc.extents[dim]; ++i, data_dst += copy_size) { + memcpy(data_dst, data_src, copy_size); + } + } +} + +template +inline void BroadcastTo(const RuntimeShape& unextended_input_shape, + const char* input_data, + const RuntimeShape& unextended_output_shape, + char* output_data, TfLiteType data_type) { + NdArrayDesc input_desc; + NdArrayDesc output_desc; + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, unextended_input_shape), + &input_desc); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, unextended_output_shape), + &output_desc); + + // Get the last dimension has broadcasting. At this dimension, the data is + // copied from input tensor to output tensor. + int last_broadcast_dim = -1; + for (int i = N - 1; i >= 0; --i) { + if (input_desc.extents[i] != output_desc.extents[i]) { + last_broadcast_dim = i; + break; + } + } + + // If non-broadcasting, just copy data from input to output tensor. + if (last_broadcast_dim == -1) { + memcpy(output_data, input_data, + unextended_input_shape.FlatSize() * TfLiteTypeGetSize(data_type)); + return; + } + + // Broadcasting using memcpy. + int indexes[N] = {0}; + BroadcastImpl(input_desc, input_data, output_desc, output_data, indexes, 0, + last_broadcast_dim, TfLiteTypeGetSize(data_type)); +} +} // namespace reference_ops +} // namespace tflite +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_BROADCAST_TO_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/ceil.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/ceil.h new file mode 100644 index 000000000..66d1dc359 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/ceil.h @@ -0,0 +1,37 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CEIL_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CEIL_H_ + +#include + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +inline void Ceil(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; ++i) { + output_data[i] = std::ceil(input_data[i]); + } +} + +} // namespace reference_ops +} // namespace tflite +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CEIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/comparisons.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/comparisons.h new file mode 100644 index 000000000..6344bdc72 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/comparisons.h @@ -0,0 +1,280 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_COMPARISONS_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_COMPARISONS_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +template +inline bool EqualFn(T lhs, T rhs) { + return lhs == rhs; +} + +template +inline bool NotEqualFn(T lhs, T rhs) { + return lhs != rhs; +} + +template +inline bool GreaterFn(T lhs, T rhs) { + return lhs > rhs; +} +template +inline bool GreaterEqualFn(T lhs, T rhs) { + return lhs >= rhs; +} +template +inline bool LessFn(T lhs, T rhs) { + return lhs < rhs; +} +template +inline bool LessEqualFn(T lhs, T rhs) { + return lhs <= rhs; +} + +template +using ComparisonFn = bool (*)(T, T); + +template F> +inline void ComparisonImpl( + const ComparisonParams& op_params, const RuntimeShape& input1_shape, + const T* input1_data, const RuntimeShape& input2_shape, + const T* input2_data, const RuntimeShape& output_shape, bool* output_data) { + const int64_t flatsize = + MatchingFlatSize(input1_shape, input2_shape, output_shape); + for (int64_t i = 0; i < flatsize; ++i) { + output_data[i] = F(input1_data[i], input2_data[i]); + } +} + +template F> +inline void Comparison(const ComparisonParams& op_params, + const RuntimeShape& input1_shape, + const float* input1_data, + const RuntimeShape& input2_shape, + const float* input2_data, + const RuntimeShape& output_shape, bool* output_data) { + ComparisonImpl(op_params, input1_shape, input1_data, input2_shape, + input2_data, output_shape, output_data); +} + +template F> +inline void ComparisonWithScaling( + const ComparisonParams& op_params, const RuntimeShape& input1_shape, + const T* input1_data, const RuntimeShape& input2_shape, + const T* input2_data, const RuntimeShape& output_shape, bool* output_data) { + int left_shift = op_params.left_shift; + int32_t input1_offset = op_params.input1_offset; + int32_t input1_multiplier = op_params.input1_multiplier; + int input1_shift = op_params.input1_shift; + int32_t input2_offset = op_params.input2_offset; + int32_t input2_multiplier = op_params.input2_multiplier; + int input2_shift = op_params.input2_shift; + + const int64_t flatsize = + MatchingFlatSize(input1_shape, input2_shape, output_shape); + for (int64_t i = 0; i < flatsize; ++i) { + const int32_t input1_val = input1_offset + input1_data[i]; + const int32_t input2_val = input2_offset + input2_data[i]; + const int32_t shifted_input1_val = input1_val * (1 << left_shift); + const int32_t shifted_input2_val = input2_val * (1 << left_shift); + const int32_t scaled_input1_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input1_val, input1_multiplier, input1_shift); + const int32_t scaled_input2_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input2_val, input2_multiplier, input2_shift); + output_data[i] = F(scaled_input1_val, scaled_input2_val); + } +} + +struct BroadcastComparison4DSlowCommon { + const RuntimeShape output_shape; + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; +}; + +inline BroadcastComparison4DSlowCommon BroadcastComparison4DSlowPreprocess( + const RuntimeShape& unextended_input1_shape, + const RuntimeShape& unextended_input2_shape, + const RuntimeShape& unextended_output_shape) { + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, + unextended_input2_shape, &desc1, &desc2); + return {RuntimeShape::ExtendedShape(4, unextended_output_shape), desc1, + desc2}; +} + +template F> +inline void BroadcastComparison4DSlowImpl( + const ComparisonParams& op_params, + const RuntimeShape& unextended_input1_shape, const T* input1_data, + const RuntimeShape& unextended_input2_shape, const T* input2_data, + const RuntimeShape& unextended_output_shape, bool* output_data) { + const BroadcastComparison4DSlowCommon dims = + BroadcastComparison4DSlowPreprocess(unextended_input1_shape, + unextended_input2_shape, + unextended_output_shape); + + for (int b = 0; b < dims.output_shape.Dims(0); ++b) { + for (int y = 0; y < dims.output_shape.Dims(1); ++y) { + for (int x = 0; x < dims.output_shape.Dims(2); ++x) { + for (int c = 0; c < dims.output_shape.Dims(3); ++c) { + output_data[Offset(dims.output_shape, b, y, x, c)] = + F(input1_data[SubscriptToIndex(dims.desc1, b, y, x, c)], + input2_data[SubscriptToIndex(dims.desc2, b, y, x, c)]); + } + } + } + } +} + +template F> +inline void BroadcastComparison4DSlow(const ComparisonParams& op_params, + const RuntimeShape& input1_shape, + const float* input1_data, + const RuntimeShape& input2_shape, + const float* input2_data, + const RuntimeShape& output_shape, + bool* output_data) { + BroadcastComparison4DSlowImpl(op_params, input1_shape, input1_data, + input2_shape, input2_data, + output_shape, output_data); +} + +template F> +inline void BroadcastComparison4DSlowWithScaling( + const ComparisonParams& op_params, + const RuntimeShape& unextended_input1_shape, const T* input1_data, + const RuntimeShape& unextended_input2_shape, const T* input2_data, + const RuntimeShape& unextended_output_shape, bool* output_data) { + const BroadcastComparison4DSlowCommon dims = + BroadcastComparison4DSlowPreprocess(unextended_input1_shape, + unextended_input2_shape, + unextended_output_shape); + + int left_shift = op_params.left_shift; + int32_t input1_offset = op_params.input1_offset; + int32_t input1_multiplier = op_params.input1_multiplier; + int input1_shift = op_params.input1_shift; + int32_t input2_offset = op_params.input2_offset; + int32_t input2_multiplier = op_params.input2_multiplier; + int input2_shift = op_params.input2_shift; + + for (int b = 0; b < dims.output_shape.Dims(0); ++b) { + for (int y = 0; y < dims.output_shape.Dims(1); ++y) { + for (int x = 0; x < dims.output_shape.Dims(2); ++x) { + for (int c = 0; c < dims.output_shape.Dims(3); ++c) { + const int32_t input1_val = + input1_offset + + input1_data[SubscriptToIndex(dims.desc1, b, y, x, c)]; + const int32_t input2_val = + input2_offset + + input2_data[SubscriptToIndex(dims.desc2, b, y, x, c)]; + const int32_t shifted_input1_val = input1_val * (1 << left_shift); + const int32_t shifted_input2_val = input2_val * (1 << left_shift); + const int32_t scaled_input1_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input1_val, input1_multiplier, input1_shift); + const int32_t scaled_input2_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input2_val, input2_multiplier, input2_shift); + output_data[Offset(dims.output_shape, b, y, x, c)] = + F(scaled_input1_val, scaled_input2_val); + } + } + } + } +} + +#define TFLITE_COMPARISON_OP(name) \ + inline void name(const ComparisonParams& op_params, \ + const RuntimeShape& input1_shape, const float* input1_data, \ + const RuntimeShape& input2_shape, const float* input2_data, \ + const RuntimeShape& output_shape, bool* output_data) { \ + Comparison(op_params, input1_shape, input1_data, input2_shape, \ + input2_data, output_shape, output_data); \ + } \ + template \ + inline void name##NoScaling( \ + const ComparisonParams& op_params, const RuntimeShape& input1_shape, \ + const T* input1_data, const RuntimeShape& input2_shape, \ + const T* input2_data, const RuntimeShape& output_shape, \ + bool* output_data) { \ + ComparisonImpl(op_params, input1_shape, input1_data, \ + input2_shape, input2_data, output_shape, \ + output_data); \ + } \ + template \ + inline void name##WithScaling( \ + const ComparisonParams& op_params, const RuntimeShape& input1_shape, \ + const T* input1_data, const RuntimeShape& input2_shape, \ + const T* input2_data, const RuntimeShape& output_shape, \ + bool* output_data) { \ + ComparisonWithScaling(op_params, input1_shape, input1_data, \ + input2_shape, input2_data, \ + output_shape, output_data); \ + } \ + template \ + inline void Broadcast4DSlow##name##NoScaling( \ + const ComparisonParams& op_params, const RuntimeShape& input1_shape, \ + const T* input1_data, const RuntimeShape& input2_shape, \ + const T* input2_data, const RuntimeShape& output_shape, \ + bool* output_data) { \ + BroadcastComparison4DSlowImpl( \ + op_params, input1_shape, input1_data, input2_shape, input2_data, \ + output_shape, output_data); \ + } \ + inline void Broadcast4DSlow##name( \ + const ComparisonParams& op_params, const RuntimeShape& input1_shape, \ + const float* input1_data, const RuntimeShape& input2_shape, \ + const float* input2_data, const RuntimeShape& output_shape, \ + bool* output_data) { \ + BroadcastComparison4DSlow(op_params, input1_shape, input1_data, \ + input2_shape, input2_data, \ + output_shape, output_data); \ + } \ + template \ + inline void Broadcast4DSlow##name##WithScaling( \ + const ComparisonParams& op_params, const RuntimeShape& input1_shape, \ + const T* input1_data, const RuntimeShape& input2_shape, \ + const T* input2_data, const RuntimeShape& output_shape, \ + bool* output_data) { \ + BroadcastComparison4DSlowWithScaling( \ + op_params, input1_shape, input1_data, input2_shape, input2_data, \ + output_shape, output_data); \ + } +TFLITE_COMPARISON_OP(Equal); +TFLITE_COMPARISON_OP(NotEqual); +TFLITE_COMPARISON_OP(Greater); +TFLITE_COMPARISON_OP(GreaterEqual); +TFLITE_COMPARISON_OP(Less); +TFLITE_COMPARISON_OP(LessEqual); +#undef TFLITE_COMPARISON_OP + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_COMPARISONS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/concatenation.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/concatenation.h new file mode 100644 index 000000000..9d2ecbecc --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/concatenation.h @@ -0,0 +1,141 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CONCATENATION_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CONCATENATION_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +inline void Concatenation(const ConcatenationParams& params, + const RuntimeShape* const* input_shapes, + const Scalar* const* input_data, + const RuntimeShape& output_shape, + Scalar* output_data) { + int axis = params.axis; + int inputs_count = params.inputs_count; + const int concat_dimensions = output_shape.DimensionsCount(); + TFLITE_DCHECK_LT(axis, concat_dimensions); + + int64_t concat_size = 0; + for (int i = 0; i < inputs_count; i++) { + TFLITE_DCHECK_EQ(input_shapes[i]->DimensionsCount(), concat_dimensions); + for (int j = 0; j < concat_dimensions; j++) { + if (j != axis) { + MatchingDim(*input_shapes[i], j, output_shape, j); + } + } + concat_size += input_shapes[i]->Dims(axis); + } + TFLITE_DCHECK_EQ(concat_size, output_shape.Dims(axis)); + int64_t outer_size = 1; + for (int i = 0; i < axis; ++i) { + outer_size *= output_shape.Dims(i); + } + // For all input arrays, + // FlatSize() = outer_size * Dims(axis) * base_inner_size; + int64_t base_inner_size = 1; + for (int i = axis + 1; i < concat_dimensions; ++i) { + base_inner_size *= output_shape.Dims(i); + } + + Scalar* output_ptr = output_data; + for (int k = 0; k < outer_size; k++) { + for (int i = 0; i < inputs_count; ++i) { + const int copy_size = input_shapes[i]->Dims(axis) * base_inner_size; + const Scalar* input_ptr = input_data[i] + k * copy_size; + memcpy(output_ptr, input_ptr, copy_size * sizeof(Scalar)); + output_ptr += copy_size; + } + } +} + +// TODO(b/174275780): The quantized implementation of concatentation isn't fully +// quantized as it takes scale as a floating point value. This should be fixed +// when optimizng this routine further. +inline void ConcatenationWithScaling(const ConcatenationParams& params, + const RuntimeShape* const* input_shapes, + const uint8_t* const* input_data, + const RuntimeShape& output_shape, + uint8_t* output_data) { + int axis = params.axis; + const int32_t* input_zeropoint = params.input_zeropoint; + const float* input_scale = params.input_scale; + int inputs_count = params.inputs_count; + const int32_t output_zeropoint = params.output_zeropoint; + const float output_scale = params.output_scale; + + const int concat_dimensions = output_shape.DimensionsCount(); + TFLITE_DCHECK_LT(axis, concat_dimensions); + + int64_t concat_size = 0; + for (int i = 0; i < inputs_count; i++) { + TFLITE_DCHECK_EQ(input_shapes[i]->DimensionsCount(), concat_dimensions); + for (int j = 0; j < concat_dimensions; j++) { + if (j != axis) { + MatchingDim(*input_shapes[i], j, output_shape, j); + } + } + concat_size += input_shapes[i]->Dims(axis); + } + TFLITE_DCHECK_EQ(concat_size, output_shape.Dims(axis)); + int64_t outer_size = 1; + for (int i = 0; i < axis; ++i) { + outer_size *= output_shape.Dims(i); + } + // For all input arrays, + // FlatSize() = outer_size * Dims(axis) * base_inner_size; + int64_t base_inner_size = 1; + for (int i = axis + 1; i < concat_dimensions; ++i) { + base_inner_size *= output_shape.Dims(i); + } + + const float inverse_output_scale = 1.f / output_scale; + uint8_t* output_ptr = output_data; + for (int k = 0; k < outer_size; k++) { + for (int i = 0; i < inputs_count; ++i) { + const int copy_size = input_shapes[i]->Dims(axis) * base_inner_size; + const uint8_t* input_ptr = input_data[i] + k * copy_size; + if (input_zeropoint[i] == output_zeropoint && + input_scale[i] == output_scale) { + memcpy(output_ptr, input_ptr, copy_size); + } else { + const float scale = input_scale[i] * inverse_output_scale; + const float bias = -input_zeropoint[i] * scale; + for (int j = 0; j < copy_size; ++j) { + const int32_t value = static_cast(tflite::TfLiteRound( + input_ptr[j] * scale + bias)) + + output_zeropoint; + output_ptr[j] = static_cast( + std::max(std::min(255, value), 0)); + } + } + output_ptr += copy_size; + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CONCATENATION_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/conv.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/conv.h new file mode 100644 index 000000000..3a53e06e7 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/conv.h @@ -0,0 +1,287 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CONV_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CONV_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +inline void Conv(const ConvParams& params, const RuntimeShape& input_shape, + const float* input_data, const RuntimeShape& filter_shape, + const float* filter_data, const RuntimeShape& bias_shape, + const float* bias_data, const RuntimeShape& output_shape, + float* output_data, const RuntimeShape& im2col_shape, + float* im2col_data) { + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const float output_activation_min = params.float_activation_min; + const float output_activation_max = params.float_activation_max; + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + + (void)im2col_data; // only used in optimized code. + (void)im2col_shape; // only used in optimized code. + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = input_shape.Dims(3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + if (bias_data) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int filter_input_depth = filter_shape.Dims(3); + const int groups = input_depth / filter_input_depth; + TFLITE_DCHECK_EQ(input_depth % filter_input_depth, 0); + const int filters_per_group = output_depth / groups; + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + const int in_y_origin = (out_y * stride_height) - pad_height; + for (int out_x = 0; out_x < output_width; ++out_x) { + const int in_x_origin = (out_x * stride_width) - pad_width; + for (int out_channel = 0; out_channel < output_depth; ++out_channel) { + auto group = out_channel / filters_per_group; + float total = 0.f; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + const int in_y = in_y_origin + dilation_height_factor * filter_y; + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = in_x_origin + dilation_width_factor * filter_x; + + // Zero padding by omitting the areas outside the image. + const bool is_point_inside_image = + (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height); + + if (!is_point_inside_image) { + continue; + } + for (int in_channel = 0; in_channel < filter_input_depth; + ++in_channel) { + float input_value = + input_data[Offset(input_shape, batch, in_y, in_x, + in_channel + group * filter_input_depth)]; + float filter_value = filter_data[Offset( + filter_shape, out_channel, filter_y, filter_x, in_channel)]; + total += (input_value * filter_value); + } + } + } + float bias_value = 0.0f; + if (bias_data) { + bias_value = bias_data[out_channel]; + } + output_data[Offset(output_shape, batch, out_y, out_x, out_channel)] = + ActivationFunctionWithMinMax(total + bias_value, + output_activation_min, + output_activation_max); + } + } + } + } +} + +inline void Conv(const ConvParams& params, const RuntimeShape& input_shape, + const uint8_t* input_data, const RuntimeShape& filter_shape, + const uint8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + uint8_t* output_data, const RuntimeShape& im2col_shape, + uint8_t* im2col_data, void* cpu_backend_context) { + (void)cpu_backend_context; // only used in optimized code. + (void)im2col_data; // only used in optimized code. + (void)im2col_shape; // only used in optimized code. + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const int32_t input_offset = params.input_offset; + const int32_t filter_offset = params.weights_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_multiplier = params.output_multiplier; + const int output_shift = params.output_shift; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = input_shape.Dims(3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + if (bias_data) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int filter_input_depth = filter_shape.Dims(3); + const int groups = input_depth / filter_input_depth; + TFLITE_DCHECK_EQ(input_depth % filter_input_depth, 0); + const int filters_per_group = output_depth / groups; + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + const int in_y_origin = (out_y * stride_height) - pad_height; + for (int out_x = 0; out_x < output_width; ++out_x) { + const int in_x_origin = (out_x * stride_width) - pad_width; + for (int out_channel = 0; out_channel < output_depth; ++out_channel) { + auto group = out_channel / filters_per_group; + int32_t acc = 0; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + const int in_y = in_y_origin + dilation_height_factor * filter_y; + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = in_x_origin + dilation_width_factor * filter_x; + + // Zero padding by omitting the areas outside the image. + const bool is_point_inside_image = + (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height); + + if (!is_point_inside_image) { + continue; + } + + for (int in_channel = 0; in_channel < filter_input_depth; + ++in_channel) { + int32_t input_val = + input_data[Offset(input_shape, batch, in_y, in_x, + in_channel + group * filter_input_depth)]; + int32_t filter_val = filter_data[Offset( + filter_shape, out_channel, filter_y, filter_x, in_channel)]; + acc += + (filter_val + filter_offset) * (input_val + input_offset); + } + } + } + if (bias_data) { + acc += bias_data[out_channel]; + } + acc = MultiplyByQuantizedMultiplier(acc, output_multiplier, + output_shift); + acc += output_offset; + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, out_channel)] = + static_cast(acc); + } + } + } + } +} + +inline void HybridConvPerChannel( + const ConvParams& params, float* scaling_factors_ptr, + const RuntimeShape& input_shape, const int8_t* input_data, + const RuntimeShape& filter_shape, const int8_t* filter_data, + const RuntimeShape& bias_shape, const float* bias_data, + const RuntimeShape& output_shape, float* output_data, + const RuntimeShape& im2col_shape, int8_t* im2col_data, + const float* per_channel_scale, int32_t* input_offset) { + (void)im2col_data; // only used in optimized code. + (void)im2col_shape; // only used in optimized code. + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const float output_activation_min = params.float_activation_min; + const float output_activation_max = params.float_activation_max; + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = input_shape.Dims(3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + if (bias_data) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int filter_input_depth = filter_shape.Dims(3); + const int groups = input_depth / filter_input_depth; + TFLITE_DCHECK_EQ(input_depth % filter_input_depth, 0); + const int filters_per_group = output_depth / groups; + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int out_channel = 0; out_channel < output_depth; ++out_channel) { + auto group = out_channel / filters_per_group; + const int in_x_origin = (out_x * stride_width) - pad_width; + const int in_y_origin = (out_y * stride_height) - pad_height; + int32_t acc = 0; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + for (int in_channel = 0; in_channel < filter_input_depth; + ++in_channel) { + const int in_x = in_x_origin + dilation_width_factor * filter_x; + const int in_y = + in_y_origin + dilation_height_factor * filter_y; + // If the location is outside the bounds of the input image, + // use zero as a default value. + if ((in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height)) { + int32_t input_val = input_data[Offset( + input_shape, batch, in_y, in_x, + in_channel + group * filter_input_depth)]; + int32_t filter_val = + filter_data[Offset(filter_shape, out_channel, filter_y, + filter_x, in_channel)]; + acc += filter_val * (input_val - input_offset[batch]); + } + } + } + } + float acc_float = + acc * per_channel_scale[out_channel] * scaling_factors_ptr[batch]; + if (bias_data) { + acc_float += bias_data[out_channel]; + } + output_data[Offset(output_shape, batch, out_y, out_x, out_channel)] = + ActivationFunctionWithMinMax(acc_float, output_activation_min, + output_activation_max); + } + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CONV_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/cumsum.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/cumsum.h new file mode 100644 index 000000000..7cbc87c08 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/cumsum.h @@ -0,0 +1,175 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CUMSUM_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CUMSUM_H_ + +#include +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" + +namespace tflite { +namespace reference_ops { + +template +inline void CumSum(const T* input_data, const RuntimeShape& shape, int32_t axis, + bool exclusive, bool reverse, T* output_data) { + const int32_t rank = shape.DimensionsCount(); + TFLITE_DCHECK_GE(rank, 1); + TFLITE_DCHECK_GE(axis, 0); + TFLITE_DCHECK_LT(axis, rank); + + size_t inner = 1; + size_t outer = 1; + size_t depth = 1; + for (int32_t i = 0; i < rank; i++) { + if (i < axis) + inner *= shape.Dims(i); + else if (i > axis) + outer *= shape.Dims(i); + else + depth = shape.Dims(i); + } + + for (size_t outer_index = 0; outer_index < outer; outer_index++) { + size_t outer_index_adj; + if (reverse) + outer_index_adj = (outer - 1) - outer_index; + else + outer_index_adj = outer_index; + for (size_t inner_index = 0; inner_index < inner; inner_index++) { + T accumulator = 0; + size_t inner_index_adj; + if (reverse) + inner_index_adj = (inner - 1) - inner_index; + else + inner_index_adj = inner_index; + for (size_t depth_index = 0; depth_index < depth; depth_index++) { + size_t depth_index_adj; + if (reverse) + depth_index_adj = (depth - 1) - depth_index; + else + depth_index_adj = depth_index; + + size_t index = outer_index_adj; + index += inner_index_adj * depth * outer; + index += depth_index_adj * outer; + + if (exclusive) { + output_data[index] = accumulator; + accumulator += input_data[index]; + } else { + accumulator += input_data[index]; + output_data[index] = accumulator; + } + } + } + } +} + +// +// Quantized INT8 CUMSUM +// +inline void CumSum(const ArithmeticParams& params, const int8_t* input_data, + const RuntimeShape& shape, int32_t axis, bool exclusive, + bool reverse, int8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + // Input offset is negative input zero point. Activation tensors are + // asymmetric quantized so they span the full int8 range. + // All inputs should have same zero-point and scale, this is checked during + // Prepare stage. + TFLITE_DCHECK_GE(-params.input1_offset, std::numeric_limits::min()); + TFLITE_DCHECK_LE(-params.input1_offset, std::numeric_limits::max()); + + const int32_t rank = shape.DimensionsCount(); + TFLITE_DCHECK_GE(rank, 1); + TFLITE_DCHECK_GE(axis, 0); + TFLITE_DCHECK_LT(axis, rank); + + size_t inner = 1; + size_t outer = 1; + size_t depth = 1; + for (int32_t i = 0; i < rank; i++) { + if (i < axis) + inner *= shape.Dims(i); + else if (i > axis) + outer *= shape.Dims(i); + else + depth = shape.Dims(i); + } + + for (size_t outer_index = 0; outer_index < outer; outer_index++) { + size_t outer_index_adj; + if (reverse) + outer_index_adj = (outer - 1) - outer_index; + else + outer_index_adj = outer_index; + for (size_t inner_index = 0; inner_index < inner; inner_index++) { + int32_t accumulator = params.input1_offset; // accumulator = 0 + accumulator *= (1 << params.left_shift); + accumulator = MultiplyByQuantizedMultiplierSmallerThanOneExp( + accumulator, params.input1_multiplier, params.input1_shift); + + size_t inner_index_adj; + if (reverse) + inner_index_adj = (inner - 1) - inner_index; + else + inner_index_adj = inner_index; + + for (size_t depth_index = 0; depth_index < depth; depth_index++) { + size_t depth_index_adj; + if (reverse) + depth_index_adj = (depth - 1) - depth_index; + else + depth_index_adj = depth_index; + + size_t index = outer_index_adj; + index += inner_index_adj * depth * outer; + index += depth_index_adj * outer; + + const int32_t y = params.input1_offset + input_data[index]; + const int32_t shifted_y = y * (1 << params.left_shift); + const int32_t scaled_y = MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_y, params.input1_multiplier, params.input1_shift); + + int32_t scaled_output; + if (exclusive) { + scaled_output = accumulator; + accumulator += scaled_y; + } else { + accumulator += scaled_y; + scaled_output = accumulator; + } + + const int32_t raw_output = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + scaled_output, params.output_multiplier, params.output_shift) + + params.output_offset; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + output_data[index] = static_cast(clamped_output); + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CUMSUM_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depth_to_space.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depth_to_space.h new file mode 100644 index 000000000..23cff2853 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depth_to_space.h @@ -0,0 +1,79 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEPTH_TO_SPACE_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEPTH_TO_SPACE_H_ + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +inline void DepthToSpace(const tflite::DepthToSpaceParams& op_params, + const RuntimeShape& unextended_input_shape, + const T* input_data, + const RuntimeShape& unextended_output_shape, + T* output_data) { + TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + const int input_depth = input_shape.Dims(3); + const int input_width = input_shape.Dims(2); + const int input_height = input_shape.Dims(1); + const int input_batch = input_shape.Dims(0); + + const int output_depth = output_shape.Dims(3); + const int output_width = output_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_batch = output_shape.Dims(0); + + const int32_t block_size = op_params.block_size; + + TFLITE_DCHECK_EQ(input_width * block_size, output_width); + TFLITE_DCHECK_EQ(input_height * block_size, output_height); + TFLITE_DCHECK_EQ(input_depth, output_depth * block_size * block_size); + TFLITE_DCHECK_EQ(input_batch, output_batch); + + for (int out_b = 0; out_b < output_batch; ++out_b) { + for (int out_h = 0; out_h < output_height; ++out_h) { + for (int out_w = 0; out_w < output_width; ++out_w) { + for (int out_d = 0; out_d < output_depth; ++out_d) { + const int in_d = + out_d + ((out_h % block_size) * block_size + out_w % block_size) * + output_depth; + + const int in_w = out_w / block_size; + const int in_h = out_h / block_size; + const int in_b = out_b; + + const int input_index = Offset(input_shape, in_b, in_h, in_w, in_d); + const int output_index = + Offset(output_shape, out_b, out_h, out_w, out_d); + + output_data[output_index] = input_data[input_index]; + } + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEPTH_TO_SPACE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h new file mode 100644 index 000000000..0cecb16b4 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h @@ -0,0 +1,100 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEPTHWISECONV_FLOAT_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEPTHWISECONV_FLOAT_H_ + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +inline void DepthwiseConv( + const DepthwiseParams& params, const RuntimeShape& input_shape, + const float* input_data, const RuntimeShape& filter_shape, + const float* filter_data, const RuntimeShape& bias_shape, + const float* bias_data, const RuntimeShape& output_shape, + float* output_data) { + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const int depth_multiplier = params.depth_multiplier; + const float output_activation_min = params.float_activation_min; + const float output_activation_max = params.float_activation_max; + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int output_depth = MatchingDim(filter_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int input_depth = input_shape.Dims(3); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + TFLITE_DCHECK_EQ(output_depth, input_depth * depth_multiplier); + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + + for (int b = 0; b < batches; ++b) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int ic = 0; ic < input_depth; ++ic) { + for (int m = 0; m < depth_multiplier; m++) { + const int oc = m + ic * depth_multiplier; + const int in_x_origin = (out_x * stride_width) - pad_width; + const int in_y_origin = (out_y * stride_height) - pad_height; + float total = 0.f; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = in_x_origin + dilation_width_factor * filter_x; + const int in_y = + in_y_origin + dilation_height_factor * filter_y; + // If the location is outside the bounds of the input image, + // use zero as a default value. + if ((in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height)) { + float input_value = + input_data[Offset(input_shape, b, in_y, in_x, ic)]; + float filter_value = filter_data[Offset( + filter_shape, 0, filter_y, filter_x, oc)]; + total += (input_value * filter_value); + } + } + } + float bias_value = 0.0f; + if (bias_data) { + bias_value = bias_data[oc]; + } + output_data[Offset(output_shape, b, out_y, out_x, oc)] = + ActivationFunctionWithMinMax(total + bias_value, + output_activation_min, + output_activation_max); + } + } + } + } + } +} + +} // end namespace reference_ops +} // end namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEPTHWISECONV_FLOAT_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depthwiseconv_uint8.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depthwiseconv_uint8.h new file mode 100644 index 000000000..bb51a39f0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/depthwiseconv_uint8.h @@ -0,0 +1,319 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEPTHWISECONV_UINT8_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEPTHWISECONV_UINT8_H_ + +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +// Used in tests and template parameters to control which version of depthwise +// convolution is called. Primarily for reference code, and specializations +// forced in tests. +enum class DepthwiseConvImplementation { + // Run all tests against kUseStandardEntry even if also testing another + // kernel, since we need to be sure that the main DepthwiseConv() function in + // optimized_ops.h dispatches to a correctly-executing kernel. + kNone = 0, // The "default" option: use the normal + // DepthwiseConv kernel (entry) function. + kUseGenericKernel, // Forced use of generic kernel. + kUseNeon3x3, // 3x3 kernel that uses NEON when available. + kUseNeon3x3DotProduct, // 3x3 kernel that uses dot-product enabled NEON + // when available. + kUseCModel3x3DotProduct, // 3x3 kernel, reference C model that is intended + // to match overall design NEON code. + kUseUnwound3x3DotProduct, // 3x3 kernel, reference C model with unwound loops + // and some arrays. + kUseIntrinsics3x3DotProduct, // 3x3 kernel using NEON intrinsics. +}; + +// Category of depthwise convolution output rounding. +enum class DepthwiseConvOutputRounding { + kNone = 0, // Invalid: specific method must be specified. + kAwayFromZero, // Original method: exact halves rounded away from zero. + kUpward, // Halves towards +infinity: adds 0.5 before truncate. + // This is where a future kNearestEven would be placed. +}; + +// Category of depthwise convolution depth multiplication. +enum class DepthwiseConvDepthMultiplication { + kNoMultiplication = 0, // Depth multiplier = 1. + kUnitInputDepth, // Input depth = 1, output depth = depth multiplier. +}; + +namespace reference_ops { +namespace depthwise_conv { + +template +inline int32_t DepthwiseConvRound(int32_t x, int32_t quantized_multiplier, + int shift) { + TFLITE_DCHECK_NE(output_rounding, DepthwiseConvOutputRounding::kNone); + return MultiplyByQuantizedMultiplier(x, quantized_multiplier, shift); +} + +// Single-rounding MultiplyByQuantizedMultiplier +#if TFLITE_SINGLE_ROUNDING +template <> +inline int32_t DepthwiseConvRound( + int32_t x, int32_t quantized_multiplier, int shift) { + using gemmlowp::RoundingDivideByPOT; + using gemmlowp::SaturatingRoundingDoublingHighMul; + int left_shift = shift > 0 ? shift : 0; + int right_shift = shift > 0 ? 0 : -shift; + return RoundingDivideByPOT(SaturatingRoundingDoublingHighMul( + x * (1 << left_shift), quantized_multiplier), + right_shift); +} + +template <> +inline int32_t DepthwiseConvRound( + int32_t x, int32_t quantized_multiplier, int shift) { + return MultiplyByQuantizedMultiplier(x, quantized_multiplier, shift); +} +// Double-rounding MultiplyByQuantizedMultiplier +#else +template <> +inline int32_t DepthwiseConvRound( + int32_t x, int32_t quantized_multiplier, int shift) { + return MultiplyByQuantizedMultiplier(x, quantized_multiplier, shift); +} + +template <> +inline int32_t DepthwiseConvRound( + int32_t x, int32_t quantized_multiplier, int shift) { + using gemmlowp::SaturatingRoundingDoublingHighMul; + const int left_shift = shift > 0 ? shift : 0; + const int right_shift = shift > 0 ? 0 : -shift; + const int rounding_offset = right_shift > 0 ? 1 << (right_shift - 1) : 0; + return (SaturatingRoundingDoublingHighMul(x * (1 << left_shift), + quantized_multiplier) + + rounding_offset) >> + right_shift; +} +#endif // TFLITE_SINGLE_ROUNDING + +template +struct DepthwiseConvBasicKernel { + static inline void Run( + const DepthwiseParams& params, const RuntimeShape& input_shape, + const uint8_t* input_data, const RuntimeShape& filter_shape, + const uint8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + uint8_t* output_data) { + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const int depth_multiplier = params.depth_multiplier; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + const int32_t input_offset = params.input_offset; + const int32_t filter_offset = params.weights_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_multiplier = params.output_multiplier; + const int output_shift = params.output_shift; + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int output_depth = MatchingDim(filter_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int input_depth = input_shape.Dims(3); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + TFLITE_DCHECK_EQ(output_depth, input_depth * depth_multiplier); + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + + for (int b = 0; b < batches; ++b) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int ic = 0; ic < input_depth; ++ic) { + for (int m = 0; m < depth_multiplier; m++) { + const int oc = m + ic * depth_multiplier; + const int in_x_origin = (out_x * stride_width) - pad_width; + const int in_y_origin = (out_y * stride_height) - pad_height; + int32_t acc = 0; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = + in_x_origin + dilation_width_factor * filter_x; + const int in_y = + in_y_origin + dilation_height_factor * filter_y; + // If the location is outside the bounds of the input image, + // use zero as a default value. + if ((in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height)) { + int32_t input_val = + input_data[Offset(input_shape, b, in_y, in_x, ic)]; + int32_t filter_val = filter_data[Offset( + filter_shape, 0, filter_y, filter_x, oc)]; + acc += (filter_val + filter_offset) * + (input_val + input_offset); + } + } + } + if (bias_data) { + acc += bias_data[oc]; + } + acc = DepthwiseConvRound(acc, output_multiplier, + output_shift); + acc += output_offset; + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_data[Offset(output_shape, b, out_y, out_x, oc)] = + static_cast(acc); + } + } + } + } + } + } + + // TODO(b/148596273): Reconcile reference versions, perhaps with common + // MultiplyByQuantizedMultiplier or DepthwiseConvRound function. + static inline void RunPerChannel( + const DepthwiseParams& params, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + int8_t* output_data) { + // Get parameters. + // TODO(b/141565753): Re-introduce ScopedProfilingLabel on Micro. + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const int depth_multiplier = params.depth_multiplier; + const int32_t input_offset = params.input_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + const int32_t* output_multiplier = params.output_multiplier_per_channel; + const int32_t* output_shift = params.output_shift_per_channel; + + // Check dimensions of the tensors. + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int output_depth = MatchingDim(filter_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int input_depth = input_shape.Dims(3); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + TFLITE_DCHECK_EQ(output_depth, input_depth * depth_multiplier); + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int in_channel = 0; in_channel < input_depth; ++in_channel) { + for (int m = 0; m < depth_multiplier; ++m) { + const int output_channel = m + in_channel * depth_multiplier; + const int in_x_origin = (out_x * stride_width) - pad_width; + const int in_y_origin = (out_y * stride_height) - pad_height; + int32_t acc = 0; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = + in_x_origin + dilation_width_factor * filter_x; + const int in_y = + in_y_origin + dilation_height_factor * filter_y; + // Zero padding by omitting the areas outside the image. + const bool is_point_inside_image = + (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height); + if (is_point_inside_image) { + int32_t input_val = input_data[Offset( + input_shape, batch, in_y, in_x, in_channel)]; + int32_t filter_val = filter_data[Offset( + filter_shape, 0, filter_y, filter_x, output_channel)]; + // Accumulate with 32 bits accumulator. + // In the nudging process during model quantization, we + // force real value of 0.0 be represented by a quantized + // value. This guarantees that the input_offset is a int8_t, + // even though it is represented using int32_t. int32_t += + // int8_t + // * (int8_t - int8_t) so the highest value we can get from + // each accumulation is [-127, 127] * ([-128, 127] - + // [-128, 127]), which is [-32512, 32512]. log2(32512) + // = 14.98, which means we can accumulate at least 2^16 + // multiplications without overflow. The accumulator is + // applied to a filter so the accumulation logic will hold + // as long as the filter size (filter_y * filter_x * + // in_channel) does not exceed 2^16, which is the case in + // all the models we have seen so far. + acc += filter_val * (input_val + input_offset); + } + } + } + if (bias_data) { + acc += bias_data[output_channel]; + } + acc = DepthwiseConvRound( + acc, output_multiplier[output_channel], + output_shift[output_channel]); + acc += output_offset; + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, + output_channel)] = static_cast(acc); + } + } + } + } + } + } +}; + +} // namespace depthwise_conv + +inline void DepthwiseConv( + const DepthwiseParams& params, const RuntimeShape& input_shape, + const uint8_t* input_data, const RuntimeShape& filter_shape, + const uint8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + uint8_t* output_data) { + return depthwise_conv::DepthwiseConvBasicKernel< + DepthwiseConvOutputRounding::kAwayFromZero>::Run(params, input_shape, + input_data, filter_shape, + filter_data, bias_shape, + bias_data, output_shape, + output_data); +} + +} // namespace reference_ops +} // end namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEPTHWISECONV_UINT8_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/dequantize.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/dequantize.h new file mode 100644 index 000000000..b90951f96 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/dequantize.h @@ -0,0 +1,78 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEQUANTIZE_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEQUANTIZE_H_ + +#include + +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +// Dequantizes into a float without rounding. +template +inline void Dequantize(const tflite::DequantizationParams& op_params, + const RuntimeShape& input_shape, + const InputT* input_data, + const RuntimeShape& output_shape, OutputT* output_data) { + int32_t zero_point = op_params.zero_point; + const double scale = op_params.scale; + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; i++) { + const int32_t val = input_data[i]; + const OutputT result = static_cast(scale * (val - zero_point)); + output_data[i] = result; + } +} + +// Dequantizes per-channel quantized tensor to float. +template +inline void PerChannelDequantize( + const tflite::PerChannelDequantizationParams& op_params, + const RuntimeShape& input_shape, const T* input_data, + const RuntimeShape& output_shape, float* output_data) { + // Ensure flat size is same. + MatchingFlatSize(input_shape, output_shape); + + const int32_t* zero_point = op_params.zero_point; + const float* scale = op_params.scale; + const int32_t quantized_dimension = op_params.quantized_dimension; + const int32_t num_dims = input_shape.DimensionsCount(); + const int32_t* dims_data = input_shape.DimsData(); + std::vector current_dim(num_dims, 0); + + do { + size_t offset = + ReducedOutputOffset(num_dims, reinterpret_cast(dims_data), + current_dim.data(), 0, nullptr); + const int channel = current_dim[quantized_dimension]; + const int32_t val = input_data[offset]; + const float result = + static_cast(scale[channel] * (val - zero_point[channel])); + output_data[offset] = result; + } while (NextIndex(num_dims, reinterpret_cast(dims_data), + current_dim.data())); +} + +} // namespace reference_ops + +} // namespace tflite +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DEQUANTIZE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/div.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/div.h new file mode 100644 index 000000000..df8da1b1a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/div.h @@ -0,0 +1,247 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DIV_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DIV_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { + +namespace reference_ops { + +template +inline void DivCheckArithmeticParams(const ArithmeticParams& params) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + // Input offset is negative input zero point. Activation tensors are + // asymmetric quantized so they span the full int8 range. + constexpr int32_t max_value = + static_cast(std::numeric_limits::max()); + TFLITE_DCHECK_GE(params.input1_offset, -max_value); + TFLITE_DCHECK_LE(params.input1_offset, max_value); + TFLITE_DCHECK_GE(params.input2_offset, -max_value); + TFLITE_DCHECK_LE(params.input2_offset, max_value); + TFLITE_DCHECK_GE(params.output_offset, -max_value); + TFLITE_DCHECK_LE(params.output_offset, max_value); +} + +// Element-wise div that can often be used for inner loop of broadcast Div as +// well as the non-broadcast Div. +template +inline void DivElementwise(int size, const ArithmeticParams& params, + const T* input1_data, const T* input2_data, + T* output_data) { + DivCheckArithmeticParams(params); + + for (int i = 0; i < size; ++i) { + int32_t input1_val = params.input1_offset + input1_data[i]; + int32_t input2_val = params.input2_offset + input2_data[i]; + TFLITE_DCHECK_NE(input2_val, 0); + if (input2_val < 0) { + // Invert signs to avoid a negative input2_val as input2_inv needs to be + // positive to be used as multiplier of MultiplyByQuantizedMultiplier. + input1_val = -input1_val; + input2_val = -input2_val; + } + int recip_shift; + const int32_t input2_inv = GetReciprocal(input2_val, 31, &recip_shift); + const int headroom = CountLeadingSignBits(input1_val); + const int32_t unscaled_quotient = + MultiplyByQuantizedMultiplierGreaterThanOne(input1_val, input2_inv, + headroom); + const int total_shift = params.output_shift - recip_shift - headroom; + const int32_t unclamped_result = + params.output_offset + + MultiplyByQuantizedMultiplierSmallerThanOneExp( + unscaled_quotient, params.output_multiplier, total_shift); + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, unclamped_result)); + output_data[i] = static_cast(clamped_output); + } +} + +inline void Div(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const uint8_t* input1_data, + const RuntimeShape& input2_shape, const uint8_t* input2_data, + const RuntimeShape& output_shape, uint8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + DivElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +inline void Div(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const int8_t* input1_data, + const RuntimeShape& input2_shape, const int8_t* input2_data, + const RuntimeShape& output_shape, int8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + DivElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +template +inline void BroadcastDivSlowQuantized( + const ArithmeticParams& params, const RuntimeShape& unextended_input1_shape, + const T* input1_data, const RuntimeShape& unextended_input2_shape, + const T* input2_data, const RuntimeShape& unextended_output_shape, + T* output_data) { + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), N); + + NdArrayDesc desc1; + NdArrayDesc desc2; + NdArrayDesc output_desc; + NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, + unextended_input2_shape, &desc1, &desc2); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, unextended_output_shape), + &output_desc); + + DivCheckArithmeticParams(params); + + auto div_func = [&](int indexes[N]) { + int32_t input1_val = + params.input1_offset + input1_data[SubscriptToIndex(desc1, indexes)]; + int32_t input2_val = + params.input2_offset + input2_data[SubscriptToIndex(desc2, indexes)]; + TFLITE_DCHECK_NE(input2_val, 0); + if (input2_val < 0) { + // Invert signs to avoid a negative input2_val as input2_inv needs to be + // positive to be used as multiplier of MultiplyByQuantizedMultiplier. + input1_val = -input1_val; + input2_val = -input2_val; + } + int recip_shift; + const int32_t input2_inv = GetReciprocal(input2_val, 31, &recip_shift); + const int headroom = CountLeadingSignBits(input1_val); + const int32_t unscaled_quotient = + MultiplyByQuantizedMultiplierGreaterThanOne(input1_val, input2_inv, + headroom); + const int total_shift = params.output_shift - recip_shift - headroom; + const int32_t unclamped_result = + params.output_offset + + MultiplyByQuantizedMultiplierSmallerThanOneExp( + unscaled_quotient, params.output_multiplier, total_shift); + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, unclamped_result)); + output_data[SubscriptToIndex(output_desc, indexes)] = + static_cast(clamped_output); + }; + NDOpsHelper(output_desc, div_func); +} + +template +inline void BroadcastDivSlow(const ArithmeticParams& params, + const RuntimeShape& unextended_input1_shape, + const uint8_t* input1_data, + const RuntimeShape& unextended_input2_shape, + const uint8_t* input2_data, + const RuntimeShape& unextended_output_shape, + uint8_t* output_data) { + BroadcastDivSlowQuantized( + params, unextended_input1_shape, input1_data, unextended_input2_shape, + input2_data, unextended_output_shape, output_data); +} + +template +inline void BroadcastDivSlow(const ArithmeticParams& params, + const RuntimeShape& unextended_input1_shape, + const int8_t* input1_data, + const RuntimeShape& unextended_input2_shape, + const int8_t* input2_data, + const RuntimeShape& unextended_output_shape, + int8_t* output_data) { + BroadcastDivSlowQuantized( + params, unextended_input1_shape, input1_data, unextended_input2_shape, + input2_data, unextended_output_shape, output_data); +} + +// TODO(jiawen): We can implement BroadcastDiv on buffers of arbitrary +// dimensionality if the runtime code does a single loop over one dimension +// that handles broadcasting as the base case. The code generator would then +// generate max(D1, D2) nested for loops. +template +void BroadcastDivSlow(const ArithmeticParams& params, + const RuntimeShape& unextended_input1_shape, + const T* input1_data, + const RuntimeShape& unextended_input2_shape, + const T* input2_data, + const RuntimeShape& unextended_output_shape, + T* output_data) { + T output_activation_min; + T output_activation_max; + GetActivationParams(params, &output_activation_min, &output_activation_max); + + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), N); + + NdArrayDesc desc1; + NdArrayDesc desc2; + NdArrayDesc output_desc; + NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, + unextended_input2_shape, &desc1, &desc2); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, unextended_output_shape), + &output_desc); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest + // stride, typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + + auto div_func = [&](int indexes[N]) { + output_data[SubscriptToIndex(output_desc, indexes)] = + ActivationFunctionWithMinMax( + input1_data[SubscriptToIndex(desc1, indexes)] / + input2_data[SubscriptToIndex(desc2, indexes)], + output_activation_min, output_activation_max); + }; + NDOpsHelper(output_desc, div_func); +} + +template +inline void Div(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const T* input1_data, + const RuntimeShape& input2_shape, const T* input2_data, + const RuntimeShape& output_shape, T* output_data) { + T output_activation_min; + T output_activation_max; + GetActivationParams(params, &output_activation_min, &output_activation_max); + + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = ActivationFunctionWithMinMax( + input1_data[i] / input2_data[i], output_activation_min, + output_activation_max); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_DIV_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/elu.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/elu.h new file mode 100644 index 000000000..3dc935898 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/elu.h @@ -0,0 +1,37 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ELU_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ELU_H_ + +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +inline void Elu(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + const float val = input_data[i]; + output_data[i] = val < 0.0f ? TfLiteExpm1(val) : val; + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ELU_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/exp.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/exp.h new file mode 100644 index 000000000..9b33bf15b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/exp.h @@ -0,0 +1,38 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_EXP_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_EXP_H_ + +#include + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +inline void Exp(const T* input_data, const size_t num_elements, + T* output_data) { + ruy::profiler::ScopeLabel label("Exp"); + for (size_t idx = 0; idx < num_elements; ++idx) { + output_data[idx] = std::exp(input_data[idx]); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_EXP_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/fill.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/fill.h new file mode 100644 index 000000000..16630e617 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/fill.h @@ -0,0 +1,38 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FILL_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FILL_H_ + +#include + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +void Fill(const RuntimeShape& value_shape, const T* value_data, + const RuntimeShape& output_shape, T* output_data) { + TFLITE_DCHECK_EQ(value_shape.DimensionsCount(), 0); + const int flat_size = output_shape.FlatSize(); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = *value_data; + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FILL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor.h new file mode 100644 index 000000000..0693fd429 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor.h @@ -0,0 +1,39 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FLOOR_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FLOOR_H_ + +#include + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +inline void Floor(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; i++) { + int offset = i; + output_data[offset] = std::floor(input_data[offset]); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FLOOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor_div.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor_div.h new file mode 100644 index 000000000..e75d473cf --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor_div.h @@ -0,0 +1,35 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FLOOR_DIV_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FLOOR_DIV_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +T FloorDiv(T input1, T input2) { + return std::floor(std::divides()(static_cast(input1), + static_cast(input2))); +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FLOOR_DIV_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor_mod.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor_mod.h new file mode 100644 index 000000000..20ce18b73 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/floor_mod.h @@ -0,0 +1,44 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FLOOR_MOD_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FLOOR_MOD_H_ + +#include +#include + +namespace tflite { + +namespace reference_ops { + +template +T FloorMod(T input1, T input2) { + struct FloatMod { + float operator()(const float lhs, const float rhs) const { + return std::fmod(lhs, rhs); + } + }; + using ModFunc = typename std::conditional::value, + std::modulus, FloatMod>::type; + ModFunc mod_func; + T trunc_mod = mod_func(input1, input2); + return (trunc_mod != 0) && ((input2 < 0) != (trunc_mod < 0)) + ? (trunc_mod + input2) + : trunc_mod; +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FLOOR_MOD_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/fully_connected.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/fully_connected.h new file mode 100644 index 000000000..cd67828d3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/fully_connected.h @@ -0,0 +1,323 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FULLY_CONNECTED_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FULLY_CONNECTED_H_ + +#include + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +inline void FullyConnected( + const FullyConnectedParams& params, const RuntimeShape& input_shape, + const float* input_data, const RuntimeShape& weights_shape, + const float* weights_data, const RuntimeShape& bias_shape, + const float* bias_data, const RuntimeShape& output_shape, + float* output_data) { + const float output_activation_min = params.float_activation_min; + const float output_activation_max = params.float_activation_max; + // TODO(b/62193649): This really should be: + // const int batches = ArraySize(output_dims, 1); + // but the current --variable_batch hack consists in overwriting the 3rd + // dimension with the runtime batch size, as we don't keep track for each + // array of which dimension is the batch dimension in it. + const int output_dims_count = output_shape.DimensionsCount(); + const int weights_dims_count = weights_shape.DimensionsCount(); + const int batches = FlatSizeSkipDim(output_shape, output_dims_count - 1); + const int output_depth = MatchingDim(weights_shape, weights_dims_count - 2, + output_shape, output_dims_count - 1); + const int accum_depth = weights_shape.Dims(weights_dims_count - 1); + for (int b = 0; b < batches; ++b) { + for (int out_c = 0; out_c < output_depth; ++out_c) { + float total = 0.f; + for (int d = 0; d < accum_depth; ++d) { + total += input_data[b * accum_depth + d] * + weights_data[out_c * accum_depth + d]; + } + float bias_value = 0.0f; + if (bias_data) { + bias_value = bias_data[out_c]; + } + output_data[out_c + output_depth * b] = ActivationFunctionWithMinMax( + total + bias_value, output_activation_min, output_activation_max); + } + } +} + +inline void FullyConnected( + const FullyConnectedParams& params, const RuntimeShape& input_shape, + const uint8_t* input_data, const RuntimeShape& filter_shape, + const uint8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + uint8_t* output_data) { + const int32_t input_offset = params.input_offset; + const int32_t filter_offset = params.weights_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_multiplier = params.output_multiplier; + const int output_shift = params.output_shift; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_GE(filter_shape.DimensionsCount(), 2); + TFLITE_DCHECK_GE(output_shape.DimensionsCount(), 1); + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + // TODO(b/62193649): This really should be: + // const int batches = ArraySize(output_dims, 1); + // but the current --variable_batch hack consists in overwriting the 3rd + // dimension with the runtime batch size, as we don't keep track for each + // array of which dimension is the batch dimension in it. + const int output_dim_count = output_shape.DimensionsCount(); + const int filter_dim_count = filter_shape.DimensionsCount(); + const int batches = FlatSizeSkipDim(output_shape, output_dim_count - 1); + const int output_depth = MatchingDim(filter_shape, filter_dim_count - 2, + output_shape, output_dim_count - 1); + const int accum_depth = filter_shape.Dims(filter_dim_count - 1); + for (int b = 0; b < batches; ++b) { + for (int out_c = 0; out_c < output_depth; ++out_c) { + int32_t acc = 0; + for (int d = 0; d < accum_depth; ++d) { + int32_t input_val = input_data[b * accum_depth + d]; + int32_t filter_val = filter_data[out_c * accum_depth + d]; + acc += (filter_val + filter_offset) * (input_val + input_offset); + } + if (bias_data) { + acc += bias_data[out_c]; + } + acc = MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift); + acc += output_offset; + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_data[out_c + output_depth * b] = static_cast(acc); + } + } +} + +inline void FullyConnected( + const FullyConnectedParams& params, const RuntimeShape& input_shape, + const uint8_t* input_data, const RuntimeShape& filter_shape, + const uint8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + int16_t* output_data) { + const int32_t input_offset = params.input_offset; + const int32_t filter_offset = params.weights_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_multiplier = params.output_multiplier; + const int output_shift = params.output_shift; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + TFLITE_DCHECK_EQ(output_offset, 0); + // TODO(b/62193649): This really should be: + // const int batches = ArraySize(output_dims, 1); + // but the current --variable_batch hack consists in overwriting the 3rd + // dimension with the runtime batch size, as we don't keep track for each + // array of which dimension is the batch dimension in it. + const int output_dim_count = output_shape.DimensionsCount(); + const int filter_dim_count = filter_shape.DimensionsCount(); + const int batches = FlatSizeSkipDim(output_shape, output_dim_count - 1); + const int output_depth = MatchingDim(filter_shape, filter_dim_count - 2, + output_shape, output_dim_count - 1); + const int accum_depth = filter_shape.Dims(filter_dim_count - 1); + for (int b = 0; b < batches; ++b) { + for (int out_c = 0; out_c < output_depth; ++out_c) { + // Internal accumulation. + // Initialize accumulator with the bias-value. + int32_t accum = bias_data[out_c]; + // Accumulation loop. + for (int d = 0; d < accum_depth; ++d) { + int16_t input_val = input_data[b * accum_depth + d] + input_offset; + int16_t filter_val = + filter_data[out_c * accum_depth + d] + filter_offset; + accum += filter_val * input_val; + } + // Down-scale the final int32_t accumulator to the scale used by our + // (16-bit, typically 3 integer bits) fixed-point format. The quantized + // multiplier and shift here have been pre-computed offline + // (e.g. by toco). + accum = + MultiplyByQuantizedMultiplier(accum, output_multiplier, output_shift); + // Saturate, cast to int16_t, and store to output array. + accum = std::max(accum, output_activation_min - output_offset); + accum = std::min(accum, output_activation_max - output_offset); + accum += output_offset; + output_data[out_c + output_depth * b] = accum; + } + } +} + +inline void ShuffledFullyConnected( + const FullyConnectedParams& params, const RuntimeShape& input_shape, + const uint8_t* input_data, const RuntimeShape& weights_shape, + const uint8_t* shuffled_weights_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + int16_t* output_data, uint8_t* shuffled_input_workspace_data) { + const int32_t output_multiplier = params.output_multiplier; + const int output_shift = params.output_shift; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + + TFLITE_DCHECK_GE(input_shape.DimensionsCount(), 1); + TFLITE_DCHECK_GE(weights_shape.DimensionsCount(), 2); + TFLITE_DCHECK_GE(output_shape.DimensionsCount(), 1); + // TODO(b/62193649): This really should be: + // const int batches = ArraySize(output_dims, 1); + // but the current --variable_batch hack consists in overwriting the 3rd + // dimension with the runtime batch size, as we don't keep track for each + // array of which dimension is the batch dimension in it. + const int output_dim_count = output_shape.DimensionsCount(); + const int weights_dim_count = weights_shape.DimensionsCount(); + const int batches = FlatSizeSkipDim(output_shape, output_dim_count - 1); + const int output_depth = MatchingDim(weights_shape, weights_dim_count - 2, + output_shape, output_dim_count - 1); + const int accum_depth = weights_shape.Dims(weights_dim_count - 1); + TFLITE_DCHECK((accum_depth % 16) == 0); + TFLITE_DCHECK((output_depth % 4) == 0); + + // Shuffling and xoring of input activations into the workspace buffer + uint8_t* shuffled_input_workspace_ptr = shuffled_input_workspace_data; + if (batches == 1) { + for (int i = 0; i < accum_depth; i++) { + shuffled_input_workspace_data[i] = input_data[i] ^ 0x80; + } + } else if (batches == 4) { + for (int c = 0; c < accum_depth; c += 16) { + for (int b = 0; b < 4; b++) { + const uint8_t* src_data_ptr = input_data + b * accum_depth + c; + for (int j = 0; j < 16; j++) { + uint8_t src_val = *src_data_ptr++; + // Flip the sign bit, so that the kernel will only need to + // reinterpret these uint8_t values as int8_t, getting for free the + // subtraction of the zero_point value 128. + uint8_t dst_val = src_val ^ 0x80; + *shuffled_input_workspace_ptr++ = dst_val; + } + } + } + } else { + TFLITE_DCHECK(false); + return; + } + + // Actual computation + if (batches == 1) { + int16_t* output_ptr = output_data; + // Shuffled weights have had their sign bit (0x80) pre-flipped (xor'd) + // so that just reinterpreting them as int8_t values is equivalent to + // subtracting 128 from them, thus implementing for free the subtraction of + // the zero_point value 128. + const int8_t* shuffled_weights_ptr = + reinterpret_cast(shuffled_weights_data); + // Likewise, we preshuffled and pre-xored the input data above. + const int8_t* shuffled_input_data = + reinterpret_cast(shuffled_input_workspace_data); + for (int c = 0; c < output_depth; c += 4) { + // Internal accumulation. + // Initialize accumulator with the bias-value. + int32_t accum[4] = {0}; + // Accumulation loop. + for (int d = 0; d < accum_depth; d += 16) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 16; j++) { + int8_t input_val = shuffled_input_data[d + j]; + int8_t weights_val = *shuffled_weights_ptr++; + accum[i] += weights_val * input_val; + } + } + } + for (int i = 0; i < 4; i++) { + // Add bias value + int32_t acc = accum[i] + bias_data[c + i]; + // Down-scale the final int32_t accumulator to the scale used by our + // (16-bit, typically 3 integer bits) fixed-point format. The quantized + // multiplier and shift here have been pre-computed offline + // (e.g. by toco). + acc = + MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift); + // Saturate, cast to int16_t, and store to output array. + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_ptr[c + i] = acc; + } + } + } else if (batches == 4) { + int16_t* output_ptr = output_data; + // Shuffled weights have had their sign bit (0x80) pre-flipped (xor'd) + // so that just reinterpreting them as int8_t values is equivalent to + // subtracting 128 from them, thus implementing for free the subtraction of + // the zero_point value 128. + const int8_t* shuffled_weights_ptr = + reinterpret_cast(shuffled_weights_data); + // Likewise, we preshuffled and pre-xored the input data above. + const int8_t* shuffled_input_data = + reinterpret_cast(shuffled_input_workspace_data); + for (int c = 0; c < output_depth; c += 4) { + const int8_t* shuffled_input_ptr = shuffled_input_data; + // Accumulation loop. + // Internal accumulation. + // Initialize accumulator with the bias-value. + int32_t accum[4][4]; + for (int i = 0; i < 4; i++) { + for (int b = 0; b < 4; b++) { + accum[i][b] = 0; + } + } + for (int d = 0; d < accum_depth; d += 16) { + for (int i = 0; i < 4; i++) { + for (int b = 0; b < 4; b++) { + for (int j = 0; j < 16; j++) { + int8_t input_val = shuffled_input_ptr[16 * b + j]; + int8_t weights_val = shuffled_weights_ptr[16 * i + j]; + accum[i][b] += weights_val * input_val; + } + } + } + shuffled_input_ptr += 64; + shuffled_weights_ptr += 64; + } + for (int i = 0; i < 4; i++) { + for (int b = 0; b < 4; b++) { + // Add bias value + int32_t acc = accum[i][b] + bias_data[c + i]; + // Down-scale the final int32_t accumulator to the scale used by our + // (16-bit, typically 3 integer bits) fixed-point format. The + // quantized multiplier and shift here have been pre-computed offline + // (e.g. by toco). + acc = MultiplyByQuantizedMultiplier(acc, output_multiplier, + output_shift); + // Saturate, cast to int16_t, and store to output array. + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_ptr[b * output_depth + c + i] = acc; + } + } + } + } else { + TFLITE_DCHECK(false); + return; + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_FULLY_CONNECTED_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/hard_swish.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/hard_swish.h new file mode 100644 index 000000000..40504f9bb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/hard_swish.h @@ -0,0 +1,168 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_HARD_SWISH_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_HARD_SWISH_H_ + +#include + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +inline int16_t SaturatingLeftShift(int16_t value, int amount) { + int64_t result = static_cast(value) * (1 << amount); + result = std::min(result, std::numeric_limits::max()); + result = std::max(result, std::numeric_limits::min()); + return result; +} + +// Similar to ARM instruction SQDMULH. +// Similar to gemmlowp::SaturatingRoundingDoublingHighMul except +// rounding to zero instead of to nearest (SQRDMULH). +inline std::int16_t SaturatingDoublingHighMul(std::int16_t a, std::int16_t b) { + bool overflow = a == b && a == std::numeric_limits::min(); + std::int32_t a_32(a); + std::int32_t b_32(b); + std::int32_t ab_32 = a_32 * b_32; + std::int16_t ab_x2_high16 = static_cast((ab_32) / (1 << 15)); + return overflow ? std::numeric_limits::max() : ab_x2_high16; +} + +template +inline void HardSwish(const RuntimeShape& input_shape, const T* input_data, + const RuntimeShape& output_shape, T* output_data) { + ruy::profiler::ScopeLabel label("ReferenceHardSwish/Float"); + auto matching_size = MatchingFlatSize(input_shape, output_shape); + const T* in_end = input_data + matching_size; + for (; input_data < in_end; input_data++, output_data++) { + const float in = *input_data; + *output_data = + in * std::min(static_cast(6), std::max(static_cast(0), in + 3)) / + 6; + } +} + +template +inline void HardSwish(const HardSwishParams& params, + const RuntimeShape& input_shape, const T* input_data, + const RuntimeShape& output_shape, T* output_data) { + ruy::profiler::ScopeLabel label("ReferenceHardSwish/Quantized"); + + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; i++) { + const int16_t input_value = input_data[i] - params.input_zero_point; + // Left-shift as much as we can without overflow/saturation to put + // significant bits in the high bits of our 16-bit fixedpoint values, so + // that fixed-point approximate computations below are as accurate as + // possible. + const int16_t input_value_on_hires_input_scale = input_value * (1 << 7); + // Compute the input value on essentially the output scale, just not + // right-shifted yet. This is the value that we'll use in the (x >= +3) + // case, and that in the general case we'll multiply against the "relu-ish" + // fixed-point multiplier in [0, 1]. + const int16_t input_value_on_preshift_output_scale = + gemmlowp::SaturatingRoundingDoublingHighMul( + input_value_on_hires_input_scale, + params.output_multiplier_fixedpoint_int16); + // Now compute the "relu-ish multiplier". In the (-3 <= x <= +3) case, that + // is just an affine rescaling of x from [-3, 3] to [0, 1]. In the general + // case, it is just that plus saturation at the boundaries of [-3, 3]. + // First, we rescale from [-3, 3] to [-1, 1], saturating. + // That is done by rescaling the input value with a fixed-point multiplier + // (reluish_multiplier_fixedpoint) and bit-shift such that we represent + // that input value on the scale where the real value 3.0f is represented + // by the quantized value 32768. (+32768 is actually not representable as + // int16_t, so this saturates at +32767, and that is seen empirically to be + // a negligible contribution to numerical error/bias). + // + // This code is careful to correctly implement any magnitude of multiplier, + // involving either a right shift or a left shift, with correct saturation + // behavior in the left-shift case. This forces this code to be more + // complicated, but is necessary for real applications: a partially + // trained quantized MobileNet v3-small model that motivated this code + // exhibits some large [min, max] range boundaries, of the order of + // magnitude of 10 or 100 depending on layers. + // + // The next few lines are basically just an ordinary + // MultiplyByQuantizedMultiplier, except that we are more careful here + // about the fine details of saturation when left-shifting, because here + // overflow in left-shift is a common case, not an anomaly as + // MultiplyByQuantizedMultiplier assumes. + int16_t reluish_value = input_value_on_hires_input_scale; + // Shift left, saturating, as much as we can while ensuring that this + // saturation will not contribute to the result. That is, left shift amount + // reduced by 1. + if (params.reluish_multiplier_exponent > 0) { + reluish_value = SaturatingLeftShift( + reluish_value, params.reluish_multiplier_exponent - 1); + } + // Apply the fixed-point multiplier, dividing the value by a divisor + // ranging in [1, 2]. + reluish_value = gemmlowp::SaturatingRoundingDoublingHighMul( + reluish_value, params.reluish_multiplier_fixedpoint_int16); + // Apply the last bit of left-shift. Thus, in the left-shifting case, if + // any saturation affects the result, it is happening here --- any + // saturation having occurred above is overwritten here, not affecting the + // result. + if (params.reluish_multiplier_exponent > 0) { + reluish_value = SaturatingLeftShift(reluish_value, 1); + } + // Shift right, in the right-shifting case. + if (params.reluish_multiplier_exponent < 0) { + reluish_value = gemmlowp::RoundingDivideByPOT( + reluish_value, -params.reluish_multiplier_exponent); + } + // At this point we have rescaled the value into a 16bit fixedpoint + // reluish_value in [-1, 1]. + // We now convert that to a 16bit fixedpoint value in [0, 1]. + reluish_value = (reluish_value + (1 << 15)) >> 1; + // Use of SaturatingDoublingHighMul here is important to cancel the biases + // from the above SaturatingRoundingDoublingHighMul. + // + // On a partially trained MobileNet-v3-small, + // + // | bias on | ImageNet + // | quantized | Top-1 + // Operation used here | values | accuracy (50k) + // --------------------------------------+------------+----------- + // SaturatingDoublingHighMul | -0.0024 | 58.920 + // SaturatingRoundingDoublingHighMul | -0.0067 | 58.064 + // + // In activations_test, this is covered by this testcase: + // QuantizedActivationsOpTest.HardSwishBias + // + const int16_t preshift_output_value = SaturatingDoublingHighMul( + reluish_value, input_value_on_preshift_output_scale); + // We were so far operating on the pre-shift output scale. Now we finally + // apply that output shift, arriving at the final output scale. + int16_t output_value = gemmlowp::RoundingDivideByPOT( + preshift_output_value, -params.output_multiplier_exponent); + output_value += params.output_zero_point; + output_value = + std::min(output_value, std::numeric_limits::max()); + output_value = + std::max(output_value, std::numeric_limits::min()); + output_data[i] = output_value; + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_HARD_SWISH_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/add.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/add.h new file mode 100644 index 000000000..8d9b318cc --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/add.h @@ -0,0 +1,145 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_ADD_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_ADD_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_integer_ops { + +inline void CheckArithmeticParams(const ArithmeticParams& params) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + // Input offset is negative input zero point. Activation tensors are + // asymmetric quantized so they span the full int8 range. + TFLITE_DCHECK_GE(-params.input1_offset, std::numeric_limits::min()); + TFLITE_DCHECK_GE(-params.input2_offset, std::numeric_limits::min()); + TFLITE_DCHECK_LE(-params.input1_offset, std::numeric_limits::max()); + TFLITE_DCHECK_LE(-params.input2_offset, std::numeric_limits::max()); +} + +inline void ElementWise( + int size, const ArithmeticParams& params, const int8_t* input1_data, + const int8_t* input2_data, int8_t* output_data, + void (*check_arithmetic_params)(const ArithmeticParams&), + int8_t (*binary_func)(int8_t, int8_t, const ArithmeticParams&)) { + CheckArithmeticParams(params); + for (int i = 0; i < size; ++i) { + output_data[i] = binary_func(input1_data[i], input2_data[i], params); + } +} + +inline void BroadcastBinaryFunction4DSlow( + const ArithmeticParams& params, const RuntimeShape& input1_shape, + const int8_t* input1_data, const RuntimeShape& input2_shape, + const int8_t* input2_data, const RuntimeShape& output_shape, + int8_t* output_data, + void (*check_arithmetic_params)(const ArithmeticParams&), + int8_t (*binary_func)(int8_t, int8_t, const ArithmeticParams&)) { + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + const RuntimeShape extended_output_shape = + RuntimeShape::ExtendedShape(4, output_shape); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + for (int b = 0; b < extended_output_shape.Dims(0); ++b) { + for (int y = 0; y < extended_output_shape.Dims(1); ++y) { + for (int x = 0; x < extended_output_shape.Dims(2); ++x) { + for (int c = 0; c < extended_output_shape.Dims(3); ++c) { + output_data[Offset(extended_output_shape, b, y, x, c)] = binary_func( + input1_data[SubscriptToIndex(desc1, b, y, x, c)], + input2_data[SubscriptToIndex(desc2, b, y, x, c)], params); + } + } + } + } +} + +inline int8_t AddFunc(int8_t x, int8_t y, const ArithmeticParams& params) { + const int32_t input1_val = params.input1_offset + x; + const int32_t input2_val = params.input2_offset + y; + const int32_t shifted_input1_val = input1_val * (1 << params.left_shift); + const int32_t shifted_input2_val = input2_val * (1 << params.left_shift); + const int32_t scaled_input1_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input1_val, params.input1_multiplier, params.input1_shift); + const int32_t scaled_input2_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input2_val, params.input2_multiplier, params.input2_shift); + const int32_t raw_sum = scaled_input1_val + scaled_input2_val; + const int32_t raw_output = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + raw_sum, params.output_multiplier, params.output_shift) + + params.output_offset; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + return static_cast(clamped_output); +} + +// Element-wise add that can often be used for inner loop of broadcast add as +// well as the non-broadcast add. +inline void AddElementwise(int size, const ArithmeticParams& params, + const int8_t* input1_data, const int8_t* input2_data, + int8_t* output_data) { + ElementWise(size, params, input1_data, input2_data, output_data, + CheckArithmeticParams, AddFunc); +} + +inline void Add(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const int8_t* input1_data, + const RuntimeShape& input2_shape, const int8_t* input2_data, + const RuntimeShape& output_shape, int8_t* output_data) { + CheckArithmeticParams(params); + + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + AddElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +inline void BroadcastAdd4DSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const int8_t* input1_data, + const RuntimeShape& input2_shape, + const int8_t* input2_data, + const RuntimeShape& output_shape, + int8_t* output_data) { + BroadcastBinaryFunction4DSlow(params, input1_shape, input1_data, input2_shape, + input2_data, output_shape, output_data, + CheckArithmeticParams, AddFunc); +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_ADD_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/conv.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/conv.h new file mode 100644 index 000000000..5ddf04aea --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/conv.h @@ -0,0 +1,254 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_CONV_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_CONV_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/portable_tensor_utils.h" + +namespace tflite { +namespace reference_integer_ops { + +// Fixed-point per-channel-quantization convolution reference kernel. +inline void ConvPerChannel( + const ConvParams& params, const int32_t* output_multiplier, + const int32_t* output_shift, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + int8_t* output_data) { + // Get parameters. + const int32_t input_offset = params.input_offset; // r = s(q - Z) + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const int32_t output_offset = params.output_offset; + + // Set min and max value of the output. + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + + // Consistency check. + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = input_shape.Dims(3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + if (bias_data) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + + // Check dimensions of the tensors. + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int filter_input_depth = filter_shape.Dims(3); + const int groups = input_depth / filter_input_depth; + TFLITE_DCHECK_EQ(input_depth % filter_input_depth, 0); + const int filters_per_group = output_depth / groups; + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + const int in_y_origin = (out_y * stride_height) - pad_height; + for (int out_x = 0; out_x < output_width; ++out_x) { + const int in_x_origin = (out_x * stride_width) - pad_width; + for (int out_channel = 0; out_channel < output_depth; ++out_channel) { + auto group = out_channel / filters_per_group; + int32_t acc = 0; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + const int in_y = in_y_origin + dilation_height_factor * filter_y; + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = in_x_origin + dilation_width_factor * filter_x; + + // Zero padding by omitting the areas outside the image. + const bool is_point_inside_image = + (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height); + + if (!is_point_inside_image) { + continue; + } + + for (int in_channel = 0; in_channel < filter_input_depth; + ++in_channel) { + int32_t input_val = + input_data[Offset(input_shape, batch, in_y, in_x, + in_channel + group * filter_input_depth)]; + int32_t filter_val = filter_data[Offset( + filter_shape, out_channel, filter_y, filter_x, in_channel)]; + // Accumulate with 32 bits accumulator. + // In the nudging process during model quantization, we force + // real value of 0.0 be represented by a quantized value. This + // guarantees that the input_offset is a int8_t, even though + // it is represented using int32_t. int32_t += int8_t * + // (int8_t - int8_t) so the highest value we can get from each + // accumulation is [-127, 127] * ([-128, 127] - + // [-128, 127]), which is [-32512, 32512]. log2(32512) + // = 14.98, which means we can accumulate at least 2^16 + // multiplications without overflow. The accumulator is + // applied to a filter so the accumulation logic will hold as + // long as the filter size (filter_y * filter_x * in_channel) + // does not exceed 2^16, which is the case in all the models + // we have seen so far. + // TODO(b/174275578): Add a check to make sure the + // accumulator depth is smaller than 2^16. + acc += filter_val * (input_val + input_offset); + } + } + } + + if (bias_data) { + acc += bias_data[out_channel]; + } + acc = MultiplyByQuantizedMultiplier( + acc, output_multiplier[out_channel], output_shift[out_channel]); + acc += output_offset; + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, out_channel)] = + static_cast(acc); + } + } + } + } +} + +inline void ConvPerChannelWithPackedInt4Weights( + const ConvParams& params, const int32_t* output_multiplier, + const int32_t* output_shift, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_input, int8_t* unpacked_filter_data, + const RuntimeShape& bias_shape, const int32_t* bias_data, + const RuntimeShape& output_shape, int8_t* output_data) { + TFLITE_DCHECK(unpacked_filter_data != nullptr); + tflite::tensor_utils::UnpackDenseInt4IntoInt8( + filter_input, filter_shape.FlatSize(), unpacked_filter_data); + ConvPerChannel(params, output_multiplier, output_shift, input_shape, + input_data, filter_shape, unpacked_filter_data, bias_shape, + bias_data, output_shape, output_data); +} + +// Fixed-point per-channel-quantization convolution reference kernel. +// 16-bit data and 8-bit filter +template +inline void ConvPerChannel( + const ConvParams& params, const int32_t* output_multiplier, + const int32_t* output_shift, const RuntimeShape& input_shape, + const int16_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const AccumScalar* bias_data, const RuntimeShape& output_shape, + int16_t* output_data) { + // Get parameters. + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + + // Set min and max value of the output. + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + + // Consistency check. + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = input_shape.Dims(3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + if (bias_data) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + + // Check dimensions of the tensors. + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int filter_input_depth = filter_shape.Dims(3); + const int groups = input_depth / filter_input_depth; + TFLITE_DCHECK_EQ(input_depth % filter_input_depth, 0); + const int filters_per_group = output_depth / groups; + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + const int in_y_origin = (out_y * stride_height) - pad_height; + for (int out_x = 0; out_x < output_width; ++out_x) { + const int in_x_origin = (out_x * stride_width) - pad_width; + for (int out_channel = 0; out_channel < output_depth; ++out_channel) { + auto group = out_channel / filters_per_group; + AccumScalar acc = 0; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + const int in_y = in_y_origin + dilation_height_factor * filter_y; + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = in_x_origin + dilation_width_factor * filter_x; + + // Zero padding by omitting the areas outside the image. + const bool is_point_inside_image = + (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height); + + if (!is_point_inside_image) { + continue; + } + + for (int in_channel = 0; in_channel < filter_input_depth; + ++in_channel) { + int32_t input_val = + input_data[Offset(input_shape, batch, in_y, in_x, + in_channel + group * filter_input_depth)]; + int32_t filter_val = filter_data[Offset( + filter_shape, out_channel, filter_y, filter_x, in_channel)]; + // Accumulate with 64 bits accumulator. + // int64_t += int8_t * int16_t so the highest value we can + // get from each accumulation is [-127, 127] * ([-32768, + // 32767] - + // [-32768, 32767]), which is [-8322945, 8322945]. + // log2(8322945) = 22.99. + acc += filter_val * input_val; + } + } + } + if (bias_data) { + acc += bias_data[out_channel]; + } + int32_t scaled_acc = MultiplyByQuantizedMultiplier( + acc, output_multiplier[out_channel], output_shift[out_channel]); + scaled_acc = std::max(scaled_acc, output_activation_min); + scaled_acc = std::min(scaled_acc, output_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, out_channel)] = + static_cast(scaled_acc); + } + } + } + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_CONV_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h new file mode 100644 index 000000000..7676fce0f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h @@ -0,0 +1,291 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_DEPTHWISE_CONV_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_DEPTHWISE_CONV_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { +inline void DepthwiseConvPerChannel( + const DepthwiseParams& params, const int32_t* output_multiplier, + const int32_t* output_shift, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + int8_t* output_data) { + // Get parameters. + // TODO(b/141565753): Re-introduce ScopedProfilingLabel on Micro. + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const int depth_multiplier = params.depth_multiplier; + const int32_t input_offset = params.input_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + + // Check dimensions of the tensors. + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int output_depth = MatchingDim(filter_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int input_depth = input_shape.Dims(3); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + TFLITE_DCHECK_EQ(output_depth, input_depth * depth_multiplier); + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int in_channel = 0; in_channel < input_depth; ++in_channel) { + for (int m = 0; m < depth_multiplier; ++m) { + const int output_channel = m + in_channel * depth_multiplier; + const int in_x_origin = (out_x * stride_width) - pad_width; + const int in_y_origin = (out_y * stride_height) - pad_height; + int32_t acc = 0; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = in_x_origin + dilation_width_factor * filter_x; + const int in_y = + in_y_origin + dilation_height_factor * filter_y; + // Zero padding by omitting the areas outside the image. + const bool is_point_inside_image = + (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height); + if (is_point_inside_image) { + int32_t input_val = input_data[Offset( + input_shape, batch, in_y, in_x, in_channel)]; + int32_t filter_val = filter_data[Offset( + filter_shape, 0, filter_y, filter_x, output_channel)]; + // Accumulate with 32 bits accumulator. + // In the nudging process during model quantization, we force + // real value of 0.0 be represented by a quantized value. This + // guarantees that the input_offset is a int8_t, even though + // it is represented using int32_t. int32_t += int8_t * + // (int8_t - int8_t) so the highest value we can get from each + // accumulation is [-127, 127] * ([-128, 127] - + // [-128, 127]), which is [-32512, 32512]. log2(32512) + // = 14.98, which means we can accumulate at least 2^16 + // multiplications without overflow. The accumulator is + // applied to a filter so the accumulation logic will hold as + // long as the filter size (filter_y * filter_x * in_channel) + // does not exceed 2^16, which is the case in all the models + // we have seen so far. + // TODO(b/174275578): Add a check to make sure the + // accumulator depth is smaller than 2^16. + acc += filter_val * (input_val + input_offset); + } + } + } + if (bias_data) { + acc += bias_data[output_channel]; + } + acc = MultiplyByQuantizedMultiplier( + acc, output_multiplier[output_channel], + output_shift[output_channel]); + acc += output_offset; + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, + output_channel)] = static_cast(acc); + } + } + } + } + } +} + +inline void DepthwiseConvPerChannel( + const DepthwiseParams& params, const int32_t* output_multiplier, + const int32_t* output_shift, const RuntimeShape& input_shape, + const int16_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const std::int64_t* bias_data, const RuntimeShape& output_shape, + int16_t* output_data) { + // Get parameters. + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const int depth_multiplier = params.depth_multiplier; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + + // Check dimensions of the tensors. + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int output_depth = MatchingDim(filter_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int input_depth = input_shape.Dims(3); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + TFLITE_DCHECK_EQ(output_depth, input_depth * depth_multiplier); + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int in_channel = 0; in_channel < input_depth; ++in_channel) { + for (int m = 0; m < depth_multiplier; ++m) { + const int output_channel = m + in_channel * depth_multiplier; + const int in_x_origin = (out_x * stride_width) - pad_width; + const int in_y_origin = (out_y * stride_height) - pad_height; + std::int64_t acc = 0; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = in_x_origin + dilation_width_factor * filter_x; + const int in_y = + in_y_origin + dilation_height_factor * filter_y; + // Zero padding by omitting the areas outside the image. + const bool is_point_inside_image = + (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height); + if (is_point_inside_image) { + int32_t input_val = input_data[Offset( + input_shape, batch, in_y, in_x, in_channel)]; + int32_t filter_val = filter_data[Offset( + filter_shape, 0, filter_y, filter_x, output_channel)]; + // Accumulate with 64 bits accumulator. + // We assume maximum of 2^16 accumulations as with the 8-bit + // case so actually the value in the accumulator should not + // exceed 40 bits + acc += static_cast(filter_val) * + static_cast(input_val); + } + } + } + if (bias_data) { + acc += bias_data[output_channel]; + } + int32_t scaled_acc = MultiplyByQuantizedMultiplier( + acc, output_multiplier[output_channel], + output_shift[output_channel]); + scaled_acc = std::max(scaled_acc, output_activation_min); + scaled_acc = std::min(scaled_acc, output_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, + output_channel)] = + static_cast(scaled_acc); + } + } + } + } + } +} + +inline void DepthwiseConvHybridPerChannel( + const DepthwiseParams& params, float* scaling_factors_ptr, + const RuntimeShape& input_shape, const int8_t* input_data, + const RuntimeShape& filter_shape, const int8_t* filter_data, + const RuntimeShape& bias_shape, const float* bias_data, + const RuntimeShape& output_shape, float* output_data, + const float* per_channel_scale, int32_t* input_offset) { + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + const int depth_multiplier = params.depth_multiplier; + const float output_activation_min = params.float_activation_min; + const float output_activation_max = params.float_activation_max; + // Check dimensions of the tensors. + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int output_depth = MatchingDim(filter_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int input_depth = input_shape.Dims(3); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int bias_depth = bias_shape.FlatSize(); + TFLITE_DCHECK_EQ(output_depth, input_depth * depth_multiplier); + TFLITE_DCHECK_EQ(bias_depth, output_depth); + + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int in_channel = 0; in_channel < input_depth; ++in_channel) { + for (int m = 0; m < depth_multiplier; ++m) { + const int output_channel = m + in_channel * depth_multiplier; + const int in_x_origin = (out_x * stride_width) - pad_width; + const int in_y_origin = (out_y * stride_height) - pad_height; + int32_t acc = 0; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + const int in_x = in_x_origin + dilation_width_factor * filter_x; + const int in_y = + in_y_origin + dilation_height_factor * filter_y; + // Zero padding by omitting the areas outside the image. + const bool is_point_inside_image = + (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && + (in_y < input_height); + if (is_point_inside_image) { + int32_t input_val = input_data[Offset( + input_shape, batch, in_y, in_x, in_channel)]; + int32_t filter_val = filter_data[Offset( + filter_shape, 0, filter_y, filter_x, output_channel)]; + acc += filter_val * (input_val - input_offset[batch]); + } + } + } + float acc_float = static_cast(acc); + acc_float *= + per_channel_scale[output_channel] * scaling_factors_ptr[batch]; + if (bias_data && output_channel < bias_depth) { + acc_float += bias_data[output_channel]; + } + output_data[Offset(output_shape, batch, out_y, out_x, + output_channel)] = + ActivationFunctionWithMinMax(acc_float, output_activation_min, + output_activation_max); + } + } + } + } + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_DEPTHWISE_CONV_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h new file mode 100644 index 000000000..634f0bffa --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h @@ -0,0 +1,201 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_FULLY_CONNECTED_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_FULLY_CONNECTED_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +// For per-channel functions, since it is defined in quantization spec that +// weights are symmetric +// (https://www.tensorflow.org/lite/performance/quantization_spec#symmetric_vs_asymmetric), +// zero_point (params.weights_offset) is always 0. +// However, for per-tensor functions, params.weights_offset is still applied for +// backward compatibility. + +inline void FullyConnectedPerChannel( + const FullyConnectedParams& params, const int32_t* output_multiplier, + const int* output_shift, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + int8_t* output_data) { + const int32_t input_offset = params.input_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_GE(filter_shape.DimensionsCount(), 2); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 2); + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + const int filter_dim_count = filter_shape.DimensionsCount(); + const int batches = output_shape.Dims(0); + const int output_depth = output_shape.Dims(1); + TFLITE_DCHECK_LE(output_depth, filter_shape.Dims(filter_dim_count - 2)); + const int accum_depth = filter_shape.Dims(filter_dim_count - 1); + for (int b = 0; b < batches; ++b) { + for (int out_c = 0; out_c < output_depth; ++out_c) { + int32_t acc = 0; + for (int d = 0; d < accum_depth; ++d) { + int32_t input_val = input_data[b * accum_depth + d]; + int32_t filter_val = filter_data[out_c * accum_depth + d]; + acc += filter_val * (input_val + input_offset); + } + if (bias_data) { + acc += bias_data[out_c]; + } + acc = MultiplyByQuantizedMultiplier(acc, output_multiplier[out_c], + output_shift[out_c]); + acc += output_offset; + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_data[out_c + output_depth * b] = static_cast(acc); + } + } +} + +template +inline void FullyConnectedPerChannel( + const FullyConnectedParams& params, const int32_t* output_multiplier, + const int* output_shift, const RuntimeShape& input_shape, + const int16_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const AccumScalar* bias_data, const RuntimeShape& output_shape, + int16_t* output_data) { + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_GE(filter_shape.DimensionsCount(), 2); + TFLITE_DCHECK_GE(output_shape.DimensionsCount(), 1); + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + const int filter_dim_count = filter_shape.DimensionsCount(); + const int output_dim_count = output_shape.DimensionsCount(); + const int batches = FlatSizeSkipDim(output_shape, output_dim_count - 1); + const int output_depth = output_shape.Dims(output_dim_count - 1); + TFLITE_DCHECK_LE(output_depth, filter_shape.Dims(filter_dim_count - 2)); + const int accum_depth = filter_shape.Dims(filter_dim_count - 1); + for (int b = 0; b < batches; ++b) { + for (int out_c = 0; out_c < output_depth; ++out_c) { + AccumScalar acc = 0; + for (int d = 0; d < accum_depth; ++d) { + int32_t input_val = input_data[b * accum_depth + d]; + int32_t filter_val = filter_data[out_c * accum_depth + d]; + acc += filter_val * input_val; + } + if (bias_data) { + acc += bias_data[out_c]; + } + int32_t acc_scaled = MultiplyByQuantizedMultiplier( + acc, output_multiplier[out_c], output_shift[out_c]); + acc_scaled = std::max(acc_scaled, output_activation_min); + acc_scaled = std::min(acc_scaled, output_activation_max); + output_data[out_c + output_depth * b] = static_cast(acc_scaled); + } + } +} + +inline void FullyConnected( + const FullyConnectedParams& params, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + int8_t* output_data) { + const int32_t input_offset = params.input_offset; + const int32_t filter_offset = params.weights_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_multiplier = params.output_multiplier; + const int output_shift = params.output_shift; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_GE(filter_shape.DimensionsCount(), 2); + TFLITE_DCHECK_GE(output_shape.DimensionsCount(), 1); + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + const int filter_dim_count = filter_shape.DimensionsCount(); + const int output_dim_count = output_shape.DimensionsCount(); + const int batches = FlatSizeSkipDim(output_shape, output_dim_count - 1); + const int output_depth = output_shape.Dims(output_dim_count - 1); + TFLITE_DCHECK_LE(output_depth, filter_shape.Dims(filter_dim_count - 2)); + const int accum_depth = filter_shape.Dims(filter_dim_count - 1); + for (int b = 0; b < batches; ++b) { + for (int out_c = 0; out_c < output_depth; ++out_c) { + int32_t acc = 0; + for (int d = 0; d < accum_depth; ++d) { + int32_t input_val = input_data[b * accum_depth + d]; + int32_t filter_val = filter_data[out_c * accum_depth + d]; + acc += (filter_val + filter_offset) * (input_val + input_offset); + } + if (bias_data) { + acc += bias_data[out_c]; + } + acc = MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift); + acc += output_offset; + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_data[out_c + output_depth * b] = static_cast(acc); + } + } +} + +template +inline void FullyConnected( + const FullyConnectedParams& params, const RuntimeShape& input_shape, + const int16_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const AccumScalar* bias_data, const RuntimeShape& output_shape, + int16_t* output_data) { + const int32_t filter_offset = params.weights_offset; + const int32_t output_multiplier = params.output_multiplier; + const int output_shift = params.output_shift; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_GE(filter_shape.DimensionsCount(), 2); + TFLITE_DCHECK_GE(output_shape.DimensionsCount(), 1); + + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + const int filter_dim_count = filter_shape.DimensionsCount(); + const int output_dim_count = output_shape.DimensionsCount(); + const int batches = FlatSizeSkipDim(output_shape, output_dim_count - 1); + const int output_depth = output_shape.Dims(output_dim_count - 1); + TFLITE_DCHECK_LE(output_depth, filter_shape.Dims(filter_dim_count - 2)); + const int accum_depth = filter_shape.Dims(filter_dim_count - 1); + for (int b = 0; b < batches; ++b) { + for (int out_c = 0; out_c < output_depth; ++out_c) { + AccumScalar acc = 0; + for (int d = 0; d < accum_depth; ++d) { + int32_t input_val = input_data[b * accum_depth + d]; + int32_t filter_val = filter_data[out_c * accum_depth + d]; + acc += (filter_val + filter_offset) * input_val; + } + if (bias_data) { + acc += bias_data[out_c]; + } + int32_t acc_scaled = + MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift); + acc_scaled = std::max(acc_scaled, output_activation_min); + acc_scaled = std::min(acc_scaled, output_activation_max); + output_data[out_c + output_depth * b] = static_cast(acc_scaled); + } + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_FULLY_CONNECTED_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/l2normalization.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/l2normalization.h new file mode 100644 index 000000000..164a83670 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/l2normalization.h @@ -0,0 +1,67 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_L2NORMALIZATION_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_L2NORMALIZATION_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +inline void L2Normalization(int32_t input_zero_point, int32_t outer_size, + int32_t depth, const int8_t* input_data, + int8_t* output_data) { + static constexpr int8_t kMinInt8 = std::numeric_limits::min(); + static constexpr int8_t kMaxInt8 = std::numeric_limits::max(); + // The output scale must be in sync with Prepare(). + // Output is in 1/128 scale so the actual output range is nudged from [-1, 1] + // to [-1, 127/128]. + static constexpr int32_t kOutputScale = 7; + for (int outer_index = 0; outer_index < outer_size; ++outer_index) { + // int32_t = (int8_t - int8_t) ^ 2. + // ([-128, 127] - [-128, 127]) ^ 2 = [0, (2^8 - 1)^2] so the accumulator is + // safe from overflowing in at least 2^16 steps. + int32_t acc = 0; + for (int inner_index = 0; inner_index < depth; ++inner_index) { + int32_t input = + input_data[depth * outer_index + inner_index] - input_zero_point; + acc += input * input; + } + int32_t inv_l2norm_multiplier; + int inv_l2norm_shift; + GetInvSqrtQuantizedMultiplierExp(acc, kReverseShift, &inv_l2norm_multiplier, + &inv_l2norm_shift); + + for (int inner_index = 0; inner_index < depth; ++inner_index) { + int32_t input = + input_data[depth * outer_index + inner_index] - input_zero_point; + + // Rescale and downcast. Rescale is folded into the division. + int32_t output_in_q24 = MultiplyByQuantizedMultiplier( + input, inv_l2norm_multiplier, inv_l2norm_shift + kOutputScale); + output_in_q24 = + std::min(static_cast(kMaxInt8), + std::max(static_cast(kMinInt8), output_in_q24)); + output_data[depth * outer_index + inner_index] = + static_cast(output_in_q24); + } + } +} +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_L2NORMALIZATION_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h new file mode 100644 index 000000000..16eff133d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h @@ -0,0 +1,121 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_LOGISTIC_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_LOGISTIC_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +inline void Logistic(int32_t input_zero_point, int32_t input_range_radius, + int32_t input_multiplier, int32_t input_left_shift, + int32_t input_size, const int8_t* input_data, + int8_t* output_data) { + // Integer bits must be in sync with Prepare() function. + static constexpr int32_t kInputIntegerBits = 4; + static constexpr int32_t kOutputIntegerBits = 8; + static constexpr int8_t kMinInt8 = std::numeric_limits::min(); + static constexpr int8_t kMaxInt8 = std::numeric_limits::max(); + static constexpr int32_t kOutputZeroPoint = -128; + + for (int i = 0; i < input_size; ++i) { + const int32_t input = + static_cast(input_data[i]) - input_zero_point; + if (input <= -input_range_radius) { + output_data[i] = kMinInt8; + } else if (input >= input_range_radius) { + output_data[i] = kMaxInt8; + } else { + const int32_t input_in_q4 = MultiplyByQuantizedMultiplier( + input, input_multiplier, input_left_shift); + using FixedPoint4 = gemmlowp::FixedPoint; + const int32_t output_in_q0 = + gemmlowp::logistic(FixedPoint4::FromRaw(input_in_q4)).raw(); + + // Rescale and downcast. + using gemmlowp::RoundingDivideByPOT; + int32_t output_in_q23 = + RoundingDivideByPOT(output_in_q0, 31 - kOutputIntegerBits); + output_in_q23 = std::min(std::max(output_in_q23 + kOutputZeroPoint, + static_cast(kMinInt8)), + static_cast(kMaxInt8)); + output_data[i] = static_cast(output_in_q23); + } + } +} + +inline void Logistic(int32_t input_multiplier, int32_t input_left_shift, + int32_t input_size, const int16_t* ptr_input_data, + int16_t* ptr_output_data) { + // We use the LUT for sigmoid and take into account, that + // tanh(x) = 2*sigmoid(2*x) - 1 + + // We scale by 3/4 to expand range [-8,8]->[-10.7,10.7]. + // In case of general parameter scale, multiplier 3 is taken into account + // in TanhPrepare function and it is included in + // input_multiplier already. + + TFLITE_DCHECK_GE(input_left_shift, 0); + if (input_multiplier == 0) { // power of two case + input_multiplier = 3 << input_left_shift; + input_left_shift = 0; + } + + int32_t round = (input_left_shift > 0) ? 1 << (input_left_shift - 1) : 0; + + for (int i = 0; i < input_size; ++i, ptr_input_data++, ptr_output_data++) { + int32_t input_data = + ((*ptr_input_data) * input_multiplier + round) >> input_left_shift; + + // We do interpolation on unsigned values. + uint32_t abs_input_data = abs(input_data); + + // We divide by 2 power of 9, because + // we need to divide by 2 in power of 7 for + // the input conversion + 1/4 from the scale above. + + // Define uh as uint32_t type not to make this function overflow. + uint32_t uh = abs_input_data >> 9; + uint32_t result; + + if (uh >= 255) { + // Saturate to maximum. + result = 0x7FFF << 10; + } else { + uint32_t ua = sigmoid_table_uint16[uh]; + uint32_t ub = sigmoid_table_uint16[uh + 1]; + uint32_t ut = abs_input_data & 0x1ff; + // Interpolation is done using the fractional bit. + result = (ua << 9) + ut * (ub - ua); + } + + result = (input_data >= 0) ? (result + (1 << 9)) + : ((1 << (16 + 9)) - result + (1 << 9) - 1); + + // Back to 16-bit. + result >>= 10; + + *ptr_output_data = result; + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_LOGISTIC_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/mean.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/mean.h new file mode 100644 index 000000000..09d37b726 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/mean.h @@ -0,0 +1,79 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_MEAN_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_MEAN_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +template +inline void Mean(const tflite::MeanParams& op_params, int32_t multiplier, + int32_t shift, const RuntimeShape& unextended_input_shape, + const integer_type* input_data, int32_t input_zero_point, + const RuntimeShape& unextended_output_shape, + integer_type* output_data, int32_t output_zero_point) { + // Current implementation only supports dimension equals 4 and simultaneous + // reduction over width and height. + TFLITE_CHECK_EQ(unextended_input_shape.DimensionsCount(), 4); + TFLITE_CHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + const int output_batch = output_shape.Dims(0); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int output_depth = output_shape.Dims(3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int num_elements_in_axis = input_width * input_height; + + TFLITE_CHECK_EQ(op_params.axis_count, 2); + TFLITE_CHECK((op_params.axis[0] == 1 && op_params.axis[1] == 2) || + (op_params.axis[0] == 2 && op_params.axis[1] == 1)); + TFLITE_CHECK_EQ(output_height, 1); + TFLITE_CHECK_EQ(output_width, 1); + + static constexpr int32_t kMinInt = std::numeric_limits::min(); + static constexpr int32_t kMaxInt = std::numeric_limits::max(); + + for (int out_b = 0; out_b < output_batch; ++out_b) { + for (int out_d = 0; out_d < output_depth; ++out_d) { + int32_t acc = 0; + for (int in_h = 0; in_h < input_height; ++in_h) { + for (int in_w = 0; in_w < input_width; ++in_w) { + acc += input_data[Offset(input_shape, out_b, in_h, in_w, out_d)] - + input_zero_point; + } + } + acc = MultiplyByQuantizedMultiplier(acc, multiplier, shift); + acc = acc > 0 ? (acc + num_elements_in_axis / 2) / num_elements_in_axis + : (acc - num_elements_in_axis / 2) / num_elements_in_axis; + acc += output_zero_point; + acc = std::min(std::max(acc, kMinInt), kMaxInt); + output_data[Offset(output_shape, out_b, 0, 0, out_d)] = + static_cast(acc); + } + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_MEAN_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/mul.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/mul.h new file mode 100644 index 000000000..778772888 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/mul.h @@ -0,0 +1,133 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_MUL_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_MUL_H_ + +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +template +inline void MulElementwise(int size, const ArithmeticParams& params, + const T* input1_data, const T* input2_data, + T* output_data) { + for (int i = 0; i < size; ++i) { + const int32_t input1_val = params.input1_offset + input1_data[i]; + const int32_t input2_val = params.input2_offset + input2_data[i]; + const int32_t unclamped_result = + params.output_offset + + MultiplyByQuantizedMultiplier(input1_val * input2_val, + params.output_multiplier, + params.output_shift); + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, unclamped_result)); + output_data[i] = static_cast(clamped_output); + } +} + +template +inline void Mul(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const T* input1_data, + const RuntimeShape& input2_shape, const T* input2_data, + const RuntimeShape& output_shape, T* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + ruy::profiler::ScopeLabel label("Mul/8bit"); + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + MulElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +// Mul with 16 bit inputs and int8_t outputs. +inline void Mul(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const int16_t* input1_data, + const RuntimeShape& input2_shape, const int16_t* input2_data, + const RuntimeShape& output_shape, int8_t* output_data) { + ruy::profiler::ScopeLabel label("Mul/Int16Int8"); + int32_t output_offset = params.output_offset; + int32_t output_activation_min = params.quantized_activation_min; + int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + for (int i = 0; i < flat_size; i++) { + // F0 uses 0 integer bits, range [-1, 1]. + using F0 = gemmlowp::FixedPoint; + + F0 unclamped_result = + F0::FromRaw(input1_data[i]) * F0::FromRaw(input2_data[i]); + int16_t rescaled_result = + gemmlowp::RoundingDivideByPOT(unclamped_result.raw(), 8); + int16_t clamped_result = std::min( + output_activation_max - output_offset, rescaled_result); + clamped_result = std::max(output_activation_min - output_offset, + clamped_result); + output_data[i] = output_offset + clamped_result; + } +} + +template +inline void BroadcastMul4DSlow( + const ArithmeticParams& params, const RuntimeShape& input1_shape, + const T* input1_data, const RuntimeShape& input2_shape, + const T* input2_data, const RuntimeShape& output_shape, T* output_data) { + ruy::profiler::ScopeLabel label("BroadcastMul4DSlow"); + + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + // The input shapes are extended as part of NdArrayDesc initialization. + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + const RuntimeShape extended_output_shape = + RuntimeShape::ExtendedShape(4, output_shape); + + for (int b = 0; b < extended_output_shape.Dims(0); ++b) { + for (int y = 0; y < extended_output_shape.Dims(1); ++y) { + for (int x = 0; x < extended_output_shape.Dims(2); ++x) { + for (int c = 0; c < extended_output_shape.Dims(3); ++c) { + const int32_t input1_val = + params.input1_offset + + input1_data[SubscriptToIndex(desc1, b, y, x, c)]; + const int32_t input2_val = + params.input2_offset + + input2_data[SubscriptToIndex(desc2, b, y, x, c)]; + const int32_t unclamped_result = + params.output_offset + + MultiplyByQuantizedMultiplier(input1_val * input2_val, + params.output_multiplier, + params.output_shift); + const int32_t clamped_output = std::min( + params.quantized_activation_max, + std::max(params.quantized_activation_min, unclamped_result)); + output_data[Offset(extended_output_shape, b, y, x, c)] = + static_cast(clamped_output); + } + } + } + } +} + +} // namespace reference_integer_ops +} // namespace tflite +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_MUL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h new file mode 100644 index 000000000..4dc31d9ed --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h @@ -0,0 +1,264 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_POOLING_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_POOLING_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +inline bool AveragePool(const PoolParams& params, + const RuntimeShape& input_shape, + const int8_t* input_data, + const RuntimeShape& output_shape, int8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + int32_t acc = 0; + int filter_count = 0; + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + acc += + input_data[Offset(input_shape, batch, in_y, in_x, channel)]; + filter_count++; + } + } + if (filter_count == 0) return false; + // Round to the closest integer value. + acc = acc > 0 ? (acc + filter_count / 2) / filter_count + : (acc - filter_count / 2) / filter_count; + acc = std::max(acc, params.quantized_activation_min); + acc = std::min(acc, params.quantized_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + static_cast(acc); + } + } + } + } + return true; +} + +inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& output_shape, + int8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + TFLITE_DCHECK_GE(params.quantized_activation_min, + std::numeric_limits::min()); + TFLITE_DCHECK_LE(params.quantized_activation_max, + std::numeric_limits::max()); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + int8_t max = std::numeric_limits::lowest(); + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + max = std::max( + max, + input_data[Offset(input_shape, batch, in_y, in_x, channel)]); + } + } + max = std::max(max, params.quantized_activation_min); + max = std::min(max, params.quantized_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + static_cast(max); + } + } + } + } +} + +inline bool AveragePool(const PoolParams& params, + const RuntimeShape& input_shape, + const int16_t* input_data, + const RuntimeShape& output_shape, + int16_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + int32_t acc = 0; + int filter_count = 0; + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + acc += + input_data[Offset(input_shape, batch, in_y, in_x, channel)]; + filter_count++; + } + } + if (filter_count == 0) return false; + // Round to the closest integer value. + acc = acc > 0 ? (acc + filter_count / 2) / filter_count + : (acc - filter_count / 2) / filter_count; + acc = std::max(acc, params.quantized_activation_min); + acc = std::min(acc, params.quantized_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + static_cast(acc); + } + } + } + } + return true; +} + +inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape, + const int16_t* input_data, const RuntimeShape& output_shape, + int16_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + TFLITE_DCHECK_GE(params.quantized_activation_min, + std::numeric_limits::min()); + TFLITE_DCHECK_LE(params.quantized_activation_max, + std::numeric_limits::max()); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + int16_t max = std::numeric_limits::lowest(); + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + max = std::max( + max, + input_data[Offset(input_shape, batch, in_y, in_x, channel)]); + } + } + max = std::max(max, params.quantized_activation_min); + max = std::min(max, params.quantized_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + static_cast(max); + } + } + } + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_POOLING_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/tanh.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/tanh.h new file mode 100644 index 000000000..93b0bb87e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/tanh.h @@ -0,0 +1,117 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_TANH_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_TANH_H_ + +#include +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +inline void Tanh(int32_t input_zero_point, int32_t input_range_radius, + int32_t input_multiplier, int32_t input_shift, + const RuntimeShape& input_shape, const int8_t* input_data, + const RuntimeShape& output_shape, int8_t* output_data) { + // Integer bits must be in sync with Prepare() function. + static constexpr int32_t kInputIntegerBits = 4; + static constexpr int32_t kOutputScale = 7; + static constexpr int32_t kMinInt8 = std::numeric_limits::min(); + static constexpr int32_t kMaxInt8 = std::numeric_limits::max(); + using F4 = gemmlowp::FixedPoint; + + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; ++i) { + const int32_t input = + static_cast(input_data[i]) - input_zero_point; + if (input <= -input_range_radius) { + output_data[i] = kMinInt8; + } else if (input >= input_range_radius) { + output_data[i] = kMaxInt8; + } else { + const int32_t input_in_q4 = + MultiplyByQuantizedMultiplier(input, input_multiplier, input_shift); + const int32_t output_in_q0 = + gemmlowp::tanh(F4::FromRaw(input_in_q4)).raw(); + + // Rescale and downcast. + using gemmlowp::RoundingDivideByPOT; + int32_t output_in_q24 = + RoundingDivideByPOT(output_in_q0, 31 - kOutputScale); + output_in_q24 = std::min(std::max(output_in_q24, kMinInt8), kMaxInt8); + output_data[i] = static_cast(output_in_q24); + } + } +} + +inline void Tanh(int32_t input_multiplier, int32_t input_left_shift, + const RuntimeShape& input_shape, const int16_t* ptr_input_data, + const RuntimeShape& output_shape, int16_t* ptr_output_data) { + // We use the LUT for sigmoid and take into account, that + // tanh(x) = 2*sigmoid(2*x) - 1 + + // We scale by 3/4 to expand range [-8,8]->[-10.7,10.7]. + // In case of general parameter scale, multiplier 3 is taken into account + // in TanhPrepare function and it is included in + // input_multiplier already. + + if (input_multiplier == 0) { // power of two case + input_multiplier = 3 << input_left_shift; + input_left_shift = 0; + } + + int32_t round = (input_left_shift > 0) ? 1 << (input_left_shift - 1) : 0; + + int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; ++i, ptr_input_data++, ptr_output_data++) { + int32_t input_data = + ((*ptr_input_data) * input_multiplier + round) >> input_left_shift; + + uint32_t abs_input_data = abs(input_data); + uint32_t uh = abs_input_data >> 8; + int32_t result; + + if (uh >= 255) { + // Saturate to maximum. + result = 0xFFFF << 8; + } else { + uint32_t ua = sigmoid_table_uint16[uh]; + uint32_t ub = sigmoid_table_uint16[uh + 1]; + + uint8_t ut = abs_input_data & 0xFF; + + result = (ua << 8) + ut * (ub - ua); + } + + result = (input_data >= 0) + ? (result - (1 << (14 + 9)) + (1 << (9 - 2))) + : (-result + (1 << (14 + 9)) + (1 << (9 - 2)) - 1); + + // Convert back to 16-bit. + result >>= (9 - 1); + + *ptr_output_data = result; + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_TANH_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/transpose_conv.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/transpose_conv.h new file mode 100644 index 000000000..92919a71d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/integer_ops/transpose_conv.h @@ -0,0 +1,224 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_TRANSPOSE_CONV_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_TRANSPOSE_CONV_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +// Fixed-point per-channel-quantization transpose convolution reference kernel. +inline void TransposeConv( + const ConvParams& params, const int32_t* output_multiplier, + const int32_t* output_shift, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + int8_t* output_data, const RuntimeShape& im2col_shape, int8_t* im2col_data, + int32_t* scratch_buffer) { + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + (void)im2col_data; // only used in optimized code. + (void)im2col_shape; // only used in optimized code. + + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = MatchingDim(input_shape, 3, filter_shape, 3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + if (bias_data) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int32_t input_offset = params.input_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_activation_min = std::numeric_limits::min(); + const int32_t output_activation_max = std::numeric_limits::max(); + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + + const int num_elements = output_shape.FlatSize(); + // We need to initialize scratch_buffer to all 0s, as we apply the same + // 'scatter' based trick as in float version. + memset(scratch_buffer, 0, num_elements * sizeof(int32_t)); + + // Loop through input elements one at a time. + for (int batch = 0; batch < batches; ++batch) { + for (int in_y = 0; in_y < input_height; ++in_y) { + for (int in_x = 0; in_x < input_width; ++in_x) { + for (int in_channel = 0; in_channel < input_depth; ++in_channel) { + // Loop through the output elements it will influence. + const int out_x_origin = (in_x * stride_width) - pad_width; + const int out_y_origin = (in_y * stride_height) - pad_height; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + for (int out_channel = 0; out_channel < output_depth; + ++out_channel) { + // Compute output element location. + const int out_x = out_x_origin + filter_x; + const int out_y = out_y_origin + filter_y; + // We cannot accumulate out of bounds. + if ((out_x >= 0) && (out_x < output_width) && (out_y >= 0) && + (out_y < output_height)) { + const int8_t input_value = input_data[Offset( + input_shape, batch, in_y, in_x, in_channel)]; + const int8_t filter_value = + filter_data[Offset(filter_shape, out_channel, filter_y, + filter_x, in_channel)]; + scratch_buffer[Offset(output_shape, batch, out_y, out_x, + out_channel)] += + (input_value + input_offset) * filter_value; + } + } + } + } + } + } + } + } + + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int out_channel = 0; out_channel < output_depth; ++out_channel) { + int32_t acc = scratch_buffer[Offset(output_shape, batch, out_y, out_x, + out_channel)]; + if (bias_data) { + acc += bias_data[out_channel]; + } + acc = MultiplyByQuantizedMultiplier( + acc, output_multiplier[out_channel], output_shift[out_channel]); + acc += output_offset; + acc = std::max(acc, output_activation_min); + acc = std::min(acc, output_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, out_channel)] = + static_cast(acc); + } + } + } + } +} + +// int16_t input (zero_point=0), int8_t filter, int32 or int64 accumulator +template +inline void TransposeConv( + const ConvParams& params, const int32_t* output_multiplier, + const int32_t* output_shift, const RuntimeShape& input_shape, + const int16_t* input_data, const RuntimeShape& filter_shape, + const int8_t* filter_data, const RuntimeShape& bias_shape, + const Scalar* bias_data, const RuntimeShape& output_shape, + int16_t* output_data, const RuntimeShape& im2col_shape, int8_t* im2col_data, + Scalar* scratch_buffer) { + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + (void)im2col_data; // only used in optimized code. + (void)im2col_shape; // only used in optimized code. + + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = MatchingDim(input_shape, 3, filter_shape, 3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + if (bias_data) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int32_t output_activation_min = std::numeric_limits::min(); + const int32_t output_activation_max = std::numeric_limits::max(); + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + + const int num_elements = output_shape.FlatSize(); + // We need to initialize scratch_buffer to all 0s, as we apply the same + // 'scatter' based trick as in float version. + memset(scratch_buffer, 0, num_elements * sizeof(Scalar)); + + // Loop through input elements one at a time. + for (int batch = 0; batch < batches; ++batch) { + for (int in_y = 0; in_y < input_height; ++in_y) { + for (int in_x = 0; in_x < input_width; ++in_x) { + for (int in_channel = 0; in_channel < input_depth; ++in_channel) { + // Loop through the output elements it will influence. + const int out_x_origin = (in_x * stride_width) - pad_width; + const int out_y_origin = (in_y * stride_height) - pad_height; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + for (int out_channel = 0; out_channel < output_depth; + ++out_channel) { + // Compute output element location. + const int out_x = out_x_origin + filter_x; + const int out_y = out_y_origin + filter_y; + // We cannot accumulate out of bounds. + if ((out_x >= 0) && (out_x < output_width) && (out_y >= 0) && + (out_y < output_height)) { + const int32_t input_value = input_data[Offset( + input_shape, batch, in_y, in_x, in_channel)]; + const int32_t filter_value = + filter_data[Offset(filter_shape, out_channel, filter_y, + filter_x, in_channel)]; + scratch_buffer[Offset(output_shape, batch, out_y, out_x, + out_channel)] += + input_value * filter_value; + } + } + } + } + } + } + } + } + + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int out_channel = 0; out_channel < output_depth; ++out_channel) { + Scalar acc = scratch_buffer[Offset(output_shape, batch, out_y, out_x, + out_channel)]; + if (bias_data) { + acc += bias_data[out_channel]; + } + int32_t scaled_acc = MultiplyByQuantizedMultiplier( + acc, output_multiplier[out_channel], output_shift[out_channel]); + scaled_acc = std::max(scaled_acc, output_activation_min); + scaled_acc = std::min(scaled_acc, output_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, out_channel)] = + static_cast(scaled_acc); + } + } + } + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_TRANSPOSE_CONV_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/l2normalization.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/l2normalization.h new file mode 100644 index 000000000..7587d2b5c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/l2normalization.h @@ -0,0 +1,90 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_L2NORMALIZATION_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_L2NORMALIZATION_H_ + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +inline void L2Normalization(const tflite::L2NormalizationParams& op_params, + const RuntimeShape& input_shape, + const float* input_data, + const RuntimeShape& output_shape, + float* output_data, float epsilon = 1e-6) { + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + for (int i = 0; i < outer_size; ++i) { + float squared_l2_norm = 0; + for (int c = 0; c < depth; ++c) { + const float val = input_data[depth * i + c]; + squared_l2_norm += val * val; + } + float l2_norm = std::sqrt(squared_l2_norm); + l2_norm = std::max(l2_norm, epsilon); + for (int c = 0; c < depth; ++c) { + output_data[depth * i + c] = input_data[depth * i + c] / l2_norm; + } + } +} + +inline void L2Normalization(const tflite::L2NormalizationParams& op_params, + const RuntimeShape& input_shape, + const uint8_t* input_data, + const RuntimeShape& output_shape, + uint8_t* output_data) { + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + const int32_t input_zero_point = op_params.input_zero_point; + + for (int i = 0; i < outer_size; ++i) { + int32_t square_l2_norm = 0; + for (int c = 0; c < depth; c++) { + int32_t diff = input_data[depth * i + c] - input_zero_point; + square_l2_norm += diff * diff; + } + int32_t inv_l2norm_multiplier; + int inv_l2norm_shift; + GetInvSqrtQuantizedMultiplierExp(square_l2_norm, kReverseShift, + &inv_l2norm_multiplier, &inv_l2norm_shift); + for (int c = 0; c < depth; c++) { + int32_t diff = input_data[depth * i + c] - input_zero_point; + int32_t rescaled_diff = MultiplyByQuantizedMultiplierSmallerThanOneExp( + 128 * diff, inv_l2norm_multiplier, inv_l2norm_shift); + int32_t unclamped_output_val = 128 + rescaled_diff; + int32_t output_val = + std::min(static_cast(255), + std::max(static_cast(0), unclamped_output_val)); + output_data[depth * i + c] = static_cast(output_val); + } + } +} + +} // namespace reference_ops +} // namespace tflite +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_L2NORMALIZATION_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/leaky_relu.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/leaky_relu.h new file mode 100644 index 000000000..06f691abd --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/leaky_relu.h @@ -0,0 +1,69 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LEAKY_RELU_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LEAKY_RELU_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_ops { + +inline void LeakyRelu(const tflite::LeakyReluParams& params, + const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + const float val = input_data[i]; + // Note that alpha might be > 1 or < 0, so we don't use std::max here. + output_data[i] = val > 0 ? val : val * params.alpha; + } +} + +template +inline void QuantizeLeakyRelu(const LeakyReluParams& params, + const RuntimeShape& input_shape, + const T* input_data, + const RuntimeShape& output_shape, + T* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + static const int32_t quantized_min = std::numeric_limits::min(); + static const int32_t quantized_max = std::numeric_limits::max(); + for (int i = 0; i < flat_size; ++i) { + const int32_t input_value = input_data[i] - params.input_offset; + int32_t unclamped_output; + if (input_value >= 0) { + unclamped_output = params.output_offset + + MultiplyByQuantizedMultiplier( + input_value, params.output_multiplier_identity, + params.output_shift_identity); + } else { + unclamped_output = params.output_offset + + MultiplyByQuantizedMultiplier( + input_value, params.output_multiplier_alpha, + params.output_shift_alpha); + } + const T clamped_output = + std::min(quantized_max, std::max(quantized_min, unclamped_output)); + output_data[i] = static_cast(clamped_output); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LEAKY_RELU_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/log_softmax.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/log_softmax.h new file mode 100644 index 000000000..67e6e667f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/log_softmax.h @@ -0,0 +1,256 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LOG_SOFTMAX_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LOG_SOFTMAX_H_ + +#include +#include +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_ops { + +inline void LogSoftmax(const SoftmaxParams& params, + const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + + for (int i = 0; i < outer_size; ++i) { + // Find max element value which we'll use to ensure numerical stability + // taking advantage of the following equality: + // log(exp(x[i])/sum(exp(x[i]))) == log(exp(x[i]+C)/sum(exp(x[i]+C))) + float max = std::numeric_limits::lowest(); + for (int c = 0; c < depth; ++c) { + max = std::max(max, input_data[i * depth + c]); + } + + // Compute sum. + float sum = 0.f; + for (int c = 0; c < depth; ++c) { + sum += std::exp(input_data[i * depth + c] - max); + } + + // Compute result. + const float log_sum = std::log(sum); + for (int c = 0; c < depth; ++c) { + output_data[i * depth + c] = input_data[i * depth + c] - max - log_sum; + } + } +} + +inline void LogSoftmax(const SoftmaxParams& params, + const RuntimeShape& input_shape, + const uint8_t* input_data, + const RuntimeShape& output_shape, uint8_t* output_data) { + const int32_t input_multiplier = params.input_multiplier; + const int32_t input_left_shift = params.input_left_shift; + const int32_t reverse_scaling_divisor = params.reverse_scaling_divisor; + const int32_t reverse_scaling_right_shift = + params.reverse_scaling_right_shift; + const int diff_min = params.diff_min; + // The representation chosen for the input to the exp() function is Q5.26. + // We need to leave extra space since values that we skip might be as large + // as -32 before multiplying by input_beta_multiplier, and therefore as + // large as -16 afterwards. Note that exp(-8) is definitely not + // insignificant to accumulation, but exp(-16) definitely is. + static constexpr int kScaledDiffIntegerBits = 5; + static constexpr int kAccumulationIntegerBits = 12; + static constexpr int kOutputIntegerBits = 4; + using FixedPointScaledDiff = + gemmlowp::FixedPoint; + using FixedPointAccum = + gemmlowp::FixedPoint; + + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + + for (int i = 0; i < outer_size; ++i) { + uint8_t max_in_row = 0; + for (int c = 0; c < depth; ++c) { + max_in_row = std::max(max_in_row, input_data[i * depth + c]); + } + + FixedPointAccum sum_of_exps = FixedPointAccum::Zero(); + for (int c = 0; c < depth; ++c) { + int32_t input_diff = + static_cast(input_data[i * depth + c]) - max_in_row; + if (input_diff >= diff_min) { + const int32_t input_diff_rescaled = + MultiplyByQuantizedMultiplierGreaterThanOne( + input_diff, input_multiplier, input_left_shift); + const FixedPointScaledDiff scaled_diff_f8 = + FixedPointScaledDiff::FromRaw(input_diff_rescaled); + sum_of_exps = sum_of_exps + gemmlowp::Rescale( + exp_on_negative_values(scaled_diff_f8)); + } + } + + const int32_t fixed_log_sum_of_exps = + log_x_for_x_greater_than_or_equal_to_1( + sum_of_exps) + .raw(); + + // rescaled_diff_min is smallest representable in + // Q(kScaledDiffIntegerBits).(31-kScaledDiffIntegerBits) plus the + // log-sub-exps that will be subtracted in the loop. + // + // The thresholds diff_min, etc are negative. + const int rescaled_diff_min = + fixed_log_sum_of_exps + std::numeric_limits::lowest(); + const int adjusted_diff_min = + std::max(static_cast( + diff_min - 1), // Note use of > below instead of >= above. + MultiplyByQuantizedMultiplierSmallerThanOneExp( + rescaled_diff_min, reverse_scaling_divisor, + -reverse_scaling_right_shift)); + + for (int c = 0; c < depth; ++c) { + int32_t input_diff = + static_cast(input_data[i * depth + c]) - max_in_row; + if (input_diff > adjusted_diff_min) { + const int32_t input_diff_rescaled = + MultiplyByQuantizedMultiplierGreaterThanOne( + input_diff, input_multiplier, input_left_shift); + int32_t unsat_output = + gemmlowp::RoundingDivideByPOT( + (input_diff_rescaled - fixed_log_sum_of_exps), + 31 - kScaledDiffIntegerBits - kOutputIntegerBits) + + 255; + + output_data[i * depth + c] = static_cast( + std::max(std::min(unsat_output, static_cast(255)), + static_cast(0))); + } else { + // Set output to smallest value. + output_data[i * depth + c] = 0; + } + } + } +} + +template +inline void LogSoftmaxQuantized(const SoftmaxParams& params, + const size_t outer_size, const size_t depth, + const RuntimeShape& input_shape, + const T* input_data, + const RuntimeShape& output_shape, + T* output_data) { + const int32_t input_multiplier = params.input_multiplier; + const int32_t input_left_shift = params.input_left_shift; + const int32_t reverse_scaling_divisor = params.reverse_scaling_divisor; + const int32_t reverse_scaling_right_shift = + params.reverse_scaling_right_shift; + const int diff_min = params.diff_min; + + static constexpr T kMinT8 = std::numeric_limits::min(); + static constexpr T kMaxT8 = std::numeric_limits::max(); + static constexpr int32_t kMinInt32 = std::numeric_limits::min(); + + // All IntegerBits must agree with Prepare function. + // Input is chosen as Q5.26 so exp(-1 * 2^5 * 2^-1) = exp(-16) is negligible. + static constexpr int kInputIntegerBits = 5; + static constexpr int kAccumulationIntegerBits = 12; + static constexpr int kOutputIntegerBits = 4; + using F5 = gemmlowp::FixedPoint; + using F12 = gemmlowp::FixedPoint; + + for (size_t outer_index = 0; outer_index < outer_size; ++outer_index) { + T max_in_row = kMinT8; + for (size_t inner_index = 0; inner_index < depth; ++inner_index) { + max_in_row = + std::max(max_in_row, input_data[outer_index * depth + inner_index]); + } + + // Accumulator "sum_of_exps_in_q12" is safe from overflowing in 2^12 steps. + F12 sum_of_exps_in_q12 = F12::FromRaw(0); + for (size_t inner_index = 0; inner_index < depth; ++inner_index) { + int32_t input_diff = + static_cast(input_data[outer_index * depth + inner_index]) - + max_in_row; + if (input_diff >= diff_min) { + const int32_t input_diff_in_q5 = MultiplyByQuantizedMultiplier( + input_diff, input_multiplier, input_left_shift); + sum_of_exps_in_q12 = + sum_of_exps_in_q12 + + gemmlowp::Rescale( + exp_on_negative_values(F5::FromRaw(input_diff_in_q5))); + } + } + + const int32_t log_sum_of_exps_in_q5 = + log_x_for_x_greater_than_or_equal_to_1( + sum_of_exps_in_q12) + .raw(); + + // Potentially reduced the valid range. shifted_log_sum_of_exps_in_q5 is + // smallest representable in Q5.26 plus the log_sum_of_exps. + const int32_t shifted_log_sum_of_exps_in_q5 = + log_sum_of_exps_in_q5 + kMinInt32; + const int32_t adjusted_diff_min = + std::max(static_cast(diff_min - 1), + MultiplyByQuantizedMultiplier(shifted_log_sum_of_exps_in_q5, + reverse_scaling_divisor, + -reverse_scaling_right_shift)); + + for (size_t inner_index = 0; inner_index < depth; ++inner_index) { + int32_t input_diff = + static_cast(input_data[outer_index * depth + inner_index]) - + max_in_row; + // Note use of > below instead of >= above. + if (input_diff > adjusted_diff_min) { + const int32_t input_diff_in_q5 = MultiplyByQuantizedMultiplier( + input_diff, input_multiplier, input_left_shift); + + // Rescale and downcast. + int32_t output_in_q27 = + gemmlowp::RoundingDivideByPOT( + (input_diff_in_q5 - log_sum_of_exps_in_q5), + 31 - kInputIntegerBits - kOutputIntegerBits) + + kMaxT8; + + output_in_q27 = + std::max(std::min(output_in_q27, static_cast(kMaxT8)), + static_cast(kMinT8)); + output_data[outer_index * depth + inner_index] = + static_cast(output_in_q27); + } else { + output_data[outer_index * depth + inner_index] = kMinT8; + } + } + } +} + +inline void LogSoftmax(const SoftmaxParams& params, const size_t outer_size, + const size_t depth, const RuntimeShape& input_shape, + const int8_t* input_data, + const RuntimeShape& output_shape, int8_t* output_data) { + LogSoftmaxQuantized(params, outer_size, depth, input_shape, input_data, + output_shape, output_data); +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LOG_SOFTMAX_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/logistic.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/logistic.h new file mode 100644 index 000000000..96b541517 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/logistic.h @@ -0,0 +1,132 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LOGISTIC_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LOGISTIC_H_ + +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/op_macros.h" + +namespace tflite { +namespace reference_ops { + +inline void Logistic(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const float cutoff_upper = 16.619047164916992188f; + const float cutoff_lower = -9.f; + + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + // Rational for using approximation in reference kernel. + // 0. This approximation gives enough precision for float. + // 1. This works around an issue on an embedded chipset where exp() does not + // return correctly as expected - exp(x) should return inf when overflown + // not 1.701417 IEEE 754 defines representation for inf. + // 2. This will speed up calculation and is matching the behavior in the + // optimized kernels. (check the definition of scalar_logistic_op) + + for (int i = 0; i < flat_size; i++) { + float val = input_data[i]; + float result; + if (val > cutoff_upper) { + result = 1.0f; + } else if (val < cutoff_lower) { + result = std::exp(val); + } else { + result = 1.f / (1.f + std::exp(-val)); + } + output_data[i] = result; + } +} + +// Convenience version that allows, for example, generated-code calls to be +// uniform between data types. +inline void Logistic(const LogisticParams&, const RuntimeShape& input_shape, + const float* input_data, const RuntimeShape& output_shape, + float* output_data) { + // Drop params: not needed. + Logistic(input_shape, input_data, output_shape, output_data); +} + +inline void Logistic(const LogisticParams& params, + const RuntimeShape& input_shape, const int16_t* input_data, + const RuntimeShape& output_shape, int16_t* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; i++) { + // F0 uses 0 integer bits, range [-1, 1]. + // This is the return type of math functions such as tanh, logistic, + // whose range is in [-1, 1]. + using F0 = gemmlowp::FixedPoint; + // F3 uses 3 integer bits, range [-8, 8], the input range expected here. + using F3 = gemmlowp::FixedPoint; + + const F3 input = F3::FromRaw(input_data[i]); + F0 output = gemmlowp::logistic(input); + output_data[i] = output.raw(); + } +} + +// Quantized int8_t logistic activation. Cheats by dequantizing and +// requantizing around the floating point logistic method. This implementation +// is slow on platforms without a floating point unit. + +// TODO(b/141211002): Delete this int8_t implementation once we can reuse the +// approach used in TFLite for int8_t Logistic. +inline void Logistic(const RuntimeShape& input_shape, const int8_t* input_data, + float input_scale, int input_zero_point, + const RuntimeShape& output_shape, int8_t* output_data, + float output_scale, int output_zero_point) { + const float cutoff_upper = 16.619047164916992188f; + const float cutoff_lower = -9.f; + + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + // Rational for using approximation in reference kernel. + // 0. This approximation gives enough precision for float. + // 1. This works around an issue on an embedded chipset where exp() does not + // return correctly as expected - exp(x) should return inf when overflown + // not 1.701417 IEEE 754 defines representation for inf. + // 2. This will speed up calculation and is matching the behavior in the + // optimized kernels. (check the definition of scalar_logistic_op) + + for (int i = 0; i < flat_size; i++) { + // Dequantize. + float val = + static_cast((input_data[i] - input_zero_point) * input_scale); + float result; + if (val > cutoff_upper) { + result = 1.0f; + } else if (val < cutoff_lower) { + result = std::exp(val); + } else { + result = 1.f / (1.f + std::exp(-val)); + } + // Requantize + int8_t output = + static_cast(result / output_scale + output_zero_point); + output_data[i] = output; + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LOGISTIC_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/lstm_cell.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/lstm_cell.h new file mode 100644 index 000000000..17b113eb9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/lstm_cell.h @@ -0,0 +1,422 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LSTM_CELL_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LSTM_CELL_H_ + +#include +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/reference/concatenation.h" +#include "tensorflow/lite/kernels/internal/reference/fully_connected.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +inline void LstmCell( + const LstmCellParams& params, const RuntimeShape& unextended_input_shape, + const float* input_data, const RuntimeShape& unextended_prev_activ_shape, + const float* prev_activ_data, const RuntimeShape& weights_shape, + const float* weights_data, const RuntimeShape& unextended_bias_shape, + const float* bias_data, const RuntimeShape& unextended_prev_state_shape, + const float* prev_state_data, + const RuntimeShape& unextended_output_state_shape, float* output_state_data, + const RuntimeShape& unextended_output_activ_shape, float* output_activ_data, + const RuntimeShape& unextended_concat_temp_shape, float* concat_temp_data, + const RuntimeShape& unextended_activ_temp_shape, float* activ_temp_data) { + TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_prev_activ_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_bias_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_prev_state_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_state_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_activ_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_concat_temp_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_activ_temp_shape.DimensionsCount(), 4); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape prev_activ_shape = + RuntimeShape::ExtendedShape(4, unextended_prev_activ_shape); + const RuntimeShape bias_shape = + RuntimeShape::ExtendedShape(4, unextended_bias_shape); + const RuntimeShape prev_state_shape = + RuntimeShape::ExtendedShape(4, unextended_prev_state_shape); + const RuntimeShape output_state_shape = + RuntimeShape::ExtendedShape(4, unextended_output_state_shape); + const RuntimeShape output_activ_shape = + RuntimeShape::ExtendedShape(4, unextended_output_activ_shape); + const RuntimeShape concat_temp_shape = + RuntimeShape::ExtendedShape(4, unextended_concat_temp_shape); + const RuntimeShape activ_temp_shape = + RuntimeShape::ExtendedShape(4, unextended_activ_temp_shape); + TFLITE_DCHECK_GE(weights_shape.DimensionsCount(), 2); + + const int weights_dim_count = weights_shape.DimensionsCount(); + const int batches = + MatchingDim(input_shape, 0, prev_activ_shape, 0, prev_state_shape, 0, + output_state_shape, 0, output_activ_shape, 0); + const int height = + MatchingDim(input_shape, 1, prev_activ_shape, 1, prev_state_shape, 1, + output_state_shape, 1, output_activ_shape, 1); + const int width = + MatchingDim(input_shape, 2, prev_activ_shape, 2, prev_state_shape, 2, + output_state_shape, 2, output_activ_shape, 2); + const int input_depth = input_shape.Dims(3); + const int prev_activ_depth = prev_activ_shape.Dims(3); + const int total_input_depth = prev_activ_depth + input_depth; + TFLITE_DCHECK_EQ(weights_shape.Dims(weights_dim_count - 1), + total_input_depth); + TFLITE_DCHECK_EQ(FlatSizeSkipDim(bias_shape, 3), 1); + const int intern_activ_depth = + MatchingDim(weights_shape, weights_dim_count - 2, bias_shape, 3); + TFLITE_DCHECK_EQ(weights_shape.FlatSize(), + intern_activ_depth * total_input_depth); + TFLITE_DCHECK_EQ(intern_activ_depth % 4, 0); + const int output_depth = + MatchingDim(prev_state_shape, 3, prev_activ_shape, 3, output_state_shape, + 3, output_activ_shape, 3); + TFLITE_DCHECK_EQ(output_depth, intern_activ_depth / 4); + + // Concatenate prev_activ and input data together + float const* concat_input_arrays_data[2] = {input_data, prev_activ_data}; + const RuntimeShape* concat_input_arrays_shapes[2] = {&input_shape, + &prev_activ_shape}; + tflite::ConcatenationParams concat_params; + concat_params.axis = 3; + concat_params.inputs_count = 2; + Concatenation(concat_params, concat_input_arrays_shapes, + concat_input_arrays_data, concat_temp_shape, concat_temp_data); + + // Fully connected + tflite::FullyConnectedParams fc_params; + fc_params.float_activation_min = std::numeric_limits::lowest(); + fc_params.float_activation_max = std::numeric_limits::max(); + FullyConnected(fc_params, concat_temp_shape, concat_temp_data, weights_shape, + weights_data, bias_shape, bias_data, activ_temp_shape, + activ_temp_data); + + // Memory state update (the LSTM "guts") + for (int b = 0; b < batches; ++b) { + for (int w = 0; w < width; ++w) { + for (int h = 0; h < height; ++h) { + for (int c = 0; c < output_depth; ++c) { + const float input_gate = + 1.f / + (1.f + std::exp(-activ_temp_data[Offset(activ_temp_shape, b, h, w, + 0 * output_depth + c)])); + const float new_input = std::tanh(activ_temp_data[Offset( + activ_temp_shape, b, h, w, 1 * output_depth + c)]); + const float forget_gate = + 1.f / + (1.f + std::exp(-activ_temp_data[Offset(activ_temp_shape, b, h, w, + 2 * output_depth + c)])); + const float output_gate = + 1.f / + (1.f + std::exp(-activ_temp_data[Offset(activ_temp_shape, b, h, w, + 3 * output_depth + c)])); + const float new_state = + input_gate * new_input + + forget_gate * + prev_state_data[Offset(prev_state_shape, b, h, w, c)]; + output_state_data[Offset(output_state_shape, b, h, w, c)] = new_state; + output_activ_data[Offset(output_activ_shape, b, h, w, c)] = + output_gate * std::tanh(new_state); + } + } + } + } +} + +// Quantized LSTM cell implementation. +// The quantization of the input, output arrays is as follows: +// - The input activations are quantized as uint8 on the interval +// [-1, 127/128]. +// The rationale for that is that is the natural interval for output +// activations (see next point) and these need to be concatenated together. +// We could accommodate different ranges by re-scaling, but we empirically +// found that setting the input activations range to be [-1, 127/128] in the +// first place, removing the need for re-scaling, greatly improves accuracy. +// - The output activations are quantized as uint8 on the interval +// [-1, 127/128]. +// The rationale for that is that the definition of a LSTM cell makes them +// intrinsically constrained in [-1, 1]; tweaking that to [-1, 127/128] +// makes for simpler, more accurate fixed-point arithmetic. +// - The output-at-previous-timestep state array is obviously quantized as +// the output activations. +// - The internal LSTM memory (not the output-at-previous-timestep, the other +// internal state array) is int16-quantized and may use any power-of-two, +// symmetric range i.e. [-2^N, 2^N * 32767/32768] for any N, which we call +// StateIntegerBits below, see the below discussion of that template +// parameter ("The StateIntegerBits template parameter"). +// - The output of the internal fully-connected node is int16-quantized +// on the interval [-8, 8 * 32767/32768], the rationale for which is +// explained just below ("Why [-8, 8] for fully-connected output?"). +// +// +// === The StateIntegerBits template parameter === +// +// The StateIntegerBits template parameter controls the fixed-point format used +// to represent the internal memory of the LSTM cell (not the +// output-at-previous-timestep, the other internal state array). It's currently +// a template parameter so that the model can control that. The most typical +// value for StateIntegerBits is 4. Other plausible values are anywhere between +// 3 and 5. We might eventually standardize on a single supported value, e.g. 4, +// and drop that template parameter. The reason why it can't be a runtime +// parameter is that this controls the fixed-point format used, i.e. we need to +// generate actually different code based on it. In particular, we generate code +// for a fixed-point tanh() implementation for that format, which internally +// uses a fixed-point exp() implementation, which internally uses a +// barrel-shifter with a number of steps that depends on StateIntegerBits. +// Another consequence of that is that a higher value of StateIntegerBits +// results in a more expensive implementation (more barrel shifter steps +// needed). +// +// +// === Why [-8, 8] for fully-connected output? === +// +// This array is only fed to Logistic and Tanh functions, for which +// the quantized implementation will want to use fixed-point arithmetic, +// requiring a power-of-two representation interval. Thus, we should right +// away quantize this array to a power-of-two interval; otherwise, +// implementation will need to rescale that, losing any benefit that a tighter +// representation interval might otherwise yield, while introducing some +// numerical error and computational overhead. +// +// Now, Logistic and Tanh +// are nearly constant (nearly equal to their horizontal asymptotes) +// outside of a small bounded interval around 0: +// +// Logistic(4) = 1 - 1.8e-2 Tanh(4) = 1 - 6.7e-4 +// Logistic(8) = 1 - 3.4e-4 Tanh(8) = 1 - 2.3e-7 +// Logistic(16) = 1 - 1.1e-7 Tanh(16) = 1 - 2.5e-14 +// +// From this, we see that clamping to [-4, 4] would be too inaccurate +// (the error of 1.8e-2 on Logistic would be felt even in 8bit precision) +// while clamping to [-16, 16] would make no difference even in float32. +// However, for a fixed-point implementation in 16-bit integers, using 5 +// integer bits to represent the [-16, 16] range would leave only 11 +// fractional bits, giving an increment of 2^-11 = 4.9e-4 between consecutive +// representable values. Notice that is higher than the +// worst-case clamping error with clamping to [-8, 8]: 3.4e-4 for Logistic. +// Using [-8, 8] thus seems like the better compromise overall, enjoying +// an increment of 2.4e-4 between representable values and a worst-case +// clamping error of 3.4e-4, both better than the increment of 4.9e-4 with +// [-16, 16]. +// +// Moreover, all other things being equal, it is nice to choose the narrower +// representation range, as that makes the implementation of fixed-point +// math functions a little cheaper (each integer bit requires an additional +// barrel-shifter atep in the implementation of exp(-x)). That is further +// reason to prefer [-8, 8] over [-16, 16]. The choice of [-16, 16] would make +// sense for 32-bit float or 32-bit fixed-point quantization, but we are +// aiming for 16-bit fixed-point quantization of these internal nodes here. +// +template +inline void LstmCell(const LstmCellParams& params, + const RuntimeShape& unextended_input_shape, + const uint8_t* input_data_uint8, + const RuntimeShape& unextended_prev_activ_shape, + const uint8_t* prev_activ_data_uint8, + const RuntimeShape& weights_shape, + const uint8_t* weights_data_uint8, + const RuntimeShape& unextended_bias_shape, + const int32_t* bias_data_int32, + const RuntimeShape& unextended_prev_state_shape, + const int16_t* prev_state_data_int16, + const RuntimeShape& unextended_output_state_shape, + int16_t* output_state_data_int16, + const RuntimeShape& unextended_output_activ_shape, + uint8_t* output_activ_data_uint8, + const RuntimeShape& unextended_concat_temp_shape, + uint8_t* concat_temp_data_uint8, + const RuntimeShape& unextended_activ_temp_shape, + int16_t* activ_temp_data_int16, void* gemmlowp_context) { + (void)gemmlowp_context; // only used in optimized code. + int32_t weights_zero_point = params.weights_zero_point; + int32_t accum_multiplier = params.accum_multiplier; + int accum_shift = params.accum_shift; + TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_prev_activ_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_bias_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_prev_state_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_state_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_activ_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_concat_temp_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_activ_temp_shape.DimensionsCount(), 4); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape prev_activ_shape = + RuntimeShape::ExtendedShape(4, unextended_prev_activ_shape); + const RuntimeShape bias_shape = + RuntimeShape::ExtendedShape(4, unextended_bias_shape); + const RuntimeShape prev_state_shape = + RuntimeShape::ExtendedShape(4, unextended_prev_state_shape); + const RuntimeShape output_state_shape = + RuntimeShape::ExtendedShape(4, unextended_output_state_shape); + const RuntimeShape output_activ_shape = + RuntimeShape::ExtendedShape(4, unextended_output_activ_shape); + const RuntimeShape concat_temp_shape = + RuntimeShape::ExtendedShape(4, unextended_concat_temp_shape); + const RuntimeShape activ_temp_shape = + RuntimeShape::ExtendedShape(4, unextended_activ_temp_shape); + TFLITE_DCHECK_GE(weights_shape.DimensionsCount(), 2); + + // Gather dimensions information, and perform consistency checks. + const int weights_dim_count = weights_shape.DimensionsCount(); + const int outer_size = MatchingFlatSizeSkipDim( + input_shape, 3, prev_activ_shape, prev_state_shape, output_state_shape, + output_activ_shape); + const int input_depth = input_shape.Dims(3); + const int prev_activ_depth = prev_activ_shape.Dims(3); + const int total_input_depth = prev_activ_depth + input_depth; + TFLITE_DCHECK_EQ(weights_shape.Dims(weights_dim_count - 1), + total_input_depth); + const int intern_activ_depth = + MatchingDim(weights_shape, weights_dim_count - 2, bias_shape, 3); + TFLITE_DCHECK_EQ(weights_shape.FlatSize(), + intern_activ_depth * total_input_depth); + TFLITE_DCHECK_EQ(FlatSizeSkipDim(bias_shape, 3), 1); + TFLITE_DCHECK_EQ(intern_activ_depth % 4, 0); + const int output_depth = + MatchingDim(prev_state_shape, 3, prev_activ_shape, 3, output_state_shape, + 3, output_activ_shape, 3); + TFLITE_DCHECK_EQ(output_depth, intern_activ_depth / 4); + const int fc_batches = FlatSizeSkipDim(activ_temp_shape, 3); + const int fc_output_depth = + MatchingDim(weights_shape, weights_dim_count - 2, activ_temp_shape, 3); + const int fc_accum_depth = total_input_depth; + TFLITE_DCHECK_EQ(fc_output_depth, 4 * output_depth); + + // Depth-concatenate prev_activ and input data together. + uint8_t const* concat_input_arrays_data[2] = {input_data_uint8, + prev_activ_data_uint8}; + const RuntimeShape* concat_input_arrays_shapes[2] = {&input_shape, + &prev_activ_shape}; + tflite::ConcatenationParams concat_params; + concat_params.axis = 3; + concat_params.inputs_count = 2; + Concatenation(concat_params, concat_input_arrays_shapes, + concat_input_arrays_data, concat_temp_shape, + concat_temp_data_uint8); + + // Implementation of the fully connected node inside the LSTM cell. + // The operands are 8-bit integers, the accumulators are internally 32bit + // integers, and the output is 16-bit fixed-point with 3 integer bits so + // the output range is [-2^3, 2^3] == [-8, 8]. The rationale for that + // is explained in the function comment above. + for (int b = 0; b < fc_batches; ++b) { + for (int out_c = 0; out_c < fc_output_depth; ++out_c) { + // Internal accumulation. + // Initialize accumulator with the bias-value. + int32_t accum = bias_data_int32[out_c]; + // Accumulation loop. + for (int d = 0; d < fc_accum_depth; ++d) { + int16_t input_val = + concat_temp_data_uint8[b * fc_accum_depth + d] - 128; + int16_t weights_val = + weights_data_uint8[out_c * fc_accum_depth + d] - weights_zero_point; + accum += input_val * weights_val; + } + // Down-scale the final int32 accumulator to the scale used by our + // (16-bit, using 3 integer bits) fixed-point format. The quantized + // multiplier and shift here have been pre-computed offline + // (e.g. by toco). + accum = + MultiplyByQuantizedMultiplier(accum, accum_multiplier, accum_shift); + // Saturate, cast to int16, and store to the temporary activations array. + accum = std::max(-32768, std::min(32767, accum)); + activ_temp_data_int16[out_c + fc_output_depth * b] = accum; + } + } + + // Rest of the LSTM cell: tanh and logistic math functions, and some adds + // and muls, all done in 16-bit fixed-point. + for (int b = 0; b < outer_size; ++b) { + for (int c = 0; c < output_depth; ++c) { + // Define the fixed-point data types that we will use here. All use + // int16 as the underlying integer type i.e. all are 16-bit fixed-point. + // They only differ by the number of integral vs. fractional bits, + // determining the range of values that they can represent. + // + // F0 uses 0 integer bits, range [-1, 1]. + // This is the return type of math functions such as tanh, logistic, + // whose range is in [-1, 1]. + using F0 = gemmlowp::FixedPoint; + // F3 uses 3 integer bits, range [-8, 8]. + // This is the range of the previous fully-connected node's output, + // which is our input here. + using F3 = gemmlowp::FixedPoint; + // FS uses StateIntegerBits integer bits, range [-2^StateIntegerBits, + // 2^StateIntegerBits]. It's used to represent the internal state, whose + // number of integer bits is currently dictated by the model. See comment + // on the StateIntegerBits template parameter above. + using FS = gemmlowp::FixedPoint; + // Implementation of input gate, using fixed-point logistic function. + F3 input_gate_input = F3::FromRaw( + activ_temp_data_int16[b * fc_output_depth + 0 * output_depth + c]); + F0 input_gate_output = gemmlowp::logistic(input_gate_input); + // Implementation of input modulation gate, using fixed-point tanh + // function. + F3 input_modulation_gate_input = F3::FromRaw( + activ_temp_data_int16[b * fc_output_depth + 1 * output_depth + c]); + F0 input_modulation_gate_output = + gemmlowp::tanh(input_modulation_gate_input); + // Implementation of forget gate, using fixed-point logistic function. + F3 forget_gate_input = F3::FromRaw( + activ_temp_data_int16[b * fc_output_depth + 2 * output_depth + c]); + F0 forget_gate_output = gemmlowp::logistic(forget_gate_input); + // Implementation of output gate, using fixed-point logistic function. + F3 output_gate_input = F3::FromRaw( + activ_temp_data_int16[b * fc_output_depth + 3 * output_depth + c]); + F0 output_gate_output = gemmlowp::logistic(output_gate_input); + // Implementation of internal multiplication nodes, still in fixed-point. + F0 input_times_input_modulation = + input_gate_output * input_modulation_gate_output; + FS prev_state = FS::FromRaw(prev_state_data_int16[b * output_depth + c]); + FS prev_state_times_forget_state = forget_gate_output * prev_state; + // Implementation of internal addition node, saturating. + FS new_state = gemmlowp::SaturatingAdd( + gemmlowp::Rescale(input_times_input_modulation), + prev_state_times_forget_state); + // Implementation of last internal Tanh node, still in fixed-point. + // Since a Tanh fixed-point implementation is specialized for a given + // number or integer bits, and each specialization can have a substantial + // code size, and we already used above a Tanh on an input with 3 integer + // bits, and per the table in the above function comment there is no + // significant accuracy to be lost by clamping to [-8, +8] for a + // 3-integer-bits representation, let us just do that. This helps people + // porting this to targets where code footprint must be minimized. + F3 new_state_f3 = gemmlowp::Rescale<3>(new_state); + F0 output_activ_int16 = output_gate_output * gemmlowp::tanh(new_state_f3); + // Store the new internal state back to memory, as 16-bit integers. + // Note: here we store the original value with StateIntegerBits, not + // the rescaled 3-integer-bits value fed to tanh. + output_state_data_int16[b * output_depth + c] = new_state.raw(); + // Down-scale the output activations to 8-bit integers, saturating, + // and store back to memory. + int16_t rescaled_output_activ = + gemmlowp::RoundingDivideByPOT(output_activ_int16.raw(), 8); + int16_t clamped_output_activ = std::max( + -128, std::min(127, rescaled_output_activ)); + output_activ_data_uint8[b * output_depth + c] = + 128 + clamped_output_activ; + } + } +} + +} // namespace reference_ops +} // namespace tflite +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_LSTM_CELL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/maximum_minimum.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/maximum_minimum.h new file mode 100644 index 000000000..cd11b4191 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/maximum_minimum.h @@ -0,0 +1,64 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_MAXIMUM_MINIMUM_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_MAXIMUM_MINIMUM_H_ + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +void MaximumMinimumBroadcastSlow(const RuntimeShape& unextended_input1_shape, + const T* input1_data, + const RuntimeShape& unextended_input2_shape, + const T* input2_data, + const RuntimeShape& unextended_output_shape, + T* output_data, Op op) { + // Uses element-wise calculation if broadcast is not required. + if (unextended_input1_shape == unextended_input2_shape) { + const int flat_size = + MatchingElementsSize(unextended_input1_shape, unextended_input2_shape, + unextended_output_shape); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = op(input1_data[i], input2_data[i]); + } + } else { + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), N); + + NdArrayDesc desc1; + NdArrayDesc desc2; + NdArrayDesc output_desc; + NdArrayDescsForElementwiseBroadcast( + unextended_input1_shape, unextended_input2_shape, &desc1, &desc2); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, unextended_output_shape), + &output_desc); + + auto maxmin_func = [&](int indexes[N]) { + output_data[SubscriptToIndex(output_desc, indexes)] = + op(input1_data[SubscriptToIndex(desc1, indexes)], + input2_data[SubscriptToIndex(desc2, indexes)]); + }; + NDOpsHelper(output_desc, maxmin_func); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_MAXIMUM_MINIMUM_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/mul.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/mul.h new file mode 100644 index 000000000..531977327 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/mul.h @@ -0,0 +1,214 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_MUL_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_MUL_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { + +namespace reference_ops { + +// Element-wise mul that can often be used for inner loop of broadcast Mul as +// well as the non-broadcast Mul. +inline void MulElementwise(int size, const ArithmeticParams& params, + const uint8_t* input1_data, + const uint8_t* input2_data, uint8_t* output_data) { + for (int i = 0; i < size; ++i) { + const int32_t input1_val = params.input1_offset + input1_data[i]; + const int32_t input2_val = params.input2_offset + input2_data[i]; + const int32_t unclamped_result = + params.output_offset + + MultiplyByQuantizedMultiplier(input1_val * input2_val, + params.output_multiplier, + params.output_shift); + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, unclamped_result)); + output_data[i] = static_cast(clamped_output); + } +} + +template +inline void Mul(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const T* input1_data, + const RuntimeShape& input2_shape, const T* input2_data, + const RuntimeShape& output_shape, T* output_data) { + T output_activation_min; + T output_activation_max; + GetActivationParams(params, &output_activation_min, &output_activation_max); + + const int flat_size = + MatchingExtendedShapeFlatSize(input1_shape, input2_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = ActivationFunctionWithMinMax( + input1_data[i] * input2_data[i], output_activation_min, + output_activation_max); + } +} + +inline void Mul(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const std::complex* input1_data, + const RuntimeShape& input2_shape, + const std::complex* input2_data, + const RuntimeShape& output_shape, + std::complex* output_data) { + const int flat_size = + MatchingExtendedShapeFlatSize(input1_shape, input2_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = input1_data[i] * input2_data[i]; + } +} + +inline void Mul(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const uint8_t* input1_data, + const RuntimeShape& input2_shape, const uint8_t* input2_data, + const RuntimeShape& output_shape, uint8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + const int flat_size = + MatchingExtendedShapeFlatSize(input1_shape, input2_shape, output_shape); + + MulElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +inline void BroadcastMul4DSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const uint8_t* input1_data, + const RuntimeShape& input2_shape, + const uint8_t* input2_data, + const RuntimeShape& output_shape, + uint8_t* output_data) { + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + const RuntimeShape extended_output_shape = + RuntimeShape::ExtendedShape(4, output_shape); + + for (int b = 0; b < extended_output_shape.Dims(0); ++b) { + for (int y = 0; y < extended_output_shape.Dims(1); ++y) { + for (int x = 0; x < extended_output_shape.Dims(2); ++x) { + for (int c = 0; c < extended_output_shape.Dims(3); ++c) { + const int32_t input1_val = + params.input1_offset + + input1_data[SubscriptToIndex(desc1, b, y, x, c)]; + const int32_t input2_val = + params.input2_offset + + input2_data[SubscriptToIndex(desc2, b, y, x, c)]; + const int32_t unclamped_result = + params.output_offset + + MultiplyByQuantizedMultiplier(input1_val * input2_val, + params.output_multiplier, + params.output_shift); + const int32_t clamped_output = std::min( + params.quantized_activation_max, + std::max(params.quantized_activation_min, unclamped_result)); + output_data[Offset(extended_output_shape, b, y, x, c)] = + static_cast(clamped_output); + } + } + } + } +} + +template +void BroadcastMul4DSlow(const ArithmeticParams& params, + const RuntimeShape& unextended_input1_shape, + const T* input1_data, + const RuntimeShape& unextended_input2_shape, + const T* input2_data, + const RuntimeShape& unextended_output_shape, + T* output_data) { + T output_activation_min; + T output_activation_max; + GetActivationParams(params, &output_activation_min, &output_activation_max); + + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, + unextended_input2_shape, &desc1, &desc2); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + for (int b = 0; b < output_shape.Dims(0); ++b) { + for (int y = 0; y < output_shape.Dims(1); ++y) { + for (int x = 0; x < output_shape.Dims(2); ++x) { + for (int c = 0; c < output_shape.Dims(3); ++c) { + output_data[Offset(output_shape, b, y, x, c)] = + ActivationFunctionWithMinMax( + input1_data[SubscriptToIndex(desc1, b, y, x, c)] * + input2_data[SubscriptToIndex(desc2, b, y, x, c)], + output_activation_min, output_activation_max); + } + } + } + } +} + +inline void BroadcastMul4DSlow(const ArithmeticParams& params, + const RuntimeShape& unextended_input1_shape, + const std::complex* input1_data, + const RuntimeShape& unextended_input2_shape, + const std::complex* input2_data, + const RuntimeShape& unextended_output_shape, + std::complex* output_data) { + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, + unextended_input2_shape, &desc1, &desc2); + + for (int b = 0; b < output_shape.Dims(0); ++b) { + for (int y = 0; y < output_shape.Dims(1); ++y) { + for (int x = 0; x < output_shape.Dims(2); ++x) { + for (int c = 0; c < output_shape.Dims(3); ++c) { + output_data[Offset(output_shape, b, y, x, c)] = + input1_data[SubscriptToIndex(desc1, b, y, x, c)] * + input2_data[SubscriptToIndex(desc2, b, y, x, c)]; + } + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_MUL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/neg.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/neg.h new file mode 100644 index 000000000..e127883f9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/neg.h @@ -0,0 +1,37 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_NEG_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_NEG_H_ + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +template +inline void Negate(const RuntimeShape& input_shape, const T* input_data, + const RuntimeShape& output_shape, T* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; ++i) { + output_data[i] = -input_data[i]; + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_NEG_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/pad.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/pad.h new file mode 100644 index 000000000..275894458 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/pad.h @@ -0,0 +1,169 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PAD_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PAD_H_ + +#include + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +// TFLite Pad supports activation tensors with up to 5 dimensions. +constexpr int PadKernelMaxDimensionCount() { return 5; } + +// There are two versions of pad: Pad and PadV2. In PadV2 there is a second +// scalar input that provides the padding value. Therefore pad_value_ptr can be +// equivalent to a simple input1_data. For Pad, it should point to a zero +// value. +// +// Note that two typenames are required, so that T=P=int32_t is considered a +// specialization distinct from P=int32_t. +template +inline void PadImpl(const tflite::PadParams& op_params, + const RuntimeShape& input_shape, const T* input_data, + const P* pad_value_ptr, const RuntimeShape& output_shape, + T* output_data) { + const RuntimeShape ext_input_shape = + RuntimeShape::ExtendedShape(PadKernelMaxDimensionCount(), input_shape); + const RuntimeShape ext_output_shape = + RuntimeShape::ExtendedShape(PadKernelMaxDimensionCount(), output_shape); + TFLITE_DCHECK_LE(op_params.left_padding_count, PadKernelMaxDimensionCount()); + TFLITE_DCHECK_LE(op_params.right_padding_count, PadKernelMaxDimensionCount()); + + // Runtime calls are currently fixed at 5 dimensions. Copy inputs so we can + // pad them to 5 dims (yes, we are "padding the padding"). + int left_padding_copy[PadKernelMaxDimensionCount()]; + for (int i = 0; i < PadKernelMaxDimensionCount(); i++) { + left_padding_copy[i] = 0; + } + for (int i = 0; i < op_params.left_padding_count; ++i) { + left_padding_copy[i + PadKernelMaxDimensionCount() - + op_params.left_padding_count] = op_params.left_padding[i]; + } + int right_padding_copy[PadKernelMaxDimensionCount()]; + for (int i = 0; i < PadKernelMaxDimensionCount(); i++) { + right_padding_copy[i] = 0; + } + for (int i = 0; i < op_params.right_padding_count; ++i) { + right_padding_copy[i + PadKernelMaxDimensionCount() - + op_params.right_padding_count] = + op_params.right_padding[i]; + } + + const int output_batch = ext_output_shape.Dims(0); + const int output_plane = ext_output_shape.Dims(1); + const int output_height = ext_output_shape.Dims(2); + const int output_width = ext_output_shape.Dims(3); + const int output_depth = ext_output_shape.Dims(4); + + const int left_b_padding = left_padding_copy[0]; + const int left_p_padding = left_padding_copy[1]; + const int left_h_padding = left_padding_copy[2]; + const int left_w_padding = left_padding_copy[3]; + const int left_d_padding = left_padding_copy[4]; + + const int right_b_padding = right_padding_copy[0]; + const int right_p_padding = right_padding_copy[1]; + const int right_h_padding = right_padding_copy[2]; + const int right_w_padding = right_padding_copy[3]; + const int right_d_padding = right_padding_copy[4]; + + const T pad_value = *pad_value_ptr; + + const T* in_ptr = input_data; + T* out_ptr = output_data; + for (int out_b = 0; out_b < output_batch; ++out_b) { + for (int out_p = 0; out_p < output_plane; ++out_p) { + for (int out_h = 0; out_h < output_height; ++out_h) { + for (int out_w = 0; out_w < output_width; ++out_w) { + for (int out_d = 0; out_d < output_depth; ++out_d) { + if (out_b < left_b_padding || + out_b >= output_batch - right_b_padding || + out_p < left_p_padding || + out_p >= output_plane - right_p_padding || + out_h < left_h_padding || + out_h >= output_height - right_h_padding || + out_w < left_w_padding || + out_w >= output_width - right_w_padding || + out_d < left_d_padding || + out_d >= output_depth - right_d_padding) { + *out_ptr++ = pad_value; + } else { + *out_ptr++ = *in_ptr++; + } + } + } + } + } + } +} + +template +inline void Pad(const tflite::PadParams& op_params, + const RuntimeShape& input_shape, const T* input_data, + const P* pad_value_ptr, const RuntimeShape& output_shape, + T* output_data) { + PadImpl(op_params, input_shape, input_data, pad_value_ptr, output_shape, + output_data); +} + +// The second (pad-value) input can be int32_t when, say, the first is uint8_t. +template +inline void Pad(const tflite::PadParams& op_params, + const RuntimeShape& input_shape, const T* input_data, + const int32_t* pad_value_ptr, const RuntimeShape& output_shape, + T* output_data) { + const T converted_pad_value = static_cast(*pad_value_ptr); + PadImpl(op_params, input_shape, input_data, &converted_pad_value, + output_shape, output_data); +} + +// This version avoids conflicting template matching. +template <> +inline void Pad(const tflite::PadParams& op_params, + const RuntimeShape& input_shape, const int32_t* input_data, + const int32_t* pad_value_ptr, const RuntimeShape& output_shape, + int32_t* output_data) { + PadImpl(op_params, input_shape, input_data, pad_value_ptr, output_shape, + output_data); +} + +template +inline void PadImageStyle(const tflite::PadParams& op_params, + const RuntimeShape& input_shape, const T* input_data, + const P* pad_value_ptr, + const RuntimeShape& output_shape, T* output_data) { + Pad(op_params, input_shape, input_data, pad_value_ptr, output_shape, + output_data); +} + +template +inline void PadImageStyle(const tflite::PadParams& op_params, + const RuntimeShape& input_shape, + const float* input_data, const P* pad_value_ptr, + const RuntimeShape& output_shape, + float* output_data) { + Pad(op_params, input_shape, input_data, pad_value_ptr, output_shape, + output_data); +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PAD_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/pooling.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/pooling.h new file mode 100644 index 000000000..fe17484cf --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/pooling.h @@ -0,0 +1,303 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_POOLING_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_POOLING_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +inline bool AveragePool(const PoolParams& params, + const RuntimeShape& input_shape, + const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + float total = 0.f; + float filter_count = 0; + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + total += + input_data[Offset(input_shape, batch, in_y, in_x, channel)]; + filter_count++; + } + } + if (filter_count == 0) return false; + const float average = total / filter_count; + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + ActivationFunctionWithMinMax(average, params.float_activation_min, + params.float_activation_max); + } + } + } + } + return true; +} + +inline bool AveragePool(const PoolParams& params, + const RuntimeShape& input_shape, + const uint8_t* input_data, + const RuntimeShape& output_shape, + uint8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + int32_t acc = 0; + int filter_count = 0; + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + acc += + input_data[Offset(input_shape, batch, in_y, in_x, channel)]; + filter_count++; + } + } + if (filter_count == 0) return false; + acc = (acc + filter_count / 2) / filter_count; + acc = std::max(acc, params.quantized_activation_min); + acc = std::min(acc, params.quantized_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + static_cast(acc); + } + } + } + } + return true; +} + +inline void L2Pool(const PoolParams& params, const RuntimeShape& input_shape, + const float* input_data, const RuntimeShape& output_shape, + float* output_data) { + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + float sum_squares = 0.f; + int filter_count = 0; + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + const float val = + input_data[Offset(input_shape, batch, in_y, in_x, channel)]; + sum_squares += val * val; + filter_count++; + } + } + const float l2pool_result = std::sqrt(sum_squares / filter_count); + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + ActivationFunctionWithMinMax(l2pool_result, + params.float_activation_min, + params.float_activation_max); + } + } + } + } +} + +inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape, + const float* input_data, const RuntimeShape& output_shape, + float* output_data) { + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + float max = std::numeric_limits::lowest(); + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + max = std::max( + max, + input_data[Offset(input_shape, batch, in_y, in_x, channel)]); + } + } + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + ActivationFunctionWithMinMax(max, params.float_activation_min, + params.float_activation_max); + } + } + } + } +} + +inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape, + const uint8_t* input_data, const RuntimeShape& output_shape, + uint8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + TFLITE_DCHECK_GE(params.quantized_activation_min, 0); + TFLITE_DCHECK_LE(params.quantized_activation_max, 255); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + uint8_t max = 0; + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + max = std::max( + max, + input_data[Offset(input_shape, batch, in_y, in_x, channel)]); + } + } + max = std::max(max, params.quantized_activation_min); + max = std::min(max, params.quantized_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + static_cast(max); + } + } + } + } +} +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_POOLING_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cpp new file mode 100644 index 000000000..3796f5db4 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cpp @@ -0,0 +1,809 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include +#include +#include +#include +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h" + +#if defined(_MSC_VER) +#define __restrict__ __restrict +#endif + +namespace tflite { +namespace tensor_utils { + +namespace { +const int32_t kInt16Max = std::numeric_limits::max(); +const int32_t kInt16Min = std::numeric_limits::min(); +} // namespace + +void PortableSymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float* min_value, + float* max_value, float* scaling_factor) { + auto minmax = std::minmax_element(values, values + size); + *min_value = *minmax.first; + *max_value = *minmax.second; + + PortableSymmetricQuantizeFloats(values, size, quantized_values, *min_value, + *max_value, scaling_factor); +} + +void PortableSymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float min_value, + float max_value, float* scaling_factor) { + const int32_t kScale = 127; + const float range = std::max(std::abs(min_value), std::abs(max_value)); + if (range == 0) { + memset(quantized_values, 0, size * sizeof(int8_t)); + *scaling_factor = 1; + return; + } + *scaling_factor = range / kScale; + const float scaling_factor_inv = kScale / range; + for (int i = 0; i < size; ++i) { + const int32_t quantized_value = + static_cast(TfLiteRound(values[i] * scaling_factor_inv)); + // Clamp: just in case some odd numeric offset. + quantized_values[i] = static_cast( + std::min(kScale, std::max(-kScale, quantized_value))); + } +} + +void PortableAsymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, + float* scaling_factor, int32_t* offset) { + const int32_t kMinScale = -128; + const int32_t kMaxScale = 127; + const double qmin_double = kMinScale; + const double qmax_double = kMaxScale; + const auto minmax = std::minmax_element(values, values + size); + const double rmin = static_cast(std::min(0.0f, *minmax.first)); + const double rmax = static_cast(std::max(0.0f, *minmax.second)); + if (rmin == rmax) { + memset(quantized_values, 0, size * sizeof(int8_t)); + *scaling_factor = 1; + *offset = 0; + return; + } else { + double scale = (rmax - rmin) / (qmax_double - qmin_double); + const double zero_point_from_min = qmin_double - rmin / scale; + const double zero_point_from_max = qmax_double - rmax / scale; + const double zero_point_from_min_error = + std::abs(qmin_double) + std::abs(rmin / scale); + const double zero_point_from_max_error = + std::abs(qmax_double) + std::abs(rmax / scale); + const double zero_point_double = + zero_point_from_min_error < zero_point_from_max_error + ? zero_point_from_min + : zero_point_from_max; + int8_t nudged_zero_point = 0; + if (zero_point_double <= qmin_double) { + nudged_zero_point = kMinScale; + } else if (zero_point_double >= qmax_double) { + nudged_zero_point = kMaxScale; + } else { + nudged_zero_point = static_cast(round(zero_point_double)); + } + *scaling_factor = scale; + *offset = nudged_zero_point; + } + const float scaling_factor_inv = 1.0f / *scaling_factor; + for (int i = 0; i < size; ++i) { + const int32_t quantized_value = static_cast( + TfLiteRound(*offset + values[i] * scaling_factor_inv)); + quantized_values[i] = + std::min(kMaxScale, std::max(kMinScale, quantized_value)); + } +} + +void PortableMatrixBatchVectorMultiplyAccumulate(const float* matrix, + int m_rows, int m_cols, + const float* vector, + int n_batch, float* result) { + float* result_in_batch = result; + for (int b = 0; b < n_batch; b++) { + const float* matrix_ptr = matrix; + for (int r = 0; r < m_rows; r++) { + float dot_prod = 0.0f; + const float* vector_in_batch = vector + b * m_cols; + for (int c = 0; c < m_cols; c++) { + dot_prod += *matrix_ptr++ * *vector_in_batch++; + } + *result_in_batch += dot_prod; + ++result_in_batch; + } + } +} + +void PortableMatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, const float* scaling_factors, + int n_batch, float* __restrict__ result) { + for (int batch = 0; batch < n_batch; ++batch, vectors += m_cols) { + const float batch_scaling_factor = scaling_factors[batch]; + // Get the address of the first row. + const int8_t* row_ptr = matrix; + for (int row = 0; row < m_rows; ++row) { + // Initialize the dot product sum for the row to 0. + int32_t dotprod = 0; +#if defined(__GNUC__) + // Prefetch the row to cache. + __builtin_prefetch(row_ptr, 0 /* prefetch for read */, + 3 /* temporal locality */); +#endif + for (int col = 0; col < m_cols; ++col, ++row_ptr) { + dotprod += (*row_ptr) * (vectors[col]); + } // for col + *result += dotprod * batch_scaling_factor; + ++result; + } // for row + } // for batch +} + +void PortableMatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, const float* scaling_factors, + int n_batch, float* __restrict__ result, const float* per_channel_scale, + const int32_t* input_offset, int32_t* scratch, int32_t* row_sums, + bool* compute_row_sums, CpuBackendContext* context) { + if (input_offset == nullptr) { + PortableMatrixBatchVectorMultiplyAccumulate( + matrix, m_rows, m_cols, vectors, scaling_factors, n_batch, result); + return; + } + if (!compute_row_sums || *compute_row_sums) { + PortableReductionSumVector(matrix, row_sums, m_rows, m_cols); + if (compute_row_sums) { + *compute_row_sums = false; + } + } + + for (int batch = 0; batch < n_batch; ++batch, vectors += m_cols) { + const float batch_scaling_factor = scaling_factors[batch]; + const int32_t batch_offset = input_offset[batch]; + const int8_t* row_ptr = matrix; + for (int row = 0; row < m_rows; ++row) { + int32_t dotprod = 0; + float scale = batch_scaling_factor; + if (per_channel_scale) { + scale *= per_channel_scale[row]; + } +#if defined(__GNUC__) + // Prefetch the row to cache. + __builtin_prefetch(row_ptr, 0 /* prefetch for read */, + 3 /* temporal locality */); +#endif + for (int col = 0; col < m_cols; ++col, ++row_ptr) { + dotprod += (*row_ptr) * vectors[col]; + } // for col + dotprod -= row_sums[row] * batch_offset; + *result += dotprod * scale; + ++result; + } // for row + } // for batch +} + +void PortableSparseMatrixBatchVectorMultiplyAccumulate1x4( + const float* __restrict__ matrix, const int32_t* __restrict__ segments, + const int32_t* __restrict__ indices, int m_rows, int m_cols, + const float* __restrict__ vector, int n_batch, float* __restrict__ result) { + const int kBlockSize = 4; + TFLITE_DCHECK_EQ(m_cols % kBlockSize, 0); + for (int batch = 0; batch < n_batch; batch++) { + const float* matrix_ptr = matrix; + for (int row = 0; row < m_rows; row++) { + float dot_prod = 0.0f; + const float* vector_in_batch = vector + batch * m_cols; + for (int i = segments[row]; i < segments[row + 1]; i++) { + const int block_start_index = indices[i] * kBlockSize; + const float* vector_block_in_batch_ptr = + vector_in_batch + block_start_index; + for (int c = 0; c < kBlockSize; c++) { + dot_prod += *matrix_ptr++ * *vector_block_in_batch_ptr++; + } + } + result[batch * m_rows + row] += dot_prod; + } + } +} + +void PortableSparseMatrixBatchVectorMultiplyAccumulate1x16( + const int8_t* __restrict__ matrix, const int32_t* __restrict__ segments, + const int32_t* __restrict__ indices, int m_rows, int m_cols, + const int8_t* __restrict__ vector, const int32_t* __restrict__ bias_vector, + int n_batch, const int32_t input_offset, const int32_t output_multiplier, + const int32_t output_shift, const int32_t output_offset, + const int32_t output_activation_min, const int32_t output_activation_max, + int8_t* __restrict__ result) { + const int kBlockSize = 16; + TFLITE_DCHECK_EQ(m_cols % kBlockSize, 0); + for (int batch = 0; batch < n_batch; ++batch) { + const int8_t* matrix_ptr = matrix; + for (int row = 0; row < m_rows; ++row) { + int32_t dot_prod = 0; + const int8_t* vector_in_batch = vector + batch * m_cols; + for (int i = segments[row]; i < segments[row + 1]; ++i) { + const int block_start_index = indices[i] * kBlockSize; + const int8_t* vector_block_in_batch_ptr = + vector_in_batch + block_start_index; + for (int c = 0; c < kBlockSize; c++) { + dot_prod += *matrix_ptr * *vector_block_in_batch_ptr++; + dot_prod += *matrix_ptr++ * input_offset; + } + } + const int32_t bias_value = bias_vector != nullptr ? bias_vector[row] : 0; + dot_prod = MultiplyByQuantizedMultiplier(dot_prod + bias_value, + output_multiplier, output_shift); + dot_prod += output_offset; + result[batch * m_rows + row] = + static_cast(ActivationFunctionWithMinMax( + dot_prod, output_activation_min, output_activation_max)); + } + } +} + +void PortableSparseMatrixBatchVectorMultiplyAccumulate( + const float* __restrict__ matrix, const uint8_t* __restrict__ ledger, + int m_rows, int m_cols, const float* __restrict__ vector, int n_batch, + float* __restrict__ result) { + const int kBlockSize = 16; + TFLITE_DCHECK_EQ( // NOLINT + m_cols % kBlockSize, 0); + for (int batch = 0; batch < n_batch; batch++) { + const float* matrix_ptr = matrix; + const uint8_t* ledger_ptr = ledger; + for (int row = 0; row < m_rows; row++) { + float dot_prod = 0.0f; + int num_nonzero_blocks = *ledger_ptr++; + if (num_nonzero_blocks > 0) { + const float* vector_in_batch = vector + batch * m_cols; + for (int i = 0; i < num_nonzero_blocks; i++) { + const int block_start_index = *ledger_ptr++ * kBlockSize; + const float* vector_block_in_batch_ptr = + vector_in_batch + block_start_index; + for (int c = 0; c < kBlockSize; c++) { + dot_prod += *matrix_ptr++ * *vector_block_in_batch_ptr++; + } + } + } + result[batch * m_rows + row] += dot_prod; + } + } +} + +void PortableSparseMatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const uint8_t* ledger, const int m_rows, + const int m_cols, const int8_t* __restrict__ vectors, + const float* scaling_factors, int n_batch, float* __restrict__ result) { + static const int kBlockSize = 16; + TFLITE_DCHECK_EQ( // NOLINT + m_cols % kBlockSize, 0); + for (int batch = 0; batch < n_batch; ++batch, vectors += m_cols) { + const float batch_scaling_factor = scaling_factors[batch]; + const uint8_t* ledger_ptr = ledger; + // Get the address of the first row. + const int8_t* row_ptr = matrix; + for (int row = 0; row < m_rows; ++row) { + // Initialize the dot product sum for the row to 0. + int32_t dotprod = 0; +#if defined(__GNUC__) + // Prefetch the row to cache. + __builtin_prefetch(row_ptr, 0 /* prefetch for read */, + 3 /* temporal locality */); +#endif + int num_nonzero_blocks = *ledger_ptr++; + for (int i = 0; i < num_nonzero_blocks; i++) { + const int block_start_index = *ledger_ptr++ * kBlockSize; + const int8_t* vector_block_ptr = vectors + block_start_index; + for (int c = 0; c < kBlockSize; c++) { + dotprod += (*row_ptr++) * (*vector_block_ptr++); + } // for block + } // for num_nonzero_blocks + result[batch * m_rows + row] += dotprod * batch_scaling_factor; + } // for row + } // for batch +} + +template +void PortableMatrixBatchVectorMultiplyAccumulateImpl( + const int8_t* input, const int32_t* bias, + const int8_t* input_to_gate_weights, int32_t multiplier, int32_t shift, + int32_t n_batch, int32_t n_input, int32_t n_output, int32_t output_zp, + T* output) { + const int16_t output_max = std::numeric_limits::max(); + const int16_t output_min = std::numeric_limits::min(); + for (int batch = 0; batch < n_batch; ++batch) { + for (int row = 0; row < n_output; ++row) { + int32_t acc = bias[row]; + for (int col = 0; col < n_input; ++col) { + int8_t input_val = input[batch * n_input + col]; + int8_t weights_val = input_to_gate_weights[row * n_input + col]; + acc += input_val * weights_val; + } + acc = MultiplyByQuantizedMultiplier(acc, multiplier, shift); + acc += output_zp; + acc += output[batch * n_output + row]; + if (acc > output_max) { + acc = output_max; + } + if (acc < output_min) { + acc = output_min; + } + output[batch * n_output + row] = static_cast(acc); + } + } +} + +void PortableMatrixBatchVectorMultiplyAccumulate( + const int8_t* input, const int32_t* bias, + const int8_t* input_to_gate_weights, int32_t multiplier, int32_t shift, + int32_t n_batch, int32_t n_input, int32_t n_output, int32_t output_zp, + int32_t* scratch, int16_t* output, CpuBackendContext* context) { + PortableMatrixBatchVectorMultiplyAccumulateImpl( + input, bias, input_to_gate_weights, multiplier, shift, n_batch, n_input, + n_output, output_zp, output); +} + +void PortableMatrixBatchVectorMultiplyAccumulate( + const int8_t* input, const int32_t* bias, + const int8_t* input_to_gate_weights, int32_t multiplier, int32_t shift, + int32_t n_batch, int32_t n_input, int32_t n_output, int32_t output_zp, + int32_t* scratch, int8_t* output, CpuBackendContext* context) { + PortableMatrixBatchVectorMultiplyAccumulateImpl( + input, bias, input_to_gate_weights, multiplier, shift, n_batch, n_input, + n_output, output_zp, output); +} + +void PortableMatrixBatchVectorMultiply(const int8_t* input, + int32_t input_zeropoint, + const int8_t* input_to_gate_weights, + int32_t input_to_gate_effective_scale_a, + int32_t input_to_gate_effective_scale_b, + int32_t n_batch, int32_t n_input, + int32_t n_cell, int8_t* gate_output, + int8_t gate_output_zp) { + const int32_t int8_max = std::numeric_limits::max(); + const int32_t int8_min = std::numeric_limits::min(); + for (int batch = 0; batch < n_batch; ++batch) { + for (int row = 0; row < n_cell; ++row) { + int32_t acc = 0; + for (int col = 0; col < n_input; ++col) { + int32_t input_val = input[batch * n_input + col]; + int8_t weights_val = input_to_gate_weights[row * n_input + col]; + acc += (input_val - input_zeropoint) * weights_val; + } + acc = MultiplyByQuantizedMultiplier(acc, input_to_gate_effective_scale_a, + input_to_gate_effective_scale_b); + acc += gate_output_zp; + if (acc > int8_max) { + acc = int8_max; + } + if (acc < int8_min) { + acc = int8_min; + } + gate_output[batch * n_cell + row] = static_cast(acc); + } + } +} + +void PortableMatrixBatchVectorMultiply( + const int16_t* hidden, const int8_t* hidden_to_output_weights, + int32_t proj_effective_scale_a, int32_t proj_effective_scale_b, + const int32_t* gate_bias, int32_t n_batch, int32_t n_hidden, + int32_t n_output, int32_t output_zp, int8_t* proj_output) { + const int16_t int8_max = std::numeric_limits::max(); + const int16_t int8_min = std::numeric_limits::min(); + for (int batch = 0; batch < n_batch; ++batch) { + for (int row = 0; row < n_output; ++row) { + int64_t acc = gate_bias[row]; + for (int col = 0; col < n_hidden; ++col) { + int16_t input_val = hidden[batch * n_hidden + col]; + int8_t weights_val = hidden_to_output_weights[row * n_hidden + col]; + int64_t curr = acc; + acc += input_val * weights_val; + if (input_val * weights_val > 0 && acc < curr) { + acc = std::numeric_limits::max(); + } + if (input_val * weights_val < 0 && acc > curr) { + acc = std::numeric_limits::min(); + } + } + acc = MultiplyByQuantizedMultiplier(acc, proj_effective_scale_a, + proj_effective_scale_b); + acc += output_zp; + if (acc > int8_max) { + acc = int8_max; + } + if (acc < int8_min) { + acc = int8_min; + } + proj_output[batch * n_output + row] = acc; + } + } +} + +void PortableApplyLayerNorm(const int16_t* input, + const int16_t* layer_norm_weights, + const int32_t* bias, int32_t layer_norm_scale_a, + int32_t layer_norm_scale_b, int32_t variance_limit, + int n_batch, int n_input, int16_t* output) { + // The square of std::pow(2, 10), which is the extra factor that makes sure + // normalized values has enough resolution. + static const int kTwoToPower20 = 1 << 20; + for (int i = 0; i < n_batch; ++i) { + int64_t sum = 0; + int64_t sum_sq = 0; + for (int j = 0; j < n_input; ++j) { + const int32_t index = i * n_input + j; + int32_t val = static_cast(input[index]); + sum += val; + sum_sq += val * val; + } + int32_t mean = + static_cast(static_cast(sum) * 1024 / n_input); + // TODO(b/173994730): Avoids overflow but only works for POT n_input. + int32_t temp = kTwoToPower20 / n_input; + int64_t variance = + sum_sq * temp - static_cast(mean) * static_cast(mean); + int32_t variance2 = static_cast(variance / kTwoToPower20); + if (variance2 < 1) { + variance2 = variance_limit; + } + int32_t stddev_inverse_a; + int stddev_inverse_b; + GetInvSqrtQuantizedMultiplierExp(variance2, /*reverse_shift*/ -1, + &stddev_inverse_a, &stddev_inverse_b); + + for (int j = 0; j < n_input; ++j) { + const int32_t index = i * n_input + j; + int32_t val = static_cast(input[index]); + int32_t shifted = 1024 * val - mean; + int32_t rescaled = MultiplyByQuantizedMultiplier( + shifted, stddev_inverse_a, stddev_inverse_b); + // TODO(jianlijianli): Saturate this. + int64_t val3 = rescaled * layer_norm_weights[j] + bias[j]; + int32_t val4 = + static_cast((val3 > 0 ? val3 + 512 : val3 - 512) / 1024); + int32_t val5 = MultiplyByQuantizedMultiplier(val4, layer_norm_scale_a, + layer_norm_scale_b + 12); + val5 = std::min(std::max(kInt16Min, val5), kInt16Max); + output[index] = static_cast(val5); + } + } +} + +void PortableApplyLayerNormFloat(const int16_t* input, + const int16_t* layer_norm_weights, + int32_t layer_norm_scale_a, + int32_t layer_norm_scale_b, + const int32_t* bias, int n_batch, int n_input, + int16_t* output) { + const int32_t int16_max = std::numeric_limits::max(); + const int32_t int16_min = std::numeric_limits::min(); + const float layer_norm_scale = + layer_norm_scale_a * + std::pow(2.0, static_cast(layer_norm_scale_b - 31)); + const float bias_scale = + static_cast(std::pow(2.0, -10)) * layer_norm_scale; + + for (int batch = 0; batch < n_batch; ++batch) { + float sum = 0.0f; + float sum_sq = 0.0f; + for (int i = 0; i < n_input; ++i) { + const int index = batch * n_input + i; + const float value = static_cast(input[index]); + sum += value; + sum_sq += value * value; + } + const float mean = sum / n_input; + float stddev_inv = 0.0f; + const float variance = sum_sq / n_input - mean * mean; + if (variance == 0) { + stddev_inv = 1.0f / std::sqrt(1e-8f); + } else { + stddev_inv = 1.0f / std::sqrt(variance); + } + for (int i = 0; i < n_input; ++i) { + const int index = batch * n_input + i; + const float normalized_value = + (static_cast(input[index]) - mean) * stddev_inv; + const float weighted_normalized_value = + normalized_value * layer_norm_weights[i] * layer_norm_scale + + bias[i] * bias_scale; + const int32_t quant_output = static_cast(round( + weighted_normalized_value * static_cast(std::pow(2, 12)))); + output[index] = std::min(int16_max, std::max(int16_min, quant_output)); + } + } +} + +void PortableMatrixScalarMultiplyAccumulate(const int8_t* matrix, + int32_t scalar, int32_t n_row, + int32_t n_col, int32_t* output) { + for (int i = 0; i < n_row; ++i) { + int32_t row_sum = 0; + for (int j = 0; j < n_col; ++j) { + row_sum += *matrix++; + } + output[i] += row_sum * scalar; + } +} + +void PortableApplySigmoid(const int16_t* input, int32_t n_batch, + int32_t n_input, int16_t* output) { + for (int batch = 0; batch < n_batch; ++batch) { + for (int c = 0; c < n_input; c++) { + using F3 = gemmlowp::FixedPoint; + using F0 = gemmlowp::FixedPoint; + const int index = batch * n_input + c; + F3 sigmoid_input = F3::FromRaw(input[index]); + F0 sigmoid_output = gemmlowp::logistic(sigmoid_input); + output[index] = sigmoid_output.raw(); + } + } +} + +void PortableApplySigmoidFloat(const int16_t* input, int32_t n_batch, + int32_t n_input, int16_t* output) { + const int32_t int16_max = std::numeric_limits::max(); + const int32_t int16_min = std::numeric_limits::min(); + for (int batch = 0; batch < n_batch; ++batch) { + for (int i = 0; i < n_input; ++i) { + const int index = batch * n_input + i; + const float float_input = + input[index] * static_cast(std::pow(2, -12)); + const float float_output = 1.0f / (1.0f + std::exp(-float_input)); + const int32_t quant_output = static_cast( + float_output * static_cast(std::pow(2, 15))); + const int32_t quant_output_clamped = + std::min(int16_max, std::max(int16_min, quant_output)); + output[index] = static_cast(quant_output_clamped); + } + } +} + +template +void PortableApplyTanhImpl(const int16_t* input, int32_t n_batch, + int32_t n_input, int16_t* output) { + using FX = gemmlowp::FixedPoint; + using F0 = gemmlowp::FixedPoint; + for (int batch = 0; batch < n_batch; ++batch) { + for (int i = 0; i < n_input; ++i) { + const int index = batch * n_input + i; + FX tanh_input = FX::FromRaw(input[index]); + F0 tanh_output = gemmlowp::tanh(tanh_input); + output[index] = tanh_output.raw(); + } + } +} + +void PortableApplyTanh(int32_t integer_bits, const int16_t* input, + int32_t n_batch, int32_t n_input, int16_t* output) { + assert(integer_bits <= 6); +#define DISPATCH_TANH(i) \ + case i: \ + PortableApplyTanhImpl(input, n_batch, n_input, output); \ + break; + switch (integer_bits) { + DISPATCH_TANH(0); + DISPATCH_TANH(1); + DISPATCH_TANH(2); + DISPATCH_TANH(3); + DISPATCH_TANH(4); + DISPATCH_TANH(5); + DISPATCH_TANH(6); + default: + return; + } +#undef DISPATCH_TANH +} + +void PortableApplyTanhFloat(const int16_t* input, int32_t n_batch, + int32_t n_input, int32_t integer_bits, + int16_t* output) { + const int32_t int16_max = std::numeric_limits::max(); + const int32_t int16_min = std::numeric_limits::min(); + const double two = 2.0; + for (int batch = 0; batch < n_batch; ++batch) { + for (int i = 0; i < n_input; ++i) { + const int index = batch * n_input + i; + const float float_input = + input[index] * std::pow(two, static_cast(integer_bits)); + const float float_output = std::tanh(float_input); + const int32_t quant_output = static_cast( + float_output * static_cast(std::pow(2, 15))); + const int32_t quant_output_clamped = + std::min(int16_max, std::max(int16_min, quant_output)); + output[index] = static_cast(quant_output_clamped); + } + } +} + +void PortableCwiseMul(const int16_t* input_1, const int16_t* input_2, + int n_batch, int n_input, int shift, int16_t* output) { + for (int batch = 0; batch < n_batch; ++batch) { + for (int i = 0; i < n_input; ++i) { + const int index = batch * n_input + i; + const int16_t a = input_1[index]; + const int16_t b = input_2[index]; + const int32_t value = static_cast(a) * static_cast(b); + output[index] = + static_cast(gemmlowp::RoundingDivideByPOT(value, shift)); + } + } +} + +void PortableCwiseMul(const int16_t* input_1, const int16_t* input_2, + int32_t multiplier, int32_t shift, int32_t n_batch, + int32_t n_input, int32_t output_zp, int8_t* output) { + for (int batch = 0; batch < n_batch; ++batch) { + for (int i = 0; i < n_input; ++i) { + const int index = batch * n_input + i; + const int16_t a = input_1[index]; + const int16_t b = input_2[index]; + int32_t value = static_cast(a) * static_cast(b); + value = MultiplyByQuantizedMultiplier(value, multiplier, shift); + value -= output_zp; + value = std::min(std::max(static_cast(-128), value), + static_cast(127)); + + output[index] = static_cast(value); + } + } +} + +void PortableCwiseAdd(const int16_t* input_1, const int16_t* input_2, + int n_batch, int n_input, int16_t* output) { + for (int batch = 0; batch < n_batch; ++batch) { + for (int i = 0; i < n_input; ++i) { + const int index = batch * n_input + i; + int32_t sum = input_1[index] + input_2[index]; + const int32_t sum_clamped = std::min(kInt16Max, std::max(kInt16Min, sum)); + output[index] = static_cast(sum_clamped); + } + } +} + +float PortableVectorVectorDotProduct(const float* vector1, const float* vector2, + int v_size) { + float result = 0.0; + for (int v = 0; v < v_size; v++) { + result += *vector1++ * *vector2++; + } + return result; +} + +namespace { +inline int32_t VectorVectorDotProduct(const int16_t* vector1, + const int16_t* vector2, int v_size) { + int32_t result = 0; + for (int v = 0; v < v_size; v++) { + result += *vector1++ * *vector2++; + } + return result; +} +} // namespace + +void PortableBatchVectorBatchVectorDotProduct(const int16_t* vector1, + const int16_t* vector2, + int v_size, int n_batch, + int32_t* result) { + for (int b = 0; b < n_batch; b++) { + result[b] = VectorVectorDotProduct(vector1, vector2, v_size); + vector1 += v_size; + vector2 += v_size; + } +} + +void PortableVectorBatchVectorCwiseProductAccumulate( + const int16_t* vector, int v_size, const int16_t* batch_vector, int n_batch, + int32_t multiplier, int shift, int16_t* result) { + for (int b = 0; b < n_batch; b++) { + for (int v = 0; v < v_size; v++) { + int32_t prod = vector[v] * *batch_vector++; + prod = MultiplyByQuantizedMultiplier(prod, multiplier, shift); + int32_t output = prod + *result; + output = std::max(std::min(static_cast(32767), output), + static_cast(-32768)); + *result++ = output; + } + } +} + +void PortableSub1Vector(const float* vector, int v_size, float* result) { + for (int v = 0; v < v_size; v++) { + *result++ = 1.0f - *vector++; + } +} + +void PortableSub1Vector(const int16_t* vector, int v_size, int16_t* result) { + static const int16_t kOne = 32767; + for (int v = 0; v < v_size; v++) { + *result++ = kOne - *vector++; + } +} + +void PortableVectorScalarMultiply(const int8_t* vector, const int v_size, + const float scale, float* result) { + for (int v = 0; v < v_size; ++v) { + *result++ = scale * *vector++; + } +} + +void PortableMeanStddevNormalization(const float* __restrict__ input_vector, + float* __restrict__ output_vector, + int v_size, int n_batch) { + for (int batch = 0; batch < n_batch; ++batch) { + float sum = 0.0f; + for (int i = 0; i < v_size; ++i) { + sum += input_vector[i]; + } + const float mean = sum / v_size; + float sum_diff_sq = 0.0f; + for (int i = 0; i < v_size; ++i) { + const float diff = input_vector[i] - mean; + sum_diff_sq += diff * diff; + } + const float variance = sum_diff_sq / v_size; + constexpr float kNormalizationConstant = 1e-8f; + const float stddev_inv = + 1.0f / std::sqrt(variance + kNormalizationConstant); + for (int i = 0; i < v_size; ++i) { + output_vector[i] = (input_vector[i] - mean) * stddev_inv; + } + input_vector += v_size; + output_vector += v_size; + } +} + +void PortableTwoGateSaturatingAdd(const int8_t* input, int8_t input_zp, + const int8_t* recurrent, int8_t recurrent_zp, + int32_t input_effective_scale_a, + int32_t input_effective_scale_b, + int32_t recurrent_effective_scale_a, + int32_t recurrent_effective_scale_b, + int32_t n_batch, int32_t n_cell, + int16_t* output) { + const int32_t int16_max = std::numeric_limits::max(); + const int32_t int16_min = std::numeric_limits::min(); + for (int i = 0; i < n_batch * n_cell; ++i) { + int32_t x = static_cast(input[i]) - static_cast(input_zp); + int32_t h = + static_cast(recurrent[i]) - static_cast(recurrent_zp); + int32_t x_scaled = MultiplyByQuantizedMultiplier(x, input_effective_scale_a, + input_effective_scale_b); + int32_t h_scaled = MultiplyByQuantizedMultiplier( + h, recurrent_effective_scale_a, recurrent_effective_scale_b); + int32_t y = h_scaled + x_scaled; + if (y > int16_max) { + y = int16_max; + } + if (y < int16_min) { + y = int16_min; + } + output[i] = static_cast(y); + } +} + +} // namespace tensor_utils +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h new file mode 100644 index 000000000..0416db093 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h @@ -0,0 +1,333 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PORTABLE_TENSOR_UTILS_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PORTABLE_TENSOR_UTILS_H_ + +#include "tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h" + +#if defined(_MSC_VER) +#define __restrict__ __restrict +#endif + +namespace tflite { +namespace tensor_utils { + +// Check if all entries of a vector are zero for float. +bool IsZeroVector(const float* vector, int v_size) { + return PortableIsZeroVector(vector, v_size); +} + +// Check if all entries of a vector are zero for int8_t. +bool IsZeroVector(const int8_t* vector, int v_size) { + return PortableIsZeroVector(vector, v_size); +} + +void SymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float* min, float* max, + float* scaling_factor) { + PortableSymmetricQuantizeFloats(values, size, quantized_values, min, max, + scaling_factor); +} + +void SymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float min_value, + float max_value, float* scaling_factor) { + PortableSymmetricQuantizeFloats(values, size, quantized_values, min_value, + max_value, scaling_factor); +} + +void AsymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float* scaling_factor, + int32_t* offset) { + PortableAsymmetricQuantizeFloats(values, size, quantized_values, + scaling_factor, offset); +} + +void MatrixBatchVectorMultiplyAccumulate(const float* matrix, int m_rows, + int m_cols, const float* vector, + int n_batch, float* result) { + PortableMatrixBatchVectorMultiplyAccumulate(matrix, m_rows, m_cols, vector, + n_batch, result); +} + +void MatrixBatchVectorMultiplyAccumulate(const int8_t* __restrict__ matrix, + const int m_rows, const int m_cols, + const int8_t* __restrict__ vector, + const float* scaling_factors, + int n_batch, + float* __restrict__ result) { + PortableMatrixBatchVectorMultiplyAccumulate(matrix, m_rows, m_cols, vector, + scaling_factors, n_batch, result); +} + +void MatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, const float* scaling_factors, + int n_batch, float* __restrict__ result, const float* per_channel_scale, + const int32_t* input_offset, int32_t* scratch, int32_t* row_sums, + bool* compute_row_sums, CpuBackendContext* context) { + PortableMatrixBatchVectorMultiplyAccumulate( + matrix, m_rows, m_cols, vectors, scaling_factors, n_batch, result, + per_channel_scale, input_offset, scratch, row_sums, compute_row_sums, + context); +} + +void MatrixBatchVectorMultiplyAccumulate(const int8_t* __restrict__ matrix, + const int m_rows, const int m_cols, + const int8_t* __restrict__ vector, + const float* scaling_factors, + int n_batch, int32_t* scratch, + float* __restrict__ result, + CpuBackendContext* context) { + PortableMatrixBatchVectorMultiplyAccumulate(matrix, m_rows, m_cols, vector, + scaling_factors, n_batch, result); +} + +void SparseMatrixBatchVectorMultiplyAccumulate1x4( + const float* __restrict__ matrix, const int32_t* __restrict__ segments, + const int32_t* __restrict__ indices, int m_rows, int m_cols, + const float* __restrict__ vector, int n_batch, float* __restrict__ result) { + PortableSparseMatrixBatchVectorMultiplyAccumulate1x4( + matrix, segments, indices, m_rows, m_cols, vector, n_batch, result); +} + +void SparseMatrixBatchVectorMultiplyAccumulate( + const float* __restrict__ matrix, const uint8_t* __restrict__ ledger, + int m_rows, int m_cols, const float* __restrict__ vector, int n_batch, + float* __restrict__ result) { + PortableSparseMatrixBatchVectorMultiplyAccumulate( + matrix, ledger, m_rows, m_cols, vector, n_batch, result); +} + +void SparseMatrixBatchVectorMultiplyAccumulate1x16( + const int8_t* __restrict__ matrix, const int32_t* __restrict__ segments, + const int32_t* __restrict__ indices, int m_rows, int m_cols, + const int8_t* __restrict__ vector, const int32_t* __restrict__ bias_vector, + int n_batch, const int32_t input_offset, const int32_t output_multiplier, + const int32_t output_shift, const int32_t output_offset, + const int32_t output_activation_min, const int32_t output_activation_max, + + int8_t* __restrict__ result) { + PortableSparseMatrixBatchVectorMultiplyAccumulate1x16( + matrix, segments, indices, m_rows, m_cols, vector, bias_vector, n_batch, + input_offset, output_multiplier, output_shift, output_offset, + output_activation_min, output_activation_max, result); +} + +void SparseMatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const uint8_t* ledger, const int m_rows, + const int m_cols, const int8_t* __restrict__ vectors, + const float* scaling_factors, int n_batch, float* __restrict__ result) { + PortableSparseMatrixBatchVectorMultiplyAccumulate( + matrix, ledger, m_rows, m_cols, vectors, scaling_factors, n_batch, + result); +} + +void MatrixBatchVectorMultiplyAccumulate( + const int8_t* input, const int32_t* bias, + const int8_t* input_to_gate_weights, int32_t multiplier, int32_t shift, + int32_t n_batch, int32_t n_input, int32_t n_output, int32_t output_zp, + int32_t* scratch, int16_t* output, CpuBackendContext* context) { + PortableMatrixBatchVectorMultiplyAccumulate( + input, bias, input_to_gate_weights, multiplier, shift, n_batch, n_input, + n_output, output_zp, scratch, output, context); +} + +void MatrixBatchVectorMultiplyAccumulate( + const int8_t* input, const int32_t* bias, + const int8_t* input_to_gate_weights, int32_t multiplier, int32_t shift, + int32_t n_batch, int32_t n_input, int32_t n_output, int32_t output_zp, + int32_t* scratch, int8_t* output, CpuBackendContext* context) { + PortableMatrixBatchVectorMultiplyAccumulate( + input, bias, input_to_gate_weights, multiplier, shift, n_batch, n_input, + n_output, output_zp, scratch, output, context); +} + +void MatrixScalarMultiplyAccumulate(const int8_t* matrix, int32_t scalar, + int32_t n_row, int32_t n_col, + int32_t* output) { + PortableMatrixScalarMultiplyAccumulate(matrix, scalar, n_row, n_col, output); +} + +void MatrixBatchVectorMultiply(const int8_t* input, int32_t input_zeropoint, + const int8_t* input_to_gate_weights, + int32_t input_to_gate_effective_scale_a, + int32_t input_to_gate_effective_scale_b, + int32_t n_batch, int32_t n_input, int32_t n_cell, + int8_t* gate_output, int8_t gate_output_zp) { + PortableMatrixBatchVectorMultiply( + input, input_zeropoint, input_to_gate_weights, + input_to_gate_effective_scale_a, input_to_gate_effective_scale_b, n_batch, + n_input, n_cell, gate_output, gate_output_zp); +} + +void MatrixBatchVectorMultiply(const int16_t* hidden, + const int8_t* hidden_to_output_weights, + int32_t proj_effective_scale_a, + int32_t proj_effective_scale_b, + const int32_t* gate_bias, int32_t n_batch, + int32_t n_hidden, int32_t n_output, + int32_t output_zp, int8_t* proj_output) { + PortableMatrixBatchVectorMultiply(hidden, hidden_to_output_weights, + proj_effective_scale_a, + proj_effective_scale_b, gate_bias, n_batch, + n_hidden, n_output, output_zp, proj_output); +} + +void ApplyLayerNorm(const int16_t* input, const int16_t* layer_norm_weights, + const int32_t* bias, int32_t layer_norm_scale_a, + int32_t layer_norm_scale_b, int32_t variance_limit, + int n_batch, int n_input, int16_t* output) { + PortableApplyLayerNorm(input, layer_norm_weights, bias, layer_norm_scale_a, + layer_norm_scale_b, variance_limit, n_batch, n_input, + output); +} + +void ApplyLayerNormFloat(const int16_t* input, + const int16_t* layer_norm_weights, + int32_t layer_norm_scale_a, int32_t layer_norm_scale_b, + const int32_t* bias, int n_batch, int n_input, + int16_t* output) { + PortableApplyLayerNormFloat(input, layer_norm_weights, layer_norm_scale_a, + layer_norm_scale_b, bias, n_batch, n_input, + output); +} + +void ApplySigmoid(const int16_t* input, int32_t n_batch, int32_t n_input, + int16_t* output) { + PortableApplySigmoid(input, n_batch, n_input, output); +} + +void ApplySigmoidFloat(const int16_t* input, int32_t n_batch, int32_t n_input, + int16_t* output) { + PortableApplySigmoidFloat(input, n_batch, n_input, output); +} + +void ApplyTanh(int32_t integer_bits, const int16_t* input, int32_t n_batch, + int32_t n_input, int16_t* output) { + PortableApplyTanh(integer_bits, input, n_batch, n_input, output); +} + +void ApplyTanhFloat(const int16_t* input, int32_t n_batch, int32_t n_input, + int32_t integer_bits, int16_t* output) { + PortableApplyTanhFloat(input, n_batch, n_input, integer_bits, output); +} + +void CwiseMul(const int16_t* input_1, const int16_t* input_2, int n_batch, + int n_input, int shift, int16_t* output) { + PortableCwiseMul(input_1, input_2, n_batch, n_input, shift, output); +} + +void CwiseMul(const int16_t* input_1, const int16_t* input_2, + int32_t multiplier, int32_t shift, int32_t n_batch, + int32_t n_input, int32_t output_zp, int8_t* output) { + PortableCwiseMul(input_1, input_2, multiplier, shift, n_batch, n_input, + output_zp, output); +} + +void CwiseAdd(const int16_t* input_1, const int16_t* input_2, int n_batch, + int n_input, int16_t* output) { + PortableCwiseAdd(input_1, input_2, n_batch, n_input, output); +} + +void CwiseClipping(float* vector, const int v_size, + const float clipping_value) { + PortableCwiseClipping(vector, v_size, clipping_value); +} + +void CwiseClipping(int16_t* vector, const int v_size, + const int16_t clipping_value) { + PortableCwiseClipping(vector, v_size, clipping_value); +} + +void CwiseClipping(int8_t* vector, const int v_size, + const int8_t clipping_value) { + PortableCwiseClipping(vector, v_size, clipping_value); +} + +void VectorBatchVectorCwiseProductAccumulate(const int16_t* vector, int v_size, + const int16_t* batch_vector, + int n_batch, int32_t multiplier, + int shift, int16_t* result) { + PortableVectorBatchVectorCwiseProductAccumulate( + vector, v_size, batch_vector, n_batch, multiplier, shift, result); +} + +float VectorVectorDotProduct(const float* vector1, const float* vector2, + int v_size) { + return PortableVectorVectorDotProduct(vector1, vector2, v_size); +} + +void BatchVectorBatchVectorDotProduct(const int16_t* vector1, + const int16_t* vector2, int v_size, + int n_batch, int32_t* result) { + PortableBatchVectorBatchVectorDotProduct(vector1, vector2, v_size, n_batch, + result); +} + +void Sub1Vector(const float* vector, int v_size, float* result) { + PortableSub1Vector(vector, v_size, result); +} + +void Sub1Vector(const int16_t* vector, int v_size, int16_t* result) { + PortableSub1Vector(vector, v_size, result); +} + +// Multiply all elements of vector with a scalar. +void VectorScalarMultiply(const int8_t* vector, int v_size, float scale, + float* result) { + PortableVectorScalarMultiply(vector, v_size, scale, result); +} + +void ReductionSumVector(const float* input_vector, float* output_vector, + int output_size, int reduction_size) { + PortableReductionSumVector(input_vector, output_vector, output_size, + reduction_size); +} + +void ReductionSumVector(const int32_t* input_vector, int32_t* output_vector, + int output_size, int reduction_size) { + PortableReductionSumVector(input_vector, output_vector, output_size, + reduction_size); +} + +void ReductionSumVector(const int8_t* input_vector, int32_t* output_vector, + int output_size, int reduction_size) { + PortableReductionSumVector(input_vector, output_vector, output_size, + reduction_size); +} + +void MeanStddevNormalization(const float* input_vector, float* output_vector, + int v_size, int n_batch) { + PortableMeanStddevNormalization(input_vector, output_vector, v_size, n_batch); +} + +void TwoGateSaturatingAdd(const int8_t* input, int8_t input_zp, + const int8_t* recurrent, int8_t recurrent_zp, + int32_t input_effective_scale_a, + int32_t input_effective_scale_b, + int32_t recurrent_effective_scale_a, + int32_t recurrent_effective_scale_b, int32_t n_batch, + int32_t n_cell, int16_t* output) { + PortableTwoGateSaturatingAdd( + input, input_zp, recurrent, recurrent_zp, input_effective_scale_a, + input_effective_scale_b, recurrent_effective_scale_a, + recurrent_effective_scale_b, n_batch, n_cell, output); +} + +} // namespace tensor_utils +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PORTABLE_TENSOR_UTILS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h new file mode 100644 index 000000000..6c404d5ec --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h @@ -0,0 +1,244 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PORTABLE_TENSOR_UTILS_IMPL_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PORTABLE_TENSOR_UTILS_IMPL_H_ + +#include +#include + +#if defined(_MSC_VER) +#define __restrict__ __restrict +#endif + +namespace tflite { + +// Not all backends support CpuBackendContext usage, so forward declare to avoid +// pulling in its implementation. +class CpuBackendContext; + +namespace tensor_utils { + +template +bool PortableIsZeroVector(const T* vector, int v_size) { + for (int i = 0; i < v_size; ++i) { + if (vector[i] != 0) { + return false; + } + } + return true; +} + +void PortableSymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float* min_value, + float* max_value, float* scaling_factor); + +void PortableSymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, float min_value, + float max_value, float* scaling_factor); + +void PortableAsymmetricQuantizeFloats(const float* values, const int size, + int8_t* quantized_values, + float* scaling_factor, int32_t* offset); + +// Multiply a matrix by a batch vector, and store results in a batch-size +// vector. +void PortableMatrixBatchVectorMultiplyAccumulate(const float* matrix, + int m_rows, int m_cols, + const float* vector, + int n_batch, float* result); + +void PortableMatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, const float* scaling_factors, + int n_batch, float* __restrict__ result); + +void PortableMatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vectors, const float* scaling_factors, + int n_batch, float* __restrict__ result, const float* per_channel_scale, + const int32_t* input_offset, int32_t* scratch, int32_t* row_sums, + bool* compute_row_sums, CpuBackendContext* context); + +void PortableMatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const int m_rows, const int m_cols, + const int8_t* __restrict__ vector, const float* scaling_factors, + int n_batch, int32_t* scratch, float* __restrict__ result, + CpuBackendContext* context); + +void PortableSparseMatrixBatchVectorMultiplyAccumulate1x4( + const float* __restrict__ matrix, const int32_t* __restrict__ segments, + const int32_t* __restrict__ indices, int m_rows, int m_cols, + const float* __restrict__ vector, int n_batch, float* __restrict__ result); + +void PortableSparseMatrixBatchVectorMultiplyAccumulate( + const float* __restrict__ matrix, const uint8_t* __restrict__ ledger, + int m_rows, int m_cols, const float* __restrict__ vector, int n_batch, + float* __restrict__ result); + +void PortableSparseMatrixBatchVectorMultiplyAccumulate1x16( + const int8_t* __restrict__ matrix, const int32_t* __restrict__ segments, + const int32_t* __restrict__ indices, int m_rows, int m_cols, + const int8_t* __restrict__ vector, const int32_t* __restrict__ bias_vector, + int n_batch, const int32_t input_offset, const int32_t output_multiplier, + const int32_t output_shift, const int32_t output_offset, + const int32_t output_activation_min, const int32_t output_activation_max, + int8_t* __restrict__ result); + +void PortableSparseMatrixBatchVectorMultiplyAccumulate( + const int8_t* __restrict__ matrix, const uint8_t* ledger, const int m_rows, + const int m_cols, const int8_t* __restrict__ vectors, + const float* scaling_factors, int n_batch, float* __restrict__ result); + +// Dot product of two vectors. +float PortableVectorVectorDotProduct(const float* vector1, const float* vector2, + int v_size); + +void PortableBatchVectorBatchVectorDotProduct(const int16_t* vector1, + const int16_t* vector2, + int v_size, int n_batch, + int32_t* result); + +void PortableVectorBatchVectorCwiseProductAccumulate( + const int16_t* vector, int v_size, const int16_t* batch_vector, int n_batch, + int32_t multiplier, int shift, int16_t* result); + +void PortableMatrixBatchVectorMultiplyAccumulate( + const int8_t* input, const int32_t* bias, + const int8_t* input_to_gate_weights, int32_t multiplier, int32_t shift, + int32_t n_batch, int32_t n_input, int32_t n_output, int32_t output_zp, + int32_t* scratch, int16_t* output, CpuBackendContext* context); + +void PortableMatrixBatchVectorMultiplyAccumulate( + const int8_t* input, const int32_t* bias, + const int8_t* input_to_gate_weights, int32_t multiplier, int32_t shift, + int32_t n_batch, int32_t n_input, int32_t n_output, int32_t output_zp, + int32_t* scratch, int8_t* output, CpuBackendContext* context); + +void PortableMatrixBatchVectorMultiply(const int8_t* input, + int32_t input_zeropoint, + const int8_t* input_to_gate_weights, + int32_t input_to_gate_effective_scale_a, + int32_t input_to_gate_effective_scale_b, + int32_t n_batch, int32_t n_input, + int32_t n_cell, int8_t* gate_output, + int8_t gate_output_zp); + +void PortableMatrixBatchVectorMultiply( + const int16_t* hidden, const int8_t* hidden_to_output_weights, + int32_t proj_effective_scale_a, int32_t proj_effective_scale_b, + const int32_t* gate_bias, int32_t n_batch, int32_t n_hidden, + int32_t n_output, int32_t output_zp, int8_t* proj_output); + +void PortableMatrixScalarMultiplyAccumulate(const int8_t* matrix, + int32_t scalar, int32_t n_row, + int32_t n_col, int32_t* output); + +void PortableApplyLayerNorm(const int16_t* input, + const int16_t* layer_norm_weights, + const int32_t* bias, int32_t layer_norm_scale_a, + int32_t layer_norm_scale_b, int32_t variance_limit, + int n_batch, int n_input, int16_t* output); + +void PortableApplyLayerNormFloat(const int16_t* input, + const int16_t* layer_norm_weights, + int32_t layer_norm_scale_a, + int32_t layer_norm_scale_b, + const int32_t* bias, int n_batch, int n_input, + int16_t* output); + +void PortableApplySigmoid(const int16_t* input, int32_t n_batch, + int32_t n_input, int16_t* output); + +void PortableApplySigmoidFloat(const int16_t* input, int32_t n_batch, + int32_t n_input, int16_t* output); + +void PortableApplyTanh(int32_t integer_bits, const int16_t* input, + int32_t n_batch, int32_t n_input, int16_t* output); + +void PortableApplyTanhFloat(const int16_t* input, int32_t n_batch, + int32_t n_input, int32_t integer_bits, + int16_t* output); + +void PortableCwiseMul(const int16_t* input_1, const int16_t* input_2, + int n_batch, int n_input, int shift, int16_t* output); + +void PortableCwiseMul(const int16_t* input_1, const int16_t* input_2, + int32_t multiplier, int32_t shift, int32_t n_batch, + int32_t n_input, int32_t output_zp, int8_t* output); + +void PortableCwiseAdd(const int16_t* input_1, const int16_t* input_2, + int n_batch, int n_input, int16_t* output); + +template +void PortableCwiseClipping(T* vector, const int v_size, + const T& clipping_value) { + for (int i = 0; i < v_size; i++) { + vector[i] = std::max(std::min(clipping_value, vector[i]), + static_cast(-clipping_value)); + } +} + +// Batch vector initialization with another vector. +void PortableVectorBatchVectorAssign(const float* vector, int v_size, + int n_batch, float* batch_vector); + +// Compute "1.0f - elements of vector" (used in CIFG). +void PortableSub1Vector(const float* vector, int v_size, float* result); + +void PortableSub1Vector(const int16_t* vector, int v_size, int16_t* result); + +// Multiply all elements of vector with a scalar. +void PortableVectorScalarMultiply(const int8_t* vector, int v_size, float scale, + float* result); + +// Reduce-sum on a vector: +// input_vector: pointer to input vector. +// output_vector: pointer to vector. +// output_size: output vector size. +// reduction_size: number of consecutive elements from input vector which are +// added to get one element of output. +template +void PortableReductionSumVector(const INPUT* input_vector, + OUTPUT* output_vector, int output_size, + int reduction_size) { + for (int o = 0; o < output_size; o++) { + OUTPUT result = 0; + for (int r = 0; r < reduction_size; r++) { + result += input_vector[r]; + } + output_vector[o] = result; + input_vector += reduction_size; + } +} + +// Layer norm for each batch. +void PortableMeanStddevNormalization(const float* __restrict__ input_vector, + float* __restrict__ output_vector, + int v_size, int n_batch); + +// Saturate Add. +void PortableTwoGateSaturatingAdd(const int8_t* input, int8_t input_zp, + const int8_t* recurrent, int8_t recurrent_zp, + int32_t input_effective_scale_a, + int32_t input_effective_scale_b, + int32_t recurrent_effective_scale_a, + int32_t recurrent_effective_scale_b, + int32_t n_batch, int32_t n_cell, + int16_t* output); + +} // namespace tensor_utils +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PORTABLE_TENSOR_UTILS_IMPL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/prelu.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/prelu.h new file mode 100644 index 000000000..aa9901d60 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/prelu.h @@ -0,0 +1,111 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PRELU_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PRELU_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +// Broadcast prelu to output_shape for quantized uint8_t/int8_t data. +template +inline void BroadcastPrelu4DSlow( + const PreluParams& params, const RuntimeShape& input_shape, + const T* input_data, const RuntimeShape& alpha_shape, const T* alpha_data, + const RuntimeShape& output_shape, T* output_data) { + TFLITE_DCHECK_LE(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(alpha_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(output_shape.DimensionsCount(), 4); + const RuntimeShape extended_output_shape = + RuntimeShape::ExtendedShape(4, output_shape); + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(input_shape, alpha_shape, &desc1, &desc2); + + for (int b = 0; b < extended_output_shape.Dims(0); ++b) { + for (int y = 0; y < extended_output_shape.Dims(1); ++y) { + for (int x = 0; x < extended_output_shape.Dims(2); ++x) { + for (int c = 0; c < extended_output_shape.Dims(3); ++c) { + int output_index = Offset(extended_output_shape, b, y, x, c); + int input_index = SubscriptToIndex(desc1, b, y, x, c); + const int32_t input_value = + params.input_offset + input_data[input_index]; + int32_t output_value; + if (input_value >= 0) { + output_value = MultiplyByQuantizedMultiplier( + input_value, params.output_multiplier_1, params.output_shift_1); + } else { + auto alpha_index = SubscriptToIndex(desc2, b, y, x, c); + const int32_t alpha_value = + params.alpha_offset + alpha_data[alpha_index]; + + output_value = MultiplyByQuantizedMultiplier( + input_value * alpha_value, params.output_multiplier_2, + params.output_shift_2); + } + output_value += params.output_offset; + + const int32_t quantized_min = std::numeric_limits::min(); + const int32_t quantized_max = std::numeric_limits::max(); + const int32_t clamped_output = + std::min(quantized_max, std::max(quantized_min, output_value)); + output_data[output_index] = static_cast(clamped_output); + } + } + } + } +} + +template +inline void Prelu(const PreluParams& params, const RuntimeShape& input_shape, + const T* input_data, const RuntimeShape& alpha_shape, + const T* alpha_data, const RuntimeShape& output_shape, + T* output_data) { + const int32_t quantized_min = std::numeric_limits::min(); + const int32_t quantized_max = std::numeric_limits::max(); + + const int flat_size = + MatchingElementsSize(input_shape, alpha_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + const int32_t input_value = params.input_offset + input_data[i]; + int32_t output_value; + if (input_value >= 0) { + output_value = MultiplyByQuantizedMultiplier( + input_value, params.output_multiplier_1, params.output_shift_1); + } else { + const int32_t alpha_value = params.alpha_offset + alpha_data[i]; + + output_value = MultiplyByQuantizedMultiplier(input_value * alpha_value, + params.output_multiplier_2, + params.output_shift_2); + } + output_value += params.output_offset; + + const int32_t clamped_output = + std::min(quantized_max, std::max(quantized_min, output_value)); + output_data[i] = static_cast(clamped_output); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PRELU_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h new file mode 100644 index 000000000..bda27693f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h @@ -0,0 +1,140 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PROCESS_BROADCAST_SHAPES_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PROCESS_BROADCAST_SHAPES_H_ + +#include + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +// Consolidates dimensions in broadcast inputs, checks for five-fold pattern. +// +// For example, if sequence of dimensions of one input is +// ..., 1, 3, 1, 7, 9, 5,... and the other is ..., 2, 3, 1, 7, 1, 1, ... +// we can consolidate these as +// ..., 1, 3*7, 9*5, ... and 2, 3*7, 1. +// +// The category is updated in the less-frequent case of shapes that are +// not suited to a fivefold-loop broadcast. +// +// Falls back to generic pattern when it does not know how to process properly. +// +// Returns true iff there is some sort of broadcast, which includes five-fold +// patterns and falling back to generic broadcast. +inline bool ProcessBroadcastShapes(const RuntimeShape& shape0, + const RuntimeShape& shape1, + tflite::ArithmeticParams* params) { + const int dims_count = + std::max(shape0.DimensionsCount(), shape1.DimensionsCount()); + + params->broadcast_category = BroadcastableOpCategory::kGenericBroadcast; + RuntimeShape scalar_shape(dims_count, 1); + + auto extended_shape0 = RuntimeShape::ExtendedShape(dims_count, shape0); + auto extended_shape1 = RuntimeShape::ExtendedShape(dims_count, shape1); + + // Check for "exact" match, implicitly accepting any scalar shapes. + if (extended_shape0 == extended_shape1) { + params->broadcast_category = BroadcastableOpCategory::kNonBroadcast; + return false; + } + + for (int i = dims_count - 1; i >= 0; --i) { + if (extended_shape0.Dims(i) == extended_shape1.Dims(i)) { + continue; + } else if (extended_shape0.Dims(i) == 1) { + params->broadcast_category = + BroadcastableOpCategory::kFirstInputBroadcastsFast; + break; + } else if (extended_shape1.Dims(i) == 1) { + params->broadcast_category = + BroadcastableOpCategory::kSecondInputBroadcastsFast; + break; + } else { + // This case is erroneous: there is a dimension that does not match and + // is not a broadcast from one shape to the other. + params->broadcast_category = BroadcastableOpCategory::kGenericBroadcast; + return true; + } + } + + if (params->broadcast_category != + BroadcastableOpCategory::kFirstInputBroadcastsFast && + params->broadcast_category != + BroadcastableOpCategory::kSecondInputBroadcastsFast) { + // This is unreachable because at least one else clause in the above loop + // must be reached. + TFLITE_DCHECK(false); + params->broadcast_category = BroadcastableOpCategory::kNonBroadcast; + return false; + } + + // From this point it is assumed contractually that corresponding dimensions + // in shape0 and shape1 are either (a) equal or (b) one or other equals 1. + const bool swap_inputs = params->broadcast_category == + BroadcastableOpCategory::kSecondInputBroadcastsFast; + const RuntimeShape* shape_a = + swap_inputs ? &extended_shape1 : &extended_shape0; + const RuntimeShape* shape_b = + swap_inputs ? &extended_shape0 : &extended_shape1; + + int i = dims_count - 1; + params->broadcast_shape[0] = 1; + params->broadcast_shape[1] = 1; + params->broadcast_shape[2] = 1; + params->broadcast_shape[3] = 1; + params->broadcast_shape[4] = 1; + // y_0 is greedy: include dims if both or neither equal 1: in other words, + // test for equality rather than (shape_a->Dims(i) != 1). + while (i >= 0 && shape_a->Dims(i) == shape_b->Dims(i)) { + params->broadcast_shape[4] *= shape_b->Dims(i); + --i; + } + // Here either input_a or input_b has dim of 1 (if i >= 0). If it is input_b + // that has the unit dimension, the next two loops are not entered. + while (i >= 0 && shape_a->Dims(i) == 1) { + params->broadcast_shape[3] *= shape_b->Dims(i); + --i; + } + while (i >= 0 && shape_a->Dims(i) == shape_b->Dims(i)) { + params->broadcast_shape[2] *= shape_a->Dims(i); + --i; + } + // Here either input_a or input_b has dim of 1 (if i >= 0). + while (i >= 0 && shape_b->Dims(i) == 1) { + params->broadcast_shape[1] *= shape_a->Dims(i); + --i; + } + while (i >= 0 && shape_a->Dims(i) == shape_b->Dims(i)) { + params->broadcast_shape[0] *= shape_b->Dims(i); + --i; + } + + // Rarer case is when the broadcast dimensions cannot be handled by a fivefold + // loop. + if (i >= 0) { + params->broadcast_category = BroadcastableOpCategory::kGenericBroadcast; + } + return true; +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_PROCESS_BROADCAST_SHAPES_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/quantize.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/quantize.h new file mode 100644 index 000000000..f304b641a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/quantize.h @@ -0,0 +1,89 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_QUANTIZE_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_QUANTIZE_H_ + +#include +#include +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +template +inline void AffineQuantize(const tflite::QuantizationParams& op_params, + const RuntimeShape& input_shape, + const InputT* input_data, + const RuntimeShape& output_shape, + OutputT* output_data) { + const int32_t zero_point = op_params.zero_point; + const double scale = op_params.scale; + const int flat_size = MatchingFlatSize(input_shape, output_shape); + static constexpr int32_t min_val = std::numeric_limits::min(); + static constexpr int32_t max_val = std::numeric_limits::max(); + + for (int i = 0; i < flat_size; i++) { + const InputT val = input_data[i]; + int32_t unclamped = + static_cast(TfLiteRound(val / static_cast(scale))) + + zero_point; + int32_t clamped = std::min(std::max(unclamped, min_val), max_val); + output_data[i] = clamped; + } +} + +// Quantizes per-channel. +template +inline void PerChannelQuantize( + const tflite::PerChannelQuantizationParams& op_params, + const RuntimeShape& input_shape, const InputT* input_data, + const RuntimeShape& output_shape, OutputT* output_data) { + // Ensure flat size is same. + MatchingFlatSize(input_shape, output_shape); + + const int32_t* zero_point = op_params.zero_point; + const float* scale = op_params.scale; + const int32_t quantized_dimension = op_params.quantized_dimension; + const int32_t num_dims = input_shape.DimensionsCount(); + const int32_t* dims_data = input_shape.DimsData(); + std::vector current_dim(num_dims, 0); + static constexpr int32_t min_val = std::numeric_limits::min(); + static constexpr int32_t max_val = std::numeric_limits::max(); + + do { + size_t offset = + ReducedOutputOffset(num_dims, reinterpret_cast(dims_data), + current_dim.data(), 0, nullptr); + const InputT val = input_data[offset]; + const int channel = current_dim[quantized_dimension]; + int32_t unclamped = static_cast(TfLiteRound( + val / static_cast(scale[channel]))) + + zero_point[channel]; + int32_t clamped = std::min(std::max(unclamped, min_val), max_val); + output_data[offset] = static_cast(clamped); + } while (NextIndex(num_dims, reinterpret_cast(dims_data), + current_dim.data())); +} + +} // namespace reference_ops + +} // namespace tflite +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_QUANTIZE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/reduce.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/reduce.h new file mode 100644 index 000000000..e83bb7b3c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/reduce.h @@ -0,0 +1,526 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_REDUCE_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_REDUCE_H_ + +#include + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/max.h" +#include "tensorflow/lite/kernels/internal/min.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/types.h" + +// Check if the reduction at index is the first one along the dimensions given +// in axis. +inline bool IsFirstReduction(const int* index, const int num_axis, + const int* axis) { + if (num_axis == 0) { + return true; + } + + TFLITE_DCHECK(index != nullptr); + TFLITE_DCHECK(axis != nullptr); + for (int axis_idx = 0; axis_idx < num_axis; ++axis_idx) { + if (index[axis[axis_idx]] != 0) { + return false; + } + } + + return true; +} + +namespace tflite { + +namespace reference_ops { + +// A generic reduce method that can be used for reduce_sum, reduce_mean, etc. +// This method iterates through input data and reduce elements along the +// dimensions given in axis. +template +inline bool Reduce(const In* input_data, const int* input_dims, + const int* output_dims, const int input_num_dims, + const int output_num_dims, const int* axis, + const int num_axis, int* input_iter, + Out reducer(Out current, const In in), Out* output_data) { + // Reset input iterator. + for (int idx = 0; idx < input_num_dims; ++idx) { + input_iter[idx] = 0; + } + // Iterate through input_data. + do { + size_t input_offset = + ReducedOutputOffset(input_num_dims, input_dims, input_iter, 0, nullptr); + size_t output_offset = ReducedOutputOffset(input_num_dims, input_dims, + input_iter, num_axis, axis); + output_data[output_offset] = + reducer(output_data[output_offset], input_data[input_offset]); + } while (NextIndex(input_num_dims, input_dims, input_iter)); + return true; +} + +// Similar to above Reduce function but takes two reducer functions. +// The 'reducer_first' is called with the first value of the reduction, +// 'reducer_next' is then called for all the others. +template +inline bool Reduce(const In* input_data, const int* input_dims, + const int* output_dims, const int input_num_dims, + const int output_num_dims, const int* axis, + const int num_axis, int* input_iter, + const std::function& reducer_first, + const std::function& reducer_next, + Out* output_data) { + // Reset input iterator. + for (int idx = 0; idx < input_num_dims; ++idx) { + input_iter[idx] = 0; + } + // Iterate through input_data. + do { + size_t input_offset = + ReducedOutputOffset(input_num_dims, input_dims, input_iter, 0, nullptr); + size_t output_offset = ReducedOutputOffset(input_num_dims, input_dims, + input_iter, num_axis, axis); + if (IsFirstReduction(input_iter, num_axis, axis)) { + output_data[output_offset] = reducer_first(input_data[input_offset]); + } else { + output_data[output_offset] = + reducer_next(output_data[output_offset], input_data[input_offset]); + } + } while (NextIndex(input_num_dims, input_dims, input_iter)); + return true; +} + +// This method parses the input 'axis' to remove duplicates and handle negative +// values, and returns a valid 'out_axis' +inline bool ResolveAxis(const int num_dims, const int* axis, + const int64_t num_axis, int* out_axis, + int* out_num_axis) { + *out_num_axis = 0; // Just in case. + // Short-circuit axis resolution for scalars; the axis will go unused. + if (num_dims == 0) { + return true; + } + // o(n^2) is fine since out_num_axis should be really small, mostly <= 4 + for (int64_t idx = 0; idx < num_axis; ++idx) { + // Handle negative index. A positive index 'p_idx' can be represented as a + // negative index 'n_idx' as: n_idx = p_idx-num_dims + // eg: For num_dims=3, [0, 1, 2] is the same as [-3, -2, -1] */ + int current = axis[idx] < 0 ? (axis[idx] + num_dims) : axis[idx]; + TFLITE_DCHECK(current >= 0 && current < num_dims); + if (current < 0 || current >= num_dims) { + return false; + } + bool is_dup = false; + for (int j = 0; j < *out_num_axis; ++j) { + if (out_axis[j] == current) { + is_dup = true; + break; + } + } + if (!is_dup) { + out_axis[*out_num_axis] = current; + *out_num_axis += 1; + } + } + return true; +} + +// This method expects that output_data has been initialized. +template +inline bool ReduceSumImpl(const In* input_data, const int* input_dims, + const int* output_dims, const int input_num_dims, + const int output_num_dims, const int* axis, + const int num_axis, int* input_iter, + Out* output_data) { + auto reducer = [](const Out current, const In in) -> Out { + const Out actual_in = static_cast(in); + return current + actual_in; + }; + return Reduce(input_data, input_dims, output_dims, input_num_dims, + output_num_dims, axis, num_axis, input_iter, reducer, + output_data); +} + +template +inline bool InitTensorDataForReduce(const int* dims, const int num_dims, + const T init_value, T* data) { + size_t num_elements = 1; + for (int idx = 0; idx < num_dims; ++idx) { + size_t current = static_cast(dims[idx]); + // Overflow prevention. + if (current > 0 && + num_elements > std::numeric_limits::max() / current) { + return false; + } + num_elements *= current; + } + for (size_t idx = 0; idx < num_elements; ++idx) { + data[idx] = init_value; + } + return true; +} + +// Computes the generic value (i.e., sum/max/min/prod) of elements across +// dimensions given in axis. It needs to pass in init_value and reducer. +template +inline bool ReduceGeneric(const T* input_data, const int* input_dims, + const int input_num_dims, T* output_data, + const int* output_dims, const int output_num_dims, + const int* axis, const int64_t num_axis_dimensions, + bool keep_dims, int* temp_index, int* resolved_axis, + T init_value, + T reducer(const T current, const T in)) { + // Reset output data. + if (!InitTensorDataForReduce(output_dims, output_num_dims, init_value, + output_data)) { + return false; + } + + // Return early when input shape has zero dim. This is done after initializing + // data for output tensor because there are cases that the input tensor is + // empty but output tensor is not. In that case, output tensor should be + // filled with init_value. + for (int i = 0; i < input_num_dims; ++i) { + if (input_dims[i] == 0) return true; + } + + // Resolve axis. + int num_resolved_axis = 0; + if (!ResolveAxis(input_num_dims, axis, num_axis_dimensions, resolved_axis, + &num_resolved_axis)) { + return false; + } + + return Reduce(input_data, input_dims, output_dims, input_num_dims, + output_num_dims, resolved_axis, num_resolved_axis, + temp_index, reducer, output_data); +} + +// Computes the mean of elements across dimensions given in axis. +// It does so in two stages, first calculates the sum of elements along the axis +// then divides it by the number of element in axis. +template +inline bool Mean(const T* input_data, const int* input_dims, + const int input_num_dims, T* output_data, + const int* output_dims, const int output_num_dims, + const int* axis, const int num_axis_dimensions, bool keep_dims, + int* temp_index, int* resolved_axis, U* temp_sum) { + ruy::profiler::ScopeLabel label("Mean"); + // Reset output data. + size_t num_outputs = 1; + for (int idx = 0; idx < output_num_dims; ++idx) { + size_t current = static_cast(output_dims[idx]); + // Overflow prevention. + if (num_outputs > std::numeric_limits::max() / current) { + return false; + } + num_outputs *= current; + } + for (size_t idx = 0; idx < num_outputs; ++idx) { + output_data[idx] = T(); + temp_sum[idx] = U(); + } + + // Resolve axis. + int num_resolved_axis = 0; + if (!ResolveAxis(input_num_dims, axis, num_axis_dimensions, resolved_axis, + &num_resolved_axis)) { + return false; + } + + if (!ReduceSumImpl(input_data, input_dims, output_dims, input_num_dims, + output_num_dims, resolved_axis, num_resolved_axis, + temp_index, temp_sum)) { + return false; + } + + // Calculate mean by dividing output_data by num of aggregated element. + size_t num_elements_in_axis = 1; + for (int idx = 0; idx < num_resolved_axis; ++idx) { + size_t current = static_cast(input_dims[resolved_axis[idx]]); + // Overflow prevention. + if (current > (std::numeric_limits::max() / num_elements_in_axis)) { + return false; + } + num_elements_in_axis *= current; + } + + if (num_elements_in_axis > 0) { + for (size_t idx = 0; idx < num_outputs; ++idx) { + output_data[idx] = + static_cast(temp_sum[idx] / static_cast(num_elements_in_axis)); + } + } + return true; +} + +template +inline void Mean(const tflite::MeanParams& op_params, + const RuntimeShape& unextended_input_shape, + const T* input_data, + const RuntimeShape& unextended_output_shape, T* output_data) { + ruy::profiler::ScopeLabel label("Mean4D"); + + // Current implementation only supports dimension equals 4 and simultaneous + // reduction over width and height. + TFLITE_CHECK_EQ(unextended_input_shape.DimensionsCount(), 4); + TFLITE_CHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + const int output_batch = output_shape.Dims(0); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int output_depth = output_shape.Dims(3); + + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + + TFLITE_CHECK_EQ(op_params.axis_count, 2); + TFLITE_CHECK((op_params.axis[0] == 1 && op_params.axis[1] == 2) || + (op_params.axis[0] == 2 && op_params.axis[1] == 1)); + TFLITE_CHECK_EQ(output_height, 1); + TFLITE_CHECK_EQ(output_width, 1); + + for (int out_b = 0; out_b < output_batch; ++out_b) { + for (int out_d = 0; out_d < output_depth; ++out_d) { + float value = 0; + for (int in_h = 0; in_h < input_height; ++in_h) { + for (int in_w = 0; in_w < input_width; ++in_w) { + value += input_data[Offset(input_shape, out_b, in_h, in_w, out_d)]; + } + } + output_data[Offset(output_shape, out_b, 0, 0, out_d)] = + value / (input_width * input_height); + } + } +} + +inline void Mean(const tflite::MeanParams& op_params, + const RuntimeShape& unextended_input_shape, + const uint8_t* input_data, int32_t input_zero_point, + float input_scale, const RuntimeShape& unextended_output_shape, + uint8_t* output_data, int32_t output_zero_point, + float output_scale) { + ruy::profiler::ScopeLabel label("Mean4D/Uint8"); + + // Current implementation only supports dimension equals 4 and simultaneous + // reduction over width and height. + TFLITE_CHECK_EQ(unextended_input_shape.DimensionsCount(), 4); + TFLITE_CHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + const int output_batch = output_shape.Dims(0); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int output_depth = output_shape.Dims(3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const float num_elements_in_axis = input_width * input_height; + + TFLITE_CHECK_EQ(op_params.axis_count, 2); + TFLITE_CHECK((op_params.axis[0] == 1 && op_params.axis[1] == 2) || + (op_params.axis[0] == 2 && op_params.axis[1] == 1)); + TFLITE_CHECK_EQ(output_height, 1); + TFLITE_CHECK_EQ(output_width, 1); + + constexpr int32_t kMinValue = std::numeric_limits::min(); + constexpr int32_t kMaxValue = std::numeric_limits::max(); + + float temp = input_zero_point * input_scale / output_scale; + temp = temp > 0 ? temp + 0.5f : temp - 0.5f; + int32_t bias = output_zero_point - static_cast(temp); + double real_scale = + static_cast(input_scale / (num_elements_in_axis * output_scale)); + + int32_t multiplier; + int shift; + QuantizeMultiplier(real_scale, &multiplier, &shift); + for (int out_b = 0; out_b < output_batch; ++out_b) { + for (int out_d = 0; out_d < output_depth; ++out_d) { + int32_t acc = 0; + for (int in_h = 0; in_h < input_height; ++in_h) { + for (int in_w = 0; in_w < input_width; ++in_w) { + acc += input_data[Offset(input_shape, out_b, in_h, in_w, out_d)]; + } + } + acc = MultiplyByQuantizedMultiplier(acc, multiplier, shift); + acc += bias; + acc = std::min(std::max(acc, kMinValue), kMaxValue); + output_data[Offset(output_shape, out_b, 0, 0, out_d)] = + static_cast(acc); + } + } +} + +// Computes the mean of elements across dimensions given in axis. +// It does so in two stages, first calculates the sum of elements along the axis +// then divides it by the number of element in axis for quantized values. +template +inline bool QuantizedMeanOrSum(const T* input_data, int32_t input_zero_point, + float input_scale, const int* input_dims, + const int input_num_dims, T* output_data, + int32_t output_zero_point, float output_scale, + const int* output_dims, + const int output_num_dims, const int* axis, + const int num_axis_dimensions, bool keep_dims, + int* temp_index, int* resolved_axis, U* temp_sum, + bool compute_sum) { + const bool uint8_case = std::is_same::value; + const bool int16_case = std::is_same::value; + if (uint8_case) { + ruy::profiler::ScopeLabel label(compute_sum ? "Sum/Uint8" : "Mean/Uint8"); + } else if (int16_case) { + ruy::profiler::ScopeLabel label(compute_sum ? "Sum/Int16" : "Mean/Int16"); + } else { + ruy::profiler::ScopeLabel label(compute_sum ? "Sum/Int8" : "Mean/Int8"); + } + // Reset output data. + size_t num_outputs = 1; + for (int idx = 0; idx < output_num_dims; ++idx) { + size_t current = static_cast(output_dims[idx]); + // Overflow prevention. + if (num_outputs > std::numeric_limits::max() / current) { + return false; + } + num_outputs *= current; + } + for (size_t idx = 0; idx < num_outputs; ++idx) { + output_data[idx] = T(); + temp_sum[idx] = U(); + } + + // Return early when input shape has zero dim. This is done after initializing + // data for output tensor because there are cases that the input tensor is + // empty but output tensor is not. In that case, output tensor should be + // filled with init_value. + for (int i = 0; i < input_num_dims; ++i) { + if (input_dims[i] == 0) return true; + } + + // Resolve axis. + int num_resolved_axis = 0; + if (!ResolveAxis(input_num_dims, axis, num_axis_dimensions, resolved_axis, + &num_resolved_axis)) { + return false; + } + + if (!ReduceSumImpl(input_data, input_dims, output_dims, input_num_dims, + output_num_dims, resolved_axis, num_resolved_axis, + temp_index, temp_sum)) { + return false; + } + + // Calculate mean by dividing output_data by num of aggregated element. + size_t num_elements_in_axis = 1; + for (int idx = 0; idx < num_resolved_axis; ++idx) { + size_t current = static_cast(input_dims[resolved_axis[idx]]); + // Overflow prevention. + if (current > (std::numeric_limits::max() / num_elements_in_axis)) { + return false; + } + num_elements_in_axis *= current; + } + + if (num_elements_in_axis > 0) { + const float scale = input_scale / output_scale; + if (compute_sum) { + // TODO(b/116341117): Eliminate float and do this completely in 8bit. + const float bias = -input_zero_point * scale * num_elements_in_axis; + for (size_t idx = 0; idx < num_outputs; ++idx) { + const U value = + static_cast(TfLiteRound(temp_sum[idx] * scale + bias)) + + output_zero_point; + output_data[idx] = static_cast(value); + } + } else { + const float bias = -input_zero_point * scale; + for (size_t idx = 0; idx < num_outputs; ++idx) { + float float_mean = static_cast(temp_sum[idx]) / + static_cast(num_elements_in_axis); + float result = TfLiteMin( + TfLiteRound(float_mean * scale + bias) + output_zero_point, + static_cast(std::numeric_limits::max())); + result = TfLiteMax(result, + static_cast(std::numeric_limits::min())); + output_data[idx] = static_cast(result); + } + } + } + return true; +} + +template +inline bool QuantizedReduceProd(const T* input_data, int32_t input_zero_point, + const RuntimeShape& input_shape, T* output_data, + int32_t output_zero_point, + const RuntimeShape& output_shape, + const int* axis, + const int64_t num_axis_dimensions, + bool keep_dims, int* temp_index, + int* resolved_axis, int32_t* temp_prod, + int32_t scaling_multiplier, int scaling_shift) { + const int32_t kMinValue = std::numeric_limits::min(); + const int32_t kMaxValue = std::numeric_limits::max(); + + // Resolve axis. + int num_resolved_axis = 0; + if (!ResolveAxis(input_shape.DimensionsCount(), axis, num_axis_dimensions, + resolved_axis, &num_resolved_axis)) { + return false; + } + + // Calculate the reduced product by rescaling each multiplication step to + // avoid an overflow. + auto reducer_first = [&](T in) -> int32_t { return in - input_zero_point; }; + + auto reducer_next = [&](int32_t current, T in) -> int32_t { + const int64_t result = + static_cast(current) * (in - input_zero_point); + return MultiplyByQuantizedMultiplier(result, scaling_multiplier, + scaling_shift); + }; + + if (!Reduce( + input_data, input_shape.DimsData(), output_shape.DimsData(), + input_shape.DimensionsCount(), output_shape.DimensionsCount(), + resolved_axis, num_resolved_axis, temp_index, reducer_first, + reducer_next, temp_prod)) { + return false; + } + + for (int i = 0; i < output_shape.FlatSize(); i++) { + int32_t result = + MultiplyByQuantizedMultiplier(static_cast(temp_prod[i]), + scaling_multiplier, scaling_shift) + + output_zero_point; + result = std::min(std::max(result, kMinValue), kMaxValue); + output_data[i] = static_cast(result); + } + + return true; +} + +} // namespace reference_ops + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_REDUCE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/requantize.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/requantize.h new file mode 100644 index 000000000..83879fbb5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/requantize.h @@ -0,0 +1,70 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_REQUANTIZE_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_REQUANTIZE_H_ + +#include + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +inline void Requantize(const input_type* input_data, int32_t size, + int32_t effective_scale_multiplier, + int32_t effective_scale_shift, int32_t input_zeropoint, + int32_t output_zeropoint, output_type* output_data) { + ruy::profiler::ScopeLabel label("Requantize"); + const bool same_scale = + (effective_scale_multiplier == 1 << 30 && effective_scale_shift == 1); + if (same_scale) { + const bool mixed_type_int8_uint8 = + std::is_same::value && + std::is_same::value; + const bool mixed_type_uint8_int8 = + std::is_same::value && + std::is_same::value; + const int32_t zero_point_diff = input_zeropoint - output_zeropoint; + // Fast path to do requantization for the case when just a shift of 128 is + // needed. + if ((mixed_type_int8_uint8 && zero_point_diff == -128) || + (mixed_type_uint8_int8 && zero_point_diff == 128)) { + for (int i = 0; i < size; ++i) { + output_data[i] = input_data[i] ^ 0x80; + } + return; + } + } + static constexpr int32_t kMinOutput = std::numeric_limits::min(); + static constexpr int32_t kMaxOutput = std::numeric_limits::max(); + for (int i = 0; i < size; ++i) { + const int32_t input = input_data[i] - input_zeropoint; + const int32_t output = + MultiplyByQuantizedMultiplier(input, effective_scale_multiplier, + effective_scale_shift) + + output_zeropoint; + const int32_t clamped_output = + std::max(std::min(output, kMaxOutput), kMinOutput); + output_data[i] = static_cast(clamped_output); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_REQUANTIZE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/resize_bilinear.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/resize_bilinear.h new file mode 100644 index 000000000..b5edadb98 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/resize_bilinear.h @@ -0,0 +1,228 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_RESIZE_BILINEAR_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_RESIZE_BILINEAR_H_ + +#include +#include +#include +#include + +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +inline void ComputeInterpolationValues(const float value, const float scale, + const bool half_pixel_centers, + int32_t input_size, float* scaled_value, + int32_t* lower_bound, + int32_t* upper_bound) { + if (half_pixel_centers) { + *scaled_value = (value + 0.5f) * scale - 0.5f; + } else { + *scaled_value = value * scale; + } + float scaled_value_floor = std::floor(*scaled_value); + *lower_bound = std::max(static_cast(scaled_value_floor), + static_cast(0)); + *upper_bound = + std::min(static_cast(std::ceil(*scaled_value)), input_size - 1); +} + +template +inline void ResizeBilinear(const tflite::ResizeBilinearParams& op_params, + const RuntimeShape& unextended_input_shape, + const T* input_data, + const RuntimeShape& unextended_output_size_shape, + const int32_t* output_size_data, + const RuntimeShape& unextended_output_shape, + T* output_data) { + // If half_pixel_centers is True, align_corners must be False. + TFLITE_DCHECK(!op_params.half_pixel_centers || !op_params.align_corners); + TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_size_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape output_size_shape = + RuntimeShape::ExtendedShape(4, unextended_output_size_shape); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + int32_t batches = MatchingDim(input_shape, 0, output_shape, 0); + int32_t input_height = input_shape.Dims(1); + int32_t input_width = input_shape.Dims(2); + int32_t depth = MatchingDim(input_shape, 3, output_shape, 3); + + TFLITE_DCHECK_EQ(output_size_shape.Dims(0), 1); + TFLITE_DCHECK_EQ(output_size_shape.Dims(1), 1); + TFLITE_DCHECK_EQ(output_size_shape.Dims(2), 1); + TFLITE_DCHECK_EQ(output_size_shape.Dims(3), 2); + int32_t output_height = + output_size_data[Offset(output_size_shape, 0, 0, 0, 0)]; + int32_t output_width = + output_size_data[Offset(output_size_shape, 0, 0, 0, 1)]; + + float height_scale = static_cast(input_height) / output_height; + float width_scale = static_cast(input_width) / output_width; + if (op_params.align_corners && output_height > 1) { + height_scale = static_cast(input_height - 1) / (output_height - 1); + } + if (op_params.align_corners && output_width > 1) { + width_scale = static_cast(input_width - 1) / (output_width - 1); + } + const float rounding_offset = std::numeric_limits::is_integer ? .5f : .0f; + + for (int b = 0; b < batches; ++b) { + for (int y = 0; y < output_height; ++y) { + float input_y; + int32_t y0, y1; + ComputeInterpolationValues(y, height_scale, op_params.half_pixel_centers, + input_height, &input_y, &y0, &y1); + for (int x = 0; x < output_width; ++x) { + float input_x; + int32_t x0, x1; + ComputeInterpolationValues(x, width_scale, op_params.half_pixel_centers, + input_width, &input_x, &x0, &x1); + for (int c = 0; c < depth; ++c) { + T interpolation = + static_cast(input_data[Offset(input_shape, b, y0, x0, c)] * + (1 - (input_y - y0)) * (1 - (input_x - x0)) + + input_data[Offset(input_shape, b, y1, x0, c)] * + (input_y - y0) * (1 - (input_x - x0)) + + input_data[Offset(input_shape, b, y0, x1, c)] * + (1 - (input_y - y0)) * (input_x - x0) + + input_data[Offset(input_shape, b, y1, x1, c)] * + (input_y - y0) * (input_x - x0) + + rounding_offset); + output_data[Offset(output_shape, b, y, x, c)] = interpolation; + } + } + } + } +} + +inline void ComputeInterpolationValuesInteger( + const int32_t value, const int32_t scale_10, const bool half_pixel_centers, + int32_t input_size, int32_t* scaled_value, int32_t* lower_bound, + int32_t* upper_bound) { + if (half_pixel_centers) { + *scaled_value = value * scale_10 + scale_10 / 2 - (1 << 9); + } else { + *scaled_value = value * scale_10; + } + constexpr int32_t zero = 0; + *lower_bound = std::max(*scaled_value / (1 << 10), zero); + *upper_bound = + std::min((*scaled_value + (1 << 10) - 1) / (1 << 10), input_size - 1); +} + +// Same as above but doesn't use any floating-point for the resize +template +inline void ResizeBilinearInteger( + const tflite::ResizeBilinearParams& op_params, + const RuntimeShape& unextended_input_shape, const T* input_data, + const RuntimeShape& unextended_output_size_shape, + const int32_t* output_size_data, + const RuntimeShape& unextended_output_shape, T* output_data) { + // If half_pixel_centers is True, align_corners must be False. + TFLITE_DCHECK(!op_params.half_pixel_centers || !op_params.align_corners); + TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_size_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape output_size_shape = + RuntimeShape::ExtendedShape(4, unextended_output_size_shape); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + const int32_t batches = MatchingDim(input_shape, 0, output_shape, 0); + const int32_t input_height = input_shape.Dims(1); + const int32_t input_width = input_shape.Dims(2); + const int32_t depth = MatchingDim(input_shape, 3, output_shape, 3); + + TFLITE_DCHECK_EQ(output_size_shape.Dims(0), 1); + TFLITE_DCHECK_EQ(output_size_shape.Dims(1), 1); + TFLITE_DCHECK_EQ(output_size_shape.Dims(2), 1); + TFLITE_DCHECK_EQ(output_size_shape.Dims(3), 2); + const int32_t output_height = + output_size_data[Offset(output_size_shape, 0, 0, 0, 0)]; + const int32_t output_width = + output_size_data[Offset(output_size_shape, 0, 0, 0, 1)]; + + int32_t height_scale_10 = + ((1 << 10) * input_height + output_height / 2) / output_height; + int32_t width_scale_10 = + ((1 << 10) * input_width + output_width / 2) / output_width; + if (op_params.align_corners && output_height > 1) { + height_scale_10 = + ((1 << 10) * (input_height - 1) + (output_height - 1) / 2) / + (output_height - 1); + } + if (op_params.align_corners && output_width > 1) { + width_scale_10 = ((1 << 10) * (input_width - 1) + (output_width - 1) / 2) / + (output_width - 1); + } + + for (int b = 0; b < batches; ++b) { + for (int y = 0; y < output_height; ++y) { + int32_t input_y, y0, y1; + ComputeInterpolationValuesInteger(y, height_scale_10, + op_params.half_pixel_centers, + input_height, &input_y, &y0, &y1); + for (int x = 0; x < output_width; ++x) { + int32_t input_x, x0, x1; + ComputeInterpolationValuesInteger(x, width_scale_10, + op_params.half_pixel_centers, + input_width, &input_x, &x0, &x1); + for (int c = 0; c < depth; ++c) { + const int64_t output_20_ll = + static_cast( + input_data[Offset(input_shape, b, y0, x0, c)]) * + ((1 << 10) - (input_y - (1 << 10) * y0)) * + ((1 << 10) - (input_x - (1 << 10) * x0)); + const int64_t output_20_lu = + static_cast( + input_data[Offset(input_shape, b, y1, x0, c)]) * + (input_y - (1 << 10) * y0) * + ((1 << 10) - (input_x - (1 << 10) * x0)); + const int64_t output_20_rl = + static_cast( + input_data[Offset(input_shape, b, y0, x1, c)]) * + ((1 << 10) - (input_y - (1 << 10) * y0)) * + (input_x - (1 << 10) * x0); + const int64_t output_20_ru = + static_cast( + input_data[Offset(input_shape, b, y1, x1, c)]) * + (input_y - (1 << 10) * y0) * (input_x - (1 << 10) * x0); + const int64_t output_20 = + output_20_ll + output_20_lu + output_20_rl + output_20_ru; + const int64_t round = (output_20 > 0) ? (1 << 19) : -(1 << 19); + const T interpolation = + static_cast((output_20 + round) / (1 << 20)); + output_data[Offset(output_shape, b, y, x, c)] = interpolation; + } + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_RESIZE_BILINEAR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h new file mode 100644 index 000000000..bf0b757e9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h @@ -0,0 +1,102 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_RESIZE_NEAREST_NEIGHBOR_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_RESIZE_NEAREST_NEIGHBOR_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +inline int32_t GetNearestNeighbor(const int input_value, + const int32_t input_size, + const int32_t output_size, + const bool align_corners, + const bool half_pixel_centers) { + const float scale = + (align_corners && output_size > 1) + ? (input_size - 1) / static_cast(output_size - 1) + : input_size / static_cast(output_size); + const float offset = half_pixel_centers ? 0.5f : 0.0f; + int32_t output_value = std::min( + align_corners + ? static_cast(TfLiteRound((input_value + offset) * scale)) + : static_cast(std::floor((input_value + offset) * scale)), + input_size - 1); + if (half_pixel_centers) { + output_value = std::max(static_cast(0), output_value); + } + return output_value; +} + +template +inline void ResizeNearestNeighbor( + const tflite::ResizeNearestNeighborParams& op_params, + const RuntimeShape& unextended_input_shape, const T* input_data, + const RuntimeShape& output_size_shape, const int32_t* output_size_data, + const RuntimeShape& unextended_output_shape, T* output_data) { + TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + int32_t batches = MatchingDim(input_shape, 0, output_shape, 0); + int32_t input_height = input_shape.Dims(1); + int32_t input_width = input_shape.Dims(2); + int32_t depth = MatchingDim(input_shape, 3, output_shape, 3); + + // The Tensorflow version of this op allows resize on the width and height + // axis only. + TFLITE_DCHECK_EQ(output_size_shape.FlatSize(), 2); + int32_t output_height = output_size_data[0]; + int32_t output_width = output_size_data[1]; + + const int col_offset = input_shape.Dims(3); + const int row_offset = input_shape.Dims(2) * col_offset; + const int batch_offset = input_shape.Dims(1) * row_offset; + + const T* input_ptr = input_data; + T* output_ptr = output_data; + for (int b = 0; b < batches; ++b) { + for (int y = 0; y < output_height; ++y) { + int32_t in_y = GetNearestNeighbor(y, input_height, output_height, + op_params.align_corners, + op_params.half_pixel_centers); + const T* y_input_ptr = input_ptr + in_y * row_offset; + for (int x = 0; x < output_width; ++x) { + int32_t in_x = GetNearestNeighbor(x, input_width, output_width, + op_params.align_corners, + op_params.half_pixel_centers); + const T* x_input_ptr = y_input_ptr + in_x * col_offset; + memcpy(output_ptr, x_input_ptr, depth * sizeof(T)); + output_ptr += depth; + } + } + input_ptr += batch_offset; + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_RESIZE_NEAREST_NEIGHBOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/round.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/round.h new file mode 100644 index 000000000..9bd8f3f2b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/round.h @@ -0,0 +1,51 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ROUND_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ROUND_H_ + +#include + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +inline float RoundToNearest(float value) { + auto floor_val = std::floor(value); + auto diff = value - floor_val; + if ((diff < 0.5f) || + ((diff == 0.5f) && (static_cast(floor_val) % 2 == 0))) { + return floor_val; + } else { + return floor_val = floor_val + 1.0f; + } +} + +inline void Round(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + // Note that this implementation matches that of tensorFlow tf.round + // and corresponds to the bankers rounding method. + // cfenv (for fesetround) is not yet supported universally on Android, so + // using a work around. + output_data[i] = RoundToNearest(input_data[i]); + } +} + +} // namespace reference_ops +} // namespace tflite +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ROUND_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/select.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/select.h new file mode 100644 index 000000000..3c0d312c6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/select.h @@ -0,0 +1,151 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SELECT_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SELECT_H_ + +#include + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +void Select(const RuntimeShape& input_condition_shape, + const D* input_condition_data, const RuntimeShape& input_x_shape, + const T* input_x_data, const RuntimeShape& input_y_shape, + const T* input_y_data, const RuntimeShape& output_shape, + T* output_data) { + ruy::profiler::ScopeLabel label("Select"); + int64_t flatsize; + // Allow select operator executions on mixed scalar tensors and one element + // tensors. + if (input_condition_shape.FlatSize() == 1 && input_x_shape.FlatSize() == 1 && + input_y_shape.FlatSize() == 1 && output_shape.FlatSize() == 1) { + flatsize = 1; + } else { + flatsize = MatchingFlatSize(input_condition_shape, input_x_shape, + input_y_shape, output_shape); + } + for (int64_t i = 0; i < flatsize; ++i) { + output_data[i] = + input_condition_data[i] ? input_x_data[i] : input_y_data[i]; + } +} + +template +void RankOneSelect(const RuntimeShape& input_condition_shape, + const D* input_condition_data, + const RuntimeShape& input_x_shape, const T* input_x_data, + const RuntimeShape& input_y_shape, const T* input_y_data, + const RuntimeShape& output_shape, T* output_data) { + ruy::profiler::ScopeLabel label("Select/RankOneSelect"); + const int64_t outer_size = input_condition_shape.FlatSize(); + int64_t inner_size; + if (input_condition_shape.DimensionsCount() == 0) { + inner_size = MatchingFlatSize(input_x_shape, input_y_shape, output_shape); + } else { + TFLITE_DCHECK_EQ( + MatchingDim(input_x_shape, 0, input_y_shape, 0, output_shape, 0), + outer_size); + inner_size = + MatchingFlatSizeSkipDim(input_x_shape, 0, input_y_shape, output_shape); + } + + int64_t offset = 0; + for (int64_t i = 0; i < outer_size; i++) { + const T* input_data = input_condition_data[i] ? input_x_data : input_y_data; + memcpy(output_data + offset, input_data + offset, inner_size * sizeof(T)); + offset += inner_size; + } +} + +template +void BroadcastSelect5DSlow(const RuntimeShape& input_condition_shape, + const D* input_condition_data, + const RuntimeShape& input_x_shape, + const T* input_x_data, + const RuntimeShape& input_y_shape, + const T* input_y_data, + const RuntimeShape& output_shape, T* output_data) { + ruy::profiler::ScopeLabel label("Select/BroadcastSelectSlow"); + TFLITE_DCHECK_LE(input_condition_shape.DimensionsCount(), 5); + TFLITE_DCHECK_LE(input_x_shape.DimensionsCount(), 5); + TFLITE_DCHECK_LE(input_y_shape.DimensionsCount(), 5); + TFLITE_DCHECK_LE(output_shape.DimensionsCount(), 5); + + NdArrayDesc<5> desc_condition; + NdArrayDesc<5> desc_x; + NdArrayDesc<5> desc_y; + NdArrayDesc<5> desc_output; + const RuntimeShape extended_output_shape = + RuntimeShape::ExtendedShape(5, output_shape); + CopyDimsToDesc(extended_output_shape, &desc_output); + NdArrayDescsForElementwiseBroadcast(input_condition_shape, input_x_shape, + input_y_shape, &desc_condition, &desc_x, + &desc_y); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest + // stride, typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for + // the best cache behavior. + for (int n = 0; n < desc_output.extents[0]; ++n) { + int out_idx_n = desc_output.extents[1] * n; + int cond_idx_n = desc_condition.strides[0] * n; + int in_idx1_n = desc_x.strides[0] * n; + int in_idx2_n = desc_y.strides[0] * n; + for (int b = 0; b < desc_output.extents[1]; ++b) { + int out_idx_b = (out_idx_n + b) * desc_output.extents[2]; + int cond_idx_b = cond_idx_n + desc_condition.strides[1] * b; + int in_idx1_b = in_idx1_n + desc_x.strides[1] * b; + int in_idx2_b = in_idx2_n + desc_y.strides[1] * b; + for (int y = 0; y < desc_output.extents[2]; ++y) { + int out_idx_y = (out_idx_b + y) * desc_output.extents[3]; + int cond_idx_y = cond_idx_b + desc_condition.strides[2] * y; + int in_idx1_y = in_idx1_b + desc_x.strides[2] * y; + int in_idx2_y = in_idx2_b + desc_y.strides[2] * y; + for (int x = 0; x < desc_output.extents[3]; ++x) { + int out_idx = (out_idx_y + x) * desc_output.extents[4]; + int cond_idx = cond_idx_y + desc_condition.strides[3] * x; + int in_idx1 = in_idx1_y + desc_x.strides[3] * x; + int in_idx2 = in_idx2_y + desc_y.strides[3] * x; + for (int c = 0; c < desc_output.extents[4]; ++c) { + output_data[out_idx] = input_condition_data[cond_idx] + ? input_x_data[in_idx1] + : input_y_data[in_idx2]; + out_idx++; + cond_idx += desc_condition.strides[4]; + in_idx1 += desc_x.strides[4]; + in_idx2 += desc_y.strides[4]; + } + } + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SELECT_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/slice.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/slice.h new file mode 100644 index 000000000..cb73ea0d0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/slice.h @@ -0,0 +1,80 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SLICE_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SLICE_H_ + +#include "tensorflow/lite/kernels/internal/portable_tensor.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +template +inline void Slice(const tflite::SliceParams& op_params, + const RuntimeShape& input_shape, + const RuntimeShape& output_shape, + SequentialTensorWriter* writer) { + const RuntimeShape ext_shape = RuntimeShape::ExtendedShape(5, input_shape); + TFLITE_DCHECK_LE(op_params.begin_count, 5); + TFLITE_DCHECK_LE(op_params.size_count, 5); + const int begin_count = op_params.begin_count; + const int size_count = op_params.size_count; + // We front-pad the begin and size vectors. + int start[5]; + int stop[5]; + for (int i = 0; i < 5; ++i) { + int padded_i = 5 - i; + start[i] = + begin_count < padded_i ? 0 : op_params.begin[begin_count - padded_i]; + stop[i] = + (size_count < padded_i || op_params.size[size_count - padded_i] == -1) + ? ext_shape.Dims(i) + : start[i] + op_params.size[size_count - padded_i]; + } + + for (int i0 = start[0]; i0 < stop[0]; ++i0) { + for (int i1 = start[1]; i1 < stop[1]; ++i1) { + for (int i2 = start[2]; i2 < stop[2]; ++i2) { + for (int i3 = start[3]; i3 < stop[3]; ++i3) { + for (int i4 = start[4]; i4 < stop[4]; ++i4) { + writer->Write(Offset(ext_shape, i0, i1, i2, i3, i4)); + } + } + } + } + } +} + +template +inline void Slice(const tflite::SliceParams& op_params, + const RuntimeShape& input_shape, const T* input_data, + const RuntimeShape& output_shape, T* output_data) { + SequentialTensorWriter writer(input_data, output_data); + return Slice(op_params, input_shape, output_shape, &writer); +} + +template +inline void Slice(const tflite::SliceParams& op_params, + const RuntimeShape& input_shape, const TfLiteTensor* input, + const RuntimeShape& output_shape, TfLiteTensor* output) { + SequentialTensorWriter writer(input, output); + return Slice(op_params, input_shape, output_shape, &writer); +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SLICE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/softmax.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/softmax.h new file mode 100644 index 000000000..f43c72024 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/softmax.h @@ -0,0 +1,233 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SOFTMAX_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SOFTMAX_H_ + +#include +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/op_macros.h" + +namespace tflite { +namespace reference_ops { + +inline void Softmax(const SoftmaxParams& params, + const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + + for (int i = 0; i < outer_size; ++i) { + // Find max element value which we'll use to ensure numerical stability + // taking advantage of the following equality: + // exp(x[i])/sum(exp(x[i])) == exp(x[i]+C)/sum(exp(x[i]+C)) + float max = std::numeric_limits::lowest(); + for (int c = 0; c < depth; ++c) { + max = std::max(max, input_data[i * depth + c]); + } + + // Compute sum. + float sum = 0.f; + for (int c = 0; c < depth; ++c) { + const float exp_c = std::exp((input_data[i * depth + c] - max) * + static_cast(params.beta)); + output_data[i * depth + c] = exp_c; + sum += exp_c; + } + + // Compute result. + for (int c = 0; c < depth; ++c) { + output_data[i * depth + c] = output_data[i * depth + c] / sum; + } + } +} + +// Quantized softmax with int8_t/uint8_t input and int8_t/uint8_t/int16_t +// output. +template +inline void Softmax(const SoftmaxParams& params, + const RuntimeShape& input_shape, const InputT* input_data, + const RuntimeShape& output_shape, OutputT* output_data) { + const int32_t input_beta_multiplier = params.input_multiplier; + const int32_t input_beta_left_shift = params.input_left_shift; + const int diff_min = params.diff_min; + // The representation chosen for the input to the exp() function is Q5.26. + // We need to leave extra space since values that we skip might be as large as + // -32 before multiplying by input_beta_multiplier, and therefore as large as + // -16 afterwards. Note that exp(-8) is definitely not insignificant to + // accumulation, but exp(-16) definitely is. + static const int kScaledDiffIntegerBits = 5; + static const int kAccumulationIntegerBits = 12; + using FixedPointScaledDiff = + gemmlowp::FixedPoint; + using FixedPointAccum = + gemmlowp::FixedPoint; + using FixedPoint0 = gemmlowp::FixedPoint; + + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + + for (int i = 0; i < outer_size; ++i) { + InputT max_in_row = std::numeric_limits::min(); + for (int c = 0; c < depth; ++c) { + max_in_row = std::max(max_in_row, input_data[i * depth + c]); + } + + FixedPointAccum sum_of_exps = FixedPointAccum::Zero(); + for (int c = 0; c < depth; ++c) { + int32_t input_diff = + static_cast(input_data[i * depth + c]) - max_in_row; + if (input_diff >= diff_min) { + const int32_t input_diff_rescaled = + MultiplyByQuantizedMultiplierGreaterThanOne( + input_diff, input_beta_multiplier, input_beta_left_shift); + const FixedPointScaledDiff scaled_diff_f8 = + FixedPointScaledDiff::FromRaw(input_diff_rescaled); + sum_of_exps = sum_of_exps + gemmlowp::Rescale( + exp_on_negative_values(scaled_diff_f8)); + } + } + + int num_bits_over_unit; + FixedPoint0 shifted_scale = FixedPoint0::FromRaw(GetReciprocal( + sum_of_exps.raw(), kAccumulationIntegerBits, &num_bits_over_unit)); + + for (int c = 0; c < depth; ++c) { + int32_t input_diff = + static_cast(input_data[i * depth + c]) - max_in_row; + if (input_diff >= diff_min) { + const int32_t input_diff_rescaled = + MultiplyByQuantizedMultiplierGreaterThanOne( + input_diff, input_beta_multiplier, input_beta_left_shift); + const FixedPointScaledDiff scaled_diff_f8 = + FixedPointScaledDiff::FromRaw(input_diff_rescaled); + + FixedPoint0 exp_in_0 = exp_on_negative_values(scaled_diff_f8); + int32_t unsat_output = gemmlowp::RoundingDivideByPOT( + (shifted_scale * exp_in_0).raw(), + num_bits_over_unit + 31 - (sizeof(OutputT) * 8)); + + const int32_t shifted_output = + unsat_output + + static_cast(std::numeric_limits::min()); + + output_data[i * depth + c] = static_cast(std::max( + std::min(shifted_output, + static_cast(std::numeric_limits::max())), + static_cast(std::numeric_limits::min()))); + } else { + output_data[i * depth + c] = std::numeric_limits::min(); + } + } + } +} + +// Computes exp(input - max_input) +inline int16_t SoftMaxCalculateExp(const SoftmaxParams& params, + const int16_t* input_data, const int depth, + int16_t max_in_row, int i, int c) { + int32_t input_diff = input_data[i * depth + c] - max_in_row; + // scale the input_diff such that [-65535, 0] correspond to [-10.0, 0.0] + // exp lut generated with range [-10, 0], as exp(-10) is negligible. + int32_t scaled_diff = MultiplyByQuantizedMultiplier( + input_diff, params.input_multiplier, params.input_left_shift); + // recenter to [-32768, 32767] + int32_t sym_scaled_diff = scaled_diff + 32767; + int16_t sat_sym_scaled_diff = + std::min(std::max(sym_scaled_diff, static_cast(-32768)), + static_cast(32767)); + // apply the exp() LUT activation function + return LUTLookup(sat_sym_scaled_diff, params.exp_lut); +} +// Quantized softmax with int16_t input and int16_t output. +inline void SoftmaxInt16(const SoftmaxParams& params, + const RuntimeShape& input_shape, + const int16_t* input_data, + const RuntimeShape& output_shape, + int16_t* output_data) { + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + + for (int i = 0; i < outer_size; ++i) { + // Find the largest element + int16_t max_in_row = std::numeric_limits::min(); + for (int c = 0; c < depth; ++c) { + max_in_row = std::max(max_in_row, input_data[i * depth + c]); + } + + // This loops computes the exp values and their sum. We will need the exp + // values later on in the function so we cache them in the output_data + // buffer. This is an optimization done to avoid calculating the exp values + // twice making use of the output_data buffer as scratch memory. + int32_t sum_of_exps = 0; // Q16.15 fixed point format. + int16_t* exp_results_Q015 = output_data + i * depth; + for (int c = 0; c < depth; ++c) { + exp_results_Q015[c] = + SoftMaxCalculateExp(params, input_data, depth, max_in_row, i, c); + sum_of_exps += exp_results_Q015[c]; + } + + // Compute the reciprocal 1/sum_of_exps + uint8_t headroom_plus_one = + CountLeadingZeros(static_cast(sum_of_exps)); + int32_t shifted_sum = + ((static_cast(sum_of_exps) << (headroom_plus_one - 1)) + + (1 << 13)) >> + 14; + // since the LUT computes 1/(1 + x) we need to first compute x = (sum - 1). + // also, the LUT expects a symmetrical input, so we must also recenter x + // from [0, 65535] to [-32768, 32767]. + int32_t sym_shifted_sum = shifted_sum + (-((1 << 15) + (1 << 16))); + int16_t sat_sym_shifted_sum = static_cast( + std::min(std::max(sym_shifted_sum, static_cast(-32768)), + static_cast(32767))); + // apply 1/(1 + x) LUT activation function + int16_t reciprocal_scale_Q015 = + LUTLookup(sat_sym_shifted_sum, params.one_over_one_plus_x_lut); + + // Rescale the exp_result with reciprocal + // range of output is [0, 32767] correspond to [0.0, 1.0] + for (int c = 0; c < depth; ++c) { + uint8_t right_shift = 31 - headroom_plus_one; + int64_t round = 1 << (right_shift - 1); + int32_t result = (static_cast(exp_results_Q015[c]) * + static_cast(reciprocal_scale_Q015) + + round) >> + right_shift; + output_data[i * depth + c] = static_cast( + std::min(std::max(result, static_cast(0)), + static_cast(32767))); + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SOFTMAX_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h new file mode 100644 index 000000000..dcef04a8f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h @@ -0,0 +1,109 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SPACE_TO_BATCH_ND_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SPACE_TO_BATCH_ND_H_ + +#include + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +// TODO(b/135760455): Move this method anonymous namespace in a cc file. +inline RuntimeShape ExtendShapeSpaceToBatch(const RuntimeShape& shape) { + if (shape.DimensionsCount() == 4) { + return shape; + } + RuntimeShape new_shape(4, 1); + new_shape.SetDim(0, shape.Dims(0)); + new_shape.SetDim(1, shape.Dims(1)); + new_shape.SetDim(3, shape.Dims(2)); + return new_shape; +} + +template +inline void SpaceToBatchND(const SpaceToBatchParams& params, + const RuntimeShape& unextended_input1_shape, + const T* input1_data, + const RuntimeShape& unextended_input2_shape, + const int32_t* block_shape_data, + const RuntimeShape& unextended_input3_shape, + const int32_t* paddings_data, + const RuntimeShape& unextended_output_shape, + T* output_data) { + ruy::profiler::ScopeLabel label("SpaceToBatchND"); + TFLITE_DCHECK_GE(unextended_input1_shape.DimensionsCount(), 3); + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(unextended_input1_shape.DimensionsCount(), + unextended_output_shape.DimensionsCount()); + + // Extends the input/output shape from 3D to 4D if needed, NHC -> NH1C. + const RuntimeShape input1_shape = + ExtendShapeSpaceToBatch(unextended_input1_shape); + const RuntimeShape output_shape = + ExtendShapeSpaceToBatch(unextended_output_shape); + + const int depth = input1_shape.Dims(3); + const int input_width = input1_shape.Dims(2); + const int input_height = input1_shape.Dims(1); + const int input_batch_size = input1_shape.Dims(0); + + const int output_width = output_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_batch_size = output_shape.Dims(0); + + const int block_shape_height = block_shape_data[0]; + const int block_shape_width = + unextended_input1_shape.DimensionsCount() == 4 ? block_shape_data[1] : 1; + const int padding_top = paddings_data[0]; + const int padding_left = + unextended_input1_shape.DimensionsCount() == 4 ? paddings_data[2] : 0; + + // For uint8 quantized, the correct padding "zero value" is the output offset. + const int32_t pad_value = params.output_offset; + for (int out_b = 0; out_b < output_batch_size; ++out_b) { + int input_batch = out_b % input_batch_size; + int shift_w = (out_b / input_batch_size) % block_shape_width; + int shift_h = (out_b / input_batch_size) / block_shape_width; + for (int out_h = 0; out_h < output_height; ++out_h) { + for (int out_w = 0; out_w < output_width; ++out_w) { + T* out = output_data + Offset(output_shape, out_b, out_h, out_w, 0); + if (out_h * block_shape_height + shift_h < padding_top || + out_h * block_shape_height + shift_h >= + padding_top + input_height || + out_w * block_shape_width + shift_w < padding_left || + out_w * block_shape_width + shift_w >= padding_left + input_width) { + // This may not execute correctly when pad_value != 0 and T != uint8. + memset(out, pad_value, depth * sizeof(T)); + } else { + const T* in = + input1_data + + Offset(input1_shape, input_batch, + (out_h * block_shape_height + shift_h) - padding_top, + (out_w * block_shape_width + shift_w) - padding_left, 0); + memcpy(out, in, depth * sizeof(T)); + } + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SPACE_TO_BATCH_ND_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/space_to_depth.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/space_to_depth.h new file mode 100644 index 000000000..7ad465494 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/space_to_depth.h @@ -0,0 +1,80 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SPACE_TO_DEPTH_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SPACE_TO_DEPTH_H_ + +#include + +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace reference_ops { + +template +inline void SpaceToDepth(const tflite::SpaceToDepthParams& op_params, + const RuntimeShape& unextended_input_shape, + const T* input_data, + const RuntimeShape& unextended_output_shape, + T* output_data) { + TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(4, unextended_input_shape); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + const int input_depth = input_shape.Dims(3); + const int input_width = input_shape.Dims(2); + const int input_height = input_shape.Dims(1); + const int input_batch = input_shape.Dims(0); + + const int output_depth = output_shape.Dims(3); + const int output_width = output_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_batch = output_shape.Dims(0); + + const int32_t block_size = op_params.block_size; + + TFLITE_DCHECK_EQ(input_width, output_width * block_size); + TFLITE_DCHECK_EQ(input_height, output_height * block_size); + TFLITE_DCHECK_EQ(input_depth * block_size * block_size, output_depth); + TFLITE_DCHECK_EQ(input_batch, output_batch); + + for (int in_b = 0; in_b < input_batch; ++in_b) { + for (int in_h = 0; in_h < input_height; ++in_h) { + for (int in_w = 0; in_w < input_width; ++in_w) { + for (int in_d = 0; in_d < input_depth; ++in_d) { + const int out_d = + in_d + ((in_h % block_size) * block_size + in_w % block_size) * + input_depth; + const int out_w = in_w / block_size; + const int out_h = in_h / block_size; + const int out_b = in_b; + + const int input_index = Offset(input_shape, in_b, in_h, in_w, in_d); + const int output_index = + Offset(output_shape, out_b, out_h, out_w, out_d); + + output_data[output_index] = input_data[input_index]; + } + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SPACE_TO_DEPTH_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/strided_slice.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/strided_slice.h new file mode 100644 index 000000000..2b71c79b2 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/strided_slice.h @@ -0,0 +1,121 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_STRIDED_SLICE_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_STRIDED_SLICE_H_ + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/portable_tensor.h" +#include "tensorflow/lite/kernels/internal/strided_slice_logic.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +template +inline void StridedSlice(const tflite::StridedSliceParams& op_params, + const RuntimeShape& unextended_input_shape, + const RuntimeShape& unextended_output_shape, + SequentialTensorWriter* writer) { + using strided_slice::LoopCondition; + using strided_slice::StartForAxis; + using strided_slice::StopForAxis; + + ruy::profiler::ScopeLabel label("StridedSlice"); + + // Note that the output_shape is not used herein. + tflite::StridedSliceParams params_copy = op_params; + + TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 5); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 5); + const RuntimeShape input_shape = + RuntimeShape::ExtendedShape(5, unextended_input_shape); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(5, unextended_output_shape); + + // Reverse and pad to 5 dimensions because that is what the runtime code + // requires (ie. all shapes must be 5D and are given backwards). + strided_slice::StridedSlicePadIndices(¶ms_copy, 5); + + const int start_0 = StartForAxis(params_copy, input_shape, 0); + const int stop_0 = StopForAxis(params_copy, input_shape, 0, start_0); + const int start_1 = StartForAxis(params_copy, input_shape, 1); + const int stop_1 = StopForAxis(params_copy, input_shape, 1, start_1); + const int start_2 = StartForAxis(params_copy, input_shape, 2); + const int stop_2 = StopForAxis(params_copy, input_shape, 2, start_2); + const int start_3 = StartForAxis(params_copy, input_shape, 3); + const int stop_3 = StopForAxis(params_copy, input_shape, 3, start_3); + const int start_4 = StartForAxis(params_copy, input_shape, 4); + const int stop_4 = StopForAxis(params_copy, input_shape, 4, start_4); + + for (int offset_0 = start_0 * input_shape.Dims(1), + end_0 = stop_0 * input_shape.Dims(1), + step_0 = params_copy.strides[0] * input_shape.Dims(1); + !LoopCondition(offset_0, end_0, params_copy.strides[0]); + offset_0 += step_0) { + for (int offset_1 = (offset_0 + start_1) * input_shape.Dims(2), + end_1 = (offset_0 + stop_1) * input_shape.Dims(2), + step_1 = params_copy.strides[1] * input_shape.Dims(2); + !LoopCondition(offset_1, end_1, params_copy.strides[1]); + offset_1 += step_1) { + for (int offset_2 = (offset_1 + start_2) * input_shape.Dims(3), + end_2 = (offset_1 + stop_2) * input_shape.Dims(3), + step_2 = params_copy.strides[2] * input_shape.Dims(3); + !LoopCondition(offset_2, end_2, params_copy.strides[2]); + offset_2 += step_2) { + for (int offset_3 = (offset_2 + start_3) * input_shape.Dims(4), + end_3 = (offset_2 + stop_3) * input_shape.Dims(4), + step_3 = params_copy.strides[3] * input_shape.Dims(4); + !LoopCondition(offset_3, end_3, params_copy.strides[3]); + offset_3 += step_3) { + for (int offset_4 = offset_3 + start_4, end_4 = offset_3 + stop_4; + !LoopCondition(offset_4, end_4, params_copy.strides[4]); + offset_4 += params_copy.strides[4]) { + writer->Write(offset_4); + } + } + } + } + } +} + +template +inline void StridedSlice(const tflite::StridedSliceParams& op_params, + const RuntimeShape& unextended_input_shape, + const T* input_data, + const RuntimeShape& unextended_output_shape, + T* output_data) { + SequentialTensorWriter writer(input_data, output_data); + StridedSlice(op_params, unextended_input_shape, unextended_output_shape, + &writer); +} + +template +inline void StridedSlice(const tflite::StridedSliceParams& op_params, + const RuntimeShape& unextended_input_shape, + const TfLiteTensor* input, + const RuntimeShape& unextended_output_shape, + TfLiteTensor* output) { + SequentialTensorWriter writer(input, output); + StridedSlice(op_params, unextended_input_shape, unextended_output_shape, + &writer); +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_STRIDED_SLICE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/sub.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/sub.h new file mode 100644 index 000000000..6af4cbd91 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/sub.h @@ -0,0 +1,479 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SUB_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SUB_H_ + +#include + +#include +#include + +#include "third_party/ruy/ruy/profiler/instrumentation.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +inline void SubNonBroadcast(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const float* input1_data, + const RuntimeShape& input2_shape, + const float* input2_data, + const RuntimeShape& output_shape, + float* output_data) { + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = ActivationFunctionWithMinMax( + input1_data[i] - input2_data[i], params.float_activation_min, + params.float_activation_max); + } +} + +inline void SubNonBroadcast(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const int32_t* input1_data, + const RuntimeShape& input2_shape, + const int32_t* input2_data, + const RuntimeShape& output_shape, + int32_t* output_data) { + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = ActivationFunctionWithMinMax( + input1_data[i] - input2_data[i], params.quantized_activation_min, + params.quantized_activation_max); + } +} + +// TODO(b/151345304): We can implement BroadcastSub on buffers of arbitrary +// dimensionality if the runtime code does a single loop over one dimension +// that handles broadcasting as the base case. The code generator would then +// generate max(D1, D2) nested for loops. +template +inline void BroadcastSubSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const float* input1_data, + const RuntimeShape& input2_shape, + const float* input2_data, + const RuntimeShape& output_shape, + float* output_data) { + ruy::profiler::ScopeLabel label("BroadcastSubSlow/float"); + TFLITE_DCHECK_LE(input1_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(input2_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(output_shape.DimensionsCount(), N); + NdArrayDesc desc1; + NdArrayDesc desc2; + NdArrayDesc output_desc; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, output_shape), &output_desc); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + auto sub_func = [&](int indexes[N]) { + output_data[SubscriptToIndex(output_desc, indexes)] = + ActivationFunctionWithMinMax( + input1_data[SubscriptToIndex(desc1, indexes)] - + input2_data[SubscriptToIndex(desc2, indexes)], + params.float_activation_min, params.float_activation_max); + }; + NDOpsHelper(output_desc, sub_func); +} + +template +inline void BroadcastSubSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const int32_t* input1_data, + const RuntimeShape& input2_shape, + const int32_t* input2_data, + const RuntimeShape& output_shape, + int32_t* output_data) { + ruy::profiler::ScopeLabel label("BroadcastSubSlow/int32_t"); + TFLITE_DCHECK_LE(input1_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(input2_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(output_shape.DimensionsCount(), N); + NdArrayDesc desc1; + NdArrayDesc desc2; + NdArrayDesc output_desc; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, output_shape), &output_desc); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + auto sub_func = [&](int indexes[N]) { + output_data[SubscriptToIndex(output_desc, indexes)] = + ActivationFunctionWithMinMax( + input1_data[SubscriptToIndex(desc1, indexes)] - + input2_data[SubscriptToIndex(desc2, indexes)], + params.quantized_activation_min, params.quantized_activation_max); + }; + NDOpsHelper(output_desc, sub_func); +} + +template +void BroadcastSubSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const int64_t* input1_data, + const RuntimeShape& input2_shape, + const int64_t* input2_data, + const RuntimeShape& output_shape, int64_t* output_data) { + ruy::profiler::ScopeLabel label("BroadcastSubSlow/int64_t"); + TFLITE_DCHECK_LE(input1_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(input2_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(output_shape.DimensionsCount(), N); + NdArrayDesc desc1; + NdArrayDesc desc2; + NdArrayDesc output_desc; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, output_shape), &output_desc); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + auto sub_func = [&](int indexes[N]) { + output_data[SubscriptToIndex(output_desc, indexes)] = + ActivationFunctionWithMinMax( + input1_data[SubscriptToIndex(desc1, indexes)] - + input2_data[SubscriptToIndex(desc2, indexes)], + params.int64_activation_min, params.int64_activation_max); + }; + NDOpsHelper(output_desc, sub_func); +} + +template +void BroadcastSubSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const T* input1_data, + const RuntimeShape& input2_shape, const T* input2_data, + const RuntimeShape& output_shape, T* output_data) { + ruy::profiler::ScopeLabel label("BroadcastSubSlow/templated"); + TFLITE_DCHECK_LE(input1_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(input2_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(output_shape.DimensionsCount(), N); + NdArrayDesc desc1; + NdArrayDesc desc2; + NdArrayDesc output_desc; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, output_shape), &output_desc); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + auto sub_func = [&](int indexes[N]) { + output_data[SubscriptToIndex(output_desc, indexes)] = + ActivationFunctionWithMinMax( + input1_data[SubscriptToIndex(desc1, indexes)] - + input2_data[SubscriptToIndex(desc2, indexes)], + params.quantized_activation_min, params.quantized_activation_max); + }; + NDOpsHelper(output_desc, sub_func); +} + +template +inline void BroadcastSub16POTSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const int16_t* input1_data, + const RuntimeShape& input2_shape, + const int16_t* input2_data, + const RuntimeShape& output_shape, + int16_t* output_data) { + ruy::profiler::ScopeLabel label("BroadcastSub16POTSlow/int16_t"); + NdArrayDesc desc1; + NdArrayDesc desc2; + NdArrayDesc output_desc; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, output_shape), &output_desc); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + auto sub_func = [&](int indexes[N]) { + const int32_t input1_val = input1_data[SubscriptToIndex(desc1, indexes)]; + const int32_t input2_val = input2_data[SubscriptToIndex(desc2, indexes)]; + const int32_t scaled_input1_val = + gemmlowp::RoundingDivideByPOT(input1_val, -params.input1_shift); + const int32_t scaled_input2_val = + gemmlowp::RoundingDivideByPOT(input2_val, -params.input2_shift); + const int32_t raw_output = scaled_input1_val - scaled_input2_val; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + output_data[SubscriptToIndex(output_desc, indexes)] = + static_cast(clamped_output); + }; + NDOpsHelper(output_desc, sub_func); +} + +template +void BroadcastQuantSubSlow(const ArithmeticParams& params, + const RuntimeShape& input1_shape, + const T* input1_data, + const RuntimeShape& input2_shape, + const T* input2_data, + const RuntimeShape& output_shape, T* output_data) { + ruy::profiler::ScopeLabel label("BroadcastQuantSubSlow/T"); + TFLITE_DCHECK_LE(input1_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(input2_shape.DimensionsCount(), N); + TFLITE_DCHECK_LE(output_shape.DimensionsCount(), N); + NdArrayDesc desc1; + NdArrayDesc desc2; + NdArrayDesc output_desc; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, output_shape), &output_desc); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + auto sub_func = [&](int indexes[N]) { + const int32_t input1_val = + params.input1_offset + input1_data[SubscriptToIndex(desc1, indexes)]; + const int32_t input2_val = + params.input2_offset + input2_data[SubscriptToIndex(desc2, indexes)]; + const int32_t shifted_input1_val = input1_val * (1 << params.left_shift); + const int32_t shifted_input2_val = input2_val * (1 << params.left_shift); + const int32_t scaled_input1_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input1_val, params.input1_multiplier, params.input1_shift); + const int32_t scaled_input2_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input2_val, params.input2_multiplier, params.input2_shift); + const int32_t raw_sub = scaled_input1_val - scaled_input2_val; + const int32_t raw_output = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + raw_sub, params.output_multiplier, params.output_shift) + + params.output_offset; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + output_data[SubscriptToIndex(output_desc, indexes)] = + static_cast(clamped_output); + }; + NDOpsHelper(output_desc, sub_func); +} + +// Element-wise add that can often be used for inner loop of broadcast add as +// well as the non-broadcast add. +template +inline void SubElementwise(int size, const ArithmeticParams& params, + const T* input1_data, const T* input2_data, + T* output_data) { + for (int i = 0; i < size; ++i) { + const int32_t input1_val = params.input1_offset + input1_data[i]; + const int32_t input2_val = params.input2_offset + input2_data[i]; + const int32_t shifted_input1_val = input1_val * (1 << params.left_shift); + const int32_t shifted_input2_val = input2_val * (1 << params.left_shift); + const int32_t scaled_input1_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input1_val, params.input1_multiplier, params.input1_shift); + const int32_t scaled_input2_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input2_val, params.input2_multiplier, params.input2_shift); + const int32_t raw_sub = scaled_input1_val - scaled_input2_val; + const int32_t raw_output = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + raw_sub, params.output_multiplier, params.output_shift) + + params.output_offset; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + output_data[i] = static_cast(clamped_output); + } +} + +inline void Sub(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const uint8_t* input1_data, + const RuntimeShape& input2_shape, const uint8_t* input2_data, + const RuntimeShape& output_shape, uint8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + TFLITE_DCHECK_GT(params.input1_offset, -256); + TFLITE_DCHECK_GT(params.input2_offset, -256); + TFLITE_DCHECK_LT(params.input1_offset, 256); + TFLITE_DCHECK_LT(params.input2_offset, 256); + SubElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +inline void Sub(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const int8_t* input1_data, + const RuntimeShape& input2_shape, const int8_t* input2_data, + const RuntimeShape& output_shape, int8_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + TFLITE_DCHECK_GE(params.input1_offset, -128); + TFLITE_DCHECK_GE(params.input2_offset, -128); + // offset = -quantization_params.zero_point in PrepareGeneralSubOp(). + // So it's maximum can be 128 not 127. + TFLITE_DCHECK_LE(params.input1_offset, 128); + TFLITE_DCHECK_LE(params.input2_offset, 128); + SubElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +inline void Sub(const ArithmeticParams& params, + const RuntimeShape& input1_shape, const int16_t* input1_data, + const RuntimeShape& input2_shape, const int16_t* input2_data, + const RuntimeShape& output_shape, int16_t* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + + TFLITE_DCHECK_EQ(params.input1_offset, 0); + TFLITE_DCHECK_EQ(params.input2_offset, 0); + SubElementwise(flat_size, params, input1_data, input2_data, output_data); +} + +template +void Sub(const ArithmeticParams& params, const RuntimeShape& input1_shape, + const T* input1_data, const RuntimeShape& input2_shape, + const T* input2_data, const RuntimeShape& output_shape, + T* output_data) { + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, + &desc2); + const RuntimeShape extended_output_shape = + RuntimeShape::ExtendedShape(4, output_shape); + + // In Tensorflow, the dimensions are canonically named (batch_number, row, + // col, channel), with extents (batches, height, width, depth), with the + // trailing dimension changing most rapidly (channels has the smallest stride, + // typically 1 element). + // + // In generated C code, we store arrays with the dimensions reversed. The + // first dimension has smallest stride. + // + // We name our variables by their Tensorflow convention, but generate C code + // nesting loops such that the innermost loop has the smallest stride for the + // best cache behavior. + for (int b = 0; b < extended_output_shape.Dims(0); ++b) { + for (int y = 0; y < extended_output_shape.Dims(1); ++y) { + for (int x = 0; x < extended_output_shape.Dims(2); ++x) { + for (int c = 0; c < extended_output_shape.Dims(3); ++c) { + output_data[Offset(extended_output_shape, b, y, x, c)] = + input1_data[SubscriptToIndex(desc1, b, y, x, c)] - + input2_data[SubscriptToIndex(desc2, b, y, x, c)]; + } + } + } + } +} + +inline void SetActivationMinMax(const ArithmeticParams& params, + int32_t* activation_min, + int32_t* activation_max) { + *activation_min = params.quantized_activation_min; + *activation_max = params.quantized_activation_max; +} + +inline void SetActivationMinMax(const ArithmeticParams& params, + float* activation_min, float* activation_max) { + *activation_min = params.float_activation_min; + *activation_max = params.float_activation_max; +} + +inline void SetActivationMinMax(const ArithmeticParams& params, + int64_t* activation_min, + int64_t* activation_max) { + *activation_min = params.int64_activation_min; + *activation_max = params.int64_activation_max; +} + +template +inline void SubWithActivation( + const ArithmeticParams& params, const RuntimeShape& input1_shape, + const T* input1_data, const RuntimeShape& input2_shape, + const T* input2_data, const RuntimeShape& output_shape, T* output_data) { + ruy::profiler::ScopeLabel label("SubWithActivation"); + const int flat_size = + MatchingElementsSize(input1_shape, input2_shape, output_shape); + T activation_min, activation_max; + SetActivationMinMax(params, &activation_min, &activation_max); + + for (int i = 0; i < flat_size; ++i) { + output_data[i] = ActivationFunctionWithMinMax( + input1_data[i] - input2_data[i], activation_min, activation_max); + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SUB_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/tanh.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/tanh.h new file mode 100644 index 000000000..9d9969176 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/tanh.h @@ -0,0 +1,129 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_TANH_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_TANH_H_ + +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/op_macros.h" + +namespace tflite { +namespace reference_ops { + +inline void Tanh(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; i++) { + float val = input_data[i]; + float result = std::tanh(val); + output_data[i] = result; + } +} + +// Convenience version that allows, for example, generated-code calls to be +// uniform between data types. +inline void Tanh(const TanhParams&, const RuntimeShape& input_shape, + const float* input_data, const RuntimeShape& output_shape, + float* output_data) { + // Drop params: not needed. + Tanh(input_shape, input_data, output_shape, output_data); +} + +inline void Tanh(const TanhParams& params, const RuntimeShape& input_shape, + const int16_t* input_data, const RuntimeShape& output_shape, + int16_t* output_data) { + const int input_left_shift = params.input_left_shift; + // Support for shifts is limited until we have a parameterized version of + // SaturatingRoundingMultiplyByPOT(). + TFLITE_DCHECK_GE(input_left_shift, 0); + TFLITE_DCHECK_LE(input_left_shift, 1); + + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + // F0 uses 0 integer bits, range [-1, 1]. + // This is the return type of math functions such as tanh, logistic, + // whose range is in [-1, 1]. + using F0 = gemmlowp::FixedPoint; + // F3 uses 3 integer bits, range [-8, 8], the input range expected here. + using F3 = gemmlowp::FixedPoint; + + if (input_left_shift == 0) { + for (int i = 0; i < flat_size; i++) { + F3 input = F3::FromRaw(input_data[i]); + F0 output = gemmlowp::tanh(input); + output_data[i] = output.raw(); + } + } else { + for (int i = 0; i < flat_size; i++) { + F3 input = F3::FromRaw( + gemmlowp::SaturatingRoundingMultiplyByPOT<1>(input_data[i])); + F0 output = gemmlowp::tanh(input); + output_data[i] = output.raw(); + } + } +} + +inline void Tanh(const TanhParams& params, const RuntimeShape& input_shape, + const uint8_t* input_data, const RuntimeShape& output_shape, + uint8_t* output_data) { + const int32_t input_zero_point = params.input_zero_point; + const int32_t input_range_radius = params.input_range_radius; + const int32_t input_multiplier = params.input_multiplier; + const int input_left_shift = params.input_left_shift; + const int32_t output_zero_point = 128; + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; i++) { + const uint8_t input_val_u8 = input_data[i]; + const int32_t input_val_centered = + static_cast(input_val_u8) - input_zero_point; + uint8_t output_val; + if (input_val_centered <= -input_range_radius) { + output_val = 0; + } else if (input_val_centered >= input_range_radius) { + output_val = 255; + } else { + const int32_t input_val_rescaled = + MultiplyByQuantizedMultiplierGreaterThanOne( + input_val_centered, input_multiplier, input_left_shift); + using FixedPoint4 = gemmlowp::FixedPoint; + using FixedPoint0 = gemmlowp::FixedPoint; + const FixedPoint4 input_val_f4 = FixedPoint4::FromRaw(input_val_rescaled); + const FixedPoint0 output_val_f0 = gemmlowp::tanh(input_val_f4); + // Convert from Q0.31 to Q24.7. + using gemmlowp::RoundingDivideByPOT; + int32_t output_val_s32 = RoundingDivideByPOT(output_val_f0.raw(), 24); + output_val_s32 += output_zero_point; + if (output_val_s32 == 256) { + output_val_s32 = 255; + } + // Reinterpret as Q0.7, encoded in uint8_t. + TFLITE_DCHECK_GE(output_val_s32, 0); + TFLITE_DCHECK_LE(output_val_s32, 255); + output_val = static_cast(output_val_s32); + } + output_data[i] = output_val; + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_TANH_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/transpose.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/transpose.h new file mode 100644 index 000000000..96aa4ccaa --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/transpose.h @@ -0,0 +1,111 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_TRANSPOSE_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_TRANSPOSE_H_ + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +template +void TransposeImpl(const TransposeParams& params, + const RuntimeShape& unextended_input_shape, + const T* input_data, + const RuntimeShape& unextended_output_shape, + T* output_data) { + const int unextended_input_size = unextended_input_shape.DimensionsCount(); + const int unextended_output_size = unextended_output_shape.DimensionsCount(); + TFLITE_DCHECK_LE(unextended_input_size, N); + TFLITE_DCHECK_LE(unextended_output_size, N); + TFLITE_DCHECK_EQ(unextended_output_size, params.perm_count); + const int input_ext_size = N - unextended_input_size; + const int output_ext_size = N - unextended_output_size; + NdArrayDesc input_desc; + NdArrayDesc output_desc; + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, unextended_input_shape), + &input_desc); + CopyDimsToDesc(RuntimeShape::ExtendedShape(N, unextended_output_shape), + &output_desc); + + // The perm data is extended to match the output, each index incremented by + // the amount of front padding of the input shape. + int extended_perm[N]; + for (int i = 0; i < N; ++i) { + extended_perm[i] = i < output_ext_size + ? i + : params.perm[i - output_ext_size] + input_ext_size; + } + + // Permutes the input shape so we don't need to permute the indexes inside + // the loop. Check to make sure output_dims is matching input_dims. + NdArrayDesc perm_input_desc; + for (int k = 0; k < N; ++k) { + TFLITE_DCHECK_EQ(input_desc.extents[extended_perm[k]], + output_desc.extents[k]); + perm_input_desc.extents[k] = input_desc.extents[extended_perm[k]]; + perm_input_desc.strides[k] = input_desc.strides[extended_perm[k]]; + } + + // Naive transpose loop (iterate on output index and compute input index). + auto tranpose_func = [&](int indexes[N]) { + output_data[SubscriptToIndex(output_desc, indexes)] = + input_data[SubscriptToIndex(perm_input_desc, indexes)]; + }; + NDOpsHelper(output_desc, tranpose_func); +} + +template +void Transpose(const TransposeParams& params, + const RuntimeShape& unextended_input_shape, const T* input_data, + const RuntimeShape& unextended_output_shape, T* output_data) { + // Transpose kernel only does rearranging values not numeric evaluations on + // each cell. It's safe to implement per size of scalar type and this trick + // keeps the total code size in a reasonable range. + switch (sizeof(T)) { + case 1: + TransposeImpl(params, unextended_input_shape, + reinterpret_cast(input_data), + unextended_output_shape, + reinterpret_cast(output_data)); + break; + case 2: + TransposeImpl(params, unextended_input_shape, + reinterpret_cast(input_data), + unextended_output_shape, + reinterpret_cast(output_data)); + break; + + case 4: + TransposeImpl(params, unextended_input_shape, + reinterpret_cast(input_data), + unextended_output_shape, + reinterpret_cast(output_data)); + break; + case 8: + TransposeImpl(params, unextended_input_shape, + reinterpret_cast(input_data), + unextended_output_shape, + reinterpret_cast(output_data)); + break; + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_TRANSPOSE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/transpose_conv.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/transpose_conv.h new file mode 100644 index 000000000..ac91f379a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/reference/transpose_conv.h @@ -0,0 +1,219 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_TRANSPOSE_CONV_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_TRANSPOSE_CONV_H_ + +#include + +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +namespace reference_ops { + +inline void TransposeConv( + const ConvParams& params, const RuntimeShape& input_shape, + const float* input_data, const RuntimeShape& filter_shape, + const float* filter_data, const RuntimeShape& bias_shape, + const float* bias_data, const RuntimeShape& output_shape, + float* output_data, const RuntimeShape& im2col_shape, float* im2col_data) { + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + (void)im2col_data; // only used in optimized code. + (void)im2col_shape; // only used in optimized code. + + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = MatchingDim(input_shape, 3, filter_shape, 3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + if (bias_data) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + + // Although transpose convolution simplifies to convolution with transposed + // weights for strides of 1, non-unitary striding complicates matters. To + // keep this reference implementation as clear as possible, we use a + // "scatter" access pattern, where we loop through all the input elements, + // computing their influence on the output, rather than looping through the + // output elements in the typical "gather" access pattern of a conv. We + // therefore must initialize the output array to zero. + const int num_elements = output_shape.FlatSize(); + for (int i = 0; i < num_elements; i++) { + output_data[i] = 0.0f; + } + + // Loop through input elements one at a time. + for (int batch = 0; batch < batches; ++batch) { + for (int in_y = 0; in_y < input_height; ++in_y) { + for (int in_x = 0; in_x < input_width; ++in_x) { + for (int in_channel = 0; in_channel < input_depth; ++in_channel) { + // Loop through the output elements it will influence + const int out_x_origin = (in_x * stride_width) - pad_width; + const int out_y_origin = (in_y * stride_height) - pad_height; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + for (int out_channel = 0; out_channel < output_depth; + ++out_channel) { + // Compute output element location + const int out_x = out_x_origin + filter_x; + const int out_y = out_y_origin + filter_y; + // We cannot accumulate out of bounds + if ((out_x >= 0) && (out_x < output_width) && (out_y >= 0) && + (out_y < output_height)) { + float input_value = input_data[Offset( + input_shape, batch, in_y, in_x, in_channel)]; + float filter_value = + filter_data[Offset(filter_shape, out_channel, filter_y, + filter_x, in_channel)]; + output_data[Offset(output_shape, batch, out_y, out_x, + out_channel)] += + input_value * filter_value; + } + } + } + } + } + } + } + } + if (bias_data) { + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int out_channel = 0; out_channel < output_depth; ++out_channel) { + output_data[Offset(output_shape, batch, out_y, out_x, + out_channel)] += bias_data[out_channel]; + } + } + } + } + } +} + +inline void TransposeConv( + const ConvParams& params, const RuntimeShape& input_shape, + const uint8_t* input_data, const RuntimeShape& filter_shape, + const uint8_t* filter_data, const RuntimeShape& bias_shape, + const int32_t* bias_data, const RuntimeShape& output_shape, + uint8_t* output_data, const RuntimeShape& im2col_shape, + uint8_t* im2col_data, int32_t* scratch_buffer) { + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int pad_width = params.padding_values.width; + const int pad_height = params.padding_values.height; + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + (void)im2col_data; // only used in optimized code. + (void)im2col_shape; // only used in optimized code. + + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = MatchingDim(input_shape, 3, filter_shape, 3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int32_t input_offset = params.input_offset; + const int32_t filter_offset = params.weights_offset; + const int32_t output_offset = params.output_offset; + const int32_t output_multiplier = params.output_multiplier; + const int output_shift = params.output_shift; + const int32_t output_activation_min = params.quantized_activation_min; + const int32_t output_activation_max = params.quantized_activation_max; + TFLITE_DCHECK_LE(output_activation_min, output_activation_max); + if (bias_data) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + + const int num_elements = output_shape.FlatSize(); + // We need to initialize scratch_buffer to all 0s, as we apply the same + // 'scatter' based trick as in float version. + memset(scratch_buffer, 0, num_elements * sizeof(int32_t)); + + // Loop through input elements one at a time. + for (int batch = 0; batch < batches; ++batch) { + for (int in_y = 0; in_y < input_height; ++in_y) { + for (int in_x = 0; in_x < input_width; ++in_x) { + for (int in_channel = 0; in_channel < input_depth; ++in_channel) { + // Loop through the output elements it will influence. + const int out_x_origin = (in_x * stride_width) - pad_width; + const int out_y_origin = (in_y * stride_height) - pad_height; + for (int filter_y = 0; filter_y < filter_height; ++filter_y) { + for (int filter_x = 0; filter_x < filter_width; ++filter_x) { + for (int out_channel = 0; out_channel < output_depth; + ++out_channel) { + // Compute output element location. + const int out_x = out_x_origin + filter_x; + const int out_y = out_y_origin + filter_y; + // We cannot accumulate out of bounds. + if ((out_x >= 0) && (out_x < output_width) && (out_y >= 0) && + (out_y < output_height)) { + uint8_t input_value = input_data[Offset( + input_shape, batch, in_y, in_x, in_channel)]; + uint8_t filter_value = + filter_data[Offset(filter_shape, out_channel, filter_y, + filter_x, in_channel)]; + scratch_buffer[Offset(output_shape, batch, out_y, out_x, + out_channel)] += + (input_value + input_offset) * + (filter_value + filter_offset); + } + } + } + } + } + } + } + } + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int out_channel = 0; out_channel < output_depth; ++out_channel) { + int32_t acc = scratch_buffer[Offset(output_shape, batch, out_y, out_x, + out_channel)]; + if (bias_data) { + acc += bias_data[out_channel]; + } + int32_t scaled_acc = MultiplyByQuantizedMultiplier( + acc, output_multiplier, output_shift); + scaled_acc += output_offset; + scaled_acc = std::max(scaled_acc, output_activation_min); + scaled_acc = std::min(scaled_acc, output_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, out_channel)] = + static_cast(scaled_acc); + } + } + } + } +} + +} // namespace reference_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_TRANSPOSE_CONV_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/runtime_shape.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/runtime_shape.h new file mode 100644 index 000000000..c2678b57d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/runtime_shape.h @@ -0,0 +1,158 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_RUNTIME_SHAPE_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_RUNTIME_SHAPE_H_ + +namespace tflite { + +template +struct Dims { + int sizes[N]; + int strides[N]; +}; + +class RuntimeShape { + public: + RuntimeShape& operator=(RuntimeShape const&) = delete; + + // RuntimeShape in TFLM supports up to 5 dimensions. + // The name kMaxSmallSize comes from the same file of the upstream + // tensorflow lite repo and need to be kept the same for max reuse. + static constexpr int kMaxSmallSize = 5; + + RuntimeShape() : size_(0) {} + + explicit RuntimeShape(int dimensions_count) : size_(dimensions_count) {} + + RuntimeShape(int shape_size, int32_t value) : size_(shape_size) { + for (int i = 0; i < shape_size; ++i) { + SetDim(i, value); + } + } + + RuntimeShape(int dimensions_count, const int32_t* dims_data) + : size_(dimensions_count) { + ReplaceWith(dimensions_count, dims_data); + } + + bool operator==(const RuntimeShape& comp) const { + return this->size_ == comp.size_ && + std::memcmp(DimsData(), comp.DimsData(), size_ * sizeof(int32_t)) == + 0; + } + + ~RuntimeShape() {} + + int32_t DimensionsCount() const { return size_; } + int32_t Dims(int i) const { + TFLITE_DCHECK_GE(i, 0); + TFLITE_DCHECK_LT(i, size_); + return dims_[i]; + } + void SetDim(int i, int32_t val) { + TFLITE_DCHECK_GE(i, 0); + TFLITE_DCHECK_LT(i, size_); + dims_[i] = val; + } + + static RuntimeShape ExtendedShape(int new_shape_size, + const RuntimeShape& shape) { + return RuntimeShape(new_shape_size, shape, 1); + } + int32_t* DimsData() { return dims_; } + const int32_t* DimsData() const { return dims_; } + const int32_t* DimsDataUpTo5D() const { return dims_; } + + void ReplaceWith(int dimensions_count, const int32_t* dims_data) { + size_ = dimensions_count; + int32_t* dst_dims = DimsData(); + std::memcpy(dst_dims, dims_data, dimensions_count * sizeof(int32_t)); + } + + // Returns the total count of elements, that is the size when flattened into a + // vector. + int FlatSize() const { + int buffer_size = 1; + const int* dims_data = reinterpret_cast(DimsData()); + for (int i = 0; i < size_; i++) { + buffer_size *= dims_data[i]; + } + return buffer_size; + } + + private: + // For use only by ExtendedShape(), written to guarantee (return-value) copy + // elision in C++17. + // This creates a shape padded to the desired size with the specified value. + RuntimeShape(int new_shape_size, const RuntimeShape& shape, int pad_value) + : size_(new_shape_size) { + // If the following check fails, it is likely because a 4D-only kernel is + // being used with an array of larger dimension count. + TFLITE_CHECK_GE(new_shape_size, shape.DimensionsCount()); + const int size_increase = new_shape_size - shape.DimensionsCount(); + for (int i = 0; i < size_increase; ++i) { + SetDim(i, pad_value); + } + std::memcpy(DimsData() + size_increase, shape.DimsData(), + sizeof(int32_t) * shape.DimensionsCount()); + } + + int32_t size_; + union { + int32_t dims_[kMaxSmallSize]; + }; +}; + +// Since tensors with '0' in their shape are valid in TF, these offset functions +// allow that as long as the corresponding index is also 0. It is upto the +// calling ops to ensure that they perform verification checks on tensor shapes +// if they don't support a particular behavior. + +inline int Offset(const RuntimeShape& shape, int i0, int i1, int i2, int i3) { + TFLITE_DCHECK_EQ(shape.DimensionsCount(), 4); + const int* dims_data = reinterpret_cast(shape.DimsData()); + TFLITE_DCHECK((dims_data[0] == 0 && i0 == 0) || + (i0 >= 0 && i0 < dims_data[0])); + TFLITE_DCHECK((dims_data[1] == 0 && i1 == 0) || + (i1 >= 0 && i1 < dims_data[1])); + TFLITE_DCHECK((dims_data[2] == 0 && i2 == 0) || + (i2 >= 0 && i2 < dims_data[2])); + TFLITE_DCHECK((dims_data[3] == 0 && i3 == 0) || + (i3 >= 0 && i3 < dims_data[3])); + return ((i0 * dims_data[1] + i1) * dims_data[2] + i2) * dims_data[3] + i3; +} + +inline int Offset(const RuntimeShape& shape, int i0, int i1, int i2, int i3, + int i4) { + TFLITE_DCHECK_EQ(shape.DimensionsCount(), 5); + const int* dims_data = reinterpret_cast(shape.DimsData()); + TFLITE_DCHECK((dims_data[0] == 0 && i0 == 0) || + (i0 >= 0 && i0 < dims_data[0])); + TFLITE_DCHECK((dims_data[1] == 0 && i1 == 0) || + (i1 >= 0 && i1 < dims_data[1])); + TFLITE_DCHECK((dims_data[2] == 0 && i2 == 0) || + (i2 >= 0 && i2 < dims_data[2])); + TFLITE_DCHECK((dims_data[3] == 0 && i3 == 0) || + (i3 >= 0 && i3 < dims_data[3])); + TFLITE_DCHECK((dims_data[4] == 0 && i4 == 0) || + (i4 >= 0 && i4 < dims_data[4])); + return (((i0 * dims_data[1] + i1) * dims_data[2] + i2) * dims_data[3] + i3) * + dims_data[4] + + i4; +} + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_RUNTIME_SHAPE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/strided_slice_logic.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/strided_slice_logic.h new file mode 100644 index 000000000..bfe84050d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/strided_slice_logic.h @@ -0,0 +1,211 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_STRIDED_SLICE_LOGIC_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_STRIDED_SLICE_LOGIC_H_ + +#include +#include + +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { +namespace strided_slice { + +// Use until std::clamp() is available from C++17. +inline int Clamp(const int v, const int lo, const int hi) { + TFLITE_DCHECK(!(hi < lo)); + if (hi < v) return hi; + if (v < lo) return lo; + return v; +} + +inline void StridedSlicePadIndices(tflite::StridedSliceParams* p, + int dim_count) { + // Add indices and mask bits to fully include extra dimensions + TFLITE_CHECK_LE(dim_count, 5); + TFLITE_CHECK_GE(dim_count, p->start_indices_count); + TFLITE_CHECK_EQ(p->start_indices_count, p->stop_indices_count); + TFLITE_CHECK_EQ(p->stop_indices_count, p->strides_count); + + const int pad_count = dim_count - p->start_indices_count; + + // Pad indices at start, so move arrays by pad_count. + for (int i = p->start_indices_count - 1; i >= 0; --i) { + p->strides[i + pad_count] = p->strides[i]; + p->start_indices[i + pad_count] = p->start_indices[i]; + p->stop_indices[i + pad_count] = p->stop_indices[i]; + } + for (int i = 0; i < pad_count; ++i) { + p->start_indices[i] = 0; + p->stop_indices[i] = 1; + p->strides[i] = 1; + } + + // Pad masks with 0s or 1s as required. + p->shrink_axis_mask <<= pad_count; + p->ellipsis_mask <<= pad_count; + p->new_axis_mask <<= pad_count; + p->begin_mask <<= pad_count; + p->end_mask <<= pad_count; + p->begin_mask |= (1 << pad_count) - 1; + p->end_mask |= (1 << pad_count) - 1; + + p->start_indices_count = dim_count; + p->stop_indices_count = dim_count; + p->strides_count = dim_count; +} + +// Return the index for the first element along that axis. This index will be a +// positive integer between [0, axis_size] (or [-1, axis_size -1] if stride < 0) +// that can be used to index directly into the data. +inline int StartForAxis(const tflite::StridedSliceParams& params, + const RuntimeShape& input_shape, int axis) { + const auto begin_mask = params.begin_mask; + const auto* start_indices = params.start_indices; + const auto* strides = params.strides; + const int axis_size = input_shape.Dims(axis); + if (axis_size == 0) { + return 0; + } + // Begin with the specified index. + int start = start_indices[axis]; + + // begin_mask override + if (begin_mask & 1 << axis) { + if (strides[axis] > 0) { + // Forward iteration - use the first element. These values will get + // clamped below (Note: We could have set them to 0 and axis_size-1, but + // use lowest() and max() to maintain symmetry with StopForAxis()) + start = std::numeric_limits::lowest(); + } else { + // Backward iteration - use the last element. + start = std::numeric_limits::max(); + } + } + + // Handle negative indices + if (start < 0) { + start += axis_size; + } + + // Clamping + if (strides[axis] > 0) { + // Forward iteration + start = Clamp(start, 0, axis_size); + } else { + // Backward iteration + start = Clamp(start, -1, axis_size - 1); + } + + return start; +} + +// Return the "real" index for the end of iteration along that axis. This is an +// "end" in the traditional C sense, in that it points to one past the last +// element. ie. So if you were iterating through all elements of a 1D array of +// size 4, this function would return 4 as the stop, because it is one past the +// "real" indices of 0, 1, 2 & 3. +inline int StopForAxis(const tflite::StridedSliceParams& params, + const RuntimeShape& input_shape, int axis, + int start_for_axis) { + const auto end_mask = params.end_mask; + const auto shrink_axis_mask = params.shrink_axis_mask; + const auto* stop_indices = params.stop_indices; + const auto* strides = params.strides; + const int axis_size = input_shape.Dims(axis); + if (axis_size == 0) { + return 0; + } + + // Begin with the specified index + const bool shrink_axis = shrink_axis_mask & (1 << axis); + int stop = stop_indices[axis]; + + // When shrinking an axis, the end position does not matter (and can be + // incorrect when negative indexing is used, see Issue #19260). Always use + // start_for_axis + 1 to generate a length 1 slice, since start_for_axis has + // already been adjusted for negative indices. + if (shrink_axis) { + return start_for_axis + 1; + } + + // end_mask override + if (end_mask & (1 << axis)) { + if (strides[axis] > 0) { + // Forward iteration - use the last element. These values will get + // clamped below + stop = std::numeric_limits::max(); + } else { + // Backward iteration - use the first element. + stop = std::numeric_limits::lowest(); + } + } + + // Handle negative indices + if (stop < 0) { + stop += axis_size; + } + + // Clamping + // Because the end index points one past the last element, we need slightly + // different clamping ranges depending on the direction. + if (strides[axis] > 0) { + // Forward iteration + stop = Clamp(stop, 0, axis_size); + } else { + // Backward iteration + stop = Clamp(stop, -1, axis_size - 1); + } + + return stop; +} + +inline bool LoopCondition(int index, int stop, int stride) { + // True when we have reached the end of an axis and should loop. + return stride > 0 ? index >= stop : index <= stop; +} + +inline tflite::StridedSliceParams BuildStridedSliceParams( + int begin_mask, int end_mask, int shrink_axis_mask, + const std::vector& start_indices, const std::vector& stop_indices, + const std::vector& strides) { + tflite::StridedSliceParams op_params; + const int dims_count = start_indices.size(); + + op_params.start_indices_count = dims_count; + op_params.stop_indices_count = dims_count; + op_params.strides_count = dims_count; + for (int i = 0; i < dims_count; ++i) { + op_params.start_indices[i] = start_indices[i]; + op_params.stop_indices[i] = stop_indices[i]; + op_params.strides[i] = strides[i]; + } + + op_params.begin_mask = begin_mask; + op_params.ellipsis_mask = 0; + op_params.end_mask = end_mask; + op_params.new_axis_mask = 0; + op_params.shrink_axis_mask = shrink_axis_mask; + + return op_params; +} + +} // namespace strided_slice + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_STRIDED_SLICE_LOGIC_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/tensor_ctypes.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/tensor_ctypes.h new file mode 100644 index 000000000..f1d3e17fc --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/tensor_ctypes.h @@ -0,0 +1,47 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_TENSOR_CTYPES_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_TENSOR_CTYPES_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +template +inline T* GetTensorData(TfLiteTensor* tensor) { + return tensor != nullptr ? reinterpret_cast(tensor->data.raw) : nullptr; +} + +template +inline const T* GetTensorData(const TfLiteTensor* tensor) { + return tensor != nullptr ? reinterpret_cast(tensor->data.raw) + : nullptr; +} + +inline RuntimeShape GetTensorShape(const TfLiteTensor* tensor) { + if (tensor == nullptr) { + return RuntimeShape(); + } + + TfLiteIntArray* dims = tensor->dims; + const int dims_size = dims->size; + const int32_t* dims_data = reinterpret_cast(dims->data); + return RuntimeShape(dims_size, dims_data); +} + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_TENSOR_CTYPES_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/tensor_utils.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/tensor_utils.cpp new file mode 100644 index 000000000..7e5d98101 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/tensor_utils.cpp @@ -0,0 +1,25 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +============================================================================== +*/ + +// internal/reference/portable_tensor_utils.h has the implementation of the +// functions declared in internal/portable_tensor_utils.h. This somewhat +// confusing setup is derived from how the code is organized in TfLite where it +// is used to select between NEON, SSE and portable implementaitons. See +// https://github.com/tensorflow/tensorflow/blob/d76c23975c4a3a0d7987cfe3f45c76566df06180/tensorflow/lite/kernels/internal/tensor_utils.cc +// for how the code is written in TfLite. + +#include "tensorflow/lite/kernels/internal/portable_tensor_utils.h" +#include "tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h" diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/types.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/types.h new file mode 100644 index 000000000..c44ba48e4 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/internal/types.h @@ -0,0 +1,1065 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_TYPES_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_TYPES_H_ + +#include +#include +#include +#include + +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/runtime_shape.h" + +namespace tflite { + +enum class FusedActivationFunctionType : uint8_t { + kNone, + kRelu6, + kRelu1, + kRelu +}; +enum class PaddingType : uint8_t { kNone, kSame, kValid }; + +struct PaddingValues { + int16_t width; + int16_t height; + // offset is used for calculating "remaining" padding, for example, `width` + // is 1 and `width_offset` is 1, so padding_left is 1 while padding_right is + // 1 + 1 = 2. + int16_t width_offset; + // Same as width_offset except it's over the height dimension. + int16_t height_offset; +}; + +struct Padding3DValues { + int16_t width; + int16_t height; + int16_t depth; + // offset is used for calculating "remaining" padding, for example, `width` + // is 1 and `width_offset` is 1, so padding_left is 1 while padding_right is + // 1 + 1 = 2. + int16_t width_offset; + // Same as width_offset except it's over the height dimension. + int16_t height_offset; + // Same as width_offset except it's over the depth dimension. + int16_t depth_offset; +}; + +// This enumeration allows for non-default formats for the weights array +// of a fully-connected operator, allowing the use of special optimized +// runtime paths. +enum class FullyConnectedWeightsFormat : uint8_t { + // Default format (flat 2D layout, the inner contiguous dimension + // is input_depth, the outer non-contiguous dimension is output_depth) + kDefault, + // Summary: optimized layout for fast CPU runtime implementation, + // aimed specifically at ARM CPUs at the moment, and specialized for + // 8-bit quantized layers. + // + // The use case we're concerned with here is: 8-bit quantization, + // large weights matrix that doesn't fit in cache (e.g. 4096x2048 in + // a key application that drove this), very small batch size (e.g. 1 -- 4). + // + // Even with 8-bit quantization of weights, the performance of memory + // accesses to the weights can become the dominant issue when + // the batch size is small, so each weight value is used in only a few + // arithmetic ops, i.e. the fully-connected node has a low arithmetic + // intensity. The specific issues that arise are of three kinds: + // (1) One may, ideally, max out DRAM bandwidth, i.e. be truly memory + // bound. That's the "good" issue to run into. + // (2) One may run into sub-optimal pre-fetching: the data hasn't been + // prefetched into the cache by the time we need it. + // (3) One may run into cache aliasing: multiple values that are + // pre-fetched, alias each other in the L1 cache (which typically + // has only 4-way set associativity in ARM CPUs) and thus evict + // each other before we get to using them. + // + // The point of this shuffling is to avoid issues (2) and (3) so that + // we get as fast as possible given only the hard constraint (1). + // This is achieved by turning the difficulty into a solution: the + // difficulty, that each value loaded from memory is used only in + // one kernel iteration, making this operation memory-intensive, hints at + // the solution, of shuffling the weights so that they are stored in the + // exact order as the kernel needs to load them, so that the memory + // accesses made by the kernel are trivial. This solves (2) because the + // trivial memory access pattern allows the CPU's automatic prefetching + // to perform very well (no need even for preload instructions), and this + // solves (3) because the values being loaded concurrently are now + // contiguous in the address space, thus don't alias each other in the cache. + // + // On ARM, we typically want our kernel to process a 4x16 block of weights + // at a time, because: + // - 16 is the number of bytes in a NEON register. + // - 4 is how many rows we need to handle concurrently in the kernel in + // order to have sufficient mutual independence of instructions to + // maximize arithmetic throughput. + // + // Finally, the 'Int8' part in the name refers to the fact that this + // weights format has each weights value encoded as a signed int8_t value, + // even if the data type of the weights buffer is uint8_t. This is intended + // to save runtime kernels the effort to have to XOR the top bit of these + // bytes before using them in signed arithmetic, see this file for more + // explanations on the 'signed int8_t trick' in matrix multiplication kernels: + // + // tensorflow/lite/toco/graph_transformations/ensure_uint8_weights_safe_for_fast_int8_kernels.cc + // + kShuffled4x16Int8, +}; + +// Quantization parameters, determining the mapping of quantized values +// to real values (i.e. determining how quantized values are mathematically +// interpreted). +// +// The correspondence is as follows: +// +// real_value = scale * (quantized_value - zero_point); +// +// In other words, zero_point designates which quantized value corresponds to +// the real 0 value, and scale designates the difference between the real values +// corresponding to consecutive quantized values differing by 1. +struct QuantizationParams { + int32_t zero_point = 0; + double scale = 0.0; +}; + +inline bool operator==(const QuantizationParams& qp1, + const QuantizationParams& qp2) { + return qp1.zero_point == qp2.zero_point && qp1.scale == qp2.scale; +} + +// Quantization parameters for each channel, determining the mapping of +// quantized values to real values. See QuantizationParams for a single set of +// parameters per tensor. This has one parameters set per each channel. +// +// The correspondence is as follows: +// +// real_value = scale[channel] * (quantized_value - zero_point[channel]); +// +struct PerChannelQuantizationParams { + // The following members typically point to the corresponding members of a + // TfLiteAffineQuantization struct. + const float* scale; + const int32_t* zero_point; + int32_t quantized_dimension; +}; + +// Gets next index to iterate through a multidimensional array. +inline bool NextIndex(const int num_dims, const int* dims, int* current) { + if (num_dims == 0) { + return false; + } + TFLITE_DCHECK(dims != nullptr); + TFLITE_DCHECK(current != nullptr); + int carry = 1; + for (int idx = num_dims - 1; idx >= 0; --idx) { + int current_val = current[idx] + carry; + TFLITE_DCHECK_GE(dims[idx], current_val); + if (dims[idx] == current_val) { + current[idx] = 0; + } else { + current[idx] = current_val; + carry = 0; + break; + } + } + return (carry == 0); +} + +// Gets offset of index if reducing on axis. When reducing, the flattened offset +// will not change, if the input index changes on the given axis. For example, +// if you have a 3D tensor and you are reducing to 2D by eliminating axis 0, +// then index (0, 1, 2) and index (1, 1, 2) will map to the same flattened +// offset. +// TODO(kanlig): uses Dims to represent dimensions. +inline size_t ReducedOutputOffset(const int num_dims, const int* dims, + const int* index, const int num_axis, + const int* axis) { + if (num_dims == 0) { + return 0; + } + TFLITE_DCHECK(dims != nullptr); + TFLITE_DCHECK(index != nullptr); + size_t offset = 0; + for (int idx = 0; idx < num_dims; ++idx) { + // if we need to skip this axis + bool is_axis = false; + if (axis != nullptr) { + for (int axis_idx = 0; axis_idx < num_axis; ++axis_idx) { + if (idx == axis[axis_idx]) { + is_axis = true; + break; + } + } + } + if (!is_axis) { + offset = offset * static_cast(dims[idx]) + + static_cast(index[idx]); + } + } + return offset; +} + +// Since tensors with '0' in their shape are valid in TF, these offset functions +// allow that as long as the corresponding index is also 0. It is upto the +// calling ops to ensure that they perform verification checks on tensor shapes +// if they don't support a particular behavior. + +inline int Offset(const Dims<4>& dims, int i0, int i1, int i2, int i3) { + TFLITE_DCHECK((i0 == 0 && dims.sizes[0] == 0) || + (i0 >= 0 && i0 < dims.sizes[0])); + TFLITE_DCHECK((i1 == 0 && dims.sizes[1] == 0) || + (i1 >= 0 && i1 < dims.sizes[1])); + TFLITE_DCHECK((i2 == 0 && dims.sizes[2] == 0) || + (i2 >= 0 && i2 < dims.sizes[2])); + TFLITE_DCHECK((i3 == 0 && dims.sizes[3] == 0) || + (i3 >= 0 && i3 < dims.sizes[3])); + return i0 * dims.strides[0] + i1 * dims.strides[1] + i2 * dims.strides[2] + + i3 * dims.strides[3]; +} + +inline int Offset(const Dims<4>& dims, int* index) { + return Offset(dims, index[0], index[1], index[2], index[3]); +} + +// Get array size, DCHECKing that the dim index is in range. +// +// Note that this will be phased out with Dims<4>, since RuntimeShape::Dims() +// already performs this check. +template +int ArraySize(const Dims& array, int index) { + TFLITE_DCHECK(index >= 0 && index < N); + return array.sizes[index]; +} + +// Get common array size, DCHECKing that they all agree. +template +int MatchingArraySize(const ArrayType1& array1, int index1, + const ArrayType2& array2, int index2) { + TFLITE_DCHECK_EQ(ArraySize(array1, index1), ArraySize(array2, index2)); + return ArraySize(array1, index1); +} + +template +int MatchingArraySize(const ArrayType1& array1, int index1, + const ArrayType2& array2, int index2, Args... args) { + TFLITE_DCHECK_EQ(ArraySize(array1, index1), ArraySize(array2, index2)); + return MatchingArraySize(array1, index1, args...); +} + +// Get common shape dim, DCHECKing that they all agree. +inline int MatchingDim(const RuntimeShape& shape1, int index1, + const RuntimeShape& shape2, int index2) { + TFLITE_DCHECK_EQ(shape1.Dims(index1), shape2.Dims(index2)); + return std::min(shape1.Dims(index1), shape2.Dims(index2)); +} + +template +int MatchingDim(const RuntimeShape& shape1, int index1, + const RuntimeShape& shape2, int index2, Args... args) { + TFLITE_DCHECK_EQ(shape1.Dims(index1), shape2.Dims(index2)); + return MatchingDim(shape1, index1, args...); +} + +// Will be phased out with Dims<4>, replaced by RuntimeShape::FlatSize(). +template +inline int FlatSize(const Dims& dims) { + int flat_size = 1; + for (int i = 0; i < N; ++i) { + flat_size *= dims.sizes[i]; + } + return flat_size; +} + +TFLITE_DEPRECATED("Prefer FlatSize.") +inline int RequiredBufferSizeForDims(const Dims<4>& dims) { + return FlatSize(dims); +} + +inline int MatchingElementsSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0) { + const int size_1 = shape.FlatSize(); + const int size_2 = check_shape_0.FlatSize(); + TFLITE_CHECK_EQ(size_1, size_2); + return size_1; +} + +inline int MatchingElementsSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1) { + const int size_1 = shape.FlatSize(); + const int size_2 = check_shape_0.FlatSize(); + const int size_3 = check_shape_1.FlatSize(); + TFLITE_CHECK_EQ(size_1, size_2); + TFLITE_CHECK_EQ(size_2, size_3); + return size_1; +} + +// Flat size calculation, checking that dimensions match with one or more other +// arrays. +inline int MatchingFlatSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0) { + TFLITE_DCHECK_EQ(shape.DimensionsCount(), check_shape_0.DimensionsCount()); + const int dims_count = shape.DimensionsCount(); + for (int i = 0; i < dims_count; ++i) { + TFLITE_DCHECK_EQ(shape.Dims(i), check_shape_0.Dims(i)); + } + return shape.FlatSize(); +} + +inline int MatchingFlatSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1) { + TFLITE_DCHECK_EQ(shape.DimensionsCount(), check_shape_0.DimensionsCount()); + const int dims_count = shape.DimensionsCount(); + for (int i = 0; i < dims_count; ++i) { + TFLITE_DCHECK_EQ(shape.Dims(i), check_shape_0.Dims(i)); + } + return MatchingFlatSize(shape, check_shape_1); +} + +inline int MatchingFlatSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1, + const RuntimeShape& check_shape_2) { + TFLITE_DCHECK_EQ(shape.DimensionsCount(), check_shape_0.DimensionsCount()); + const int dims_count = shape.DimensionsCount(); + for (int i = 0; i < dims_count; ++i) { + TFLITE_DCHECK_EQ(shape.Dims(i), check_shape_0.Dims(i)); + } + return MatchingFlatSize(shape, check_shape_1, check_shape_2); +} + +inline int MatchingFlatSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1, + const RuntimeShape& check_shape_2, + const RuntimeShape& check_shape_3) { + TFLITE_DCHECK_EQ(shape.DimensionsCount(), check_shape_0.DimensionsCount()); + const int dims_count = shape.DimensionsCount(); + for (int i = 0; i < dims_count; ++i) { + TFLITE_DCHECK_EQ(shape.Dims(i), check_shape_0.Dims(i)); + } + return MatchingFlatSize(shape, check_shape_1, check_shape_2, check_shape_3); +} + +// Flat size calculation, checking that dimensions match with one or more other +// arrays. +template +inline int MatchingFlatSize(const Dims& dims, const Dims& check_dims_0) { + for (int i = 0; i < N; ++i) { + TFLITE_DCHECK_EQ(ArraySize(dims, i), ArraySize(check_dims_0, i)); + } + return FlatSize(dims); +} + +template +inline int MatchingFlatSize(const Dims& dims, const Dims& check_dims_0, + const Dims& check_dims_1) { + for (int i = 0; i < N; ++i) { + TFLITE_DCHECK_EQ(ArraySize(dims, i), ArraySize(check_dims_0, i)); + } + return MatchingFlatSize(dims, check_dims_1); +} + +template +inline int MatchingFlatSize(const Dims& dims, const Dims& check_dims_0, + const Dims& check_dims_1, + const Dims& check_dims_2) { + for (int i = 0; i < N; ++i) { + TFLITE_DCHECK_EQ(ArraySize(dims, i), ArraySize(check_dims_0, i)); + } + return MatchingFlatSize(dims, check_dims_1, check_dims_2); +} + +template +inline int MatchingFlatSize(const Dims& dims, const Dims& check_dims_0, + const Dims& check_dims_1, + const Dims& check_dims_2, + const Dims& check_dims_3) { + for (int i = 0; i < N; ++i) { + TFLITE_DCHECK_EQ(ArraySize(dims, i), ArraySize(check_dims_0, i)); + } + return MatchingFlatSize(dims, check_dims_1, check_dims_2, check_dims_3); +} + +// Flat size calculation, checking if their extended shapes match. +inline int MatchingExtendedShapeFlatSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0) { + const int shape_dims = shape.DimensionsCount(); + const int check_shape_0_dims = check_shape_0.DimensionsCount(); + const int min_dims = std::min(shape_dims, check_shape_0_dims); + + for (int i = 0; i < min_dims; ++i) { + TFLITE_DCHECK_EQ(shape.Dims(shape_dims - 1 - i), + check_shape_0.Dims(check_shape_0_dims - 1 - i)); + } + for (int i = min_dims; i < shape_dims; ++i) { + TFLITE_DCHECK_EQ(shape.Dims(shape_dims - 1 - i), 1); + } + for (int i = min_dims; i < check_shape_0_dims; ++i) { + TFLITE_DCHECK_EQ(check_shape_0.Dims(check_shape_0_dims - 1 - i), 1); + } + return shape.FlatSize(); +} + +inline int MatchingExtendedShapeFlatSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1) { + const int flat_size = MatchingExtendedShapeFlatSize(shape, check_shape_0); + TFLITE_DCHECK_EQ(MatchingExtendedShapeFlatSize(shape, check_shape_1), + flat_size); + return flat_size; +} + +inline int MatchingExtendedShapeFlatSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1, + const RuntimeShape& check_shape_2) { + const int flat_size = MatchingExtendedShapeFlatSize(shape, check_shape_0); + TFLITE_DCHECK_EQ( + MatchingExtendedShapeFlatSize(shape, check_shape_1, check_shape_2), + flat_size); + return flat_size; +} + +inline int MatchingExtendedShapeFlatSize(const RuntimeShape& shape, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1, + const RuntimeShape& check_shape_2, + const RuntimeShape& check_shape_3) { + const int flat_size = MatchingExtendedShapeFlatSize(shape, check_shape_0); + TFLITE_DCHECK_EQ(MatchingExtendedShapeFlatSize(shape, check_shape_1, + check_shape_2, check_shape_3), + flat_size); + return flat_size; +} + +// Data is required to be contiguous, and so many operators can use either the +// full array flat size or the flat size with one dimension skipped (commonly +// the depth). +template +inline int FlatSizeSkipDim(const Dims& dims, int skip_dim) { + TFLITE_DCHECK(skip_dim >= 0 && skip_dim < N); + int flat_size = 1; + for (int i = 0; i < N; ++i) { + flat_size *= (i == skip_dim) ? 1 : dims.sizes[i]; + } + return flat_size; +} + +// A combination of MatchingFlatSize() and FlatSizeSkipDim(). +template +inline int MatchingFlatSizeSkipDim(const Dims& dims, int skip_dim, + const Dims& check_dims_0) { + for (int i = 0; i < N; ++i) { + if (i != skip_dim) { + TFLITE_DCHECK_EQ(ArraySize(dims, i), ArraySize(check_dims_0, i)); + } + } + return FlatSizeSkipDim(dims, skip_dim); +} + +template +inline int MatchingFlatSizeSkipDim(const Dims& dims, int skip_dim, + const Dims& check_dims_0, + const Dims& check_dims_1) { + for (int i = 0; i < N; ++i) { + if (i != skip_dim) { + TFLITE_DCHECK_EQ(ArraySize(dims, i), ArraySize(check_dims_0, i)); + } + } + return MatchingFlatSizeSkipDim(dims, skip_dim, check_dims_1); +} + +template +inline int MatchingFlatSizeSkipDim(const Dims& dims, int skip_dim, + const Dims& check_dims_0, + const Dims& check_dims_1, + const Dims& check_dims_2) { + for (int i = 0; i < N; ++i) { + if (i != skip_dim) { + TFLITE_DCHECK_EQ(ArraySize(dims, i), ArraySize(check_dims_0, i)); + } + } + return MatchingFlatSizeSkipDim(dims, skip_dim, check_dims_1, check_dims_2); +} + +template +inline int MatchingFlatSizeSkipDim(const Dims& dims, int skip_dim, + const Dims& check_dims_0, + const Dims& check_dims_1, + const Dims& check_dims_2, + const Dims& check_dims_3) { + for (int i = 0; i < N; ++i) { + if (i != skip_dim) { + TFLITE_DCHECK_EQ(ArraySize(dims, i), ArraySize(check_dims_0, i)); + } + } + return MatchingFlatSizeSkipDim(dims, skip_dim, check_dims_1, check_dims_2, + check_dims_3); +} + +// Data is required to be contiguous, and so many operators can use either the +// full array flat size or the flat size with one dimension skipped (commonly +// the depth). +inline int FlatSizeSkipDim(const RuntimeShape& shape, int skip_dim) { + const int dims_count = shape.DimensionsCount(); + TFLITE_DCHECK(skip_dim >= 0 && skip_dim < dims_count); + const auto* dims_data = shape.DimsData(); + int flat_size = 1; + for (int i = 0; i < dims_count; ++i) { + flat_size *= (i == skip_dim) ? 1 : dims_data[i]; + } + return flat_size; +} + +// A combination of MatchingFlatSize() and FlatSizeSkipDim(). +inline int MatchingFlatSizeSkipDim(const RuntimeShape& shape, int skip_dim, + const RuntimeShape& check_shape_0) { + const int dims_count = shape.DimensionsCount(); + for (int i = 0; i < dims_count; ++i) { + if (i != skip_dim) { + TFLITE_DCHECK_EQ(shape.Dims(i), check_shape_0.Dims(i)); + } + } + return FlatSizeSkipDim(shape, skip_dim); +} + +inline int MatchingFlatSizeSkipDim(const RuntimeShape& shape, int skip_dim, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1) { + const int dims_count = shape.DimensionsCount(); + for (int i = 0; i < dims_count; ++i) { + if (i != skip_dim) { + TFLITE_DCHECK_EQ(shape.Dims(i), check_shape_0.Dims(i)); + } + } + return MatchingFlatSizeSkipDim(shape, skip_dim, check_shape_1); +} + +inline int MatchingFlatSizeSkipDim(const RuntimeShape& shape, int skip_dim, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1, + const RuntimeShape& check_shape_2) { + const int dims_count = shape.DimensionsCount(); + for (int i = 0; i < dims_count; ++i) { + if (i != skip_dim) { + TFLITE_DCHECK_EQ(shape.Dims(i), check_shape_0.Dims(i)); + } + } + return MatchingFlatSizeSkipDim(shape, skip_dim, check_shape_1, check_shape_2); +} + +inline int MatchingFlatSizeSkipDim(const RuntimeShape& shape, int skip_dim, + const RuntimeShape& check_shape_0, + const RuntimeShape& check_shape_1, + const RuntimeShape& check_shape_2, + const RuntimeShape& check_shape_3) { + const int dims_count = shape.DimensionsCount(); + for (int i = 0; i < dims_count; ++i) { + if (i != skip_dim) { + TFLITE_DCHECK_EQ(shape.Dims(i), check_shape_0.Dims(i)); + } + } + return MatchingFlatSizeSkipDim(shape, skip_dim, check_shape_1, check_shape_2, + check_shape_3); +} + +template +bool IsPackedWithoutStrides(const Dims& dims) { + int expected_stride = 1; + for (int d = 0; d < N; d++) { + if (dims.strides[d] != expected_stride) return false; + expected_stride *= dims.sizes[d]; + } + return true; +} + +template +void ComputeStrides(Dims* dims) { + dims->strides[0] = 1; + for (int d = 1; d < N; d++) { + dims->strides[d] = dims->strides[d - 1] * dims->sizes[d - 1]; + } +} + +enum class BroadcastableOpCategory : uint8_t { + kNone, + kNonBroadcast, // Matching input shapes. + kFirstInputBroadcastsFast, // Fivefold nested loops. + kSecondInputBroadcastsFast, // Fivefold nested loops. + kGenericBroadcast, // Fall-back. +}; + +struct MinMax { + float min; + float max; +}; +static_assert(sizeof(MinMax) == 8, ""); + +struct ActivationParams { + FusedActivationFunctionType activation_type; + // uint8_t, etc, activation params. + int32_t quantized_activation_min; + int32_t quantized_activation_max; +}; + +struct ReluParams : public ActivationParams { + int32_t input_offset; + int32_t output_offset; + int32_t output_multiplier; + int output_shift; +}; + +// Styles of resizing op usages. For example, kImageStyle can be used with a Pad +// op for pattern-specific optimization. +enum class ResizingCategory : uint8_t { + kNone, + kImageStyle, // 4D, operating on inner dimensions, say {0, a, b, 0}. + kGenericResize, +}; + +// For Add, Sub, Mul ops. +struct ArithmeticParams { + // Shape dependent / common to data / op types. + BroadcastableOpCategory broadcast_category; + // uint8_t inference params. + int32_t input1_offset; + int32_t input2_offset; + int32_t output_offset; + int32_t output_multiplier; + int output_shift; + // Add / Sub, not Mul, uint8_t inference params. + int left_shift; + int32_t input1_multiplier; + int input1_shift; + int32_t input2_multiplier; + int input2_shift; + + // TODO(b/158622529): Union the following activation params. + // uint8_t, etc, activation params. + int32_t quantized_activation_min; + int32_t quantized_activation_max; + // float activation params. + float float_activation_min; + float float_activation_max; + // int64_t activation params. + int64_t int64_activation_min; + int64_t int64_activation_max; + + // Processed output dimensions. + // Let input "a" be the one that broadcasts in the faster-changing dimension. + // Then, after coalescing, for shapes {a0, a1, a2, a3, a4} and + // {b0, b1, b2, b3, b4}, + // broadcast_shape[4] = b0 = a0. + // broadcast_shape[3] = b1; a1 = 1. + // broadcast_shape[2] = b2 = a2. + // broadcast_shape[1] = a3; b3 = 1. + // broadcast_shape[0] = b4 = a4. + int broadcast_shape[5]; +}; + +struct ConcatenationParams { + int8_t axis; + const int32_t* input_zeropoint; + const float* input_scale; + uint16_t inputs_count; + int32_t output_zeropoint; + float output_scale; +}; + +struct ComparisonParams { + // uint8_t inference params. + int left_shift; + int32_t input1_offset; + int32_t input1_multiplier; + int input1_shift; + int32_t input2_offset; + int32_t input2_multiplier; + int input2_shift; + // Shape dependent / common to inference types. + bool is_broadcast; +}; + +struct ConvParams { + PaddingType padding_type; + PaddingValues padding_values; + // TODO(starka): This was just "stride", so check that width+height is OK. + int16_t stride_width; + int16_t stride_height; + int16_t dilation_width_factor; + int16_t dilation_height_factor; + // uint8_t inference params. + // TODO(b/65838351): Use smaller types if appropriate. + int32_t input_offset; + int32_t weights_offset; + int32_t output_offset; + int32_t output_multiplier; + int output_shift; + // uint8_t, etc, activation params. + int32_t quantized_activation_min; + int32_t quantized_activation_max; + // float activation params. + float float_activation_min; + float float_activation_max; +}; + +struct Conv3DParams { + Padding3DValues padding_values; + int stride_width; + int stride_height; + int stride_depth; + int dilation_width; + int dilation_height; + int dilation_depth; + // float activation params. + float float_activation_min; + float float_activation_max; +}; + +typedef Conv3DParams Conv3DTransposeParams; + +struct DepthToSpaceParams { + int32_t block_size; +}; + +struct DepthwiseParams { + PaddingType padding_type; + PaddingValues padding_values; + int16_t stride_width; + int16_t stride_height; + int16_t dilation_width_factor; + int16_t dilation_height_factor; + int16_t depth_multiplier; + // uint8_t inference params. + // TODO(b/65838351): Use smaller types if appropriate. + int32_t input_offset; + int32_t weights_offset; + int32_t output_offset; + int32_t output_multiplier; + int output_shift; + // uint8_t, etc, activation params. + int32_t quantized_activation_min; + int32_t quantized_activation_max; + // float activation params. + float float_activation_min; + float float_activation_max; + const int32_t* output_multiplier_per_channel; + const int32_t* output_shift_per_channel; +}; + +struct DequantizationParams { + double scale; + int32_t zero_point; +}; + +struct PerChannelDequantizationParams { + const float* scale; + const int32_t* zero_point; + int32_t quantized_dimension; +}; + +struct FakeQuantParams { + MinMax minmax; + int32_t num_bits; +}; + +struct FullyConnectedParams { + // uint8_t inference params. + // TODO(b/65838351): Use smaller types if appropriate. + int32_t input_offset; + int32_t weights_offset; + int32_t output_offset; + int32_t output_multiplier; + int output_shift; + // uint8_t, etc, activation params. + int32_t quantized_activation_min; + int32_t quantized_activation_max; + // float activation params. + float float_activation_min; + float float_activation_max; + // Mark the operands as cacheable if they are unchanging, e.g. weights. + bool lhs_cacheable; + bool rhs_cacheable; + FullyConnectedWeightsFormat weights_format; +}; + +struct GatherParams { + int16_t axis; + int16_t batch_dims; +}; + +struct L2NormalizationParams { + // uint8_t inference params. + int32_t input_zero_point; +}; + +struct LocalResponseNormalizationParams { + int32_t range; + double bias; + double alpha; + double beta; +}; + +struct HardSwishParams { + // zero_point of the input activations. + int16_t input_zero_point; + // zero_point of the output activations. + int16_t output_zero_point; + // 16bit fixed-point component of the multiplier to apply to go from the + // "high-res input scale", which is the input scale multiplied by 2^7, to the + // "relu-ish scale", which 3.0/32768. + // See the implementation of HardSwishPrepare. + int16_t reluish_multiplier_fixedpoint_int16; + // exponent/bit-shift component of the aforementioned multiplier. + int reluish_multiplier_exponent; + // 16bit fixed-point component of the multiplier to apply to go from the + // "high-res input scale", which is the input scale multiplied by 2^7, to the + // output scale. + // See the implementation of HardSwishPrepare. + int16_t output_multiplier_fixedpoint_int16; + // exponent/bit-shift component of the aforementioned multiplier. + int output_multiplier_exponent; +}; + +struct LogisticParams { + // uint8_t inference params. + int32_t input_zero_point; + int32_t input_range_radius; + int32_t input_multiplier; + int input_left_shift; +}; + +struct LstmCellParams { + int32_t weights_zero_point; + int32_t accum_multiplier; + int accum_shift; + int state_integer_bits; +}; + +struct MeanParams { + int8_t axis_count; + int16_t axis[4]; +}; + +struct PackParams { + int8_t axis; + const int32_t* input_zeropoint; + const float* input_scale; + uint16_t inputs_count; + int32_t output_zeropoint; + float output_scale; +}; + +struct PadParams { + int8_t left_padding_count; + int32_t left_padding[5]; + int8_t right_padding_count; + int32_t right_padding[5]; + ResizingCategory resizing_category; +}; + +struct PreluParams { + int32_t input_offset; + int32_t alpha_offset; + int32_t output_offset; + int32_t output_multiplier_1; + int output_shift_1; + int32_t output_multiplier_2; + int output_shift_2; +}; + +struct PoolParams { + FusedActivationFunctionType activation; + PaddingType padding_type; + PaddingValues padding_values; + int stride_height; + int stride_width; + int filter_height; + int filter_width; + // uint8_t, etc, activation params. + int32_t quantized_activation_min; + int32_t quantized_activation_max; + // float activation params. + float float_activation_min; + float float_activation_max; +}; + +struct ReshapeParams { + int8_t shape_count; + int32_t shape[4]; +}; + +struct ResizeBilinearParams { + bool align_corners; + // half_pixel_centers assumes pixels are of half the actual dimensions, and + // yields more accurate resizes. Corresponds to the same argument for the + // original TensorFlow op in TF2.0. + bool half_pixel_centers; +}; + +struct ResizeNearestNeighborParams { + bool align_corners; + bool half_pixel_centers; +}; + +struct SliceParams { + int8_t begin_count; + int32_t begin[5]; + int8_t size_count; + int32_t size[5]; +}; + +struct SoftmaxParams { + // beta is not really used (not a Tensorflow parameter) and not implemented + // for LogSoftmax. + double beta; + // uint8_t inference params. Used even when beta defaults to 1.0. + int32_t input_multiplier; + int32_t input_left_shift; + // Reverse scaling is only used by LogSoftmax. + int32_t reverse_scaling_divisor; + int32_t reverse_scaling_right_shift; + int diff_min; + int32_t zero_point; + float scale; + float* table; + // int16 LUT for exp(x), where x uniform distributed between [-10.0 , 0.0] + int16_t* exp_lut; + // int16 LUT for 1 / (1 + x), where x uniform distributed between [0.0 , 1.0] + int16_t* one_over_one_plus_x_lut; + uint8_t* uint8_table1; + uint8_t* uint8_table2; +}; + +struct SpaceToBatchParams { + // "Zero" padding for uint8_t means padding with the output offset. + int32_t output_offset; +}; + +struct SpaceToDepthParams { + int32_t block_size; +}; + +struct SplitParams { + // Graphs that split into, say, 2000 nodes are encountered. The indices in + // OperatorEdges are of type uint16_t. + uint16_t num_split; + int16_t axis; +}; + +struct SqueezeParams { + int8_t squeeze_dims_count; + int32_t squeeze_dims[4]; +}; + +struct StridedSliceParams { + int8_t start_indices_count; + int32_t start_indices[5]; + int8_t stop_indices_count; + int32_t stop_indices[5]; + int8_t strides_count; + int32_t strides[5]; + + uint16_t begin_mask; + uint16_t ellipsis_mask; + uint16_t end_mask; + uint16_t new_axis_mask; + uint16_t shrink_axis_mask; +}; + +struct TanhParams { + int32_t input_zero_point; + int32_t input_range_radius; + int32_t input_multiplier; + int input_left_shift; +}; + +struct TransposeParams { + int8_t perm_count; + int32_t perm[5]; +}; + +struct UnpackParams { + uint16_t num_split; + int16_t axis; +}; + +struct LeakyReluParams { + float alpha; + int32_t input_offset; + int32_t output_offset; + int32_t output_multiplier_alpha; + int32_t output_shift_alpha; + int32_t output_multiplier_identity; + int32_t output_shift_identity; +}; + +template +inline void SetActivationParams(float min, float max, P* params) { + params->float_activation_min = min; + params->float_activation_max = max; +} + +template +inline void SetActivationParams(int32_t min, int32_t max, P* params) { + params->quantized_activation_min = min; + params->quantized_activation_max = max; +} + +template +inline void SetActivationParams(int64_t min, int64_t max, P* params) { + params->int64_activation_min = min; + params->int64_activation_max = max; +} + +template +inline void GetActivationParams(const P& params, int32_t* min, int32_t* max) { + *min = params.quantized_activation_min; + *max = params.quantized_activation_max; +} + +template +inline void GetActivationParams(const P& params, float* min, float* max) { + *min = params.float_activation_min; + *max = params.float_activation_max; +} + +template +inline void GetActivationParams(const P& params, int64_t* min, int64_t* max) { + *min = params.int64_activation_min; + *max = params.int64_activation_max; +} + +// Type trait to check of given type has size smaller than 4 bytes. +template +struct is_small_integer + : public std::integral_constant::value || + std::is_same::value || + std::is_same::value || + std::is_same::value> {}; + +// Type trait to check of given type is int32 or int64. +template +struct is_int32_or_int64 + : public std::integral_constant::value || + std::is_same::value> { +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_TYPES_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/kernel_util.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/kernel_util.cpp new file mode 100644 index 000000000..e8b2dfd61 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/kernel_util.cpp @@ -0,0 +1,594 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/kernel_util.h" + +#include +#include + +#include +#include +#include +#include +#ifndef ARDUINO +#include +#endif // ARDUINO + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/context_util.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" + +#if defined(__APPLE__) +#include "TargetConditionals.h" +#endif + +namespace tflite { + +namespace { + +// Assumes tensor_index is a valid index (in bounds) +inline TfLiteTensor* GetTensorAtIndex(const TfLiteContext* context, + int tensor_index) { + if (context->tensors != nullptr) { + return &context->tensors[tensor_index]; + } else { + return context->GetTensor(context, tensor_index); + } +} + +// Validate in a single place to reduce binary size +inline TfLiteStatus ValidateTensorIndexingSafe(const TfLiteContext* context, + int index, int max_size, + const int* tensor_indices, + int* tensor_index) { + if (index < 0 || index >= max_size) { + TF_LITE_KERNEL_LOG(const_cast(context), + "Invalid tensor index %d (not in [0, %d))\n", index, + max_size); + return kTfLiteError; + } + if (tensor_indices[index] == kTfLiteOptionalTensor) { + TF_LITE_KERNEL_LOG(const_cast(context), + "Tensor at index %d was optional but was expected\n", + index); + return kTfLiteError; + } + + *tensor_index = tensor_indices[index]; + return kTfLiteOk; +} + +// Same as above but returns -1 for invalid inputs instead of status + logging +// error. +inline int ValidateTensorIndexing(const TfLiteContext* context, int index, + int max_size, const int* tensor_indices) { + if (index >= 0 && index < max_size) { + const int tensor_index = tensor_indices[index]; + if (tensor_index != kTfLiteOptionalTensor) { + return tensor_index; + } + } + return -1; +} + +inline TfLiteTensor* GetMutableInput(const TfLiteContext* context, + const TfLiteNode* node, int index) { + const int tensor_index = ValidateTensorIndexing( + context, index, node->inputs->size, node->inputs->data); + if (tensor_index < 0) { + return nullptr; + } + return GetTensorAtIndex(context, tensor_index); +} + +inline TfLiteStatus GetMutableInputSafe(const TfLiteContext* context, + const TfLiteNode* node, int index, + const TfLiteTensor** tensor) { + int tensor_index; + TF_LITE_ENSURE_OK( + context, ValidateTensorIndexingSafe(context, index, node->inputs->size, + node->inputs->data, &tensor_index)); + *tensor = GetTensorAtIndex(context, tensor_index); + return kTfLiteOk; +} + +} // anonymous namespace. + +const TfLiteTensor* GetInput(const TfLiteContext* context, + const TfLiteNode* node, int index) { + return GetMutableInput(context, node, index); +} + +TfLiteStatus GetInputSafe(const TfLiteContext* context, const TfLiteNode* node, + int index, const TfLiteTensor** tensor) { + return GetMutableInputSafe(context, node, index, tensor); +} + +TfLiteTensor* GetVariableInput(TfLiteContext* context, const TfLiteNode* node, + int index) { + TfLiteTensor* tensor = GetMutableInput(context, node, index); + if (tensor == nullptr) return nullptr; + return tensor->is_variable ? tensor : nullptr; +} + +TfLiteTensor* GetOutput(TfLiteContext* context, const TfLiteNode* node, + int index) { + const int tensor_index = ValidateTensorIndexing( + context, index, node->outputs->size, node->outputs->data); + if (tensor_index < 0) { + return nullptr; + } + return GetTensorAtIndex(context, tensor_index); +} + +TfLiteStatus GetOutputSafe(const TfLiteContext* context, const TfLiteNode* node, + int index, TfLiteTensor** tensor) { + int tensor_index; + TF_LITE_ENSURE_OK( + context, ValidateTensorIndexingSafe(context, index, node->outputs->size, + node->outputs->data, &tensor_index)); + *tensor = GetTensorAtIndex(context, tensor_index); + return kTfLiteOk; +} + +const TfLiteTensor* GetOptionalInputTensor(const TfLiteContext* context, + const TfLiteNode* node, int index) { + return GetInput(context, node, index); +} + +#ifndef ARDUINO +TfLiteTensor* GetTemporary(TfLiteContext* context, const TfLiteNode* node, + int index) { + const int tensor_index = ValidateTensorIndexing( + context, index, node->temporaries->size, node->temporaries->data); + if (tensor_index < 0) { + return nullptr; + } + return GetTensorAtIndex(context, tensor_index); +} + +TfLiteStatus GetTemporarySafe(const TfLiteContext* context, + const TfLiteNode* node, int index, + TfLiteTensor** tensor) { + int tensor_index; + TF_LITE_ENSURE_OK(context, ValidateTensorIndexingSafe( + context, index, node->temporaries->size, + node->temporaries->data, &tensor_index)); + *tensor = GetTensorAtIndex(context, tensor_index); + return kTfLiteOk; +} + +const TfLiteTensor* GetIntermediates(TfLiteContext* context, + const TfLiteNode* node, int index) { + const int tensor_index = ValidateTensorIndexing( + context, index, node->intermediates->size, node->intermediates->data); + if (tensor_index < 0) { + return nullptr; + } + return GetTensorAtIndex(context, tensor_index); +} + +TfLiteStatus GetIntermediatesSafe(const TfLiteContext* context, + const TfLiteNode* node, int index, + TfLiteTensor** tensor) { + int tensor_index; + TF_LITE_ENSURE_OK(context, ValidateTensorIndexingSafe( + context, index, node->intermediates->size, + node->intermediates->data, &tensor_index)); + *tensor = GetTensorAtIndex(context, tensor_index); + return kTfLiteOk; +} +#endif // ARDUINO + +// Per-axis +TfLiteStatus PopulateConvolutionQuantizationParams( + TfLiteContext* context, const TfLiteTensor* input, + const TfLiteTensor* filter, const TfLiteTensor* bias, TfLiteTensor* output, + const TfLiteFusedActivation& activation, int32_t* multiplier, int* shift, + int32_t* output_activation_min, int32_t* output_activation_max, + int32_t* per_channel_multiplier, int32_t* per_channel_shift) { + const auto* affine_quantization = + reinterpret_cast(filter->quantization.params); + return PopulateConvolutionQuantizationParams( + context, input, filter, bias, output, activation, multiplier, shift, + output_activation_min, output_activation_max, per_channel_multiplier, + per_channel_shift, affine_quantization->scale->size); +} + +// Per-axis & per-tensor +TfLiteStatus PopulateConvolutionQuantizationParams( + TfLiteContext* context, const TfLiteTensor* input, + const TfLiteTensor* filter, const TfLiteTensor* bias, TfLiteTensor* output, + const TfLiteFusedActivation& activation, int32_t* multiplier, int* shift, + int32_t* output_activation_min, int32_t* output_activation_max, + int32_t* per_channel_multiplier, int32_t* per_channel_shift, + int num_channels) { + TF_LITE_ENSURE_EQ(context, input->quantization.type, + kTfLiteAffineQuantization); + TF_LITE_ENSURE_EQ(context, filter->quantization.type, + kTfLiteAffineQuantization); + // TODO(jianlijianli): Enable bias type check and bias scale == input scale + // * filter scale for each channel in affine quantization once bias + // quantization is properly populated. + // TF_LITE_ENSURE_EQ(context, bias->quantization.type, + // kTfLiteAffineQuantization); + + // Check data type. + const auto* affine_quantization = + reinterpret_cast(filter->quantization.params); + TF_LITE_ENSURE(context, affine_quantization); + TF_LITE_ENSURE(context, affine_quantization->scale); + const bool is_per_channel = affine_quantization->scale->size > 1; + if (is_per_channel) { + // Currently only Int8/Int16 is supported for per channel quantization. + TF_LITE_ENSURE(context, + input->type == kTfLiteInt8 || input->type == kTfLiteInt16); + TF_LITE_ENSURE(context, + filter->type == kTfLiteInt8 || filter->type == kTfLiteInt4); + TF_LITE_ENSURE_EQ(context, affine_quantization->scale->size, num_channels); + TF_LITE_ENSURE_EQ( + context, num_channels, + filter->dims->data[affine_quantization->quantized_dimension]); + } + + // Populate multiplier and shift using affine quantization. + const float input_scale = input->params.scale; + const float output_scale = output->params.scale; + const float* filter_scales = affine_quantization->scale->data; + for (int i = 0; i < num_channels; ++i) { + // If per-tensor quantization parameter is specified, broadcast it along the + // quantization dimension (channels_out). + const float scale = is_per_channel ? filter_scales[i] : filter_scales[0]; + const double filter_scale = static_cast(scale); + const double effective_output_scale = static_cast(input_scale) * + filter_scale / + static_cast(output_scale); + int32_t significand; + int channel_shift; + QuantizeMultiplier(effective_output_scale, &significand, &channel_shift); + per_channel_multiplier[i] = significand; + per_channel_shift[i] = channel_shift; + } + + // Populate scalar quantization parameters. + // This check on legacy quantization parameters is kept only for backward + // compatibility. + if (input->type == kTfLiteUInt8) { + // Check bias scale == input scale * filter scale. + double real_multiplier = 0.0; + TF_LITE_ENSURE_STATUS(GetQuantizedConvolutionMultipler( + context, input, filter, bias, output, &real_multiplier)); + int exponent; + + // Populate quantization parameters with multiplier and shift. + QuantizeMultiplier(real_multiplier, multiplier, &exponent); + *shift = -exponent; + } + if (input->type == kTfLiteInt8 || input->type == kTfLiteUInt8 || + input->type == kTfLiteInt16) { + TF_LITE_ENSURE_STATUS(CalculateActivationRangeQuantized( + context, activation, output, output_activation_min, + output_activation_max)); + } + return kTfLiteOk; +} + +TfLiteStatus GetQuantizedConvolutionMultipler(TfLiteContext* context, + const TfLiteTensor* input, + const TfLiteTensor* filter, + const TfLiteTensor* bias, + TfLiteTensor* output, + double* multiplier) { + const double input_product_scale = static_cast(input->params.scale) * + static_cast(filter->params.scale); + // The following conditions must be guaranteed by the training pipeline. + if (bias) { + const double bias_scale = static_cast(bias->params.scale); + // Here we're making sure the input_product_scale & bias_scale are about the + // same. Since we have: + // (output - output_zp) * output_scale = + // input_product_scale * input_product + bias * bias_scale ---- (0) + // + // (0) equals: + // (input_product + bias) * input_product_scale ----- (1) + // + + // bias * (bias_scale - input_product_scale) ------ (2) + // + // For the real kernel computation, we're doing (1), so we really need to + // make sure (2) has minimum impact on the output, so: + // bias * (bias_scale - input_product_scale) / output_scale should be + // a small number for an integer. + // Since normally bias should be within a small range. + // We should expect (bias_scale - input_product_scale) / output_scale to + // be a small number like 0.02. + const double scale_diff = std::abs(input_product_scale - bias_scale); + const double output_scale = static_cast(output->params.scale); + + TF_LITE_ENSURE(context, scale_diff / output_scale <= 0.02); + } + return GetQuantizedConvolutionMultipler(context, input, filter, output, + multiplier); +} + +TfLiteStatus GetQuantizedConvolutionMultipler(TfLiteContext* context, + const TfLiteTensor* input, + const TfLiteTensor* filter, + TfLiteTensor* output, + double* multiplier) { + const double input_product_scale = + static_cast(input->params.scale * filter->params.scale); + TF_LITE_ENSURE(context, input_product_scale >= 0); + *multiplier = input_product_scale / static_cast(output->params.scale); + + return kTfLiteOk; +} + +namespace { + +inline TfLiteStatus Quantize(TfLiteContext* context, float scale, + int32_t zero_point, float f, int32_t& q) { + const float tmp = TfLiteRound(f / scale); + const bool no_integer_overflow_from_quantization = + (tmp >= static_cast(std::numeric_limits::min()) && + tmp <= static_cast(std::numeric_limits::max())); + TF_LITE_ENSURE(context, no_integer_overflow_from_quantization); + q = zero_point + static_cast(tmp); + return kTfLiteOk; +} + +TfLiteStatus CalculateActivationRangeQuantizedImpl( + TfLiteContext* context, TfLiteFusedActivation activation, int32_t qmin, + int32_t qmax, TfLiteTensor* output, int32_t* act_min, int32_t* act_max) { + const auto scale = output->params.scale; + const auto zero_point = output->params.zero_point; + + int32_t tmp_q; + if (activation == kTfLiteActRelu) { + TF_LITE_ENSURE_OK(context, + Quantize(context, scale, zero_point, 0.0, tmp_q)); + *act_min = std::max(qmin, tmp_q); + *act_max = qmax; + } else if (activation == kTfLiteActRelu6) { + TF_LITE_ENSURE_OK(context, + Quantize(context, scale, zero_point, 0.0, tmp_q)); + *act_min = std::max(qmin, tmp_q); + TF_LITE_ENSURE_OK(context, + Quantize(context, scale, zero_point, 6.0, tmp_q)); + *act_max = std::min(qmax, tmp_q); + } else if (activation == kTfLiteActReluN1To1) { + TF_LITE_ENSURE_OK(context, + Quantize(context, scale, zero_point, -1.0, tmp_q)); + *act_min = std::max(qmin, tmp_q); + TF_LITE_ENSURE_OK(context, + Quantize(context, scale, zero_point, 1.0, tmp_q)); + *act_max = std::min(qmax, tmp_q); + } else { + *act_min = qmin; + *act_max = qmax; + } + return kTfLiteOk; +} +} // namespace + +TfLiteStatus CalculateActivationRangeQuantized(TfLiteContext* context, + TfLiteFusedActivation activation, + TfLiteTensor* output, + int32_t* act_min, + int32_t* act_max) { + int32_t qmin = 0; + int32_t qmax = 0; + if (output->type == kTfLiteUInt8) { + qmin = std::numeric_limits::min(); + qmax = std::numeric_limits::max(); + } else if (output->type == kTfLiteInt8) { + qmin = std::numeric_limits::min(); + qmax = std::numeric_limits::max(); + } else if (output->type == kTfLiteInt16) { + qmin = std::numeric_limits::min(); + qmax = std::numeric_limits::max(); + } else { + TF_LITE_ENSURE(context, false); + } + + return CalculateActivationRangeQuantizedImpl(context, activation, qmin, qmax, + output, act_min, act_max); +} + +bool HaveSameShapes(const TfLiteTensor* input1, const TfLiteTensor* input2) { + return TfLiteIntArrayEqual(input1->dims, input2->dims); +} + +#ifndef ARDUINO +TfLiteStatus GetOutputShapeFromInput(TfLiteContext* context, + const TfLiteTensor* input, + TfLiteIntArray** output_shape) { + if (NumDimensions(input) != 1) { + TF_LITE_KERNEL_LOG(const_cast(context), + "Invalid %dD input tensor (must be a 1D tensor).", + NumDimensions(input)); + return kTfLiteError; + } + const int output_dims = SizeOfDimension(input, 0); + std::unique_ptr shape( + TfLiteIntArrayCreate(output_dims), TfLiteIntArrayFree); + for (int i = 0; i < output_dims; i++) { + shape->data[i] = input->data.i32[i]; + } + *output_shape = shape.release(); + return kTfLiteOk; +} + +// TODO(b/172067338): Having this function be part of TF_LITE_STATIC_MEMORY +// build results in a 6KB size increase, even though the function is unsused for +// that build. What appears to be happening is that while the linker drops the +// unsused function, the string library that gets pulled in is not dropped, +// resulting in the increased binary size. +const std::string GetShapeDebugString(const TfLiteIntArray* shape) { + std::string str; + for (int d = 0; d < shape->size; ++d) { + if (str.empty()) + str = "[" + std::to_string(shape->data[d]); + else + // Don't add space after "," to make the output consistent with + // tensorflow::shape_inference::InferenceContext::DebugString() + str += "," + std::to_string(shape->data[d]); + } + if (str.empty()) { + str = "[]"; + } else { + str += "]"; + } + return str; +} + +TfLiteStatus CalculateShapeForBroadcast(TfLiteContext* context, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + TfLiteIntArray** output_shape) { + const int dims1 = NumDimensions(input1); + const int dims2 = NumDimensions(input2); + const int out_dims = std::max(dims1, dims2); + + std::unique_ptr shape( + TfLiteIntArrayCreate(out_dims), TfLiteIntArrayFree); + for (int i = 0; i < out_dims; ++i) { + const int d1 = i >= dims1 ? 1 : SizeOfDimension(input1, dims1 - i - 1); + const int d2 = i >= dims2 ? 1 : SizeOfDimension(input2, dims2 - i - 1); + if (!(d1 == d2 || d1 == 1 || d2 == 1)) { + TF_LITE_KERNEL_LOG(context, + "Given shapes, %s and %s, are not broadcastable.", + GetShapeDebugString(input1->dims).c_str(), + GetShapeDebugString(input2->dims).c_str()); + return kTfLiteError; + } + + if (d1 == 0 || d2 == 0) { + shape->data[out_dims - i - 1] = 0; + } else { + shape->data[out_dims - i - 1] = std::max(d1, d2); + } + } + *output_shape = shape.release(); + return kTfLiteOk; +} + +TfLiteStatus CalculateShapeForBroadcast(TfLiteContext* context, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + const TfLiteTensor* input3, + TfLiteIntArray** output_shape) { + const int dims1 = NumDimensions(input1); + const int dims2 = NumDimensions(input2); + const int dims3 = NumDimensions(input3); + const int out_dims = std::max(std::max(dims1, dims2), dims3); + std::unique_ptr shape( + TfLiteIntArrayCreate(out_dims), TfLiteIntArrayFree); + for (int i = 0; i < out_dims; ++i) { + const int d1 = i >= dims1 ? 1 : SizeOfDimension(input1, dims1 - i - 1); + const int d2 = i >= dims2 ? 1 : SizeOfDimension(input2, dims2 - i - 1); + const int d3 = i >= dims3 ? 1 : SizeOfDimension(input3, dims3 - i - 1); + const int min_value = std::min(std::min(d1, d2), d3); + int max_value = std::max(std::max(d1, d2), d3); + // If one dimention is 0, others must be 0 or 1. + if (min_value == 0) max_value = 0; + if (!(d1 == 1 || d1 == max_value) || !(d2 == 1 || d2 == max_value) || + !(d3 == 1 || d3 == max_value)) { + TF_LITE_KERNEL_LOG(context, + "Given shapes, %s, %s and %s, are not broadcastable.", + GetShapeDebugString(input1->dims).c_str(), + GetShapeDebugString(input2->dims).c_str(), + GetShapeDebugString(input3->dims).c_str()); + return kTfLiteError; + } + shape->data[out_dims - i - 1] = max_value; + } + *output_shape = shape.release(); + return kTfLiteOk; +} +#endif // ARDUINO + +// Size of string is not constant, return 0 in such case. +int TfLiteTypeGetSize(TfLiteType type) { + switch (type) { + case kTfLiteUInt8: + static_assert(sizeof(uint8_t) == 1, ""); + return 1; + case kTfLiteInt8: + static_assert(sizeof(int8_t) == 1, ""); + return 1; + case kTfLiteBool: + return sizeof(bool); + case kTfLiteUInt16: + static_assert(sizeof(uint16_t) == 2, ""); + return 2; + case kTfLiteInt16: + static_assert(sizeof(int16_t) == 2, ""); + return 2; + case kTfLiteFloat16: + static_assert(sizeof(int16_t) == 2, ""); + return 2; + case kTfLiteFloat32: + static_assert(sizeof(float) == 4, ""); + return 4; + case kTfLiteInt32: + static_assert(sizeof(int32_t) == 4, ""); + return 4; + case kTfLiteUInt32: + static_assert(sizeof(uint32_t) == 4, ""); + return 4; + case kTfLiteInt64: + static_assert(sizeof(int64_t) == 8, ""); + return 8; + case kTfLiteUInt64: + static_assert(sizeof(uint64_t) == 8, ""); + return 8; + case kTfLiteFloat64: + static_assert(sizeof(double) == 8, ""); + return 8; + case kTfLiteComplex64: + static_assert(sizeof(std::complex) == 8, ""); + return 8; + case kTfLiteComplex128: + static_assert(sizeof(std::complex) == 16, ""); + return 16; + default: + return 0; + } +} + +bool IsMobilePlatform() { +#if defined(ANDROID) || defined(__ANDROID__) + return true; +#elif defined(__APPLE__) +#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE + return true; +#endif +#endif + return false; +} + +bool HasUnspecifiedDimension(const TfLiteTensor* tensor) { +#ifndef ARDUINO + if (tensor->dims_signature) { + for (int i : TfLiteIntArrayView(tensor->dims_signature)) { + if (i == -1) return true; + } + } +#endif // ARDUINO + return false; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/kernel_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/kernel_util.h new file mode 100644 index 000000000..781e27778 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/kernel_util.h @@ -0,0 +1,330 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_KERNEL_UTIL_H_ +#define TENSORFLOW_LITE_KERNELS_KERNEL_UTIL_H_ + +#include + +#include +#ifndef ARDUINO +#include +#endif // ARDUINO + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +// A fair number of functions in this header have historically been inline. +// It is ok to change functions to not be inline if the latency with +// benchmark_model for MobileNet + MobileBERT is unaffected. If such a change is +// made, move the newly non-inlined function declarations to the top of this +// header file. + +// Note: You must check if result is not null: +// +// TfLiteTensor* my_tensor = GetInput(context, node, kMyTensorIdx); +// TF_LITE_ENSURE(context, my_tensor != nullptr); +// +// This is because the index might point to the optional tensor constant +// (kTfLiteOptionalTensor) in which case there is no tensor to return. +const TfLiteTensor* GetInput(const TfLiteContext* context, + const TfLiteNode* node, int index); + +// Same as `GetInput` but returns boolean and uses output argument for tensor. +// +// TfLiteTensor* my_tensor; +// TF_LITE_ENSURE_OK(context, +// GetInputSafe(context, node, kMyTensorIdx, &my_tensor)); +// // can use my_tensor directly from here onwards, it is not nullptr +// +// Should be used in cases where the binary size is too large. +TfLiteStatus GetInputSafe(const TfLiteContext* context, const TfLiteNode* node, + int index, const TfLiteTensor** tensor); + +// Note: You must check if result is not null: +// +// TfLiteTensor* my_tensor = GetVariableInput(context, node, kMyTensorIdx); +// TF_LITE_ENSURE(context, my_tensor != nullptr); +// +// This is because the index might point to the optional tensor constant +// (kTfLiteOptionalTensor) in which case there is no tensor to return. +TfLiteTensor* GetVariableInput(TfLiteContext* context, const TfLiteNode* node, + int index); + +// Note: You must check if result is not null: +// +// TfLiteTensor* my_tensor = GetOutput(context, node, kMyTensorIdx); +// TF_LITE_ENSURE(context, my_tensor != nullptr); +// +// This is because the index might point to the optional tensor constant +// (kTfLiteOptionalTensor) in which case there is no tensor to return. +TfLiteTensor* GetOutput(TfLiteContext* context, const TfLiteNode* node, + int index); + +// Same as `GetOutput` but returns boolean and uses output argument for tensor. +// +// TfLiteTensor* my_tensor; +// TF_LITE_ENSURE_OK(context, +// GetOutputSafe(context, node, kMyTensorIdx, &my_tensor)); +// // can use my_tensor directly from here onwards, it is not nullptr +// +// Should be used in cases where the binary size is too large. +TfLiteStatus GetOutputSafe(const TfLiteContext* context, const TfLiteNode* node, + int index, TfLiteTensor** tensor); + +// Note: You must check if result is not null: +// +// TfLiteTensor* my_tensor = GetOptionalInputTensor(context, node, kIdx); +// TF_LITE_ENSURE(context, my_tensor != nullptr); +// +// This is because the index might point to the optional tensor constant +// (kTfLiteOptionalTensor) in which case there is no tensor to return. +// +// Deprecated. GetInput has the same functionality. +const TfLiteTensor* GetOptionalInputTensor(const TfLiteContext* context, + const TfLiteNode* node, int index); + +#ifndef ARDUINO +// Note: You must check if result is not null: +// +// TfLiteTensor* my_tensor = GetTemporary(context, node, kMyTensorIdx); +// TF_LITE_ENSURE(context, my_tensor != nullptr); +// +// This is because the index might point to the optional tensor constant +// (kTfLiteOptionalTensor) in which case there is no tensor to return. +TfLiteTensor* GetTemporary(TfLiteContext* context, const TfLiteNode* node, + int index); + +// Same as `GetTemporary` but returns boolean and uses output argument for +// tensor. +// +// TfLiteTensor* my_tensor; +// TF_LITE_ENSURE_OK(context, +// GetTemporarySafe(context, node, kMyTensorIdx, +// &my_tensor)); +// // can use my_tensor directly from here onwards, it is not nullptr +// +// Should be used in cases where the binary size is too large. +TfLiteStatus GetTemporarySafe(const TfLiteContext* context, + const TfLiteNode* node, int index, + TfLiteTensor** tensor); + +// Note: You must check if result is not null: +// +// TfLiteTensor* my_tensor = GetIntermediates(context, node, kMyTensorIdx); +// TF_LITE_ENSURE(context, my_tensor != nullptr); +// +// This is because the index might point to the optional tensor constant +// (kTfLiteOptionalTensor) in which case there is no tensor to return. +const TfLiteTensor* GetIntermediates(TfLiteContext* context, + const TfLiteNode* node, int index); + +// Same as `GetIntermediates` but returns boolean and uses output argument for +// tensor. +// +// TfLiteTensor* my_tensor; +// TF_LITE_ENSURE_OK(context, +// GetIntermediatesSafe(context, node, kMyTensorIdx, +// &my_tensor)); +// // can use my_tensor directly from here onwards, it is not nullptr +// +// Should be used in cases where the binary size is too large. +TfLiteStatus GetIntermediatesSafe(const TfLiteContext* context, + const TfLiteNode* node, int index, + TfLiteTensor** tensor); +#endif // ARDUINO + +inline int NumDimensions(const TfLiteTensor* t) { return t->dims->size; } +inline int SizeOfDimension(const TfLiteTensor* t, int dim) { + return t->dims->data[dim]; +} + +inline int NumInputs(const TfLiteNode* node) { + return node->inputs == nullptr ? 0 : node->inputs->size; +} +inline int NumOutputs(const TfLiteNode* node) { + return node->outputs == nullptr ? 0 : node->outputs->size; +} + +#ifndef ARDUINO +inline int NumIntermediates(const TfLiteNode* node) { + return node->intermediates->size; +} +#endif // ARDUINO + +inline int64_t NumElements(const TfLiteIntArray* dims) { + int64_t count = 1; + for (int i = 0; i < dims->size; ++i) { + count *= dims->data[i]; + } + return count; +} + +inline int64_t NumElements(const TfLiteTensor* t) { + return NumElements(t->dims); +} + +inline int64_t NumElements(const int* dims, int num_dims) { + int64_t count = 1; + for (int i = 0; i < num_dims; ++i) { + count *= dims[i]; + } + return count; +} + +// Determines whether tensor is constant. +// TODO(b/138199592): Introduce new query which checks for constant OR +// persistent-read-only, which would be useful for most tensor kernels that +// are potentially dynamic based on the input tensor value availability at the +// time of prepare. +inline bool IsConstantTensor(const TfLiteTensor* tensor) { + return tensor->allocation_type == kTfLiteMmapRo; +} + +inline bool IsConstantOrPersistentTensor(const TfLiteTensor* tensor) { + return IsConstantTensor(tensor) || + (tensor->allocation_type == kTfLitePersistentRo); +} + +// Determines whether tensor is dynamic. Note that a tensor can be non-const and +// not dynamic. This function specifically checks for a dynamic tensor. +inline bool IsDynamicTensor(const TfLiteTensor* tensor) { + return tensor->allocation_type == kTfLiteDynamic; +} + +// Sets tensor to dynamic. +inline void SetTensorToDynamic(TfLiteTensor* tensor) { + if (tensor->allocation_type != kTfLiteDynamic) { + tensor->allocation_type = kTfLiteDynamic; + tensor->data.raw = nullptr; + } +} + +// Sets tensor to persistent and read-only. +inline void SetTensorToPersistentRo(TfLiteTensor* tensor) { + if (tensor->allocation_type != kTfLitePersistentRo) { + tensor->allocation_type = kTfLitePersistentRo; + tensor->data.raw = nullptr; + } +} + +// Determines whether it is a hybrid op - one that has float inputs and +// quantized weights. +inline bool IsHybridOp(const TfLiteTensor* input, const TfLiteTensor* weight) { + return ((weight->type == kTfLiteUInt8 || weight->type == kTfLiteInt8) && + input->type == kTfLiteFloat32); +} + +// Check dimensionality match and populate OpData for Conv and DepthwiseConv. +TfLiteStatus PopulateConvolutionQuantizationParams( + TfLiteContext* context, const TfLiteTensor* input, + const TfLiteTensor* filter, const TfLiteTensor* bias, TfLiteTensor* output, + const TfLiteFusedActivation& activation, int32_t* multiplier, int* shift, + int32_t* output_activation_min, int32_t* output_activation_max, + int32_t* per_channel_multiplier, int32_t* per_channel_shift); + +TfLiteStatus PopulateConvolutionQuantizationParams( + TfLiteContext* context, const TfLiteTensor* input, + const TfLiteTensor* filter, const TfLiteTensor* bias, TfLiteTensor* output, + const TfLiteFusedActivation& activation, int32_t* multiplier, int* shift, + int32_t* output_activation_min, int32_t* output_activation_max, + int32_t* per_channel_multiplier, int32_t* per_channel_shift, + int num_channels); + +// Calculates the multiplication factor for a quantized convolution (or +// quantized depthwise convolution) involving the given tensors. Returns an +// error if the scales of the tensors are not compatible. +TfLiteStatus GetQuantizedConvolutionMultipler(TfLiteContext* context, + const TfLiteTensor* input, + const TfLiteTensor* filter, + const TfLiteTensor* bias, + TfLiteTensor* output, + double* multiplier); + +TfLiteStatus GetQuantizedConvolutionMultipler(TfLiteContext* context, + const TfLiteTensor* input, + const TfLiteTensor* filter, + TfLiteTensor* output, + double* multiplier); + +// Calculates the useful quantized range of an activation layer given its +// activation tensor. +TfLiteStatus CalculateActivationRangeQuantized(TfLiteContext* context, + TfLiteFusedActivation activation, + TfLiteTensor* output, + int32_t* act_min, + int32_t* act_max); + +// Calculates the useful range of an activation layer given its activation +// tensor.a +template +void CalculateActivationRange(TfLiteFusedActivation activation, + T* activation_min, T* activation_max) { + if (activation == kTfLiteActRelu) { + *activation_min = 0; + *activation_max = std::numeric_limits::max(); + } else if (activation == kTfLiteActRelu6) { + *activation_min = 0; + *activation_max = 6; + } else if (activation == kTfLiteActReluN1To1) { + *activation_min = -1; + *activation_max = 1; + } else { + *activation_min = std::numeric_limits::lowest(); + *activation_max = std::numeric_limits::max(); + } +} + +// Return true if the given tensors have the same shape. +bool HaveSameShapes(const TfLiteTensor* input1, const TfLiteTensor* input2); + +#if !defined(ARDUINO) +// Gets the output shape from the input tensor. +TfLiteStatus GetOutputShapeFromInput(TfLiteContext* context, + const TfLiteTensor* input, + TfLiteIntArray** output_shape); + +const std::string GetShapeDebugString(const TfLiteIntArray* shape); + +#endif // !defined(ARDUINO) + +// Calculates the output_shape that is necessary for element-wise operations +// with broadcasting involving the two input tensors. +TfLiteStatus CalculateShapeForBroadcast(TfLiteContext* context, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + TfLiteIntArray** output_shape); + +// Calculates the output_shape that is necessary for element-wise operations +// with broadcasting involving the three input tensors. +TfLiteStatus CalculateShapeForBroadcast(TfLiteContext* context, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + const TfLiteTensor* input3, + TfLiteIntArray** output_shape); + +// Return the size of given type in bytes. Return 0 in case of string. +int TfLiteTypeGetSize(TfLiteType type); + +// Whether the current platform is mobile (Android or iOS). +bool IsMobilePlatform(); + +// Returns whether there is unspecified dimension in the tensor's dim signature. +bool HasUnspecifiedDimension(const TfLiteTensor* tensor); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_KERNEL_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/op_macros.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/op_macros.h new file mode 100644 index 000000000..ba297de5c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/op_macros.h @@ -0,0 +1,38 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_OP_MACROS_H_ +#define TENSORFLOW_LITE_KERNELS_OP_MACROS_H_ + +#include "tensorflow/lite/micro/debug_log.h" + +#if !defined(TF_LITE_MCU_DEBUG_LOG) +#include +#define TFLITE_ABORT abort() +#else +inline void AbortImpl() { + DebugLog("HALTED\n"); + while (1) { + } +} +#define TFLITE_ABORT AbortImpl(); +#endif + +#if defined(ARDUINO) +#define TFLITE_ASSERT_FALSE (static_cast(0)) +#else +#define TFLITE_ASSERT_FALSE TFLITE_ABORT +#endif + +#endif // TENSORFLOW_LITE_KERNELS_OP_MACROS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/padding.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/padding.h new file mode 100644 index 000000000..d9cca3ea1 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/kernels/padding.h @@ -0,0 +1,115 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_PADDING_H_ +#define TENSORFLOW_LITE_KERNELS_PADDING_H_ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +inline int ComputePadding(int stride, int dilation_rate, int in_size, + int filter_size, int out_size) { + int effective_filter_size = (filter_size - 1) * dilation_rate + 1; + int padding = ((out_size - 1) * stride + effective_filter_size - in_size) / 2; + return padding > 0 ? padding : 0; +} + +// It's not guaranteed that padding is symmetric. It's important to keep +// offset for algorithms need all paddings. +inline int ComputePaddingWithOffset(int stride, int dilation_rate, int in_size, + int filter_size, int out_size, + int* offset) { + int effective_filter_size = (filter_size - 1) * dilation_rate + 1; + int total_padding = + ((out_size - 1) * stride + effective_filter_size - in_size); + total_padding = total_padding > 0 ? total_padding : 0; + *offset = total_padding % 2; + return total_padding / 2; +} + +// Matching GetWindowedOutputSize in TensorFlow. +inline int ComputeOutSize(TfLitePadding padding, int image_size, + int filter_size, int stride, int dilation_rate = 1) { + int effective_filter_size = (filter_size - 1) * dilation_rate + 1; + + // TODO(b/186448822): This uses 0 since the function has no other way to + // report error case + if (stride == 0) return 0; + + switch (padding) { + case kTfLitePaddingSame: + return (image_size + stride - 1) / stride; + case kTfLitePaddingValid: + return (image_size + stride - effective_filter_size) / stride; + default: + return 0; + } +} + +inline TfLitePaddingValues ComputePaddingHeightWidth( + int stride_height, int stride_width, int dilation_rate_height, + int dilation_rate_width, int in_height, int in_width, int filter_height, + int filter_width, TfLitePadding padding, int* out_height, int* out_width) { + *out_width = ComputeOutSize(padding, in_width, filter_width, stride_width, + dilation_rate_width); + *out_height = ComputeOutSize(padding, in_height, filter_height, stride_height, + dilation_rate_height); + + TfLitePaddingValues padding_values; + int offset = 0; + padding_values.height = + ComputePaddingWithOffset(stride_height, dilation_rate_height, in_height, + filter_height, *out_height, &offset); + padding_values.height_offset = offset; + padding_values.width = + ComputePaddingWithOffset(stride_width, dilation_rate_width, in_width, + filter_width, *out_width, &offset); + padding_values.width_offset = offset; + return padding_values; +} + +inline Padding3DValues ComputePadding3DValues( + int stride_height, int stride_width, int stride_depth, + int dilation_rate_height, int dilation_rate_width, int dilation_rate_depth, + int in_height, int in_width, int in_depth, int filter_height, + int filter_width, int filter_depth, TfLitePadding padding, int* out_height, + int* out_width, int* out_depth) { + *out_width = ComputeOutSize(padding, in_width, filter_width, stride_width, + dilation_rate_width); + *out_height = ComputeOutSize(padding, in_height, filter_height, stride_height, + dilation_rate_height); + *out_depth = ComputeOutSize(padding, in_depth, filter_depth, stride_depth, + dilation_rate_depth); + + Padding3DValues padding_values; + int offset = 0; + padding_values.depth = + ComputePaddingWithOffset(stride_depth, dilation_rate_depth, in_depth, + filter_depth, *out_depth, &offset); + padding_values.depth_offset = offset; + padding_values.height = + ComputePaddingWithOffset(stride_height, dilation_rate_height, in_height, + filter_height, *out_height, &offset); + padding_values.height_offset = offset; + padding_values.width = + ComputePaddingWithOffset(stride_width, dilation_rate_width, in_width, + filter_width, *out_width, &offset); + padding_values.width_offset = offset; + return padding_values; +} +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_PADDING_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/all_ops_resolver.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/all_ops_resolver.cpp new file mode 100644 index 000000000..150f45259 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/all_ops_resolver.cpp @@ -0,0 +1,123 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/all_ops_resolver.h" + +#include "tensorflow/lite/micro/kernels/micro_ops.h" + +namespace tflite { + +AllOpsResolver::AllOpsResolver() { + // Please keep this list of Builtin Operators in alphabetical order. + AddAbs(); + AddAdd(); + AddAddN(); + AddArgMax(); + AddArgMin(); + AddAssignVariable(); + AddAveragePool2D(); + AddBatchToSpaceNd(); + AddBroadcastArgs(); + AddBroadcastTo(); + AddCallOnce(); + AddCast(); + AddCeil(); + AddCircularBuffer(); + AddConcatenation(); + AddConv2D(); + AddCos(); + AddCumSum(); + AddDepthToSpace(); + AddDepthwiseConv2D(); + AddDequantize(); + AddDetectionPostprocess(); + AddDiv(); + AddElu(); + AddEqual(); + AddEthosU(); + AddExp(); + AddExpandDims(); + AddFill(); + AddFloor(); + AddFloorDiv(); + AddFloorMod(); + AddFullyConnected(); + AddGather(); + AddGatherNd(); + AddGreater(); + AddGreaterEqual(); + AddHardSwish(); + AddIf(); + AddL2Normalization(); + AddL2Pool2D(); + AddLeakyRelu(); + AddLess(); + AddLessEqual(); + AddLog(); + AddLogicalAnd(); + AddLogicalNot(); + AddLogicalOr(); + AddLogistic(); + AddLogSoftmax(); + AddMaxPool2D(); + AddMaximum(); + AddMean(); + AddMinimum(); + AddMirrorPad(); + AddMul(); + AddNeg(); + AddNotEqual(); + AddPack(); + AddPad(); + AddPadV2(); + AddPrelu(); + AddQuantize(); + AddReadVariable(); + AddReduceMax(); + AddRelu(); + AddRelu6(); + AddReshape(); + AddResizeBilinear(); + AddResizeNearestNeighbor(); + AddRound(); + AddRsqrt(); + AddSelectV2(); + AddShape(); + AddSin(); + AddSlice(); + AddSoftmax(); + AddSpaceToBatchNd(); + AddSpaceToDepth(); + AddSplit(); + AddSplitV(); + AddSqrt(); + AddSquare(); + AddSquaredDifference(); + AddSqueeze(); + AddStridedSlice(); + AddSub(); + AddSum(); + AddSvdf(); + AddTanh(); + AddTranspose(); + AddTransposeConv(); + AddUnidirectionalSequenceLSTM(); + AddUnpack(); + AddVarHandle(); + AddWhile(); + AddZerosLike(); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/all_ops_resolver.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/all_ops_resolver.h new file mode 100644 index 000000000..391b4f08e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/all_ops_resolver.h @@ -0,0 +1,38 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_ALL_OPS_RESOLVER_H_ +#define TENSORFLOW_LITE_MICRO_ALL_OPS_RESOLVER_H_ + +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/micro_mutable_op_resolver.h" + +namespace tflite { + +// The magic number in the template parameter is the maximum number of ops that +// can be added to AllOpsResolver. It can be increased if needed. And most +// applications that care about the memory footprint will want to directly use +// MicroMutableOpResolver and have an application specific template parameter. +// The examples directory has sample code for this. +class AllOpsResolver : public MicroMutableOpResolver<128> { + public: + AllOpsResolver(); + + private: + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_ALL_OPS_RESOLVER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/ibuffer_allocator.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/ibuffer_allocator.h new file mode 100644 index 000000000..b92d6b2d9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/ibuffer_allocator.h @@ -0,0 +1,100 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_IBUFFER_ALLOCATOR_H_ +#define TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_IBUFFER_ALLOCATOR_H_ + +#include +#include + +#include "tensorflow/lite/c/c_api_types.h" + +namespace tflite { +// Interface classes that the TFLM framework relies on to get buffers it needs. +// There are two types of buffers that the TFLM framework requires: persistent +// and non-persistent. Persistent buffers, once allocated, are never freed by +// the TFLM framework. Non-persist buffers can be allocated and deallocated by +// the TFLM framework. This file defines two interfaces classes that TFLM +// framework will rely on to manage these buffers. + +// Interface class for managing persistent buffers. +class IPersistentBufferAllocator { + public: + IPersistentBufferAllocator() {} + virtual ~IPersistentBufferAllocator() {} + + // Allocates persistent memory. The persistent buffer is never freed. + virtual uint8_t* AllocatePersistentBuffer(size_t size, size_t alignment) = 0; + + // Returns the size of all persistent allocations in bytes. + virtual size_t GetPersistentUsedBytes() const = 0; +}; + +// Interface class for managing non-persistent buffers. +// The default non-persistent buffers are temp buffers that are not resizable. +// Support of at least one resizable buffer is required. +class INonPersistentBufferAllocator { + public: + INonPersistentBufferAllocator() {} + virtual ~INonPersistentBufferAllocator() {} + + // Allocates a temporary buffer. This buffer is not resizable. + virtual uint8_t* AllocateTemp(size_t size, size_t alignment) = 0; + + // Signals that a temporary buffer is no longer needed. + virtual void DeallocateTemp(uint8_t* buf) = 0; + + // Returns true if all temporary buffers are already deallocated. + virtual bool IsAllTempDeallocated() = 0; + + // Signals that all temporary allocations can be reclaimed. TFLM calls this + // API when it knows that all temporary buffers that it requested has been + // deallocated. The goal of API is to facilitate implementations of + // INonPersistentBufferAllocator can reuse buffer with some reasonable + // complexity. + virtual TfLiteStatus ResetTempAllocations() = 0; + + // Returns a buffer that is resizable viable ResizeBuffer(). + virtual uint8_t* AllocateResizableBuffer(size_t size, size_t alignment) = 0; + + // Resizes a buffer that is previously returned by the + // AllocateResizableBuffer. + virtual TfLiteStatus ResizeBuffer(uint8_t* resizable_buf, size_t size, + size_t alignment) = 0; + + // Frees up the memory occupied by the resizable buffer. + virtual TfLiteStatus DeallocateResizableBuffer(uint8_t* resizable_buf) = 0; + + // Returns a pointer pointing to the start of the overlay memory, which is + // used for activation tensors and scratch buffers by kernels at Invoke stage. + virtual uint8_t* GetOverlayMemoryAddress() const = 0; + + // Reserves the size of the overlay memory. This overlay is reserved for the + // kernels at Invoke stage. This is referred to as the overlay because before + // Invoket state, the same memory can be used for temp buffers. The layout of + // the memory is planned by the memory planner separately at Invoke stage. + virtual TfLiteStatus ReserveNonPersistentOverlayMemory(size_t size, + size_t alignment) = 0; + + // Returns the size of non-persistent buffer in use. + virtual size_t GetNonPersistentUsedBytes() const = 0; + + // Returns the number of bytes available with a given alignment. This number + // takes in account any temporary allocations. + virtual size_t GetAvailableMemory(size_t alignment) const = 0; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_IBUFFER_ALLOCATOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.cpp new file mode 100644 index 000000000..a8f00eadc --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.cpp @@ -0,0 +1,170 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.h" + +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +NonPersistentArenaBufferAllocator::NonPersistentArenaBufferAllocator( + uint8_t* buffer, size_t buffer_size) + : buffer_head_(buffer), + buffer_tail_(buffer + buffer_size), + head_temp_(buffer), + next_temp_(buffer) {} + +NonPersistentArenaBufferAllocator::~NonPersistentArenaBufferAllocator() {} + +// Allocates a temporary buffer. This buffer is not resizable. +uint8_t* NonPersistentArenaBufferAllocator::AllocateTemp(size_t size, + size_t alignment) { + uint8_t* const aligned_result = AlignPointerUp(next_temp_, alignment); + const size_t available_memory = buffer_tail_ - aligned_result; + if (available_memory < size) { + MicroPrintf( + "Failed to allocate temp memory. Requested: %u, " + "available %u, missing: %u", + size, available_memory, size - available_memory); + return nullptr; + } + next_temp_ = aligned_result + size; + temp_buffer_ptr_check_sum_ ^= reinterpret_cast(aligned_result); + temp_buffer_count_++; + return aligned_result; +} + +// Signals that a temporary buffer is no longer needed. +void NonPersistentArenaBufferAllocator::DeallocateTemp(uint8_t* temp_buf) { + temp_buffer_ptr_check_sum_ ^= reinterpret_cast(temp_buf); + temp_buffer_count_--; +} + +// Returns true if all temporary buffers are already deallocated. +bool NonPersistentArenaBufferAllocator::IsAllTempDeallocated() { + if (temp_buffer_count_ != 0 || temp_buffer_ptr_check_sum_ != 0) { + MicroPrintf( + "Number of allocated temp buffers: %d. Checksum passing status: %d", + temp_buffer_count_, !temp_buffer_ptr_check_sum_); + return false; + } + return true; +} + +// Signals that all temporary allocations can be reclaimed. TFLM calls this +// API when it knows that all temporary buffers that it requested has been +// deallocated. The goal of API is to facilitate implementations of +// INonPersistentBufferAllocator can reuse buffer with some reasonable +// complexity. +TfLiteStatus NonPersistentArenaBufferAllocator::ResetTempAllocations() { + if (!IsAllTempDeallocated()) { + MicroPrintf( + "All temp buffers must be freed before calling ResetTempAllocations()"); + return kTfLiteError; + } + next_temp_ = head_temp_; + return kTfLiteOk; +} + +// Returns a buffer that is resizable viable ResizeBuffer(). +uint8_t* NonPersistentArenaBufferAllocator::AllocateResizableBuffer( + size_t size, size_t alignment) { + // Only supports one resizable buffer, which starts at the buffer head. + uint8_t* expected_resizable_buf = AlignPointerUp(buffer_head_, alignment); + + if (resizable_buffer_allocated_) { + MicroPrintf( + "Cannot allocate a new resizable buffer when one is already allocated"); + return nullptr; + } + + if (ResizeBuffer(expected_resizable_buf, size, alignment) == kTfLiteOk) { + resizable_buffer_allocated_ = true; + return expected_resizable_buf; + } + return nullptr; +} + +// Resizes a buffer that is previously returned by the AllocateResizableBuffer. +// Note that ResizeBuffer(old_resizable_buf, 0, 1) effectively deallocates +// a previous allocated resizable buffer. +TfLiteStatus NonPersistentArenaBufferAllocator::ResizeBuffer( + uint8_t* resizable_buf, size_t size, size_t alignment) { + // Only supports one resizable buffer, which starts at the buffer head. + uint8_t* expect_resizable_buf = AlignPointerUp(buffer_head_, alignment); + if (resizable_buf != expect_resizable_buf) { + MicroPrintf("Internal error: buffer is not resizable"); + return kTfLiteError; + } + if (head_temp_ != next_temp_) { + MicroPrintf("ResetTempAllocations() is not called before ResizeBuffer()."); + return kTfLiteError; + } + + const size_t available_memory = buffer_tail_ - expect_resizable_buf; + if (available_memory < size) { + MicroPrintf( + "Failed to resize buffer. Requested: %u, available %u, missing: %u", + size, available_memory, size - available_memory); + return kTfLiteError; + } + head_temp_ = expect_resizable_buf + size; + next_temp_ = head_temp_; + + return kTfLiteOk; +} + +// Frees up the memory occupied by the resizable buffer. +TfLiteStatus NonPersistentArenaBufferAllocator::DeallocateResizableBuffer( + uint8_t* resizable_buf) { + TfLiteStatus status = ResizeBuffer(resizable_buf, 0, 1); + if (status == kTfLiteOk) { + resizable_buffer_allocated_ = false; + } + return status; +} + +// Returns a pointer pointing to the start of the overlay memory, which is +// used for activation tensors and scratch buffers by kernels at Invoke stage. +uint8_t* NonPersistentArenaBufferAllocator::GetOverlayMemoryAddress() const { + return buffer_head_; +} + +// Reserves the size of the overlay memory. This overlay is reserved for the +// kernels at Invoke stage. This is referred to as the overlay because before +// Invoket state, the same memory can be used for temp buffers. The layout of +// the memory is planned by the memory planner separately at Invoke stage. +TfLiteStatus +NonPersistentArenaBufferAllocator::ReserveNonPersistentOverlayMemory( + size_t size, size_t alignment) { + uint8_t* expect_resizable_buf = AlignPointerUp(buffer_head_, alignment); + return ResizeBuffer(expect_resizable_buf, size, alignment); +} + +// Returns the size of non-persistent buffer in use. +size_t NonPersistentArenaBufferAllocator::GetNonPersistentUsedBytes() const { + return (next_temp_ - buffer_head_); +} + +// Returns the number of bytes available with a given alignment. This number +// takes in account any temporary allocations. +size_t NonPersistentArenaBufferAllocator::GetAvailableMemory( + size_t alignment) const { + uint8_t* const aligned_temp = AlignPointerUp(next_temp_, alignment); + uint8_t* const aligned_tail = AlignPointerDown(buffer_tail_, alignment); + return aligned_tail - aligned_temp; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.h new file mode 100644 index 000000000..ebd376466 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.h @@ -0,0 +1,104 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_NON_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_ +#define TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_NON_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_ + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/arena_allocator/ibuffer_allocator.h" +#include "tensorflow/lite/micro/compatibility.h" + +namespace tflite { + +// Implement INonPersistentBufferAllocator on an arena that is dedicated for +// non-persistent buffers. +class NonPersistentArenaBufferAllocator : public INonPersistentBufferAllocator { + public: + NonPersistentArenaBufferAllocator(uint8_t* buffer, size_t buffer_size); + virtual ~NonPersistentArenaBufferAllocator(); + + // Allocates a temporary buffer. This buffer is not resizable. + uint8_t* AllocateTemp(size_t size, size_t alignment) override; + + // Signals that a temporary buffer is no longer needed. + void DeallocateTemp(uint8_t* buf) override; + + // Returns true if all temporary buffers are already deallocated. + bool IsAllTempDeallocated() override; + + // Signals that all temporary allocations can be reclaimed. TFLM calls this + // API when it knows that all temporary buffers that it requested has been + // deallocated. + TfLiteStatus ResetTempAllocations() override; + + // Returns a buffer that is resizable viable ResizeBuffer(). + uint8_t* AllocateResizableBuffer(size_t size, size_t alignment) override; + + // Resizes a buffer that is previously returned by the + // AllocateResizableBuffer. + TfLiteStatus ResizeBuffer(uint8_t* resizable_buf, size_t size, + size_t alignment) override; + + // Frees up the memory occupied by the resizable buffer. + TfLiteStatus DeallocateResizableBuffer(uint8_t* resizable_buf) override; + + // Returns a pointer pointing to the start of the overlay memory, which is + // used for activation tensors and scratch buffers by kernels at Invoke stage. + uint8_t* GetOverlayMemoryAddress() const override; + + // Reserves the size of the overlay memory. This overlay is reserved for the + // kernels at Invoke stage. This is referred to as the overlay because before + // Invoket state, the same memory can be used for temp buffers. The layout of + // the memory is planned by the memory planner separately at Invoke stage. + TfLiteStatus ReserveNonPersistentOverlayMemory(size_t size, + size_t alignment) override; + + // Returns the size of non-persistent buffer in use. + size_t GetNonPersistentUsedBytes() const override; + + // Returns the number of bytes available with a given alignment. This number + // takes in account any temporary allocations. + size_t GetAvailableMemory(size_t alignment) const override; + + TF_LITE_REMOVE_VIRTUAL_DELETE + + private: + // The memory arena that this allocator manages. + uint8_t* const buffer_head_; + uint8_t* const buffer_tail_; + + // The whole region is split into two parts: + // buffer_head_ to head_temp_ - 1 belongs to the only resizable buffer. + // head_temp_ to buffer_tail_ can be used for (non-resizable) temp buffers. + uint8_t* head_temp_; + + // next_temp_ points to the next available temp buffer allocation address and + // its range is between head_temp_ and buffer_tail_ + uint8_t* next_temp_; + + // XOR Check sum for outstanding temp buffers. + // If all temp buffers are deallocated OR no temp buffers are allocated, + // temp_buffer_ptr_check_sum_ == nullptr. + intptr_t temp_buffer_ptr_check_sum_ = 0; + // Count of outstanding temp buffers. + int temp_buffer_count_ = 0; + bool resizable_buffer_allocated_ = false; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_NON_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.cpp new file mode 100644 index 000000000..a770bc9df --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.cpp @@ -0,0 +1,52 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.h" + +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +PersistentArenaBufferAllocator::PersistentArenaBufferAllocator( + uint8_t* buffer, size_t buffer_size) + : buffer_head_(buffer), + buffer_tail_(buffer + buffer_size), + tail_temp_(buffer_tail_) {} + +PersistentArenaBufferAllocator::~PersistentArenaBufferAllocator() {} + +uint8_t* PersistentArenaBufferAllocator::AllocatePersistentBuffer( + size_t size, size_t alignment) { + uint8_t* const aligned_result = + AlignPointerDown(tail_temp_ - size, alignment); + if (aligned_result < buffer_head_) { +#ifndef TF_LITE_STRIP_ERROR_STRINGS + const size_t missing_memory = buffer_head_ - aligned_result; + MicroPrintf( + "Failed to allocate tail memory. Requested: %u, " + "available %u, missing: %u", + size, size - missing_memory, missing_memory); +#endif + return nullptr; + } + tail_temp_ = aligned_result; + return aligned_result; +} + +size_t PersistentArenaBufferAllocator::GetPersistentUsedBytes() const { + return buffer_tail_ - tail_temp_; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.h new file mode 100644 index 000000000..2c8e3dca5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.h @@ -0,0 +1,58 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_ +#define TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_ + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/arena_allocator/ibuffer_allocator.h" +#include "tensorflow/lite/micro/compatibility.h" + +namespace tflite { + +// PersistentArenaBufferAllocator is an implementatation of +// IPersistentBufferAllocator interface on an arena that is dedicated for +// persistent buffers. +class PersistentArenaBufferAllocator : public IPersistentBufferAllocator { + public: + PersistentArenaBufferAllocator(uint8_t* buffer, size_t buffer_size); + virtual ~PersistentArenaBufferAllocator(); + + // Allocates persistent memory. The persistent buffer is never freed. + // Returns nullptr if errors occured. + uint8_t* AllocatePersistentBuffer(size_t size, size_t alignment) override; + + // Returns the size of all persistent allocations in bytes. + size_t GetPersistentUsedBytes() const override; + + TF_LITE_REMOVE_VIRTUAL_DELETE + private: + // The memory arena that this allocator manages. + uint8_t* const buffer_head_; + uint8_t* const buffer_tail_; + + // The whole region is split into two parts: + // tail_temp_ to buffer_tail_ contains allocated buffers; + // buffer_head_ to tail_temp_ - 1 belongs to still available spaces. + // So in essence, the allocated region grows from the bottom and emulates + // SingleArenaBufferAllocator's persistent part. + uint8_t* tail_temp_; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.cpp new file mode 100644 index 000000000..e21e36469 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.cpp @@ -0,0 +1,85 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.h" + +#include + +#include "tensorflow/lite/kernels/internal/compatibility.h" + +namespace tflite { + +RecordingSingleArenaBufferAllocator::RecordingSingleArenaBufferAllocator( + uint8_t* buffer_head, size_t buffer_size) + : SingleArenaBufferAllocator(buffer_head, buffer_size), + requested_head_bytes_(0), + requested_tail_bytes_(0), + used_bytes_(0), + alloc_count_(0) {} + +RecordingSingleArenaBufferAllocator::~RecordingSingleArenaBufferAllocator() {} + +RecordingSingleArenaBufferAllocator* +RecordingSingleArenaBufferAllocator::Create(uint8_t* buffer_head, + size_t buffer_size) { + TFLITE_DCHECK(buffer_head != nullptr); + RecordingSingleArenaBufferAllocator tmp = + RecordingSingleArenaBufferAllocator(buffer_head, buffer_size); + + uint8_t* allocator_buffer = tmp.AllocatePersistentBuffer( + sizeof(RecordingSingleArenaBufferAllocator), + alignof(RecordingSingleArenaBufferAllocator)); + // Use the default copy constructor to populate internal states. + return new (allocator_buffer) RecordingSingleArenaBufferAllocator(tmp); +} + +size_t RecordingSingleArenaBufferAllocator::GetRequestedBytes() const { + return requested_head_bytes_ + requested_tail_bytes_; +} + +size_t RecordingSingleArenaBufferAllocator::GetUsedBytes() const { + return used_bytes_; +} + +size_t RecordingSingleArenaBufferAllocator::GetAllocatedCount() const { + return alloc_count_; +} + +TfLiteStatus RecordingSingleArenaBufferAllocator::ResizeBuffer( + uint8_t* resizable_buf, size_t size, size_t alignment) { + const uint8_t* previous_head = head(); + TfLiteStatus status = + SingleArenaBufferAllocator::ResizeBuffer(resizable_buf, size, alignment); + if (status == kTfLiteOk) { + used_bytes_ += head() - previous_head; + requested_head_bytes_ = size; + } + return status; +} + +uint8_t* RecordingSingleArenaBufferAllocator::AllocatePersistentBuffer( + size_t size, size_t alignment) { + const uint8_t* previous_tail = tail(); + uint8_t* result = + SingleArenaBufferAllocator::AllocatePersistentBuffer(size, alignment); + if (result != nullptr) { + used_bytes_ += previous_tail - tail(); + requested_tail_bytes_ += size; + alloc_count_++; + } + return result; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.h new file mode 100644 index 000000000..321215439 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.h @@ -0,0 +1,78 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_RECORDING_SINGLE_ARENA_BUFFER_ALLOCATOR_H_ +#define TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_RECORDING_SINGLE_ARENA_BUFFER_ALLOCATOR_H_ + +#include "tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/compatibility.h" + +namespace tflite { + +// Utility class used to log allocations of a SingleArenaBufferAllocator. Should +// only be used in debug/evaluation settings or unit tests to evaluate +// allocation usage. +class RecordingSingleArenaBufferAllocator : public SingleArenaBufferAllocator { + public: + // TODO(b/246776144): Will be removed with http://b/246776144 + RecordingSingleArenaBufferAllocator(ErrorReporter* error_reporter, + uint8_t* buffer_head, size_t buffer_size) + : RecordingSingleArenaBufferAllocator(buffer_head, buffer_size) { + (void)error_reporter; + } + + RecordingSingleArenaBufferAllocator(uint8_t* buffer_head, size_t buffer_size); + // TODO(b/157615197): Cleanup constructors/destructor and use factory + // functions. + ~RecordingSingleArenaBufferAllocator() override; + + static RecordingSingleArenaBufferAllocator* Create(uint8_t* buffer_head, + size_t buffer_size); + + // TODO(b/246776144): Will be removed with http://b/246776144 + static RecordingSingleArenaBufferAllocator* Create( + ErrorReporter* error_reporter, uint8_t* buffer_head, size_t buffer_size) { + (void)error_reporter; + return RecordingSingleArenaBufferAllocator::Create(buffer_head, + buffer_size); + } + + // Returns the number of bytes requested from the head or tail. + size_t GetRequestedBytes() const; + + // Returns the number of bytes actually allocated from the head or tail. This + // value will be >= to the number of requested bytes due to padding and + // alignment. + size_t GetUsedBytes() const; + + // Returns the number of alloc calls from the head or tail. + size_t GetAllocatedCount() const; + + TfLiteStatus ResizeBuffer(uint8_t* resizable_buf, size_t size, + size_t alignment) override; + uint8_t* AllocatePersistentBuffer(size_t size, size_t alignment) override; + + private: + size_t requested_head_bytes_; + size_t requested_tail_bytes_; + size_t used_bytes_; + size_t alloc_count_; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_RECORDING_SINGLE_ARENA_BUFFER_ALLOCATOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.cpp new file mode 100644 index 000000000..8655cfdce --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.cpp @@ -0,0 +1,199 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h" + +#include +#include +#include + +#include "tensorflow/lite/c/c_api_types.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +SingleArenaBufferAllocator::SingleArenaBufferAllocator(uint8_t* buffer_head, + uint8_t* buffer_tail) + : buffer_head_(buffer_head), + buffer_tail_(buffer_tail), + head_(buffer_head), + tail_(buffer_tail), + temp_(buffer_head_) {} + +SingleArenaBufferAllocator::SingleArenaBufferAllocator(uint8_t* buffer, + size_t buffer_size) + : SingleArenaBufferAllocator(buffer, buffer + buffer_size) {} + +/* static */ +SingleArenaBufferAllocator* SingleArenaBufferAllocator::Create( + uint8_t* buffer_head, size_t buffer_size) { + TFLITE_DCHECK(buffer_head != nullptr); + SingleArenaBufferAllocator tmp = + SingleArenaBufferAllocator(buffer_head, buffer_size); + + // Allocate enough bytes from the buffer to create a + // SingleArenaBufferAllocator. The new instance will use the current adjusted + // tail buffer from the tmp allocator instance. + uint8_t* allocator_buffer = tmp.AllocatePersistentBuffer( + sizeof(SingleArenaBufferAllocator), alignof(SingleArenaBufferAllocator)); + // Use the default copy constructor to populate internal states. + return new (allocator_buffer) SingleArenaBufferAllocator(tmp); +} + +SingleArenaBufferAllocator::~SingleArenaBufferAllocator() {} + +uint8_t* SingleArenaBufferAllocator::AllocateResizableBuffer(size_t size, + size_t alignment) { + // Only supports one resizable buffer, which starts at the buffer head. + uint8_t* expect_resizable_buf = AlignPointerUp(buffer_head_, alignment); + if (ResizeBuffer(expect_resizable_buf, size, alignment) == kTfLiteOk) { + return expect_resizable_buf; + } + return nullptr; +} + +TfLiteStatus SingleArenaBufferAllocator::DeallocateResizableBuffer( + uint8_t* resizable_buf) { + return ResizeBuffer(resizable_buf, 0, 1); +} + +TfLiteStatus SingleArenaBufferAllocator::ReserveNonPersistentOverlayMemory( + size_t size, size_t alignment) { + uint8_t* expect_resizable_buf = AlignPointerUp(buffer_head_, alignment); + return ResizeBuffer(expect_resizable_buf, size, alignment); +} + +TfLiteStatus SingleArenaBufferAllocator::ResizeBuffer(uint8_t* resizable_buf, + size_t size, + size_t alignment) { + // Only supports one resizable buffer, which starts at the buffer head. + uint8_t* expect_resizable_buf = AlignPointerUp(buffer_head_, alignment); + if (head_ != temp_ || resizable_buf != expect_resizable_buf) { + MicroPrintf( + "Internal error: either buffer is not resizable or " + "ResetTempAllocations() is not called before ResizeBuffer()."); + return kTfLiteError; + } + + uint8_t* const aligned_result = AlignPointerUp(buffer_head_, alignment); + const size_t available_memory = tail_ - aligned_result; + if (available_memory < size) { + MicroPrintf( + "Failed to resize buffer. Requested: %u, available %u, missing: %u", + size, available_memory, size - available_memory); + return kTfLiteError; + } + head_ = aligned_result + size; + temp_ = head_; + + return kTfLiteOk; +} + +uint8_t* SingleArenaBufferAllocator::AllocatePersistentBuffer( + size_t size, size_t alignment) { + uint8_t* const aligned_result = AlignPointerDown(tail_ - size, alignment); + if (aligned_result < head_) { +#ifndef TF_LITE_STRIP_ERROR_STRINGS + const size_t missing_memory = head_ - aligned_result; + MicroPrintf( + "Failed to allocate tail memory. Requested: %u, " + "available %u, missing: %u", + size, size - missing_memory, missing_memory); +#endif + return nullptr; + } + tail_ = aligned_result; + return aligned_result; +} + +uint8_t* SingleArenaBufferAllocator::AllocateTemp(size_t size, + size_t alignment) { + uint8_t* const aligned_result = AlignPointerUp(temp_, alignment); + const size_t available_memory = tail_ - aligned_result; + if (available_memory < size) { + MicroPrintf( + "Failed to allocate temp memory. Requested: %u, " + "available %u, missing: %u", + size, available_memory, size - available_memory); + return nullptr; + } + temp_ = aligned_result + size; + temp_buffer_ptr_check_sum_ ^= (reinterpret_cast(aligned_result)); + temp_buffer_count_++; + return aligned_result; +} + +void SingleArenaBufferAllocator::DeallocateTemp(uint8_t* temp_buf) { + temp_buffer_ptr_check_sum_ ^= (reinterpret_cast(temp_buf)); + temp_buffer_count_--; +} + +bool SingleArenaBufferAllocator::IsAllTempDeallocated() { + if (temp_buffer_count_ != 0 || temp_buffer_ptr_check_sum_ != 0) { + MicroPrintf( + "Number of allocated temp buffers: %d. Checksum passing status: %d", + temp_buffer_count_, !temp_buffer_ptr_check_sum_); + return false; + } + return true; +} + +TfLiteStatus SingleArenaBufferAllocator::ResetTempAllocations() { + // TODO(b/209453859): enable error check based on IsAllTempDeallocated after + // all AllocateTemp have been paird with DeallocateTemp + if (!IsAllTempDeallocated()) { + MicroPrintf( + "All temp buffers must be freed before calling ResetTempAllocations()"); + return kTfLiteError; + } + temp_ = head_; + return kTfLiteOk; +} + +uint8_t* SingleArenaBufferAllocator::GetOverlayMemoryAddress() const { + return buffer_head_; +} + +size_t SingleArenaBufferAllocator::GetNonPersistentUsedBytes() const { + return std::max(head_ - buffer_head_, temp_ - buffer_head_); +} + +size_t SingleArenaBufferAllocator::GetPersistentUsedBytes() const { + return buffer_tail_ - tail_; +} + +size_t SingleArenaBufferAllocator::GetAvailableMemory(size_t alignment) const { + uint8_t* const aligned_temp = AlignPointerUp(temp_, alignment); + uint8_t* const aligned_tail = AlignPointerDown(tail_, alignment); + return aligned_tail - aligned_temp; +} + +size_t SingleArenaBufferAllocator::GetUsedBytes() const { + return GetPersistentUsedBytes() + GetNonPersistentUsedBytes(); +} + +size_t SingleArenaBufferAllocator::GetBufferSize() const { + return buffer_tail_ - buffer_head_; +} + +uint8_t* SingleArenaBufferAllocator::head() const { return head_; } + +uint8_t* SingleArenaBufferAllocator::tail() const { return tail_; } + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h new file mode 100644 index 000000000..68aa35a1a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h @@ -0,0 +1,165 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_SINGLE_ARENA_BUFFER_ALLOCATOR_H_ +#define TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_SINGLE_ARENA_BUFFER_ALLOCATOR_H_ + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/micro/arena_allocator/ibuffer_allocator.h" +#include "tensorflow/lite/micro/compatibility.h" + +namespace tflite { + +// TODO(petewarden): This allocator never frees up or reuses any memory, even +// though we have enough information about lifetimes of the tensors to do so. +// This makes it pretty wasteful, so we should use a more intelligent method. +class SingleArenaBufferAllocator : public INonPersistentBufferAllocator, + public IPersistentBufferAllocator { + public: + // TODO(b/246776144): Will be removed with http://b/246776144 + SingleArenaBufferAllocator(ErrorReporter* error_reporter, + uint8_t* buffer_head, uint8_t* buffer_tail) + : SingleArenaBufferAllocator(buffer_head, buffer_tail) { + (void)error_reporter; + } + SingleArenaBufferAllocator(ErrorReporter* error_reporter, uint8_t* buffer, + size_t buffer_size) + : SingleArenaBufferAllocator(buffer, buffer_size) { + (void)error_reporter; + } + + // TODO(b/157615197): Cleanup constructors/destructor and use factory + // functions. + SingleArenaBufferAllocator(uint8_t* buffer_head, uint8_t* buffer_tail); + SingleArenaBufferAllocator(uint8_t* buffer, size_t buffer_size); + virtual ~SingleArenaBufferAllocator(); + + // TODO(b/246776144): Will be removed with http://b/246776144 + static SingleArenaBufferAllocator* Create(ErrorReporter* error_reporter, + uint8_t* buffer_head, + size_t buffer_size) { + (void)error_reporter; + return SingleArenaBufferAllocator::Create(buffer_head, buffer_size); + } + + // Creates a new SingleArenaBufferAllocator from a given buffer head and size. + static SingleArenaBufferAllocator* Create(uint8_t* buffer_head, + size_t buffer_size); + + // Resizes a buffer that is previously returned by the + // AllocateResizableBuffer. In current implementation, it Adjusts the head + // (lowest address and moving upwards) memory allocation to a given size. + // Calls to this method will also invalidate all temporary allocation values + // (it sets the location of temp space at the end of the head section). This + // call will fail if a chain of allocations through AllocateTemp() have not + // been cleaned up with a call to ResetTempAllocations(). + virtual TfLiteStatus ResizeBuffer(uint8_t* resizable_buf, size_t size, + size_t alignment) override; + + // Returns a buffer that is resizable viable ResizeBuffer(). Only one + // resizable buffer is currently supported. + virtual uint8_t* AllocateResizableBuffer(size_t size, + size_t alignment) override; + + // Frees up the memory occupied by the resizable buffer + virtual TfLiteStatus DeallocateResizableBuffer( + uint8_t* resizable_buf) override; + + // Reserves the non-persistent memory that is planned by the memory planner. + virtual TfLiteStatus ReserveNonPersistentOverlayMemory( + size_t size, size_t alignment) override; + + // Allocates persistent memory starting at the tail of the arena (highest + // address and moving downwards). + virtual uint8_t* AllocatePersistentBuffer(size_t size, + size_t alignment) override; + + // Allocates a temporary buffer from the head of the arena (lowest address and + // moving upwards) but does not update the actual head allocation size or + // position. The returned buffer is guaranteed until either + // ResetTempAllocations() is called or another call to AllocateFromHead(). + // Repeat calls to this function will create a chain of temp allocations. All + // calls to AllocateTemp() must end with a call to ResetTempAllocations(). If + // AllocateFromHead() is called before a call to ResetTempAllocations(), it + // will fail with an error message. + virtual uint8_t* AllocateTemp(size_t size, size_t alignment) override; + + // Signals that a temporary buffer is no longer needed. This is currently for + // book-keeping purpose and the memory region are not immediately available + // for re-use. The deallocated memory region are only reclaimed after + // ResetTempAllocations is called as it is right now. + virtual void DeallocateTemp(uint8_t* buf) override; + + // Returns true if all temporary buffers are already deallocated. + virtual bool IsAllTempDeallocated() override; + + // Resets a chain of temporary allocations back to the current head of the + // arena (lowest address). + virtual TfLiteStatus ResetTempAllocations() override; + + // Returns a pointer to the buffer currently assigned to the head section. + // This buffer is set by calling SetHeadSize(). + uint8_t* GetOverlayMemoryAddress() const override; + + // Returns the size of the head section in bytes. + size_t GetNonPersistentUsedBytes() const override; + + // Returns the size of all allocations in the tail section in bytes. + size_t GetPersistentUsedBytes() const override; + + // Returns the number of bytes available with a given alignment. This number + // takes in account any temporary allocations. + size_t GetAvailableMemory(size_t alignment) const override; + + // Returns the number of used bytes in the allocator. This number takes in + // account any temporary allocations. + size_t GetUsedBytes() const; + + TF_LITE_REMOVE_VIRTUAL_DELETE + + protected: + // Returns a pointer to the current end of the head buffer. + uint8_t* head() const; + + // Returns a pointer to the current end of the tail buffer. + uint8_t* tail() const; + + private: + size_t GetBufferSize() const; + uint8_t* buffer_head_; + uint8_t* buffer_tail_; + uint8_t* head_; + uint8_t* tail_; + uint8_t* temp_; + + // The combination of the checksum of outstanding temporary buffer pointers + // AND the count of outstanding temporary buffer provide a low cost mechanism + // to audit temporary buffers' allocation and deallocation. + // + // XOR Check sum for outstanding temp buffers. + // If all temp buffers are deallocated OR no temp buffers are allocated, + // temp_buffer_ptr_check_sum_ == nullptr. + intptr_t temp_buffer_ptr_check_sum_ = 0; + // Count of outstanding temp buffers. + int temp_buffer_count_ = 0; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_SINGLE_ARENA_BUFFER_ALLOCATOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/compatibility.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/compatibility.h new file mode 100644 index 000000000..983de7d14 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/compatibility.h @@ -0,0 +1,32 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_COMPATIBILITY_H_ +#define TENSORFLOW_LITE_MICRO_COMPATIBILITY_H_ + +// C++ will automatically create class-specific delete operators for virtual +// objects, which by default call the global delete function. For embedded +// applications we want to avoid this, and won't be calling new/delete on these +// objects, so we need to override the default implementation with one that does +// nothing to avoid linking in ::delete(). +// This macro needs to be included in all subclasses of a virtual base class in +// the private section. +#ifdef ARDUINO +#define TF_LITE_REMOVE_VIRTUAL_DELETE \ + void operator delete(void* p) {} +#else +#define TF_LITE_REMOVE_VIRTUAL_DELETE +#endif + +#endif // TENSORFLOW_LITE_MICRO_COMPATIBILITY_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/debug_log.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/debug_log.cpp new file mode 100644 index 000000000..630143ce6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/debug_log.cpp @@ -0,0 +1,30 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +// This file is empty to ensure that a specialized implementation of +// debug_log.h is used (instead of the default implementation from +// tensorflow/lite/micro/debug_log.cc). +// +// The actual target-specific implementation of debug_log.h is in +// system_setup.cc since that allows us to consolidate all the target-specific +// specializations into one source file. + +#include +#include "tensorflow/lite/micro/debug_log.h" + +extern void TFL_Log(char* s); + +void DebugLog(const char* s) { + TFL_Log((char*)s); +}; \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/debug_log.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/debug_log.h new file mode 100644 index 000000000..c2840d0f4 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/debug_log.h @@ -0,0 +1,31 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_DEBUG_LOG_H_ +#define TENSORFLOW_LITE_MICRO_DEBUG_LOG_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// This function should be implemented by each target platform, and provide a +// way for strings to be output to some text stream. For more information, see +// tensorflow/lite/micro/debug_log.cc. +void DebugLog(const char* s); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // TENSORFLOW_LITE_MICRO_DEBUG_LOG_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/fake_micro_context.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/fake_micro_context.cpp new file mode 100644 index 000000000..81f74ae36 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/fake_micro_context.cpp @@ -0,0 +1,106 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/fake_micro_context.h" + +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/micro_allocator.h" +#include "tensorflow/lite/micro/micro_arena_constants.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { +// Dummy static variables to allow creation of dummy MicroAllocator. +// All tests are guarateed to run serially. +static constexpr int KDummyTensorArenaSize = 256; +static uint8_t dummy_tensor_arena[KDummyTensorArenaSize]; +} // namespace + +FakeMicroContext::FakeMicroContext(TfLiteTensor* tensors, + SingleArenaBufferAllocator* allocator, + MicroGraph* micro_graph) + : MicroContext( + MicroAllocator::Create(dummy_tensor_arena, KDummyTensorArenaSize), + nullptr, micro_graph), + tensors_(tensors), + allocator_(allocator) {} + +TfLiteTensor* FakeMicroContext::AllocateTempTfLiteTensor(int tensor_index) { + allocated_tensor_count_++; + return &tensors_[tensor_index]; +} + +void FakeMicroContext::DeallocateTempTfLiteTensor(TfLiteTensor* tensor) { + allocated_tensor_count_--; +} + +bool FakeMicroContext::IsAllTempTfLiteTensorDeallocated() { + return !allocated_tensor_count_; +} + +TfLiteEvalTensor* FakeMicroContext::GetEvalTensor(int tensor_index) { + TfLiteEvalTensor* eval_tensor = + reinterpret_cast(allocator_->AllocateTemp( + sizeof(TfLiteEvalTensor), alignof(TfLiteEvalTensor))); + TFLITE_DCHECK(eval_tensor != nullptr); + + // In unit tests, the TfLiteTensor pointer contains the source of truth for + // buffers and values: + eval_tensor->data = tensors_[tensor_index].data; + eval_tensor->dims = tensors_[tensor_index].dims; + eval_tensor->type = tensors_[tensor_index].type; + return eval_tensor; +} + +void* FakeMicroContext::AllocatePersistentBuffer(size_t bytes) { + // FakeMicroContext use SingleArenaBufferAllocator, which does not + // automatically apply the buffer alignment like MicroAllocator. The buffer + // alignment is potentially wasteful but allows the fake_micro_context to work + // correctly with optimized kernels. + return allocator_->AllocatePersistentBuffer(bytes, + MicroArenaBufferAlignment()); +} + +TfLiteStatus FakeMicroContext::RequestScratchBufferInArena(size_t bytes, + int* buffer_index) { + TFLITE_DCHECK(buffer_index != nullptr); + + if (scratch_buffer_count_ == kNumScratchBuffers_) { + MicroPrintf("Exceeded the maximum number of scratch tensors allowed (%d).", + kNumScratchBuffers_); + return kTfLiteError; + } + + // For tests, we allocate scratch buffers from the tail and keep them around + // for the lifetime of model. This means that the arena size in the tests will + // be more than what we would have if the scratch buffers could share memory. + scratch_buffers_[scratch_buffer_count_] = + allocator_->AllocatePersistentBuffer(bytes, MicroArenaBufferAlignment()); + TFLITE_DCHECK(scratch_buffers_[scratch_buffer_count_] != nullptr); + + *buffer_index = scratch_buffer_count_++; + return kTfLiteOk; +} + +void* FakeMicroContext::GetScratchBuffer(int buffer_index) { + TFLITE_DCHECK(scratch_buffer_count_ <= kNumScratchBuffers_); + if (buffer_index >= scratch_buffer_count_) { + return nullptr; + } + return scratch_buffers_[buffer_index]; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/fake_micro_context.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/fake_micro_context.h new file mode 100644 index 000000000..31b39d384 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/fake_micro_context.h @@ -0,0 +1,56 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_FAKE_MICRO_CONTEXT_H_ +#define TENSORFLOW_LITE_MICRO_FAKE_MICRO_CONTEXT_H_ + +#include "tensorflow/lite/micro/micro_context.h" +#include "tensorflow/lite/micro/micro_graph.h" + +namespace tflite { +// A fake of MicroContext for kernel util tests. +class FakeMicroContext : public MicroContext { + public: + FakeMicroContext(TfLiteTensor* tensors, SingleArenaBufferAllocator* allocator, + MicroGraph* micro_graph); + + void* AllocatePersistentBuffer(size_t bytes) override; + TfLiteStatus RequestScratchBufferInArena(size_t bytes, + int* buffer_index) override; + void* GetScratchBuffer(int buffer_index) override; + + TfLiteTensor* AllocateTempTfLiteTensor(int tensor_index) override; + void DeallocateTempTfLiteTensor(TfLiteTensor* tensor) override; + bool IsAllTempTfLiteTensorDeallocated(); + + TfLiteEvalTensor* GetEvalTensor(int tensor_index) override; + + private: + static constexpr int kNumScratchBuffers_ = 12; + + int scratch_buffer_count_ = 0; + uint8_t* scratch_buffers_[kNumScratchBuffers_]; + + TfLiteTensor* tensors_; + int allocated_tensor_count_ = 0; + + SingleArenaBufferAllocator* allocator_; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_FAKE_MICRO_CONTEXT_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/flatbuffer_utils.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/flatbuffer_utils.cpp new file mode 100644 index 000000000..9996172ba --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/flatbuffer_utils.cpp @@ -0,0 +1,84 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/flatbuffer_utils.h" + +namespace tflite { + +FlexbufferWrapper::FlexbufferWrapper(const uint8_t* buffer, size_t size) + : flexbuffers::Vector(flexbuffers::GetRoot(buffer, size).AsVector()) {} + +int64_t FlexbufferWrapper::ElementAsInt64(size_t i) const { + const uint8_t* elem = data_ + i * byte_width_; + return ::flexbuffers::ReadInt64(elem, byte_width_); +} + +uint64_t FlexbufferWrapper::ElementAsUInt64(size_t i) const { + const uint8_t* elem = data_ + i * byte_width_; + return ::flexbuffers::ReadUInt64(elem, byte_width_); +} + +int32_t FlexbufferWrapper::ElementAsInt32(size_t i) const { + return static_cast(ElementAsInt64(i)); +} + +bool FlexbufferWrapper::ElementAsBool(size_t i) const { + return static_cast(ElementAsUInt64(i)); +} + +double FlexbufferWrapper::ElementAsDouble(size_t i) const { + const uint8_t* elem = data_ + i * byte_width_; + return ::flexbuffers::ReadDouble(elem, byte_width_); +} + +float FlexbufferWrapper::ElementAsFloat(size_t i) const { + return static_cast(FlexbufferWrapper::ElementAsDouble(i)); +} + +// TODO(b/192589496): Ops must always be there. Remove this function when fixed +uint32_t NumSubgraphOperators(const SubGraph* subgraph) { + if (subgraph->operators() != nullptr) { + return subgraph->operators()->size(); + } else { + return 0; + } +} +// TODO(b/192589496): Ops must always be there. Remove this function when fixed +uint32_t NumSubgraphOperators(const Model* model, int subgraph_idx) { + const SubGraph* subgraph = model->subgraphs()->Get(subgraph_idx); + return NumSubgraphOperators(subgraph); +} + +TfLiteIntArray* FlatBufferVectorToTfLiteTypeArray( + const flatbuffers::Vector* flatbuffer_array) { + // On little-endian machines, TfLiteIntArray happens to have the same memory + // layout as flatbuffers:Vector, so we can reinterpret_cast the + // flatbuffer vector and avoid a copy and malloc. + // TODO(b/188459715): audit this usage of const_cast. + return const_cast( + reinterpret_cast(flatbuffer_array)); +} + +TfLiteFloatArray* FlatBufferVectorToTfLiteTypeArray( + const flatbuffers::Vector* flatbuffer_array) { + // On little-endian machines, TfLiteFloatArray happens to have the same memory + // layout as flatbuffers:Vector, so we can reinterpret_cast the + // flatbuffer vector and avoid a copy and malloc. + // TODO(b/188459715): audit this usage of const_cast. + return const_cast( + reinterpret_cast(flatbuffer_array)); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/flatbuffer_utils.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/flatbuffer_utils.h new file mode 100644 index 000000000..e3f421017 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/flatbuffer_utils.h @@ -0,0 +1,65 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef THIRD_PARTY_TFLITE_MICRO_TENSORFLOW_LITE_MICRO_FLATBUFFER_UTILS_H_ +#define THIRD_PARTY_TFLITE_MICRO_TENSORFLOW_LITE_MICRO_FLATBUFFER_UTILS_H_ + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "third_party/flatbuffers/include/flatbuffers/flexbuffers.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +// Kernels use flexbuffers::Map to pack their init parameters in a tflite file, +// with the parameter names as map keys and the parameter values as the +// corresponding map values. +// Accessing the map values using the flexbuffers:Map class is inline heavy, +// which can cause the code size to bloat beyond what's reasonable for a micro +// application. Use this class instead, when possible. +// FlexbufferWrapper takes advantage of the following properties of +// flexbuffers::Map: +// 1. It can be viewed as a flexbuffers::Vector of the values. +// 2. The values in the vector are ordered alphabetically by their keys. +// 3. All integer and Boolean values are stored as 64-bit numbers. +// 4. All floating point values are stored as double precision numbers. +// The properties are mentioned in the flexbuffers docs, but we rely on +// a unit test to catch design changes. +class FlexbufferWrapper : public flexbuffers::Vector { + public: + // Construct with a serialized flexbuffer 'buffer' of 'size' bytes + explicit FlexbufferWrapper(const uint8_t* buffer, size_t size); + int64_t ElementAsInt64(size_t i) const; + uint64_t ElementAsUInt64(size_t i) const; + int32_t ElementAsInt32(size_t i) const; + bool ElementAsBool(size_t i) const; + double ElementAsDouble(size_t i) const; + float ElementAsFloat(size_t i) const; +}; + +// Return the number of operators in a subgraph tflite +uint32_t NumSubgraphOperators(const SubGraph* subgraph); +uint32_t NumSubgraphOperators(const Model* model, int subgraph_idx); + +// Converts a flatbuffer array to a TfLiteArray. +// TODO(b/188459715): These function convert a const input to a non-const via a +// const_cast. It is unclear exactly why this is required. +TfLiteIntArray* FlatBufferVectorToTfLiteTypeArray( + const flatbuffers::Vector* flatbuffer_array); +TfLiteFloatArray* FlatBufferVectorToTfLiteTypeArray( + const flatbuffers::Vector* flatbuffer_array); + +} // namespace tflite + +#endif // THIRD_PARTY_TFLITE_MICRO_TENSORFLOW_LITE_MICRO_FLATBUFFER_UTILS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activation_utils.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activation_utils.h new file mode 100644 index 000000000..95ecc26dd --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activation_utils.h @@ -0,0 +1,57 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_ACTIVATION_UTILS_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_ACTIVATION_UTILS_H_ + +#include +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/max.h" +#include "tensorflow/lite/kernels/internal/min.h" + +namespace tflite { +namespace ops { +namespace micro { + +// Returns the floating point value for a fused activation: +inline float ActivationValFloat(TfLiteFusedActivation act, float a) { + switch (act) { + case kTfLiteActNone: + return a; + case kTfLiteActRelu: + return TfLiteMax(0.0f, a); + case kTfLiteActReluN1To1: + return TfLiteMax(-1.0f, TfLiteMin(a, 1.0f)); + case kTfLiteActRelu6: + return TfLiteMax(0.0f, TfLiteMin(a, 6.0f)); + case kTfLiteActTanh: + return std::tanh(a); + case kTfLiteActSignBit: + return std::signbit(a); + case kTfLiteActSigmoid: + return 1.0f / (1.0f + std::exp(-a)); + } + return 0.0f; // To indicate an unsupported activation (i.e. when a new fused + // activation is added to the enum and not handled here). +} + +} // namespace micro +} // namespace ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_ACTIVATION_UTILS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations.cc new file mode 100644 index 000000000..716dd6fc7 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations.cc @@ -0,0 +1,120 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/activations.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { + +void* ReluInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(ReluOpData)); +} + +TfLiteStatus ReluEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const ReluOpData& data = *(static_cast(node->user_data)); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kActivationsInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kActivationsOutputTensor); + + switch (input->type) { + case kTfLiteFloat32: { + ReluFloat(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + + return kTfLiteOk; + } + case kTfLiteInt8: { + tflite::ReluQuantized(data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } + default: { + MicroPrintf("Only float32 is supported currently, got %s", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + } +} + +void* Relu6Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(Relu6OpData)); +} + +TfLiteStatus Relu6Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const Relu6OpData& data = *(static_cast(node->user_data)); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kActivationsInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kActivationsOutputTensor); + + switch (input->type) { + case kTfLiteFloat32: { + Relu6Float(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + + return kTfLiteOk; + } + case kTfLiteInt8: { + Relu6Quantized(data.zero_int8, data.six_int8, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } + default: { + MicroPrintf("Only float32 is supported currently, got %s", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + } +} + +} // namespace + +TfLiteRegistration Register_RELU() { + return tflite::micro::RegisterOp(ReluInit, ReluPrepare, ReluEval); +} + +TfLiteRegistration Register_RELU6() { + return tflite::micro::RegisterOp(Relu6Init, Relu6Prepare, Relu6Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations.h new file mode 100644 index 000000000..e953f0e0d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations.h @@ -0,0 +1,63 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_ACTIVATIONS_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_ACTIVATIONS_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +extern const int kActivationsInputTensor; +extern const int kActivationsOutputTensor; + +struct ReluOpData { + ReluParams params; +}; + +struct Relu6OpData { + int8_t six_int8; + int8_t zero_int8; +}; + +void ReluQuantized(const ReluOpData& data, const RuntimeShape& input_shape, + const RuntimeShape& output_shape, const int8_t* input_data, + int8_t* output_data); + +template +void CalculateReluOpData(const TfLiteTensor* input, TfLiteTensor* output, + ReluOpData* data); + +void ReluFloat(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data); + +void Relu6Float(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data); + +void Relu6Quantized(int8_t lower, int8_t upper, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& output_shape, + int8_t* output_data); + +TfLiteStatus ReluPrepare(TfLiteContext* context, TfLiteNode* node); + +TfLiteStatus Relu6Prepare(TfLiteContext* context, TfLiteNode* node); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_ACTIVATIONS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations_common.cc new file mode 100644 index 000000000..4403edc87 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/activations_common.cc @@ -0,0 +1,158 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/activations.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +const int kActivationsInputTensor = 0; +const int kActivationsOutputTensor = 0; + +void ReluQuantized(const ReluOpData& data, const RuntimeShape& input_shape, + const RuntimeShape& output_shape, const int8_t* input_data, + int8_t* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + const int32_t val = static_cast(input_data[i]); + int32_t clamped = + data.params.output_offset + + MultiplyByQuantizedMultiplier(val - data.params.input_offset, + data.params.output_multiplier, + data.params.output_shift); + clamped = std::max(data.params.quantized_activation_min, clamped); + clamped = std::min(data.params.quantized_activation_max, clamped); + output_data[i] = static_cast(clamped); + } +} + +template +void CalculateReluOpData(const TfLiteTensor* input, TfLiteTensor* output, + ReluOpData* data) { + float act_min = 0.0; + float act_max = std::numeric_limits::infinity(); + double real_multiplier = static_cast(input->params.scale) / + static_cast(output->params.scale); + + const RuntimeShape input_shape = GetTensorShape(input); + const RuntimeShape output_shape = GetTensorShape(output); + + QuantizeMultiplier(real_multiplier, &data->params.output_multiplier, + &data->params.output_shift); + + data->params.quantized_activation_min = std::max( + static_cast(std::numeric_limits::min()), + output->params.zero_point + + static_cast(roundf(act_min / output->params.scale))); + data->params.quantized_activation_max = + act_max == std::numeric_limits::infinity() + ? static_cast(std::numeric_limits::max()) + : std::min(static_cast(std::numeric_limits::max()), + output->params.zero_point + + static_cast( + roundf(act_max / output->params.scale))); + data->params.input_offset = input->params.zero_point; + data->params.output_offset = output->params.zero_point; +} + +void ReluFloat(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + const float val = input_data[i]; + const float lower = 0.0f; + const float clamped = val < lower ? lower : val; + output_data[i] = clamped; + } +} + +void Relu6Float(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + const float val = input_data[i]; + const float upper = 6.0f; + const float lower = 0.0f; + const float clamped = val > upper ? upper : val < lower ? lower : val; + output_data[i] = clamped; + } +} + +void Relu6Quantized(int8_t lower, int8_t upper, const RuntimeShape& input_shape, + const int8_t* input_data, const RuntimeShape& output_shape, + int8_t* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + const int8_t val = input_data[i]; + const int8_t clamped = val > upper ? upper : val < lower ? lower : val; + output_data[i] = clamped; + } +} + +TfLiteStatus ReluPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + ReluOpData* data = static_cast(node->user_data); + + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kActivationsInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kActivationsOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + if (input->type == kTfLiteInt8) { + CalculateReluOpData(input, output, data); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Relu6Prepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + Relu6OpData* data = static_cast(node->user_data); + + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kActivationsInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + + if (input->type == kTfLiteInt8) { + data->six_int8 = FloatToQuantizedType(6.0f, input->params.scale, + input->params.zero_point); + data->zero_int8 = input->params.zero_point; + } + + micro_context->DeallocateTempTfLiteTensor(input); + + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add.cc new file mode 100644 index 000000000..81b3b9c9b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add.cc @@ -0,0 +1,165 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/add.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/add.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/add.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +void EvalAdd(TfLiteContext* context, TfLiteNode* node, TfLiteAddParams* params, + const OpDataAdd* data, const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params; + SetActivationParams(data->output_activation_min_f32, + data->output_activation_max_f32, &op_params); + if (data->requires_broadcast) { + reference_ops::BroadcastAdd4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_ops::Add(op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } +} + +TfLiteStatus EvalAddQuantized(TfLiteContext* context, TfLiteNode* node, + TfLiteAddParams* params, const OpDataAdd* data, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params; + op_params.left_shift = data->left_shift; + op_params.input1_offset = data->input1_offset; + op_params.input1_multiplier = data->input1_multiplier; + op_params.input1_shift = data->input1_shift; + op_params.input2_offset = data->input2_offset; + op_params.input2_multiplier = data->input2_multiplier; + op_params.input2_shift = data->input2_shift; + op_params.output_offset = data->output_offset; + op_params.output_multiplier = data->output_multiplier; + op_params.output_shift = data->output_shift; + SetActivationParams(data->output_activation_min, data->output_activation_max, + &op_params); + bool need_broadcast = reference_ops::ProcessBroadcastShapes( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), &op_params); + + switch (output->type) { + case kTfLiteInt8: { + if (need_broadcast) { + reference_integer_ops::BroadcastAdd4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_integer_ops::Add( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } + break; + } + case kTfLiteInt16: { + if (need_broadcast) { + reference_ops::BroadcastAdd4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_ops::Add(op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + false); + } + break; + } + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(output->type), output->type); + return kTfLiteError; + } + + return kTfLiteOk; +} + +void* AddInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataAdd)); +} + +TfLiteStatus AddEval(TfLiteContext* context, TfLiteNode* node) { + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataAdd* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kAddInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kAddInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kAddOutputTensor); + + if (output->type == kTfLiteFloat32) { + EvalAdd(context, node, params, data, input1, input2, output); + } else if (output->type == kTfLiteInt8 || output->type == kTfLiteInt16) { + TF_LITE_ENSURE_OK(context, EvalAddQuantized(context, node, params, data, + input1, input2, output)); + } else { + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(output->type), + output->type); + return kTfLiteError; + } + + return kTfLiteOk; +} + +TfLiteRegistration Register_ADD() { + return tflite::micro::RegisterOp(AddInit, AddPrepare, AddEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add.h new file mode 100644 index 000000000..e2e5d23ba --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add.h @@ -0,0 +1,77 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_ADD_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_ADD_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +extern const int kAddInputTensor1; +extern const int kAddInputTensor2; +extern const int kAddOutputTensor; + +struct OpDataAdd { + bool requires_broadcast; + + // These fields are used in both the general 8-bit -> 8bit quantized path, + // and the special 16-bit -> 16bit quantized path + int input1_shift; + int input2_shift; + int32_t output_activation_min; + int32_t output_activation_max; + + // These fields are used only in the general 8-bit -> 8bit quantized path + int32_t input1_multiplier; + int32_t input2_multiplier; + int32_t output_multiplier; + int output_shift; + int left_shift; + int32_t input1_offset; + int32_t input2_offset; + int32_t output_offset; + + // Used only for float evals: + float output_activation_min_f32; + float output_activation_max_f32; +}; + +TfLiteStatus CalculateOpDataAdd(TfLiteContext* context, TfLiteAddParams* params, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + TfLiteTensor* output, OpDataAdd* data); + +TfLiteStatus AddPrepare(TfLiteContext* context, TfLiteNode* node); + +// Generic must define registration function. +TfLiteRegistration Register_ADD(); + +#if defined(CMSIS_NN) +TfLiteRegistration Register_ADD_INT8(); + +TfLiteRegistration Register_ADD_INT16(); +#else +// Fallback registration +inline TfLiteRegistration Register_ADD_INT8() { return Register_ADD(); } + +inline TfLiteRegistration Register_ADD_INT16() { return Register_ADD(); } +#endif +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_ADD_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add_common.cc new file mode 100644 index 000000000..b285b800c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add_common.cc @@ -0,0 +1,106 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/add.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/add.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/add.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" + +namespace tflite { + +const int kAddInputTensor1 = 0; +const int kAddInputTensor2 = 1; +const int kAddOutputTensor = 0; + +TfLiteStatus CalculateOpDataAdd(TfLiteContext* context, TfLiteAddParams* params, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + TfLiteTensor* output, OpDataAdd* data) { + data->requires_broadcast = !HaveSameShapes(input1, input2); + + if (output->type == kTfLiteInt8 || output->type == kTfLiteInt16) { + // 8bit -> 8bit general quantized path, with general rescalings + data->input1_offset = -input1->params.zero_point; + data->input2_offset = -input2->params.zero_point; + data->output_offset = output->params.zero_point; + data->left_shift = (output->type == kTfLiteInt16) ? 15 : 20; + const double twice_max_input_scale = + 2 * static_cast( + std::max(input1->params.scale, input2->params.scale)); + const double real_input1_multiplier = + static_cast(input1->params.scale) / twice_max_input_scale; + const double real_input2_multiplier = + static_cast(input2->params.scale) / twice_max_input_scale; + const double real_output_multiplier = + twice_max_input_scale / + ((1 << data->left_shift) * static_cast(output->params.scale)); + + QuantizeMultiplierSmallerThanOneExp( + real_input1_multiplier, &data->input1_multiplier, &data->input1_shift); + + QuantizeMultiplierSmallerThanOneExp( + real_input2_multiplier, &data->input2_multiplier, &data->input2_shift); + + QuantizeMultiplierSmallerThanOneExp( + real_output_multiplier, &data->output_multiplier, &data->output_shift); + + TF_LITE_ENSURE_STATUS(CalculateActivationRangeQuantized( + context, params->activation, output, &data->output_activation_min, + &data->output_activation_max)); + } else if (output->type == kTfLiteFloat32) { + CalculateActivationRange(params->activation, + &data->output_activation_min_f32, + &data->output_activation_max_f32); + } + + return kTfLiteOk; +} + +TfLiteStatus AddPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input1 = + micro_context->AllocateTempInputTensor(node, kAddInputTensor1); + TF_LITE_ENSURE(context, input1 != nullptr); + TfLiteTensor* input2 = + micro_context->AllocateTempInputTensor(node, kAddInputTensor2); + TF_LITE_ENSURE(context, input2 != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kAddOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + OpDataAdd* data = static_cast(node->user_data); + auto* params = reinterpret_cast(node->builtin_data); + + TF_LITE_ENSURE_STATUS( + CalculateOpDataAdd(context, params, input1, input2, output, data)); + + micro_context->DeallocateTempTfLiteTensor(input1); + micro_context->DeallocateTempTfLiteTensor(input2); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add_n.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add_n.cc new file mode 100644 index 000000000..1139e1a95 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/add_n.cc @@ -0,0 +1,215 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/add_n.h" + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor0 = 0; +constexpr int kOutputTensor = 0; + +constexpr int kAddNIntegerShift = 20; + +// only used with INT8 tensors +struct OpData { + int32_t output_activation_min; + int32_t output_activation_max; + int32_t input_offset; + int32_t output_offset; + int32_t input_multiplier; + int32_t output_multiplier; + int input_shift; + int output_shift; + int left_shift; + int scratch_index; +}; + +TfLiteStatus CalculateOpData(TfLiteContext* context, TfLiteNode* node) { + int num_inputs = NumInputs(node); + TF_LITE_ENSURE(context, num_inputs >= 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input_tensor_first = + micro_context->AllocateTempInputTensor(node, kInputTensor0); + TF_LITE_ENSURE(context, input_tensor_first != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + // Check that all tensors have the same shape and type. + TF_LITE_ENSURE_TYPES_EQ(context, output->type, input_tensor_first->type); + for (int i = kInputTensor0 + 1; i < num_inputs; ++i) { + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, i); + TF_LITE_ENSURE(context, input != nullptr); + TF_LITE_ENSURE(context, HaveSameShapes(input_tensor_first, input)); + TF_LITE_ENSURE_TYPES_EQ(context, input_tensor_first->type, input->type); + + // Check that all INT8 input tensors have the same zero-point and scale. + if (input_tensor_first->type == kTfLiteInt8) { + TF_LITE_ENSURE(context, input_tensor_first->params.zero_point == + input->params.zero_point); + TF_LITE_ENSURE(context, + input_tensor_first->params.scale == input->params.scale); + } + + micro_context->DeallocateTempTfLiteTensor(input); + } + + if (output->type == kTfLiteFloat32) { + // Allocate scratch buffer space for pointer to each tensor's data + // and store the scratch buffer index in the node's user_data + int scratch_index; + size_t scratch_size = sizeof(float*) * num_inputs; + TF_LITE_ENSURE_OK(context, context->RequestScratchBufferInArena( + context, scratch_size, &scratch_index)); + node->user_data = + reinterpret_castuser_data)>(scratch_index); + } else if (output->type == kTfLiteInt8) { + node->user_data = + context->AllocatePersistentBuffer(context, sizeof(OpData)); + OpData* data = static_cast(node->user_data); + + // Allocate scratch buffer space for pointer to each tensor's data + // and store the scratch buffer index in OpData + size_t scratch_size = sizeof(int8_t*) * num_inputs; + TF_LITE_ENSURE_OK( + context, context->RequestScratchBufferInArena(context, scratch_size, + &data->scratch_index)); + + // 8bit -> 8bit general quantized path, with general rescalings + data->input_offset = -input_tensor_first->params.zero_point; + data->output_offset = output->params.zero_point; + data->left_shift = kAddNIntegerShift; + const double twice_max_input_scale = + 2 * static_cast(input_tensor_first->params.scale); + const double real_input_multiplier = + static_cast(input_tensor_first->params.scale) / + twice_max_input_scale; + const double real_output_multiplier = + twice_max_input_scale / + ((1 << data->left_shift) * static_cast(output->params.scale)); + + QuantizeMultiplierSmallerThanOneExp( + real_input_multiplier, &data->input_multiplier, &data->input_shift); + + QuantizeMultiplierSmallerThanOneExp( + real_output_multiplier, &data->output_multiplier, &data->output_shift); + + TF_LITE_ENSURE_STATUS(CalculateActivationRangeQuantized( + context, kTfLiteActNone, output, &data->output_activation_min, + &data->output_activation_max)); + } else { + MicroPrintf("ADD_N only supports FLOAT32 and INT8, got %s.", + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + + micro_context->DeallocateTempTfLiteTensor(input_tensor_first); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + return CalculateOpData(context, node); +} + +template +inline const T** CopyInputsToScratchBuffer(TfLiteContext* context, + TfLiteNode* node, + const int scratch_index) { + int num_inputs = NumInputs(node); + void* scratch_buffer = context->GetScratchBuffer(context, scratch_index); + const T** all_inputs = static_cast(scratch_buffer); + for (int i = 0; i < num_inputs; i++) { + const TfLiteEvalTensor* next_input = + tflite::micro::GetEvalInput(context, node, kInputTensor0 + i); + all_inputs[i] = tflite::micro::GetTensorData(next_input); + } + + return all_inputs; +} + +template +void EvalAddN(TfLiteContext* context, TfLiteNode* node, + TfLiteEvalTensor* output) { + int num_inputs = NumInputs(node); + + int scratch_index = + static_cast(reinterpret_cast(node->user_data)); + const T** all_inputs = + CopyInputsToScratchBuffer(context, node, scratch_index); + + reference_ops::AddN(tflite::micro::GetTensorShape(output), num_inputs, + all_inputs, tflite::micro::GetTensorData(output)); +} + +template +void EvalAddNQuantized(TfLiteContext* context, TfLiteNode* node, + TfLiteEvalTensor* output) { + int num_inputs = NumInputs(node); + + OpData* data = static_cast(node->user_data); + const T** all_inputs = + CopyInputsToScratchBuffer(context, node, data->scratch_index); + + ArithmeticParams params; + params.left_shift = data->left_shift; + params.input1_offset = data->input_offset; + params.input1_multiplier = data->input_multiplier; + params.input1_shift = data->input_shift; + params.output_offset = data->output_offset; + params.output_multiplier = data->output_multiplier; + params.output_shift = data->output_shift; + SetActivationParams(data->output_activation_min, data->output_activation_max, + ¶ms); + + reference_ops::AddN(params, tflite::micro::GetTensorShape(output), num_inputs, + all_inputs, tflite::micro::GetTensorData(output)); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + if (output->type == kTfLiteFloat32) { + EvalAddN(context, node, output); + } else if (output->type == kTfLiteInt8) { + EvalAddNQuantized(context, node, output); + } else { + MicroPrintf("ADD_N only supports FLOAT32 and INT8, got %s.", + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_ADD_N() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/arg_min_max.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/arg_min_max.cc new file mode 100644 index 000000000..d0e433c5d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/arg_min_max.cc @@ -0,0 +1,116 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/arg_min_max.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/micro_utils.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace arg_min_max { + +constexpr int kInputTensor = 0; +constexpr int kAxis = 1; +constexpr int kOutputTensor = 0; + +template +inline void ArgMinMaxHelper(const RuntimeShape& input1_shape, + const T1* input1_data, const T3* input2_data, + const RuntimeShape& output_shape, T2* output_data, + bool is_arg_max) { + if (is_arg_max) { + reference_ops::ArgMinMax(input1_shape, input1_data, input2_data, + output_shape, output_data, micro::Greater()); + } else { + reference_ops::ArgMinMax(input1_shape, input1_data, input2_data, + output_shape, output_data, micro::Less()); + } +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node, bool is_arg_max) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + const TfLiteEvalTensor* axis = + tflite::micro::GetEvalInput(context, node, kAxis); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + +#define TF_LITE_ARG_MIN_MAX(data_type, axis_type, output_type) \ + ArgMinMaxHelper(tflite::micro::GetTensorShape(input), \ + tflite::micro::GetTensorData(input), \ + tflite::micro::GetTensorData(axis), \ + tflite::micro::GetTensorShape(output), \ + tflite::micro::GetTensorData(output), \ + is_arg_max) + if (axis->type == kTfLiteInt32) { + if (output->type == kTfLiteInt32) { + switch (input->type) { + case kTfLiteFloat32: + TF_LITE_ARG_MIN_MAX(float, int32_t, int32_t); + break; + case kTfLiteInt8: + TF_LITE_ARG_MIN_MAX(int8_t, int32_t, int32_t); + break; + default: + MicroPrintf( + "Only float32, uint8_t and int8_t are " + "supported currently, got %s.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + } else { + MicroPrintf("Only int32_t are supported currently, got %s.", + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else { + MicroPrintf("Only int32_t are supported currently, got %s.", + TfLiteTypeGetName(axis->type)); + return kTfLiteError; + } + +#undef TF_LITE_ARG_MIN_MAX + + return kTfLiteOk; +} + +TfLiteStatus ArgMinEval(TfLiteContext* context, TfLiteNode* node) { + return Eval(context, node, false); +} + +TfLiteStatus ArgMaxEval(TfLiteContext* context, TfLiteNode* node) { + return Eval(context, node, true); +} + +} // namespace arg_min_max + +TfLiteRegistration Register_ARG_MAX() { + return tflite::micro::RegisterOp(nullptr, nullptr, arg_min_max::ArgMaxEval); +} + +TfLiteRegistration Register_ARG_MIN() { + return tflite::micro::RegisterOp(nullptr, nullptr, arg_min_max::ArgMinEval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/assign_variable.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/assign_variable.cc new file mode 100644 index 000000000..f3aa12fa4 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/assign_variable.cc @@ -0,0 +1,101 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_graph.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_resource_variable.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +namespace { + +constexpr int kInputVariableId = 0; +constexpr int kInputValue = 1; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 0); + + // This must be a TfLiteEvalTensor despite this being in Prepare, because + // CreateTensor allocates a temp tensor from the flatbuffer, which does not + // contain the correct ID generated within the VAR_HANDLE op. EvalTensors are + // all allocated during StartModelAllocation which happens before + // init/prepare, and VAR_HANDLE Prepare() references its own op_data in the + // TfLiteEvalTensor, so reading the ID here is valid. + const TfLiteEvalTensor* input_resource_id_tensor = + tflite::micro::GetEvalInput(context, node, kInputVariableId); + TFLITE_DCHECK(input_resource_id_tensor != nullptr); + TF_LITE_ENSURE(context, (input_resource_id_tensor->type == kTfLiteResource || + input_resource_id_tensor->type == kTfLiteInt32)); + TF_LITE_ENSURE_EQ(context, NumElements(input_resource_id_tensor->dims), 1); + + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + TfLiteTensor* input_value = + micro_context->AllocateTempInputTensor(node, kInputValue); + TFLITE_DCHECK(input_value != nullptr); + + MicroGraph& graph_info = micro_context->graph(); + + MicroResourceVariables* resources = graph_info.GetResourceVariables(); + TF_LITE_ENSURE_OK(context, + resources->Allocate(input_resource_id_tensor->data.i32[0], + context, input_value)); + + micro_context->DeallocateTempTfLiteTensor(input_value); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input_id = + tflite::micro::GetEvalInput(context, node, kInputVariableId); + TFLITE_DCHECK(input_id != nullptr); + + const TfLiteEvalTensor* input_value = + tflite::micro::GetEvalInput(context, node, kInputValue); + TFLITE_DCHECK(input_value != nullptr); + + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + MicroGraph& graph_info = micro_context->graph(); + + MicroResourceVariables* resources = graph_info.GetResourceVariables(); + if (resources == nullptr) { + MicroPrintf( + "ASSIGN_VARIABLE requires resource variables. Please create " + "ResourceVariables and pass it to the interpreter."); + return kTfLiteError; + } + TF_LITE_ENSURE_OK(context, + resources->Assign(input_id->data.i32[0], input_value)); + return kTfLiteOk; +} + +} // namespace. + +TfLiteRegistration Register_ASSIGN_VARIABLE() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/batch_to_space_nd.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/batch_to_space_nd.cc new file mode 100644 index 000000000..83fb35688 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/batch_to_space_nd.cc @@ -0,0 +1,112 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/batch_to_space_nd.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +namespace { + +constexpr int kInputTensor = 0; +constexpr int kBlockShapeTensor = 1; +constexpr int kCropsTensor = 2; +constexpr int kOutputTensor = 0; + +// Currently, only 3D NHC and 4D NHWC input/output op_context are supported. +// In case of 3D input, it will be extended to 3D NHWC by adding W=1. +// The 4D array need to have exactly 2 spatial dimensions. +// TODO(b/149952582): Support arbitrary dimension in SpaceToBatchND. +const int kInputOutputMinDimensionNum = 3; +const int kInputOutputMaxDimensionNum = 4; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 3); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, input != nullptr && output != nullptr); + + TF_LITE_ENSURE(context, NumDimensions(input) >= kInputOutputMinDimensionNum); + TF_LITE_ENSURE(context, NumDimensions(output) >= kInputOutputMinDimensionNum); + TF_LITE_ENSURE(context, NumDimensions(input) <= kInputOutputMaxDimensionNum); + TF_LITE_ENSURE(context, NumDimensions(output) <= kInputOutputMaxDimensionNum); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + const TfLiteEvalTensor* block_shape = + tflite::micro::GetEvalInput(context, node, kBlockShapeTensor); + const TfLiteEvalTensor* crops = + tflite::micro::GetEvalInput(context, node, kCropsTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: + reference_ops::BatchToSpaceND( + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(block_shape), + tflite::micro::GetTensorData(block_shape), + tflite::micro::GetTensorShape(crops), + tflite::micro::GetTensorData(crops), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt8: + reference_ops::BatchToSpaceND( + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(block_shape), + tflite::micro::GetTensorData(block_shape), + tflite::micro::GetTensorShape(crops), + tflite::micro::GetTensorData(crops), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace. + +TfLiteRegistration Register_BATCH_TO_SPACE_ND() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/broadcast_args.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/broadcast_args.cc new file mode 100644 index 000000000..be2672ec9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/broadcast_args.cc @@ -0,0 +1,91 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/broadcast_args.h" + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_context.h" + +namespace tflite { +namespace { +constexpr int kShape1Tensor = 0; +constexpr int kShape2Tensor = 1; +constexpr int kOutputTensor = 0; + +TfLiteStatus BroadcastArgsPrepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE(context, NumInputs(node) == 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* shape1 = + micro_context->AllocateTempInputTensor(node, kShape1Tensor); + TfLiteTensor* shape2 = + micro_context->AllocateTempInputTensor(node, kShape2Tensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + + TF_LITE_ENSURE(context, + shape1->type == kTfLiteInt32 || shape1->type == kTfLiteInt64); + TF_LITE_ENSURE_EQ(context, shape1->type, shape2->type); + TF_LITE_ENSURE_EQ(context, shape1->type, output->type); + + // Ensures the shapes are 1D tensor. + TF_LITE_ENSURE_EQ(context, NumDimensions(shape1), 1); + TF_LITE_ENSURE_EQ(context, NumDimensions(shape2), 1); + + // Ensure the shape of the output tensor is compatible + TF_LITE_ENSURE_EQ(context, NumDimensions(output), 1); + + micro_context->DeallocateTempTfLiteTensor(shape1); + micro_context->DeallocateTempTfLiteTensor(shape2); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus BroadcastArgsEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* shape1 = + micro::GetEvalInput(context, node, kShape1Tensor); + const TfLiteEvalTensor* shape2 = + micro::GetEvalInput(context, node, kShape2Tensor); + TfLiteEvalTensor* output = micro::GetEvalOutput(context, node, kOutputTensor); + + if (output->type == kTfLiteInt32) { + reference_ops::BroadcastArgs( + micro::GetTensorShape(shape1), micro::GetTensorData(shape1), + micro::GetTensorShape(shape2), micro::GetTensorData(shape2), + micro::GetTensorShape(output), micro::GetTensorData(output)); + } else { + reference_ops::BroadcastArgs( + micro::GetTensorShape(shape1), micro::GetTensorData(shape1), + micro::GetTensorShape(shape2), micro::GetTensorData(shape2), + micro::GetTensorShape(output), micro::GetTensorData(output)); + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_BROADCAST_ARGS() { + return tflite::micro::RegisterOp(nullptr, BroadcastArgsPrepare, + BroadcastArgsEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/broadcast_to.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/broadcast_to.cc new file mode 100644 index 000000000..63a14db25 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/broadcast_to.cc @@ -0,0 +1,123 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/broadcast_to.h" + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_context.h" + +namespace tflite { + +namespace { +constexpr int kInputTensor = 0; +constexpr int kShapeTensor = 1; +constexpr int kOutputTensor = 0; +// Support a maximum of 5 dimensions in TFLM. +constexpr int kMaxDims = 5; + +TfLiteStatus ValidateOutputTensor(TfLiteContext* context, TfLiteTensor* input, + TfLiteTensor* shape, TfLiteTensor* output) { + // Ensures the shape is 1D tensor. + TF_LITE_ENSURE_EQ(context, NumDimensions(shape), 1); + + // Ensure output dims is not less than input dims. + int input_num_dims = NumDimensions(input); + int output_num_dims = NumDimensions(output); + int shape_num_dims = SizeOfDimension(shape, 0); + TF_LITE_ENSURE_MSG(context, output_num_dims == shape_num_dims, + "Output must match with the expected shape dimension."); + TF_LITE_ENSURE_MSG(context, input_num_dims <= output_num_dims, + "Output shape must be broadcastable from input shape."); + TF_LITE_ENSURE_MSG(context, output_num_dims <= kMaxDims, + "BroadcastTo only supports 1-5D tensor."); + + // Check if output shape is broadcastable from input shape. + auto get_shape_data = [shape](int i) -> int32_t { + if (shape->type == kTfLiteInt32) { + return GetTensorData(shape)[i]; + } else { + return GetTensorData(shape)[i]; + } + }; + + int extending_dims = output_num_dims - input_num_dims; + for (int idx = 0; idx < input_num_dims; ++idx) { + TF_LITE_ENSURE_MSG( + context, + (SizeOfDimension(input, idx) == 1 || + SizeOfDimension(input, idx) == get_shape_data(extending_dims + idx)), + "Output shape must be broadcastable from input shape."); + } + + // Validating the shape of the output tensor. + tflite::RuntimeShape output_shape = tflite::GetTensorShape(output); + for (int idx = 0; idx < output_num_dims; ++idx) { + TF_LITE_ENSURE(context, output_shape.Dims(idx) == get_shape_data(idx)); + } + return kTfLiteOk; +} + +TfLiteStatus BroadcastToPrepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE(context, NumInputs(node) == 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TfLiteTensor* shape = + micro_context->AllocateTempInputTensor(node, kShapeTensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + + TF_LITE_ENSURE_MSG(context, (NumDimensions(input) <= kMaxDims), + "BroadcastTo only supports 1-5D tensor."); + + TF_LITE_ENSURE(context, + shape->type == kTfLiteInt32 || shape->type == kTfLiteInt64); + TF_LITE_ENSURE_EQ(context, input->type, output->type); + + // Does not support String type due to its variable size. This limitation is + // the same as TFLite. + TF_LITE_ENSURE(context, input->type != kTfLiteString); + + TF_LITE_ENSURE_STATUS(ValidateOutputTensor(context, input, shape, output)); + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(shape); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus BroadcastToEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = micro::GetEvalOutput(context, node, kOutputTensor); + + // BroadcastTo op support upto 5 dims, different from 8 dims in TFLite. + reference_ops::BroadcastTo( + micro::GetTensorShape(input), input->data.raw, + micro::GetTensorShape(output), output->data.raw, input->type); + return kTfLiteOk; +} +} // namespace + +TfLiteRegistration Register_BROADCAST_TO() { + return tflite::micro::RegisterOp(nullptr, BroadcastToPrepare, + BroadcastToEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/call_once.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/call_once.cc new file mode 100644 index 000000000..200242b2c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/call_once.cc @@ -0,0 +1,88 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_context.h" +#include "tensorflow/lite/micro/micro_graph.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +namespace { + +struct OpData { + int init_subgraph_index; + bool has_run; +}; + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + OpData* op_data = reinterpret_cast(node->user_data); + const auto* params = + reinterpret_cast(node->builtin_data); + op_data->init_subgraph_index = params->init_subgraph_index; + op_data->has_run = false; + + TF_LITE_ENSURE(context, NumInputs(node) == 0); + TF_LITE_ENSURE(context, NumOutputs(node) == 0); + + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + MicroGraph& graph_info = micro_context->graph(); + + TF_LITE_ENSURE(context, + op_data->init_subgraph_index < graph_info.NumSubgraphs()); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + OpData* op_data = reinterpret_cast(node->user_data); + + // Call once only runs one time then is a no-op for every subsequent call. + if (op_data->has_run) { + return kTfLiteOk; + } + + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + MicroGraph& graph_info = micro_context->graph(); + + TF_LITE_ENSURE_OK(context, + graph_info.InvokeSubgraph(op_data->init_subgraph_index)); + + op_data->has_run = true; + + return kTfLiteOk; +} + +} // namespace. + +TfLiteRegistration Register_CALL_ONCE() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/cast.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/cast.cc new file mode 100644 index 000000000..0a0204d2e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/cast.cc @@ -0,0 +1,114 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +template +void copyCast(const FromT* in, ToT* out, int num_elements) { + std::transform(in, in + num_elements, out, + [](FromT a) { return static_cast(a); }); +} + +template +TfLiteStatus copyToTensor(TfLiteContext* context, const FromT* in, + TfLiteEvalTensor* out, int num_elements) { + switch (out->type) { + case kTfLiteInt8: + copyCast(in, out->data.int8, num_elements); + break; + case kTfLiteInt16: + copyCast(in, out->data.i16, num_elements); + break; + case kTfLiteInt32: + copyCast(in, out->data.i32, num_elements); + break; + case kTfLiteFloat32: + copyCast(in, tflite::micro::GetTensorData(out), num_elements); + break; + default: + // Unsupported type. + MicroPrintf("Output type %s (%d) not supported.", + TfLiteTypeGetName(out->type), out->type); + } + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + int num_elements = MatchingFlatSize(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorShape(output)); + + switch (input->type) { + case kTfLiteInt8: + return copyToTensor(context, input->data.int8, output, num_elements); + case kTfLiteInt16: + return copyToTensor(context, tflite::micro::GetTensorData(input), + output, num_elements); + case kTfLiteInt32: + return copyToTensor(context, tflite::micro::GetTensorData(input), + output, num_elements); + case kTfLiteUInt32: + return copyToTensor(context, + tflite::micro::GetTensorData(input), output, + num_elements); + case kTfLiteFloat32: + return copyToTensor(context, tflite::micro::GetTensorData(input), + output, num_elements); + default: + // Unsupported type. + MicroPrintf("Input type %s (%d) not supported.", + TfLiteTypeGetName(input->type), input->type); + } + return kTfLiteOk; +} +} // namespace + +TfLiteRegistration Register_CAST() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ceil.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ceil.cc new file mode 100644 index 000000000..a390a7355 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ceil.cc @@ -0,0 +1,75 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/ceil.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace ceil { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, kTfLiteFloat32); + TF_LITE_ENSURE_TYPES_EQ(context, output->type, input->type); + TF_LITE_ENSURE_EQ(context, output->bytes, input->bytes); + TF_LITE_ENSURE_EQ(context, output->dims->size, input->dims->size); + for (int i = 0; i < output->dims->size; ++i) { + TF_LITE_ENSURE_EQ(context, output->dims->data[i], input->dims->data[i]); + } + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + reference_ops::Ceil(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + + return kTfLiteOk; +} +} // namespace ceil + +TfLiteRegistration Register_CEIL() { + return tflite::micro::RegisterOp(nullptr, ceil::Prepare, ceil::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer.cc new file mode 100644 index 000000000..9779c32d9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer.cc @@ -0,0 +1,117 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/circular_buffer.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/flatbuffer_utils.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +/* + * The circular buffer custom operator is used to implement strided streaming + * convolutions on TFLite Micro. Each time this operator is invoked, it checks + * whether or not to run, based on a predetermined stride in time. If the op + * runs, it inserts the input into the end of the output buffer and shifts the + * output values towards the start of the buffer. It discards the oldest value + * in the output buffer. + * + * Input: [, , , ] + * + * After shifting: + * Output: [, , , ] + * + * We make some assumptions in this custom operator: + * - Input shape must be [1, 1, 1, depth] + * - Output shape must be [1, num_slots, 1, depth] + * - Input and output types must match. + * - Input and output quantization params must be identical. + */ +namespace tflite { + +void* CircularBufferInit(TfLiteContext* context, const char* buffer, + size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + OpDataCircularBuffer* op_data = static_cast( + context->AllocatePersistentBuffer(context, sizeof(OpDataCircularBuffer))); + + if (buffer != nullptr && length > 0) { + const uint8_t* buffer_t = reinterpret_cast(buffer); + tflite::FlexbufferWrapper wrapper(buffer_t, length); + op_data->cycles_max = wrapper.ElementAsInt32(kCircularBufferCyclesMaxIndex); + } else { + op_data->cycles_max = 0; + } + + return op_data; +} + +// Shifts buffer over by the output depth, and write new input to end of buffer. +// num_slots is the number of samples stored in the output buffer. +// depth is the size of each sample. +void EvalInt8(const int8_t* input, int num_slots, int depth, int8_t* output) { + memmove(output, &output[depth], (num_slots - 1) * depth); + memcpy(&output[(num_slots - 1) * depth], input, depth); +} + +TfLiteStatus CircularBufferEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kCircularBufferInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kCircularBufferOutputTensor); + + TFLITE_DCHECK(node->user_data != nullptr); + OpDataCircularBuffer* data = + reinterpret_cast(node->user_data); + + int num_slots = output->dims->data[1]; + int depth = output->dims->data[2] * output->dims->data[3]; + + if (input->type == kTfLiteInt8) { + EvalInt8(tflite::micro::GetTensorData(input), num_slots, depth, + tflite::micro::GetTensorData(output)); + } else { + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + + if (--data->cycles_until_run != 0) { + // Signal the interpreter to end current run if the delay before op invoke + // has not been reached. + // TODO(b/149795762): Add kTfLiteAbort to TfLiteStatus enum. + return static_cast(kTfLiteAbort); + } + + data->cycles_until_run = data->cycles_max; + + return kTfLiteOk; +} + +TfLiteRegistration* Register_CIRCULAR_BUFFER() { + static TfLiteRegistration r = tflite::micro::RegisterOp( + CircularBufferInit, CircularBufferPrepare, CircularBufferEval); + return &r; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer.h new file mode 100644 index 000000000..51adf746d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer.h @@ -0,0 +1,48 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_CIRCULAR_BUFFER_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_CIRCULAR_BUFFER_H_ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +// The CircularBuffer op has one input and one output tensor. +extern const int kCircularBufferInputTensor; +extern const int kCircularBufferOutputTensor; + +// Indices into the init flexbuffer's vector. +// The parameter's name is in the comment that follows. +// Elements in the vectors are ordered alphabetically by parameter name. +extern const int kCircularBufferCyclesMaxIndex; // 'cycles_max' + +// TODO(b/149795762): Add this to TfLiteStatus enum. +extern const TfLiteStatus kTfLiteAbort; + +// These fields control the stride period of a strided streaming model. This op +// returns kTfLiteAbort until cycles_until_run-- is zero. At this time, +// cycles_until_run is reset to cycles_max. +struct OpDataCircularBuffer { + int cycles_until_run; + int cycles_max; +}; + +TfLiteStatus CircularBufferPrepare(TfLiteContext* context, TfLiteNode* node); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_CIRCULAR_BUFFER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer_common.cc new file mode 100644 index 000000000..81db6e65f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer_common.cc @@ -0,0 +1,97 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/flatbuffer_utils.h" +#include "tensorflow/lite/micro/kernels/circular_buffer.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { + +// The CircularBuffer op has one input and one output tensor. +const int kCircularBufferInputTensor = 0; +const int kCircularBufferOutputTensor = 0; + +// Indices into the init flexbuffer's vector. +// The parameter's name is in the comment that follows. +// Elements in the vectors are ordered alphabetically by parameter name. +const int kCircularBufferCyclesMaxIndex = 0; // 'cycles_max' + +// TODO(b/149795762): Add this to TfLiteStatus enum. +const TfLiteStatus kTfLiteAbort = static_cast(-9); + +TfLiteStatus CircularBufferPrepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kCircularBufferInputTensor); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor( + node, kCircularBufferOutputTensor); + + TFLITE_DCHECK(node->user_data != nullptr); + OpDataCircularBuffer* op_data = + static_cast(node->user_data); + + TF_LITE_ENSURE(context, input != nullptr); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_EQ(context, input->dims->data[0], output->dims->data[0]); + TF_LITE_ENSURE_EQ(context, 1, input->dims->data[1]); + TF_LITE_ENSURE_EQ(context, input->dims->data[2], output->dims->data[2]); + TF_LITE_ENSURE_EQ(context, output->dims->data[3], input->dims->data[3]); + + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + // The circular buffer custom operator currently only supports int8. + TF_LITE_ENSURE_TYPES_EQ(context, input->type, kTfLiteInt8); + + if (op_data->cycles_max <= 0) { + // The last circular buffer layer simply accumulates outputs, and does not + // run periodically. + // TODO(b/150001379): Move this special case logic to the tflite flatbuffer. + static int cb_prepare_count = 0; + cb_prepare_count++; + // These checks specifically work for the only two streaming models + // supported on TFLM. They use the shape of the output tensor along with the + // layer number to determine if the circular buffer period should be 1 or 2. + + // These models are outlined int the following documents: + // https://docs.google.com/document/d/1lc_G2ZFhjiKFo02UHjBaljye1xsL0EkfybkaVELEE3Q/edit?usp=sharing + // https://docs.google.com/document/d/1pGc42PuWyrk-Jy1-9qeqtggvsmHr1ifz8Lmqfpr2rKA/edit?usp=sharing + if (output->dims->data[1] == 5 || output->dims->data[1] == 13 || + output->dims->data[1] == 25 || + (cb_prepare_count == 5 && output->dims->data[2] == 2 && + output->dims->data[3] == 96)) { + op_data->cycles_max = 1; + cb_prepare_count = 0; + } else { + op_data->cycles_max = 2; + } + } + op_data->cycles_until_run = op_data->cycles_max; + node->user_data = op_data; + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer_flexbuffers_generated_data.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer_flexbuffers_generated_data.h new file mode 100644 index 000000000..2fbf4fe96 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/circular_buffer_flexbuffers_generated_data.h @@ -0,0 +1,22 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_FLEXBUFFERS_GENERATED_DATA_H +#define TENSORFLOW_LITE_MICRO_KERNELS_FLEXBUFFERS_GENERATED_DATA_H + +extern const int g_gen_data_size_circular_buffer_config; +extern const unsigned char g_gen_data_circular_buffer_config[]; + +#endif diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/comparisons.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/comparisons.cc new file mode 100644 index 000000000..597856cd2 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/comparisons.cc @@ -0,0 +1,618 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/comparisons.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace comparisons { +namespace { + +struct OpData { + ComparisonParams params; +}; + +constexpr int kInputTensor1 = 0; +constexpr int kInputTensor2 = 1; +constexpr int kOutputTensor = 0; + +TfLiteStatus EqualEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const OpData* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + RuntimeShape input1_shape = tflite::micro::GetTensorShape(input1); + RuntimeShape input2_shape = tflite::micro::GetTensorShape(input2); + RuntimeShape output_shape = tflite::micro::GetTensorShape(output); + bool* output_data = tflite::micro::GetTensorData(output); + + bool requires_broadcast = !tflite::micro::HaveSameShapes(input1, input2); + switch (input1->type) { + case kTfLiteBool: + requires_broadcast + ? reference_ops::Broadcast4DSlowEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::EqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteFloat32: + requires_broadcast + ? reference_ops::Broadcast4DSlowEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::EqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt32: + requires_broadcast + ? reference_ops::Broadcast4DSlowEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::EqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt64: + requires_broadcast + ? reference_ops::Broadcast4DSlowEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::EqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt8: + requires_broadcast + ? reference_ops::Broadcast4DSlowEqualWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::EqualWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(input1->type), input1->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +// TODO(renjieliu): Refactor the logic to avoid duplications. +TfLiteStatus NotEqualEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const OpData* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + RuntimeShape input1_shape = tflite::micro::GetTensorShape(input1); + RuntimeShape input2_shape = tflite::micro::GetTensorShape(input2); + RuntimeShape output_shape = tflite::micro::GetTensorShape(output); + bool* output_data = tflite::micro::GetTensorData(output); + + bool requires_broadcast = !tflite::micro::HaveSameShapes(input1, input2); + switch (input1->type) { + case kTfLiteBool: + requires_broadcast + ? reference_ops::Broadcast4DSlowNotEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::NotEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteFloat32: + requires_broadcast + ? reference_ops::Broadcast4DSlowNotEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::NotEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt32: + requires_broadcast + ? reference_ops::Broadcast4DSlowNotEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::NotEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt64: + requires_broadcast + ? reference_ops::Broadcast4DSlowNotEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::NotEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt8: + requires_broadcast + ? reference_ops::Broadcast4DSlowNotEqualWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::NotEqualWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(input1->type), input1->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus GreaterEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const OpData* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + RuntimeShape input1_shape = tflite::micro::GetTensorShape(input1); + RuntimeShape input2_shape = tflite::micro::GetTensorShape(input2); + RuntimeShape output_shape = tflite::micro::GetTensorShape(output); + bool* output_data = tflite::micro::GetTensorData(output); + + bool requires_broadcast = !tflite::micro::HaveSameShapes(input1, input2); + switch (input1->type) { + case kTfLiteFloat32: + requires_broadcast + ? reference_ops::Broadcast4DSlowGreaterNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::GreaterNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt32: + requires_broadcast + ? reference_ops::Broadcast4DSlowGreaterNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::GreaterNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt64: + requires_broadcast + ? reference_ops::Broadcast4DSlowGreaterNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::GreaterNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt8: + requires_broadcast + ? reference_ops::Broadcast4DSlowGreaterWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::GreaterWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(input1->type), input1->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus GreaterEqualEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const OpData* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + RuntimeShape input1_shape = tflite::micro::GetTensorShape(input1); + RuntimeShape input2_shape = tflite::micro::GetTensorShape(input2); + RuntimeShape output_shape = tflite::micro::GetTensorShape(output); + bool* output_data = tflite::micro::GetTensorData(output); + + bool requires_broadcast = !tflite::micro::HaveSameShapes(input1, input2); + switch (input1->type) { + case kTfLiteFloat32: + requires_broadcast + ? reference_ops::Broadcast4DSlowGreaterEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::GreaterEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt32: + requires_broadcast + ? reference_ops::Broadcast4DSlowGreaterEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::GreaterEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt64: + requires_broadcast + ? reference_ops::Broadcast4DSlowGreaterEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::GreaterEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt8: + requires_broadcast + ? reference_ops::Broadcast4DSlowGreaterEqualWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::GreaterEqualWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(input1->type), input1->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus LessEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const OpData* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + RuntimeShape input1_shape = tflite::micro::GetTensorShape(input1); + RuntimeShape input2_shape = tflite::micro::GetTensorShape(input2); + RuntimeShape output_shape = tflite::micro::GetTensorShape(output); + bool* output_data = tflite::micro::GetTensorData(output); + + bool requires_broadcast = !tflite::micro::HaveSameShapes(input1, input2); + switch (input1->type) { + case kTfLiteFloat32: + requires_broadcast + ? reference_ops::Broadcast4DSlowLessNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::LessNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt32: + requires_broadcast + ? reference_ops::Broadcast4DSlowLessNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::LessNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt64: + requires_broadcast + ? reference_ops::Broadcast4DSlowLessNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::LessNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt8: + requires_broadcast + ? reference_ops::Broadcast4DSlowLessWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::LessWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(input1->type), input1->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus LessEqualEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const OpData* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + RuntimeShape input1_shape = tflite::micro::GetTensorShape(input1); + RuntimeShape input2_shape = tflite::micro::GetTensorShape(input2); + RuntimeShape output_shape = tflite::micro::GetTensorShape(output); + bool* output_data = tflite::micro::GetTensorData(output); + + bool requires_broadcast = !tflite::micro::HaveSameShapes(input1, input2); + switch (input1->type) { + case kTfLiteFloat32: + requires_broadcast + ? reference_ops::Broadcast4DSlowLessEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::LessEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt32: + requires_broadcast + ? reference_ops::Broadcast4DSlowLessEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::LessEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt64: + requires_broadcast + ? reference_ops::Broadcast4DSlowLessEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::LessEqualNoScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + case kTfLiteInt8: + requires_broadcast + ? reference_ops::Broadcast4DSlowLessEqualWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data) + : reference_ops::LessEqualWithScaling( + data->params, input1_shape, + tflite::micro::GetTensorData(input1), input2_shape, + tflite::micro::GetTensorData(input2), output_shape, + output_data); + break; + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(input1->type), input1->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + OpData* data = static_cast(node->user_data); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input1 = + micro_context->AllocateTempInputTensor(node, kInputTensor1); + TF_LITE_ENSURE(context, input1 != nullptr); + TfLiteTensor* input2 = + micro_context->AllocateTempInputTensor(node, kInputTensor2); + TF_LITE_ENSURE(context, input2 != nullptr); + + if (input1->type == kTfLiteInt8) { + auto input1_offset = -input1->params.zero_point; + auto input2_offset = -input2->params.zero_point; + const int kLeftShift = 8; + + int32_t input1_multiplier; + int input1_shift; + QuantizeMultiplierSmallerThanOneExp( + static_cast(input1->params.scale), &input1_multiplier, + &input1_shift); + int32_t input2_multiplier; + int input2_shift; + QuantizeMultiplierSmallerThanOneExp( + static_cast(input2->params.scale), &input2_multiplier, + &input2_shift); + + data->params.left_shift = kLeftShift; + data->params.input1_offset = input1_offset; + data->params.input1_multiplier = input1_multiplier; + data->params.input1_shift = input1_shift; + data->params.input2_offset = input2_offset; + data->params.input2_multiplier = input2_multiplier; + data->params.input2_shift = input2_shift; + } + + micro_context->DeallocateTempTfLiteTensor(input1); + micro_context->DeallocateTempTfLiteTensor(input2); + + return kTfLiteOk; +} + +} // namespace comparisons + +TfLiteRegistration Register_EQUAL() { + return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare, + comparisons::EqualEval); +} + +TfLiteRegistration Register_NOT_EQUAL() { + return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare, + comparisons::NotEqualEval); +} + +TfLiteRegistration Register_GREATER() { + return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare, + comparisons::GreaterEval); +} + +TfLiteRegistration Register_GREATER_EQUAL() { + return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare, + comparisons::GreaterEqualEval); +} + +TfLiteRegistration Register_LESS() { + return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare, + comparisons::LessEval); +} + +TfLiteRegistration Register_LESS_EQUAL() { + return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare, + comparisons::LessEqualEval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/concatenation.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/concatenation.cc new file mode 100644 index 000000000..a3f1cc346 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/concatenation.cc @@ -0,0 +1,263 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/concatenation.h" + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/portable_tensor.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace concatenation { + +constexpr int kMaxInputNum = 10; // Maximum number of input tensors +constexpr int kOutputTensor = 0; + +struct OpData { + ConcatenationParams params; +}; + +// Handles negative axis index, coerces to positive index value. +inline int CalculatePositiveAxis(int axis, const TfLiteTensor* output_tensor) { + if (axis >= 0) { + return axis; + } else { + return NumDimensions(output_tensor) + axis; + } +} + +// The following functions are helpers to get tensor data in the format that the +// reference op implementation expects. They provide the same functionality as +// class VectorOfTensors and class VectorOfQuantizedTensors in TFLite. + +// Gets shapes from a list of tensors. +inline void GetAllInputTensorShapes(const TfLiteContext* context, + const TfLiteNode* node, + RuntimeShape all_shapes[kMaxInputNum]) { + TFLITE_DCHECK(context != nullptr); + TFLITE_DCHECK(node != nullptr); + for (int i = 0; i < node->inputs->size; ++i) { + const TfLiteEvalTensor* t = tflite::micro::GetEvalInput(context, node, i); + RuntimeShape shape = tflite::micro::GetTensorShape(t); + all_shapes[i].ReplaceWith(shape.DimensionsCount(), shape.DimsData()); + } +} + +// Get shape pointers from a list of shapes. +inline void GetShapesPointers(const RuntimeShape* shapes, size_t num, + const RuntimeShape* pointers[]) { + for (size_t i = 0; i < num; ++i) { + pointers[i] = &shapes[i]; + } +} + +// Gets data pointers from a list of tensors. +template +inline void GetAllInputTensorData(const TfLiteContext* context, + const TfLiteNode* node, + T* all_data[kMaxInputNum]) { + TFLITE_DCHECK(context != nullptr); + TFLITE_DCHECK(node != nullptr); + for (int i = 0; i < node->inputs->size; ++i) { + const TfLiteEvalTensor* t = tflite::micro::GetEvalInput(context, node, i); + all_data[i] = tflite::micro::GetTensorData(t); + } +} + +template +void EvalUnquantized(TfLiteContext* context, TfLiteNode* node) { + // Collect the shapes and data pointer of input tensors + RuntimeShape inputs_shape[kMaxInputNum]; + const RuntimeShape* inputs_shape_ptr[kMaxInputNum]; + const data_type* inputs_data[kMaxInputNum]; + GetAllInputTensorShapes(context, node, inputs_shape); + GetShapesPointers(inputs_shape, node->inputs->size, inputs_shape_ptr); + GetAllInputTensorData(context, node, inputs_data); + + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpData* data = static_cast(node->user_data); + + reference_ops::Concatenation(data->params, inputs_shape_ptr, inputs_data, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + // This function only checks the types. Additional shape validations are + // performed in the reference implementation called during Eval(). + const TfLiteConcatenationParams* params = + reinterpret_cast(node->builtin_data); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input_tensor = micro_context->AllocateTempInputTensor(node, 0); + TF_LITE_ENSURE(context, input_tensor != nullptr); + TfLiteType input_type = input_tensor->type; + TfLiteTensor* output_tensor = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output_tensor != nullptr); + TfLiteType output_type = output_tensor->type; + + micro_context->DeallocateTempTfLiteTensor(input_tensor); + micro_context->DeallocateTempTfLiteTensor(output_tensor); + + // Check activation and input type + TF_LITE_ENSURE_EQ(context, params->activation, kTfLiteActNone); + TF_LITE_ENSURE(context, + input_type == kTfLiteFloat32 || input_type == kTfLiteInt8 || + input_type == kTfLiteInt16 || input_type == kTfLiteInt32 || + input_type == kTfLiteInt64 || input_type == kTfLiteBool); + + // Output type must match input type + TF_LITE_ENSURE_EQ(context, output_type, input_type); + + // This implementation does not support large number of input tensors + const int num_inputs = NumInputs(node); + TF_LITE_ENSURE(context, num_inputs <= kMaxInputNum); + + // Shapes with dimensions >4 are not yet supported with static allocation. + for (int i = 0; i < num_inputs; ++i) { + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, i); + TF_LITE_ENSURE(context, input != nullptr); + int num_dimensions = NumDimensions(input); + + if (num_dimensions > RuntimeShape::kMaxSmallSize) { + MicroPrintf( + "Op Concatenation does not currently support num dimensions > %d " + "Tensor has %d dimensions.", + RuntimeShape::kMaxSmallSize, num_dimensions); + return kTfLiteError; + } + micro_context->DeallocateTempTfLiteTensor(input); + } + + // Calculate OpData. + TFLITE_DCHECK(node->user_data != nullptr); + OpData* data = static_cast(node->user_data); + + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + switch (output_type) { // Already know in/outtypes are same. + case kTfLiteBool: + case kTfLiteFloat32: + case kTfLiteInt16: + case kTfLiteInt32: + case kTfLiteInt64: { + data->params.axis = CalculatePositiveAxis(params->axis, output); + data->params.inputs_count = node->inputs->size; + break; + } + case kTfLiteInt8: { + data->params.axis = CalculatePositiveAxis(params->axis, output); + data->params.inputs_count = node->inputs->size; + + float* input_scales = + reinterpret_cast(context->AllocatePersistentBuffer( + context, node->inputs->size * sizeof(float))); + + int32_t* input_zero_points = + reinterpret_cast(context->AllocatePersistentBuffer( + context, node->inputs->size * sizeof(int32_t))); + + // Allocate persistent scale and zeropoint buffers. + // Store input scale and zero point values in OpParams: + for (int i = 0; i < node->inputs->size; ++i) { + TfLiteTensor* t = micro_context->AllocateTempInputTensor(node, i); + TF_LITE_ENSURE(context, t != nullptr); + input_scales[i] = t->params.scale; + input_zero_points[i] = t->params.zero_point; + micro_context->DeallocateTempTfLiteTensor(t); + } + + data->params.input_scale = input_scales; + data->params.input_zeropoint = input_zero_points; + data->params.output_zeropoint = output->params.zero_point; + data->params.output_scale = output->params.scale; + break; + } + default: + MicroPrintf("Op Concatenation does not currently support Type '%s'.", + TfLiteTypeGetName(output_type)); + return kTfLiteError; + } + + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* output_tensor = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + TF_LITE_ENSURE(context, output_tensor != nullptr); + TfLiteType output_type = output_tensor->type; + + switch (output_type) { // Already know in/outtypes are same. + case kTfLiteFloat32: + EvalUnquantized(context, node); + break; + case kTfLiteInt32: + EvalUnquantized(context, node); + break; + case kTfLiteInt8: + EvalUnquantized(context, node); + break; + case kTfLiteInt64: + EvalUnquantized(context, node); + break; + case kTfLiteInt16: + EvalUnquantized(context, node); + break; + case kTfLiteBool: + EvalUnquantized(context, node); + break; + + default: + MicroPrintf("Op Concatenation does not currently support Type '%s'.", + TfLiteTypeGetName(output_type)); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace concatenation + +TfLiteRegistration Register_CONCATENATION() { + return tflite::micro::RegisterOp(concatenation::Init, concatenation::Prepare, + concatenation::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv.cc new file mode 100644 index 000000000..36c57655a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv.cc @@ -0,0 +1,166 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/conv.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/reference/conv.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/conv.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataConv)); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kConvInputTensor); + const TfLiteEvalTensor* filter = + tflite::micro::GetEvalInput(context, node, kConvWeightsTensor); + const TfLiteEvalTensor* bias = + (NumInputs(node) == 3) + ? tflite::micro::GetEvalInput(context, node, kConvBiasTensor) + : nullptr; + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kConvOutputTensor); + + TFLITE_DCHECK(node->builtin_data != nullptr); + const auto& params = + *(reinterpret_cast(node->builtin_data)); + TFLITE_DCHECK(node->user_data != nullptr); + const auto& data = *(static_cast(node->user_data)); + + TF_LITE_ENSURE_EQ(context, input->type, output->type); + TF_LITE_ENSURE_MSG( + context, + input->type == filter->type || + (input->type == kTfLiteInt16 && filter->type == kTfLiteInt8) || + (input->type == kTfLiteInt8 && filter->type == kTfLiteInt4), + "Hybrid models are not supported on TFLite Micro."); + + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: { + tflite::reference_ops::Conv( + ConvParamsFloat(params, data), tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + tflite::micro::GetTensorShape(nullptr), nullptr); + break; + } + case kTfLiteInt16: { + switch (bias->type) { + case kTfLiteInt32: { + reference_integer_ops::ConvPerChannel( + ConvParamsQuantized(params, data), + data.per_channel_output_multiplier, data.per_channel_output_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + case kTfLiteInt64: { + reference_integer_ops::ConvPerChannel( + ConvParamsQuantized(params, data), + data.per_channel_output_multiplier, data.per_channel_output_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + default: + MicroPrintf("Bias type %s (%d) not supported.", + TfLiteTypeGetName(bias->type), bias->type); + return kTfLiteError; + } + break; + } + case kTfLiteInt8: { + switch (filter->type) { + case kTfLiteInt4: { + int8_t* unpacked_filter_data = nullptr; + OpDataConv* op_data = static_cast(node->user_data); + unpacked_filter_data = static_cast( + context->GetScratchBuffer(context, op_data->filter_buffer_index)); + reference_integer_ops::ConvPerChannelWithPackedInt4Weights( + ConvParamsQuantized(params, data), + data.per_channel_output_multiplier, data.per_channel_output_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + unpacked_filter_data, tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + case kTfLiteInt8: { + reference_integer_ops::ConvPerChannel( + ConvParamsQuantized(params, data), + data.per_channel_output_multiplier, data.per_channel_output_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + default: + MicroPrintf("Weight type %s (%d) not supported.", + TfLiteTypeGetName(filter->type), filter->type); + return kTfLiteError; + } + break; + } + default: + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_CONV_2D() { + return tflite::micro::RegisterOp(Init, ConvPrepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv.h new file mode 100644 index 000000000..06e9db43a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv.h @@ -0,0 +1,116 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_CONV_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_CONV_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +struct OpDataConv { + TfLitePaddingValues padding; + + // Cached tensor zero point values for quantized operations. + int32_t input_zero_point; + int32_t filter_zero_point; + int32_t output_zero_point; + + // The scaling factor from input to output (aka the 'real multiplier') can + // be represented as a fixed point multiplier plus a left shift. + int32_t output_multiplier; + int output_shift; + + // Per channel output multiplier and shift. + int32_t* per_channel_output_multiplier; + int32_t* per_channel_output_shift; + + // The range of the fused activation layer. For example for kNone and + // uint8_t these would be 0 and 255. + int32_t output_activation_min; + int32_t output_activation_max; + + // A buffer used to store unpacked filter values. This is used if the source + // tensor is of n-bit precision that cannot be easily processed by kernels. + int filter_buffer_index; +}; + +extern const int kConvInputTensor; +extern const int kConvWeightsTensor; +extern const int kConvBiasTensor; +extern const int kConvOutputTensor; +extern const int kConvQuantizedDimension; + +// Returns a ConvParams struct with all the parameters needed for a +// float computation. +ConvParams ConvParamsFloat(const TfLiteConvParams& params, + const OpDataConv& data); + +// Returns a ConvParams struct with all the parameters needed for a +// quantized computation. +ConvParams ConvParamsQuantized(const TfLiteConvParams& params, + const OpDataConv& data); + +TfLiteStatus CalculateOpDataConv(TfLiteContext* context, TfLiteNode* node, + const TfLiteConvParams& params, int width, + int height, int filter_width, + int filter_height, int out_width, + int out_height, const TfLiteType data_type, + OpDataConv* data); + +TfLiteStatus ConvPrepare(TfLiteContext* context, TfLiteNode* node); + +// This is the most generic TfLiteRegistration. The actual supported types may +// still be target dependent. The only requirement is that every implementation +// (reference or optimized) must define this function. +TfLiteRegistration Register_CONV_2D(); + +#if defined(XTENSA) +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int8 activations and int8 weights and always calls the reference +// implementation. +TfLiteRegistration Register_CONV_2D_INT8REF(); +#else +inline TfLiteRegistration Register_CONV_2D_INT8REF() { + return Register_CONV_2D(); +} +#endif + +#if defined(CMSIS_NN) +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int8 activations and int8 weights and uses the latency optimized +// implementations. +TfLiteRegistration Register_CONV_2D_INT8(); + +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int16 activations and int8 weights and uses the latency optimized +// implementations. +TfLiteRegistration Register_CONV_2D_INT16(); + +#else +inline TfLiteRegistration Register_CONV_2D_INT8() { return Register_CONV_2D(); } + +inline TfLiteRegistration Register_CONV_2D_INT16() { + return Register_CONV_2D(); +} +#endif + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_CONV_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv_common.cc new file mode 100644 index 000000000..c548c932c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv_common.cc @@ -0,0 +1,202 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/c_api_types.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/padding.h" +#include "tensorflow/lite/micro/kernels/conv.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { + +const int kConvInputTensor = 0; +const int kConvWeightsTensor = 1; +const int kConvBiasTensor = 2; +const int kConvOutputTensor = 0; + +// Conv is quantized along dimension 0: +// https://www.tensorflow.org/lite/performance/quantization_spec +const int kConvQuantizedDimension = 0; + +// Returns a ConvParams struct with all the parameters needed for a +// float computation. +ConvParams ConvParamsFloat(const TfLiteConvParams& params, + const OpDataConv& data) { + ConvParams op_params; + CalculateActivationRange(params.activation, &op_params.float_activation_min, + &op_params.float_activation_max); + op_params.padding_type = tflite::micro::RuntimePaddingType(params.padding); + op_params.padding_values.width = data.padding.width; + op_params.padding_values.height = data.padding.height; + op_params.stride_width = params.stride_width; + op_params.stride_height = params.stride_height; + op_params.dilation_width_factor = params.dilation_width_factor; + op_params.dilation_height_factor = params.dilation_height_factor; + return op_params; +} + +// Returns a ConvParams struct with all the parameters needed for a +// quantized computation. +ConvParams ConvParamsQuantized(const TfLiteConvParams& params, + const OpDataConv& data) { + ConvParams op_params; + op_params.input_offset = -data.input_zero_point; + op_params.weights_offset = -data.filter_zero_point; + op_params.output_offset = data.output_zero_point; + op_params.output_multiplier = data.output_multiplier; + op_params.output_shift = -data.output_shift; + op_params.padding_type = tflite::micro::RuntimePaddingType(params.padding); + op_params.padding_values.height = data.padding.height; + op_params.padding_values.width = data.padding.width; + op_params.stride_height = params.stride_height; + op_params.stride_width = params.stride_width; + op_params.dilation_height_factor = params.dilation_height_factor; + op_params.dilation_width_factor = params.dilation_width_factor; + op_params.quantized_activation_min = data.output_activation_min; + op_params.quantized_activation_max = data.output_activation_max; + return op_params; +} + +TfLiteStatus CalculateOpDataConv(TfLiteContext* context, TfLiteNode* node, + const TfLiteConvParams& params, int width, + int height, int filter_width, + int filter_height, int out_width, + int out_height, const TfLiteType data_type, + OpDataConv* data) { + bool has_bias = node->inputs->size == 3; + // Check number of inputs/outputs + TF_LITE_ENSURE(context, has_bias || node->inputs->size == 2); + TF_LITE_ENSURE_EQ(context, node->outputs->size, 1); + + // Matching GetWindowedOutputSize in TensorFlow. + auto padding = params.padding; + data->padding = ComputePaddingHeightWidth( + params.stride_height, params.stride_width, params.dilation_height_factor, + params.dilation_width_factor, height, width, filter_height, filter_width, + padding, &out_height, &out_width); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kConvInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = + micro_context->AllocateTempInputTensor(node, kConvWeightsTensor); + TF_LITE_ENSURE(context, filter != nullptr); + TfLiteTensor* bias = + micro_context->AllocateTempInputTensor(node, kConvBiasTensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kConvOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + // Note that quantized inference requires that all tensors have their + // parameters set. This is usually done during quantized training. + if (data_type != kTfLiteFloat32) { + int output_channels = filter->dims->data[kConvQuantizedDimension]; + + TF_LITE_ENSURE_STATUS(tflite::PopulateConvolutionQuantizationParams( + context, input, filter, bias, output, params.activation, + &data->output_multiplier, &data->output_shift, + &data->output_activation_min, &data->output_activation_max, + data->per_channel_output_multiplier, data->per_channel_output_shift, + output_channels)); + } + + data->input_zero_point = input->params.zero_point; + data->filter_zero_point = filter->params.zero_point; + data->output_zero_point = output->params.zero_point; + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(filter); + micro_context->DeallocateTempTfLiteTensor(output); + micro_context->DeallocateTempTfLiteTensor(bias); + + return kTfLiteOk; +} + +TfLiteStatus ConvPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + OpDataConv* data = static_cast(node->user_data); + const auto& params = + *(static_cast(node->builtin_data)); + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kConvOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kConvInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = + micro_context->AllocateTempInputTensor(node, kConvWeightsTensor); + TF_LITE_ENSURE(context, filter != nullptr); + + const int input_width = input->dims->data[2]; + const int input_height = input->dims->data[1]; + const int filter_width = filter->dims->data[2]; + const int filter_height = filter->dims->data[1]; + const int output_width = output->dims->data[2]; + const int output_height = output->dims->data[1]; + + // Dynamically allocate per-channel quantization parameters. + const int num_channels = filter->dims->data[kConvQuantizedDimension]; + data->per_channel_output_multiplier = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + data->per_channel_output_shift = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + + // All per-channel quantized tensors need valid zero point and scale arrays. + if (input->type == kTfLiteInt8 || input->type == kTfLiteInt16) { + TF_LITE_ENSURE_EQ(context, filter->quantization.type, + kTfLiteAffineQuantization); + + const auto* affine_quantization = + static_cast(filter->quantization.params); + TFLITE_DCHECK(affine_quantization != nullptr); + TFLITE_DCHECK(affine_quantization->scale != nullptr); + TFLITE_DCHECK(affine_quantization->zero_point != nullptr); + + TF_LITE_ENSURE(context, + affine_quantization->scale->size == 1 || + affine_quantization->scale->size == + filter->dims->data[kConvQuantizedDimension]); + } + + TF_LITE_ENSURE_STATUS(CalculateOpDataConv( + context, node, params, input_width, input_height, filter_width, + filter_height, output_width, output_height, input->type, data)); + + if (filter->type == kTfLiteInt4) { + int filter_size = + RuntimeShape(filter->dims->size, + reinterpret_cast(filter->dims->data)) + .FlatSize(); + context->RequestScratchBufferInArena(context, filter_size, + &data->filter_buffer_index); + } + + micro_context->DeallocateTempTfLiteTensor(filter); + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv_test.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv_test.h new file mode 100644 index 000000000..47ba8ac40 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/conv_test.h @@ -0,0 +1,113 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_CONV_TEST_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_CONV_TEST_H_ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/kernels/kernel_runner.h" +#include "tensorflow/lite/micro/kernels/micro_ops.h" +#include "tensorflow/lite/micro/test_helpers.h" +#include "tensorflow/lite/micro/testing/micro_test.h" + +namespace tflite { +namespace testing { + +TfLiteStatus InvokeConv(TfLiteTensor* tensors, int tensors_size, + int output_length, TfLiteConvParams* conv_params, + TfLiteRegistration registration, float* output_data); + +TfLiteStatus InvokeConv(TfLiteTensor* tensors, int tensors_size, + int output_length, TfLiteConvParams* conv_params, + TfLiteRegistration registration, int8_t* output_data); + +TfLiteStatus InvokeConv(TfLiteTensor* tensors, int tensors_size, + int output_length, TfLiteConvParams* conv_params, + TfLiteRegistration registration, uint8_t* output_data); + +TfLiteStatus ValidateConvGoldens(TfLiteTensor* tensors, int tensors_size, + const float* expected_output_data, + int output_length, + TfLiteConvParams* conv_params, + TfLiteRegistration registration, + float* output_data, float tolerance = 1e-5); + +TfLiteStatus ValidateConvGoldens(TfLiteTensor* tensors, int tensors_size, + const int8_t* expected_output_data, + int output_length, + TfLiteConvParams* conv_params, + TfLiteRegistration registration, + int8_t* output_data, float tolerance = 1e-5); + +TfLiteStatus ValidateConvGoldens(TfLiteTensor* tensors, int tensors_size, + const uint8_t* expected_output_data, + int output_length, + TfLiteConvParams* conv_params, + TfLiteRegistration registration, + uint8_t* output_data, float tolerance = 1e-5); + +TfLiteStatus TestConvFloat(int* input_dims_data, const float* input_data, + int* filter_dims_data, const float* filter_data, + int* bias_dims_data, const float* bias_data, + int* output_dims_data, + const float* expected_output_data, + TfLiteConvParams* conv_params, + TfLiteRegistration registration, float* output_data); + +TfLiteStatus TestConvQuantizedPerLayer( + int* input_dims_data, const float* input_data, uint8_t* input_quantized, + float input_scale, int* filter_dims_data, const float* filter_data, + uint8_t* filter_quantized, float filter_scale, int* bias_dims_data, + const float* bias_data, int32_t* bias_quantized, int* output_dims_data, + const float* expected_output_data, uint8_t* expected_output_quantized, + float output_scale, TfLiteConvParams* conv_params, + TfLiteRegistration registration, uint8_t* output_data); + +TfLiteStatus TestConvQuantizedPerChannel( + int* input_dims_data, const float* input_data, int8_t* input_quantized, + float input_scale, int input_zero_point, int* filter_dims_data, + const float* filter_data, int8_t* filter_data_quantized, + int* bias_dims_data, const float* bias_data, int32_t* bias_data_quantized, + float* bias_scales, int* bias_zero_points, int* output_dims_data, + const float* expected_output_data, int8_t* expected_output_data_quantized, + float output_scale, int output_zero_point, TfLiteConvParams* conv_params, + TfLiteRegistration registration, int8_t* output_data); + +TfLiteStatus TestConvQuantizedPerChannel( + int* input_dims_data, const float* input_data, int16_t* input_quantized, + float input_scale, int input_zero_point, int* filter_dims_data, + const float* filter_data, int8_t* filter_data_quantized, + int* bias_dims_data, const float* bias_data, + std::int64_t* bias_data_quantized, float* bias_scales, + int* bias_zero_points, int* output_dims_data, + const float* expected_output_data, int16_t* expected_output_data_quantized, + float output_scale, int output_zero_point, TfLiteConvParams* conv_params, + TfLiteRegistration registration, int16_t* output_data); + +TfLiteStatus TestConvQuantizedPerChannel( + int* input_dims_data, const float* input_data, int16_t* input_quantized, + float input_scale, int input_zero_point, int* filter_dims_data, + const float* filter_data, int8_t* filter_data_quantized, + int* bias_dims_data, const float* bias_data, int32_t* bias_data_quantized, + float* bias_scales, int* bias_zero_points, int* output_dims_data, + const float* expected_output_data, int16_t* expected_output_data_quantized, + float output_scale, int output_zero_point, TfLiteConvParams* conv_params, + TfLiteRegistration registration, int16_t* output_data); + +} // namespace testing +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_CONV_TEST_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/cumsum.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/cumsum.cc new file mode 100644 index 000000000..4f8a96591 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/cumsum.cc @@ -0,0 +1,175 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/cumsum.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor = 0; +constexpr int kAxisTensor = 1; +constexpr int kOutputTensor = 0; + +constexpr int kCumSumIntegerShift = 20; + +// only used with INT8 tensors +struct OpData { + int32_t output_activation_min; + int32_t output_activation_max; + int32_t input_offset; + int32_t output_offset; + int32_t input_multiplier; + int32_t output_multiplier; + int input_shift; + int output_shift; + int left_shift; +}; + +TfLiteStatus CalculateOpData(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TfLiteTensor* axis = + micro_context->AllocateTempInputTensor(node, kAxisTensor); + + TF_LITE_ENSURE(context, + input->type == kTfLiteFloat32 || input->type == kTfLiteInt8); + TF_LITE_ENSURE_EQ(context, axis->type, kTfLiteInt32); + + TF_LITE_ENSURE_EQ(context, NumElements(axis), 1); + + TF_LITE_ENSURE(context, NumDimensions(input) >= 1); + + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + + TF_LITE_ENSURE_EQ(context, input->type, output->type); + TF_LITE_ENSURE(context, HaveSameShapes(input, output)); + + if (output->type == kTfLiteInt8) { + node->user_data = + context->AllocatePersistentBuffer(context, sizeof(OpData)); + OpData* data = static_cast(node->user_data); + + // 8bit -> 8bit general quantized path, with general rescalings + data->input_offset = -input->params.zero_point; + data->output_offset = output->params.zero_point; + data->left_shift = kCumSumIntegerShift; + const double twice_max_input_scale = + 2 * static_cast(input->params.scale); + const double real_input_multiplier = + static_cast(input->params.scale) / twice_max_input_scale; + const double real_output_multiplier = + twice_max_input_scale / + ((1 << data->left_shift) * static_cast(output->params.scale)); + + QuantizeMultiplierSmallerThanOneExp( + real_input_multiplier, &data->input_multiplier, &data->input_shift); + + QuantizeMultiplierSmallerThanOneExp( + real_output_multiplier, &data->output_multiplier, &data->output_shift); + + TF_LITE_ENSURE_STATUS(CalculateActivationRangeQuantized( + context, kTfLiteActNone, output, &data->output_activation_min, + &data->output_activation_max)); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(axis); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + return CalculateOpData(context, node); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + const TfLiteEvalTensor* axis_tensor = + tflite::micro::GetEvalInput(context, node, kAxisTensor); + + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + auto* cs_params = static_cast(node->builtin_data); + auto input_shape = tflite::micro::GetTensorShape(input); + + int32_t axis = *tflite::micro::GetTensorData(axis_tensor); + if (axis < 0) axis += input_shape.DimensionsCount(); + + if (axis < 0 || axis >= input_shape.DimensionsCount()) { + MicroPrintf("CUMSUM Invalid axis: %d", axis); + return kTfLiteError; + } + + switch (input->type) { + case kTfLiteFloat32: { + reference_ops::CumSum(tflite::micro::GetTensorData(input), + input_shape, axis, cs_params->exclusive, + cs_params->reverse, + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } break; + + case kTfLiteInt8: { + auto* data = static_cast(node->user_data); + ArithmeticParams params; + params.left_shift = data->left_shift; + params.input1_offset = data->input_offset; + params.input1_multiplier = data->input_multiplier; + params.input1_shift = data->input_shift; + params.output_offset = data->output_offset; + params.output_multiplier = data->output_multiplier; + params.output_shift = data->output_shift; + SetActivationParams(data->output_activation_min, + data->output_activation_max, ¶ms); + reference_ops::CumSum(params, tflite::micro::GetTensorData(input), + input_shape, axis, cs_params->exclusive, + cs_params->reverse, + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } break; + + default: { + MicroPrintf("CUMSUM only supports FLOAT32 and INT8, got %s.", + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } + + return kTfLiteError; +} + +} // namespace + +TfLiteRegistration Register_CUMSUM() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depth_to_space.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depth_to_space.cc new file mode 100644 index 000000000..7f229fbf4 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depth_to_space.cc @@ -0,0 +1,142 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/depth_to_space.h" + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +// input/output tensor shape rank associations +constexpr int kBatchRank = 0; +constexpr int kHeightRank = 1; +constexpr int kWidthRank = 2; +constexpr int kDepthRank = 3; + +TfLiteStatus CalculateOpData(TfLiteContext* context, TfLiteNode* node) { + auto* params = + reinterpret_cast(node->builtin_data); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_EQ(context, NumDimensions(input), 4); + + auto data_type = output->type; + TF_LITE_ENSURE(context, + data_type == kTfLiteFloat32 || data_type == kTfLiteInt8); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + const int block_size = params->block_size; + TF_LITE_ENSURE(context, block_size > 0); + const int input_height = input->dims->data[kHeightRank]; + const int input_width = input->dims->data[kWidthRank]; + const int input_channels = input->dims->data[kDepthRank]; + int output_height = input_height * block_size; + int output_width = input_width * block_size; + int output_channels = input_channels / block_size / block_size; + + TF_LITE_ENSURE_EQ(context, input_height, output_height / block_size); + TF_LITE_ENSURE_EQ(context, input_width, output_width / block_size); + TF_LITE_ENSURE_EQ(context, input_channels, + output_channels * block_size * block_size); + + // We must update the output tensor dimensions. + // The dims storage is expected to be the same area in memory + // for both TfLiteTensor and TfLiteEvalTensor. This is important + // because TfLiteTensor in the MicroInterpreter is a temporary + // allocation. For the KernelRunner interpreter, TfLiteEvalTensor + // is a temporary allocation. We must therefore relocate the dims + // from the FlatBuffer to the persistant storage arena. + TfLiteEvalTensor* output_eval = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + TF_LITE_ENSURE_OK(context, tflite::micro::CreateWritableTensorDimsWithCopy( + context, output, output_eval)); + output->dims->data[kBatchRank] = input->dims->data[kBatchRank]; + output->dims->data[kHeightRank] = output_height; + output->dims->data[kWidthRank] = output_width; + output->dims->data[kDepthRank] = output_channels; + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + return CalculateOpData(context, node); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + auto* params = + reinterpret_cast(node->builtin_data); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + tflite::DepthToSpaceParams op_params; + op_params.block_size = static_cast(params->block_size); + + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: + reference_ops::DepthToSpace(op_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt8: + reference_ops::DepthToSpace(op_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("DEPTH_TO_SPACE only supports FLOAT32 and INT8, got %s.", + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_DEPTH_TO_SPACE() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv.cc new file mode 100644 index 000000000..146da07fa --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv.cc @@ -0,0 +1,99 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/depthwise_conv.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/padding.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataConv)); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + auto& params = + *(reinterpret_cast(node->builtin_data)); + const OpDataConv& data = *(static_cast(node->user_data)); + + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kDepthwiseConvOutputTensor); + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kDepthwiseConvInputTensor); + const TfLiteEvalTensor* filter = + tflite::micro::GetEvalInput(context, node, kDepthwiseConvWeightsTensor); + const TfLiteEvalTensor* bias = + (NumInputs(node) == 3) + ? tflite::micro::GetEvalInput(context, node, kDepthwiseConvBiasTensor) + : nullptr; + + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: { + tflite::reference_ops::DepthwiseConv( + DepthwiseConvParamsFloat(params, data), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + case kTfLiteInt8: { + reference_integer_ops::DepthwiseConvPerChannel( + DepthwiseConvParamsQuantized(params, data), + data.per_channel_output_multiplier, data.per_channel_output_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + default: + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_DEPTHWISE_CONV_2D() { + return tflite::micro::RegisterOp(Init, DepthwiseConvPrepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv.h new file mode 100644 index 000000000..562438d7c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv.h @@ -0,0 +1,80 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_DEPTHWISE_CONV_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_DEPTHWISE_CONV_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/micro/kernels/conv.h" + +namespace tflite { + +extern const int kDepthwiseConvInputTensor; +extern const int kDepthwiseConvWeightsTensor; +extern const int kDepthwiseConvBiasTensor; +extern const int kDepthwiseConvOutputTensor; +extern const int kDepthwiseConvQuantizedDimension; + +// Returns a DepthwiseParams struct with all the parameters needed for a +// float computation. +DepthwiseParams DepthwiseConvParamsFloat( + const TfLiteDepthwiseConvParams& params, const OpDataConv& data); + +// Returns a DepthwiseParams struct with all the parameters needed for a +// quantized computation. +DepthwiseParams DepthwiseConvParamsQuantized( + const TfLiteDepthwiseConvParams& params, const OpDataConv& data); + +TfLiteStatus CalculateOpDataDepthwiseConv( + TfLiteContext* context, TfLiteNode* node, + const TfLiteDepthwiseConvParams& params, int width, int height, + int filter_width, int filter_height, int out_width, int out_height, + const TfLiteType data_type, OpDataConv* data); + +TfLiteStatus DepthwiseConvPrepare(TfLiteContext* context, TfLiteNode* node); + +// This is the most generic TfLiteRegistration. The actual supported types may +// still be target dependent. The only requirement is that every implementation +// (reference or optimized) must define this function. +TfLiteRegistration Register_DEPTHWISE_CONV_2D(); + +#if defined(CMSIS_NN) +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int8 activations and int8 weights and uses the latency optimized +// implementations. +TfLiteRegistration Register_DEPTHWISE_CONV_2D_INT8(); + +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int16 activations and int8 weights and uses the latency optimized +// implementations. +TfLiteRegistration Register_DEPTHWISE_CONV_2D_INT16(); + +#else +inline TfLiteRegistration Register_DEPTHWISE_CONV_2D_INT8() { + return Register_DEPTHWISE_CONV_2D(); +} + +inline TfLiteRegistration Register_DEPTHWISE_CONV_2D_INT16() { + return Register_DEPTHWISE_CONV_2D(); +} +#endif + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_DEPTHWISE_CONV_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv_common.cc new file mode 100644 index 000000000..3bf07274e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/depthwise_conv_common.cc @@ -0,0 +1,202 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/padding.h" +#include "tensorflow/lite/micro/kernels/depthwise_conv.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { + +const int kDepthwiseConvInputTensor = 0; +const int kDepthwiseConvWeightsTensor = 1; +const int kDepthwiseConvBiasTensor = 2; +const int kDepthwiseConvOutputTensor = 0; + +// DepthwiseConv is quantized along dimension 3: +// https://www.tensorflow.org/lite/performance/quantization_spec +const int kDepthwiseConvQuantizedDimension = 3; + +// Returns a DepthwiseParams struct with all the parameters needed for a +// float computation. +DepthwiseParams DepthwiseConvParamsFloat( + const TfLiteDepthwiseConvParams& params, const OpDataConv& data) { + DepthwiseParams op_params; + CalculateActivationRange(params.activation, &op_params.float_activation_min, + &op_params.float_activation_max); + op_params.padding_type = tflite::micro::RuntimePaddingType(params.padding); + op_params.padding_values.width = data.padding.width; + op_params.padding_values.height = data.padding.height; + op_params.stride_width = params.stride_width; + op_params.stride_height = params.stride_height; + op_params.dilation_width_factor = params.dilation_width_factor; + op_params.dilation_height_factor = params.dilation_height_factor; + op_params.depth_multiplier = params.depth_multiplier; + return op_params; +} + +// Returns a DepthwiseParams struct with all the parameters needed for a +// quantized computation. +DepthwiseParams DepthwiseConvParamsQuantized( + const TfLiteDepthwiseConvParams& params, const OpDataConv& data) { + DepthwiseParams op_params; + op_params.input_offset = -data.input_zero_point; + op_params.weights_offset = -data.filter_zero_point; + op_params.output_offset = data.output_zero_point; + op_params.output_multiplier = data.output_multiplier; + op_params.output_shift = -data.output_shift; + op_params.padding_type = tflite::micro::RuntimePaddingType(params.padding); + op_params.padding_values.height = data.padding.height; + op_params.padding_values.width = data.padding.width; + op_params.stride_height = params.stride_height; + op_params.stride_width = params.stride_width; + op_params.dilation_height_factor = params.dilation_height_factor; + op_params.dilation_width_factor = params.dilation_width_factor; + op_params.depth_multiplier = params.depth_multiplier; + op_params.quantized_activation_min = data.output_activation_min; + op_params.quantized_activation_max = data.output_activation_max; + return op_params; +} + +TfLiteStatus CalculateOpDataDepthwiseConv( + TfLiteContext* context, TfLiteNode* node, + const TfLiteDepthwiseConvParams& params, int width, int height, + int filter_width, int filter_height, int out_width, int out_height, + const TfLiteType data_type, OpDataConv* data) { + bool has_bias = node->inputs->size == 3; + // Check number of inputs/outputs + TF_LITE_ENSURE(context, has_bias || node->inputs->size == 2); + TF_LITE_ENSURE_EQ(context, node->outputs->size, 1); + + // Matching GetWindowedOutputSize in TensorFlow. + auto padding = params.padding; + data->padding = ComputePaddingHeightWidth( + params.stride_height, params.stride_width, params.dilation_height_factor, + params.dilation_width_factor, height, width, filter_height, filter_width, + padding, &out_height, &out_width); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kConvInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = + micro_context->AllocateTempInputTensor(node, kConvWeightsTensor); + TF_LITE_ENSURE(context, filter != nullptr); + TfLiteTensor* bias = + micro_context->AllocateTempInputTensor(node, kConvBiasTensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kConvOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + // Note that quantized inference requires that all tensors have their + // parameters set. This is usually done during quantized training. + if (data_type != kTfLiteFloat32) { + int output_channels = filter->dims->data[kDepthwiseConvQuantizedDimension]; + + TF_LITE_ENSURE_STATUS(tflite::PopulateConvolutionQuantizationParams( + context, input, filter, bias, output, params.activation, + &data->output_multiplier, &data->output_shift, + &data->output_activation_min, &data->output_activation_max, + data->per_channel_output_multiplier, data->per_channel_output_shift, + output_channels)); + } + + data->input_zero_point = input->params.zero_point; + data->filter_zero_point = filter->params.zero_point; + data->output_zero_point = output->params.zero_point; + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(filter); + micro_context->DeallocateTempTfLiteTensor(bias); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus DepthwiseConvPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + OpDataConv* data = static_cast(node->user_data); + const auto& params = + *(static_cast(node->builtin_data)); + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kDepthwiseConvOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kDepthwiseConvInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = + micro_context->AllocateTempInputTensor(node, kDepthwiseConvWeightsTensor); + TF_LITE_ENSURE(context, filter != nullptr); + + const int input_width = input->dims->data[2]; + const int input_height = input->dims->data[1]; + const int filter_width = filter->dims->data[2]; + const int filter_height = filter->dims->data[1]; + const int output_width = output->dims->data[2]; + const int output_height = output->dims->data[1]; + + // Dynamically allocate per-channel quantization parameters. + const int num_channels = filter->dims->data[kDepthwiseConvQuantizedDimension]; + data->per_channel_output_multiplier = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + data->per_channel_output_shift = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + + // All per-channel quantized tensors need valid zero point and scale arrays. + if (input->type == kTfLiteInt8) { + TF_LITE_ENSURE_EQ(context, filter->quantization.type, + kTfLiteAffineQuantization); + + const auto* affine_quantization = + static_cast(filter->quantization.params); + TFLITE_DCHECK(affine_quantization != nullptr); + TFLITE_DCHECK(affine_quantization->scale != nullptr); + TFLITE_DCHECK(affine_quantization->zero_point != nullptr); + + TF_LITE_ENSURE( + context, affine_quantization->scale->size == 1 || + affine_quantization->scale->size == + filter->dims->data[kDepthwiseConvQuantizedDimension]); + + TF_LITE_ENSURE_EQ(context, affine_quantization->scale->size, + affine_quantization->zero_point->size); + } + + TF_LITE_ENSURE_STATUS(CalculateOpDataDepthwiseConv( + context, node, params, input_width, input_height, filter_width, + filter_height, output_width, output_height, input->type, data)); + + micro_context->DeallocateTempTfLiteTensor(output); + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(filter); + + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize.cc new file mode 100644 index 000000000..f51db508d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize.cc @@ -0,0 +1,88 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/dequantize.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/quantize.h" +#include "tensorflow/lite/kernels/internal/reference/requantize.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/dequantize.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +void* DequantizeInit(TfLiteContext* context, const char* buffer, + size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(DequantizeOpData)); +} + +TfLiteStatus DequantizeEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + DequantizeOpData* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + + if (output->type == kTfLiteFloat32) { + switch (input->type) { + case kTfLiteInt8: + reference_ops::Dequantize(data->quantization_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt16: + reference_ops::Dequantize(data->quantization_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteUInt8: + reference_ops::Dequantize(data->quantization_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else { + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + + return kTfLiteOk; +} + +TfLiteRegistration Register_DEQUANTIZE() { + return tflite::micro::RegisterOp(DequantizeInit, DequantizePrepare, + DequantizeEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize.h new file mode 100644 index 000000000..fe6ec1697 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize.h @@ -0,0 +1,38 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_DEQUANTIZE_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_DEQUANTIZE_H_ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +struct DequantizeOpData { + tflite::DequantizationParams quantization_params; + // The scaling factor from input to output (aka the 'real multiplier') can + // be represented as a fixed point multiplier plus a left shift. + int32_t output_multiplier; + int output_shift; + int32_t output_zero_point; +}; + +TfLiteStatus DequantizePrepare(TfLiteContext* context, TfLiteNode* node); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_DEQUANTIZE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize_common.cc new file mode 100644 index 000000000..438f9cda8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/dequantize_common.cc @@ -0,0 +1,67 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/dequantize.h" +#include "tensorflow/lite/kernels/internal/reference/quantize.h" +#include "tensorflow/lite/kernels/internal/reference/requantize.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/dequantize.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { + +TfLiteStatus DequantizePrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + DequantizeOpData* data = static_cast(node->user_data); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + + // TODO(b/140515557): Add cached dequant to improve hybrid model performance. + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, 0); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor(node, 0); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE(context, input->type == kTfLiteInt8 || + input->type == kTfLiteInt16 || + input->type == kTfLiteUInt8); + TF_LITE_ENSURE(context, output->type == kTfLiteFloat32); + + if (output->type == kTfLiteInt32) { + const double effective_output_scale = + static_cast(input->params.scale) / + static_cast(output->params.scale); + QuantizeMultiplier(effective_output_scale, &data->output_multiplier, + &data->output_shift); + } + + data->quantization_params.zero_point = input->params.zero_point; + data->quantization_params.scale = static_cast(input->params.scale); + data->output_zero_point = output->params.zero_point; + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/detection_postprocess.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/detection_postprocess.cc new file mode 100644 index 000000000..7aadbbf85 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/detection_postprocess.cc @@ -0,0 +1,807 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flexbuffers.h" +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { + +/** + * This version of detection_postprocess is specific to TFLite Micro. It + * contains the following differences between the TFLite version: + * + * 1.) Temporaries (temporary tensors) - Micro use instead scratch buffer API. + * 2.) Output dimensions - the TFLite version does not support undefined out + * dimensions. So model must have static out dimensions. + */ + +// Input tensors +constexpr int kInputTensorBoxEncodings = 0; +constexpr int kInputTensorClassPredictions = 1; +constexpr int kInputTensorAnchors = 2; + +// Output tensors +constexpr int kOutputTensorDetectionBoxes = 0; +constexpr int kOutputTensorDetectionClasses = 1; +constexpr int kOutputTensorDetectionScores = 2; +constexpr int kOutputTensorNumDetections = 3; + +constexpr int kNumCoordBox = 4; +constexpr int kBatchSize = 1; + +constexpr int kNumDetectionsPerClass = 100; + +// Object Detection model produces axis-aligned boxes in two formats: +// BoxCorner represents the lower left corner (xmin, ymin) and +// the upper right corner (xmax, ymax). +// CenterSize represents the center (xcenter, ycenter), height and width. +// BoxCornerEncoding and CenterSizeEncoding are related as follows: +// ycenter = y / y_scale * anchor.h + anchor.y; +// xcenter = x / x_scale * anchor.w + anchor.x; +// half_h = 0.5*exp(h/ h_scale)) * anchor.h; +// half_w = 0.5*exp(w / w_scale)) * anchor.w; +// ymin = ycenter - half_h +// ymax = ycenter + half_h +// xmin = xcenter - half_w +// xmax = xcenter + half_w +struct BoxCornerEncoding { + float ymin; + float xmin; + float ymax; + float xmax; +}; + +struct CenterSizeEncoding { + float y; + float x; + float h; + float w; +}; +// We make sure that the memory allocations are contiguous with static_assert. +static_assert(sizeof(BoxCornerEncoding) == sizeof(float) * kNumCoordBox, + "Size of BoxCornerEncoding is 4 float values"); +static_assert(sizeof(CenterSizeEncoding) == sizeof(float) * kNumCoordBox, + "Size of CenterSizeEncoding is 4 float values"); + +struct OpData { + int max_detections; + int max_classes_per_detection; // Fast Non-Max-Suppression + int detections_per_class; // Regular Non-Max-Suppression + float non_max_suppression_score_threshold; + float intersection_over_union_threshold; + int num_classes; + bool use_regular_non_max_suppression; + CenterSizeEncoding scale_values; + + // Scratch buffers indexes + int active_candidate_idx; + int decoded_boxes_idx; + int scores_idx; + int score_buffer_idx; + int keep_scores_idx; + int scores_after_regular_non_max_suppression_idx; + int sorted_values_idx; + int keep_indices_idx; + int sorted_indices_idx; + int buffer_idx; + int selected_idx; + + // Cached tensor scale and zero point values for quantized operations + TfLiteQuantizationParams input_box_encodings; + TfLiteQuantizationParams input_class_predictions; + TfLiteQuantizationParams input_anchors; +}; + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + OpData* op_data = nullptr; + + const uint8_t* buffer_t = reinterpret_cast(buffer); + const flexbuffers::Map& m = flexbuffers::GetRoot(buffer_t, length).AsMap(); + op_data = reinterpret_cast( + context->AllocatePersistentBuffer(context, sizeof(OpData))); + + op_data->max_detections = m["max_detections"].AsInt32(); + op_data->max_classes_per_detection = m["max_classes_per_detection"].AsInt32(); + if (m["detections_per_class"].IsNull()) + op_data->detections_per_class = kNumDetectionsPerClass; + else + op_data->detections_per_class = m["detections_per_class"].AsInt32(); + if (m["use_regular_nms"].IsNull()) + op_data->use_regular_non_max_suppression = false; + else + op_data->use_regular_non_max_suppression = m["use_regular_nms"].AsBool(); + + op_data->non_max_suppression_score_threshold = + m["nms_score_threshold"].AsFloat(); + op_data->intersection_over_union_threshold = m["nms_iou_threshold"].AsFloat(); + op_data->num_classes = m["num_classes"].AsInt32(); + op_data->scale_values.y = m["y_scale"].AsFloat(); + op_data->scale_values.x = m["x_scale"].AsFloat(); + op_data->scale_values.h = m["h_scale"].AsFloat(); + op_data->scale_values.w = m["w_scale"].AsFloat(); + + return op_data; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + auto* op_data = static_cast(node->user_data); + + MicroContext* micro_context = GetMicroContext(context); + + // Inputs: box_encodings, scores, anchors + TF_LITE_ENSURE_EQ(context, NumInputs(node), 3); + TfLiteTensor* input_box_encodings = + micro_context->AllocateTempInputTensor(node, kInputTensorBoxEncodings); + TfLiteTensor* input_class_predictions = + micro_context->AllocateTempInputTensor(node, + kInputTensorClassPredictions); + TfLiteTensor* input_anchors = + micro_context->AllocateTempInputTensor(node, kInputTensorAnchors); + TF_LITE_ENSURE_EQ(context, NumDimensions(input_box_encodings), 3); + TF_LITE_ENSURE_EQ(context, NumDimensions(input_class_predictions), 3); + TF_LITE_ENSURE_EQ(context, NumDimensions(input_anchors), 2); + + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 4); + const int num_boxes = input_box_encodings->dims->data[1]; + const int num_classes = op_data->num_classes; + + op_data->input_box_encodings.scale = input_box_encodings->params.scale; + op_data->input_box_encodings.zero_point = + input_box_encodings->params.zero_point; + op_data->input_class_predictions.scale = + input_class_predictions->params.scale; + op_data->input_class_predictions.zero_point = + input_class_predictions->params.zero_point; + op_data->input_anchors.scale = input_anchors->params.scale; + op_data->input_anchors.zero_point = input_anchors->params.zero_point; + + // Scratch tensors + context->RequestScratchBufferInArena(context, num_boxes, + &op_data->active_candidate_idx); + context->RequestScratchBufferInArena(context, + num_boxes * kNumCoordBox * sizeof(float), + &op_data->decoded_boxes_idx); + context->RequestScratchBufferInArena( + context, + input_class_predictions->dims->data[1] * + input_class_predictions->dims->data[2] * sizeof(float), + &op_data->scores_idx); + + // Additional buffers + context->RequestScratchBufferInArena(context, num_boxes * sizeof(float), + &op_data->score_buffer_idx); + context->RequestScratchBufferInArena(context, num_boxes * sizeof(float), + &op_data->keep_scores_idx); + context->RequestScratchBufferInArena( + context, op_data->max_detections * num_boxes * sizeof(float), + &op_data->scores_after_regular_non_max_suppression_idx); + context->RequestScratchBufferInArena( + context, op_data->max_detections * num_boxes * sizeof(float), + &op_data->sorted_values_idx); + context->RequestScratchBufferInArena(context, num_boxes * sizeof(int), + &op_data->keep_indices_idx); + context->RequestScratchBufferInArena( + context, op_data->max_detections * num_boxes * sizeof(int), + &op_data->sorted_indices_idx); + int buffer_size = std::max(num_classes, op_data->max_detections); + context->RequestScratchBufferInArena( + context, buffer_size * num_boxes * sizeof(int), &op_data->buffer_idx); + buffer_size = std::min(num_boxes, op_data->max_detections); + context->RequestScratchBufferInArena( + context, buffer_size * num_boxes * sizeof(int), &op_data->selected_idx); + + // Outputs: detection_boxes, detection_scores, detection_classes, + // num_detections + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 4); + + micro_context->DeallocateTempTfLiteTensor(input_box_encodings); + micro_context->DeallocateTempTfLiteTensor(input_class_predictions); + micro_context->DeallocateTempTfLiteTensor(input_anchors); + + return kTfLiteOk; +} + +class Dequantizer { + public: + Dequantizer(int zero_point, float scale) + : zero_point_(zero_point), scale_(scale) {} + float operator()(uint8_t x) { + return (static_cast(x) - zero_point_) * scale_; + } + + private: + int zero_point_; + float scale_; +}; + +template +T ReInterpretTensor(const TfLiteEvalTensor* tensor) { + const float* tensor_base = tflite::micro::GetTensorData(tensor); + return reinterpret_cast(tensor_base); +} + +template +T ReInterpretTensor(TfLiteEvalTensor* tensor) { + float* tensor_base = tflite::micro::GetTensorData(tensor); + return reinterpret_cast(tensor_base); +} + +TfLiteStatus DecodeCenterSizeBoxes(TfLiteContext* context, TfLiteNode* node, + OpData* op_data) { + // Parse input tensor boxencodings + const TfLiteEvalTensor* input_box_encodings = + tflite::micro::GetEvalInput(context, node, kInputTensorBoxEncodings); + TF_LITE_ENSURE_EQ(context, input_box_encodings->dims->data[0], kBatchSize); + const int num_boxes = input_box_encodings->dims->data[1]; + TF_LITE_ENSURE(context, input_box_encodings->dims->data[2] >= kNumCoordBox); + const TfLiteEvalTensor* input_anchors = + tflite::micro::GetEvalInput(context, node, kInputTensorAnchors); + + // Decode the boxes to get (ymin, xmin, ymax, xmax) based on the anchors + CenterSizeEncoding box_centersize; + CenterSizeEncoding scale_values = op_data->scale_values; + CenterSizeEncoding anchor; + for (int idx = 0; idx < num_boxes; ++idx) { + switch (input_box_encodings->type) { + // Float + case kTfLiteFloat32: { + // Please see DequantizeBoxEncodings function for the support detail. + const int box_encoding_idx = idx * input_box_encodings->dims->data[2]; + const float* boxes = &(tflite::micro::GetTensorData( + input_box_encodings)[box_encoding_idx]); + box_centersize = *reinterpret_cast(boxes); + anchor = + ReInterpretTensor(input_anchors)[idx]; + break; + } + default: + // Unsupported type. + return kTfLiteError; + } + + float ycenter = static_cast(static_cast(box_centersize.y) / + static_cast(scale_values.y) * + static_cast(anchor.h) + + static_cast(anchor.y)); + + float xcenter = static_cast(static_cast(box_centersize.x) / + static_cast(scale_values.x) * + static_cast(anchor.w) + + static_cast(anchor.x)); + + float half_h = + static_cast(0.5 * + (std::exp(static_cast(box_centersize.h) / + static_cast(scale_values.h))) * + static_cast(anchor.h)); + float half_w = + static_cast(0.5 * + (std::exp(static_cast(box_centersize.w) / + static_cast(scale_values.w))) * + static_cast(anchor.w)); + + float* decoded_boxes = reinterpret_cast( + context->GetScratchBuffer(context, op_data->decoded_boxes_idx)); + auto& box = reinterpret_cast(decoded_boxes)[idx]; + box.ymin = ycenter - half_h; + box.xmin = xcenter - half_w; + box.ymax = ycenter + half_h; + box.xmax = xcenter + half_w; + } + return kTfLiteOk; +} + +void DecreasingPartialArgSort(const float* values, int num_values, + int num_to_sort, int* indices) { + std::iota(indices, indices + num_values, 0); + std::partial_sort(indices, indices + num_to_sort, indices + num_values, + [&values](const int i, const int j) { + return std::tie(values[i], j) > std::tie(values[j], i); + }); +} + +template +void InsertionSort(int* start, int* end, Compare compare) { + for (int* i = start; i != end; ++i) { + std::rotate(std::upper_bound(start, i, *i, compare), i, i + 1); + } +} + +template +void TopDownMerge(int* values, int* scratch, const int half_num_values, + int num_values, Compare compare) { + int left = 0; + int right = half_num_values; + + for (int i = 0; i < num_values; i++) { + if (left >= half_num_values || + (right < num_values && compare(values[right], values[left]))) { + scratch[i] = values[right++]; + } else { + scratch[i] = values[left++]; + } + } + memcpy(values, scratch, num_values * sizeof(int)); +} + +template +void MergeSort(int* values, int* scratch, const int num_values, + Compare compare) { + constexpr int threshold = 20; + + if (num_values < threshold) { + InsertionSort(values, values + num_values, compare); + return; + } + + const int half_num_values = num_values / 2; + + MergeSort(values, scratch, half_num_values, compare); + MergeSort(values + half_num_values, scratch, num_values - half_num_values, + compare); + TopDownMerge(values, scratch, half_num_values, num_values, compare); +} + +void DecreasingArgSort(const float* values, int num_values, int* indices, + int* scratch) { + std::iota(indices, indices + num_values, 0); + + MergeSort(indices, scratch, num_values, [&values](const int i, const int j) { + return values[i] > values[j]; + }); +} + +int SelectDetectionsAboveScoreThreshold(const float* values, int size, + const float threshold, + float* keep_values, int* keep_indices) { + int counter = 0; + for (int i = 0; i < size; i++) { + if (values[i] >= threshold) { + keep_values[counter] = values[i]; + keep_indices[counter] = i; + counter++; + } + } + return counter; +} + +bool ValidateBoxes(const float* decoded_boxes, const int num_boxes) { + for (int i = 0; i < num_boxes; ++i) { + // ymax>=ymin, xmax>=xmin + auto& box = reinterpret_cast(decoded_boxes)[i]; + if (box.ymin >= box.ymax || box.xmin >= box.xmax) { + return false; + } + } + return true; +} + +float ComputeIntersectionOverUnion(const float* decoded_boxes, const int i, + const int j) { + auto& box_i = reinterpret_cast(decoded_boxes)[i]; + auto& box_j = reinterpret_cast(decoded_boxes)[j]; + const float area_i = (box_i.ymax - box_i.ymin) * (box_i.xmax - box_i.xmin); + const float area_j = (box_j.ymax - box_j.ymin) * (box_j.xmax - box_j.xmin); + if (area_i <= 0 || area_j <= 0) return 0.0; + const float intersection_ymin = std::max(box_i.ymin, box_j.ymin); + const float intersection_xmin = std::max(box_i.xmin, box_j.xmin); + const float intersection_ymax = std::min(box_i.ymax, box_j.ymax); + const float intersection_xmax = std::min(box_i.xmax, box_j.xmax); + const float intersection_area = + std::max(intersection_ymax - intersection_ymin, 0.0) * + std::max(intersection_xmax - intersection_xmin, 0.0); + return intersection_area / (area_i + area_j - intersection_area); +} + +// NonMaxSuppressionSingleClass() prunes out the box locations with high overlap +// before selecting the highest scoring boxes (max_detections in number) +// It assumes all boxes are good in beginning and sorts based on the scores. +// If lower-scoring box has too much overlap with a higher-scoring box, +// we get rid of the lower-scoring box. +// Complexity is O(N^2) pairwise comparison between boxes +TfLiteStatus NonMaxSuppressionSingleClassHelper( + TfLiteContext* context, TfLiteNode* node, OpData* op_data, + const float* scores, int* selected, int* selected_size, + int max_detections) { + const TfLiteEvalTensor* input_box_encodings = + tflite::micro::GetEvalInput(context, node, kInputTensorBoxEncodings); + const int num_boxes = input_box_encodings->dims->data[1]; + const float non_max_suppression_score_threshold = + op_data->non_max_suppression_score_threshold; + const float intersection_over_union_threshold = + op_data->intersection_over_union_threshold; + // Maximum detections should be positive. + TF_LITE_ENSURE(context, (max_detections >= 0)); + // intersection_over_union_threshold should be positive + // and should be less than 1. + TF_LITE_ENSURE(context, (intersection_over_union_threshold > 0.0f) && + (intersection_over_union_threshold <= 1.0f)); + // Validate boxes + float* decoded_boxes = reinterpret_cast( + context->GetScratchBuffer(context, op_data->decoded_boxes_idx)); + + TF_LITE_ENSURE(context, ValidateBoxes(decoded_boxes, num_boxes)); + + // threshold scores + int* keep_indices = reinterpret_cast( + context->GetScratchBuffer(context, op_data->keep_indices_idx)); + float* keep_scores = reinterpret_cast( + context->GetScratchBuffer(context, op_data->keep_scores_idx)); + int num_scores_kept = SelectDetectionsAboveScoreThreshold( + scores, num_boxes, non_max_suppression_score_threshold, keep_scores, + keep_indices); + int* sorted_indices = reinterpret_cast( + context->GetScratchBuffer(context, op_data->sorted_indices_idx)); + + // Reusing keep_indices for scratch buffer and write back its values + // after the sorting is done. + DecreasingArgSort(keep_scores, num_scores_kept, sorted_indices, keep_indices); + int counter = 0; + for (int i = 0; i < num_boxes; i++) { + if (scores[i] >= non_max_suppression_score_threshold) { + keep_indices[counter] = i; + counter++; + } + } + + const int num_boxes_kept = num_scores_kept; + const int output_size = std::min(num_boxes_kept, max_detections); + *selected_size = 0; + + int num_active_candidate = num_boxes_kept; + uint8_t* active_box_candidate = reinterpret_cast( + context->GetScratchBuffer(context, op_data->active_candidate_idx)); + + for (int row = 0; row < num_boxes_kept; row++) { + active_box_candidate[row] = 1; + } + for (int i = 0; i < num_boxes_kept; ++i) { + if (num_active_candidate == 0 || *selected_size >= output_size) break; + if (active_box_candidate[i] == 1) { + selected[(*selected_size)++] = keep_indices[sorted_indices[i]]; + active_box_candidate[i] = 0; + num_active_candidate--; + } else { + continue; + } + for (int j = i + 1; j < num_boxes_kept; ++j) { + if (active_box_candidate[j] == 1) { + float intersection_over_union = ComputeIntersectionOverUnion( + decoded_boxes, keep_indices[sorted_indices[i]], + keep_indices[sorted_indices[j]]); + + if (intersection_over_union > intersection_over_union_threshold) { + active_box_candidate[j] = 0; + num_active_candidate--; + } + } + } + } + + return kTfLiteOk; +} + +// This function implements a regular version of Non Maximal Suppression (NMS) +// for multiple classes where +// 1) we do NMS separately for each class across all anchors and +// 2) keep only the highest anchor scores across all classes +// 3) The worst runtime of the regular NMS is O(K*N^2) +// where N is the number of anchors and K the number of +// classes. +TfLiteStatus NonMaxSuppressionMultiClassRegularHelper(TfLiteContext* context, + TfLiteNode* node, + OpData* op_data, + const float* scores) { + const TfLiteEvalTensor* input_box_encodings = + tflite::micro::GetEvalInput(context, node, kInputTensorBoxEncodings); + const TfLiteEvalTensor* input_class_predictions = + tflite::micro::GetEvalInput(context, node, kInputTensorClassPredictions); + TfLiteEvalTensor* detection_boxes = + tflite::micro::GetEvalOutput(context, node, kOutputTensorDetectionBoxes); + TfLiteEvalTensor* detection_classes = tflite::micro::GetEvalOutput( + context, node, kOutputTensorDetectionClasses); + TfLiteEvalTensor* detection_scores = + tflite::micro::GetEvalOutput(context, node, kOutputTensorDetectionScores); + TfLiteEvalTensor* num_detections = + tflite::micro::GetEvalOutput(context, node, kOutputTensorNumDetections); + + const int num_boxes = input_box_encodings->dims->data[1]; + const int num_classes = op_data->num_classes; + const int num_detections_per_class = op_data->detections_per_class; + const int max_detections = op_data->max_detections; + const int num_classes_with_background = + input_class_predictions->dims->data[2]; + // The row index offset is 1 if background class is included and 0 otherwise. + int label_offset = num_classes_with_background - num_classes; + TF_LITE_ENSURE(context, num_detections_per_class > 0); + + // For each class, perform non-max suppression. + float* class_scores = reinterpret_cast( + context->GetScratchBuffer(context, op_data->score_buffer_idx)); + int* box_indices_after_regular_non_max_suppression = reinterpret_cast( + context->GetScratchBuffer(context, op_data->buffer_idx)); + float* scores_after_regular_non_max_suppression = + reinterpret_cast(context->GetScratchBuffer( + context, op_data->scores_after_regular_non_max_suppression_idx)); + + int size_of_sorted_indices = 0; + int* sorted_indices = reinterpret_cast( + context->GetScratchBuffer(context, op_data->sorted_indices_idx)); + float* sorted_values = reinterpret_cast( + context->GetScratchBuffer(context, op_data->sorted_values_idx)); + + for (int col = 0; col < num_classes; col++) { + for (int row = 0; row < num_boxes; row++) { + // Get scores of boxes corresponding to all anchors for single class + class_scores[row] = + *(scores + row * num_classes_with_background + col + label_offset); + } + // Perform non-maximal suppression on single class + int selected_size = 0; + int* selected = reinterpret_cast( + context->GetScratchBuffer(context, op_data->selected_idx)); + TF_LITE_ENSURE_STATUS(NonMaxSuppressionSingleClassHelper( + context, node, op_data, class_scores, selected, &selected_size, + num_detections_per_class)); + // Add selected indices from non-max suppression of boxes in this class + int output_index = size_of_sorted_indices; + for (int i = 0; i < selected_size; i++) { + int selected_index = selected[i]; + + box_indices_after_regular_non_max_suppression[output_index] = + (selected_index * num_classes_with_background + col + label_offset); + scores_after_regular_non_max_suppression[output_index] = + class_scores[selected_index]; + output_index++; + } + // Sort the max scores among the selected indices + // Get the indices for top scores + int num_indices_to_sort = std::min(output_index, max_detections); + DecreasingPartialArgSort(scores_after_regular_non_max_suppression, + output_index, num_indices_to_sort, sorted_indices); + + // Copy values to temporary vectors + for (int row = 0; row < num_indices_to_sort; row++) { + int temp = sorted_indices[row]; + sorted_indices[row] = box_indices_after_regular_non_max_suppression[temp]; + sorted_values[row] = scores_after_regular_non_max_suppression[temp]; + } + // Copy scores and indices from temporary vectors + for (int row = 0; row < num_indices_to_sort; row++) { + box_indices_after_regular_non_max_suppression[row] = sorted_indices[row]; + scores_after_regular_non_max_suppression[row] = sorted_values[row]; + } + size_of_sorted_indices = num_indices_to_sort; + } + + // Allocate output tensors + for (int output_box_index = 0; output_box_index < max_detections; + output_box_index++) { + if (output_box_index < size_of_sorted_indices) { + const int anchor_index = floor( + box_indices_after_regular_non_max_suppression[output_box_index] / + num_classes_with_background); + const int class_index = + box_indices_after_regular_non_max_suppression[output_box_index] - + anchor_index * num_classes_with_background - label_offset; + const float selected_score = + scores_after_regular_non_max_suppression[output_box_index]; + // detection_boxes + float* decoded_boxes = reinterpret_cast( + context->GetScratchBuffer(context, op_data->decoded_boxes_idx)); + ReInterpretTensor(detection_boxes)[output_box_index] = + reinterpret_cast(decoded_boxes)[anchor_index]; + // detection_classes + tflite::micro::GetTensorData(detection_classes)[output_box_index] = + class_index; + // detection_scores + tflite::micro::GetTensorData(detection_scores)[output_box_index] = + selected_score; + } else { + ReInterpretTensor( + detection_boxes)[output_box_index] = {0.0f, 0.0f, 0.0f, 0.0f}; + // detection_classes + tflite::micro::GetTensorData(detection_classes)[output_box_index] = + 0.0f; + // detection_scores + tflite::micro::GetTensorData(detection_scores)[output_box_index] = + 0.0f; + } + } + tflite::micro::GetTensorData(num_detections)[0] = + size_of_sorted_indices; + + return kTfLiteOk; +} + +// This function implements a fast version of Non Maximal Suppression for +// multiple classes where +// 1) we keep the top-k scores for each anchor and +// 2) during NMS, each anchor only uses the highest class score for sorting. +// 3) Compared to standard NMS, the worst runtime of this version is O(N^2) +// instead of O(KN^2) where N is the number of anchors and K the number of +// classes. +TfLiteStatus NonMaxSuppressionMultiClassFastHelper(TfLiteContext* context, + TfLiteNode* node, + OpData* op_data, + const float* scores) { + const TfLiteEvalTensor* input_box_encodings = + tflite::micro::GetEvalInput(context, node, kInputTensorBoxEncodings); + const TfLiteEvalTensor* input_class_predictions = + tflite::micro::GetEvalInput(context, node, kInputTensorClassPredictions); + TfLiteEvalTensor* detection_boxes = + tflite::micro::GetEvalOutput(context, node, kOutputTensorDetectionBoxes); + + TfLiteEvalTensor* detection_classes = tflite::micro::GetEvalOutput( + context, node, kOutputTensorDetectionClasses); + TfLiteEvalTensor* detection_scores = + tflite::micro::GetEvalOutput(context, node, kOutputTensorDetectionScores); + TfLiteEvalTensor* num_detections = + tflite::micro::GetEvalOutput(context, node, kOutputTensorNumDetections); + + const int num_boxes = input_box_encodings->dims->data[1]; + const int num_classes = op_data->num_classes; + const int max_categories_per_anchor = op_data->max_classes_per_detection; + const int num_classes_with_background = + input_class_predictions->dims->data[2]; + + // The row index offset is 1 if background class is included and 0 otherwise. + int label_offset = num_classes_with_background - num_classes; + TF_LITE_ENSURE(context, (max_categories_per_anchor > 0)); + const int num_categories_per_anchor = + std::min(max_categories_per_anchor, num_classes); + float* max_scores = reinterpret_cast( + context->GetScratchBuffer(context, op_data->score_buffer_idx)); + int* sorted_class_indices = reinterpret_cast( + context->GetScratchBuffer(context, op_data->buffer_idx)); + + for (int row = 0; row < num_boxes; row++) { + const float* box_scores = + scores + row * num_classes_with_background + label_offset; + int* class_indices = sorted_class_indices + row * num_classes; + DecreasingPartialArgSort(box_scores, num_classes, num_categories_per_anchor, + class_indices); + max_scores[row] = box_scores[class_indices[0]]; + } + + // Perform non-maximal suppression on max scores + int selected_size = 0; + int* selected = reinterpret_cast( + context->GetScratchBuffer(context, op_data->selected_idx)); + TF_LITE_ENSURE_STATUS(NonMaxSuppressionSingleClassHelper( + context, node, op_data, max_scores, selected, &selected_size, + op_data->max_detections)); + + // Allocate output tensors + int output_box_index = 0; + + for (int i = 0; i < selected_size; i++) { + int selected_index = selected[i]; + + const float* box_scores = + scores + selected_index * num_classes_with_background + label_offset; + const int* class_indices = + sorted_class_indices + selected_index * num_classes; + + for (int col = 0; col < num_categories_per_anchor; ++col) { + int box_offset = num_categories_per_anchor * output_box_index + col; + + // detection_boxes + float* decoded_boxes = reinterpret_cast( + context->GetScratchBuffer(context, op_data->decoded_boxes_idx)); + ReInterpretTensor(detection_boxes)[box_offset] = + reinterpret_cast(decoded_boxes)[selected_index]; + + // detection_classes + tflite::micro::GetTensorData(detection_classes)[box_offset] = + class_indices[col]; + + // detection_scores + tflite::micro::GetTensorData(detection_scores)[box_offset] = + box_scores[class_indices[col]]; + + output_box_index++; + } + } + + tflite::micro::GetTensorData(num_detections)[0] = output_box_index; + return kTfLiteOk; +} + +TfLiteStatus NonMaxSuppressionMultiClass(TfLiteContext* context, + TfLiteNode* node, OpData* op_data) { + // Get the input tensors + const TfLiteEvalTensor* input_box_encodings = + tflite::micro::GetEvalInput(context, node, kInputTensorBoxEncodings); + const TfLiteEvalTensor* input_class_predictions = + tflite::micro::GetEvalInput(context, node, kInputTensorClassPredictions); + const int num_boxes = input_box_encodings->dims->data[1]; + const int num_classes = op_data->num_classes; + + TF_LITE_ENSURE_EQ(context, input_class_predictions->dims->data[0], + kBatchSize); + TF_LITE_ENSURE_EQ(context, input_class_predictions->dims->data[1], num_boxes); + const int num_classes_with_background = + input_class_predictions->dims->data[2]; + + TF_LITE_ENSURE(context, (num_classes_with_background - num_classes <= 1)); + TF_LITE_ENSURE(context, (num_classes_with_background >= num_classes)); + + const float* scores; + switch (input_class_predictions->type) { + case kTfLiteFloat32: + scores = tflite::micro::GetTensorData(input_class_predictions); + break; + default: + // Unsupported type. + return kTfLiteError; + } + + if (op_data->use_regular_non_max_suppression) { + TF_LITE_ENSURE_STATUS(NonMaxSuppressionMultiClassRegularHelper( + context, node, op_data, scores)); + } else { + TF_LITE_ENSURE_STATUS( + NonMaxSuppressionMultiClassFastHelper(context, node, op_data, scores)); + } + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE(context, (kBatchSize == 1)); + auto* op_data = static_cast(node->user_data); + + // These two functions correspond to two blocks in the Object Detection model. + // In future, we would like to break the custom op in two blocks, which is + // currently not feasible because we would like to input quantized inputs + // and do all calculations in float. Mixed quantized/float calculations are + // currently not supported in TFLite. + + // This fills in temporary decoded_boxes + // by transforming input_box_encodings and input_anchors from + // CenterSizeEncodings to BoxCornerEncoding + TF_LITE_ENSURE_STATUS(DecodeCenterSizeBoxes(context, node, op_data)); + + // This fills in the output tensors + // by choosing effective set of decoded boxes + // based on Non Maximal Suppression, i.e. selecting + // highest scoring non-overlapping boxes. + TF_LITE_ENSURE_STATUS(NonMaxSuppressionMultiClass(context, node, op_data)); + + return kTfLiteOk; +} +} // namespace + +TfLiteRegistration* Register_DETECTION_POSTPROCESS() { + static TfLiteRegistration r = tflite::micro::RegisterOp(Init, Prepare, Eval); + return &r; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/detection_postprocess_flexbuffers_generated_data.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/detection_postprocess_flexbuffers_generated_data.h new file mode 100644 index 000000000..f5b9eae01 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/detection_postprocess_flexbuffers_generated_data.h @@ -0,0 +1,25 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_FLEXBUFFERS_GENERATED_DATA_H +#define TENSORFLOW_LITE_MICRO_KERNELS_FLEXBUFFERS_GENERATED_DATA_H + +extern const int g_gen_data_size_none_regular_nms; +extern const unsigned char g_gen_data_none_regular_nms[]; + +extern const int g_gen_data_size_regular_nms; +extern const unsigned char g_gen_data_regular_nms[]; + +#endif diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/div.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/div.cc new file mode 100644 index 000000000..5c9861269 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/div.cc @@ -0,0 +1,208 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/div.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor1 = 0; +constexpr int kInputTensor2 = 1; +constexpr int kOutputTensor = 0; + +struct OpDataDiv { + // Parameters used in the quantized paths where the output is 8bit + int32_t input1_zero_point; + int32_t input2_zero_point; + int32_t output_zero_point; + int32_t output_activation_min; + int32_t output_activation_max; + + // Parameters used in all quantized paths + int32_t output_multiplier; + int output_shift; +}; + +TfLiteStatus CalculateOpDataDiv(TfLiteContext* context, TfLiteTensor* input1, + TfLiteTensor* input2, TfLiteTensor* output, + TfLiteDivParams* params, OpDataDiv* data) { + TF_LITE_ENSURE_TYPES_EQ(context, input1->type, input2->type); + TF_LITE_ENSURE_TYPES_EQ(context, input1->type, output->type); + + if (output->type == kTfLiteInt8) { + TF_LITE_ENSURE_STATUS(CalculateActivationRangeQuantized( + context, params->activation, output, &data->output_activation_min, + &data->output_activation_max)); + const double real_multiplier = static_cast( + input1->params.scale / (input2->params.scale * output->params.scale)); + QuantizeMultiplier(real_multiplier, &data->output_multiplier, + &data->output_shift); + data->input1_zero_point = input1->params.zero_point; + data->input2_zero_point = input2->params.zero_point; + data->output_zero_point = output->params.zero_point; + } + + return kTfLiteOk; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataDiv)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input1 = + micro_context->AllocateTempInputTensor(node, kInputTensor1); + TF_LITE_ENSURE(context, input1 != nullptr); + TfLiteTensor* input2 = + micro_context->AllocateTempInputTensor(node, kInputTensor2); + TF_LITE_ENSURE(context, input2 != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + OpDataDiv* data = static_cast(node->user_data); + auto* params = reinterpret_cast(node->builtin_data); + + TF_LITE_ENSURE_STATUS( + CalculateOpDataDiv(context, input1, input2, output, params, data)); + + micro_context->DeallocateTempTfLiteTensor(input1); + micro_context->DeallocateTempTfLiteTensor(input2); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +void EvalDiv(TfLiteContext* context, TfLiteNode* node, TfLiteDivParams* params, + const OpDataDiv* data, const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params = {}; + +#define TF_LITE_DIV(type, opname, data_type) \ + data_type output_activation_min, output_activation_max; \ + CalculateActivationRange(params->activation, &output_activation_min, \ + &output_activation_max); \ + SetActivationParams(output_activation_min, output_activation_max, \ + &op_params); \ + type::opname(op_params, tflite::micro::GetTensorShape(input1), \ + tflite::micro::GetTensorData(input1), \ + tflite::micro::GetTensorShape(input2), \ + tflite::micro::GetTensorData(input2), \ + tflite::micro::GetTensorShape(output), \ + tflite::micro::GetTensorData(output)) + + bool requires_broadcast = reference_ops::ProcessBroadcastShapes( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), &op_params); + + if (requires_broadcast) { + TF_LITE_DIV(reference_ops, BroadcastDivSlow, float); + } else { + TF_LITE_DIV(reference_ops, Div, float); + } +#undef TF_LITE_DIV +} + +TfLiteStatus EvalQuantized(TfLiteContext* context, TfLiteNode* node, + TfLiteDivParams* params, const OpDataDiv* data, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params = {}; + +#define TF_LITE_DIV(type, opname, dtype) \ + type::opname(op_params, tflite::micro::GetTensorShape(input1), \ + tflite::micro::GetTensorData(input1), \ + tflite::micro::GetTensorShape(input2), \ + tflite::micro::GetTensorData(input2), \ + tflite::micro::GetTensorShape(output), \ + tflite::micro::GetTensorData(output)) + + if (input1->type == kTfLiteInt8 && input2->type == kTfLiteInt8 && + output->type == kTfLiteInt8) { + SetActivationParams(data->output_activation_min, + data->output_activation_max, &op_params); + op_params.input1_offset = -data->input1_zero_point; + op_params.input2_offset = -data->input2_zero_point; + op_params.output_offset = data->output_zero_point; + op_params.output_multiplier = data->output_multiplier; + op_params.output_shift = data->output_shift; + + bool requires_broadcast = reference_ops::ProcessBroadcastShapes( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), &op_params); + + if (requires_broadcast) { + TF_LITE_DIV(reference_ops, BroadcastDivSlow, int8_t); + } else { + TF_LITE_DIV(reference_ops, Div, int8_t); + } +#undef TF_LITE_DIV + } else { + MicroPrintf("Unsupported combination of input and output types in DIV."); + return kTfLiteError; + } + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + auto* params = static_cast(node->builtin_data); + TFLITE_DCHECK(node->user_data != nullptr); + auto* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + if (output->type == kTfLiteFloat32) { + EvalDiv(context, node, params, data, input1, input2, output); + } else if (output->type == kTfLiteInt8) { + TF_LITE_ENSURE_OK(context, EvalQuantized(context, node, params, data, + input1, input2, output)); + } else { + MicroPrintf( + "DIV only supports FLOAT32, quantized INT8 " + "now, got type %s (%d).", + TfLiteTypeGetName(output->type), output->type); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_DIV() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/elementwise.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/elementwise.cc new file mode 100644 index 000000000..81b27039f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/elementwise.cc @@ -0,0 +1,430 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace elementwise { +namespace { + +constexpr int kAbsNameId = 0; +constexpr int kRsrqtNameId = 1; + +const int kElementwiseInputTensor = 0; +const int kElementwiseOutputTensor = 0; + +struct OpDataAbsRsqrt { + int32_t multiplier; + int shift; + int input_offset; + int output_offset; + bool needs_rescale; + TfLiteQuantizationType input_quantization_type; + TfLiteType input_type; +}; + +bool IsNumericSupportedType(const TfLiteType type) { + return type == kTfLiteFloat32; +} + +bool IsLogicalSupportedType(const TfLiteType type) { + return type == kTfLiteBool; +} + +bool IsAbsSupportedType(const TfLiteType type) { + return type == kTfLiteFloat32 || type == kTfLiteInt8 || type == kTfLiteInt16; +} + +bool IsRsqrtSupportedType(const TfLiteType type) { + return type == kTfLiteFloat32 || type == kTfLiteInt8; +} + +inline void SetAbsOutputMultiplier(const float input_scale, + const float output_scale, + int32_t* multiplier, int* shift) { + QuantizeMultiplier(static_cast(input_scale / output_scale), + multiplier, shift); +} + +inline void SetRsqrtOutputMultiplier(const float input_scale, + const float output_scale, + int32_t* multiplier, int* shift) { + const double scale = + 1. / static_cast((std::sqrt(input_scale) * output_scale)); + QuantizeMultiplier(scale, multiplier, shift); +} + +typedef bool (*IsSupportedType)(TfLiteType); +template +TfLiteStatus GenericPrepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kElementwiseInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kElementwiseOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + if (!IsSupportedType(input->type)) { + MicroPrintf("Input data type %s (%d) is not supported.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +typedef bool (*IsSupportedType)(TfLiteType); +template +TfLiteStatus PrepareAbsRsqrt(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, 0); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor(node, 0); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + if (!IsSupportedType(input->type)) { + MicroPrintf("Input data type %s (%d) is not supported.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + + auto* op_data = static_cast(node->user_data); + op_data->input_type = input->type; + + // For int16 type input, we support both quantized and non-quantized + // evaluation. + if (op_nameid == kAbsNameId) { + op_data->input_quantization_type = input->quantization.type; + } + + if (input->type == kTfLiteInt8 || + (input->type == kTfLiteInt16 && + input->quantization.type != kTfLiteNoQuantization)) { + TF_LITE_ENSURE_EQ(context, input->quantization.type, + kTfLiteAffineQuantization); + TF_LITE_ENSURE_EQ(context, output->quantization.type, + kTfLiteAffineQuantization); + const auto* input_params = + reinterpret_cast(input->quantization.params); + const auto* output_params = reinterpret_cast( + output->quantization.params); + TF_LITE_ENSURE(context, input_params != nullptr); + TF_LITE_ENSURE(context, input_params->scale != nullptr); + TF_LITE_ENSURE(context, input_params->scale->size > 0); + TF_LITE_ENSURE(context, input_params->zero_point->size > 0); + TF_LITE_ENSURE(context, output_params != nullptr); + TF_LITE_ENSURE(context, output_params->scale != nullptr); + TF_LITE_ENSURE(context, output_params->scale->size > 0); + TF_LITE_ENSURE(context, output_params->zero_point->size > 0); + op_data->input_offset = input_params->zero_point->data[0]; + op_data->output_offset = output_params->zero_point->data[0]; + if (input->type == kTfLiteInt16) { + TF_LITE_ENSURE_EQ(context, op_data->input_offset, 0); + TF_LITE_ENSURE_EQ(context, op_data->output_offset, 0); + } + const float input_scale = input_params->scale->data[0]; + const float output_scale = output_params->scale->data[0]; + op_data->needs_rescale = input_scale != output_scale; + if (op_nameid == kAbsNameId && op_data->needs_rescale) { + SetAbsOutputMultiplier(input_scale, output_scale, &op_data->multiplier, + &op_data->shift); + } else if (op_nameid == kRsrqtNameId) { + SetRsqrtOutputMultiplier(input_scale, output_scale, &op_data->multiplier, + &op_data->shift); + } + } + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +template +inline TfLiteStatus EvalImplQuantized( + TfLiteContext* context, TfLiteNode* node, + T func(TfLiteContext*, TfLiteNode*, T), + TfLiteStatus validate_input_func(TfLiteContext*, TfLiteNode*, T), + TfLiteType expected_type) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, expected_type); + const size_t num_elements = ElementCount(*input->dims); + const T* in_data = tflite::micro::GetTensorData(input); + T* out_data = tflite::micro::GetTensorData(output); + for (size_t i = 0; i < num_elements; ++i) { + if (validate_input_func) { + TF_LITE_ENSURE_OK(context, + validate_input_func(context, node, in_data[i])); + } + out_data[i] = func(context, node, in_data[i]); + } + return kTfLiteOk; +} + +template +inline T AbsHelper(T i) { + return std::abs(i); +} + +template +inline TfLiteStatus EvalImpl(TfLiteContext* context, TfLiteNode* node, + T func(T), TfLiteStatus validate_input_func(T), + TfLiteType expected_type) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, expected_type); + const size_t num_elements = ElementCount(*input->dims); + const T* in_data = tflite::micro::GetTensorData(input); + T* out_data = tflite::micro::GetTensorData(output); + for (size_t i = 0; i < num_elements; ++i) { + if (validate_input_func) { + TF_LITE_ENSURE_OK(context, validate_input_func(in_data[i])); + } + out_data[i] = func(in_data[i]); + } + return kTfLiteOk; +} + +inline TfLiteStatus EvalNumeric(TfLiteContext* context, TfLiteNode* node, + float float_func(float)) { + return EvalImpl(context, node, float_func, + /*validate_input_func=*/nullptr, kTfLiteFloat32); +} + +inline TfLiteStatus EvalLogical(TfLiteContext* context, TfLiteNode* node, + + bool bool_func(bool)) { + return EvalImpl(context, node, bool_func, + /*validate_input_func=*/nullptr, kTfLiteBool); +} + +void* ElementWiseAbsRsqrtInit(TfLiteContext* context, const char* buffer, + size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataAbsRsqrt)); +} + +template +inline T AbsEvalQuantized(TfLiteContext* context, TfLiteNode* node, T i) { + const auto* op_data = static_cast(node->user_data); + const int kMin = std::numeric_limits::min(); + const int kMax = std::numeric_limits::max(); + + const int32_t value = std::abs(i - op_data->input_offset); + if (!op_data->needs_rescale) { + return static_cast( + std::min(std::max(static_cast(value + op_data->output_offset), + static_cast(kMin)), + static_cast(kMax))); + } + + const int32_t output = tflite::MultiplyByQuantizedMultiplier( + value, op_data->multiplier, op_data->shift) + + op_data->output_offset; + return static_cast(std::min( + std::max(static_cast(output), static_cast(kMin)), + static_cast(kMax))); +} + +template +inline T RsqrtEvalQuantized(TfLiteContext* context, TfLiteNode* node, T i) { + const auto* op_data = static_cast(node->user_data); + const int kMin = std::numeric_limits::min(); + const int kMax = std::numeric_limits::max(); + + const int32_t value = (i - op_data->input_offset); + const int32_t kShift = 20; // Shift to keep value integer. + if (value == 0) { + // Assume that any value close to 0 represents the max output value. + return static_cast(kMax); + } + int32_t inv_sqrt_multiplier; + int inv_sqrt_shift; + GetInvSqrtQuantizedMultiplierExp(value, kReverseShift, &inv_sqrt_multiplier, + &inv_sqrt_shift); + const int32_t data = tflite::MultiplyByQuantizedMultiplier( + static_cast(1), inv_sqrt_multiplier, inv_sqrt_shift + kShift); + const int32_t output = + tflite::MultiplyByQuantizedMultiplier(data, op_data->multiplier, + op_data->shift - kShift) + + op_data->output_offset; + return static_cast(std::min( + std::max(static_cast(output), static_cast(kMin)), + static_cast(kMax))); +} + +template +TfLiteStatus validate_input_func(TfLiteContext* context, TfLiteNode* node, + T i) { + const auto* op_data = static_cast(node->user_data); + + TF_LITE_ENSURE_MSG(context, i >= op_data->input_offset, + "Rsqrt is only defined for positive values"); + return static_cast(kTfLiteOk); +} + +TfLiteStatus AbsEval(TfLiteContext* context, TfLiteNode* node) { + OpDataAbsRsqrt* op_data = reinterpret_cast(node->user_data); + TfLiteType type = op_data->input_type; + TfLiteQuantizationType input_quantization_type = + op_data->input_quantization_type; + TfLiteStatus eval_result; + + switch (type) { + case kTfLiteFloat32: + eval_result = EvalNumeric(context, node, std::abs); + break; + case kTfLiteInt8: + eval_result = + EvalImplQuantized(context, node, AbsEvalQuantized, + /*validate_input_func=*/nullptr, type); + break; + case kTfLiteInt16: + eval_result = + input_quantization_type == kTfLiteNoQuantization + ? EvalImpl(context, node, AbsHelper, + /*validate_input_func=*/nullptr, type) + : EvalImplQuantized(context, node, AbsEvalQuantized, + /*validate_input_func=*/nullptr, + type); + break; + default: + MicroPrintf("Current data type %s is not supported.", + TfLiteTypeGetName(type)); + return kTfLiteError; + break; + } + return eval_result; +} + +TfLiteStatus SinEval(TfLiteContext* context, TfLiteNode* node) { + return EvalNumeric(context, node, std::sin); +} + +TfLiteStatus CosEval(TfLiteContext* context, TfLiteNode* node) { + return EvalNumeric(context, node, std::cos); +} + +TfLiteStatus LogEval(TfLiteContext* context, TfLiteNode* node) { + return EvalNumeric(context, node, std::log); +} + +TfLiteStatus SqrtEval(TfLiteContext* context, TfLiteNode* node) { + return EvalNumeric(context, node, std::sqrt); +} + +TfLiteStatus RsqrtEval(TfLiteContext* context, TfLiteNode* node) { + const auto* op_data = static_cast(node->user_data); + TfLiteType type = op_data->input_type; + switch (type) { + case kTfLiteFloat32: + return EvalImpl( + context, node, [](float f) { return 1.f / std::sqrt(f); }, + /*validate_input_func=*/nullptr, type); + case kTfLiteInt8: + return EvalImplQuantized(context, node, + elementwise::RsqrtEvalQuantized, + elementwise::validate_input_func, type); + + default: + MicroPrintf("Current data type %s is not supported.", + TfLiteTypeGetName(type)); + return kTfLiteError; + } +} + +TfLiteStatus SquareEval(TfLiteContext* context, TfLiteNode* node) { + return EvalNumeric(context, node, [](float f) { return f * f; }); +} + +TfLiteStatus LogicalNotEval(TfLiteContext* context, TfLiteNode* node) { + return EvalLogical(context, node, [](bool v) { return !v; }); +} + +} // namespace +} // namespace elementwise + +TfLiteRegistration Register_ABS() { + return tflite::micro::RegisterOp( + elementwise::ElementWiseAbsRsqrtInit, + elementwise::PrepareAbsRsqrt, + elementwise::AbsEval); +} + +TfLiteRegistration Register_SIN() { + return tflite::micro::RegisterOp( + nullptr, elementwise::GenericPrepare, + elementwise::SinEval); +} + +TfLiteRegistration Register_COS() { + return tflite::micro::RegisterOp( + nullptr, elementwise::GenericPrepare, + elementwise::CosEval); +} + +TfLiteRegistration Register_LOG() { + return tflite::micro::RegisterOp( + nullptr, elementwise::GenericPrepare, + elementwise::LogEval); +} + +TfLiteRegistration Register_SQRT() { + return tflite::micro::RegisterOp( + nullptr, elementwise::GenericPrepare, + elementwise::SqrtEval); +} + +TfLiteRegistration Register_RSQRT() { + return tflite::micro::RegisterOp( + elementwise::ElementWiseAbsRsqrtInit, + elementwise::PrepareAbsRsqrt, + elementwise::RsqrtEval); +} + +TfLiteRegistration Register_SQUARE() { + return tflite::micro::RegisterOp( + nullptr, elementwise::GenericPrepare, + elementwise::SquareEval); +} + +TfLiteRegistration Register_LOGICAL_NOT() { + return tflite::micro::RegisterOp( + nullptr, elementwise::GenericPrepare, + elementwise::LogicalNotEval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/elu.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/elu.cc new file mode 100644 index 000000000..c4786d6fc --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/elu.cc @@ -0,0 +1,151 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/elu.h" + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +// Input/output tensor index. +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +// OLD-TODO(b/142762739): We should figure out a multi-threading plan for most +// of the activation ops below. + +struct OpData { + int8_t table[256]; +}; + +using TransformFunc = float (*)(float); + +template +void PopulateLookupTable(const TfLiteTensor* input, const TfLiteTensor* output, + const TransformFunc transform, OpData* data) { + if (sizeof(T) != 1) { + MicroPrintf("Lookup table valid only for 8bit"); + TFLITE_ABORT; + } + + const float inverse_scale = 1 / output->params.scale; + int32_t maxval = std::numeric_limits::max(); + int32_t minval = std::numeric_limits::min(); + for (int32_t val = minval; val <= maxval; ++val) { + const float dequantized = + input->params.scale * (val - input->params.zero_point); + const float transformed = transform(dequantized); + const float rescaled = TfLiteRound(transformed * inverse_scale); + const int32_t quantized = + static_cast(rescaled + output->params.zero_point); + data->table[static_cast(static_cast(val))] = + static_cast(std::max(std::min(maxval, quantized), minval)); + } +} + +// OLD-TODO(b/143696793): move this to optimized_ops. +void EvalUsingLookupTable(const OpData* data, const TfLiteEvalTensor* input, + TfLiteEvalTensor* output) { + const int size = MatchingFlatSize(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorShape(output)); + int8_t* output_data = tflite::micro::GetTensorData(output); + const int8_t* input_data = tflite::micro::GetTensorData(input); + + for (int i = 0; i < size; ++i) { + output_data[i] = data->table[static_cast(input_data[i])]; + } +} + +TfLiteStatus CalculateOpData(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + // Use LUT to handle quantized elu path. + if (input->type == kTfLiteInt8) { + OpData* data = static_cast(node->user_data); + TransformFunc transform = [](float value) { + return value < 0.0f ? std::exp(value) - 1.0f : value; + }; + PopulateLookupTable(input, output, transform, data); + } + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +void* EluInit(TfLiteContext* context, const char* buffer, size_t length) { + // This is a builtin op, so we don't use the contents in 'buffer', if any. + // Instead, we allocate a new object to carry information from Prepare() to + // Eval(). + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus EluPrepare(TfLiteContext* context, TfLiteNode* node) { + return CalculateOpData(context, node); +} + +TfLiteStatus EluEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + switch (input->type) { + case kTfLiteFloat32: { + reference_ops::Elu(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } + case kTfLiteInt8: { + const OpData* data = static_cast(node->user_data); + EvalUsingLookupTable(data, input, output); + return kTfLiteOk; + } + default: + MicroPrintf("ELU only supports float32 and int8 currently, got %s.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } +} + +} // namespace + +TfLiteRegistration Register_ELU() { + return tflite::micro::RegisterOp(EluInit, EluPrepare, EluEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/README.md b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/README.md new file mode 100644 index 000000000..b0c215fbd --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/README.md @@ -0,0 +1,11 @@ +# Info + +These are the Espressif chipset specific replacement kernels. +The kernels call optimized routines or reference routines depending upon optimization option selected. + +By default optimizations are selected if available. +To change this behaviour, please make the appropriate `ESP-NN` menu selection after running: + +``` +idf.py menuconfig +``` diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/add.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/add.cc new file mode 100644 index 000000000..f9ee538b9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/add.cc @@ -0,0 +1,203 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/add.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/add.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/add.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +#include + +#if ESP_NN +// #include +#include "esp-nn/include/esp_nn.h" +#endif + +long long add_total_time = 0; + +namespace tflite { + +void EvalAdd(TfLiteContext* context, TfLiteNode* node, TfLiteAddParams* params, + const OpDataAdd* data, const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params; + SetActivationParams(data->output_activation_min_f32, + data->output_activation_max_f32, &op_params); + if (data->requires_broadcast) { + reference_ops::BroadcastAdd4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_ops::Add(op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } +} + +TfLiteStatus EvalAddQuantized(TfLiteContext* context, TfLiteNode* node, + TfLiteAddParams* params, const OpDataAdd* data, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params; + op_params.left_shift = data->left_shift; + op_params.input1_offset = data->input1_offset; + op_params.input1_multiplier = data->input1_multiplier; + op_params.input1_shift = data->input1_shift; + op_params.input2_offset = data->input2_offset; + op_params.input2_multiplier = data->input2_multiplier; + op_params.input2_shift = data->input2_shift; + op_params.output_offset = data->output_offset; + op_params.output_multiplier = data->output_multiplier; + op_params.output_shift = data->output_shift; + SetActivationParams(data->output_activation_min, data->output_activation_max, + &op_params); + bool need_broadcast = reference_ops::ProcessBroadcastShapes( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), &op_params); + + switch (output->type) { + case kTfLiteInt8: { + if (need_broadcast) { + reference_integer_ops::BroadcastAdd4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { +#if ESP_NN + const int8_t *input1_data = tflite::micro::GetTensorData(input1); + const int8_t *input2_data = tflite::micro::GetTensorData(input2); + int8_t *out_data = tflite::micro::GetTensorData(output); + + esp_nn_add_elementwise_s8(input1_data, + input2_data, + data->input1_offset, + data->input2_offset, + data->input1_multiplier, + data->input2_multiplier, + data->input1_shift, + data->input2_shift, + data->left_shift, + out_data, + data->output_offset, + data->output_multiplier, + data->output_shift, + data->output_activation_min, + data->output_activation_max, + MatchingElementsSize(tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorShape(output)) + ); +#else + reference_integer_ops::Add( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +#endif + } + break; + } + case kTfLiteInt16: { + if (need_broadcast) { + reference_ops::BroadcastAdd4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_ops::Add(op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + false); + } + break; + } + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(output->type), output->type); + return kTfLiteError; + } + + return kTfLiteOk; +} + +void* AddInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataAdd)); +} + +TfLiteStatus AddEval(TfLiteContext* context, TfLiteNode* node) { + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataAdd* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kAddInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kAddInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kAddOutputTensor); + + long long start_time = esp_timer_get_time(); + + if (output->type == kTfLiteFloat32) { + EvalAdd(context, node, params, data, input1, input2, output); + } else if (output->type == kTfLiteInt8 || output->type == kTfLiteInt16) { + TF_LITE_ENSURE_OK(context, EvalAddQuantized(context, node, params, data, + input1, input2, output)); + } else { + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(output->type), + output->type); + return kTfLiteError; + } + add_total_time += esp_timer_get_time() - start_time; + + return kTfLiteOk; +} + +TfLiteRegistration Register_ADD() { + return tflite::micro::RegisterOp(AddInit, AddPrepare, AddEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/conv.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/conv.cc new file mode 100644 index 000000000..3782413f0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/conv.cc @@ -0,0 +1,345 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/conv.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/conv.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/conv.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/padding.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +#include + +#if ESP_NN +// #include +#include "esp-nn/include/esp_nn.h" +#endif + + +long long conv_total_time = 0; + +namespace tflite { +namespace { + +struct NodeData { + OpDataConv op_data; +#if ESP_NN + int buffer_idx; +#endif +}; + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(NodeData)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + NodeData* data = static_cast(node->user_data); + const auto& params = + *(static_cast(node->builtin_data)); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kConvInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = + micro_context->AllocateTempInputTensor(node, kConvWeightsTensor); + TF_LITE_ENSURE(context, filter != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kConvOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + const int input_width = input->dims->data[2]; + const int input_height = input->dims->data[1]; + const int filter_width = filter->dims->data[2]; + const int filter_height = filter->dims->data[1]; + const int output_width = output->dims->data[2]; + const int output_height = output->dims->data[1]; + + // Dynamically allocate per-channel quantization parameters. + const int num_channels = filter->dims->data[kConvQuantizedDimension]; + data->op_data.per_channel_output_multiplier = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + data->op_data.per_channel_output_shift = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + + // All per-channel quantized tensors need valid zero point and scale arrays. + if (input->type == kTfLiteInt8) { + TF_LITE_ENSURE_EQ(context, filter->quantization.type, + kTfLiteAffineQuantization); + + const auto* affine_quantization = + static_cast(filter->quantization.params); + TFLITE_DCHECK(affine_quantization != nullptr); + TFLITE_DCHECK(affine_quantization->scale != nullptr); + TFLITE_DCHECK(affine_quantization->zero_point != nullptr); + + TF_LITE_ENSURE(context, + affine_quantization->scale->size == 1 || + affine_quantization->scale->size == + filter->dims->data[kConvQuantizedDimension]); + TF_LITE_ENSURE_EQ(context, affine_quantization->scale->size, + affine_quantization->zero_point->size); + } + + TF_LITE_ENSURE_STATUS(CalculateOpDataConv( + context, node, params, input_width, input_height, filter_width, + filter_height, output_width, output_height, input->type, &data->op_data)); + +#if ESP_NN + if (input->type == kTfLiteInt8) { + data_dims_t input_dims = { + .width = input_width, .height = input_height, + .channels = input->dims->data[3], 1 + }; + data_dims_t output_dims = { + .width = output_width, .height = output_height, + .channels = output->dims->data[3], 1 + }; + data_dims_t filter_dims = {.width = filter_width, .height = filter_height, 0, 0}; + conv_params_t conv_params = { + .in_offset = 0, .out_offset = 0, + .stride = {params.stride_width, params.stride_height}, + .padding = {data->op_data.padding.width, data->op_data.padding.height}, + .dilation = {0, 0}, .activation = {-128, 127} + }; + + int scratch_buf_size = esp_nn_get_conv_scratch_size( + &input_dims, &filter_dims, &output_dims, &conv_params); + if (scratch_buf_size > 0) { + TF_LITE_ENSURE_STATUS(context->RequestScratchBufferInArena( + context, scratch_buf_size, &data->buffer_idx)); + } else { + data->buffer_idx = -1; + } + } +#endif + + micro_context->DeallocateTempTfLiteTensor(output); + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(filter); + + return kTfLiteOk; +} + +#if ESP_NN +// Fixed-point per-channel-quantization convolution Int8 function wrapper. +inline void EvalQuantizedPerChannel( + TfLiteContext* context, TfLiteNode* node, const TfLiteConvParams& params, + const NodeData& data, const TfLiteEvalTensor* input, + const TfLiteEvalTensor* filter, const TfLiteEvalTensor* bias, + TfLiteEvalTensor* output) { + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + + if (dilation_width_factor == 1 && dilation_height_factor == 1) { + // Get parameters. + RuntimeShape filter_shape = tflite::micro::GetTensorShape(filter); + RuntimeShape input_shape = tflite::micro::GetTensorShape(input); + RuntimeShape output_shape = tflite::micro::GetTensorShape(output); + RuntimeShape bias_shape = tflite::micro::GetTensorShape(bias); + + const int8_t *input_data = tflite::micro::GetTensorData(input); + int8_t *output_data = tflite::micro::GetTensorData(output); + + const int32_t input_offset = -data.op_data.input_zero_point; + const int32_t output_offset = data.op_data.output_zero_point; + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int pad_width = data.op_data.padding.width; + const int pad_height = data.op_data.padding.height; + + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + + // Set min and max value of the output. + const int32_t activation_min = data.op_data.output_activation_min; + const int32_t activation_max = data.op_data.output_activation_max; + + // Consistency check. + TFLITE_DCHECK_LE(activation_min, activation_max); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batch_size = MatchingDim(input_shape, 0, output_shape, 0); + const int input_depth = MatchingDim(input_shape, 3, filter_shape, 3); + const int output_depth = MatchingDim(filter_shape, 0, output_shape, 3); + + if (tflite::micro::GetTensorData(bias)) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + + void *scratch_buf = NULL; + if (data.buffer_idx > -1) { + scratch_buf = context->GetScratchBuffer(context, data.buffer_idx); + } + esp_nn_set_conv_scratch_buf(scratch_buf); + + const int input_size = input_width * input_height * input_depth; + const int output_size = output_width * output_height * output_depth; + + data_dims_t input_dims = { + .width = input_width, .height = input_height, + .channels = input_depth, 1 + }; + data_dims_t output_dims = { + .width = output_width, .height = output_height, + .channels = output_depth, 1 + }; + data_dims_t filter_dims = {.width = filter_width, .height = filter_height, 0, 0}; + conv_params_t conv_params = { + .in_offset = input_offset, .out_offset = output_offset, + .stride = {stride_width, stride_height}, + .padding = {pad_width, pad_height}, + .dilation = {0, 0}, + .activation = {activation_min, activation_max} + }; + quant_data_t quant_data = { + .shift = data.op_data.per_channel_output_shift, + .mult = data.op_data.per_channel_output_multiplier + }; + + for (int i_batch = 0; i_batch < batch_size; i_batch++) { + esp_nn_conv_s8(&input_dims, input_data + i_batch * input_size, + &filter_dims, tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorData(bias), + &output_dims, output_data + i_batch * output_size, + &conv_params, &quant_data); + } + } else { + reference_integer_ops::ConvPerChannel( + ConvParamsQuantized(params, data.op_data), + data.op_data.per_channel_output_multiplier, + data.op_data.per_channel_output_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } +} +#endif + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kConvInputTensor); + const TfLiteEvalTensor* filter = + tflite::micro::GetEvalInput(context, node, kConvWeightsTensor); + const TfLiteEvalTensor* bias = + (NumInputs(node) == 3) + ? tflite::micro::GetEvalInput(context, node, kConvBiasTensor) + : nullptr; + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kConvOutputTensor); + + TFLITE_DCHECK(node->builtin_data != nullptr); + const auto& params = + *(reinterpret_cast(node->builtin_data)); + TFLITE_DCHECK(node->user_data != nullptr); + const auto& data = *(static_cast(node->user_data)); + + TF_LITE_ENSURE_EQ(context, input->type, output->type); + TF_LITE_ENSURE_MSG(context, input->type == filter->type, + "Hybrid models are not supported on TFLite Micro."); + + long long start_time = esp_timer_get_time(); + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: { + tflite::reference_ops::Conv( + ConvParamsFloat(params, data.op_data), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + tflite::micro::GetTensorShape(nullptr), nullptr); + break; + } + case kTfLiteInt8: { +#if ESP_NN + EvalQuantizedPerChannel(context, node, params, data, input, filter, + bias, output); +#else + reference_integer_ops::ConvPerChannel( + ConvParamsQuantized(params, data.op_data), + data.op_data.per_channel_output_multiplier, + data.op_data.per_channel_output_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +#endif + break; + } + case kTfLiteUInt8: { + //EvalQuantized + reference_ops::Conv(ConvParamsQuantized(params, data.op_data), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + tflite::micro::GetTensorShape(nullptr), nullptr, + nullptr); + break; + } + default: + TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + long long time_this_instance = esp_timer_get_time() - start_time; + conv_total_time += time_this_instance; + //printf("time this instance: %llu\n", time_this_instance / 1000); + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_CONV_2D() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/depthwise_conv.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/depthwise_conv.cc new file mode 100644 index 000000000..75bfeb638 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/depthwise_conv.cc @@ -0,0 +1,347 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/depthwise_conv.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h" +#include "tensorflow/lite/kernels/internal/reference/depthwiseconv_uint8.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/depthwise_conv.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/padding.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +#include + +#if ESP_NN +// #include +#include "esp-nn/include/esp_nn.h" +#endif + +long long dc_total_time = 0; + +namespace tflite { +namespace { + +struct NodeData { + OpDataConv op_data; +#if ESP_NN + int buffer_idx; +#endif +}; + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(NodeData)); +} + +#if ESP_NN +inline void EvalQuantizedPerChannel(TfLiteContext* context, TfLiteNode* node, + const TfLiteDepthwiseConvParams& params, + const NodeData& data, + const TfLiteEvalTensor* input, + const TfLiteEvalTensor* filter, + const TfLiteEvalTensor* bias, + TfLiteEvalTensor* output) { + const int dilation_width_factor = params.dilation_width_factor; + const int dilation_height_factor = params.dilation_height_factor; + + if (dilation_width_factor == 1 && dilation_height_factor == 1) { + // Get parameters. + RuntimeShape input_shape = tflite::micro::GetTensorShape(input); + RuntimeShape filter_shape = tflite::micro::GetTensorShape(filter); + RuntimeShape output_shape = tflite::micro::GetTensorShape(output); + RuntimeShape bias_shape = tflite::micro::GetTensorShape(bias); + + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + + const int8_t *input_data = tflite::micro::GetTensorData(input); + int8_t *output_data = tflite::micro::GetTensorData(output); + + const int depth_multiplier = params.depth_multiplier; + const int32_t input_offset = -data.op_data.input_zero_point; + const int32_t output_offset = data.op_data.output_zero_point; + const int stride_width = params.stride_width; + const int stride_height = params.stride_height; + const int pad_width = data.op_data.padding.width; + const int pad_height = data.op_data.padding.height; + + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int input_depth = input_shape.Dims(3); + const int filter_height = filter_shape.Dims(1); + const int filter_width = filter_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + + // Set min and max value of the output. + const int32_t activation_min = data.op_data.output_activation_min; + const int32_t activation_max = data.op_data.output_activation_max; + + // Consistency check. + TFLITE_DCHECK_LE(activation_min, activation_max); + const int batch_size = MatchingDim(input_shape, 0, output_shape, 0); + const int output_depth = MatchingDim(filter_shape, 3, output_shape, 3); + + TFLITE_DCHECK_EQ(output_depth, input_depth * depth_multiplier); + if (tflite::micro::GetTensorData(bias)) { + TFLITE_DCHECK_EQ(bias_shape.FlatSize(), output_depth); + } + + const int input_size = input_width * input_height * input_depth; + const int output_size = output_width * output_height * output_depth; + void *scratch_buf = NULL; + if (data.buffer_idx > -1) { + scratch_buf = context->GetScratchBuffer(context, data.buffer_idx); + } + + esp_nn_set_depthwise_conv_scratch_buf(scratch_buf); + + data_dims_t input_dims = { + .width = input_width, .height = input_height, + .channels = input_depth, 1 + }; + data_dims_t output_dims = { + .width = output_width, .height = output_height, + .channels = output_depth, 1 + }; + data_dims_t filter_dims = {.width = filter_width, .height = filter_height, 0, 0}; + dw_conv_params_t conv_params = { + .in_offset = input_offset, .out_offset = output_offset, + .ch_mult = depth_multiplier, + .stride = {stride_width, stride_height}, + .padding = {pad_width, pad_height}, .dilation = {0, 0}, + .activation = {activation_min, activation_max} + }; + quant_data_t quant_data = { + .shift = data.op_data.per_channel_output_shift, + .mult = data.op_data.per_channel_output_multiplier + }; + + for (int i_batch = 0; i_batch < batch_size; i_batch++) { + esp_nn_depthwise_conv_s8(&input_dims, input_data + i_batch * input_size, + &filter_dims, tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorData(bias), + &output_dims, output_data + i_batch * output_size, + &conv_params, &quant_data); + } + } else { + reference_integer_ops::DepthwiseConvPerChannel( + DepthwiseConvParamsQuantized(params, data.op_data), + data.op_data.per_channel_output_multiplier, + data.op_data.per_channel_output_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } +} +#endif + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + NodeData* data = static_cast(node->user_data); + const TfLiteDepthwiseConvParams& params = + *(static_cast(node->builtin_data)); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kConvInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = + micro_context->AllocateTempInputTensor(node, kConvWeightsTensor); + TF_LITE_ENSURE(context, filter != nullptr); + TfLiteTensor* bias = + micro_context->AllocateTempInputTensor(node, kConvBiasTensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kConvOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + const int input_width = input->dims->data[2]; + const int input_height = input->dims->data[1]; + const int filter_width = filter->dims->data[2]; + const int filter_height = filter->dims->data[1]; + const int output_width = output->dims->data[2]; + const int output_height = output->dims->data[1]; + + // Dynamically allocate per-channel quantization parameters. + const int num_channels = filter->dims->data[kDepthwiseConvQuantizedDimension]; + data->op_data.per_channel_output_multiplier = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + data->op_data.per_channel_output_shift = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + + // All per-channel quantized tensors need valid zero point and scale arrays. + if (input->type == kTfLiteInt8) { + TF_LITE_ENSURE_EQ(context, filter->quantization.type, + kTfLiteAffineQuantization); + + const auto* affine_quantization = + static_cast(filter->quantization.params); + TFLITE_DCHECK(affine_quantization != nullptr); + TFLITE_DCHECK(affine_quantization->scale != nullptr); + TFLITE_DCHECK(affine_quantization->zero_point != nullptr); + + TF_LITE_ENSURE( + context, affine_quantization->scale->size == 1 || + affine_quantization->scale->size == + filter->dims->data[kDepthwiseConvQuantizedDimension]); + + TF_LITE_ENSURE_EQ(context, affine_quantization->scale->size, + affine_quantization->zero_point->size); + } + + TF_LITE_ENSURE_STATUS(CalculateOpDataDepthwiseConv( + context, node, params, input_width, input_height, filter_width, + filter_height, output_width, output_height, input->type, &data->op_data)); + +#if ESP_NN + if (input->type == kTfLiteInt8) { + data_dims_t input_dims = { + .width = input_width, .height = input_height, + .channels = input->dims->data[3], 1 + }; + data_dims_t output_dims = { + .width = output_width, .height = output_height, + .channels = output->dims->data[3], 1 + }; + data_dims_t filter_dims = {.width = filter_width, .height = filter_height, 0, 0}; + dw_conv_params_t conv_params = { + .in_offset = 0, .out_offset = 0, + .ch_mult = params.depth_multiplier, + .stride = {params.stride_width, params.stride_height}, + .padding = {data->op_data.padding.width, data->op_data.padding.height}, + .dilation = {0, 0}, .activation = {-128, 127} + }; + + int scratch_buf_size = esp_nn_get_depthwise_conv_scratch_size( + &input_dims, &filter_dims, &output_dims, &conv_params); + if (scratch_buf_size > 0) { + TF_LITE_ENSURE_STATUS(context->RequestScratchBufferInArena( + context, scratch_buf_size, &data->buffer_idx)); + } else { + data->buffer_idx = -1; + } + } +#endif + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(filter); + micro_context->DeallocateTempTfLiteTensor(bias); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + auto& params = + *(reinterpret_cast(node->builtin_data)); + const NodeData& data = *(static_cast(node->user_data)); + + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kDepthwiseConvOutputTensor); + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kDepthwiseConvInputTensor); + const TfLiteEvalTensor* filter = + tflite::micro::GetEvalInput(context, node, kDepthwiseConvWeightsTensor); + const TfLiteEvalTensor* bias = + (NumInputs(node) == 3) + ? tflite::micro::GetEvalInput(context, node, kDepthwiseConvBiasTensor) + : nullptr; + + long long start_time = esp_timer_get_time(); + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: + tflite::reference_ops::DepthwiseConv( + DepthwiseConvParamsFloat(params, data.op_data), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt8: +#if ESP_NN + EvalQuantizedPerChannel(context, node, params, data, input, filter, bias, + output); +#else + reference_integer_ops::DepthwiseConvPerChannel( + DepthwiseConvParamsQuantized(params, data.op_data), + data.op_data.per_channel_output_multiplier, + data.op_data.per_channel_output_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +#endif + break; + case kTfLiteUInt8: + //EvalQuantized(context, node, params, &data, input, filter, bias, output); + reference_ops::DepthwiseConv( + DepthwiseConvParamsQuantized(params, data.op_data), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + default: + TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + long long time_this_instance = esp_timer_get_time() - start_time; + dc_total_time += time_this_instance; + // printf("time this instance: %llu\n", time_this_instance / 1000); + + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_DEPTHWISE_CONV_2D() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/fully_connected.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/fully_connected.cc new file mode 100644 index 000000000..bc102e7c7 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/fully_connected.cc @@ -0,0 +1,193 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/fully_connected.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/fully_connected.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +#if ESP_NN +// #include +#include "esp-nn/include/esp_nn.h" +#endif + +#include + +long long fc_total_time = 0; + +namespace tflite { +namespace { + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, + sizeof(OpDataFullyConnected)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + auto* data = static_cast(node->user_data); + const auto params = + static_cast(node->builtin_data); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kFullyConnectedInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = micro_context->AllocateTempInputTensor( + node, kFullyConnectedWeightsTensor); + TF_LITE_ENSURE(context, filter != nullptr); + TfLiteTensor* bias = + micro_context->AllocateTempInputTensor(node, kFullyConnectedBiasTensor); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor( + node, kFullyConnectedOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + TF_LITE_ENSURE_MSG(context, input->type == filter->type, + "Hybrid models are not supported on TFLite Micro."); + + TF_LITE_ENSURE_OK(context, CalculateOpDataFullyConnected( + context, params->activation, input->type, + input, filter, bias, output, data)); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(filter); + if (bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(bias); + } + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + const auto* params = + static_cast(node->builtin_data); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kFullyConnectedInputTensor); + const TfLiteEvalTensor* filter = + tflite::micro::GetEvalInput(context, node, kFullyConnectedWeightsTensor); + const TfLiteEvalTensor* bias = + tflite::micro::GetEvalInput(context, node, kFullyConnectedBiasTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kFullyConnectedOutputTensor); + + TFLITE_DCHECK(node->user_data != nullptr); + const auto& data = + *(static_cast(node->user_data)); + + long long start_time = esp_timer_get_time(); + // Checks in Prepare ensure input, output and filter types are all the same. + switch (input->type) { + case kTfLiteFloat32: { + tflite::reference_ops::FullyConnected( + FullyConnectedParamsFloat(params->activation), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + + case kTfLiteInt8: { + const int32_t* bias_data = + nullptr != bias ? tflite::micro::GetTensorData(bias) + : nullptr; +#if ESP_NN + const RuntimeShape& filter_shape = tflite::micro::GetTensorShape(filter); + const RuntimeShape& output_shape = tflite::micro::GetTensorShape(output); + const int filter_dim_count = filter_shape.DimensionsCount(); + const int batches = output_shape.Dims(0); + const int output_depth = output_shape.Dims(1); + TFLITE_DCHECK_LE(output_depth, filter_shape.Dims(filter_dim_count - 2)); + const int accum_depth = filter_shape.Dims(filter_dim_count - 1); + + const int8_t *input_data = tflite::micro::GetTensorData(input); + int8_t *output_data = tflite::micro::GetTensorData(output); + const int8_t *filter_data = tflite::micro::GetTensorData(filter); + + for (int b = 0; b < batches; ++b) { + esp_nn_fully_connected_s8(input_data, -data.input_zero_point, + accum_depth, + filter_data, -data.filter_zero_point, + bias_data, output_data, output_depth, + data.output_zero_point, + data.output_shift, data.output_multiplier, + data.output_activation_min, + data.output_activation_max); + input_data += accum_depth; + output_data += output_depth; + } +#else + tflite::reference_integer_ops::FullyConnected( + FullyConnectedParamsQuantized(data), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), bias_data, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +#endif + break; + } + + case kTfLiteUInt8: { + tflite::reference_ops::FullyConnected( + FullyConnectedParamsQuantized(data), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + default: { + TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + } + fc_total_time += esp_timer_get_time() - start_time; + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_FULLY_CONNECTED() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/mul.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/mul.cc new file mode 100644 index 000000000..65618ed59 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/mul.cc @@ -0,0 +1,125 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/mul.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/mul.h" +#include "tensorflow/lite/kernels/internal/reference/mul.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +#if ESP_NN +// #include +#include "esp-nn/include/esp_nn.h" +#endif + +#include + +long long mul_total_time = 0; + +namespace tflite { +#if ESP_NN +void MulEvalQuantized(TfLiteContext* context, TfLiteNode* node, + const OpDataMul* data, const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params = {}; + op_params.quantized_activation_min = data->output_activation_min; + op_params.quantized_activation_max = data->output_activation_max; + op_params.float_activation_max = data->output_activation_max_f32; + op_params.input1_offset = -data->input1_zero_point; + op_params.input2_offset = -data->input2_zero_point; + op_params.output_offset = data->output_zero_point; + op_params.output_multiplier = data->output_multiplier; + op_params.output_shift = data->output_shift; + + bool need_broadcast = reference_ops::ProcessBroadcastShapes( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), &op_params); + + if (need_broadcast) { + reference_integer_ops::BroadcastMul4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + const int8_t *input1_data = tflite::micro::GetTensorData(input1); + const int8_t *input2_data = tflite::micro::GetTensorData(input2); + int8_t *out_data = tflite::micro::GetTensorData(output); + + esp_nn_mul_elementwise_s8(input1_data, input2_data, op_params.input1_offset, + op_params.input2_offset, out_data, op_params.output_offset, + op_params.output_multiplier, op_params.output_shift, + op_params.quantized_activation_min, op_params.quantized_activation_max, + MatchingElementsSize(tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorShape(output))); + } +} +#endif + +TfLiteStatus MulEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataMul* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kMulInput1Tensor); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kMulInput2Tensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kMulOutputTensor); + + long long start_time = esp_timer_get_time(); + switch (input1->type) { + case kTfLiteInt8: +#if ESP_NN + MulEvalQuantized(context, node, data, input1, input2, output); +#else + EvalMulQuantizedReference(context, node, data, input1, input2, output); +#endif + break; + case kTfLiteInt32: + EvalMulQuantizedReference(context, node, data, input1, input2, output); + break; + case kTfLiteFloat32: + EvalMulFloatReference(context, node, params, data, input1, input2, + output); + break; + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(input1->type), input1->type); + return kTfLiteError; + } + mul_total_time += esp_timer_get_time() - start_time; + return kTfLiteOk; +} + +TfLiteRegistration Register_MUL() { + return tflite::micro::RegisterOp(MulInit, MulPrepare, MulEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/pooling.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/pooling.cc new file mode 100644 index 000000000..f7214665d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/pooling.cc @@ -0,0 +1,233 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/pooling.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/pooling.h" +#include "tensorflow/lite/micro/micro_log.h" + +#if ESP_NN +// #include +#include "esp-nn/include/esp_nn.h" +#endif + +#include + +long long pooling_total_time = 0; + +namespace tflite { + +namespace { +#if ESP_NN +void AverageEvalQuantized(TfLiteContext* context, const TfLiteNode* node, + const TfLitePoolParams* params, const OpDataPooling* data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output) { + + const int stride_height = params->stride_height; + const int stride_width = params->stride_width; + const int filter_height = params->filter_height; + const int filter_width = params->filter_width; + const int activation_min = data->activation_min; + const int activation_max = data->activation_max; + const int pad_height = data->padding.height; + const int pad_width = data->padding.width; + + const RuntimeShape& input_shape = tflite::micro::GetTensorShape(input); + const RuntimeShape& output_shape = tflite::micro::GetTensorShape(output); + TFLITE_DCHECK_LE(activation_min, activation_max); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + + const int8_t *input_data = tflite::micro::GetTensorData(input); + int8_t *output_data = tflite::micro::GetTensorData(output); + + const int input_size = input_width * input_height * depth; + const int output_size = output_width * output_height * depth; + + if (depth % 4 == 0) { // S3 version only supports channels multiple of 4 + for (int batch = 0; batch < batches; ++batch) { + esp_nn_avg_pool_s8(input_data, input_width, input_height, + output_data, output_width, output_height, + stride_width, stride_height, + filter_width, filter_height, + pad_width, pad_height, + activation_min, activation_max, depth); + input_data += input_size; + output_data += output_size; + } + } else { + for (int batch = 0; batch < batches; ++batch) { + esp_nn_avg_pool_s8_ansi(input_data, input_width, input_height, + output_data, output_width, output_height, + stride_width, stride_height, + filter_width, filter_height, + pad_width, pad_height, + activation_min, activation_max, depth); + input_data += input_size; + output_data += output_size; + } + } +} + +void MaxEvalQuantized(TfLiteContext* context, TfLiteNode* node, + TfLitePoolParams* params, const OpDataPooling* data, + const TfLiteEvalTensor* input, TfLiteEvalTensor* output) { + + const int stride_height = params->stride_height; + const int stride_width = params->stride_width; + const int filter_height = params->filter_height; + const int filter_width = params->filter_width; + const int activation_min = data->activation_min; + const int activation_max = data->activation_max; + const int pad_height = data->padding.height; + const int pad_width = data->padding.width; + + const RuntimeShape& input_shape = tflite::micro::GetTensorShape(input); + const RuntimeShape& output_shape = tflite::micro::GetTensorShape(output); + TFLITE_DCHECK_LE(activation_min, activation_max); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + + const int8_t *input_data = tflite::micro::GetTensorData(input); + int8_t *output_data = tflite::micro::GetTensorData(output); + + const int input_size = input_width * input_height * depth; + const int output_size = output_width * output_height * depth; + if (depth % 4 == 0) { // S3 version only supports channels multiple of 4 + for (int batch = 0; batch < batches; ++batch) { + esp_nn_max_pool_s8(input_data, input_width, input_height, + output_data, output_width, output_height, + stride_width, stride_height, + filter_width, filter_height, + pad_width, pad_height, + activation_min, activation_max, depth); + input_data += input_size; + output_data += output_size; + } + } else { + for (int batch = 0; batch < batches; ++batch) { + esp_nn_max_pool_s8_ansi(input_data, input_width, input_height, + output_data, output_width, output_height, + stride_width, stride_height, + filter_width, filter_height, + pad_width, pad_height, + activation_min, activation_max, depth); + input_data += input_size; + output_data += output_size; + } + } +} +#endif + +TfLiteStatus AverageEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataPooling* data = + static_cast(node->user_data); + + const TfLiteEvalTensor* input = + micro::GetEvalInput(context, node, kPoolingInputTensor); + TfLiteEvalTensor* output = + micro::GetEvalOutput(context, node, kPoolingOutputTensor); + + long long start_time = esp_timer_get_time(); + // Inputs and outputs share the same type, guaranteed by the converter. + switch (input->type) { + case kTfLiteFloat32: + AveragePoolingEvalFloat(context, node, params, data, input, output); + break; + case kTfLiteInt8: +#if ESP_NN + AverageEvalQuantized(context, node, params, data, input, output); +#else + AveragePoolingEvalQuantized(context, node, params, data, input, output); +#endif + break; + default: + TF_LITE_KERNEL_LOG(context, "Input type %s is not currently supported", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + pooling_total_time += esp_timer_get_time() - start_time; + return kTfLiteOk; +} + +TfLiteStatus MaxEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataPooling* data = + static_cast(node->user_data); + + const TfLiteEvalTensor* input = + micro::GetEvalInput(context, node, kPoolingInputTensor); + TfLiteEvalTensor* output = + micro::GetEvalOutput(context, node, kPoolingOutputTensor); + + long long start_time = esp_timer_get_time(); + switch (input->type) { + case kTfLiteFloat32: + MaxPoolingEvalFloat(context, node, params, data, input, output); + break; + case kTfLiteInt8: +#if ESP_NN + MaxEvalQuantized(context, node, params, data, input, output); +#else + MaxPoolingEvalQuantized(context, node, params, data, input, output); +#endif + break; + default: + TF_LITE_KERNEL_LOG(context, "Type %s not currently supported.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + pooling_total_time += esp_timer_get_time() - start_time; + return kTfLiteOk; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataPooling)); +} + +} // namespace + +TfLiteRegistration Register_AVERAGE_POOL_2D() { + return tflite::micro::RegisterOp(Init, PoolingPrepare, AverageEval); +} + +TfLiteRegistration Register_MAX_POOL_2D() { + return tflite::micro::RegisterOp(Init, PoolingPrepare, MaxEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/softmax.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/softmax.cc new file mode 100644 index 000000000..5748435b6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/esp_nn/softmax.cc @@ -0,0 +1,209 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/softmax.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/softmax.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +#include + +#if ESP_NN +// #include +#include "esp-nn/include/esp_nn.h" +#endif + +long long softmax_total_time = 0; + +namespace tflite { +namespace { +// Softmax parameter data that persists in user_data +const int kInt16LUTArraySize = 513; + +struct NodeData { + SoftmaxParams op_data; +#if ESP_NN + int buffer_idx; +#endif +}; + +static void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(NodeData)); +} + +void SoftmaxQuantized(TfLiteContext* context, const TfLiteEvalTensor* input, + TfLiteEvalTensor* output, const NodeData* data) { + if (input->type == kTfLiteInt8) { + if (output->type == kTfLiteInt16) { + tflite::reference_ops::Softmax( + data->op_data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { +#if ESP_NN + const int32_t input_beta_multiplier = data->op_data.input_multiplier; + const int32_t input_beta_left_shift = data->op_data.input_left_shift; + const int diff_min = data->op_data.diff_min; + const RuntimeShape input_shape = tflite::micro::GetTensorShape(input); + const RuntimeShape output_shape = tflite::micro::GetTensorShape(output); + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + const int8_t *in_ptr = tflite::micro::GetTensorData(input); + int8_t *out_ptr = tflite::micro::GetTensorData(output); + void *scratch_buf = NULL; + if (data->buffer_idx > -1) { + scratch_buf = context->GetScratchBuffer(context, data->buffer_idx); + } + esp_nn_set_softmax_scratch_buf(scratch_buf); + esp_nn_softmax_s8(in_ptr, outer_size, depth, input_beta_multiplier, + input_beta_left_shift, diff_min, out_ptr); +#else + tflite::reference_ops::Softmax( + data->op_data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +#endif + } + } else { + tflite::reference_ops::SoftmaxInt16( + data->op_data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } +} + +static TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + + TFLITE_DCHECK(node->user_data != nullptr); + NodeData data = *static_cast(node->user_data); + + long long start_time = esp_timer_get_time(); + switch (input->type) { + case kTfLiteFloat32: { + tflite::reference_ops::Softmax( + data.op_data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } + break; + case kTfLiteInt8: + case kTfLiteInt16: { + SoftmaxQuantized(context, input, output, &data); + } + break; + default: + TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + softmax_total_time += esp_timer_get_time() - start_time; + return kTfLiteOk; +} + +static TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, 0); + TF_LITE_ENSURE(context, input != nullptr); + TF_LITE_ENSURE(context, NumDimensions(input) >= 1); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor(node, 0); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE(context, node->user_data != nullptr); + NodeData* data = static_cast(node->user_data); + // Only allocate LUTs for KTfLiteInt16 data type + if (input->type == kTfLiteInt16) { + void* raw_exp_lut = context->AllocatePersistentBuffer( + context, sizeof(int16_t) * kInt16LUTArraySize); + TF_LITE_ENSURE(context, raw_exp_lut != nullptr); + data->op_data.exp_lut = reinterpret_cast(raw_exp_lut); + void* one_over_one_plus_x_lut = context->AllocatePersistentBuffer( + context, sizeof(int16_t) * kInt16LUTArraySize); + TF_LITE_ENSURE(context, one_over_one_plus_x_lut != nullptr); + data->op_data.one_over_one_plus_x_lut = + reinterpret_cast(one_over_one_plus_x_lut); + } + + if (output->type == kTfLiteInt16) { + TF_LITE_ENSURE(context, + input->type == kTfLiteInt8 || input->type == kTfLiteInt16); + } else { + TF_LITE_ENSURE_EQ(context, input->type, output->type); + } + + // Populate LUT if required + if (input->type == kTfLiteInt16) { + TF_LITE_ENSURE_EQ(context, output->params.zero_point, 0); + // exp LUT only used on negative values + // we consider exp(-10.0) is insignificant to accumulation + gen_lut( + [](float value) { return std::exp(value); }, -10.0f, 0.0f, -1.0f, 1.0f, + data->op_data.exp_lut); + gen_lut( + [](float value) { return 1.0f / (1.0f + value); }, 0.0f, 1.0f, -1.0f, + 1.0f, data->op_data.one_over_one_plus_x_lut); + data->op_data.zero_point = output->params.zero_point; + data->op_data.scale = output->params.scale; + } + + auto* params = static_cast(node->builtin_data); + auto ret_val = + CalculateSoftmaxParams(context, input, output, params, &data->op_data); + +#if ESP_NN + if (output->type == kTfLiteInt8 && input->type == kTfLiteInt8) { + const int32_t input_width = input->dims->data[1]; + const int32_t input_height = input->dims->data[2]; + int scratch_buf_size = esp_nn_get_softmax_scratch_size(input_width, + input_height); + if (scratch_buf_size > 0) { + TF_LITE_ENSURE_STATUS(context->RequestScratchBufferInArena( + context, scratch_buf_size, &data->buffer_idx)); + } + } +#endif + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return ret_val; +} + +} // namespace + +TfLiteRegistration Register_SOFTMAX() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ethosu.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ethosu.cc new file mode 100644 index 000000000..c305121e8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ethosu.cc @@ -0,0 +1,27 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// +// This is a stub file for non-Ethos platforms +// +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +TfLiteRegistration* Register_ETHOSU() { return nullptr; } + +const char* GetString_ETHOSU() { return ""; } + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ethosu.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ethosu.h new file mode 100644 index 000000000..cfbb0d3f7 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/ethosu.h @@ -0,0 +1,28 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_ETHOSU_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_ETHOSU_H_ + +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +TfLiteRegistration* Register_ETHOSU(); + +const char* GetString_ETHOSU(); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_ETHOSU_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/exp.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/exp.cc new file mode 100644 index 000000000..a835ee0af --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/exp.cc @@ -0,0 +1,79 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/exp.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, kTfLiteFloat32); + TF_LITE_ENSURE_TYPES_EQ(context, output->type, input->type); + TF_LITE_ENSURE_EQ(context, output->bytes, input->bytes); + TF_LITE_ENSURE_EQ(context, output->dims->size, input->dims->size); + for (int i = 0; i < output->dims->size; ++i) { + TF_LITE_ENSURE_EQ(context, output->dims->data[i], input->dims->data[i]); + } + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + int flat_size = MatchingFlatSize(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorShape(output)); + + if (input->type == kTfLiteFloat32) { + reference_ops::Exp(tflite::micro::GetTensorData(input), + static_cast(flat_size), + tflite::micro::GetTensorData(output)); + } else { + MicroPrintf("Type %s (%d) currently not supported by Exp.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + return kTfLiteOk; +} +} // namespace + +TfLiteRegistration Register_EXP() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/expand_dims.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/expand_dims.cc new file mode 100644 index 000000000..ad45dd882 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/expand_dims.cc @@ -0,0 +1,149 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor = 0; +constexpr int kAxisTensor = 1; +constexpr int kOutputTensor = 0; + +TfLiteStatus GetAxisValueFromTensor(TfLiteContext* context, + const TfLiteTensor* axis, + int32_t* axis_value) { + const int axis_dims = (tflite::GetTensorShape(axis)).DimensionsCount(); + if (axis_dims > 1) { + MicroPrintf("Axis has only one element for Expand_Dims.", axis_dims); + return kTfLiteError; + } + + if (kTfLiteInt32 == (axis->type)) { + const int32_t* axis_ptr = tflite::GetTensorData(axis); + *axis_value = axis_ptr[0]; + return kTfLiteOk; + } else { + MicroPrintf("Axis type %s (%d) not supported by Expand_Dims.", + TfLiteTypeGetName(axis->type), axis->type); + return kTfLiteError; + } +} + +// Verifies that the output tensor's dimension shape is equivalent to inserting +// a dimension of length 1 at the dimension index axis of input's shape as +// defined in https://www.tensorflow.org/api_docs/python/tf/expand_dims. +TfLiteStatus VerifyTensorDim(TfLiteContext* context, const TfLiteTensor* input, + const TfLiteTensor* axis_tensor, + const TfLiteTensor* output) { + int32_t axis_value = 0; + TF_LITE_ENSURE_OK(context, + GetAxisValueFromTensor(context, axis_tensor, &axis_value)); + + tflite::RuntimeShape input_shape = tflite::GetTensorShape(input); + if (axis_value < 0) { + axis_value = input_shape.DimensionsCount() + 1 + axis_value; + } + TF_LITE_ENSURE(context, axis_value <= input_shape.DimensionsCount()); + + // TFLM only supports fixed dimension tensor and assumes that the output shape + // is fully specified in the model. As such, TFLM directly use the pointer to + // the dimension array in the model buffer. + tflite::RuntimeShape output_shape = tflite::GetTensorShape(output); + + TF_LITE_ENSURE(context, output_shape.DimensionsCount() == + input_shape.DimensionsCount() + 1); + for (int i = 0; i < output_shape.DimensionsCount(); ++i) { + if (i < axis_value) { + TF_LITE_ENSURE(context, output_shape.Dims(i) == input_shape.Dims(i)); + } else if (i == axis_value) { + TF_LITE_ENSURE(context, output_shape.Dims(i) == 1); + } else { + TF_LITE_ENSURE(context, output_shape.Dims(i) == input_shape.Dims(i - 1)); + } + } + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* axis = + micro_context->AllocateTempInputTensor(node, kAxisTensor); + TF_LITE_ENSURE(context, axis != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + output->type = input->type; + if (IsDynamicTensor(axis)) { + MicroPrintf("DynamicTensor is not yet supported by Expand_Dims."); + return kTfLiteError; + } + TF_LITE_ENSURE_OK(context, VerifyTensorDim(context, input, axis, output)); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(axis); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +template +void memCopyN(T* out, const T* in, const int num_elements) { + for (int i = 0; i < num_elements; ++i) { + out[i] = in[i]; + } +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + const int flat_size = ElementCount(*input->dims); + + switch (input->type) { + case kTfLiteFloat32: { + memCopyN(tflite::micro::GetTensorData(output), + tflite::micro::GetTensorData(input), flat_size); + } break; + case kTfLiteInt8: { + memCopyN(tflite::micro::GetTensorData(output), + tflite::micro::GetTensorData(input), flat_size); + } break; + default: + MicroPrintf( + "Expand_Dims only currently supports int8 and float32, got %d.", + input->type); + return kTfLiteError; + } + return kTfLiteOk; +} +} // namespace + +TfLiteRegistration Register_EXPAND_DIMS() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fill.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fill.cc new file mode 100644 index 000000000..6a3f4998e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fill.cc @@ -0,0 +1,140 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/fill.h" + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +namespace { + +template +TfLiteStatus EnsureEqImpl(TfLiteContext* context, const TfLiteIntArray* array, + const TfLiteTensor* tensor) { + for (int i = 0; i < array->size; ++i) { + TF_LITE_ENSURE_EQ(context, array->data[i], GetTensorData(tensor)[i]); + } + return kTfLiteOk; +} + +// Ensure the equality of an int array and a tensor, which must be +// one-dimensional and of an integer type. +TfLiteStatus EnsureEq(TfLiteContext* context, const TfLiteIntArray* array, + const TfLiteTensor* tensor) { + TF_LITE_ENSURE_EQ(context, NumDimensions(tensor), 1); + const auto tensor_len = tensor->dims->data[0]; + TF_LITE_ENSURE_EQ(context, array->size, tensor_len); + + switch (tensor->type) { + case kTfLiteInt8: + return EnsureEqImpl(context, array, tensor); + case kTfLiteInt16: + return EnsureEqImpl(context, array, tensor); + case kTfLiteInt32: + return EnsureEqImpl(context, array, tensor); + case kTfLiteInt64: + return EnsureEqImpl(context, array, tensor); + default: + MicroPrintf("cannot compare int array to tensor of type %d.", + tensor->type); + return kTfLiteError; + } +} + +constexpr int kDimsTensor = 0; +constexpr int kValueTensor = 1; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + // Ensure inputs and outputs exist. + TfLiteTensor* dims = + micro_context->AllocateTempInputTensor(node, kDimsTensor); + TF_LITE_ENSURE(context, dims != nullptr); + TfLiteTensor* value = + micro_context->AllocateTempInputTensor(node, kValueTensor); + TF_LITE_ENSURE(context, value != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + // The value tensor must be a scalar. + TF_LITE_ENSURE_EQ(context, NumDimensions(value), 0); + + // The value type and output type must match. + TF_LITE_ENSURE_EQ(context, value->type, output->type); + + // The dimension of the output tensor is known in model already. + TFLITE_DCHECK(output->dims != nullptr); + + if (dims->data.data != nullptr) { + // When the dims tensor is specified in model already (i.e. is not an + // activation tensor), the dims tensor must match the output tensor shape. + // As a byproduct, ensures the dims tensor is of an integer type. + TF_LITE_ENSURE_OK(context, EnsureEq(context, output->dims, dims)); + } + + micro_context->DeallocateTempTfLiteTensor(dims); + micro_context->DeallocateTempTfLiteTensor(value); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +template +void FillImpl(const TfLiteEvalTensor* value, TfLiteEvalTensor* output) { + reference_ops::Fill( + micro::GetTensorShape(value), micro::GetTensorData(value), + micro::GetTensorShape(output), micro::GetTensorData(output)); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* value = + micro::GetEvalInput(context, node, kValueTensor); + TfLiteEvalTensor* output = micro::GetEvalOutput(context, node, kOutputTensor); + + switch (value->type) { + case kTfLiteFloat32: + FillImpl(value, output); + break; + case kTfLiteInt32: + FillImpl(value, output); + break; + case kTfLiteInt8: + FillImpl(value, output); + break; + default: + MicroPrintf("Fill only currently supports float32 for input 1, got %d.", + TfLiteTypeGetName(value->type)); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_FILL() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor.cc new file mode 100644 index 000000000..6b2a4cc25 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor.cc @@ -0,0 +1,50 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/floor.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace floor { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, kTfLiteFloat32); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + reference_ops::Floor(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; +} +} // namespace floor + +TfLiteRegistration Register_FLOOR() { + return tflite::micro::RegisterOp(nullptr, nullptr, floor::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor_div.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor_div.cc new file mode 100644 index 000000000..f143d28af --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor_div.cc @@ -0,0 +1,130 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/floor_div.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/reference/binary_function.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { + +// Input/output tensor index. +constexpr int kInputTensor1 = 0; +constexpr int kInputTensor2 = 1; +constexpr int kOutputTensor = 0; + +TfLiteStatus CalculateOpData(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TfLiteTensor* input1 = + micro_context->AllocateTempInputTensor(node, kInputTensor1); + TF_LITE_ENSURE(context, input1 != nullptr); + TfLiteTensor* input2 = + micro_context->AllocateTempInputTensor(node, kInputTensor2); + TF_LITE_ENSURE(context, input2 != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_TYPES_EQ(context, input1->type, input2->type); + TF_LITE_ENSURE_TYPES_EQ(context, input1->type, output->type); + + micro_context->DeallocateTempTfLiteTensor(input1); + micro_context->DeallocateTempTfLiteTensor(input2); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + return nullptr; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + return CalculateOpData(context, node); +} + +template +TfLiteStatus EvalFloorDiv(TfLiteContext* context, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + const T* denominator_data = tflite::micro::GetTensorData(input2); + + // Validate the denominator. + for (int i = 0; i < tflite::ElementCount(*input2->dims); ++i) { + if (std::equal_to()(denominator_data[i], 0)) { + MicroPrintf("Division by 0"); + return kTfLiteError; + } + } + + bool requires_broadcast = !tflite::micro::HaveSameShapes(input1, input2); + + if (requires_broadcast) { + reference_ops::BroadcastBinaryFunction4DSlow( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), denominator_data, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), reference_ops::FloorDiv); + } else { + reference_ops::BinaryFunction( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), denominator_data, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), reference_ops::FloorDiv); + } + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + switch (input1->type) { + case kTfLiteFloat32: { + return EvalFloorDiv(context, input1, input2, output); + } + default: { + MicroPrintf("Type '%s' is not supported by FLOOR_DIV.", + TfLiteTypeGetName(input1->type)); + return kTfLiteError; + } + } +} + +} // namespace + +TfLiteRegistration Register_FLOOR_DIV() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor_mod.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor_mod.cc new file mode 100644 index 000000000..939a4dd78 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/floor_mod.cc @@ -0,0 +1,128 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/floor_mod.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/reference/binary_function.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +// OLD-TODO(b/117523611): We should factor out a binary_op and put binary ops +// there. +namespace tflite { +namespace { + +// Input/output tensor index. +constexpr int kInputTensor1 = 0; +constexpr int kInputTensor2 = 1; +constexpr int kOutputTensor = 0; + +// OLD-TODO(b/117912880): Support quantization. + +TfLiteStatus CalculateOpData(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TfLiteTensor* input1 = + micro_context->AllocateTempInputTensor(node, kInputTensor1); + TF_LITE_ENSURE(context, input1 != nullptr); + TfLiteTensor* input2 = + micro_context->AllocateTempInputTensor(node, kInputTensor2); + TF_LITE_ENSURE(context, input2 != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_TYPES_EQ(context, input1->type, input2->type); + TF_LITE_ENSURE_TYPES_EQ(context, input1->type, output->type); + + micro_context->DeallocateTempTfLiteTensor(input1); + micro_context->DeallocateTempTfLiteTensor(input2); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + return nullptr; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + return CalculateOpData(context, node); +} + +template +TfLiteStatus EvalFloorMod(TfLiteContext* context, bool requires_broadcast, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + const T* denominator_data = tflite::micro::GetTensorData(input2); + + if (requires_broadcast) { + reference_ops::BroadcastBinaryFunction4DSlow( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), denominator_data, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), reference_ops::FloorMod); + } else { + reference_ops::BinaryFunction( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), denominator_data, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), reference_ops::FloorMod); + } + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + bool requires_broadcast = !tflite::micro::HaveSameShapes(input1, input2); + + switch (input1->type) { + case kTfLiteFloat32: { + return EvalFloorMod(context, requires_broadcast, input1, input2, + output); + } + default: { + MicroPrintf("Type '%s' is not supported by FLOOR_MOD.", + TfLiteTypeGetName(input1->type)); + return kTfLiteError; + } + } +} + +} // namespace + +TfLiteRegistration Register_FLOOR_MOD() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected.cc new file mode 100644 index 000000000..6b73f4857 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected.cc @@ -0,0 +1,159 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/fully_connected.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/fully_connected.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, + sizeof(OpDataFullyConnected)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + auto* data = static_cast(node->user_data); + const auto params = + static_cast(node->builtin_data); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kFullyConnectedInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = micro_context->AllocateTempInputTensor( + node, kFullyConnectedWeightsTensor); + TF_LITE_ENSURE(context, filter != nullptr); + TfLiteTensor* bias = + micro_context->AllocateTempInputTensor(node, kFullyConnectedBiasTensor); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor( + node, kFullyConnectedOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + TF_LITE_ENSURE_OK(context, CalculateOpDataFullyConnected( + context, params->activation, input->type, + input, filter, bias, output, data)); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(filter); + if (bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(bias); + } + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + const auto* params = + static_cast(node->builtin_data); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kFullyConnectedInputTensor); + const TfLiteEvalTensor* filter = + tflite::micro::GetEvalInput(context, node, kFullyConnectedWeightsTensor); + const TfLiteEvalTensor* bias = + tflite::micro::GetEvalInput(context, node, kFullyConnectedBiasTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kFullyConnectedOutputTensor); + + TFLITE_DCHECK(node->user_data != nullptr); + const auto& data = + *(static_cast(node->user_data)); + + // Checks in Prepare ensure input, output and filter types are all the same. + switch (input->type) { + case kTfLiteFloat32: { + const float* bias_data = + nullptr != bias ? tflite::micro::GetTensorData(bias) : nullptr; + + tflite::reference_ops::FullyConnected( + FullyConnectedParamsFloat(params->activation), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), bias_data, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + + case kTfLiteInt8: { + const int32_t* bias_data = + nullptr != bias ? tflite::micro::GetTensorData(bias) + : nullptr; + + tflite::reference_integer_ops::FullyConnected( + FullyConnectedParamsQuantized(data), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), bias_data, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + + case kTfLiteInt16: { + const int64_t* bias_data = + nullptr != bias ? tflite::micro::GetTensorData(bias) + : nullptr; + + tflite::reference_integer_ops::FullyConnected( + FullyConnectedParamsQuantized(data), + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), bias_data, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + } + + default: { + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_FULLY_CONNECTED() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected.h new file mode 100644 index 000000000..93026cd59 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected.h @@ -0,0 +1,104 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_FULLY_CONNECTED_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_FULLY_CONNECTED_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +struct OpDataFullyConnected { + // The scaling factor from input to output (aka the 'real multiplier') can + // be represented as a fixed point multiplier plus a left shift. + int32_t output_multiplier; + int output_shift; + // The range of the fused activation layer. For example for kNone and + // uint8_t these would be 0 and 255. + int32_t output_activation_min; + int32_t output_activation_max; + // The index of the temporary tensor where the quantized inputs are cached. + int input_quantized_index; + // Cached zero point values of tensors. + int32_t input_zero_point; + int32_t filter_zero_point; + int32_t output_zero_point; +}; + +extern const int kFullyConnectedInputTensor; +extern const int kFullyConnectedWeightsTensor; +extern const int kFullyConnectedBiasTensor; +extern const int kFullyConnectedOutputTensor; + +// Returns a FullyConnectedParams struct with all the parameters needed for a +// float computation. +FullyConnectedParams FullyConnectedParamsFloat( + TfLiteFusedActivation activation); + +// Returns a FullyConnectedParams struct with all the parameters needed for a +// quantized computation. +FullyConnectedParams FullyConnectedParamsQuantized( + const OpDataFullyConnected& op_data); + +TfLiteStatus CalculateOpDataFullyConnected( + TfLiteContext* context, TfLiteFusedActivation activation, + TfLiteType data_type, const TfLiteTensor* input, const TfLiteTensor* filter, + const TfLiteTensor* bias, TfLiteTensor* output, OpDataFullyConnected* data); + +// This is the most generic TfLiteRegistration. The actual supported types may +// still be target dependent. The only requirement is that every implementation +// (reference or optimized) must define this function. +TfLiteRegistration Register_FULLY_CONNECTED(); + +#if defined(CMSIS_NN) || defined(HEXAGON) +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int8. +TfLiteRegistration Register_FULLY_CONNECTED_INT8(); + +#else +// Note that while this block gets used for both reference and optimized kernels +// that do not have any specialized implementations, the only goal here is to +// define fallback implementation that allow reference kernels to still be used +// from applications that call a more specific kernel variant. + +inline TfLiteRegistration Register_FULLY_CONNECTED_INT8() { + return Register_FULLY_CONNECTED(); +} + +#endif + +#if defined(CMSIS_NN) +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int16. +TfLiteRegistration Register_FULLY_CONNECTED_INT16(); + +#else +// Note that while this block gets used for both reference and optimized kernels +// that do not have any specialized implementations, the only goal here is to +// define fallback implementation that allow reference kernels to still be used +// from applications that call a more specific kernel variant. + +inline TfLiteRegistration Register_FULLY_CONNECTED_INT16() { + return Register_FULLY_CONNECTED(); +} + +#endif + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_FULLY_CONNECTED_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected_common.cc new file mode 100644 index 000000000..e7d0056c3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/fully_connected_common.cc @@ -0,0 +1,83 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/fully_connected.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/fully_connected.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { + +const int kFullyConnectedInputTensor = 0; +const int kFullyConnectedWeightsTensor = 1; +const int kFullyConnectedBiasTensor = 2; +const int kFullyConnectedOutputTensor = 0; + +FullyConnectedParams FullyConnectedParamsQuantized( + const OpDataFullyConnected& op_data) { + FullyConnectedParams op_params; + op_params.input_offset = -op_data.input_zero_point; + op_params.weights_offset = -op_data.filter_zero_point; + op_params.output_offset = op_data.output_zero_point; + op_params.output_multiplier = op_data.output_multiplier; + op_params.output_shift = op_data.output_shift; + op_params.quantized_activation_min = op_data.output_activation_min; + op_params.quantized_activation_max = op_data.output_activation_max; + return op_params; +} + +FullyConnectedParams FullyConnectedParamsFloat( + TfLiteFusedActivation activation) { + FullyConnectedParams op_params; + CalculateActivationRange(activation, &op_params.float_activation_min, + &op_params.float_activation_max); + return op_params; +} + +TfLiteStatus CalculateOpDataFullyConnected( + TfLiteContext* context, TfLiteFusedActivation activation, + TfLiteType data_type, const TfLiteTensor* input, const TfLiteTensor* filter, + const TfLiteTensor* bias, TfLiteTensor* output, + OpDataFullyConnected* data) { + if (data_type != kTfLiteFloat32) { + double real_multiplier = 0.0; + TF_LITE_ENSURE_STATUS(GetQuantizedConvolutionMultipler( + context, input, filter, bias, output, &real_multiplier)); + QuantizeMultiplier(real_multiplier, &data->output_multiplier, + &data->output_shift); + + data->input_zero_point = input->params.zero_point; + // Filter weights will always be symmetric quantized since we only support + // int8 quantization. See + // https://github.com/tensorflow/tensorflow/issues/44912 for additional + // context. + TFLITE_DCHECK(filter->params.zero_point == 0); + data->filter_zero_point = filter->params.zero_point; + data->output_zero_point = output->params.zero_point; + + return CalculateActivationRangeQuantized(context, activation, output, + &data->output_activation_min, + &data->output_activation_max); + } + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/gather.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/gather.cc new file mode 100644 index 000000000..4ec534731 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/gather.cc @@ -0,0 +1,224 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor = 0; +constexpr int kInputPositions = 1; +constexpr int kOutputTensor = 0; + +template +TfLiteStatus Gather(const TfLiteGatherParams* params, + const TfLiteEvalTensor* input, + const TfLiteEvalTensor* coords, TfLiteEvalTensor* output) { + const InputT* input_data = tflite::micro::GetTensorData(input); + const CoordsT* coords_data = tflite::micro::GetTensorData(coords); + InputT* output_data = tflite::micro::GetTensorData(output); + const TfLiteIntArray* input_dims = input->dims; + const int input_dims_size = input_dims->size; + int axis = params->axis; + if (axis < 0) { + axis += input_dims_size; + } + TFLITE_DCHECK_GE(axis, 0); + TFLITE_DCHECK_LT(axis, input_dims_size); + + int batch_dims = params->batch_dims; + // batch_dims should be in range: [-rank(coords), rank(coords)]. + // Negative batch_dims is added with rank of coords. + const TfLiteIntArray* coords_dims = coords->dims; + const int coords_dims_size = coords_dims->size; + if (batch_dims < 0) { + batch_dims += coords_dims_size; + } + TFLITE_DCHECK_GE(batch_dims, 0); + TFLITE_DCHECK_LT(batch_dims, input_dims_size); + TFLITE_DCHECK_LE(batch_dims, coords_dims_size); + TFLITE_DCHECK_GE(axis, batch_dims); + for (int i = 0; i < batch_dims; ++i) { + TFLITE_DCHECK_EQ(input_dims->data[i], coords_dims->data[i]); + } + + const int axis_size = input_dims->data[axis]; + + int batch_size = 1; + for (int i = 0; i < batch_dims; ++i) { + batch_size *= input_dims->data[i]; + } + int outer_size = 1; + for (int i = batch_dims; i < axis; ++i) { + outer_size *= input_dims->data[i]; + } + int inner_size = 1; + for (int i = axis + 1; i < input_dims_size; ++i) { + inner_size *= input_dims->data[i]; + } + int coord_size = 1; + for (int i = batch_dims; i < coords_dims_size; ++i) { + coord_size *= coords_dims->data[i]; + } + + for (int batch = 0; batch < batch_size; ++batch) { + for (int outer = 0; outer < outer_size; ++outer) { + for (int coord = 0; coord < coord_size; ++coord) { + TFLITE_DCHECK_GE(coords_data[coord], 0); + TFLITE_DCHECK_LT(coords_data[coord], axis_size); + std::memcpy(output_data + + (((batch * outer_size) + outer) * coord_size + coord) * + inner_size, + input_data + (((batch * outer_size) + outer) * axis_size + + coords_data[batch * coord_size + coord]) * + inner_size, + sizeof(InputT) * inner_size); + } + } + } + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + const auto* params = + reinterpret_cast(node->builtin_data); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* coords = + micro_context->AllocateTempInputTensor(node, kInputPositions); + TF_LITE_ENSURE(context, coords != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + switch (coords->type) { + case kTfLiteInt32: + break; + default: + MicroPrintf("Positions of type '%s' are not supported by gather.", + TfLiteTypeGetName(coords->type)); + return kTfLiteError; + break; + } + + // Assign to output the input type. + output->type = input->type; + + // Check conditions for different types. + switch (input->type) { + case kTfLiteFloat32: + case kTfLiteInt8: + break; + default: + MicroPrintf("Type '%s' is not supported by gather.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + break; + } + + int axis = params->axis; + if (axis < 0) { + axis += NumDimensions(input); + } + TF_LITE_ENSURE(context, 0 <= axis && axis < NumDimensions(input)); + + int batch_dims = params->batch_dims; + // batch_dims should be in range: [-rank(coords), rank(coords)]. + // Negative batch_dims is added with rank of coords. + if (batch_dims < 0) { + batch_dims += NumDimensions(coords); + } + TF_LITE_ENSURE(context, batch_dims <= axis); + TF_LITE_ENSURE(context, 0 <= batch_dims && batch_dims < NumDimensions(input)); + TF_LITE_ENSURE(context, batch_dims <= NumDimensions(coords)); + for (int i = 0; i < batch_dims; ++i) { + TF_LITE_ENSURE_EQ(context, input->dims->data[i], coords->dims->data[i]); + } + + // GATHER updates the output tensor dimensions, but TfLiteTensor in the + // MicroInterpreter is a temporary allocation. We must therefore relocate the + // dims from the FlatBuffer to the persistant storage arena. + TfLiteEvalTensor* output_eval = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + TF_LITE_ENSURE_OK(context, tflite::micro::CreateWritableTensorDimsWithCopy( + context, output, output_eval)); + + TfLiteIntArray* output_shape = output->dims; + output_shape->size = + NumDimensions(input) + NumDimensions(coords) - 1 - batch_dims; + int output_index = 0; + for (int i = 0; i < axis; ++i) { + output_shape->data[output_index++] = input->dims->data[i]; + } + for (int i = batch_dims; i < coords->dims->size; ++i) { + output_shape->data[output_index++] = coords->dims->data[i]; + } + for (int i = axis + 1; i < input->dims->size; ++i) { + output_shape->data[output_index++] = input->dims->data[i]; + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(coords); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const auto* params = + reinterpret_cast(node->builtin_data); + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + const TfLiteEvalTensor* coords = + tflite::micro::GetEvalInput(context, node, kInputPositions); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + if (coords->type == kTfLiteInt32) { + switch (input->type) { + case kTfLiteFloat32: + return Gather(params, input, coords, output); + break; + case kTfLiteInt8: + return Gather(params, input, coords, output); + break; + default: + MicroPrintf("Type '%s' is not supported by gather.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + break; + } + } + return kTfLiteOk; +} +} // namespace + +TfLiteRegistration Register_GATHER() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/gather_nd.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/gather_nd.cc new file mode 100644 index 000000000..1f46dd1ef --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/gather_nd.cc @@ -0,0 +1,205 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { + +constexpr int kParams = 0; +constexpr int kIndices = 1; +constexpr int kOutputTensor = 0; +constexpr int MAX_INDICES_ND = 5; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TfLiteTensor* params = micro_context->AllocateTempInputTensor(node, kParams); + TF_LITE_ENSURE(context, params != nullptr); + TfLiteTensor* indices = + micro_context->AllocateTempInputTensor(node, kIndices); + TF_LITE_ENSURE(context, indices != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + switch (params->type) { + case kTfLiteFloat32: + case kTfLiteInt8: + break; + default: + MicroPrintf("Params of type '%s' are not supported by gather_nd.", + TfLiteTypeGetName(params->type)); + return kTfLiteError; + break; + } + switch (indices->type) { + case kTfLiteInt32: + break; + default: + MicroPrintf("Indices of type '%s' are not supported by gather_nd.", + TfLiteTypeGetName(indices->type)); + return kTfLiteError; + } + + const int params_rank = NumDimensions(params); + const int indices_rank = NumDimensions(indices); + const int indices_nd = SizeOfDimension(indices, indices_rank - 1); + if (params_rank < 1) { + MicroPrintf("Params must be at least a vector."); + return kTfLiteError; + } + if (indices_rank < 1) { + MicroPrintf("Indices must be at least a vector."); + return kTfLiteError; + } + if (indices_nd > params_rank) { + MicroPrintf("Index innermost dimension length must be <= params rank."); + return kTfLiteError; + } + if (indices_nd > MAX_INDICES_ND) { + MicroPrintf("Index innermost dimension length must not exceed %d.", + MAX_INDICES_ND); + return kTfLiteError; + } + + // Assign to output the input type. + output->type = params->type; + + // TFLM gather_nd does not create the output tensor, but it needs to ensure + // that the output shape is correct. The result shape is + // indices.shape[:-1] + params.shape[indices.shape[-1]:] + TfLiteIntArray* output_shape = output->dims; + int output_index = 0; + for (int i = 0; i < indices_rank - 1; ++i) { + output_shape->data[output_index++] = indices->dims->data[i]; + } + for (int i = indices_nd; i < params_rank; ++i) { + output_shape->data[output_index++] = params->dims->data[i]; + } + output_shape->size = output_index; + + micro_context->DeallocateTempTfLiteTensor(params); + micro_context->DeallocateTempTfLiteTensor(indices); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +template +TfLiteStatus GatherNd(const TfLiteEvalTensor* params, + const TfLiteEvalTensor* indices, + TfLiteEvalTensor* output) { + const int indices_dims = indices->dims->size; + const int indices_nd = indices->dims->data[indices_dims - 1]; + const int params_dims = params->dims->size; + const IndicesT* index_data = tflite::micro::GetTensorData(indices); + const ParamsT* param_data = tflite::micro::GetTensorData(params); + ParamsT* output_data = tflite::micro::GetTensorData(output); + + int n_slices = 1; + for (int i = 0; i < indices_dims - 1; ++i) { + n_slices *= indices->dims->data[i]; + } + + // If indices[-1] == params.rank, fetch single elements. + // If indices[-1] < params.rank, fetch slices. + int slice_size = 1; + for (int i = indices_nd; i < params_dims; ++i) { + slice_size *= params->dims->data[i]; + } + + int params_flat_size = ElementCount(*params->dims); + int remain_flat_size = params_flat_size; + + // Number of elements per dimension + int dims_to_count[MAX_INDICES_ND]; + for (int i = 0; i < indices_nd; ++i) { + dims_to_count[i] = remain_flat_size / params->dims->data[i]; + remain_flat_size = dims_to_count[i]; + } + + for (int i = 0; i < n_slices; ++i) { + int from_pos = 0; + for (int j = 0; j < indices_nd; ++j) { + int offset = i * indices_nd + j; + IndicesT index = index_data[offset]; + from_pos += index * dims_to_count[j]; + } + if (from_pos < 0 || from_pos + slice_size > params_flat_size) { + return kTfLiteError; + } + std::memcpy(output_data + i * slice_size, param_data + from_pos, + sizeof(ParamsT) * slice_size); + } + return kTfLiteOk; +} + +template +TfLiteStatus EvalGatherNd(TfLiteContext* context, + const TfLiteEvalTensor* params, + const TfLiteEvalTensor* indices, + TfLiteEvalTensor* output) { + TfLiteStatus status = kTfLiteError; + switch (params->type) { + case kTfLiteFloat32: + status = GatherNd(params, indices, output); + break; + case kTfLiteInt8: + status = GatherNd(params, indices, output); + break; + default: + MicroPrintf("Params type '%s' are not supported by gather_nd.", + TfLiteTypeGetName(params->type)); + return kTfLiteError; + } + if (status != kTfLiteOk) { + MicroPrintf("gather_nd index out of bounds"); + } + return status; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* params = + tflite::micro::GetEvalInput(context, node, kParams); + const TfLiteEvalTensor* indices = + tflite::micro::GetEvalInput(context, node, kIndices); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + switch (indices->type) { + case kTfLiteInt32: + return EvalGatherNd(context, params, indices, output); + break; + default: + MicroPrintf("Indices of type '%s' are not supported by gather_nd.", + TfLiteTypeGetName(indices->type)); + return kTfLiteError; + } +} +} // namespace + +TfLiteRegistration Register_GATHER_ND() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish.cc new file mode 100644 index 000000000..a0b3f7c62 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish.cc @@ -0,0 +1,75 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/hard_swish.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/hard_swish.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { +void* HardSwishInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(HardSwishParams)); +} + +TfLiteStatus HardSwishEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kHardSwishInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kHardSwishOutputTensor); + HardSwishParams* params = static_cast(node->user_data); + + switch (input->type) { + case kTfLiteFloat32: { + tflite::reference_ops::HardSwish( + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } break; + case kTfLiteInt8: { + tflite::reference_ops::HardSwish( + *params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } break; + default: { + MicroPrintf("Unsupported type %s", TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_HARD_SWISH() { + return tflite::micro::RegisterOp(HardSwishInit, tflite::HardSwishPrepare, + HardSwishEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish.h new file mode 100644 index 000000000..3ffe60dce --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish.h @@ -0,0 +1,30 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_HARD_SWISH_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_HARD_SWISH_H_ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +extern const int kHardSwishInputTensor; +extern const int kHardSwishOutputTensor; + +TfLiteStatus HardSwishPrepare(TfLiteContext* context, TfLiteNode* node); +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_HARD_SWISH_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish_common.cc new file mode 100644 index 000000000..8f8465226 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/hard_swish_common.cc @@ -0,0 +1,86 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/hard_swish.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/hard_swish.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +const int kHardSwishInputTensor = 0; +const int kHardSwishOutputTensor = 0; + +TfLiteStatus HardSwishPrepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TFLITE_DCHECK(node->user_data != nullptr); + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kHardSwishInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kHardSwishOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + if (input->type == kTfLiteInt8) { + HardSwishParams* params = static_cast(node->user_data); + + params->input_zero_point = input->params.zero_point; + params->output_zero_point = output->params.zero_point; + + const float input_scale = input->params.scale; + const float hires_input_scale = (1.0f / 128.0f) * input_scale; + const float reluish_scale = 3.0f / 32768.0f; + const float output_scale = output->params.scale; + + const double output_multiplier = + static_cast(hires_input_scale / output_scale); + int32_t output_multiplier_fixedpoint_int32; + QuantizeMultiplier(output_multiplier, &output_multiplier_fixedpoint_int32, + ¶ms->output_multiplier_exponent); + DownScaleInt32ToInt16Multiplier( + output_multiplier_fixedpoint_int32, + ¶ms->output_multiplier_fixedpoint_int16); + + TF_LITE_ENSURE(context, params->output_multiplier_exponent <= 0); + + const double reluish_multiplier = + static_cast(hires_input_scale / reluish_scale); + int32_t reluish_multiplier_fixedpoint_int32; + QuantizeMultiplier(reluish_multiplier, &reluish_multiplier_fixedpoint_int32, + ¶ms->reluish_multiplier_exponent); + DownScaleInt32ToInt16Multiplier( + reluish_multiplier_fixedpoint_int32, + ¶ms->reluish_multiplier_fixedpoint_int16); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/if.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/if.cc new file mode 100644 index 000000000..39eca8b48 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/if.cc @@ -0,0 +1,121 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_context.h" +#include "tensorflow/lite/micro/micro_graph.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +namespace { + +struct OpData { + int then_subgraph_index; + int else_subgraph_index; +}; + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + OpData* op_data = reinterpret_cast(node->user_data); + const auto* params = + reinterpret_cast(node->builtin_data); + op_data->then_subgraph_index = params->then_subgraph_index; + op_data->else_subgraph_index = params->else_subgraph_index; + + TF_LITE_ENSURE(context, node->inputs->size > 0); + + // The first input is the condition. + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + TfLiteTensor* cond = micro_context->AllocateTempInputTensor(node, 0); + + TF_LITE_ENSURE(context, cond != nullptr); + TF_LITE_ENSURE_EQ(context, cond->type, kTfLiteBool); + TF_LITE_ENSURE_EQ(context, NumElements(cond), 1); + + micro_context->DeallocateTempTfLiteTensor(cond); + + // The first input of the node is the condition. The rest of inputs are + // passed to the branch subgraphs. Therefore, the number of subgraph inputs + // will be the number of node inputs - 1. + size_t num_inputs = node->inputs->size - 1; + size_t num_outputs = node->outputs->size; + + MicroGraph& graph_info = micro_context->graph(); + + TF_LITE_ENSURE(context, + op_data->then_subgraph_index < graph_info.NumSubgraphs()); + TF_LITE_ENSURE(context, + op_data->else_subgraph_index < graph_info.NumSubgraphs()); + + TF_LITE_ENSURE_EQ(context, num_inputs, + graph_info.NumSubgraphInputs(op_data->then_subgraph_index)); + TF_LITE_ENSURE_EQ( + context, num_outputs, + graph_info.NumSubgraphOutputs(op_data->then_subgraph_index)); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const OpData* op_data = reinterpret_cast(node->user_data); + + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + TfLiteTensor* cond = micro_context->AllocateTempInputTensor(node, 0); + + TF_LITE_ENSURE(context, cond != nullptr); + bool cond_value = cond->data.b[0]; + micro_context->DeallocateTempTfLiteTensor(cond); + + MicroGraph* graph_info = µ_context->graph(); + // Currently we copy the input / output between the subgraphs. + int active_branch_subgraph_index = + cond_value ? op_data->then_subgraph_index : op_data->else_subgraph_index; + + TF_LITE_ENSURE_OK(context, + tflite::micro::CopyOpInputsToSubgraphInputs( + context, node, graph_info, active_branch_subgraph_index, + /*first_tensor_idx=*/1)); + + TF_LITE_ENSURE_OK(context, + graph_info->InvokeSubgraph(active_branch_subgraph_index)); + + TF_LITE_ENSURE_OK( + context, tflite::micro::CopySubgraphOutputsToOpOutputs( + context, node, graph_info, active_branch_subgraph_index)); + + return kTfLiteOk; +} + +} // namespace. + +TfLiteRegistration Register_IF() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_runner.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_runner.cc new file mode 100644 index 000000000..b31aa0ebb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_runner.cc @@ -0,0 +1,122 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/kernel_runner.h" + +#include "tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/micro_arena_constants.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/test_helpers.h" + +namespace tflite { +namespace micro { + +// TODO(b/161841696): Consider moving away from global arena buffers: +constexpr int KernelRunner::kKernelRunnerBufferSize_; +uint8_t KernelRunner::kKernelRunnerBuffer_[]; + +void ClearBufferApi(TfLiteContext* context_) { + context_->GetScratchBuffer = nullptr; + context_->GetExternalContext = nullptr; + context_->AllocatePersistentBuffer = nullptr; + context_->RequestScratchBufferInArena = nullptr; +} + +KernelRunner::KernelRunner(const TfLiteRegistration& registration, + TfLiteTensor* tensors, int tensors_size, + TfLiteIntArray* inputs, TfLiteIntArray* outputs, + void* builtin_data, TfLiteIntArray* intermediates) + : registration_(registration), + allocator_(SingleArenaBufferAllocator::Create(kKernelRunnerBuffer_, + kKernelRunnerBufferSize_)), + mock_micro_graph_(allocator_), + fake_micro_context_(tensors, allocator_, &mock_micro_graph_) { + // Prepare TfLiteContext: + context_.impl_ = static_cast(&fake_micro_context_); + context_.ReportError = MicroContextReportOpError; + context_.recommended_num_threads = 1; + context_.GetTensor = MicroContextGetTensor; + context_.GetEvalTensor = MicroContextGetEvalTensor; + tflite::micro::ClearBufferApi(&context_); + context_.AllocatePersistentBuffer = MicroContextAllocatePersistentBuffer; + + context_.recommended_num_threads = 0; + + // Prepare TfLiteNode: + node_.inputs = inputs; + node_.outputs = outputs; + node_.builtin_data = builtin_data; + node_.intermediates = intermediates; +} + +bool KernelRunner::ValidateTempBufferDeallocated() { + return fake_micro_context_.IsAllTempTfLiteTensorDeallocated(); +} + +TfLiteStatus KernelRunner::InitAndPrepare(const char* init_data, + size_t length) { + if (registration_.init) { + tflite::micro::ClearBufferApi(&context_); + context_.AllocatePersistentBuffer = MicroContextAllocatePersistentBuffer; + node_.user_data = registration_.init(&context_, init_data, length); + } + + TF_LITE_ENSURE(&context_, ValidateTempBufferDeallocated()); + + if (registration_.prepare) { + tflite ::micro::ClearBufferApi(&context_); + context_.AllocatePersistentBuffer = MicroContextAllocatePersistentBuffer; + context_.RequestScratchBufferInArena = + MicroContextRequestScratchBufferInArena; + context_.GetExternalContext = MicroContextGetExternalContext; + TF_LITE_ENSURE_STATUS(registration_.prepare(&context_, &node_)); + } + + TF_LITE_ENSURE(&context_, ValidateTempBufferDeallocated()); + + return kTfLiteOk; +} + +TfLiteStatus KernelRunner::Invoke() { + tflite::micro::ClearBufferApi(&context_); + context_.GetScratchBuffer = MicroContextGetScratchBuffer; + + if (registration_.invoke == nullptr) { + MicroPrintf("TfLiteRegistration missing invoke function pointer!"); + return kTfLiteError; + } + + TF_LITE_ENSURE_STATUS(registration_.invoke(&context_, &node_)); + + TF_LITE_ENSURE(&context_, ValidateTempBufferDeallocated()); + + return kTfLiteOk; +} + +TfLiteStatus KernelRunner::Free() { + tflite::micro::ClearBufferApi(&context_); + context_.GetScratchBuffer = MicroContextGetScratchBuffer; + + if (registration_.free == nullptr) { + MicroPrintf("TfLiteRegistration missing free function pointer!"); + return kTfLiteError; + } + + registration_.free(&context_, node_.user_data); + return kTfLiteOk; +} +} // namespace micro +} // namespace tflite \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_runner.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_runner.h new file mode 100644 index 000000000..c7d53c3a5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_runner.h @@ -0,0 +1,81 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_KERNEL_RUNNER_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_KERNEL_RUNNER_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/fake_micro_context.h" +#include "tensorflow/lite/micro/mock_micro_graph.h" + +namespace tflite { +namespace micro { + +// Helper class to perform a simulated kernel (i.e. TfLiteRegistration) +// lifecycle (init, prepare, invoke). All internal allocations are handled by +// this class. Simply pass in the registration, list of required tensors, inputs +// array, outputs array, and any pre-builtin data. Calling Invoke() will +// automatically walk the kernel and outputs will be ready on the TfLiteTensor +// output provided during construction. +class KernelRunner { + public: + KernelRunner(const TfLiteRegistration& registration, TfLiteTensor* tensors, + int tensors_size, TfLiteIntArray* inputs, + TfLiteIntArray* outputs, void* builtin_data, + TfLiteIntArray* intermediates = nullptr); + + // Calls init and prepare on the kernel (i.e. TfLiteRegistration) struct. Any + // exceptions will be DebugLog'd and returned as a status code. + TfLiteStatus InitAndPrepare(const char* init_data = nullptr, + size_t length = 0); + + // Calls init, prepare, and invoke on a given TfLiteRegistration pointer. + // After successful invoke, results will be available in the output tensor as + // passed into the constructor of this class. + TfLiteStatus Invoke(); + + // Calls Free on a given TfLiteRegistration pointer(if it's implemented). + // After successful Free, kTfLiteOk status will be returned. If Free is not + // implemented for a given kernel kTfLiteError will be returned. + TfLiteStatus Free(); + + // Returns a pointer to the internal MockMicroGraph which KernelRunner uses + // to stub out MicroGraph methods and track invocations on each subgraph. + MockMicroGraph* GetMockGraph() { return &mock_micro_graph_; } + + // Returns true if all temp buffer in tests are deallocated. + // TODO(b/209453859): move this function to private after deallocation checks + // are enabled for all kernel tests. + bool ValidateTempBufferDeallocated(); + + private: + static constexpr int kKernelRunnerBufferSize_ = 10000; + static uint8_t kKernelRunnerBuffer_[kKernelRunnerBufferSize_]; + + TfLiteContext context_ = {}; + TfLiteNode node_ = {}; + const TfLiteRegistration& registration_; + + SingleArenaBufferAllocator* allocator_; + MockMicroGraph mock_micro_graph_; + FakeMicroContext fake_micro_context_; +}; + +} // namespace micro +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_KERNEL_RUNNER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_util.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_util.cc new file mode 100644 index 000000000..0499260f5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_util.cc @@ -0,0 +1,260 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace micro { + +namespace { + +int ValidateTensorIndexing(const TfLiteContext* context, int index, + int max_size, const int* tensor_indices) { + if (index >= 0 && index < max_size) { + const int tensor_index = tensor_indices[index]; + if (tensor_index != kTfLiteOptionalTensor) { + return tensor_index; + } + } + return -1; +} + +} // namespace + +TfLiteRegistration RegisterOp( + void* (*init)(TfLiteContext* context, const char* buffer, size_t length), + TfLiteStatus (*prepare)(TfLiteContext* context, TfLiteNode* node), + TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node), + void (*free)(TfLiteContext* context, void* buffer)) { + return {/*init=*/init, + /*free=*/free, + /*prepare=*/prepare, + /*invoke=*/invoke, + /*profiling_string=*/nullptr, + /*builtin_code=*/0, + /*custom_name=*/nullptr, + /*version=*/0, + /*registration_external=*/nullptr}; +} + +// Returns a mutable tensor for a given input index. is_variable must be checked +// during prepare when the full TfLiteTensor is available. +TfLiteEvalTensor* GetMutableEvalInput(const TfLiteContext* context, + const TfLiteNode* node, int index) { + TFLITE_DCHECK(context != nullptr); + TFLITE_DCHECK(node != nullptr); + const int tensor_index = ValidateTensorIndexing( + context, index, node->inputs->size, node->inputs->data); + + if (tensor_index < 0) { + return nullptr; + } + + return context->GetEvalTensor(context, node->inputs->data[index]); +} + +// Returns the TfLiteEvalTensor struct for a given input index in a node. +const TfLiteEvalTensor* GetEvalInput(const TfLiteContext* context, + const TfLiteNode* node, int index) { + return GetMutableEvalInput(context, node, index); +} + +// Returns the TfLiteEvalTensor struct for a given output index in a node. +TfLiteEvalTensor* GetEvalOutput(const TfLiteContext* context, + const TfLiteNode* node, int index) { + TFLITE_DCHECK(context != nullptr); + TFLITE_DCHECK(node != nullptr); + return context->GetEvalTensor(context, node->outputs->data[index]); +} + +bool HaveSameShapes(const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2) { + TFLITE_DCHECK(input1 != nullptr); + TFLITE_DCHECK(input2 != nullptr); + return TfLiteIntArrayEqual(input1->dims, input2->dims); +} + +const RuntimeShape GetTensorShape(const TfLiteEvalTensor* tensor) { + if (tensor == nullptr || tensor->dims == nullptr) { + return RuntimeShape(); + } + TfLiteIntArray* dims = tensor->dims; + const int dims_size = dims->size; + const int32_t* dims_data = reinterpret_cast(dims->data); + return RuntimeShape(dims_size, dims_data); +} + +PaddingType RuntimePaddingType(TfLitePadding padding) { + switch (padding) { + case TfLitePadding::kTfLitePaddingSame: + return PaddingType::kSame; + case TfLitePadding::kTfLitePaddingValid: + return PaddingType::kValid; + case TfLitePadding::kTfLitePaddingUnknown: + default: + return PaddingType::kNone; + } +} + +// Relocate tensor dims from FlatBuffer to the persistent storage arena. +// The old dims data is copied to the new storage area. +// The tensor and eval_tensor must be the same tensor. +// Only use during Prepare phase. +TfLiteStatus CreateWritableTensorDimsWithCopy(TfLiteContext* context, + TfLiteTensor* tensor, + TfLiteEvalTensor* eval_tensor) { + TF_LITE_ENSURE(context, tensor != nullptr); + TF_LITE_ENSURE(context, eval_tensor != nullptr); + TF_LITE_ENSURE(context, context->AllocatePersistentBuffer != nullptr); + int ranks = tensor->dims->size; + size_t alloc_size = TfLiteIntArrayGetSizeInBytes(ranks); + TfLiteIntArray* new_dims = static_cast( + context->AllocatePersistentBuffer(context, alloc_size)); + TfLiteIntArray* old_dims = tensor->dims; + new_dims->size = ranks; + tensor->dims = new_dims; + eval_tensor->dims = new_dims; + for (int i = 0; i < ranks; i++) { + new_dims->data[i] = old_dims->data[i]; + } + + return kTfLiteOk; +} + +// Verify that both tensors have the same type and size, then return the size +// of both tensors in bytes if they are the same, or -1 if they are different. +size_t ValidateAndGetTensorSizes(const TfLiteEvalTensor* tensor1, + const TfLiteEvalTensor* tensor2) { + TFLITE_DCHECK(tensor1->type == tensor2->type); + size_t tensor1_size = 0; + size_t tensor2_size = 0; + TfLiteEvalTensorByteLength(tensor1, &tensor1_size); + TfLiteEvalTensorByteLength(tensor2, &tensor2_size); + return (tensor1_size == tensor2_size) ? tensor1_size : -1; +} + +TfLiteStatus CopyOpInputsToOpOutputs(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE(context, node->inputs->size == node->outputs->size); + for (int i = 0; i < node->inputs->size; i++) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, i); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, i); + int bytes = ValidateAndGetTensorSizes(input, output); + TF_LITE_ENSURE(context, bytes >= 0); + memcpy(output->data.raw, input->data.raw, bytes); + } + return kTfLiteOk; +} + +// Args: +// 1. int8_t tensor_data - int8_t buffer of unknown size who's data you'd +// like +// to print +// 2. int n_btyes - a small int representing number of bytes you want to +// print +// to debug output. It should always be <= tensor_data's size. +// 3. prefix - optional message you'd like to print before printing bytes +// +// Purpose: +// Function takes in paramaters above and prints n_bytes bytes from the +// tensor_data buffer. This can be use to debug the output of a model and it's +// op. + +void PrintNBytes(const int8_t* tensor_data, int n_bytes, const char* prefix) { + if (prefix != nullptr) { + MicroPrintf("%s", prefix); + } + + for (int i = 0; i < n_bytes; ++i) { + MicroPrintf(" %x", tensor_data[i]); + } + MicroPrintf("\n"); +} + +// same as the PrintNBytes above but the buffer needs to be extracted out of the +// TfLiteEvalTensor* +void PrintNBytes(const TfLiteEvalTensor* tensor, int n_bytes, + const char* prefix) { + const int8_t* tensor_data = tflite::micro::GetTensorData(tensor); + PrintNBytes(tensor_data, n_bytes, prefix); +} + +// same as the PrintNBytes above but the buffer needs to be extracted out of the +// TfLiteEvalTensor* +void PrintNBytes(const TfLiteTensor* tensor, int n_bytes, const char* prefix) { + const int8_t* tensor_data = tflite::GetTensorData(tensor); + PrintNBytes(tensor_data, n_bytes, prefix); +} + +TfLiteStatus CopyOpInputsToSubgraphInputs(TfLiteContext* context, + TfLiteNode* node, + MicroGraph* graph_info, + int subgraph_idx, + int first_tensor_idx) { + TF_LITE_ENSURE(context, + static_cast(node->inputs->size - first_tensor_idx) == + graph_info->NumSubgraphInputs(subgraph_idx)); + for (int i = 0; i < node->inputs->size - first_tensor_idx; i++) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, i + first_tensor_idx); + TfLiteEvalTensor* subgraph_input = + graph_info->GetSubgraphInput(subgraph_idx, i); + int bytes = ValidateAndGetTensorSizes(input, subgraph_input); + TF_LITE_ENSURE(context, bytes >= 0); + memcpy(subgraph_input->data.raw, input->data.raw, bytes); + } + return kTfLiteOk; +} + +TfLiteStatus CopyOpOutputsToSubgraphInputs(TfLiteContext* context, + TfLiteNode* node, + MicroGraph* graph_info, + int subgraph_idx) { + TF_LITE_ENSURE(context, static_cast(node->outputs->size) == + graph_info->NumSubgraphInputs(subgraph_idx)); + for (int i = 0; i < node->outputs->size; i++) { + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, i); + TfLiteEvalTensor* subgraph_input = + graph_info->GetSubgraphInput(subgraph_idx, i); + int bytes = ValidateAndGetTensorSizes(output, subgraph_input); + TF_LITE_ENSURE(context, bytes >= 0); + memcpy(subgraph_input->data.raw, output->data.raw, bytes); + } + return kTfLiteOk; +} + +TfLiteStatus CopySubgraphOutputsToOpOutputs(TfLiteContext* context, + TfLiteNode* node, + MicroGraph* graph_info, + int subgraph_idx) { + TF_LITE_ENSURE(context, static_cast(node->outputs->size) == + graph_info->NumSubgraphOutputs(subgraph_idx)); + for (int i = 0; i < node->outputs->size; i++) { + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, i); + TfLiteEvalTensor* subgraph_output = + graph_info->GetSubgraphOutput(subgraph_idx, i); + int bytes = ValidateAndGetTensorSizes(output, subgraph_output); + TF_LITE_ENSURE(context, bytes >= 0); + memcpy(output->data.raw, subgraph_output->data.raw, bytes); + } + return kTfLiteOk; +} + +} // namespace micro +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_util.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_util.h new file mode 100644 index 000000000..aa369605e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/kernel_util.h @@ -0,0 +1,137 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_KERNEL_UTIL_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_KERNEL_UTIL_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/micro/micro_context.h" + +namespace tflite { +namespace micro { + +TfLiteRegistration RegisterOp( + void* (*init)(TfLiteContext* context, const char* buffer, size_t length), + TfLiteStatus (*prepare)(TfLiteContext* context, TfLiteNode* node), + TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node), + void (*free)(TfLiteContext* context, void* buffer) = nullptr); + +// Prints out n bytes in a int8_t buffer as hex +void PrintNBytes(const int8_t* tensor_data, int n_bytes, + const char* prefix = nullptr); + +// Prints out the the n bytes in a TfLiteEvalTensor as hex +void PrintNBytes(const TfLiteEvalTensor* tensor, int n_bytes, + const char* prefix = nullptr); + +// Prints out the the n bytes in a TfLiteTensor as hex +void PrintNBytes(const TfLiteTensor* tensor, int n_bytes, + const char* prefix = nullptr); + +// Returns a mutable tensor for a given input index. is_variable must be checked +// during prepare when the full TfLiteTensor is available. +TfLiteEvalTensor* GetMutableEvalInput(const TfLiteContext* context, + const TfLiteNode* node, int index); + +// Returns the TfLiteEvalTensor struct for a given input index in a node. +const TfLiteEvalTensor* GetEvalInput(const TfLiteContext* context, + const TfLiteNode* node, int index); + +// Returns the TfLiteEvalTensor struct for a given output index in a node. +TfLiteEvalTensor* GetEvalOutput(const TfLiteContext* context, + const TfLiteNode* node, int index); + +// Returns data for a TfLiteEvalTensor struct that are expected to exist. +template +T* GetTensorData(TfLiteEvalTensor* tensor) { + TFLITE_DCHECK(tensor != nullptr); + return reinterpret_cast(tensor->data.raw); +} + +// Returns const data for a TfLiteEvalTensor struct that are expected to exist. +template +const T* GetTensorData(const TfLiteEvalTensor* tensor) { + TFLITE_DCHECK(tensor != nullptr); + return reinterpret_cast(tensor->data.raw); +} + +// Returns data for a TfLiteEvalTensor struct that could be null. +template +T* GetOptionalTensorData(TfLiteEvalTensor* tensor) { + return tensor == nullptr ? nullptr : reinterpret_cast(tensor->data.raw); +} + +// Returns const data for a TfLiteEvalTensor struct that could be null. +template +const T* GetOptionalTensorData(const TfLiteEvalTensor* tensor) { + return tensor == nullptr ? nullptr + : reinterpret_cast(tensor->data.raw); +} + +// Returns the shape of a TfLiteEvalTensor struct. +const RuntimeShape GetTensorShape(const TfLiteEvalTensor* tensor); + +// Return true if the given tensors have the same shape. +bool HaveSameShapes(const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2); + +PaddingType RuntimePaddingType(TfLitePadding padding); + +// Relocate tensor dims from FlatBuffer to the persistent storage arena. +// The old dims data is copied to the new storage area. +// The tensor and eval_tensor must be the same tensor. +// Only use during Prepare phase. +TfLiteStatus CreateWritableTensorDimsWithCopy(TfLiteContext* context, + TfLiteTensor* tensor, + TfLiteEvalTensor* eval_tensor); + +// Copy all op input tensors to op output tensors. Requires all op input tensor +// shapes and types to be identical to op output tensor shapes and types. +TfLiteStatus CopyOpInputsToOpOutputs(TfLiteContext* context, TfLiteNode* node); + +// Copy all op input tensors to subgraph input tensors. Requires all op input +// tensor shapes and types to be identical to subgraph input tensor shapes and +// types. +TfLiteStatus CopyOpInputsToSubgraphInputs(TfLiteContext* context, + TfLiteNode* node, + MicroGraph* graph_info, + int subgraph_idx, + int first_tensor_idx); + +// Copy all op output tensors to subgraph input tensors. Requires all op output +// tensor shapes and types to be identical to subgraph input tensor shapes and +// types. +TfLiteStatus CopyOpOutputsToSubgraphInputs(TfLiteContext* context, + TfLiteNode* node, + MicroGraph* graph_info, + int subgraph_idx); + +// Copy all subgraph output tensors to op outputs. Requires all subgraph output +// tensor shapes and types to be identical to op output tensor shapes and types. +TfLiteStatus CopySubgraphOutputsToOpOutputs(TfLiteContext* context, + TfLiteNode* node, + MicroGraph* graph_info, + int subgraph_idx); + +} // namespace micro +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_KERNEL_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/l2_pool_2d.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/l2_pool_2d.cc new file mode 100644 index 000000000..d4225e466 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/l2_pool_2d.cc @@ -0,0 +1,142 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/reference/pooling.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/padding.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +// Input/output tensor index. +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +// required rank for input/output tensor shape +constexpr int kTensorShapeRank = 4; + +// input/output tensor shape rank associations +enum { kBatchRank = 0, kHeightRank, kWidthRank, kChannelRank }; + +TfLiteStatus L2Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + auto* params = static_cast(node->builtin_data); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TF_LITE_ENSURE_EQ(context, NumDimensions(input), kTensorShapeRank); + TF_LITE_ENSURE_EQ(context, NumDimensions(output), kTensorShapeRank); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + int batches = SizeOfDimension(input, kBatchRank); + int height = SizeOfDimension(input, kHeightRank); + int width = SizeOfDimension(input, kWidthRank); + int channels_out = SizeOfDimension(input, kChannelRank); + + // Matching GetWindowedOutputSize in TensorFlow. + auto padding = params->padding; + int out_width, out_height; + + params->computed.padding = ComputePaddingHeightWidth( + params->stride_height, params->stride_width, 1, 1, height, width, + params->filter_height, params->filter_width, padding, &out_height, + &out_width); + + // We currently don't have a quantized implementation of L2Pool + TF_LITE_ENSURE_TYPES_EQ(context, input->type, kTfLiteFloat32); + + // We must update the output tensor dimensions. + // The dims storage is expected to be the same area in memory + // for both TfLiteTensor and TfLiteEvalTensor. This is important + // because TfLiteTensor in the MicroInterpreter is a temporary + // allocation. For the KernelRunner interpreter, TfLiteEvalTensor + // is a temporary allocation. We must therefore relocate the dims + // from the FlatBuffer to the persistant storage arena. + TfLiteEvalTensor* output_eval = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + TF_LITE_ENSURE_OK(context, tflite::micro::CreateWritableTensorDimsWithCopy( + context, output, output_eval)); + output->dims->data[kBatchRank] = batches; + output->dims->data[kHeightRank] = out_height; + output->dims->data[kWidthRank] = out_width; + output->dims->data[kChannelRank] = channels_out; + + micro_context->DeallocateTempTfLiteTensor(output); + micro_context->DeallocateTempTfLiteTensor(input); + + return kTfLiteOk; +} + +void L2EvalFloat(const TfLitePoolParams& params, const TfLiteEvalTensor& input, + tflite::PoolParams* op_params, TfLiteEvalTensor* output) { + float activation_min, activation_max; + CalculateActivationRange(params.activation, &activation_min, &activation_max); + + op_params->float_activation_min = activation_min; + op_params->float_activation_max = activation_max; + reference_ops::L2Pool(*op_params, tflite::micro::GetTensorShape(&input), + tflite::micro::GetTensorData(&input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +} + +TfLiteStatus L2Eval(TfLiteContext* context, TfLiteNode* node) { + auto* params = static_cast(node->builtin_data); + + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + + tflite::PoolParams op_params; + op_params.stride_height = params->stride_height; + op_params.stride_width = params->stride_width; + op_params.filter_height = params->filter_height; + op_params.filter_width = params->filter_width; + op_params.padding_values.height = params->computed.padding.height; + op_params.padding_values.width = params->computed.padding.width; + + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: + L2EvalFloat(*params, *input, &op_params, output); + break; + default: + MicroPrintf("L2_POOL_2D only supports float32 currently, got %s.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_L2_POOL_2D() { + return tflite::micro::RegisterOp(nullptr, L2Prepare, L2Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/l2norm.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/l2norm.cc new file mode 100644 index 000000000..5adea8e29 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/l2norm.cc @@ -0,0 +1,148 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/portable_tensor.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/l2normalization.h" +#include "tensorflow/lite/kernels/internal/reference/l2normalization.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace l2norm { + +namespace { + +// This file has two implementation of L2Norm. +enum KernelType { + kReference, + kGenericOptimized, +}; + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +} // namespace + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + auto* params = reinterpret_cast(node->builtin_data); + L2NormalizationParams* data = + static_cast(node->user_data); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE(context, NumDimensions(input) <= 4); + + TF_LITE_ENSURE(context, + output->type == kTfLiteFloat32 || output->type == kTfLiteInt8); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + if (output->type == kTfLiteInt8) { + data->input_zero_point = input->params.zero_point; + } else if (output->type == kTfLiteFloat32) { + data->input_zero_point = 0; + } + + // Our implementations don't currently support activations. + TF_LITE_ENSURE_EQ(context, params->activation, kTfLiteActNone); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, + sizeof(L2NormalizationParams)); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const L2NormalizationParams& data = + *(static_cast(node->user_data)); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + // TODO(b/143912164): instead of hardcode the epsilon here, we should read it + // from tensorflow, i.e., adding a params. + // We don't compute epsilon for quantized kernel: + // + // epsilon_float = (epsilon_quant - zp) * scale + // so + // espsilon_quant = epsilon_float / scale + zp + // We know epsilon_float is just a very small number to avoid division by + // zero error, and scale is > 1, so the integer value of epsilon for quant + // is just dominated by the zero point. + // Also, GetInvSqrtQuantizedMultiplierExp handles the scenario where the sum + // of input value squared is zero case well. + // So we don't even need to do handle the epsilon for quantized kernel case. + const float epsilon = 1e-6f; + if (output->type == kTfLiteFloat32) { + reference_ops::L2Normalization(data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + epsilon); + } else if (output->type == kTfLiteInt8) { + const auto input_shape = tflite::micro::GetTensorShape(input); + const auto output_shape = tflite::micro::GetTensorShape(output); + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + reference_integer_ops::L2Normalization( + data.input_zero_point, outer_size, depth, + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorData(output)); + } else { + MicroPrintf("Output type is %s, requires float.", + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace l2norm + +TfLiteRegistration Register_L2NORM_REF() { + return tflite::micro::RegisterOp(l2norm::Init, l2norm::Prepare, l2norm::Eval); +} + +TfLiteRegistration Register_L2_NORMALIZATION() { return Register_L2NORM_REF(); } + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu.cc new file mode 100644 index 000000000..7b51ebcb3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu.cc @@ -0,0 +1,95 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/leaky_relu.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/leaky_relu.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +template +void QuantizeLeakyRelu(const LeakyReluOpData& data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output) { + LeakyReluParams op_params = {}; + + op_params.input_offset = data.input_zero_point; + op_params.output_offset = data.output_zero_point; + op_params.output_multiplier_alpha = data.output_multiplier_alpha; + op_params.output_shift_alpha = data.output_shift_alpha; + op_params.output_multiplier_identity = data.output_multiplier_identity; + op_params.output_shift_identity = data.output_shift_identity; + reference_ops::QuantizeLeakyRelu(op_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +} + +void* LeakyReluInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(LeakyReluOpData)); +} + +TfLiteStatus LeakyReluEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + const LeakyReluOpData& data = *static_cast(node->user_data); + + switch (input->type) { + case kTfLiteFloat32: { + LeakyReluParams op_params = {}; + const auto* params = + static_cast(node->builtin_data); + + op_params.alpha = params->alpha; + reference_ops::LeakyRelu(op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } break; + case kTfLiteInt8: { + QuantizeLeakyRelu(data, input, output); + return kTfLiteOk; + } break; + case kTfLiteInt16: { + QuantizeLeakyRelu(data, input, output); + return kTfLiteOk; + } break; + default: + MicroPrintf("Only float32, int8 are supported by LEAKY_RELU, got %s.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + + return kTfLiteError; +} + +TfLiteRegistration Register_LEAKY_RELU() { + return tflite::micro::RegisterOp(LeakyReluInit, LeakyReluPrepare, + LeakyReluEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu.h new file mode 100644 index 000000000..dfcd6e93d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu.h @@ -0,0 +1,43 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_LEAKY_RELU_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_LEAKY_RELU_H_ + +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +// Input/output tensor index. +extern const int kInputTensor; +extern const int kOutputTensor; + +struct LeakyReluOpData { + // quantization parameters + int32_t output_multiplier_alpha; + int32_t output_shift_alpha; + int32_t output_multiplier_identity; + int32_t output_shift_identity; + int32_t input_zero_point; + int32_t output_zero_point; +}; + +TfLiteStatus CalculateOpDataLeakyRelu(TfLiteContext* context, TfLiteNode* node); + +TfLiteStatus LeakyReluPrepare(TfLiteContext* context, TfLiteNode* node); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_LEAKY_RELU_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu_common.cc new file mode 100644 index 000000000..7d3cb176f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/leaky_relu_common.cc @@ -0,0 +1,79 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/leaky_relu.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/leaky_relu.h" + +namespace tflite { + +// Input/output tensor index. +const int kInputTensor = 0; +const int kOutputTensor = 0; + +TfLiteStatus CalculateOpDataLeakyRelu(TfLiteContext* context, + TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + if (output->type == kTfLiteInt8 || output->type == kTfLiteInt16) { + LeakyReluOpData* data = static_cast(node->user_data); + const auto* params = + static_cast(node->builtin_data); + + data->input_zero_point = input->params.zero_point; + data->output_zero_point = output->params.zero_point; + + int output_shift_alpha; + double alpha_multiplier = static_cast(input->params.scale) * + static_cast(params->alpha) / + static_cast(output->params.scale); + QuantizeMultiplier(alpha_multiplier, &data->output_multiplier_alpha, + &output_shift_alpha); + data->output_shift_alpha = static_cast(output_shift_alpha); + + int output_shift_identity; + double identity_multiplier = static_cast(input->params.scale) / + static_cast(output->params.scale); + QuantizeMultiplier(identity_multiplier, &data->output_multiplier_identity, + &output_shift_identity); + data->output_shift_identity = static_cast(output_shift_identity); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus LeakyReluPrepare(TfLiteContext* context, TfLiteNode* node) { + return CalculateOpDataLeakyRelu(context, node); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/log_softmax.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/log_softmax.cc new file mode 100644 index 000000000..0b1838c30 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/log_softmax.cc @@ -0,0 +1,148 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/log_softmax.h" + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +// used only with quantized data +struct LogSoftmaxOpData { + int32_t input_multiplier; + int32_t input_left_shift; + int32_t reverse_scaling_divisor; + int32_t reverse_scaling_right_shift; + int diff_min; + size_t outer_size; // number of tensor elements skipping computation axis + size_t depth; // number of tensor elements on computation axis +}; + +// input/output tensor index +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus CalculateOpData(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + TF_LITE_ENSURE(context, HaveSameShapes(input, output)); + + if (input->type == kTfLiteInt8) { + node->user_data = + context->AllocatePersistentBuffer(context, sizeof(LogSoftmaxOpData)); + auto data = static_cast(node->user_data); + + // quantization datum + constexpr int32_t kOutputZeroPoint = 127; + constexpr float kOutputScale = 16.0 / 256; + constexpr double kBeta = 1.0; + constexpr int kScaledDiffIntegerBits = 5; + + TF_LITE_ENSURE(context, output->params.scale == kOutputScale); + TF_LITE_ENSURE(context, output->params.zero_point == kOutputZeroPoint); + + int input_left_shift; + int reverse_scaling_right_shift; + tflite::PreprocessLogSoftmaxScalingExp( + kBeta, static_cast(input->params.scale), kScaledDiffIntegerBits, + &data->input_multiplier, &input_left_shift, + &data->reverse_scaling_divisor, &reverse_scaling_right_shift); + data->input_left_shift = static_cast(input_left_shift); + data->reverse_scaling_right_shift = + static_cast(-reverse_scaling_right_shift); + // diff_min has a negative value, and is used to limit the maximum magnitude + // of the diffs, which are <= 0. + data->diff_min = + -tflite::CalculateInputRadius(kScaledDiffIntegerBits, input_left_shift); + + RuntimeShape input_shape = GetTensorShape(input); + const int trailing_dim = input_shape.DimensionsCount() - 1; + data->outer_size = + static_cast(FlatSizeSkipDim(input_shape, trailing_dim)); + data->depth = static_cast(input_shape.Dims(trailing_dim)); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus LogSoftmaxPrepare(TfLiteContext* context, TfLiteNode* node) { + return CalculateOpData(context, node); +} + +TfLiteStatus LogSoftmaxEval(TfLiteContext* context, TfLiteNode* node) { + const LogSoftmaxOpData* data = + static_cast(node->user_data); + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + switch (input->type) { + case kTfLiteFloat32: { + SoftmaxParams op_params = {}; + reference_ops::LogSoftmax(op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } + case kTfLiteInt8: { + SoftmaxParams op_params = {}; + op_params.input_multiplier = data->input_multiplier; + op_params.input_left_shift = data->input_left_shift; + op_params.reverse_scaling_divisor = data->reverse_scaling_divisor; + op_params.reverse_scaling_right_shift = data->reverse_scaling_right_shift; + op_params.diff_min = data->diff_min; + reference_ops::LogSoftmax(op_params, data->outer_size, data->depth, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } + default: + MicroPrintf("LOG_SOFTMAX only supports float32, int8, got %s.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } +} + +} // namespace + +TfLiteRegistration Register_LOG_SOFTMAX() { + return tflite::micro::RegisterOp(nullptr, LogSoftmaxPrepare, LogSoftmaxEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical.cc new file mode 100644 index 000000000..c85e0c5be --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical.cc @@ -0,0 +1,44 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/micro/kernels/logical.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/reference/binary_function.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { +namespace { + +TfLiteStatus LogicalOrEval(TfLiteContext* context, TfLiteNode* node) { + return LogicalImpl(context, node, LogicalOr); +} + +TfLiteStatus LogicalAndEval(TfLiteContext* context, TfLiteNode* node) { + return LogicalImpl(context, node, LogicalAnd); +} + +} // namespace + +TfLiteRegistration Register_LOGICAL_OR() { + return tflite::micro::RegisterOp(nullptr, nullptr, LogicalOrEval); +} + +TfLiteRegistration Register_LOGICAL_AND() { + return tflite::micro::RegisterOp(nullptr, nullptr, LogicalAndEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical.h new file mode 100644 index 000000000..e70e45762 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical.h @@ -0,0 +1,35 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_LOGICAL_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_LOGICAL_H_ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { +// Input/output tensor index. +extern const int kLogicalInputTensor1; +extern const int kLogicalInputTensor2; +extern const int kLogicalOutputTensor; + +TfLiteStatus LogicalImpl(TfLiteContext* context, TfLiteNode* node, + bool (*func)(bool, bool)); + +bool LogicalOr(bool x, bool y); +bool LogicalAnd(bool x, bool y); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_LOGICAL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical_common.cc new file mode 100644 index 000000000..2612d3a4b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logical_common.cc @@ -0,0 +1,63 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/reference/binary_function.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/logical.h" + +namespace tflite { + +// Input/output tensor index. +const int kLogicalInputTensor1 = 0; +const int kLogicalInputTensor2 = 1; +const int kLogicalOutputTensor = 0; + +TfLiteStatus LogicalImpl(TfLiteContext* context, TfLiteNode* node, + bool (*func)(bool, bool)) { + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kLogicalInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kLogicalInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kLogicalOutputTensor); + + if (tflite::micro::HaveSameShapes(input1, input2)) { + reference_ops::BinaryFunction( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), func); + } else { + reference_ops::BroadcastBinaryFunction4DSlow( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), func); + } + + return kTfLiteOk; +} + +bool LogicalOr(bool x, bool y) { return x || y; } + +bool LogicalAnd(bool x, bool y) { return x && y; } + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic.cc new file mode 100644 index 000000000..108206ad3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic.cc @@ -0,0 +1,111 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/logistic.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/logistic.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +void* LogisticInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataLogistic)); +} + +TfLiteStatus LogisticEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kLogisticInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kLogisticOutputTensor); + + TFLITE_DCHECK(node->user_data != nullptr); + OpDataLogistic* data = static_cast(node->user_data); + + if (input->type == kTfLiteFloat32) { + switch (output->type) { + case kTfLiteFloat32: { + reference_ops::Logistic(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else if (input->type == kTfLiteInt16) { + switch (output->type) { + case kTfLiteInt16: { + reference_integer_ops::Logistic( + data->input_multiplier, data->input_left_shift, + NumElements(input->dims), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else if (input->type == kTfLiteInt8) { + switch (output->type) { + case kTfLiteInt8: { + reference_integer_ops::Logistic( + data->input_zero_point, data->input_range_radius, + data->input_multiplier, data->input_left_shift, + NumElements(input->dims), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else { + // TODO(b/141211002): Also support other data types once we have supported + // temporary tensors in TFLM. + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_LOGISTIC() { + return tflite::micro::RegisterOp(LogisticInit, LogisticPrepare, LogisticEval); +} +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic.h new file mode 100644 index 000000000..1de0cdab6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic.h @@ -0,0 +1,42 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_LOGISTIC_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_LOGISTIC_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { +extern const int kLogisticInputTensor; +extern const int kLogisticOutputTensor; + +struct OpDataLogistic { + int32_t input_zero_point; + int32_t input_range_radius; + int32_t input_multiplier; + int input_left_shift; +}; + +TfLiteStatus CalculateArithmeticOpDataLogistic(TfLiteContext* context, + TfLiteNode* node, + OpDataLogistic* data); + +TfLiteStatus LogisticPrepare(TfLiteContext* context, TfLiteNode* node); + +} // namespace tflite +#endif // TENSORFLOW_LITE_MICRO_KERNELS_LOGISTIC_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic_common.cc new file mode 100644 index 000000000..a79fd6bbf --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/logistic_common.cc @@ -0,0 +1,119 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h" +#include "tensorflow/lite/kernels/internal/reference/logistic.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/logistic.h" + +namespace tflite { +const int kLogisticInputTensor = 0; +const int kLogisticOutputTensor = 0; + +TfLiteStatus CalculateArithmeticOpDataLogistic(TfLiteContext* context, + TfLiteNode* node, + OpDataLogistic* data) { + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kLogisticInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kLogisticOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + if (input->type == kTfLiteInt8) { + TF_LITE_ENSURE_EQ(context, output->params.zero_point, + std::numeric_limits::min()); + + static constexpr int kInputIntegerBits = 4; + const double input_real_multiplier = + static_cast(input->params.scale) * + static_cast(1 << (31 - kInputIntegerBits)); + + data->input_zero_point = input->params.zero_point; + + const double q = std::frexp(input_real_multiplier, &data->input_left_shift); + data->input_multiplier = static_cast(TfLiteRound(q * (1ll << 31))); + + data->input_range_radius = + CalculateInputRadius(kInputIntegerBits, data->input_left_shift, 31); + } + + if (input->type == kTfLiteInt16) { + static constexpr int kInputIntegerBits = 3; + static constexpr int kOutputFractionalBits = 15; + + // See comments in TanhPrepare about requiring zero_point==0 + // and a power-of-two ("POT") scale. + + TF_LITE_ENSURE_EQ(context, input->params.zero_point, 0); + TF_LITE_ENSURE_EQ(context, output->params.zero_point, 0); + + int input_scale_log2_rounded; + bool param_scale_pot = + CheckedLog2(input->params.scale, &input_scale_log2_rounded); + + data->input_left_shift = + (15 - kInputIntegerBits) + input_scale_log2_rounded; + param_scale_pot &= (data->input_left_shift == 0); + + if (param_scale_pot) { + data->input_multiplier = 0; + } else { + // Calculate multiplier to change input scale to 1/(3*4096) + // as required by the table lookup. + // In this scaling +/-2^17 represents +/-10.7 + double multiplier = + static_cast(input->params.scale) * 4096.0 * 3.0; + + data->input_left_shift = 0; + + while (multiplier <= 32767.0 / 2.0 && data->input_left_shift <= 30) { + data->input_left_shift++; + multiplier = multiplier * 2.0; + } + + data->input_multiplier = static_cast(multiplier); + } + + int output_scale_log2_rounded; + TF_LITE_ENSURE( + context, CheckedLog2(output->params.scale, &output_scale_log2_rounded)); + TF_LITE_ENSURE_EQ(context, output_scale_log2_rounded, + -kOutputFractionalBits); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus LogisticPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + OpDataLogistic* data = static_cast(node->user_data); + + return CalculateArithmeticOpDataLogistic(context, node, data); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_eval.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_eval.cc new file mode 100644 index 000000000..04952c1d0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_eval.cc @@ -0,0 +1,1459 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/micro/kernels/lstm_eval.h" + +#include +#include +#include +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/portable_tensor_utils.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/tanh.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/micro_tensor_utils.h" + +namespace tflite { +namespace { +// Calculates a single LSTM gate. +// +// Implements the following formula: (* is matrix multiply) +// gate = activate(W_input * input + W_aux * aux_input + +// W_peephole * cell + W_recurrent * prev_output + bias) +// with layer norm: +// gate = activate(W_norm * normalize(...) + bias) // not adding bias inside +// +// Activation is sigmoid except for the "cell" gate (configurable, usually tanh) +// +// Parameters: +// Input vectors (to LSTM): | Size: | Optional? +// input | n_input | +// aux_input | n_aux_input | y (bidir LSTM) +// Input vectors (persistent states): +// output_state | n_output | +// cell_state | n_cell | +// 'Constant' inputs: +// input_to_gate_weights | n_cell * n_input | +// aux_input_to_gate_weights | n_cell * n_aux_input | y (bidir LSTM) +// recurrent_to_gate_weights | n_cell * n_output | +// cell_to_gate_weights | n_cell | y (peephole) +// gate_bias | n_cell | +// layer_norm_coefficients | n_cell | y (layer norm) +// Output vector: +// gate | n_cell | +// Scalar parameters: +// n_batch - batch size / number of vectors +// n_input, n_aux_input, n_output, n_cell - size of vectors. +// activation - activation to use. +// is_input_all_zeros, is_aux_input_all_zeros - if input vectors are all zero. +// use_layer_norm - if doing layer norm LSTM. +inline void CalculateLstmGateFloat( + const float* input, const float* input_to_gate_weights, + const float* aux_input, const float* aux_input_to_gate_weights, + const float* output_state, const float* recurrent_to_gate_weights, + const float* cell_state, const float* cell_to_gate_weights, + const float* layer_norm_coefficients, const float* gate_bias, + const int n_batch, const int n_input, const int n_aux_input, + const int n_output, const int n_cell, + const TfLiteFusedActivation activation, float* gate, + const bool is_input_all_zeros, const bool is_aux_input_all_zeros) { + const bool use_peephole = (cell_to_gate_weights != nullptr); + const bool use_layer_norm = (layer_norm_coefficients != nullptr); + + // Initialize scratch buffers with bias for regular lstm or initialize with + // zero for layer norm lstm. + if (use_layer_norm) { + memset(gate, 0, n_cell * n_batch * sizeof(float)); + } else { + tflite::tensor_utils::VectorBatchVectorAssign(gate_bias, n_cell, n_batch, + gate); + } + // For each batch and cell: compute input_weight * input. + // Skip if input is all zeros. + if (!is_input_all_zeros) { + tflite::tensor_utils::MatrixBatchVectorMultiplyAccumulate( + input_to_gate_weights, n_cell, n_input, input, n_batch, gate); + } + // For each batch and cell: compute aux_input_weight * aux_input. + // Skip if auxiliary input is not available or all zeros. + if (!is_aux_input_all_zeros) { + tflite::tensor_utils::MatrixBatchVectorMultiplyAccumulate( + aux_input_to_gate_weights, n_cell, n_aux_input, aux_input, n_batch, + gate); + } + // For each batch and cell: compute recurrent_weight * output_state. + tflite::tensor_utils::MatrixBatchVectorMultiplyAccumulate( + recurrent_to_gate_weights, n_cell, n_output, output_state, n_batch, gate); + // For each batch and cell: compute cell_weight .* cell_state (peephole LSTM) + if (use_peephole) { + tflite::tensor_utils::VectorBatchVectorCwiseProductAccumulate( + cell_to_gate_weights, n_cell, cell_state, n_batch, gate); + } + // Do layer normalization (if layer norm LSTM) + if (use_layer_norm) { + tflite::tensor_utils::MeanStddevNormalization(gate, gate, n_cell, n_batch); + tflite::tensor_utils::VectorBatchVectorCwiseProduct( + layer_norm_coefficients, n_cell, gate, n_batch, gate); + tflite::tensor_utils::VectorBatchVectorAdd(gate_bias, n_cell, n_batch, + gate); + } + // Apply activation + tflite::PortableApplyActivationToVector(gate, n_batch * n_cell, activation, + gate); +} + +// Updates the LSTM cell state, used by both float and hybrid LSTM versions. +// +// Implements the following formula: +// cell_state_new = clip(forget_gate * cell_state + input_gate * cell_gate) +// +// With CIFG LSTM, input gate is replaced by (1-forget_gate). +// +// Parameters: +// - n_batch, n_cell: sizes of vectors +// - cell_state: input/output vector, size n_batch*n_cell +// - input_gate: input vector, size n_batch*n_cell. +// - forget_gate: input/scratch vector, size n_batch*n_cell, modified with CIFG +// - cell_gate: input vector, size n_batch*n_cell. +// - use_cifg: use 1-forget_gate instead of input_gate. +// - clip: if > 0, clip the resulting cell state to [-clip, +clip]. +void UpdateLstmCellFloat(int n_batch, int n_cell, float* cell_state, + const float* input_gate, float* forget_gate, + const float* cell_gate, bool use_cifg, float clip) { + tflite::tensor_utils::VectorVectorCwiseProduct(forget_gate, cell_state, + n_batch * n_cell, cell_state); + + if (use_cifg) { + // With CIFG, input_gate = 1-forget_gate. Use the forget_gate array as + // scratch, as input_gate array is not allocated in this case. (Be careful + // not to write to the scratch before reading the forget gate data.) + float* scratch = forget_gate; + tflite::tensor_utils::Sub1Vector(forget_gate, n_batch * n_cell, scratch); + tflite::tensor_utils::VectorVectorCwiseProductAccumulate( + cell_gate, scratch, n_batch * n_cell, cell_state); + } else { + tflite::tensor_utils::VectorVectorCwiseProductAccumulate( + cell_gate, input_gate, n_batch * n_cell, cell_state); + } + if (clip > 0.0f) { + tflite::tensor_utils::CwiseClipping(cell_state, n_batch * n_cell, clip); + } +} + +// Calculates the output state tensor of an LSTM step. +// +// Implements the following formula: +// output_no_projection = output_gate .* activate(cell_state) +// (elementwise vector product) +// If no projection is used: +// output = output_state = output_no_projection +// With projection: +// output = output_state = clip(W*output_no_projection + bias) +// +// Output might not have a different 'stride' than n_batch, so we need to copy. +// +// Parameters: +// - n_batch: batches: the number of distinct vectors in each array. +// - n_cell, n_output: sizes of vectors. +// - cell_state, output_gate: input vectors, size n_batch*n_cell. +// - projection_weights, projection_weights_scale, projection_bias: +// constant inputs, describing projection matrix and bias. +// - proj_clip: if > 0, clip the output of the projection. +// - output_state: output vector, size n_batch*n_output. Must be contigous. +// - scratch: scratch area, size n_batch*n_cell. +void CalculateLstmOutputFloat(int n_batch, int n_cell, int n_output, + const float* cell_state, const float* output_gate, + TfLiteFusedActivation activation, + const float* projection_weights, + const float* projection_bias, + const float proj_clip, float* output_state, + float* scratch) { + tflite::PortableApplyActivationToVector(cell_state, n_batch * n_cell, + activation, scratch); + tflite::tensor_utils::VectorVectorCwiseProduct(output_gate, scratch, + n_batch * n_cell, scratch); + + const bool use_projection = (projection_weights != nullptr); + const bool use_projection_bias = (projection_bias != nullptr); + + if (use_projection) { + if (use_projection_bias) { + tflite::tensor_utils::VectorBatchVectorAssign(projection_bias, n_output, + n_batch, output_state); + } else { + memset(output_state, 0, n_batch * n_output * sizeof(float)); + } + tflite::tensor_utils::MatrixBatchVectorMultiplyAccumulate( + projection_weights, n_output, n_cell, scratch, n_batch, output_state); + if (proj_clip > 0.0f) { + tflite::tensor_utils::CwiseClipping(output_state, n_batch * n_output, + proj_clip); + } + } else { + std::memcpy(output_state, scratch, n_batch * n_output * sizeof(float)); + } +} + +// Calculates a single LSTM gate, int8x8_16 version. +// Implements the same functionality as CalculateLstmGateFloat. +void CalculateLstmGateInteger8x8_16( + // Input and weights + const int8_t* input, const int8_t* input_to_gate_weights, + const int32_t* input_to_gate_bias, const int32_t input_to_gate_scale_a, + const int32_t input_to_gate_scale_b, + // Output state and weights + const int8_t* output_state, const int8_t* recurrent_to_gate_weights, + const int32_t* recurrent_to_gate_bias, + const int32_t recurrent_to_gate_scale_a, + const int32_t recurrent_to_gate_scale_b, + // Cell state and weights + const int16_t* cell_state, const int16_t* cell_to_gate_weights, + const int32_t cell_to_gate_scale_a, const int32_t cell_to_gate_scale_b, + // Layer normalization parameters (layer norm LSTM) + const int16_t* layer_norm_coefficients, const int32_t* layer_norm_bias, + const int32_t layer_norm_input_scale_a, + const int32_t layer_norm_input_scale_b, + const int32_t layer_norm_variance_guard, + // Array sizes + const int n_batch, const int n_input, const int n_output, const int n_cell, + const TfLiteFusedActivation activation, + // Output + int16_t* gate, + // Parameters for performance optimizations + // Scratch arrays + int32_t* scratch5) { + const bool use_peephole = (cell_to_gate_weights != nullptr); + const bool use_layer_norm = (layer_norm_coefficients != nullptr); + + // Initialize scratch buffers with zeros. Note that unlike float and hybrid + // versions, bias is only used in layer normalization. + memset(gate, 0, n_batch * n_cell * sizeof(int16_t)); + // For each batch and cell: compute input_weight * input. + tflite::tensor_utils::MatrixBatchVectorMultiplyAccumulate( + input, input_to_gate_bias, input_to_gate_weights, input_to_gate_scale_a, + input_to_gate_scale_b, n_batch, n_input, n_cell, 0, scratch5, gate, + nullptr); + // Note: no aux_input. + + // For each batch and cell: compute recurrent_weight * output_state. + tflite::tensor_utils::MatrixBatchVectorMultiplyAccumulate( + output_state, recurrent_to_gate_bias, recurrent_to_gate_weights, + recurrent_to_gate_scale_a, recurrent_to_gate_scale_b, n_batch, n_output, + n_cell, 0, scratch5, gate, nullptr); + // For each batch and cell: compute cell_weight * cell_state (peephole LSTM) + if (use_peephole) { + tflite::tensor_utils::VectorBatchVectorCwiseProductAccumulate( + cell_to_gate_weights, n_output, cell_state, n_batch, + cell_to_gate_scale_a, cell_to_gate_scale_b, gate); + } + // Do layer normalization (if layer norm LSTM) + if (use_layer_norm) { + tflite::tensor_utils::ApplyLayerNorm( + gate, layer_norm_coefficients, layer_norm_bias, + layer_norm_input_scale_a, layer_norm_input_scale_b, + layer_norm_variance_guard, n_batch, n_cell, gate); + } + // Apply activation + switch (activation) { + case kTfLiteActSigmoid: + + reference_integer_ops::Logistic( + 0 /*data->input_multiplier*/, 0 /*data->input_left_shift */, + n_batch * n_cell /*NumElements(input->dims)*/, + gate /* tflite::micro::GetTensorData(input) */, + gate /*tflite::micro::GetTensorData(output) */); + + break; + case kTfLiteActTanh: { + int32_t dims_data = n_batch * n_cell; + RuntimeShape tanh_inp_shape = RuntimeShape(1, &dims_data); + reference_integer_ops::Tanh(0, 0, tanh_inp_shape, gate, tanh_inp_shape, + gate); + } break; + default: + // Only Sigmoid or Tanh is used. + TFLITE_ASSERT_FALSE; + } +} + +// Updates the LSTM cell state, used by both integer LSTM versions. +// Also see UpdateLstmCellFloat. +// +// Parameters: +// - n_batch, n_cell: sizes of vectors +// - cell_state: input/output vector, size n_batch*n_cell +// - cell_state_scale: scaling factor of cell state. +// - input_gate: input vector, size n_batch*n_cell. +// - forget_gate: input/scratch vector, size n_batch*n_cell, always modified. +// - cell_gate: input vector, size n_batch*n_cell. +// - use_cifg: use 1-forget_gate instead of input_gate. +// - clip: if > 0, clip the resulting cell state to [-clip, +clip]. +void UpdateLstmCellInteger(int n_batch, int n_cell, int16_t* cell_state, + int32_t cell_state_scale, const int16_t* input_gate, + int16_t* forget_gate, const int16_t* cell_gate, + bool use_cifg, int16_t clip) { + // Use the forget_gate array as scratch, as input_gate array is not allocated + // in CIFG case. (Be careful not to write to the scratch before reading the + // forget gate data.) + int16_t* scratch = forget_gate; + + tflite::tensor_utils::CwiseMul(forget_gate, cell_state, n_batch, n_cell, 15, + cell_state); + if (use_cifg) { + tflite::tensor_utils::Sub1Vector(forget_gate, n_batch * n_cell, scratch); + tflite::tensor_utils::CwiseMul(scratch, cell_gate, n_batch, n_cell, + 30 + cell_state_scale, scratch); + } else { + tflite::tensor_utils::CwiseMul(input_gate, cell_gate, n_batch, n_cell, + 30 + cell_state_scale, scratch); + } + tflite::tensor_utils::CwiseAdd(cell_state, scratch, n_batch, n_cell, + cell_state); + + if (clip > 0) { + tflite::tensor_utils::CwiseClipping(cell_state, n_batch * n_cell, clip); + } +} + +// Calculates the output state tensor of an LSTM step. See Float and hybrid +// versions as well. +// +// Parameters: +// - n_batch: batches: the number of distinct vectors in each array. +// - n_cell, n_output: sizes of vectors. +// - cell_state, output_gate: input vectors, size n_batch*n_cell. +// - cell_state_scale: scaling of cell_state. +// - hidden_scale_[a|b]: effective scale of cell_state.*output_gate +// - hidden_zp: zero_point for cell_state.*output_gate +// - projection_weights, proj_scale_[a|b], projection_bias: +// constant inputs, describing projection matrix and bias. +// - output_state_zp: zero point of output_state. (Input, calibrated value.) +// - quantized_proj_clip: if > 0, clip the output of the projection. +// - output_state: output vector, size n_batch*n_output. Must be contigous. +// - scratch0: scratch area of size n_batch*n_cell +// - scratch1: scratch area of size n_batch*n_cell +// - scratch2: scratch area used by MatrixBatchVectorMultiplyAccumulate +void CalculateLstmOutputInteger8x8_16( + int n_batch, int n_cell, int n_output, int16_t* cell_state, + int32_t cell_state_scale, const int16_t* output_gate, + int32_t hidden_scale_a, int32_t hidden_scale_b, int32_t hidden_zp, + const int8_t* projection_weights, int32_t proj_scale_a, + int32_t proj_scale_b, const int32_t* projection_bias, + int32_t output_state_zp, int8_t quantized_proj_clip, int8_t* output_state, + int16_t* scratch0, int8_t* scratch1, int32_t* scratch2) { + // Note: unlike float/hybrid, the activation is always Tanh. + + { + int32_t tanh_input_left_shift = (15 + cell_state_scale) - 3; + int32_t dims_data = n_batch * n_cell; + if (tanh_input_left_shift < 0) /* handling negative shift value */ + { + int32_t i; + tanh_input_left_shift = -tanh_input_left_shift; + for (i = 0; i < dims_data; i++) { + cell_state[i] = cell_state[i] >> tanh_input_left_shift; + } + tanh_input_left_shift = 0; + } + RuntimeShape tanh_inp_shape = RuntimeShape(1, &dims_data); + reference_integer_ops::Tanh(0, tanh_input_left_shift, tanh_inp_shape, + cell_state, tanh_inp_shape, scratch0); + } + tflite::tensor_utils::CwiseMul(output_gate, scratch0, hidden_scale_a, + hidden_scale_b, n_batch, n_cell, hidden_zp, + scratch1); + + const bool use_projection = (projection_weights != nullptr); + + if (use_projection) { + // Note: no bias like in float/hybrid + memset(output_state, 0, n_batch * n_output * sizeof(int8_t)); + tflite::tensor_utils::MatrixBatchVectorMultiplyAccumulate( + scratch1, projection_bias, projection_weights, proj_scale_a, + proj_scale_b, n_batch, n_cell, n_output, output_state_zp, scratch2, + output_state, nullptr); + if (quantized_proj_clip > 0) { + tflite::tensor_utils::CwiseClipping(output_state, n_batch * n_output, + quantized_proj_clip); + } + } else { + std::memcpy(output_state, scratch1, n_batch * n_output * sizeof(int8_t)); + } +} + +// Performs an LSTM batch inference step for input specified by input_ptr. +// The LSTM cell is specified by the pointers to its weights (*_weights_ptr) and +// biases (*_bias_ptr), and buffers (*_scratch), along with additional +// parameters: +// - params: various LSTM params including activation, clipping, etc., +// - n_batch: size of batch, +// - n_cell: number of cells (or units), +// - n_input: the input size, +// - n_aux_input: the auxiliary input size. +// - n_output: the output size. +// - output_batch_leading_dim: the leading dimension of the output buffer. +// +// Input of size 'n_batch * n_input': +// input_ptr +// Input of size 'n_batch * n_aux_input': +// aux_input_ptr - optional (can be nullptr) +// +// LSTM weights: +// Input weights of size 'n_cell * n_input': +// input_to_input_weights - optional +// input_to_forget_weights +// input_to_cell_weights +// input_to_output_weights +// Auxiliary input weights of size 'n_cell * n_aux_input': +// aux_input_to_input_weights - optional +// aux_input_to_forget_weights - optional +// aux_input_to_cell_weights - optional +// aux_input_to_output_weights - optional +// Recurrent weights of size 'n_cell * n_output': +// recurrent_to_input_weights - optional +// recurrent_to_forget_weights +// recurrent_to_cell_weights +// recurrent_to_input_weights +// Peephole weights of size 'n_cell', representing diagonal matrices. +// cell_to_input_weights - optional +// cell_to_cell_weights - optional +// cell_to_output_weights - optional +// Projection weights of size 'n_output * n_cell' +// projection_weights_ptr - optional +// Gate biases of size 'n_cell': +// input_gate_bias_ptr - optional +// forget_gate_bias_ptr +// cell_gate_bias_ptr +// output_gate_bias_ptr +// +// Layer norm coefficients of size 'n_cell', representing diagonal matrices. +// input_layer_norm_coefficients_ptr - optional +// forget_layer_norm_coefficients_ptr - optional +// cell_layer_norm_coefficients_ptr - optional +// output_layer_norm_coefficients_ptr - optional +// +// The pointers to the cell and output state and the output are updated. +// +// The pointers input_ptr, aux_input_ptr, and output_ptr point to data aligned +// in batch_major order, and each step processes batch_size many inputs from +// input_ptr, and updates batch_size many cell and output states. +// +// The output_batch_dim is output.shape[-1], i.e. the outermost dimension of the +// output tensor, and in most cases will be equal to n_output. It is usually not +// when we want to store the LSTM output into a slice of the output tensor, e.g. +// for bidirectional LSTMs with merge_outputs. In this case, the batched +// operations cannot be used since they assume that the batched outputs are +// contiguous, and we manually loop over the batched outputs. +inline void LstmStepFloat( + const float* input_ptr, const float* input_to_input_weights_ptr, + const float* input_to_forget_weights_ptr, + const float* input_to_cell_weights_ptr, + const float* input_to_output_weights_ptr, const float* aux_input_ptr, + const float* aux_input_to_input_weights_ptr, + const float* aux_input_to_forget_weights_ptr, + const float* aux_input_to_cell_weights_ptr, + const float* aux_input_to_output_weights_ptr, + const float* recurrent_to_input_weights_ptr, + const float* recurrent_to_forget_weights_ptr, + const float* recurrent_to_cell_weights_ptr, + const float* recurrent_to_output_weights_ptr, + const float* cell_to_input_weights_ptr, + const float* cell_to_forget_weights_ptr, + const float* cell_to_output_weights_ptr, + const float* input_layer_norm_coefficients_ptr, + const float* forget_layer_norm_coefficients_ptr, + const float* cell_layer_norm_coefficients_ptr, + const float* output_layer_norm_coefficients_ptr, + const float* input_gate_bias_ptr, const float* forget_gate_bias_ptr, + const float* cell_gate_bias_ptr, const float* output_gate_bias_ptr, + const float* projection_weights_ptr, const float* projection_bias_ptr, + const TfLiteLSTMParams* params, int n_batch, int n_cell, int n_input, + int n_aux_input, int n_output, int output_batch_leading_dim, + float* output_state_ptr, float* cell_state_ptr, float* scratch0, + float* scratch1, float* scratch2, float* scratch3, float* output_ptr) { + // Since we have already checked that weights are all there or none, we can + // check the existence of only one to the get the condition. + const bool use_cifg = (input_to_input_weights_ptr == nullptr); + + // Make named scratch buffers. + float* input_gate_scratch = scratch0; + float* forget_gate_scratch = scratch1; + float* cell_gate_scratch = scratch2; + float* output_gate_scratch = scratch3; + + // Check if inputs are all zeros so we can skip some computations. + const bool is_input_all_zeros = + tflite::tensor_utils::IsZeroVector(input_ptr, n_batch * n_input); + const bool is_aux_input_all_zeros = + (aux_input_ptr == nullptr || tflite::tensor_utils::IsZeroVector( + aux_input_ptr, n_batch * n_aux_input)); + if (!use_cifg) { + // Calculate the input gate. (If not CIFG.) + CalculateLstmGateFloat( + input_ptr, input_to_input_weights_ptr, aux_input_ptr, + aux_input_to_input_weights_ptr, output_state_ptr, + recurrent_to_input_weights_ptr, cell_state_ptr, + cell_to_input_weights_ptr, input_layer_norm_coefficients_ptr, + input_gate_bias_ptr, n_batch, n_input, n_aux_input, n_output, n_cell, + /*activation=*/kTfLiteActSigmoid, input_gate_scratch, + is_input_all_zeros, is_aux_input_all_zeros); + } + // Calculate the forget gate. + CalculateLstmGateFloat( + input_ptr, input_to_forget_weights_ptr, aux_input_ptr, + aux_input_to_forget_weights_ptr, output_state_ptr, + recurrent_to_forget_weights_ptr, cell_state_ptr, + cell_to_forget_weights_ptr, forget_layer_norm_coefficients_ptr, + forget_gate_bias_ptr, n_batch, n_input, n_aux_input, n_output, n_cell, + /*activation=*/kTfLiteActSigmoid, forget_gate_scratch, is_input_all_zeros, + is_aux_input_all_zeros); + // Calculate the cell update gate. + CalculateLstmGateFloat(input_ptr, input_to_cell_weights_ptr, aux_input_ptr, + aux_input_to_cell_weights_ptr, output_state_ptr, + recurrent_to_cell_weights_ptr, /*cell_state=*/nullptr, + /*cell_to_gate_weights=*/nullptr, + cell_layer_norm_coefficients_ptr, cell_gate_bias_ptr, + n_batch, n_input, n_aux_input, n_output, n_cell, + params->activation, cell_gate_scratch, + is_input_all_zeros, is_aux_input_all_zeros); + // Update the cell state. + UpdateLstmCellFloat(n_batch, n_cell, cell_state_ptr, input_gate_scratch, + forget_gate_scratch, cell_gate_scratch, use_cifg, + params->cell_clip); + // Calculate output gate. + CalculateLstmGateFloat( + input_ptr, input_to_output_weights_ptr, aux_input_ptr, + aux_input_to_output_weights_ptr, output_state_ptr, + recurrent_to_output_weights_ptr, cell_state_ptr, + cell_to_output_weights_ptr, output_layer_norm_coefficients_ptr, + output_gate_bias_ptr, n_batch, n_input, n_aux_input, n_output, n_cell, + /*activation=*/kTfLiteActSigmoid, output_gate_scratch, is_input_all_zeros, + is_aux_input_all_zeros); + // Update the output state. + CalculateLstmOutputFloat(n_batch, n_cell, n_output, cell_state_ptr, + output_gate_scratch, params->activation, + projection_weights_ptr, projection_bias_ptr, + params->proj_clip, output_state_ptr, scratch2); + // Copy output state to the output. Note that the output's rows may not be + // contiguous (output_batch_leading_dim != n_output). + for (int b = 0; b < n_batch; b++) { + std::memcpy(output_ptr + b * output_batch_leading_dim, + output_state_ptr + b * n_output, n_output * sizeof(float)); + } +} + +// Fully quantized lstm kernel for 16 bit gate matmul output. +// +// Input tensor of size n_batch * n_input: +// input_ptr +// +// LSTM weights: +// Quantized input weights of size 'n_cell * n_input': +// input_to_input_weight_ptr - optional +// input_to_forget_weight_ptr - optional +// input_to_cell_weight_ptr - optional +// input_to_output_weight_ptr - optional +// +// Quantized recurrent weights of size 'n_cell * n_output': +// recurrent_to_input_weight_ptr - optional +// recurrent_to_forget_weights_ptr +// recurrent_to_cell_weights_ptr +// recurrent_to_input_weights_ptr +// +// Quantized peephole weights of size 'n_cell', representing diagonal matrices. +// cell_to_input_weights - optional +// cell_to_cell_weights - optional +// cell_to_output_weights - optional +// +// Quantized projection weights of size 'n_output * n_cell' +// projection_weight_ptr - optional +// +// Weight scales (scalars) for each of the weights above. +// effective_input_to_input_scale_a - optional +// effective_input_to_input_scale_b - optional +// effective_input_to_forget_scale_a +// effective_input_to_forget_scale_b +// effective_input_to_cell_scale_a +// effective_input_to_cell_scale_b +// effective_input_to_output_scale_a +// effective_input_to_output_scale_b +// effective_recurrent_to_input_scale_a - optional +// effective_recurrent_to_input_scale_b - optional +// effective_recurrent_to_forget_scale_a +// effective_recurrent_to_forget_scale_b +// effective_recurrent_to_cell_scale_a +// effective_recurrent_to_cell_scale_b +// effective_recurrent_to_output_scale_a +// effective_recurrent_to_output_scale_b +// effective_proj_scale_a - optional +// effective_proj_scale_b - optional +// +// Gate biases of size 'n_cell': +// input_gate_bias_ptr - optional +// forget_gate_bias_ptr +// cell_gate_bias_ptr +// output_gate_bias_ptr +// +// Layer norm coefficients of size 'n_cell', representing diagonal matrices. +// layer_norm_input_weight_ptr - optional +// layer_norm_forget_weight_ptr - optional +// layer_norm_cell_weight_ptr - optional +// layer_norm_output_weight_ptr - optional +// +// Layer norm scales of size 'n_cell'. +// layer_norm_input_scale_a - optional +// layer_norm_input_scale_b - optional +// layer_norm_forget_scale_a - optional +// layer_norm_forget_scale_b - optional +// layer_norm_cell_scale_a - optional +// layer_norm_cell_scale_b - optional +// layer_norm_output_scale_a - optional +// layer_norm_output_scale_b - optional +// +// Scalar values: +// quantized_cell_clip: quantized clip value for cell. +// quantized_proj_clip: quantized clip value for projection. +// cell_state_scale: the power of two scale for cell state. +// +// Zero points: +// output_state_zp: zero point of output state +// hidden_zp: zero point for hidden state. +// +// Temporary pre-allocated storage for the calculation. Each is of size n_cell * +// n_batch. +// scratch0 +// scratch1 +// scratch2 +// scratch3 +// scratch4 +// scratch5: this scratch buffer is created purely for optimizing the +// MatrixBatchVectorMultiplyAccumulate. +// +// Outputs: +// output_state_ptr - size 'n_batch * n_output' +// cell_state_ptr - size 'n_batch * n_cell' +// output_ptr - size 'n_batch * n_output' +// TODO(b/159947023): scratch0 is not used if (!cifg). Don't allocate then. +inline void LstmStepInteger8x8_16( + const int8_t* input_ptr, const int8_t* input_to_input_weight_ptr, + int32_t effective_input_to_input_scale_a, + int32_t effective_input_to_input_scale_b, + const int8_t* input_to_forget_weight_ptr, + int32_t effective_input_to_forget_scale_a, + int32_t effective_input_to_forget_scale_b, + const int8_t* input_to_cell_weight_ptr, + int32_t effective_input_to_cell_scale_a, + int32_t effective_input_to_cell_scale_b, + const int8_t* input_to_output_weight_ptr, + int32_t effective_input_to_output_scale_a, + int32_t effective_input_to_output_scale_b, + const int8_t* recurrent_to_input_weight_ptr, + int32_t effective_recurrent_to_input_scale_a, + int32_t effective_recurrent_to_input_scale_b, + const int8_t* recurrent_to_forget_weight_ptr, + int32_t effective_recurrent_to_forget_scale_a, + int32_t effective_recurrent_to_forget_scale_b, + const int8_t* recurrent_to_cell_weight_ptr, + int32_t effective_recurrent_to_cell_scale_a, + int32_t effective_recurrent_to_cell_scale_b, + const int8_t* recurrent_to_output_weight_ptr, + int32_t effective_recurrent_to_output_scale_a, + int32_t effective_recurrent_to_output_scale_b, + const int16_t* cell_to_input_weight_ptr, + int32_t effective_cell_to_input_scale_a, + int32_t effective_cell_to_input_scale_b, + const int16_t* cell_to_forget_weight_ptr, + int32_t effective_cell_to_forget_scale_a, + int32_t effective_cell_to_forget_scale_b, + const int16_t* cell_to_output_weight_ptr, + int32_t effective_cell_to_output_scale_a, + int32_t effective_cell_to_output_scale_b, + const int8_t* projection_weight_ptr, int32_t effective_proj_scale_a, + int32_t effective_proj_scale_b, int32_t hidden_zp, + int32_t effective_hidden_scale_a, int32_t effective_hidden_scale_b, + const int16_t* layer_norm_input_weight_ptr, + int32_t layer_norm_input_scale_a, int32_t layer_norm_input_scale_b, + const int16_t* layer_norm_forget_weight_ptr, + int32_t layer_norm_forget_scale_a, int32_t layer_norm_forget_scale_b, + const int16_t* layer_norm_cell_weight_ptr, int32_t layer_norm_cell_scale_a, + int32_t layer_norm_cell_scale_b, + const int16_t* layer_norm_output_weight_ptr, + int32_t layer_norm_output_scale_a, int32_t layer_norm_output_scale_b, + const int32_t* input_gate_bias_ptr, const int32_t* forget_gate_bias_ptr, + const int32_t* cell_gate_bias_ptr, const int32_t* output_gate_bias_ptr, + int16_t quantized_cell_clip, int8_t quantized_proj_clip, + int32_t cell_state_scale, int32_t input_variance_guard, + int32_t forget_variance_guard, int32_t cell_variance_guard, + int32_t output_variance_guard, + const int32_t* input_to_forget_effective_bias, + const int32_t* recurrent_to_forget_effective_bias, + const int32_t* input_to_cell_effective_bias, + const int32_t* recurrent_to_cell_effective_bias, + const int32_t* input_to_output_effective_bias, + const int32_t* recurrent_to_output_effective_bias, + const int32_t* input_to_input_effective_bias, + const int32_t* recurrent_to_input_effective_bias, + const int32_t* projection_effective_bias, int n_batch, int n_cell, + int n_input, int n_output, int8_t* output_state_ptr, + int32_t output_state_zp, int16_t* cell_state_ptr, int8_t* output_ptr, + int16_t* scratch0, int16_t* scratch1, int16_t* scratch2, int16_t* scratch3, + int8_t* scratch4, int32_t* scratch5) { + // Make named scratch buffers for the different gates. + int16_t* input_gate_scratch = scratch0; + int16_t* forget_gate_scratch = scratch1; + int16_t* cell_gate_scratch = scratch2; + int16_t* output_gate_scratch = scratch3; + + // Since we have already checked that weights are all there or none, we + // can check the existence of only one to the get the condition. + const bool use_cifg = (input_to_input_weight_ptr == nullptr); + + // Check for nullptrs. + TFLITE_DCHECK(input_to_forget_effective_bias); + TFLITE_DCHECK(recurrent_to_forget_effective_bias); + TFLITE_DCHECK(input_to_cell_effective_bias); + TFLITE_DCHECK(recurrent_to_cell_effective_bias); + TFLITE_DCHECK(input_to_output_effective_bias); + TFLITE_DCHECK(recurrent_to_output_effective_bias); + if (!use_cifg) { + TFLITE_DCHECK(input_to_input_effective_bias); + TFLITE_DCHECK(recurrent_to_input_effective_bias); + } + const bool use_projection = (projection_weight_ptr != nullptr); + if (use_projection) { + TFLITE_DCHECK(projection_effective_bias); + } + if (!use_cifg) { + // Calculate the input gate. (If not CIFG.) + CalculateLstmGateInteger8x8_16( + input_ptr, input_to_input_weight_ptr, input_to_input_effective_bias, + effective_input_to_input_scale_a, effective_input_to_input_scale_b, + output_state_ptr, recurrent_to_input_weight_ptr, + recurrent_to_input_effective_bias, effective_recurrent_to_input_scale_a, + effective_recurrent_to_input_scale_b, cell_state_ptr, + cell_to_input_weight_ptr, effective_cell_to_input_scale_a, + effective_cell_to_input_scale_b, layer_norm_input_weight_ptr, + input_gate_bias_ptr, layer_norm_input_scale_a, layer_norm_input_scale_b, + input_variance_guard, n_batch, n_input, n_output, n_cell, + kTfLiteActSigmoid, input_gate_scratch, scratch5); + } + // Calculate the forget gate. + CalculateLstmGateInteger8x8_16( + input_ptr, input_to_forget_weight_ptr, input_to_forget_effective_bias, + effective_input_to_forget_scale_a, effective_input_to_forget_scale_b, + output_state_ptr, recurrent_to_forget_weight_ptr, + recurrent_to_forget_effective_bias, effective_recurrent_to_forget_scale_a, + effective_recurrent_to_forget_scale_b, cell_state_ptr, + cell_to_forget_weight_ptr, effective_cell_to_forget_scale_a, + effective_cell_to_forget_scale_b, layer_norm_forget_weight_ptr, + forget_gate_bias_ptr, layer_norm_forget_scale_a, + layer_norm_forget_scale_b, forget_variance_guard, n_batch, n_input, + n_output, n_cell, kTfLiteActSigmoid, forget_gate_scratch, scratch5); + // Calculate the cell update gate. + CalculateLstmGateInteger8x8_16( + input_ptr, input_to_cell_weight_ptr, input_to_cell_effective_bias, + effective_input_to_cell_scale_a, effective_input_to_cell_scale_b, + output_state_ptr, recurrent_to_cell_weight_ptr, + recurrent_to_cell_effective_bias, effective_recurrent_to_cell_scale_a, + effective_recurrent_to_cell_scale_b, cell_state_ptr, + /*cell_to_gate_weights=*/nullptr, /*cell_to_gate_scale_a=*/0, + /*cell_to_gate_scale_b=*/0, layer_norm_cell_weight_ptr, + cell_gate_bias_ptr, layer_norm_cell_scale_a, layer_norm_cell_scale_b, + cell_variance_guard, n_batch, n_input, n_output, n_cell, kTfLiteActTanh, + cell_gate_scratch, scratch5); + // Update the cell state. + UpdateLstmCellInteger(n_batch, n_cell, cell_state_ptr, cell_state_scale, + input_gate_scratch, forget_gate_scratch, + cell_gate_scratch, use_cifg, quantized_cell_clip); + // Calculate the output gate. + CalculateLstmGateInteger8x8_16( + input_ptr, input_to_output_weight_ptr, input_to_output_effective_bias, + effective_input_to_output_scale_a, effective_input_to_output_scale_b, + output_state_ptr, recurrent_to_output_weight_ptr, + recurrent_to_output_effective_bias, effective_recurrent_to_output_scale_a, + effective_recurrent_to_output_scale_b, cell_state_ptr, + cell_to_output_weight_ptr, effective_cell_to_output_scale_a, + effective_cell_to_output_scale_b, layer_norm_output_weight_ptr, + output_gate_bias_ptr, layer_norm_output_scale_a, + layer_norm_output_scale_b, output_variance_guard, n_batch, n_input, + n_output, n_cell, kTfLiteActSigmoid, output_gate_scratch, scratch5); + // Update the output state. + CalculateLstmOutputInteger8x8_16( + n_batch, n_cell, n_output, cell_state_ptr, cell_state_scale, + output_gate_scratch, effective_hidden_scale_a, effective_hidden_scale_b, + hidden_zp, projection_weight_ptr, effective_proj_scale_a, + effective_proj_scale_b, projection_effective_bias, output_state_zp, + quantized_proj_clip, output_state_ptr, scratch0, scratch4, scratch5); + // Copy output state to the output. Note that unlike float or hybrid, output + // is always contiguous. + std::memcpy(output_ptr, output_state_ptr, + n_batch * n_output * sizeof(int8_t)); +} + +} // namespace + +TfLiteStatus EvalFloatLstm( + const TfLiteEvalTensor* input, + const TfLiteEvalTensor* input_to_input_weights, + const TfLiteEvalTensor* input_to_forget_weights, + const TfLiteEvalTensor* input_to_cell_weights, + const TfLiteEvalTensor* input_to_output_weights, + const TfLiteEvalTensor* recurrent_to_input_weights, + const TfLiteEvalTensor* recurrent_to_forget_weights, + const TfLiteEvalTensor* recurrent_to_cell_weights, + const TfLiteEvalTensor* recurrent_to_output_weights, + const TfLiteEvalTensor* cell_to_input_weights, + const TfLiteEvalTensor* cell_to_forget_weights, + const TfLiteEvalTensor* cell_to_output_weights, + const TfLiteEvalTensor* input_layer_norm_coefficients, + const TfLiteEvalTensor* forget_layer_norm_coefficients, + const TfLiteEvalTensor* cell_layer_norm_coefficients, + const TfLiteEvalTensor* output_layer_norm_coefficients, + const TfLiteEvalTensor* aux_input, + const TfLiteEvalTensor* aux_input_to_input_weights, + const TfLiteEvalTensor* aux_input_to_forget_weights, + const TfLiteEvalTensor* aux_input_to_cell_weights, + const TfLiteEvalTensor* aux_input_to_output_weights, + const TfLiteEvalTensor* input_gate_bias, + const TfLiteEvalTensor* forget_gate_bias, + const TfLiteEvalTensor* cell_gate_bias, + const TfLiteEvalTensor* output_gate_bias, + const TfLiteEvalTensor* projection_weights, + const TfLiteEvalTensor* projection_bias, const TfLiteLSTMParams* params, + bool forward_sequence, bool time_major, int output_offset, + float* scratch_buffer, TfLiteEvalTensor* output_state, + TfLiteEvalTensor* cell_state, TfLiteEvalTensor* output) { + TFLITE_DCHECK(input->dims->size >= 2 && input->dims->size <= 3); + int max_time, n_batch; + if (input->dims->size == 3) { + max_time = (time_major) ? input->dims->data[0] : input->dims->data[1]; + n_batch = (time_major) ? input->dims->data[1] : input->dims->data[0]; + } else { + max_time = 1; + n_batch = input->dims->data[0]; + } + const int n_input = input->dims->data[input->dims->size - 1]; + const int aux_input_size = + (aux_input) ? aux_input->dims->data[aux_input->dims->size - 1] : 0; + + // n_cell and n_output will be the same size when there is no projection. + const int n_cell = input_to_output_weights->dims->data[0]; + const int n_output = recurrent_to_output_weights->dims->data[1]; + + // Since we have already checked that weights are all there or none, we can + // check the existence of only one to the get the condition. + const bool use_cifg = (input_to_input_weights == nullptr); + + // Index the scratch buffers pointers to the global scratch buffer. + float* input_gate_scratch = nullptr; + float* cell_gate_scratch = nullptr; + float* forget_gate_scratch = nullptr; + float* output_gate_scratch = nullptr; + if (use_cifg) { + cell_gate_scratch = scratch_buffer; + forget_gate_scratch = scratch_buffer + n_cell * n_batch; + output_gate_scratch = scratch_buffer + 2 * n_cell * n_batch; + } else { + input_gate_scratch = scratch_buffer; + cell_gate_scratch = scratch_buffer + n_cell * n_batch; + forget_gate_scratch = scratch_buffer + 2 * n_cell * n_batch; + output_gate_scratch = scratch_buffer + 3 * n_cell * n_batch; + } + + const int output_batch_leading_dim = + output->dims->data[output->dims->size - 1]; + if (time_major) { + // Loop through the sequence. + const int input_step = n_batch * n_input; + const int output_step = n_batch * output_batch_leading_dim; + for (int t = 0; t < max_time; t++) { + // If this is the forward_sequence, step forward, otherwise step + // backwards. + const int t_rel = forward_sequence ? t : max_time - t - 1; + const float* input_ptr = + tflite::micro::GetTensorData(input) + t_rel * input_step; + const float* aux_input_ptr = nullptr; + if (aux_input) { + aux_input_ptr = + tflite::micro::GetTensorData(aux_input) + t_rel * input_step; + } + float* output_ptr = tflite::micro::GetTensorData(output) + + t_rel * output_step + output_offset; + + LstmStepFloat( + input_ptr, + input_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_input_weights), + input_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_forget_weights), + input_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_cell_weights), + input_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_output_weights), + aux_input_ptr, + aux_input_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(aux_input_to_input_weights), + aux_input_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + aux_input_to_forget_weights), + aux_input_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(aux_input_to_cell_weights), + aux_input_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + aux_input_to_output_weights), + recurrent_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(recurrent_to_input_weights), + recurrent_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_forget_weights), + recurrent_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(recurrent_to_cell_weights), + recurrent_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_output_weights), + cell_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_input_weights), + cell_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_forget_weights), + cell_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_output_weights), + input_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + input_layer_norm_coefficients), + forget_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + forget_layer_norm_coefficients), + cell_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + cell_layer_norm_coefficients), + output_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + output_layer_norm_coefficients), + input_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_gate_bias), + forget_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(forget_gate_bias), + cell_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_gate_bias), + output_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(output_gate_bias), + projection_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(projection_weights), + projection_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(projection_bias), + params, n_batch, n_cell, n_input, aux_input_size, n_output, + output_batch_leading_dim, + tflite::micro::GetTensorData(output_state), + tflite::micro::GetTensorData(cell_state), input_gate_scratch, + forget_gate_scratch, cell_gate_scratch, output_gate_scratch, + output_ptr); + } + } else { + for (int b = 0; b < n_batch; b++) { + const int input_step = n_input; + const int output_step = output_batch_leading_dim; + for (int t = 0; t < max_time; t++) { + // If this is the forward_sequence, step forward, otherwise step + // backwards. + const int t_rel = forward_sequence ? t : max_time - t - 1; + const int time_offset = b * max_time + t_rel; + const float* input_ptr = tflite::micro::GetTensorData(input) + + time_offset * input_step; + const float* aux_input_ptr = nullptr; + if (aux_input) { + aux_input_ptr = tflite::micro::GetTensorData(aux_input) + + time_offset * input_step; + } + float* output_ptr = tflite::micro::GetTensorData(output) + + time_offset * output_step + output_offset; + + // Offset the {output,cell}_state pointers to the right batch. + float* output_state_ptr = + tflite::micro::GetTensorData(output_state) + + b * output_batch_leading_dim; + float* cell_state_ptr = + tflite::micro::GetTensorData(cell_state) + b * n_cell; + // Offset the scratch pointers to the right batch. + float* input_gate_scratch_ptr = + input_gate_scratch ? input_gate_scratch + b * n_cell : nullptr; + float* forget_gate_scratch_ptr = forget_gate_scratch + b * n_cell; + float* cell_gate_scratch_ptr = cell_gate_scratch + b * n_cell; + float* output_gate_scratch_ptr = output_gate_scratch + b * n_cell; + + LstmStepFloat( + input_ptr, + input_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_input_weights), + input_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_forget_weights), + input_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_cell_weights), + input_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_output_weights), + aux_input_ptr, + aux_input_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + aux_input_to_input_weights), + aux_input_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + aux_input_to_forget_weights), + aux_input_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + aux_input_to_cell_weights), + aux_input_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + aux_input_to_output_weights), + recurrent_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_input_weights), + recurrent_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_forget_weights), + recurrent_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_cell_weights), + recurrent_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_output_weights), + cell_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_input_weights), + cell_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_forget_weights), + cell_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_output_weights), + input_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + input_layer_norm_coefficients), + forget_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + forget_layer_norm_coefficients), + cell_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + cell_layer_norm_coefficients), + output_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + output_layer_norm_coefficients), + input_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_gate_bias), + forget_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(forget_gate_bias), + cell_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_gate_bias), + output_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(output_gate_bias), + projection_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(projection_weights), + projection_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(projection_bias), + params, + /*n_batch=*/1, n_cell, n_input, aux_input_size, n_output, + output_batch_leading_dim, output_state_ptr, cell_state_ptr, + input_gate_scratch_ptr, forget_gate_scratch_ptr, + cell_gate_scratch_ptr, output_gate_scratch_ptr, output_ptr); + } + } + } + return kTfLiteOk; +} + +TfLiteStatus EvalInteger8x8_16Lstm( + const TfLiteEvalTensor* input, + const TfLiteEvalTensor* input_to_input_weights, + const TfLiteEvalTensor* input_to_forget_weights, + const TfLiteEvalTensor* input_to_cell_weights, + const TfLiteEvalTensor* input_to_output_weights, + const TfLiteEvalTensor* recurrent_to_input_weights, + const TfLiteEvalTensor* recurrent_to_forget_weights, + const TfLiteEvalTensor* recurrent_to_cell_weights, + const TfLiteEvalTensor* recurrent_to_output_weights, + const TfLiteEvalTensor* cell_to_input_weights, + const TfLiteEvalTensor* cell_to_forget_weights, + const TfLiteEvalTensor* cell_to_output_weights, + const TfLiteEvalTensor* input_layer_norm_coefficients, + const TfLiteEvalTensor* forget_layer_norm_coefficients, + const TfLiteEvalTensor* cell_layer_norm_coefficients, + const TfLiteEvalTensor* output_layer_norm_coefficients, + const TfLiteEvalTensor* input_gate_bias, + const TfLiteEvalTensor* forget_gate_bias, + const TfLiteEvalTensor* cell_gate_bias, + const TfLiteEvalTensor* output_gate_bias, + const TfLiteEvalTensor* projection_weights, + const TfLiteEvalTensor* projection_bias, const TfLiteLSTMParams* params, + bool forward_sequence, bool time_major, + const IntegerLstmParameter* integer_lstm_param, int32_t output_state_zp, + TfLiteEvalTensor* output_state, TfLiteEvalTensor* cell_state, + TfLiteEvalTensor* output, int16_t* scratch0, int16_t* scratch1, + int16_t* scratch2, int16_t* scratch3, int8_t* scratch4, int32_t* scratch5) { + TFLITE_DCHECK(input->dims->size >= 2 && input->dims->size <= 3); + const int n_input = input->dims->data[input->dims->size - 1]; + int max_time, n_batch; + if (input->dims->size == 2) { + max_time = 1; + n_batch = input->dims->data[0]; + } else { + max_time = (time_major) ? input->dims->data[0] : input->dims->data[1]; + n_batch = (time_major) ? input->dims->data[1] : input->dims->data[0]; + } + + // n_cell and n_output will be the same size when there is no projection. + const int n_cell = input_to_output_weights->dims->data[0]; + const int n_output = recurrent_to_output_weights->dims->data[1]; + + // Get params for time/batch/sequence. + const int output_batch_leading_dim = + output->dims->data[output->dims->size - 1]; + + if (time_major) { + const int input_step = n_batch * n_input; + const int output_step = n_batch * output_batch_leading_dim; + for (int t = 0; t < max_time; t++) { + const int t_rel = t; + int8_t* output_ptr = + tflite::micro::GetTensorData(output) + t_rel * output_step; + const int8_t* input_ptr = + tflite::micro::GetTensorData(input) + t_rel * input_step; + LstmStepInteger8x8_16( + input_ptr, + input_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_input_weights), + integer_lstm_param->effective_input_to_input_scale_a, + integer_lstm_param->effective_input_to_input_scale_b, + input_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_forget_weights), + integer_lstm_param->effective_input_to_forget_scale_a, + integer_lstm_param->effective_input_to_forget_scale_b, + input_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_cell_weights), + integer_lstm_param->effective_input_to_cell_scale_a, + integer_lstm_param->effective_input_to_cell_scale_b, + input_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_output_weights), + integer_lstm_param->effective_input_to_output_scale_a, + integer_lstm_param->effective_input_to_output_scale_b, + recurrent_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_input_weights), + integer_lstm_param->effective_recurrent_to_input_scale_a, + integer_lstm_param->effective_recurrent_to_input_scale_b, + recurrent_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_forget_weights), + integer_lstm_param->effective_recurrent_to_forget_scale_a, + integer_lstm_param->effective_recurrent_to_forget_scale_b, + recurrent_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(recurrent_to_cell_weights), + integer_lstm_param->effective_recurrent_to_cell_scale_a, + integer_lstm_param->effective_recurrent_to_cell_scale_b, + recurrent_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_output_weights), + integer_lstm_param->effective_recurrent_to_output_scale_a, + integer_lstm_param->effective_recurrent_to_output_scale_b, + cell_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_input_weights), + integer_lstm_param->effective_cell_to_input_scale_a, + integer_lstm_param->effective_cell_to_input_scale_b, + cell_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_forget_weights), + integer_lstm_param->effective_cell_to_forget_scale_a, + integer_lstm_param->effective_cell_to_forget_scale_b, + cell_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_output_weights), + integer_lstm_param->effective_cell_to_output_scale_a, + integer_lstm_param->effective_cell_to_output_scale_b, + projection_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(projection_weights), + integer_lstm_param->effective_proj_scale_a, + integer_lstm_param->effective_proj_scale_b, + integer_lstm_param->hidden_zp, + integer_lstm_param->effective_hidden_scale_a, + integer_lstm_param->effective_hidden_scale_b, + input_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + input_layer_norm_coefficients), + integer_lstm_param->layer_norm_input_scale_a, + integer_lstm_param->layer_norm_input_scale_b, + forget_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + forget_layer_norm_coefficients), + integer_lstm_param->layer_norm_forget_scale_a, + integer_lstm_param->layer_norm_forget_scale_b, + cell_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + cell_layer_norm_coefficients), + integer_lstm_param->layer_norm_cell_scale_a, + integer_lstm_param->layer_norm_cell_scale_b, + output_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + output_layer_norm_coefficients), + integer_lstm_param->layer_norm_output_scale_a, + integer_lstm_param->layer_norm_output_scale_b, + input_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_gate_bias), + forget_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(forget_gate_bias), + cell_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_gate_bias), + output_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(output_gate_bias), + integer_lstm_param->quantized_cell_clip, + integer_lstm_param->quantized_proj_clip, + integer_lstm_param->cell_scale, + integer_lstm_param->input_variance_guard, + integer_lstm_param->forget_variance_guard, + integer_lstm_param->cell_variance_guard, + integer_lstm_param->output_variance_guard, + integer_lstm_param->input_to_forget_effective_bias, + integer_lstm_param->recurrent_to_forget_effective_bias, + integer_lstm_param->input_to_cell_effective_bias, + integer_lstm_param->recurrent_to_cell_effective_bias, + integer_lstm_param->input_to_output_effective_bias, + integer_lstm_param->recurrent_to_output_effective_bias, + integer_lstm_param->input_to_input_effective_bias, + integer_lstm_param->recurrent_to_input_effective_bias, + integer_lstm_param->projection_effective_bias, n_batch, n_cell, + n_input, n_output, tflite::micro::GetTensorData(output_state), + output_state_zp, tflite::micro::GetTensorData(cell_state), + output_ptr, scratch0, scratch1, scratch2, scratch3, scratch4, + scratch5); + } + } else { + for (int b = 0; b < n_batch; b++) { + const int input_step = n_input; + const int output_step = output_batch_leading_dim; + for (int t = 0; t < max_time; t++) { + // If this is the forward_sequence, step forward, otherwise step + // backwards. + const int t_rel = forward_sequence ? t : max_time - t - 1; + const int time_offset = b * max_time + t_rel; + const int8_t* input_ptr = tflite::micro::GetTensorData(input) + + time_offset * input_step; + int8_t* output_ptr = tflite::micro::GetTensorData(output) + + time_offset * output_step; + + // Offset the {output,cell}_state pointers to the right batch. + int8_t* output_state_ptr = + tflite::micro::GetTensorData(output_state) + + b * output_batch_leading_dim; + int16_t* cell_state_ptr = + tflite::micro::GetTensorData(cell_state) + b * n_cell; + + LstmStepInteger8x8_16( + input_ptr, + input_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_input_weights), + integer_lstm_param->effective_input_to_input_scale_a, + integer_lstm_param->effective_input_to_input_scale_b, + input_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_forget_weights), + integer_lstm_param->effective_input_to_forget_scale_a, + integer_lstm_param->effective_input_to_forget_scale_b, + input_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_cell_weights), + integer_lstm_param->effective_input_to_cell_scale_a, + integer_lstm_param->effective_input_to_cell_scale_b, + input_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_to_output_weights), + integer_lstm_param->effective_input_to_output_scale_a, + integer_lstm_param->effective_input_to_output_scale_b, + recurrent_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_input_weights), + integer_lstm_param->effective_recurrent_to_input_scale_a, + integer_lstm_param->effective_recurrent_to_input_scale_b, + recurrent_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_forget_weights), + integer_lstm_param->effective_recurrent_to_forget_scale_a, + integer_lstm_param->effective_recurrent_to_forget_scale_b, + recurrent_to_cell_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_cell_weights), + integer_lstm_param->effective_recurrent_to_cell_scale_a, + integer_lstm_param->effective_recurrent_to_cell_scale_b, + recurrent_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData( + recurrent_to_output_weights), + integer_lstm_param->effective_recurrent_to_output_scale_a, + integer_lstm_param->effective_recurrent_to_output_scale_b, + cell_to_input_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_input_weights), + integer_lstm_param->effective_cell_to_input_scale_a, + integer_lstm_param->effective_cell_to_input_scale_b, + cell_to_forget_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_forget_weights), + integer_lstm_param->effective_cell_to_forget_scale_a, + integer_lstm_param->effective_cell_to_forget_scale_b, + cell_to_output_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_to_output_weights), + integer_lstm_param->effective_cell_to_output_scale_a, + integer_lstm_param->effective_cell_to_output_scale_b, + projection_weights == nullptr + ? nullptr + : tflite::micro::GetTensorData(projection_weights), + integer_lstm_param->effective_proj_scale_a, + integer_lstm_param->effective_proj_scale_b, + integer_lstm_param->hidden_zp, + integer_lstm_param->effective_hidden_scale_a, + integer_lstm_param->effective_hidden_scale_b, + input_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + input_layer_norm_coefficients), + integer_lstm_param->layer_norm_input_scale_a, + integer_lstm_param->layer_norm_input_scale_b, + forget_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + forget_layer_norm_coefficients), + integer_lstm_param->layer_norm_forget_scale_a, + integer_lstm_param->layer_norm_forget_scale_b, + cell_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + cell_layer_norm_coefficients), + integer_lstm_param->layer_norm_cell_scale_a, + integer_lstm_param->layer_norm_cell_scale_b, + output_layer_norm_coefficients == nullptr + ? nullptr + : tflite::micro::GetTensorData( + output_layer_norm_coefficients), + integer_lstm_param->layer_norm_output_scale_a, + integer_lstm_param->layer_norm_output_scale_b, + input_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(input_gate_bias), + forget_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(forget_gate_bias), + cell_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(cell_gate_bias), + output_gate_bias == nullptr + ? nullptr + : tflite::micro::GetTensorData(output_gate_bias), + integer_lstm_param->quantized_cell_clip, + integer_lstm_param->quantized_proj_clip, + integer_lstm_param->cell_scale, + integer_lstm_param->input_variance_guard, + integer_lstm_param->forget_variance_guard, + integer_lstm_param->cell_variance_guard, + integer_lstm_param->output_variance_guard, + integer_lstm_param->input_to_forget_effective_bias, + integer_lstm_param->recurrent_to_forget_effective_bias, + integer_lstm_param->input_to_cell_effective_bias, + integer_lstm_param->recurrent_to_cell_effective_bias, + integer_lstm_param->input_to_output_effective_bias, + integer_lstm_param->recurrent_to_output_effective_bias, + integer_lstm_param->input_to_input_effective_bias, + integer_lstm_param->recurrent_to_input_effective_bias, + integer_lstm_param->projection_effective_bias, /*n_batch=*/1, + n_cell, n_input, n_output, output_state_ptr, output_state_zp, + cell_state_ptr, output_ptr, scratch0, scratch1, scratch2, scratch3, + scratch4, scratch5); + } + } + } + + return kTfLiteOk; +} + +} // namespace tflite \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_eval.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_eval.h new file mode 100644 index 000000000..262735dd0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_eval.h @@ -0,0 +1,154 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_LSTM_EVAL_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_LSTM_EVAL_H_ + +#include +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +// Pamameters for integer LSTM. +// Consider split this into two Integer Parameters if more fields are added. +struct IntegerLstmParameter { + int32_t effective_input_to_input_scale_a; + int32_t effective_input_to_input_scale_b; + int32_t effective_recurrent_to_input_scale_a; + int32_t effective_recurrent_to_input_scale_b; + int32_t effective_cell_to_input_scale_a; + int32_t effective_cell_to_input_scale_b; + int32_t effective_input_to_forget_scale_a; + int32_t effective_input_to_forget_scale_b; + int32_t effective_recurrent_to_forget_scale_a; + int32_t effective_recurrent_to_forget_scale_b; + int32_t effective_cell_to_forget_scale_a; + int32_t effective_cell_to_forget_scale_b; + int32_t effective_input_to_cell_scale_a; + int32_t effective_input_to_cell_scale_b; + int32_t effective_recurrent_to_cell_scale_a; + int32_t effective_recurrent_to_cell_scale_b; + int32_t effective_input_to_output_scale_a; + int32_t effective_input_to_output_scale_b; + int32_t effective_recurrent_to_output_scale_a; + int32_t effective_recurrent_to_output_scale_b; + int32_t effective_cell_to_output_scale_a; + int32_t effective_cell_to_output_scale_b; + int32_t effective_proj_scale_a; + int32_t effective_proj_scale_b; + int32_t effective_hidden_scale_a; + int32_t effective_hidden_scale_b; + int32_t layer_norm_input_scale_a; + int32_t layer_norm_input_scale_b; + int32_t layer_norm_forget_scale_a; + int32_t layer_norm_forget_scale_b; + int32_t layer_norm_cell_scale_a; + int32_t layer_norm_cell_scale_b; + int32_t layer_norm_output_scale_a; + int32_t layer_norm_output_scale_b; + // Quantized clip value for cell and projection. Zero value means no clipping. + int16_t quantized_cell_clip; + int8_t quantized_proj_clip; + int32_t hidden_zp; + int32_t cell_scale; + + int32_t input_variance_guard; + int32_t forget_variance_guard; + int32_t cell_variance_guard; + int32_t output_variance_guard; + + // Pre-calculate bias + zero_point * weight. + int32_t* input_to_forget_effective_bias; + int32_t* recurrent_to_forget_effective_bias; + int32_t* input_to_cell_effective_bias; + int32_t* recurrent_to_cell_effective_bias; + int32_t* input_to_output_effective_bias; + int32_t* recurrent_to_output_effective_bias; + int32_t* input_to_input_effective_bias; + int32_t* recurrent_to_input_effective_bias; + int32_t* projection_effective_bias; + + // Scale and zero point for intermediate tensors. + // Used only in the 8x8_8 case. + int32_t intermediate_scale_a[8]; + int32_t intermediate_scale_b[8]; + int32_t intermediate_zp[12]; +}; + +TfLiteStatus EvalFloatLstm( + const TfLiteEvalTensor* input, + const TfLiteEvalTensor* input_to_input_weights, + const TfLiteEvalTensor* input_to_forget_weights, + const TfLiteEvalTensor* input_to_cell_weights, + const TfLiteEvalTensor* input_to_output_weights, + const TfLiteEvalTensor* recurrent_to_input_weights, + const TfLiteEvalTensor* recurrent_to_forget_weights, + const TfLiteEvalTensor* recurrent_to_cell_weights, + const TfLiteEvalTensor* recurrent_to_output_weights, + const TfLiteEvalTensor* cell_to_input_weights, + const TfLiteEvalTensor* cell_to_forget_weights, + const TfLiteEvalTensor* cell_to_output_weights, + const TfLiteEvalTensor* input_layer_norm_coefficients, + const TfLiteEvalTensor* forget_layer_norm_coefficients, + const TfLiteEvalTensor* cell_layer_norm_coefficients, + const TfLiteEvalTensor* output_layer_norm_coefficients, + const TfLiteEvalTensor* aux_input, + const TfLiteEvalTensor* aux_input_to_input_weights, + const TfLiteEvalTensor* aux_input_to_forget_weights, + const TfLiteEvalTensor* aux_input_to_cell_weights, + const TfLiteEvalTensor* aux_input_to_output_weights, + const TfLiteEvalTensor* input_gate_bias, + const TfLiteEvalTensor* forget_gate_bias, + const TfLiteEvalTensor* cell_gate_bias, + const TfLiteEvalTensor* output_gate_bias, + const TfLiteEvalTensor* projection_weights, + const TfLiteEvalTensor* projection_bias, const TfLiteLSTMParams* params, + bool forward_sequence, bool time_major, int output_offset, + float* scratch_buffer, TfLiteEvalTensor* output_state, + TfLiteEvalTensor* cell_state, TfLiteEvalTensor* output); + +TfLiteStatus EvalInteger8x8_16Lstm( + const TfLiteEvalTensor* input, + const TfLiteEvalTensor* input_to_input_weights, + const TfLiteEvalTensor* input_to_forget_weights, + const TfLiteEvalTensor* input_to_cell_weights, + const TfLiteEvalTensor* input_to_output_weights, + const TfLiteEvalTensor* recurrent_to_input_weights, + const TfLiteEvalTensor* recurrent_to_forget_weights, + const TfLiteEvalTensor* recurrent_to_cell_weights, + const TfLiteEvalTensor* recurrent_to_output_weights, + const TfLiteEvalTensor* cell_to_input_weights, + const TfLiteEvalTensor* cell_to_forget_weights, + const TfLiteEvalTensor* cell_to_output_weights, + const TfLiteEvalTensor* input_layer_norm_coefficients, + const TfLiteEvalTensor* forget_layer_norm_coefficients, + const TfLiteEvalTensor* cell_layer_norm_coefficients, + const TfLiteEvalTensor* output_layer_norm_coefficients, + const TfLiteEvalTensor* input_gate_bias, + const TfLiteEvalTensor* forget_gate_bias, + const TfLiteEvalTensor* cell_gate_bias, + const TfLiteEvalTensor* output_gate_bias, + const TfLiteEvalTensor* projection_weights, + const TfLiteEvalTensor* projection_bias, const TfLiteLSTMParams* params, + bool forward_sequence, bool time_major, + const IntegerLstmParameter* integer_lstm_param, int32_t output_state_zp, + TfLiteEvalTensor* output_state, TfLiteEvalTensor* cell_state, + TfLiteEvalTensor* output, int16_t* scratch0, int16_t* scratch1, + int16_t* scratch2, int16_t* scratch3, int8_t* scratch4, int32_t* scratch5); + +} // namespace tflite +#endif // TENSORFLOW_LITE_MICRO_KERNELS_LSTM_EVAL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_shared.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_shared.h new file mode 100644 index 000000000..ee34b8489 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/lstm_shared.h @@ -0,0 +1,67 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_LSTM_SHARED_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_LSTM_SHARED_H_ + +namespace tflite { + +// Input Tensors of size {n_batch, n_input} +constexpr int kLstmInputTensor = 0; + +// Input weight tensors of size: {n_cell, n_input} +constexpr int kLstmInputToInputWeightsTensor = 1; // Optional +constexpr int kLstmInputToForgetWeightsTensor = 2; +constexpr int kLstmInputToCellWeightsTensor = 3; +constexpr int kLstmInputToOutputWeightsTensor = 4; + +// Recurrent weight tensors of size {n_cell, n_output} +constexpr int kLstmRecurrentToInputWeightsTensor = 5; // Optional +constexpr int kLstmRecurrentToForgetWeightsTensor = 6; +constexpr int kLstmRecurrentToCellWeightsTensor = 7; +constexpr int kLstmRecurrentToOutputWeightsTensor = 8; + +// Peephole weights tensors of size {n_cell}, representing a diagonal matrix. +constexpr int kLstmCellToInputWeightsTensor = 9; // Optional +constexpr int kLstmCellToForgetWeightsTensor = 10; // Optional +constexpr int kLstmCellToOutputWeightsTensor = 11; // Optional + +// Gates bias tensors of size {n_cell} +constexpr int kLstmInputGateBiasTensor = 12; // Optional +constexpr int kLstmForgetGateBiasTensor = 13; +constexpr int kLstmCellGateBiasTensor = 14; +constexpr int kLstmOutputGateBiasTensor = 15; + +// Projection weight tensor of size {n_output, n_cell} +constexpr int kLstmProjectionWeightsTensor = 16; // Optional +// Projection bias tensor of size {n_output} +constexpr int kLstmProjectionBiasTensor = 17; // Optional + +// These state tensors are defined as variable tensors, and will be modified by +// this op. +constexpr int kLstmOutputStateTensor = 18; +constexpr int kLstmCellStateTensor = 19; + +// Layer norm coefficient tensors of size {n_cell}, representing a diagonal +// matrix. +constexpr int kLstmInputLayerNormCoefficientsTensor = 20; // Optional +constexpr int kLstmForgetLayerNormCoefficientsTensor = 21; // Optional +constexpr int kLstmCellLayerNormCoefficientsTensor = 22; // Optional +constexpr int kLstmOutputLayerNormCoefficientsTensor = 23; // Optional + +// Output tensors. +constexpr int kLstmOutputTensor = 0; + +} // namespace tflite +#endif // TENSORFLOW_LITE_MICRO_KERNELS_LSTM_SHARED_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/maximum_minimum.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/maximum_minimum.cc new file mode 100644 index 000000000..1aebdefdc --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/maximum_minimum.cc @@ -0,0 +1,132 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/maximum_minimum.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace maximum_minimum { +namespace { + +// This file has a reference implementation of TFMaximum/TFMinimum. +enum KernelType { + kReference, +}; + +constexpr int kInputTensor1 = 0; +constexpr int kInputTensor2 = 1; +constexpr int kOutputTensor = 0; + +struct OpContext { + OpContext(TfLiteContext* context, TfLiteNode* node) { + input1 = tflite::micro::GetEvalInput(context, node, kInputTensor1); + input2 = tflite::micro::GetEvalInput(context, node, kInputTensor2); + output = tflite::micro::GetEvalOutput(context, node, kOutputTensor); + } + const TfLiteEvalTensor* input1; + const TfLiteEvalTensor* input2; + TfLiteEvalTensor* output; +}; + +struct MaximumOp { + template + static data_type op(data_type el1, data_type el2) { + return el1 > el2 ? el1 : el2; + } +}; + +struct MinimumOp { + template + static data_type op(data_type el1, data_type el2) { + return el1 < el2 ? el1 : el2; + } +}; + +} // namespace + +template +void TFLiteOperation(TfLiteContext* context, TfLiteNode* node, + const OpContext& op_context) { + reference_ops::MaximumMinimumBroadcastSlow( + tflite::micro::GetTensorShape(op_context.input1), + tflite::micro::GetTensorData(op_context.input1), + tflite::micro::GetTensorShape(op_context.input2), + tflite::micro::GetTensorData(op_context.input2), + tflite::micro::GetTensorShape(op_context.output), + tflite::micro::GetTensorData(op_context.output), + op_type::template op); +} + +template +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + OpContext op_context(context, node); + + if (kernel_type == kReference) { + switch (op_context.output->type) { + case kTfLiteFloat32: + TFLiteOperation(context, node, op_context); + break; + case kTfLiteInt8: + TFLiteOperation(context, node, op_context); + break; + case kTfLiteInt32: + TFLiteOperation(context, node, op_context); + break; + case kTfLiteInt64: + TFLiteOperation(context, node, op_context); + break; + default: + MicroPrintf("Type %s (%d) is not supported by Maximum/Minimum.", + TfLiteTypeGetName(op_context.output->type), + op_context.output->type); + return kTfLiteError; + } + } else { + MicroPrintf("Kernel type not supported by Maximum/Minimum."); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace maximum_minimum + +TfLiteRegistration Register_MAXIMUM() { + return tflite::micro::RegisterOp( + nullptr, nullptr, + maximum_minimum::Eval); +} + +TfLiteRegistration Register_MINIMUM() { + return tflite::micro::RegisterOp( + nullptr, nullptr, + maximum_minimum::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_ops.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_ops.h new file mode 100644 index 000000000..68583f75e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_ops.h @@ -0,0 +1,135 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_MICRO_OPS_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_MICRO_OPS_H_ + +#include "tensorflow/lite/c/common.h" + +// Forward declaration of all micro op kernel registration methods. These +// registrations are included with the standard `BuiltinOpResolver`. +// +// This header is particularly useful in cases where only a subset of ops are +// needed. In such cases, the client can selectively add only the registrations +// their model requires, using a custom `(Micro)MutableOpResolver`. Selective +// registration in turn allows the linker to strip unused kernels. + +namespace tflite { + +// TFLM is incrementally moving towards a flat tflite namespace +// (https://abseil.io/tips/130). Any new ops (or cleanup of existing ops should +// have their Register function declarations in the tflite namespace. + +TfLiteRegistration Register_ADD(); +TfLiteRegistration Register_ADD_N(); +TfLiteRegistration Register_ASSIGN_VARIABLE(); +TfLiteRegistration Register_AVERAGE_POOL_2D(); +TfLiteRegistration Register_BATCH_TO_SPACE_ND(); +TfLiteRegistration Register_BROADCAST_ARGS(); +TfLiteRegistration Register_BROADCAST_TO(); +TfLiteRegistration Register_CALL_ONCE(); +TfLiteRegistration Register_CAST(); +// TODO(b/160234179): Change custom OPs to also return by value. +TfLiteRegistration* Register_CIRCULAR_BUFFER(); +TfLiteRegistration Register_CUMSUM(); +TfLiteRegistration Register_DEPTH_TO_SPACE(); +TfLiteRegistration Register_DEPTHWISE_CONV_2D(); +TfLiteRegistration Register_DEQUANTIZE(); +TfLiteRegistration Register_DIV(); +TfLiteRegistration Register_ELU(); +TfLiteRegistration Register_EXP(); +TfLiteRegistration Register_EXPAND_DIMS(); +TfLiteRegistration Register_FILL(); +TfLiteRegistration Register_FLOOR_DIV(); +TfLiteRegistration Register_FLOOR_MOD(); +TfLiteRegistration Register_GATHER(); +TfLiteRegistration Register_GATHER_ND(); +TfLiteRegistration Register_HARD_SWISH(); +TfLiteRegistration Register_IF(); +TfLiteRegistration Register_L2_POOL_2D(); +TfLiteRegistration Register_LEAKY_RELU(); +TfLiteRegistration Register_LOG_SOFTMAX(); +TfLiteRegistration Register_LOGICAL_AND(); +TfLiteRegistration Register_LOGICAL_OR(); +TfLiteRegistration Register_LOGISTIC(); +TfLiteRegistration Register_MAX_POOL_2D(); +TfLiteRegistration Register_MIRROR_PAD(); +TfLiteRegistration Register_PRELU(); +TfLiteRegistration Register_MUL(); +TfLiteRegistration Register_QUANTIZE(); +TfLiteRegistration Register_READ_VARIABLE(); +TfLiteRegistration Register_RELU(); +TfLiteRegistration Register_RELU6(); +TfLiteRegistration Register_RESIZE_BILINEAR(); +TfLiteRegistration Register_SELECT_V2(); +TfLiteRegistration Register_SHAPE(); +TfLiteRegistration Register_SLICE(); +TfLiteRegistration Register_SPACE_TO_BATCH_ND(); +TfLiteRegistration Register_SPACE_TO_DEPTH(); +TfLiteRegistration Register_SQUARED_DIFFERENCE(); +TfLiteRegistration Register_SQUEEZE(); +TfLiteRegistration Register_SUB(); +TfLiteRegistration Register_SUM(); +TfLiteRegistration Register_SVDF(); +TfLiteRegistration Register_TRANSPOSE(); +TfLiteRegistration Register_TRANSPOSE_CONV(); +// TODO(b/230666079): resolve conflict with xtensa implementation +TfLiteRegistration Register_UNIDIRECTIONAL_SEQUENCE_LSTM(); +TfLiteRegistration Register_VAR_HANDLE(); +TfLiteRegistration Register_WHILE(); +TfLiteRegistration Register_ZEROS_LIKE(); + +namespace ops { +namespace micro { + +TfLiteRegistration Register_ABS(); +TfLiteRegistration Register_ARG_MAX(); +TfLiteRegistration Register_ARG_MIN(); +TfLiteRegistration Register_CEIL(); +TfLiteRegistration Register_CONCATENATION(); +TfLiteRegistration Register_COS(); +TfLiteRegistration Register_EQUAL(); +TfLiteRegistration Register_FLOOR(); +TfLiteRegistration Register_GREATER(); +TfLiteRegistration Register_GREATER_EQUAL(); +TfLiteRegistration Register_LESS(); +TfLiteRegistration Register_LESS_EQUAL(); +TfLiteRegistration Register_LOG(); +TfLiteRegistration Register_LOGICAL_NOT(); +TfLiteRegistration Register_MAXIMUM(); +TfLiteRegistration Register_MINIMUM(); +TfLiteRegistration Register_NEG(); +TfLiteRegistration Register_NOT_EQUAL(); +TfLiteRegistration Register_PACK(); +TfLiteRegistration Register_PAD(); +TfLiteRegistration Register_PADV2(); +TfLiteRegistration Register_RESHAPE(); +TfLiteRegistration Register_RESIZE_NEAREST_NEIGHBOR(); +TfLiteRegistration Register_ROUND(); +TfLiteRegistration Register_RSQRT(); +TfLiteRegistration Register_SIN(); +TfLiteRegistration Register_SPLIT(); +TfLiteRegistration Register_SPLIT_V(); +TfLiteRegistration Register_SQRT(); +TfLiteRegistration Register_SQUARE(); +TfLiteRegistration Register_STRIDED_SLICE(); +TfLiteRegistration Register_UNPACK(); +TfLiteRegistration Register_L2_NORMALIZATION(); +TfLiteRegistration Register_TANH(); + +} // namespace micro +} // namespace ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_MICRO_OPS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_tensor_utils.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_tensor_utils.cc new file mode 100644 index 000000000..628be9b4b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_tensor_utils.cc @@ -0,0 +1,67 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/micro/kernels/micro_tensor_utils.h" + +#include +#include +#include +#include +#include +#include + +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/cppmath.h" +#include "tensorflow/lite/kernels/op_macros.h" + +namespace tflite { + +// Apply sigmoid to elements of a vector. +void PortableApplySigmoidToVector(const float* vector, int v_size, + float* result) { + for (int v = 0; v < v_size; v++) { + result[v] = 1.0f / (1.0f + std::exp(-vector[v])); + } +} + +void PortableApplyTanhToVector(const float* vector, int v_size, float* result) { + for (int v = 0; v < v_size; v++) { + result[v] = std::tanh(vector[v]); + } +} + +void PortableApplyActivationToVector(const float* vector, int v_size, + TfLiteFusedActivation activation, + float* result) { + switch (activation) { + case kTfLiteActNone: + return; + case kTfLiteActRelu: + return tflite::tensor_utils::ApplyReluToVector(vector, v_size, result); + case kTfLiteActReluN1To1: + return tflite::tensor_utils::ApplyRelu1ToVector(vector, v_size, result); + case kTfLiteActRelu6: + return tflite::tensor_utils::ApplyRelu6ToVector(vector, v_size, result); + case kTfLiteActTanh: + return PortableApplyTanhToVector(vector, v_size, result); + case kTfLiteActSignBit: + return tflite::tensor_utils::ApplySignbitToVector(vector, v_size, result); + case kTfLiteActSigmoid: + return PortableApplySigmoidToVector(vector, v_size, result); + } +} + +} // namespace tflite \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_tensor_utils.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_tensor_utils.h new file mode 100644 index 000000000..0b87f0aea --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_tensor_utils.h @@ -0,0 +1,56 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This file and the associated .cc file is branched from +// tensorflow/lite/kernels/internal/reference/portable_tensor_utils* +// TFLM needs to create its own because the original files are coupled with +// the tensor_utils module, which we cannot reuse due to its use of the +// Eigen library. + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_MICRO_TENSOR_UTILS_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_MICRO_TENSOR_UTILS_H_ + +#include +#include +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/portable_tensor_utils.h" + +#if defined(_MSC_VER) +#define __restrict__ __restrict +#endif + +namespace tflite { + +// Not all backends support CpuBackendContext usage, so forward declare to avoid +// pulling in its implementation. +// TODO(b/230666277): consider removing this since micro does not utilize it +class CpuBackendContext; + +// Apply sigmoid to elements of a vector. +void PortableApplySigmoidToVector(const float* vector, int v_size, + float* result); +// Apply tanh to elements of a vector +void PortableApplyTanhToVector(const float* vector, int v_size, float* result); +// Apply appropriate activation function to elements of a vector. +void PortableApplyActivationToVector(const float* vector, int v_size, + TfLiteFusedActivation activation, + float* result); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_MICRO_TENSOR_UTILS_H_ \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_utils.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_utils.h new file mode 100644 index 000000000..e406ac12f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/micro_utils.h @@ -0,0 +1,40 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_MICRO_UTILS_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_MICRO_UTILS_H_ +namespace tflite { +namespace ops { +namespace micro { + +// Same as gtl::Greater but defined here to reduce dependencies and +// binary size for micro environment. +struct Greater { + template + bool operator()(const T& x, const T& y) const { + return x > y; + } +}; + +struct Less { + template + bool operator()(const T& x, const T& y) const { + return x < y; + } +}; + +} // namespace micro +} // namespace ops +} // namespace tflite +#endif // TENSORFLOW_LITE_MICRO_KERNELS_MICRO_UTILS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mirror_pad.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mirror_pad.cc new file mode 100644 index 000000000..90d3bd9e0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mirror_pad.cc @@ -0,0 +1,215 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { +namespace { + +struct OpDataMirrorPad { + int input_dims; + int output_size; + int offset; + int output_dims_num_elements_buffer_index; + int input_dims_num_elements_buffer_index; +}; + +// Helper method that fills the left and right pads. +template +inline void GetPadding(const T* data, int offset, int64_t* left_pad, + int64_t* right_pad) { + *left_pad = static_cast(*(data + offset * 2)); + *right_pad = static_cast(*(data + offset * 2 + 1)); +} + +// Given dimension index and the left/right padding. +// Returns the corresponding dimension in the input array. +inline int GetInputDimension(int padded_dimension, int left_pad, int right_pad, + int input_dim_size, int offset) { + if (padded_dimension < left_pad) { + const int original_ind = left_pad + offset - 1; + return original_ind - (std::min(padded_dimension, original_ind - offset)); + } + padded_dimension -= left_pad; + if (padded_dimension >= input_dim_size) { + padded_dimension -= input_dim_size; + const int original_ind = input_dim_size - (1 + offset); + return original_ind - std::min(padded_dimension, original_ind); + } + return padded_dimension; +} + +// Given and index in output array, returns the index of the value +// in input array. +int GetFlatIndex(int index, int num_dims, + const TfLiteEvalTensor* padding_matrix, + const TfLiteIntArray* input_dims, + int* output_dims_num_elements, int* input_dims_num_elements, + const int offset) { + int flat_index = 0; + int64_t left_pad = 0, right_pad = 0, dimension_index, index_in_input; + + for (int i = 0; i < num_dims; ++i) { + switch (padding_matrix->type) { + case kTfLiteInt32: + GetPadding(padding_matrix->data.i32, i, &left_pad, &right_pad); + break; + case kTfLiteInt64: + GetPadding(padding_matrix->data.i64, i, &left_pad, &right_pad); + break; + default: + break; + } + dimension_index = index / output_dims_num_elements[i]; + + index_in_input = GetInputDimension(dimension_index, left_pad, right_pad, + input_dims->data[i], offset); + + flat_index += index_in_input * (input_dims_num_elements)[i]; + index %= output_dims_num_elements[i]; + } + + return flat_index; +} + +template +void MirrorPad(const TfLiteEvalTensor* padding_matrix, + const TfLiteIntArray* input_dims, int* output_dims_num_elements, + int* input_dims_num_elements, const T* input_data, + T* output_data, const int offset, const int num_dims, + const int output_size) { + for (int i = 0; i < output_size; ++i) { + output_data[i] = input_data[GetFlatIndex( + i, num_dims, padding_matrix, input_dims, output_dims_num_elements, + input_dims_num_elements, offset)]; + } +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TfLiteStatus status = kTfLiteOk; + const OpDataMirrorPad* data = + static_cast(node->user_data); + + const TfLiteEvalTensor* input_tensor = + tflite::micro::GetEvalInput(context, node, 0); + const TfLiteEvalTensor* padding_matrix = + tflite::micro::GetEvalInput(context, node, 1); + + TfLiteEvalTensor* output_tensor = + tflite::micro::GetEvalOutput(context, node, 0); + const int input_dims = data->input_dims; + const int output_size = data->output_size; + + int* input_dims_num_elements = (int*)context->GetScratchBuffer( + context, data->input_dims_num_elements_buffer_index); + int* output_dims_num_elements = (int*)context->GetScratchBuffer( + context, data->output_dims_num_elements_buffer_index); + + for (int i = 0; i < input_dims; i++) { + output_dims_num_elements[i] = 1; + input_dims_num_elements[i] = 1; + } + + for (int i = input_dims - 2; i >= 0; i--) { + output_dims_num_elements[i] = + output_dims_num_elements[i + 1] * output_tensor->dims->data[i + 1]; + + input_dims_num_elements[i] = + input_dims_num_elements[i + 1] * input_tensor->dims->data[i + 1]; + } + + switch (output_tensor->type) { + case kTfLiteFloat32: { + MirrorPad(padding_matrix, input_tensor->dims, output_dims_num_elements, + input_dims_num_elements, + tflite::micro::GetTensorData(input_tensor), + tflite::micro::GetTensorData(output_tensor), + data->offset, input_dims, output_size); + break; + } + case kTfLiteInt8: { + MirrorPad(padding_matrix, input_tensor->dims, output_dims_num_elements, + input_dims_num_elements, + tflite::micro::GetTensorData(input_tensor), + tflite::micro::GetTensorData(output_tensor), + data->offset, input_dims, output_size); + break; + } + default: + status = kTfLiteError; + break; + } + +#undef TF_LITE_MIRROR_PAD + + return status; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataMirrorPad)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TFLITE_DCHECK(node->user_data != nullptr); + OpDataMirrorPad* data = static_cast(node->user_data); + + TfLiteTensor* input_tensor = micro_context->AllocateTempInputTensor(node, 0); + TfLiteTensor* padding_matrix = + micro_context->AllocateTempInputTensor(node, 1); + TfLiteTensor* output_tensor = + micro_context->AllocateTempOutputTensor(node, 0); + + TF_LITE_ENSURE_EQ(context, NumDimensions(padding_matrix), 2); + TF_LITE_ENSURE_EQ(context, SizeOfDimension(padding_matrix, 0), + NumDimensions(input_tensor)); + auto* params = + reinterpret_cast(node->builtin_data); + if (params == nullptr) { + return kTfLiteError; + } + + data->offset = + params->mode != TfLiteMirrorPaddingMode::kTfLiteMirrorPaddingReflect ? 0 + : 1; + data->input_dims = NumDimensions(input_tensor); + data->output_size = NumElements(output_tensor); + + TF_LITE_ENSURE_STATUS(context->RequestScratchBufferInArena( + context, data->input_dims * sizeof(int), + &data->output_dims_num_elements_buffer_index)); + TF_LITE_ENSURE_STATUS(context->RequestScratchBufferInArena( + context, data->input_dims * sizeof(int), + &data->input_dims_num_elements_buffer_index)); + + micro_context->DeallocateTempTfLiteTensor(input_tensor); + micro_context->DeallocateTempTfLiteTensor(padding_matrix); + micro_context->DeallocateTempTfLiteTensor(output_tensor); + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_MIRROR_PAD() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul.cc new file mode 100644 index 000000000..abbfb3ebf --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul.cc @@ -0,0 +1,67 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/mul.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/mul.h" +#include "tensorflow/lite/kernels/internal/reference/mul.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +TfLiteStatus MulEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataMul* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kMulInput1Tensor); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kMulInput2Tensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kMulOutputTensor); + + switch (input1->type) { + case kTfLiteInt8: + case kTfLiteInt32: + EvalMulQuantizedReference(context, node, data, input1, input2, output); + break; + case kTfLiteFloat32: + EvalMulFloatReference(context, node, params, data, input1, input2, + output); + break; + default: + MicroPrintf("Type %s (%d) not supported.", + TfLiteTypeGetName(input1->type), input1->type); + return kTfLiteError; + } + + return kTfLiteOk; +} + +TfLiteRegistration Register_MUL() { + return tflite::micro::RegisterOp(MulInit, MulPrepare, MulEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul.h new file mode 100644 index 000000000..0c6379e11 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul.h @@ -0,0 +1,74 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_MUL_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_MUL_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +extern const int kMulInput1Tensor; +extern const int kMulInput2Tensor; +extern const int kMulOutputTensor; + +struct OpDataMul { + int32_t input1_zero_point; + int32_t input2_zero_point; + + int32_t output_activation_min; + int32_t output_activation_max; + int32_t output_zero_point; + int32_t output_multiplier; + int output_shift; + + float output_activation_min_f32; + float output_activation_max_f32; +}; + +void* MulInit(TfLiteContext* context, const char* buffer, size_t length); + +TfLiteStatus CalculateOpDataMul(TfLiteContext* context, TfLiteNode* node, + TfLiteMulParams* params, OpDataMul* data); + +TfLiteStatus MulPrepare(TfLiteContext* context, TfLiteNode* node); + +void EvalMulQuantizedReference(TfLiteContext* context, TfLiteNode* node, + const OpDataMul* data, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output); + +void EvalMulFloatReference(TfLiteContext* context, TfLiteNode* node, + TfLiteMulParams* params, const OpDataMul* data, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output); + +// Generic must define registration function. +TfLiteRegistration Register_MUL(); + +#if defined(CMSIS_NN) +TfLiteRegistration Register_MUL_INT8(); +#else +// Fallback registration +inline TfLiteRegistration Register_MUL_INT8() { return Register_MUL(); } +#endif +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_MUL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul_common.cc new file mode 100644 index 000000000..6d19ac7aa --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/mul_common.cc @@ -0,0 +1,184 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/mul.h" +#include "tensorflow/lite/kernels/internal/reference/mul.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/mul.h" +#include "tensorflow/lite/micro/memory_helpers.h" + +namespace tflite { + +const int kMulInput1Tensor = 0; +const int kMulInput2Tensor = 1; +const int kMulOutputTensor = 0; + +void* MulInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataMul)); +} + +TfLiteStatus CalculateOpDataMul(TfLiteContext* context, TfLiteNode* node, + TfLiteMulParams* params, OpDataMul* data) { + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input1 = + micro_context->AllocateTempInputTensor(node, kMulInput1Tensor); + TF_LITE_ENSURE(context, input1 != nullptr); + TfLiteTensor* input2 = + micro_context->AllocateTempInputTensor(node, kMulInput2Tensor); + TF_LITE_ENSURE(context, input2 != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kMulOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TF_LITE_ENSURE_TYPES_EQ(context, input1->type, input2->type); + + if (output->type == kTfLiteInt8) { + TF_LITE_ENSURE_STATUS(CalculateActivationRangeQuantized( + context, params->activation, output, &data->output_activation_min, + &data->output_activation_max)); + + double real_multiplier = static_cast(input1->params.scale) * + static_cast(input2->params.scale) / + static_cast(output->params.scale); + QuantizeMultiplier(real_multiplier, &data->output_multiplier, + &data->output_shift); + + data->input1_zero_point = input1->params.zero_point; + data->input2_zero_point = input2->params.zero_point; + data->output_zero_point = output->params.zero_point; + } else if (output->type == kTfLiteInt32) { + CalculateActivationRange(params->activation, &data->output_activation_min, + &data->output_activation_max); + } else { + CalculateActivationRange(params->activation, + &data->output_activation_min_f32, + &data->output_activation_max_f32); + } + + micro_context->DeallocateTempTfLiteTensor(input1); + micro_context->DeallocateTempTfLiteTensor(input2); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus MulPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + OpDataMul* data = static_cast(node->user_data); + + return CalculateOpDataMul(context, node, params, data); +} + +void EvalMulQuantizedReference(TfLiteContext* context, TfLiteNode* node, + const OpDataMul* data, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params = {}; + op_params.quantized_activation_min = data->output_activation_min; + op_params.quantized_activation_max = data->output_activation_max; + op_params.float_activation_max = data->output_activation_max_f32; + op_params.input1_offset = -data->input1_zero_point; + op_params.input2_offset = -data->input2_zero_point; + op_params.output_offset = data->output_zero_point; + op_params.output_multiplier = data->output_multiplier; + op_params.output_shift = data->output_shift; + + bool need_broadcast = reference_ops::ProcessBroadcastShapes( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), &op_params); + + if (input1->type == kTfLiteInt8) { + if (need_broadcast) { + reference_integer_ops::BroadcastMul4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_integer_ops::Mul(op_params, + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } + } else if (input1->type == kTfLiteInt32) { + if (need_broadcast) { + reference_ops::BroadcastMul4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_ops::Mul(op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } + } +} + +void EvalMulFloatReference(TfLiteContext* context, TfLiteNode* node, + TfLiteMulParams* params, const OpDataMul* data, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params = {}; + op_params.float_activation_min = data->output_activation_min_f32; + op_params.float_activation_max = data->output_activation_max_f32; + + bool need_broadcast = reference_ops::ProcessBroadcastShapes( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), &op_params); + + if (need_broadcast) { + reference_ops::BroadcastMul4DSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_ops::Mul(op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/neg.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/neg.cc new file mode 100644 index 000000000..36c7eac66 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/neg.cc @@ -0,0 +1,60 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/neg.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace neg { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + switch (input->type) { + // TODO(wangtz): handle for kTfLiteInt8 + case kTfLiteFloat32: + reference_ops::Negate(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace neg + +TfLiteRegistration Register_NEG() { + return tflite::micro::RegisterOp(nullptr, nullptr, neg::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pack.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pack.cc new file mode 100644 index 000000000..5e322b87b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pack.cc @@ -0,0 +1,117 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace pack { +namespace { + +constexpr int kOutputTensor = 0; + +template +TfLiteStatus PackImpl(TfLiteContext* context, TfLiteNode* node, + TfLiteEvalTensor* output, int values_count, int axis) { + const TfLiteEvalTensor* input0 = + tflite::micro::GetEvalInput(context, node, 0); + + const int dimensions = output->dims->size; + const TfLiteIntArray* input_dims = input0->dims; + const TfLiteIntArray* output_dims = output->dims; + + if (axis < 0) { + axis += dimensions; + } + + int outer_size = 1; + for (int i = 0; i < axis; ++i) { + outer_size *= output_dims->data[i]; + } + int copy_size = 1; + for (int i = axis + 1; i < dimensions; ++i) { + copy_size *= output_dims->data[i]; + } + int input_size = 1; + for (int i = 0; i < input_dims->size; ++i) { + input_size *= input_dims->data[i]; + } + TFLITE_DCHECK_EQ(input_size, copy_size * outer_size); + + T* output_data = tflite::micro::GetTensorData(output); + + for (int i = 0; i < values_count; ++i) { + const TfLiteEvalTensor* t = tflite::micro::GetEvalInput(context, node, i); + const T* input_data = tflite::micro::GetTensorData(t); + for (int k = 0; k < outer_size; ++k) { + const T* input_ptr = input_data + copy_size * k; + int loc = k * values_count * copy_size + i * copy_size; + T* output_ptr = output_data + loc; + for (int j = 0; j < copy_size; ++j) output_ptr[j] = input_ptr[j]; + } + } + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLitePackParams* data = + reinterpret_cast(node->builtin_data); + + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + switch (output->type) { + case kTfLiteFloat32: { + return PackImpl(context, node, output, data->values_count, + data->axis); + } + case kTfLiteInt8: { + return PackImpl(context, node, output, data->values_count, + data->axis); + } + case kTfLiteInt32: { + return PackImpl(context, node, output, data->values_count, + data->axis); + } + case kTfLiteInt64: { + return PackImpl(context, node, output, data->values_count, + data->axis); + } + default: { + MicroPrintf("Type '%s' is not supported by pack.", + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } + + return kTfLiteOk; +} + +} // namespace +} // namespace pack + +TfLiteRegistration Register_PACK() { + return tflite::micro::RegisterOp(nullptr, nullptr, pack::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pad.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pad.cc new file mode 100644 index 000000000..a0f2aeee2 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pad.cc @@ -0,0 +1,237 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/pad.h" + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/portable_tensor.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace pad { +namespace { + +struct OpData { + PadParams params; + int32_t output_zero_point; +}; + +} // namespace + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TFLITE_DCHECK(node->user_data != nullptr); + OpData* data = static_cast(node->user_data); + + TF_LITE_ENSURE(context, NumInputs(node) == 2 || NumInputs(node) == 3); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, /*index=*/0); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* paddings = + micro_context->AllocateTempInputTensor(node, /*index=*/1); + TF_LITE_ENSURE(context, paddings != nullptr); + TfLiteTensor* constant_values = + NumInputs(node) == 3 + ? micro_context->AllocateTempInputTensor(node, /*index=*/2) + : nullptr; + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, /*index=*/0); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_EQ(context, input->type, output->type); + + // Current implementations rely on the inputs being <= 4D. + TF_LITE_ENSURE(context, NumDimensions(input) <= + reference_ops::PadKernelMaxDimensionCount()); + + if (constant_values != nullptr) { + TF_LITE_ENSURE_EQ(context, input->type, constant_values->type); + // Ensure that constant_values is a scalar. + TF_LITE_ENSURE_EQ(context, NumElements(constant_values), 1); + } + + // There must be a pair of paddings for each output dimension. + TF_LITE_ENSURE_EQ(context, GetTensorShape(paddings).FlatSize(), + output->dims->size * 2); + + // On Micro, outputs must be properly sized by the converter. + // NOTE: This data is only available because the paddings buffer is stored in + // the flatbuffer: + TF_LITE_ENSURE(context, IsConstantTensor(paddings)); + const int32_t* paddings_data = GetTensorData(paddings); + for (int i = 0; i < output->dims->size; i++) { + int output_dim = output->dims->data[i]; + int expected_dim = + input->dims->data[i] + paddings_data[i * 2] + paddings_data[i * 2 + 1]; + TF_LITE_ENSURE_EQ(context, output_dim, expected_dim); + } + + // Calculate OpData: + data->params.resizing_category = ResizingCategory::kGenericResize; + const int paddings_total = GetTensorShape(paddings).FlatSize(); + if (paddings_total == 8 && (paddings_data[0] == 0 && paddings_data[1] == 0) && + (paddings_data[6] == 0 && paddings_data[7] == 0)) { + data->params.resizing_category = ResizingCategory::kImageStyle; + } + + const int num_input_dimensions = NumDimensions(input); + data->params.left_padding_count = num_input_dimensions; + data->params.right_padding_count = num_input_dimensions; + + for (int idx = num_input_dimensions - 1; idx >= 0; --idx) { + data->params.left_padding[idx] = paddings_data[idx * 2]; + data->params.right_padding[idx] = paddings_data[idx * 2 + 1]; + } + + if (input->type == kTfLiteInt8) { + if (constant_values == nullptr) { + // Quantized Pad requires that 0 is represented in the quantized + // range. + TF_LITE_ENSURE(context, output->params.zero_point >= + std::numeric_limits::min()); + TF_LITE_ENSURE(context, output->params.zero_point <= + std::numeric_limits::max()); + } else { + // Quantized Pad requires that 'constant_values' is represented in the + // same quantized range as the input and output tensors. + TF_LITE_ENSURE_EQ(context, output->params.zero_point, + constant_values->params.zero_point); + TF_LITE_ENSURE_EQ(context, static_cast(output->params.scale), + static_cast(constant_values->params.scale)); + } + data->output_zero_point = output->params.zero_point; + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(paddings); + if (constant_values != nullptr) { + micro_context->DeallocateTempTfLiteTensor(constant_values); + } + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const OpData* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, /*index=*/0); + const TfLiteEvalTensor* constant_values = + NumInputs(node) == 3 + ? tflite::micro::GetEvalInput(context, node, /*index=*/2) + : nullptr; + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, /*index=*/0); + + switch (input->type) { + case kTfLiteFloat32: { + float pad_value = + constant_values == nullptr + ? 0.f + : *tflite::micro::GetTensorData(constant_values); + if (data->params.resizing_category == ResizingCategory::kImageStyle) { + reference_ops::PadImageStyle( + data->params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), &pad_value, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_ops::Pad(data->params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + &pad_value, tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } + } break; + case kTfLiteInt8: { + int8_t pad_value; + if (constant_values == nullptr) { + pad_value = static_cast(data->output_zero_point); + } else { + pad_value = *tflite::micro::GetTensorData(constant_values); + } + if (data->params.resizing_category == ResizingCategory::kImageStyle) { + reference_ops::PadImageStyle( + data->params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), &pad_value, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + reference_ops::Pad(data->params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + &pad_value, tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } + } break; + case kTfLiteInt16: { + int16_t pad_value = + constant_values == nullptr + ? 0 + : *tflite::micro::GetTensorData(constant_values); + reference_ops::Pad(data->params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + &pad_value, tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } break; + case kTfLiteInt32: { + int32_t pad_value = + constant_values == nullptr + ? 0 + : *tflite::micro::GetTensorData(constant_values); + reference_ops::Pad(data->params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + &pad_value, tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } break; + default: + + MicroPrintf("Type %s not currently supported by Pad.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace pad + +TfLiteRegistration Register_PAD() { + return tflite::micro::RegisterOp(pad::Init, pad::Prepare, pad::Eval); +} + +// Also register Pad as PadV2. +TfLiteRegistration Register_PADV2() { + return tflite::micro::RegisterOp(pad::Init, pad::Prepare, pad::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling.cc new file mode 100644 index 000000000..d9b147ad8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling.cc @@ -0,0 +1,99 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/pooling.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/pooling.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +namespace { + +TfLiteStatus AverageEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataPooling* data = + static_cast(node->user_data); + + const TfLiteEvalTensor* input = + micro::GetEvalInput(context, node, kPoolingInputTensor); + TfLiteEvalTensor* output = + micro::GetEvalOutput(context, node, kPoolingOutputTensor); + + // Inputs and outputs share the same type, guaranteed by the converter. + switch (input->type) { + case kTfLiteFloat32: + AveragePoolingEvalFloat(context, node, params, data, input, output); + break; + case kTfLiteInt8: + AveragePoolingEvalQuantized(context, node, params, data, input, output); + break; + default: + MicroPrintf("Input type %s is not currently supported", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus MaxEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataPooling* data = + static_cast(node->user_data); + + const TfLiteEvalTensor* input = + micro::GetEvalInput(context, node, kPoolingInputTensor); + TfLiteEvalTensor* output = + micro::GetEvalOutput(context, node, kPoolingOutputTensor); + + switch (input->type) { + case kTfLiteFloat32: + MaxPoolingEvalFloat(context, node, params, data, input, output); + break; + case kTfLiteInt8: + MaxPoolingEvalQuantized(context, node, params, data, input, output); + break; + default: + MicroPrintf("Type %s not currently supported.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataPooling)); +} + +} // namespace + +TfLiteRegistration Register_AVERAGE_POOL_2D() { + return tflite::micro::RegisterOp(Init, PoolingPrepare, AverageEval); +} + +TfLiteRegistration Register_MAX_POOL_2D() { + return tflite::micro::RegisterOp(Init, PoolingPrepare, MaxEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling.h new file mode 100644 index 000000000..493250ee1 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling.h @@ -0,0 +1,85 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_POOLING_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_POOLING_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/kernels/micro_ops.h" + +namespace tflite { + +extern const int kPoolingInputTensor; +extern const int kPoolingOutputTensor; + +struct OpDataPooling { + TfLitePaddingValues padding; + int32_t activation_min; + int32_t activation_max; + float activation_min_f32; + float activation_max_f32; +}; + +TfLiteStatus CalculateOpDataPooling(const TfLiteContext* context, + const TfLitePoolParams* params, + const TfLiteTensor* input, + const TfLiteTensor* output, + OpDataPooling* data); + +TfLiteStatus PoolingPrepare(TfLiteContext* context, TfLiteNode* node); + +void AveragePoolingEvalFloat(const TfLiteContext* context, + const TfLiteNode* node, + const TfLitePoolParams* params, + const OpDataPooling* data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output); + +void AveragePoolingEvalQuantized(TfLiteContext* context, const TfLiteNode* node, + const TfLitePoolParams* params, + const OpDataPooling* data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output); + +void MaxPoolingEvalFloat(TfLiteContext* context, TfLiteNode* node, + TfLitePoolParams* params, const OpDataPooling* data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output); + +void MaxPoolingEvalQuantized(TfLiteContext* context, TfLiteNode* node, + TfLitePoolParams* params, + const OpDataPooling* data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output); + +#if defined(CMSIS_NN) +TfLiteRegistration Register_AVERAGE_POOL_2D_INT8(); + +TfLiteRegistration Register_MAX_POOL_2D_INT8(); +#else +inline TfLiteRegistration Register_AVERAGE_POOL_2D_INT8() { + return tflite::Register_AVERAGE_POOL_2D(); +} + +inline TfLiteRegistration Register_MAX_POOL_2D_INT8() { + return tflite::Register_MAX_POOL_2D(); +} +#endif +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_POOLING_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling_common.cc new file mode 100644 index 000000000..ddc18f0bb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/pooling_common.cc @@ -0,0 +1,170 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h" +#include "tensorflow/lite/kernels/internal/reference/pooling.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/padding.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/pooling.h" + +namespace tflite { + +const int kPoolingInputTensor = 0; +const int kPoolingOutputTensor = 0; + +TfLiteStatus CalculateOpDataPooling(const TfLiteContext* context, + const TfLitePoolParams* params, + const TfLiteTensor* input, + const TfLiteTensor* output, + OpDataPooling* data) { + // input: batch, height, width, channel + int height = SizeOfDimension(input, 1); + int width = SizeOfDimension(input, 2); + + int out_height, out_width; + + data->padding = ComputePaddingHeightWidth( + params->stride_height, params->stride_width, + /*dilation_rate_height=*/1, + /*dilation_rate_width=*/1, height, width, params->filter_height, + params->filter_width, params->padding, &out_height, &out_width); + + return kTfLiteOk; +} + +TfLiteStatus PoolingPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + auto* params = reinterpret_cast(node->builtin_data); + + TFLITE_DCHECK(node->user_data != nullptr); + OpDataPooling* data = static_cast(node->user_data); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kPoolingInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kPoolingOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_STATUS( + CalculateOpDataPooling(context, params, input, output, data)); + + if (input->type == kTfLiteFloat32) { + CalculateActivationRange(params->activation, &data->activation_min_f32, + &data->activation_max_f32); + } else if (input->type == kTfLiteInt8) { + CalculateActivationRangeQuantized(context, params->activation, output, + &data->activation_min, + &data->activation_max); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +void AveragePoolingEvalFloat(const TfLiteContext* context, + const TfLiteNode* node, + const TfLitePoolParams* params, + const OpDataPooling* data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output) { + PoolParams op_params; + op_params.stride_height = params->stride_height; + op_params.stride_width = params->stride_width; + op_params.filter_height = params->filter_height; + op_params.filter_width = params->filter_width; + op_params.padding_values.height = data->padding.height; + op_params.padding_values.width = data->padding.width; + op_params.float_activation_min = data->activation_min_f32; + op_params.float_activation_max = data->activation_max_f32; + reference_ops::AveragePool(op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +} + +void AveragePoolingEvalQuantized(TfLiteContext* context, const TfLiteNode* node, + const TfLitePoolParams* params, + const OpDataPooling* data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output) { + TFLITE_DCHECK(input->type == kTfLiteInt8); + + PoolParams op_params; + op_params.stride_height = params->stride_height; + op_params.stride_width = params->stride_width; + op_params.filter_height = params->filter_height; + op_params.filter_width = params->filter_width; + op_params.padding_values.height = data->padding.height; + op_params.padding_values.width = data->padding.width; + op_params.quantized_activation_min = data->activation_min; + op_params.quantized_activation_max = data->activation_max; + + reference_integer_ops::AveragePool( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +} + +void MaxPoolingEvalFloat(TfLiteContext* context, TfLiteNode* node, + TfLitePoolParams* params, const OpDataPooling* data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output) { + tflite::PoolParams op_params; + op_params.stride_height = params->stride_height; + op_params.stride_width = params->stride_width; + op_params.filter_height = params->filter_height; + op_params.filter_width = params->filter_width; + op_params.padding_values.height = data->padding.height; + op_params.padding_values.width = data->padding.width; + op_params.float_activation_min = data->activation_min_f32; + op_params.float_activation_max = data->activation_max_f32; + reference_ops::MaxPool(op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +} + +void MaxPoolingEvalQuantized(TfLiteContext* context, TfLiteNode* node, + TfLitePoolParams* params, + const OpDataPooling* data, + const TfLiteEvalTensor* input, + TfLiteEvalTensor* output) { + tflite::PoolParams op_params; + op_params.stride_height = params->stride_height; + op_params.stride_width = params->stride_width; + op_params.filter_height = params->filter_height; + op_params.filter_width = params->filter_width; + op_params.padding_values.height = data->padding.height; + op_params.padding_values.width = data->padding.width; + op_params.quantized_activation_min = data->activation_min; + op_params.quantized_activation_max = data->activation_max; + + reference_integer_ops::MaxPool(op_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu.cc new file mode 100644 index 000000000..f4294723f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu.cc @@ -0,0 +1,75 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/prelu.h" + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/prelu.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +void* PreluInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(PreluParams)); +} + +TfLiteStatus PreluEval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const PreluParams& params = + *(static_cast(node->user_data)); + + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + const TfLiteEvalTensor* alpha = tflite::micro::GetEvalInput(context, node, 1); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + + switch (input->type) { + case kTfLiteFloat32: { + BroadcastPrelu4DSlowFloat(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(alpha), + tflite::micro::GetTensorData(alpha), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } break; + case kTfLiteInt8: { + reference_ops::BroadcastPrelu4DSlow( + params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(alpha), + tflite::micro::GetTensorData(alpha), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } break; + default: + MicroPrintf("Only float32 and uint8_t are supported currently, got %d.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } +} + +TfLiteRegistration Register_PRELU() { + return tflite::micro::RegisterOp(PreluInit, PreluPrepare, PreluEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu.h new file mode 100644 index 000000000..571d1e88a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu.h @@ -0,0 +1,39 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_PRELU_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_PRELU_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +TfLiteStatus CalculatePreluParams(const TfLiteTensor* input, + const TfLiteTensor* alpha, + TfLiteTensor* output, PreluParams* params); + +void BroadcastPrelu4DSlowFloat(const RuntimeShape& unextended_input1_shape, + const float* input1_data, + const RuntimeShape& unextended_input2_shape, + const float* input2_data, + const RuntimeShape& unextended_output_shape, + float* output_data); + +TfLiteStatus PreluPrepare(TfLiteContext* context, TfLiteNode* node); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_PRELU_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu_common.cc new file mode 100644 index 000000000..1a89cadf9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/prelu_common.cc @@ -0,0 +1,105 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/prelu.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/prelu.h" + +namespace tflite { + +TfLiteStatus CalculatePreluParams(const TfLiteTensor* input, + const TfLiteTensor* alpha, + TfLiteTensor* output, PreluParams* params) { + if (output->type == kTfLiteInt8 || output->type == kTfLiteInt16) { + double real_multiplier_1 = static_cast(input->params.scale) / + static_cast(output->params.scale); + double real_multiplier_2 = static_cast(input->params.scale) * + static_cast(alpha->params.scale) / + static_cast(output->params.scale); + QuantizeMultiplier(real_multiplier_1, ¶ms->output_multiplier_1, + ¶ms->output_shift_1); + QuantizeMultiplier(real_multiplier_2, ¶ms->output_multiplier_2, + ¶ms->output_shift_2); + + params->input_offset = -input->params.zero_point; + params->alpha_offset = -alpha->params.zero_point; + params->output_offset = output->params.zero_point; + } + + return kTfLiteOk; +} + +void BroadcastPrelu4DSlowFloat(const RuntimeShape& unextended_input1_shape, + const float* input1_data, + const RuntimeShape& unextended_input2_shape, + const float* input2_data, + const RuntimeShape& unextended_output_shape, + float* output_data) { + TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + const RuntimeShape output_shape = + RuntimeShape::ExtendedShape(4, unextended_output_shape); + + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, + unextended_input2_shape, &desc1, &desc2); + + for (int b = 0; b < output_shape.Dims(0); ++b) { + for (int y = 0; y < output_shape.Dims(1); ++y) { + for (int x = 0; x < output_shape.Dims(2); ++x) { + for (int c = 0; c < output_shape.Dims(3); ++c) { + auto out_idx = Offset(output_shape, b, y, x, c); + auto in1_idx = SubscriptToIndex(desc1, b, y, x, c); + auto in2_idx = SubscriptToIndex(desc2, b, y, x, c); + auto in1_val = input1_data[in1_idx]; + auto in2_val = input2_data[in2_idx]; + output_data[out_idx] = in1_val >= 0.0f ? in1_val : in1_val * in2_val; + } + } + } + } +} + +TfLiteStatus PreluPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + PreluParams* params = static_cast(node->user_data); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, 0); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* alpha = micro_context->AllocateTempInputTensor(node, 1); + TF_LITE_ENSURE(context, alpha != nullptr); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor(node, 0); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_OK(context, + CalculatePreluParams(input, alpha, output, params)); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(alpha); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize.cc new file mode 100644 index 000000000..b5eb9c3c9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize.cc @@ -0,0 +1,41 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/quantize.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, + sizeof(OpDataQuantizeReference)); +} + +} // namespace + +TfLiteRegistration Register_QUANTIZE() { + return tflite::micro::RegisterOp(Init, PrepareQuantizeReference, + EvalQuantizeReference); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize.h new file mode 100644 index 000000000..ba93809a2 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize.h @@ -0,0 +1,37 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_QUANTIZE_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_QUANTIZE_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +struct OpDataQuantizeReference { + tflite::QuantizationParams quantization_params; + // The scaling factor from input to output (aka the 'real multiplier') can + // be represented as a fixed point multiplier plus a left shift. + int32_t requantize_output_multiplier; + int requantize_output_shift; + + int32_t input_zero_point; +}; + +TfLiteStatus EvalQuantizeReference(TfLiteContext* context, TfLiteNode* node); +TfLiteStatus PrepareQuantizeReference(TfLiteContext* context, TfLiteNode* node); +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_QUANTIZE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize_common.cc new file mode 100644 index 000000000..cb04eafce --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/quantize_common.cc @@ -0,0 +1,239 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/quantize.h" +#include "tensorflow/lite/kernels/internal/reference/requantize.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/quantize.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +TfLiteStatus PrepareQuantizeReference(TfLiteContext* context, + TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + auto* data = static_cast(node->user_data); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, 0); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor(node, 0); + TF_LITE_ENSURE(context, output != nullptr); + + // TODO(b/128934713): Add support for fixed-point per-channel quantization. + // Currently this only support affine per-layer quantization. + TF_LITE_ENSURE_EQ(context, output->quantization.type, + kTfLiteAffineQuantization); + const auto* affine_quantization = + reinterpret_cast(output->quantization.params); + TF_LITE_ENSURE(context, affine_quantization); + TF_LITE_ENSURE(context, affine_quantization->scale); + TF_LITE_ENSURE(context, affine_quantization->scale->size == 1); + + TF_LITE_ENSURE( + context, input->type == kTfLiteFloat32 || input->type == kTfLiteInt32 || + input->type == kTfLiteInt16 || input->type == kTfLiteInt8 || + input->type == kTfLiteUInt8); + TF_LITE_ENSURE(context, output->type == kTfLiteInt8 || + output->type == kTfLiteInt16 || + output->type == kTfLiteInt32 || + output->type == kTfLiteUInt8); + + if ((input->type == kTfLiteInt16 && output->type == kTfLiteInt8) || + (input->type == kTfLiteInt8 && output->type == kTfLiteInt8) || + (input->type == kTfLiteInt8 && output->type == kTfLiteUInt8) || + (input->type == kTfLiteUInt8 && output->type == kTfLiteInt8) || + (input->type == kTfLiteInt8 && output->type == kTfLiteInt16) || + (input->type == kTfLiteInt8 && output->type == kTfLiteInt32) || + (input->type == kTfLiteInt16 && output->type == kTfLiteInt16) || + (input->type == kTfLiteInt16 && output->type == kTfLiteInt32) || + (input->type == kTfLiteInt32 && output->type == kTfLiteInt8) || + (input->type == kTfLiteInt32 && output->type == kTfLiteInt16)) { + double effective_scale = static_cast(input->params.scale) / + static_cast(output->params.scale); + + QuantizeMultiplier(effective_scale, &data->requantize_output_multiplier, + &data->requantize_output_shift); + } + + data->quantization_params.zero_point = output->params.zero_point; + data->quantization_params.scale = static_cast(output->params.scale); + + data->input_zero_point = input->params.zero_point; + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus EvalQuantizeReference(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + auto* data = static_cast(node->user_data); + + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + + if (input->type == kTfLiteFloat32) { + switch (output->type) { + case kTfLiteInt8: + reference_ops::AffineQuantize( + data->quantization_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt16: + reference_ops::AffineQuantize( + data->quantization_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else if (input->type == kTfLiteInt32) { + size_t size = ElementCount(*input->dims); + switch (output->type) { + case kTfLiteInt8: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt16: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else if (input->type == kTfLiteInt16) { + size_t size = ElementCount(*input->dims); + switch (output->type) { + case kTfLiteInt8: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt16: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + case kTfLiteInt32: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else if (input->type == kTfLiteInt8) { + // Int8 to Int8 requantization, required if the input and output tensors + // have different scales and/or zero points. + size_t size = ElementCount(*input->dims); + switch (output->type) { + case kTfLiteInt8: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + break; + case kTfLiteUInt8: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt16: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt32: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else if (input->type == kTfLiteUInt8) { + size_t size = ElementCount(*input->dims); + switch (output->type) { + case kTfLiteInt8: + reference_ops::Requantize( + tflite::micro::GetTensorData(input), size, + data->requantize_output_multiplier, data->requantize_output_shift, + data->input_zero_point, data->quantization_params.zero_point, + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + } else { + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/read_variable.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/read_variable.cc new file mode 100644 index 000000000..600a1bdd5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/read_variable.cc @@ -0,0 +1,87 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_graph.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_resource_variable.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +namespace { + +constexpr int kInputVariableId = 0; +constexpr int kOutputValue = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(NumInputs(node) == 1); + TFLITE_DCHECK(NumOutputs(node) == 1); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input_resource_id_tensor = + micro_context->AllocateTempInputTensor(node, kInputVariableId); + + TFLITE_DCHECK(input_resource_id_tensor != nullptr); + TFLITE_DCHECK(input_resource_id_tensor->type == kTfLiteResource); + TFLITE_DCHECK(NumElements(input_resource_id_tensor) == 1); + + micro_context->DeallocateTempTfLiteTensor(input_resource_id_tensor); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input_resource_id_tensor = + tflite::micro::GetEvalInput(context, node, kInputVariableId); + TFLITE_DCHECK(input_resource_id_tensor != nullptr); + + TfLiteEvalTensor* output_value = + tflite::micro::GetEvalOutput(context, node, kOutputValue); + TFLITE_DCHECK(output_value != nullptr); + + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + MicroGraph& graph_info = micro_context->graph(); + + MicroResourceVariables* resources = graph_info.GetResourceVariables(); + if (resources == nullptr) { + MicroPrintf( + "READ_VARIABLE requires resource variables. Please create " + "ResourceVariables and pass it to the interpreter."); + return kTfLiteError; + } + TF_LITE_ENSURE_OK( + context, + resources->Read(input_resource_id_tensor->data.i32[0], output_value)); + return kTfLiteOk; +} + +} // namespace. + +TfLiteRegistration Register_READ_VARIABLE() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce.cc new file mode 100644 index 000000000..b4734f932 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce.cc @@ -0,0 +1,72 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/reduce.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/mean.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/reduce.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +void* InitReduce(TfLiteContext* context, const char* buffer, size_t length) { + return context->AllocatePersistentBuffer(context, sizeof(OpDataReduce)); +} + +TfLiteStatus PrepareMax(TfLiteContext* context, TfLiteNode* node) { + return PrepareMaxHelper(context, node, + static_cast(node->user_data)); +} + +TfLiteStatus PrepareMeanOrSum(TfLiteContext* context, TfLiteNode* node) { + return PrepareMeanOrSumHelper(context, node, + static_cast(node->user_data)); +} + +TfLiteStatus EvalMean(TfLiteContext* context, TfLiteNode* node) { + return EvalMeanHelper(context, node, + static_cast(node->user_data)); +} + +TfLiteStatus EvalMax(TfLiteContext* context, TfLiteNode* node) { + OpDataReduce* op_data = static_cast(node->user_data); + return EvalMaxHelper(context, node, op_data); +} + +TfLiteStatus EvalSum(TfLiteContext* context, TfLiteNode* node) { + return EvalSumHelper(context, node, + static_cast(node->user_data)); +} + +TfLiteRegistration Register_MEAN() { + return tflite::micro::RegisterOp(InitReduce, PrepareMeanOrSum, EvalMean); +} + +TfLiteRegistration Register_REDUCE_MAX() { + return tflite::micro::RegisterOp(InitReduce, PrepareMax, EvalMax); +} + +TfLiteRegistration Register_SUM() { + return tflite::micro::RegisterOp(InitReduce, PrepareMeanOrSum, EvalSum); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce.h new file mode 100644 index 000000000..8d5240696 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce.h @@ -0,0 +1,64 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_REDUCE_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_REDUCE_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +extern const int kMaxNumberOfAxis; +extern const int kMaxNumberOfReducedAxis; + +struct OpDataReduce { + int32_t multiplier; + int shift; + int temp_buffer_idx; + int resolved_axis_idx; + int input_zp; + float input_scale; + int output_zp; + float output_scale; + int num_output_elements; +}; + +TfLiteStatus PrepareMaxHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data); + +TfLiteStatus PrepareMeanOrSumHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data); + +TfLiteStatus EvalMaxHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data); +TfLiteStatus EvalMeanHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data); +TfLiteStatus EvalSumHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data); + +void ReduceResolveAxis(const int* axis_data, int axis_count, + MeanParams* op_params); + +TfLiteRegistration Register_MEAN(); +TfLiteRegistration Register_REDUCE_MAX(); +TfLiteRegistration Register_SUM(); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_REDUCE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce_common.cc new file mode 100644 index 000000000..e84c0dc86 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reduce_common.cc @@ -0,0 +1,374 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/mean.h" +#include "tensorflow/lite/kernels/internal/reference/reduce.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/reduce.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +const int kMaxNumberOfAxis = 5; +const int kMaxNumberOfReducedAxis = 2; + +TfLiteStatus PrepareSimple(TfLiteContext* context, TfLiteNode* node, + int32_t* multiplier, int* shift) { + MicroContext* micro_context = GetMicroContext(context); + + // Inputs Tensor (dtype depends on quantization): + // [0] = Input + // [1] = Axis + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, 0); + + // Outputs Tensor (dtype depends on quantization): + // [0] = Output + + // Validate number of inputs and outputs + TF_LITE_ENSURE_EQ(context, node->inputs->size, 2); + TF_LITE_ENSURE_EQ(context, node->outputs->size, 1); + + // Validate axis type + TfLiteTensor* axis = micro_context->AllocateTempInputTensor(node, 1); + TF_LITE_ENSURE(context, axis != nullptr); + TF_LITE_ENSURE_TYPES_EQ(context, axis->type, kTfLiteInt32); + + if (input->type == kTfLiteInt8) { + TfLiteTensor* output = micro_context->AllocateTempOutputTensor(node, 0); + const double real_multiplier = static_cast(input->params.scale) / + static_cast(output->params.scale); + QuantizeMultiplier(real_multiplier, multiplier, shift); + micro_context->DeallocateTempTfLiteTensor(output); + } + micro_context->DeallocateTempTfLiteTensor(axis); + micro_context->DeallocateTempTfLiteTensor(input); + return kTfLiteOk; +} + +TfLiteStatus PrepareMaxHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data) { + TF_LITE_ENSURE_OK(context, PrepareSimple(context, node, &op_data->multiplier, + &op_data->shift)); + + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, 0); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor(node, 0); + TfLiteTensor* axis = micro_context->AllocateTempInputTensor(node, 1); + + op_data->input_scale = input->params.scale; + op_data->output_scale = output->params.scale; + op_data->num_output_elements = NumElements(output); + + context->RequestScratchBufferInArena(context, sizeof(int) * input->dims->size, + &op_data->temp_buffer_idx); + context->RequestScratchBufferInArena( + context, sizeof(int) * static_cast(ElementCount(*axis->dims)), + &op_data->resolved_axis_idx); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + micro_context->DeallocateTempTfLiteTensor(axis); + return kTfLiteOk; +} + +TfLiteStatus PrepareMeanOrSumHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data) { + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, 0); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor(node, 0); + if (input->type == kTfLiteInt8 || input->type == kTfLiteInt16) { + const double real_multiplier = static_cast(input->params.scale) / + static_cast(output->params.scale); + QuantizeMultiplier(real_multiplier, &op_data->multiplier, &op_data->shift); + } + + int output_size = NumElements(output); + if (input->type == kTfLiteInt8 || input->type == kTfLiteInt16) { + context->RequestScratchBufferInArena(context, output_size * sizeof(int32_t), + &op_data->temp_buffer_idx); + op_data->input_zp = input->params.zero_point; + op_data->input_scale = input->params.scale; + op_data->output_zp = output->params.zero_point; + op_data->output_scale = output->params.scale; + } + + TF_LITE_ENSURE_OK( + context, + PrepareSimple(context, node, &(op_data->multiplier), &(op_data->shift))); + // TODO(b/144955155): Support uint8_t(b/144955155) and int8_t(b/144955018) + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +void ResolveAxis(const int* axis_data, int axis_count, + tflite::MeanParams* op_params) { + int i = 0; + for (; i < axis_count; ++i) { + op_params->axis[i] = static_cast(axis_data[i]); + } + for (; i < 4; ++i) { + op_params->axis[i] = 1; + } + op_params->axis_count = axis_count; +} + +TfLiteStatus EvalMeanHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + const TfLiteEvalTensor* axis = tflite::micro::GetEvalInput(context, node, 1); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TfLiteReducerParams* params = + reinterpret_cast(node->builtin_data); + + int num_axis = static_cast(ElementCount(*axis->dims)); + int temp_index[kMaxNumberOfAxis]; + int resolved_axis[kMaxNumberOfReducedAxis]; + + tflite::MeanParams op_params; + ResolveAxis(tflite::micro::GetTensorData(axis), num_axis, &op_params); + + // Special case mean implementation exists for 4D mean across axes 1 and 2. + bool special_case_4d_axes_1_and_2 = + input->dims->size == 4 && op_params.axis_count == 2 && + ((op_params.axis[0] == 1 && op_params.axis[1] == 2) || + (op_params.axis[0] == 2 && op_params.axis[1] == 1)); + + switch (input->type) { + case kTfLiteFloat32: { + // Defer to specialized implementation for 4D Mean across axes 1 & 2. + if (params->keep_dims && special_case_4d_axes_1_and_2) { + reference_ops::Mean(op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + TF_LITE_ENSURE( + context, + reference_ops::Mean( + tflite::micro::GetTensorData(input), input->dims->data, + input->dims->size, tflite::micro::GetTensorData(output), + output->dims->data, output->dims->size, + tflite::micro::GetTensorData(axis), num_axis, + params->keep_dims, temp_index, resolved_axis, + tflite::micro::GetTensorData(output))); + } + } break; + case kTfLiteInt8: { + // Defer to specialized implementation for 4D Mean across axes 1 & 2. + if (params->keep_dims && special_case_4d_axes_1_and_2) { + reference_integer_ops::Mean( + op_params, op_data->multiplier, op_data->shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), op_data->input_zp, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), op_data->output_zp); + } else if (op_data->input_zp == op_data->output_zp && + op_data->input_scale == op_data->output_scale) { + int32_t* temp_buffer = static_cast( + context->GetScratchBuffer(context, op_data->temp_buffer_idx)); + TF_LITE_ENSURE( + context, + reference_ops::Mean( + tflite::micro::GetTensorData(input), input->dims->data, + input->dims->size, tflite::micro::GetTensorData(output), + output->dims->data, output->dims->size, + tflite::micro::GetTensorData(axis), num_axis, + params->keep_dims, temp_index, resolved_axis, temp_buffer)); + } else { + int32_t* temp_buffer = static_cast( + context->GetScratchBuffer(context, op_data->temp_buffer_idx)); + TF_LITE_ENSURE( + context, + reference_ops::QuantizedMeanOrSum( + tflite::micro::GetTensorData(input), op_data->input_zp, + op_data->input_scale, input->dims->data, input->dims->size, + tflite::micro::GetTensorData(output), + op_data->output_zp, op_data->output_scale, output->dims->data, + output->dims->size, tflite::micro::GetTensorData(axis), + num_axis, params->keep_dims, temp_index, resolved_axis, + temp_buffer, false)); + } + } break; + case kTfLiteInt16: { + // Defer to specialized implementation for 4D Mean across axes 1 & 2. + if (params->keep_dims && special_case_4d_axes_1_and_2) { + reference_integer_ops::Mean( + op_params, op_data->multiplier, op_data->shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), op_data->input_zp, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), op_data->output_zp); + } else if (op_data->input_zp == op_data->output_zp && + op_data->input_scale == op_data->output_scale) { + int32_t* temp_buffer = static_cast( + context->GetScratchBuffer(context, op_data->temp_buffer_idx)); + TF_LITE_ENSURE( + context, + reference_ops::Mean(tflite::micro::GetTensorData(input), + input->dims->data, input->dims->size, + tflite::micro::GetTensorData(output), + output->dims->data, output->dims->size, + tflite::micro::GetTensorData(axis), + num_axis, params->keep_dims, temp_index, + resolved_axis, temp_buffer)); + } else { + int32_t* temp_buffer = static_cast( + context->GetScratchBuffer(context, op_data->temp_buffer_idx)); + TF_LITE_ENSURE( + context, + reference_ops::QuantizedMeanOrSum( + tflite::micro::GetTensorData(input), op_data->input_zp, + op_data->input_scale, input->dims->data, input->dims->size, + tflite::micro::GetTensorData(output), + op_data->output_zp, op_data->output_scale, output->dims->data, + output->dims->size, tflite::micro::GetTensorData(axis), + num_axis, params->keep_dims, temp_index, resolved_axis, + temp_buffer, false)); + } + } break; + default: + TF_LITE_ENSURE_MSG(context, false, + "Currently, only float32, int8 or int16 input type " + "is supported."); + } + return kTfLiteOk; +} + +TfLiteStatus EvalMaxHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + const TfLiteEvalTensor* axis = tflite::micro::GetEvalInput(context, node, 1); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + TfLiteReducerParams* params = + static_cast(node->builtin_data); + + // Interpret an axis tensor with null dimensions as a scalar + int num_axis = static_cast(ElementCount(*axis->dims)); + int* temp_buffer = static_cast( + context->GetScratchBuffer(context, op_data->temp_buffer_idx)); + int* resolved_axis = static_cast( + context->GetScratchBuffer(context, op_data->resolved_axis_idx)); + switch (input->type) { + case kTfLiteFloat32: + TF_LITE_ENSURE( + context, + reference_ops::ReduceGeneric( + tflite::micro::GetTensorData(input), input->dims->data, + input->dims->size, tflite::micro::GetTensorData(output), + output->dims->data, output->dims->size, + tflite::micro::GetTensorData(axis), num_axis, + params->keep_dims, temp_buffer, resolved_axis, + std::numeric_limits::lowest(), + [](const float current, const float in) -> float { + return (in > current) ? in : current; + })); + break; + case kTfLiteInt8: + TF_LITE_ENSURE_EQ(context, static_cast(op_data->input_scale), + static_cast(op_data->output_scale)); + TF_LITE_ENSURE_EQ(context, op_data->input_zp, op_data->output_zp); + TF_LITE_ENSURE( + context, + reference_ops::ReduceGeneric( + tflite::micro::GetTensorData(input), input->dims->data, + input->dims->size, tflite::micro::GetTensorData(output), + output->dims->data, output->dims->size, + tflite::micro::GetTensorData(axis), num_axis, + params->keep_dims, temp_buffer, resolved_axis, + std::numeric_limits::lowest(), + [](const int8_t current, const int8_t in) -> int8_t { + return (in > current) ? in : current; + })); + break; + default: + MicroPrintf("Only float32 and int8 types are supported."); + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus EvalSumHelper(TfLiteContext* context, TfLiteNode* node, + OpDataReduce* op_data) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + const TfLiteEvalTensor* axis = tflite::micro::GetEvalInput(context, node, 1); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + TfLiteReducerParams* params = + static_cast(node->builtin_data); + + // Interpret an axis tensor with null dimensions as a scalar. + int num_axis = static_cast(ElementCount(*axis->dims)); + int temp_index[kMaxNumberOfAxis]; + int resolved_axis[kMaxNumberOfReducedAxis]; + + switch (input->type) { + case kTfLiteFloat32: { + TF_LITE_ENSURE( + context, + reference_ops::ReduceGeneric( + tflite::micro::GetTensorData(input), input->dims->data, + input->dims->size, tflite::micro::GetTensorData(output), + output->dims->data, output->dims->size, + tflite::micro::GetTensorData(axis), num_axis, + params->keep_dims, temp_index, resolved_axis, /*init_value=*/0.f, + [](const float current, const float in) -> float { + return in + current; + })); + } break; + case kTfLiteInt8: { + int32_t* temp_buffer = static_cast( + context->GetScratchBuffer(context, op_data->temp_buffer_idx)); + TF_LITE_ENSURE( + context, + reference_ops::QuantizedMeanOrSum( + tflite::micro::GetTensorData(input), op_data->input_zp, + op_data->input_scale, input->dims->data, input->dims->size, + tflite::micro::GetTensorData(output), op_data->output_zp, + op_data->output_scale, output->dims->data, output->dims->size, + tflite::micro::GetTensorData(axis), num_axis, + params->keep_dims, temp_index, resolved_axis, temp_buffer, + /*compute_sum=*/true)); + } break; + case kTfLiteInt16: { + int32_t* temp_buffer = static_cast( + context->GetScratchBuffer(context, op_data->temp_buffer_idx)); + TF_LITE_ENSURE( + context, + reference_ops::QuantizedMeanOrSum( + tflite::micro::GetTensorData(input), op_data->input_zp, + op_data->input_scale, input->dims->data, input->dims->size, + tflite::micro::GetTensorData(output), op_data->output_zp, + op_data->output_scale, output->dims->data, output->dims->size, + tflite::micro::GetTensorData(axis), num_axis, + params->keep_dims, temp_index, resolved_axis, temp_buffer, + /*compute_sum=*/true)); + } break; + default: + MicroPrintf("Only float32, int8, and int16 types are supported."); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reshape.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reshape.cc new file mode 100644 index 000000000..832ba2612 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/reshape.cc @@ -0,0 +1,118 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace reshape { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus ReshapeOutput(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + // Tensorflow's Reshape allows one of the shape components to have the + // special -1 value, meaning it will be calculated automatically based on the + // input. Here we calculate what that dimension should be so that the number + // of output elements in the same as the number of input elements. + int num_input_elements = NumElements(input); + TfLiteIntArray* output_shape = output->dims; + + if (NumInputs(node) == 1 && // Legacy scalar supported with params. + output_shape->size == 1 && output_shape->data[0] == 0) { + // Legacy tflite models use a shape parameter of [0] to indicate scalars, + // so adjust accordingly. TODO(b/111614235): Allow zero-sized buffers during + // toco conversion. + output_shape->size = 0; + } + + int num_output_elements = 1; + int stretch_dim = -1; + for (int i = 0; i < output_shape->size; ++i) { + int value = output_shape->data[i]; + if (value == -1) { + TF_LITE_ENSURE_EQ(context, stretch_dim, -1); + stretch_dim = i; + } else { + num_output_elements *= value; + } + } + if (stretch_dim != -1) { + output_shape->data[stretch_dim] = num_input_elements / num_output_elements; + num_output_elements *= output_shape->data[stretch_dim]; + } + + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + TF_LITE_ENSURE_EQ(context, num_input_elements, num_output_elements); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE(context, NumInputs(node) == 1 || NumInputs(node) == 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TF_LITE_ENSURE_EQ(context, ReshapeOutput(context, node), kTfLiteOk); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + // TODO(b/162522304): storing input bytes in OpData increases some models + // significantly, possibly due to alignment issues. + size_t input_bytes; + TF_LITE_ENSURE_STATUS(TfLiteTypeSizeOf(input->type, &input_bytes)); + input_bytes *= ElementCount(*input->dims); + + // Do nothing for in-place reshape. + if (input->data.raw != output->data.raw) { + // Otherwise perform reshape with copy. + memcpy(output->data.raw, input->data.raw, input_bytes); + } + return kTfLiteOk; +} + +} // namespace reshape + +TfLiteRegistration Register_RESHAPE() { + return tflite::micro::RegisterOp(nullptr, reshape::Prepare, reshape::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/resize_bilinear.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/resize_bilinear.cc new file mode 100644 index 000000000..56432e1b5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/resize_bilinear.cc @@ -0,0 +1,116 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/resize_bilinear.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor = 0; +constexpr int kSizeTensor = 1; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TfLiteTensor* size = + micro_context->AllocateTempInputTensor(node, kSizeTensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + + TF_LITE_ENSURE_EQ(context, NumDimensions(input), 4); + TF_LITE_ENSURE_EQ(context, NumDimensions(size), 1); + + TF_LITE_ENSURE_EQ(context, size->type, kTfLiteInt32); + output->type = input->type; + + TF_LITE_ENSURE_MSG(context, IsConstantTensor(size), + "Non constant size tensor not supported"); + + // Ensure params are valid. + auto* params = + reinterpret_cast(node->builtin_data); + if (params->half_pixel_centers && params->align_corners) { + MicroPrintf("If half_pixel_centers is True, align_corners must be False."); + return kTfLiteError; + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(size); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + auto* params = + reinterpret_cast(node->builtin_data); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + const TfLiteEvalTensor* size = + tflite::micro::GetEvalInput(context, node, kSizeTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + if (output->type == kTfLiteFloat32) { + tflite::ResizeBilinearParams op_params; + op_params.align_corners = params->align_corners; + op_params.half_pixel_centers = params->half_pixel_centers; + reference_ops::ResizeBilinear(op_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(size), + tflite::micro::GetTensorData(size), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else if (output->type == kTfLiteInt8) { + tflite::ResizeBilinearParams op_params; + op_params.align_corners = params->align_corners; + op_params.half_pixel_centers = params->half_pixel_centers; + reference_ops::ResizeBilinearInteger( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(size), + tflite::micro::GetTensorData(size), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + MicroPrintf("Output type is %d, requires float or int8.", output->type); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_RESIZE_BILINEAR() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc new file mode 100644 index 000000000..756cf03fa --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc @@ -0,0 +1,126 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace resize_nearest_neighbor { + +constexpr int kInputTensor = 0; +constexpr int kSizeTensor = 1; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TfLiteTensor* size = + micro_context->AllocateTempInputTensor(node, kSizeTensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + + // Our current implementations rely on the input being 4D, + // and the size being 1D tensor with exactly 2 elements. + TF_LITE_ENSURE_EQ(context, NumDimensions(input), 4); + TF_LITE_ENSURE_EQ(context, NumDimensions(size), 1); + TF_LITE_ENSURE_EQ(context, size->type, kTfLiteInt32); + TF_LITE_ENSURE_EQ(context, size->dims->data[0], 2); + + output->type = input->type; + + if (!IsConstantTensor(size)) { + MicroPrintf("Dynamic tensors are unsupported in tfmicro."); + return kTfLiteError; + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(size); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + auto* params = + reinterpret_cast(node->builtin_data); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + const TfLiteEvalTensor* size = + tflite::micro::GetEvalInput(context, node, kSizeTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + tflite::ResizeNearestNeighborParams op_params; + op_params.align_corners = params->align_corners; + op_params.half_pixel_centers = false; + + if (output->type == kTfLiteFloat32) { + reference_ops::ResizeNearestNeighbor( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(size), + tflite::micro::GetTensorData(size), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else if (output->type == kTfLiteInt8) { + reference_ops::ResizeNearestNeighbor( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(size), + tflite::micro::GetTensorData(size), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else if (output->type == kTfLiteInt16) { + reference_ops::ResizeNearestNeighbor( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(size), + tflite::micro::GetTensorData(size), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + MicroPrintf("Output tensor type %s (%d) not supported.", + TfLiteTypeGetName(output->type), output->type); + + return kTfLiteError; + } + + return kTfLiteOk; +} +} // namespace resize_nearest_neighbor + +TfLiteRegistration Register_RESIZE_NEAREST_NEIGHBOR() { + return tflite::micro::RegisterOp(nullptr, resize_nearest_neighbor::Prepare, + resize_nearest_neighbor::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/round.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/round.cc new file mode 100644 index 000000000..0bda8783a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/round.cc @@ -0,0 +1,76 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/round.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace round { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, kTfLiteFloat32); + TF_LITE_ENSURE_TYPES_EQ(context, output->type, input->type); + TF_LITE_ENSURE_EQ(context, output->bytes, input->bytes); + TF_LITE_ENSURE_EQ(context, output->dims->size, input->dims->size); + for (int i = 0; i < output->dims->size; ++i) { + TF_LITE_ENSURE_EQ(context, output->dims->data[i], input->dims->data[i]); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + reference_ops::Round(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + + return kTfLiteOk; +} +} // namespace round + +TfLiteRegistration Register_ROUND() { + return tflite::micro::RegisterOp(nullptr, round::Prepare, round::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/select.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/select.cc new file mode 100644 index 000000000..1b05bd2fb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/select.cc @@ -0,0 +1,197 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/select.h" + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +constexpr int kInputTensorCondition = 0; +constexpr int kInputTensorX = 1; +constexpr int kInputTensorY = 2; +constexpr int kOutputTensor = 0; + +struct OpData { + bool requires_broadcast; + // True if input condition is scalar or input condition has rank one and + // matches the first dimension of other inputs. + bool has_low_rank_input_condition; +}; + +void* SelectInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + auto* data = static_cast( + context->AllocatePersistentBuffer(context, sizeof(OpData))); + data->requires_broadcast = false; + data->has_low_rank_input_condition = false; + return data; +} + +TfLiteStatus CheckBroadcastShape(TfLiteContext* context, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + const TfLiteTensor* input3, + const TfLiteIntArray* output_shape) { + const int dims1 = NumDimensions(input1); + const int dims2 = NumDimensions(input2); + const int dims3 = NumDimensions(input3); + const int out_dims = std::max(std::max(dims1, dims2), dims3); + TF_LITE_ENSURE_EQ(context, out_dims, output_shape->size); + + for (int i = 0; i < out_dims; ++i) { + const int d1 = i >= dims1 ? 1 : SizeOfDimension(input1, dims1 - i - 1); + const int d2 = i >= dims2 ? 1 : SizeOfDimension(input2, dims2 - i - 1); + const int d3 = i >= dims3 ? 1 : SizeOfDimension(input3, dims3 - i - 1); + const int min_value = std::min(std::min(d1, d2), d3); + int max_value = std::max(std::max(d1, d2), d3); + // If one dimention is 0, others must be 0 or 1. + if (min_value == 0) max_value = 0; + if (!(d1 == 1 || d1 == max_value) || !(d2 == 1 || d2 == max_value) || + !(d3 == 1 || d3 == max_value)) { + MicroPrintf("Given shapes are not broadcastable."); + return kTfLiteError; + } + TF_LITE_ENSURE_EQ(context, output_shape->data[out_dims - i - 1], max_value); + } + return kTfLiteOk; +} + +TfLiteStatus SelectPrepare(TfLiteContext* context, TfLiteNode* node) { + OpData* data = reinterpret_cast(node->user_data); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 3); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input_condition = + micro_context->AllocateTempInputTensor(node, kInputTensorCondition); + + TfLiteTensor* input_x = + micro_context->AllocateTempInputTensor(node, kInputTensorX); + + TfLiteTensor* input_y = + micro_context->AllocateTempInputTensor(node, kInputTensorY); + + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + + // Input must be bool. + TF_LITE_ENSURE_TYPES_EQ(context, input_condition->type, kTfLiteBool); + TF_LITE_ENSURE_TYPES_EQ(context, input_x->type, input_y->type); + output->type = input_x->type; + + // Respect the original output shape when there are mixed shapes to represent + // a scalar data. + if (GetTensorShape(input_condition).FlatSize() == 1 && + GetTensorShape(input_x).FlatSize() == 1 && + GetTensorShape(input_y).FlatSize() == 1 && + GetTensorShape(output).FlatSize() == 1) { + return kTfLiteOk; + } + + bool same_shape = HaveSameShapes(input_condition, input_x) && + HaveSameShapes(input_x, input_y); + if (!same_shape) { + TF_LITE_ENSURE_OK( + context, CheckBroadcastShape(context, input_condition, input_x, input_y, + output->dims)); + data->requires_broadcast = true; + } + + micro_context->DeallocateTempTfLiteTensor(input_condition); + micro_context->DeallocateTempTfLiteTensor(input_x); + micro_context->DeallocateTempTfLiteTensor(input_y); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus SelectEval(TfLiteContext* context, TfLiteNode* node) { + OpData* data = static_cast(node->user_data); + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input_condition = + micro_context->AllocateTempInputTensor(node, kInputTensorCondition); + + TfLiteTensor* input_x = + micro_context->AllocateTempInputTensor(node, kInputTensorX); + + TfLiteTensor* input_y = + micro_context->AllocateTempInputTensor(node, kInputTensorY); + + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + +#define TF_LITE_SELECT(type, op) \ + reference_ops::op(GetTensorShape(input_condition), \ + GetTensorData(input_condition), \ + GetTensorShape(input_x), GetTensorData(input_x), \ + GetTensorShape(input_y), GetTensorData(input_y), \ + GetTensorShape(output), GetTensorData(output)); + +#define TF_LITE_SWITCH(type, op) \ + switch (type) { \ + case kTfLiteFloat32: \ + TF_LITE_SELECT(float, op); \ + break; \ + case kTfLiteInt8: \ + TF_LITE_SELECT(int8_t, op); \ + break; \ + case kTfLiteInt16: \ + TF_LITE_SELECT(int16_t, op); \ + break; \ + default: \ + MicroPrintf("Does not support type other than %s, but got %s", \ + "int8|int16|float32", TfLiteTypeGetName(type)); \ + return kTfLiteError; \ + } + + if (data->has_low_rank_input_condition) { + MicroPrintf("Not yet implemented."); + return kTfLiteError; + } else if (data->requires_broadcast) { + TF_LITE_SWITCH(input_x->type, BroadcastSelect5DSlow); + } else { + TF_LITE_SWITCH(input_x->type, Select); + } + +#undef TF_LITE_SELECT +#undef TF_LITE_SWITCH + micro_context->DeallocateTempTfLiteTensor(input_condition); + micro_context->DeallocateTempTfLiteTensor(input_x); + micro_context->DeallocateTempTfLiteTensor(input_y); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +// SelectV2 op selects values of 'x' if the corresponding value of 'condition' +// is true or the value of 'y' if false. There are valid condition input sizes: +// +// 1. Either the same shape (in which case the select is elementwise), or +// 2. Broadcastable shapes between 'condition', 'x' and 'y'. +TfLiteRegistration Register_SELECT_V2() { + return tflite::micro::RegisterOp(tflite::SelectInit, tflite::SelectPrepare, + tflite::SelectEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/shape.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/shape.cc new file mode 100644 index 000000000..e85bb81f7 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/shape.cc @@ -0,0 +1,67 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +namespace { +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +void ExtractShape(const TfLiteEvalTensor* input, int32_t* output_data) { + for (int i = 0; i < input->dims->size; ++i) { + output_data[i] = input->dims->data[i]; + } +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + if (output->type != kTfLiteInt32) { + MicroPrintf("Output type %s (%d) not supported.", + TfLiteTypeGetName(output->type), output->type); + return kTfLiteError; + } else { + ExtractShape(input, tflite::micro::GetTensorData(output)); + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_SHAPE() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/slice.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/slice.cc new file mode 100644 index 000000000..cc3cd5b42 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/slice.cc @@ -0,0 +1,157 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/slice.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +namespace { + +constexpr int kInputTensor = 0; +constexpr int kBeginTensor = 1; +constexpr int kSizeTensor = 2; +constexpr int kOutputTensor = 0; + +const int kMaxDim = 5; + +template +void GetBeginAndSizeVectors(int dimensions, const TfLiteEvalTensor* begin, + const TfLiteEvalTensor* size, int32_t* begins, + int32_t* sizes) { + int offset = kMaxDim - dimensions; + for (int idx = 0; idx < dimensions; ++idx) { + begins[offset + idx] = tflite::micro::GetTensorData(begin)[idx]; + sizes[offset + idx] = tflite::micro::GetTensorData(size)[idx]; + } +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 3); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TFLITE_DCHECK(input != nullptr); + TfLiteTensor* begin = + micro_context->AllocateTempInputTensor(node, kBeginTensor); + TFLITE_DCHECK(begin != nullptr); + TfLiteTensor* size = + micro_context->AllocateTempInputTensor(node, kSizeTensor); + TFLITE_DCHECK(size != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TFLITE_DCHECK(output != nullptr); + + // Ensure validity of input tensor and its dimension. + TFLITE_DCHECK(input->type == output->type); + TFLITE_DCHECK(begin->type == size->type); + TFLITE_DCHECK(begin->type == kTfLiteInt32 || begin->type == kTfLiteInt64); + TFLITE_DCHECK(size->type == kTfLiteInt32 || size->type == kTfLiteInt64); + TFLITE_DCHECK(NumDimensions(begin) == 1); + TFLITE_DCHECK(NumDimensions(size) == 1); + TFLITE_DCHECK(NumElements(begin) == NumElements(size)); + TFLITE_DCHECK(NumDimensions(input) <= kMaxDim); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(begin); + micro_context->DeallocateTempTfLiteTensor(size); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + const TfLiteEvalTensor* begin = + tflite::micro::GetEvalInput(context, node, kBeginTensor); + const TfLiteEvalTensor* size = + tflite::micro::GetEvalInput(context, node, kSizeTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + tflite::SliceParams op_params; + op_params.begin_count = kMaxDim; + op_params.size_count = kMaxDim; + for (int i = 0; i < kMaxDim; ++i) { + op_params.begin[i] = 0; + op_params.size[i] = 1; + } + + if (begin->type == kTfLiteInt32) { + GetBeginAndSizeVectors(input->dims->size, begin, size, + op_params.begin, op_params.size); + } else if (begin->type == kTfLiteInt64) { + GetBeginAndSizeVectors(input->dims->size, begin, size, + op_params.begin, op_params.size); + } else { + MicroPrintf("Begin tensor type %s (%d) not supported.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + + switch (input->type) { + case kTfLiteFloat32: + reference_ops::Slice(op_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt32: + reference_ops::Slice( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt8: + reference_ops::Slice( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt16: + reference_ops::Slice( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("Input tensor type %s (%d) not supported.", + TfLiteTypeGetName(input->type), input->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_SLICE() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax.cc new file mode 100644 index 000000000..67a1b4065 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax.cc @@ -0,0 +1,90 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/softmax.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/softmax.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +void SoftmaxQuantized(const TfLiteEvalTensor* input, TfLiteEvalTensor* output, + const SoftmaxParams& op_data) { + if (input->type == kTfLiteInt8) { + if (output->type == kTfLiteInt16) { + tflite::reference_ops::Softmax( + op_data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + tflite::reference_ops::Softmax( + op_data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } + } else { + tflite::reference_ops::SoftmaxInt16( + op_data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } +} + +TfLiteStatus SoftmaxEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + + TFLITE_DCHECK(node->user_data != nullptr); + SoftmaxParams op_data = *static_cast(node->user_data); + + switch (input->type) { + case kTfLiteFloat32: { + tflite::reference_ops::Softmax( + op_data, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } + case kTfLiteInt8: + case kTfLiteInt16: { + SoftmaxQuantized(input, output, op_data); + return kTfLiteOk; + } + default: + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } +} +} // namespace + +TfLiteRegistration Register_SOFTMAX() { + return tflite::micro::RegisterOp(SoftmaxInit, SoftmaxPrepare, SoftmaxEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax.h new file mode 100644 index 000000000..7096d2020 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax.h @@ -0,0 +1,69 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_SOFTMAX_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_SOFTMAX_H_ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" + +namespace tflite { + +void* SoftmaxInit(TfLiteContext* context, const char* buffer, size_t length); + +// Common helper function to SoftmaxPrepare. +TfLiteStatus CalculateSoftmaxParams(TfLiteContext* context, + const TfLiteTensor* input, + TfLiteTensor* output, + const TfLiteSoftmaxParams* params, + SoftmaxParams* op_data); + +TfLiteStatus SoftmaxPrepare(TfLiteContext* context, TfLiteNode* node); + +// This is the most generic TfLiteRegistration. The actual supported types may +// still be target dependent. The only requirement is that every implementation +// (reference or optimized) must define this function. +TfLiteRegistration Register_SOFTMAX(); + +#if defined(XTENSA) || defined(CMSIS_NN) +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int8 input and int16 output. +TfLiteRegistration Register_SOFTMAX_INT8_INT16(); +#else +inline TfLiteRegistration Register_SOFTMAX_INT8_INT16() { + return Register_SOFTMAX(); +} +#endif + +#if defined(CMSIS_NN) +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int8 input/output and uses the latency optimized implementations. +TfLiteRegistration Register_SOFTMAX_INT8(); + +// Returns a TfLiteRegistration struct for kernel variant that only supports +// int16 input/output and uses the latency optimized implementations. +TfLiteRegistration Register_SOFTMAX_INT16(); + +#else +inline TfLiteRegistration Register_SOFTMAX_INT8() { return Register_SOFTMAX(); } + +inline TfLiteRegistration Register_SOFTMAX_INT16() { + return Register_SOFTMAX(); +} +#endif + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_SOFTMAX_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax_common.cc new file mode 100644 index 000000000..62b8b290b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/softmax_common.cc @@ -0,0 +1,168 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/softmax.h" +#include "tensorflow/lite/micro/micro_context.h" + +namespace tflite { + +namespace { +// Softmax parameter data that persists in user_data +const int kInt16LUTArraySize = LUTSize(); + +TfLiteStatus InitializeLutForInt16(TfLiteContext* context, + const TfLiteTensor* input, + TfLiteTensor* output, + SoftmaxParams* op_data) { + // Only allocate LUTs for KTfLiteInt16 data type + if (input->type == kTfLiteInt16) { + void* raw_exp_lut = context->AllocatePersistentBuffer( + context, sizeof(int16_t) * kInt16LUTArraySize); + TF_LITE_ENSURE(context, raw_exp_lut != nullptr); + op_data->exp_lut = reinterpret_cast(raw_exp_lut); + void* one_over_one_plus_x_lut = context->AllocatePersistentBuffer( + context, sizeof(int16_t) * kInt16LUTArraySize); + TF_LITE_ENSURE(context, one_over_one_plus_x_lut != nullptr); + op_data->one_over_one_plus_x_lut = + reinterpret_cast(one_over_one_plus_x_lut); + } + + if (output->type == kTfLiteInt16) { + TF_LITE_ENSURE(context, + input->type == kTfLiteInt8 || input->type == kTfLiteInt16); + } else { + TF_LITE_ENSURE_EQ(context, input->type, output->type); + } + + // Populate LUT if required + if (input->type == kTfLiteInt16) { + TF_LITE_ENSURE_EQ(context, output->params.zero_point, 0); + // exp LUT only used on negative values + // we consider exp(-10.0) is insignificant to accumulation + const int32_t range = std::numeric_limits::max() - + std::numeric_limits::min(); + LUTPopulate( + 10.0f / range, std::numeric_limits::max(), 2.0f / range, 0, + [](float value) { return std::exp(value); }, op_data->exp_lut); + + LUTPopulate( + 1.0f / range, std::numeric_limits::min(), 2.0f / range, 0, + [](float value) { return 1.0f / (1.0f + value); }, + op_data->one_over_one_plus_x_lut); + + op_data->zero_point = output->params.zero_point; + op_data->scale = output->params.scale; + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteStatus CalculateSoftmaxParams(TfLiteContext* context, + const TfLiteTensor* input, + TfLiteTensor* output, + const TfLiteSoftmaxParams* params, + SoftmaxParams* op_data) { + if (InitializeLutForInt16(context, input, output, op_data) != kTfLiteOk) { + return kTfLiteError; + } + + if (input->type == kTfLiteInt8 || input->type == kTfLiteInt16) { + if (input->type == kTfLiteInt16) { + TF_LITE_ENSURE_EQ(context, input->params.zero_point, 0); + TF_LITE_ENSURE_EQ(context, output->params.zero_point, 0); + TF_LITE_ENSURE_NEAR(context, output->params.scale, 1.f / 32768, + (0.001f * 1.f / 32768)); + } else { // input->type == kTfLiteInt8 + TF_LITE_ENSURE_TYPES_EQ(context, input->type, kTfLiteInt8); + if (output->type == kTfLiteInt16) { + TF_LITE_ENSURE_EQ(context, output->params.zero_point, -32768); + TF_LITE_ENSURE_NEAR(context, output->params.scale, 1.f / 65536, + (0.001f * 1.f / 65536)); + } else { // output->type == kTfLiteint8 + TF_LITE_ENSURE_TYPES_EQ(context, output->type, kTfLiteInt8); + TF_LITE_ENSURE_EQ(context, output->params.zero_point, -128); + TF_LITE_ENSURE(context, output->params.scale == 1.f / 256); + } + } + + static const int kScaledDiffIntegerBits = 5; + + // Calculate input_multiplier and input_left_shift + if (input->type == kTfLiteInt16) { + int input_left_shift; + double input_scale_beta_rescale = + static_cast(input->params.scale) * + static_cast(params->beta) / + (10.0 / 65535.0); // scale the input_diff such that [-65535, 0] + // correspond to [-10.0, 0.0] + QuantizeMultiplier(input_scale_beta_rescale, &op_data->input_multiplier, + &input_left_shift); + op_data->input_left_shift = input_left_shift; + } else { + int input_left_shift; + tflite::PreprocessSoftmaxScaling( + static_cast(params->beta), + static_cast(input->params.scale), kScaledDiffIntegerBits, + &op_data->input_multiplier, &input_left_shift); + op_data->input_left_shift = input_left_shift; + op_data->diff_min = + -1.0 * tflite::CalculateInputRadius(kScaledDiffIntegerBits, + op_data->input_left_shift); + } + } else { + TF_LITE_ENSURE_TYPES_EQ(context, input->type, kTfLiteFloat32); + TF_LITE_ENSURE_TYPES_EQ(context, output->type, kTfLiteFloat32); + op_data->beta = static_cast(params->beta); + } + return kTfLiteOk; +} + +void* SoftmaxInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(SoftmaxParams)); +} + +TfLiteStatus SoftmaxPrepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = micro_context->AllocateTempInputTensor(node, 0); + TF_LITE_ENSURE(context, input != nullptr); + TF_LITE_ENSURE(context, NumDimensions(input) >= 1); + TfLiteTensor* output = micro_context->AllocateTempOutputTensor(node, 0); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE(context, node->user_data != nullptr); + SoftmaxParams* op_data = static_cast(node->user_data); + + auto* params = static_cast(node->builtin_data); + auto ret_val = + CalculateSoftmaxParams(context, input, output, params, op_data); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return ret_val; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/space_to_batch_nd.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/space_to_batch_nd.cc new file mode 100644 index 000000000..11b32c3f6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/space_to_batch_nd.cc @@ -0,0 +1,121 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/space_to_batch_nd.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +namespace { + +constexpr int kInputTensor = 0; +constexpr int kBlockShapeTensor = 1; +constexpr int kCropsTensor = 2; +constexpr int kOutputTensor = 0; + +// Currently, only 3D NHC and 4D NHWC input/output op_context are supported. +// In case of 3D input, it will be extended to 3D NHWC by adding W=1. +// The 4D array need to have exactly 2 spatial dimensions. +// TODO(b/149952582): Support arbitrary dimension in SpaceToBatchND. +const int kInputOutputMinDimensionNum = 3; +const int kInputOutputMaxDimensionNum = 4; + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(SpaceToBatchParams)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 3); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, input != nullptr && output != nullptr); + + TF_LITE_ENSURE(context, NumDimensions(input) >= kInputOutputMinDimensionNum); + TF_LITE_ENSURE(context, NumDimensions(output) >= kInputOutputMinDimensionNum); + TF_LITE_ENSURE(context, NumDimensions(input) <= kInputOutputMaxDimensionNum); + TF_LITE_ENSURE(context, NumDimensions(output) <= kInputOutputMaxDimensionNum); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const SpaceToBatchParams& params = + *(static_cast(node->user_data)); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + const TfLiteEvalTensor* block_shape = + tflite::micro::GetEvalInput(context, node, kBlockShapeTensor); + const TfLiteEvalTensor* crops = + tflite::micro::GetEvalInput(context, node, kCropsTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: + reference_ops::SpaceToBatchND( + params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(block_shape), + tflite::micro::GetTensorData(block_shape), + tflite::micro::GetTensorShape(crops), + tflite::micro::GetTensorData(crops), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt8: + reference_ops::SpaceToBatchND( + params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(block_shape), + tflite::micro::GetTensorData(block_shape), + tflite::micro::GetTensorShape(crops), + tflite::micro::GetTensorData(crops), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace. + +TfLiteRegistration Register_SPACE_TO_BATCH_ND() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/space_to_depth.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/space_to_depth.cc new file mode 100644 index 000000000..3640e2cdb --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/space_to_depth.cc @@ -0,0 +1,127 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/space_to_depth.h" + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +namespace { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; +constexpr int kBatchRank = 0; +constexpr int kHeightRank = 1; +constexpr int kWidthRank = 2; +constexpr int kDepthRank = 3; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + auto* params = + reinterpret_cast(node->builtin_data); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_EQ(context, NumDimensions(input), 4); + + auto data_type = output->type; + TF_LITE_ENSURE(context, + data_type == kTfLiteFloat32 || data_type == kTfLiteInt8); + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + const int block_size = params->block_size; + const int input_height = input->dims->data[kHeightRank]; + const int input_width = input->dims->data[kWidthRank]; + int output_height = input_height / block_size; + int output_width = input_width / block_size; + + TF_LITE_ENSURE_EQ(context, input_height, output_height * block_size); + TF_LITE_ENSURE_EQ(context, input_width, output_width * block_size); + + // Relocate dims to the persistent storage arena before changing them, + // otherwise we'd be modifying temporary copies made by the interpreters each + // time they process the layer. + TfLiteEvalTensor* output_eval = + micro::GetEvalOutput(context, node, kOutputTensor); + TF_LITE_ENSURE_OK(context, micro::CreateWritableTensorDimsWithCopy( + context, output, output_eval)); + + output->dims->data[kBatchRank] = input->dims->data[kBatchRank]; + output->dims->data[kHeightRank] = output_height; + output->dims->data[kWidthRank] = output_width; + output->dims->data[kDepthRank] = + input->dims->data[kDepthRank] * block_size * block_size; + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + auto* params = + reinterpret_cast(node->builtin_data); + + const TfLiteEvalTensor* input = + micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = micro::GetEvalOutput(context, node, kOutputTensor); + + SpaceToDepthParams op_params; + op_params.block_size = params->block_size; + + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: + reference_ops::SpaceToDepth(op_params, micro::GetTensorShape(input), + micro::GetTensorData(input), + micro::GetTensorShape(output), + micro::GetTensorData(output)); + break; + case kTfLiteInt8: + reference_ops::SpaceToDepth(op_params, micro::GetTensorShape(input), + micro::GetTensorData(input), + micro::GetTensorShape(output), + micro::GetTensorData(output)); + break; + default: + MicroPrintf("SPACE_TO_DEPTH only supports FLOAT32 and INT8, got %s.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_SPACE_TO_DEPTH() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/split.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/split.cc new file mode 100644 index 000000000..4ff748562 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/split.cc @@ -0,0 +1,128 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace split { + +template +TfLiteStatus SplitImpl(TfLiteContext* context, TfLiteNode* node, + const TfLiteEvalTensor* input, int axis_value) { + const int output_count = NumOutputs(node); + const TfLiteIntArray* input_dims = input->dims; + const TfLiteEvalTensor* output0 = + tflite::micro::GetEvalOutput(context, node, 0); + const TfLiteIntArray* output_dims = output0->dims; + + const int split_dimensions = input_dims->size; + int axis = axis_value < 0 ? axis_value + split_dimensions : axis_value; + + TFLITE_DCHECK_LT(axis, split_dimensions); + TFLITE_DCHECK_EQ(output_dims->size, split_dimensions); + + int64_t split_size = output_dims->data[axis] * output_count; + + TFLITE_DCHECK_EQ(split_size, input_dims->data[axis]); + int64_t outer_size = 1; + for (int i = 0; i < axis; ++i) { + outer_size *= input_dims->data[i]; + } + + int64_t base_inner_size = 1; + for (int i = axis + 1; i < split_dimensions; ++i) { + base_inner_size *= input_dims->data[i]; + } + + const T* input_ptr = tflite::micro::GetTensorData(input); + for (int k = 0; k < outer_size; ++k) { + for (int i = 0; i < output_count; ++i) { + TfLiteEvalTensor* t = tflite::micro::GetEvalOutput(context, node, i); + T* output_data = tflite::micro::GetTensorData(t); + const int copy_size = output_dims->data[axis] * base_inner_size; + T* output_ptr = output_data + k * copy_size; + for (int j = 0; j < copy_size; ++j) output_ptr[j] = input_ptr[j]; + input_ptr += copy_size; + } + } + + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* axis = micro_context->AllocateTempInputTensor(node, 0); + TF_LITE_ENSURE(context, axis != nullptr); + + // Dynamic output tensors are needed if axis tensor is not constant. + // But Micro doesn't support dynamic memory allocation, so we only support + // constant axis tensor for now. + TF_LITE_ENSURE_MSG(context, IsConstantTensor(axis), + "Non constant axis tensor not supported"); + + micro_context->DeallocateTempTfLiteTensor(axis); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* axis = tflite::micro::GetEvalInput(context, node, 0); + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 1); + + int axis_value = tflite::micro::GetTensorData(axis)[0]; + if (axis_value < 0) { + axis_value += input->dims->size; + } + + TF_LITE_ENSURE(context, axis_value >= 0); + TF_LITE_ENSURE(context, axis_value < input->dims->size); + + switch (input->type) { + case kTfLiteFloat32: { + return SplitImpl(context, node, input, axis_value); + } + case kTfLiteInt8: { + return SplitImpl(context, node, input, axis_value); + } + case kTfLiteInt16: { + return SplitImpl(context, node, input, axis_value); + } + case kTfLiteInt32: { + return SplitImpl(context, node, input, axis_value); + } + default: + MicroPrintf("Type %s currently not supported.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace split + +TfLiteRegistration Register_SPLIT() { + return tflite::micro::RegisterOp(nullptr, split::Prepare, split::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/split_v.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/split_v.cc new file mode 100644 index 000000000..d0002d57c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/split_v.cc @@ -0,0 +1,130 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace split_v { + +template +TfLiteStatus SplitImpl(TfLiteContext* context, TfLiteNode* node, + const TfLiteEvalTensor* input, int axis_value) { + const TfLiteIntArray* input_dims = input->dims; + const TfLiteEvalTensor* output0 = + tflite::micro::GetEvalOutput(context, node, 0); + + const int split_dimensions = input_dims->size; + + TFLITE_DCHECK_LT(axis_value, split_dimensions); + TFLITE_DCHECK_EQ(output0->dims->size, split_dimensions); + + int64_t split_size = 0; + const int output_count = NumOutputs(node); + for (int i = 0; i < output_count; i++) { + split_size += + tflite::micro::GetEvalOutput(context, node, i)->dims->data[axis_value]; + } + TFLITE_DCHECK_EQ(split_size, input_dims->data[axis_value]); + int64_t outer_size = 1; + for (int i = 0; i < axis_value; ++i) { + outer_size *= input_dims->data[i]; + } + + int64_t base_inner_size = 1; + for (int i = axis_value + 1; i < split_dimensions; ++i) { + base_inner_size *= input_dims->data[i]; + } + + const T* input_ptr = tflite::micro::GetTensorData(input); + for (int k = 0; k < outer_size; ++k) { + for (int i = 0; i < output_count; ++i) { + TfLiteEvalTensor* output_tensor = + tflite::micro::GetEvalOutput(context, node, i); + T* output_data = tflite::micro::GetTensorData(output_tensor); + const int copy_size = + output_tensor->dims->data[axis_value] * base_inner_size; + T* output_ptr = output_data + k * copy_size; + for (int j = 0; j < copy_size; ++j) output_ptr[j] = input_ptr[j]; + input_ptr += copy_size; + } + } + + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 3); + + MicroContext* micro_context = GetMicroContext(context); + // Dynamic output tensors are needed if axis tensor is not constant. + // But Micro doesn't support dynamic memory allocation, so we only support + // constant axis tensor for now. + TfLiteTensor* axis = micro_context->AllocateTempInputTensor(node, 2); + TF_LITE_ENSURE_MSG(context, IsConstantTensor(axis), + "Non constant axis tensor not supported"); + micro_context->DeallocateTempTfLiteTensor(axis); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + const TfLiteEvalTensor* axis = tflite::micro::GetEvalInput(context, node, 2); + + int axis_value = tflite::micro::GetTensorData(axis)[0]; + if (axis_value < 0) { + axis_value += input->dims->size; + } + + TF_LITE_ENSURE(context, axis_value >= 0); + TF_LITE_ENSURE(context, axis_value < input->dims->size); + + switch (input->type) { + case kTfLiteFloat32: { + return SplitImpl(context, node, input, axis_value); + } + case kTfLiteInt8: { + return SplitImpl(context, node, input, axis_value); + } + case kTfLiteInt16: { + return SplitImpl(context, node, input, axis_value); + } + case kTfLiteInt32: { + return SplitImpl(context, node, input, axis_value); + } + default: + MicroPrintf("Type %s currently not supported.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace split_v + +TfLiteRegistration Register_SPLIT_V() { + return tflite::micro::RegisterOp(nullptr, split_v::Prepare, split_v::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/squared_difference.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/squared_difference.cc new file mode 100644 index 000000000..8786a8715 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/squared_difference.cc @@ -0,0 +1,247 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/binary_function.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/add.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_context.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { +constexpr int kInputTensor1 = 0; +constexpr int kInputTensor2 = 1; +constexpr int kOutputTensor = 0; + +struct OpData { + bool requires_broadcast; + ArithmeticParams arithmetic_params; +}; + +template +T SquaredDifference(T input1, T input2) { + const T difference = input1 - input2; + return difference * difference; +} + +void* SquaredDifferenceInit(TfLiteContext* context, const char* buffer, + size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus SquaredDifferencePrepare(TfLiteContext* context, + TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + OpData* data = reinterpret_cast(node->user_data); + data->requires_broadcast = false; + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input1 = + micro_context->AllocateTempInputTensor(node, kInputTensor1); + TF_LITE_ENSURE(context, input1 != nullptr); + TfLiteTensor* input2 = + micro_context->AllocateTempInputTensor(node, kInputTensor2); + TF_LITE_ENSURE(context, input2 != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_TYPES_EQ(context, input1->type, input2->type); + output->type = input2->type; + + // Ensure the quantization parameters are equivalent. + if (input1->type == kTfLiteInt8) { + const auto& input1_quantization_params = input1->params; + const auto& input2_quantization_params = input2->params; + const auto& output_quantization_params = output->params; + const int32_t integer_type_min = std::numeric_limits::min(); + const int32_t integer_type_max = std::numeric_limits::max(); + TF_LITE_ENSURE(context, + input1_quantization_params.zero_point >= integer_type_min); + TF_LITE_ENSURE(context, + input1_quantization_params.zero_point <= integer_type_max); + TF_LITE_ENSURE(context, + input2_quantization_params.zero_point >= integer_type_min); + TF_LITE_ENSURE(context, + input2_quantization_params.zero_point <= integer_type_max); + TF_LITE_ENSURE(context, + output_quantization_params.zero_point >= integer_type_min); + TF_LITE_ENSURE(context, + output_quantization_params.zero_point <= integer_type_max); + data->arithmetic_params.input1_offset = + -input1_quantization_params.zero_point; + data->arithmetic_params.input2_offset = + -input2_quantization_params.zero_point; + data->arithmetic_params.output_offset = + output_quantization_params.zero_point; + + // shift to make integer for scales. + // 7 is selected so that maximum shifted result 255^2 * (1 << (7 * 2 )) + // does not overflow signed 32-bit integer + data->arithmetic_params.left_shift = 7; + const double twice_max_input_scale = + 2.0 * static_cast(std::max(input1_quantization_params.scale, + input2_quantization_params.scale)); + const double real_input1_multiplier = + static_cast(input1_quantization_params.scale) / + twice_max_input_scale; + double real_input2_multiplier = + static_cast(input2_quantization_params.scale) / + twice_max_input_scale; + const double real_output_multiplier = + (twice_max_input_scale * twice_max_input_scale) / + static_cast((1 << data->arithmetic_params.left_shift * 2) * + output_quantization_params.scale); + QuantizeMultiplierSmallerThanOneExp( + real_input1_multiplier, &data->arithmetic_params.input1_multiplier, + &data->arithmetic_params.input1_shift); + QuantizeMultiplierSmallerThanOneExp( + real_input2_multiplier, &data->arithmetic_params.input2_multiplier, + &data->arithmetic_params.input2_shift); + QuantizeMultiplierSmallerThanOneExp( + real_output_multiplier, &data->arithmetic_params.output_multiplier, + &data->arithmetic_params.output_shift); + data->arithmetic_params.quantized_activation_min = + std::numeric_limits::min(); + data->arithmetic_params.quantized_activation_max = + std::numeric_limits::max(); + } + + data->requires_broadcast = !HaveSameShapes(input1, input2); + + micro_context->DeallocateTempTfLiteTensor(input1); + micro_context->DeallocateTempTfLiteTensor(input2); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +inline int8_t SquaredDifference(int8_t x, int8_t y, + const ArithmeticParams& params) { + const int32_t input1_val = params.input1_offset + x; + const int32_t input2_val = params.input2_offset + y; + const int32_t shifted_input1_val = input1_val * (1 << params.left_shift); + const int32_t shifted_input2_val = input2_val * (1 << params.left_shift); + const int32_t scaled_input1_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input1_val, params.input1_multiplier, params.input1_shift); + const int32_t scaled_input2_val = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + shifted_input2_val, params.input2_multiplier, params.input2_shift); + const int32_t raw_diff = scaled_input1_val - scaled_input2_val; + + // Max of this is 255^2 * (1 << 14), so won't overflow 32 bits. + const int32_t squared_raw_diff = raw_diff * raw_diff; + const int32_t raw_output = + MultiplyByQuantizedMultiplierSmallerThanOneExp( + squared_raw_diff, params.output_multiplier, params.output_shift) + + params.output_offset; + const int32_t clamped_output = + std::min(params.quantized_activation_max, + std::max(params.quantized_activation_min, raw_output)); + return static_cast(clamped_output); +} + +template +void EvalQuantizedSquaredDifference(TfLiteContext* context, TfLiteNode* node, + const OpData* data, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + const auto* op_data = static_cast(node->user_data); + if (data->requires_broadcast) { + reference_integer_ops::BroadcastBinaryFunction4DSlow( + op_data->arithmetic_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + reference_integer_ops::CheckArithmeticParams, SquaredDifference); + } else { + const int flat_size = tflite::micro::GetTensorShape(input1).FlatSize(); + reference_integer_ops::ElementWise( + flat_size, op_data->arithmetic_params, + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorData(output), + reference_integer_ops::CheckArithmeticParams, SquaredDifference); + } +} + +template +void EvalSquaredDifference(TfLiteContext* context, TfLiteNode* node, + const OpData* data, const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + if (data->requires_broadcast) { + reference_ops::BroadcastBinaryFunction4DSlow( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), SquaredDifference); + } else { + reference_ops::BinaryFunction( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), SquaredDifference); + } +} + +TfLiteStatus SquaredDifferenceEval(TfLiteContext* context, TfLiteNode* node) { + OpData* data = reinterpret_cast(node->user_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + if (output->type == kTfLiteFloat32) { + EvalSquaredDifference(context, node, data, input1, input2, output); + } else if (output->type == kTfLiteInt32) { + EvalSquaredDifference(context, node, data, input1, input2, output); + } else if (output->type == kTfLiteInt8) { + EvalQuantizedSquaredDifference(context, node, data, input1, input2, + output); + } else { + MicroPrintf( + "SquaredDifference only supports FLOAT32, INT32 and INT8 now, got %d.", + output->type); + return kTfLiteError; + } + + return kTfLiteOk; +} +} // namespace + +TfLiteRegistration Register_SQUARED_DIFFERENCE() { + return tflite::micro::RegisterOp( + SquaredDifferenceInit, SquaredDifferencePrepare, SquaredDifferenceEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/squeeze.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/squeeze.cc new file mode 100644 index 000000000..017538498 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/squeeze.cc @@ -0,0 +1,118 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +struct SqueezeContext { + SqueezeContext(TfLiteContext* context, TfLiteNode* node) { + params = reinterpret_cast(node->builtin_data); + micro_context = GetMicroContext(context); + input = micro_context->AllocateTempInputTensor(node, 0); + output = micro_context->AllocateTempOutputTensor(node, 0); + } + ~SqueezeContext() { + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + } + MicroContext* micro_context; + TfLiteSqueezeParams* params; + TfLiteTensor* input; + TfLiteTensor* output; +}; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + SqueezeContext op_context(context, node); + const int input_num_dims = NumDimensions(op_context.input); + const int num_squeeze_dims = op_context.params->num_squeeze_dims; + + // Determines number of dimensions of output tensor after squeeze. + const TfLiteIntArray* input_dims = op_context.input->dims; + const TfLiteIntArray* output_dims = op_context.output->dims; + const int* squeeze_dims = op_context.params->squeeze_dims; + + constexpr int max_squeeze_dims = 8; + TF_LITE_ENSURE(context, input_num_dims <= max_squeeze_dims); + bool should_squeeze[max_squeeze_dims] = {}; + + if (num_squeeze_dims == 0) { + for (int idx = 0; idx < input_num_dims; ++idx) { + if (input_dims->data[idx] == 1) { + should_squeeze[idx] = true; + } + } + } else { + for (int idx = 0; idx < num_squeeze_dims; ++idx) { + int current = squeeze_dims[idx] < 0 ? squeeze_dims[idx] + input_num_dims + : squeeze_dims[idx]; + TF_LITE_ENSURE(context, current >= 0 && current < input_num_dims && + input_dims->data[current] == 1); + should_squeeze[current] = true; + } + } + + // Ensure output dimensions are big enough. + for (int in_idx = 0, out_idx = 0; in_idx < input_num_dims; ++in_idx) { + if (!should_squeeze[in_idx]) { + TFLITE_CHECK_GE(output_dims->data[out_idx++], input_dims->data[in_idx]); + } + } + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + + if (input->type == kTfLiteString) { + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } + + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + size_t input_byte_size; + size_t output_byte_size; + TF_LITE_ENSURE_OK(context, + TfLiteEvalTensorByteLength(input, &input_byte_size)); + TF_LITE_ENSURE_OK(context, + TfLiteEvalTensorByteLength(output, &output_byte_size)); + + TF_LITE_ENSURE_EQ(context, input_byte_size, output_byte_size); + memcpy(output->data.raw, input->data.raw, input_byte_size); + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_SQUEEZE() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/strided_slice.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/strided_slice.cc new file mode 100644 index 000000000..9985cf913 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/strided_slice.cc @@ -0,0 +1,210 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/strided_slice.h" + +#include +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace strided_slice { + +constexpr int kInputTensor = 0; +constexpr int kBeginTensor = 1; +constexpr int kEndTensor = 2; +constexpr int kStridesTensor = 3; +constexpr int kOutputTensor = 0; + +struct StridedSliceContext { + StridedSliceContext(TfLiteContext* context, TfLiteNode* node) { + params = reinterpret_cast(node->builtin_data); + micro_context = GetMicroContext(context); + input = micro_context->AllocateTempInputTensor(node, kInputTensor); + begin = micro_context->AllocateTempInputTensor(node, kBeginTensor); + end = micro_context->AllocateTempInputTensor(node, kEndTensor); + strides = micro_context->AllocateTempInputTensor(node, kStridesTensor); + output = micro_context->AllocateTempOutputTensor(node, kOutputTensor); + dims = NumDimensions(input); + } + ~StridedSliceContext() { + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(begin); + micro_context->DeallocateTempTfLiteTensor(end); + micro_context->DeallocateTempTfLiteTensor(strides); + micro_context->DeallocateTempTfLiteTensor(output); + } + const TfLiteStridedSliceParams* params; + MicroContext* micro_context; + TfLiteTensor* input; + TfLiteTensor* begin; + TfLiteTensor* end; + TfLiteTensor* strides; + TfLiteTensor* output; + int dims; +}; + +// This Op only supports 1-4D cases and since we use the reference 4D +// implementation, the 1-3D tensors are mapped to 4D. +const int kMaxDim = 4; + +tflite::StridedSliceParams BuildStridedSliceParams( + StridedSliceContext* op_context) { + tflite::StridedSliceParams op_params; + op_params.start_indices_count = op_context->dims; + op_params.stop_indices_count = op_context->dims; + op_params.strides_count = op_context->dims; + + for (int i = 0; i < op_context->dims; ++i) { + op_params.start_indices[i] = GetTensorData(op_context->begin)[i]; + op_params.stop_indices[i] = GetTensorData(op_context->end)[i]; + op_params.strides[i] = GetTensorData(op_context->strides)[i]; + } + + op_params.begin_mask = op_context->params->begin_mask; + op_params.ellipsis_mask = 0; + op_params.end_mask = op_context->params->end_mask; + op_params.new_axis_mask = 0; + op_params.shrink_axis_mask = op_context->params->shrink_axis_mask; + return op_params; +} + +// Processes the indexing tensors (begin, end and strides) to resize the +// output tensor. This function is callable from both Prepare() and Eval() as +// long as the caller ensures the indexing tensors are present. +TfLiteStatus CheckOutputSize(TfLiteContext* context, + StridedSliceContext* op_context) { + using ::tflite::strided_slice::StartForAxis; + using ::tflite::strided_slice::StopForAxis; + TfLiteIntArray* output_shape = op_context->output->dims; + int shape_size = 0; + auto op_params = BuildStridedSliceParams(op_context); + auto input_shape = GetTensorShape(op_context->input); + for (int idx = 0; idx < op_context->dims; ++idx) { + int32_t stride = GetTensorData(op_context->strides)[idx]; + TF_LITE_ENSURE_MSG(context, stride != 0, "stride value has to be non-zero"); + int32_t begin = StartForAxis(op_params, input_shape, idx); + int32_t end = StopForAxis(op_params, input_shape, idx, begin); + + // When shrinking an axis, the end position does not matter (and can be + // incorrect when negative indexing is used, see Issue #19260). Always use + // begin + 1 to generate a length 1 slice, since begin has + // already been adjusted for negative indices by StartForAxis. + const bool shrink_axis = op_context->params->shrink_axis_mask & (1 << idx); + if (shrink_axis) { + end = begin + 1; + } + + // This is valid for both positive and negative strides + int32_t dim_shape = std::ceil((end - begin) / static_cast(stride)); + dim_shape = dim_shape < 0 ? 0 : dim_shape; + if (!shrink_axis) { + TF_LITE_ENSURE_EQ(context, output_shape->data[shape_size], dim_shape); + shape_size++; + } + } + TF_LITE_ENSURE_EQ(context, output_shape->size, shape_size); + return kTfLiteOk; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(StridedSliceParams)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + StridedSliceParams* op_params = + static_cast(node->user_data); + TF_LITE_ENSURE_EQ(context, NumInputs(node), 4); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + StridedSliceContext op_context(context, node); + TF_LITE_ENSURE_MSG(context, op_context.dims <= kMaxDim, + "input dim should not exceed 4"); + auto params = BuildStridedSliceParams(&op_context); + memcpy(op_params, ¶ms, sizeof(StridedSliceParams)); + return CheckOutputSize(context, &op_context); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + const StridedSliceParams& op_params = + *(static_cast(node->user_data)); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + switch (output->type) { + case kTfLiteFloat32: + reference_ops::StridedSlice(op_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt8: + reference_ops::StridedSlice(op_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt16: + reference_ops::StridedSlice( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt32: + reference_ops::StridedSlice( + op_params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteBool: + reference_ops::StridedSlice(op_params, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } + return kTfLiteOk; +} +} // namespace strided_slice + +TfLiteRegistration Register_STRIDED_SLICE() { + return tflite::micro::RegisterOp(strided_slice::Init, strided_slice::Prepare, + strided_slice::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub.cc new file mode 100644 index 000000000..a54c488fd --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub.cc @@ -0,0 +1,168 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/sub.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/add.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/reference/sub.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +void* SubInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataSub)); +} + +void EvalSub(TfLiteContext* context, TfLiteNode* node, TfLiteSubParams* params, + const OpDataSub* data, const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, TfLiteEvalTensor* output) { + float output_activation_min, output_activation_max; + CalculateActivationRange(params->activation, &output_activation_min, + &output_activation_max); + tflite::ArithmeticParams op_params; + SetActivationParams(output_activation_min, output_activation_max, &op_params); + if (data->requires_broadcast) { + tflite::reference_ops::BroadcastSubSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + tflite::reference_ops::SubWithActivation( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } +} + +TfLiteStatus EvalSubQuantized(TfLiteContext* context, TfLiteNode* node, + TfLiteSubParams* params, const OpDataSub* data, + const TfLiteEvalTensor* input1, + const TfLiteEvalTensor* input2, + TfLiteEvalTensor* output) { + tflite::ArithmeticParams op_params; + op_params.left_shift = data->left_shift; + op_params.input1_offset = data->input1_offset; + op_params.input1_multiplier = data->input1_multiplier; + op_params.input1_shift = data->input1_shift; + op_params.input2_offset = data->input2_offset; + op_params.input2_multiplier = data->input2_multiplier; + op_params.input2_shift = data->input2_shift; + op_params.output_offset = data->output_offset; + op_params.output_multiplier = data->output_multiplier; + op_params.output_shift = data->output_shift; + SetActivationParams(data->output_activation_min, data->output_activation_max, + &op_params); + bool need_broadcast = reference_ops::ProcessBroadcastShapes( + tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorShape(input2), &op_params); + + switch (output->type) { + case kTfLiteInt8: { + if (need_broadcast) { + tflite::reference_ops::BroadcastQuantSubSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + tflite::reference_ops::Sub( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } + break; + } + case kTfLiteInt16: { + if (need_broadcast) { + tflite::reference_ops::BroadcastQuantSubSlow( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else { + tflite::reference_ops::Sub( + op_params, tflite::micro::GetTensorShape(input1), + tflite::micro::GetTensorData(input1), + tflite::micro::GetTensorShape(input2), + tflite::micro::GetTensorData(input2), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } + break; + } + default: + MicroPrintf("Quantized type %s not currently supported.", + TfLiteTypeGetName(output->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus SubEval(TfLiteContext* context, TfLiteNode* node) { + auto* params = reinterpret_cast(node->builtin_data); + + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, kSubInputTensor1); + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, kSubInputTensor2); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kSubOutputTensor); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataSub& data = *(static_cast(node->user_data)); + + if (output->type == kTfLiteFloat32) { + EvalSub(context, node, params, &data, input1, input2, output); + } else if (output->type == kTfLiteInt8 || output->type == kTfLiteInt16) { + TF_LITE_ENSURE_OK(context, EvalSubQuantized(context, node, params, &data, + input1, input2, output)); + } else { + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(output->type), + output->type); + return kTfLiteError; + } + + return kTfLiteOk; +} + +TfLiteRegistration Register_SUB() { + return tflite::micro::RegisterOp(SubInit, SubPrepare, SubEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub.h new file mode 100644 index 000000000..299002210 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub.h @@ -0,0 +1,60 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_SUB_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_SUB_H_ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +extern const int kSubInputTensor1; +extern const int kSubInputTensor2; +extern const int kSubOutputTensor; + +struct OpDataSub { + bool requires_broadcast; + + // These fields are used in both the general 8-bit -> 8bit quantized path, + // and the special 16-bit -> 16bit quantized path + int input1_shift; + int input2_shift; + int32_t output_activation_min; + int32_t output_activation_max; + + // These fields are used only in the general 8-bit -> 8bit quantized path + int32_t input1_multiplier; + int32_t input2_multiplier; + int32_t output_multiplier; + int output_shift; + int left_shift; + int32_t input1_offset; + int32_t input2_offset; + int32_t output_offset; +}; + +TfLiteStatus CalculateOpDataSub(TfLiteContext* context, TfLiteSubParams* params, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + TfLiteTensor* output, OpDataSub* data); + +TfLiteStatus SubPrepare(TfLiteContext* context, TfLiteNode* node); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_SUB_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub_common.cc new file mode 100644 index 000000000..7ad3aa6aa --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/sub_common.cc @@ -0,0 +1,109 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/add.h" +#include "tensorflow/lite/kernels/internal/reference/process_broadcast_shapes.h" +#include "tensorflow/lite/kernels/internal/reference/sub.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/sub.h" + +namespace tflite { + +const int kSubInputTensor1 = 0; +const int kSubInputTensor2 = 1; +const int kSubOutputTensor = 0; + +TfLiteStatus CalculateOpDataSub(TfLiteContext* context, TfLiteSubParams* params, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + TfLiteTensor* output, OpDataSub* data) { + data->requires_broadcast = !HaveSameShapes(input1, input2); + + if (output->type == kTfLiteInt8 || output->type == kTfLiteInt16) { + // 8bit -> 8bit general quantized path, with general rescalings + data->input1_offset = -input1->params.zero_point; + data->input2_offset = -input2->params.zero_point; + data->output_offset = output->params.zero_point; + + // The shift is set to 15 in case of 16-bit and 20 in case of 8-bit, + // accordingly. In case of 16-bit we have 65535 << 15 which is less than 1 + // << 31, therefore the addition will still fit in a 32 bit accumulator. + data->left_shift = output->type == kTfLiteInt16 ? 15 : 20; + const float twice_max_input_scale = + 2 * std::max(input1->params.scale, input2->params.scale); + const double real_input1_multiplier = + static_cast(input1->params.scale) / + static_cast(twice_max_input_scale); + const double real_input2_multiplier = + static_cast(input2->params.scale) / + static_cast(twice_max_input_scale); + const double real_output_multiplier = + static_cast(twice_max_input_scale) / + ((1 << data->left_shift) * static_cast(output->params.scale)); + + QuantizeMultiplierSmallerThanOneExp( + real_input1_multiplier, &data->input1_multiplier, &data->input1_shift); + + QuantizeMultiplierSmallerThanOneExp( + real_input2_multiplier, &data->input2_multiplier, &data->input2_shift); + + QuantizeMultiplierSmallerThanOneExp( + real_output_multiplier, &data->output_multiplier, &data->output_shift); + + TF_LITE_ENSURE_STATUS(CalculateActivationRangeQuantized( + context, params->activation, output, &data->output_activation_min, + &data->output_activation_max)); + } + + return kTfLiteOk; +} + +TfLiteStatus SubPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + OpDataSub* data = static_cast(node->user_data); + auto* params = reinterpret_cast(node->builtin_data); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input1 = + micro_context->AllocateTempInputTensor(node, kSubInputTensor1); + TF_LITE_ENSURE(context, input1 != nullptr); + TfLiteTensor* input2 = + micro_context->AllocateTempInputTensor(node, kSubInputTensor2); + TF_LITE_ENSURE(context, input2 != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kSubOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_STATUS( + CalculateOpDataSub(context, params, input1, input2, output, data)); + + micro_context->DeallocateTempTfLiteTensor(input1); + micro_context->DeallocateTempTfLiteTensor(input2); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf.cc new file mode 100644 index 000000000..f6aa4e8b9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf.cc @@ -0,0 +1,106 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/kernels/svdf.h" + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/activation_utils.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace { + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpDataSvdf)); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + auto* params = reinterpret_cast(node->builtin_data); + TFLITE_DCHECK(node->user_data != nullptr); + const OpDataSvdf& data = *(static_cast(node->user_data)); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kSvdfInputTensor); + const TfLiteEvalTensor* weights_feature = + tflite::micro::GetEvalInput(context, node, kSvdfWeightsFeatureTensor); + const TfLiteEvalTensor* weights_time = + tflite::micro::GetEvalInput(context, node, kSvdfWeightsTimeTensor); + const TfLiteEvalTensor* bias = + (NumInputs(node) == 5) + ? tflite::micro::GetEvalInput(context, node, kSvdfBiasTensor) + : nullptr; + TfLiteEvalTensor* activation_state = tflite::micro::GetMutableEvalInput( + context, node, kSvdfInputActivationStateTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kSvdfOutputTensor); + + switch (weights_feature->type) { + case kTfLiteFloat32: { + EvalFloatSvdfReference( + context, node, input, weights_feature, weights_time, bias, params, + data.scratch_tensor_index, activation_state, output); + return kTfLiteOk; + break; + } + + case kTfLiteInt8: { + switch (weights_time->type) { + case kTfLiteInt16: { + EvalInt16SvdfReference(context, node, input, weights_feature, + weights_time, bias, params, activation_state, + output, data); + return kTfLiteOk; + break; + } + case kTfLiteInt8: { + EvalInt8SvdfReference(context, node, input, weights_feature, + weights_time, bias, params, activation_state, + output, data); + return kTfLiteOk; + break; + } + default: + MicroPrintf("Type %s not currently supported.", + TfLiteTypeGetName(weights_time->type)); + return kTfLiteError; + } + } + + default: + MicroPrintf("Type %s not currently supported.", + TfLiteTypeGetName(weights_feature->type)); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_SVDF() { + return tflite::micro::RegisterOp(Init, PrepareSvdf, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf.h new file mode 100644 index 000000000..0915c9fdc --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf.h @@ -0,0 +1,99 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_SVDF_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_SVDF_H_ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +struct OpDataSvdf { + int32_t effective_scale_1_a; + int32_t effective_scale_2_a; + // b versions of each scale are kept at int since the numbers are just the + // shift value - typically between [-32, 32]. + int effective_scale_1_b; + int effective_scale_2_b; + int scratch_tensor_index; + int scratch_output_tensor_index; + + // Cached tensor zero point values for quantized operations. + int input_zero_point; + int output_zero_point; + int activation_state_zero_point; +}; + +// Input tensors. +extern const int kSvdfInputTensor; +extern const int kSvdfWeightsFeatureTensor; +extern const int kSvdfWeightsTimeTensor; +extern const int kSvdfBiasTensor; +// This is a variable tensor, and will be modified by this op. +extern const int kSvdfInputActivationStateTensor; + +// Output tensor. +extern const int kSvdfOutputTensor; + +void EvalInt8SvdfReference(TfLiteContext* context, TfLiteNode* node, + const TfLiteEvalTensor* input_tensor, + const TfLiteEvalTensor* weights_feature_tensor, + const TfLiteEvalTensor* weights_time_tensor, + const TfLiteEvalTensor* bias_tensor, + const TfLiteSVDFParams* params, + TfLiteEvalTensor* activation_state_tensor, + TfLiteEvalTensor* output_tensor, + const OpDataSvdf& data); + +// TODO(#523): remove 16-bit code when no longer needed. +void EvalInt16SvdfReference(TfLiteContext* context, TfLiteNode* node, + const TfLiteEvalTensor* input_tensor, + const TfLiteEvalTensor* weights_feature_tensor, + const TfLiteEvalTensor* weights_time_tensor, + const TfLiteEvalTensor* bias_tensor, + const TfLiteSVDFParams* params, + TfLiteEvalTensor* activation_state_tensor, + TfLiteEvalTensor* output_tensor, + const OpDataSvdf& data); + +void EvalFloatSvdfReference( + TfLiteContext* context, TfLiteNode* node, const TfLiteEvalTensor* input, + const TfLiteEvalTensor* weights_feature, + const TfLiteEvalTensor* weights_time, const TfLiteEvalTensor* bias, + const TfLiteSVDFParams* params, int scratch_tensor_index, + TfLiteEvalTensor* activation_state, TfLiteEvalTensor* output); + +TfLiteStatus PrepareSvdf(TfLiteContext* context, TfLiteNode* node); + +// This is the most generic TfLiteRegistration. The actual supported types may +// still be target dependent. The only requirement is that every implementation +// (reference or optimized) must define this function. +TfLiteRegistration Register_SVDF(); + +#if defined(HEXAGON) || defined(CMSIS_NN) +TfLiteRegistration Register_SVDF_INT8(); + +#else +// Note that while this block gets used for both reference and optimized kernels +// that do not have any specialized implementations, the only goal here is to +// define fallback implementation that allow reference kernels to still be used +// from applications that call a more specific kernel variant. + +inline TfLiteRegistration Register_SVDF_INT8() { return Register_SVDF(); } + +#endif +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_SVDF_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf_common.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf_common.cc new file mode 100644 index 000000000..ed74358bc --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/svdf_common.cc @@ -0,0 +1,516 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/activation_utils.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/svdf.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +/** + * This version of SVDF is specific to TFLite Micro. It contains the following + * differences between the TFLite version: + * + * 1.) Scratch tensor allocation - scratch tensors must be known ahead of time + * for the Micro interpreter. + * 2.) Output dimensions - the TFLite version determines output size and runtime + * and resizes the output tensor. Micro runtime does not support tensor + * resizing. + */ + +const int kSvdfInputTensor = 0; +const int kSvdfWeightsFeatureTensor = 1; +const int kSvdfWeightsTimeTensor = 2; +const int kSvdfBiasTensor = 3; +const int kSvdfInputActivationStateTensor = + 4; // This is a variable tensor, and will be modified by this op. +const int kSvdfOutputTensor = 0; + +template +void EvalIntegerSvdfReference(TfLiteContext* context, TfLiteNode* node, + const TfLiteEvalTensor* input_tensor, + const TfLiteEvalTensor* weights_feature_tensor, + const TfLiteEvalTensor* weights_time_tensor, + const TfLiteEvalTensor* bias_tensor, + const TfLiteSVDFParams* params, + TfLiteEvalTensor* activation_state_tensor, + TfLiteEvalTensor* output_tensor, + const OpDataSvdf& data) { + const int n_rank = params->rank; + const int n_batch = input_tensor->dims->data[0]; + const int n_input = input_tensor->dims->data[1]; + const int n_filter = weights_feature_tensor->dims->data[0]; + const int n_unit = n_filter / n_rank; + const int n_memory = weights_time_tensor->dims->data[1]; + + TFLITE_DCHECK(context != nullptr); + TFLITE_DCHECK(context->GetScratchBuffer != nullptr); + + int32_t* scratch_tensor = static_cast( + context->GetScratchBuffer(context, data.scratch_tensor_index)); + int32_t* scratch_output_tensor = static_cast( + context->GetScratchBuffer(context, data.scratch_output_tensor_index)); + + // Shift states. + T* const state_ptr = tflite::micro::GetTensorData(activation_state_tensor); + + // Left shift the activation_state. + { + T* new_state_start = state_ptr; + const T* old_state_start = state_ptr + 1; + const T* old_state_end = state_ptr + n_batch * n_filter * n_memory; + while (old_state_start != old_state_end) { + *new_state_start++ = *old_state_start++; + } + } + + // Note: no need to clear the latest activation, matmul is not accumulative. + + // Feature matmul. + { + T* state = tflite::micro::GetTensorData(activation_state_tensor); + const int8_t* input = tflite::micro::GetTensorData(input_tensor); + const int8_t* weight_feature = + tflite::micro::GetTensorData(weights_feature_tensor); + const int32_t output_max = std::numeric_limits::max(); + const int32_t output_min = std::numeric_limits::min(); + T* result_in_batch = state + (n_memory - 1); + for (int b = 0; b < n_batch; b++) { + const int8_t* matrix_ptr = weight_feature; + for (int r = 0; r < n_filter; r++) { + int32_t dot_prod = 0; + const int8_t* vector_in_batch = input + b * n_input; + for (int c = 0; c < n_input; c++) { + dot_prod += + *matrix_ptr++ * (*vector_in_batch++ - data.input_zero_point); + } + dot_prod = MultiplyByQuantizedMultiplier( + dot_prod, data.effective_scale_1_a, data.effective_scale_1_b); + dot_prod = std::min(std::max(output_min, dot_prod), output_max); + // The int16 version of the op assumes a zero_point of 0. This + // code accounts for the potentially non-zero zero_point for the int8 + // version of the op. + *result_in_batch = data.activation_state_zero_point + dot_prod; + result_in_batch += n_memory; + } + } + } + + // Time. + { + for (int b = 0; b < n_batch; ++b) { + int32_t* scratch_ptr_batch = scratch_tensor + b * n_filter; + + // Perform batched vector dot product: + const T* vector1_ptr = + tflite::micro::GetTensorData(weights_time_tensor); + const T* vector2_ptr = + tflite::micro::GetTensorData(activation_state_tensor) + + b * n_memory * n_filter; + + for (int i = 0; i < n_filter; i++) { + *scratch_ptr_batch = 0; + for (int j = 0; j < n_memory; j++) { + *scratch_ptr_batch += + *vector1_ptr++ * + (*vector2_ptr++ - data.activation_state_zero_point); + } + scratch_ptr_batch++; + } + } + } + + // Reduce, add bias, rescale, activation. + { + // Add bias. + if (bias_tensor) { + // Vector batch assign: + const int32_t* bias_data = + tflite::micro::GetTensorData(bias_tensor); + for (int i = 0; i < n_batch; ++i) { + int32_t* output_ptr = scratch_output_tensor + i * n_unit; + const int32_t* bias_ptr = bias_data; + for (int j = 0; j < n_unit; ++j) { + *output_ptr++ = *bias_ptr++; + } + } + } else { + int32_t* output_ptr = scratch_output_tensor; + for (int i = 0; i < n_batch * n_unit; ++i) { + *output_ptr++ = 0; + } + } + + // Reduce. + for (int b = 0; b < n_batch; ++b) { + int32_t* output_temp_ptr = scratch_output_tensor + b * n_unit; + int32_t* scratch_ptr_batch = scratch_tensor + b * n_filter; + + // Reduction sum vector + for (int i = 0; i < n_unit; ++i) { + for (int j = 0; j < n_rank; ++j) { + output_temp_ptr[i] += *scratch_ptr_batch++; + } + } + } + + // Rescale. + const int32_t output_max = std::numeric_limits::max(); + const int32_t output_min = std::numeric_limits::min(); + for (int i = 0; i < n_batch * n_unit; ++i) { + int32_t x1 = scratch_output_tensor[i]; + int32_t x2 = MultiplyByQuantizedMultiplier(x1, data.effective_scale_2_a, + data.effective_scale_2_b); + int32_t x3 = x2 + data.output_zero_point; + int32_t x4 = std::min(std::max(output_min, x3), output_max); + tflite::micro::GetTensorData(output_tensor)[i] = + static_cast(x4); + } + } +} + +/** + * Generate two versions of the integer code. One with int16_t type for the + * time weights and the activation state, and another one with int8_t for the + * same. + */ + +void EvalInt16SvdfReference(TfLiteContext* context, TfLiteNode* node, + const TfLiteEvalTensor* input_tensor, + const TfLiteEvalTensor* weights_feature_tensor, + const TfLiteEvalTensor* weights_time_tensor, + const TfLiteEvalTensor* bias_tensor, + const TfLiteSVDFParams* params, + TfLiteEvalTensor* activation_state_tensor, + TfLiteEvalTensor* output_tensor, + const OpDataSvdf& data) { + EvalIntegerSvdfReference( + context, node, input_tensor, weights_feature_tensor, weights_time_tensor, + bias_tensor, params, activation_state_tensor, output_tensor, data); +} + +void EvalInt8SvdfReference(TfLiteContext* context, TfLiteNode* node, + const TfLiteEvalTensor* input_tensor, + const TfLiteEvalTensor* weights_feature_tensor, + const TfLiteEvalTensor* weights_time_tensor, + const TfLiteEvalTensor* bias_tensor, + const TfLiteSVDFParams* params, + TfLiteEvalTensor* activation_state_tensor, + TfLiteEvalTensor* output_tensor, + const OpDataSvdf& data) { + EvalIntegerSvdfReference( + context, node, input_tensor, weights_feature_tensor, weights_time_tensor, + bias_tensor, params, activation_state_tensor, output_tensor, data); +} + +static inline void ApplyTimeWeightsBiasAndActivation( + int batch_size, int memory_size, int num_filters, int num_units, int rank, + const float* const weights_time_ptr, const float* const bias_ptr, + TfLiteFusedActivation activation, float* const state_ptr, + float* const scratch_ptr, float* const output_ptr) { + // Compute matmul(activation_state, weights_time). + for (int b = 0; b < batch_size; ++b) { + // Perform batched vector dot product: + float* scratch_ptr_batch = scratch_ptr + b * num_filters; + const float* vector1_ptr = weights_time_ptr; + const float* vector2_ptr = state_ptr + b * memory_size * num_filters; + for (int i = 0; i < num_filters; ++i) { + *scratch_ptr_batch = 0.f; + for (int j = 0; j < memory_size; ++j) { + *scratch_ptr_batch += *vector1_ptr++ * *vector2_ptr++; + } + scratch_ptr_batch++; + } + } + + // Initialize output with bias if provided. + if (bias_ptr) { + // VectorBatchVectorAssign + for (int i = 0; i < batch_size; ++i) { + float* output_data = output_ptr + i * num_units; + const float* bias_data = bias_ptr; + for (int j = 0; j < num_units; ++j) { + *output_data++ = *bias_data++; + } + } + } else { + float* output_data = output_ptr; + for (int i = 0; i < batch_size * num_units; ++i) { + *output_data++ = 0.0f; + } + } + + // Reduction sum. + for (int b = 0; b < batch_size; ++b) { + float* output_ptr_batch = output_ptr + b * num_units; + float* scratch_ptr_batch = scratch_ptr + b * num_filters; + + // Reduction sum vector + for (int i = 0; i < num_units; ++i) { + for (int j = 0; j < rank; j++) { + output_ptr_batch[i] += *scratch_ptr_batch++; + } + } + } + + // Apply activation. + for (int b = 0; b < batch_size; ++b) { + float* output_ptr_batch = output_ptr + b * num_units; + for (int i = 0; i < num_units; ++i) { + *output_ptr_batch = + tflite::ops::micro::ActivationValFloat(activation, *output_ptr_batch); + ++output_ptr_batch; + } + } +} + +void EvalFloatSvdfReference( + TfLiteContext* context, TfLiteNode* node, const TfLiteEvalTensor* input, + const TfLiteEvalTensor* weights_feature, + const TfLiteEvalTensor* weights_time, const TfLiteEvalTensor* bias, + const TfLiteSVDFParams* params, int scratch_tensor_index, + TfLiteEvalTensor* activation_state, TfLiteEvalTensor* output) { + const int rank = params->rank; + const int batch_size = input->dims->data[0]; + const int input_size = input->dims->data[1]; + const int num_filters = weights_feature->dims->data[0]; + const int num_units = num_filters / rank; + const int memory_size = weights_time->dims->data[1]; + + const float* weights_feature_ptr = + tflite::micro::GetTensorData(weights_feature); + const float* weights_time_ptr = + tflite::micro::GetTensorData(weights_time); + const float* bias_ptr = tflite::micro::GetTensorData(bias); + const float* input_ptr = tflite::micro::GetTensorData(input); + + float* state_ptr = tflite::micro::GetTensorData(activation_state); + + TFLITE_DCHECK(context != nullptr); + TFLITE_DCHECK(context->GetScratchBuffer != nullptr); + + float* scratch_ptr = static_cast( + context->GetScratchBuffer(context, scratch_tensor_index)); + + float* output_ptr = tflite::micro::GetTensorData(output); + + // Left shift the activation_state. + { + float* new_state_start = state_ptr; + const float* old_state_start = state_ptr + 1; + const float* old_state_end = + state_ptr + batch_size * num_filters * memory_size; + while (old_state_start != old_state_end) { + *new_state_start++ = *old_state_start++; + } + } + + // Note: no need to clear the latest activation, matmul is not accumulative. + + // Compute conv1d(inputs, weights_feature). + // The activation_state's rightmost column is used to save current cycle + // activation. This is achieved by starting at state_ptr[memory_size - 1] and + // having the stride equal to memory_size. + + // Perform batched matrix vector multiply operation: + { + const float* matrix = weights_feature_ptr; + const float* vector = input_ptr; + float* result = &state_ptr[memory_size - 1]; + float* result_in_batch = result; + for (int i = 0; i < batch_size; ++i) { + const float* matrix_ptr = matrix; + for (int j = 0; j < num_filters; ++j) { + float dot_prod = 0.0f; + const float* vector_in_batch = vector + i * input_size; + for (int k = 0; k < input_size; ++k) { + dot_prod += *matrix_ptr++ * *vector_in_batch++; + } + *result_in_batch = dot_prod; + result_in_batch += memory_size; + } + } + } + + ApplyTimeWeightsBiasAndActivation( + batch_size, memory_size, num_filters, num_units, rank, weights_time_ptr, + bias_ptr, params->activation, state_ptr, scratch_ptr, output_ptr); +} + +TfLiteStatus PrepareSvdf(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->builtin_data != nullptr); + + const auto* params = static_cast(node->builtin_data); + + MicroContext* micro_context = GetMicroContext(context); + + // Validate Tensor Inputs (dtype depends on quantization): + // [0] = Input, {2, batch_size, input_size} + // [1] = Weights Feature, {2, num_filters, input_size} + // [2] = Weights Time, {2, num_filters, memory_size} + // [3] = Bias (optional), {1, num_units} + // [4] = Activation State (variable), + // {2, batch_size, memory_size * num_filters} + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kSvdfInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* weights_feature = + micro_context->AllocateTempInputTensor(node, kSvdfWeightsFeatureTensor); + TF_LITE_ENSURE(context, weights_feature != nullptr); + TfLiteTensor* weights_time = + micro_context->AllocateTempInputTensor(node, kSvdfWeightsTimeTensor); + TF_LITE_ENSURE(context, weights_time != nullptr); + TfLiteTensor* bias = + micro_context->AllocateTempInputTensor(node, kSvdfBiasTensor); + TfLiteTensor* activation_state = micro_context->AllocateTempInputTensor( + node, kSvdfInputActivationStateTensor); + TF_LITE_ENSURE(context, activation_state != nullptr); + + // Define input constants based on input tensor definition above: + const int rank = params->rank; + const int input_size = input->dims->data[1]; + const int batch_size = input->dims->data[0]; + const int num_filters = weights_feature->dims->data[0]; + TF_LITE_ENSURE_EQ(context, num_filters % rank, 0); + const int num_units = num_filters / rank; + const int memory_size = weights_time->dims->data[1]; + + // Validate Input Tensor: + TF_LITE_ENSURE(context, + input->type == kTfLiteFloat32 || input->type == kTfLiteInt8); + TF_LITE_ENSURE_EQ(context, NumDimensions(input), 2); + + // Validate Tensor Output: + // [0] = float/int8_t, {2, batch_size, num_units} + TF_LITE_ENSURE_EQ(context, node->outputs->size, 1); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kSvdfOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TF_LITE_ENSURE_EQ(context, NumDimensions(output), 2); + TF_LITE_ENSURE_EQ(context, output->dims->data[0], batch_size); + TF_LITE_ENSURE_EQ(context, output->dims->data[1], num_units); + + // Validate Weights Feature Input Tensor: + TF_LITE_ENSURE_EQ(context, NumDimensions(weights_feature), 2); + TF_LITE_ENSURE_EQ(context, weights_feature->dims->data[1], input_size); + + // Validate Weights Time Input Tensor: + TF_LITE_ENSURE_EQ(context, NumDimensions(weights_time), 2); + TF_LITE_ENSURE_EQ(context, weights_time->dims->data[0], num_filters); + TF_LITE_ENSURE_EQ(context, weights_time->dims->data[1], memory_size); + + // Validate Optional Bias Input Tensor: + if (bias != nullptr) { + TF_LITE_ENSURE_EQ(context, bias->dims->data[0], num_units); + } + + // Validate Activation State Input Tensor: + TF_LITE_ENSURE_EQ(context, NumDimensions(activation_state), 2); + TF_LITE_ENSURE_EQ(context, activation_state->dims->data[0], batch_size); + TF_LITE_ENSURE_EQ(context, activation_state->dims->data[1], + memory_size * num_filters); + // Since is_variable is not part of TFLiteEvalTensor, check is_variable here. + TF_LITE_ENSURE_EQ(context, activation_state->is_variable, true); + + TF_LITE_ENSURE_EQ(context, node->inputs->size, 5); + + TFLITE_DCHECK(node->user_data != nullptr); + OpDataSvdf* data = static_cast(node->user_data); + + if (input->type == kTfLiteInt8) { + TF_LITE_ENSURE_EQ(context, weights_feature->type, kTfLiteInt8); + TF_LITE_ENSURE(context, (weights_time->type == kTfLiteInt16) || + (weights_time->type == kTfLiteInt8)); + TF_LITE_ENSURE(context, (activation_state->type == kTfLiteInt16) || + (activation_state->type == kTfLiteInt8)); + if (bias != nullptr) { + TF_LITE_ENSURE_EQ(context, bias->type, kTfLiteInt32); + } + + TF_LITE_ENSURE_TYPES_EQ(context, output->type, kTfLiteInt8); + + const double effective_scale_1 = + static_cast(input->params.scale) * + static_cast(weights_feature->params.scale) / + static_cast(activation_state->params.scale); + const double effective_scale_2 = + static_cast(activation_state->params.scale) * + static_cast(weights_time->params.scale) / + static_cast(output->params.scale); + + // TODO(b/162018098): Use TF_LITE_ENSURE_NEAR when it is ready. + TF_LITE_ENSURE( + context, + std::abs(static_cast(bias->params.scale) - + (static_cast(activation_state->params.scale) * + static_cast(weights_time->params.scale))) < 1e-5); + + QuantizeMultiplier(effective_scale_1, &(data->effective_scale_1_a), + &(data->effective_scale_1_b)); + QuantizeMultiplier(effective_scale_2, &(data->effective_scale_2_a), + &(data->effective_scale_2_b)); + + data->input_zero_point = input->params.zero_point; + data->output_zero_point = output->params.zero_point; + data->activation_state_zero_point = activation_state->params.zero_point; + + TFLITE_DCHECK(context->RequestScratchBufferInArena != nullptr); + + const TfLiteStatus scratch_status = context->RequestScratchBufferInArena( + context, batch_size * num_filters * sizeof(int32_t), + &(data->scratch_tensor_index)); + TF_LITE_ENSURE_OK(context, scratch_status); + + const TfLiteStatus scratch_output_status = + context->RequestScratchBufferInArena( + context, batch_size * num_units * sizeof(int32_t), + &(data->scratch_output_tensor_index)); + TF_LITE_ENSURE_OK(context, scratch_output_status); + } else { + TF_LITE_ENSURE_EQ(context, weights_feature->type, kTfLiteFloat32); + TF_LITE_ENSURE_EQ(context, weights_time->type, kTfLiteFloat32); + TF_LITE_ENSURE_EQ(context, activation_state->type, kTfLiteFloat32); + if (bias != nullptr) { + TF_LITE_ENSURE_EQ(context, bias->type, kTfLiteFloat32); + } + TF_LITE_ENSURE_TYPES_EQ(context, output->type, kTfLiteFloat32); + + TFLITE_DCHECK(context->RequestScratchBufferInArena != nullptr); + const TfLiteStatus scratch_status = context->RequestScratchBufferInArena( + context, batch_size * num_filters * sizeof(float), + &(data->scratch_tensor_index)); + TF_LITE_ENSURE_OK(context, scratch_status); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(weights_feature); + micro_context->DeallocateTempTfLiteTensor(weights_time); + micro_context->DeallocateTempTfLiteTensor(activation_state); + micro_context->DeallocateTempTfLiteTensor(output); + micro_context->DeallocateTempTfLiteTensor(bias); + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/tanh.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/tanh.cc new file mode 100644 index 000000000..e10399307 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/tanh.cc @@ -0,0 +1,204 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/integer_ops/tanh.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/tanh.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace activations { +namespace { +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +struct OpData { + int32_t input_zero_point; + int32_t input_range_radius; + int32_t input_multiplier; + int input_left_shift; +}; + +void* TanhInit(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus CalculateArithmeticOpData(TfLiteContext* context, TfLiteNode* node, + OpData* data) { + MicroContext* micro_context = GetMicroContext(context); + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + + TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); + + if (input->type == kTfLiteInt8) { + static constexpr int kInputIntegerBits = 4; + const double input_real_multiplier = + static_cast(input->params.scale) * + static_cast(1 << (31 - kInputIntegerBits)); + + const double q = std::frexp(input_real_multiplier, &data->input_left_shift); + data->input_multiplier = static_cast(TfLiteRound(q * (1ll << 31))); + + data->input_range_radius = + CalculateInputRadius(kInputIntegerBits, data->input_left_shift, 31); + } + + if (input->type == kTfLiteInt16) { + static constexpr int kInputIntegerBits = 3; + static constexpr int kOutputFractionalBits = 15; + + // These operators are implemented in fixed-point arithmetic, + // which intrinsically wants symmetric ranges (zero_point==0) + // and power-of-two scales (power-of-two is abbreviated below as POT). + // While more general support would be possible by means of rescaling, + // that would add some overhead and some loss of accuracy and wouldn't + // be used at the moment as current quantized LSTM applications are + // happy with symmetric, power-of-two-scales quantization. So we just + // implement that narrow case only for now. + + TF_LITE_ENSURE_EQ(context, input->params.zero_point, 0); + TF_LITE_ENSURE_EQ(context, output->params.zero_point, 0); + + int input_scale_log2_rounded; + bool param_scale_pot = + CheckedLog2(input->params.scale, &input_scale_log2_rounded); + + data->input_left_shift = + (15 - kInputIntegerBits) + input_scale_log2_rounded; + param_scale_pot &= + (data->input_left_shift == 0 || data->input_left_shift == 1); + + if (param_scale_pot) { + data->input_multiplier = 0; + } else { + // Calculate multiplier to change input scale to 1/(3*4096) + // as required by the table lookup. + // The number 3.0 in the multiplier comes from here, + // because the interval is [-10.7, 10.7] instead of [-8, 8]. + // So, in this scaling +/-2^17 represents +/-10.7. + + double multiplier = + static_cast(input->params.scale) * 4096.0 * 3.0; + data->input_left_shift = 0; + + while (multiplier <= 32767.0 / 2.0 && data->input_left_shift <= 30) { + data->input_left_shift++; + multiplier = multiplier * 2.0; + } + + data->input_multiplier = static_cast(multiplier); + } + + int output_scale_log2_rounded; + TF_LITE_ENSURE( + context, CheckedLog2(output->params.scale, &output_scale_log2_rounded)); + TF_LITE_ENSURE_EQ(context, output_scale_log2_rounded, + -kOutputFractionalBits); + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +TfLiteStatus TanhPrepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + + OpData* data = static_cast(node->user_data); + + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + data->input_zero_point = input->params.zero_point; + TF_LITE_ENSURE_OK(context, CalculateArithmeticOpData(context, node, data)); + + micro_context->DeallocateTempTfLiteTensor(input); + return kTfLiteOk; +} + +} // namespace + +TfLiteStatus TanhEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpData& data = *(static_cast(node->user_data)); + + switch (input->type) { + case kTfLiteFloat32: { + reference_ops::Tanh(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } break; + case kTfLiteInt16: { + reference_integer_ops::Tanh( + data.input_multiplier, data.input_left_shift, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } break; + case kTfLiteInt8: { + reference_integer_ops::Tanh( + data.input_zero_point, data.input_range_radius, data.input_multiplier, + data.input_left_shift, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + return kTfLiteOk; + } break; + default: + MicroPrintf("Input %s, output %s not supported.", + TfLiteTypeGetName(input->type), + TfLiteTypeGetName(output->type), context); + return kTfLiteError; + } +} + +} // namespace activations + +TfLiteRegistration Register_TANH() { + return tflite::micro::RegisterOp( + activations::TanhInit, activations::TanhPrepare, activations::TanhEval); +} +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/transpose.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/transpose.cc new file mode 100644 index 000000000..daa75f173 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/transpose.cc @@ -0,0 +1,122 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/kernels/internal/reference/transpose.h" + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor = 0; +constexpr int kPermTensor = 1; +constexpr int kOutputTensor = 0; + +struct TransposeContext { + TransposeContext(TfLiteContext* context, TfLiteNode* node) { + micro_context = GetMicroContext(context); + input = micro_context->AllocateTempInputTensor(node, kInputTensor); + perm = micro_context->AllocateTempInputTensor(node, kPermTensor); + output = micro_context->AllocateTempOutputTensor(node, kOutputTensor); + } + ~TransposeContext() { + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(perm); + micro_context->DeallocateTempTfLiteTensor(output); + } + MicroContext* micro_context; + TfLiteTensor* input; + TfLiteTensor* perm; + TfLiteTensor* output; +}; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + TransposeContext op_context(context, node); + + // Ensure validity of input tensor. + TF_LITE_ENSURE_MSG(context, NumDimensions(op_context.input) <= 5, + "Transpose op only supports 1D-5D input arrays."); + TF_LITE_ENSURE_TYPES_EQ(context, op_context.input->type, + op_context.output->type); + + int dims = NumDimensions(op_context.input); + const int32_t* perm_data = GetTensorData(op_context.perm); + + // Ensure validity of the permutations tensor as a 1D tensor. + TF_LITE_ENSURE_EQ(context, NumDimensions(op_context.perm), 1); + TF_LITE_ENSURE_EQ(context, op_context.perm->dims->data[0], dims); + for (int idx = 0; idx < dims; ++idx) { + TF_LITE_ENSURE_MSG(context, (perm_data[idx] >= 0 && perm_data[idx] < dims), + "Transpose op permutations array is out of bounds."); + } + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* perm_tensor = + tflite::micro::GetEvalInput(context, node, kPermTensor); + const int32_t* perm_data = perm_tensor->data.i32; + const int size = perm_tensor->dims->data[0]; + TransposeParams params; + params.perm_count = size; + for (int i = 0; i < size; ++i) { + params.perm[i] = perm_data[i]; + } + + // Transpose kernel only does rearranging values not numeric evaluations + // on each cell. It's safe to implement per size of scalar type and this + // trick keeps the total code size in a reasonable range. + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + switch (input->type) { + case kTfLiteFloat32: + reference_ops::Transpose(params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + case kTfLiteInt8: + reference_ops::Transpose(params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + break; + default: + MicroPrintf( + "Type %s is currently not supported by Transpose. " + "Only float32 and int8 is supported", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_TRANSPOSE() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/transpose_conv.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/transpose_conv.cc new file mode 100644 index 000000000..4b1df78ba --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/transpose_conv.cc @@ -0,0 +1,344 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/internal/reference/transpose_conv.h" + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/common.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/transpose_conv.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/padding.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +// For the TfLite transpose_conv implementation, input tensor 0 corresponds to +// the OutputShapeTensor. However, since TFLM does not support dynamic tensors, +// the TFLM implementation ignores input tensor 0 and the only inputs we care +// about are kFilterTensor, kInputTensor and kBiasTensor. +constexpr int kFilterTensor = 1; +constexpr int kInputTensor = 2; +constexpr int kBiasTensor = 3; +constexpr int kOutputTensor = 0; + +// Conv is quantized along dimension 0: +// https://www.tensorflow.org/lite/performance/quantization_spec +constexpr int kConvQuantizedDimension = 0; + +struct OpData { + ConvParams params; + + // A scratch buffer is required for quantized implementations. + int scratch_buffer_index; + + // TODO(b/192090531): Remove this once all 8x16 transpose conv models use + // 64-bit biases. + int bias_converted_buffer_index; + + // Multiplier and shift arrays are required for the int8 implementation. + int32_t* per_channel_output_multiplier; + int32_t* per_channel_output_shift; +}; + +inline PaddingType RuntimePaddingType(TfLitePadding padding) { + switch (padding) { + case TfLitePadding::kTfLitePaddingSame: + return PaddingType::kSame; + case TfLitePadding::kTfLitePaddingValid: + return PaddingType::kValid; + case TfLitePadding::kTfLitePaddingUnknown: + default: + return PaddingType::kNone; + } +} + +TfLiteStatus CalculateOpData(TfLiteContext* context, TfLiteNode* node, + const TfLiteTransposeConvParams* params, int width, + int height, int filter_width, int filter_height, + const TfLiteType data_type, OpData* data) { + bool has_bias = node->inputs->size == 4; + // Check number of inputs/outputs + TF_LITE_ENSURE(context, has_bias || node->inputs->size == 3); + TF_LITE_ENSURE_EQ(context, node->outputs->size, 1); + + // Matching GetWindowedOutputSize in TensorFlow. + auto padding = params->padding; + int unused_output_width; + int unused_output_height; + TfLitePaddingValues padding_values = ComputePaddingHeightWidth( + params->stride_height, params->stride_width, 1, + 1, // Dilation height and width are always 1 for transpose_conv. + height, width, filter_height, filter_width, padding, + &unused_output_height, &unused_output_width); + + data->params.padding_type = RuntimePaddingType(padding); + data->params.padding_values.width = padding_values.width; + data->params.padding_values.height = padding_values.height; + + // Note that quantized inference requires that all tensors have their + // parameters set. This is usually done during quantized training. + if (data_type != kTfLiteFloat32) { + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = + micro_context->AllocateTempInputTensor(node, kFilterTensor); + TF_LITE_ENSURE(context, filter != nullptr); + TfLiteTensor* bias = + micro_context->AllocateTempInputTensor(node, kBiasTensor); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + int output_channels = filter->dims->data[kConvQuantizedDimension]; + + TF_LITE_ENSURE_STATUS(tflite::PopulateConvolutionQuantizationParams( + context, input, filter, bias, output, kTfLiteActNone, + &data->params.output_multiplier, &data->params.output_shift, + &data->params.quantized_activation_min, + &data->params.quantized_activation_max, + data->per_channel_output_multiplier, data->per_channel_output_shift, + output_channels)); + + // TODO(b/192090531): Remove this once all 8x16 transpose conv models use + // 64-bit biases. + if (input->type == kTfLiteInt16) { + TFLITE_DCHECK(filter->type == kTfLiteInt8); + TFLITE_DCHECK(output->type == kTfLiteInt16); + if (bias->type == kTfLiteInt16) { + TFLITE_DCHECK( + context->RequestScratchBufferInArena( + context, GetTensorShape(bias).FlatSize() * sizeof(std::int64_t), + &(data->bias_converted_buffer_index)) == kTfLiteOk); + } + } + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(filter); + micro_context->DeallocateTempTfLiteTensor(output); + if (bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(bias); + } + } + return kTfLiteOk; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TFLITE_DCHECK(node->user_data != nullptr); + TFLITE_DCHECK(node->builtin_data != nullptr); + + OpData* data = static_cast(node->user_data); + const auto params = + static_cast(node->builtin_data); + + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* filter = + micro_context->AllocateTempInputTensor(node, kFilterTensor); + TF_LITE_ENSURE(context, filter != nullptr); + + // Get height and width of the output. + const int width = SizeOfDimension(output, 2); + const int height = SizeOfDimension(output, 1); + const int filter_width = SizeOfDimension(filter, 2); + const int filter_height = SizeOfDimension(filter, 1); + + // Dynamically allocate per-channel quantization parameters. + const int num_channels = filter->dims->data[kConvQuantizedDimension]; + data->per_channel_output_multiplier = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + data->per_channel_output_shift = + static_cast(context->AllocatePersistentBuffer( + context, num_channels * sizeof(int32_t))); + + // Quantized kernels use an int32 scratch buffer. + if (input->type == kTfLiteInt8) { + TFLITE_DCHECK(context->RequestScratchBufferInArena != nullptr); + TFLITE_DCHECK(context->RequestScratchBufferInArena( + context, + GetTensorShape(output).FlatSize() * sizeof(int32_t), + &(data->scratch_buffer_index)) == kTfLiteOk); + } + + // Quantized 16x8 kernels use an int64 scratch buffer. + if (input->type == kTfLiteInt16) { + TFLITE_DCHECK(context->RequestScratchBufferInArena != nullptr); + TFLITE_DCHECK(context->RequestScratchBufferInArena( + context, + GetTensorShape(output).FlatSize() * sizeof(std::int64_t), + &(data->scratch_buffer_index)) == kTfLiteOk); + } + + // All per-channel quantized tensors need valid zero point and scale arrays. + if (input->type == kTfLiteInt8 || input->type == kTfLiteInt16) { + TF_LITE_ENSURE_EQ(context, filter->quantization.type, + kTfLiteAffineQuantization); + + const auto* affine_quantization = + static_cast(filter->quantization.params); + TF_LITE_ENSURE(context, affine_quantization); + TF_LITE_ENSURE(context, affine_quantization->scale); + TF_LITE_ENSURE(context, affine_quantization->zero_point); + + TF_LITE_ENSURE(context, + affine_quantization->scale->size == 1 || + affine_quantization->scale->size == + filter->dims->data[kConvQuantizedDimension]); + TF_LITE_ENSURE_EQ(context, affine_quantization->scale->size, + affine_quantization->zero_point->size); + } + + TF_LITE_ENSURE_STATUS(CalculateOpData(context, node, params, width, height, + filter_width, filter_height, + input->type, data)); + + // Offsets (zero points) + data->params.input_offset = -input->params.zero_point; + data->params.weights_offset = -filter->params.zero_point; + data->params.output_offset = output->params.zero_point; + + // Stride + data->params.stride_width = params->stride_width; + data->params.stride_height = params->stride_height; + + micro_context->DeallocateTempTfLiteTensor(output); + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(filter); + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + const TfLiteEvalTensor* filter = + tflite::micro::GetEvalInput(context, node, kFilterTensor); + const TfLiteEvalTensor* bias = + (NumInputs(node) == 4) + ? tflite::micro::GetEvalInput(context, node, kBiasTensor) + : nullptr; + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + + TFLITE_DCHECK(node->user_data != nullptr); + const OpData& data = *(static_cast(node->user_data)); + + TF_LITE_ENSURE_EQ(context, input->type, output->type); + TF_LITE_ENSURE_MSG( + context, + input->type == filter->type || + (input->type == kTfLiteInt16 && filter->type == kTfLiteInt8), + "Hybrid models are not supported on TFLite Micro."); + + switch (input->type) { // Already know in/out types are same. + case kTfLiteFloat32: { + reference_ops::TransposeConv( + data.params, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + tflite::micro::GetTensorShape(nullptr), nullptr); + break; + } + case kTfLiteInt8: { + int32_t* scratch_buffer = static_cast( + context->GetScratchBuffer(context, data.scratch_buffer_index)); + reference_integer_ops::TransposeConv( + data.params, data.per_channel_output_multiplier, + data.per_channel_output_shift, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + tflite::micro::GetTensorShape(nullptr), nullptr, scratch_buffer); + break; + } + case kTfLiteInt16: { + std::int64_t* scratch_buffer = static_cast( + context->GetScratchBuffer(context, data.scratch_buffer_index)); + // TODO(b/192090531): Remove this once all 8x16 transpose conv models use + // 64-bit biases. + if (bias != nullptr && bias->type == kTfLiteInt16) { + std::int64_t* bias_converted_buffer = + static_cast(context->GetScratchBuffer( + context, data.bias_converted_buffer_index)); + for (int i = 0; i < tflite::micro::GetTensorShape(bias).FlatSize(); + i++) { + bias_converted_buffer[i] = bias->data.i16[i]; + } + reference_integer_ops::TransposeConv( + data.params, data.per_channel_output_multiplier, + data.per_channel_output_shift, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), bias_converted_buffer, + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + tflite::micro::GetTensorShape(nullptr), nullptr, scratch_buffer); + } else { + reference_integer_ops::TransposeConv( + data.params, data.per_channel_output_multiplier, + data.per_channel_output_shift, tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(filter), + tflite::micro::GetTensorData(filter), + tflite::micro::GetTensorShape(bias), + tflite::micro::GetOptionalTensorData(bias), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output), + tflite::micro::GetTensorShape(nullptr), nullptr, scratch_buffer); + } + break; + } + default: + MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type), + input->type); + return kTfLiteError; + } + return kTfLiteOk; +} + +} // namespace + +TfLiteRegistration Register_TRANSPOSE_CONV() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm.cc new file mode 100644 index 000000000..f8b231349 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm.cc @@ -0,0 +1,1387 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/portable_tensor_utils.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/lstm_eval.h" +#include "tensorflow/lite/micro/kernels/lstm_shared.h" +#include "tensorflow/lite/micro/kernels/micro_tensor_utils.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +namespace { + +constexpr int scratch_index_size = 12; + +struct UnidirectionalSequenceLstmOpData { + // If the lstm is layer norm. + bool use_layer_norm; + // The scratch index. + int scratch_index[scratch_index_size]; + + int32_t row_sums_size; + int32_t* row_sums; + bool compute_row_sums = false; + + int32_t input_zero_point; + int32_t output_state_zero_point; + + IntegerLstmParameter integer_lstm_param; +}; + +TfLiteStatus PopulateQuantizedLstmParams8x8_16( + TfLiteContext* context, TfLiteNode* node, + IntegerLstmParameter* integer_lstm_param) { + MicroContext* micro_context = GetMicroContext(context); + + // Calculate quantized clip for projection and cell. + const auto* params = + static_cast(node->builtin_data); + const float cell_clip = params->cell_clip; + const float proj_clip = params->proj_clip; + + TfLiteTensor* cell_state = + micro_context->AllocateTempInputTensor(node, kLstmCellStateTensor); + TF_LITE_ENSURE(context, cell_state != nullptr); + TF_LITE_ENSURE(context, cell_state->is_variable); + TfLiteTensor* output_tensor = + micro_context->AllocateTempOutputTensor(node, kLstmOutputTensor); + + TF_LITE_ENSURE(context, + cell_state->quantization.type != kTfLiteNoQuantization); + auto* cell_state_params = + static_cast(cell_state->quantization.params); + TF_LITE_ENSURE(context, + output_tensor->quantization.type != kTfLiteNoQuantization); + auto* proj_params = static_cast( + output_tensor->quantization.params); + if (cell_clip > 0.0f) { + integer_lstm_param->quantized_cell_clip = static_cast(std::min( + std::max(cell_clip / cell_state_params->scale->data[0], -32768.0f), + 32767.0f)); + } else { + integer_lstm_param->quantized_cell_clip = 0; + } + if (proj_clip > 0.0f) { + integer_lstm_param->quantized_proj_clip = static_cast(std::min( + std::max(proj_clip / proj_params->scale->data[0], -128.0f), 127.0f)); + } else { + integer_lstm_param->quantized_proj_clip = 0; + } + + // Calculate effective scales. + UnidirectionalSequenceLstmOpData* op_data = + static_cast(node->user_data); + const bool use_layer_norm = op_data->use_layer_norm; + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kLstmInputTensor); + + TfLiteTensor* input_to_input_weights = micro_context->AllocateTempInputTensor( + node, kLstmInputToInputWeightsTensor); + TfLiteTensor* input_to_forget_weights = + micro_context->AllocateTempInputTensor(node, + kLstmInputToForgetWeightsTensor); + TfLiteTensor* input_to_cell_weights = micro_context->AllocateTempInputTensor( + node, kLstmInputToCellWeightsTensor); + TfLiteTensor* input_to_output_weights = + micro_context->AllocateTempInputTensor(node, + kLstmInputToOutputWeightsTensor); + + TfLiteTensor* recurrent_to_input_weights = + micro_context->AllocateTempInputTensor( + node, kLstmRecurrentToInputWeightsTensor); + TfLiteTensor* recurrent_to_forget_weights = + micro_context->AllocateTempInputTensor( + node, kLstmRecurrentToForgetWeightsTensor); + TfLiteTensor* recurrent_to_cell_weights = + micro_context->AllocateTempInputTensor(node, + kLstmRecurrentToCellWeightsTensor); + TfLiteTensor* recurrent_to_output_weights = + micro_context->AllocateTempInputTensor( + node, kLstmRecurrentToOutputWeightsTensor); + + TfLiteTensor* cell_to_input_weights = micro_context->AllocateTempInputTensor( + node, kLstmCellToInputWeightsTensor); + TfLiteTensor* cell_to_forget_weights = micro_context->AllocateTempInputTensor( + node, kLstmCellToForgetWeightsTensor); + TfLiteTensor* cell_to_output_weights = micro_context->AllocateTempInputTensor( + node, kLstmCellToOutputWeightsTensor); + + TfLiteTensor* input_layer_norm_coefficients = + micro_context->AllocateTempInputTensor( + node, kLstmInputLayerNormCoefficientsTensor); + TfLiteTensor* forget_layer_norm_coefficients = + micro_context->AllocateTempInputTensor( + node, kLstmForgetLayerNormCoefficientsTensor); + TfLiteTensor* cell_layer_norm_coefficients = + micro_context->AllocateTempInputTensor( + node, kLstmCellLayerNormCoefficientsTensor); + TfLiteTensor* output_layer_norm_coefficients = + micro_context->AllocateTempInputTensor( + node, kLstmOutputLayerNormCoefficientsTensor); + + TfLiteTensor* projection_weights = micro_context->AllocateTempInputTensor( + node, kLstmProjectionWeightsTensor); + + TfLiteTensor* output_state = + micro_context->AllocateTempInputTensor(node, kLstmOutputStateTensor); + TF_LITE_ENSURE(context, output_state != nullptr); + TF_LITE_ENSURE(context, output_state->is_variable); + + // Since we have already checked that weights are all there or none, we can + // check the existence of only one to get the condition. + const bool use_cifg = (input_to_input_weights == nullptr); + const bool use_peephole = (cell_to_output_weights != nullptr); + const bool use_projection = (projection_weights != nullptr); + + // Get intermediate scales and zero points. + float intermediate_scale[5]; + int32_t intermediate_zp[5]; + for (int i = 0; i < 4; ++i) { + if (use_layer_norm) { + TfLiteTensor* intermediate = + micro_context->AllocateTempIntermediateTensor(node, i); + TF_LITE_ENSURE(context, + intermediate->quantization.type != kTfLiteNoQuantization); + auto* params_intermediate = static_cast( + intermediate->quantization.params); + intermediate_scale[i] = params_intermediate->scale->data[0]; + intermediate_zp[i] = params_intermediate->zero_point->data[0]; + if (intermediate != nullptr) { + micro_context->DeallocateTempTfLiteTensor(intermediate); + } + } else { + // Q3.12 for activation functions. + intermediate_scale[i] = std::pow(2.0f, -12.0f); + intermediate_zp[i] = 0; + } + } + // In the absence of projection, hidden becomes otuput and this intermediate + // is ignored. + TfLiteTensor* hidden = micro_context->AllocateTempIntermediateTensor(node, 4); + TF_LITE_ENSURE(context, hidden->quantization.type != kTfLiteNoQuantization); + auto* hidden_params = + static_cast(hidden->quantization.params); + intermediate_scale[4] = hidden_params->scale->data[0]; + intermediate_zp[4] = hidden_params->zero_point->data[0]; + if (hidden != nullptr) { + micro_context->DeallocateTempTfLiteTensor(hidden); + } + + // Scales. + const float default_scale = 1.0; + float input_scale = default_scale; + float input_to_input_weight_scale = default_scale; + float recurrent_to_input_weight_scale = default_scale; + float cell_to_input_weight_scale = default_scale; + float input_to_forget_weight_scale = default_scale; + float recurrent_to_forget_weight_scale = default_scale; + float cell_to_forget_weight_scale = default_scale; + float input_to_cell_weight_scale = default_scale; + float recurrent_to_cell_weight_scale = default_scale; + float input_to_output_weight_scale = default_scale; + float recurrent_to_output_weight_scale = default_scale; + float cell_to_output_weight_scale = default_scale; + float projection_weight_scale = default_scale; + float layer_norm_input_scale = default_scale; + float layer_norm_forget_scale = default_scale; + float layer_norm_cell_scale = default_scale; + float layer_norm_output_scale = default_scale; + float output_state_scale = default_scale; + int cell_scale = 1; + + // Effective scales. + float effective_input_to_input_scale = default_scale; + float effective_recurrent_to_input_scale = default_scale; + float effective_cell_to_input_scale = default_scale; + float effective_input_to_forget_scale = default_scale; + float effective_recurrent_to_forget_scale = default_scale; + float effective_cell_to_forget_scale = default_scale; + float effective_input_to_cell_scale = default_scale; + float effective_recurrent_to_cell_scale = default_scale; + float effective_input_to_output_scale = default_scale; + float effective_recurrent_to_output_scale = default_scale; + float effective_cell_to_output_scale = default_scale; + float effective_proj_scale = default_scale; + float effective_hidden_scale = default_scale; + + // Populate scales. + if (!use_cifg) { + input_to_input_weight_scale = input_to_input_weights->params.scale; + recurrent_to_input_weight_scale = recurrent_to_input_weights->params.scale; + } + + if (use_peephole) { + if (!use_cifg) { + cell_to_input_weight_scale = cell_to_input_weights->params.scale; + } + cell_to_forget_weight_scale = cell_to_forget_weights->params.scale; + cell_to_output_weight_scale = cell_to_output_weights->params.scale; + } + + if (use_layer_norm) { + if (!use_cifg) { + layer_norm_input_scale = input_layer_norm_coefficients->params.scale; + } + layer_norm_forget_scale = forget_layer_norm_coefficients->params.scale; + layer_norm_cell_scale = cell_layer_norm_coefficients->params.scale; + layer_norm_output_scale = output_layer_norm_coefficients->params.scale; + } + + if (use_projection) { + projection_weight_scale = projection_weights->params.scale; + } + output_state_scale = output_state->params.scale; + + input_to_forget_weight_scale = input_to_forget_weights->params.scale; + input_to_cell_weight_scale = input_to_cell_weights->params.scale; + input_to_output_weight_scale = input_to_output_weights->params.scale; + recurrent_to_forget_weight_scale = recurrent_to_forget_weights->params.scale; + recurrent_to_cell_weight_scale = recurrent_to_cell_weights->params.scale; + recurrent_to_output_weight_scale = recurrent_to_output_weights->params.scale; + + // Check cell state (already used above) + TF_LITE_ENSURE(context, CheckedLog2(cell_state->params.scale, &cell_scale)); + // TF_LITE_ENSURE(context, cell_scale <= -9); + integer_lstm_param->cell_scale = cell_scale; + input_scale = input->params.scale; + + // Calculate effective scales. + if (!use_cifg) { + effective_input_to_input_scale = + input_to_input_weight_scale * input_scale / intermediate_scale[0]; + effective_recurrent_to_input_scale = recurrent_to_input_weight_scale * + output_state_scale / + intermediate_scale[0]; + } + effective_input_to_forget_scale = + input_to_forget_weight_scale * input_scale / intermediate_scale[1]; + effective_recurrent_to_forget_scale = recurrent_to_forget_weight_scale * + output_state_scale / + intermediate_scale[1]; + + effective_input_to_cell_scale = + input_to_cell_weight_scale * input_scale / intermediate_scale[2]; + effective_recurrent_to_cell_scale = recurrent_to_cell_weight_scale * + output_state_scale / + intermediate_scale[2]; + + effective_input_to_output_scale = + input_to_output_weight_scale * input_scale / intermediate_scale[3]; + effective_recurrent_to_output_scale = recurrent_to_output_weight_scale * + output_state_scale / + intermediate_scale[3]; + + effective_hidden_scale = + std::pow(2.0f, -15.0f) / intermediate_scale[4] * std::pow(2.0f, -15.0f); + + effective_proj_scale = + projection_weight_scale * intermediate_scale[4] / output_state_scale; + + if (use_peephole) { + if (!use_cifg) { + effective_cell_to_input_scale = + std::pow(2.0f, static_cast(cell_scale)) * + cell_to_input_weight_scale / intermediate_scale[0]; + } + effective_cell_to_forget_scale = + std::pow(2.0f, static_cast(cell_scale)) * + cell_to_forget_weight_scale / intermediate_scale[1]; + effective_cell_to_output_scale = + std::pow(2.0f, static_cast(cell_scale)) * + cell_to_output_weight_scale / intermediate_scale[3]; + } + + // Decompose scales. + int shift_output; + QuantizeMultiplier(static_cast(effective_input_to_input_scale), + &integer_lstm_param->effective_input_to_input_scale_a, + &shift_output); + integer_lstm_param->effective_input_to_input_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_recurrent_to_input_scale), + &integer_lstm_param->effective_recurrent_to_input_scale_a, + &shift_output); + integer_lstm_param->effective_recurrent_to_input_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_cell_to_input_scale), + &integer_lstm_param->effective_cell_to_input_scale_a, + &shift_output); + integer_lstm_param->effective_cell_to_input_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_input_to_forget_scale), + &integer_lstm_param->effective_input_to_forget_scale_a, + &shift_output); + integer_lstm_param->effective_input_to_forget_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_recurrent_to_forget_scale), + &integer_lstm_param->effective_recurrent_to_forget_scale_a, + &shift_output); + integer_lstm_param->effective_recurrent_to_forget_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_cell_to_forget_scale), + &integer_lstm_param->effective_cell_to_forget_scale_a, + &shift_output); + integer_lstm_param->effective_cell_to_forget_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_input_to_cell_scale), + &integer_lstm_param->effective_input_to_cell_scale_a, + &shift_output); + integer_lstm_param->effective_input_to_cell_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_recurrent_to_cell_scale), + &integer_lstm_param->effective_recurrent_to_cell_scale_a, + &shift_output); + integer_lstm_param->effective_recurrent_to_cell_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_input_to_output_scale), + &integer_lstm_param->effective_input_to_output_scale_a, + &shift_output); + integer_lstm_param->effective_input_to_output_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_recurrent_to_output_scale), + &integer_lstm_param->effective_recurrent_to_output_scale_a, + &shift_output); + integer_lstm_param->effective_recurrent_to_output_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_cell_to_output_scale), + &integer_lstm_param->effective_cell_to_output_scale_a, + &shift_output); + integer_lstm_param->effective_cell_to_output_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_proj_scale), + &integer_lstm_param->effective_proj_scale_a, + &shift_output); + integer_lstm_param->effective_proj_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(effective_hidden_scale), + &integer_lstm_param->effective_hidden_scale_a, + &shift_output); + integer_lstm_param->effective_hidden_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(layer_norm_input_scale), + &integer_lstm_param->layer_norm_input_scale_a, + &shift_output); + integer_lstm_param->layer_norm_input_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(layer_norm_forget_scale), + &integer_lstm_param->layer_norm_forget_scale_a, + &shift_output); + integer_lstm_param->layer_norm_forget_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(layer_norm_cell_scale), + &integer_lstm_param->layer_norm_cell_scale_a, + &shift_output); + integer_lstm_param->layer_norm_cell_scale_b = + static_cast(shift_output); + QuantizeMultiplier(static_cast(layer_norm_output_scale), + &integer_lstm_param->layer_norm_output_scale_a, + &shift_output); + integer_lstm_param->layer_norm_output_scale_b = + static_cast(shift_output); + + integer_lstm_param->hidden_zp = intermediate_zp[4]; + + // 10000 is used to make sure the kernel logic does not overflow. + if (!use_cifg) { + integer_lstm_param->input_variance_guard = + std::max(1, static_cast(10000 * layer_norm_input_scale)); + } + integer_lstm_param->forget_variance_guard = + std::max(1, static_cast(10000 * layer_norm_forget_scale)); + integer_lstm_param->cell_variance_guard = + std::max(1, static_cast(10000 * layer_norm_cell_scale)); + integer_lstm_param->output_variance_guard = + std::max(1, static_cast(10000 * layer_norm_output_scale)); + + if (cell_state != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_state); + } + if (output_tensor != nullptr) { + micro_context->DeallocateTempTfLiteTensor(output_tensor); + } + if (input != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input); + } + if (input_to_input_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_input_weights); + } + if (input_to_forget_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_forget_weights); + } + if (input_to_cell_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_cell_weights); + } + if (input_to_output_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_output_weights); + } + if (recurrent_to_input_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_input_weights); + } + if (recurrent_to_forget_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_forget_weights); + } + if (recurrent_to_cell_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_cell_weights); + } + if (recurrent_to_output_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_output_weights); + } + if (cell_to_input_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_to_input_weights); + } + if (cell_to_forget_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_to_forget_weights); + } + if (cell_to_output_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_to_output_weights); + } + if (input_layer_norm_coefficients != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_layer_norm_coefficients); + } + if (forget_layer_norm_coefficients != nullptr) { + micro_context->DeallocateTempTfLiteTensor(forget_layer_norm_coefficients); + } + if (cell_layer_norm_coefficients != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_layer_norm_coefficients); + } + if (output_layer_norm_coefficients != nullptr) { + micro_context->DeallocateTempTfLiteTensor(output_layer_norm_coefficients); + } + if (projection_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(projection_weights); + } + if (output_state != nullptr) { + micro_context->DeallocateTempTfLiteTensor(output_state); + } + + return kTfLiteOk; +} + +// Temporary buffers used for hybrid mode +enum HybridTempBuffer { + kPrimaryScratchBuffer = 0, + kInputQuantized = 1, + kOutputStateQuantized = 2, + kCellStateQuantized = 3, + kInputScalingFactors = 4, + kOutputStateScalingFactors = 5, + kProductScalingFactors = 6, + kRecoveredCellWeights = 7, + kAccumScratch = 8, + kInputZeroPoints = 9, + kOutputStateZeroPoints = 10, + kScales = 11, + kNumHybridTempBuffers = 12, +}; + +void* UnidirectionalSequenceLstmInit(TfLiteContext* context, const char* buffer, + size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer( + context, sizeof(UnidirectionalSequenceLstmOpData)); +} + +// Check that input tensor dimensions matches with each other. +TfLiteStatus CheckInputTensorDimensions(TfLiteContext* context, + TfLiteNode* node, int n_input, + int n_output, int n_cell, + bool use_layer_norm, bool is_integer) { + MicroContext* micro_context = GetMicroContext(context); + + const auto* params = reinterpret_cast(node->builtin_data); + + // Making sure clipping parameters have valid values. + // == 0 means no clipping + // > 0 means clipping + TF_LITE_ENSURE(context, params->cell_clip >= 0); + TF_LITE_ENSURE(context, params->proj_clip >= 0); + + TfLiteTensor* input_to_input_weights = micro_context->AllocateTempInputTensor( + node, kLstmInputToInputWeightsTensor); + if (input_to_input_weights != nullptr) { + TF_LITE_ENSURE_EQ(context, input_to_input_weights->dims->size, 2); + TF_LITE_ENSURE_EQ(context, input_to_input_weights->dims->data[0], n_cell); + TF_LITE_ENSURE_EQ(context, input_to_input_weights->dims->data[1], n_input); + } + + TfLiteTensor* input_to_forget_weights = + micro_context->AllocateTempInputTensor(node, + kLstmInputToForgetWeightsTensor); + TF_LITE_ENSURE_EQ(context, input_to_forget_weights->dims->size, 2); + TF_LITE_ENSURE_EQ(context, input_to_forget_weights->dims->data[0], n_cell); + TF_LITE_ENSURE_EQ(context, input_to_forget_weights->dims->data[1], n_input); + + TfLiteTensor* input_to_cell_weights = micro_context->AllocateTempInputTensor( + node, kLstmInputToCellWeightsTensor); + TF_LITE_ENSURE_EQ(context, input_to_cell_weights->dims->size, 2); + TF_LITE_ENSURE_EQ(context, input_to_cell_weights->dims->data[0], n_cell); + TF_LITE_ENSURE_EQ(context, input_to_cell_weights->dims->data[1], n_input); + + TfLiteTensor* recurrent_to_input_weights = + micro_context->AllocateTempInputTensor( + node, kLstmRecurrentToInputWeightsTensor); + if (recurrent_to_input_weights != nullptr) { + TF_LITE_ENSURE_EQ(context, recurrent_to_input_weights->dims->size, 2); + TF_LITE_ENSURE_EQ(context, recurrent_to_input_weights->dims->data[0], + n_cell); + TF_LITE_ENSURE_EQ(context, recurrent_to_input_weights->dims->data[1], + n_output); + } + + TfLiteTensor* recurrent_to_forget_weights = + micro_context->AllocateTempInputTensor( + node, kLstmRecurrentToForgetWeightsTensor); + TF_LITE_ENSURE_EQ(context, recurrent_to_forget_weights->dims->size, 2); + TF_LITE_ENSURE_EQ(context, recurrent_to_forget_weights->dims->data[0], + n_cell); + TF_LITE_ENSURE_EQ(context, recurrent_to_forget_weights->dims->data[1], + n_output); + + TfLiteTensor* recurrent_to_cell_weights = + micro_context->AllocateTempInputTensor(node, + kLstmRecurrentToCellWeightsTensor); + TF_LITE_ENSURE_EQ(context, recurrent_to_cell_weights->dims->size, 2); + TF_LITE_ENSURE_EQ(context, recurrent_to_cell_weights->dims->data[0], n_cell); + TF_LITE_ENSURE_EQ(context, recurrent_to_cell_weights->dims->data[1], + n_output); + + // We make sure the input-gate's parameters are either both present (regular + // LSTM) or not at all (CIFG-LSTM). + const bool cifg_weights_all_or_none = + ((input_to_input_weights != nullptr) && + (recurrent_to_input_weights != nullptr)) || + ((input_to_input_weights == nullptr) && + (recurrent_to_input_weights == nullptr)); + TF_LITE_ENSURE(context, cifg_weights_all_or_none == true); + + TfLiteTensor* cell_to_input_weights = micro_context->AllocateTempInputTensor( + node, kLstmCellToInputWeightsTensor); + if (cell_to_input_weights != nullptr) { + TF_LITE_ENSURE_EQ(context, cell_to_input_weights->dims->size, 1); + TF_LITE_ENSURE_EQ(context, cell_to_input_weights->dims->data[0], n_cell); + TF_LITE_ENSURE_TYPES_EQ( + context, cell_to_input_weights->type, + is_integer ? kTfLiteInt16 : input_to_forget_weights->type); + } + + TfLiteTensor* cell_to_forget_weights = micro_context->AllocateTempInputTensor( + node, kLstmCellToForgetWeightsTensor); + if (cell_to_forget_weights != nullptr) { + TF_LITE_ENSURE_EQ(context, cell_to_forget_weights->dims->size, 1); + TF_LITE_ENSURE_EQ(context, cell_to_forget_weights->dims->data[0], n_cell); + TF_LITE_ENSURE_TYPES_EQ( + context, cell_to_forget_weights->type, + is_integer ? kTfLiteInt16 : input_to_forget_weights->type); + } + + TfLiteTensor* cell_to_output_weights = micro_context->AllocateTempInputTensor( + node, kLstmCellToOutputWeightsTensor); + if (cell_to_output_weights != nullptr) { + TF_LITE_ENSURE_EQ(context, cell_to_output_weights->dims->size, 1); + TF_LITE_ENSURE_EQ(context, cell_to_output_weights->dims->data[0], n_cell); + TF_LITE_ENSURE_TYPES_EQ( + context, cell_to_output_weights->type, + is_integer ? kTfLiteInt16 : input_to_forget_weights->type); + } + + // Making sure the peephole weights are there all or none. + const bool use_cifg = (input_to_input_weights == nullptr); + const bool peephole_weights_all_or_none = + ((cell_to_input_weights != nullptr || use_cifg) && + (cell_to_forget_weights != nullptr) && + (cell_to_output_weights != nullptr)) || + ((cell_to_input_weights == nullptr) && + (cell_to_forget_weights == nullptr) && + (cell_to_output_weights == nullptr)); + TF_LITE_ENSURE(context, peephole_weights_all_or_none == true); + + // Make sure the input gate bias is present only when not a CIFG-LSTM. + TfLiteTensor* input_gate_bias = + micro_context->AllocateTempInputTensor(node, kLstmInputGateBiasTensor); + if (use_cifg) { + TF_LITE_ENSURE_EQ(context, input_gate_bias, nullptr); + } else { + TF_LITE_ENSURE_EQ(context, input_gate_bias->dims->size, 1); + TF_LITE_ENSURE_EQ(context, input_gate_bias->dims->data[0], n_cell); + if (is_integer) { + TF_LITE_ENSURE_TYPES_EQ(context, input_gate_bias->type, kTfLiteInt32); + } else { + TF_LITE_ENSURE_TYPES_EQ(context, input_gate_bias->type, kTfLiteFloat32); + } + } + + TfLiteTensor* forget_gate_bias = + micro_context->AllocateTempInputTensor(node, kLstmForgetGateBiasTensor); + TF_LITE_ENSURE_EQ(context, forget_gate_bias->dims->size, 1); + TF_LITE_ENSURE_EQ(context, forget_gate_bias->dims->data[0], n_cell); + if (is_integer) { + TF_LITE_ENSURE_TYPES_EQ(context, forget_gate_bias->type, kTfLiteInt32); + } else { + TF_LITE_ENSURE_TYPES_EQ(context, forget_gate_bias->type, kTfLiteFloat32); + } + + TfLiteTensor* cell_gate_bias = + micro_context->AllocateTempInputTensor(node, kLstmCellGateBiasTensor); + TF_LITE_ENSURE_EQ(context, cell_gate_bias->dims->size, 1); + TF_LITE_ENSURE_EQ(context, cell_gate_bias->dims->data[0], n_cell); + if (is_integer) { + TF_LITE_ENSURE_TYPES_EQ(context, cell_gate_bias->type, kTfLiteInt32); + } else { + TF_LITE_ENSURE_TYPES_EQ(context, cell_gate_bias->type, kTfLiteFloat32); + } + + TfLiteTensor* output_gate_bias = + micro_context->AllocateTempInputTensor(node, kLstmOutputGateBiasTensor); + TF_LITE_ENSURE_EQ(context, output_gate_bias->dims->size, 1); + TF_LITE_ENSURE_EQ(context, output_gate_bias->dims->data[0], n_cell); + if (is_integer) { + TF_LITE_ENSURE_TYPES_EQ(context, output_gate_bias->type, kTfLiteInt32); + } else { + TF_LITE_ENSURE_TYPES_EQ(context, output_gate_bias->type, kTfLiteFloat32); + } + + TfLiteTensor* projection_weights = micro_context->AllocateTempInputTensor( + node, kLstmProjectionWeightsTensor); + if (projection_weights != nullptr) { + TF_LITE_ENSURE_EQ(context, projection_weights->dims->size, 2); + TF_LITE_ENSURE_EQ(context, projection_weights->dims->data[0], n_output); + TF_LITE_ENSURE_EQ(context, projection_weights->dims->data[1], n_cell); + } + + TfLiteTensor* projection_bias = + micro_context->AllocateTempInputTensor(node, kLstmProjectionBiasTensor); + if (projection_bias != nullptr) { + TF_LITE_ENSURE_EQ(context, projection_bias->dims->size, 1); + TF_LITE_ENSURE_EQ(context, projection_bias->dims->data[0], n_output); + if (is_integer) { + TF_LITE_ENSURE_TYPES_EQ(context, projection_bias->type, kTfLiteInt32); + } else { + TF_LITE_ENSURE_TYPES_EQ(context, projection_bias->type, kTfLiteFloat32); + } + } + + // Making sure the projection tensors are consistent: + // 1) If projection weight is not present, then projection bias should not be + // present. + // 2) If projection weight is present, then projection bias is optional. + const bool projecton_tensors_consistent = + ((projection_weights != nullptr) || (projection_bias == nullptr)); + TF_LITE_ENSURE(context, projecton_tensors_consistent == true); + + if (use_layer_norm) { + TfLiteTensor* input_layer_norm_coefficients = + micro_context->AllocateTempInputTensor( + node, kLstmInputLayerNormCoefficientsTensor); + if (use_cifg) { + TF_LITE_ENSURE_EQ(context, input_layer_norm_coefficients, nullptr); + } else { + TF_LITE_ENSURE(context, input_layer_norm_coefficients != nullptr); + TF_LITE_ENSURE_EQ(context, input_layer_norm_coefficients->dims->size, 1); + TF_LITE_ENSURE_EQ(context, input_layer_norm_coefficients->dims->data[0], + n_cell); + if (is_integer) { + TF_LITE_ENSURE_TYPES_EQ(context, input_layer_norm_coefficients->type, + kTfLiteInt16); + } else { + TF_LITE_ENSURE_TYPES_EQ(context, input_layer_norm_coefficients->type, + kTfLiteFloat32); + } + } + + TfLiteTensor* forget_layer_norm_coefficients = + micro_context->AllocateTempInputTensor( + node, kLstmForgetLayerNormCoefficientsTensor); + TF_LITE_ENSURE_EQ(context, forget_layer_norm_coefficients->dims->size, 1); + TF_LITE_ENSURE_EQ(context, forget_layer_norm_coefficients->dims->data[0], + n_cell); + if (is_integer) { + TF_LITE_ENSURE_TYPES_EQ(context, forget_layer_norm_coefficients->type, + kTfLiteInt16); + } else { + TF_LITE_ENSURE_TYPES_EQ(context, forget_layer_norm_coefficients->type, + kTfLiteFloat32); + } + + TfLiteTensor* cell_layer_norm_coefficients = + micro_context->AllocateTempInputTensor( + node, kLstmCellLayerNormCoefficientsTensor); + TF_LITE_ENSURE_EQ(context, cell_layer_norm_coefficients->dims->size, 1); + TF_LITE_ENSURE_EQ(context, cell_layer_norm_coefficients->dims->data[0], + n_cell); + if (is_integer) { + TF_LITE_ENSURE_TYPES_EQ(context, cell_layer_norm_coefficients->type, + kTfLiteInt16); + } else { + TF_LITE_ENSURE_TYPES_EQ(context, cell_layer_norm_coefficients->type, + kTfLiteFloat32); + } + + TfLiteTensor* output_layer_norm_coefficients = + micro_context->AllocateTempInputTensor( + node, kLstmOutputLayerNormCoefficientsTensor); + TF_LITE_ENSURE_EQ(context, output_layer_norm_coefficients->dims->size, 1); + TF_LITE_ENSURE_EQ(context, output_layer_norm_coefficients->dims->data[0], + n_cell); + if (is_integer) { + TF_LITE_ENSURE_TYPES_EQ(context, output_layer_norm_coefficients->type, + kTfLiteInt16); + } else { + TF_LITE_ENSURE_TYPES_EQ(context, output_layer_norm_coefficients->type, + kTfLiteFloat32); + } + if (input_layer_norm_coefficients != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_layer_norm_coefficients); + } + if (forget_layer_norm_coefficients != nullptr) { + micro_context->DeallocateTempTfLiteTensor(forget_layer_norm_coefficients); + } + if (cell_layer_norm_coefficients != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_layer_norm_coefficients); + } + if (output_layer_norm_coefficients != nullptr) { + micro_context->DeallocateTempTfLiteTensor(output_layer_norm_coefficients); + } + } + + if (input_to_input_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_input_weights); + } + if (input_to_forget_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_forget_weights); + } + if (input_to_cell_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_cell_weights); + } + if (recurrent_to_input_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_input_weights); + } + if (recurrent_to_forget_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_forget_weights); + } + micro_context->DeallocateTempTfLiteTensor(recurrent_to_cell_weights); + if (cell_to_input_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_to_input_weights); + } + if (cell_to_forget_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_to_forget_weights); + } + if (cell_to_output_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_to_output_weights); + } + if (input_gate_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_gate_bias); + } + if (forget_gate_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(forget_gate_bias); + } + if (cell_gate_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_gate_bias); + } + if (output_gate_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(output_gate_bias); + } + if (projection_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(projection_weights); + } + if (projection_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(projection_bias); + } + + return kTfLiteOk; +} + +TfLiteStatus PrecomputeZeroPointTimesWeightWithBias( + TfLiteContext* context, int32_t zero_point, + const TfLiteTensor* weight_tensor, const TfLiteTensor* bias_tensor, + int32_t** output) { + if (weight_tensor == nullptr) { + return kTfLiteOk; + } + + const RuntimeShape& weight_shape = GetTensorShape(weight_tensor); + TF_LITE_ENSURE_EQ(context, weight_shape.DimensionsCount(), 2); + const int row = weight_shape.Dims(0); + const int col = weight_shape.Dims(1); + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + *output = static_cast( + context->AllocatePersistentBuffer(context, row * sizeof(int32_t))); + + if (bias_tensor == nullptr) { + memset(*output, 0, row * sizeof(int32_t)); + } else { + const int32_t* bias = GetTensorData(bias_tensor); + memcpy(*output, bias, row * sizeof(int32_t)); + } + if (zero_point != 0) { + const int8_t* weight = GetTensorData(weight_tensor); + tflite::tensor_utils::MatrixScalarMultiplyAccumulate(weight, zero_point, + row, col, *output); + } + return kTfLiteOk; +} + +TfLiteStatus PopulatePrecomputedZPTimesWeightsWithBias( + TfLiteContext* context, UnidirectionalSequenceLstmOpData* op_data, + TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kLstmInputTensor); + TfLiteTensor* output_state = + micro_context->AllocateTempInputTensor(node, kLstmOutputStateTensor); + TF_LITE_ENSURE(context, output_state != nullptr); + TF_LITE_ENSURE(context, output_state->is_variable); + + const int32_t input_zero_point = -input->params.zero_point; + const int32_t output_state_zero_point = -output_state->params.zero_point; + + TfLiteTensor* input_to_input_weights = micro_context->AllocateTempInputTensor( + node, kLstmInputToInputWeightsTensor); + TfLiteTensor* input_to_forget_weights = + micro_context->AllocateTempInputTensor(node, + kLstmInputToForgetWeightsTensor); + TfLiteTensor* input_to_cell_weights = micro_context->AllocateTempInputTensor( + node, kLstmInputToCellWeightsTensor); + TfLiteTensor* input_to_output_weights = + micro_context->AllocateTempInputTensor(node, + kLstmInputToOutputWeightsTensor); + + TfLiteTensor* recurrent_to_input_weights = + micro_context->AllocateTempInputTensor( + node, kLstmRecurrentToInputWeightsTensor); + TfLiteTensor* recurrent_to_forget_weights = + micro_context->AllocateTempInputTensor( + node, kLstmRecurrentToForgetWeightsTensor); + TfLiteTensor* recurrent_to_cell_weights = + micro_context->AllocateTempInputTensor(node, + kLstmRecurrentToCellWeightsTensor); + TfLiteTensor* recurrent_to_output_weights = + micro_context->AllocateTempInputTensor( + node, kLstmRecurrentToOutputWeightsTensor); + + TfLiteTensor* projection_weights = micro_context->AllocateTempInputTensor( + node, kLstmProjectionWeightsTensor); + TfLiteTensor* projection_bias = + micro_context->AllocateTempInputTensor(node, kLstmProjectionBiasTensor); + + IntegerLstmParameter* integer_lstm_params = &op_data->integer_lstm_param; + + TfLiteTensor* intermediate = + micro_context->AllocateTempIntermediateTensor(node, 4); + TF_LITE_ENSURE(context, + intermediate->quantization.type != kTfLiteNoQuantization); + const auto* params = + static_cast(intermediate->quantization.params); + const int32_t hidden_zp = params->zero_point->data[0]; + + // Get bias and perform zero point calculation. + // When there is layer normalization, the gate bias does not apply to matmul + // directly: + // y = ln(w * x + w * r + w * c) + b. + const bool is_layer_norm = op_data->use_layer_norm; + + // Forget gate. + TfLiteTensor* forget_gate_bias = is_layer_norm + ? nullptr + : micro_context->AllocateTempInputTensor( + node, kLstmForgetGateBiasTensor); + TF_LITE_ENSURE_OK( + context, + PrecomputeZeroPointTimesWeightWithBias( + context, input_zero_point, input_to_forget_weights, forget_gate_bias, + &(integer_lstm_params->input_to_forget_effective_bias))); + + TF_LITE_ENSURE_OK( + context, + PrecomputeZeroPointTimesWeightWithBias( + context, output_state_zero_point, recurrent_to_forget_weights, + nullptr, &(integer_lstm_params->recurrent_to_forget_effective_bias))); + + // Modulation gate. + TfLiteTensor* cell_gate_bias = is_layer_norm + ? nullptr + : micro_context->AllocateTempInputTensor( + node, kLstmCellGateBiasTensor); + TF_LITE_ENSURE_OK( + context, + PrecomputeZeroPointTimesWeightWithBias( + context, input_zero_point, input_to_cell_weights, cell_gate_bias, + &(integer_lstm_params->input_to_cell_effective_bias))); + TF_LITE_ENSURE_OK( + context, + PrecomputeZeroPointTimesWeightWithBias( + context, output_state_zero_point, recurrent_to_cell_weights, nullptr, + &(integer_lstm_params->recurrent_to_cell_effective_bias))); + + // Output gate. + TfLiteTensor* output_gate_bias = is_layer_norm + ? nullptr + : micro_context->AllocateTempInputTensor( + node, kLstmOutputGateBiasTensor); + TF_LITE_ENSURE_OK( + context, + PrecomputeZeroPointTimesWeightWithBias( + context, input_zero_point, input_to_output_weights, output_gate_bias, + &(integer_lstm_params->input_to_output_effective_bias))); + + TF_LITE_ENSURE_OK( + context, + PrecomputeZeroPointTimesWeightWithBias( + context, output_state_zero_point, recurrent_to_output_weights, + nullptr, &(integer_lstm_params->recurrent_to_output_effective_bias))); + + // Input gate. The calculation is only meaningful for non-cifg case. + TfLiteTensor* input_gate_bias = is_layer_norm + ? nullptr + : micro_context->AllocateTempInputTensor( + node, kLstmInputGateBiasTensor); + TF_LITE_ENSURE_OK( + context, + PrecomputeZeroPointTimesWeightWithBias( + context, input_zero_point, input_to_input_weights, input_gate_bias, + &(integer_lstm_params->input_to_input_effective_bias))); + TF_LITE_ENSURE_OK( + context, + PrecomputeZeroPointTimesWeightWithBias( + context, output_state_zero_point, recurrent_to_input_weights, nullptr, + &(integer_lstm_params->recurrent_to_input_effective_bias))); + + // Projection bias. The calculation is only meaningful for with projection. + TF_LITE_ENSURE_OK(context, + PrecomputeZeroPointTimesWeightWithBias( + context, hidden_zp, projection_weights, projection_bias, + &(integer_lstm_params->projection_effective_bias))); + + if (input != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input); + } + if (output_state != nullptr) { + micro_context->DeallocateTempTfLiteTensor(output_state); + } + if (input_to_input_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_input_weights); + } + if (input_to_forget_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_forget_weights); + } + if (input_to_cell_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_cell_weights); + } + if (input_to_output_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_output_weights); + } + if (recurrent_to_input_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_input_weights); + } + if (recurrent_to_forget_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_forget_weights); + } + if (recurrent_to_cell_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_cell_weights); + } + if (recurrent_to_output_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_output_weights); + } + if (projection_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(projection_weights); + } + if (projection_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(projection_bias); + } + if (forget_gate_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(forget_gate_bias); + } + if (cell_gate_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_gate_bias); + } + if (output_gate_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(output_gate_bias); + } + if (input_gate_bias != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_gate_bias); + } + + if (intermediate != nullptr) { + micro_context->DeallocateTempTfLiteTensor(intermediate); + } + + return kTfLiteOk; +} + +// Resize the output and state tensors based on the sizes of the input tensors. +// Allocate a temporary scratch tensor. Also check that the sizes of the input +// tensors match each other. +TfLiteStatus UnidirectionalSequenceLstmPrepare(TfLiteContext* context, + TfLiteNode* node) { + UnidirectionalSequenceLstmOpData* op_data = + reinterpret_cast(node->user_data); + + MicroContext* micro_context = GetMicroContext(context); + + // Check we have all the inputs and outputs we need. + bool use_layer_norm = false; + if (node->inputs->size == 24) { + TfLiteTensor* forget_layer_norm_coefficients = + micro_context->AllocateTempInputTensor( + node, kLstmForgetLayerNormCoefficientsTensor); + if (forget_layer_norm_coefficients == nullptr) { + use_layer_norm = false; + } else { + use_layer_norm = true; + } + if (forget_layer_norm_coefficients != nullptr) { + micro_context->DeallocateTempTfLiteTensor(forget_layer_norm_coefficients); + } + } else if (node->inputs->size == 20) { + // This is deprecated and is only kept here for backward compatibility. + use_layer_norm = false; + } else { + MicroPrintf("The LSTM Full kernel expects 20 or 24 inputs. Got %d inputs", + node->inputs->size); + return kTfLiteError; + } + TF_LITE_ENSURE_EQ(context, node->outputs->size, 1); + op_data->use_layer_norm = use_layer_norm; + + // Inferring batch size, number of outputs and sequence length and + // number of cells from the input tensors. + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kLstmInputTensor); + op_data->input_zero_point = input->params.zero_point; + const bool is_integer = input->type == kTfLiteInt8; + TF_LITE_ENSURE(context, input->dims->size > 1); + const auto* params = + reinterpret_cast( + node->builtin_data); + const bool time_major = params->time_major; + const int n_batch = time_major ? input->dims->data[1] : input->dims->data[0]; + const int n_input = input->dims->data[2]; + + TfLiteTensor* input_to_output_weights = + micro_context->AllocateTempInputTensor(node, + kLstmInputToOutputWeightsTensor); + const int n_cell = input_to_output_weights->dims->data[0]; + TF_LITE_ENSURE_EQ(context, input_to_output_weights->dims->size, 2); + TF_LITE_ENSURE_EQ(context, input_to_output_weights->dims->data[1], n_input); + + TfLiteTensor* recurrent_to_output_weights = + micro_context->AllocateTempInputTensor( + node, kLstmRecurrentToOutputWeightsTensor); + TF_LITE_ENSURE_EQ(context, recurrent_to_output_weights->dims->size, 2); + TF_LITE_ENSURE_EQ(context, recurrent_to_output_weights->dims->data[0], + n_cell); + const int n_output = recurrent_to_output_weights->dims->data[1]; + + // Check that input tensor dimensions matches with each other. + TF_LITE_ENSURE_OK( + context, CheckInputTensorDimensions(context, node, n_input, n_output, + n_cell, use_layer_norm, is_integer)); + + // Get the pointer to output, output_state and cell_state buffer tensors. + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kLstmOutputTensor); + + TfLiteTensor* output_state = + micro_context->AllocateTempInputTensor(node, kLstmOutputStateTensor); + TF_LITE_ENSURE(context, output_state != nullptr); + TF_LITE_ENSURE(context, output_state->is_variable); + op_data->output_state_zero_point = output_state->params.zero_point; + TfLiteTensor* cell_state = + micro_context->AllocateTempInputTensor(node, kLstmCellStateTensor); + TF_LITE_ENSURE(context, cell_state != nullptr); + TF_LITE_ENSURE(context, cell_state->is_variable); + + // Check the shape of input state tensors. + // These tensor may be 1D or 2D. It's fine as long as the total size is + // correct. + TF_LITE_ENSURE_EQ(context, NumElements(output_state), n_batch * n_output); + TF_LITE_ENSURE_EQ(context, NumElements(cell_state), n_batch * n_cell); + + // Check the shape of output tensor against that of input tensor + TF_LITE_ENSURE_EQ(context, output->dims->size, 3); + TF_LITE_ENSURE_EQ(context, input->dims->data[0], output->dims->data[0]); + TF_LITE_ENSURE_EQ(context, input->dims->data[1], output->dims->data[1]); + TF_LITE_ENSURE_EQ(context, output->dims->data[2], n_output); + + if (is_integer) { + const int num_intermediate_tensors = node->intermediates->size; + TF_LITE_ENSURE(context, num_intermediate_tensors == 5); + } + + TfLiteTensor* input_to_input_weights = micro_context->AllocateTempInputTensor( + node, kLstmInputToInputWeightsTensor); + + const bool use_cifg = (input_to_input_weights == nullptr); + + // Create a primary scratch buffer for hybrid and float + // If is_integer, primary scratch buffer has a different size + if (!is_integer) { + int scratch_buffer_size[2]; + scratch_buffer_size[0] = n_batch; + + if (use_cifg) { + // Reserving space for Cell, Forget, Output gates + scratch_buffer_size[1] = n_cell * 3; + } else { + // Reserving space for Input, Cell, Forget, Output gates + scratch_buffer_size[1] = n_cell * 4; + } + + TF_LITE_ENSURE_OK(context, + context->RequestScratchBufferInArena( + context, + scratch_buffer_size[0] * scratch_buffer_size[1] * + TfLiteTypeGetSize(input->type), + &(op_data->scratch_index[kPrimaryScratchBuffer]))); + } + + if (is_integer) { + // Integer UnidirectionalSequenceLSTM prepare function for 8x8->16. + // This code path needs 5 intermediate tensors per Op. + // Populate quantization parameters. + PopulateQuantizedLstmParams8x8_16(context, node, + &op_data->integer_lstm_param); + // Allocate scratch buffer. Need 4 16-bit buffer with size n_batch * n_cell + // and 1 8-bit buffer with size n_batch * n_cell. For integer + // UnidirectionalSequenceLSTM, we do not need the extra 32-bit buffer. + for (int i = 0; i < 5; ++i) { + TfLiteType buffer_type = kTfLiteInt16; + + if (i == 4) { + buffer_type = kTfLiteInt8; + } + + TF_LITE_ENSURE_OK( + context, + context->RequestScratchBufferInArena( + context, n_batch * n_cell * TfLiteTypeGetSize(buffer_type), + &(op_data->scratch_index[i]))); + } + + // Populate precomputed zp * weight. + TF_LITE_ENSURE_OK(context, PopulatePrecomputedZPTimesWeightsWithBias( + context, op_data, node)); + } + + if (input != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input); + } + if (input_to_output_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_output_weights); + } + if (recurrent_to_output_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(recurrent_to_output_weights); + } + if (output != nullptr) { + micro_context->DeallocateTempTfLiteTensor(output); + } + if (output_state != nullptr) { + micro_context->DeallocateTempTfLiteTensor(output_state); + } + if (cell_state != nullptr) { + micro_context->DeallocateTempTfLiteTensor(cell_state); + } + + if (input_to_input_weights != nullptr) { + micro_context->DeallocateTempTfLiteTensor(input_to_input_weights); + } + return kTfLiteOk; +} + +TfLiteStatus UnidirectionalSequenceLstmEval(TfLiteContext* context, + TfLiteNode* node) { + TFLITE_DCHECK(context->GetScratchBuffer != nullptr); + + const auto* params = + reinterpret_cast( + node->builtin_data); + const UnidirectionalSequenceLstmOpData* op_data = + reinterpret_cast(node->user_data); + const bool use_layer_norm = op_data->use_layer_norm; + const bool time_major = params->time_major; + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kLstmInputTensor); + + const TfLiteEvalTensor* input_to_input_weights = tflite::micro::GetEvalInput( + context, node, kLstmInputToInputWeightsTensor); + + const TfLiteEvalTensor* input_to_forget_weights = tflite::micro::GetEvalInput( + context, node, kLstmInputToForgetWeightsTensor); + + const TfLiteEvalTensor* input_to_cell_weights = + tflite::micro::GetEvalInput(context, node, kLstmInputToCellWeightsTensor); + + const TfLiteEvalTensor* input_to_output_weights = tflite::micro::GetEvalInput( + context, node, kLstmInputToOutputWeightsTensor); + + const TfLiteEvalTensor* recurrent_to_input_weights = + tflite::micro::GetEvalInput(context, node, + kLstmRecurrentToInputWeightsTensor); + + const TfLiteEvalTensor* recurrent_to_forget_weights = + tflite::micro::GetEvalInput(context, node, + kLstmRecurrentToForgetWeightsTensor); + + const TfLiteEvalTensor* recurrent_to_cell_weights = + tflite::micro::GetEvalInput(context, node, + kLstmRecurrentToCellWeightsTensor); + + const TfLiteEvalTensor* recurrent_to_output_weights = + tflite::micro::GetEvalInput(context, node, + kLstmRecurrentToOutputWeightsTensor); + + const TfLiteEvalTensor* cell_to_input_weights = + tflite::micro::GetEvalInput(context, node, kLstmCellToInputWeightsTensor); + + const TfLiteEvalTensor* cell_to_forget_weights = tflite::micro::GetEvalInput( + context, node, kLstmCellToForgetWeightsTensor); + + const TfLiteEvalTensor* cell_to_output_weights = tflite::micro::GetEvalInput( + context, node, kLstmCellToOutputWeightsTensor); + + const TfLiteEvalTensor* input_gate_bias = + tflite::micro::GetEvalInput(context, node, kLstmInputGateBiasTensor); + + const TfLiteEvalTensor* forget_gate_bias = + tflite::micro::GetEvalInput(context, node, kLstmForgetGateBiasTensor); + + const TfLiteEvalTensor* cell_gate_bias = + tflite::micro::GetEvalInput(context, node, kLstmCellGateBiasTensor); + + const TfLiteEvalTensor* output_gate_bias = + tflite::micro::GetEvalInput(context, node, kLstmOutputGateBiasTensor); + + const TfLiteEvalTensor* projection_weights = + tflite::micro::GetEvalInput(context, node, kLstmProjectionWeightsTensor); + + const TfLiteEvalTensor* projection_bias = + tflite::micro::GetEvalInput(context, node, kLstmProjectionBiasTensor); + + TfLiteEvalTensor* output_state = + tflite::micro::GetMutableEvalInput(context, node, kLstmOutputStateTensor); + + TfLiteEvalTensor* cell_state = + tflite::micro::GetMutableEvalInput(context, node, kLstmCellStateTensor); + + TFLITE_DCHECK(cell_state != nullptr); + + const TfLiteEvalTensor* input_layer_norm_coefficients = + use_layer_norm ? tflite::micro::GetEvalInput( + context, node, kLstmInputLayerNormCoefficientsTensor) + : nullptr; + const TfLiteEvalTensor* forget_layer_norm_coefficients = + use_layer_norm + ? tflite::micro::GetEvalInput(context, node, + kLstmForgetLayerNormCoefficientsTensor) + : nullptr; + const TfLiteEvalTensor* cell_layer_norm_coefficients = + use_layer_norm ? tflite::micro::GetEvalInput( + context, node, kLstmCellLayerNormCoefficientsTensor) + : nullptr; + const TfLiteEvalTensor* output_layer_norm_coefficients = + use_layer_norm + ? tflite::micro::GetEvalInput(context, node, + kLstmOutputLayerNormCoefficientsTensor) + : nullptr; + + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kLstmOutputTensor); + + // Copy out the LSTM specific params so they can be passed in the function. + TfLiteLSTMParams lstm_params; + lstm_params.activation = params->activation; + lstm_params.cell_clip = params->cell_clip; + lstm_params.proj_clip = params->proj_clip; + lstm_params.asymmetric_quantize_inputs = params->asymmetric_quantize_inputs; + + switch (input_to_output_weights->type) { + case kTfLiteFloat32: { + // Index the scratch buffers pointers to the global scratch buffer. + return EvalFloatLstm( + input, input_to_input_weights, input_to_forget_weights, + input_to_cell_weights, input_to_output_weights, + recurrent_to_input_weights, recurrent_to_forget_weights, + recurrent_to_cell_weights, recurrent_to_output_weights, + cell_to_input_weights, cell_to_forget_weights, cell_to_output_weights, + input_layer_norm_coefficients, forget_layer_norm_coefficients, + cell_layer_norm_coefficients, output_layer_norm_coefficients, + /*aux_input=*/nullptr, + /*aux_input_to_input_weights=*/nullptr, + /*aux_input_to_forget_weights=*/nullptr, + /*aux_input_to_cell_weights=*/nullptr, + /*aux_input_to_output_weights=*/nullptr, input_gate_bias, + forget_gate_bias, cell_gate_bias, output_gate_bias, + projection_weights, projection_bias, &lstm_params, + /*forward_sequence=*/true, time_major, + /*output_offset=*/0, + reinterpret_cast(context->GetScratchBuffer( + context, op_data->scratch_index[kPrimaryScratchBuffer])), + output_state, cell_state, output); + } break; + case kTfLiteUInt8: + case kTfLiteInt8: { + return EvalInteger8x8_16Lstm( + input, input_to_input_weights, input_to_forget_weights, + input_to_cell_weights, input_to_output_weights, + recurrent_to_input_weights, recurrent_to_forget_weights, + recurrent_to_cell_weights, recurrent_to_output_weights, + cell_to_input_weights, cell_to_forget_weights, cell_to_output_weights, + input_layer_norm_coefficients, forget_layer_norm_coefficients, + cell_layer_norm_coefficients, output_layer_norm_coefficients, + input_gate_bias, forget_gate_bias, cell_gate_bias, output_gate_bias, + projection_weights, projection_bias, &lstm_params, + /*forward_sequence=*/true, time_major, &op_data->integer_lstm_param, + op_data->output_state_zero_point, output_state, cell_state, output, + reinterpret_cast( + context->GetScratchBuffer(context, op_data->scratch_index[0])), + reinterpret_cast( + context->GetScratchBuffer(context, op_data->scratch_index[1])), + reinterpret_cast( + context->GetScratchBuffer(context, op_data->scratch_index[2])), + reinterpret_cast( + context->GetScratchBuffer(context, op_data->scratch_index[3])), + reinterpret_cast( + context->GetScratchBuffer(context, op_data->scratch_index[4])), + nullptr); + } break; + default: + MicroPrintf("Type %s is not currently supported.", + TfLiteTypeGetName(input_to_output_weights->type)); + return kTfLiteError; + } +} + +} // namespace + +TfLiteRegistration Register_UNIDIRECTIONAL_SEQUENCE_LSTM() { + return tflite::micro::RegisterOp(UnidirectionalSequenceLstmInit, + UnidirectionalSequenceLstmPrepare, + UnidirectionalSequenceLstmEval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test_config.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test_config.h new file mode 100644 index 000000000..24c838faf --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test_config.h @@ -0,0 +1,244 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_KERNELS_UNIDIRECTIONAL_SEQUENCE_LSTM_TEST_CONFIG_H_ +#define TENSORFLOW_LITE_MICRO_KERNELS_UNIDIRECTIONAL_SEQUENCE_LSTM_TEST_CONFIG_H_ + +#include "tensorflow/lite/c/common.h" + +namespace tflite { +namespace testing { + +// TODO(b/230666079) enable below tests for xtensa when the xtensa +// kernel is reconciled with reference kernel +#if !defined(XTENSA) + +struct LstmIntegerTestConfig { + const int n_batch; + const int n_input; + const int n_cell; + const int n_output; + const int sequence_length; + const bool time_major; + const bool use_cifg; + const bool use_peephole; + const bool use_projection_weights; + const bool use_projection_bias; + const bool use_layer_norm; + const bool use_8x8_8_implementation; + float intermediate_scale[5][2]; + int intermediate_zp[5][2]; + TfLiteAffineQuantization* intermediate_qparam; + + const float* input; + int8_t* input_quant; + + const float* input_to_input_weights; + int8_t* lstm_i2i_quant; + const float* input_to_forget_weights; + int8_t* lstm_i2f_quant; + const float* input_to_cell_weights; + int8_t* lstm_i2c_quant; + const float* input_to_output_weights; + int8_t* lstm_i2o_quant; + + const float* recurrent_to_input_weights; + int8_t* lstm_r2i_quant; + const float* recurrent_to_forget_weights; + int8_t* lstm_r2f_quant; + const float* recurrent_to_cell_weights; + int8_t* lstm_r2c_quant; + const float* recurrent_to_output_weights; + int8_t* lstm_r2o_quant; + + const float* cell_to_input_weights; + int16_t* lstm_c2i_quant; + const float* cell_to_forget_weights; + int16_t* lstm_c2f_quant; + const float* cell_to_output_weights; + int16_t* lstm_c2o_quant; + + const float* input_gate_bias; + int32_t* lstm_igate_bias_quant; + const float* forget_gate_bias; + int32_t* lstm_fgate_bias_quant; + const float* cell_gate_bias; + int32_t* lstm_cgate_bias_quant; + const float* output_gate_bias; + int32_t* lstm_ogate_bias_quant; + + const float* projection_weights; + int8_t* lstm_proj_w_quant; + const float* projection_bias; + int32_t* projection_bias_quant; + + int16_t* output_state; + int16_t* cell_state; + + const float* input_layer_norm_coefficients; + int16_t* lstm_input_layer_norm_coeff_quant; + const float* forget_layer_norm_coefficients; + int16_t* lstm_forget_layer_norm_coeff_quant; + const float* cell_layer_norm_coefficients; + int16_t* lstm_cell_layer_norm_coeff_quant; + const float* output_layer_norm_coefficients; + int16_t* lstm_output_layer_norm_coeff_quant; + + int8_t* output; + const int8_t* expected_output; + + bool asymmetric_quantize_inputs; + const float ranges[25][2]; +}; + +struct LstmFloatTestConfig { + const int n_batch; + const int n_input; + const int n_cell; + const int n_output; + const int sequence_length; + const bool time_major; + const bool use_cifg; + const bool use_peephole; + const bool use_projection_weights; + const bool use_projection_bias; + const bool use_layer_norm; + const float cell_clip; + const float proj_clip; + + const float* input_original; + float* input; + + const float* input_to_input_weights; + const float* input_to_forget_weights; + const float* input_to_cell_weights; + const float* input_to_output_weights; + + const float* recurrent_to_input_weights; + const float* recurrent_to_forget_weights; + const float* recurrent_to_cell_weights; + const float* recurrent_to_output_weights; + + const float* cell_to_input_weights; + const float* cell_to_forget_weights; + const float* cell_to_output_weights; + + const float* input_gate_bias; + const float* forget_gate_bias; + const float* cell_gate_bias; + const float* output_gate_bias; + + const float* projection_weights; + const float* projection_bias; + + float* output_state; + float* cell_state; + + const float* input_layer_norm_coefficients; + const float* forget_layer_norm_coefficients; + const float* cell_layer_norm_coefficients; + const float* output_layer_norm_coefficients; + + float* output; + const float* expected_output_original; + float* expected_output; +}; + +struct LstmWeightQuantizationBuffers { + int8_t* lstm_i2i_quant; + float* lstm_i2i_scale; + int* lstm_i2i_zp; + TfLiteAffineQuantization* lstm_i2i_qparam; + + int8_t* lstm_i2f_quant; + float* lstm_i2f_scale; + int* lstm_i2f_zp; + TfLiteAffineQuantization* lstm_i2f_qparam; + + int8_t* lstm_i2c_quant; + float* lstm_i2c_scale; + int* lstm_i2c_zp; + TfLiteAffineQuantization* lstm_i2c_qparam; + + int8_t* lstm_i2o_quant; + float* lstm_i2o_scale; + int* lstm_i2o_zp; + TfLiteAffineQuantization* lstm_i2o_qparam; + + int8_t* lstm_r2i_quant; + float* lstm_r2i_scale; + int* lstm_r2i_zp; + TfLiteAffineQuantization* lstm_r2i_qparam; + + int8_t* lstm_r2f_quant; + float* lstm_r2f_scale; + int* lstm_r2f_zp; + TfLiteAffineQuantization* lstm_r2f_qparam; + + int8_t* lstm_r2c_quant; + float* lstm_r2c_scale; + int* lstm_r2c_zp; + TfLiteAffineQuantization* lstm_r2c_qparam; + + int8_t* lstm_r2o_quant; + float* lstm_r2o_scale; + int* lstm_r2o_zp; + TfLiteAffineQuantization* lstm_r2o_qparam; + + int8_t* lstm_c2i_quant; + float* lstm_c2i_scale; + int* lstm_c2i_zp; + TfLiteAffineQuantization* lstm_c2i_qparam; + + int8_t* lstm_c2f_quant; + float* lstm_c2f_scale; + int* lstm_c2f_zp; + TfLiteAffineQuantization* lstm_c2f_qparam; + + int8_t* lstm_c2o_quant; + float* lstm_c2o_scale; + int* lstm_c2o_zp; + TfLiteAffineQuantization* lstm_c2o_qparam; + + int8_t* lstm_proj_w_quant; + float* lstm_proj_w_scale; + int* lstm_proj_w_zp; + TfLiteAffineQuantization* lstm_proj_w_qparam; +}; + +extern LstmIntegerTestConfig lstm_integer_no_peephole_config; + +extern LstmIntegerTestConfig lstm_integer_peephole_config; + +extern LstmFloatTestConfig lstm_no_cifg_no_peephole_no_proj_config; + +extern LstmFloatTestConfig lstm_cifg_peephole_no_proj_config; + +extern LstmFloatTestConfig lstm_no_cifg_peephole_proj_config; + +extern LstmFloatTestConfig lstm_no_cifg_peephole_proj_bias_config; + +extern LstmWeightQuantizationBuffers lstm_no_cifg_no_peephole_no_proj_buffers; + +extern LstmWeightQuantizationBuffers lstm_cifg_peephole_no_proj_buffers; + +extern LstmWeightQuantizationBuffers lstm_no_cifg_peephole_proj_buffers; + +extern LstmFloatTestConfig cifg_peephole_no_proj_config_layer_norm; + +#endif // !defined(XTENSA) +} // namespace testing +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_KERNELS_UNIDIRECTIONAL_SEQUENCE_LSTM_TEST_CONFIG_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unpack.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unpack.cc new file mode 100644 index 000000000..b58df2e73 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/unpack.cc @@ -0,0 +1,112 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace ops { +namespace micro { +namespace unpack { +namespace { + +constexpr int kInputTensor = 0; + +template +TfLiteStatus UnpackImpl(TfLiteContext* context, TfLiteNode* node, + const TfLiteEvalTensor* input, int output_count, + int axis) { + const TfLiteEvalTensor* output0 = + tflite::micro::GetEvalOutput(context, node, 0); + const TfLiteIntArray* input_dims = input->dims; + const TfLiteIntArray* output_dims = output0->dims; + const int dimensions = input_dims->size; + + if (axis < 0) { + axis += input->dims->size; + } + + TFLITE_DCHECK_LT(axis, dimensions); + + int outer_size = 1; + for (int i = 0; i < axis; ++i) { + outer_size *= input_dims->data[i]; + } + int copy_size = 1; + for (int i = axis + 1; i < dimensions; ++i) { + copy_size *= input_dims->data[i]; + } + int output_size = 1; + for (int i = 0; i < output_dims->size; ++i) { + output_size *= output_dims->data[i]; + } + TFLITE_DCHECK_EQ(output_size, copy_size * outer_size); + + const T* input_data = tflite::micro::GetTensorData(input); + + for (int i = 0; i < output_count; ++i) { + TfLiteEvalTensor* t = tflite::micro::GetEvalOutput(context, node, i); + T* output_data = tflite::micro::GetTensorData(t); + for (int k = 0; k < outer_size; ++k) { + T* output_ptr = output_data + copy_size * k; + int loc = k * output_count * copy_size + i * copy_size; + const T* input_ptr = input_data + loc; + for (int j = 0; j < copy_size; ++j) output_ptr[j] = input_ptr[j]; + } + } + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + TfLiteUnpackParams* data = + reinterpret_cast(node->builtin_data); + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + + switch (input->type) { + case kTfLiteFloat32: { + return UnpackImpl(context, node, input, data->num, data->axis); + } + case kTfLiteInt32: { + return UnpackImpl(context, node, input, data->num, data->axis); + } + case kTfLiteInt8: { + return UnpackImpl(context, node, input, data->num, data->axis); + } + default: { + MicroPrintf("Type '%s' is not supported by unpack.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } + } + + return kTfLiteOk; +} +} // namespace +} // namespace unpack + +TfLiteRegistration Register_UNPACK() { + return tflite::micro::RegisterOp(nullptr, nullptr, unpack::Eval); +} + +} // namespace micro +} // namespace ops +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/var_handle.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/var_handle.cc new file mode 100644 index 000000000..cbd2485ca --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/var_handle.cc @@ -0,0 +1,93 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_graph.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_resource_variable.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +namespace { + +struct OpData { + int32_t resource_id; +}; + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + OpData* op_data = reinterpret_cast(node->user_data); + const auto* params = + reinterpret_cast(node->builtin_data); + + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + MicroGraph& graph_info = micro_context->graph(); + + MicroResourceVariables* resources = graph_info.GetResourceVariables(); + if (resources == nullptr) { + MicroPrintf( + "VAR_HANDLE requires resource variables. Please create " + "ResourceVariables and pass it to the interpreter."); + return kTfLiteError; + } + op_data->resource_id = + resources->CreateIdIfNoneFound(params->container, params->shared_name); + if (op_data->resource_id < 0) { + return kTfLiteError; + } + + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TFLITE_DCHECK(output != nullptr); + + // Assign saved resource_id so this output tensor will always return the + // correct resource id. + output->data.i32 = &op_data->resource_id; + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + OpData* op_data = reinterpret_cast(node->user_data); + + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TFLITE_DCHECK(output != nullptr); + + // Assign saved resource_id so this output tensor will always return the + // correct resource id. + output->data.i32 = &op_data->resource_id; + return kTfLiteOk; +} + +} // namespace. + +TfLiteRegistration Register_VAR_HANDLE() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/while.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/while.cc new file mode 100644 index 000000000..811c9eaec --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/while.cc @@ -0,0 +1,133 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_context.h" +#include "tensorflow/lite/micro/micro_graph.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +namespace { + +struct OpData { + int cond_subgraph_index; + int body_subgraph_index; +}; + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr); + return context->AllocatePersistentBuffer(context, sizeof(OpData)); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + OpData* op_data = reinterpret_cast(node->user_data); + const auto* params = + reinterpret_cast(node->builtin_data); + + op_data->cond_subgraph_index = params->cond_subgraph_index; + op_data->body_subgraph_index = params->body_subgraph_index; + + // The first input is the condition. + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + + size_t num_inputs = node->inputs->size; + size_t num_outputs = node->outputs->size; + + MicroGraph& graph_info = micro_context->graph(); + + TF_LITE_ENSURE(context, + op_data->cond_subgraph_index < graph_info.NumSubgraphs()); + TF_LITE_ENSURE(context, + op_data->body_subgraph_index < graph_info.NumSubgraphs()); + + TF_LITE_ENSURE_EQ(context, num_inputs, + graph_info.NumSubgraphInputs(op_data->cond_subgraph_index)); + TF_LITE_ENSURE_EQ(context, num_inputs, + graph_info.NumSubgraphInputs(op_data->body_subgraph_index)); + TF_LITE_ENSURE_EQ(context, num_inputs, num_outputs); + TF_LITE_ENSURE_EQ( + context, num_outputs, + graph_info.NumSubgraphOutputs(op_data->body_subgraph_index)); + + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const OpData* op_data = reinterpret_cast(node->user_data); + + tflite::MicroContext* micro_context = tflite::GetMicroContext(context); + MicroGraph* graph_info = µ_context->graph(); + + TF_LITE_ENSURE_OK(context, + tflite::micro::CopyOpInputsToSubgraphInputs( + context, node, graph_info, op_data->cond_subgraph_index, + /*first_tensor_idx=*/0)); + + TF_LITE_ENSURE_OK(context, + graph_info->InvokeSubgraph(op_data->cond_subgraph_index)); + + TfLiteEvalTensor* cond_subgraph_output = graph_info->GetSubgraphOutput( + op_data->cond_subgraph_index, /*tensor_idx=*/0); + bool cond_value = cond_subgraph_output->data.b[0]; + + TF_LITE_ENSURE_OK(context, + tflite::micro::CopyOpInputsToSubgraphInputs( + context, node, graph_info, op_data->body_subgraph_index, + /*first_tensor_idx=*/0)); + TF_LITE_ENSURE_OK(context, + tflite::micro::CopyOpInputsToOpOutputs(context, node)); + + while (cond_value == true) { + // Copy output of this iteration back to the body input. + TF_LITE_ENSURE_OK( + context, tflite::micro::CopyOpOutputsToSubgraphInputs( + context, node, graph_info, op_data->body_subgraph_index)); + TF_LITE_ENSURE_OK(context, + graph_info->InvokeSubgraph(op_data->body_subgraph_index)); + + TF_LITE_ENSURE_OK( + context, tflite::micro::CopySubgraphOutputsToOpOutputs( + context, node, graph_info, op_data->body_subgraph_index)); + TF_LITE_ENSURE_OK( + context, tflite::micro::CopyOpOutputsToSubgraphInputs( + context, node, graph_info, op_data->cond_subgraph_index)); + TF_LITE_ENSURE_OK(context, + graph_info->InvokeSubgraph(op_data->cond_subgraph_index)); + + cond_subgraph_output = graph_info->GetSubgraphOutput( + op_data->cond_subgraph_index, /*tensor_idx=*/0); + cond_value = cond_subgraph_output->data.b[0]; + } + + return kTfLiteOk; +} + +} // namespace. + +TfLiteRegistration Register_WHILE() { + return tflite::micro::RegisterOp(Init, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/zeros_like.cc b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/zeros_like.cc new file mode 100644 index 000000000..bb0c3147c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/kernels/zeros_like.cc @@ -0,0 +1,88 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +namespace { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + MicroContext* micro_context = GetMicroContext(context); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + TfLiteTensor* output = + micro_context->AllocateTempOutputTensor(node, kOutputTensor); + TF_LITE_ENSURE(context, output != nullptr); + output->type = input->type; + + micro_context->DeallocateTempTfLiteTensor(input); + micro_context->DeallocateTempTfLiteTensor(output); + return kTfLiteOk; +} + +template +void resetZeros(T* out, const int num_elements) { + for (int i = 0; i < num_elements; ++i) { + out[i] = static_cast(0); + } +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TfLiteEvalTensor* output = + tflite::micro::GetEvalOutput(context, node, kOutputTensor); + int flat_size = MatchingFlatSize(tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorShape(output)); + switch (input->type) { + case kTfLiteInt64: + resetZeros(tflite::micro::GetTensorData(output), flat_size); + break; + case kTfLiteInt32: + resetZeros(tflite::micro::GetTensorData(output), flat_size); + break; + case kTfLiteInt8: + resetZeros(tflite::micro::GetTensorData(output), flat_size); + break; + case kTfLiteFloat32: + resetZeros(tflite::micro::GetTensorData(output), flat_size); + break; + default: + MicroPrintf( + "ZerosLike only currently supports int64, int32, " + "and float32, got %d.", + input->type); + return kTfLiteError; + } + return kTfLiteOk; +} +} // namespace + +TfLiteRegistration Register_ZEROS_LIKE() { + return tflite::micro::RegisterOp(nullptr, Prepare, Eval); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_helpers.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_helpers.cpp new file mode 100644 index 000000000..c653babc2 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_helpers.cpp @@ -0,0 +1,173 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/memory_helpers.h" + +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/flatbuffer_conversions.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +uint8_t* AlignPointerUp(uint8_t* data, size_t alignment) { + std::uintptr_t data_as_uintptr_t = reinterpret_cast(data); + uint8_t* aligned_result = reinterpret_cast( + ((data_as_uintptr_t + (alignment - 1)) / alignment) * alignment); + return aligned_result; +} + +uint8_t* AlignPointerDown(uint8_t* data, size_t alignment) { + std::uintptr_t data_as_uintptr_t = reinterpret_cast(data); + uint8_t* aligned_result = + reinterpret_cast((data_as_uintptr_t / alignment) * alignment); + return aligned_result; +} + +size_t AlignSizeUp(size_t size, size_t alignment) { + size_t aligned_size = (((size + (alignment - 1)) / alignment) * alignment); + return aligned_size; +} + +TfLiteStatus TfLiteTypeSizeOf(TfLiteType type, size_t* size) { + switch (type) { + case kTfLiteFloat16: + *size = sizeof(int16_t); + break; + case kTfLiteFloat32: + *size = sizeof(float); + break; + case kTfLiteFloat64: + *size = sizeof(double); + break; + case kTfLiteInt16: + *size = sizeof(int16_t); + break; + case kTfLiteInt32: + *size = sizeof(int32_t); + break; + case kTfLiteUInt32: + *size = sizeof(uint32_t); + break; + case kTfLiteUInt8: + *size = sizeof(uint8_t); + break; + case kTfLiteInt8: + *size = sizeof(int8_t); + break; + case kTfLiteInt64: + *size = sizeof(int64_t); + break; + case kTfLiteUInt64: + *size = sizeof(uint64_t); + break; + case kTfLiteBool: + *size = sizeof(bool); + break; + case kTfLiteResource: + *size = sizeof(int32_t); + break; + case kTfLiteComplex64: + *size = sizeof(float) * 2; + break; + case kTfLiteComplex128: + *size = sizeof(double) * 2; + break; + case kTfLiteInt4: + *size = sizeof(int8_t); + break; + default: + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus BytesRequiredForTensor(const tflite::Tensor& flatbuffer_tensor, + size_t* bytes, size_t* type_size) { + int element_count = 1; + // If flatbuffer_tensor.shape == nullptr, then flatbuffer_tensor is a scalar + // so has 1 element. + if (flatbuffer_tensor.shape() != nullptr) { + for (size_t n = 0; n < flatbuffer_tensor.shape()->Length(); ++n) { + element_count *= flatbuffer_tensor.shape()->Get(n); + } + } + + TfLiteType tf_lite_type; + TF_LITE_ENSURE_STATUS(ConvertTensorType(flatbuffer_tensor.type(), + &tf_lite_type, + tflite::GetMicroErrorReporter())); + TF_LITE_ENSURE_STATUS(TfLiteTypeSizeOf(tf_lite_type, type_size)); + *bytes = element_count * (*type_size); + return kTfLiteOk; +} + +TfLiteStatus TfLiteEvalTensorByteLength(const TfLiteEvalTensor* eval_tensor, + size_t* out_bytes) { + TFLITE_DCHECK(out_bytes != nullptr); + + int element_count = 1; + // If eval_tensor->dims == nullptr, then tensor is a scalar so has 1 element. + if (eval_tensor->dims != nullptr) { + for (int n = 0; n < eval_tensor->dims->size; ++n) { + element_count *= eval_tensor->dims->data[n]; + } + } + size_t type_size; + TF_LITE_ENSURE_STATUS(TfLiteTypeSizeOf(eval_tensor->type, &type_size)); + *out_bytes = element_count * type_size; + return kTfLiteOk; +} + +TfLiteStatus AllocateOutputDimensionsFromInput(TfLiteContext* context, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + TfLiteTensor* output) { + const TfLiteTensor* input = nullptr; + + TF_LITE_ENSURE(context, input1->dims != nullptr); + TF_LITE_ENSURE(context, input2->dims != nullptr); + TF_LITE_ENSURE(context, output->dims->size == 0); + + input = input1->dims->size > input2->dims->size ? input1 : input2; + TF_LITE_ENSURE(context, output->type == input->type); + + size_t size = 0; + TfLiteTypeSizeOf(input->type, &size); + const int dimensions_count = tflite::GetTensorShape(input).DimensionsCount(); + for (int i = 0; i < dimensions_count; i++) { + size *= input->dims->data[i]; + } + + output->bytes = size; + + output->dims = + reinterpret_cast(context->AllocatePersistentBuffer( + context, TfLiteIntArrayGetSizeInBytes(size))); + + output->dims->size = input->dims->size; + for (int i = 0; i < dimensions_count; i++) { + output->dims->data[i] = input->dims->data[i]; + } + + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_helpers.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_helpers.h new file mode 100644 index 000000000..ccdbed2ff --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_helpers.h @@ -0,0 +1,57 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MEMORY_HELPERS_H_ +#define TENSORFLOW_LITE_MICRO_MEMORY_HELPERS_H_ + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +// Returns the next pointer address aligned to the given alignment. +uint8_t* AlignPointerUp(uint8_t* data, size_t alignment); + +// Returns the previous pointer address aligned to the given alignment. +uint8_t* AlignPointerDown(uint8_t* data, size_t alignment); + +// Returns an increased size that's a multiple of alignment. +size_t AlignSizeUp(size_t size, size_t alignment); + +// Returns size in bytes for a given TfLiteType. +TfLiteStatus TfLiteTypeSizeOf(TfLiteType type, size_t* size); + +// How many bytes are needed to hold a tensor's contents. +TfLiteStatus BytesRequiredForTensor(const tflite::Tensor& flatbuffer_tensor, + size_t* bytes, size_t* type_size); + +// How many bytes are used in a TfLiteEvalTensor instance. The byte length is +// returned in out_bytes. +TfLiteStatus TfLiteEvalTensorByteLength(const TfLiteEvalTensor* eval_tensor, + size_t* out_bytes); + +// Deduce output dimensions from input and allocate given size. +// Useful for operators with two inputs where the largest input should equal the +// output dimension. +TfLiteStatus AllocateOutputDimensionsFromInput(TfLiteContext* context, + const TfLiteTensor* input1, + const TfLiteTensor* input2, + TfLiteTensor* output); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MEMORY_HELPERS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/greedy_memory_planner.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/greedy_memory_planner.cpp new file mode 100644 index 000000000..471a5b229 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/greedy_memory_planner.cpp @@ -0,0 +1,448 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/memory_planner/greedy_memory_planner.h" + +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_string.h" + +namespace tflite { + +namespace { + +// Returns a character representing a numbered buffer +// for GreedyMemoryPlanner::PrintMemoryPlan() +char GetOrdinalCharacter(int i) { + if (i < 10) { + return '0' + i; + } else if (i < 36) { + return 'a' + (i - 10); + } else if (i < 62) { + return 'A' + (i - 36); + } + return '*'; +} + +} // namespace + +// Simple stable in-place sort function. Not time-efficient for large arrays. +// Would normally be in an anonymous namespace to keep it private, but we want +// to be able to test it externally. +void ReverseSortInPlace(int* values, int* ids, int size) { + bool any_swapped; + do { + any_swapped = false; + for (int i = 1; i < size; ++i) { + if (values[i - 1] < values[i]) { + const int value_temp = values[i - 1]; + values[i - 1] = values[i]; + values[i] = value_temp; + const int id_temp = ids[i - 1]; + ids[i - 1] = ids[i]; + ids[i] = id_temp; + any_swapped = true; + } + } + } while (any_swapped); +} + +GreedyMemoryPlanner::GreedyMemoryPlanner() {} + +TfLiteStatus GreedyMemoryPlanner::Init(unsigned char* scratch_buffer, + int scratch_buffer_size) { + // Reset internal states + buffer_count_ = 0; + need_to_calculate_offsets_ = true; + + // Allocate the arrays we need within the scratch buffer arena. + max_buffer_count_ = scratch_buffer_size / per_buffer_size(); + + unsigned char* next_free = scratch_buffer; + requirements_ = reinterpret_cast(next_free); + next_free += sizeof(BufferRequirements) * max_buffer_count_; + + buffer_sizes_sorted_ = reinterpret_cast(next_free); + next_free += sizeof(int) * max_buffer_count_; + + buffer_ids_sorted_ = reinterpret_cast(next_free); + next_free += sizeof(int) * max_buffer_count_; + + buffers_sorted_by_offset_ = reinterpret_cast(next_free); + next_free += sizeof(ListEntry) * max_buffer_count_; + + buffer_offsets_ = reinterpret_cast(next_free); + return kTfLiteOk; +} + +GreedyMemoryPlanner::~GreedyMemoryPlanner() { + // We don't own the scratch buffer, so don't deallocate anything. +} + +TfLiteStatus GreedyMemoryPlanner::AddBuffer(int size, int first_time_used, + int last_time_used) { + if (buffer_count_ >= max_buffer_count_) { + MicroPrintf("Too many buffers (max is %d)", max_buffer_count_); + return kTfLiteError; + } + BufferRequirements* current = &requirements_[buffer_count_]; + current->size = size; + current->first_time_used = first_time_used; + current->last_time_used = last_time_used; + current->offline_offset = kOnlinePlannedBuffer; + ++buffer_count_; + need_to_calculate_offsets_ = true; + return kTfLiteOk; +} + +TfLiteStatus GreedyMemoryPlanner::AddBuffer(int size, int first_time_used, + int last_time_used, + int offline_offset) { + BufferRequirements* current = &requirements_[buffer_count_]; + if (AddBuffer(size, first_time_used, last_time_used) != kTfLiteOk) { + return kTfLiteError; + } + current->offline_offset = offline_offset; + return kTfLiteOk; +} + +bool GreedyMemoryPlanner::DoesEntryOverlapInTime( + const GreedyMemoryPlanner::ListEntry* entry, const int first_time_used, + const int last_time_used) const { + const BufferRequirements* entry_requirements = + &requirements_[entry->requirements_index]; + if (entry_requirements->first_time_used > last_time_used) { + return false; + } + if (first_time_used > entry_requirements->last_time_used) { + return false; + } + return true; +} + +GreedyMemoryPlanner::ListEntry* +GreedyMemoryPlanner::NextSimultaneouslyActiveBuffer( + const GreedyMemoryPlanner::ListEntry* start, const int first_time_used, + const int last_time_used) { + ListEntry* result = nullptr; + ListEntry* candidate_next_entry; + if (start == nullptr) { + candidate_next_entry = &buffers_sorted_by_offset_[first_entry_index_]; + } else { + if (start->next_entry_index == -1) { + return nullptr; + } + candidate_next_entry = &buffers_sorted_by_offset_[start->next_entry_index]; + } + do { + if (DoesEntryOverlapInTime(candidate_next_entry, first_time_used, + last_time_used)) { + result = candidate_next_entry; + break; + } + if (candidate_next_entry->next_entry_index == -1) { + break; + } + candidate_next_entry = + &buffers_sorted_by_offset_[candidate_next_entry->next_entry_index]; + } while (true); + return result; +} + +void GreedyMemoryPlanner::CalculateOffsetsIfNeeded() { + if (!need_to_calculate_offsets_ || (buffer_count_ == 0)) { + return; + } + need_to_calculate_offsets_ = false; + + // Start off by ordering the buffers in descending order of size. + // This helps find a more compact layout. Intuitively, you can think + // about putting the large buffers in place first, and then the + // smaller buffers can fit in the gaps, rather than fragmenting the + // gaps with small buffers at the beginning. Add offline planned offsets + // first in the list, since they have a predetermined offset. + int idx_from_tail = buffer_count_; + int idx_from_head = 0; + for (int i = 0; i < buffer_count_; ++i) { + if (requirements_[i].offline_offset == kOnlinePlannedBuffer) { + idx_from_tail--; + buffer_sizes_sorted_[idx_from_tail] = requirements_[i].size; + buffer_ids_sorted_[idx_from_tail] = i; + buffer_offsets_[i] = -1; + } else { + buffer_sizes_sorted_[idx_from_head] = requirements_[i].size; + buffer_ids_sorted_[idx_from_head] = i; + buffer_offsets_[i] = requirements_[i].offline_offset; + idx_from_head++; + } + } + + // This sorting algorithm is naive, and may end up taking a very long time + // with hundreds of buffers. Do not sort the offline planned offsets. + ReverseSortInPlace(&buffer_sizes_sorted_[idx_from_head], + &buffer_ids_sorted_[idx_from_head], + buffer_count_ - idx_from_head); + + // Initialize the first entry to the first buffer in + // buffer_ids_sorted_. + // - If there are no offline planned offsets, the largest buffer will be + // first, and the buffers will be handled in size order. + // - If offline offsets are present, these will be handled first in order + // for the greedy algorithm to utilized gaps in the offline plan. + first_entry_index_ = 0; + next_free_entry_ = 1; + ListEntry* first_entry = &buffers_sorted_by_offset_[first_entry_index_]; + first_entry->next_entry_index = -1; // to mark the entry as end of list + int buffer_id = buffer_ids_sorted_[0]; + first_entry->requirements_index = buffer_id; + if (requirements_[buffer_id].offline_offset == kOnlinePlannedBuffer) { + buffer_offsets_[buffer_id] = 0; + } + first_entry->offset = buffer_offsets_[buffer_id]; + + // Work through the rest of the buffers to find a good gap to place each one. + for (int i = 1; i < buffer_count_; ++i) { + // The id is the order the buffer was originally added by the client. + buffer_id = buffer_ids_sorted_[i]; + // Look at what size and time range the buffer needs to be active. + BufferRequirements* wanted_requirements = &requirements_[buffer_id]; + const int wanted_size = wanted_requirements->size; + const int wanted_first_time_used = wanted_requirements->first_time_used; + const int wanted_last_time_used = wanted_requirements->last_time_used; + + // Find the first buffer that's active in our time range. All placed + // buffers are stored in the order of their starting position in the arena + // so that it's easy to find the next buffer in memory, and so the gap. + // The candidate_entry variable holds the buffer that we're considering + // placing the current buffer after. + + int candidate_offset = 0; + // Loop through the offset-ordered list of buffers, looking for gaps. + if (wanted_requirements->offline_offset == kOnlinePlannedBuffer) { + ListEntry* prior_entry = nullptr; + while (true) { + // Find out what the next active buffer is. + ListEntry* next_entry = NextSimultaneouslyActiveBuffer( + prior_entry, wanted_first_time_used, wanted_last_time_used); + + if (prior_entry) { + BufferRequirements* candidate_requirements = + &requirements_[prior_entry->requirements_index]; + const int prior_entry_offset = + prior_entry->offset + candidate_requirements->size; + if (prior_entry_offset > candidate_offset) { + candidate_offset = prior_entry_offset; + } + } + if (next_entry == nullptr) { + // We're at the end of the list, so we can always append the buffer + // here. + break; + } + // Find out how much space there is between us and the next buffer. + const int gap = next_entry->offset - candidate_offset; + if (gap >= wanted_size) { + // This entry has a big enough gap between it and the next, so + // use it! + break; + } + // The gap wasn't big enough, so move on to another candidate. + prior_entry = next_entry; + } + } else { + // Offline planned offset are to be considered constant + candidate_offset = wanted_requirements->offline_offset; + } + // At this point, we've either found a gap (possibly at the end of the + // list) and want to place the buffer there, or there are no other active + // buffers in this time range and so we can put it at offset zero. + // Record the buffer's offset in our plan. + buffer_offsets_[buffer_id] = candidate_offset; + // Add the newly-placed buffer to our offset-ordered list, so that + // subsequent passes can fit in their buffers around it. + ListEntry* new_entry = &buffers_sorted_by_offset_[next_free_entry_]; + new_entry->offset = candidate_offset; + new_entry->requirements_index = buffer_id; + const int new_entry_index = next_free_entry_; + ++next_free_entry_; + + if (first_entry->offset > candidate_offset) { + // The new entry offset is smaller than the first entry offset => + // replace the first entry + first_entry = new_entry; + first_entry->next_entry_index = first_entry_index_; + first_entry_index_ = new_entry_index; + } else { + ListEntry* current_entry = first_entry; + // Make sure that we insert the buffer at the correct place in the + // buffer-offset-ordered list + while (true) { + const int next_entry_index = current_entry->next_entry_index; + if (next_entry_index == -1) { + // We're at the end of the list, so just add the new entry here. + current_entry->next_entry_index = new_entry_index; + new_entry->next_entry_index = -1; + break; + } + // not at the end of the list -> take a look at next entry + ListEntry* next_entry = &buffers_sorted_by_offset_[next_entry_index]; + if (next_entry->offset > candidate_offset) { + // We're at the right spot to do an insertion and retain the sorting + // order, so place the new entry here. + new_entry->next_entry_index = current_entry->next_entry_index; + current_entry->next_entry_index = new_entry_index; + break; + } + current_entry = next_entry; + } + } + } +} + +size_t GreedyMemoryPlanner::GetMaximumMemorySize() { + CalculateOffsetsIfNeeded(); + if (buffer_count_ == 0) { + return 0; + } + ListEntry* entry = &buffers_sorted_by_offset_[first_entry_index_]; + size_t max_size = 0; + while (entry) { + BufferRequirements* requirements = + &requirements_[entry->requirements_index]; + const size_t current_size = entry->offset + requirements->size; + if (current_size > max_size) { + max_size = current_size; + } + if (entry->next_entry_index == -1) { + break; + } + entry = &buffers_sorted_by_offset_[entry->next_entry_index]; + } + return max_size; +} + +void GreedyMemoryPlanner::PrintMemoryPlan() { + CalculateOffsetsIfNeeded(); + + for (int i = 0; i < buffer_count_; ++i) { + MicroPrintf("%c (id=%d): size=%d, offset=%d, first_used=%d last_used=%d", + GetOrdinalCharacter(i), i, requirements_[i].size, + buffer_offsets_[i], requirements_[i].first_time_used, + requirements_[i].last_time_used); + } + + constexpr int kLineWidth = 80; + int max_size = kLineWidth; + int max_time = 0; + for (int i = 0; i < buffer_count_; ++i) { + BufferRequirements* requirements = &requirements_[i]; + const int offset = buffer_offsets_[i]; + const int last_time_used = requirements->last_time_used; + const int size = offset + requirements->size; + if (size > max_size) { + max_size = size; + } + if (last_time_used > max_time) { + max_time = last_time_used; + } + } + + char line[kLineWidth + 1]; + for (int t = 0; t <= max_time; ++t) { + for (int c = 0; c < kLineWidth; ++c) { + line[c] = '.'; + } + int memory_use = 0; + for (int i = 0; i < buffer_count_; ++i) { + BufferRequirements* requirements = &requirements_[i]; + if ((t < requirements->first_time_used) || + (t > requirements->last_time_used)) { + continue; + } + const int offset = buffer_offsets_[i]; + if (offset == -1) { + continue; + } + const int size = requirements->size; + memory_use += size; + const int line_start = (offset * kLineWidth) / max_size; + const int line_end = ((offset + size) * kLineWidth) / max_size; + for (int n = line_start; n < line_end; ++n) { + if (line[n] == '.') { + line[n] = GetOrdinalCharacter(i); + } else { + line[n] = '!'; + } + } + } + line[kLineWidth] = 0; + + MicroPrintf("%s%d: %s (%dk)", t < 10 ? " " : "", t, (const char*)line, + (memory_use + 1023) / 1024); + } +} + +int GreedyMemoryPlanner::GetBufferCount() { return buffer_count_; } + +TfLiteStatus GreedyMemoryPlanner::GetOffsetForBuffer(int buffer_index, + int* offset) { + CalculateOffsetsIfNeeded(); + if ((buffer_index < 0) || (buffer_index >= buffer_count_)) { + MicroPrintf("buffer index %d is outside range 0 to %d", buffer_index, + buffer_count_); + return kTfLiteError; + } + *offset = buffer_offsets_[buffer_index]; + return kTfLiteOk; +} + +bool GreedyMemoryPlanner::DoAnyBuffersOverlap() { + CalculateOffsetsIfNeeded(); + bool were_overlaps_found = false; + for (int i = 0; i < buffer_count_; ++i) { + BufferRequirements* a_requirements = &requirements_[i]; + const int a_start_offset = buffer_offsets_[i]; + const int a_first_time_used = a_requirements->first_time_used; + const int a_last_time_used = a_requirements->last_time_used; + const int a_end_offset = a_start_offset + a_requirements->size; + for (int j = 0; j < buffer_count_; ++j) { + if (i == j) { + continue; + } + BufferRequirements* b_requirements = &requirements_[j]; + const int b_start_offset = buffer_offsets_[j]; + const int b_first_time_used = b_requirements->first_time_used; + const int b_last_time_used = b_requirements->last_time_used; + const int b_end_offset = b_start_offset + b_requirements->size; + if ((a_first_time_used > b_last_time_used) || + (b_first_time_used > a_last_time_used)) { + // Buffers don't overlap in time. + continue; + } + if ((a_start_offset >= b_end_offset) || + (b_start_offset >= a_end_offset)) { + // No overlap in memory. + continue; + } + were_overlaps_found = true; + MicroPrintf("Overlap: %d (%d=>%d, %d->%d) vs %d (%d=>%d, %d->%d)", i, + a_first_time_used, a_last_time_used, a_start_offset, + a_end_offset, j, b_first_time_used, b_last_time_used, + b_start_offset, b_end_offset); + } + } + return were_overlaps_found; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/greedy_memory_planner.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/greedy_memory_planner.h new file mode 100644 index 000000000..ae3705d33 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/greedy_memory_planner.h @@ -0,0 +1,165 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_GREEDY_MEMORY_PLANNER_H_ +#define TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_GREEDY_MEMORY_PLANNER_H_ + +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/memory_planner/micro_memory_planner.h" + +namespace tflite { + +constexpr int kOnlinePlannedBuffer = -1; + +// A memory planner that uses a greedy algorithm to arrange buffers in memory +// to minimize the overall arena size needed. +// +// The algorithm works like this: +// - The client enters the buffer information through AddBuffer(). +// - When a function like GetOffsetForBuffer() is called, the +// CalculateOffsetsIfNeeded() method is invoked. +// - If an up to date plan is not already present, one will be calculated. +// - The buffers are sorted in descending order of size. +// - The largest buffer is placed at offset zero. +// - The rest of the buffers are looped through in descending size order. +// - The other buffers that need to be in memory at the same time are found. +// - The first gap between simultaneously active buffers that the current +// buffer fits into will be used. +// - If no large-enough gap is found, the current buffer is placed after the +// last buffer that's simultaneously active. +// - This continues until all buffers are placed, and the offsets stored. +// +// This is not guaranteed to produce the best placement, since that's an +// NP-Complete problem, but in practice it should produce one that's decent. +class GreedyMemoryPlanner : public MicroMemoryPlanner { + public: + GreedyMemoryPlanner(); + ~GreedyMemoryPlanner() override; + + // You need to pass in an area of memory to be used for planning. The client + // should ensure the validity of the memory when it needs to use this object. + // This memory isn't owned by this object, so management should be handled by + // the client. This is so it can be stack or globally allocated if necessary + // on devices without dynamic memory allocation. How many buffers can be + // planned for will depend on the size of this scratch memory, so you should + // enlarge it if you see an error when calling AddBuffer(). The memory can be + // reused once you're done with the planner, as long as you copy the + // calculated offsets to another location. Each buffer requires about 36 bytes + // of scratch. + TfLiteStatus Init(unsigned char* scratch_buffer, + int scratch_buffer_size) override; + + // Record details of a buffer we want to place. + TfLiteStatus AddBuffer(int size, int first_time_used, + int last_time_used) override; + + // Record details of an offline planned buffer offset we want to place. + // offline_offset is the buffer offset from the start of the arena. + TfLiteStatus AddBuffer(int size, int first_time_used, int last_time_used, + int offline_offset) override; + + // Returns the high-water mark of used memory. This is the minimum size of a + // memory arena you'd need to allocate to hold these buffers. + size_t GetMaximumMemorySize() override; + + // How many buffers have been recorded. + int GetBufferCount() override; + + // Where a given buffer should be placed in the memory arena. + // This information is stored in the memory arena itself, so once the arena + // is used for inference, it will be overwritten. + TfLiteStatus GetOffsetForBuffer(int buffer_index, int* offset) override; + + // Prints an ascii-art diagram of the buffer layout plan. + void PrintMemoryPlan() override; + + // Debug method to check whether any buffer allocations are overlapping. This + // is an O(N^2) complexity operation, so only use for testing. + bool DoAnyBuffersOverlap(); + + // Used to store a list of buffers ordered by their offset. + struct ListEntry { + int offset; + int requirements_index; + int next_entry_index; + }; + + // Number of bytes required in order to plan a buffer. + static size_t per_buffer_size() { + const int per_buffer_size = + sizeof(BufferRequirements) + // requirements_ + sizeof(int) + // buffer_sizes_sorted_ + sizeof(int) + // buffer_ids_sorted_ + sizeof(ListEntry) + // buffers_sorted_by_offset_ + sizeof(int); // buffer_offsets_; + return per_buffer_size; + } + + private: + // Whether a buffer is active in a given time range. + bool DoesEntryOverlapInTime(const ListEntry* entry, const int first_time_used, + const int last_time_used) const; + + // Walks the list to return the next buffer that is active in a given time + // range, or a null pointer if there are none. + ListEntry* NextSimultaneouslyActiveBuffer(const ListEntry* start, + const int first_time_used, + const int last_time_used); + + // If there isn't an up to date plan, calculate a new one. + void CalculateOffsetsIfNeeded(); + + // How many buffers we can plan for, based on the arena size we're given in + // the constructor. + int max_buffer_count_; + + // The number of buffers added so far. + int buffer_count_; + + // Records the client-provided information about each buffer. + struct BufferRequirements { + int size; + int offline_offset; + int first_time_used; + int last_time_used; + }; + + // Working arrays used during the layout algorithm. + BufferRequirements* requirements_; + // buffer_sizes_sorted_ and buffer_ids_sorted_ are sorted according to: + // { + // offline planned buffers, + // online planned buffers sorted by size + // } + int* buffer_sizes_sorted_; + int* buffer_ids_sorted_; + ListEntry* buffers_sorted_by_offset_; + int next_free_entry_; // Index of the next free entry of + // buffers_sorted_by_offset_ + int first_entry_index_; // Index of the first entry (smallest offset) of + // buffers_sorted_by_offset_ + + // Stores the outcome of the plan, the location of each buffer in the arena. + int* buffer_offsets_; + + // Whether buffers have been added since the last plan was calculated. + bool need_to_calculate_offsets_; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_GREEDY_MEMORY_PLANNER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/linear_memory_planner.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/linear_memory_planner.cpp new file mode 100644 index 000000000..5c6afb545 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/linear_memory_planner.cpp @@ -0,0 +1,53 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/memory_planner/linear_memory_planner.h" + +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +LinearMemoryPlanner::LinearMemoryPlanner() + : current_buffer_count_(0), next_free_offset_(0) {} +LinearMemoryPlanner::~LinearMemoryPlanner() {} + +TfLiteStatus LinearMemoryPlanner::AddBuffer(int size, int first_time_used, + int last_time_used) { + if (current_buffer_count_ >= kMaxBufferCount) { + MicroPrintf("Too many buffers (max is %d)", kMaxBufferCount); + return kTfLiteError; + } + buffer_offsets_[current_buffer_count_] = next_free_offset_; + next_free_offset_ += size; + ++current_buffer_count_; + return kTfLiteOk; +} + +size_t LinearMemoryPlanner::GetMaximumMemorySize() { return next_free_offset_; } + +int LinearMemoryPlanner::GetBufferCount() { return current_buffer_count_; } + +TfLiteStatus LinearMemoryPlanner::GetOffsetForBuffer(int buffer_index, + int* offset) { + if ((buffer_index < 0) || (buffer_index >= current_buffer_count_)) { + MicroPrintf("buffer index %d is outside range 0 to %d", buffer_index, + current_buffer_count_); + return kTfLiteError; + } + *offset = buffer_offsets_[buffer_index]; + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/linear_memory_planner.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/linear_memory_planner.h new file mode 100644 index 000000000..d4938ddc7 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/linear_memory_planner.h @@ -0,0 +1,49 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_LINEAR_MEMORY_PLANNER_H_ +#define TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_LINEAR_MEMORY_PLANNER_H_ + +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/memory_planner/micro_memory_planner.h" + +namespace tflite { + +// The simplest possible memory planner that just lays out all buffers at +// increasing offsets without trying to reuse memory. +class LinearMemoryPlanner : public MicroMemoryPlanner { + public: + LinearMemoryPlanner(); + ~LinearMemoryPlanner() override; + + TfLiteStatus AddBuffer(int size, int first_time_used, + int last_time_used) override; + + size_t GetMaximumMemorySize() override; + int GetBufferCount() override; + TfLiteStatus GetOffsetForBuffer(int buffer_index, int* offset) override; + + private: + static constexpr int kMaxBufferCount = 1024; + size_t buffer_offsets_[kMaxBufferCount]; + int current_buffer_count_; + size_t next_free_offset_; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_LINEAR_MEMORY_PLANNER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/memory_plan_struct.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/memory_plan_struct.h new file mode 100644 index 000000000..c8c431cce --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/memory_plan_struct.h @@ -0,0 +1,73 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_MEMORY_PLAN_STRUCT_H_ +#define TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_MEMORY_PLAN_STRUCT_H_ + +#include +#include + +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +// This is an experimental feature and subjected to change. +// More description is available at +// tensorflow/lite/micro/docs/offline_memory_plan.md. + +// Describes a buffer's layout inside an arena. This struct should be kept as +// small as possible for memory footprint sensitive applications and should use +// only primitive fields, making it easy to adjust offline. +struct BufferDescriptor { + // Starting offset inside an arena for this buffer. + // Offset is the minimum information needed for the buffer. The user knows + // the model and the size of each buffer in order to lay out a valid buffer + // plan. + int32_t offset; +}; + +// A structure describing the lay out of buffers inside an arena. +struct BufferPlan { + // Number of buffers described in this plan. + int32_t buffer_count; + + // Each element describes one buffer. + // Buffer index is implicit by the order of AddBuffer() call. + // Specifically, indices of activation tensors are 0 … N-1 where N is the + // number of activation tensors. + // The rest are based on the order of OP requests. + // + // This is a flexible array member and should ideally be + // arena_entries[]; However, in order to support a variety + // of compilers (and without needing to add ifdef's), we + // are implementing the flexible array member with an array of + // length 1 as the last member of the struct. When the size of a BufferPlan + // is needed, use the provided SizeOfBufferPlan(buffer_count) that + // accounts for this implemenatation caveat. + BufferDescriptor buffer_plan_entries[1]; +}; + +// Returns size of a BufferPlan given a buffer count. This size is compile time +// known if buffer_count is a compile time constant. +constexpr size_t SizeOfBufferPlan(int32_t buffer_count) { + // Minus 1 because a BufferPlan struct have a BufferDescriptor already. + // Max to provide a lower bound for the corner case of buffer_count = 0. + return sizeof(BufferPlan) + + sizeof(BufferDescriptor) * Max(buffer_count - 1, 0); +} + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_MEMORY_PLAN_STRUCT_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/micro_memory_planner.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/micro_memory_planner.h new file mode 100644 index 000000000..0bfe693a3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/micro_memory_planner.h @@ -0,0 +1,91 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MICRO_MEMORY_PLANNER_MEMORY_PLANNER_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_MEMORY_PLANNER_MEMORY_PLANNER_H_ + +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +// Interface class for planning the layout of memory buffers during the +// execution of a graph. +// It's designed to be used by a client that iterates in any order through the +// buffers it wants to lay out, and then calls the getter functions for +// information about the calculated layout. For example: +// +// SomeMemoryPlanner planner; +// planner.AddBuffer(100, 0, 1); // Buffer 0 +// planner.AddBuffer(50, 2, 3); // Buffer 1 +// planner.AddBuffer(50, 2, 3); // Buffer 2 +// +// int offset0; +// TF_EXPECT_OK(planner.GetOffsetForBuffer(0, &offset0)); +// int offset1; +// TF_EXPECT_OK(planner.GetOffsetForBuffer(1, &offset1)); +// int offset2; +// TF_EXPECT_OK(planner.GetOffsetForBuffer(2, &offset2)); +// const int arena_size_needed = planner.GetMaximumMemorySize(); +// +// The goal is for applications to be able to experiment with different layout +// strategies without changing their client code, by swapping out classes that +// implement this interface.= +class MicroMemoryPlanner { + public: + MicroMemoryPlanner() {} + virtual ~MicroMemoryPlanner() {} + + // Pass information about a buffer's size and lifetime to the layout + // algorithm. The order this is called implicitly assigns an index to the + // result, so the buffer information that's passed into the N-th call of + // this method will be used as the buffer_index argument to + // GetOffsetForBuffer(). + virtual TfLiteStatus AddBuffer(int size, int first_time_used, + int last_time_used) = 0; + + // Record details of an offline planned buffer offset we want to place. + // offline_offset is the buffer offset from the start of the arena. + // This is to support offline memory planning from the flatbuffer metadata. + // By default, it returns an error. + virtual TfLiteStatus AddBuffer(int size, int first_time_used, + int last_time_used, int offline_offset) { + return kTfLiteError; + } + + // The largest contiguous block of memory that's needed to hold the layout. + virtual size_t GetMaximumMemorySize() = 0; + // How many buffers have been added to the planner. + virtual int GetBufferCount() = 0; + // Calculated layout offset for the N-th buffer added to the planner. + virtual TfLiteStatus GetOffsetForBuffer(int buffer_index, int* offset) = 0; + + // Provides the scratch buffer in case that the memory planner needs it. + // The lifetime of scratch buffers lifetime lasts until the static memory plan + // is committed. + // The default implementation is for the memory planner that does not need + // scratch buffer and simply returns ok. + virtual TfLiteStatus Init(unsigned char* scratch_buffer, + int scratch_buffer_size) { + return kTfLiteOk; + } + + virtual void PrintMemoryPlan() { + // Default does nothing. + } +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_MEMORY_PLANNER_MEMORY_PLANNER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.cpp new file mode 100644 index 000000000..9bcb80c12 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.cpp @@ -0,0 +1,66 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.h" + +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +NonPersistentMemoryPlannerShim::NonPersistentMemoryPlannerShim( + const BufferPlan* buffer_plan) + : buffer_plan_(buffer_plan), buffer_request_count_(0) {} + +NonPersistentMemoryPlannerShim::~NonPersistentMemoryPlannerShim() {} + +TfLiteStatus NonPersistentMemoryPlannerShim::AddBuffer(int size, + int first_time_used, + int last_time_used) { + buffer_request_count_++; + if (buffer_request_count_ > buffer_plan_->buffer_count) { + MicroPrintf( + "Attempting to add buffer %d, but only %d buffers in given buffer " + "plan.", + buffer_request_count_, buffer_plan_->buffer_count); + return kTfLiteError; + } + return kTfLiteOk; +} + +size_t NonPersistentMemoryPlannerShim::GetMaximumMemorySize() { + // Simply return 0 to let the framework accept this memory plan + // because the client ensure validity of the memory plan. + return 0; +} + +// How many buffers are in the given memory plan. +int NonPersistentMemoryPlannerShim::GetBufferCount() { + return buffer_plan_->buffer_count; +} + +TfLiteStatus NonPersistentMemoryPlannerShim::GetOffsetForBuffer( + int buffer_request_index, int* offset) { + if (buffer_request_index >= buffer_plan_->buffer_count) { + MicroPrintf( + "Attempting to get offset for buffer %d, but only %d buffers in given " + "buffer plan.", + buffer_request_index, buffer_plan_->buffer_count); + return kTfLiteError; + } + *offset = buffer_plan_->buffer_plan_entries[buffer_request_index].offset; + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.h new file mode 100644 index 000000000..8f9bb26a3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.h @@ -0,0 +1,129 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_NON_PERSISTENT_MEMORY_PLANNER_SHIM_H__ +#define TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_NON_PERSISTENT_MEMORY_PLANNER_SHIM_H__ + +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/memory_planner/memory_plan_struct.h" +#include "tensorflow/lite/micro/memory_planner/micro_memory_planner.h" + +namespace tflite { + +/* This is an experimental feature and subjected to change. + * +The NonPersistentMemoryPlannerShim enables TFLM to work with an external tooling +that can plan the offset of each non persistent buffer for the Model within the +TFLM arena. + +If the NonPersistentMemoryPlannerShim is used, then the final binary does not +have any of the symbols associated with the GreedyMemoryPlanner which results in +a reduced memory footprint. + +Additionally, the offline planning of the non-persistent buffers can be used to +have a more efficient utilization compared to the GreedyMemoryPlanner. + +For example, consider the following hypothetical model: + +A1(400) A2(401) +──┬─────────┐ ┌─────────── + │ │ │ + │ │ │ + │ ▼ ▼ + │ ┌────────┐ + │ │ OP1 │ + │ └───┬────┘ A4(201) + │ A3(10) │ │ + │ │ │ + │ │ │ + │ ┌───┴────┐ │ + │ │ OP2 │◄────────┤ + │ └───┬────┘ │ + │ A5(11) │ A6(202) │ + │ │ │ │ + │ ▼ │ │ + │ ┌────────┐ │ │ + │ │ OP3 │◄─┘ │ + │ └───┬────┘ │ + │ │ A8(200) │ + │ A7(12) │ │ │ + │ │ │ │ + │ ┌───┴────┐◄──┘ │ + └──────►│ OP4 │ │ + └───┬────┘◄────────┘ + │ + A9(13) │ + ▼ + +The GreedyMemoryPlanner will give the following memory layout that requires 1012 +bytes of scratch arena size: + +┌─────────────────────────────────────────┬──────────────────────────┬────────┬───────┐ +│ A2(401) │ A1(400) │ A4(201)│ +A3(10)│ +└─────────────────────────────────────────┴──────────────────────────┴────────┴───────┘ + +┌───────────┬──────┬──────┐ +│ A6(202) │A5(11)│A7(12)│ +└───────────┴──────┴──────┘ + +┌──────────┬───────┐ +│ A8(200) │A9(13) │ +└──────────┴───────┘ + +But a more efficient offline memory plan that requires only 826 bytes of scratch +arena size can be + +┌──────────────────────────────────────┬─────────────────────────────┬───────┬──────┐ +│ A1(400) │ A2(401) │ +A3(10)│A5(11)│ +└──────────────────────────────────────┴─────────────────────────────┴───────┴──────┘ + + ┌────────────────┬────────────┬────────┬───────┐ + │A4(201) │ A8(200) │A9(13) +│A7(12) │ └────────────────┴────────────┴────────┴───────┘ + + ┌─────────────┐ + │ A6(202) │ + └─────────────┘ + +*/ +class NonPersistentMemoryPlannerShim : public MicroMemoryPlanner { + public: + // Does not take ownership of buffer_plan, which must refer to a valid + // BufferPlan that outlives this object. + explicit NonPersistentMemoryPlannerShim(const BufferPlan* buffer_plan); + ~NonPersistentMemoryPlannerShim() override; + + TfLiteStatus GetOffsetForBuffer(int buffer_request_index, + int* offset) override; + + TfLiteStatus AddBuffer(int size, int first_time_used, + int last_time_used) override; + size_t GetMaximumMemorySize() override; + int GetBufferCount() override; + + private: + const BufferPlan* buffer_plan_; // not owned, can't be null + + // The number of buffers requested so far. Used for error checking. + int buffer_request_count_; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MEMORY_PLANNER_NON_PERSISTENT_MEMORY_PLANNER_SHIM_H__ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocation_info.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocation_info.cpp new file mode 100644 index 000000000..8686453b3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocation_info.cpp @@ -0,0 +1,353 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/micro/micro_allocation_info.h" + +#include "tensorflow/lite/c/c_api_types.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/memory_planner/greedy_memory_planner.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +namespace { +constexpr char kOfflineMemAllocMetadata[] = "OfflineMemoryAllocation"; +constexpr int kUninitializedLifetime = -1; +} // namespace + +// Mark the given Allocation info as first created at the specified allocation +// scope count. Only the first creation must be recorded since the allocation +// scope count monotonically increases throughout the lifetime marking process. +void AllocationInfoBuilder::UpdateFirstCreated(AllocationInfo* current, + int allocation_scope_count) { + TFLITE_DCHECK(current->first_created <= allocation_scope_count); + if (current->first_created == kUninitializedLifetime) { + current->first_created = allocation_scope_count; + } +} + +// Mark the given AllocationInfo as last used at the specified allocation scope +// count. Update the last used marker every time, since the allocation scope +// count monotonically increases through the lifetime marking process. +void AllocationInfoBuilder::UpdateLastUsed(AllocationInfo* current, + int allocation_scope_count) { + TFLITE_DCHECK(current->last_used <= allocation_scope_count); + current->last_used = allocation_scope_count; +} + +TfLiteStatus AllocationInfoBuilder::MarkSubgraphLifetimesIfNecessary( + const Operator* op, internal::ScratchBufferRequest* scratch_buffer_requests, + ScratchBufferHandle* scratch_buffer_handles, + SubgraphAllocations* allocations) { + int first_subgraph_index = -1; + int second_subgraph_index = -1; + const OperatorCode* opcode = + model_->operator_codes()->Get(op->opcode_index()); + switch (opcode->builtin_code()) { + case BuiltinOperator_IF: { + first_subgraph_index = + op->builtin_options_as_IfOptions()->then_subgraph_index(); + second_subgraph_index = + op->builtin_options_as_IfOptions()->else_subgraph_index(); + break; + } + case BuiltinOperator_CALL_ONCE: { + first_subgraph_index = + op->builtin_options_as_CallOnceOptions()->init_subgraph_index(); + break; + } + case BuiltinOperator_WHILE: { + first_subgraph_index = + op->builtin_options_as_WhileOptions()->cond_subgraph_index(); + second_subgraph_index = + op->builtin_options_as_WhileOptions()->body_subgraph_index(); + break; + } + default: { + break; + } + } + if (first_subgraph_index != -1) { + // Enter a new allocation scope for each subgraph. + allocation_scope_count_++; + TF_LITE_ENSURE_STATUS( + MarkAllocationLifetimes(first_subgraph_index, scratch_buffer_requests, + scratch_buffer_handles, allocations)); + } + if (second_subgraph_index != -1) { + // Enter a new allocation scope for each subgraph. + allocation_scope_count_++; + TF_LITE_ENSURE_STATUS( + MarkAllocationLifetimes(second_subgraph_index, scratch_buffer_requests, + scratch_buffer_handles, allocations)); + } + return kTfLiteOk; +} + +TfLiteStatus AllocationInfoBuilder::CreateAllocationInfo( + int scratch_buffer_request_count) { + size_t subgraph_offsets_length = model_->subgraphs()->size() * sizeof(size_t); + info_.subgraph_offsets = + reinterpret_cast(non_persistent_allocator_->AllocateTemp( + subgraph_offsets_length, alignof(size_t))); + if (info_.subgraph_offsets == nullptr) { + MicroPrintf( + "Failed to allocate memory for memory planning, %d bytes required", + subgraph_offsets_length); + return kTfLiteError; + } + size_t tensor_count = 0; + for (size_t subgraph_idx = 0; subgraph_idx < model_->subgraphs()->size(); + subgraph_idx++) { + // Add all tensors in each subgraph to the AllocationInfo array. Even weight + // tensors are added but marked with needs_allocating = false. Including all + // tensors in the graph here simplifies logic. + info_.subgraph_offsets[subgraph_idx] = tensor_count; + tensor_count += model_->subgraphs()->Get(subgraph_idx)->tensors()->size(); + } + info_.tensor_count = tensor_count; + + // Scratch buffer allocations follow tensor allocations, so the scratch offset + // is equal to the number of tensor allocations. + info_.scratch_offset = tensor_count; + info_.allocation_info_count = tensor_count + scratch_buffer_request_count; + info_.scratch_buffer_count = scratch_buffer_request_count; + size_t bytes = sizeof(AllocationInfo) * info_.allocation_info_count; + + // Allocate an array of AllocationInfo structs from the temp section. This + // struct will be used by AllocationInfoBuilder to find buffer usage. + info_.allocation_info = reinterpret_cast( + non_persistent_allocator_->AllocateTemp(bytes, alignof(AllocationInfo))); + if (info_.allocation_info == nullptr) { + MicroPrintf( + "Failed to allocate memory for memory planning, %d bytes required", + bytes); + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus AllocationInfoBuilder::FreeAllocationInfo() { + non_persistent_allocator_->DeallocateTemp( + reinterpret_cast(info_.allocation_info)); + non_persistent_allocator_->DeallocateTemp( + reinterpret_cast(info_.subgraph_offsets)); + return kTfLiteOk; +} + +TfLiteStatus AllocationInfoBuilder::ValidateSubgraph( + const SubGraph* subgraph, TfLiteEvalTensor* eval_tensors) { + uint32_t operators_size = NumSubgraphOperators(subgraph); + + for (uint32_t i = 0; i < operators_size; i++) { + const auto op = subgraph->operators()->Get(i); + for (size_t n = 0; + op->intermediates() != nullptr && n < op->intermediates()->size(); + n++) { + const int tensor_index = op->intermediates()->Get(n); + size_t tensor_size = -1; + TF_LITE_ENSURE_STATUS(TfLiteEvalTensorByteLength( + &eval_tensors[tensor_index], &tensor_size)); + if (tensor_size != 0) { + MicroPrintf( + "Does not support intermediate tensor with non-zero size: %d", + tensor_size); + return kTfLiteError; + } + } + } + return kTfLiteOk; +} + +TfLiteStatus AllocationInfoBuilder::InitializeAllocationInfo( + const int32_t* offline_offsets, SubgraphAllocations* allocations) { + AllocationInfo* allocation_info = info_.allocation_info; + // Initialize allocation info for every tensor in every subgraph. + for (size_t subgraph_idx = 0; subgraph_idx < model_->subgraphs()->size(); + subgraph_idx++) { + const SubGraph* subgraph = model_->subgraphs()->Get(subgraph_idx); + TfLiteEvalTensor* eval_tensors = allocations[subgraph_idx].tensors; + AllocationInfo* subgraph_allocation_info = + &allocation_info[info_.subgraph_offsets[subgraph_idx]]; + + // Ensure constraints are met. + TF_LITE_ENSURE_STATUS(ValidateSubgraph(subgraph, eval_tensors)); + + for (size_t i = 0; i < subgraph->tensors()->size(); ++i) { + AllocationInfo* current = &subgraph_allocation_info[i]; + current->output_ptr = &(eval_tensors[i].data.data); + + TF_LITE_ENSURE_STATUS( + TfLiteEvalTensorByteLength(&eval_tensors[i], ¤t->bytes)); + + current->first_created = kUninitializedLifetime; + current->last_used = kUninitializedLifetime; + current->needs_allocating = + (eval_tensors[i].data.data == nullptr) && + (!subgraph->tensors()->Get(i)->is_variable()) && + (current->bytes != 0); + if (offline_offsets) { + current->offline_offset = offline_offsets[i]; + } else { + current->offline_offset = kOnlinePlannedBuffer; + } + } + } + // Initialize allocation info for every scratch buffer. + AllocationInfo* scratch_allocation_info = + &allocation_info[info_.scratch_offset]; + for (size_t i = 0; i < info_.scratch_buffer_count; i++) { + AllocationInfo* current = &scratch_allocation_info[i]; + current->first_created = kUninitializedLifetime; + current->last_used = kUninitializedLifetime; + current->needs_allocating = true; + current->offline_offset = kOnlinePlannedBuffer; + } + return kTfLiteOk; +} + +TfLiteStatus AllocationInfoBuilder::MarkAllocationLifetimes( + int subgraph_idx, internal::ScratchBufferRequest* scratch_buffer_requests, + ScratchBufferHandle* scratch_buffer_handles, + SubgraphAllocations* allocations) { + const SubGraph* subgraph = model_->subgraphs()->Get(subgraph_idx); + + AllocationInfo* allocation_info = info_.allocation_info; + // Each subgraph's tensor allocations are in a contiguous block starting at + // subgraph_offsets_[subgraph index] with one entry per tensor. + AllocationInfo* subgraph_allocation_info = + &allocation_info[info_.subgraph_offsets[subgraph_idx]]; + + uint32_t operators_size = NumSubgraphOperators(subgraph); + // Mark all inputs as created at the start of the subgraph invocation. + for (size_t i = 0; + subgraph->inputs() != nullptr && i < subgraph->inputs()->size(); ++i) { + const int tensor_index = subgraph->inputs()->Get(i); + AllocationInfo* current = &subgraph_allocation_info[tensor_index]; + UpdateFirstCreated(current, allocation_scope_count_); + } + + for (uint32_t i = 0; i < operators_size; i++) { + // Each operator has a new allocation scope. + allocation_scope_count_++; + const auto* op = subgraph->operators()->Get(i); + // Figure out when the first creation and use of each tensor is. + for (size_t n = 0; op->outputs() != nullptr && n < op->outputs()->size(); + ++n) { + const int tensor_index = op->outputs()->Get(n); + AllocationInfo* current = &subgraph_allocation_info[tensor_index]; + UpdateFirstCreated(current, allocation_scope_count_); + } + + // Keep track of scope count before any subgraphs, so that scratch buffers' + // lifetime within a control flow op properly overlaps with all subgraphs. + int start_allocation_scope_count = allocation_scope_count_; + + // Control flow operators can invoke subgraphs. Plan these subgraphs + // before continuing on to the rest of the graph. + MarkSubgraphLifetimesIfNecessary(op, scratch_buffer_requests, + scratch_buffer_handles, allocations); + + // Figure out when the last use of each tensor is. + for (size_t n = 0; op->inputs() != nullptr && n < op->inputs()->size(); + ++n) { + const int tensor_index = op->inputs()->Get(n); + // Optional bias tensors can have an index of -1 when they are omitted. + if (tensor_index >= 0) { + AllocationInfo* current = &subgraph_allocation_info[tensor_index]; + // No need to update creation since it is either marked by the subgraph + // or producer op, or it is not part of the memory plan (weight, bias + // tensor). + UpdateLastUsed(current, allocation_scope_count_); + } + } + for (size_t n = 0; op->outputs() != nullptr && n < op->outputs()->size(); + ++n) { + const int tensor_index = op->outputs()->Get(n); + AllocationInfo* current = &subgraph_allocation_info[tensor_index]; + UpdateLastUsed(current, allocation_scope_count_); + } + + // Mark thse lifetime of scratch buffers belonging to the current node. This + // operation is O(N * M) where N is the total number of visited nodes and M + // is the total number of scratch buffers. + // TODO(b/217794030): Optimize this memory planning code. + AllocationInfo* scratch_allocation_info = + &allocation_info[info_.scratch_offset]; + for (size_t scratch_idx = 0; scratch_idx < info_.scratch_buffer_count; + scratch_idx++) { + internal::ScratchBufferRequest request = + scratch_buffer_requests[scratch_idx]; + AllocationInfo* current = &scratch_allocation_info[scratch_idx]; + if (request.node_idx == static_cast(i) && + request.subgraph_idx == static_cast(subgraph_idx)) { + ScratchBufferHandle* current_handle = + &(scratch_buffer_handles[scratch_idx]); + current->output_ptr = reinterpret_cast(¤t_handle->data); + current->bytes = request.bytes; + UpdateFirstCreated(current, start_allocation_scope_count); + UpdateLastUsed(current, allocation_scope_count_); + } + } + } + + // Mark all outputs as persistent to the end of the subgraph invocation. + for (size_t i = 0; + subgraph->outputs() != nullptr && i < subgraph->outputs()->size(); ++i) { + const int tensor_index = subgraph->outputs()->Get(i); + AllocationInfo* current = &subgraph_allocation_info[tensor_index]; + UpdateLastUsed(current, allocation_scope_count_); + } + return kTfLiteOk; +} + +// Get offline tensors allocation plan. See +// micro/docs/memory_management.md for more info. +TfLiteStatus AllocationInfoBuilder::GetOfflinePlannedOffsets( + const int32_t** offline_planner_offsets) { + if (model_->metadata()) { + for (size_t i = 0; i < model_->metadata()->size(); ++i) { + auto metadata = model_->metadata()->Get(i); + const size_t metadata_name_size = (size_t)metadata->name()->size(); + + if ((strncmp(metadata->name()->c_str(), kOfflineMemAllocMetadata, + std::min(metadata_name_size, + strlen(kOfflineMemAllocMetadata))) == 0) && + metadata_name_size == strlen(kOfflineMemAllocMetadata)) { + const flatbuffers::Vector>* buffers = + model_->buffers(); + auto* buffer = (*buffers)[metadata->buffer()]; + auto* array = buffer->data(); + const uint32_t* metadata_buffer = + reinterpret_cast(array->data()); + const size_t nbr_tensors = static_cast(metadata_buffer[2]); + *offline_planner_offsets = + reinterpret_cast(&metadata_buffer[3]); + + if (info_.tensor_count != nbr_tensors) { + MicroPrintf( + "Nbr of offline buffer offsets (%d) in metadata " + "not equal nbr tensors (%d)\n", + nbr_tensors, info_.tensor_count); + return kTfLiteError; + } + } + } + } + return kTfLiteOk; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocation_info.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocation_info.h new file mode 100644 index 000000000..946d9f5f6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocation_info.h @@ -0,0 +1,139 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MICRO_ALLOCATION_INFO_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_ALLOCATION_INFO_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/flatbuffer_conversions.h" +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/flatbuffer_utils.h" +#include "tensorflow/lite/micro/micro_allocator.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +// Used to hold information used during allocation calculations. +struct AllocationInfo { + size_t bytes; + void** output_ptr; + int first_created; + int last_used; + int32_t offline_offset; + bool needs_allocating; +}; + +// Used to hold the allocation info list and related metadata for the entire +// graph (including subgraphs). Since all subgraphs are planned together, the +// allocation info list contains allocations for all subgraphs. Track the offset +// into this list for each subgraph then reserve space to track all allocations. +// +// The AllocationInfo list is a contiguous list of allocations across all +// subgraphs and scratch buffers. Each element here is marked as +// st. The following is a possible +// AllocationInfo list: +// [s0t0, s0t1, s1t0, s2t1, s1t2, s3t0, s3t1, scratch0, scratch1, scratch2] +// +// For this example, the subgraph offsets would be [0, 2, 5] and the scratch +// offset would be 7. +struct GraphAllocationInfo { + AllocationInfo* allocation_info; + size_t allocation_info_count; + size_t* subgraph_offsets; + size_t scratch_offset; + size_t tensor_count; + size_t scratch_buffer_count; +}; + +// A helper class to construct AllocationInfo array. This array contains the +// lifetime of tensors / scratch_buffer and will be used to calculate the memory +// plan. Methods need to be called in order from `Create`, Init`, `Add*`, to +// `Finish`. +class AllocationInfoBuilder { + public: + AllocationInfoBuilder(const Model* model, + INonPersistentBufferAllocator* non_persistent_allocator) + : model_(model), non_persistent_allocator_(non_persistent_allocator) {} + + // Check if model contains offline planned buffer offsets. + // - If there's no metadata available, offline_planner_offsets is not set + // - If there's metadata available, offline_planner_offsets will point to the + // first offset in the metadata buffer list. + TfLiteStatus GetOfflinePlannedOffsets( + const int32_t** offline_planner_offsets); + + // Allocate memory for the allocation info array as well as offsets into that + // array for each subgraph. + TfLiteStatus CreateAllocationInfo(int scratch_buffer_request_count); + + // Release memory used for the allocation info array. + TfLiteStatus FreeAllocationInfo(); + + // Initialize AllocationInfo for all tensors and scratch buffers in the graph. + TfLiteStatus InitializeAllocationInfo(const int32_t* offline_offsets, + SubgraphAllocations* allocations); + + // Mark the scope of each tensor and scratch buffer across the graph. Enter + // all possible subgraphs invoked by each control flow operator. This method + // marks the maximum lifetime of each buffer so that tensors are correctly + // planned for all valid invocation flows. + TfLiteStatus MarkAllocationLifetimes( + int subgraph_idx, internal::ScratchBufferRequest* scratch_buffer_request, + ScratchBufferHandle* scratch_buffer_handles, + SubgraphAllocations* allocations); + + // Identify control flow operators and recursively mark all subgraphs which + // that operator can invoke. The lifetime of all tensors within a subgraph + // can only be extended. The order of subgraph invocation does not matter + // since subgraphs within the same control flow operator are executed + // within their own allocation scope (planned buffers in a subgraph cannot + // persist beyond the end of that subgraph's invocation). + TfLiteStatus MarkSubgraphLifetimesIfNecessary( + const Operator* op, + internal::ScratchBufferRequest* scratch_buffer_requests, + ScratchBufferHandle* scratch_buffer_handles, + SubgraphAllocations* allocations); + + // Returns the number of allocations. + int AllocationCount() const { return info_.allocation_info_count; } + + // Returns a pointer to the built AllocationInfo array. + AllocationInfo* Finish() const { return info_.allocation_info; } + + private: + // Mark the given Allocation info as first created at the specified allocation + // scope count. Only the first creation must be recorded since the allocation + // scope count monotonically increases throughout the lifetime marking + // process. + void UpdateFirstCreated(AllocationInfo* current, int allocation_scope_count); + + // Mark the given AllocationInfo as last used at the specified allocation + // scope + // count. Update the last used marker every time, since the allocation scope + // count monotonically increases through the lifetime marking process. + void UpdateLastUsed(AllocationInfo* current, int allocation_scope_count); + + // Validate if a subgraph satisfies assumptions. + TfLiteStatus ValidateSubgraph(const SubGraph* subgraph, + TfLiteEvalTensor* eval_tensors); + + const tflite::Model* model_ = nullptr; + INonPersistentBufferAllocator* non_persistent_allocator_ = nullptr; + GraphAllocationInfo info_; + int allocation_scope_count_ = 0; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_ALLOCATION_INFO_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocator.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocator.cpp new file mode 100644 index 000000000..06cef9d79 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocator.cpp @@ -0,0 +1,940 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/micro_allocator.h" + +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/c_api_types.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/flatbuffer_conversions.h" +#include "tensorflow/lite/core/api/op_resolver.h" +#include "tensorflow/lite/core/api/tensor_utils.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/flatbuffer_utils.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/memory_planner/greedy_memory_planner.h" +#include "tensorflow/lite/micro/memory_planner/micro_memory_planner.h" +#include "tensorflow/lite/micro/micro_allocation_info.h" +#include "tensorflow/lite/micro/micro_arena_constants.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/schema/schema_generated.h" +#include "tensorflow/lite/schema/schema_utils.h" + +namespace tflite { + +namespace { + +// Maximum number of scratch buffer requests per operator. Operator kernels that +// request more than this value will receive an exception. +constexpr size_t kMaxScratchBuffersPerOp = 12; + +// Sentinel value used as a placeholder to mark a ScratchBufferRequest request +// needs a node id assignment. +constexpr int kUnassignedScratchBufferRequestIndex = -1; + +const TfLiteIntArray kZeroLengthIntArray = {}; + +class MicroBuiltinDataAllocator : public BuiltinDataAllocator { + public: + explicit MicroBuiltinDataAllocator( + IPersistentBufferAllocator* persistent_allocator) + : persistent_allocator_(persistent_allocator) {} + + void* Allocate(size_t size, size_t alignment_hint) override { + return persistent_allocator_->AllocatePersistentBuffer(size, + alignment_hint); + } + void Deallocate(void* data) override { + // Do not deallocate, builtin data needs to be available for the life time + // of the model. + } + + TF_LITE_REMOVE_VIRTUAL_DELETE + + private: + IPersistentBufferAllocator* persistent_allocator_; +}; + +TfLiteStatus CreatePlan(MicroMemoryPlanner* planner, + const AllocationInfo* allocation_info, + size_t allocation_info_size) { + // Add the tensors to our allocation plan. + for (size_t i = 0; i < allocation_info_size; ++i) { + const AllocationInfo* current = &allocation_info[i]; + if (current->needs_allocating) { + size_t aligned_bytes_required = + AlignSizeUp(current->bytes, MicroArenaBufferAlignment()); + if (current->offline_offset == kOnlinePlannedBuffer) { + TF_LITE_ENSURE_STATUS(planner->AddBuffer(aligned_bytes_required, + current->first_created, + current->last_used)); + } else { + TF_LITE_ENSURE_STATUS( + planner->AddBuffer(aligned_bytes_required, current->first_created, + current->last_used, current->offline_offset)); + } + } + } + return kTfLiteOk; +} + +TfLiteStatus CommitPlan(MicroMemoryPlanner* planner, uint8_t* starting_point, + const AllocationInfo* allocation_info, + size_t allocation_info_size) { + // Figure out the actual memory addresses for each buffer, based on the plan. + int planner_index = 0; + for (size_t i = 0; i < allocation_info_size; ++i) { + const AllocationInfo* current = &allocation_info[i]; + if (current->needs_allocating) { + int offset = -1; + TF_LITE_ENSURE_STATUS( + planner->GetOffsetForBuffer(planner_index, &offset)); + *current->output_ptr = reinterpret_cast(starting_point + offset); + ++planner_index; + } + } + return kTfLiteOk; +} + +IPersistentBufferAllocator* CreatePersistentArenaAllocator(uint8_t* buffer_head, + size_t buffer_size) { + // Align the actually used area by the tail because persistent buffer grows + // from the bottom to top. + uint8_t* aligned_buffer_tail = + AlignPointerDown(buffer_head + buffer_size, MicroArenaBufferAlignment()); + size_t aligned_buffer_size = aligned_buffer_tail - buffer_head; + PersistentArenaBufferAllocator tmp = + PersistentArenaBufferAllocator(buffer_head, aligned_buffer_size); + + // Allocate enough bytes from the buffer to create a + // SingleArenaBufferAllocator. The new instance will use the current adjusted + // tail buffer from the tmp allocator instance. + uint8_t* allocator_buffer = + tmp.AllocatePersistentBuffer(sizeof(PersistentArenaBufferAllocator), + alignof(PersistentArenaBufferAllocator)); + // Use the default copy constructor to populate internal states. + return new (allocator_buffer) PersistentArenaBufferAllocator(tmp); +} + +// NonPersistentBufferAllocator instance is created in the persistent buffer +// because it has to be persistent to keep track of the non-persistent buffer +// information. +INonPersistentBufferAllocator* CreateNonPersistentArenaAllocator( + uint8_t* buffer_head, size_t buffer_size, + IPersistentBufferAllocator* persistent_buffer_allocator) { + uint8_t* allocator_buffer = + persistent_buffer_allocator->AllocatePersistentBuffer( + sizeof(NonPersistentArenaBufferAllocator), + alignof(NonPersistentArenaBufferAllocator)); + // Align the actually used area by the head because persistent buffer grows + // from the head to bottom. + uint8_t* aligned_buffer_head = + AlignPointerUp(buffer_head, MicroArenaBufferAlignment()); + size_t aligned_buffer_size = buffer_head + buffer_size - aligned_buffer_head; + + INonPersistentBufferAllocator* non_persistent_buffer_allocator = + new (allocator_buffer) NonPersistentArenaBufferAllocator( + aligned_buffer_head, aligned_buffer_size); + return non_persistent_buffer_allocator; +} + +} // namespace + +namespace internal { + +// Returns a pointer to any buffer associated with the flatbuffer tensor. Can +// return nullptr if no buffer is found. +void* GetFlatbufferTensorBuffer( + const tflite::Tensor& flatbuffer_tensor, + const flatbuffers::Vector>* buffers) { + // We need to figure out where the actual contents of this tensor are stored + // in memory. We'll check to see if there's a serialized buffer (pretty much + // the same as a constant op in TensorFlow) associated with this tensor first, + // and if there is update the runtime structure to point to its location in + // memory. + // First see if there's any buffer information in the serialized tensor. + // TODO(b/170379532): Add better unit tests to validate flatbuffer values. + void* out_buffer = nullptr; + if (auto* buffer = (*buffers)[flatbuffer_tensor.buffer()]) { + // If we've found a buffer, does it have any data? + if (auto* array = buffer->data()) { + // If it has any data, is the data size larger than zero? + if (array->size()) { + // We've found a buffer with valid data, so update the runtime tensor + // data structure to point to it. + out_buffer = const_cast(static_cast(array->data())); + } + } + // TODO(petewarden): It's not clear in what circumstances we could have a + // buffer in the serialized tensor, but it doesn't have any data in it. Is + // that a validly-generated file, and if so what does it mean, or is it an + // error condition? It would be good to tighten up the specification to make + // it less ambiguous. + } + return out_buffer; +} + +TfLiteStatus InitializeTfLiteTensorFromFlatbuffer( + IPersistentBufferAllocator* persistent_buffer_allocator, + INonPersistentBufferAllocator* non_persistent_buffer_allocator, + bool allocate_temp, const tflite::Tensor& flatbuffer_tensor, + const flatbuffers::Vector>* buffers, + TfLiteTensor* result) { + TFLITE_DCHECK(result != nullptr); + + *result = {}; + // Make sure the serialized type is one we know how to deal with, and convert + // it from a flatbuffer enum into a constant used by the kernel C API. + TF_LITE_ENSURE_STATUS(ConvertTensorType(flatbuffer_tensor.type(), + &result->type, + tflite::GetMicroErrorReporter())); + // Make sure we remember if the serialized tensor is designated as a variable. + result->is_variable = flatbuffer_tensor.is_variable(); + + result->data.data = GetFlatbufferTensorBuffer(flatbuffer_tensor, buffers); + + // TODO(petewarden): Some of these paths aren't getting enough testing + // coverage, so we should figure out some tests that exercise them. + if (result->data.data == nullptr) { + // The tensor contents haven't been set from a serialized buffer, so + // make a note that they will be allocated from memory. The actual + // allocation won't happen until later. + result->allocation_type = kTfLiteArenaRw; + } else { + // We set the data from a serialized buffer, so record tha. + result->allocation_type = kTfLiteMmapRo; + } + + // Figure out what the size in bytes of the buffer is and store it. + size_t type_size; + TF_LITE_ENSURE_STATUS( + BytesRequiredForTensor(flatbuffer_tensor, &result->bytes, &type_size)); + + if (flatbuffer_tensor.shape() == nullptr) { + // flatbuffer_tensor.shape() can return a nullptr in the case of a scalar + // tensor. + // TODO(b/188459715): figure out why const_cast is required here. + result->dims = const_cast(&kZeroLengthIntArray); + } else { + // TFLM doesn't allow reshaping the tensor which requires dynamic memory + // allocation so it is safe to drop the const qualifier. In the future, if + // we really want to update the tensor shape, we can always pass in a new + // TfLiteIntArray - especially we have to do so if the dimension is + result->dims = FlatBufferVectorToTfLiteTypeArray(flatbuffer_tensor.shape()); + } + + // Copy the quantization information from the serialized data. + const auto* src_quantization = flatbuffer_tensor.quantization(); + if (src_quantization && src_quantization->scale() && + (src_quantization->scale()->size() > 0) && + src_quantization->zero_point() && + (src_quantization->zero_point()->size() > 0)) { + // Always populate the TfLiteTensor.params field, even if there are + // per-channel quantization parameters. + result->params.scale = src_quantization->scale()->Get(0); + // Note that the zero_point field in the FlatBuffers schema is a 64-bit + // integer, but the zero_point field in the TfLiteQuantizationParams struct + // is a 32-bit integer. + result->params.zero_point = + static_cast(src_quantization->zero_point()->Get(0)); + + // Populate per-channel quantization params. + int channels = src_quantization->scale()->size(); + TfLiteAffineQuantization* quantization = + allocate_temp + ? reinterpret_cast( + non_persistent_buffer_allocator->AllocateTemp( + sizeof(TfLiteAffineQuantization), + alignof(TfLiteAffineQuantization))) + : reinterpret_cast( + persistent_buffer_allocator->AllocatePersistentBuffer( + sizeof(TfLiteAffineQuantization), + alignof(TfLiteAffineQuantization))); + if (quantization == nullptr) { + MicroPrintf("Unable to allocate TfLiteAffineQuantization.\n"); + return kTfLiteError; + } + + // TODO(b/153688719): Reduce tail allocation by using a global zero-point + // buffer. This value can not be reused from the flatbuffer since the + // zero_point is stored as a int64_t. + quantization->zero_point = + allocate_temp + ? reinterpret_cast( + non_persistent_buffer_allocator->AllocateTemp( + TfLiteIntArrayGetSizeInBytes(channels), + alignof(TfLiteIntArray))) + : reinterpret_cast( + persistent_buffer_allocator->AllocatePersistentBuffer( + TfLiteIntArrayGetSizeInBytes(channels), + alignof(TfLiteIntArray))); + if (quantization->zero_point == nullptr) { + MicroPrintf("Unable to allocate quantization->zero_point.\n"); + return kTfLiteError; + } + + quantization->scale = + FlatBufferVectorToTfLiteTypeArray(src_quantization->scale()); + + quantization->zero_point->size = channels; + int* zero_point_data = quantization->zero_point->data; + for (int i = 0; i < channels; i++) { + // As a space-saving optimization, zero point arrays for weights can be + // reduced to a single value, since all zero points for weights are 0. + zero_point_data[i] = src_quantization->zero_point()->size() == + src_quantization->scale()->size() + ? src_quantization->zero_point()->Get(i) + : src_quantization->zero_point()->Get(0); + } + // TODO(rocky): Need to add a micro_allocator test case that fails when + // this is not copied: + quantization->quantized_dimension = src_quantization->quantized_dimension(); + + result->quantization = {kTfLiteAffineQuantization, quantization}; + } + return kTfLiteOk; +} + +TfLiteStatus InitializeTfLiteEvalTensorFromFlatbuffer( + const tflite::Tensor& flatbuffer_tensor, + const flatbuffers::Vector>* buffers, + TfLiteEvalTensor* result) { + *result = {}; + // Make sure the serialized type is one we know how to deal with, and convert + // it from a flatbuffer enum into a constant used by the kernel C API. + TF_LITE_ENSURE_STATUS(ConvertTensorType(flatbuffer_tensor.type(), + &result->type, + tflite::GetMicroErrorReporter())); + + result->data.data = GetFlatbufferTensorBuffer(flatbuffer_tensor, buffers); + + if (flatbuffer_tensor.shape() == nullptr) { + // flatbuffer_tensor.shape() can return a nullptr in the case of a scalar + // tensor. + result->dims = const_cast(&kZeroLengthIntArray); + } else { + result->dims = FlatBufferVectorToTfLiteTypeArray(flatbuffer_tensor.shape()); + } + return kTfLiteOk; +} + +} // namespace internal + +size_t MicroAllocator::GetDefaultTailUsage(bool is_memory_planner_given) { + // TODO(b/208703041): a template version of AlignSizeUp to make expression + // shorter. + size_t total_size = + AlignSizeUp(sizeof(SingleArenaBufferAllocator), + alignof(SingleArenaBufferAllocator)) + + AlignSizeUp(sizeof(MicroAllocator), alignof(MicroAllocator)) + + AlignSizeUp(sizeof(MicroBuiltinDataAllocator), + alignof(MicroBuiltinDataAllocator)) + + AlignSizeUp(sizeof(SubgraphAllocations), alignof(SubgraphAllocations)); + if (!is_memory_planner_given) { + total_size += + AlignSizeUp(sizeof(GreedyMemoryPlanner), alignof(GreedyMemoryPlanner)); + } + return total_size; +} + +MicroAllocator::MicroAllocator(SingleArenaBufferAllocator* memory_allocator, + MicroMemoryPlanner* memory_planner) + : non_persistent_buffer_allocator_(memory_allocator), + persistent_buffer_allocator_(memory_allocator), + memory_planner_(memory_planner), + model_is_allocating_(false) {} + +MicroAllocator::MicroAllocator( + IPersistentBufferAllocator* persistent_buffer_allocator, + INonPersistentBufferAllocator* non_persistent_buffer_allocator, + MicroMemoryPlanner* memory_planner) + : non_persistent_buffer_allocator_(non_persistent_buffer_allocator), + persistent_buffer_allocator_(persistent_buffer_allocator), + memory_planner_(memory_planner), + model_is_allocating_(false) {} + +MicroAllocator::~MicroAllocator() {} + +MicroAllocator* MicroAllocator::Create(uint8_t* tensor_arena, size_t arena_size, + MicroMemoryPlanner* memory_planner) { + uint8_t* aligned_arena = + AlignPointerUp(tensor_arena, MicroArenaBufferAlignment()); + size_t aligned_arena_size = tensor_arena + arena_size - aligned_arena; + SingleArenaBufferAllocator* memory_allocator = + SingleArenaBufferAllocator::Create(aligned_arena, aligned_arena_size); + + return Create(memory_allocator, memory_planner); +} + +MicroAllocator* MicroAllocator::Create(uint8_t* tensor_arena, + size_t arena_size) { + uint8_t* aligned_arena = + AlignPointerUp(tensor_arena, MicroArenaBufferAlignment()); + size_t aligned_arena_size = tensor_arena + arena_size - aligned_arena; + SingleArenaBufferAllocator* memory_allocator = + SingleArenaBufferAllocator::Create(aligned_arena, aligned_arena_size); + + // By default create GreedyMemoryPlanner. + // If a different MemoryPlanner is needed, use the other api. + uint8_t* memory_planner_buffer = memory_allocator->AllocatePersistentBuffer( + sizeof(GreedyMemoryPlanner), alignof(GreedyMemoryPlanner)); + GreedyMemoryPlanner* memory_planner = + new (memory_planner_buffer) GreedyMemoryPlanner(); + + return Create(memory_allocator, memory_planner); +} + +MicroAllocator* MicroAllocator::Create( + SingleArenaBufferAllocator* memory_allocator, + MicroMemoryPlanner* memory_planner) { + TFLITE_DCHECK(memory_allocator != nullptr); + TFLITE_DCHECK(memory_planner != nullptr); + + uint8_t* allocator_buffer = memory_allocator->AllocatePersistentBuffer( + sizeof(MicroAllocator), alignof(MicroAllocator)); + MicroAllocator* allocator = new (allocator_buffer) + MicroAllocator(memory_allocator, memory_allocator, memory_planner); + return allocator; +} + +MicroAllocator* MicroAllocator::Create(uint8_t* persistent_tensor_arena, + size_t persistent_arena_size, + uint8_t* non_persistent_tensor_arena, + size_t non_persistent_arena_size) { + TFLITE_DCHECK(persistent_tensor_arena != nullptr); + TFLITE_DCHECK(non_persistent_tensor_arena != nullptr); + TFLITE_DCHECK(persistent_tensor_arena != non_persistent_tensor_arena); + + IPersistentBufferAllocator* persistent_buffer_allocator = + CreatePersistentArenaAllocator(persistent_tensor_arena, + persistent_arena_size); + INonPersistentBufferAllocator* non_persistent_buffer_allocator = + CreateNonPersistentArenaAllocator(non_persistent_tensor_arena, + non_persistent_arena_size, + persistent_buffer_allocator); + + uint8_t* memory_planner_buffer = + persistent_buffer_allocator->AllocatePersistentBuffer( + sizeof(GreedyMemoryPlanner), alignof(GreedyMemoryPlanner)); + GreedyMemoryPlanner* memory_planner = + new (memory_planner_buffer) GreedyMemoryPlanner(); + + uint8_t* micro_allocator_buffer = + persistent_buffer_allocator->AllocatePersistentBuffer( + sizeof(MicroAllocator), alignof(MicroAllocator)); + MicroAllocator* allocator = new (micro_allocator_buffer) + MicroAllocator(persistent_buffer_allocator, + non_persistent_buffer_allocator, memory_planner); + return allocator; +} + +SubgraphAllocations* MicroAllocator::StartModelAllocation(const Model* model) { + TFLITE_DCHECK(model != nullptr); + + if (model_is_allocating_) { + MicroPrintf( + "MicroAllocator: Model allocation started before " + "finishing previously allocated model"); + return nullptr; + } + + model_is_allocating_ = true; + + uint8_t* data_allocator_buffer = + persistent_buffer_allocator_->AllocatePersistentBuffer( + sizeof(MicroBuiltinDataAllocator), + alignof(MicroBuiltinDataAllocator)); + builtin_data_allocator_ = new (data_allocator_buffer) + MicroBuiltinDataAllocator(persistent_buffer_allocator_); + + if (InitScratchBufferData() != kTfLiteOk) { + return nullptr; + } + + // Allocate struct to store eval tensors, nodes and registrations. + SubgraphAllocations* output = reinterpret_cast( + persistent_buffer_allocator_->AllocatePersistentBuffer( + sizeof(SubgraphAllocations) * model->subgraphs()->size(), + alignof(SubgraphAllocations))); + if (output == nullptr) { + MicroPrintf("Failed to allocate memory for model metadata."); + return nullptr; + } + + if (AllocateTfLiteEvalTensors(model, output) != kTfLiteOk || + AllocateNodeAndRegistrations(model, output) != kTfLiteOk) { + return nullptr; + } + return output; +} + +TfLiteStatus MicroAllocator::FinishModelAllocation( + const Model* model, SubgraphAllocations* subgraph_allocations, + ScratchBufferHandle** scratch_buffer_handles) { + if (!model_is_allocating_) { + MicroPrintf( + "MicroAllocator: Model allocation finished before " + "starting allocating model"); + return kTfLiteError; + } + + // Allocate scratch buffer metadata. + TF_LITE_ENSURE_STATUS(AllocateScratchBufferHandles( + scratch_buffer_handles, scratch_buffer_request_count_)); + + // Allocate buffers for variable tensors. + for (size_t subgraph_idx = 0; subgraph_idx < model->subgraphs()->size(); + subgraph_idx++) { + const SubGraph* subgraph = model->subgraphs()->Get(subgraph_idx); + TFLITE_DCHECK(subgraph != nullptr); + TF_LITE_ENSURE_STATUS(AllocateVariables( + subgraph, subgraph_allocations[subgraph_idx].tensors)); + } + + // Plan all subgraphs and scratch buffers together. + TF_LITE_ENSURE_STATUS(CommitStaticMemoryPlan(model, subgraph_allocations, + *scratch_buffer_handles)); + model_is_allocating_ = false; + return kTfLiteOk; +} + +void* MicroAllocator::AllocatePersistentBuffer(size_t bytes) { + return persistent_buffer_allocator_->AllocatePersistentBuffer( + bytes, MicroArenaBufferAlignment()); +} + +TfLiteStatus MicroAllocator::RequestScratchBufferInArena(size_t bytes, + int subgraph_idx, + int* buffer_idx) { + // All scratch buffer requests are stored in the head section of the arena + // when a model is in the prepare phase. First align a scratch buffer request + // pointer to the start of the head: + internal::ScratchBufferRequest* requests = GetScratchBufferRequests(); + + // Count the number of requested scratch buffers for the current node: + size_t current_node_request_count = 0; + for (size_t i = 0; i < scratch_buffer_request_count_; ++i) { + if (requests[i].node_idx == kUnassignedScratchBufferRequestIndex) { + ++current_node_request_count; + } + } + + // First, ensure that the per-kernel request has not exceeded the limit: + if (current_node_request_count >= kMaxScratchBuffersPerOp) { + MicroPrintf("Scratch buffer request exeeds limit per operator (%d)", + kMaxScratchBuffersPerOp); + return kTfLiteError; + } + + // Initialize and assign values for the request at the current index: + internal::ScratchBufferRequest* current_request = + &requests[scratch_buffer_request_count_]; + *current_request = {}; + // Assign -1 as a sentinel value that will be updated when the node finishes + // allocating: + current_request->bytes = bytes; + current_request->node_idx = kUnassignedScratchBufferRequestIndex; + current_request->subgraph_idx = subgraph_idx; + + // Assign the current request index to the out-param: + *buffer_idx = scratch_buffer_request_count_; + + // Bump the request count to prepare for the next request: + ++scratch_buffer_request_count_; + return kTfLiteOk; +} + +TfLiteStatus MicroAllocator::FinishPrepareNodeAllocations(int node_id) { + // When a node has finished preparing, all temp allocations performed by the + // kernel should be cleaned up: + TF_LITE_ENSURE_STATUS(ResetTempAllocations()); + + // Find and update any new scratch buffer requests for the current node: + internal::ScratchBufferRequest* requests = GetScratchBufferRequests(); + + for (size_t i = 0; i < scratch_buffer_request_count_; ++i) { + // A request with a node_idx of -1 is a sentinel value used to indicate this + // was a new request for the current node. The allocator finally knows the + // node index at this point. Assign the value and update the list of new + // requests so the head section can be adjusted to allow for the next kernel + // to allocate at most kMaxScratchBuffersPerOp requests: + if (requests[i].node_idx == kUnassignedScratchBufferRequestIndex) { + requests[i].node_idx = node_id; + } + } + + // Ensure that the head is re-adjusted to allow for another at-most + // kMaxScratchBuffersPerOp scratch buffer requests in the next operator: + TF_LITE_ENSURE_STATUS(non_persistent_buffer_allocator_->ResizeBuffer( + scratch_buffer_head_, + sizeof(internal::ScratchBufferRequest) * + (scratch_buffer_request_count_ + kMaxScratchBuffersPerOp), + alignof(internal::ScratchBufferRequest))); + + return kTfLiteOk; +} + +size_t MicroAllocator::used_bytes() const { + return non_persistent_buffer_allocator_->GetNonPersistentUsedBytes() + + persistent_buffer_allocator_->GetPersistentUsedBytes(); +} + +TfLiteStatus MicroAllocator::AllocateNodeAndRegistrations( + const Model* model, SubgraphAllocations* subgraph_allocations) { + TFLITE_DCHECK(subgraph_allocations != nullptr); + + for (size_t subgraph_idx = 0; subgraph_idx < model->subgraphs()->size(); + subgraph_idx++) { + const SubGraph* subgraph = model->subgraphs()->Get(subgraph_idx); + TFLITE_DCHECK(subgraph != nullptr); + + uint32_t operators_size = NumSubgraphOperators(subgraph); + + // Initialize NodeAndRegistrations for the subgraph. + NodeAndRegistration* output = reinterpret_cast( + persistent_buffer_allocator_->AllocatePersistentBuffer( + sizeof(NodeAndRegistration) * operators_size, + alignof(NodeAndRegistration))); + if (output == nullptr) { + MicroPrintf("Failed to allocate memory for node_and_registrations."); + return kTfLiteError; + } + subgraph_allocations[subgraph_idx].node_and_registrations = output; + } + return kTfLiteOk; +} + +TfLiteTensor* MicroAllocator::AllocatePersistentTfLiteTensor( + const Model* model, const SubgraphAllocations* subgraph_allocations, + int tensor_index, int subgraph_index) { + const SubGraph* subgraph = model->subgraphs()->Get(subgraph_index); + TFLITE_DCHECK(subgraph != nullptr); + + // This value is allocated from persistent arena space. It is guaranteed to be + // around for the lifetime of the application. + TfLiteTensor* tensor = AllocatePersistentTfLiteTensorInternal(); + + // Populate any fields from the flatbuffer, since this TfLiteTensor struct is + // allocated in the persistent section of the arena, ensure that additional + // allocations also take place in that section of the arena. + if (PopulateTfLiteTensorFromFlatbuffer( + model, tensor, tensor_index, subgraph_index, + /*allocate_temp=*/false) != kTfLiteOk) { + MicroPrintf( + "Failed to populate a persistent TfLiteTensor struct " + "from flatbuffer data!"); + return nullptr; + } + + if (subgraph_allocations != nullptr) { + // Tensor buffers that are allocated at runtime (e.g. non-weight buffers) + // and not located in the flatbuffer are stored on the pre-allocated list of + // TfLiteEvalTensors structs. These structs are the source of truth, simply + // point the corresponding buffer to the new TfLiteTensor data value. + tensor->data.data = + subgraph_allocations[subgraph_index].tensors[tensor_index].data.data; + // TfLiteEvalTensor structs must also be the source of truth for the + // TfLiteTensor dims. + tensor->dims = + subgraph_allocations[subgraph_index].tensors[tensor_index].dims; + } + return tensor; +} + +void MicroAllocator::DeallocateTempTfLiteTensor(TfLiteTensor* tensor) { + TFLITE_DCHECK(tensor != nullptr); + + if (tensor->quantization.type == kTfLiteAffineQuantization) { + TFLITE_DCHECK(tensor->quantization.params != nullptr); + TfLiteAffineQuantization* quantization = + reinterpret_cast( + tensor->quantization.params); + + non_persistent_buffer_allocator_->DeallocateTemp( + reinterpret_cast(quantization->zero_point)); + non_persistent_buffer_allocator_->DeallocateTemp( + reinterpret_cast(quantization)); + } + + // Clear the data in case someone still access tensor arena by mistake + tensor->quantization.type = kTfLiteNoQuantization; + tensor->quantization.params = nullptr; + tensor->data.data = nullptr; + tensor->dims = nullptr; + non_persistent_buffer_allocator_->DeallocateTemp( + reinterpret_cast(tensor)); +} + +TfLiteTensor* MicroAllocator::AllocateTempTfLiteTensor( + const Model* model, const SubgraphAllocations* subgraph_allocations, + int tensor_index, int subgraph_index) { + const SubGraph* subgraph = model->subgraphs()->Get(subgraph_index); + TFLITE_DCHECK(subgraph != nullptr); + + // This value is allocated from temporary arena space. It is guaranteed to be + // around for at least the scope of the calling function. Since this struct + // allocation takes place in temp space, no need to own or cleanup. + TfLiteTensor* tensor = reinterpret_cast( + non_persistent_buffer_allocator_->AllocateTemp(sizeof(TfLiteTensor), + alignof(TfLiteTensor))); + + // Populate any fields from the flatbuffer, since this TfLiteTensor struct is + // allocated in the temp section of the arena, ensure that additional + // allocations also take place in that section of the arena. + if (PopulateTfLiteTensorFromFlatbuffer(model, tensor, tensor_index, + subgraph_index, + /*allocate_temp=*/true) != kTfLiteOk) { + MicroPrintf( + "Failed to populate a temp TfLiteTensor struct from flatbuffer data!"); + return nullptr; + } + + if (subgraph_allocations != nullptr) { + // Tensor buffers that are allocated at runtime (e.g. non-weight buffers) + // and not located in the flatbuffer are stored on the pre-allocated list of + // TfLiteEvalTensors structs. These structs are the source of truth, simply + // point the corresponding buffer to the new TfLiteTensor data value. + tensor->data.data = + subgraph_allocations[subgraph_index].tensors[tensor_index].data.data; + // TfLiteEvalTensor structs must also be the source of truth for the + // TfLiteTensor dims. + tensor->dims = + subgraph_allocations[subgraph_index].tensors[tensor_index].dims; + } + return tensor; +} + +TfLiteStatus MicroAllocator::ResetTempAllocations() { + return non_persistent_buffer_allocator_->ResetTempAllocations(); +} + +bool MicroAllocator::IsAllTempDeallocated() { + return non_persistent_buffer_allocator_->IsAllTempDeallocated(); +} + +TfLiteStatus MicroAllocator::AllocateTfLiteEvalTensors( + const Model* model, SubgraphAllocations* subgraph_allocations) { + TFLITE_DCHECK(subgraph_allocations != nullptr); + + for (size_t subgraph_idx = 0; subgraph_idx < model->subgraphs()->size(); + subgraph_idx++) { + const SubGraph* subgraph = model->subgraphs()->Get(subgraph_idx); + TFLITE_DCHECK(subgraph != nullptr); + + size_t alloc_count = subgraph->tensors()->size(); + TfLiteEvalTensor* tensors = reinterpret_cast( + persistent_buffer_allocator_->AllocatePersistentBuffer( + sizeof(TfLiteEvalTensor) * alloc_count, alignof(TfLiteEvalTensor))); + if (tensors == nullptr) { + MicroPrintf( + "Failed to allocate memory for context->eval_tensors, " + "%d bytes required", + sizeof(TfLiteEvalTensor) * alloc_count); + return kTfLiteError; + } + + for (size_t i = 0; i < alloc_count; ++i) { + TfLiteStatus status = internal::InitializeTfLiteEvalTensorFromFlatbuffer( + *subgraph->tensors()->Get(i), model->buffers(), &tensors[i]); + if (status != kTfLiteOk) { + MicroPrintf("Failed to initialize tensor %d", i); + return kTfLiteError; + } + } + subgraph_allocations[subgraph_idx].tensors = tensors; + } + return kTfLiteOk; +} + +TfLiteStatus MicroAllocator::AllocateVariables(const SubGraph* subgraph, + TfLiteEvalTensor* eval_tensors) { + for (size_t i = 0; i < subgraph->tensors()->size(); ++i) { + auto* tensor = subgraph->tensors()->Get(i); + if (tensor->is_variable()) { + size_t buffer_size; + TF_LITE_ENSURE_STATUS( + TfLiteEvalTensorByteLength(&eval_tensors[i], &buffer_size)); + + eval_tensors[i].data.data = + persistent_buffer_allocator_->AllocatePersistentBuffer( + buffer_size, MicroArenaBufferAlignment()); + + if (eval_tensors[i].data.data == nullptr) { + MicroPrintf("Failed to allocate variable tensor of size %d", + buffer_size); + return kTfLiteError; + } + } + } + return kTfLiteOk; +} + +TfLiteTensor* MicroAllocator::AllocatePersistentTfLiteTensorInternal() { + return reinterpret_cast( + persistent_buffer_allocator_->AllocatePersistentBuffer( + sizeof(TfLiteTensor), alignof(TfLiteTensor))); +} + +TfLiteStatus MicroAllocator::PopulateTfLiteTensorFromFlatbuffer( + const Model* model, TfLiteTensor* tensor, int tensor_index, + int subgraph_idx, bool allocate_temp) { + // TODO(b/162311891): This method serves as a stub to ensure quantized + // allocations in the tail can be recorded. Once the interpreter has APIs for + // accessing buffers on TfLiteEvalTensor this method can be dropped. + return internal::InitializeTfLiteTensorFromFlatbuffer( + persistent_buffer_allocator_, non_persistent_buffer_allocator_, + allocate_temp, + *model->subgraphs()->Get(subgraph_idx)->tensors()->Get(tensor_index), + model->buffers(), tensor); +} + +TfLiteStatus MicroAllocator::CommitStaticMemoryPlan( + const Model* model, SubgraphAllocations* allocations, + ScratchBufferHandle* scratch_buffer_handles) { + size_t head_usage = 0; + // Create static memory plan + // 1. Calculate AllocationInfo to know the lifetime of each tensor/buffer. + // 2. Add them into the planner (such as the GreedyMemoryPlanner). + // 3. Static memory planning using the planner. + // 4. Set tensor/buffer pointers based on the offsets from the previous step. + // + // Note that AllocationInfo is only needed for creating the plan. It will be + // allocated from the temp section and cleaned up at the bottom of this + // function. + + // Use the AllocationInfoBuilder class to help determine where buffers are + // used in the subgraph. + AllocationInfoBuilder builder(model, non_persistent_buffer_allocator_); + TF_LITE_ENSURE_STATUS( + builder.CreateAllocationInfo(scratch_buffer_request_count_)); + + const int32_t* offline_planner_offsets = nullptr; + TF_LITE_ENSURE_STATUS( + builder.GetOfflinePlannedOffsets(&offline_planner_offsets)); + TF_LITE_ENSURE_STATUS( + builder.InitializeAllocationInfo(offline_planner_offsets, allocations)); + + internal::ScratchBufferRequest* scratch_buffer_requests = + GetScratchBufferRequests(); + TF_LITE_ENSURE_STATUS(builder.MarkAllocationLifetimes( + 0, scratch_buffer_requests, scratch_buffer_handles, allocations)); + int allocation_info_count = builder.AllocationCount(); + AllocationInfo* allocation_info = builder.Finish(); + + // Remaining arena size that memory planner can use for calculating offsets. + size_t remaining_arena_size = + non_persistent_buffer_allocator_->GetAvailableMemory( + MicroArenaBufferAlignment()); + uint8_t* planner_arena = non_persistent_buffer_allocator_->AllocateTemp( + remaining_arena_size, MicroArenaBufferAlignment()); + TF_LITE_ENSURE(tflite::GetMicroErrorReporter(), planner_arena != nullptr); + memory_planner_->Init(planner_arena, remaining_arena_size); + TF_LITE_ENSURE_STATUS( + CreatePlan(memory_planner_, allocation_info, allocation_info_count)); + + // Commit the plan. + TF_LITE_ENSURE_STATUS( + CommitPlan(memory_planner_, + non_persistent_buffer_allocator_->GetOverlayMemoryAddress(), + allocation_info, allocation_info_count)); + + // Reset all temp allocations used above: + builder.FreeAllocationInfo(); + non_persistent_buffer_allocator_->DeallocateTemp(planner_arena); + TF_LITE_ENSURE_STATUS( + non_persistent_buffer_allocator_->ResetTempAllocations()); + TF_LITE_ENSURE_STATUS( + non_persistent_buffer_allocator_->DeallocateResizableBuffer( + scratch_buffer_head_)); + +#ifdef TF_LITE_SHOW_MEMORY_USE + memory_planner_->PrintMemoryPlan(); +#endif + head_usage = memory_planner_->GetMaximumMemorySize(); + + // The head is used to store memory plans for one model at a time during the + // model preparation stage, and is re-purposed to store scratch buffer handles + // during model invocation. The head must be as large as the greater of the + // largest model memory plan's size and the total space required for all + // scratch buffer handles. + if (max_head_buffer_usage_ < head_usage) { + max_head_buffer_usage_ = head_usage; + } + + // The head is used for storing scratch buffer allocations before finalizing a + // memory plan in this function. Ensure that the head is set to the largest + // memory plan sent through the allocator: + TF_LITE_ENSURE_STATUS( + non_persistent_buffer_allocator_->ReserveNonPersistentOverlayMemory( + max_head_buffer_usage_, MicroArenaBufferAlignment())); + return kTfLiteOk; +} + +TfLiteStatus MicroAllocator::AllocateScratchBufferHandles( + ScratchBufferHandle** scratch_buffer_handles, size_t handle_count) { + TFLITE_DCHECK(scratch_buffer_handles != nullptr); + + if (scratch_buffer_request_count_ == 0) { + // No scratch buffer requests were requested during model allocation. + return kTfLiteOk; + } + + // Allocate a consecutive block of memory store the scratch buffer handles. + // This alignment ensures quick lookup during inference time for the model: + *scratch_buffer_handles = reinterpret_cast( + persistent_buffer_allocator_->AllocatePersistentBuffer( + sizeof(ScratchBufferHandle) * handle_count, + alignof(ScratchBufferHandle))); + + return kTfLiteOk; +} + +TfLiteStatus MicroAllocator::InitScratchBufferData() { + // A model is preparing to allocate resources, ensure that scratch buffer + // request counter is cleared: + scratch_buffer_request_count_ = 0; + + // All requests will be stored in the head section. Each kernel is allowed at + // most kMaxScratchBuffersPerOp requests. Adjust the head to reserve at most + // that many requests to begin: + scratch_buffer_head_ = + non_persistent_buffer_allocator_->AllocateResizableBuffer( + sizeof(internal::ScratchBufferRequest) * kMaxScratchBuffersPerOp, + alignof(internal::ScratchBufferRequest)); + if (scratch_buffer_head_ == nullptr) { + return kTfLiteError; + } + + return kTfLiteOk; +} + +internal::ScratchBufferRequest* MicroAllocator::GetScratchBufferRequests() { + return reinterpret_cast(AlignPointerUp( + scratch_buffer_head_, alignof(internal::ScratchBufferRequest))); +} + +BuiltinDataAllocator* MicroAllocator::GetBuiltinDataAllocator() { + return builtin_data_allocator_; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocator.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocator.h new file mode 100644 index 000000000..1f2f5162e --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_allocator.h @@ -0,0 +1,357 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MICRO_ALLOCATOR_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_ALLOCATOR_H_ + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/flatbuffer_conversions.h" +#include "tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/flatbuffer_utils.h" +#include "tensorflow/lite/micro/memory_planner/micro_memory_planner.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +// TODO(b/199402574): rename to tflite_internal or just remove internal +// namespace. +namespace internal { + +// Sets up all of the data structure members for a TfLiteTensor based on the +// contents of a serialized tensor in the flatbuffer. +// TODO(b/162311891): Drop this method when the interpreter has an API for +// returning buffers on TfLiteEvalTensor. +TfLiteStatus InitializeTfLiteTensorFromFlatbuffer( + IPersistentBufferAllocator* persistent_buffer_allocator, + INonPersistentBufferAllocator* non_persistent_buffer_allocator, + bool allocate_temp, const tflite::Tensor& flatbuffer_tensor, + const flatbuffers::Vector>* buffers, + TfLiteTensor* result); + +// Holds placeholder information for a scratch buffer request from a kernel. +// This struct is only used during the model prepare stage. Each request from a +// kernel is stored in the head section. During the prepare stage, the head +// section will at least hold kMaxScratchBuffersPerOp number of requests plus +// any requests from previous kernel requests. +// +// When the memory plan is finalized, these structs are no longer used in favor +// of a sequential, array of ScratchBufferHandle allocations in the tail +// section. These allocations are indexed by the request API defined in the +// TfLiteContext struct. +struct ScratchBufferRequest { + // Number of bytes required by the buffer. The actual allocated size might be + // greater than `bytes` due to buffer alignment. + size_t bytes; + // Node where the buffer is allocated for. This provides useful information to + // determine the lifetime of the buffer. In AllocationInfo, this buffer will + // have `before` = node_idx and `after` = node_idx. + int node_idx; + int subgraph_idx; +}; + +} // namespace internal + +struct NodeAndRegistration { + TfLiteNode node; + const TfLiteRegistration* registration; +}; + +// Holds a pointer to a buffer for a scratch buffer requested by a kernel during +// the model prepare stage. This struct is allocated in-place and allows for +// quick pointer-indexed lookup for speed during model inference. +struct ScratchBufferHandle { + // Pointer to location of the scratch buffer: + uint8_t* data; +}; + +// Stores all per-subgraph allocations. This includes the node and registration +// array, and tensor list for each subgraph. +struct SubgraphAllocations { + NodeAndRegistration* node_and_registrations; + TfLiteEvalTensor* tensors; +}; + +// Allocator responsible for allocating memory for all intermediate tensors +// necessary to invoke a model. +// +// The lifetime of the model, tensor arena and error reporter must be at +// least as long as that of the allocator object, since the allocator needs +// them to be accessible during its entire lifetime. +// +// The MicroAllocator simply plans out additional allocations that are required +// to standup a model for inference in TF Micro. This class currently relies on +// an additional allocator - SingleArenaBufferAllocator - for all allocations +// from an arena. These allocations are divided into head (non-persistent) and +// tail (persistent) regions: +// +// Memory layout to help understand how it works +// This information could change in the future version. +// ************** .memory_allocator->GetBuffer() +// Tensors/Scratch buffers (head) +// ************** .head_watermark +// unused memory +// ************** .memory_allocator->GetBuffer() + ->GetMaxBufferSize() +// - ->GetDataSize() +// persistent area (tail) +// ************** .memory_allocator->GetBuffer() + ->GetMaxBufferSize() +class MicroAllocator { + public: + // TODO(b/246776144): Will be removed with http://b/246776144 + static MicroAllocator* Create(uint8_t* tensor_arena, size_t arena_size, + ErrorReporter* error_reporter) { + (void)error_reporter; + return MicroAllocator::Create(tensor_arena, arena_size); + } + + // Creates a MicroAllocator instance from a given tensor arena. This arena + // will be managed by the created instance. The GreedyMemoryPlanner will + // by default be used and created on the arena. + // Note: Please use alignas(16) to make sure tensor_arena is 16 + // bytes aligned, otherwise some head room will be wasted. + // TODO(b/157615197): Cleanup constructor + factory usage. + static MicroAllocator* Create(uint8_t* tensor_arena, size_t arena_size); + + // TODO(b/246776144): Will be removed with http://b/246776144 + static MicroAllocator* Create(uint8_t* tensor_arena, size_t arena_size, + MicroMemoryPlanner* memory_planner, + ErrorReporter* error_reporter) { + (void)error_reporter; + return MicroAllocator::Create(tensor_arena, arena_size, memory_planner); + } + + // Creates a MicroAllocator instance from a given tensor arena and a given + // MemoryPlanner. This arena will be managed by the created instance. Note: + // Please use alignas(16) to make sure tensor_arena is 16 bytes + // aligned, otherwise some head room will be wasted. + static MicroAllocator* Create(uint8_t* tensor_arena, size_t arena_size, + MicroMemoryPlanner* memory_planner); + + // TODO(b/246776144): Will be removed with http://b/246776144 + static MicroAllocator* Create(SingleArenaBufferAllocator* memory_allocator, + MicroMemoryPlanner* memory_planner, + ErrorReporter* error_reporter) { + (void)error_reporter; + return MicroAllocator::Create(memory_allocator, memory_planner); + } + + // Creates a MicroAllocator instance using the provided + // SingleArenaBufferAllocator instance and the MemoryPlanner. This allocator + // instance will use the SingleArenaBufferAllocator instance to manage + // allocations internally. + static MicroAllocator* Create(SingleArenaBufferAllocator* memory_allocator, + MicroMemoryPlanner* memory_planner); + + // TODO(b/246776144): Will be removed with http://b/246776144 + static MicroAllocator* Create(uint8_t* persistent_tensor_arena, + size_t persistent_arena_size, + uint8_t* non_persistent_tensor_arena, + size_t non_persistent_arena_size, + ErrorReporter* error_reporter) { + (void)error_reporter; + return MicroAllocator::Create( + persistent_tensor_arena, persistent_arena_size, + non_persistent_tensor_arena, non_persistent_arena_size); + } + + // Creates a MicroAllocator instance using the provided + // SingleArenaBufferAllocator instance and the MemoryPlanner. This allocator + // instance will use the SingleArenaBufferAllocator instance to manage + // allocations internally. + static MicroAllocator* Create(uint8_t* persistent_tensor_arena, + size_t persistent_arena_size, + uint8_t* non_persistent_tensor_arena, + size_t non_persistent_arena_size); + + // Returns the fixed amount of memory overhead of MicroAllocator. + static size_t GetDefaultTailUsage(bool is_memory_planner_given); + + // Allocates internal resources required for model inference for each subgraph + // from the arena. + // + // This method will run through the flatbuffer data supplied in the model to + // properly allocate tensor, node, and op registration data. This method is + // expected to be followed with a call to FinishModelAllocation() Returns a + // pointer to an array of SubgraphAllocations (also stored in the tail of the + // arena) where each index corresponds to a different subgraph in the model. + // Return value is nullptr if the allocations failed. + SubgraphAllocations* StartModelAllocation(const Model* model); + + // Finish allocating internal resources required for model inference. + // + // -Plan the memory for activation tensors and scratch buffers. + // -Update eval tensors for each subgraph based on planned offsets. + // -Allocate scratch buffer handles array and update based on planned offsets. + // + // This method should be called after assigning model resources + // in StartModelAllocation(). The subgraph_allocations pointer should be the + // value passed into this class during StartModelAllocation(). Scratch buffer + // handles are stored in the out-param `scratch_buffer_handles` array which is + // allocated in this method. This value will be used in `GetScratchBuffer` + // call to retrieve scratch buffers. + TfLiteStatus FinishModelAllocation( + const Model* model, SubgraphAllocations* subgraph_allocations, + ScratchBufferHandle** scratch_buffer_handles); + + // Allocates a TfLiteTensor struct and populates the returned value with + // properties from the model flatbuffer. This struct is allocated from + // persistent arena memory is only guaranteed for the lifetime of the + // application. The eval_tensors pointer should be the value passed into this + // class during StartModelAllocation() and contains the source-of-truth for + // buffers. + virtual TfLiteTensor* AllocatePersistentTfLiteTensor( + const Model* model, const SubgraphAllocations* subgraph_allocations, + int tensor_index, int subgraph_index); + + // Allocates a TfLiteTensor struct and populates the returned value with + // properties from the model flatbuffer. This struct is allocated from + // temporary arena memory is only guaranteed until a call is made to + // ResetTempAllocations(). Subgraph_allocaitons contains the array of + // TfLiteEvalTensors. If the newly allocated temp at the specified subgraph + // and tensor index is already present int the TfLiteEvalTensor array, its + // data buffer will be re-used. + virtual TfLiteTensor* AllocateTempTfLiteTensor( + const Model* model, const SubgraphAllocations* subgraph_allocations, + int tensor_index, int subgraph_index); + + virtual void DeallocateTempTfLiteTensor(TfLiteTensor*); + + // Resets all temporary allocations. This method should be called after a + // chain of temp allocations (e.g. chain of TfLiteTensor objects via + // AllocateTfLiteTensor()). + virtual TfLiteStatus ResetTempAllocations(); + + // Returns true if all temporary buffers including temp TfLiteTensor are + // already deallocated. + virtual bool IsAllTempDeallocated(); + + // Allocates persistent buffer which has the same life time as the allocator. + // The memory is immediately available and is allocated from the tail of the + // arena. + virtual void* AllocatePersistentBuffer(size_t bytes); + + // Register a scratch buffer of size `bytes` for Node with `node_id`. + // This method only requests a buffer with a given size to be used after a + // model has finished allocation via FinishModelAllocation(). All requested + // buffers will be accessible by the out-param in that method. + TfLiteStatus RequestScratchBufferInArena(size_t bytes, int subgraph_idx, + int* buffer_idx); + + // Finish allocating a specific NodeAndRegistration prepare block (kernel + // entry for a model) with a given node ID. This call ensures that any scratch + // buffer requests and temporary allocations are handled and ready for the + // next node prepare block. + TfLiteStatus FinishPrepareNodeAllocations(int node_id); + + // Returns the arena usage in bytes, only available after + // `FinishModelAllocation`. Otherwise, it will return 0. + size_t used_bytes() const; + + BuiltinDataAllocator* GetBuiltinDataAllocator(); + + protected: + MicroAllocator(SingleArenaBufferAllocator* memory_allocator, + MicroMemoryPlanner* memory_planner); + MicroAllocator(IPersistentBufferAllocator* persistent_buffer_allocator, + INonPersistentBufferAllocator* non_persistent_buffer_allocator, + MicroMemoryPlanner* memory_planner); + virtual ~MicroAllocator(); + + // Allocates an array in the arena to hold pointers to the node and + // registration pointers required to represent the inference graph of the + // model. + virtual TfLiteStatus AllocateNodeAndRegistrations( + const Model* model, SubgraphAllocations* subgraph_allocations); + + // Allocates the list of persistent TfLiteEvalTensors that are used for the + // "eval" phase of model inference. These structs will be the source of truth + // for all tensor buffers. + virtual TfLiteStatus AllocateTfLiteEvalTensors( + const Model* model, SubgraphAllocations* subgraph_allocations); + // Allocates persistent tensor buffers for variable tensors in the subgraph. + virtual TfLiteStatus AllocateVariables(const SubGraph* subgraph, + TfLiteEvalTensor* eval_tensors); + + // Allocate and return a persistent TfLiteTensor. + // TODO(b/162311891): Drop this method when the interpreter has an API for + // accessing TfLiteEvalTensor structs. + virtual TfLiteTensor* AllocatePersistentTfLiteTensorInternal(); + + // Populates a TfLiteTensor struct with data from the model flatbuffer. Any + // quantization data is allocated from either the tail (persistent) or temp + // sections of the arena based on the allocation flag. + virtual TfLiteStatus PopulateTfLiteTensorFromFlatbuffer(const Model* model, + TfLiteTensor* tensor, + int tensor_index, + int subgraph_idx, + bool allocate_temp); + + private: + // Commits a memory plan for all non-persistent buffer allocations in the + // 'head' section of the memory arena. The eval_tensors pointer is the list of + // pre-allocated TfLiteEvalTensor structs that will point to the buffers that + // will be allocated into the head section in this function call. The + // scratch_buffer_handles pointer is the array of pre-allocated + // ScratchBufferHandle structs that will point to allocated buffers also in + // the head section. + virtual TfLiteStatus CommitStaticMemoryPlan( + const Model* model, SubgraphAllocations* allocations, + ScratchBufferHandle* scratch_buffer_handles); + + // Allocates an array of ScratchBufferHandle structs in the tail section for a + // given number of handles. + virtual TfLiteStatus AllocateScratchBufferHandles( + ScratchBufferHandle** scratch_buffer_handles, size_t handle_count); + + // Clears all internal scratch buffer request counts and resets the head to + // prepare for kernels to request scratch buffer data when a model is + // preparing. + TfLiteStatus InitScratchBufferData(); + + // Returns the pointer for the array of ScratchBufferRequest allocations in + // the head section. + internal::ScratchBufferRequest* GetScratchBufferRequests(); + + // A simple memory allocator that always allocate from the arena tail or head. + INonPersistentBufferAllocator* non_persistent_buffer_allocator_; + IPersistentBufferAllocator* persistent_buffer_allocator_; + + // Allocator used to allocate persistent builtin data. + BuiltinDataAllocator* builtin_data_allocator_; + + // Activation buffer memory planner. + MicroMemoryPlanner* memory_planner_; + + bool model_is_allocating_; + + // Holds the number of ScratchBufferRequest instances stored in the head + // section when a model is allocating. + size_t scratch_buffer_request_count_ = 0; + + // Holds ScratchBufferRequest when a model is allocating + uint8_t* scratch_buffer_head_ = nullptr; + + // Holds the byte length of the memory plan with the largest head usage. Used + // to ensure that multi-tenant allocations can share the head for buffers. + size_t max_head_buffer_usage_ = 0; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite +#endif // TENSORFLOW_LITE_MICRO_MICRO_ALLOCATOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_arena_constants.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_arena_constants.h new file mode 100644 index 000000000..828281760 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_arena_constants.h @@ -0,0 +1,28 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MICRO_ARENA_CONSTANTS_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_ARENA_CONSTANTS_H_ + +namespace tflite { + +// The default buffer alignment requirement. +// We align tensor buffers to 16-byte boundaries, since this is a common +// requirement for SIMD extensions. +constexpr int MicroArenaBufferAlignment() { return 16; } + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_ARENA_CONSTANTS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_context.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_context.cpp new file mode 100644 index 000000000..9e3d71de9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_context.cpp @@ -0,0 +1,130 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/micro_context.h" + +#include +#include +#include + +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +MicroContext::MicroContext(MicroAllocator* allocator, const Model* model, + MicroGraph* graph) + : allocator_(*allocator), graph_(*graph), model_(model) {} + +MicroContext::~MicroContext() {} + +void* MicroContext::AllocatePersistentBuffer(size_t bytes) { + return allocator_.AllocatePersistentBuffer(bytes); +} + +TfLiteStatus MicroContext::RequestScratchBufferInArena(size_t bytes, + int* buffer_idx) { + return allocator_.RequestScratchBufferInArena( + bytes, graph_.GetCurrentSubgraphIndex(), buffer_idx); +} + +void* MicroContext::GetScratchBuffer(int buffer_idx) { + ScratchBufferHandle* handle = scratch_buffer_handles_ + buffer_idx; + return handle->data; +} + +TfLiteTensor* MicroContext::AllocateTempTfLiteTensor(int tensor_idx) { + return allocator_.AllocateTempTfLiteTensor(model_, graph_.GetAllocations(), + tensor_idx, + graph_.GetCurrentSubgraphIndex()); +} + +int MicroContext::GetTensorIndex(int index, int max_size, + const int* tensor_indices) { + if (index >= 0 && index < max_size) { + const int tensor_index = tensor_indices[index]; + if (tensor_index != kTfLiteOptionalTensor) { + return tensor_index; + } + } + return -1; +} + +TfLiteTensor* MicroContext::AllocateTempInputTensor(const TfLiteNode* node, + int index) { + const int tensor_index = + GetTensorIndex(index, node->inputs->size, node->inputs->data); + if (tensor_index < 0) { + return nullptr; + } + return AllocateTempTfLiteTensor(tensor_index); +} + +TfLiteTensor* MicroContext::AllocateTempOutputTensor(const TfLiteNode* node, + int index) { + const int tensor_index = + GetTensorIndex(index, node->outputs->size, node->outputs->data); + if (tensor_index < 0) { + return nullptr; + } + return AllocateTempTfLiteTensor(tensor_index); +} + +TfLiteTensor* MicroContext::AllocateTempIntermediateTensor( + const TfLiteNode* node, int index) { + const int tensor_index = GetTensorIndex(index, node->intermediates->size, + node->intermediates->data); + if (tensor_index < 0) { + return nullptr; + } + return AllocateTempTfLiteTensor(tensor_index); +} + +void MicroContext::DeallocateTempTfLiteTensor(TfLiteTensor* tensor) { + return allocator_.DeallocateTempTfLiteTensor(tensor); +} + +TfLiteEvalTensor* MicroContext::GetEvalTensor(int tensor_idx) { + return &graph_.GetAllocations()[graph_.GetCurrentSubgraphIndex()] + .tensors[tensor_idx]; +} + +void MicroContext::SetScratchBufferHandles( + ScratchBufferHandle* scratch_buffer_handles) { + scratch_buffer_handles_ = scratch_buffer_handles; +} + +TfLiteStatus MicroContext::set_external_context( + void* external_context_payload) { + if (external_context_payload == nullptr || + external_context_payload_ != nullptr) { + MicroPrintf( + "Attempting to set external context to %x but it was %x already", + external_context_payload, external_context_payload_); + return kTfLiteError; + } + + external_context_payload_ = external_context_payload; + return kTfLiteOk; +} + +void MicroContextReportOpError(struct TfLiteContext* context, + const char* format, ...) { + va_list args; + va_start(args, format); + GetMicroErrorReporter()->Report(format, args); + va_end(args); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_context.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_context.h new file mode 100644 index 000000000..e7be65444 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_context.h @@ -0,0 +1,161 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MICRO_CONTEXT_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_CONTEXT_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_allocator.h" +#include "tensorflow/lite/micro/micro_graph.h" + +namespace tflite { +// MicroContext is eventually going to become the API between TFLM and the +// kernels, replacing all the functions in TfLiteContext. The end state is code +// kernels to have code like: +// +// MicroContext* micro_context = GetMicroContext(context); +// micro_context-> +class MicroContext { + public: + // Does not take any ownership, and all pointers must refer to valid objects + // that outlive the one constructed. + explicit MicroContext(MicroAllocator* allocator, const Model* model, + MicroGraph* graph); + virtual ~MicroContext(); + + // Allocate persistent buffer which has the same life time as the interpreter. + // Returns nullptr on failure. + // The memory is allocated from the tail. + // This method is only available in Init or Prepare stage. + // Virtual so that it can be faked for kernel tests. + virtual void* AllocatePersistentBuffer(size_t bytes); + + // Request a scratch buffer in the arena through static memory planning. + // This method is only available in Prepare stage and the buffer is allocated + // by the interpreter between Prepare and Eval stage. In Eval stage, + // GetScratchBuffer API can be used to fetch the address. + // Virtual so that it can be faked for kernel tests. + virtual TfLiteStatus RequestScratchBufferInArena(size_t bytes, + int* buffer_idx); + + // Get the scratch buffer pointer. + // This method is only available in Eval stage. + // Virtual so that it can be faked for kernel tests. + virtual void* GetScratchBuffer(int buffer_idx); + + // Returns a temporary TfLiteTensor struct for a given index. + // Virtual so that it can be faked for kernel tests. + virtual TfLiteTensor* AllocateTempTfLiteTensor(int tensor_idx); + + // Returns a temporary TfLiteTensor struct for the specified input tensor of a + // given mode. This is the recommended API over the deprecated + // GetInput/GetInputSafe to get a temp input tensor. The returned tensor shall + // be freed via calling DeallocateTempTfLiteTensor. + virtual TfLiteTensor* AllocateTempInputTensor(const TfLiteNode* node, + int index); + + // Returns a temporary TfLiteTensor struct for the specified output tensor of + // a given mode. This is the recommended API over the deprecated + // GetOutput/GetOutputSafe to get a temp output tensor. The returned tensor + // shall be freed via calling DeallocateTempTfLiteTensor. + virtual TfLiteTensor* AllocateTempOutputTensor(const TfLiteNode* node, + int index); + + // Returns a temporary TfLiteTensor struct for the specified intermediate + // tensor of a given mode. This is the recommended API over the deprecated + // GetIntermediates/GetIntermediatesSafe to get a temp intermediate tensor. + // The returned tensor shall be freed via calling DeallocateTempTfLiteTensor. + virtual TfLiteTensor* AllocateTempIntermediateTensor(const TfLiteNode* node, + int index); + + // Deallocates a temp TfLiteTensor. + // Virtual so that it can be faked for kernel tests. + virtual void DeallocateTempTfLiteTensor(TfLiteTensor* tensor); + + // Returns a TfLiteEvalTensor struct for a given index. + // Virtual so that it can be faked for kernel tests. + virtual TfLiteEvalTensor* GetEvalTensor(int tensor_idx); + + // Does not take ownership of the pointer and the pointer must refer to valid + // an object that outlive this class instance. + // This can only be called once to set one external context. + TfLiteStatus set_external_context(void* external_context_payload); + + void* external_context() { return external_context_payload_; } + + MicroGraph& graph() { return graph_; } + + // Sets the pointer to a list of ScratchBufferHandle instances. + // Not API between TFLM and kernels. Primarily used by the framework for + // housekeeping in MicroContext. + void SetScratchBufferHandles(ScratchBufferHandle* scratch_buffer_handles); + + private: + // Return the tensor index as tensor_indices[index]. tensor_indices is of + // max_size. Return -1 if index is not in the valid range of tensor_indices. + int GetTensorIndex(int index, int max_size, const int* tensor_indices); + + MicroAllocator& allocator_; + MicroGraph& graph_; + const Model* model_; + + ScratchBufferHandle* scratch_buffer_handles_ = nullptr; + void* external_context_payload_ = nullptr; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +inline MicroContext* GetMicroContext(const struct TfLiteContext* context) { + return reinterpret_cast(context->impl_); +} + +// Deprecated API. Prefer to using the MicroContext API directly from the +// kernels. +// TODO(b/213010668): migrate all existing kernels to use MicroContext, delete +// these functions, and remove corresponding members from the TfLiteContext +// struct for TFLM. +inline void* MicroContextAllocatePersistentBuffer(TfLiteContext* ctx, + size_t bytes) { + return GetMicroContext(ctx)->AllocatePersistentBuffer(bytes); +} +inline TfLiteStatus MicroContextRequestScratchBufferInArena(TfLiteContext* ctx, + size_t bytes, + int* buffer_idx) { + return GetMicroContext(ctx)->RequestScratchBufferInArena(bytes, buffer_idx); +} +inline void* MicroContextGetScratchBuffer(TfLiteContext* ctx, int buffer_idx) { + return GetMicroContext(ctx)->GetScratchBuffer(buffer_idx); +} +inline TfLiteTensor* MicroContextGetTensor(const struct TfLiteContext* context, + int tensor_idx) { + return GetMicroContext(context)->AllocateTempTfLiteTensor(tensor_idx); +} +inline TfLiteEvalTensor* MicroContextGetEvalTensor( + const struct TfLiteContext* context, int tensor_idx) { + return GetMicroContext(context)->GetEvalTensor(tensor_idx); +} +inline TfLiteExternalContext* MicroContextGetExternalContext( + TfLiteContext* context, TfLiteExternalContextType unused) { + return reinterpret_cast( + GetMicroContext(context)->external_context()); +} + +// Requests that an error be reported with format string msg. +void MicroContextReportOpError(struct TfLiteContext* context, + const char* format, ...); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_CONTEXT_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_error_reporter.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_error_reporter.cpp new file mode 100644 index 000000000..5eea81406 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_error_reporter.cpp @@ -0,0 +1,41 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/micro_error_reporter.h" + +#include +#include +#include + +namespace { +uint8_t micro_error_reporter_buffer[sizeof(tflite::MicroErrorReporter)]; +tflite::MicroErrorReporter* error_reporter_ = nullptr; + +} // namespace + +namespace tflite { +ErrorReporter* GetMicroErrorReporter() { + if (error_reporter_ == nullptr) { + error_reporter_ = new (micro_error_reporter_buffer) MicroErrorReporter(); + } + return error_reporter_; +} + +int MicroErrorReporter::Report(const char* format, va_list args) { + Log(format, args); + return 0; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_error_reporter.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_error_reporter.h new file mode 100644 index 000000000..a79f728b9 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_error_reporter.h @@ -0,0 +1,39 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MICRO_ERROR_REPORTER_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_ERROR_REPORTER_H_ + +#include + +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/micro/compatibility.h" +// TODO(b/246776144): Move this include statement to the cc file. +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { +// Get a pointer to a singleton global error reporter. +ErrorReporter* GetMicroErrorReporter(); +class MicroErrorReporter : public ErrorReporter { + public: + ~MicroErrorReporter() override {} + int Report(const char* format, va_list args) override; + + private: + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_ERROR_REPORTER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_graph.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_graph.cpp new file mode 100644 index 000000000..a52b28c28 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_graph.cpp @@ -0,0 +1,248 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/micro_graph.h" + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/micro/flatbuffer_utils.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_profiler.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +namespace { + +const char* OpNameFromRegistration(const TfLiteRegistration* registration) { + if (registration->builtin_code == BuiltinOperator_CUSTOM) { + return registration->custom_name; + } else { + return EnumNameBuiltinOperator(BuiltinOperator(registration->builtin_code)); + } +} + +} // namespace + +MicroGraph::MicroGraph(TfLiteContext* context, const Model* model, + MicroAllocator* allocator, + MicroResourceVariables* resource_variables) + : context_(context), + model_(model), + allocator_(allocator), + current_subgraph_index_(0), + resource_variables_(resource_variables) { + if (model != nullptr) { + subgraphs_ = model->subgraphs(); + } +} + +MicroGraph::~MicroGraph() {} + +TfLiteStatus MicroGraph::InitSubgraphs() { + int previous_subgraph_idx = current_subgraph_index_; + + for (size_t subgraph_idx = 0; subgraph_idx < subgraphs_->size(); + subgraph_idx++) { + current_subgraph_index_ = subgraph_idx; + uint32_t operators_size = NumSubgraphOperators(model_, subgraph_idx); + for (size_t i = 0; i < operators_size; ++i) { + TfLiteNode* node = + &(subgraph_allocations_[subgraph_idx].node_and_registrations[i].node); + const TfLiteRegistration* registration = + subgraph_allocations_[subgraph_idx] + .node_and_registrations[i] + .registration; + size_t init_data_size; + const char* init_data; + if (registration->builtin_code == BuiltinOperator_CUSTOM) { + init_data = reinterpret_cast(node->custom_initial_data); + init_data_size = node->custom_initial_data_size; + } else { + init_data = reinterpret_cast(node->builtin_data); + init_data_size = 0; + } + if (registration->init) { + node->user_data = + registration->init(context_, init_data, init_data_size); + } + } + } + current_subgraph_index_ = previous_subgraph_idx; + + return kTfLiteOk; +} + +TfLiteStatus MicroGraph::PrepareSubgraphs() { + int previous_subgraph_idx = current_subgraph_index_; + + for (size_t subgraph_idx = 0; subgraph_idx < subgraphs_->size(); + subgraph_idx++) { + current_subgraph_index_ = subgraph_idx; + uint32_t operators_size = NumSubgraphOperators(model_, subgraph_idx); + for (size_t i = 0; i < operators_size; ++i) { + TfLiteNode* node = + &(subgraph_allocations_[subgraph_idx].node_and_registrations[i].node); + const TfLiteRegistration* registration = + subgraph_allocations_[subgraph_idx] + .node_and_registrations[i] + .registration; + if (registration->prepare != nullptr) { + TfLiteStatus prepare_status = registration->prepare(context_, node); + if (prepare_status != kTfLiteOk) { + MicroPrintf("Node %s (number %df) failed to prepare with status %d", + OpNameFromRegistration(registration), i, prepare_status); + return kTfLiteError; + } + } + allocator_->FinishPrepareNodeAllocations(/*node_id=*/i); + } + } + current_subgraph_index_ = previous_subgraph_idx; + + return kTfLiteOk; +} + +TfLiteStatus MicroGraph::FreeSubgraphs() { + int previous_subgraph_idx = current_subgraph_index_; + + for (size_t subgraph_idx = 0; subgraph_idx < subgraphs_->size(); + subgraph_idx++) { + current_subgraph_index_ = subgraph_idx; + uint32_t operators_size = NumSubgraphOperators(model_, subgraph_idx); + for (size_t i = 0; i < operators_size; ++i) { + TfLiteNode* node = + &(subgraph_allocations_[subgraph_idx].node_and_registrations[i].node); + const TfLiteRegistration* registration = + subgraph_allocations_[subgraph_idx] + .node_and_registrations[i] + .registration; + // registration is allocated outside the interpreter, so double check to + // make sure it's not nullptr; + if (registration != nullptr && registration->free != nullptr) { + registration->free(context_, node->user_data); + } + } + } + current_subgraph_index_ = previous_subgraph_idx; + + return kTfLiteOk; +} + +TfLiteStatus MicroGraph::InvokeSubgraph(int subgraph_idx) { + int previous_subgraph_idx = current_subgraph_index_; + current_subgraph_index_ = subgraph_idx; + + if (static_cast(subgraph_idx) >= subgraphs_->size()) { + MicroPrintf("Accessing subgraph %d but only %d subgraphs found", + subgraph_idx, subgraphs_->size()); + return kTfLiteError; + } + uint32_t operators_size = NumSubgraphOperators(model_, subgraph_idx); + for (size_t i = 0; i < operators_size; ++i) { + TfLiteNode* node = + &(subgraph_allocations_[subgraph_idx].node_and_registrations[i].node); + const TfLiteRegistration* registration = subgraph_allocations_[subgraph_idx] + .node_and_registrations[i] + .registration; + +// This ifdef is needed (even though ScopedMicroProfiler itself is a no-op with +// -DTF_LITE_STRIP_ERROR_STRINGS) because the function OpNameFromRegistration is +// only defined for builds with the error strings. +#if !defined(TF_LITE_STRIP_ERROR_STRINGS) + ScopedMicroProfiler scoped_profiler( + OpNameFromRegistration(registration), + reinterpret_cast(context_->profiler)); +#endif + + TFLITE_DCHECK(registration->invoke); + TfLiteStatus invoke_status = registration->invoke(context_, node); + + // All TfLiteTensor structs used in the kernel are allocated from temp + // memory in the allocator. This creates a chain of allocations in the + // temp section. The call below resets the chain of allocations to + // prepare for the next call. + allocator_->ResetTempAllocations(); + + if (invoke_status == kTfLiteError) { + MicroPrintf("Node %s (number %d) failed to invoke with status %d", + OpNameFromRegistration(registration), i, invoke_status); + return kTfLiteError; + } else if (invoke_status != kTfLiteOk) { + return invoke_status; + } + } + current_subgraph_index_ = previous_subgraph_idx; + return kTfLiteOk; +} + +TfLiteStatus MicroGraph::ResetVariableTensors() { + for (size_t subgraph_idx = 0; subgraph_idx < subgraphs_->size(); + subgraph_idx++) { + const SubGraph* subgraph = (*subgraphs_)[subgraph_idx]; + for (size_t i = 0; i < subgraph->tensors()->size(); ++i) { + auto* tensor = subgraph->tensors()->Get(i); + if (tensor->is_variable()) { + size_t buffer_size; + TF_LITE_ENSURE_STATUS(TfLiteEvalTensorByteLength( + &subgraph_allocations_[subgraph_idx].tensors[i], &buffer_size)); + + int value = 0; + if (tensor->type() == tflite::TensorType_INT8) { + value = tensor->quantization()->zero_point()->Get(0); + } + memset(subgraph_allocations_[subgraph_idx].tensors[i].data.raw, value, + buffer_size); + } + } + } + if (resource_variables_ != nullptr) { + resource_variables_->ResetAll(); + } + + return kTfLiteOk; +} + +int MicroGraph::NumSubgraphs() { return model_->subgraphs()->size(); } + +void MicroGraph::SetSubgraphAllocations( + SubgraphAllocations* subgraph_allocations) { + subgraph_allocations_ = subgraph_allocations; +} + +size_t MicroGraph::NumSubgraphInputs(int subgraph_idx) { + return model_->subgraphs()->Get(subgraph_idx)->inputs()->size(); +} + +TfLiteEvalTensor* MicroGraph::GetSubgraphInput(int subgraph_idx, + int input_idx) { + int tensor_idx = + model_->subgraphs()->Get(subgraph_idx)->inputs()->Get(input_idx); + return &subgraph_allocations_[subgraph_idx].tensors[tensor_idx]; +} + +size_t MicroGraph::NumSubgraphOutputs(int subgraph_idx) { + return model_->subgraphs()->Get(subgraph_idx)->outputs()->size(); +} + +TfLiteEvalTensor* MicroGraph::GetSubgraphOutput(int subgraph_idx, + int output_idx) { + int tensor_idx = + model_->subgraphs()->Get(subgraph_idx)->outputs()->Get(output_idx); + return &subgraph_allocations_[subgraph_idx].tensors[tensor_idx]; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_graph.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_graph.h new file mode 100644 index 000000000..942082aca --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_graph.h @@ -0,0 +1,104 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MICRO_GRAPH_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_GRAPH_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_allocator.h" +#include "tensorflow/lite/micro/micro_resource_variable.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +// Abstracts the details of interacting with the tflite::Model. +// +// Provides methods to access, initialize, prepare, invoke and free any +// subgraph in the tflite::Graph. +class MicroGraph { + public: + // The lifetime of the context, model, allocator and resource_variables must + // be at least as long as that of the graph object, since the this class may + // need to access them at any time. If resource_variables is a nullptr, + // GetResourceVariables will return a nullptr. + MicroGraph(TfLiteContext* context, const Model* model, + MicroAllocator* allocator, + MicroResourceVariables* resource_variables); + virtual ~MicroGraph(); + + // Sets up builtin data and calls TfLiteRegistration->Init for every operator + // in every subgraph in the model. + virtual TfLiteStatus InitSubgraphs(); + + // Calls TfLiteRegistration->Prepare for every operator in every subgraph in + // the model. + virtual TfLiteStatus PrepareSubgraphs(); + + // Calls TfLiteRegistration->Free for every operator in every subgraph in the + // model. + virtual TfLiteStatus FreeSubgraphs(); + + // Calls TfLiteRegistration->Invoke for every operator in a single subgraph in + // the model. + virtual TfLiteStatus InvokeSubgraph(int subgraph_idx); + + // Zeros out all variable tensors in all subgraphs in the model. + virtual TfLiteStatus ResetVariableTensors(); + + // Number of tensor inputs to a specified subgraph in the model. + virtual size_t NumSubgraphInputs(int subgraph_idx); + + // Get the specified input tensor of a specified subgraph in the model. + virtual TfLiteEvalTensor* GetSubgraphInput(int subgraph_idx, int input_idx); + + // Number of tensor outputs from a specified subgraph in the model. + virtual size_t NumSubgraphOutputs(int subgraph_idx); + + // Get the specified output tensor of a specified subgraph in the model. + virtual TfLiteEvalTensor* GetSubgraphOutput(int subgraph_idx, int output_idx); + + // Number of subgraphs in the model. + virtual int NumSubgraphs(); + + // Hook to pass in subgraph allocations tracked within the interpreter, + // allowing MicroGraph to init / prepare / invoke subgraphs in the model. + void SetSubgraphAllocations(SubgraphAllocations* subgraph_allocations); + + // Get the current subgraph index. Within an on operator, this is guaranteed + // to be the subgraph of that operator. + int GetCurrentSubgraphIndex() { return current_subgraph_index_; } + + // Gets the list of alloctions for each subgraph. This is the source of truth + // for all per-subgraph allocation data. + SubgraphAllocations* GetAllocations() { return subgraph_allocations_; } + + // Get the resource variables for this TFLM graph. + MicroResourceVariables* GetResourceVariables() { return resource_variables_; } + + private: + TfLiteContext* context_; + const Model* model_; + MicroAllocator* allocator_; + SubgraphAllocations* subgraph_allocations_ = nullptr; + int current_subgraph_index_; + MicroResourceVariables* resource_variables_; + const flatbuffers::Vector>* subgraphs_; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_GRAPH_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_interpreter.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_interpreter.cpp new file mode 100644 index 000000000..f850bd2bf --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_interpreter.cpp @@ -0,0 +1,319 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/micro/micro_interpreter.h" + +#include +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/c_api_types.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/tensor_utils.h" +#include "tensorflow/lite/micro/flatbuffer_utils.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_allocator.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_op_resolver.h" +#include "tensorflow/lite/micro/micro_profiler_interface.h" +#include "tensorflow/lite/schema/schema_generated.h" +#include "tensorflow/lite/schema/schema_utils.h" + +namespace tflite { + +MicroInterpreter::MicroInterpreter(const Model* model, + const MicroOpResolver& op_resolver, + uint8_t* tensor_arena, + size_t tensor_arena_size, + MicroResourceVariables* resource_variables, + MicroProfilerInterface* profiler) + : model_(model), + op_resolver_(op_resolver), + allocator_(*MicroAllocator::Create(tensor_arena, tensor_arena_size)), + + graph_(&context_, model, &allocator_, resource_variables), + tensors_allocated_(false), + initialization_status_(kTfLiteError), + input_tensors_(nullptr), + output_tensors_(nullptr), + micro_context_(&allocator_, model_, &graph_) { + Init(profiler); +} + +MicroInterpreter::MicroInterpreter(const Model* model, + const MicroOpResolver& op_resolver, + MicroAllocator* allocator, + MicroResourceVariables* resource_variables, + MicroProfilerInterface* profiler) + : model_(model), + op_resolver_(op_resolver), + allocator_(*allocator), + graph_(&context_, model, allocator, resource_variables), + tensors_allocated_(false), + initialization_status_(kTfLiteError), + input_tensors_(nullptr), + output_tensors_(nullptr), + micro_context_(&allocator_, model_, &graph_) { + Init(profiler); +} + +MicroInterpreter::~MicroInterpreter() { + if (graph_.GetAllocations() != nullptr) { + graph_.FreeSubgraphs(); + } +} + +void MicroInterpreter::Init(MicroProfilerInterface* profiler) { + context_.impl_ = static_cast(µ_context_); + context_.ReportError = MicroContextReportOpError; + context_.GetTensor = MicroContextGetTensor; + context_.GetEvalTensor = MicroContextGetEvalTensor; + context_.profiler = profiler; + + initialization_status_ = kTfLiteOk; +} + +TfLiteStatus MicroInterpreter::PrepareNodeAndRegistrationDataFromFlatbuffer() { + for (int subgraph_idx = 0; subgraph_idx < graph_.NumSubgraphs(); + subgraph_idx++) { + const SubGraph* subgraph = model_->subgraphs()->Get(subgraph_idx); + TFLITE_DCHECK(subgraph != nullptr); + + auto* opcodes = model_->operator_codes(); + BuiltinDataAllocator* builtin_data_allocator = + allocator_.GetBuiltinDataAllocator(); + uint32_t operators_size = NumSubgraphOperators(subgraph); + for (size_t i = 0; i < operators_size; ++i) { + const auto* op = subgraph->operators()->Get(i); + const size_t index = op->opcode_index(); + if (index >= opcodes->size()) { + MicroPrintf("Missing registration for opcode_index %d\n", index); + return kTfLiteError; + } + const auto* opcode = opcodes->Get(index); + TfLiteStatus status = GetRegistrationFromOpCode( + opcode, op_resolver_, tflite::GetMicroErrorReporter(), + &(graph_.GetAllocations()[subgraph_idx] + .node_and_registrations[i] + .registration)); + if (status != kTfLiteOk) { + MicroPrintf("Failed to get registration from op code %s\n ", + EnumNameBuiltinOperator(GetBuiltinCode(opcode))); + return status; + } + const auto* registration = graph_.GetAllocations()[subgraph_idx] + .node_and_registrations[i] + .registration; + if (registration == nullptr) { + MicroPrintf("Skipping op for opcode_index %d\n", index); + return kTfLiteError; + } + BuiltinOperator op_type = + static_cast(registration->builtin_code); + + const char* custom_data = nullptr; + size_t custom_data_size = 0; + unsigned char* builtin_data = nullptr; + + if (op_type == BuiltinOperator_CUSTOM) { + // Custom Ops may or may not have a non-null custom_options field. + if (op->custom_options() != nullptr) { + custom_data = + reinterpret_cast(op->custom_options()->data()); + custom_data_size = op->custom_options()->size(); + } + } else { + if (op->custom_options() != nullptr) { + MicroPrintf( + "Unsupported behavior: found builtin operator %s with custom " + "options.\n", + EnumNameBuiltinOperator(op_type)); + return kTfLiteError; + } + + MicroOpResolver::BuiltinParseFunction parser = + op_resolver_.GetOpDataParser(op_type); + if (parser == nullptr) { + MicroPrintf("Did not find a parser for %s", + EnumNameBuiltinOperator(op_type)); + + return kTfLiteError; + } + TF_LITE_ENSURE_STATUS(parser(op, tflite::GetMicroErrorReporter(), + builtin_data_allocator, + (void**)(&builtin_data))); + } + + TfLiteIntArray* inputs_array = + FlatBufferVectorToTfLiteTypeArray(op->inputs()); + TfLiteIntArray* outputs_array = + FlatBufferVectorToTfLiteTypeArray(op->outputs()); + + TfLiteNode* node = &( + graph_.GetAllocations()[subgraph_idx].node_and_registrations[i].node); + *node = {}; + node->inputs = inputs_array; + node->outputs = outputs_array; + node->builtin_data = reinterpret_cast(builtin_data); + node->custom_initial_data = custom_data; + node->custom_initial_data_size = custom_data_size; + + if (op->intermediates() && (op->intermediates()->size() > 0)) { + node->intermediates = + FlatBufferVectorToTfLiteTypeArray(op->intermediates()); + } + } + } + return kTfLiteOk; +} + +TfLiteStatus MicroInterpreter::AllocateTensors() { + SubgraphAllocations* allocations = allocator_.StartModelAllocation(model_); + + graph_.SetSubgraphAllocations(allocations); + + TF_LITE_ENSURE_STATUS(PrepareNodeAndRegistrationDataFromFlatbuffer()); + + // Only allow AllocatePersistentBuffer in Init stage. + context_.AllocatePersistentBuffer = MicroContextAllocatePersistentBuffer; + context_.RequestScratchBufferInArena = nullptr; + context_.GetScratchBuffer = nullptr; + context_.GetExternalContext = nullptr; + TF_LITE_ENSURE_STATUS(graph_.InitSubgraphs()); + + // Both AllocatePersistentBuffer and RequestScratchBufferInArena is + // available in Prepare stage. + context_.RequestScratchBufferInArena = + MicroContextRequestScratchBufferInArena; + // external_context become available in Prepare stage. + context_.GetExternalContext = MicroContextGetExternalContext; + + TF_LITE_ENSURE_STATUS(graph_.PrepareSubgraphs()); + + // Prepare is done, we're ready for Invoke. Memory allocation is no longer + // allowed. Kernels can only fetch scratch buffers via GetScratchBuffer. + context_.AllocatePersistentBuffer = nullptr; + context_.RequestScratchBufferInArena = nullptr; + context_.GetScratchBuffer = MicroContextGetScratchBuffer; + + TF_LITE_ENSURE_OK(&context_, allocator_.FinishModelAllocation( + model_, graph_.GetAllocations(), + &scratch_buffer_handles_)); + + micro_context_.SetScratchBufferHandles(scratch_buffer_handles_); + + // TODO(b/162311891): Drop these allocations when the interpreter supports + // handling buffers from TfLiteEvalTensor. + input_tensors_ = + reinterpret_cast(allocator_.AllocatePersistentBuffer( + sizeof(TfLiteTensor*) * inputs_size())); + if (input_tensors_ == nullptr) { + MicroPrintf( + "Failed to allocate memory for context->input_tensors_, " + "%d bytes required", + sizeof(TfLiteTensor*) * inputs_size()); + return kTfLiteError; + } + + for (size_t i = 0; i < inputs_size(); ++i) { + input_tensors_[i] = allocator_.AllocatePersistentTfLiteTensor( + model_, graph_.GetAllocations(), inputs().Get(i), 0); + if (input_tensors_[i] == nullptr) { + MicroPrintf("Failed to initialize input tensor %d", i); + return kTfLiteError; + } + } + + // TODO(b/162311891): Drop these allocations when the interpreter supports + // handling buffers from TfLiteEvalTensor. + output_tensors_ = + reinterpret_cast(allocator_.AllocatePersistentBuffer( + sizeof(TfLiteTensor*) * outputs_size())); + if (output_tensors_ == nullptr) { + MicroPrintf( + "Failed to allocate memory for context->output_tensors_, " + "%d bytes required", + sizeof(TfLiteTensor*) * outputs_size()); + return kTfLiteError; + } + + for (size_t i = 0; i < outputs_size(); ++i) { + output_tensors_[i] = allocator_.AllocatePersistentTfLiteTensor( + model_, graph_.GetAllocations(), outputs().Get(i), 0); + if (output_tensors_[i] == nullptr) { + MicroPrintf("Failed to initialize output tensor %d", i); + return kTfLiteError; + } + } + + TF_LITE_ENSURE_STATUS(ResetVariableTensors()); + + tensors_allocated_ = true; + return kTfLiteOk; +} + +TfLiteStatus MicroInterpreter::Invoke() { + if (initialization_status_ != kTfLiteOk) { + MicroPrintf("Invoke() called after initialization failed\n"); + return kTfLiteError; + } + + // Ensure tensors are allocated before the interpreter is invoked to avoid + // difficult to debug segfaults. + if (!tensors_allocated_) { + TF_LITE_ENSURE_OK(&context_, AllocateTensors()); + } + return graph_.InvokeSubgraph(0); +} + +TfLiteTensor* MicroInterpreter::input(size_t index) { + const size_t length = inputs_size(); + if (index >= length) { + MicroPrintf("Input index %d out of range (length is %d)", index, length); + return nullptr; + } + return input_tensors_[index]; +} + +TfLiteTensor* MicroInterpreter::output(size_t index) { + const size_t length = outputs_size(); + if (index >= length) { + MicroPrintf("Output index %d out of range (length is %d)", index, length); + return nullptr; + } + return output_tensors_[index]; +} +// Repurposing free subgraphs to reset state for some ops for now +// will reset api is made. See b/220940833#comment25 for more context. +TfLiteStatus MicroInterpreter::Reset() { + TfLiteStatus status = graph_.FreeSubgraphs(); + if (status != kTfLiteOk) { + return status; + } + return graph_.ResetVariableTensors(); +} + +// TODO: remove this API completely in favor of MicroInterpreter::Reset +TfLiteStatus MicroInterpreter::ResetVariableTensors() { + return graph_.ResetVariableTensors(); +} + +TfLiteStatus MicroInterpreter::SetMicroExternalContext( + void* external_context_payload) { + return micro_context_.set_external_context(external_context_payload); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_interpreter.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_interpreter.h new file mode 100644 index 000000000..ee48a76d7 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_interpreter.h @@ -0,0 +1,196 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MICRO_INTERPRETER_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_INTERPRETER_H_ + +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/c_api_types.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/micro/micro_allocator.h" +#include "tensorflow/lite/micro/micro_context.h" +#include "tensorflow/lite/micro/micro_graph.h" +#include "tensorflow/lite/micro/micro_op_resolver.h" +#include "tensorflow/lite/micro/micro_profiler_interface.h" +#include "tensorflow/lite/portable_type_to_tflitetype.h" +#include "tensorflow/lite/schema/schema_generated.h" + +/// Copied from tensorflow/lite/version.h to avoid a dependency chain into +// tensorflow/core. +#define TFLITE_SCHEMA_VERSION (3) + +namespace tflite { + +class MicroInterpreter { + public: + // TODO(b/246776144): Will be removed with http://b/246776144 + MicroInterpreter(const Model* model, const MicroOpResolver& op_resolver, + uint8_t* tensor_arena, size_t tensor_arena_size, + ErrorReporter* error_reporter, + MicroResourceVariables* resource_variables = nullptr, + MicroProfilerInterface* profiler = nullptr) + : MicroInterpreter(model, op_resolver, tensor_arena, tensor_arena_size, + resource_variables, profiler) { + (void)error_reporter; + } + + // The lifetime of the model, op resolver, tensor arena, error reporter, + // resource variables, and profiler must be at least as long as that of the + // interpreter object, since the interpreter may need to access them at any + // time. This means that you should usually create them with the same scope as + // each other, for example having them all allocated on the stack as local + // variables through a top-level function. The interpreter doesn't do any + // deallocation of any of the pointed-to objects, ownership remains with the + // caller. + MicroInterpreter(const Model* model, const MicroOpResolver& op_resolver, + uint8_t* tensor_arena, size_t tensor_arena_size, + MicroResourceVariables* resource_variables = nullptr, + MicroProfilerInterface* profiler = nullptr); + + // TODO(b/246776144): Will be removed with http://b/246776144 + MicroInterpreter(const Model* model, const MicroOpResolver& op_resolver, + MicroAllocator* allocator, ErrorReporter* error_reporter, + MicroResourceVariables* resource_variables = nullptr, + MicroProfilerInterface* profiler = nullptr) + : MicroInterpreter(model, op_resolver, allocator, resource_variables, + profiler) { + (void)error_reporter; + } + + // Create an interpreter instance using an existing MicroAllocator instance. + // This constructor should be used when creating an allocator that needs to + // have allocation handled in more than one interpreter or for recording + // allocations inside the interpreter. The lifetime of the allocator must be + // as long as that of the interpreter object. + MicroInterpreter(const Model* model, const MicroOpResolver& op_resolver, + MicroAllocator* allocator, + MicroResourceVariables* resource_variables = nullptr, + MicroProfilerInterface* profiler = nullptr); + + ~MicroInterpreter(); + + // Runs through the model and allocates all necessary input, output and + // intermediate tensors. + TfLiteStatus AllocateTensors(); + + // In order to support partial graph runs for strided models, this can return + // values other than kTfLiteOk and kTfLiteError. + // TODO(b/149795762): Add this to the TfLiteStatus enum. + TfLiteStatus Invoke(); + + // This is the recommended API for an application to pass an external payload + // pointer as an external context to kernels. The life time of the payload + // pointer should be at least as long as this interpreter. TFLM supports only + // one external context. + TfLiteStatus SetMicroExternalContext(void* external_context_payload); + + TfLiteTensor* input(size_t index); + size_t inputs_size() const { + return model_->subgraphs()->Get(0)->inputs()->size(); + } + const flatbuffers::Vector& inputs() const { + return *model_->subgraphs()->Get(0)->inputs(); + } + TfLiteTensor* input_tensor(size_t index) { return input(index); } + template + T* typed_input_tensor(int tensor_index) { + if (TfLiteTensor* tensor_ptr = input_tensor(tensor_index)) { + if (tensor_ptr->type == typeToTfLiteType()) { + return GetTensorData(tensor_ptr); + } + } + return nullptr; + } + + TfLiteTensor* output(size_t index); + size_t outputs_size() const { + return model_->subgraphs()->Get(0)->outputs()->size(); + } + const flatbuffers::Vector& outputs() const { + return *model_->subgraphs()->Get(0)->outputs(); + } + TfLiteTensor* output_tensor(size_t index) { return output(index); } + template + T* typed_output_tensor(int tensor_index) { + if (TfLiteTensor* tensor_ptr = output_tensor(tensor_index)) { + if (tensor_ptr->type == typeToTfLiteType()) { + return GetTensorData(tensor_ptr); + } + } + return nullptr; + } + + // Reset the state to be what you would expect when the interpreter is first + // created. i.e. after Init and Prepare is called for the very first time. + TfLiteStatus Reset(); + + // TODO(b/244457206): remove this in favor of Reset() + // Reset all variable tensors to the default value. + TfLiteStatus ResetVariableTensors(); + + TfLiteStatus initialization_status() const { return initialization_status_; } + + // Populates node and registration pointers representing the inference graph + // of the model from values inside the flatbuffer (loaded from the TfLiteModel + // instance). Persistent data (e.g. operator data) is allocated from the + // arena. + TfLiteStatus PrepareNodeAndRegistrationDataFromFlatbuffer(); + + // For debugging only. + // Returns the actual used arena in bytes. This method gives the optimal arena + // size. It's only available after `AllocateTensors` has been called. + // Note that normally `tensor_arena` requires 16 bytes alignment to fully + // utilize the space. If it's not the case, the optimial arena size would be + // arena_used_bytes() + 16. + size_t arena_used_bytes() const { return allocator_.used_bytes(); } + + protected: + const MicroAllocator& allocator() const { return allocator_; } + const TfLiteContext& context() const { return context_; } + + private: + // TODO(b/158263161): Consider switching to Create() function to enable better + // error reporting during initialization. + void Init(MicroProfilerInterface* profiler); + + // Gets the current subgraph index used from within context methods. + int get_subgraph_index() { return graph_.GetCurrentSubgraphIndex(); } + + const Model* model_; + const MicroOpResolver& op_resolver_; + TfLiteContext context_ = {}; + MicroAllocator& allocator_; + MicroGraph graph_; + bool tensors_allocated_; + + TfLiteStatus initialization_status_; + + ScratchBufferHandle* scratch_buffer_handles_ = nullptr; + + // TODO(b/162311891): Clean these pointers up when this class supports buffers + // from TfLiteEvalTensor. + TfLiteTensor** input_tensors_; + TfLiteTensor** output_tensors_; + + MicroContext micro_context_; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_INTERPRETER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_log.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_log.cpp new file mode 100644 index 000000000..9c8ccaa3c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_log.cpp @@ -0,0 +1,47 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/micro_log.h" + +#include +#include +#include + +#if !defined(TF_LITE_STRIP_ERROR_STRINGS) +#include "tensorflow/lite/micro/debug_log.h" +#include "tensorflow/lite/micro/micro_string.h" +#endif + +void Log(const char* format, va_list args) { +#if !defined(TF_LITE_STRIP_ERROR_STRINGS) + // Only pulling in the implementation of this function for builds where we + // expect to make use of it to be extra cautious about not increasing the code + // size. + static constexpr int kMaxLogLen = 256; + char log_buffer[kMaxLogLen]; + MicroVsnprintf(log_buffer, kMaxLogLen, format, args); + DebugLog(log_buffer); + DebugLog("\r\n"); +#endif +} + +#if !defined(TF_LITE_STRIP_ERROR_STRINGS) +void MicroPrintf(const char* format, ...) { + va_list args; + va_start(args, format); + Log(format, args); + va_end(args); +} +#endif diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_log.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_log.h new file mode 100644 index 000000000..d9cfbe8c0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_log.h @@ -0,0 +1,44 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MICRO_LOG_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_LOG_H_ + +#include + +// This is a free function used to perform the actual logging. +// This function will be used by MicroPrintf and MicroErrorReporter::Report() +void Log(const char* format, va_list args); + +#if !defined(TF_LITE_STRIP_ERROR_STRINGS) +// This function can be used independent of the MicroErrorReporter to get +// printf-like functionalitys and are common to all target platforms. +void MicroPrintf(const char* format, ...); +#else +// We use a #define to ensure that the strings are completely stripped, to +// prevent an unnecessary increase in the binary size. +#define MicroPrintf(...) tflite::Unused(__VA_ARGS__) +#endif + +namespace tflite { + +// From +// https://stackoverflow.com/questions/23235910/variadic-unused-function-macro +template +void Unused(Args&&... args) { + (void)(sizeof...(args)); +} +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_LOG_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_mutable_op_resolver.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_mutable_op_resolver.h new file mode 100644 index 000000000..9093a97e0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_mutable_op_resolver.h @@ -0,0 +1,652 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MICRO_MUTABLE_OP_RESOLVER_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_MUTABLE_OP_RESOLVER_H_ + +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/flatbuffer_conversions.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/kernels/add.h" +#include "tensorflow/lite/micro/kernels/conv.h" +#include "tensorflow/lite/micro/kernels/depthwise_conv.h" +#include "tensorflow/lite/micro/kernels/ethosu.h" +#include "tensorflow/lite/micro/kernels/fully_connected.h" +#include "tensorflow/lite/micro/kernels/micro_ops.h" +#include "tensorflow/lite/micro/kernels/pooling.h" +#include "tensorflow/lite/micro/kernels/reduce.h" +#include "tensorflow/lite/micro/kernels/softmax.h" +#include "tensorflow/lite/micro/micro_error_reporter.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_op_resolver.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +TfLiteRegistration* Register_DETECTION_POSTPROCESS(); + +template +class MicroMutableOpResolver : public MicroOpResolver { + public: + TF_LITE_REMOVE_VIRTUAL_DELETE + + // TODO(b/246776144): Will be removed with http://b/246776144 + explicit MicroMutableOpResolver(ErrorReporter* error_reporter = nullptr) { + (void)error_reporter; + } + + // explicit MicroMutableOpResolver() {} + + const TfLiteRegistration* FindOp(tflite::BuiltinOperator op) const override { + if (op == BuiltinOperator_CUSTOM) return nullptr; + + for (unsigned int i = 0; i < registrations_len_; ++i) { + const TfLiteRegistration& registration = registrations_[i]; + if (registration.builtin_code == op) { + return ®istration; + } + } + return nullptr; + } + + const TfLiteRegistration* FindOp(const char* op) const override { + for (unsigned int i = 0; i < registrations_len_; ++i) { + const TfLiteRegistration& registration = registrations_[i]; + if ((registration.builtin_code == BuiltinOperator_CUSTOM) && + (strcmp(registration.custom_name, op) == 0)) { + return ®istration; + } + } + return nullptr; + } + + MicroOpResolver::BuiltinParseFunction GetOpDataParser( + BuiltinOperator op) const override { + TFLITE_DCHECK(num_buitin_ops_ <= tOpCount); + for (unsigned int i = 0; i < num_buitin_ops_; ++i) { + if (builtin_codes_[i] == op) return builtin_parsers_[i]; + } + return nullptr; + } + + // Registers a Custom Operator with the MicroOpResolver. + // + // Only the first call for a given name will be successful. i.e. if this + // function is called again for a previously added Custom Operator, the + // MicroOpResolver will be unchanged and this function will return + // kTfLiteError. + TfLiteStatus AddCustom(const char* name, TfLiteRegistration* registration) { + if (registrations_len_ >= tOpCount) { + MicroPrintf( + "Couldn't register custom op '%s', resolver size is too" + "small (%d)", + name, tOpCount); + return kTfLiteError; + } + + if (FindOp(name) != nullptr) { + MicroPrintf("Calling AddCustom for the same op more than once "); + MicroPrintf("is not supported (Op: %s).", name); + return kTfLiteError; + } + + TfLiteRegistration* new_registration = ®istrations_[registrations_len_]; + registrations_len_ += 1; + + *new_registration = *registration; + new_registration->builtin_code = BuiltinOperator_CUSTOM; + new_registration->custom_name = name; + return kTfLiteOk; + } + + // The Add* functions below add the various Builtin operators to the + // MicroMutableOpResolver object. + + TfLiteStatus AddAbs() { + return AddBuiltin(BuiltinOperator_ABS, tflite::ops::micro::Register_ABS(), + ParseAbs); + } + + TfLiteStatus AddAdd(const TfLiteRegistration& registration = Register_ADD()) { + return AddBuiltin(BuiltinOperator_ADD, registration, ParseAdd); + } + + TfLiteStatus AddAddN() { + return AddBuiltin(BuiltinOperator_ADD_N, tflite::Register_ADD_N(), + ParseAddN); + } + + TfLiteStatus AddArgMax() { + return AddBuiltin(BuiltinOperator_ARG_MAX, + tflite::ops::micro::Register_ARG_MAX(), ParseArgMax); + } + + TfLiteStatus AddArgMin() { + return AddBuiltin(BuiltinOperator_ARG_MIN, + tflite::ops::micro::Register_ARG_MIN(), ParseArgMin); + } + + TfLiteStatus AddAssignVariable() { + return AddBuiltin(BuiltinOperator_ASSIGN_VARIABLE, + tflite::Register_ASSIGN_VARIABLE(), ParseAssignVariable); + } + + TfLiteStatus AddAveragePool2D( + const TfLiteRegistration& registration = Register_AVERAGE_POOL_2D()) { + return AddBuiltin(BuiltinOperator_AVERAGE_POOL_2D, registration, ParsePool); + } + + TfLiteStatus AddBatchToSpaceNd() { + return AddBuiltin(BuiltinOperator_BATCH_TO_SPACE_ND, + Register_BATCH_TO_SPACE_ND(), ParseBatchToSpaceNd); + } + + TfLiteStatus AddBroadcastArgs() { + return AddBuiltin(BuiltinOperator_BROADCAST_ARGS, Register_BROADCAST_ARGS(), + ParseBroadcastArgs); + } + + TfLiteStatus AddBroadcastTo() { + return AddBuiltin(BuiltinOperator_BROADCAST_TO, Register_BROADCAST_TO(), + ParseBroadcastTo); + } + + TfLiteStatus AddCallOnce() { + return AddBuiltin(BuiltinOperator_CALL_ONCE, Register_CALL_ONCE(), + ParseCallOnce); + } + + TfLiteStatus AddCast() { + return AddBuiltin(BuiltinOperator_CAST, Register_CAST(), ParseCast); + } + + TfLiteStatus AddCeil() { + return AddBuiltin(BuiltinOperator_CEIL, tflite::ops::micro::Register_CEIL(), + ParseCeil); + } + + TfLiteStatus AddCircularBuffer() { + return AddCustom("CIRCULAR_BUFFER", tflite::Register_CIRCULAR_BUFFER()); + } + + TfLiteStatus AddConcatenation() { + return AddBuiltin(BuiltinOperator_CONCATENATION, + tflite::ops::micro::Register_CONCATENATION(), + ParseConcatenation); + } + + TfLiteStatus AddConv2D( + const TfLiteRegistration& registration = Register_CONV_2D()) { + return AddBuiltin(BuiltinOperator_CONV_2D, registration, ParseConv2D); + } + + TfLiteStatus AddCos() { + return AddBuiltin(BuiltinOperator_COS, tflite::ops::micro::Register_COS(), + ParseCos); + } + + TfLiteStatus AddCumSum() { + return AddBuiltin(BuiltinOperator_CUMSUM, tflite::Register_CUMSUM(), + ParseCumsum); + } + + TfLiteStatus AddDepthToSpace() { + return AddBuiltin(BuiltinOperator_DEPTH_TO_SPACE, + tflite::Register_DEPTH_TO_SPACE(), ParseDepthToSpace); + } + + TfLiteStatus AddDepthwiseConv2D( + const TfLiteRegistration& registration = Register_DEPTHWISE_CONV_2D()) { + return AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, registration, + ParseDepthwiseConv2D); + } + + TfLiteStatus AddDequantize() { + return AddBuiltin(BuiltinOperator_DEQUANTIZE, tflite::Register_DEQUANTIZE(), + ParseDequantize); + } + + TfLiteStatus AddDetectionPostprocess() { + return AddCustom("TFLite_Detection_PostProcess", + tflite::Register_DETECTION_POSTPROCESS()); + } + + TfLiteStatus AddDiv() { + return AddBuiltin(BuiltinOperator_DIV, tflite::Register_DIV(), ParseDiv); + } + + TfLiteStatus AddElu() { + return AddBuiltin(BuiltinOperator_ELU, tflite::Register_ELU(), ParseElu); + } + + TfLiteStatus AddEqual() { + return AddBuiltin(BuiltinOperator_EQUAL, + tflite::ops::micro::Register_EQUAL(), ParseEqual); + } + + TfLiteStatus AddEthosU() { + TfLiteRegistration* registration = tflite::Register_ETHOSU(); + if (registration) { + return AddCustom(tflite::GetString_ETHOSU(), registration); + } + return kTfLiteOk; + } + + TfLiteStatus AddExp() { + return AddBuiltin(BuiltinOperator_EXP, Register_EXP(), ParseExp); + } + + TfLiteStatus AddExpandDims() { + return AddBuiltin(BuiltinOperator_EXPAND_DIMS, Register_EXPAND_DIMS(), + ParseExpandDims); + } + + TfLiteStatus AddFill() { + return AddBuiltin(BuiltinOperator_FILL, tflite::Register_FILL(), ParseFill); + } + + TfLiteStatus AddFloor() { + return AddBuiltin(BuiltinOperator_FLOOR, + tflite::ops::micro::Register_FLOOR(), ParseFloor); + } + + TfLiteStatus AddFloorDiv() { + return AddBuiltin(BuiltinOperator_FLOOR_DIV, tflite::Register_FLOOR_DIV(), + ParseFloorDiv); + } + + TfLiteStatus AddFloorMod() { + return AddBuiltin(BuiltinOperator_FLOOR_MOD, tflite::Register_FLOOR_MOD(), + ParseFloorMod); + } + + TfLiteStatus AddFullyConnected( + const TfLiteRegistration& registration = Register_FULLY_CONNECTED()) { + return AddBuiltin(BuiltinOperator_FULLY_CONNECTED, registration, + ParseFullyConnected); + } + + TfLiteStatus AddGather() { + return AddBuiltin(BuiltinOperator_GATHER, tflite::Register_GATHER(), + ParseGather); + } + + TfLiteStatus AddGatherNd() { + return AddBuiltin(BuiltinOperator_GATHER_ND, tflite::Register_GATHER_ND(), + ParseGatherNd); + } + + TfLiteStatus AddGreater() { + return AddBuiltin(BuiltinOperator_GREATER, + tflite::ops::micro::Register_GREATER(), ParseGreater); + } + + TfLiteStatus AddGreaterEqual() { + return AddBuiltin(BuiltinOperator_GREATER_EQUAL, + tflite::ops::micro::Register_GREATER_EQUAL(), + ParseGreaterEqual); + } + + TfLiteStatus AddHardSwish() { + return AddBuiltin(BuiltinOperator_HARD_SWISH, tflite::Register_HARD_SWISH(), + ParseHardSwish); + } + + TfLiteStatus AddIf() { + return AddBuiltin(BuiltinOperator_IF, tflite::Register_IF(), ParseIf); + } + + TfLiteStatus AddL2Normalization() { + return AddBuiltin(BuiltinOperator_L2_NORMALIZATION, + tflite::ops::micro::Register_L2_NORMALIZATION(), + ParseL2Normalization); + } + + TfLiteStatus AddL2Pool2D() { + return AddBuiltin(BuiltinOperator_L2_POOL_2D, tflite::Register_L2_POOL_2D(), + ParsePool); + } + + TfLiteStatus AddLeakyRelu() { + return AddBuiltin(BuiltinOperator_LEAKY_RELU, tflite::Register_LEAKY_RELU(), + ParseLeakyRelu); + } + + TfLiteStatus AddLess() { + return AddBuiltin(BuiltinOperator_LESS, tflite::ops::micro::Register_LESS(), + ParseLess); + } + + TfLiteStatus AddLessEqual() { + return AddBuiltin(BuiltinOperator_LESS_EQUAL, + tflite::ops::micro::Register_LESS_EQUAL(), + ParseLessEqual); + } + + TfLiteStatus AddLog() { + return AddBuiltin(BuiltinOperator_LOG, tflite::ops::micro::Register_LOG(), + ParseLog); + } + + TfLiteStatus AddLogicalAnd() { + return AddBuiltin(BuiltinOperator_LOGICAL_AND, + tflite::Register_LOGICAL_AND(), ParseLogicalAnd); + } + + TfLiteStatus AddLogicalNot() { + return AddBuiltin(BuiltinOperator_LOGICAL_NOT, + tflite::ops::micro::Register_LOGICAL_NOT(), + ParseLogicalNot); + } + + TfLiteStatus AddLogicalOr() { + return AddBuiltin(BuiltinOperator_LOGICAL_OR, tflite::Register_LOGICAL_OR(), + ParseLogicalOr); + } + + TfLiteStatus AddLogistic() { + return AddBuiltin(BuiltinOperator_LOGISTIC, tflite::Register_LOGISTIC(), + ParseLogistic); + } + + TfLiteStatus AddLogSoftmax() { + return AddBuiltin(BuiltinOperator_LOG_SOFTMAX, + tflite::Register_LOG_SOFTMAX(), ParseLogSoftmax); + } + + TfLiteStatus AddMaximum() { + return AddBuiltin(BuiltinOperator_MAXIMUM, + tflite::ops::micro::Register_MAXIMUM(), ParseMaximum); + } + + TfLiteStatus AddMaxPool2D( + const TfLiteRegistration& registration = Register_MAX_POOL_2D()) { + return AddBuiltin(BuiltinOperator_MAX_POOL_2D, registration, ParsePool); + } + + TfLiteStatus AddMirrorPad() { + return AddBuiltin(BuiltinOperator_MIRROR_PAD, tflite::Register_MIRROR_PAD(), + ParseMirrorPad); + } + + TfLiteStatus AddMean() { + return AddBuiltin(BuiltinOperator_MEAN, Register_MEAN(), ParseReducer); + } + + TfLiteStatus AddMinimum() { + return AddBuiltin(BuiltinOperator_MINIMUM, + tflite::ops::micro::Register_MINIMUM(), ParseMinimum); + } + + TfLiteStatus AddMul(const TfLiteRegistration& registration = Register_MUL()) { + return AddBuiltin(BuiltinOperator_MUL, registration, ParseMul); + } + + TfLiteStatus AddNeg() { + return AddBuiltin(BuiltinOperator_NEG, tflite::ops::micro::Register_NEG(), + ParseNeg); + } + + TfLiteStatus AddNotEqual() { + return AddBuiltin(BuiltinOperator_NOT_EQUAL, + tflite::ops::micro::Register_NOT_EQUAL(), ParseNotEqual); + } + + TfLiteStatus AddPack() { + return AddBuiltin(BuiltinOperator_PACK, tflite::ops::micro::Register_PACK(), + ParsePack); + } + + TfLiteStatus AddPad() { + return AddBuiltin(BuiltinOperator_PAD, tflite::ops::micro::Register_PAD(), + ParsePad); + } + + TfLiteStatus AddPadV2() { + return AddBuiltin(BuiltinOperator_PADV2, + tflite::ops::micro::Register_PADV2(), ParsePadV2); + } + + TfLiteStatus AddPrelu() { + return AddBuiltin(BuiltinOperator_PRELU, tflite::Register_PRELU(), + ParsePrelu); + } + + TfLiteStatus AddQuantize() { + return AddBuiltin(BuiltinOperator_QUANTIZE, Register_QUANTIZE(), + ParseQuantize); + } + + TfLiteStatus AddReadVariable() { + return AddBuiltin(BuiltinOperator_READ_VARIABLE, + tflite::Register_READ_VARIABLE(), ParseReadVariable); + } + + TfLiteStatus AddReduceMax() { + return AddBuiltin(BuiltinOperator_REDUCE_MAX, Register_REDUCE_MAX(), + ParseReducer); + } + + TfLiteStatus AddRelu() { + return AddBuiltin(BuiltinOperator_RELU, tflite::Register_RELU(), ParseRelu); + } + + TfLiteStatus AddRelu6() { + return AddBuiltin(BuiltinOperator_RELU6, tflite::Register_RELU6(), + ParseRelu6); + } + + TfLiteStatus AddReshape() { + return AddBuiltin(BuiltinOperator_RESHAPE, + tflite::ops::micro::Register_RESHAPE(), ParseReshape); + } + + TfLiteStatus AddResizeBilinear() { + return AddBuiltin(BuiltinOperator_RESIZE_BILINEAR, + Register_RESIZE_BILINEAR(), ParseResizeBilinear); + } + + TfLiteStatus AddResizeNearestNeighbor() { + return AddBuiltin(BuiltinOperator_RESIZE_NEAREST_NEIGHBOR, + tflite::ops::micro::Register_RESIZE_NEAREST_NEIGHBOR(), + ParseResizeNearestNeighbor); + } + + TfLiteStatus AddRound() { + return AddBuiltin(BuiltinOperator_ROUND, + tflite::ops::micro::Register_ROUND(), ParseRound); + } + + TfLiteStatus AddRsqrt() { + return AddBuiltin(BuiltinOperator_RSQRT, + tflite::ops::micro::Register_RSQRT(), ParseRsqrt); + } + + TfLiteStatus AddSelectV2() { + return AddBuiltin(BuiltinOperator_SELECT_V2, Register_SELECT_V2(), + ParseSelectV2); + } + + TfLiteStatus AddShape() { + return AddBuiltin(BuiltinOperator_SHAPE, Register_SHAPE(), ParseShape); + } + + TfLiteStatus AddSin() { + return AddBuiltin(BuiltinOperator_SIN, tflite::ops::micro::Register_SIN(), + ParseSin); + } + + TfLiteStatus AddSlice() { + return AddBuiltin(BuiltinOperator_SLICE, Register_SLICE(), ParseSlice); + } + + TfLiteStatus AddSoftmax( + const TfLiteRegistration& registration = Register_SOFTMAX()) { + return AddBuiltin(BuiltinOperator_SOFTMAX, registration, ParseSoftmax); + } + + TfLiteStatus AddSpaceToBatchNd() { + return AddBuiltin(BuiltinOperator_SPACE_TO_BATCH_ND, + Register_SPACE_TO_BATCH_ND(), ParseSpaceToBatchNd); + } + + TfLiteStatus AddSpaceToDepth() { + return AddBuiltin(BuiltinOperator_SPACE_TO_DEPTH, Register_SPACE_TO_DEPTH(), + ParseSpaceToDepth); + } + + TfLiteStatus AddSplit() { + return AddBuiltin(BuiltinOperator_SPLIT, + tflite::ops::micro::Register_SPLIT(), ParseSplit); + } + + TfLiteStatus AddSplitV() { + return AddBuiltin(BuiltinOperator_SPLIT_V, + tflite::ops::micro::Register_SPLIT_V(), ParseSplitV); + } + + TfLiteStatus AddSqueeze() { + return AddBuiltin(BuiltinOperator_SQUEEZE, Register_SQUEEZE(), + ParseSqueeze); + } + + TfLiteStatus AddSqrt() { + return AddBuiltin(BuiltinOperator_SQRT, tflite::ops::micro::Register_SQRT(), + ParseSqrt); + } + + TfLiteStatus AddSquare() { + return AddBuiltin(BuiltinOperator_SQUARE, + tflite::ops::micro::Register_SQUARE(), ParseSquare); + } + + TfLiteStatus AddSquaredDifference() { + return AddBuiltin(BuiltinOperator_SQUARED_DIFFERENCE, + tflite::Register_SQUARED_DIFFERENCE(), + ParseSquaredDifference); + } + + TfLiteStatus AddStridedSlice() { + return AddBuiltin(BuiltinOperator_STRIDED_SLICE, + tflite::ops::micro::Register_STRIDED_SLICE(), + ParseStridedSlice); + } + + TfLiteStatus AddSub() { + return AddBuiltin(BuiltinOperator_SUB, tflite::Register_SUB(), ParseSub); + } + + TfLiteStatus AddSum() { + return AddBuiltin(BuiltinOperator_SUM, Register_SUM(), ParseReducer); + } + + TfLiteStatus AddSvdf( + const TfLiteRegistration& registration = Register_SVDF()) { + return AddBuiltin(BuiltinOperator_SVDF, registration, ParseSvdf); + } + + TfLiteStatus AddTanh() { + return AddBuiltin(BuiltinOperator_TANH, tflite::ops::micro::Register_TANH(), + ParseTanh); + } + + TfLiteStatus AddTransposeConv() { + return AddBuiltin(BuiltinOperator_TRANSPOSE_CONV, + tflite::Register_TRANSPOSE_CONV(), ParseTransposeConv); + } + + TfLiteStatus AddTranspose() { + return AddBuiltin(BuiltinOperator_TRANSPOSE, Register_TRANSPOSE(), + ParseTranspose); + } + + TfLiteStatus AddUnpack() { + return AddBuiltin(BuiltinOperator_UNPACK, + tflite::ops::micro::Register_UNPACK(), ParseUnpack); + } + + TfLiteStatus AddUnidirectionalSequenceLSTM() { + return AddBuiltin(BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM, + Register_UNIDIRECTIONAL_SEQUENCE_LSTM(), + ParseUnidirectionalSequenceLSTM); + } + + TfLiteStatus AddVarHandle() { + return AddBuiltin(BuiltinOperator_VAR_HANDLE, Register_VAR_HANDLE(), + ParseVarHandle); + } + + TfLiteStatus AddWhile() { + return AddBuiltin(BuiltinOperator_WHILE, Register_WHILE(), ParseWhile); + } + + TfLiteStatus AddZerosLike() { + return AddBuiltin(BuiltinOperator_ZEROS_LIKE, Register_ZEROS_LIKE(), + ParseZerosLike); + } + + unsigned int GetRegistrationLength() { return registrations_len_; } + + private: + TfLiteStatus AddBuiltin(tflite::BuiltinOperator op, + const TfLiteRegistration& registration, + MicroOpResolver::BuiltinParseFunction parser) { + if (op == BuiltinOperator_CUSTOM) { + MicroPrintf("Invalid parameter BuiltinOperator_CUSTOM to the "); + MicroPrintf("AddBuiltin function."); + return kTfLiteError; + } + + if (FindOp(op) != nullptr) { + MicroPrintf("Calling AddBuiltin with the same op more than "); + MicroPrintf("once is not supported (Op: #%d).", op); + return kTfLiteError; + } + + if (registrations_len_ >= tOpCount) { + MicroPrintf("Couldn't register builtin op #%d, resolver size ", op); + MicroPrintf("is too small (%d).", tOpCount); + return kTfLiteError; + } + + registrations_[registrations_len_] = registration; + // Strictly speaking, the builtin_code is not necessary for TFLM but filling + // it in regardless. + registrations_[registrations_len_].builtin_code = op; + registrations_len_++; + + builtin_codes_[num_buitin_ops_] = op; + builtin_parsers_[num_buitin_ops_] = parser; + num_buitin_ops_++; + + return kTfLiteOk; + } + + TfLiteRegistration registrations_[tOpCount]; + unsigned int registrations_len_ = 0; + + // Arrays (and counter) to store the builtin codes and their corresponding + // parse functions as these are registered with the Op Resolver. + BuiltinOperator builtin_codes_[tOpCount]; + MicroOpResolver::BuiltinParseFunction builtin_parsers_[tOpCount]; + unsigned int num_buitin_ops_ = 0; +}; + +}; // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_MUTABLE_OP_RESOLVER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_op_resolver.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_op_resolver.h new file mode 100644 index 000000000..757b6b894 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_op_resolver.h @@ -0,0 +1,73 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MICRO_OP_RESOLVER_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_OP_RESOLVER_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/core/api/flatbuffer_conversions.h" +#include "tensorflow/lite/core/api/op_resolver.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +// This is an interface for the OpResolver for TFLiteMicro. The differences from +// the TFLite OpResolver base class are to: +// * explicitly remove support for Op versions +// * allow for finer grained registration of the Builtin Ops to reduce code +// size for TFLiteMicro. +// +// We need an interface class instead of directly using MicroMutableOpResolver +// because MicroMutableOpResolver is a class template with the number of +// registered Ops as the template parameter. +class MicroOpResolver : public OpResolver { + public: + typedef TfLiteStatus (*BuiltinParseFunction)(const Operator* op, + ErrorReporter* error_reporter, + BuiltinDataAllocator* allocator, + void** builtin_data); + + // Returns the Op registration struct corresponding to the enum code from the + // flatbuffer schema. Returns nullptr if the op is not found or if op == + // BuiltinOperator_CUSTOM. + virtual const TfLiteRegistration* FindOp(BuiltinOperator op) const = 0; + + // Returns the Op registration struct corresponding to the custom operator by + // name. + virtual const TfLiteRegistration* FindOp(const char* op) const = 0; + + // This implementation exists for compatibility with the OpResolver base class + // and disregards the version parameter. + const TfLiteRegistration* FindOp(BuiltinOperator op, + int version) const final { + return FindOp(op); + } + + // This implementation exists for compatibility with the OpResolver base class + // and disregards the version parameter. + const TfLiteRegistration* FindOp(const char* op, int version) const final { + return FindOp(op); + } + + // Returns the operator specific parsing function for the OpData for a + // BuiltinOperator (if registered), else nullptr. + virtual BuiltinParseFunction GetOpDataParser(BuiltinOperator op) const = 0; + + ~MicroOpResolver() override {} +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_OP_RESOLVER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler.cpp new file mode 100644 index 000000000..e9eb5e549 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler.cpp @@ -0,0 +1,115 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/micro/micro_profiler.h" + +#include +#include +#include + +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_time.h" + +namespace tflite { + +uint32_t MicroProfiler::BeginEvent(const char* tag) { + if (num_events_ == kMaxEvents) { + num_events_ = 0; + } + + tags_[num_events_] = tag; + start_ticks_[num_events_] = GetCurrentTimeTicks(); + end_ticks_[num_events_] = start_ticks_[num_events_] - 1; + return num_events_++; +} + +void MicroProfiler::EndEvent(uint32_t event_handle) { + TFLITE_DCHECK(event_handle < kMaxEvents); + end_ticks_[event_handle] = GetCurrentTimeTicks(); +} + +uint32_t MicroProfiler::GetTotalTicks() const { + int32_t ticks = 0; + for (int i = 0; i < num_events_; ++i) { + ticks += end_ticks_[i] - start_ticks_[i]; + } + return ticks; +} + +void MicroProfiler::Log() const { +#if !defined(TF_LITE_STRIP_ERROR_STRINGS) + for (int i = 0; i < num_events_; ++i) { + uint32_t ticks = end_ticks_[i] - start_ticks_[i]; + MicroPrintf("%s took %" PRIu32 " ticks (%d ms).", tags_[i], ticks, + TicksToMs(ticks)); + } +#endif +} + +void MicroProfiler::LogCsv() const { +#if !defined(TF_LITE_STRIP_ERROR_STRINGS) + MicroPrintf("\"Event\",\"Tag\",\"Ticks\""); + for (int i = 0; i < num_events_; ++i) { + uint32_t ticks = end_ticks_[i] - start_ticks_[i]; + MicroPrintf("%d,%s,%" PRIu32, i, tags_[i], ticks); + } +#endif +} + +void MicroProfiler::LogTicksPerTagCsv() { +#if !defined(TF_LITE_STRIP_ERROR_STRINGS) + MicroPrintf( + "\"Unique Tag\",\"Total ticks across all events with that tag.\""); + int total_ticks = 0; + for (int i = 0; i < num_events_; ++i) { + uint32_t ticks = end_ticks_[i] - start_ticks_[i]; + TFLITE_DCHECK(tags_[i] != nullptr); + int position = FindExistingOrNextPosition(tags_[i]); + TFLITE_DCHECK(position >= 0); + total_ticks_per_tag[position].tag = tags_[i]; + total_ticks_per_tag[position].ticks = + total_ticks_per_tag[position].ticks + ticks; + total_ticks += ticks; + } + + for (int i = 0; i < num_events_; ++i) { + TicksPerTag each_tag_entry = total_ticks_per_tag[i]; + if (each_tag_entry.tag == nullptr) { + break; + } + MicroPrintf("%s, %d", each_tag_entry.tag, each_tag_entry.ticks); + } + MicroPrintf("total number of ticks, %d", total_ticks); +#endif +} + +// This method finds a particular array element in the total_ticks_per_tag array +// with the matching tag_name passed in the method. If it can find a +// matching array element that has the same tag_name, then it will return the +// position of the matching element. But if it unable to find a matching element +// with the given tag_name, it will return the next available empty position +// from the array. +int MicroProfiler::FindExistingOrNextPosition(const char* tag_name) { + int pos = 0; + for (; pos < num_events_; pos++) { + TicksPerTag each_tag_entry = total_ticks_per_tag[pos]; + if (each_tag_entry.tag == nullptr || + strcmp(each_tag_entry.tag, tag_name) == 0) { + return pos; + } + } + return pos < num_events_ ? pos : -1; +} +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler.h new file mode 100644 index 000000000..0648588c4 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler.h @@ -0,0 +1,138 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MICRO_PROFILER_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_PROFILER_H_ + +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/micro_profiler_interface.h" + +namespace tflite { + +// MicroProfiler creates a common way to gain fine-grained insight into runtime +// performance. Bottleck operators can be identified along with slow code +// sections. This can be used in conjunction with running the relevant micro +// benchmark to evaluate end-to-end performance. +class MicroProfiler : public MicroProfilerInterface { + public: + MicroProfiler() = default; + virtual ~MicroProfiler() = default; + + // Marks the start of a new event and returns an event handle that can be used + // to mark the end of the event via EndEvent. The lifetime of the tag + // parameter must exceed that of the MicroProfiler. + virtual uint32_t BeginEvent(const char* tag) override; + + // Marks the end of an event associated with event_handle. It is the + // responsibility of the caller to ensure than EndEvent is called once and + // only once per event_handle. + // + // If EndEvent is called more than once for the same event_handle, the last + // call will be used as the end of event marker.If EndEvent is called 0 times + // for a particular event_handle, the duration of that event will be 0 ticks. + virtual void EndEvent(uint32_t event_handle) override; + + // Clears all the events that have been currently profiled. + void ClearEvents() { num_events_ = 0; } + + // Returns the sum of the ticks taken across all the events. This number + // is only meaningful if all of the events are disjoint (the end time of + // event[i] <= start time of event[i+1]). + uint32_t GetTotalTicks() const; + + // Prints the profiling information of each of the events in human readable + // form. + void Log() const; + + // Prints the profiling information of each of the events in CSV (Comma + // Separated Value) form. + void LogCsv() const; + + // Prints total ticks for each unique tag in CSV format. + // Output will have one row for each unique tag along with the + // total ticks summed across all events with that particular tag. + void LogTicksPerTagCsv(); + + private: + // Maximum number of events that this class can keep track of. If we call + // AddEvent more than kMaxEvents number of times, then the oldest event's + // profiling information will be overwritten. + static constexpr int kMaxEvents = 1024; + + const char* tags_[kMaxEvents]; + uint32_t start_ticks_[kMaxEvents]; + uint32_t end_ticks_[kMaxEvents]; + int num_events_ = 0; + + struct TicksPerTag { + const char* tag; + uint32_t ticks; + }; + // In practice, the number of tags will be much lower than the number of + // events. But it is theoretically possible that each event to be unique and + // hence we allow total_ticks_per_tag to have kMaxEvents entries. + TicksPerTag total_ticks_per_tag[kMaxEvents] = {}; + + int FindExistingOrNextPosition(const char* tag_name); + + TF_LITE_REMOVE_VIRTUAL_DELETE; +}; + +#if defined(TF_LITE_STRIP_ERROR_STRINGS) +// For release builds, the ScopedMicroProfiler is a noop. +// +// This is done because the ScipedProfiler is used as part of the +// MicroInterpreter and we want to ensure zero overhead for the release builds. +class ScopedMicroProfiler { + public: + explicit ScopedMicroProfiler(const char* tag, MicroProfiler* profiler) {} +}; + +#else + +// This class can be used to add events to a MicroProfiler object that span the +// lifetime of the ScopedMicroProfiler object. +// Usage example: +// +// MicroProfiler profiler(); +// ... +// { +// ScopedMicroProfiler scoped_profiler("custom_tag", profiler); +// work_to_profile(); +// } +class ScopedMicroProfiler { + public: + explicit ScopedMicroProfiler(const char* tag, MicroProfiler* profiler) + : profiler_(profiler) { + if (profiler_ != nullptr) { + event_handle_ = profiler_->BeginEvent(tag); + } + } + + ~ScopedMicroProfiler() { + if (profiler_ != nullptr) { + profiler_->EndEvent(event_handle_); + } + } + + private: + uint32_t event_handle_ = 0; + MicroProfiler* profiler_ = nullptr; +}; +#endif // !defined(TF_LITE_STRIP_ERROR_STRINGS) + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_PROFILER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler_interface.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler_interface.h new file mode 100644 index 000000000..f839a74ae --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_profiler_interface.h @@ -0,0 +1,38 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MICRO_PROFILER_INTERFACE_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_PROFILER_INTERFACE_H_ + +#include + +namespace tflite { + +// Interface class that the TFLM framework relies on for profiling. +class MicroProfilerInterface { + public: + virtual ~MicroProfilerInterface() {} + + // Marks the start of a new event and returns an event handle that can be used + // to mark the end of the event via EndEvent. + virtual uint32_t BeginEvent(const char* tag) = 0; + + // Marks the end of an event associated with event_handle. + virtual void EndEvent(uint32_t event_handle) = 0; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_PROFILER_INTERFACE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_resource_variable.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_resource_variable.cpp new file mode 100644 index 000000000..e6cea845b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_resource_variable.cpp @@ -0,0 +1,148 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/micro_resource_variable.h" + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_utils.h" + +namespace tflite { + +namespace {} // namespace + +MicroResourceVariables* MicroResourceVariables::Create( + MicroAllocator* allocator, int max_num_variables) { + TFLITE_DCHECK(allocator != nullptr); + + uint8_t* allocator_buffer = static_cast( + allocator->AllocatePersistentBuffer(sizeof(MicroResourceVariables))); + MicroResourceVariable* variable_array = + static_cast(allocator->AllocatePersistentBuffer( + sizeof(MicroResourceVariable) * max_num_variables)); + MicroResourceVariables* variables = new (allocator_buffer) + MicroResourceVariables(variable_array, max_num_variables); + return variables; +} + +int MicroResourceVariables::CreateIdIfNoneFound(const char* container, + const char* shared_name) { + int resource_id = FindId(container, shared_name); + if (resource_id >= 0) { + return resource_id; + } + + // no existing variable found for the given container and shared name pair. + if (num_resource_variables_ >= max_variable_count_) { + MicroPrintf( + "Failed to allocate resource variable. Maximum resource variable count " + "(%d) " + "reached.", + max_variable_count_); + return -1; + } + + resource_id = num_resource_variables_++; + resource_variables_[resource_id].container = container; + resource_variables_[resource_id].shared_name = shared_name; + resource_variables_[resource_id].resource_buffer = nullptr; + resource_variables_[resource_id].bytes = 0; + return resource_id; +} + +TfLiteStatus MicroResourceVariables::Read(int id, + const TfLiteEvalTensor* tensor) { + if (id < 0 || id >= num_resource_variables_) { + MicroPrintf("Attempting to read non-existent resource variable %d", id); + return kTfLiteError; + } + MicroResourceVariable variable = resource_variables_[id]; + TFLITE_DCHECK(EvalTensorBytes(tensor) == variable.bytes); + TFLITE_DCHECK(variable.resource_buffer != nullptr); + memcpy(tensor->data.raw, variable.resource_buffer, variable.bytes); + return kTfLiteOk; +} + +TfLiteStatus MicroResourceVariables::Allocate(int id, TfLiteContext* context, + const TfLiteTensor* tensor) { + if (id < 0 || id >= num_resource_variables_) { + MicroPrintf("Attempting to read non-existent resource variable %d", id); + return kTfLiteError; + } + + MicroResourceVariable& variable = resource_variables_[id]; + + if (variable.resource_buffer == nullptr) { + variable.bytes = tensor->bytes; + variable.resource_buffer = + context->AllocatePersistentBuffer(context, tensor->bytes); + if (variable.resource_buffer == nullptr) { + MicroPrintf("Failed to allocate resource buffer."); + return kTfLiteError; + } + // Zero out resource buffers by deafult. Buffers can be initialized to + // nonzero values using ASSIGN_VARIABLE. + memset(variable.resource_buffer, 0, variable.bytes); + } + + return kTfLiteOk; +} + +TfLiteStatus MicroResourceVariables::Assign(int id, + const TfLiteEvalTensor* tensor) { + if (id < 0 || id >= num_resource_variables_) { + MicroPrintf("Attempting to read non-existent resource variable %d", id); + return kTfLiteError; + } + MicroResourceVariable variable = resource_variables_[id]; + + if (variable.resource_buffer == nullptr) { + MicroPrintf( + "Attempting to assign from a TfLiteEvalTensor before the resource " + "buffer has been allocated. Make sure to call AssignResourceVariable " + "with a TfLiteTensor first."); + return kTfLiteError; + } + TFLITE_DCHECK(EvalTensorBytes(tensor) == variable.bytes); + memcpy(variable.resource_buffer, tensor->data.raw, variable.bytes); + return kTfLiteOk; +} + +TfLiteStatus MicroResourceVariables::ResetAll() { + for (int i = 0; i < num_resource_variables_; i++) { + MicroResourceVariable variable = resource_variables_[i]; + memset(variable.resource_buffer, 0, variable.bytes); + } + return kTfLiteOk; +} + +int MicroResourceVariables::FindId(const char* container, + const char* shared_name) { + for (int i = 0; i < num_resource_variables_; i++) { + // Some TFLite flatbuffers contain null container names to save space. + if ((container == nullptr || + !strcmp(container, resource_variables_[i].container)) && + !strcmp(shared_name, resource_variables_[i].shared_name)) { + return i; + } + } + return -1; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_resource_variable.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_resource_variable.h new file mode 100644 index 000000000..e8df991c3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_resource_variable.h @@ -0,0 +1,87 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TFLITE_MICRO_TENSORFLOW_LITE_MICRO_MICRO_RESOURCE_H_ +#define TFLITE_MICRO_TENSORFLOW_LITE_MICRO_MICRO_RESOURCE_H_ + +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_allocator.h" + +namespace tflite { + +class MicroResourceVariables { + public: + // Create + static MicroResourceVariables* Create(MicroAllocator* allocator, + int num_variables); + + // Creates a resource variable if none is available for the given container + // and shared name pair. Returns the resource ID corresponding to the + // container and shared name pair. If allocation fails, the returned resource + // ID will be negative. The the container and shared_name must outlive this + // class. + int CreateIdIfNoneFound(const char* container, const char* shared_name); + + // Read the resource buffer associated with the given ID into the given + // tensor. + TfLiteStatus Read(int id, const TfLiteEvalTensor* tensor); + + // Allocates the resource buffer if none has been allocated, based on the + // length of the input tensor. Copies input tensor contents to the resource + // buffer. + TfLiteStatus Allocate(int id, TfLiteContext* context, + const TfLiteTensor* tensor); + + // Copies input tensor contents to the resource buffer. + // AllocateResourceVariable with a TFLite tensor must have been called first + // in order to allocate the resource buffer. + TfLiteStatus Assign(int id, const TfLiteEvalTensor* tensor); + + // Zeros out all resource buffers. + TfLiteStatus ResetAll(); + + private: + int FindId(const char* container, const char* shared_name); + + // Micro resource contains the mapping between resource container/name strings + // and resouce IDs. Each resource ID corresponds to a resource buffer pointer. + // The resouce ID is created during the VAR_HANDLE operator preparation stage. + // The resource buffer pointer is created during ASSIGN_VARIABLE preparation + // stage based on the size of the TFLiteTensor being assigned. + struct MicroResourceVariable { + const char* container; + const char* shared_name; + void* resource_buffer; + + // This is only for verifying read size. + size_t bytes; + }; + + MicroResourceVariables(MicroResourceVariable* variables, + int max_variable_count) + : resource_variables_(variables), + max_variable_count_(max_variable_count), + num_resource_variables_(0) {} + + MicroResourceVariable* resource_variables_; + int max_variable_count_; + int num_resource_variables_; +}; + +} // namespace tflite + +#endif // TFLITE_MICRO_TENSORFLOW_LITE_MICRO_MICRO_RESOURCE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_string.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_string.cpp new file mode 100644 index 000000000..bb41a9e39 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_string.cpp @@ -0,0 +1,317 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Implements debug logging for numbers by converting them into strings and then +// calling the main DebugLog(char*) function. These are separated into a +// different file so that platforms can just implement the string output version +// of DebugLog() and then get the numerical variations without requiring any +// more code. + +#include "tensorflow/lite/micro/micro_string.h" + +#include +#include +#include + +namespace { + +// Int formats can need up to 10 bytes for the value plus a single byte for the +// sign. +constexpr int kMaxIntCharsNeeded = 10 + 1; +// Hex formats can need up to 8 bytes for the value plus two bytes for the "0x". +constexpr int kMaxHexCharsNeeded = 8 + 2; + +// Float formats can need up to 7 bytes for the fraction plus 3 bytes for "x2^" +// plus 3 bytes for the exponent and a single sign bit. +constexpr float kMaxFloatCharsNeeded = 7 + 3 + 3 + 1; + +// All input buffers to the number conversion functions must be this long. +const int kFastToBufferSize = 48; + +// Reverses a zero-terminated string in-place. +char* ReverseStringInPlace(char* start, char* end) { + char* p1 = start; + char* p2 = end - 1; + while (p1 < p2) { + char tmp = *p1; + *p1++ = *p2; + *p2-- = tmp; + } + return start; +} + +// Appends a string to a string, in-place. You need to pass in the maximum +// string length as the second argument. +char* StrCatStr(char* main, int main_max_length, const char* to_append) { + char* current = main; + while (*current != 0) { + ++current; + } + char* current_end = main + (main_max_length - 1); + while ((*to_append != 0) && (current < current_end)) { + *current = *to_append; + ++current; + ++to_append; + } + *current = 0; + return current; +} + +// Populates the provided buffer with an ASCII representation of the number. +char* FastUInt32ToBufferLeft(uint32_t i, char* buffer, int base) { + char* start = buffer; + do { + int32_t digit = i % base; + char character; + if (digit < 10) { + character = '0' + digit; + } else { + character = 'a' + (digit - 10); + } + *buffer++ = character; + i /= base; + } while (i > 0); + *buffer = 0; + ReverseStringInPlace(start, buffer); + return buffer; +} + +// Populates the provided buffer with an ASCII representation of the number. +char* FastInt32ToBufferLeft(int32_t i, char* buffer) { + uint32_t u = i; + if (i < 0) { + *buffer++ = '-'; + u = -u; + } + return FastUInt32ToBufferLeft(u, buffer, 10); +} + +// Converts a number to a string and appends it to another. +char* StrCatInt32(char* main, int main_max_length, int32_t number) { + char number_string[kFastToBufferSize]; + FastInt32ToBufferLeft(number, number_string); + return StrCatStr(main, main_max_length, number_string); +} + +// Converts a number to a string and appends it to another. +char* StrCatUInt32(char* main, int main_max_length, uint32_t number, int base) { + char number_string[kFastToBufferSize]; + FastUInt32ToBufferLeft(number, number_string, base); + return StrCatStr(main, main_max_length, number_string); +} + +// Populates the provided buffer with ASCII representation of the float number. +// Avoids the use of any floating point instructions (since these aren't +// supported on many microcontrollers) and as a consequence prints values with +// power-of-two exponents. +char* FastFloatToBufferLeft(float f, char* buffer) { + char* current = buffer; + char* current_end = buffer + (kFastToBufferSize - 1); + // Access the bit fields of the floating point value to avoid requiring any + // float instructions. These constants are derived from IEEE 754. + const uint32_t sign_mask = 0x80000000; + const uint32_t exponent_mask = 0x7f800000; + const int32_t exponent_shift = 23; + const int32_t exponent_bias = 127; + const uint32_t fraction_mask = 0x007fffff; + uint32_t u; + memcpy(&u, &f, sizeof(int32_t)); + const int32_t exponent = + ((u & exponent_mask) >> exponent_shift) - exponent_bias; + const uint32_t fraction = (u & fraction_mask); + // Expect ~0x2B1B9D3 for fraction. + if (u & sign_mask) { + *current = '-'; + current += 1; + } + *current = 0; + // These are special cases for infinities and not-a-numbers. + if (exponent == 128) { + if (fraction == 0) { + current = StrCatStr(current, (current_end - current), "Inf"); + return current; + } else { + current = StrCatStr(current, (current_end - current), "NaN"); + return current; + } + } + // 0x007fffff (8388607) represents 0.99... for the fraction, so to print the + // correct decimal digits we need to scale our value before passing it to the + // conversion function. This scale should be 10000000/8388608 = 1.1920928955. + // We can approximate this using multiply-adds and right-shifts using the + // values in this array. The 1. portion of the number string is printed out + // in a fixed way before the fraction, below. + const int32_t scale_shifts_size = 13; + const int8_t scale_shifts[13] = {3, 4, 8, 11, 13, 14, 17, + 18, 19, 20, 21, 22, 23}; + uint32_t scaled_fraction = fraction; + for (int i = 0; i < scale_shifts_size; ++i) { + scaled_fraction += (fraction >> scale_shifts[i]); + } + *current = '1'; + current += 1; + *current = '.'; + current += 1; + *current = 0; + + // Prepend leading zeros to fill in all 7 bytes of the fraction. Truncate + // zeros off the end of the fraction. Every fractional value takes 7 bytes. + // For example, 2500 would be written into the buffer as 0002500 since it + // represents .00025. + constexpr int kMaxFractionalDigits = 7; + + // Abort early if there is not enough space in the buffer. + if (current_end - current <= kMaxFractionalDigits) { + return current; + } + + // Pre-fill buffer with zeros to ensure zero-truncation works properly. + for (int i = 1; i < kMaxFractionalDigits; i++) { + *(current + i) = '0'; + } + + // Track how large the fraction is to add leading zeros. + char* previous = current; + current = StrCatUInt32(current, (current_end - current), scaled_fraction, 10); + int fraction_digits = current - previous; + int leading_zeros = kMaxFractionalDigits - fraction_digits; + + // Overwrite the null terminator from StrCatUInt32 to ensure zero-trunctaion + // works properly. + *current = '0'; + + // Shift fraction values and prepend zeros if necessary. + if (leading_zeros != 0) { + for (int i = 0; i < fraction_digits; i++) { + current--; + *(current + leading_zeros) = *current; + *current = '0'; + } + current += kMaxFractionalDigits; + } + + // Truncate trailing zeros for cleaner logs. Ensure we leave at least one + // fractional character for the case when scaled_fraction is 0. + while (*(current - 1) == '0' && (current - 1) > previous) { + current--; + } + *current = 0; + current = StrCatStr(current, (current_end - current), "*2^"); + current = StrCatInt32(current, (current_end - current), exponent); + return current; +} + +int FormatInt32(char* output, int32_t i) { + return static_cast(FastInt32ToBufferLeft(i, output) - output); +} + +int FormatUInt32(char* output, uint32_t i) { + return static_cast(FastUInt32ToBufferLeft(i, output, 10) - output); +} + +int FormatHex(char* output, uint32_t i) { + return static_cast(FastUInt32ToBufferLeft(i, output, 16) - output); +} + +int FormatFloat(char* output, float i) { + return static_cast(FastFloatToBufferLeft(i, output) - output); +} + +} // namespace + +extern "C" int MicroVsnprintf(char* output, int len, const char* format, + va_list args) { + int output_index = 0; + const char* current = format; + // One extra character must be left for the null terminator. + const int usable_length = len - 1; + while (*current != '\0' && output_index < usable_length) { + if (*current == '%') { + current++; + switch (*current) { + case 'd': + // Cut off log message if format could exceed log buffer length. + if (usable_length - output_index < kMaxIntCharsNeeded) { + output[output_index++] = '\0'; + return output_index; + } + output_index += + FormatInt32(&output[output_index], va_arg(args, int32_t)); + current++; + break; + case 'u': + if (usable_length - output_index < kMaxIntCharsNeeded) { + output[output_index++] = '\0'; + return output_index; + } + output_index += + FormatUInt32(&output[output_index], va_arg(args, uint32_t)); + current++; + break; + case 'x': + if (usable_length - output_index < kMaxHexCharsNeeded) { + output[output_index++] = '\0'; + return output_index; + } + output[output_index++] = '0'; + output[output_index++] = 'x'; + output_index += + FormatHex(&output[output_index], va_arg(args, uint32_t)); + current++; + break; + case 'f': + if (usable_length - output_index < kMaxFloatCharsNeeded) { + output[output_index++] = '\0'; + return output_index; + } + output_index += + FormatFloat(&output[output_index], va_arg(args, double)); + current++; + break; + case '%': + output[output_index++] = *current++; + break; + case 'c': + if (usable_length - output_index < 1) { + output[output_index++] = '\0'; + return output_index; + } + output[output_index++] = va_arg(args, int32_t); + current++; + break; + case 's': + char* string = va_arg(args, char*); + int string_idx = 0; + while (string_idx + output_index < usable_length && + string[string_idx] != '\0') { + output[output_index++] = string[string_idx++]; + } + current++; + } + } else { + output[output_index++] = *current++; + } + } + output[output_index++] = '\0'; + return output_index; +} + +extern "C" int MicroSnprintf(char* output, int len, const char* format, ...) { + va_list args; + va_start(args, format); + int bytes_written = MicroVsnprintf(output, len, format, args); + va_end(args); + return bytes_written; +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_string.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_string.h new file mode 100644 index 000000000..59303e82b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_string.h @@ -0,0 +1,33 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MICRO_STRING_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_STRING_H_ + +#include + +// Implements simple string formatting for numeric types. Returns the number of +// bytes written to output. +extern "C" { +// Functionally equivalent to vsnprintf, trimmed down for TFLite Micro. +// MicroSnprintf() is implemented using MicroVsnprintf(). +int MicroVsnprintf(char* output, int len, const char* format, va_list args); +// Functionally equavalent to snprintf, trimmed down for TFLite Micro. +// For example, MicroSnprintf(buffer, 10, "int %d", 10) will put the string +// "int 10" in the buffer. +// Floating point values are logged in exponent notation (1.XXX*2^N). +int MicroSnprintf(char* output, int len, const char* format, ...); +} + +#endif // TENSORFLOW_LITE_MICRO_MICRO_STRING_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_time.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_time.cpp new file mode 100644 index 000000000..d50cb3fc3 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_time.cpp @@ -0,0 +1,63 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Reference implementation of timer functions. Platforms are not required to +// implement these timer methods, but they are required to enable profiling. + +// On platforms that have a POSIX stack or C library, it can be written using +// methods from or clock() from . + +// To add an equivalent function for your own platform, create your own +// implementation file, and place it in a subfolder with named after the OS +// you're targeting. For example, see the Cortex M bare metal version in +// tensorflow/lite/micro/bluepill/micro_time.cc or the mbed one on +// tensorflow/lite/micro/mbed/micro_time.cc. + +#include "tensorflow/lite/micro/micro_time.h" + +// #include "peripherals/utility.h" + +#if defined(TF_LITE_USE_CTIME) +#include +#endif + +namespace tflite { + +#if !defined(TF_LITE_USE_CTIME) + +// Reference implementation of the ticks_per_second() function that's required +// for a platform to support Tensorflow Lite for Microcontrollers profiling. +// This returns 0 by default because timing is an optional feature that builds +// without errors on platforms that do not need it. +uint32_t ticks_per_second() { return 1000000; } + +// Reference implementation of the GetCurrentTimeTicks() function that's +// required for a platform to support Tensorflow Lite for Microcontrollers +// profiling. This returns 0 by default because timing is an optional feature +// that builds without errors on platforms that do not need it. +// uint32_t GetCurrentTimeTicks() { return peripherals::MicrosecondsCounter(); } + +uint32_t GetCurrentTimeTicks() { return 0; } + +#else // defined(TF_LITE_USE_CTIME) + +// For platforms that support ctime, we implment the micro_time interface in +// this central location. +uint32_t ticks_per_second() { return CLOCKS_PER_SEC; } + +uint32_t GetCurrentTimeTicks() { return clock(); } +#endif + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_time.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_time.h new file mode 100644 index 000000000..7a8ab455c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_time.h @@ -0,0 +1,36 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_MICRO_TIME_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_TIME_H_ + +#include + +namespace tflite { + +// These functions should be implemented by each target platform, and provide an +// accurate tick count along with how many ticks there are per second. +uint32_t ticks_per_second(); + +// Return time in ticks. The meaning of a tick varies per platform. +uint32_t GetCurrentTimeTicks(); + +inline uint32_t TicksToMs(int32_t ticks) { + return static_cast(1000.0f * static_cast(ticks) / + static_cast(ticks_per_second())); +} + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_TIME_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_utils.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_utils.cpp new file mode 100644 index 000000000..b84407db6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_utils.cpp @@ -0,0 +1,91 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/micro_utils.h" + +#include +#include +#include + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/op_macros.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +int ElementCount(const TfLiteIntArray& dims) { + int result = 1; + for (int i = 0; i < dims.size; ++i) { + result *= dims.data[i]; + } + return result; +} + +size_t EvalTensorBytes(const TfLiteEvalTensor* tensor) { + size_t bytes_per_element; + TFLITE_DCHECK(kTfLiteOk == + TfLiteTypeSizeOf(tensor->type, &bytes_per_element)); + return ElementCount(*tensor->dims) * bytes_per_element; +} + +void SignedSymmetricPerChannelQuantize(const float* values, + TfLiteIntArray* dims, + int quantized_dimension, + int8_t* quantized_values, + float* scaling_factors) { + int input_size = ElementCount(*dims); + int channel_count = dims->data[quantized_dimension]; + int per_channel_size = input_size / channel_count; + + int stride; + int channel_stride; + if (quantized_dimension == 0) { + stride = 1; + channel_stride = per_channel_size; + } else if (quantized_dimension == 3) { + stride = channel_count; + channel_stride = 1; + } else { + MicroPrintf("quantized dimension must be 0 or 3"); + TFLITE_ABORT; + } + + // Calculate scales for each channel. + for (int channel = 0; channel < channel_count; channel++) { + float min = 0; + float max = 0; + + for (int i = 0; i < per_channel_size; i++) { + int idx = channel * channel_stride + i * stride; + min = fminf(min, values[idx]); + max = fmaxf(max, values[idx]); + } + scaling_factors[channel] = + fmaxf(fabs(min), fabs(max)) / std::numeric_limits::max(); + for (int i = 0; i < per_channel_size; i++) { + int idx = channel * channel_stride + i * stride; + const int32_t quantized_value = + static_cast(roundf(values[idx] / scaling_factors[channel])); + // Clamp: just in case some odd numeric offset. + quantized_values[idx] = + fminf(std::numeric_limits::max(), + fmaxf(std::numeric_limits::min() + 1, quantized_value)); + } + } +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_utils.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_utils.h new file mode 100644 index 000000000..84d5c4373 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/micro_utils.h @@ -0,0 +1,143 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MICRO_UTILS_H_ +#define TENSORFLOW_LITE_MICRO_MICRO_UTILS_H_ + +#include +#include +#include +#include + +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +// Returns number of elements in the shape array. + +int ElementCount(const TfLiteIntArray& dims); + +size_t EvalTensorBytes(const TfLiteEvalTensor* tensor); + +// C++11 does not support constexpr max; hence, use ternary conditional to +// create our own constexpr Max function. +constexpr int Max(int a, int b) { return a >= b ? a : b; } + +// Converts a float value into a quantized value. Note that large values (close +// to max int and min int) may see significant error due to a lack of floating +// point granularity for large values. +template +T FloatToQuantizedType(const float value, const float scale, int zero_point) { + int32_t result = round(value / scale) + zero_point; + result = + std::max(static_cast(std::numeric_limits::min()), result); + result = + std::min(static_cast(std::numeric_limits::max()), result); + return result; +} + +template +T FloatToSymmetricQuantizedType(const float value, const float scale) { + // 64-bit values are required since 8x16 conv accumulates to int64, meaning + // an int64 bias is required. + std::int64_t result = round(value / scale); + result = std::max( + static_cast(std::numeric_limits::min() + 1), result); + result = std::min(static_cast(std::numeric_limits::max()), + result); + return result; +} + +// Helper methods to quantize arrays of floats to the desired format. +// +// There are several key flavors of quantization in TfLite: +// asymmetric symmetric per channel +// int8_t | X | X | X | +// uint8_t | X | X | | +// int16_t | X | | | +// int32_t | | X | X | +// +// The per-op quantization spec can be found here: +// https://www.tensorflow.org/lite/performance/quantization_spec +template +void Quantize(const float* input, T* output, int num_elements, float scale, + int zero_point) { + for (int i = 0; i < num_elements; i++) { + output[i] = FloatToQuantizedType(input[i], scale, zero_point); + } +} + +template +void SymmetricQuantize(const float* input, T* output, int num_elements, + float scale) { + for (int i = 0; i < num_elements; i++) { + output[i] = FloatToSymmetricQuantizedType(input[i], scale); + } +} + +template +void SymmetricPerChannelQuantize(const float* input, T* output, + int num_elements, int num_channels, + float* scales) { + int elements_per_channel = num_elements / num_channels; + for (int i = 0; i < num_channels; i++) { + for (int j = 0; j < elements_per_channel; j++) { + output[i * elements_per_channel + j] = FloatToSymmetricQuantizedType( + input[i * elements_per_channel + j], scales[i]); + } + } +} + +void SignedSymmetricPerChannelQuantize(const float* values, + TfLiteIntArray* dims, + int quantized_dimension, + int8_t* quantized_values, + float* scaling_factor); + +// Quantizes inputs based on the values provided, choosing the smallest range +// which includes all input values. +template +void SymmetricQuantizeCalculateScales(const float* values, TfLiteIntArray* dims, + T* output, float* scale) { + int input_size = ElementCount(*dims); + + float min = 0; + float max = 0; + for (int i = 0; i < input_size; i++) { + min = fminf(min, values[i]); + max = fmaxf(max, values[i]); + } + *scale = fmaxf(std::abs(min), std::abs(max)) / std::numeric_limits::max(); + for (int i = 0; i < input_size; i++) { + const int32_t quantized_value = + static_cast(roundf(values[i] / *scale)); + // Clamp: just in case some odd numeric offset. + quantized_value = fminf(std::numeric_limits::max(), quantized_value); + quantized_value = fmaxf(std::numeric_limits::min() + 1, quantized_value); + output[i] = quantized_value; + } +} + +template +void Dequantize(const T* values, const int size, const float scale, + int zero_point, float* dequantized_values) { + for (int i = 0; i < size; ++i) { + dequantized_values[i] = (values[i] - zero_point) * scale; + } +} + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MICRO_UTILS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/mock_micro_graph.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/mock_micro_graph.cpp new file mode 100644 index 000000000..438a40653 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/mock_micro_graph.cpp @@ -0,0 +1,66 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/mock_micro_graph.h" + +#include "tensorflow/lite/micro/test_helpers.h" + +namespace tflite { + +MockMicroGraph::MockMicroGraph(SingleArenaBufferAllocator* allocator) + : MicroGraph(nullptr, nullptr, nullptr, nullptr), + allocator_(allocator), + init_count_(0), + prepare_count_(0), + free_count_(0) { + memset(invoke_counts_, 0, sizeof(invoke_counts_)); + mock_tensor_ = + reinterpret_cast(allocator_->AllocatePersistentBuffer( + sizeof(TfLiteEvalTensor), alignof(TfLiteEvalTensor))); + int* dims_array = reinterpret_cast( + allocator_->AllocatePersistentBuffer(3 * sizeof(int), alignof(int))); + float* data_array = reinterpret_cast( + allocator_->AllocatePersistentBuffer(2 * sizeof(float), alignof(float))); + int dims[] = {2, 1, 2}; + memcpy(dims_array, dims, 3 * sizeof(int)); + mock_tensor_->dims = testing::IntArrayFromInts(dims_array); + mock_tensor_->data.f = data_array; + mock_tensor_->type = kTfLiteFloat32; +} + +TfLiteStatus MockMicroGraph::InvokeSubgraph(int subgraph_idx) { + invoke_counts_[subgraph_idx]++; + return kTfLiteOk; +} + +TfLiteStatus MockMicroGraph::ResetVariableTensors() { return kTfLiteOk; } + +size_t MockMicroGraph::NumSubgraphInputs(int subgraph_idx) { return 1; } + +TfLiteEvalTensor* MockMicroGraph::GetSubgraphInput(int subgraph_idx, + int tensor_idx) { + return mock_tensor_; +} + +size_t MockMicroGraph::NumSubgraphOutputs(int subgraph_idx) { return 1; } + +TfLiteEvalTensor* MockMicroGraph::GetSubgraphOutput(int subgraph_idx, + int tensor_idx) { + return mock_tensor_; +} + +int MockMicroGraph::NumSubgraphs() { return kMaxSubgraphs; } + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/mock_micro_graph.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/mock_micro_graph.h new file mode 100644 index 000000000..3ae7d7cf0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/mock_micro_graph.h @@ -0,0 +1,60 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_MOCK_MICRO_GRAPH_H_ +#define TENSORFLOW_LITE_MICRO_MOCK_MICRO_GRAPH_H_ + +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/micro/micro_allocator.h" +#include "tensorflow/lite/micro/micro_graph.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +// MockMicroGraph stubs out all MicroGraph methods used during invoke. A count +// of the number of calls to invoke for each subgraph is maintained for +// validation of control flow operators. +class MockMicroGraph : public MicroGraph { + public: + explicit MockMicroGraph(SingleArenaBufferAllocator* allocator); + TfLiteStatus InvokeSubgraph(int subgraph_idx) override; + TfLiteStatus ResetVariableTensors() override; + size_t NumSubgraphInputs(int subgraph_idx) override; + TfLiteEvalTensor* GetSubgraphInput(int subgraph_idx, int tensor_idx) override; + size_t NumSubgraphOutputs(int subgraph_idx) override; + TfLiteEvalTensor* GetSubgraphOutput(int subgraph_idx, + int tensor_idx) override; + int NumSubgraphs() override; + int get_init_count() const { return init_count_; } + int get_prepare_count() const { return prepare_count_; } + int get_free_count() const { return free_count_; } + int get_invoke_count(int subgraph_idx) const { + return invoke_counts_[subgraph_idx]; + } + + private: + static constexpr int kMaxSubgraphs = 10; + SingleArenaBufferAllocator* allocator_; + TfLiteEvalTensor* mock_tensor_; + int init_count_; + int prepare_count_; + int free_count_; + int invoke_counts_[kMaxSubgraphs]; + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_MOCK_MICRO_GRAPH_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_allocator.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_allocator.cpp new file mode 100644 index 000000000..289ed1815 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_allocator.cpp @@ -0,0 +1,256 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/recording_micro_allocator.h" + +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/memory_planner/greedy_memory_planner.h" +#include "tensorflow/lite/micro/micro_allocator.h" +#include "tensorflow/lite/micro/micro_log.h" + +namespace tflite { + +size_t RecordingMicroAllocator::GetDefaultTailUsage() { + // RecordingMicroAllocator inherits from MicroAllocator and its tail usage is + // similar with MicroAllocator with SingleArenaBufferAllocator and + // MicroAllocator being replaced. + // TODO(b/208703041): a template version of AlignSizeUp to make expression + // shorter. + return MicroAllocator::GetDefaultTailUsage( + /*is_memory_planner_given=*/false) + + AlignSizeUp(sizeof(RecordingSingleArenaBufferAllocator), + alignof(RecordingSingleArenaBufferAllocator)) - + AlignSizeUp(sizeof(SingleArenaBufferAllocator), + alignof(SingleArenaBufferAllocator)) + + AlignSizeUp(sizeof(RecordingMicroAllocator), + alignof(RecordingMicroAllocator)) - + AlignSizeUp(sizeof(MicroAllocator), alignof(MicroAllocator)); +} + +RecordingMicroAllocator::RecordingMicroAllocator( + RecordingSingleArenaBufferAllocator* recording_memory_allocator, + MicroMemoryPlanner* memory_planner) + : MicroAllocator(recording_memory_allocator, memory_planner), + recording_memory_allocator_(recording_memory_allocator) {} + +RecordingMicroAllocator* RecordingMicroAllocator::Create(uint8_t* tensor_arena, + size_t arena_size) { + RecordingSingleArenaBufferAllocator* simple_memory_allocator = + RecordingSingleArenaBufferAllocator::Create(tensor_arena, arena_size); + TFLITE_DCHECK(simple_memory_allocator != nullptr); + + uint8_t* memory_planner_buffer = + simple_memory_allocator->AllocatePersistentBuffer( + sizeof(GreedyMemoryPlanner), alignof(GreedyMemoryPlanner)); + GreedyMemoryPlanner* memory_planner = + new (memory_planner_buffer) GreedyMemoryPlanner(); + + uint8_t* allocator_buffer = simple_memory_allocator->AllocatePersistentBuffer( + sizeof(RecordingMicroAllocator), alignof(RecordingMicroAllocator)); + RecordingMicroAllocator* allocator = new (allocator_buffer) + RecordingMicroAllocator(simple_memory_allocator, memory_planner); + return allocator; +} + +RecordedAllocation RecordingMicroAllocator::GetRecordedAllocation( + RecordedAllocationType allocation_type) const { + switch (allocation_type) { + case RecordedAllocationType::kTfLiteEvalTensorData: + return recorded_tflite_eval_tensor_data_; + case RecordedAllocationType::kPersistentTfLiteTensorData: + return recorded_persistent_tflite_tensor_data_; + case RecordedAllocationType::kPersistentTfLiteTensorQuantizationData: + return recorded_persistent_tflite_tensor_quantization_data_; + case RecordedAllocationType::kPersistentBufferData: + return recorded_persistent_buffer_data_; + case RecordedAllocationType::kTfLiteTensorVariableBufferData: + return recorded_tflite_tensor_variable_buffer_data_; + case RecordedAllocationType::kNodeAndRegistrationArray: + return recorded_node_and_registration_array_data_; + case RecordedAllocationType::kOpData: + return recorded_op_data_; + } + MicroPrintf("Invalid allocation type supplied: %d", allocation_type); + return RecordedAllocation(); +} + +const RecordingSingleArenaBufferAllocator* +RecordingMicroAllocator::GetSimpleMemoryAllocator() const { + return recording_memory_allocator_; +} + +void RecordingMicroAllocator::PrintAllocations() const { + MicroPrintf("[RecordingMicroAllocator] Arena allocation total %d bytes", + recording_memory_allocator_->GetUsedBytes()); + MicroPrintf("[RecordingMicroAllocator] Arena allocation head %d bytes", + recording_memory_allocator_->GetNonPersistentUsedBytes()); + MicroPrintf("[RecordingMicroAllocator] Arena allocation tail %d bytes", + recording_memory_allocator_->GetPersistentUsedBytes()); + PrintRecordedAllocation(RecordedAllocationType::kTfLiteEvalTensorData, + "TfLiteEvalTensor data", "allocations"); + PrintRecordedAllocation(RecordedAllocationType::kPersistentTfLiteTensorData, + "Persistent TfLiteTensor data", "tensors"); + PrintRecordedAllocation( + RecordedAllocationType::kPersistentTfLiteTensorQuantizationData, + "Persistent TfLiteTensor quantization data", "allocations"); + PrintRecordedAllocation(RecordedAllocationType::kPersistentBufferData, + "Persistent buffer data", "allocations"); + PrintRecordedAllocation( + RecordedAllocationType::kTfLiteTensorVariableBufferData, + "TfLiteTensor variable buffer data", "allocations"); + PrintRecordedAllocation(RecordedAllocationType::kNodeAndRegistrationArray, + "NodeAndRegistration struct", + "NodeAndRegistration structs"); + PrintRecordedAllocation(RecordedAllocationType::kOpData, + "Operator runtime data", "OpData structs"); +} + +void* RecordingMicroAllocator::AllocatePersistentBuffer(size_t bytes) { + RecordedAllocation allocations = SnapshotAllocationUsage(); + void* buffer = MicroAllocator::AllocatePersistentBuffer(bytes); + RecordAllocationUsage(allocations, recorded_persistent_buffer_data_); + + return buffer; +} + +void RecordingMicroAllocator::PrintRecordedAllocation( + RecordedAllocationType allocation_type, const char* allocation_name, + const char* allocation_description) const { +#ifndef TF_LITE_STRIP_ERROR_STRINGS + RecordedAllocation allocation = GetRecordedAllocation(allocation_type); + if (allocation.used_bytes > 0 || allocation.requested_bytes > 0) { + MicroPrintf( + "[RecordingMicroAllocator] '%s' used %d bytes with alignment overhead " + "(requested %d bytes for %d %s)", + allocation_name, allocation.used_bytes, allocation.requested_bytes, + allocation.count, allocation_description); + } +#endif +} + +TfLiteStatus RecordingMicroAllocator::AllocateNodeAndRegistrations( + const Model* model, SubgraphAllocations* subgraph_allocations) { + RecordedAllocation allocations = SnapshotAllocationUsage(); + + TfLiteStatus status = + MicroAllocator::AllocateNodeAndRegistrations(model, subgraph_allocations); + + RecordAllocationUsage(allocations, + recorded_node_and_registration_array_data_); + + for (size_t subgraph_idx = 0; subgraph_idx < model->subgraphs()->size(); + subgraph_idx++) { + // The allocation count in SingleArenaBufferAllocator will only be 1. To + // provide better logging, decrement by 1 and add in the actual number of + // operators used in the graph: The allocation for this recording will + // always be 1. This is because the parent class mallocs one large + // allocation for the number of nodes in the graph (e.g. + // sizeof(NodeAndRegistration) * num_nodes). To prevent extra overhead and + // potential for fragmentation, manually adjust the accounting by + // decrementing by 1 and adding the actual number of nodes used in the + // graph: + if (model->subgraphs()->Get(subgraph_idx)->operators()) { + recorded_node_and_registration_array_data_.count += + model->subgraphs()->Get(subgraph_idx)->operators()->size() - 1; + } else { + recorded_node_and_registration_array_data_.count -= 1; + } + } + return status; +} + +TfLiteStatus RecordingMicroAllocator::AllocateTfLiteEvalTensors( + const Model* model, SubgraphAllocations* subgraph_allocations) { + RecordedAllocation allocations = SnapshotAllocationUsage(); + + TfLiteStatus status = + MicroAllocator::AllocateTfLiteEvalTensors(model, subgraph_allocations); + + RecordAllocationUsage(allocations, recorded_tflite_eval_tensor_data_); + + for (size_t subgraph_idx = 0; subgraph_idx < model->subgraphs()->size(); + subgraph_idx++) { + // The allocation for this recording will always be 1. This is because the + // parent class mallocs one large allocation for the number of tensors in + // the graph (e.g. sizeof(TfLiteEvalTensor) * num_tensors). To prevent extra + // overhead and potential for fragmentation, manually adjust the accounting + // by decrementing by 1 and adding the actual number of tensors used in the + // graph: + recorded_tflite_eval_tensor_data_.count += + model->subgraphs()->Get(subgraph_idx)->tensors()->size() - 1; + } + return status; +} + +TfLiteStatus RecordingMicroAllocator::AllocateVariables( + const SubGraph* subgraph, TfLiteEvalTensor* eval_tensors) { + RecordedAllocation allocations = SnapshotAllocationUsage(); + + TfLiteStatus status = + MicroAllocator::AllocateVariables(subgraph, eval_tensors); + + RecordAllocationUsage(allocations, + recorded_tflite_tensor_variable_buffer_data_); + return status; +} + +TfLiteTensor* +RecordingMicroAllocator::AllocatePersistentTfLiteTensorInternal() { + RecordedAllocation allocations = SnapshotAllocationUsage(); + + TfLiteTensor* result = + MicroAllocator::AllocatePersistentTfLiteTensorInternal(); + + RecordAllocationUsage(allocations, recorded_persistent_tflite_tensor_data_); + return result; +} + +TfLiteStatus RecordingMicroAllocator::PopulateTfLiteTensorFromFlatbuffer( + const Model* model, TfLiteTensor* tensor, int tensor_index, + int subgraph_index, bool allocate_temp) { + RecordedAllocation allocations = SnapshotAllocationUsage(); + + TfLiteStatus status = MicroAllocator::PopulateTfLiteTensorFromFlatbuffer( + model, tensor, tensor_index, subgraph_index, allocate_temp); + + RecordAllocationUsage(allocations, + recorded_persistent_tflite_tensor_quantization_data_); + return status; +} + +RecordedAllocation RecordingMicroAllocator::SnapshotAllocationUsage() const { + return {/*requested_bytes=*/recording_memory_allocator_->GetRequestedBytes(), + /*used_bytes=*/recording_memory_allocator_->GetUsedBytes(), + /*count=*/recording_memory_allocator_->GetAllocatedCount()}; +} + +void RecordingMicroAllocator::RecordAllocationUsage( + const RecordedAllocation& snapshotted_allocation, + RecordedAllocation& recorded_allocation) { + recorded_allocation.requested_bytes += + recording_memory_allocator_->GetRequestedBytes() - + snapshotted_allocation.requested_bytes; + recorded_allocation.used_bytes += + recording_memory_allocator_->GetUsedBytes() - + snapshotted_allocation.used_bytes; + recorded_allocation.count += + recording_memory_allocator_->GetAllocatedCount() - + snapshotted_allocation.count; +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_allocator.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_allocator.h new file mode 100644 index 000000000..1b1e0ead1 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_allocator.h @@ -0,0 +1,132 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_RECORDING_MICRO_ALLOCATOR_H_ +#define TENSORFLOW_LITE_MICRO_RECORDING_MICRO_ALLOCATOR_H_ + +#include "tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.h" +#include "tensorflow/lite/micro/compatibility.h" +#include "tensorflow/lite/micro/micro_allocator.h" + +namespace tflite { + +// List of buckets currently recorded by this class. Each type keeps a list of +// allocated information during model initialization. +// TODO(b/169834511): Add tracking for scratch buffer allocations. +enum class RecordedAllocationType { + kTfLiteEvalTensorData, + kPersistentTfLiteTensorData, + kPersistentTfLiteTensorQuantizationData, + kPersistentBufferData, + kTfLiteTensorVariableBufferData, + kNodeAndRegistrationArray, + kOpData, +}; + +// Container for holding information about allocation recordings by a given +// type. Each recording contains the number of bytes requested, the actual bytes +// allocated (can defer from requested by alignment), and the number of items +// allocated. +struct RecordedAllocation { + size_t requested_bytes; + size_t used_bytes; + size_t count; +}; + +// Utility subclass of MicroAllocator that records all allocations +// inside the arena. A summary of allocations can be logged through the +// ErrorReporter by invoking LogAllocations(). This special allocator requires +// an instance of RecordingSingleArenaBufferAllocator to capture allocations in +// the head and tail. Arena allocation recording can be retrieved by type +// through the GetRecordedAllocation() function. This class should only be used +// for auditing memory usage or integration testing. +class RecordingMicroAllocator : public MicroAllocator { + public: + // TODO(b/246776144): Will be removed with http://b/246776144 + static RecordingMicroAllocator* Create(uint8_t* tensor_arena, + size_t arena_size, + ErrorReporter* error_reporter) { + (void)error_reporter; + return RecordingMicroAllocator::Create(tensor_arena, arena_size); + } + + static RecordingMicroAllocator* Create(uint8_t* tensor_arena, + size_t arena_size); + + // Returns the fixed amount of memory overhead of RecordingMicroAllocator. + static size_t GetDefaultTailUsage(); + + // Returns the recorded allocations information for a given allocation type. + RecordedAllocation GetRecordedAllocation( + RecordedAllocationType allocation_type) const; + + const RecordingSingleArenaBufferAllocator* GetSimpleMemoryAllocator() const; + + // Logs out through the ErrorReporter all allocation recordings by type + // defined in RecordedAllocationType. + void PrintAllocations() const; + + void* AllocatePersistentBuffer(size_t bytes) override; + + protected: + TfLiteStatus AllocateNodeAndRegistrations( + const Model* model, SubgraphAllocations* subgraph_allocations) override; + TfLiteStatus AllocateTfLiteEvalTensors( + const Model* model, SubgraphAllocations* subgraph_allocations) override; + TfLiteStatus AllocateVariables(const SubGraph* subgraph, + TfLiteEvalTensor* eval_tensors) override; + // TODO(b/162311891): Once all kernels have been updated to the new API drop + // this method. It is only used to record TfLiteTensor persistent allocations. + TfLiteTensor* AllocatePersistentTfLiteTensorInternal() override; + + // TODO(b/162311891): Once all kernels have been updated to the new API drop + // this function since all allocations for quantized data will take place in + // the temp section. + TfLiteStatus PopulateTfLiteTensorFromFlatbuffer(const Model* model, + TfLiteTensor* tensor, + int tensor_index, + int subgraph_index, + bool allocate_temp) override; + + private: + RecordingMicroAllocator(RecordingSingleArenaBufferAllocator* memory_allocator, + MicroMemoryPlanner* memory_planner); + + void PrintRecordedAllocation(RecordedAllocationType allocation_type, + const char* allocation_name, + const char* allocation_description) const; + + RecordedAllocation SnapshotAllocationUsage() const; + void RecordAllocationUsage(const RecordedAllocation& snapshotted_allocation, + RecordedAllocation& recorded_allocation); + + const RecordingSingleArenaBufferAllocator* recording_memory_allocator_; + + RecordedAllocation recorded_tflite_eval_tensor_data_ = {}; + RecordedAllocation recorded_persistent_tflite_tensor_data_ = {}; + RecordedAllocation recorded_persistent_tflite_tensor_quantization_data_ = {}; + RecordedAllocation recorded_persistent_buffer_data_ = {}; + RecordedAllocation recorded_tflite_tensor_variable_buffer_data_ = {}; + RecordedAllocation recorded_node_and_registration_array_data_ = {}; + + // TODO(b/187993291): Re-enable OpData allocating tracking. + RecordedAllocation recorded_op_data_ = {}; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_RECORDING_MICRO_ALLOCATOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_interpreter.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_interpreter.h new file mode 100644 index 000000000..70b7260be --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/recording_micro_interpreter.h @@ -0,0 +1,94 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_RECORDING_MICRO_INTERPRETER_H_ +#define TENSORFLOW_LITE_MICRO_RECORDING_MICRO_INTERPRETER_H_ + +#include "tensorflow/lite/micro/micro_interpreter.h" +#include "tensorflow/lite/micro/micro_profiler_interface.h" +#include "tensorflow/lite/micro/recording_micro_allocator.h" + +namespace tflite { + +// Utility subclass that enables internal recordings of the MicroInterpreter. +// This class should be used to audit and analyze memory arena usage for a given +// model and interpreter. +// +// After construction and the first Invoke() or AllocateTensors() call - the +// memory usage is recorded and available through the GetMicroAllocator() +// function. See RecordingMicroAlloctor for more details on what is currently +// recorded from arena allocations. +// +// It is recommended for users to increase the tensor arena size by at least 1kb +// to ensure enough additional memory is available for internal recordings. +class RecordingMicroInterpreter : public MicroInterpreter { + public: + RecordingMicroInterpreter(const Model* model, + const MicroOpResolver& op_resolver, + uint8_t* tensor_arena, size_t tensor_arena_size, + MicroResourceVariables* resource_variable = nullptr, + MicroProfilerInterface* profiler = nullptr) + : MicroInterpreter( + model, op_resolver, + RecordingMicroAllocator::Create(tensor_arena, tensor_arena_size), + resource_variable, profiler), + recording_micro_allocator_( + static_cast(allocator())) {} + + RecordingMicroInterpreter(const Model* model, + const MicroOpResolver& op_resolver, + RecordingMicroAllocator* allocator, + MicroResourceVariables* resource_variable = nullptr, + MicroProfilerInterface* profiler = nullptr) + : MicroInterpreter(model, op_resolver, allocator, resource_variable, + profiler), + recording_micro_allocator_(*allocator) {} + + // TODO(b/246776144): Will be removed with http://b/246776144 + RecordingMicroInterpreter(const Model* model, + const MicroOpResolver& op_resolver, + uint8_t* tensor_arena, size_t tensor_arena_size, + ErrorReporter* error_reporter, + MicroResourceVariables* resource_variable = nullptr, + MicroProfilerInterface* profiler = nullptr) + : MicroInterpreter(model, op_resolver, + RecordingMicroAllocator::Create( + tensor_arena, tensor_arena_size, error_reporter), + error_reporter, resource_variable, profiler), + recording_micro_allocator_( + static_cast(allocator())) {} + + // TODO(b/246776144): Will be removed with http://b/246776144 + RecordingMicroInterpreter(const Model* model, + const MicroOpResolver& op_resolver, + RecordingMicroAllocator* allocator, + ErrorReporter* error_reporter, + MicroResourceVariables* resource_variable = nullptr, + MicroProfilerInterface* profiler = nullptr) + : MicroInterpreter(model, op_resolver, allocator, error_reporter, + resource_variable, profiler), + recording_micro_allocator_(*allocator) {} + + const RecordingMicroAllocator& GetMicroAllocator() const { + return recording_micro_allocator_; + } + + private: + const RecordingMicroAllocator& recording_micro_allocator_; +}; + +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_RECORDING_MICRO_INTERPRETER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/system_setup.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/system_setup.cpp new file mode 100644 index 000000000..dfa4e6336 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/system_setup.cpp @@ -0,0 +1,138 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/system_setup.h" + +#include + +#include "tensorflow/lite/micro/debug_log.h" + +#if defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) +#define ARDUINO_EXCLUDE_CODE +#endif // defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE) + +#ifndef ARDUINO_EXCLUDE_CODE + +#include "Arduino.h" + +// The Arduino DUE uses a different object for the default serial port shown in +// the monitor than most other models, so make sure we pick the right one. See +// https://github.com/arduino/Arduino/issues/3088#issuecomment-406655244 +#if defined(__SAM3X8E__) +#define DEBUG_SERIAL_OBJECT (SerialUSB) +#else +#define DEBUG_SERIAL_OBJECT (Serial) +#endif + +extern "C" void DebugLog(const char* s) { DEBUG_SERIAL_OBJECT.print(s); } + +namespace tflite { + +constexpr ulong kSerialMaxInitWait = 4000; // milliseconds + +void InitializeTarget() { + DEBUG_SERIAL_OBJECT.begin(9600); + ulong start_time = millis(); + while (!DEBUG_SERIAL_OBJECT) { + // allow for Arduino IDE Serial Monitor synchronization + if (millis() - start_time > kSerialMaxInitWait) { + break; + } + } +} + +} // namespace tflite + +namespace test_over_serial { + +// Change baud rate on default serial port +void SerialChangeBaudRate(const int baud) { + DEBUG_SERIAL_OBJECT.begin(baud); + ulong start_time = millis(); + while (!DEBUG_SERIAL_OBJECT) { + // allow for Arduino IDE Serial Monitor synchronization + if (millis() - start_time > tflite::kSerialMaxInitWait) { + break; + } + } +} + +class _RingBuffer : public RingBufferN { + public: + bool need_reset = false; +}; + +static _RingBuffer _ring_buffer; + +// SerialReadLine +// Read a set of ASCII characters from the default +// serial port. Data is read up to the first newline ('\\n') character. +// This function uses an internal buffer which is automatically reset. +// The buffer will not contain the newline character. +// The buffer will be zero ('\\0') terminated. +// The value is in milliseconds. Any negative value means that +// the wait for data will be forever. +// Returns std::pair. +// The first pair element is the number of characters in buffer not including +// the newline character or zero terminator. +// Returns {0, NULL} if the timeout occurs. +std::pair SerialReadLine(int timeout) { + if (_ring_buffer.need_reset) { + _ring_buffer.need_reset = false; + _ring_buffer.clear(); + } + + ulong start_time = millis(); + + while (true) { + int value = DEBUG_SERIAL_OBJECT.read(); + if (value >= 0) { + if (value == '\n') { + // read a newline character + _ring_buffer.store_char('\0'); + _ring_buffer.need_reset = true; + break; + } else { + // read other character + _ring_buffer.store_char(value); + if (_ring_buffer.availableForStore() == 1) { + // buffer is full + _ring_buffer.store_char('\0'); + _ring_buffer.need_reset = true; + break; + } + } + } + if (timeout < 0) { + // wait forever + continue; + } else if (millis() - start_time >= static_cast(timeout)) { + // timeout + return std::make_pair(0UL, reinterpret_cast(NULL)); + } + } + + return std::make_pair(static_cast(_ring_buffer.available() - 1), + reinterpret_cast(_ring_buffer._aucBuffer)); +} + +// SerialWrite +// Write the ASCII characters in to the default serial port. +// The must be zero terminated. +void SerialWrite(const char* buffer) { DEBUG_SERIAL_OBJECT.print(buffer); } + +} // namespace test_over_serial + +#endif // ARDUINO_EXCLUDE_CODE diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/system_setup.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/system_setup.h new file mode 100644 index 000000000..ce49ddbe5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/system_setup.h @@ -0,0 +1,59 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_MICRO_SYSTEM_SETUP_H_ +#define TENSORFLOW_LITE_MICRO_SYSTEM_SETUP_H_ + +#include +#include + +namespace tflite { + +// This should called during initialization of TFLM binaries and tests. It can +// be specialized if there is a need for custom target-specific intialization. +// For more information, see tensorflow/lite/micro/system_setup.cc. +void InitializeTarget(); + +} // namespace tflite + +namespace test_over_serial { + +// computed for Arduino Nano 33 BLE Sense +constexpr size_t kSerialMaxInputLength = (64); + +// Change baud rate on default serial port +void SerialChangeBaudRate(const int baud); + +// SerialReadLine +// Read a set of ASCII characters from the default +// serial port. Data is read up to the first newline ('\\n') character. +// This function uses an internal buffer which is automatically reset. +// The buffer will not contain the newline character. +// The buffer will be zero ('\\0') terminated. +// The value is in milliseconds. Any negative value means that +// the wait for data will be forever. +// Returns std::pair. +// The first pair element is the number of characters in buffer not including +// the newline character or zero terminator. +// Returns {0, NULL} if the timeout occurs. +std::pair SerialReadLine(int timeout); + +// SerialWrite +// Write the ASCII characters in to the default serial port. +// The must be zero terminated. +void SerialWrite(const char* buffer); + +} // namespace test_over_serial + +#endif // TENSORFLOW_LITE_MICRO_SYSTEM_SETUP_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helper_custom_ops.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helper_custom_ops.cpp new file mode 100644 index 000000000..b87cb5ae8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helper_custom_ops.cpp @@ -0,0 +1,112 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/test_helper_custom_ops.h" + +#include +#include +#include +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/all_ops_resolver.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/micro_utils.h" +#include "tensorflow/lite/schema/schema_generated.h" + +// TODO(b/170464050): Use TFLM test only version of schema_utils. + +namespace tflite { +namespace testing { + +const TfLiteRegistration* PackerOp::getRegistration() { + return GetMutableRegistration(); +} + +TfLiteRegistration* PackerOp::GetMutableRegistration() { + static TfLiteRegistration r; + r.init = Init; + r.prepare = Prepare; + r.invoke = Invoke; + r.free = Free; + return &r; +} + +void* PackerOp::Init(TfLiteContext* context, const char* buffer, + size_t length) { + freed_ = false; + // Do nothing. + return nullptr; +} + +void PackerOp::Free(TfLiteContext* context, void* buffer) { freed_ = true; } + +TfLiteStatus PackerOp::Prepare(TfLiteContext* context, TfLiteNode* node) { + return kTfLiteOk; +} + +TfLiteStatus PackerOp::Invoke(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, 0); + TF_LITE_ENSURE(context, input1 != nullptr); + const int32_t* input1_data = input1->data.i32; + TF_LITE_ENSURE_EQ(context, input1->dims->size, 1); + const int32_t input1_len = input1->dims->data[0]; + + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, 1); + TF_LITE_ENSURE(context, input2 != nullptr); + const int32_t* input2_data = input2->data.i32; + TF_LITE_ENSURE_EQ(context, input2->dims->size, 1); + const int32_t input2_len = input2->dims->data[0]; + + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TF_LITE_ENSURE(context, output != nullptr); + int32_t* output_data = output->data.i32; + int32_t output_len = output->dims->data[0]; + + // Fill output with input: first with the first tensor, then with the second + // tensor up to the size of the output tensor. + int cnt = 0; + int i; + for (i = 0; i < input1_len && cnt < output_len; i++, cnt++) { + output_data[cnt] = input1_data[i]; + } + if (cnt >= output_len) { + return kTfLiteOk; + } + + for (i = 0; i < input2_len && cnt < output_len; i++, cnt++) { + output_data[cnt] = input2_data[i]; + } + if (cnt >= output_len) { + return kTfLiteOk; + } + + for (; cnt < output_len; cnt++) { + output_data[cnt] = 0; + } + return kTfLiteOk; +} + +bool PackerOp::freed_ = false; + +} // namespace testing +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helper_custom_ops.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helper_custom_ops.h new file mode 100644 index 000000000..9c950fc93 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helper_custom_ops.h @@ -0,0 +1,50 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_TEST_HELPER_CUSTOM_OPS_H_ +#define TENSORFLOW_LITE_MICRO_TEST_HELPER_CUSTOM_OPS_H_ + +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/micro/all_ops_resolver.h" +#include "tensorflow/lite/micro/micro_utils.h" +#include "tensorflow/lite/portable_type_to_tflitetype.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +namespace testing { + +class PackerOp { + public: + static const TfLiteRegistration* getRegistration(); + static TfLiteRegistration* GetMutableRegistration(); + static void* Init(TfLiteContext* context, const char* buffer, size_t length); + static void Free(TfLiteContext* context, void* buffer); + static TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node); + static TfLiteStatus Invoke(TfLiteContext* context, TfLiteNode* node); + + private: + static bool freed_; +}; + +} // namespace testing +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_TEST_HELPER_CUSTOM_OPS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helpers.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helpers.cpp new file mode 100644 index 000000000..003b64aab --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helpers.cpp @@ -0,0 +1,1913 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/micro/test_helpers.h" + +#include +#include +#include +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/micro/all_ops_resolver.h" +#include "tensorflow/lite/micro/kernels/kernel_util.h" +#include "tensorflow/lite/micro/memory_helpers.h" +#include "tensorflow/lite/micro/micro_arena_constants.h" +#include "tensorflow/lite/micro/micro_utils.h" +#include "tensorflow/lite/micro/test_helper_custom_ops.h" +#include "tensorflow/lite/schema/schema_generated.h" + +// TODO(b/170464050): Use TFLM test only version of schema_utils. + +namespace tflite { +namespace testing { +namespace { + +class StackAllocator : public flatbuffers::Allocator { + public: + StackAllocator(size_t alignment) : data_size_(0) { + data_ = AlignPointerUp(data_backing_, alignment); + } + + uint8_t* allocate(size_t size) override { + TFLITE_DCHECK((data_size_ + size) <= kStackAllocatorSize); + uint8_t* result = data_; + data_ += size; + data_size_ += size; + return result; + } + + void deallocate(uint8_t* p, size_t) override {} + + static StackAllocator& instance(size_t alignment = 1) { + // Avoid using true dynamic memory allocation to be portable to bare metal. + static char inst_memory[sizeof(StackAllocator)]; + static StackAllocator* inst = new (inst_memory) StackAllocator(alignment); + return *inst; + } + + static constexpr size_t kStackAllocatorSize = 8192; + + private: + uint8_t data_backing_[kStackAllocatorSize]; + uint8_t* data_; + int data_size_; + + TF_LITE_REMOVE_VIRTUAL_DELETE +}; + +flatbuffers::FlatBufferBuilder* BuilderInstance() { + static char inst_memory[sizeof(flatbuffers::FlatBufferBuilder)]; + static flatbuffers::FlatBufferBuilder* inst = + new (inst_memory) flatbuffers::FlatBufferBuilder( + StackAllocator::kStackAllocatorSize, + &StackAllocator::instance(MicroArenaBufferAlignment())); + return inst; +} + +// A wrapper around FlatBuffer API to help build model easily. +class ModelBuilder { + public: + typedef int32_t Tensor; + typedef int Operator; + typedef int Node; + + // `builder` needs to be available until BuildModel is called. + explicit ModelBuilder(flatbuffers::FlatBufferBuilder* builder) + : builder_(builder) {} + + // Registers an operator that will be used in the model. + Operator RegisterOp(BuiltinOperator op, const char* custom_code); + + // Adds a tensor to the model. + Tensor AddTensor(TensorType type, std::initializer_list shape) { + return AddTensorImpl(type, /* is_variable */ false, shape); + } + + // Adds a variable tensor to the model. + Tensor AddVariableTensor(TensorType type, + std::initializer_list shape) { + return AddTensorImpl(type, /* is_variable */ true, shape); + } + + // Adds a node to the model with given input and output Tensors. + Node AddNode(Operator op, std::initializer_list inputs, + std::initializer_list outputs, + std::initializer_list intermediates = + std::initializer_list{}); + + void AddMetadata(const char* description_string, + const int32_t* metadata_buffer_data, size_t num_elements); + + // Constructs the flatbuffer model using `builder_` and return a pointer to + // it. The returned model has the same lifetime as `builder_`. + // Note the default value of 0 for num_subgraph_inputs means all tensor inputs + // are in subgraph input list. + const Model* BuildModel(std::initializer_list inputs, + std::initializer_list outputs, + size_t num_subgraph_inputs = 0); + + private: + // Adds a tensor to the model. + Tensor AddTensorImpl(TensorType type, bool is_variable, + std::initializer_list shape); + + flatbuffers::FlatBufferBuilder* builder_; + + static constexpr int kMaxOperatorCodes = 10; + flatbuffers::Offset operator_codes_[kMaxOperatorCodes]; + int next_operator_code_id_ = 0; + + static constexpr int kMaxOperators = 50; + flatbuffers::Offset operators_[kMaxOperators]; + int next_operator_id_ = 0; + + static constexpr int kMaxTensors = 50; + flatbuffers::Offset tensors_[kMaxTensors]; + + static constexpr int kMaxMetadataBuffers = 10; + + static constexpr int kMaxMetadatas = 10; + flatbuffers::Offset metadata_[kMaxMetadatas]; + + flatbuffers::Offset metadata_buffers_[kMaxMetadataBuffers]; + + int nbr_of_metadata_buffers_ = 0; + + int next_tensor_id_ = 0; +}; + +ModelBuilder::Operator ModelBuilder::RegisterOp(BuiltinOperator op, + const char* custom_code) { + TFLITE_DCHECK(next_operator_code_id_ <= kMaxOperatorCodes); + operator_codes_[next_operator_code_id_] = tflite::CreateOperatorCodeDirect( + *builder_, /*deprecated_builtin_code=*/0, custom_code, /*version=*/0, op); + next_operator_code_id_++; + return next_operator_code_id_ - 1; +} + +ModelBuilder::Node ModelBuilder::AddNode( + ModelBuilder::Operator op, + std::initializer_list inputs, + std::initializer_list outputs, + std::initializer_list intermediates) { + TFLITE_DCHECK(next_operator_id_ <= kMaxOperators); + operators_[next_operator_id_] = tflite::CreateOperator( + *builder_, op, builder_->CreateVector(inputs.begin(), inputs.size()), + builder_->CreateVector(outputs.begin(), outputs.size()), + BuiltinOptions_NONE, + /*builtin_options=*/0, + /*custom_options=*/0, tflite::CustomOptionsFormat_FLEXBUFFERS, + /*mutating_variable_inputs =*/0, + builder_->CreateVector(intermediates.begin(), intermediates.size())); + next_operator_id_++; + return next_operator_id_ - 1; +} + +void ModelBuilder::AddMetadata(const char* description_string, + const int32_t* metadata_buffer_data, + size_t num_elements) { + metadata_[ModelBuilder::nbr_of_metadata_buffers_] = + CreateMetadata(*builder_, builder_->CreateString(description_string), + 1 + ModelBuilder::nbr_of_metadata_buffers_); + + metadata_buffers_[nbr_of_metadata_buffers_] = tflite::CreateBuffer( + *builder_, builder_->CreateVector((uint8_t*)metadata_buffer_data, + sizeof(uint32_t) * num_elements)); + + ModelBuilder::nbr_of_metadata_buffers_++; +} + +const Model* ModelBuilder::BuildModel( + std::initializer_list inputs, + std::initializer_list outputs, + size_t num_subgraph_inputs) { + // Model schema requires an empty buffer at idx 0. + size_t buffer_size = 1 + ModelBuilder::nbr_of_metadata_buffers_; + flatbuffers::Offset buffers[kMaxMetadataBuffers]; + buffers[0] = tflite::CreateBuffer(*builder_); + + // Place the metadata buffers first in the buffer since the indices for them + // have already been set in AddMetadata() + for (int i = 1; i < ModelBuilder::nbr_of_metadata_buffers_ + 1; ++i) { + buffers[i] = metadata_buffers_[i - 1]; + } + + // Default to single subgraph model. + constexpr size_t subgraphs_size = 1; + + // Find out number of subgraph inputs. + if (num_subgraph_inputs == 0) { + // This is the default case. + num_subgraph_inputs = inputs.size(); + } else { + // A non-zero value of num_subgraph_inputs means that some of + // the operator input tensors are not subgraph inputs. + TFLITE_DCHECK(num_subgraph_inputs <= inputs.size()); + } + + const flatbuffers::Offset subgraphs[subgraphs_size] = { + tflite::CreateSubGraph( + *builder_, builder_->CreateVector(tensors_, next_tensor_id_), + builder_->CreateVector(inputs.begin(), num_subgraph_inputs), + builder_->CreateVector(outputs.begin(), outputs.size()), + builder_->CreateVector(operators_, next_operator_id_), + builder_->CreateString("test_subgraph"))}; + + flatbuffers::Offset model_offset; + if (ModelBuilder::nbr_of_metadata_buffers_ > 0) { + model_offset = tflite::CreateModel( + *builder_, 0, + builder_->CreateVector(operator_codes_, next_operator_code_id_), + builder_->CreateVector(subgraphs, subgraphs_size), + builder_->CreateString("teset_model"), + builder_->CreateVector(buffers, buffer_size), 0, + builder_->CreateVector(metadata_, + ModelBuilder::nbr_of_metadata_buffers_)); + } else { + model_offset = tflite::CreateModel( + *builder_, 0, + builder_->CreateVector(operator_codes_, next_operator_code_id_), + builder_->CreateVector(subgraphs, subgraphs_size), + builder_->CreateString("teset_model"), + builder_->CreateVector(buffers, buffer_size)); + } + + tflite::FinishModelBuffer(*builder_, model_offset); + void* model_pointer = builder_->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +ModelBuilder::Tensor ModelBuilder::AddTensorImpl( + TensorType type, bool is_variable, std::initializer_list shape) { + TFLITE_DCHECK(next_tensor_id_ <= kMaxTensors); + tensors_[next_tensor_id_] = tflite::CreateTensor( + *builder_, builder_->CreateVector(shape.begin(), shape.size()), type, + /* buffer */ 0, /* name */ 0, /* quantization */ 0, + /* is_variable */ is_variable, + /* sparsity */ 0); + next_tensor_id_++; + return next_tensor_id_ - 1; +} + +const Model* BuildSimpleStatefulModel() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* fb_builder = BuilderInstance(); + + ModelBuilder model_builder(fb_builder); + + const int op_id = + model_builder.RegisterOp(BuiltinOperator_CUSTOM, "simple_stateful_op"); + const int input_tensor = model_builder.AddTensor(TensorType_INT8, {3}); + const int median_tensor = model_builder.AddTensor(TensorType_INT8, {3}); + const int invoke_count_tensor = + model_builder.AddTensor(TensorType_INT32, {1}); + const int intermediate_tensor = + model_builder.AddTensor(TensorType_FLOAT32, {0}); + + model_builder.AddNode(op_id, {input_tensor}, + {median_tensor, invoke_count_tensor}, + {intermediate_tensor}); + return model_builder.BuildModel({input_tensor}, + {median_tensor, invoke_count_tensor}); +} + +const Model* BuildSimpleModelWithBranch() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* fb_builder = BuilderInstance(); + + ModelBuilder model_builder(fb_builder); + /* Model structure + | t0 + +------| + | v + | +---------+ + | | n0 | + | | | + | +---------+ + v + + | + +---------+ | t1 + | n1 | | + | | | + +---------+ | + | | + t2 | v + | +---------+ + +-->| n2 | + | | + +-------|-+ + |t3 + v + */ + const int op_id = + model_builder.RegisterOp(BuiltinOperator_CUSTOM, "mock_custom"); + const int t0 = model_builder.AddTensor(TensorType_FLOAT32, {2, 2, 3}); + const int t1 = model_builder.AddTensor(TensorType_FLOAT32, {2, 2, 3}); + const int t2 = model_builder.AddTensor(TensorType_FLOAT32, {2, 2, 3}); + const int t3 = model_builder.AddTensor(TensorType_FLOAT32, {2, 2, 3}); + model_builder.AddNode(op_id, {t0}, {t1}); // n0 + model_builder.AddNode(op_id, {t0}, {t2}); // n1 + model_builder.AddNode(op_id, {t1, t2}, {t3}); // n2 + return model_builder.BuildModel({t0}, {t3}); +} + +const Model* BuildModelWithOfflinePlanning(int number_of_tensors, + const int32_t* metadata_buffer, + NodeConnection* node_conn, + int num_conns, + int num_subgraph_inputs) { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* fb_builder = BuilderInstance(); + + ModelBuilder model_builder(fb_builder); + + const int op_id = + model_builder.RegisterOp(BuiltinOperator_CUSTOM, "mock_custom"); + + for (int i = 0; i < number_of_tensors; ++i) { + model_builder.AddTensor(TensorType_FLOAT32, {2, 2, 3}); + } + + for (int i = 0; i < num_conns; ++i) { + model_builder.AddNode(op_id, node_conn[i].input, node_conn[i].output); + } + + model_builder.AddMetadata( + "OfflineMemoryAllocation", metadata_buffer, + number_of_tensors + tflite::testing::kOfflinePlannerHeaderSize); + + return model_builder.BuildModel( + node_conn[0].input, node_conn[num_conns - 1].output, num_subgraph_inputs); +} + +const Model* BuildModelWithUnusedInputs() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + + constexpr size_t buffers_size = 1; + const Offset buffers[buffers_size] = {CreateBuffer(*builder)}; + constexpr size_t tensor_shape_size = 2; + const int32_t tensor_shape[tensor_shape_size] = {1, 64}; + constexpr size_t tensors_size = 4; + const Offset tensors[tensors_size] = { + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 0, + builder->CreateString("test_input_tensor"), 0, false), + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 0, + builder->CreateString("test_unused_input_tensor"), 0, false), + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 0, + builder->CreateString("test_output_tensor"), 0, false), + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 0, + builder->CreateString("test_unused_tensor"), 0, false), + }; + constexpr size_t inputs_size = 2; + const int32_t inputs[inputs_size] = {0, 1}; + constexpr size_t outputs_size = 1; + const int32_t outputs[outputs_size] = {2}; + constexpr size_t operator_inputs_size = 1; + const int32_t operator_inputs[operator_inputs_size] = {0}; + constexpr size_t operator_outputs_size = 1; + const int32_t operator_outputs[operator_outputs_size] = {2}; + constexpr size_t operators_size = 1; + const Offset operators[operators_size] = { + CreateOperator( + *builder, 0, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, operator_outputs_size), + BuiltinOptions_NONE), + }; + constexpr size_t subgraphs_size = 1; + const Offset subgraphs[subgraphs_size] = { + CreateSubGraph(*builder, builder->CreateVector(tensors, tensors_size), + builder->CreateVector(inputs, inputs_size), + builder->CreateVector(outputs, outputs_size), + builder->CreateVector(operators, operators_size), + builder->CreateString("test_subgraph"))}; + constexpr size_t operator_codes_size = 1; + const Offset operator_codes[operator_codes_size] = { + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "mock_custom", + /*version=*/0, BuiltinOperator_CUSTOM)}; + const Offset model_offset = CreateModel( + *builder, 0, builder->CreateVector(operator_codes, operator_codes_size), + builder->CreateVector(subgraphs, subgraphs_size), + builder->CreateString("test_model"), + builder->CreateVector(buffers, buffers_size)); + FinishModelBuffer(*builder, model_offset); + void* model_pointer = builder->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +const Model* BuildModelWithUnusedOperatorOutputs() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + + constexpr size_t buffers_size = 1; + const Offset buffers[buffers_size] = {CreateBuffer(*builder)}; + constexpr size_t tensor_shape_size = 2; + const int32_t tensor_shape[tensor_shape_size] = {1, 64}; + constexpr size_t tensors_size = 2; + const Offset tensors[tensors_size] = { + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 0, + builder->CreateString("test_input_tensor"), 0, false), + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 0, + builder->CreateString("test_unused_output_tensor"), 0, false)}; + constexpr size_t inputs_size = 0; + const int32_t inputs[inputs_size] = {}; + constexpr size_t outputs_size = 1; + const int32_t outputs[outputs_size] = {0}; + constexpr size_t operator_inputs_size = 0; + const int32_t operator_inputs[operator_inputs_size] = {}; + constexpr size_t operator_outputs_size = 2; + const int32_t operator_outputs[operator_outputs_size] = {0, 1}; + constexpr size_t operators_size = 1; + const Offset operators[operators_size] = { + CreateOperator( + *builder, 0, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, operator_outputs_size), + BuiltinOptions_NONE), + }; + constexpr size_t subgraphs_size = 1; + const Offset subgraphs[subgraphs_size] = { + CreateSubGraph(*builder, builder->CreateVector(tensors, tensors_size), + builder->CreateVector(inputs, inputs_size), + builder->CreateVector(outputs, outputs_size), + builder->CreateVector(operators, operators_size), + builder->CreateString("test_subgraph"))}; + constexpr size_t operator_codes_size = 1; + const Offset operator_codes[operator_codes_size] = { + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "mock_custom", + /*version=*/0, BuiltinOperator_CUSTOM)}; + const Offset model_offset = CreateModel( + *builder, 0, builder->CreateVector(operator_codes, operator_codes_size), + builder->CreateVector(subgraphs, subgraphs_size), + builder->CreateString("test_model"), + builder->CreateVector(buffers, buffers_size)); + FinishModelBuffer(*builder, model_offset); + void* model_pointer = builder->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +const Model* BuildModelWith256x256Tensor() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* fb_builder = BuilderInstance(); + + ModelBuilder model_builder(fb_builder); + + const int op_id = + model_builder.RegisterOp(BuiltinOperator_CUSTOM, "mock_custom"); + const int input1_tensor = + model_builder.AddTensor(TensorType_INT8, {256, 256}); + const int input2_tensor = + model_builder.AddTensor(TensorType_INT8, {256, 256}); + const int output_tensor = + model_builder.AddTensor(TensorType_INT8, {256, 256}); + + model_builder.AddNode(op_id, {input1_tensor, input2_tensor}, {output_tensor}); + return model_builder.BuildModel({input1_tensor, input2_tensor}, + {output_tensor}); +} + +const Model* BuildSimpleMockModel() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + + constexpr size_t buffer_data_size = 1; + const uint8_t buffer_data[buffer_data_size] = {21}; + constexpr size_t buffers_size = 2; + const Offset buffers[buffers_size] = { + CreateBuffer(*builder), + CreateBuffer(*builder, + builder->CreateVector(buffer_data, buffer_data_size))}; + constexpr size_t tensor_shape_size = 1; + const int32_t tensor_shape[tensor_shape_size] = {1}; + constexpr size_t tensors_size = 4; + const Offset tensors[tensors_size] = { + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, + builder->CreateString("test_input_tensor"), 0, false), + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 1, + builder->CreateString("test_weight_tensor"), 0, false), + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, + builder->CreateString("test_output_tensor"), 0, false), + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, + builder->CreateString("test_output2_tensor"), 0, false), + }; + constexpr size_t inputs_size = 1; + const int32_t inputs[inputs_size] = {0}; + constexpr size_t outputs_size = 2; + const int32_t outputs[outputs_size] = {2, 3}; + constexpr size_t operator_inputs_size = 2; + const int32_t operator_inputs[operator_inputs_size] = {0, 1}; + constexpr size_t operator_outputs_size = 1; + const int32_t operator_outputs[operator_outputs_size] = {2}; + const int32_t operator2_outputs[operator_outputs_size] = {3}; + constexpr size_t operators_size = 2; + const Offset operators[operators_size] = { + CreateOperator( + *builder, 0, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, operator_outputs_size), + BuiltinOptions_NONE), + CreateOperator( + *builder, 0, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator2_outputs, operator_outputs_size), + BuiltinOptions_NONE), + }; + constexpr size_t subgraphs_size = 1; + const Offset subgraphs[subgraphs_size] = { + CreateSubGraph(*builder, builder->CreateVector(tensors, tensors_size), + builder->CreateVector(inputs, inputs_size), + builder->CreateVector(outputs, outputs_size), + builder->CreateVector(operators, operators_size), + builder->CreateString("test_subgraph"))}; + constexpr size_t operator_codes_size = 1; + const Offset operator_codes[operator_codes_size] = { + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "mock_custom", + /*version=*/0, BuiltinOperator_CUSTOM)}; + const Offset model_offset = CreateModel( + *builder, 0, builder->CreateVector(operator_codes, operator_codes_size), + builder->CreateVector(subgraphs, subgraphs_size), + builder->CreateString("test_model"), + builder->CreateVector(buffers, buffers_size)); + FinishModelBuffer(*builder, model_offset); + void* model_pointer = builder->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +const Model* BuildComplexMockModel() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + + constexpr size_t buffer_data_size = 1; + const uint8_t buffer_data_1[buffer_data_size] = {21}; + const uint8_t buffer_data_2[buffer_data_size] = {21}; + const uint8_t buffer_data_3[buffer_data_size] = {21}; + constexpr size_t buffers_size = 7; + const Offset buffers[buffers_size] = { + // Op 1 buffers: + CreateBuffer(*builder), + CreateBuffer(*builder), + CreateBuffer(*builder, + builder->CreateVector(buffer_data_1, buffer_data_size)), + // Op 2 buffers: + CreateBuffer(*builder), + CreateBuffer(*builder, + builder->CreateVector(buffer_data_2, buffer_data_size)), + // Op 3 buffers: + CreateBuffer(*builder), + CreateBuffer(*builder, + builder->CreateVector(buffer_data_3, buffer_data_size)), + }; + constexpr size_t tensor_shape_size = 1; + const int32_t tensor_shape[tensor_shape_size] = {1}; + + constexpr size_t tensors_size = 10; + const Offset tensors[tensors_size] = { + // Op 1 inputs: + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, builder->CreateString("test_input_tensor_1"), 0, + false /* is_variable */), + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 1, builder->CreateString("test_variable_tensor_1"), + 0, true /* is_variable */), + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 2, builder->CreateString("test_weight_tensor_1"), 0, + false /* is_variable */), + // Op 1 output / Op 2 input: + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, builder->CreateString("test_output_tensor_1"), 0, + false /* is_variable */), + // Op 2 inputs: + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 1, builder->CreateString("test_variable_tensor_2"), + 0, true /* is_variable */), + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 2, builder->CreateString("test_weight_tensor_2"), 0, + false /* is_variable */), + // Op 2 output / Op 3 input: + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, builder->CreateString("test_output_tensor_2"), 0, + false /* is_variable */), + // Op 3 inputs: + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 1, builder->CreateString("test_variable_tensor_3"), + 0, true /* is_variable */), + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 2, builder->CreateString("test_weight_tensor_3"), 0, + false /* is_variable */), + // Op 3 output: + CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, builder->CreateString("test_output_tensor_3"), 0, + false /* is_variable */), + }; + + constexpr size_t operators_size = 3; + Offset operators[operators_size]; + { + // Set Op 1 attributes: + constexpr size_t operator_inputs_size = 3; + const int32_t operator_inputs[operator_inputs_size] = {0, 1, 2}; + constexpr size_t operator_outputs_size = 1; + const int32_t operator_outputs[operator_outputs_size] = {3}; + + operators[0] = {CreateOperator( + *builder, 0, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, operator_outputs_size), + BuiltinOptions_NONE)}; + } + + { + // Set Op 2 attributes + constexpr size_t operator_inputs_size = 3; + const int32_t operator_inputs[operator_inputs_size] = {3, 4, 5}; + constexpr size_t operator_outputs_size = 1; + const int32_t operator_outputs[operator_outputs_size] = {6}; + + operators[1] = {CreateOperator( + *builder, 0, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, operator_outputs_size), + BuiltinOptions_NONE)}; + } + + { + // Set Op 3 attributes + constexpr size_t operator_inputs_size = 3; + const int32_t operator_inputs[operator_inputs_size] = {6, 7, 8}; + constexpr size_t operator_outputs_size = 1; + const int32_t operator_outputs[operator_outputs_size] = {9}; + + operators[2] = {CreateOperator( + *builder, 0, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, operator_outputs_size), + BuiltinOptions_NONE)}; + } + + constexpr size_t inputs_size = 1; + const int32_t inputs[inputs_size] = {0}; + constexpr size_t outputs_size = 1; + const int32_t outputs[outputs_size] = {9}; + + constexpr size_t subgraphs_size = 1; + const Offset subgraphs[subgraphs_size] = { + CreateSubGraph(*builder, builder->CreateVector(tensors, tensors_size), + builder->CreateVector(inputs, inputs_size), + builder->CreateVector(outputs, outputs_size), + builder->CreateVector(operators, operators_size), + builder->CreateString("test_subgraph"))}; + + constexpr size_t operator_codes_size = 1; + const Offset operator_codes[operator_codes_size] = { + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "mock_custom", + /*version=*/0, BuiltinOperator_CUSTOM)}; + + const Offset model_offset = CreateModel( + *builder, 0, builder->CreateVector(operator_codes, operator_codes_size), + builder->CreateVector(subgraphs, subgraphs_size), + builder->CreateString("test_model"), + builder->CreateVector(buffers, buffers_size)); + + FinishModelBuffer(*builder, model_offset); + void* model_pointer = builder->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +const Model* BuildSimpleMultipleInputsModel() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + + constexpr size_t buffers_size = 1; + const Offset buffers[buffers_size] = { + CreateBuffer(*builder), + }; + constexpr size_t tensor_shape_size = 1; + const int32_t tensor_shape[tensor_shape_size] = {1}; + constexpr size_t tensors_size = 4; + const Offset tensors[tensors_size] = { + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, + builder->CreateString("test_input_tensor1"), 0, false), + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT8, 0, + builder->CreateString("test_input_tensor2"), 0, false), + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, + builder->CreateString("test_input_tensor3"), 0, false), + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, + builder->CreateString("test_output_tensor"), 0, false), + }; + constexpr size_t inputs_size = 3; + const int32_t inputs[inputs_size] = {0, 1, 2}; + constexpr size_t outputs_size = 1; + const int32_t outputs[outputs_size] = {3}; + constexpr size_t operator_inputs_size = 3; + const int32_t operator_inputs[operator_inputs_size] = {0, 1, 2}; + constexpr size_t operator_outputs_size = 1; + const int32_t operator_outputs[operator_outputs_size] = {3}; + constexpr size_t operators_size = 1; + const Offset operators[operators_size] = { + CreateOperator( + *builder, 0, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, operator_outputs_size), + BuiltinOptions_NONE), + }; + constexpr size_t subgraphs_size = 1; + const Offset subgraphs[subgraphs_size] = { + CreateSubGraph(*builder, builder->CreateVector(tensors, tensors_size), + builder->CreateVector(inputs, inputs_size), + builder->CreateVector(outputs, outputs_size), + builder->CreateVector(operators, operators_size), + builder->CreateString("test_subgraph"))}; + constexpr size_t operator_codes_size = 1; + const Offset operator_codes[operator_codes_size] = { + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "multiple_inputs_op", + /*version=*/0, BuiltinOperator_CUSTOM)}; + const Offset model_offset = CreateModel( + *builder, 0, builder->CreateVector(operator_codes, operator_codes_size), + builder->CreateVector(subgraphs, subgraphs_size), + builder->CreateString("test_model"), + builder->CreateVector(buffers, buffers_size)); + FinishModelBuffer(*builder, model_offset); + void* model_pointer = builder->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +const Model* BuildSimpleModelWithSubgraphsAndIf() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + + constexpr size_t buffers_size = 1; + const Offset buffers[buffers_size] = { + CreateBuffer(*builder), + }; + const int32_t condition_tensor_shape[] = {1}; + const int32_t data_tensor_shape[] = {1, 2}; + constexpr size_t tensors_size = 4; + const Offset subgraph1_tensors[tensors_size] = { + CreateTensor(*builder, builder->CreateVector(condition_tensor_shape, 1), + TensorType_BOOL, 0, + builder->CreateString("condition tensor"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 2), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor1"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 2), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor2"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 2), + TensorType_FLOAT32, 0, + builder->CreateString("output_tensor"), 0, false), + }; + const Offset subgraph2_tensors[tensors_size] = { + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 2), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor1"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 2), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor2"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 2), + TensorType_FLOAT32, 0, + builder->CreateString("output_tensor"), 0, false), + }; + const Offset subgraph3_tensors[tensors_size] = { + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 2), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor1"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 2), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor2"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 2), + TensorType_FLOAT32, 0, + builder->CreateString("output_tensor"), 0, false), + }; + + constexpr size_t if_inputs_size = 3; + const int32_t if_inputs[if_inputs_size] = {0, 1, 2}; + constexpr size_t outputs_size = 1; + const int32_t if_outputs[outputs_size] = {3}; + constexpr size_t operator_inputs_size = 2; + const int32_t operator_inputs[operator_inputs_size] = {0, 1}; + const int32_t operator_outputs[outputs_size] = {2}; + constexpr size_t operators_size = 1; + const Offset subgraph1_operators[operators_size] = { + CreateOperator( + *builder, 0, builder->CreateVector(if_inputs, if_inputs_size), + builder->CreateVector(if_outputs, outputs_size), + BuiltinOptions_IfOptions, CreateIfOptions(*builder, 1, 2).Union()), + }; + const Offset subgraph2_operators[operators_size] = { + CreateOperator( + *builder, 1, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, outputs_size), + BuiltinOptions_NONE), + }; + const Offset subgraph3_operators[operators_size] = { + CreateOperator( + *builder, 2, + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, outputs_size), + BuiltinOptions_NONE), + }; + constexpr size_t subgraphs_size = 3; + const Offset subgraphs[subgraphs_size] = { + CreateSubGraph(*builder, builder->CreateVector(subgraph1_tensors, 4), + builder->CreateVector(if_inputs, if_inputs_size), + builder->CreateVector(if_outputs, outputs_size), + builder->CreateVector(subgraph1_operators, operators_size), + builder->CreateString("if_subgraph")), + CreateSubGraph( + *builder, builder->CreateVector(subgraph2_tensors, 3), + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, outputs_size), + builder->CreateVector(subgraph2_operators, operators_size), + builder->CreateString("then_subgraph")), + CreateSubGraph( + *builder, builder->CreateVector(subgraph3_tensors, 3), + builder->CreateVector(operator_inputs, operator_inputs_size), + builder->CreateVector(operator_outputs, outputs_size), + builder->CreateVector(subgraph3_operators, operators_size), + builder->CreateString("else_subgraph")), + }; + constexpr size_t operator_codes_size = 3; + const Offset operator_codes[operator_codes_size] = { + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "multiple_inputs_op", + /*version=*/0, BuiltinOperator_IF), + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "multiple_inputs_op", + /*version=*/0, BuiltinOperator_ADD), + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "multiple_inputs_op", + /*version=*/0, BuiltinOperator_MUL), + }; + const Offset model_offset = CreateModel( + *builder, 0, builder->CreateVector(operator_codes, operator_codes_size), + builder->CreateVector(subgraphs, subgraphs_size), + builder->CreateString("test_model"), + builder->CreateVector(buffers, buffers_size)); + FinishModelBuffer(*builder, model_offset); + void* model_pointer = builder->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +const Model* BuildSimpleModelWithSubgraphsAndWhile() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + + constexpr size_t buffers_size = 1; + const Offset buffers[buffers_size] = { + CreateBuffer(*builder), + }; + const int32_t data_tensor_shape[] = {1, 1}; + constexpr size_t while_tensors_size = 4; + constexpr size_t op_tensors_size = 3; + const Offset subgraph0_tensors[while_tensors_size] = { + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor0"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor1"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_FLOAT32, 0, + builder->CreateString("output_tensor0"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_FLOAT32, 0, + builder->CreateString("output_tensor1"), 0, false), + }; + const Offset subgraph1_tensors[op_tensors_size] = { + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor1"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor2"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_BOOL, 0, + builder->CreateString("condition_tensor"), 0, false), + }; + const Offset subgraph2_tensors[op_tensors_size] = { + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor0"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_FLOAT32, 0, + builder->CreateString("input_tensor1"), 0, false), + CreateTensor(*builder, builder->CreateVector(data_tensor_shape, 1), + TensorType_FLOAT32, 0, + builder->CreateString("output_tensor0"), 0, false), + }; + + constexpr size_t inputs_size = 2; + const int32_t inputs[inputs_size] = {0, 1}; + constexpr size_t while_outputs_size = 2; + const int32_t while_outputs[while_outputs_size] = {2, 3}; + constexpr size_t cond_outputs_size = 1; + const int32_t cond_outputs[cond_outputs_size] = {2}; + constexpr size_t add_outputs_size = 1; + const int32_t add_outputs[add_outputs_size] = {2}; + constexpr size_t add_subgraph_outputs_size = 2; + const int32_t add_subgraph_outputs[add_subgraph_outputs_size] = {2, 1}; + constexpr size_t operators_size = 1; + const Offset subgraph0_operators[operators_size] = { + CreateOperator(*builder, 0, builder->CreateVector(inputs, inputs_size), + builder->CreateVector(while_outputs, while_outputs_size), + BuiltinOptions_WhileOptions, + CreateWhileOptions(*builder, 1, 2).Union()), + }; + const Offset subgraph1_operators[operators_size] = { + CreateOperator(*builder, 1, builder->CreateVector(inputs, inputs_size), + builder->CreateVector(cond_outputs, cond_outputs_size), + BuiltinOptions_NONE), + }; + const Offset subgraph2_operators[operators_size] = { + CreateOperator(*builder, 2, builder->CreateVector(inputs, inputs_size), + builder->CreateVector(add_outputs, add_outputs_size), + BuiltinOptions_NONE), + }; + constexpr size_t subgraphs_size = 3; + const Offset subgraphs[subgraphs_size] = { + CreateSubGraph(*builder, builder->CreateVector(subgraph0_tensors, 4), + builder->CreateVector(inputs, inputs_size), + builder->CreateVector(while_outputs, while_outputs_size), + builder->CreateVector(subgraph0_operators, operators_size), + builder->CreateString("while_subgraph")), + CreateSubGraph(*builder, builder->CreateVector(subgraph1_tensors, 3), + builder->CreateVector(inputs, inputs_size), + builder->CreateVector(cond_outputs, cond_outputs_size), + builder->CreateVector(subgraph1_operators, operators_size), + builder->CreateString("cond_subgraph")), + CreateSubGraph(*builder, builder->CreateVector(subgraph2_tensors, 3), + builder->CreateVector(inputs, inputs_size), + builder->CreateVector(add_subgraph_outputs, + add_subgraph_outputs_size), + builder->CreateVector(subgraph2_operators, operators_size), + builder->CreateString("body_subgraph")), + }; + constexpr size_t operator_codes_size = 3; + const Offset operator_codes[operator_codes_size] = { + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "multiple_inputs_op", + /*version=*/0, BuiltinOperator_WHILE), + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "multiple_inputs_op", + /*version=*/0, BuiltinOperator_LESS), + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "multiple_inputs_op", + /*version=*/0, BuiltinOperator_ADD), + }; + const Offset model_offset = CreateModel( + *builder, 0, builder->CreateVector(operator_codes, operator_codes_size), + builder->CreateVector(subgraphs, subgraphs_size), + builder->CreateString("test_model"), + builder->CreateVector(buffers, buffers_size)); + FinishModelBuffer(*builder, model_offset); + void* model_pointer = builder->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +// Build a model with If and two subgraphs: two data tensors A1 of size 2, A2 of +// size 4 are first concatenated, then cut to a new tensor A3 of size 3; the new +// tensor A3 of size 3 is then concatenated with A2 tensor of size 4 to produce +// a final output tensor A4. This model is specially crafted to capture the +// corner case outlined in go/avoid-memory-corruption-in-if-operator. +// +// Subgraph0 +// A0(1) A2_0(4) A1_0(2) +// | | | ---+ +// v v v | +// +--------------+ | +// | IF | | +// +------+-------+ | +// | A3_0(3) | +// v | +// +--------------+ | +// | CUSTOM |<---+ +// +------+-------+ +// | +// v +// A4_0(8) +// +// Subgraph1/2 +// A1_1(2) A2_1(4) +// | | +// v v +// +---------------+ +// | CUSTOM | +// +-------+-------+ +// | +// v A3_1(3) +// +// And it leads to memory plan as below +// +// Subgraph0 Layout +// +// +// <------------A4_0 -------------> <----- A2_0-------> <----A3_0 ---> +// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +// | | | | | | | | | 3 | 4 | 5 | 6 | | | | +// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +// +// +----+----+----+ +// | 1 | 2 | A0 | +// +----+----+----+ +// <---A1_0--> +// +// Subgraph 1 Layout +// +// +----+----+----+----+----+----+----+----+----+ +// | | | | | | | | | | +// +----+----+----+----+----+----+----+----+----+ +// +// +// <------A2_1 -------><----A3_1 ---><--A1_1---> +// +// +// A1_1 of subgraph 1 will overlap with A2_0 of subgraph 0. +// In a buggy implementation of IF, two overwrite may happen: +// 1. copying input from A1_0 to A1_1 overwrites A2_0 before A2_0 is copied to +// A2_1; thus subgraph 1 produce incorrect output. +// 2. copying output from A3_1 to A4_0 overwrites A1_0, which should remain +// intact so that it can be used by the OP after the IF operator in subgraph 0 +// + +const Model* BuildModelWithIfAndSubgraphInputTensorOverlap() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + + constexpr TensorType kTensorType = TensorType_INT32; + constexpr int kBlockSize = + tflite::MicroArenaBufferAlignment() / sizeof(int32_t); + constexpr size_t kBuffersCount = 1; + const Offset buffers[kBuffersCount] = { + CreateBuffer(*builder), + }; + const int32_t kConditionTensorShape[] = {1}; + const int32_t kIfInput1TensorShape[] = {2 * kBlockSize}; + const int32_t kIfInput2TensorShape[] = {4 * kBlockSize}; + const int32_t kIfOutputTensorShape[] = {3 * kBlockSize}; + const int32_t kFinalOutputTensorShape[] = {8 * kBlockSize}; + constexpr size_t kSubgraph0TensorsCount = 5; + const Offset kSubgraph0Tensors[kSubgraph0TensorsCount] = { + CreateTensor(*builder, builder->CreateVector(kConditionTensorShape, 1), + TensorType_BOOL, 0, + builder->CreateString("condition tensor"), 0, false), + CreateTensor(*builder, builder->CreateVector(kIfInput1TensorShape, 1), + kTensorType, 0, builder->CreateString("if_input_tensor1"), 0, + false), + CreateTensor(*builder, builder->CreateVector(kIfInput2TensorShape, 1), + kTensorType, 0, builder->CreateString("if_input_tensor2"), 0, + false), + CreateTensor(*builder, builder->CreateVector(kIfOutputTensorShape, 1), + kTensorType, 0, builder->CreateString("if_output_tensor"), 0, + false), + CreateTensor(*builder, builder->CreateVector(kFinalOutputTensorShape, 1), + kTensorType, 0, builder->CreateString("final_output_tensor"), + 0, false), + }; + + // Subgraph 1 is the chosen path if condition tensor in IF is true. + constexpr size_t kSubgraph1TensorsCount = 3; + const Offset kSubgraph1Tensors[kSubgraph1TensorsCount] = { + CreateTensor(*builder, builder->CreateVector(kIfInput1TensorShape, 1), + kTensorType, 0, + builder->CreateString("subgraph1_input_tensor1"), 0, false), + CreateTensor(*builder, builder->CreateVector(kIfInput2TensorShape, 1), + kTensorType, 0, + builder->CreateString("subgraph1_input_tensor2"), 0, false), + CreateTensor(*builder, builder->CreateVector(kIfOutputTensorShape, 1), + kTensorType, 0, + builder->CreateString("subgraph1_output_tensor"), 0, false), + }; + + // Subgraph 2 is the chosen path if condition tensor in IF is false + constexpr size_t kSubgraph2TensorsCount = 3; + const Offset kSubgraph2Tensors[kSubgraph2TensorsCount] = { + CreateTensor(*builder, builder->CreateVector(kIfInput1TensorShape, 1), + kTensorType, 0, builder->CreateString("if_input_tensor1"), 0, + false), + CreateTensor(*builder, builder->CreateVector(kIfInput2TensorShape, 1), + kTensorType, 0, builder->CreateString("if_input_tensor2"), 0, + false), + CreateTensor(*builder, builder->CreateVector(kIfOutputTensorShape, 1), + kTensorType, 0, builder->CreateString("if_output_tensor"), 0, + false), + }; + + constexpr int kIfOpCodeIndex = 0; + constexpr int kCustomOpCodeIndex = 1; + + constexpr size_t kIfInputsCount = 3; + const int32_t kIfInputs[kIfInputsCount] = {0, 1, 2}; + constexpr size_t kOutputsCount = 1; + const int32_t kIfOutputs[kOutputsCount] = {3}; + constexpr size_t kOpAfterIfInputsCount = 2; + const int32_t kOpAfterIfInputs[kOpAfterIfInputsCount] = {3, 2}; + const int32_t kOpAfterIfOutputs[kOutputsCount] = {4}; + constexpr size_t kOperatorsCount = 2; + const Offset kSubgraph0Operators[kOperatorsCount] = { + CreateOperator(*builder, kIfOpCodeIndex, + builder->CreateVector(kIfInputs, kIfInputsCount), + builder->CreateVector(kIfOutputs, kOutputsCount), + BuiltinOptions_IfOptions, + CreateIfOptions(*builder, 1, 2).Union()), + CreateOperator( + *builder, kCustomOpCodeIndex, + builder->CreateVector(kOpAfterIfInputs, kOpAfterIfInputsCount), + builder->CreateVector(kOpAfterIfOutputs, kOutputsCount)), + }; + + constexpr size_t kSubgraph1InputsCount = 2; + const int32_t kSubgraph1Inputs[kSubgraph1InputsCount] = {0, 1}; + constexpr size_t kSubgraph1OutputsCount = 1; + const int32_t kSubgraph1Outputs[kSubgraph1OutputsCount] = {2}; + constexpr size_t kSubgraph1OperatorsCount = 1; + const Offset kSubgraph1Operators[kSubgraph1OperatorsCount] = { + CreateOperator( + *builder, kCustomOpCodeIndex, + builder->CreateVector(kSubgraph1Inputs, kSubgraph1InputsCount), + builder->CreateVector(kSubgraph1Outputs, kSubgraph1OutputsCount), + BuiltinOptions_NONE), + }; + + constexpr size_t kSubgraph2InputsCount = 2; + const int32_t kSubgraph2Inputs[kSubgraph2InputsCount] = {0, 1}; + constexpr size_t kSubgraph2OutputsCount = 1; + const int32_t kSubgraph2Outputs[kSubgraph2OutputsCount] = {2}; + constexpr size_t kSubgraph2OperatorsCount = 1; + const Offset kSubgraph2Operators[kSubgraph2OperatorsCount] = { + CreateOperator( + *builder, kCustomOpCodeIndex, + builder->CreateVector(kSubgraph2Inputs, kSubgraph2InputsCount), + builder->CreateVector(kSubgraph2Outputs, kSubgraph2OutputsCount), + BuiltinOptions_NONE), + }; + + constexpr size_t kSubgraphsCount = 3; + const Offset kSubgraphs[kSubgraphsCount] = { + CreateSubGraph( + *builder, + builder->CreateVector(kSubgraph0Tensors, kSubgraph0TensorsCount), + builder->CreateVector(kIfInputs, kIfInputsCount), + builder->CreateVector(kOpAfterIfOutputs, kOutputsCount), + builder->CreateVector(kSubgraph0Operators, kOperatorsCount), + builder->CreateString("if_subgraph")), + CreateSubGraph( + *builder, + builder->CreateVector(kSubgraph1Tensors, kSubgraph1TensorsCount), + builder->CreateVector(kSubgraph1Inputs, kSubgraph1InputsCount), + builder->CreateVector(kSubgraph1Outputs, kSubgraph1OutputsCount), + builder->CreateVector(kSubgraph1Operators, kSubgraph1OperatorsCount), + builder->CreateString("then_subgraph")), + CreateSubGraph( + *builder, + builder->CreateVector(kSubgraph2Tensors, kSubgraph2TensorsCount), + builder->CreateVector(kSubgraph2Inputs, kSubgraph2InputsCount), + builder->CreateVector(kSubgraph2Outputs, kSubgraph2OutputsCount), + builder->CreateVector(kSubgraph2Operators, kSubgraph2OperatorsCount), + builder->CreateString("else_subgraph")), + }; + + constexpr size_t kOperatorCodesCount = 2; + const Offset kOperatorCodes[kOperatorCodesCount] = { + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, "if", + /*version=*/0, BuiltinOperator_IF), + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "custom_packer_op", + /*version=*/0, BuiltinOperator_CUSTOM), + }; + const Offset kModelOffset = CreateModel( + *builder, 0, builder->CreateVector(kOperatorCodes, kOperatorCodesCount), + builder->CreateVector(kSubgraphs, kSubgraphsCount), + builder->CreateString("test_model"), + builder->CreateVector(buffers, kBuffersCount)); + FinishModelBuffer(*builder, kModelOffset); + void* model_pointer = builder->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +// Mock model with one main subgraph containing a single CALL_ONCE op (with null +// inputs and outputs) which invokes a second subgraph which has null inputs and +// outputs. +const Model* BuildSimpleMockModelWithNullInputsOutputs() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + + constexpr size_t buffers_size = 1; + const Offset buffers[buffers_size] = { + CreateBuffer(*builder), + }; + constexpr size_t tensor_shape_size = 1; + const int32_t tensor_shape[tensor_shape_size] = {0}; + constexpr size_t tensors_size = 1; + const Offset tensors[tensors_size] = { + CreateTensor(*builder, + builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, + builder->CreateString("test_input_tensor1"), 0, false), + }; + constexpr size_t subgraph0_inputs_size = 1; + const int32_t subgraph0_inputs[subgraph0_inputs_size] = {0}; + constexpr size_t subgraph0_outputs_size = 1; + const int32_t subgraph0_outputs[subgraph0_outputs_size] = {0}; + constexpr size_t operators_size = 1; + const Offset subgraph0_operators[operators_size] = { + CreateOperator(*builder, 0, {}, {}, BuiltinOptions_CallOnceOptions, + CreateCallOnceOptions(*builder, 1).Union()), + }; + const Offset subgraph1_operators[operators_size] = { + CreateOperator(*builder, 1, {}, {}, BuiltinOptions_NONE)}; + constexpr size_t subgraphs_size = 2; + const Offset subgraphs[subgraphs_size] = { + CreateSubGraph( + *builder, builder->CreateVector(tensors, tensors_size), + builder->CreateVector(subgraph0_inputs, subgraph0_inputs_size), + builder->CreateVector(subgraph0_outputs, subgraph0_outputs_size), + builder->CreateVector(subgraph0_operators, operators_size), + builder->CreateString("main_subgraph")), + CreateSubGraph(*builder, builder->CreateVector(tensors, tensors_size), {}, + {}, + builder->CreateVector(subgraph1_operators, operators_size), + builder->CreateString("secondary subgraph")), + }; + constexpr size_t operator_codes_size = 2; + const Offset operator_codes[operator_codes_size] = { + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, + "call_once_op", + /*version=*/0, BuiltinOperator_CALL_ONCE), + CreateOperatorCodeDirect(*builder, /*deprecated_builtin_code=*/0, "no_op", + /*version=*/0, BuiltinOperator_CUSTOM)}; + const Offset model_offset = CreateModel( + *builder, 0, builder->CreateVector(operator_codes, operator_codes_size), + builder->CreateVector(subgraphs, subgraphs_size), + builder->CreateString("test_model"), + builder->CreateVector(buffers, buffers_size)); + FinishModelBuffer(*builder, model_offset); + void* model_pointer = builder->GetBufferPointer(); + const Model* model = flatbuffers::GetRoot(model_pointer); + return model; +} + +} // namespace + +const TfLiteRegistration* SimpleStatefulOp::getRegistration() { + return GetMutableRegistration(); +} + +TfLiteRegistration* SimpleStatefulOp::GetMutableRegistration() { + static TfLiteRegistration r; + r.init = Init; + r.prepare = Prepare; + r.invoke = Invoke; + return &r; +} + +void* SimpleStatefulOp::Init(TfLiteContext* context, const char* buffer, + size_t length) { + TFLITE_DCHECK(context->AllocateBufferForEval == nullptr); + TFLITE_DCHECK(context->GetScratchBuffer == nullptr); + TFLITE_DCHECK(context->RequestScratchBufferInArena == nullptr); + + void* raw = context->AllocatePersistentBuffer(context, sizeof(OpData)); + OpData* data = reinterpret_cast(raw); + *data = {}; + return raw; +} + +TfLiteStatus SimpleStatefulOp::Prepare(TfLiteContext* context, + TfLiteNode* node) { + OpData* data = reinterpret_cast(node->user_data); + + // Make sure that the input is in uint8_t with at least 1 data entry. + MicroContext* micro_context = GetMicroContext(context); + TfLiteTensor* input = + micro_context->AllocateTempInputTensor(node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + + if (input->type != kTfLiteInt8) return kTfLiteError; + if (NumElements(input->dims) == 0) return kTfLiteError; + + // Allocate a temporary buffer with the same size of input for sorting. + TF_LITE_ENSURE_STATUS(context->RequestScratchBufferInArena( + context, sizeof(uint8_t) * NumElements(input->dims), + &data->sorting_buffer)); + // We can interleave scratch / persistent buffer allocation. + data->invoke_count = reinterpret_cast( + context->AllocatePersistentBuffer(context, sizeof(int))); + *data->invoke_count = 0; + + micro_context->DeallocateTempTfLiteTensor(input); + return kTfLiteOk; +} + +TfLiteStatus SimpleStatefulOp::Invoke(TfLiteContext* context, + TfLiteNode* node) { + OpData* data = reinterpret_cast(node->user_data); + *data->invoke_count += 1; + + const TfLiteEvalTensor* input = + tflite::micro::GetEvalInput(context, node, kInputTensor); + TF_LITE_ENSURE(context, input != nullptr); + const uint8_t* input_data = input->data.uint8; + int size = NumElements(input->dims); + + uint8_t* sorting_buffer = reinterpret_cast( + context->GetScratchBuffer(context, data->sorting_buffer)); + // Copy inputs data to the sorting buffer. We don't want to mutate the input + // tensor as it might be used by a another node. + for (int i = 0; i < size; i++) { + sorting_buffer[i] = input_data[i]; + } + + // In place insertion sort on `sorting_buffer`. + for (int i = 1; i < size; i++) { + for (int j = i; j > 0 && sorting_buffer[j] < sorting_buffer[j - 1]; j--) { + std::swap(sorting_buffer[j], sorting_buffer[j - 1]); + } + } + + TfLiteEvalTensor* median = + tflite::micro::GetEvalOutput(context, node, kMedianTensor); + TF_LITE_ENSURE(context, median != nullptr); + uint8_t* median_data = median->data.uint8; + TfLiteEvalTensor* invoke_count = + tflite::micro::GetEvalOutput(context, node, kInvokeCount); + TF_LITE_ENSURE(context, invoke_count != nullptr); + int32_t* invoke_count_data = invoke_count->data.i32; + + median_data[0] = sorting_buffer[size / 2]; + invoke_count_data[0] = *data->invoke_count; + return kTfLiteOk; +} + +const TfLiteRegistration* MockCustom::getRegistration() { + return GetMutableRegistration(); +} + +TfLiteRegistration* MockCustom::GetMutableRegistration() { + static TfLiteRegistration r; + r.init = Init; + r.prepare = Prepare; + r.invoke = Invoke; + r.free = Free; + return &r; +} + +void* MockCustom::Init(TfLiteContext* context, const char* buffer, + size_t length) { + // We don't support delegate in TFL micro. This is a weak check to test if + // context struct being zero-initialized. + TFLITE_DCHECK(context->ReplaceNodeSubsetsWithDelegateKernels == nullptr); + freed_ = false; + // Do nothing. + return nullptr; +} + +void MockCustom::Free(TfLiteContext* context, void* buffer) { freed_ = true; } + +TfLiteStatus MockCustom::Prepare(TfLiteContext* context, TfLiteNode* node) { + return kTfLiteOk; +} + +TfLiteStatus MockCustom::Invoke(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + TF_LITE_ENSURE(context, input != nullptr); + const int32_t* input_data = input->data.i32; + const TfLiteEvalTensor* weight = + tflite::micro::GetEvalInput(context, node, 1); + TF_LITE_ENSURE(context, weight != nullptr); + const uint8_t* weight_data = weight->data.uint8; + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TF_LITE_ENSURE(context, output != nullptr); + int32_t* output_data = output->data.i32; + output_data[0] = + 0; // Catch output tensor sharing memory with an input tensor + output_data[0] = input_data[0] + weight_data[0]; + return kTfLiteOk; +} + +bool MockCustom::freed_ = false; + +const TfLiteRegistration* MultipleInputs::getRegistration() { + return GetMutableRegistration(); +} + +TfLiteRegistration* MultipleInputs::GetMutableRegistration() { + static TfLiteRegistration r; + r.init = Init; + r.prepare = Prepare; + r.invoke = Invoke; + r.free = Free; + return &r; +} + +void* MultipleInputs::Init(TfLiteContext* context, const char* buffer, + size_t length) { + // We don't support delegate in TFL micro. This is a weak check to test if + // context struct being zero-initialized. + TFLITE_DCHECK(context->ReplaceNodeSubsetsWithDelegateKernels == nullptr); + freed_ = false; + // Do nothing. + return nullptr; +} + +void MultipleInputs::Free(TfLiteContext* context, void* buffer) { + freed_ = true; +} + +TfLiteStatus MultipleInputs::Prepare(TfLiteContext* context, TfLiteNode* node) { + return kTfLiteOk; +} + +TfLiteStatus MultipleInputs::Invoke(TfLiteContext* context, TfLiteNode* node) { + const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); + TF_LITE_ENSURE(context, input != nullptr); + const int32_t* input_data = input->data.i32; + const TfLiteEvalTensor* input1 = + tflite::micro::GetEvalInput(context, node, 1); + TF_LITE_ENSURE(context, input1 != nullptr); + const int32_t* input_data1 = input1->data.i32; + const TfLiteEvalTensor* input2 = + tflite::micro::GetEvalInput(context, node, 2); + TF_LITE_ENSURE(context, input2 != nullptr); + const int32_t* input_data2 = input2->data.i32; + + TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); + TF_LITE_ENSURE(context, output != nullptr); + int32_t* output_data = output->data.i32; + output_data[0] = + 0; // Catch output tensor sharing memory with an input tensor + output_data[0] = input_data[0] + input_data1[0] + input_data2[0]; + return kTfLiteOk; +} + +bool MultipleInputs::freed_ = false; + +const TfLiteRegistration* NoOp::getRegistration() { + return GetMutableRegistration(); +} + +TfLiteRegistration* NoOp::GetMutableRegistration() { + static TfLiteRegistration r; + r.init = Init; + r.prepare = Prepare; + r.invoke = Invoke; + r.free = Free; + return &r; +} + +void* NoOp::Init(TfLiteContext* context, const char* buffer, size_t length) { + // We don't support delegate in TFL micro. This is a weak check to test if + // context struct being zero-initialized. + TFLITE_DCHECK(context->ReplaceNodeSubsetsWithDelegateKernels == nullptr); + freed_ = false; + // Do nothing. + return nullptr; +} + +void NoOp::Free(TfLiteContext* context, void* buffer) { freed_ = true; } + +TfLiteStatus NoOp::Prepare(TfLiteContext* context, TfLiteNode* node) { + return kTfLiteOk; +} + +TfLiteStatus NoOp::Invoke(TfLiteContext* context, TfLiteNode* node) { + return kTfLiteOk; +} + +bool NoOp::freed_ = false; + +AllOpsResolver GetOpResolver() { + AllOpsResolver op_resolver; + op_resolver.AddCustom("mock_custom", MockCustom::GetMutableRegistration()); + op_resolver.AddCustom("simple_stateful_op", + SimpleStatefulOp::GetMutableRegistration()); + op_resolver.AddCustom("multiple_inputs_op", + MultipleInputs::GetMutableRegistration()); + op_resolver.AddCustom("no_op", NoOp::GetMutableRegistration()); + op_resolver.AddCustom("custom_packer_op", PackerOp::GetMutableRegistration()); + return op_resolver; +} + +const Model* GetModelWithUnusedInputs() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildModelWithUnusedInputs()); + } + return model; +} + +const Model* GetModelWithUnusedOperatorOutputs() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildModelWithUnusedOperatorOutputs()); + } + return model; +} + +const Model* GetModelWith256x256Tensor() { + static const Model* model = BuildModelWith256x256Tensor(); + return model; +} + +const Model* GetSimpleMockModel() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildSimpleMockModel()); + } + return model; +} + +const Model* GetSimpleMultipleInputsModel() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildSimpleMultipleInputsModel()); + } + return model; +} + +const Model* GetSimpleModelWithSubgraphsAndIf() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildSimpleModelWithSubgraphsAndIf()); + } + return model; +} + +const Model* GetSimpleModelWithSubgraphsAndWhile() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildSimpleModelWithSubgraphsAndWhile()); + } + return model; +} + +const Model* GetModelWithIfAndSubgraphInputTensorOverlap() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildModelWithIfAndSubgraphInputTensorOverlap()); + } + return model; +} + +const Model* GetSimpleModelWithNullInputsAndOutputs() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildSimpleMockModelWithNullInputsOutputs()); + } + return model; +} + +const Model* GetComplexMockModel() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildComplexMockModel()); + } + return model; +} + +const Model* GetSimpleModelWithBranch() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildSimpleModelWithBranch()); + } + return model; +} + +const Model* GetModelWithOfflinePlanning(int num_tensors, + const int32_t* metadata_buffer, + NodeConnection* node_conn, + int num_conns, + int num_subgraph_inputs) { + const Model* model = BuildModelWithOfflinePlanning( + num_tensors, metadata_buffer, node_conn, num_conns, num_subgraph_inputs); + return model; +} + +const Model* GetSimpleStatefulModel() { + static Model* model = nullptr; + if (!model) { + model = const_cast(BuildSimpleStatefulModel()); + } + return model; +} + +const Tensor* Create1dFlatbufferTensor(int size, bool is_variable) { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + constexpr size_t tensor_shape_size = 1; + const int32_t tensor_shape[tensor_shape_size] = {size}; + const Offset tensor_offset = CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, builder->CreateString("test_tensor"), 0, + is_variable); + builder->Finish(tensor_offset); + void* tensor_pointer = builder->GetBufferPointer(); + const Tensor* tensor = flatbuffers::GetRoot(tensor_pointer); + return tensor; +} + +const Tensor* CreateQuantizedFlatbufferTensor(int size) { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + constexpr size_t quant_params_size = 1; + const float min_array[quant_params_size] = {0.1f}; + const float max_array[quant_params_size] = {0.2f}; + const float scale_array[quant_params_size] = {0.3f}; + const int64_t zero_point_array[quant_params_size] = {100ll}; + + const Offset quant_params = + CreateQuantizationParameters( + *builder, + /*min=*/builder->CreateVector(min_array, quant_params_size), + /*max=*/builder->CreateVector(max_array, quant_params_size), + /*scale=*/ + builder->CreateVector(scale_array, quant_params_size), + /*zero_point=*/ + builder->CreateVector(zero_point_array, quant_params_size)); + + constexpr size_t tensor_shape_size = 1; + const int32_t tensor_shape[tensor_shape_size] = {size}; + const Offset tensor_offset = CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, builder->CreateString("test_tensor"), quant_params, + false); + builder->Finish(tensor_offset); + void* tensor_pointer = builder->GetBufferPointer(); + const Tensor* tensor = flatbuffers::GetRoot(tensor_pointer); + return tensor; +} + +const Tensor* CreateMissingQuantizationFlatbufferTensor(int size) { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + const Offset quant_params = + CreateQuantizationParameters(*builder, 0, 0, 0, 0, + QuantizationDetails_NONE, 0, 0); + constexpr size_t tensor_shape_size = 1; + const int32_t tensor_shape[tensor_shape_size] = {size}; + const Offset tensor_offset = CreateTensor( + *builder, builder->CreateVector(tensor_shape, tensor_shape_size), + TensorType_INT32, 0, builder->CreateString("test_tensor"), quant_params, + false); + builder->Finish(tensor_offset); + void* tensor_pointer = builder->GetBufferPointer(); + const Tensor* tensor = flatbuffers::GetRoot(tensor_pointer); + return tensor; +} + +const flatbuffers::Vector>* +CreateFlatbufferBuffers() { + using flatbuffers::Offset; + flatbuffers::FlatBufferBuilder* builder = BuilderInstance(); + constexpr size_t buffers_size = 1; + const Offset buffers[buffers_size] = { + CreateBuffer(*builder), + }; + const flatbuffers::Offset>> + buffers_offset = builder->CreateVector(buffers, buffers_size); + builder->Finish(buffers_offset); + void* buffers_pointer = builder->GetBufferPointer(); + const flatbuffers::Vector>* result = + flatbuffers::GetRoot>>( + buffers_pointer); + return result; +} + +int TestStrcmp(const char* a, const char* b) { + if ((a == nullptr) || (b == nullptr)) { + return -1; + } + while ((*a != 0) && (*a == *b)) { + a++; + b++; + } + return *reinterpret_cast(a) - + *reinterpret_cast(b); +} + +// Wrapper to forward kernel errors to the interpreter's error reporter. +void ReportOpError(struct TfLiteContext* context, const char* format, ...) { +#ifndef TF_LITE_STRIP_ERROR_STRINGS + ErrorReporter* error_reporter = static_cast(context->impl_); + va_list args; + va_start(args, format); + TF_LITE_REPORT_ERROR(error_reporter, format, args); + va_end(args); +#endif +} + +// Create a TfLiteIntArray from an array of ints. The first element in the +// supplied array must be the size of the array expressed as an int. +TfLiteIntArray* IntArrayFromInts(int* int_array) { + return reinterpret_cast(int_array); +} + +// Create a TfLiteFloatArray from an array of floats. The first element in the +// supplied array must be the size of the array expressed as a float. +TfLiteFloatArray* FloatArrayFromFloats(const float* floats) { + static_assert(sizeof(float) == sizeof(int), + "assumes sizeof(float) == sizeof(int) to perform casting"); + int size = static_cast(floats[0]); + *reinterpret_cast(const_cast(floats)) = size; + return reinterpret_cast(const_cast(floats)); +} + +TfLiteTensor CreateQuantizedBiasTensor(const float* data, int16_t* quantized, + TfLiteIntArray* dims, float input_scale, + float weights_scale, bool is_variable) { + float bias_scale = input_scale * weights_scale; + tflite::SymmetricQuantize(data, quantized, ElementCount(*dims), bias_scale); + + // Quantized int16_t tensors always have a zero point of 0, since the range of + // int16_t values is large, and because zero point costs extra cycles during + // processing. + TfLiteTensor result = + CreateQuantizedTensor(quantized, dims, bias_scale, 0, is_variable); + return result; +} + +TfLiteTensor CreateQuantizedBiasTensor(const float* data, int32_t* quantized, + TfLiteIntArray* dims, float input_scale, + float weights_scale, bool is_variable) { + float bias_scale = input_scale * weights_scale; + tflite::SymmetricQuantize(data, quantized, ElementCount(*dims), bias_scale); + + // Quantized int32_t tensors always have a zero point of 0, since the range of + // int32_t values is large, and because zero point costs extra cycles during + // processing. + TfLiteTensor result = + CreateQuantizedTensor(quantized, dims, bias_scale, 0, is_variable); + return result; +} + +TfLiteTensor CreateQuantizedBiasTensor(const float* data, + std::int64_t* quantized, + TfLiteIntArray* dims, float input_scale, + float weights_scale, bool is_variable) { + float bias_scale = input_scale * weights_scale; + tflite::SymmetricQuantize(data, quantized, ElementCount(*dims), bias_scale); + + // Quantized int32_t tensors always have a zero point of 0, since the range of + // int32_t values is large, and because zero point costs extra cycles during + // processing. + TfLiteTensor result = + CreateQuantizedTensor(quantized, dims, bias_scale, 0, is_variable); + return result; +} + +// Quantizes int32_t bias tensor with per-channel weights determined by input +// scale multiplied by weight scale for each channel. +template +TfLiteTensor CreatePerChannelQuantizedBiasTensor( + const float* input, T* quantized, TfLiteIntArray* dims, float input_scale, + float* weight_scales, float* scales, int* zero_points, + TfLiteAffineQuantization* affine_quant, int quantized_dimension, + bool is_variable) { + int input_size = ElementCount(*dims); + int num_channels = dims->data[quantized_dimension]; + // First element is reserved for array length + zero_points[0] = num_channels; + scales[0] = static_cast(num_channels); + float* scales_array = &scales[1]; + for (int i = 0; i < num_channels; i++) { + scales_array[i] = input_scale * weight_scales[i]; + zero_points[i + 1] = 0; + } + + SymmetricPerChannelQuantize(input, quantized, input_size, num_channels, + scales_array); + + affine_quant->scale = FloatArrayFromFloats(scales); + affine_quant->zero_point = IntArrayFromInts(zero_points); + affine_quant->quantized_dimension = quantized_dimension; + + TfLiteTensor result = CreateTensor(quantized, dims, is_variable); + result.quantization = {kTfLiteAffineQuantization, affine_quant}; + return result; +} + +TfLiteTensor CreatePerChannelQuantizedBiasTensor( + const float* input, int32_t* quantized, TfLiteIntArray* dims, + float input_scale, float* weight_scales, float* scales, int* zero_points, + TfLiteAffineQuantization* affine_quant, int quantized_dimension, + bool is_variable) { + return CreatePerChannelQuantizedBiasTensor( + input, quantized, dims, input_scale, weight_scales, scales, zero_points, + affine_quant, quantized_dimension, is_variable); +} + +TfLiteTensor CreatePerChannelQuantizedBiasTensor( + const float* input, std::int64_t* quantized, TfLiteIntArray* dims, + float input_scale, float* weight_scales, float* scales, int* zero_points, + TfLiteAffineQuantization* affine_quant, int quantized_dimension, + bool is_variable) { + return CreatePerChannelQuantizedBiasTensor( + input, quantized, dims, input_scale, weight_scales, scales, zero_points, + affine_quant, quantized_dimension, is_variable); +} + +TfLiteTensor CreateSymmetricPerChannelQuantizedTensor( + const float* input, int8_t* quantized, TfLiteIntArray* dims, float* scales, + int* zero_points, TfLiteAffineQuantization* affine_quant, + int quantized_dimension, bool is_variable) { + int channel_count = dims->data[quantized_dimension]; + scales[0] = static_cast(channel_count); + zero_points[0] = channel_count; + + SignedSymmetricPerChannelQuantize(input, dims, quantized_dimension, quantized, + &scales[1]); + + for (int i = 0; i < channel_count; i++) { + zero_points[i + 1] = 0; + } + + affine_quant->scale = FloatArrayFromFloats(scales); + affine_quant->zero_point = IntArrayFromInts(zero_points); + affine_quant->quantized_dimension = quantized_dimension; + + TfLiteTensor result = CreateTensor(quantized, dims, is_variable); + result.quantization = {kTfLiteAffineQuantization, affine_quant}; + return result; +} + +size_t GetModelTensorCount(const Model* model) { + auto* subgraphs = model->subgraphs(); + if (subgraphs) { + return (*subgraphs)[0]->tensors()->size(); + } + return 0; +} + +} // namespace testing +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helpers.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helpers.h new file mode 100644 index 000000000..459d3f265 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/micro/test_helpers.h @@ -0,0 +1,298 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_MICRO_TEST_HELPERS_H_ +#define TENSORFLOW_LITE_MICRO_TEST_HELPERS_H_ + +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/c/common.h" +#include "tensorflow/lite/kernels/internal/compatibility.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/micro/all_ops_resolver.h" +#include "tensorflow/lite/micro/micro_utils.h" +#include "tensorflow/lite/portable_type_to_tflitetype.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +namespace testing { + +constexpr int kOfflinePlannerHeaderSize = 3; + +struct NodeConnection_ { + std::initializer_list input; + std::initializer_list output; +}; +typedef struct NodeConnection_ NodeConnection; + +// A simple operator that returns the median of the input with the number of +// times the kernel was invoked. The implementation below is deliberately +// complicated, just to demonstrate how kernel memory planning works. +class SimpleStatefulOp { + static constexpr int kBufferNotAllocated = 0; + // Inputs: + static constexpr int kInputTensor = 0; + // Outputs: + static constexpr int kMedianTensor = 0; + static constexpr int kInvokeCount = 1; + struct OpData { + int* invoke_count = nullptr; + int sorting_buffer = kBufferNotAllocated; + }; + + public: + static const TfLiteRegistration* getRegistration(); + static TfLiteRegistration* GetMutableRegistration(); + static void* Init(TfLiteContext* context, const char* buffer, size_t length); + static TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node); + static TfLiteStatus Invoke(TfLiteContext* context, TfLiteNode* node); +}; + +class MockCustom { + public: + static const TfLiteRegistration* getRegistration(); + static TfLiteRegistration* GetMutableRegistration(); + static void* Init(TfLiteContext* context, const char* buffer, size_t length); + static void Free(TfLiteContext* context, void* buffer); + static TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node); + static TfLiteStatus Invoke(TfLiteContext* context, TfLiteNode* node); + + static bool freed_; +}; + +// A simple operator with the purpose of testing multiple inputs. It returns +// the sum of the inputs. +class MultipleInputs { + public: + static const TfLiteRegistration* getRegistration(); + static TfLiteRegistration* GetMutableRegistration(); + static void* Init(TfLiteContext* context, const char* buffer, size_t length); + static void Free(TfLiteContext* context, void* buffer); + static TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node); + static TfLiteStatus Invoke(TfLiteContext* context, TfLiteNode* node); + + static bool freed_; +}; + +// A simple no-op operator. +class NoOp { + public: + static const TfLiteRegistration* getRegistration(); + static TfLiteRegistration* GetMutableRegistration(); + static void* Init(TfLiteContext* context, const char* buffer, size_t length); + static void Free(TfLiteContext* context, void* buffer); + static TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node); + static TfLiteStatus Invoke(TfLiteContext* context, TfLiteNode* node); + + static bool freed_; +}; + +// Returns an Op Resolver that can be used in the testing code. +AllOpsResolver GetOpResolver(); + +// Returns a simple example flatbuffer TensorFlow Lite model. Contains 1 input, +// 1 layer of weights, 1 output Tensor, and 1 operator. +const Model* GetSimpleMockModel(); + +// Returns a flatbuffer TensorFlow Lite model with more inputs, variable +// tensors, and operators. +const Model* GetComplexMockModel(); + +// Returns a simple example flatbuffer TensorFlow Lite model. Contains 1 input, +// 1 layer of weights, 1 output Tensor, and 1 operator. +// The size of all three tensors is 256 x 256, which is larger than what other +// models provide from this test helper. +const Model* GetModelWith256x256Tensor(); + +// Returns a simple flatbuffer model with two branches. +const Model* GetSimpleModelWithBranch(); + +// Returns a simple example flatbuffer TensorFlow Lite model. Contains 3 inputs, +// 1 output Tensor, and 1 operator. +const Model* GetSimpleMultipleInputsModel(); + +// Returns a simple flatbuffer model with offline planned tensors +// @param[in] num_tensors Number of tensors in the model. +// @param[in] metadata_buffer Metadata for offline planner. +// @param[in] node_con List of connections, i.e. operators +// in the model. +// @param[in] num_conns Number of connections. +// @param[in] num_subgraph_inputs How many of the input tensors are in +// the subgraph inputs. The default value +// of 0 means all of the input tensors +// are in the subgraph input list. There +// must be at least 1 input tensor in the +// subgraph input list. +const Model* GetModelWithOfflinePlanning(int num_tensors, + const int32_t* metadata_buffer, + NodeConnection* node_conn, + int num_conns, + int num_subgraph_inputs = 0); + +// Returns a flatbuffer with a single operator, two inputs (one unused) and one +// output. +const Model* GetModelWithUnusedInputs(); + +// Returns a flatbuffer with a single operator, zero inputs and two outputs +// (one unused). +const Model* GetModelWithUnusedOperatorOutputs(); + +// Returns a flatbuffer model with `simple_stateful_op` +const Model* GetSimpleStatefulModel(); + +// Returns a flatbuffer model with "if" and two subgraphs. +const Model* GetSimpleModelWithSubgraphsAndIf(); + +// Returns a flatbuffer model with "while" and three subgraphs. +const Model* GetSimpleModelWithSubgraphsAndWhile(); + +// Returns a flatbuffer model with "if" and two subgraphs and the input tensor 1 +// of "if" subgraph overlaps with the input tensor 2 of subgraph 1. +const Model* GetModelWithIfAndSubgraphInputTensorOverlap(); + +// Returns a flatbuffer model with null subgraph/operator inputs and outputs. +const Model* GetSimpleModelWithNullInputsAndOutputs(); + +// Builds a one-dimensional flatbuffer tensor of the given size. +const Tensor* Create1dFlatbufferTensor(int size, bool is_variable = false); + +// Builds a one-dimensional flatbuffer tensor of the given size with +// quantization metadata. +const Tensor* CreateQuantizedFlatbufferTensor(int size); + +// Creates a one-dimensional tensor with no quantization metadata. +const Tensor* CreateMissingQuantizationFlatbufferTensor(int size); + +// Creates a vector of flatbuffer buffers. +const flatbuffers::Vector>* +CreateFlatbufferBuffers(); + +// Performs a simple string comparison without requiring standard C library. +int TestStrcmp(const char* a, const char* b); + +// Wrapper to forward kernel errors to the interpreter's error reporter. +void ReportOpError(struct TfLiteContext* context, const char* format, ...); + +void PopulateContext(TfLiteTensor* tensors, int tensors_size, + TfLiteContext* context); + +// Create a TfLiteIntArray from an array of ints. The first element in the +// supplied array must be the size of the array expressed as an int. +TfLiteIntArray* IntArrayFromInts(int* int_array); + +// Create a TfLiteFloatArray from an array of floats. The first element in the +// supplied array must be the size of the array expressed as a float. +TfLiteFloatArray* FloatArrayFromFloats(const float* floats); + +template +TfLiteTensor CreateTensor(const T* data, TfLiteIntArray* dims, + const bool is_variable = false) { + TfLiteTensor result; + result.dims = dims; + result.params = {}; + result.quantization = {kTfLiteNoQuantization, nullptr}; + result.is_variable = is_variable; + result.allocation_type = kTfLiteMemNone; + result.type = typeToTfLiteType(); + // Const cast is used to allow passing in const and non-const arrays within a + // single CreateTensor method. A Const array should be used for immutable + // input tensors and non-const array should be used for mutable and output + // tensors. + result.data.data = const_cast(data); + result.quantization = {kTfLiteAffineQuantization, nullptr}; + result.bytes = ElementCount(*dims) * sizeof(T); + return result; +} + +template +TfLiteTensor CreateQuantizedTensor(const T* data, TfLiteIntArray* dims, + const float scale, const int zero_point = 0, + const bool is_variable = false) { + TfLiteTensor result = CreateTensor(data, dims, is_variable); + result.params = {scale, zero_point}; + result.quantization = {kTfLiteAffineQuantization, nullptr}; + return result; +} + +template +TfLiteTensor CreateQuantizedTensor(const float* input, T* quantized, + TfLiteIntArray* dims, float scale, + int zero_point, bool is_variable = false) { + int input_size = ElementCount(*dims); + tflite::Quantize(input, quantized, input_size, scale, zero_point); + return CreateQuantizedTensor(quantized, dims, scale, zero_point, is_variable); +} + +TfLiteTensor CreateQuantizedBiasTensor(const float* data, int16_t* quantized, + TfLiteIntArray* dims, float input_scale, + float weights_scale, + bool is_variable = false); + +TfLiteTensor CreateQuantizedBiasTensor(const float* data, int32_t* quantized, + TfLiteIntArray* dims, float input_scale, + float weights_scale, + bool is_variable = false); + +TfLiteTensor CreateQuantizedBiasTensor(const float* data, + std::int64_t* quantized, + TfLiteIntArray* dims, float input_scale, + float weights_scale, + bool is_variable = false); + +// Quantizes int32_t bias tensor with per-channel weights determined by input +// scale multiplied by weight scale for each channel. +TfLiteTensor CreatePerChannelQuantizedBiasTensor( + const float* input, int32_t* quantized, TfLiteIntArray* dims, + float input_scale, float* weight_scales, float* scales, int* zero_points, + TfLiteAffineQuantization* affine_quant, int quantized_dimension, + bool is_variable = false); + +// Quantizes int64_t bias tensor with per-channel weights determined by input +// scale multiplied by weight scale for each channel. +TfLiteTensor CreatePerChannelQuantizedBiasTensor( + const float* input, std::int64_t* quantized, TfLiteIntArray* dims, + float input_scale, float* weight_scales, float* scales, int* zero_points, + TfLiteAffineQuantization* affine_quant, int quantized_dimension, + bool is_variable = false); + +TfLiteTensor CreateSymmetricPerChannelQuantizedTensor( + const float* input, int8_t* quantized, TfLiteIntArray* dims, float* scales, + int* zero_points, TfLiteAffineQuantization* affine_quant, + int quantized_dimension, bool is_variable = false); + +// Returns the number of tensors in the default subgraph for a tflite::Model. +size_t GetModelTensorCount(const Model* model); + +// Derives the quantization scaling factor from a min and max range. +template +inline float ScaleFromMinMax(const float min, const float max) { + return (max - min) / + static_cast((std::numeric_limits::max() * 1.0) - + std::numeric_limits::min()); +} + +// Derives the quantization zero point from a min and max range. +template +inline int ZeroPointFromMinMax(const float min, const float max) { + return static_cast(std::numeric_limits::min()) + + static_cast(-min / ScaleFromMinMax(min, max) + 0.5f); +} + +} // namespace testing +} // namespace tflite + +#endif // TENSORFLOW_LITE_MICRO_TEST_HELPERS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/portable_type_to_tflitetype.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/portable_type_to_tflitetype.h new file mode 100644 index 000000000..52d7fdefe --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/portable_type_to_tflitetype.h @@ -0,0 +1,75 @@ +/* Copyright 2019 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_PORTABLE_TYPE_TO_TFLITETYPE_H_ +#define TENSORFLOW_LITE_PORTABLE_TYPE_TO_TFLITETYPE_H_ + +// Most of the definitions have been moved to this subheader so that Micro +// can include it without relying on and , which isn't +// available on all platforms. + +// Arduino build defines abs as a macro here. That is invalid C++, and breaks +// libc++'s header, undefine it. +#ifdef abs +#undef abs +#endif + +#include + +#include "tensorflow/lite/c/common.h" + +namespace tflite { + +// Map statically from a C++ type to a TfLiteType. Used in interpreter for +// safe casts. +// Example: +// typeToTfLiteType() -> kTfLiteBool +template +constexpr TfLiteType typeToTfLiteType() { + return kTfLiteNoType; +} +// Map from TfLiteType to the corresponding C++ type. +// Example: +// TfLiteTypeToType::Type -> bool +template +struct TfLiteTypeToType {}; // Specializations below + +// Template specialization for both typeToTfLiteType and TfLiteTypeToType. +#define MATCH_TYPE_AND_TFLITE_TYPE(CPP_TYPE, TFLITE_TYPE_ENUM) \ + template <> \ + constexpr TfLiteType typeToTfLiteType() { \ + return TFLITE_TYPE_ENUM; \ + } \ + template <> \ + struct TfLiteTypeToType { \ + using Type = CPP_TYPE; \ + } + +// No string mapping is included here, since the TF Lite packed representation +// doesn't correspond to a C++ type well. +MATCH_TYPE_AND_TFLITE_TYPE(int32_t, kTfLiteInt32); +MATCH_TYPE_AND_TFLITE_TYPE(uint32_t, kTfLiteUInt32); +MATCH_TYPE_AND_TFLITE_TYPE(int16_t, kTfLiteInt16); +MATCH_TYPE_AND_TFLITE_TYPE(uint16_t, kTfLiteUInt16); +MATCH_TYPE_AND_TFLITE_TYPE(int64_t, kTfLiteInt64); +MATCH_TYPE_AND_TFLITE_TYPE(float, kTfLiteFloat32); +MATCH_TYPE_AND_TFLITE_TYPE(unsigned char, kTfLiteUInt8); +MATCH_TYPE_AND_TFLITE_TYPE(int8_t, kTfLiteInt8); +MATCH_TYPE_AND_TFLITE_TYPE(bool, kTfLiteBool); +MATCH_TYPE_AND_TFLITE_TYPE(TfLiteFloat16, kTfLiteFloat16); +MATCH_TYPE_AND_TFLITE_TYPE(double, kTfLiteFloat64); +MATCH_TYPE_AND_TFLITE_TYPE(uint64_t, kTfLiteUInt64); + +} // namespace tflite +#endif // TENSORFLOW_LITE_PORTABLE_TYPE_TO_TFLITETYPE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_generated.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_generated.h new file mode 100644 index 000000000..43aaba396 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_generated.h @@ -0,0 +1,20139 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_SCHEMA_TFLITE_H_ +#define FLATBUFFERS_GENERATED_SCHEMA_TFLITE_H_ + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 2 && + FLATBUFFERS_VERSION_MINOR == 0 && + FLATBUFFERS_VERSION_REVISION == 6, + "Non-compatible flatbuffers version included"); + +namespace tflite { + +struct CustomQuantization; +struct CustomQuantizationBuilder; +struct CustomQuantizationT; + +struct QuantizationParameters; +struct QuantizationParametersBuilder; +struct QuantizationParametersT; + +struct Int32Vector; +struct Int32VectorBuilder; +struct Int32VectorT; + +struct Uint16Vector; +struct Uint16VectorBuilder; +struct Uint16VectorT; + +struct Uint8Vector; +struct Uint8VectorBuilder; +struct Uint8VectorT; + +struct DimensionMetadata; +struct DimensionMetadataBuilder; +struct DimensionMetadataT; + +struct SparsityParameters; +struct SparsityParametersBuilder; +struct SparsityParametersT; + +struct VariantSubType; +struct VariantSubTypeBuilder; +struct VariantSubTypeT; + +struct Tensor; +struct TensorBuilder; +struct TensorT; + +struct Conv2DOptions; +struct Conv2DOptionsBuilder; +struct Conv2DOptionsT; + +struct Conv3DOptions; +struct Conv3DOptionsBuilder; +struct Conv3DOptionsT; + +struct Pool2DOptions; +struct Pool2DOptionsBuilder; +struct Pool2DOptionsT; + +struct DepthwiseConv2DOptions; +struct DepthwiseConv2DOptionsBuilder; +struct DepthwiseConv2DOptionsT; + +struct ConcatEmbeddingsOptions; +struct ConcatEmbeddingsOptionsBuilder; +struct ConcatEmbeddingsOptionsT; + +struct LSHProjectionOptions; +struct LSHProjectionOptionsBuilder; +struct LSHProjectionOptionsT; + +struct SVDFOptions; +struct SVDFOptionsBuilder; +struct SVDFOptionsT; + +struct RNNOptions; +struct RNNOptionsBuilder; +struct RNNOptionsT; + +struct SequenceRNNOptions; +struct SequenceRNNOptionsBuilder; +struct SequenceRNNOptionsT; + +struct BidirectionalSequenceRNNOptions; +struct BidirectionalSequenceRNNOptionsBuilder; +struct BidirectionalSequenceRNNOptionsT; + +struct FullyConnectedOptions; +struct FullyConnectedOptionsBuilder; +struct FullyConnectedOptionsT; + +struct SoftmaxOptions; +struct SoftmaxOptionsBuilder; +struct SoftmaxOptionsT; + +struct ConcatenationOptions; +struct ConcatenationOptionsBuilder; +struct ConcatenationOptionsT; + +struct AddOptions; +struct AddOptionsBuilder; +struct AddOptionsT; + +struct MulOptions; +struct MulOptionsBuilder; +struct MulOptionsT; + +struct L2NormOptions; +struct L2NormOptionsBuilder; +struct L2NormOptionsT; + +struct LocalResponseNormalizationOptions; +struct LocalResponseNormalizationOptionsBuilder; +struct LocalResponseNormalizationOptionsT; + +struct LSTMOptions; +struct LSTMOptionsBuilder; +struct LSTMOptionsT; + +struct UnidirectionalSequenceLSTMOptions; +struct UnidirectionalSequenceLSTMOptionsBuilder; +struct UnidirectionalSequenceLSTMOptionsT; + +struct BidirectionalSequenceLSTMOptions; +struct BidirectionalSequenceLSTMOptionsBuilder; +struct BidirectionalSequenceLSTMOptionsT; + +struct ResizeBilinearOptions; +struct ResizeBilinearOptionsBuilder; +struct ResizeBilinearOptionsT; + +struct ResizeNearestNeighborOptions; +struct ResizeNearestNeighborOptionsBuilder; +struct ResizeNearestNeighborOptionsT; + +struct CallOptions; +struct CallOptionsBuilder; +struct CallOptionsT; + +struct PadOptions; +struct PadOptionsBuilder; +struct PadOptionsT; + +struct PadV2Options; +struct PadV2OptionsBuilder; +struct PadV2OptionsT; + +struct ReshapeOptions; +struct ReshapeOptionsBuilder; +struct ReshapeOptionsT; + +struct SpaceToBatchNDOptions; +struct SpaceToBatchNDOptionsBuilder; +struct SpaceToBatchNDOptionsT; + +struct BatchToSpaceNDOptions; +struct BatchToSpaceNDOptionsBuilder; +struct BatchToSpaceNDOptionsT; + +struct SkipGramOptions; +struct SkipGramOptionsBuilder; +struct SkipGramOptionsT; + +struct SpaceToDepthOptions; +struct SpaceToDepthOptionsBuilder; +struct SpaceToDepthOptionsT; + +struct DepthToSpaceOptions; +struct DepthToSpaceOptionsBuilder; +struct DepthToSpaceOptionsT; + +struct SubOptions; +struct SubOptionsBuilder; +struct SubOptionsT; + +struct DivOptions; +struct DivOptionsBuilder; +struct DivOptionsT; + +struct TopKV2Options; +struct TopKV2OptionsBuilder; +struct TopKV2OptionsT; + +struct EmbeddingLookupSparseOptions; +struct EmbeddingLookupSparseOptionsBuilder; +struct EmbeddingLookupSparseOptionsT; + +struct GatherOptions; +struct GatherOptionsBuilder; +struct GatherOptionsT; + +struct TransposeOptions; +struct TransposeOptionsBuilder; +struct TransposeOptionsT; + +struct ExpOptions; +struct ExpOptionsBuilder; +struct ExpOptionsT; + +struct CosOptions; +struct CosOptionsBuilder; +struct CosOptionsT; + +struct ReducerOptions; +struct ReducerOptionsBuilder; +struct ReducerOptionsT; + +struct SqueezeOptions; +struct SqueezeOptionsBuilder; +struct SqueezeOptionsT; + +struct SplitOptions; +struct SplitOptionsBuilder; +struct SplitOptionsT; + +struct SplitVOptions; +struct SplitVOptionsBuilder; +struct SplitVOptionsT; + +struct StridedSliceOptions; +struct StridedSliceOptionsBuilder; +struct StridedSliceOptionsT; + +struct LogSoftmaxOptions; +struct LogSoftmaxOptionsBuilder; +struct LogSoftmaxOptionsT; + +struct CastOptions; +struct CastOptionsBuilder; +struct CastOptionsT; + +struct DequantizeOptions; +struct DequantizeOptionsBuilder; +struct DequantizeOptionsT; + +struct MaximumMinimumOptions; +struct MaximumMinimumOptionsBuilder; +struct MaximumMinimumOptionsT; + +struct TileOptions; +struct TileOptionsBuilder; +struct TileOptionsT; + +struct ArgMaxOptions; +struct ArgMaxOptionsBuilder; +struct ArgMaxOptionsT; + +struct ArgMinOptions; +struct ArgMinOptionsBuilder; +struct ArgMinOptionsT; + +struct GreaterOptions; +struct GreaterOptionsBuilder; +struct GreaterOptionsT; + +struct GreaterEqualOptions; +struct GreaterEqualOptionsBuilder; +struct GreaterEqualOptionsT; + +struct LessOptions; +struct LessOptionsBuilder; +struct LessOptionsT; + +struct LessEqualOptions; +struct LessEqualOptionsBuilder; +struct LessEqualOptionsT; + +struct NegOptions; +struct NegOptionsBuilder; +struct NegOptionsT; + +struct SelectOptions; +struct SelectOptionsBuilder; +struct SelectOptionsT; + +struct SliceOptions; +struct SliceOptionsBuilder; +struct SliceOptionsT; + +struct TransposeConvOptions; +struct TransposeConvOptionsBuilder; +struct TransposeConvOptionsT; + +struct ExpandDimsOptions; +struct ExpandDimsOptionsBuilder; +struct ExpandDimsOptionsT; + +struct SparseToDenseOptions; +struct SparseToDenseOptionsBuilder; +struct SparseToDenseOptionsT; + +struct EqualOptions; +struct EqualOptionsBuilder; +struct EqualOptionsT; + +struct NotEqualOptions; +struct NotEqualOptionsBuilder; +struct NotEqualOptionsT; + +struct ShapeOptions; +struct ShapeOptionsBuilder; +struct ShapeOptionsT; + +struct RankOptions; +struct RankOptionsBuilder; +struct RankOptionsT; + +struct PowOptions; +struct PowOptionsBuilder; +struct PowOptionsT; + +struct FakeQuantOptions; +struct FakeQuantOptionsBuilder; +struct FakeQuantOptionsT; + +struct PackOptions; +struct PackOptionsBuilder; +struct PackOptionsT; + +struct LogicalOrOptions; +struct LogicalOrOptionsBuilder; +struct LogicalOrOptionsT; + +struct OneHotOptions; +struct OneHotOptionsBuilder; +struct OneHotOptionsT; + +struct AbsOptions; +struct AbsOptionsBuilder; +struct AbsOptionsT; + +struct HardSwishOptions; +struct HardSwishOptionsBuilder; +struct HardSwishOptionsT; + +struct LogicalAndOptions; +struct LogicalAndOptionsBuilder; +struct LogicalAndOptionsT; + +struct LogicalNotOptions; +struct LogicalNotOptionsBuilder; +struct LogicalNotOptionsT; + +struct UnpackOptions; +struct UnpackOptionsBuilder; +struct UnpackOptionsT; + +struct FloorDivOptions; +struct FloorDivOptionsBuilder; +struct FloorDivOptionsT; + +struct SquareOptions; +struct SquareOptionsBuilder; +struct SquareOptionsT; + +struct ZerosLikeOptions; +struct ZerosLikeOptionsBuilder; +struct ZerosLikeOptionsT; + +struct FillOptions; +struct FillOptionsBuilder; +struct FillOptionsT; + +struct FloorModOptions; +struct FloorModOptionsBuilder; +struct FloorModOptionsT; + +struct RangeOptions; +struct RangeOptionsBuilder; +struct RangeOptionsT; + +struct LeakyReluOptions; +struct LeakyReluOptionsBuilder; +struct LeakyReluOptionsT; + +struct SquaredDifferenceOptions; +struct SquaredDifferenceOptionsBuilder; +struct SquaredDifferenceOptionsT; + +struct MirrorPadOptions; +struct MirrorPadOptionsBuilder; +struct MirrorPadOptionsT; + +struct UniqueOptions; +struct UniqueOptionsBuilder; +struct UniqueOptionsT; + +struct ReverseV2Options; +struct ReverseV2OptionsBuilder; +struct ReverseV2OptionsT; + +struct AddNOptions; +struct AddNOptionsBuilder; +struct AddNOptionsT; + +struct GatherNdOptions; +struct GatherNdOptionsBuilder; +struct GatherNdOptionsT; + +struct WhereOptions; +struct WhereOptionsBuilder; +struct WhereOptionsT; + +struct ReverseSequenceOptions; +struct ReverseSequenceOptionsBuilder; +struct ReverseSequenceOptionsT; + +struct MatrixDiagOptions; +struct MatrixDiagOptionsBuilder; +struct MatrixDiagOptionsT; + +struct QuantizeOptions; +struct QuantizeOptionsBuilder; +struct QuantizeOptionsT; + +struct MatrixSetDiagOptions; +struct MatrixSetDiagOptionsBuilder; +struct MatrixSetDiagOptionsT; + +struct IfOptions; +struct IfOptionsBuilder; +struct IfOptionsT; + +struct CallOnceOptions; +struct CallOnceOptionsBuilder; +struct CallOnceOptionsT; + +struct WhileOptions; +struct WhileOptionsBuilder; +struct WhileOptionsT; + +struct NonMaxSuppressionV4Options; +struct NonMaxSuppressionV4OptionsBuilder; +struct NonMaxSuppressionV4OptionsT; + +struct NonMaxSuppressionV5Options; +struct NonMaxSuppressionV5OptionsBuilder; +struct NonMaxSuppressionV5OptionsT; + +struct ScatterNdOptions; +struct ScatterNdOptionsBuilder; +struct ScatterNdOptionsT; + +struct SelectV2Options; +struct SelectV2OptionsBuilder; +struct SelectV2OptionsT; + +struct DensifyOptions; +struct DensifyOptionsBuilder; +struct DensifyOptionsT; + +struct SegmentSumOptions; +struct SegmentSumOptionsBuilder; +struct SegmentSumOptionsT; + +struct BatchMatMulOptions; +struct BatchMatMulOptionsBuilder; +struct BatchMatMulOptionsT; + +struct CumsumOptions; +struct CumsumOptionsBuilder; +struct CumsumOptionsT; + +struct BroadcastToOptions; +struct BroadcastToOptionsBuilder; +struct BroadcastToOptionsT; + +struct Rfft2dOptions; +struct Rfft2dOptionsBuilder; +struct Rfft2dOptionsT; + +struct HashtableOptions; +struct HashtableOptionsBuilder; +struct HashtableOptionsT; + +struct HashtableFindOptions; +struct HashtableFindOptionsBuilder; +struct HashtableFindOptionsT; + +struct HashtableImportOptions; +struct HashtableImportOptionsBuilder; +struct HashtableImportOptionsT; + +struct HashtableSizeOptions; +struct HashtableSizeOptionsBuilder; +struct HashtableSizeOptionsT; + +struct VarHandleOptions; +struct VarHandleOptionsBuilder; +struct VarHandleOptionsT; + +struct ReadVariableOptions; +struct ReadVariableOptionsBuilder; +struct ReadVariableOptionsT; + +struct AssignVariableOptions; +struct AssignVariableOptionsBuilder; +struct AssignVariableOptionsT; + +struct RandomOptions; +struct RandomOptionsBuilder; +struct RandomOptionsT; + +struct BucketizeOptions; +struct BucketizeOptionsBuilder; +struct BucketizeOptionsT; + +struct GeluOptions; +struct GeluOptionsBuilder; +struct GeluOptionsT; + +struct DynamicUpdateSliceOptions; +struct DynamicUpdateSliceOptionsBuilder; +struct DynamicUpdateSliceOptionsT; + +struct UnsortedSegmentProdOptions; +struct UnsortedSegmentProdOptionsBuilder; +struct UnsortedSegmentProdOptionsT; + +struct UnsortedSegmentMaxOptions; +struct UnsortedSegmentMaxOptionsBuilder; +struct UnsortedSegmentMaxOptionsT; + +struct UnsortedSegmentSumOptions; +struct UnsortedSegmentSumOptionsBuilder; +struct UnsortedSegmentSumOptionsT; + +struct ATan2Options; +struct ATan2OptionsBuilder; +struct ATan2OptionsT; + +struct UnsortedSegmentMinOptions; +struct UnsortedSegmentMinOptionsBuilder; +struct UnsortedSegmentMinOptionsT; + +struct SignOptions; +struct SignOptionsBuilder; +struct SignOptionsT; + +struct OperatorCode; +struct OperatorCodeBuilder; +struct OperatorCodeT; + +struct Operator; +struct OperatorBuilder; +struct OperatorT; + +struct SubGraph; +struct SubGraphBuilder; +struct SubGraphT; + +struct Buffer; +struct BufferBuilder; +struct BufferT; + +struct Metadata; +struct MetadataBuilder; +struct MetadataT; + +struct TensorMap; +struct TensorMapBuilder; +struct TensorMapT; + +struct SignatureDef; +struct SignatureDefBuilder; +struct SignatureDefT; + +struct Model; +struct ModelBuilder; +struct ModelT; + +enum TensorType : int8_t { + TensorType_FLOAT32 = 0, + TensorType_FLOAT16 = 1, + TensorType_INT32 = 2, + TensorType_UINT8 = 3, + TensorType_INT64 = 4, + TensorType_STRING = 5, + TensorType_BOOL = 6, + TensorType_INT16 = 7, + TensorType_COMPLEX64 = 8, + TensorType_INT8 = 9, + TensorType_FLOAT64 = 10, + TensorType_COMPLEX128 = 11, + TensorType_UINT64 = 12, + TensorType_RESOURCE = 13, + TensorType_VARIANT = 14, + TensorType_UINT32 = 15, + TensorType_UINT16 = 16, + TensorType_INT4 = 17, + TensorType_MIN = TensorType_FLOAT32, + TensorType_MAX = TensorType_INT4 +}; + +inline const TensorType (&EnumValuesTensorType())[18] { + static const TensorType values[] = { + TensorType_FLOAT32, + TensorType_FLOAT16, + TensorType_INT32, + TensorType_UINT8, + TensorType_INT64, + TensorType_STRING, + TensorType_BOOL, + TensorType_INT16, + TensorType_COMPLEX64, + TensorType_INT8, + TensorType_FLOAT64, + TensorType_COMPLEX128, + TensorType_UINT64, + TensorType_RESOURCE, + TensorType_VARIANT, + TensorType_UINT32, + TensorType_UINT16, + TensorType_INT4 + }; + return values; +} + +inline const char * const *EnumNamesTensorType() { + static const char * const names[19] = { + "FLOAT32", + "FLOAT16", + "INT32", + "UINT8", + "INT64", + "STRING", + "BOOL", + "INT16", + "COMPLEX64", + "INT8", + "FLOAT64", + "COMPLEX128", + "UINT64", + "RESOURCE", + "VARIANT", + "UINT32", + "UINT16", + "INT4", + nullptr + }; + return names; +} + +inline const char *EnumNameTensorType(TensorType e) { + if (flatbuffers::IsOutRange(e, TensorType_FLOAT32, TensorType_INT4)) return ""; + const size_t index = static_cast(e); + return EnumNamesTensorType()[index]; +} + +enum QuantizationDetails : uint8_t { + QuantizationDetails_NONE = 0, + QuantizationDetails_CustomQuantization = 1, + QuantizationDetails_MIN = QuantizationDetails_NONE, + QuantizationDetails_MAX = QuantizationDetails_CustomQuantization +}; + +inline const QuantizationDetails (&EnumValuesQuantizationDetails())[2] { + static const QuantizationDetails values[] = { + QuantizationDetails_NONE, + QuantizationDetails_CustomQuantization + }; + return values; +} + +inline const char * const *EnumNamesQuantizationDetails() { + static const char * const names[3] = { + "NONE", + "CustomQuantization", + nullptr + }; + return names; +} + +inline const char *EnumNameQuantizationDetails(QuantizationDetails e) { + if (flatbuffers::IsOutRange(e, QuantizationDetails_NONE, QuantizationDetails_CustomQuantization)) return ""; + const size_t index = static_cast(e); + return EnumNamesQuantizationDetails()[index]; +} + +template struct QuantizationDetailsTraits { + static const QuantizationDetails enum_value = QuantizationDetails_NONE; +}; + +template<> struct QuantizationDetailsTraits { + static const QuantizationDetails enum_value = QuantizationDetails_CustomQuantization; +}; + +template struct QuantizationDetailsUnionTraits { + static const QuantizationDetails enum_value = QuantizationDetails_NONE; +}; + +template<> struct QuantizationDetailsUnionTraits { + static const QuantizationDetails enum_value = QuantizationDetails_CustomQuantization; +}; + +struct QuantizationDetailsUnion { + QuantizationDetails type; + void *value; + + QuantizationDetailsUnion() : type(QuantizationDetails_NONE), value(nullptr) {} + QuantizationDetailsUnion(QuantizationDetailsUnion&& u) FLATBUFFERS_NOEXCEPT : + type(QuantizationDetails_NONE), value(nullptr) + { std::swap(type, u.type); std::swap(value, u.value); } + QuantizationDetailsUnion(const QuantizationDetailsUnion &); + QuantizationDetailsUnion &operator=(const QuantizationDetailsUnion &u) + { QuantizationDetailsUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; } + QuantizationDetailsUnion &operator=(QuantizationDetailsUnion &&u) FLATBUFFERS_NOEXCEPT + { std::swap(type, u.type); std::swap(value, u.value); return *this; } + ~QuantizationDetailsUnion() { Reset(); } + + void Reset(); + + template + void Set(T&& val) { + typedef typename std::remove_reference::type RT; + Reset(); + type = QuantizationDetailsUnionTraits::enum_value; + if (type != QuantizationDetails_NONE) { + value = new RT(std::forward(val)); + } + } + + static void *UnPack(const void *obj, QuantizationDetails type, const flatbuffers::resolver_function_t *resolver); + flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const; + + tflite::CustomQuantizationT *AsCustomQuantization() { + return type == QuantizationDetails_CustomQuantization ? + reinterpret_cast(value) : nullptr; + } + const tflite::CustomQuantizationT *AsCustomQuantization() const { + return type == QuantizationDetails_CustomQuantization ? + reinterpret_cast(value) : nullptr; + } +}; + +bool VerifyQuantizationDetails(flatbuffers::Verifier &verifier, const void *obj, QuantizationDetails type); +bool VerifyQuantizationDetailsVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); + +enum DimensionType : int8_t { + DimensionType_DENSE = 0, + DimensionType_SPARSE_CSR = 1, + DimensionType_MIN = DimensionType_DENSE, + DimensionType_MAX = DimensionType_SPARSE_CSR +}; + +inline const DimensionType (&EnumValuesDimensionType())[2] { + static const DimensionType values[] = { + DimensionType_DENSE, + DimensionType_SPARSE_CSR + }; + return values; +} + +inline const char * const *EnumNamesDimensionType() { + static const char * const names[3] = { + "DENSE", + "SPARSE_CSR", + nullptr + }; + return names; +} + +inline const char *EnumNameDimensionType(DimensionType e) { + if (flatbuffers::IsOutRange(e, DimensionType_DENSE, DimensionType_SPARSE_CSR)) return ""; + const size_t index = static_cast(e); + return EnumNamesDimensionType()[index]; +} + +enum SparseIndexVector : uint8_t { + SparseIndexVector_NONE = 0, + SparseIndexVector_Int32Vector = 1, + SparseIndexVector_Uint16Vector = 2, + SparseIndexVector_Uint8Vector = 3, + SparseIndexVector_MIN = SparseIndexVector_NONE, + SparseIndexVector_MAX = SparseIndexVector_Uint8Vector +}; + +inline const SparseIndexVector (&EnumValuesSparseIndexVector())[4] { + static const SparseIndexVector values[] = { + SparseIndexVector_NONE, + SparseIndexVector_Int32Vector, + SparseIndexVector_Uint16Vector, + SparseIndexVector_Uint8Vector + }; + return values; +} + +inline const char * const *EnumNamesSparseIndexVector() { + static const char * const names[5] = { + "NONE", + "Int32Vector", + "Uint16Vector", + "Uint8Vector", + nullptr + }; + return names; +} + +inline const char *EnumNameSparseIndexVector(SparseIndexVector e) { + if (flatbuffers::IsOutRange(e, SparseIndexVector_NONE, SparseIndexVector_Uint8Vector)) return ""; + const size_t index = static_cast(e); + return EnumNamesSparseIndexVector()[index]; +} + +template struct SparseIndexVectorTraits { + static const SparseIndexVector enum_value = SparseIndexVector_NONE; +}; + +template<> struct SparseIndexVectorTraits { + static const SparseIndexVector enum_value = SparseIndexVector_Int32Vector; +}; + +template<> struct SparseIndexVectorTraits { + static const SparseIndexVector enum_value = SparseIndexVector_Uint16Vector; +}; + +template<> struct SparseIndexVectorTraits { + static const SparseIndexVector enum_value = SparseIndexVector_Uint8Vector; +}; + +template struct SparseIndexVectorUnionTraits { + static const SparseIndexVector enum_value = SparseIndexVector_NONE; +}; + +template<> struct SparseIndexVectorUnionTraits { + static const SparseIndexVector enum_value = SparseIndexVector_Int32Vector; +}; + +template<> struct SparseIndexVectorUnionTraits { + static const SparseIndexVector enum_value = SparseIndexVector_Uint16Vector; +}; + +template<> struct SparseIndexVectorUnionTraits { + static const SparseIndexVector enum_value = SparseIndexVector_Uint8Vector; +}; + +struct SparseIndexVectorUnion { + SparseIndexVector type; + void *value; + + SparseIndexVectorUnion() : type(SparseIndexVector_NONE), value(nullptr) {} + SparseIndexVectorUnion(SparseIndexVectorUnion&& u) FLATBUFFERS_NOEXCEPT : + type(SparseIndexVector_NONE), value(nullptr) + { std::swap(type, u.type); std::swap(value, u.value); } + SparseIndexVectorUnion(const SparseIndexVectorUnion &); + SparseIndexVectorUnion &operator=(const SparseIndexVectorUnion &u) + { SparseIndexVectorUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; } + SparseIndexVectorUnion &operator=(SparseIndexVectorUnion &&u) FLATBUFFERS_NOEXCEPT + { std::swap(type, u.type); std::swap(value, u.value); return *this; } + ~SparseIndexVectorUnion() { Reset(); } + + void Reset(); + + template + void Set(T&& val) { + typedef typename std::remove_reference::type RT; + Reset(); + type = SparseIndexVectorUnionTraits::enum_value; + if (type != SparseIndexVector_NONE) { + value = new RT(std::forward(val)); + } + } + + static void *UnPack(const void *obj, SparseIndexVector type, const flatbuffers::resolver_function_t *resolver); + flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const; + + tflite::Int32VectorT *AsInt32Vector() { + return type == SparseIndexVector_Int32Vector ? + reinterpret_cast(value) : nullptr; + } + const tflite::Int32VectorT *AsInt32Vector() const { + return type == SparseIndexVector_Int32Vector ? + reinterpret_cast(value) : nullptr; + } + tflite::Uint16VectorT *AsUint16Vector() { + return type == SparseIndexVector_Uint16Vector ? + reinterpret_cast(value) : nullptr; + } + const tflite::Uint16VectorT *AsUint16Vector() const { + return type == SparseIndexVector_Uint16Vector ? + reinterpret_cast(value) : nullptr; + } + tflite::Uint8VectorT *AsUint8Vector() { + return type == SparseIndexVector_Uint8Vector ? + reinterpret_cast(value) : nullptr; + } + const tflite::Uint8VectorT *AsUint8Vector() const { + return type == SparseIndexVector_Uint8Vector ? + reinterpret_cast(value) : nullptr; + } +}; + +bool VerifySparseIndexVector(flatbuffers::Verifier &verifier, const void *obj, SparseIndexVector type); +bool VerifySparseIndexVectorVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); + +enum BuiltinOperator : int32_t { + BuiltinOperator_ADD = 0, + BuiltinOperator_AVERAGE_POOL_2D = 1, + BuiltinOperator_CONCATENATION = 2, + BuiltinOperator_CONV_2D = 3, + BuiltinOperator_DEPTHWISE_CONV_2D = 4, + BuiltinOperator_DEPTH_TO_SPACE = 5, + BuiltinOperator_DEQUANTIZE = 6, + BuiltinOperator_EMBEDDING_LOOKUP = 7, + BuiltinOperator_FLOOR = 8, + BuiltinOperator_FULLY_CONNECTED = 9, + BuiltinOperator_HASHTABLE_LOOKUP = 10, + BuiltinOperator_L2_NORMALIZATION = 11, + BuiltinOperator_L2_POOL_2D = 12, + BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION = 13, + BuiltinOperator_LOGISTIC = 14, + BuiltinOperator_LSH_PROJECTION = 15, + BuiltinOperator_LSTM = 16, + BuiltinOperator_MAX_POOL_2D = 17, + BuiltinOperator_MUL = 18, + BuiltinOperator_RELU = 19, + BuiltinOperator_RELU_N1_TO_1 = 20, + BuiltinOperator_RELU6 = 21, + BuiltinOperator_RESHAPE = 22, + BuiltinOperator_RESIZE_BILINEAR = 23, + BuiltinOperator_RNN = 24, + BuiltinOperator_SOFTMAX = 25, + BuiltinOperator_SPACE_TO_DEPTH = 26, + BuiltinOperator_SVDF = 27, + BuiltinOperator_TANH = 28, + BuiltinOperator_CONCAT_EMBEDDINGS = 29, + BuiltinOperator_SKIP_GRAM = 30, + BuiltinOperator_CALL = 31, + BuiltinOperator_CUSTOM = 32, + BuiltinOperator_EMBEDDING_LOOKUP_SPARSE = 33, + BuiltinOperator_PAD = 34, + BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN = 35, + BuiltinOperator_GATHER = 36, + BuiltinOperator_BATCH_TO_SPACE_ND = 37, + BuiltinOperator_SPACE_TO_BATCH_ND = 38, + BuiltinOperator_TRANSPOSE = 39, + BuiltinOperator_MEAN = 40, + BuiltinOperator_SUB = 41, + BuiltinOperator_DIV = 42, + BuiltinOperator_SQUEEZE = 43, + BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM = 44, + BuiltinOperator_STRIDED_SLICE = 45, + BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN = 46, + BuiltinOperator_EXP = 47, + BuiltinOperator_TOPK_V2 = 48, + BuiltinOperator_SPLIT = 49, + BuiltinOperator_LOG_SOFTMAX = 50, + BuiltinOperator_DELEGATE = 51, + BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM = 52, + BuiltinOperator_CAST = 53, + BuiltinOperator_PRELU = 54, + BuiltinOperator_MAXIMUM = 55, + BuiltinOperator_ARG_MAX = 56, + BuiltinOperator_MINIMUM = 57, + BuiltinOperator_LESS = 58, + BuiltinOperator_NEG = 59, + BuiltinOperator_PADV2 = 60, + BuiltinOperator_GREATER = 61, + BuiltinOperator_GREATER_EQUAL = 62, + BuiltinOperator_LESS_EQUAL = 63, + BuiltinOperator_SELECT = 64, + BuiltinOperator_SLICE = 65, + BuiltinOperator_SIN = 66, + BuiltinOperator_TRANSPOSE_CONV = 67, + BuiltinOperator_SPARSE_TO_DENSE = 68, + BuiltinOperator_TILE = 69, + BuiltinOperator_EXPAND_DIMS = 70, + BuiltinOperator_EQUAL = 71, + BuiltinOperator_NOT_EQUAL = 72, + BuiltinOperator_LOG = 73, + BuiltinOperator_SUM = 74, + BuiltinOperator_SQRT = 75, + BuiltinOperator_RSQRT = 76, + BuiltinOperator_SHAPE = 77, + BuiltinOperator_POW = 78, + BuiltinOperator_ARG_MIN = 79, + BuiltinOperator_FAKE_QUANT = 80, + BuiltinOperator_REDUCE_PROD = 81, + BuiltinOperator_REDUCE_MAX = 82, + BuiltinOperator_PACK = 83, + BuiltinOperator_LOGICAL_OR = 84, + BuiltinOperator_ONE_HOT = 85, + BuiltinOperator_LOGICAL_AND = 86, + BuiltinOperator_LOGICAL_NOT = 87, + BuiltinOperator_UNPACK = 88, + BuiltinOperator_REDUCE_MIN = 89, + BuiltinOperator_FLOOR_DIV = 90, + BuiltinOperator_REDUCE_ANY = 91, + BuiltinOperator_SQUARE = 92, + BuiltinOperator_ZEROS_LIKE = 93, + BuiltinOperator_FILL = 94, + BuiltinOperator_FLOOR_MOD = 95, + BuiltinOperator_RANGE = 96, + BuiltinOperator_RESIZE_NEAREST_NEIGHBOR = 97, + BuiltinOperator_LEAKY_RELU = 98, + BuiltinOperator_SQUARED_DIFFERENCE = 99, + BuiltinOperator_MIRROR_PAD = 100, + BuiltinOperator_ABS = 101, + BuiltinOperator_SPLIT_V = 102, + BuiltinOperator_UNIQUE = 103, + BuiltinOperator_CEIL = 104, + BuiltinOperator_REVERSE_V2 = 105, + BuiltinOperator_ADD_N = 106, + BuiltinOperator_GATHER_ND = 107, + BuiltinOperator_COS = 108, + BuiltinOperator_WHERE = 109, + BuiltinOperator_RANK = 110, + BuiltinOperator_ELU = 111, + BuiltinOperator_REVERSE_SEQUENCE = 112, + BuiltinOperator_MATRIX_DIAG = 113, + BuiltinOperator_QUANTIZE = 114, + BuiltinOperator_MATRIX_SET_DIAG = 115, + BuiltinOperator_ROUND = 116, + BuiltinOperator_HARD_SWISH = 117, + BuiltinOperator_IF = 118, + BuiltinOperator_WHILE = 119, + BuiltinOperator_NON_MAX_SUPPRESSION_V4 = 120, + BuiltinOperator_NON_MAX_SUPPRESSION_V5 = 121, + BuiltinOperator_SCATTER_ND = 122, + BuiltinOperator_SELECT_V2 = 123, + BuiltinOperator_DENSIFY = 124, + BuiltinOperator_SEGMENT_SUM = 125, + BuiltinOperator_BATCH_MATMUL = 126, + BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES = 127, + BuiltinOperator_CUMSUM = 128, + BuiltinOperator_CALL_ONCE = 129, + BuiltinOperator_BROADCAST_TO = 130, + BuiltinOperator_RFFT2D = 131, + BuiltinOperator_CONV_3D = 132, + BuiltinOperator_IMAG = 133, + BuiltinOperator_REAL = 134, + BuiltinOperator_COMPLEX_ABS = 135, + BuiltinOperator_HASHTABLE = 136, + BuiltinOperator_HASHTABLE_FIND = 137, + BuiltinOperator_HASHTABLE_IMPORT = 138, + BuiltinOperator_HASHTABLE_SIZE = 139, + BuiltinOperator_REDUCE_ALL = 140, + BuiltinOperator_CONV_3D_TRANSPOSE = 141, + BuiltinOperator_VAR_HANDLE = 142, + BuiltinOperator_READ_VARIABLE = 143, + BuiltinOperator_ASSIGN_VARIABLE = 144, + BuiltinOperator_BROADCAST_ARGS = 145, + BuiltinOperator_RANDOM_STANDARD_NORMAL = 146, + BuiltinOperator_BUCKETIZE = 147, + BuiltinOperator_RANDOM_UNIFORM = 148, + BuiltinOperator_MULTINOMIAL = 149, + BuiltinOperator_GELU = 150, + BuiltinOperator_DYNAMIC_UPDATE_SLICE = 151, + BuiltinOperator_RELU_0_TO_1 = 152, + BuiltinOperator_UNSORTED_SEGMENT_PROD = 153, + BuiltinOperator_UNSORTED_SEGMENT_MAX = 154, + BuiltinOperator_UNSORTED_SEGMENT_SUM = 155, + BuiltinOperator_ATAN2 = 156, + BuiltinOperator_UNSORTED_SEGMENT_MIN = 157, + BuiltinOperator_SIGN = 158, + BuiltinOperator_MIN = BuiltinOperator_ADD, + BuiltinOperator_MAX = BuiltinOperator_SIGN +}; + +inline const BuiltinOperator (&EnumValuesBuiltinOperator())[159] { + static const BuiltinOperator values[] = { + BuiltinOperator_ADD, + BuiltinOperator_AVERAGE_POOL_2D, + BuiltinOperator_CONCATENATION, + BuiltinOperator_CONV_2D, + BuiltinOperator_DEPTHWISE_CONV_2D, + BuiltinOperator_DEPTH_TO_SPACE, + BuiltinOperator_DEQUANTIZE, + BuiltinOperator_EMBEDDING_LOOKUP, + BuiltinOperator_FLOOR, + BuiltinOperator_FULLY_CONNECTED, + BuiltinOperator_HASHTABLE_LOOKUP, + BuiltinOperator_L2_NORMALIZATION, + BuiltinOperator_L2_POOL_2D, + BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION, + BuiltinOperator_LOGISTIC, + BuiltinOperator_LSH_PROJECTION, + BuiltinOperator_LSTM, + BuiltinOperator_MAX_POOL_2D, + BuiltinOperator_MUL, + BuiltinOperator_RELU, + BuiltinOperator_RELU_N1_TO_1, + BuiltinOperator_RELU6, + BuiltinOperator_RESHAPE, + BuiltinOperator_RESIZE_BILINEAR, + BuiltinOperator_RNN, + BuiltinOperator_SOFTMAX, + BuiltinOperator_SPACE_TO_DEPTH, + BuiltinOperator_SVDF, + BuiltinOperator_TANH, + BuiltinOperator_CONCAT_EMBEDDINGS, + BuiltinOperator_SKIP_GRAM, + BuiltinOperator_CALL, + BuiltinOperator_CUSTOM, + BuiltinOperator_EMBEDDING_LOOKUP_SPARSE, + BuiltinOperator_PAD, + BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN, + BuiltinOperator_GATHER, + BuiltinOperator_BATCH_TO_SPACE_ND, + BuiltinOperator_SPACE_TO_BATCH_ND, + BuiltinOperator_TRANSPOSE, + BuiltinOperator_MEAN, + BuiltinOperator_SUB, + BuiltinOperator_DIV, + BuiltinOperator_SQUEEZE, + BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM, + BuiltinOperator_STRIDED_SLICE, + BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN, + BuiltinOperator_EXP, + BuiltinOperator_TOPK_V2, + BuiltinOperator_SPLIT, + BuiltinOperator_LOG_SOFTMAX, + BuiltinOperator_DELEGATE, + BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM, + BuiltinOperator_CAST, + BuiltinOperator_PRELU, + BuiltinOperator_MAXIMUM, + BuiltinOperator_ARG_MAX, + BuiltinOperator_MINIMUM, + BuiltinOperator_LESS, + BuiltinOperator_NEG, + BuiltinOperator_PADV2, + BuiltinOperator_GREATER, + BuiltinOperator_GREATER_EQUAL, + BuiltinOperator_LESS_EQUAL, + BuiltinOperator_SELECT, + BuiltinOperator_SLICE, + BuiltinOperator_SIN, + BuiltinOperator_TRANSPOSE_CONV, + BuiltinOperator_SPARSE_TO_DENSE, + BuiltinOperator_TILE, + BuiltinOperator_EXPAND_DIMS, + BuiltinOperator_EQUAL, + BuiltinOperator_NOT_EQUAL, + BuiltinOperator_LOG, + BuiltinOperator_SUM, + BuiltinOperator_SQRT, + BuiltinOperator_RSQRT, + BuiltinOperator_SHAPE, + BuiltinOperator_POW, + BuiltinOperator_ARG_MIN, + BuiltinOperator_FAKE_QUANT, + BuiltinOperator_REDUCE_PROD, + BuiltinOperator_REDUCE_MAX, + BuiltinOperator_PACK, + BuiltinOperator_LOGICAL_OR, + BuiltinOperator_ONE_HOT, + BuiltinOperator_LOGICAL_AND, + BuiltinOperator_LOGICAL_NOT, + BuiltinOperator_UNPACK, + BuiltinOperator_REDUCE_MIN, + BuiltinOperator_FLOOR_DIV, + BuiltinOperator_REDUCE_ANY, + BuiltinOperator_SQUARE, + BuiltinOperator_ZEROS_LIKE, + BuiltinOperator_FILL, + BuiltinOperator_FLOOR_MOD, + BuiltinOperator_RANGE, + BuiltinOperator_RESIZE_NEAREST_NEIGHBOR, + BuiltinOperator_LEAKY_RELU, + BuiltinOperator_SQUARED_DIFFERENCE, + BuiltinOperator_MIRROR_PAD, + BuiltinOperator_ABS, + BuiltinOperator_SPLIT_V, + BuiltinOperator_UNIQUE, + BuiltinOperator_CEIL, + BuiltinOperator_REVERSE_V2, + BuiltinOperator_ADD_N, + BuiltinOperator_GATHER_ND, + BuiltinOperator_COS, + BuiltinOperator_WHERE, + BuiltinOperator_RANK, + BuiltinOperator_ELU, + BuiltinOperator_REVERSE_SEQUENCE, + BuiltinOperator_MATRIX_DIAG, + BuiltinOperator_QUANTIZE, + BuiltinOperator_MATRIX_SET_DIAG, + BuiltinOperator_ROUND, + BuiltinOperator_HARD_SWISH, + BuiltinOperator_IF, + BuiltinOperator_WHILE, + BuiltinOperator_NON_MAX_SUPPRESSION_V4, + BuiltinOperator_NON_MAX_SUPPRESSION_V5, + BuiltinOperator_SCATTER_ND, + BuiltinOperator_SELECT_V2, + BuiltinOperator_DENSIFY, + BuiltinOperator_SEGMENT_SUM, + BuiltinOperator_BATCH_MATMUL, + BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES, + BuiltinOperator_CUMSUM, + BuiltinOperator_CALL_ONCE, + BuiltinOperator_BROADCAST_TO, + BuiltinOperator_RFFT2D, + BuiltinOperator_CONV_3D, + BuiltinOperator_IMAG, + BuiltinOperator_REAL, + BuiltinOperator_COMPLEX_ABS, + BuiltinOperator_HASHTABLE, + BuiltinOperator_HASHTABLE_FIND, + BuiltinOperator_HASHTABLE_IMPORT, + BuiltinOperator_HASHTABLE_SIZE, + BuiltinOperator_REDUCE_ALL, + BuiltinOperator_CONV_3D_TRANSPOSE, + BuiltinOperator_VAR_HANDLE, + BuiltinOperator_READ_VARIABLE, + BuiltinOperator_ASSIGN_VARIABLE, + BuiltinOperator_BROADCAST_ARGS, + BuiltinOperator_RANDOM_STANDARD_NORMAL, + BuiltinOperator_BUCKETIZE, + BuiltinOperator_RANDOM_UNIFORM, + BuiltinOperator_MULTINOMIAL, + BuiltinOperator_GELU, + BuiltinOperator_DYNAMIC_UPDATE_SLICE, + BuiltinOperator_RELU_0_TO_1, + BuiltinOperator_UNSORTED_SEGMENT_PROD, + BuiltinOperator_UNSORTED_SEGMENT_MAX, + BuiltinOperator_UNSORTED_SEGMENT_SUM, + BuiltinOperator_ATAN2, + BuiltinOperator_UNSORTED_SEGMENT_MIN, + BuiltinOperator_SIGN + }; + return values; +} + +inline const char * const *EnumNamesBuiltinOperator() { + static const char * const names[160] = { + "ADD", + "AVERAGE_POOL_2D", + "CONCATENATION", + "CONV_2D", + "DEPTHWISE_CONV_2D", + "DEPTH_TO_SPACE", + "DEQUANTIZE", + "EMBEDDING_LOOKUP", + "FLOOR", + "FULLY_CONNECTED", + "HASHTABLE_LOOKUP", + "L2_NORMALIZATION", + "L2_POOL_2D", + "LOCAL_RESPONSE_NORMALIZATION", + "LOGISTIC", + "LSH_PROJECTION", + "LSTM", + "MAX_POOL_2D", + "MUL", + "RELU", + "RELU_N1_TO_1", + "RELU6", + "RESHAPE", + "RESIZE_BILINEAR", + "RNN", + "SOFTMAX", + "SPACE_TO_DEPTH", + "SVDF", + "TANH", + "CONCAT_EMBEDDINGS", + "SKIP_GRAM", + "CALL", + "CUSTOM", + "EMBEDDING_LOOKUP_SPARSE", + "PAD", + "UNIDIRECTIONAL_SEQUENCE_RNN", + "GATHER", + "BATCH_TO_SPACE_ND", + "SPACE_TO_BATCH_ND", + "TRANSPOSE", + "MEAN", + "SUB", + "DIV", + "SQUEEZE", + "UNIDIRECTIONAL_SEQUENCE_LSTM", + "STRIDED_SLICE", + "BIDIRECTIONAL_SEQUENCE_RNN", + "EXP", + "TOPK_V2", + "SPLIT", + "LOG_SOFTMAX", + "DELEGATE", + "BIDIRECTIONAL_SEQUENCE_LSTM", + "CAST", + "PRELU", + "MAXIMUM", + "ARG_MAX", + "MINIMUM", + "LESS", + "NEG", + "PADV2", + "GREATER", + "GREATER_EQUAL", + "LESS_EQUAL", + "SELECT", + "SLICE", + "SIN", + "TRANSPOSE_CONV", + "SPARSE_TO_DENSE", + "TILE", + "EXPAND_DIMS", + "EQUAL", + "NOT_EQUAL", + "LOG", + "SUM", + "SQRT", + "RSQRT", + "SHAPE", + "POW", + "ARG_MIN", + "FAKE_QUANT", + "REDUCE_PROD", + "REDUCE_MAX", + "PACK", + "LOGICAL_OR", + "ONE_HOT", + "LOGICAL_AND", + "LOGICAL_NOT", + "UNPACK", + "REDUCE_MIN", + "FLOOR_DIV", + "REDUCE_ANY", + "SQUARE", + "ZEROS_LIKE", + "FILL", + "FLOOR_MOD", + "RANGE", + "RESIZE_NEAREST_NEIGHBOR", + "LEAKY_RELU", + "SQUARED_DIFFERENCE", + "MIRROR_PAD", + "ABS", + "SPLIT_V", + "UNIQUE", + "CEIL", + "REVERSE_V2", + "ADD_N", + "GATHER_ND", + "COS", + "WHERE", + "RANK", + "ELU", + "REVERSE_SEQUENCE", + "MATRIX_DIAG", + "QUANTIZE", + "MATRIX_SET_DIAG", + "ROUND", + "HARD_SWISH", + "IF", + "WHILE", + "NON_MAX_SUPPRESSION_V4", + "NON_MAX_SUPPRESSION_V5", + "SCATTER_ND", + "SELECT_V2", + "DENSIFY", + "SEGMENT_SUM", + "BATCH_MATMUL", + "PLACEHOLDER_FOR_GREATER_OP_CODES", + "CUMSUM", + "CALL_ONCE", + "BROADCAST_TO", + "RFFT2D", + "CONV_3D", + "IMAG", + "REAL", + "COMPLEX_ABS", + "HASHTABLE", + "HASHTABLE_FIND", + "HASHTABLE_IMPORT", + "HASHTABLE_SIZE", + "REDUCE_ALL", + "CONV_3D_TRANSPOSE", + "VAR_HANDLE", + "READ_VARIABLE", + "ASSIGN_VARIABLE", + "BROADCAST_ARGS", + "RANDOM_STANDARD_NORMAL", + "BUCKETIZE", + "RANDOM_UNIFORM", + "MULTINOMIAL", + "GELU", + "DYNAMIC_UPDATE_SLICE", + "RELU_0_TO_1", + "UNSORTED_SEGMENT_PROD", + "UNSORTED_SEGMENT_MAX", + "UNSORTED_SEGMENT_SUM", + "ATAN2", + "UNSORTED_SEGMENT_MIN", + "SIGN", + nullptr + }; + return names; +} + +inline const char *EnumNameBuiltinOperator(BuiltinOperator e) { + if (flatbuffers::IsOutRange(e, BuiltinOperator_ADD, BuiltinOperator_SIGN)) return ""; + const size_t index = static_cast(e); + return EnumNamesBuiltinOperator()[index]; +} + +enum BuiltinOptions : uint8_t { + BuiltinOptions_NONE = 0, + BuiltinOptions_Conv2DOptions = 1, + BuiltinOptions_DepthwiseConv2DOptions = 2, + BuiltinOptions_ConcatEmbeddingsOptions = 3, + BuiltinOptions_LSHProjectionOptions = 4, + BuiltinOptions_Pool2DOptions = 5, + BuiltinOptions_SVDFOptions = 6, + BuiltinOptions_RNNOptions = 7, + BuiltinOptions_FullyConnectedOptions = 8, + BuiltinOptions_SoftmaxOptions = 9, + BuiltinOptions_ConcatenationOptions = 10, + BuiltinOptions_AddOptions = 11, + BuiltinOptions_L2NormOptions = 12, + BuiltinOptions_LocalResponseNormalizationOptions = 13, + BuiltinOptions_LSTMOptions = 14, + BuiltinOptions_ResizeBilinearOptions = 15, + BuiltinOptions_CallOptions = 16, + BuiltinOptions_ReshapeOptions = 17, + BuiltinOptions_SkipGramOptions = 18, + BuiltinOptions_SpaceToDepthOptions = 19, + BuiltinOptions_EmbeddingLookupSparseOptions = 20, + BuiltinOptions_MulOptions = 21, + BuiltinOptions_PadOptions = 22, + BuiltinOptions_GatherOptions = 23, + BuiltinOptions_BatchToSpaceNDOptions = 24, + BuiltinOptions_SpaceToBatchNDOptions = 25, + BuiltinOptions_TransposeOptions = 26, + BuiltinOptions_ReducerOptions = 27, + BuiltinOptions_SubOptions = 28, + BuiltinOptions_DivOptions = 29, + BuiltinOptions_SqueezeOptions = 30, + BuiltinOptions_SequenceRNNOptions = 31, + BuiltinOptions_StridedSliceOptions = 32, + BuiltinOptions_ExpOptions = 33, + BuiltinOptions_TopKV2Options = 34, + BuiltinOptions_SplitOptions = 35, + BuiltinOptions_LogSoftmaxOptions = 36, + BuiltinOptions_CastOptions = 37, + BuiltinOptions_DequantizeOptions = 38, + BuiltinOptions_MaximumMinimumOptions = 39, + BuiltinOptions_ArgMaxOptions = 40, + BuiltinOptions_LessOptions = 41, + BuiltinOptions_NegOptions = 42, + BuiltinOptions_PadV2Options = 43, + BuiltinOptions_GreaterOptions = 44, + BuiltinOptions_GreaterEqualOptions = 45, + BuiltinOptions_LessEqualOptions = 46, + BuiltinOptions_SelectOptions = 47, + BuiltinOptions_SliceOptions = 48, + BuiltinOptions_TransposeConvOptions = 49, + BuiltinOptions_SparseToDenseOptions = 50, + BuiltinOptions_TileOptions = 51, + BuiltinOptions_ExpandDimsOptions = 52, + BuiltinOptions_EqualOptions = 53, + BuiltinOptions_NotEqualOptions = 54, + BuiltinOptions_ShapeOptions = 55, + BuiltinOptions_PowOptions = 56, + BuiltinOptions_ArgMinOptions = 57, + BuiltinOptions_FakeQuantOptions = 58, + BuiltinOptions_PackOptions = 59, + BuiltinOptions_LogicalOrOptions = 60, + BuiltinOptions_OneHotOptions = 61, + BuiltinOptions_LogicalAndOptions = 62, + BuiltinOptions_LogicalNotOptions = 63, + BuiltinOptions_UnpackOptions = 64, + BuiltinOptions_FloorDivOptions = 65, + BuiltinOptions_SquareOptions = 66, + BuiltinOptions_ZerosLikeOptions = 67, + BuiltinOptions_FillOptions = 68, + BuiltinOptions_BidirectionalSequenceLSTMOptions = 69, + BuiltinOptions_BidirectionalSequenceRNNOptions = 70, + BuiltinOptions_UnidirectionalSequenceLSTMOptions = 71, + BuiltinOptions_FloorModOptions = 72, + BuiltinOptions_RangeOptions = 73, + BuiltinOptions_ResizeNearestNeighborOptions = 74, + BuiltinOptions_LeakyReluOptions = 75, + BuiltinOptions_SquaredDifferenceOptions = 76, + BuiltinOptions_MirrorPadOptions = 77, + BuiltinOptions_AbsOptions = 78, + BuiltinOptions_SplitVOptions = 79, + BuiltinOptions_UniqueOptions = 80, + BuiltinOptions_ReverseV2Options = 81, + BuiltinOptions_AddNOptions = 82, + BuiltinOptions_GatherNdOptions = 83, + BuiltinOptions_CosOptions = 84, + BuiltinOptions_WhereOptions = 85, + BuiltinOptions_RankOptions = 86, + BuiltinOptions_ReverseSequenceOptions = 87, + BuiltinOptions_MatrixDiagOptions = 88, + BuiltinOptions_QuantizeOptions = 89, + BuiltinOptions_MatrixSetDiagOptions = 90, + BuiltinOptions_HardSwishOptions = 91, + BuiltinOptions_IfOptions = 92, + BuiltinOptions_WhileOptions = 93, + BuiltinOptions_DepthToSpaceOptions = 94, + BuiltinOptions_NonMaxSuppressionV4Options = 95, + BuiltinOptions_NonMaxSuppressionV5Options = 96, + BuiltinOptions_ScatterNdOptions = 97, + BuiltinOptions_SelectV2Options = 98, + BuiltinOptions_DensifyOptions = 99, + BuiltinOptions_SegmentSumOptions = 100, + BuiltinOptions_BatchMatMulOptions = 101, + BuiltinOptions_CumsumOptions = 102, + BuiltinOptions_CallOnceOptions = 103, + BuiltinOptions_BroadcastToOptions = 104, + BuiltinOptions_Rfft2dOptions = 105, + BuiltinOptions_Conv3DOptions = 106, + BuiltinOptions_HashtableOptions = 107, + BuiltinOptions_HashtableFindOptions = 108, + BuiltinOptions_HashtableImportOptions = 109, + BuiltinOptions_HashtableSizeOptions = 110, + BuiltinOptions_VarHandleOptions = 111, + BuiltinOptions_ReadVariableOptions = 112, + BuiltinOptions_AssignVariableOptions = 113, + BuiltinOptions_RandomOptions = 114, + BuiltinOptions_BucketizeOptions = 115, + BuiltinOptions_GeluOptions = 116, + BuiltinOptions_DynamicUpdateSliceOptions = 117, + BuiltinOptions_UnsortedSegmentProdOptions = 118, + BuiltinOptions_UnsortedSegmentMaxOptions = 119, + BuiltinOptions_UnsortedSegmentMinOptions = 120, + BuiltinOptions_UnsortedSegmentSumOptions = 121, + BuiltinOptions_ATan2Options = 122, + BuiltinOptions_SignOptions = 123, + BuiltinOptions_MIN = BuiltinOptions_NONE, + BuiltinOptions_MAX = BuiltinOptions_SignOptions +}; + +inline const BuiltinOptions (&EnumValuesBuiltinOptions())[124] { + static const BuiltinOptions values[] = { + BuiltinOptions_NONE, + BuiltinOptions_Conv2DOptions, + BuiltinOptions_DepthwiseConv2DOptions, + BuiltinOptions_ConcatEmbeddingsOptions, + BuiltinOptions_LSHProjectionOptions, + BuiltinOptions_Pool2DOptions, + BuiltinOptions_SVDFOptions, + BuiltinOptions_RNNOptions, + BuiltinOptions_FullyConnectedOptions, + BuiltinOptions_SoftmaxOptions, + BuiltinOptions_ConcatenationOptions, + BuiltinOptions_AddOptions, + BuiltinOptions_L2NormOptions, + BuiltinOptions_LocalResponseNormalizationOptions, + BuiltinOptions_LSTMOptions, + BuiltinOptions_ResizeBilinearOptions, + BuiltinOptions_CallOptions, + BuiltinOptions_ReshapeOptions, + BuiltinOptions_SkipGramOptions, + BuiltinOptions_SpaceToDepthOptions, + BuiltinOptions_EmbeddingLookupSparseOptions, + BuiltinOptions_MulOptions, + BuiltinOptions_PadOptions, + BuiltinOptions_GatherOptions, + BuiltinOptions_BatchToSpaceNDOptions, + BuiltinOptions_SpaceToBatchNDOptions, + BuiltinOptions_TransposeOptions, + BuiltinOptions_ReducerOptions, + BuiltinOptions_SubOptions, + BuiltinOptions_DivOptions, + BuiltinOptions_SqueezeOptions, + BuiltinOptions_SequenceRNNOptions, + BuiltinOptions_StridedSliceOptions, + BuiltinOptions_ExpOptions, + BuiltinOptions_TopKV2Options, + BuiltinOptions_SplitOptions, + BuiltinOptions_LogSoftmaxOptions, + BuiltinOptions_CastOptions, + BuiltinOptions_DequantizeOptions, + BuiltinOptions_MaximumMinimumOptions, + BuiltinOptions_ArgMaxOptions, + BuiltinOptions_LessOptions, + BuiltinOptions_NegOptions, + BuiltinOptions_PadV2Options, + BuiltinOptions_GreaterOptions, + BuiltinOptions_GreaterEqualOptions, + BuiltinOptions_LessEqualOptions, + BuiltinOptions_SelectOptions, + BuiltinOptions_SliceOptions, + BuiltinOptions_TransposeConvOptions, + BuiltinOptions_SparseToDenseOptions, + BuiltinOptions_TileOptions, + BuiltinOptions_ExpandDimsOptions, + BuiltinOptions_EqualOptions, + BuiltinOptions_NotEqualOptions, + BuiltinOptions_ShapeOptions, + BuiltinOptions_PowOptions, + BuiltinOptions_ArgMinOptions, + BuiltinOptions_FakeQuantOptions, + BuiltinOptions_PackOptions, + BuiltinOptions_LogicalOrOptions, + BuiltinOptions_OneHotOptions, + BuiltinOptions_LogicalAndOptions, + BuiltinOptions_LogicalNotOptions, + BuiltinOptions_UnpackOptions, + BuiltinOptions_FloorDivOptions, + BuiltinOptions_SquareOptions, + BuiltinOptions_ZerosLikeOptions, + BuiltinOptions_FillOptions, + BuiltinOptions_BidirectionalSequenceLSTMOptions, + BuiltinOptions_BidirectionalSequenceRNNOptions, + BuiltinOptions_UnidirectionalSequenceLSTMOptions, + BuiltinOptions_FloorModOptions, + BuiltinOptions_RangeOptions, + BuiltinOptions_ResizeNearestNeighborOptions, + BuiltinOptions_LeakyReluOptions, + BuiltinOptions_SquaredDifferenceOptions, + BuiltinOptions_MirrorPadOptions, + BuiltinOptions_AbsOptions, + BuiltinOptions_SplitVOptions, + BuiltinOptions_UniqueOptions, + BuiltinOptions_ReverseV2Options, + BuiltinOptions_AddNOptions, + BuiltinOptions_GatherNdOptions, + BuiltinOptions_CosOptions, + BuiltinOptions_WhereOptions, + BuiltinOptions_RankOptions, + BuiltinOptions_ReverseSequenceOptions, + BuiltinOptions_MatrixDiagOptions, + BuiltinOptions_QuantizeOptions, + BuiltinOptions_MatrixSetDiagOptions, + BuiltinOptions_HardSwishOptions, + BuiltinOptions_IfOptions, + BuiltinOptions_WhileOptions, + BuiltinOptions_DepthToSpaceOptions, + BuiltinOptions_NonMaxSuppressionV4Options, + BuiltinOptions_NonMaxSuppressionV5Options, + BuiltinOptions_ScatterNdOptions, + BuiltinOptions_SelectV2Options, + BuiltinOptions_DensifyOptions, + BuiltinOptions_SegmentSumOptions, + BuiltinOptions_BatchMatMulOptions, + BuiltinOptions_CumsumOptions, + BuiltinOptions_CallOnceOptions, + BuiltinOptions_BroadcastToOptions, + BuiltinOptions_Rfft2dOptions, + BuiltinOptions_Conv3DOptions, + BuiltinOptions_HashtableOptions, + BuiltinOptions_HashtableFindOptions, + BuiltinOptions_HashtableImportOptions, + BuiltinOptions_HashtableSizeOptions, + BuiltinOptions_VarHandleOptions, + BuiltinOptions_ReadVariableOptions, + BuiltinOptions_AssignVariableOptions, + BuiltinOptions_RandomOptions, + BuiltinOptions_BucketizeOptions, + BuiltinOptions_GeluOptions, + BuiltinOptions_DynamicUpdateSliceOptions, + BuiltinOptions_UnsortedSegmentProdOptions, + BuiltinOptions_UnsortedSegmentMaxOptions, + BuiltinOptions_UnsortedSegmentMinOptions, + BuiltinOptions_UnsortedSegmentSumOptions, + BuiltinOptions_ATan2Options, + BuiltinOptions_SignOptions + }; + return values; +} + +inline const char * const *EnumNamesBuiltinOptions() { + static const char * const names[125] = { + "NONE", + "Conv2DOptions", + "DepthwiseConv2DOptions", + "ConcatEmbeddingsOptions", + "LSHProjectionOptions", + "Pool2DOptions", + "SVDFOptions", + "RNNOptions", + "FullyConnectedOptions", + "SoftmaxOptions", + "ConcatenationOptions", + "AddOptions", + "L2NormOptions", + "LocalResponseNormalizationOptions", + "LSTMOptions", + "ResizeBilinearOptions", + "CallOptions", + "ReshapeOptions", + "SkipGramOptions", + "SpaceToDepthOptions", + "EmbeddingLookupSparseOptions", + "MulOptions", + "PadOptions", + "GatherOptions", + "BatchToSpaceNDOptions", + "SpaceToBatchNDOptions", + "TransposeOptions", + "ReducerOptions", + "SubOptions", + "DivOptions", + "SqueezeOptions", + "SequenceRNNOptions", + "StridedSliceOptions", + "ExpOptions", + "TopKV2Options", + "SplitOptions", + "LogSoftmaxOptions", + "CastOptions", + "DequantizeOptions", + "MaximumMinimumOptions", + "ArgMaxOptions", + "LessOptions", + "NegOptions", + "PadV2Options", + "GreaterOptions", + "GreaterEqualOptions", + "LessEqualOptions", + "SelectOptions", + "SliceOptions", + "TransposeConvOptions", + "SparseToDenseOptions", + "TileOptions", + "ExpandDimsOptions", + "EqualOptions", + "NotEqualOptions", + "ShapeOptions", + "PowOptions", + "ArgMinOptions", + "FakeQuantOptions", + "PackOptions", + "LogicalOrOptions", + "OneHotOptions", + "LogicalAndOptions", + "LogicalNotOptions", + "UnpackOptions", + "FloorDivOptions", + "SquareOptions", + "ZerosLikeOptions", + "FillOptions", + "BidirectionalSequenceLSTMOptions", + "BidirectionalSequenceRNNOptions", + "UnidirectionalSequenceLSTMOptions", + "FloorModOptions", + "RangeOptions", + "ResizeNearestNeighborOptions", + "LeakyReluOptions", + "SquaredDifferenceOptions", + "MirrorPadOptions", + "AbsOptions", + "SplitVOptions", + "UniqueOptions", + "ReverseV2Options", + "AddNOptions", + "GatherNdOptions", + "CosOptions", + "WhereOptions", + "RankOptions", + "ReverseSequenceOptions", + "MatrixDiagOptions", + "QuantizeOptions", + "MatrixSetDiagOptions", + "HardSwishOptions", + "IfOptions", + "WhileOptions", + "DepthToSpaceOptions", + "NonMaxSuppressionV4Options", + "NonMaxSuppressionV5Options", + "ScatterNdOptions", + "SelectV2Options", + "DensifyOptions", + "SegmentSumOptions", + "BatchMatMulOptions", + "CumsumOptions", + "CallOnceOptions", + "BroadcastToOptions", + "Rfft2dOptions", + "Conv3DOptions", + "HashtableOptions", + "HashtableFindOptions", + "HashtableImportOptions", + "HashtableSizeOptions", + "VarHandleOptions", + "ReadVariableOptions", + "AssignVariableOptions", + "RandomOptions", + "BucketizeOptions", + "GeluOptions", + "DynamicUpdateSliceOptions", + "UnsortedSegmentProdOptions", + "UnsortedSegmentMaxOptions", + "UnsortedSegmentMinOptions", + "UnsortedSegmentSumOptions", + "ATan2Options", + "SignOptions", + nullptr + }; + return names; +} + +inline const char *EnumNameBuiltinOptions(BuiltinOptions e) { + if (flatbuffers::IsOutRange(e, BuiltinOptions_NONE, BuiltinOptions_SignOptions)) return ""; + const size_t index = static_cast(e); + return EnumNamesBuiltinOptions()[index]; +} + +template struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NONE; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_Conv2DOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DepthwiseConv2DOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ConcatEmbeddingsOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LSHProjectionOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_Pool2DOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SVDFOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_RNNOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FullyConnectedOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SoftmaxOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ConcatenationOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_AddOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_L2NormOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LocalResponseNormalizationOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LSTMOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ResizeBilinearOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CallOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReshapeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SkipGramOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SpaceToDepthOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_EmbeddingLookupSparseOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MulOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_PadOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GatherOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BatchToSpaceNDOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SpaceToBatchNDOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_TransposeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReducerOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SubOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DivOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SqueezeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SequenceRNNOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_StridedSliceOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ExpOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_TopKV2Options; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SplitOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LogSoftmaxOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CastOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DequantizeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MaximumMinimumOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ArgMaxOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LessOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NegOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_PadV2Options; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GreaterOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GreaterEqualOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LessEqualOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SelectOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SliceOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_TransposeConvOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SparseToDenseOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_TileOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ExpandDimsOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_EqualOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NotEqualOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ShapeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_PowOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ArgMinOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FakeQuantOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_PackOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LogicalOrOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_OneHotOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LogicalAndOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LogicalNotOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnpackOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FloorDivOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SquareOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ZerosLikeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FillOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceLSTMOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceRNNOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnidirectionalSequenceLSTMOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FloorModOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_RangeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ResizeNearestNeighborOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LeakyReluOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SquaredDifferenceOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MirrorPadOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_AbsOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SplitVOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UniqueOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReverseV2Options; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_AddNOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GatherNdOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CosOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_WhereOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_RankOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReverseSequenceOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MatrixDiagOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_QuantizeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MatrixSetDiagOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HardSwishOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_IfOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_WhileOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DepthToSpaceOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV4Options; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV5Options; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ScatterNdOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SelectV2Options; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DensifyOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SegmentSumOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BatchMatMulOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CumsumOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CallOnceOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BroadcastToOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_Rfft2dOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_Conv3DOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HashtableOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HashtableFindOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HashtableImportOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HashtableSizeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_VarHandleOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReadVariableOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_AssignVariableOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_RandomOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BucketizeOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GeluOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DynamicUpdateSliceOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentProdOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentMaxOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentMinOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentSumOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ATan2Options; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SignOptions; +}; + +template struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NONE; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_Conv2DOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DepthwiseConv2DOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ConcatEmbeddingsOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LSHProjectionOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_Pool2DOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SVDFOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_RNNOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FullyConnectedOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SoftmaxOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ConcatenationOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_AddOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_L2NormOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LocalResponseNormalizationOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LSTMOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ResizeBilinearOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CallOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReshapeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SkipGramOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SpaceToDepthOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_EmbeddingLookupSparseOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MulOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_PadOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GatherOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BatchToSpaceNDOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SpaceToBatchNDOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_TransposeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReducerOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SubOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DivOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SqueezeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SequenceRNNOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_StridedSliceOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ExpOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_TopKV2Options; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SplitOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LogSoftmaxOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CastOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DequantizeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MaximumMinimumOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ArgMaxOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LessOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NegOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_PadV2Options; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GreaterOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GreaterEqualOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LessEqualOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SelectOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SliceOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_TransposeConvOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SparseToDenseOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_TileOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ExpandDimsOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_EqualOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NotEqualOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ShapeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_PowOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ArgMinOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FakeQuantOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_PackOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LogicalOrOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_OneHotOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LogicalAndOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LogicalNotOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnpackOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FloorDivOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SquareOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ZerosLikeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FillOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceLSTMOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceRNNOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnidirectionalSequenceLSTMOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_FloorModOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_RangeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ResizeNearestNeighborOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LeakyReluOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SquaredDifferenceOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MirrorPadOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_AbsOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SplitVOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UniqueOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReverseV2Options; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_AddNOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GatherNdOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CosOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_WhereOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_RankOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReverseSequenceOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MatrixDiagOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_QuantizeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MatrixSetDiagOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HardSwishOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_IfOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_WhileOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DepthToSpaceOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV4Options; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV5Options; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ScatterNdOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SelectV2Options; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DensifyOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SegmentSumOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BatchMatMulOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CumsumOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_CallOnceOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BroadcastToOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_Rfft2dOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_Conv3DOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HashtableOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HashtableFindOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HashtableImportOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_HashtableSizeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_VarHandleOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ReadVariableOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_AssignVariableOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_RandomOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_BucketizeOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_GeluOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_DynamicUpdateSliceOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentProdOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentMaxOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentMinOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentSumOptions; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_ATan2Options; +}; + +template<> struct BuiltinOptionsUnionTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SignOptions; +}; + +struct BuiltinOptionsUnion { + BuiltinOptions type; + void *value; + + BuiltinOptionsUnion() : type(BuiltinOptions_NONE), value(nullptr) {} + BuiltinOptionsUnion(BuiltinOptionsUnion&& u) FLATBUFFERS_NOEXCEPT : + type(BuiltinOptions_NONE), value(nullptr) + { std::swap(type, u.type); std::swap(value, u.value); } + BuiltinOptionsUnion(const BuiltinOptionsUnion &); + BuiltinOptionsUnion &operator=(const BuiltinOptionsUnion &u) + { BuiltinOptionsUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; } + BuiltinOptionsUnion &operator=(BuiltinOptionsUnion &&u) FLATBUFFERS_NOEXCEPT + { std::swap(type, u.type); std::swap(value, u.value); return *this; } + ~BuiltinOptionsUnion() { Reset(); } + + void Reset(); + + template + void Set(T&& val) { + typedef typename std::remove_reference::type RT; + Reset(); + type = BuiltinOptionsUnionTraits::enum_value; + if (type != BuiltinOptions_NONE) { + value = new RT(std::forward(val)); + } + } + + static void *UnPack(const void *obj, BuiltinOptions type, const flatbuffers::resolver_function_t *resolver); + flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const; + + tflite::Conv2DOptionsT *AsConv2DOptions() { + return type == BuiltinOptions_Conv2DOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::Conv2DOptionsT *AsConv2DOptions() const { + return type == BuiltinOptions_Conv2DOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::DepthwiseConv2DOptionsT *AsDepthwiseConv2DOptions() { + return type == BuiltinOptions_DepthwiseConv2DOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::DepthwiseConv2DOptionsT *AsDepthwiseConv2DOptions() const { + return type == BuiltinOptions_DepthwiseConv2DOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ConcatEmbeddingsOptionsT *AsConcatEmbeddingsOptions() { + return type == BuiltinOptions_ConcatEmbeddingsOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ConcatEmbeddingsOptionsT *AsConcatEmbeddingsOptions() const { + return type == BuiltinOptions_ConcatEmbeddingsOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LSHProjectionOptionsT *AsLSHProjectionOptions() { + return type == BuiltinOptions_LSHProjectionOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LSHProjectionOptionsT *AsLSHProjectionOptions() const { + return type == BuiltinOptions_LSHProjectionOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::Pool2DOptionsT *AsPool2DOptions() { + return type == BuiltinOptions_Pool2DOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::Pool2DOptionsT *AsPool2DOptions() const { + return type == BuiltinOptions_Pool2DOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SVDFOptionsT *AsSVDFOptions() { + return type == BuiltinOptions_SVDFOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SVDFOptionsT *AsSVDFOptions() const { + return type == BuiltinOptions_SVDFOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::RNNOptionsT *AsRNNOptions() { + return type == BuiltinOptions_RNNOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::RNNOptionsT *AsRNNOptions() const { + return type == BuiltinOptions_RNNOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::FullyConnectedOptionsT *AsFullyConnectedOptions() { + return type == BuiltinOptions_FullyConnectedOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::FullyConnectedOptionsT *AsFullyConnectedOptions() const { + return type == BuiltinOptions_FullyConnectedOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SoftmaxOptionsT *AsSoftmaxOptions() { + return type == BuiltinOptions_SoftmaxOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SoftmaxOptionsT *AsSoftmaxOptions() const { + return type == BuiltinOptions_SoftmaxOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ConcatenationOptionsT *AsConcatenationOptions() { + return type == BuiltinOptions_ConcatenationOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ConcatenationOptionsT *AsConcatenationOptions() const { + return type == BuiltinOptions_ConcatenationOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::AddOptionsT *AsAddOptions() { + return type == BuiltinOptions_AddOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::AddOptionsT *AsAddOptions() const { + return type == BuiltinOptions_AddOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::L2NormOptionsT *AsL2NormOptions() { + return type == BuiltinOptions_L2NormOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::L2NormOptionsT *AsL2NormOptions() const { + return type == BuiltinOptions_L2NormOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LocalResponseNormalizationOptionsT *AsLocalResponseNormalizationOptions() { + return type == BuiltinOptions_LocalResponseNormalizationOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LocalResponseNormalizationOptionsT *AsLocalResponseNormalizationOptions() const { + return type == BuiltinOptions_LocalResponseNormalizationOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LSTMOptionsT *AsLSTMOptions() { + return type == BuiltinOptions_LSTMOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LSTMOptionsT *AsLSTMOptions() const { + return type == BuiltinOptions_LSTMOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ResizeBilinearOptionsT *AsResizeBilinearOptions() { + return type == BuiltinOptions_ResizeBilinearOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ResizeBilinearOptionsT *AsResizeBilinearOptions() const { + return type == BuiltinOptions_ResizeBilinearOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::CallOptionsT *AsCallOptions() { + return type == BuiltinOptions_CallOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::CallOptionsT *AsCallOptions() const { + return type == BuiltinOptions_CallOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ReshapeOptionsT *AsReshapeOptions() { + return type == BuiltinOptions_ReshapeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ReshapeOptionsT *AsReshapeOptions() const { + return type == BuiltinOptions_ReshapeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SkipGramOptionsT *AsSkipGramOptions() { + return type == BuiltinOptions_SkipGramOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SkipGramOptionsT *AsSkipGramOptions() const { + return type == BuiltinOptions_SkipGramOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SpaceToDepthOptionsT *AsSpaceToDepthOptions() { + return type == BuiltinOptions_SpaceToDepthOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SpaceToDepthOptionsT *AsSpaceToDepthOptions() const { + return type == BuiltinOptions_SpaceToDepthOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::EmbeddingLookupSparseOptionsT *AsEmbeddingLookupSparseOptions() { + return type == BuiltinOptions_EmbeddingLookupSparseOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::EmbeddingLookupSparseOptionsT *AsEmbeddingLookupSparseOptions() const { + return type == BuiltinOptions_EmbeddingLookupSparseOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::MulOptionsT *AsMulOptions() { + return type == BuiltinOptions_MulOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::MulOptionsT *AsMulOptions() const { + return type == BuiltinOptions_MulOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::PadOptionsT *AsPadOptions() { + return type == BuiltinOptions_PadOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::PadOptionsT *AsPadOptions() const { + return type == BuiltinOptions_PadOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::GatherOptionsT *AsGatherOptions() { + return type == BuiltinOptions_GatherOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::GatherOptionsT *AsGatherOptions() const { + return type == BuiltinOptions_GatherOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::BatchToSpaceNDOptionsT *AsBatchToSpaceNDOptions() { + return type == BuiltinOptions_BatchToSpaceNDOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::BatchToSpaceNDOptionsT *AsBatchToSpaceNDOptions() const { + return type == BuiltinOptions_BatchToSpaceNDOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SpaceToBatchNDOptionsT *AsSpaceToBatchNDOptions() { + return type == BuiltinOptions_SpaceToBatchNDOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SpaceToBatchNDOptionsT *AsSpaceToBatchNDOptions() const { + return type == BuiltinOptions_SpaceToBatchNDOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::TransposeOptionsT *AsTransposeOptions() { + return type == BuiltinOptions_TransposeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::TransposeOptionsT *AsTransposeOptions() const { + return type == BuiltinOptions_TransposeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ReducerOptionsT *AsReducerOptions() { + return type == BuiltinOptions_ReducerOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ReducerOptionsT *AsReducerOptions() const { + return type == BuiltinOptions_ReducerOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SubOptionsT *AsSubOptions() { + return type == BuiltinOptions_SubOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SubOptionsT *AsSubOptions() const { + return type == BuiltinOptions_SubOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::DivOptionsT *AsDivOptions() { + return type == BuiltinOptions_DivOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::DivOptionsT *AsDivOptions() const { + return type == BuiltinOptions_DivOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SqueezeOptionsT *AsSqueezeOptions() { + return type == BuiltinOptions_SqueezeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SqueezeOptionsT *AsSqueezeOptions() const { + return type == BuiltinOptions_SqueezeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SequenceRNNOptionsT *AsSequenceRNNOptions() { + return type == BuiltinOptions_SequenceRNNOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SequenceRNNOptionsT *AsSequenceRNNOptions() const { + return type == BuiltinOptions_SequenceRNNOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::StridedSliceOptionsT *AsStridedSliceOptions() { + return type == BuiltinOptions_StridedSliceOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::StridedSliceOptionsT *AsStridedSliceOptions() const { + return type == BuiltinOptions_StridedSliceOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ExpOptionsT *AsExpOptions() { + return type == BuiltinOptions_ExpOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ExpOptionsT *AsExpOptions() const { + return type == BuiltinOptions_ExpOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::TopKV2OptionsT *AsTopKV2Options() { + return type == BuiltinOptions_TopKV2Options ? + reinterpret_cast(value) : nullptr; + } + const tflite::TopKV2OptionsT *AsTopKV2Options() const { + return type == BuiltinOptions_TopKV2Options ? + reinterpret_cast(value) : nullptr; + } + tflite::SplitOptionsT *AsSplitOptions() { + return type == BuiltinOptions_SplitOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SplitOptionsT *AsSplitOptions() const { + return type == BuiltinOptions_SplitOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LogSoftmaxOptionsT *AsLogSoftmaxOptions() { + return type == BuiltinOptions_LogSoftmaxOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LogSoftmaxOptionsT *AsLogSoftmaxOptions() const { + return type == BuiltinOptions_LogSoftmaxOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::CastOptionsT *AsCastOptions() { + return type == BuiltinOptions_CastOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::CastOptionsT *AsCastOptions() const { + return type == BuiltinOptions_CastOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::DequantizeOptionsT *AsDequantizeOptions() { + return type == BuiltinOptions_DequantizeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::DequantizeOptionsT *AsDequantizeOptions() const { + return type == BuiltinOptions_DequantizeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::MaximumMinimumOptionsT *AsMaximumMinimumOptions() { + return type == BuiltinOptions_MaximumMinimumOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::MaximumMinimumOptionsT *AsMaximumMinimumOptions() const { + return type == BuiltinOptions_MaximumMinimumOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ArgMaxOptionsT *AsArgMaxOptions() { + return type == BuiltinOptions_ArgMaxOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ArgMaxOptionsT *AsArgMaxOptions() const { + return type == BuiltinOptions_ArgMaxOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LessOptionsT *AsLessOptions() { + return type == BuiltinOptions_LessOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LessOptionsT *AsLessOptions() const { + return type == BuiltinOptions_LessOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::NegOptionsT *AsNegOptions() { + return type == BuiltinOptions_NegOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::NegOptionsT *AsNegOptions() const { + return type == BuiltinOptions_NegOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::PadV2OptionsT *AsPadV2Options() { + return type == BuiltinOptions_PadV2Options ? + reinterpret_cast(value) : nullptr; + } + const tflite::PadV2OptionsT *AsPadV2Options() const { + return type == BuiltinOptions_PadV2Options ? + reinterpret_cast(value) : nullptr; + } + tflite::GreaterOptionsT *AsGreaterOptions() { + return type == BuiltinOptions_GreaterOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::GreaterOptionsT *AsGreaterOptions() const { + return type == BuiltinOptions_GreaterOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::GreaterEqualOptionsT *AsGreaterEqualOptions() { + return type == BuiltinOptions_GreaterEqualOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::GreaterEqualOptionsT *AsGreaterEqualOptions() const { + return type == BuiltinOptions_GreaterEqualOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LessEqualOptionsT *AsLessEqualOptions() { + return type == BuiltinOptions_LessEqualOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LessEqualOptionsT *AsLessEqualOptions() const { + return type == BuiltinOptions_LessEqualOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SelectOptionsT *AsSelectOptions() { + return type == BuiltinOptions_SelectOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SelectOptionsT *AsSelectOptions() const { + return type == BuiltinOptions_SelectOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SliceOptionsT *AsSliceOptions() { + return type == BuiltinOptions_SliceOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SliceOptionsT *AsSliceOptions() const { + return type == BuiltinOptions_SliceOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::TransposeConvOptionsT *AsTransposeConvOptions() { + return type == BuiltinOptions_TransposeConvOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::TransposeConvOptionsT *AsTransposeConvOptions() const { + return type == BuiltinOptions_TransposeConvOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SparseToDenseOptionsT *AsSparseToDenseOptions() { + return type == BuiltinOptions_SparseToDenseOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SparseToDenseOptionsT *AsSparseToDenseOptions() const { + return type == BuiltinOptions_SparseToDenseOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::TileOptionsT *AsTileOptions() { + return type == BuiltinOptions_TileOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::TileOptionsT *AsTileOptions() const { + return type == BuiltinOptions_TileOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ExpandDimsOptionsT *AsExpandDimsOptions() { + return type == BuiltinOptions_ExpandDimsOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ExpandDimsOptionsT *AsExpandDimsOptions() const { + return type == BuiltinOptions_ExpandDimsOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::EqualOptionsT *AsEqualOptions() { + return type == BuiltinOptions_EqualOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::EqualOptionsT *AsEqualOptions() const { + return type == BuiltinOptions_EqualOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::NotEqualOptionsT *AsNotEqualOptions() { + return type == BuiltinOptions_NotEqualOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::NotEqualOptionsT *AsNotEqualOptions() const { + return type == BuiltinOptions_NotEqualOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ShapeOptionsT *AsShapeOptions() { + return type == BuiltinOptions_ShapeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ShapeOptionsT *AsShapeOptions() const { + return type == BuiltinOptions_ShapeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::PowOptionsT *AsPowOptions() { + return type == BuiltinOptions_PowOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::PowOptionsT *AsPowOptions() const { + return type == BuiltinOptions_PowOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ArgMinOptionsT *AsArgMinOptions() { + return type == BuiltinOptions_ArgMinOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ArgMinOptionsT *AsArgMinOptions() const { + return type == BuiltinOptions_ArgMinOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::FakeQuantOptionsT *AsFakeQuantOptions() { + return type == BuiltinOptions_FakeQuantOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::FakeQuantOptionsT *AsFakeQuantOptions() const { + return type == BuiltinOptions_FakeQuantOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::PackOptionsT *AsPackOptions() { + return type == BuiltinOptions_PackOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::PackOptionsT *AsPackOptions() const { + return type == BuiltinOptions_PackOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LogicalOrOptionsT *AsLogicalOrOptions() { + return type == BuiltinOptions_LogicalOrOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LogicalOrOptionsT *AsLogicalOrOptions() const { + return type == BuiltinOptions_LogicalOrOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::OneHotOptionsT *AsOneHotOptions() { + return type == BuiltinOptions_OneHotOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::OneHotOptionsT *AsOneHotOptions() const { + return type == BuiltinOptions_OneHotOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LogicalAndOptionsT *AsLogicalAndOptions() { + return type == BuiltinOptions_LogicalAndOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LogicalAndOptionsT *AsLogicalAndOptions() const { + return type == BuiltinOptions_LogicalAndOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LogicalNotOptionsT *AsLogicalNotOptions() { + return type == BuiltinOptions_LogicalNotOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LogicalNotOptionsT *AsLogicalNotOptions() const { + return type == BuiltinOptions_LogicalNotOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::UnpackOptionsT *AsUnpackOptions() { + return type == BuiltinOptions_UnpackOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::UnpackOptionsT *AsUnpackOptions() const { + return type == BuiltinOptions_UnpackOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::FloorDivOptionsT *AsFloorDivOptions() { + return type == BuiltinOptions_FloorDivOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::FloorDivOptionsT *AsFloorDivOptions() const { + return type == BuiltinOptions_FloorDivOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SquareOptionsT *AsSquareOptions() { + return type == BuiltinOptions_SquareOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SquareOptionsT *AsSquareOptions() const { + return type == BuiltinOptions_SquareOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ZerosLikeOptionsT *AsZerosLikeOptions() { + return type == BuiltinOptions_ZerosLikeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ZerosLikeOptionsT *AsZerosLikeOptions() const { + return type == BuiltinOptions_ZerosLikeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::FillOptionsT *AsFillOptions() { + return type == BuiltinOptions_FillOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::FillOptionsT *AsFillOptions() const { + return type == BuiltinOptions_FillOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::BidirectionalSequenceLSTMOptionsT *AsBidirectionalSequenceLSTMOptions() { + return type == BuiltinOptions_BidirectionalSequenceLSTMOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::BidirectionalSequenceLSTMOptionsT *AsBidirectionalSequenceLSTMOptions() const { + return type == BuiltinOptions_BidirectionalSequenceLSTMOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::BidirectionalSequenceRNNOptionsT *AsBidirectionalSequenceRNNOptions() { + return type == BuiltinOptions_BidirectionalSequenceRNNOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::BidirectionalSequenceRNNOptionsT *AsBidirectionalSequenceRNNOptions() const { + return type == BuiltinOptions_BidirectionalSequenceRNNOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::UnidirectionalSequenceLSTMOptionsT *AsUnidirectionalSequenceLSTMOptions() { + return type == BuiltinOptions_UnidirectionalSequenceLSTMOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::UnidirectionalSequenceLSTMOptionsT *AsUnidirectionalSequenceLSTMOptions() const { + return type == BuiltinOptions_UnidirectionalSequenceLSTMOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::FloorModOptionsT *AsFloorModOptions() { + return type == BuiltinOptions_FloorModOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::FloorModOptionsT *AsFloorModOptions() const { + return type == BuiltinOptions_FloorModOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::RangeOptionsT *AsRangeOptions() { + return type == BuiltinOptions_RangeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::RangeOptionsT *AsRangeOptions() const { + return type == BuiltinOptions_RangeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ResizeNearestNeighborOptionsT *AsResizeNearestNeighborOptions() { + return type == BuiltinOptions_ResizeNearestNeighborOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ResizeNearestNeighborOptionsT *AsResizeNearestNeighborOptions() const { + return type == BuiltinOptions_ResizeNearestNeighborOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::LeakyReluOptionsT *AsLeakyReluOptions() { + return type == BuiltinOptions_LeakyReluOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::LeakyReluOptionsT *AsLeakyReluOptions() const { + return type == BuiltinOptions_LeakyReluOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SquaredDifferenceOptionsT *AsSquaredDifferenceOptions() { + return type == BuiltinOptions_SquaredDifferenceOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SquaredDifferenceOptionsT *AsSquaredDifferenceOptions() const { + return type == BuiltinOptions_SquaredDifferenceOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::MirrorPadOptionsT *AsMirrorPadOptions() { + return type == BuiltinOptions_MirrorPadOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::MirrorPadOptionsT *AsMirrorPadOptions() const { + return type == BuiltinOptions_MirrorPadOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::AbsOptionsT *AsAbsOptions() { + return type == BuiltinOptions_AbsOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::AbsOptionsT *AsAbsOptions() const { + return type == BuiltinOptions_AbsOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SplitVOptionsT *AsSplitVOptions() { + return type == BuiltinOptions_SplitVOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SplitVOptionsT *AsSplitVOptions() const { + return type == BuiltinOptions_SplitVOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::UniqueOptionsT *AsUniqueOptions() { + return type == BuiltinOptions_UniqueOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::UniqueOptionsT *AsUniqueOptions() const { + return type == BuiltinOptions_UniqueOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ReverseV2OptionsT *AsReverseV2Options() { + return type == BuiltinOptions_ReverseV2Options ? + reinterpret_cast(value) : nullptr; + } + const tflite::ReverseV2OptionsT *AsReverseV2Options() const { + return type == BuiltinOptions_ReverseV2Options ? + reinterpret_cast(value) : nullptr; + } + tflite::AddNOptionsT *AsAddNOptions() { + return type == BuiltinOptions_AddNOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::AddNOptionsT *AsAddNOptions() const { + return type == BuiltinOptions_AddNOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::GatherNdOptionsT *AsGatherNdOptions() { + return type == BuiltinOptions_GatherNdOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::GatherNdOptionsT *AsGatherNdOptions() const { + return type == BuiltinOptions_GatherNdOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::CosOptionsT *AsCosOptions() { + return type == BuiltinOptions_CosOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::CosOptionsT *AsCosOptions() const { + return type == BuiltinOptions_CosOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::WhereOptionsT *AsWhereOptions() { + return type == BuiltinOptions_WhereOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::WhereOptionsT *AsWhereOptions() const { + return type == BuiltinOptions_WhereOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::RankOptionsT *AsRankOptions() { + return type == BuiltinOptions_RankOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::RankOptionsT *AsRankOptions() const { + return type == BuiltinOptions_RankOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ReverseSequenceOptionsT *AsReverseSequenceOptions() { + return type == BuiltinOptions_ReverseSequenceOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ReverseSequenceOptionsT *AsReverseSequenceOptions() const { + return type == BuiltinOptions_ReverseSequenceOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::MatrixDiagOptionsT *AsMatrixDiagOptions() { + return type == BuiltinOptions_MatrixDiagOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::MatrixDiagOptionsT *AsMatrixDiagOptions() const { + return type == BuiltinOptions_MatrixDiagOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::QuantizeOptionsT *AsQuantizeOptions() { + return type == BuiltinOptions_QuantizeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::QuantizeOptionsT *AsQuantizeOptions() const { + return type == BuiltinOptions_QuantizeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::MatrixSetDiagOptionsT *AsMatrixSetDiagOptions() { + return type == BuiltinOptions_MatrixSetDiagOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::MatrixSetDiagOptionsT *AsMatrixSetDiagOptions() const { + return type == BuiltinOptions_MatrixSetDiagOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::HardSwishOptionsT *AsHardSwishOptions() { + return type == BuiltinOptions_HardSwishOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::HardSwishOptionsT *AsHardSwishOptions() const { + return type == BuiltinOptions_HardSwishOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::IfOptionsT *AsIfOptions() { + return type == BuiltinOptions_IfOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::IfOptionsT *AsIfOptions() const { + return type == BuiltinOptions_IfOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::WhileOptionsT *AsWhileOptions() { + return type == BuiltinOptions_WhileOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::WhileOptionsT *AsWhileOptions() const { + return type == BuiltinOptions_WhileOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::DepthToSpaceOptionsT *AsDepthToSpaceOptions() { + return type == BuiltinOptions_DepthToSpaceOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::DepthToSpaceOptionsT *AsDepthToSpaceOptions() const { + return type == BuiltinOptions_DepthToSpaceOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::NonMaxSuppressionV4OptionsT *AsNonMaxSuppressionV4Options() { + return type == BuiltinOptions_NonMaxSuppressionV4Options ? + reinterpret_cast(value) : nullptr; + } + const tflite::NonMaxSuppressionV4OptionsT *AsNonMaxSuppressionV4Options() const { + return type == BuiltinOptions_NonMaxSuppressionV4Options ? + reinterpret_cast(value) : nullptr; + } + tflite::NonMaxSuppressionV5OptionsT *AsNonMaxSuppressionV5Options() { + return type == BuiltinOptions_NonMaxSuppressionV5Options ? + reinterpret_cast(value) : nullptr; + } + const tflite::NonMaxSuppressionV5OptionsT *AsNonMaxSuppressionV5Options() const { + return type == BuiltinOptions_NonMaxSuppressionV5Options ? + reinterpret_cast(value) : nullptr; + } + tflite::ScatterNdOptionsT *AsScatterNdOptions() { + return type == BuiltinOptions_ScatterNdOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ScatterNdOptionsT *AsScatterNdOptions() const { + return type == BuiltinOptions_ScatterNdOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SelectV2OptionsT *AsSelectV2Options() { + return type == BuiltinOptions_SelectV2Options ? + reinterpret_cast(value) : nullptr; + } + const tflite::SelectV2OptionsT *AsSelectV2Options() const { + return type == BuiltinOptions_SelectV2Options ? + reinterpret_cast(value) : nullptr; + } + tflite::DensifyOptionsT *AsDensifyOptions() { + return type == BuiltinOptions_DensifyOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::DensifyOptionsT *AsDensifyOptions() const { + return type == BuiltinOptions_DensifyOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::SegmentSumOptionsT *AsSegmentSumOptions() { + return type == BuiltinOptions_SegmentSumOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SegmentSumOptionsT *AsSegmentSumOptions() const { + return type == BuiltinOptions_SegmentSumOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::BatchMatMulOptionsT *AsBatchMatMulOptions() { + return type == BuiltinOptions_BatchMatMulOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::BatchMatMulOptionsT *AsBatchMatMulOptions() const { + return type == BuiltinOptions_BatchMatMulOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::CumsumOptionsT *AsCumsumOptions() { + return type == BuiltinOptions_CumsumOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::CumsumOptionsT *AsCumsumOptions() const { + return type == BuiltinOptions_CumsumOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::CallOnceOptionsT *AsCallOnceOptions() { + return type == BuiltinOptions_CallOnceOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::CallOnceOptionsT *AsCallOnceOptions() const { + return type == BuiltinOptions_CallOnceOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::BroadcastToOptionsT *AsBroadcastToOptions() { + return type == BuiltinOptions_BroadcastToOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::BroadcastToOptionsT *AsBroadcastToOptions() const { + return type == BuiltinOptions_BroadcastToOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::Rfft2dOptionsT *AsRfft2dOptions() { + return type == BuiltinOptions_Rfft2dOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::Rfft2dOptionsT *AsRfft2dOptions() const { + return type == BuiltinOptions_Rfft2dOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::Conv3DOptionsT *AsConv3DOptions() { + return type == BuiltinOptions_Conv3DOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::Conv3DOptionsT *AsConv3DOptions() const { + return type == BuiltinOptions_Conv3DOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::HashtableOptionsT *AsHashtableOptions() { + return type == BuiltinOptions_HashtableOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::HashtableOptionsT *AsHashtableOptions() const { + return type == BuiltinOptions_HashtableOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::HashtableFindOptionsT *AsHashtableFindOptions() { + return type == BuiltinOptions_HashtableFindOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::HashtableFindOptionsT *AsHashtableFindOptions() const { + return type == BuiltinOptions_HashtableFindOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::HashtableImportOptionsT *AsHashtableImportOptions() { + return type == BuiltinOptions_HashtableImportOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::HashtableImportOptionsT *AsHashtableImportOptions() const { + return type == BuiltinOptions_HashtableImportOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::HashtableSizeOptionsT *AsHashtableSizeOptions() { + return type == BuiltinOptions_HashtableSizeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::HashtableSizeOptionsT *AsHashtableSizeOptions() const { + return type == BuiltinOptions_HashtableSizeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::VarHandleOptionsT *AsVarHandleOptions() { + return type == BuiltinOptions_VarHandleOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::VarHandleOptionsT *AsVarHandleOptions() const { + return type == BuiltinOptions_VarHandleOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ReadVariableOptionsT *AsReadVariableOptions() { + return type == BuiltinOptions_ReadVariableOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::ReadVariableOptionsT *AsReadVariableOptions() const { + return type == BuiltinOptions_ReadVariableOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::AssignVariableOptionsT *AsAssignVariableOptions() { + return type == BuiltinOptions_AssignVariableOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::AssignVariableOptionsT *AsAssignVariableOptions() const { + return type == BuiltinOptions_AssignVariableOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::RandomOptionsT *AsRandomOptions() { + return type == BuiltinOptions_RandomOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::RandomOptionsT *AsRandomOptions() const { + return type == BuiltinOptions_RandomOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::BucketizeOptionsT *AsBucketizeOptions() { + return type == BuiltinOptions_BucketizeOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::BucketizeOptionsT *AsBucketizeOptions() const { + return type == BuiltinOptions_BucketizeOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::GeluOptionsT *AsGeluOptions() { + return type == BuiltinOptions_GeluOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::GeluOptionsT *AsGeluOptions() const { + return type == BuiltinOptions_GeluOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::DynamicUpdateSliceOptionsT *AsDynamicUpdateSliceOptions() { + return type == BuiltinOptions_DynamicUpdateSliceOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::DynamicUpdateSliceOptionsT *AsDynamicUpdateSliceOptions() const { + return type == BuiltinOptions_DynamicUpdateSliceOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::UnsortedSegmentProdOptionsT *AsUnsortedSegmentProdOptions() { + return type == BuiltinOptions_UnsortedSegmentProdOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::UnsortedSegmentProdOptionsT *AsUnsortedSegmentProdOptions() const { + return type == BuiltinOptions_UnsortedSegmentProdOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::UnsortedSegmentMaxOptionsT *AsUnsortedSegmentMaxOptions() { + return type == BuiltinOptions_UnsortedSegmentMaxOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::UnsortedSegmentMaxOptionsT *AsUnsortedSegmentMaxOptions() const { + return type == BuiltinOptions_UnsortedSegmentMaxOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::UnsortedSegmentMinOptionsT *AsUnsortedSegmentMinOptions() { + return type == BuiltinOptions_UnsortedSegmentMinOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::UnsortedSegmentMinOptionsT *AsUnsortedSegmentMinOptions() const { + return type == BuiltinOptions_UnsortedSegmentMinOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::UnsortedSegmentSumOptionsT *AsUnsortedSegmentSumOptions() { + return type == BuiltinOptions_UnsortedSegmentSumOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::UnsortedSegmentSumOptionsT *AsUnsortedSegmentSumOptions() const { + return type == BuiltinOptions_UnsortedSegmentSumOptions ? + reinterpret_cast(value) : nullptr; + } + tflite::ATan2OptionsT *AsATan2Options() { + return type == BuiltinOptions_ATan2Options ? + reinterpret_cast(value) : nullptr; + } + const tflite::ATan2OptionsT *AsATan2Options() const { + return type == BuiltinOptions_ATan2Options ? + reinterpret_cast(value) : nullptr; + } + tflite::SignOptionsT *AsSignOptions() { + return type == BuiltinOptions_SignOptions ? + reinterpret_cast(value) : nullptr; + } + const tflite::SignOptionsT *AsSignOptions() const { + return type == BuiltinOptions_SignOptions ? + reinterpret_cast(value) : nullptr; + } +}; + +bool VerifyBuiltinOptions(flatbuffers::Verifier &verifier, const void *obj, BuiltinOptions type); +bool VerifyBuiltinOptionsVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); + +enum Padding : int8_t { + Padding_SAME = 0, + Padding_VALID = 1, + Padding_MIN = Padding_SAME, + Padding_MAX = Padding_VALID +}; + +inline const Padding (&EnumValuesPadding())[2] { + static const Padding values[] = { + Padding_SAME, + Padding_VALID + }; + return values; +} + +inline const char * const *EnumNamesPadding() { + static const char * const names[3] = { + "SAME", + "VALID", + nullptr + }; + return names; +} + +inline const char *EnumNamePadding(Padding e) { + if (flatbuffers::IsOutRange(e, Padding_SAME, Padding_VALID)) return ""; + const size_t index = static_cast(e); + return EnumNamesPadding()[index]; +} + +enum ActivationFunctionType : int8_t { + ActivationFunctionType_NONE = 0, + ActivationFunctionType_RELU = 1, + ActivationFunctionType_RELU_N1_TO_1 = 2, + ActivationFunctionType_RELU6 = 3, + ActivationFunctionType_TANH = 4, + ActivationFunctionType_SIGN_BIT = 5, + ActivationFunctionType_MIN = ActivationFunctionType_NONE, + ActivationFunctionType_MAX = ActivationFunctionType_SIGN_BIT +}; + +inline const ActivationFunctionType (&EnumValuesActivationFunctionType())[6] { + static const ActivationFunctionType values[] = { + ActivationFunctionType_NONE, + ActivationFunctionType_RELU, + ActivationFunctionType_RELU_N1_TO_1, + ActivationFunctionType_RELU6, + ActivationFunctionType_TANH, + ActivationFunctionType_SIGN_BIT + }; + return values; +} + +inline const char * const *EnumNamesActivationFunctionType() { + static const char * const names[7] = { + "NONE", + "RELU", + "RELU_N1_TO_1", + "RELU6", + "TANH", + "SIGN_BIT", + nullptr + }; + return names; +} + +inline const char *EnumNameActivationFunctionType(ActivationFunctionType e) { + if (flatbuffers::IsOutRange(e, ActivationFunctionType_NONE, ActivationFunctionType_SIGN_BIT)) return ""; + const size_t index = static_cast(e); + return EnumNamesActivationFunctionType()[index]; +} + +enum LSHProjectionType : int8_t { + LSHProjectionType_UNKNOWN = 0, + LSHProjectionType_SPARSE = 1, + LSHProjectionType_DENSE = 2, + LSHProjectionType_MIN = LSHProjectionType_UNKNOWN, + LSHProjectionType_MAX = LSHProjectionType_DENSE +}; + +inline const LSHProjectionType (&EnumValuesLSHProjectionType())[3] { + static const LSHProjectionType values[] = { + LSHProjectionType_UNKNOWN, + LSHProjectionType_SPARSE, + LSHProjectionType_DENSE + }; + return values; +} + +inline const char * const *EnumNamesLSHProjectionType() { + static const char * const names[4] = { + "UNKNOWN", + "SPARSE", + "DENSE", + nullptr + }; + return names; +} + +inline const char *EnumNameLSHProjectionType(LSHProjectionType e) { + if (flatbuffers::IsOutRange(e, LSHProjectionType_UNKNOWN, LSHProjectionType_DENSE)) return ""; + const size_t index = static_cast(e); + return EnumNamesLSHProjectionType()[index]; +} + +enum FullyConnectedOptionsWeightsFormat : int8_t { + FullyConnectedOptionsWeightsFormat_DEFAULT = 0, + FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8 = 1, + FullyConnectedOptionsWeightsFormat_MIN = FullyConnectedOptionsWeightsFormat_DEFAULT, + FullyConnectedOptionsWeightsFormat_MAX = FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8 +}; + +inline const FullyConnectedOptionsWeightsFormat (&EnumValuesFullyConnectedOptionsWeightsFormat())[2] { + static const FullyConnectedOptionsWeightsFormat values[] = { + FullyConnectedOptionsWeightsFormat_DEFAULT, + FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8 + }; + return values; +} + +inline const char * const *EnumNamesFullyConnectedOptionsWeightsFormat() { + static const char * const names[3] = { + "DEFAULT", + "SHUFFLED4x16INT8", + nullptr + }; + return names; +} + +inline const char *EnumNameFullyConnectedOptionsWeightsFormat(FullyConnectedOptionsWeightsFormat e) { + if (flatbuffers::IsOutRange(e, FullyConnectedOptionsWeightsFormat_DEFAULT, FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8)) return ""; + const size_t index = static_cast(e); + return EnumNamesFullyConnectedOptionsWeightsFormat()[index]; +} + +enum LSTMKernelType : int8_t { + LSTMKernelType_FULL = 0, + LSTMKernelType_BASIC = 1, + LSTMKernelType_MIN = LSTMKernelType_FULL, + LSTMKernelType_MAX = LSTMKernelType_BASIC +}; + +inline const LSTMKernelType (&EnumValuesLSTMKernelType())[2] { + static const LSTMKernelType values[] = { + LSTMKernelType_FULL, + LSTMKernelType_BASIC + }; + return values; +} + +inline const char * const *EnumNamesLSTMKernelType() { + static const char * const names[3] = { + "FULL", + "BASIC", + nullptr + }; + return names; +} + +inline const char *EnumNameLSTMKernelType(LSTMKernelType e) { + if (flatbuffers::IsOutRange(e, LSTMKernelType_FULL, LSTMKernelType_BASIC)) return ""; + const size_t index = static_cast(e); + return EnumNamesLSTMKernelType()[index]; +} + +enum CombinerType : int8_t { + CombinerType_SUM = 0, + CombinerType_MEAN = 1, + CombinerType_SQRTN = 2, + CombinerType_MIN = CombinerType_SUM, + CombinerType_MAX = CombinerType_SQRTN +}; + +inline const CombinerType (&EnumValuesCombinerType())[3] { + static const CombinerType values[] = { + CombinerType_SUM, + CombinerType_MEAN, + CombinerType_SQRTN + }; + return values; +} + +inline const char * const *EnumNamesCombinerType() { + static const char * const names[4] = { + "SUM", + "MEAN", + "SQRTN", + nullptr + }; + return names; +} + +inline const char *EnumNameCombinerType(CombinerType e) { + if (flatbuffers::IsOutRange(e, CombinerType_SUM, CombinerType_SQRTN)) return ""; + const size_t index = static_cast(e); + return EnumNamesCombinerType()[index]; +} + +enum MirrorPadMode : int8_t { + MirrorPadMode_REFLECT = 0, + MirrorPadMode_SYMMETRIC = 1, + MirrorPadMode_MIN = MirrorPadMode_REFLECT, + MirrorPadMode_MAX = MirrorPadMode_SYMMETRIC +}; + +inline const MirrorPadMode (&EnumValuesMirrorPadMode())[2] { + static const MirrorPadMode values[] = { + MirrorPadMode_REFLECT, + MirrorPadMode_SYMMETRIC + }; + return values; +} + +inline const char * const *EnumNamesMirrorPadMode() { + static const char * const names[3] = { + "REFLECT", + "SYMMETRIC", + nullptr + }; + return names; +} + +inline const char *EnumNameMirrorPadMode(MirrorPadMode e) { + if (flatbuffers::IsOutRange(e, MirrorPadMode_REFLECT, MirrorPadMode_SYMMETRIC)) return ""; + const size_t index = static_cast(e); + return EnumNamesMirrorPadMode()[index]; +} + +enum CustomOptionsFormat : int8_t { + CustomOptionsFormat_FLEXBUFFERS = 0, + CustomOptionsFormat_MIN = CustomOptionsFormat_FLEXBUFFERS, + CustomOptionsFormat_MAX = CustomOptionsFormat_FLEXBUFFERS +}; + +inline const CustomOptionsFormat (&EnumValuesCustomOptionsFormat())[1] { + static const CustomOptionsFormat values[] = { + CustomOptionsFormat_FLEXBUFFERS + }; + return values; +} + +inline const char * const *EnumNamesCustomOptionsFormat() { + static const char * const names[2] = { + "FLEXBUFFERS", + nullptr + }; + return names; +} + +inline const char *EnumNameCustomOptionsFormat(CustomOptionsFormat e) { + if (flatbuffers::IsOutRange(e, CustomOptionsFormat_FLEXBUFFERS, CustomOptionsFormat_FLEXBUFFERS)) return ""; + const size_t index = static_cast(e); + return EnumNamesCustomOptionsFormat()[index]; +} + +struct CustomQuantizationT : public flatbuffers::NativeTable { + typedef CustomQuantization TableType; + std::vector custom{}; +}; + +struct CustomQuantization FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef CustomQuantizationT NativeTableType; + typedef CustomQuantizationBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_CUSTOM = 4 + }; + const flatbuffers::Vector *custom() const { + return GetPointer *>(VT_CUSTOM); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_CUSTOM) && + verifier.VerifyVector(custom()) && + verifier.EndTable(); + } + CustomQuantizationT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(CustomQuantizationT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct CustomQuantizationBuilder { + typedef CustomQuantization Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_custom(flatbuffers::Offset> custom) { + fbb_.AddOffset(CustomQuantization::VT_CUSTOM, custom); + } + explicit CustomQuantizationBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateCustomQuantization( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> custom = 0) { + CustomQuantizationBuilder builder_(_fbb); + builder_.add_custom(custom); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateCustomQuantizationDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *custom = nullptr) { + if (custom) { _fbb.ForceVectorAlignment(custom->size(), sizeof(uint8_t), 16); } + auto custom__ = custom ? _fbb.CreateVector(*custom) : 0; + return tflite::CreateCustomQuantization( + _fbb, + custom__); +} + +flatbuffers::Offset CreateCustomQuantization(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct QuantizationParametersT : public flatbuffers::NativeTable { + typedef QuantizationParameters TableType; + std::vector min{}; + std::vector max{}; + std::vector scale{}; + std::vector zero_point{}; + tflite::QuantizationDetailsUnion details{}; + int32_t quantized_dimension = 0; +}; + +struct QuantizationParameters FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef QuantizationParametersT NativeTableType; + typedef QuantizationParametersBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_MIN = 4, + VT_MAX = 6, + VT_SCALE = 8, + VT_ZERO_POINT = 10, + VT_DETAILS_TYPE = 12, + VT_DETAILS = 14, + VT_QUANTIZED_DIMENSION = 16 + }; + const flatbuffers::Vector *min() const { + return GetPointer *>(VT_MIN); + } + const flatbuffers::Vector *max() const { + return GetPointer *>(VT_MAX); + } + const flatbuffers::Vector *scale() const { + return GetPointer *>(VT_SCALE); + } + const flatbuffers::Vector *zero_point() const { + return GetPointer *>(VT_ZERO_POINT); + } + tflite::QuantizationDetails details_type() const { + return static_cast(GetField(VT_DETAILS_TYPE, 0)); + } + const void *details() const { + return GetPointer(VT_DETAILS); + } + template const T *details_as() const; + const tflite::CustomQuantization *details_as_CustomQuantization() const { + return details_type() == tflite::QuantizationDetails_CustomQuantization ? static_cast(details()) : nullptr; + } + int32_t quantized_dimension() const { + return GetField(VT_QUANTIZED_DIMENSION, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_MIN) && + verifier.VerifyVector(min()) && + VerifyOffset(verifier, VT_MAX) && + verifier.VerifyVector(max()) && + VerifyOffset(verifier, VT_SCALE) && + verifier.VerifyVector(scale()) && + VerifyOffset(verifier, VT_ZERO_POINT) && + verifier.VerifyVector(zero_point()) && + VerifyField(verifier, VT_DETAILS_TYPE, 1) && + VerifyOffset(verifier, VT_DETAILS) && + VerifyQuantizationDetails(verifier, details(), details_type()) && + VerifyField(verifier, VT_QUANTIZED_DIMENSION, 4) && + verifier.EndTable(); + } + QuantizationParametersT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(QuantizationParametersT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const QuantizationParametersT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +template<> inline const tflite::CustomQuantization *QuantizationParameters::details_as() const { + return details_as_CustomQuantization(); +} + +struct QuantizationParametersBuilder { + typedef QuantizationParameters Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_min(flatbuffers::Offset> min) { + fbb_.AddOffset(QuantizationParameters::VT_MIN, min); + } + void add_max(flatbuffers::Offset> max) { + fbb_.AddOffset(QuantizationParameters::VT_MAX, max); + } + void add_scale(flatbuffers::Offset> scale) { + fbb_.AddOffset(QuantizationParameters::VT_SCALE, scale); + } + void add_zero_point(flatbuffers::Offset> zero_point) { + fbb_.AddOffset(QuantizationParameters::VT_ZERO_POINT, zero_point); + } + void add_details_type(tflite::QuantizationDetails details_type) { + fbb_.AddElement(QuantizationParameters::VT_DETAILS_TYPE, static_cast(details_type), 0); + } + void add_details(flatbuffers::Offset details) { + fbb_.AddOffset(QuantizationParameters::VT_DETAILS, details); + } + void add_quantized_dimension(int32_t quantized_dimension) { + fbb_.AddElement(QuantizationParameters::VT_QUANTIZED_DIMENSION, quantized_dimension, 0); + } + explicit QuantizationParametersBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateQuantizationParameters( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> min = 0, + flatbuffers::Offset> max = 0, + flatbuffers::Offset> scale = 0, + flatbuffers::Offset> zero_point = 0, + tflite::QuantizationDetails details_type = tflite::QuantizationDetails_NONE, + flatbuffers::Offset details = 0, + int32_t quantized_dimension = 0) { + QuantizationParametersBuilder builder_(_fbb); + builder_.add_quantized_dimension(quantized_dimension); + builder_.add_details(details); + builder_.add_zero_point(zero_point); + builder_.add_scale(scale); + builder_.add_max(max); + builder_.add_min(min); + builder_.add_details_type(details_type); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateQuantizationParametersDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *min = nullptr, + const std::vector *max = nullptr, + const std::vector *scale = nullptr, + const std::vector *zero_point = nullptr, + tflite::QuantizationDetails details_type = tflite::QuantizationDetails_NONE, + flatbuffers::Offset details = 0, + int32_t quantized_dimension = 0) { + auto min__ = min ? _fbb.CreateVector(*min) : 0; + auto max__ = max ? _fbb.CreateVector(*max) : 0; + auto scale__ = scale ? _fbb.CreateVector(*scale) : 0; + auto zero_point__ = zero_point ? _fbb.CreateVector(*zero_point) : 0; + return tflite::CreateQuantizationParameters( + _fbb, + min__, + max__, + scale__, + zero_point__, + details_type, + details, + quantized_dimension); +} + +flatbuffers::Offset CreateQuantizationParameters(flatbuffers::FlatBufferBuilder &_fbb, const QuantizationParametersT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct Int32VectorT : public flatbuffers::NativeTable { + typedef Int32Vector TableType; + std::vector values{}; +}; + +struct Int32Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef Int32VectorT NativeTableType; + typedef Int32VectorBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VALUES = 4 + }; + const flatbuffers::Vector *values() const { + return GetPointer *>(VT_VALUES); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_VALUES) && + verifier.VerifyVector(values()) && + verifier.EndTable(); + } + Int32VectorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(Int32VectorT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct Int32VectorBuilder { + typedef Int32Vector Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_values(flatbuffers::Offset> values) { + fbb_.AddOffset(Int32Vector::VT_VALUES, values); + } + explicit Int32VectorBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateInt32Vector( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> values = 0) { + Int32VectorBuilder builder_(_fbb); + builder_.add_values(values); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateInt32VectorDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *values = nullptr) { + auto values__ = values ? _fbb.CreateVector(*values) : 0; + return tflite::CreateInt32Vector( + _fbb, + values__); +} + +flatbuffers::Offset CreateInt32Vector(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct Uint16VectorT : public flatbuffers::NativeTable { + typedef Uint16Vector TableType; + std::vector values{}; +}; + +struct Uint16Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef Uint16VectorT NativeTableType; + typedef Uint16VectorBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VALUES = 4 + }; + const flatbuffers::Vector *values() const { + return GetPointer *>(VT_VALUES); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_VALUES) && + verifier.VerifyVector(values()) && + verifier.EndTable(); + } + Uint16VectorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(Uint16VectorT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct Uint16VectorBuilder { + typedef Uint16Vector Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_values(flatbuffers::Offset> values) { + fbb_.AddOffset(Uint16Vector::VT_VALUES, values); + } + explicit Uint16VectorBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUint16Vector( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> values = 0) { + Uint16VectorBuilder builder_(_fbb); + builder_.add_values(values); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateUint16VectorDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *values = nullptr) { + if (values) { _fbb.ForceVectorAlignment(values->size(), sizeof(uint16_t), 4); } + auto values__ = values ? _fbb.CreateVector(*values) : 0; + return tflite::CreateUint16Vector( + _fbb, + values__); +} + +flatbuffers::Offset CreateUint16Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct Uint8VectorT : public flatbuffers::NativeTable { + typedef Uint8Vector TableType; + std::vector values{}; +}; + +struct Uint8Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef Uint8VectorT NativeTableType; + typedef Uint8VectorBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VALUES = 4 + }; + const flatbuffers::Vector *values() const { + return GetPointer *>(VT_VALUES); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_VALUES) && + verifier.VerifyVector(values()) && + verifier.EndTable(); + } + Uint8VectorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(Uint8VectorT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct Uint8VectorBuilder { + typedef Uint8Vector Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_values(flatbuffers::Offset> values) { + fbb_.AddOffset(Uint8Vector::VT_VALUES, values); + } + explicit Uint8VectorBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUint8Vector( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> values = 0) { + Uint8VectorBuilder builder_(_fbb); + builder_.add_values(values); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateUint8VectorDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *values = nullptr) { + if (values) { _fbb.ForceVectorAlignment(values->size(), sizeof(uint8_t), 4); } + auto values__ = values ? _fbb.CreateVector(*values) : 0; + return tflite::CreateUint8Vector( + _fbb, + values__); +} + +flatbuffers::Offset CreateUint8Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct DimensionMetadataT : public flatbuffers::NativeTable { + typedef DimensionMetadata TableType; + tflite::DimensionType format = tflite::DimensionType_DENSE; + int32_t dense_size = 0; + tflite::SparseIndexVectorUnion array_segments{}; + tflite::SparseIndexVectorUnion array_indices{}; +}; + +struct DimensionMetadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef DimensionMetadataT NativeTableType; + typedef DimensionMetadataBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FORMAT = 4, + VT_DENSE_SIZE = 6, + VT_ARRAY_SEGMENTS_TYPE = 8, + VT_ARRAY_SEGMENTS = 10, + VT_ARRAY_INDICES_TYPE = 12, + VT_ARRAY_INDICES = 14 + }; + tflite::DimensionType format() const { + return static_cast(GetField(VT_FORMAT, 0)); + } + int32_t dense_size() const { + return GetField(VT_DENSE_SIZE, 0); + } + tflite::SparseIndexVector array_segments_type() const { + return static_cast(GetField(VT_ARRAY_SEGMENTS_TYPE, 0)); + } + const void *array_segments() const { + return GetPointer(VT_ARRAY_SEGMENTS); + } + template const T *array_segments_as() const; + const tflite::Int32Vector *array_segments_as_Int32Vector() const { + return array_segments_type() == tflite::SparseIndexVector_Int32Vector ? static_cast(array_segments()) : nullptr; + } + const tflite::Uint16Vector *array_segments_as_Uint16Vector() const { + return array_segments_type() == tflite::SparseIndexVector_Uint16Vector ? static_cast(array_segments()) : nullptr; + } + const tflite::Uint8Vector *array_segments_as_Uint8Vector() const { + return array_segments_type() == tflite::SparseIndexVector_Uint8Vector ? static_cast(array_segments()) : nullptr; + } + tflite::SparseIndexVector array_indices_type() const { + return static_cast(GetField(VT_ARRAY_INDICES_TYPE, 0)); + } + const void *array_indices() const { + return GetPointer(VT_ARRAY_INDICES); + } + template const T *array_indices_as() const; + const tflite::Int32Vector *array_indices_as_Int32Vector() const { + return array_indices_type() == tflite::SparseIndexVector_Int32Vector ? static_cast(array_indices()) : nullptr; + } + const tflite::Uint16Vector *array_indices_as_Uint16Vector() const { + return array_indices_type() == tflite::SparseIndexVector_Uint16Vector ? static_cast(array_indices()) : nullptr; + } + const tflite::Uint8Vector *array_indices_as_Uint8Vector() const { + return array_indices_type() == tflite::SparseIndexVector_Uint8Vector ? static_cast(array_indices()) : nullptr; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FORMAT, 1) && + VerifyField(verifier, VT_DENSE_SIZE, 4) && + VerifyField(verifier, VT_ARRAY_SEGMENTS_TYPE, 1) && + VerifyOffset(verifier, VT_ARRAY_SEGMENTS) && + VerifySparseIndexVector(verifier, array_segments(), array_segments_type()) && + VerifyField(verifier, VT_ARRAY_INDICES_TYPE, 1) && + VerifyOffset(verifier, VT_ARRAY_INDICES) && + VerifySparseIndexVector(verifier, array_indices(), array_indices_type()) && + verifier.EndTable(); + } + DimensionMetadataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(DimensionMetadataT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +template<> inline const tflite::Int32Vector *DimensionMetadata::array_segments_as() const { + return array_segments_as_Int32Vector(); +} + +template<> inline const tflite::Uint16Vector *DimensionMetadata::array_segments_as() const { + return array_segments_as_Uint16Vector(); +} + +template<> inline const tflite::Uint8Vector *DimensionMetadata::array_segments_as() const { + return array_segments_as_Uint8Vector(); +} + +template<> inline const tflite::Int32Vector *DimensionMetadata::array_indices_as() const { + return array_indices_as_Int32Vector(); +} + +template<> inline const tflite::Uint16Vector *DimensionMetadata::array_indices_as() const { + return array_indices_as_Uint16Vector(); +} + +template<> inline const tflite::Uint8Vector *DimensionMetadata::array_indices_as() const { + return array_indices_as_Uint8Vector(); +} + +struct DimensionMetadataBuilder { + typedef DimensionMetadata Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_format(tflite::DimensionType format) { + fbb_.AddElement(DimensionMetadata::VT_FORMAT, static_cast(format), 0); + } + void add_dense_size(int32_t dense_size) { + fbb_.AddElement(DimensionMetadata::VT_DENSE_SIZE, dense_size, 0); + } + void add_array_segments_type(tflite::SparseIndexVector array_segments_type) { + fbb_.AddElement(DimensionMetadata::VT_ARRAY_SEGMENTS_TYPE, static_cast(array_segments_type), 0); + } + void add_array_segments(flatbuffers::Offset array_segments) { + fbb_.AddOffset(DimensionMetadata::VT_ARRAY_SEGMENTS, array_segments); + } + void add_array_indices_type(tflite::SparseIndexVector array_indices_type) { + fbb_.AddElement(DimensionMetadata::VT_ARRAY_INDICES_TYPE, static_cast(array_indices_type), 0); + } + void add_array_indices(flatbuffers::Offset array_indices) { + fbb_.AddOffset(DimensionMetadata::VT_ARRAY_INDICES, array_indices); + } + explicit DimensionMetadataBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateDimensionMetadata( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::DimensionType format = tflite::DimensionType_DENSE, + int32_t dense_size = 0, + tflite::SparseIndexVector array_segments_type = tflite::SparseIndexVector_NONE, + flatbuffers::Offset array_segments = 0, + tflite::SparseIndexVector array_indices_type = tflite::SparseIndexVector_NONE, + flatbuffers::Offset array_indices = 0) { + DimensionMetadataBuilder builder_(_fbb); + builder_.add_array_indices(array_indices); + builder_.add_array_segments(array_segments); + builder_.add_dense_size(dense_size); + builder_.add_array_indices_type(array_indices_type); + builder_.add_array_segments_type(array_segments_type); + builder_.add_format(format); + return builder_.Finish(); +} + +flatbuffers::Offset CreateDimensionMetadata(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SparsityParametersT : public flatbuffers::NativeTable { + typedef SparsityParameters TableType; + std::vector traversal_order{}; + std::vector block_map{}; + std::vector> dim_metadata{}; + SparsityParametersT() = default; + SparsityParametersT(const SparsityParametersT &o); + SparsityParametersT(SparsityParametersT&&) FLATBUFFERS_NOEXCEPT = default; + SparsityParametersT &operator=(SparsityParametersT o) FLATBUFFERS_NOEXCEPT; +}; + +struct SparsityParameters FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SparsityParametersT NativeTableType; + typedef SparsityParametersBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_TRAVERSAL_ORDER = 4, + VT_BLOCK_MAP = 6, + VT_DIM_METADATA = 8 + }; + const flatbuffers::Vector *traversal_order() const { + return GetPointer *>(VT_TRAVERSAL_ORDER); + } + const flatbuffers::Vector *block_map() const { + return GetPointer *>(VT_BLOCK_MAP); + } + const flatbuffers::Vector> *dim_metadata() const { + return GetPointer> *>(VT_DIM_METADATA); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_TRAVERSAL_ORDER) && + verifier.VerifyVector(traversal_order()) && + VerifyOffset(verifier, VT_BLOCK_MAP) && + verifier.VerifyVector(block_map()) && + VerifyOffset(verifier, VT_DIM_METADATA) && + verifier.VerifyVector(dim_metadata()) && + verifier.VerifyVectorOfTables(dim_metadata()) && + verifier.EndTable(); + } + SparsityParametersT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SparsityParametersT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SparsityParametersBuilder { + typedef SparsityParameters Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_traversal_order(flatbuffers::Offset> traversal_order) { + fbb_.AddOffset(SparsityParameters::VT_TRAVERSAL_ORDER, traversal_order); + } + void add_block_map(flatbuffers::Offset> block_map) { + fbb_.AddOffset(SparsityParameters::VT_BLOCK_MAP, block_map); + } + void add_dim_metadata(flatbuffers::Offset>> dim_metadata) { + fbb_.AddOffset(SparsityParameters::VT_DIM_METADATA, dim_metadata); + } + explicit SparsityParametersBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSparsityParameters( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> traversal_order = 0, + flatbuffers::Offset> block_map = 0, + flatbuffers::Offset>> dim_metadata = 0) { + SparsityParametersBuilder builder_(_fbb); + builder_.add_dim_metadata(dim_metadata); + builder_.add_block_map(block_map); + builder_.add_traversal_order(traversal_order); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateSparsityParametersDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *traversal_order = nullptr, + const std::vector *block_map = nullptr, + const std::vector> *dim_metadata = nullptr) { + auto traversal_order__ = traversal_order ? _fbb.CreateVector(*traversal_order) : 0; + auto block_map__ = block_map ? _fbb.CreateVector(*block_map) : 0; + auto dim_metadata__ = dim_metadata ? _fbb.CreateVector>(*dim_metadata) : 0; + return tflite::CreateSparsityParameters( + _fbb, + traversal_order__, + block_map__, + dim_metadata__); +} + +flatbuffers::Offset CreateSparsityParameters(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct VariantSubTypeT : public flatbuffers::NativeTable { + typedef VariantSubType TableType; + std::vector shape{}; + tflite::TensorType type = tflite::TensorType_FLOAT32; + bool has_rank = false; +}; + +struct VariantSubType FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef VariantSubTypeT NativeTableType; + typedef VariantSubTypeBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SHAPE = 4, + VT_TYPE = 6, + VT_HAS_RANK = 8 + }; + const flatbuffers::Vector *shape() const { + return GetPointer *>(VT_SHAPE); + } + tflite::TensorType type() const { + return static_cast(GetField(VT_TYPE, 0)); + } + bool has_rank() const { + return GetField(VT_HAS_RANK, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_SHAPE) && + verifier.VerifyVector(shape()) && + VerifyField(verifier, VT_TYPE, 1) && + VerifyField(verifier, VT_HAS_RANK, 1) && + verifier.EndTable(); + } + VariantSubTypeT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(VariantSubTypeT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct VariantSubTypeBuilder { + typedef VariantSubType Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_shape(flatbuffers::Offset> shape) { + fbb_.AddOffset(VariantSubType::VT_SHAPE, shape); + } + void add_type(tflite::TensorType type) { + fbb_.AddElement(VariantSubType::VT_TYPE, static_cast(type), 0); + } + void add_has_rank(bool has_rank) { + fbb_.AddElement(VariantSubType::VT_HAS_RANK, static_cast(has_rank), 0); + } + explicit VariantSubTypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateVariantSubType( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> shape = 0, + tflite::TensorType type = tflite::TensorType_FLOAT32, + bool has_rank = false) { + VariantSubTypeBuilder builder_(_fbb); + builder_.add_shape(shape); + builder_.add_has_rank(has_rank); + builder_.add_type(type); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateVariantSubTypeDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *shape = nullptr, + tflite::TensorType type = tflite::TensorType_FLOAT32, + bool has_rank = false) { + auto shape__ = shape ? _fbb.CreateVector(*shape) : 0; + return tflite::CreateVariantSubType( + _fbb, + shape__, + type, + has_rank); +} + +flatbuffers::Offset CreateVariantSubType(flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct TensorT : public flatbuffers::NativeTable { + typedef Tensor TableType; + std::vector shape{}; + tflite::TensorType type = tflite::TensorType_FLOAT32; + uint32_t buffer = 0; + std::string name{}; + std::unique_ptr quantization{}; + bool is_variable = false; + std::unique_ptr sparsity{}; + std::vector shape_signature{}; + bool has_rank = false; + std::vector> variant_tensors{}; + TensorT() = default; + TensorT(const TensorT &o); + TensorT(TensorT&&) FLATBUFFERS_NOEXCEPT = default; + TensorT &operator=(TensorT o) FLATBUFFERS_NOEXCEPT; +}; + +struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TensorT NativeTableType; + typedef TensorBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SHAPE = 4, + VT_TYPE = 6, + VT_BUFFER = 8, + VT_NAME = 10, + VT_QUANTIZATION = 12, + VT_IS_VARIABLE = 14, + VT_SPARSITY = 16, + VT_SHAPE_SIGNATURE = 18, + VT_HAS_RANK = 20, + VT_VARIANT_TENSORS = 22 + }; + const flatbuffers::Vector *shape() const { + return GetPointer *>(VT_SHAPE); + } + tflite::TensorType type() const { + return static_cast(GetField(VT_TYPE, 0)); + } + uint32_t buffer() const { + return GetField(VT_BUFFER, 0); + } + const flatbuffers::String *name() const { + return GetPointer(VT_NAME); + } + const tflite::QuantizationParameters *quantization() const { + return GetPointer(VT_QUANTIZATION); + } + bool is_variable() const { + return GetField(VT_IS_VARIABLE, 0) != 0; + } + const tflite::SparsityParameters *sparsity() const { + return GetPointer(VT_SPARSITY); + } + const flatbuffers::Vector *shape_signature() const { + return GetPointer *>(VT_SHAPE_SIGNATURE); + } + bool has_rank() const { + return GetField(VT_HAS_RANK, 0) != 0; + } + const flatbuffers::Vector> *variant_tensors() const { + return GetPointer> *>(VT_VARIANT_TENSORS); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_SHAPE) && + verifier.VerifyVector(shape()) && + VerifyField(verifier, VT_TYPE, 1) && + VerifyField(verifier, VT_BUFFER, 4) && + VerifyOffset(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyOffset(verifier, VT_QUANTIZATION) && + verifier.VerifyTable(quantization()) && + VerifyField(verifier, VT_IS_VARIABLE, 1) && + VerifyOffset(verifier, VT_SPARSITY) && + verifier.VerifyTable(sparsity()) && + VerifyOffset(verifier, VT_SHAPE_SIGNATURE) && + verifier.VerifyVector(shape_signature()) && + VerifyField(verifier, VT_HAS_RANK, 1) && + VerifyOffset(verifier, VT_VARIANT_TENSORS) && + verifier.VerifyVector(variant_tensors()) && + verifier.VerifyVectorOfTables(variant_tensors()) && + verifier.EndTable(); + } + TensorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(TensorT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const TensorT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct TensorBuilder { + typedef Tensor Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_shape(flatbuffers::Offset> shape) { + fbb_.AddOffset(Tensor::VT_SHAPE, shape); + } + void add_type(tflite::TensorType type) { + fbb_.AddElement(Tensor::VT_TYPE, static_cast(type), 0); + } + void add_buffer(uint32_t buffer) { + fbb_.AddElement(Tensor::VT_BUFFER, buffer, 0); + } + void add_name(flatbuffers::Offset name) { + fbb_.AddOffset(Tensor::VT_NAME, name); + } + void add_quantization(flatbuffers::Offset quantization) { + fbb_.AddOffset(Tensor::VT_QUANTIZATION, quantization); + } + void add_is_variable(bool is_variable) { + fbb_.AddElement(Tensor::VT_IS_VARIABLE, static_cast(is_variable), 0); + } + void add_sparsity(flatbuffers::Offset sparsity) { + fbb_.AddOffset(Tensor::VT_SPARSITY, sparsity); + } + void add_shape_signature(flatbuffers::Offset> shape_signature) { + fbb_.AddOffset(Tensor::VT_SHAPE_SIGNATURE, shape_signature); + } + void add_has_rank(bool has_rank) { + fbb_.AddElement(Tensor::VT_HAS_RANK, static_cast(has_rank), 0); + } + void add_variant_tensors(flatbuffers::Offset>> variant_tensors) { + fbb_.AddOffset(Tensor::VT_VARIANT_TENSORS, variant_tensors); + } + explicit TensorBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTensor( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> shape = 0, + tflite::TensorType type = tflite::TensorType_FLOAT32, + uint32_t buffer = 0, + flatbuffers::Offset name = 0, + flatbuffers::Offset quantization = 0, + bool is_variable = false, + flatbuffers::Offset sparsity = 0, + flatbuffers::Offset> shape_signature = 0, + bool has_rank = false, + flatbuffers::Offset>> variant_tensors = 0) { + TensorBuilder builder_(_fbb); + builder_.add_variant_tensors(variant_tensors); + builder_.add_shape_signature(shape_signature); + builder_.add_sparsity(sparsity); + builder_.add_quantization(quantization); + builder_.add_name(name); + builder_.add_buffer(buffer); + builder_.add_shape(shape); + builder_.add_has_rank(has_rank); + builder_.add_is_variable(is_variable); + builder_.add_type(type); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTensorDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *shape = nullptr, + tflite::TensorType type = tflite::TensorType_FLOAT32, + uint32_t buffer = 0, + const char *name = nullptr, + flatbuffers::Offset quantization = 0, + bool is_variable = false, + flatbuffers::Offset sparsity = 0, + const std::vector *shape_signature = nullptr, + bool has_rank = false, + const std::vector> *variant_tensors = nullptr) { + auto shape__ = shape ? _fbb.CreateVector(*shape) : 0; + auto name__ = name ? _fbb.CreateString(name) : 0; + auto shape_signature__ = shape_signature ? _fbb.CreateVector(*shape_signature) : 0; + auto variant_tensors__ = variant_tensors ? _fbb.CreateVector>(*variant_tensors) : 0; + return tflite::CreateTensor( + _fbb, + shape__, + type, + buffer, + name__, + quantization, + is_variable, + sparsity, + shape_signature__, + has_rank, + variant_tensors__); +} + +flatbuffers::Offset CreateTensor(flatbuffers::FlatBufferBuilder &_fbb, const TensorT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct Conv2DOptionsT : public flatbuffers::NativeTable { + typedef Conv2DOptions TableType; + tflite::Padding padding = tflite::Padding_SAME; + int32_t stride_w = 0; + int32_t stride_h = 0; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + int32_t dilation_w_factor = 1; + int32_t dilation_h_factor = 1; +}; + +struct Conv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef Conv2DOptionsT NativeTableType; + typedef Conv2DOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_PADDING = 4, + VT_STRIDE_W = 6, + VT_STRIDE_H = 8, + VT_FUSED_ACTIVATION_FUNCTION = 10, + VT_DILATION_W_FACTOR = 12, + VT_DILATION_H_FACTOR = 14 + }; + tflite::Padding padding() const { + return static_cast(GetField(VT_PADDING, 0)); + } + int32_t stride_w() const { + return GetField(VT_STRIDE_W, 0); + } + int32_t stride_h() const { + return GetField(VT_STRIDE_H, 0); + } + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + int32_t dilation_w_factor() const { + return GetField(VT_DILATION_W_FACTOR, 1); + } + int32_t dilation_h_factor() const { + return GetField(VT_DILATION_H_FACTOR, 1); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_PADDING, 1) && + VerifyField(verifier, VT_STRIDE_W, 4) && + VerifyField(verifier, VT_STRIDE_H, 4) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_DILATION_W_FACTOR, 4) && + VerifyField(verifier, VT_DILATION_H_FACTOR, 4) && + verifier.EndTable(); + } + Conv2DOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(Conv2DOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct Conv2DOptionsBuilder { + typedef Conv2DOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_padding(tflite::Padding padding) { + fbb_.AddElement(Conv2DOptions::VT_PADDING, static_cast(padding), 0); + } + void add_stride_w(int32_t stride_w) { + fbb_.AddElement(Conv2DOptions::VT_STRIDE_W, stride_w, 0); + } + void add_stride_h(int32_t stride_h) { + fbb_.AddElement(Conv2DOptions::VT_STRIDE_H, stride_h, 0); + } + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(Conv2DOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_dilation_w_factor(int32_t dilation_w_factor) { + fbb_.AddElement(Conv2DOptions::VT_DILATION_W_FACTOR, dilation_w_factor, 1); + } + void add_dilation_h_factor(int32_t dilation_h_factor) { + fbb_.AddElement(Conv2DOptions::VT_DILATION_H_FACTOR, dilation_h_factor, 1); + } + explicit Conv2DOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateConv2DOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::Padding padding = tflite::Padding_SAME, + int32_t stride_w = 0, + int32_t stride_h = 0, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + int32_t dilation_w_factor = 1, + int32_t dilation_h_factor = 1) { + Conv2DOptionsBuilder builder_(_fbb); + builder_.add_dilation_h_factor(dilation_h_factor); + builder_.add_dilation_w_factor(dilation_w_factor); + builder_.add_stride_h(stride_h); + builder_.add_stride_w(stride_w); + builder_.add_fused_activation_function(fused_activation_function); + builder_.add_padding(padding); + return builder_.Finish(); +} + +flatbuffers::Offset CreateConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct Conv3DOptionsT : public flatbuffers::NativeTable { + typedef Conv3DOptions TableType; + tflite::Padding padding = tflite::Padding_SAME; + int32_t stride_d = 0; + int32_t stride_w = 0; + int32_t stride_h = 0; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + int32_t dilation_d_factor = 1; + int32_t dilation_w_factor = 1; + int32_t dilation_h_factor = 1; +}; + +struct Conv3DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef Conv3DOptionsT NativeTableType; + typedef Conv3DOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_PADDING = 4, + VT_STRIDE_D = 6, + VT_STRIDE_W = 8, + VT_STRIDE_H = 10, + VT_FUSED_ACTIVATION_FUNCTION = 12, + VT_DILATION_D_FACTOR = 14, + VT_DILATION_W_FACTOR = 16, + VT_DILATION_H_FACTOR = 18 + }; + tflite::Padding padding() const { + return static_cast(GetField(VT_PADDING, 0)); + } + int32_t stride_d() const { + return GetField(VT_STRIDE_D, 0); + } + int32_t stride_w() const { + return GetField(VT_STRIDE_W, 0); + } + int32_t stride_h() const { + return GetField(VT_STRIDE_H, 0); + } + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + int32_t dilation_d_factor() const { + return GetField(VT_DILATION_D_FACTOR, 1); + } + int32_t dilation_w_factor() const { + return GetField(VT_DILATION_W_FACTOR, 1); + } + int32_t dilation_h_factor() const { + return GetField(VT_DILATION_H_FACTOR, 1); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_PADDING, 1) && + VerifyField(verifier, VT_STRIDE_D, 4) && + VerifyField(verifier, VT_STRIDE_W, 4) && + VerifyField(verifier, VT_STRIDE_H, 4) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_DILATION_D_FACTOR, 4) && + VerifyField(verifier, VT_DILATION_W_FACTOR, 4) && + VerifyField(verifier, VT_DILATION_H_FACTOR, 4) && + verifier.EndTable(); + } + Conv3DOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(Conv3DOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct Conv3DOptionsBuilder { + typedef Conv3DOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_padding(tflite::Padding padding) { + fbb_.AddElement(Conv3DOptions::VT_PADDING, static_cast(padding), 0); + } + void add_stride_d(int32_t stride_d) { + fbb_.AddElement(Conv3DOptions::VT_STRIDE_D, stride_d, 0); + } + void add_stride_w(int32_t stride_w) { + fbb_.AddElement(Conv3DOptions::VT_STRIDE_W, stride_w, 0); + } + void add_stride_h(int32_t stride_h) { + fbb_.AddElement(Conv3DOptions::VT_STRIDE_H, stride_h, 0); + } + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(Conv3DOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_dilation_d_factor(int32_t dilation_d_factor) { + fbb_.AddElement(Conv3DOptions::VT_DILATION_D_FACTOR, dilation_d_factor, 1); + } + void add_dilation_w_factor(int32_t dilation_w_factor) { + fbb_.AddElement(Conv3DOptions::VT_DILATION_W_FACTOR, dilation_w_factor, 1); + } + void add_dilation_h_factor(int32_t dilation_h_factor) { + fbb_.AddElement(Conv3DOptions::VT_DILATION_H_FACTOR, dilation_h_factor, 1); + } + explicit Conv3DOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateConv3DOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::Padding padding = tflite::Padding_SAME, + int32_t stride_d = 0, + int32_t stride_w = 0, + int32_t stride_h = 0, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + int32_t dilation_d_factor = 1, + int32_t dilation_w_factor = 1, + int32_t dilation_h_factor = 1) { + Conv3DOptionsBuilder builder_(_fbb); + builder_.add_dilation_h_factor(dilation_h_factor); + builder_.add_dilation_w_factor(dilation_w_factor); + builder_.add_dilation_d_factor(dilation_d_factor); + builder_.add_stride_h(stride_h); + builder_.add_stride_w(stride_w); + builder_.add_stride_d(stride_d); + builder_.add_fused_activation_function(fused_activation_function); + builder_.add_padding(padding); + return builder_.Finish(); +} + +flatbuffers::Offset CreateConv3DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct Pool2DOptionsT : public flatbuffers::NativeTable { + typedef Pool2DOptions TableType; + tflite::Padding padding = tflite::Padding_SAME; + int32_t stride_w = 0; + int32_t stride_h = 0; + int32_t filter_width = 0; + int32_t filter_height = 0; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; +}; + +struct Pool2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef Pool2DOptionsT NativeTableType; + typedef Pool2DOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_PADDING = 4, + VT_STRIDE_W = 6, + VT_STRIDE_H = 8, + VT_FILTER_WIDTH = 10, + VT_FILTER_HEIGHT = 12, + VT_FUSED_ACTIVATION_FUNCTION = 14 + }; + tflite::Padding padding() const { + return static_cast(GetField(VT_PADDING, 0)); + } + int32_t stride_w() const { + return GetField(VT_STRIDE_W, 0); + } + int32_t stride_h() const { + return GetField(VT_STRIDE_H, 0); + } + int32_t filter_width() const { + return GetField(VT_FILTER_WIDTH, 0); + } + int32_t filter_height() const { + return GetField(VT_FILTER_HEIGHT, 0); + } + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_PADDING, 1) && + VerifyField(verifier, VT_STRIDE_W, 4) && + VerifyField(verifier, VT_STRIDE_H, 4) && + VerifyField(verifier, VT_FILTER_WIDTH, 4) && + VerifyField(verifier, VT_FILTER_HEIGHT, 4) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + verifier.EndTable(); + } + Pool2DOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(Pool2DOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct Pool2DOptionsBuilder { + typedef Pool2DOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_padding(tflite::Padding padding) { + fbb_.AddElement(Pool2DOptions::VT_PADDING, static_cast(padding), 0); + } + void add_stride_w(int32_t stride_w) { + fbb_.AddElement(Pool2DOptions::VT_STRIDE_W, stride_w, 0); + } + void add_stride_h(int32_t stride_h) { + fbb_.AddElement(Pool2DOptions::VT_STRIDE_H, stride_h, 0); + } + void add_filter_width(int32_t filter_width) { + fbb_.AddElement(Pool2DOptions::VT_FILTER_WIDTH, filter_width, 0); + } + void add_filter_height(int32_t filter_height) { + fbb_.AddElement(Pool2DOptions::VT_FILTER_HEIGHT, filter_height, 0); + } + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(Pool2DOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + explicit Pool2DOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreatePool2DOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::Padding padding = tflite::Padding_SAME, + int32_t stride_w = 0, + int32_t stride_h = 0, + int32_t filter_width = 0, + int32_t filter_height = 0, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE) { + Pool2DOptionsBuilder builder_(_fbb); + builder_.add_filter_height(filter_height); + builder_.add_filter_width(filter_width); + builder_.add_stride_h(stride_h); + builder_.add_stride_w(stride_w); + builder_.add_fused_activation_function(fused_activation_function); + builder_.add_padding(padding); + return builder_.Finish(); +} + +flatbuffers::Offset CreatePool2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct DepthwiseConv2DOptionsT : public flatbuffers::NativeTable { + typedef DepthwiseConv2DOptions TableType; + tflite::Padding padding = tflite::Padding_SAME; + int32_t stride_w = 0; + int32_t stride_h = 0; + int32_t depth_multiplier = 0; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + int32_t dilation_w_factor = 1; + int32_t dilation_h_factor = 1; +}; + +struct DepthwiseConv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef DepthwiseConv2DOptionsT NativeTableType; + typedef DepthwiseConv2DOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_PADDING = 4, + VT_STRIDE_W = 6, + VT_STRIDE_H = 8, + VT_DEPTH_MULTIPLIER = 10, + VT_FUSED_ACTIVATION_FUNCTION = 12, + VT_DILATION_W_FACTOR = 14, + VT_DILATION_H_FACTOR = 16 + }; + tflite::Padding padding() const { + return static_cast(GetField(VT_PADDING, 0)); + } + int32_t stride_w() const { + return GetField(VT_STRIDE_W, 0); + } + int32_t stride_h() const { + return GetField(VT_STRIDE_H, 0); + } + int32_t depth_multiplier() const { + return GetField(VT_DEPTH_MULTIPLIER, 0); + } + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + int32_t dilation_w_factor() const { + return GetField(VT_DILATION_W_FACTOR, 1); + } + int32_t dilation_h_factor() const { + return GetField(VT_DILATION_H_FACTOR, 1); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_PADDING, 1) && + VerifyField(verifier, VT_STRIDE_W, 4) && + VerifyField(verifier, VT_STRIDE_H, 4) && + VerifyField(verifier, VT_DEPTH_MULTIPLIER, 4) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_DILATION_W_FACTOR, 4) && + VerifyField(verifier, VT_DILATION_H_FACTOR, 4) && + verifier.EndTable(); + } + DepthwiseConv2DOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(DepthwiseConv2DOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const DepthwiseConv2DOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct DepthwiseConv2DOptionsBuilder { + typedef DepthwiseConv2DOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_padding(tflite::Padding padding) { + fbb_.AddElement(DepthwiseConv2DOptions::VT_PADDING, static_cast(padding), 0); + } + void add_stride_w(int32_t stride_w) { + fbb_.AddElement(DepthwiseConv2DOptions::VT_STRIDE_W, stride_w, 0); + } + void add_stride_h(int32_t stride_h) { + fbb_.AddElement(DepthwiseConv2DOptions::VT_STRIDE_H, stride_h, 0); + } + void add_depth_multiplier(int32_t depth_multiplier) { + fbb_.AddElement(DepthwiseConv2DOptions::VT_DEPTH_MULTIPLIER, depth_multiplier, 0); + } + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(DepthwiseConv2DOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_dilation_w_factor(int32_t dilation_w_factor) { + fbb_.AddElement(DepthwiseConv2DOptions::VT_DILATION_W_FACTOR, dilation_w_factor, 1); + } + void add_dilation_h_factor(int32_t dilation_h_factor) { + fbb_.AddElement(DepthwiseConv2DOptions::VT_DILATION_H_FACTOR, dilation_h_factor, 1); + } + explicit DepthwiseConv2DOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateDepthwiseConv2DOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::Padding padding = tflite::Padding_SAME, + int32_t stride_w = 0, + int32_t stride_h = 0, + int32_t depth_multiplier = 0, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + int32_t dilation_w_factor = 1, + int32_t dilation_h_factor = 1) { + DepthwiseConv2DOptionsBuilder builder_(_fbb); + builder_.add_dilation_h_factor(dilation_h_factor); + builder_.add_dilation_w_factor(dilation_w_factor); + builder_.add_depth_multiplier(depth_multiplier); + builder_.add_stride_h(stride_h); + builder_.add_stride_w(stride_w); + builder_.add_fused_activation_function(fused_activation_function); + builder_.add_padding(padding); + return builder_.Finish(); +} + +flatbuffers::Offset CreateDepthwiseConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const DepthwiseConv2DOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ConcatEmbeddingsOptionsT : public flatbuffers::NativeTable { + typedef ConcatEmbeddingsOptions TableType; + int32_t num_channels = 0; + std::vector num_columns_per_channel{}; + std::vector embedding_dim_per_channel{}; +}; + +struct ConcatEmbeddingsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ConcatEmbeddingsOptionsT NativeTableType; + typedef ConcatEmbeddingsOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NUM_CHANNELS = 4, + VT_NUM_COLUMNS_PER_CHANNEL = 6, + VT_EMBEDDING_DIM_PER_CHANNEL = 8 + }; + int32_t num_channels() const { + return GetField(VT_NUM_CHANNELS, 0); + } + const flatbuffers::Vector *num_columns_per_channel() const { + return GetPointer *>(VT_NUM_COLUMNS_PER_CHANNEL); + } + const flatbuffers::Vector *embedding_dim_per_channel() const { + return GetPointer *>(VT_EMBEDDING_DIM_PER_CHANNEL); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_NUM_CHANNELS, 4) && + VerifyOffset(verifier, VT_NUM_COLUMNS_PER_CHANNEL) && + verifier.VerifyVector(num_columns_per_channel()) && + VerifyOffset(verifier, VT_EMBEDDING_DIM_PER_CHANNEL) && + verifier.VerifyVector(embedding_dim_per_channel()) && + verifier.EndTable(); + } + ConcatEmbeddingsOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ConcatEmbeddingsOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ConcatEmbeddingsOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ConcatEmbeddingsOptionsBuilder { + typedef ConcatEmbeddingsOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_num_channels(int32_t num_channels) { + fbb_.AddElement(ConcatEmbeddingsOptions::VT_NUM_CHANNELS, num_channels, 0); + } + void add_num_columns_per_channel(flatbuffers::Offset> num_columns_per_channel) { + fbb_.AddOffset(ConcatEmbeddingsOptions::VT_NUM_COLUMNS_PER_CHANNEL, num_columns_per_channel); + } + void add_embedding_dim_per_channel(flatbuffers::Offset> embedding_dim_per_channel) { + fbb_.AddOffset(ConcatEmbeddingsOptions::VT_EMBEDDING_DIM_PER_CHANNEL, embedding_dim_per_channel); + } + explicit ConcatEmbeddingsOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateConcatEmbeddingsOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t num_channels = 0, + flatbuffers::Offset> num_columns_per_channel = 0, + flatbuffers::Offset> embedding_dim_per_channel = 0) { + ConcatEmbeddingsOptionsBuilder builder_(_fbb); + builder_.add_embedding_dim_per_channel(embedding_dim_per_channel); + builder_.add_num_columns_per_channel(num_columns_per_channel); + builder_.add_num_channels(num_channels); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateConcatEmbeddingsOptionsDirect( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t num_channels = 0, + const std::vector *num_columns_per_channel = nullptr, + const std::vector *embedding_dim_per_channel = nullptr) { + auto num_columns_per_channel__ = num_columns_per_channel ? _fbb.CreateVector(*num_columns_per_channel) : 0; + auto embedding_dim_per_channel__ = embedding_dim_per_channel ? _fbb.CreateVector(*embedding_dim_per_channel) : 0; + return tflite::CreateConcatEmbeddingsOptions( + _fbb, + num_channels, + num_columns_per_channel__, + embedding_dim_per_channel__); +} + +flatbuffers::Offset CreateConcatEmbeddingsOptions(flatbuffers::FlatBufferBuilder &_fbb, const ConcatEmbeddingsOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LSHProjectionOptionsT : public flatbuffers::NativeTable { + typedef LSHProjectionOptions TableType; + tflite::LSHProjectionType type = tflite::LSHProjectionType_UNKNOWN; +}; + +struct LSHProjectionOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LSHProjectionOptionsT NativeTableType; + typedef LSHProjectionOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_TYPE = 4 + }; + tflite::LSHProjectionType type() const { + return static_cast(GetField(VT_TYPE, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_TYPE, 1) && + verifier.EndTable(); + } + LSHProjectionOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LSHProjectionOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LSHProjectionOptionsBuilder { + typedef LSHProjectionOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_type(tflite::LSHProjectionType type) { + fbb_.AddElement(LSHProjectionOptions::VT_TYPE, static_cast(type), 0); + } + explicit LSHProjectionOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLSHProjectionOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::LSHProjectionType type = tflite::LSHProjectionType_UNKNOWN) { + LSHProjectionOptionsBuilder builder_(_fbb); + builder_.add_type(type); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLSHProjectionOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SVDFOptionsT : public flatbuffers::NativeTable { + typedef SVDFOptions TableType; + int32_t rank = 0; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + bool asymmetric_quantize_inputs = false; +}; + +struct SVDFOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SVDFOptionsT NativeTableType; + typedef SVDFOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_RANK = 4, + VT_FUSED_ACTIVATION_FUNCTION = 6, + VT_ASYMMETRIC_QUANTIZE_INPUTS = 8 + }; + int32_t rank() const { + return GetField(VT_RANK, 0); + } + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool asymmetric_quantize_inputs() const { + return GetField(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_RANK, 4) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && + verifier.EndTable(); + } + SVDFOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SVDFOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SVDFOptionsBuilder { + typedef SVDFOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_rank(int32_t rank) { + fbb_.AddElement(SVDFOptions::VT_RANK, rank, 0); + } + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(SVDFOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs) { + fbb_.AddElement(SVDFOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS, static_cast(asymmetric_quantize_inputs), 0); + } + explicit SVDFOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSVDFOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t rank = 0, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + bool asymmetric_quantize_inputs = false) { + SVDFOptionsBuilder builder_(_fbb); + builder_.add_rank(rank); + builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSVDFOptions(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct RNNOptionsT : public flatbuffers::NativeTable { + typedef RNNOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + bool asymmetric_quantize_inputs = false; +}; + +struct RNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef RNNOptionsT NativeTableType; + typedef RNNOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4, + VT_ASYMMETRIC_QUANTIZE_INPUTS = 6 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool asymmetric_quantize_inputs() const { + return GetField(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && + verifier.EndTable(); + } + RNNOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RNNOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct RNNOptionsBuilder { + typedef RNNOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(RNNOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs) { + fbb_.AddElement(RNNOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS, static_cast(asymmetric_quantize_inputs), 0); + } + explicit RNNOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateRNNOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + bool asymmetric_quantize_inputs = false) { + RNNOptionsBuilder builder_(_fbb); + builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SequenceRNNOptionsT : public flatbuffers::NativeTable { + typedef SequenceRNNOptions TableType; + bool time_major = false; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + bool asymmetric_quantize_inputs = false; +}; + +struct SequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SequenceRNNOptionsT NativeTableType; + typedef SequenceRNNOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_TIME_MAJOR = 4, + VT_FUSED_ACTIVATION_FUNCTION = 6, + VT_ASYMMETRIC_QUANTIZE_INPUTS = 8 + }; + bool time_major() const { + return GetField(VT_TIME_MAJOR, 0) != 0; + } + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool asymmetric_quantize_inputs() const { + return GetField(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_TIME_MAJOR, 1) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && + verifier.EndTable(); + } + SequenceRNNOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SequenceRNNOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SequenceRNNOptionsBuilder { + typedef SequenceRNNOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_time_major(bool time_major) { + fbb_.AddElement(SequenceRNNOptions::VT_TIME_MAJOR, static_cast(time_major), 0); + } + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(SequenceRNNOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs) { + fbb_.AddElement(SequenceRNNOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS, static_cast(asymmetric_quantize_inputs), 0); + } + explicit SequenceRNNOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSequenceRNNOptions( + flatbuffers::FlatBufferBuilder &_fbb, + bool time_major = false, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + bool asymmetric_quantize_inputs = false) { + SequenceRNNOptionsBuilder builder_(_fbb); + builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs); + builder_.add_fused_activation_function(fused_activation_function); + builder_.add_time_major(time_major); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct BidirectionalSequenceRNNOptionsT : public flatbuffers::NativeTable { + typedef BidirectionalSequenceRNNOptions TableType; + bool time_major = false; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + bool merge_outputs = false; + bool asymmetric_quantize_inputs = false; +}; + +struct BidirectionalSequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef BidirectionalSequenceRNNOptionsT NativeTableType; + typedef BidirectionalSequenceRNNOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_TIME_MAJOR = 4, + VT_FUSED_ACTIVATION_FUNCTION = 6, + VT_MERGE_OUTPUTS = 8, + VT_ASYMMETRIC_QUANTIZE_INPUTS = 10 + }; + bool time_major() const { + return GetField(VT_TIME_MAJOR, 0) != 0; + } + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool merge_outputs() const { + return GetField(VT_MERGE_OUTPUTS, 0) != 0; + } + bool asymmetric_quantize_inputs() const { + return GetField(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_TIME_MAJOR, 1) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_MERGE_OUTPUTS, 1) && + VerifyField(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && + verifier.EndTable(); + } + BidirectionalSequenceRNNOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(BidirectionalSequenceRNNOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceRNNOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct BidirectionalSequenceRNNOptionsBuilder { + typedef BidirectionalSequenceRNNOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_time_major(bool time_major) { + fbb_.AddElement(BidirectionalSequenceRNNOptions::VT_TIME_MAJOR, static_cast(time_major), 0); + } + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(BidirectionalSequenceRNNOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_merge_outputs(bool merge_outputs) { + fbb_.AddElement(BidirectionalSequenceRNNOptions::VT_MERGE_OUTPUTS, static_cast(merge_outputs), 0); + } + void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs) { + fbb_.AddElement(BidirectionalSequenceRNNOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS, static_cast(asymmetric_quantize_inputs), 0); + } + explicit BidirectionalSequenceRNNOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateBidirectionalSequenceRNNOptions( + flatbuffers::FlatBufferBuilder &_fbb, + bool time_major = false, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + bool merge_outputs = false, + bool asymmetric_quantize_inputs = false) { + BidirectionalSequenceRNNOptionsBuilder builder_(_fbb); + builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs); + builder_.add_merge_outputs(merge_outputs); + builder_.add_fused_activation_function(fused_activation_function); + builder_.add_time_major(time_major); + return builder_.Finish(); +} + +flatbuffers::Offset CreateBidirectionalSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceRNNOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct FullyConnectedOptionsT : public flatbuffers::NativeTable { + typedef FullyConnectedOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + tflite::FullyConnectedOptionsWeightsFormat weights_format = tflite::FullyConnectedOptionsWeightsFormat_DEFAULT; + bool keep_num_dims = false; + bool asymmetric_quantize_inputs = false; +}; + +struct FullyConnectedOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FullyConnectedOptionsT NativeTableType; + typedef FullyConnectedOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4, + VT_WEIGHTS_FORMAT = 6, + VT_KEEP_NUM_DIMS = 8, + VT_ASYMMETRIC_QUANTIZE_INPUTS = 10 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + tflite::FullyConnectedOptionsWeightsFormat weights_format() const { + return static_cast(GetField(VT_WEIGHTS_FORMAT, 0)); + } + bool keep_num_dims() const { + return GetField(VT_KEEP_NUM_DIMS, 0) != 0; + } + bool asymmetric_quantize_inputs() const { + return GetField(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_WEIGHTS_FORMAT, 1) && + VerifyField(verifier, VT_KEEP_NUM_DIMS, 1) && + VerifyField(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && + verifier.EndTable(); + } + FullyConnectedOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(FullyConnectedOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct FullyConnectedOptionsBuilder { + typedef FullyConnectedOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(FullyConnectedOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_weights_format(tflite::FullyConnectedOptionsWeightsFormat weights_format) { + fbb_.AddElement(FullyConnectedOptions::VT_WEIGHTS_FORMAT, static_cast(weights_format), 0); + } + void add_keep_num_dims(bool keep_num_dims) { + fbb_.AddElement(FullyConnectedOptions::VT_KEEP_NUM_DIMS, static_cast(keep_num_dims), 0); + } + void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs) { + fbb_.AddElement(FullyConnectedOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS, static_cast(asymmetric_quantize_inputs), 0); + } + explicit FullyConnectedOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateFullyConnectedOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + tflite::FullyConnectedOptionsWeightsFormat weights_format = tflite::FullyConnectedOptionsWeightsFormat_DEFAULT, + bool keep_num_dims = false, + bool asymmetric_quantize_inputs = false) { + FullyConnectedOptionsBuilder builder_(_fbb); + builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs); + builder_.add_keep_num_dims(keep_num_dims); + builder_.add_weights_format(weights_format); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateFullyConnectedOptions(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SoftmaxOptionsT : public flatbuffers::NativeTable { + typedef SoftmaxOptions TableType; + float beta = 0.0f; +}; + +struct SoftmaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SoftmaxOptionsT NativeTableType; + typedef SoftmaxOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_BETA = 4 + }; + float beta() const { + return GetField(VT_BETA, 0.0f); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_BETA, 4) && + verifier.EndTable(); + } + SoftmaxOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SoftmaxOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SoftmaxOptionsBuilder { + typedef SoftmaxOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_beta(float beta) { + fbb_.AddElement(SoftmaxOptions::VT_BETA, beta, 0.0f); + } + explicit SoftmaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSoftmaxOptions( + flatbuffers::FlatBufferBuilder &_fbb, + float beta = 0.0f) { + SoftmaxOptionsBuilder builder_(_fbb); + builder_.add_beta(beta); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ConcatenationOptionsT : public flatbuffers::NativeTable { + typedef ConcatenationOptions TableType; + int32_t axis = 0; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; +}; + +struct ConcatenationOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ConcatenationOptionsT NativeTableType; + typedef ConcatenationOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_AXIS = 4, + VT_FUSED_ACTIVATION_FUNCTION = 6 + }; + int32_t axis() const { + return GetField(VT_AXIS, 0); + } + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_AXIS, 4) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + verifier.EndTable(); + } + ConcatenationOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ConcatenationOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ConcatenationOptionsBuilder { + typedef ConcatenationOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_axis(int32_t axis) { + fbb_.AddElement(ConcatenationOptions::VT_AXIS, axis, 0); + } + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(ConcatenationOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + explicit ConcatenationOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateConcatenationOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t axis = 0, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE) { + ConcatenationOptionsBuilder builder_(_fbb); + builder_.add_axis(axis); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateConcatenationOptions(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct AddOptionsT : public flatbuffers::NativeTable { + typedef AddOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + bool pot_scale_int16 = true; +}; + +struct AddOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef AddOptionsT NativeTableType; + typedef AddOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4, + VT_POT_SCALE_INT16 = 6 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool pot_scale_int16() const { + return GetField(VT_POT_SCALE_INT16, 1) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_POT_SCALE_INT16, 1) && + verifier.EndTable(); + } + AddOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(AddOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct AddOptionsBuilder { + typedef AddOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(AddOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_pot_scale_int16(bool pot_scale_int16) { + fbb_.AddElement(AddOptions::VT_POT_SCALE_INT16, static_cast(pot_scale_int16), 1); + } + explicit AddOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateAddOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + bool pot_scale_int16 = true) { + AddOptionsBuilder builder_(_fbb); + builder_.add_pot_scale_int16(pot_scale_int16); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateAddOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct MulOptionsT : public flatbuffers::NativeTable { + typedef MulOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; +}; + +struct MulOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef MulOptionsT NativeTableType; + typedef MulOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + verifier.EndTable(); + } + MulOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(MulOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct MulOptionsBuilder { + typedef MulOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(MulOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + explicit MulOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateMulOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE) { + MulOptionsBuilder builder_(_fbb); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct L2NormOptionsT : public flatbuffers::NativeTable { + typedef L2NormOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; +}; + +struct L2NormOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef L2NormOptionsT NativeTableType; + typedef L2NormOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + verifier.EndTable(); + } + L2NormOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(L2NormOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct L2NormOptionsBuilder { + typedef L2NormOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(L2NormOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + explicit L2NormOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateL2NormOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE) { + L2NormOptionsBuilder builder_(_fbb); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateL2NormOptions(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LocalResponseNormalizationOptionsT : public flatbuffers::NativeTable { + typedef LocalResponseNormalizationOptions TableType; + int32_t radius = 0; + float bias = 0.0f; + float alpha = 0.0f; + float beta = 0.0f; +}; + +struct LocalResponseNormalizationOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LocalResponseNormalizationOptionsT NativeTableType; + typedef LocalResponseNormalizationOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_RADIUS = 4, + VT_BIAS = 6, + VT_ALPHA = 8, + VT_BETA = 10 + }; + int32_t radius() const { + return GetField(VT_RADIUS, 0); + } + float bias() const { + return GetField(VT_BIAS, 0.0f); + } + float alpha() const { + return GetField(VT_ALPHA, 0.0f); + } + float beta() const { + return GetField(VT_BETA, 0.0f); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_RADIUS, 4) && + VerifyField(verifier, VT_BIAS, 4) && + VerifyField(verifier, VT_ALPHA, 4) && + VerifyField(verifier, VT_BETA, 4) && + verifier.EndTable(); + } + LocalResponseNormalizationOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LocalResponseNormalizationOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LocalResponseNormalizationOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LocalResponseNormalizationOptionsBuilder { + typedef LocalResponseNormalizationOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_radius(int32_t radius) { + fbb_.AddElement(LocalResponseNormalizationOptions::VT_RADIUS, radius, 0); + } + void add_bias(float bias) { + fbb_.AddElement(LocalResponseNormalizationOptions::VT_BIAS, bias, 0.0f); + } + void add_alpha(float alpha) { + fbb_.AddElement(LocalResponseNormalizationOptions::VT_ALPHA, alpha, 0.0f); + } + void add_beta(float beta) { + fbb_.AddElement(LocalResponseNormalizationOptions::VT_BETA, beta, 0.0f); + } + explicit LocalResponseNormalizationOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLocalResponseNormalizationOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t radius = 0, + float bias = 0.0f, + float alpha = 0.0f, + float beta = 0.0f) { + LocalResponseNormalizationOptionsBuilder builder_(_fbb); + builder_.add_beta(beta); + builder_.add_alpha(alpha); + builder_.add_bias(bias); + builder_.add_radius(radius); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLocalResponseNormalizationOptions(flatbuffers::FlatBufferBuilder &_fbb, const LocalResponseNormalizationOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LSTMOptionsT : public flatbuffers::NativeTable { + typedef LSTMOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + float cell_clip = 0.0f; + float proj_clip = 0.0f; + tflite::LSTMKernelType kernel_type = tflite::LSTMKernelType_FULL; + bool asymmetric_quantize_inputs = false; +}; + +struct LSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LSTMOptionsT NativeTableType; + typedef LSTMOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4, + VT_CELL_CLIP = 6, + VT_PROJ_CLIP = 8, + VT_KERNEL_TYPE = 10, + VT_ASYMMETRIC_QUANTIZE_INPUTS = 12 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + float cell_clip() const { + return GetField(VT_CELL_CLIP, 0.0f); + } + float proj_clip() const { + return GetField(VT_PROJ_CLIP, 0.0f); + } + tflite::LSTMKernelType kernel_type() const { + return static_cast(GetField(VT_KERNEL_TYPE, 0)); + } + bool asymmetric_quantize_inputs() const { + return GetField(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_CELL_CLIP, 4) && + VerifyField(verifier, VT_PROJ_CLIP, 4) && + VerifyField(verifier, VT_KERNEL_TYPE, 1) && + VerifyField(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && + verifier.EndTable(); + } + LSTMOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LSTMOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LSTMOptionsBuilder { + typedef LSTMOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(LSTMOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_cell_clip(float cell_clip) { + fbb_.AddElement(LSTMOptions::VT_CELL_CLIP, cell_clip, 0.0f); + } + void add_proj_clip(float proj_clip) { + fbb_.AddElement(LSTMOptions::VT_PROJ_CLIP, proj_clip, 0.0f); + } + void add_kernel_type(tflite::LSTMKernelType kernel_type) { + fbb_.AddElement(LSTMOptions::VT_KERNEL_TYPE, static_cast(kernel_type), 0); + } + void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs) { + fbb_.AddElement(LSTMOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS, static_cast(asymmetric_quantize_inputs), 0); + } + explicit LSTMOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLSTMOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + float cell_clip = 0.0f, + float proj_clip = 0.0f, + tflite::LSTMKernelType kernel_type = tflite::LSTMKernelType_FULL, + bool asymmetric_quantize_inputs = false) { + LSTMOptionsBuilder builder_(_fbb); + builder_.add_proj_clip(proj_clip); + builder_.add_cell_clip(cell_clip); + builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs); + builder_.add_kernel_type(kernel_type); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct UnidirectionalSequenceLSTMOptionsT : public flatbuffers::NativeTable { + typedef UnidirectionalSequenceLSTMOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + float cell_clip = 0.0f; + float proj_clip = 0.0f; + bool time_major = false; + bool asymmetric_quantize_inputs = false; +}; + +struct UnidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef UnidirectionalSequenceLSTMOptionsT NativeTableType; + typedef UnidirectionalSequenceLSTMOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4, + VT_CELL_CLIP = 6, + VT_PROJ_CLIP = 8, + VT_TIME_MAJOR = 10, + VT_ASYMMETRIC_QUANTIZE_INPUTS = 12 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + float cell_clip() const { + return GetField(VT_CELL_CLIP, 0.0f); + } + float proj_clip() const { + return GetField(VT_PROJ_CLIP, 0.0f); + } + bool time_major() const { + return GetField(VT_TIME_MAJOR, 0) != 0; + } + bool asymmetric_quantize_inputs() const { + return GetField(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_CELL_CLIP, 4) && + VerifyField(verifier, VT_PROJ_CLIP, 4) && + VerifyField(verifier, VT_TIME_MAJOR, 1) && + VerifyField(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && + verifier.EndTable(); + } + UnidirectionalSequenceLSTMOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(UnidirectionalSequenceLSTMOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnidirectionalSequenceLSTMOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct UnidirectionalSequenceLSTMOptionsBuilder { + typedef UnidirectionalSequenceLSTMOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(UnidirectionalSequenceLSTMOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_cell_clip(float cell_clip) { + fbb_.AddElement(UnidirectionalSequenceLSTMOptions::VT_CELL_CLIP, cell_clip, 0.0f); + } + void add_proj_clip(float proj_clip) { + fbb_.AddElement(UnidirectionalSequenceLSTMOptions::VT_PROJ_CLIP, proj_clip, 0.0f); + } + void add_time_major(bool time_major) { + fbb_.AddElement(UnidirectionalSequenceLSTMOptions::VT_TIME_MAJOR, static_cast(time_major), 0); + } + void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs) { + fbb_.AddElement(UnidirectionalSequenceLSTMOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS, static_cast(asymmetric_quantize_inputs), 0); + } + explicit UnidirectionalSequenceLSTMOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUnidirectionalSequenceLSTMOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + float cell_clip = 0.0f, + float proj_clip = 0.0f, + bool time_major = false, + bool asymmetric_quantize_inputs = false) { + UnidirectionalSequenceLSTMOptionsBuilder builder_(_fbb); + builder_.add_proj_clip(proj_clip); + builder_.add_cell_clip(cell_clip); + builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs); + builder_.add_time_major(time_major); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateUnidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnidirectionalSequenceLSTMOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct BidirectionalSequenceLSTMOptionsT : public flatbuffers::NativeTable { + typedef BidirectionalSequenceLSTMOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + float cell_clip = 0.0f; + float proj_clip = 0.0f; + bool merge_outputs = false; + bool time_major = true; + bool asymmetric_quantize_inputs = false; +}; + +struct BidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef BidirectionalSequenceLSTMOptionsT NativeTableType; + typedef BidirectionalSequenceLSTMOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4, + VT_CELL_CLIP = 6, + VT_PROJ_CLIP = 8, + VT_MERGE_OUTPUTS = 10, + VT_TIME_MAJOR = 12, + VT_ASYMMETRIC_QUANTIZE_INPUTS = 14 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + float cell_clip() const { + return GetField(VT_CELL_CLIP, 0.0f); + } + float proj_clip() const { + return GetField(VT_PROJ_CLIP, 0.0f); + } + bool merge_outputs() const { + return GetField(VT_MERGE_OUTPUTS, 0) != 0; + } + bool time_major() const { + return GetField(VT_TIME_MAJOR, 1) != 0; + } + bool asymmetric_quantize_inputs() const { + return GetField(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_CELL_CLIP, 4) && + VerifyField(verifier, VT_PROJ_CLIP, 4) && + VerifyField(verifier, VT_MERGE_OUTPUTS, 1) && + VerifyField(verifier, VT_TIME_MAJOR, 1) && + VerifyField(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && + verifier.EndTable(); + } + BidirectionalSequenceLSTMOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(BidirectionalSequenceLSTMOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceLSTMOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct BidirectionalSequenceLSTMOptionsBuilder { + typedef BidirectionalSequenceLSTMOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(BidirectionalSequenceLSTMOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_cell_clip(float cell_clip) { + fbb_.AddElement(BidirectionalSequenceLSTMOptions::VT_CELL_CLIP, cell_clip, 0.0f); + } + void add_proj_clip(float proj_clip) { + fbb_.AddElement(BidirectionalSequenceLSTMOptions::VT_PROJ_CLIP, proj_clip, 0.0f); + } + void add_merge_outputs(bool merge_outputs) { + fbb_.AddElement(BidirectionalSequenceLSTMOptions::VT_MERGE_OUTPUTS, static_cast(merge_outputs), 0); + } + void add_time_major(bool time_major) { + fbb_.AddElement(BidirectionalSequenceLSTMOptions::VT_TIME_MAJOR, static_cast(time_major), 1); + } + void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs) { + fbb_.AddElement(BidirectionalSequenceLSTMOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS, static_cast(asymmetric_quantize_inputs), 0); + } + explicit BidirectionalSequenceLSTMOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateBidirectionalSequenceLSTMOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + float cell_clip = 0.0f, + float proj_clip = 0.0f, + bool merge_outputs = false, + bool time_major = true, + bool asymmetric_quantize_inputs = false) { + BidirectionalSequenceLSTMOptionsBuilder builder_(_fbb); + builder_.add_proj_clip(proj_clip); + builder_.add_cell_clip(cell_clip); + builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs); + builder_.add_time_major(time_major); + builder_.add_merge_outputs(merge_outputs); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateBidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceLSTMOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ResizeBilinearOptionsT : public flatbuffers::NativeTable { + typedef ResizeBilinearOptions TableType; + bool align_corners = false; + bool half_pixel_centers = false; +}; + +struct ResizeBilinearOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ResizeBilinearOptionsT NativeTableType; + typedef ResizeBilinearOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ALIGN_CORNERS = 8, + VT_HALF_PIXEL_CENTERS = 10 + }; + bool align_corners() const { + return GetField(VT_ALIGN_CORNERS, 0) != 0; + } + bool half_pixel_centers() const { + return GetField(VT_HALF_PIXEL_CENTERS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ALIGN_CORNERS, 1) && + VerifyField(verifier, VT_HALF_PIXEL_CENTERS, 1) && + verifier.EndTable(); + } + ResizeBilinearOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ResizeBilinearOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ResizeBilinearOptionsBuilder { + typedef ResizeBilinearOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_align_corners(bool align_corners) { + fbb_.AddElement(ResizeBilinearOptions::VT_ALIGN_CORNERS, static_cast(align_corners), 0); + } + void add_half_pixel_centers(bool half_pixel_centers) { + fbb_.AddElement(ResizeBilinearOptions::VT_HALF_PIXEL_CENTERS, static_cast(half_pixel_centers), 0); + } + explicit ResizeBilinearOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateResizeBilinearOptions( + flatbuffers::FlatBufferBuilder &_fbb, + bool align_corners = false, + bool half_pixel_centers = false) { + ResizeBilinearOptionsBuilder builder_(_fbb); + builder_.add_half_pixel_centers(half_pixel_centers); + builder_.add_align_corners(align_corners); + return builder_.Finish(); +} + +flatbuffers::Offset CreateResizeBilinearOptions(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ResizeNearestNeighborOptionsT : public flatbuffers::NativeTable { + typedef ResizeNearestNeighborOptions TableType; + bool align_corners = false; + bool half_pixel_centers = false; +}; + +struct ResizeNearestNeighborOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ResizeNearestNeighborOptionsT NativeTableType; + typedef ResizeNearestNeighborOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ALIGN_CORNERS = 4, + VT_HALF_PIXEL_CENTERS = 6 + }; + bool align_corners() const { + return GetField(VT_ALIGN_CORNERS, 0) != 0; + } + bool half_pixel_centers() const { + return GetField(VT_HALF_PIXEL_CENTERS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ALIGN_CORNERS, 1) && + VerifyField(verifier, VT_HALF_PIXEL_CENTERS, 1) && + verifier.EndTable(); + } + ResizeNearestNeighborOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ResizeNearestNeighborOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ResizeNearestNeighborOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ResizeNearestNeighborOptionsBuilder { + typedef ResizeNearestNeighborOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_align_corners(bool align_corners) { + fbb_.AddElement(ResizeNearestNeighborOptions::VT_ALIGN_CORNERS, static_cast(align_corners), 0); + } + void add_half_pixel_centers(bool half_pixel_centers) { + fbb_.AddElement(ResizeNearestNeighborOptions::VT_HALF_PIXEL_CENTERS, static_cast(half_pixel_centers), 0); + } + explicit ResizeNearestNeighborOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateResizeNearestNeighborOptions( + flatbuffers::FlatBufferBuilder &_fbb, + bool align_corners = false, + bool half_pixel_centers = false) { + ResizeNearestNeighborOptionsBuilder builder_(_fbb); + builder_.add_half_pixel_centers(half_pixel_centers); + builder_.add_align_corners(align_corners); + return builder_.Finish(); +} + +flatbuffers::Offset CreateResizeNearestNeighborOptions(flatbuffers::FlatBufferBuilder &_fbb, const ResizeNearestNeighborOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct CallOptionsT : public flatbuffers::NativeTable { + typedef CallOptions TableType; + uint32_t subgraph = 0; +}; + +struct CallOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef CallOptionsT NativeTableType; + typedef CallOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SUBGRAPH = 4 + }; + uint32_t subgraph() const { + return GetField(VT_SUBGRAPH, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_SUBGRAPH, 4) && + verifier.EndTable(); + } + CallOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(CallOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct CallOptionsBuilder { + typedef CallOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_subgraph(uint32_t subgraph) { + fbb_.AddElement(CallOptions::VT_SUBGRAPH, subgraph, 0); + } + explicit CallOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateCallOptions( + flatbuffers::FlatBufferBuilder &_fbb, + uint32_t subgraph = 0) { + CallOptionsBuilder builder_(_fbb); + builder_.add_subgraph(subgraph); + return builder_.Finish(); +} + +flatbuffers::Offset CreateCallOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct PadOptionsT : public flatbuffers::NativeTable { + typedef PadOptions TableType; +}; + +struct PadOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef PadOptionsT NativeTableType; + typedef PadOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + PadOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(PadOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct PadOptionsBuilder { + typedef PadOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit PadOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreatePadOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + PadOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreatePadOptions(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct PadV2OptionsT : public flatbuffers::NativeTable { + typedef PadV2Options TableType; +}; + +struct PadV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef PadV2OptionsT NativeTableType; + typedef PadV2OptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + PadV2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(PadV2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadV2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct PadV2OptionsBuilder { + typedef PadV2Options Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit PadV2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreatePadV2Options( + flatbuffers::FlatBufferBuilder &_fbb) { + PadV2OptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreatePadV2Options(flatbuffers::FlatBufferBuilder &_fbb, const PadV2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ReshapeOptionsT : public flatbuffers::NativeTable { + typedef ReshapeOptions TableType; + std::vector new_shape{}; +}; + +struct ReshapeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ReshapeOptionsT NativeTableType; + typedef ReshapeOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NEW_SHAPE = 4 + }; + const flatbuffers::Vector *new_shape() const { + return GetPointer *>(VT_NEW_SHAPE); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_NEW_SHAPE) && + verifier.VerifyVector(new_shape()) && + verifier.EndTable(); + } + ReshapeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ReshapeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ReshapeOptionsBuilder { + typedef ReshapeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_new_shape(flatbuffers::Offset> new_shape) { + fbb_.AddOffset(ReshapeOptions::VT_NEW_SHAPE, new_shape); + } + explicit ReshapeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateReshapeOptions( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> new_shape = 0) { + ReshapeOptionsBuilder builder_(_fbb); + builder_.add_new_shape(new_shape); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateReshapeOptionsDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *new_shape = nullptr) { + auto new_shape__ = new_shape ? _fbb.CreateVector(*new_shape) : 0; + return tflite::CreateReshapeOptions( + _fbb, + new_shape__); +} + +flatbuffers::Offset CreateReshapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SpaceToBatchNDOptionsT : public flatbuffers::NativeTable { + typedef SpaceToBatchNDOptions TableType; +}; + +struct SpaceToBatchNDOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SpaceToBatchNDOptionsT NativeTableType; + typedef SpaceToBatchNDOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + SpaceToBatchNDOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SpaceToBatchNDOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SpaceToBatchNDOptionsBuilder { + typedef SpaceToBatchNDOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit SpaceToBatchNDOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSpaceToBatchNDOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + SpaceToBatchNDOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSpaceToBatchNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct BatchToSpaceNDOptionsT : public flatbuffers::NativeTable { + typedef BatchToSpaceNDOptions TableType; +}; + +struct BatchToSpaceNDOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef BatchToSpaceNDOptionsT NativeTableType; + typedef BatchToSpaceNDOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + BatchToSpaceNDOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(BatchToSpaceNDOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct BatchToSpaceNDOptionsBuilder { + typedef BatchToSpaceNDOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit BatchToSpaceNDOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateBatchToSpaceNDOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + BatchToSpaceNDOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateBatchToSpaceNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SkipGramOptionsT : public flatbuffers::NativeTable { + typedef SkipGramOptions TableType; + int32_t ngram_size = 0; + int32_t max_skip_size = 0; + bool include_all_ngrams = false; +}; + +struct SkipGramOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SkipGramOptionsT NativeTableType; + typedef SkipGramOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NGRAM_SIZE = 4, + VT_MAX_SKIP_SIZE = 6, + VT_INCLUDE_ALL_NGRAMS = 8 + }; + int32_t ngram_size() const { + return GetField(VT_NGRAM_SIZE, 0); + } + int32_t max_skip_size() const { + return GetField(VT_MAX_SKIP_SIZE, 0); + } + bool include_all_ngrams() const { + return GetField(VT_INCLUDE_ALL_NGRAMS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_NGRAM_SIZE, 4) && + VerifyField(verifier, VT_MAX_SKIP_SIZE, 4) && + VerifyField(verifier, VT_INCLUDE_ALL_NGRAMS, 1) && + verifier.EndTable(); + } + SkipGramOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SkipGramOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SkipGramOptionsBuilder { + typedef SkipGramOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_ngram_size(int32_t ngram_size) { + fbb_.AddElement(SkipGramOptions::VT_NGRAM_SIZE, ngram_size, 0); + } + void add_max_skip_size(int32_t max_skip_size) { + fbb_.AddElement(SkipGramOptions::VT_MAX_SKIP_SIZE, max_skip_size, 0); + } + void add_include_all_ngrams(bool include_all_ngrams) { + fbb_.AddElement(SkipGramOptions::VT_INCLUDE_ALL_NGRAMS, static_cast(include_all_ngrams), 0); + } + explicit SkipGramOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSkipGramOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t ngram_size = 0, + int32_t max_skip_size = 0, + bool include_all_ngrams = false) { + SkipGramOptionsBuilder builder_(_fbb); + builder_.add_max_skip_size(max_skip_size); + builder_.add_ngram_size(ngram_size); + builder_.add_include_all_ngrams(include_all_ngrams); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSkipGramOptions(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SpaceToDepthOptionsT : public flatbuffers::NativeTable { + typedef SpaceToDepthOptions TableType; + int32_t block_size = 0; +}; + +struct SpaceToDepthOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SpaceToDepthOptionsT NativeTableType; + typedef SpaceToDepthOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_BLOCK_SIZE = 4 + }; + int32_t block_size() const { + return GetField(VT_BLOCK_SIZE, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_BLOCK_SIZE, 4) && + verifier.EndTable(); + } + SpaceToDepthOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SpaceToDepthOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SpaceToDepthOptionsBuilder { + typedef SpaceToDepthOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_block_size(int32_t block_size) { + fbb_.AddElement(SpaceToDepthOptions::VT_BLOCK_SIZE, block_size, 0); + } + explicit SpaceToDepthOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSpaceToDepthOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t block_size = 0) { + SpaceToDepthOptionsBuilder builder_(_fbb); + builder_.add_block_size(block_size); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSpaceToDepthOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct DepthToSpaceOptionsT : public flatbuffers::NativeTable { + typedef DepthToSpaceOptions TableType; + int32_t block_size = 0; +}; + +struct DepthToSpaceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef DepthToSpaceOptionsT NativeTableType; + typedef DepthToSpaceOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_BLOCK_SIZE = 4 + }; + int32_t block_size() const { + return GetField(VT_BLOCK_SIZE, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_BLOCK_SIZE, 4) && + verifier.EndTable(); + } + DepthToSpaceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(DepthToSpaceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct DepthToSpaceOptionsBuilder { + typedef DepthToSpaceOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_block_size(int32_t block_size) { + fbb_.AddElement(DepthToSpaceOptions::VT_BLOCK_SIZE, block_size, 0); + } + explicit DepthToSpaceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateDepthToSpaceOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t block_size = 0) { + DepthToSpaceOptionsBuilder builder_(_fbb); + builder_.add_block_size(block_size); + return builder_.Finish(); +} + +flatbuffers::Offset CreateDepthToSpaceOptions(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SubOptionsT : public flatbuffers::NativeTable { + typedef SubOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; + bool pot_scale_int16 = true; +}; + +struct SubOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SubOptionsT NativeTableType; + typedef SubOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4, + VT_POT_SCALE_INT16 = 6 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool pot_scale_int16() const { + return GetField(VT_POT_SCALE_INT16, 1) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + VerifyField(verifier, VT_POT_SCALE_INT16, 1) && + verifier.EndTable(); + } + SubOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SubOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SubOptionsBuilder { + typedef SubOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(SubOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + void add_pot_scale_int16(bool pot_scale_int16) { + fbb_.AddElement(SubOptions::VT_POT_SCALE_INT16, static_cast(pot_scale_int16), 1); + } + explicit SubOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSubOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE, + bool pot_scale_int16 = true) { + SubOptionsBuilder builder_(_fbb); + builder_.add_pot_scale_int16(pot_scale_int16); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSubOptions(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct DivOptionsT : public flatbuffers::NativeTable { + typedef DivOptions TableType; + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE; +}; + +struct DivOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef DivOptionsT NativeTableType; + typedef DivOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FUSED_ACTIVATION_FUNCTION = 4 + }; + tflite::ActivationFunctionType fused_activation_function() const { + return static_cast(GetField(VT_FUSED_ACTIVATION_FUNCTION, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && + verifier.EndTable(); + } + DivOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(DivOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct DivOptionsBuilder { + typedef DivOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_fused_activation_function(tflite::ActivationFunctionType fused_activation_function) { + fbb_.AddElement(DivOptions::VT_FUSED_ACTIVATION_FUNCTION, static_cast(fused_activation_function), 0); + } + explicit DivOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateDivOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::ActivationFunctionType fused_activation_function = tflite::ActivationFunctionType_NONE) { + DivOptionsBuilder builder_(_fbb); + builder_.add_fused_activation_function(fused_activation_function); + return builder_.Finish(); +} + +flatbuffers::Offset CreateDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct TopKV2OptionsT : public flatbuffers::NativeTable { + typedef TopKV2Options TableType; +}; + +struct TopKV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TopKV2OptionsT NativeTableType; + typedef TopKV2OptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + TopKV2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(TopKV2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct TopKV2OptionsBuilder { + typedef TopKV2Options Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit TopKV2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTopKV2Options( + flatbuffers::FlatBufferBuilder &_fbb) { + TopKV2OptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateTopKV2Options(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct EmbeddingLookupSparseOptionsT : public flatbuffers::NativeTable { + typedef EmbeddingLookupSparseOptions TableType; + tflite::CombinerType combiner = tflite::CombinerType_SUM; +}; + +struct EmbeddingLookupSparseOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef EmbeddingLookupSparseOptionsT NativeTableType; + typedef EmbeddingLookupSparseOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_COMBINER = 4 + }; + tflite::CombinerType combiner() const { + return static_cast(GetField(VT_COMBINER, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_COMBINER, 1) && + verifier.EndTable(); + } + EmbeddingLookupSparseOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(EmbeddingLookupSparseOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const EmbeddingLookupSparseOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct EmbeddingLookupSparseOptionsBuilder { + typedef EmbeddingLookupSparseOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_combiner(tflite::CombinerType combiner) { + fbb_.AddElement(EmbeddingLookupSparseOptions::VT_COMBINER, static_cast(combiner), 0); + } + explicit EmbeddingLookupSparseOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateEmbeddingLookupSparseOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::CombinerType combiner = tflite::CombinerType_SUM) { + EmbeddingLookupSparseOptionsBuilder builder_(_fbb); + builder_.add_combiner(combiner); + return builder_.Finish(); +} + +flatbuffers::Offset CreateEmbeddingLookupSparseOptions(flatbuffers::FlatBufferBuilder &_fbb, const EmbeddingLookupSparseOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct GatherOptionsT : public flatbuffers::NativeTable { + typedef GatherOptions TableType; + int32_t axis = 0; + int32_t batch_dims = 0; +}; + +struct GatherOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef GatherOptionsT NativeTableType; + typedef GatherOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_AXIS = 4, + VT_BATCH_DIMS = 6 + }; + int32_t axis() const { + return GetField(VT_AXIS, 0); + } + int32_t batch_dims() const { + return GetField(VT_BATCH_DIMS, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_AXIS, 4) && + VerifyField(verifier, VT_BATCH_DIMS, 4) && + verifier.EndTable(); + } + GatherOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(GatherOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct GatherOptionsBuilder { + typedef GatherOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_axis(int32_t axis) { + fbb_.AddElement(GatherOptions::VT_AXIS, axis, 0); + } + void add_batch_dims(int32_t batch_dims) { + fbb_.AddElement(GatherOptions::VT_BATCH_DIMS, batch_dims, 0); + } + explicit GatherOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateGatherOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t axis = 0, + int32_t batch_dims = 0) { + GatherOptionsBuilder builder_(_fbb); + builder_.add_batch_dims(batch_dims); + builder_.add_axis(axis); + return builder_.Finish(); +} + +flatbuffers::Offset CreateGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct TransposeOptionsT : public flatbuffers::NativeTable { + typedef TransposeOptions TableType; +}; + +struct TransposeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TransposeOptionsT NativeTableType; + typedef TransposeOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + TransposeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(TransposeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct TransposeOptionsBuilder { + typedef TransposeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit TransposeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTransposeOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + TransposeOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateTransposeOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ExpOptionsT : public flatbuffers::NativeTable { + typedef ExpOptions TableType; +}; + +struct ExpOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ExpOptionsT NativeTableType; + typedef ExpOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + ExpOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ExpOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ExpOptionsBuilder { + typedef ExpOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit ExpOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateExpOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + ExpOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateExpOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct CosOptionsT : public flatbuffers::NativeTable { + typedef CosOptions TableType; +}; + +struct CosOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef CosOptionsT NativeTableType; + typedef CosOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + CosOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(CosOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct CosOptionsBuilder { + typedef CosOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit CosOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateCosOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + CosOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateCosOptions(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ReducerOptionsT : public flatbuffers::NativeTable { + typedef ReducerOptions TableType; + bool keep_dims = false; +}; + +struct ReducerOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ReducerOptionsT NativeTableType; + typedef ReducerOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_KEEP_DIMS = 4 + }; + bool keep_dims() const { + return GetField(VT_KEEP_DIMS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_KEEP_DIMS, 1) && + verifier.EndTable(); + } + ReducerOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ReducerOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ReducerOptionsBuilder { + typedef ReducerOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_keep_dims(bool keep_dims) { + fbb_.AddElement(ReducerOptions::VT_KEEP_DIMS, static_cast(keep_dims), 0); + } + explicit ReducerOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateReducerOptions( + flatbuffers::FlatBufferBuilder &_fbb, + bool keep_dims = false) { + ReducerOptionsBuilder builder_(_fbb); + builder_.add_keep_dims(keep_dims); + return builder_.Finish(); +} + +flatbuffers::Offset CreateReducerOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SqueezeOptionsT : public flatbuffers::NativeTable { + typedef SqueezeOptions TableType; + std::vector squeeze_dims{}; +}; + +struct SqueezeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SqueezeOptionsT NativeTableType; + typedef SqueezeOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SQUEEZE_DIMS = 4 + }; + const flatbuffers::Vector *squeeze_dims() const { + return GetPointer *>(VT_SQUEEZE_DIMS); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_SQUEEZE_DIMS) && + verifier.VerifyVector(squeeze_dims()) && + verifier.EndTable(); + } + SqueezeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SqueezeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SqueezeOptionsBuilder { + typedef SqueezeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_squeeze_dims(flatbuffers::Offset> squeeze_dims) { + fbb_.AddOffset(SqueezeOptions::VT_SQUEEZE_DIMS, squeeze_dims); + } + explicit SqueezeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSqueezeOptions( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> squeeze_dims = 0) { + SqueezeOptionsBuilder builder_(_fbb); + builder_.add_squeeze_dims(squeeze_dims); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateSqueezeOptionsDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *squeeze_dims = nullptr) { + auto squeeze_dims__ = squeeze_dims ? _fbb.CreateVector(*squeeze_dims) : 0; + return tflite::CreateSqueezeOptions( + _fbb, + squeeze_dims__); +} + +flatbuffers::Offset CreateSqueezeOptions(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SplitOptionsT : public flatbuffers::NativeTable { + typedef SplitOptions TableType; + int32_t num_splits = 0; +}; + +struct SplitOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SplitOptionsT NativeTableType; + typedef SplitOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NUM_SPLITS = 4 + }; + int32_t num_splits() const { + return GetField(VT_NUM_SPLITS, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_NUM_SPLITS, 4) && + verifier.EndTable(); + } + SplitOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SplitOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SplitOptionsBuilder { + typedef SplitOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_num_splits(int32_t num_splits) { + fbb_.AddElement(SplitOptions::VT_NUM_SPLITS, num_splits, 0); + } + explicit SplitOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSplitOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t num_splits = 0) { + SplitOptionsBuilder builder_(_fbb); + builder_.add_num_splits(num_splits); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSplitOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SplitVOptionsT : public flatbuffers::NativeTable { + typedef SplitVOptions TableType; + int32_t num_splits = 0; +}; + +struct SplitVOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SplitVOptionsT NativeTableType; + typedef SplitVOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NUM_SPLITS = 4 + }; + int32_t num_splits() const { + return GetField(VT_NUM_SPLITS, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_NUM_SPLITS, 4) && + verifier.EndTable(); + } + SplitVOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SplitVOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SplitVOptionsBuilder { + typedef SplitVOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_num_splits(int32_t num_splits) { + fbb_.AddElement(SplitVOptions::VT_NUM_SPLITS, num_splits, 0); + } + explicit SplitVOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSplitVOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t num_splits = 0) { + SplitVOptionsBuilder builder_(_fbb); + builder_.add_num_splits(num_splits); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSplitVOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct StridedSliceOptionsT : public flatbuffers::NativeTable { + typedef StridedSliceOptions TableType; + int32_t begin_mask = 0; + int32_t end_mask = 0; + int32_t ellipsis_mask = 0; + int32_t new_axis_mask = 0; + int32_t shrink_axis_mask = 0; +}; + +struct StridedSliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef StridedSliceOptionsT NativeTableType; + typedef StridedSliceOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_BEGIN_MASK = 4, + VT_END_MASK = 6, + VT_ELLIPSIS_MASK = 8, + VT_NEW_AXIS_MASK = 10, + VT_SHRINK_AXIS_MASK = 12 + }; + int32_t begin_mask() const { + return GetField(VT_BEGIN_MASK, 0); + } + int32_t end_mask() const { + return GetField(VT_END_MASK, 0); + } + int32_t ellipsis_mask() const { + return GetField(VT_ELLIPSIS_MASK, 0); + } + int32_t new_axis_mask() const { + return GetField(VT_NEW_AXIS_MASK, 0); + } + int32_t shrink_axis_mask() const { + return GetField(VT_SHRINK_AXIS_MASK, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_BEGIN_MASK, 4) && + VerifyField(verifier, VT_END_MASK, 4) && + VerifyField(verifier, VT_ELLIPSIS_MASK, 4) && + VerifyField(verifier, VT_NEW_AXIS_MASK, 4) && + VerifyField(verifier, VT_SHRINK_AXIS_MASK, 4) && + verifier.EndTable(); + } + StridedSliceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(StridedSliceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct StridedSliceOptionsBuilder { + typedef StridedSliceOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_begin_mask(int32_t begin_mask) { + fbb_.AddElement(StridedSliceOptions::VT_BEGIN_MASK, begin_mask, 0); + } + void add_end_mask(int32_t end_mask) { + fbb_.AddElement(StridedSliceOptions::VT_END_MASK, end_mask, 0); + } + void add_ellipsis_mask(int32_t ellipsis_mask) { + fbb_.AddElement(StridedSliceOptions::VT_ELLIPSIS_MASK, ellipsis_mask, 0); + } + void add_new_axis_mask(int32_t new_axis_mask) { + fbb_.AddElement(StridedSliceOptions::VT_NEW_AXIS_MASK, new_axis_mask, 0); + } + void add_shrink_axis_mask(int32_t shrink_axis_mask) { + fbb_.AddElement(StridedSliceOptions::VT_SHRINK_AXIS_MASK, shrink_axis_mask, 0); + } + explicit StridedSliceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateStridedSliceOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t begin_mask = 0, + int32_t end_mask = 0, + int32_t ellipsis_mask = 0, + int32_t new_axis_mask = 0, + int32_t shrink_axis_mask = 0) { + StridedSliceOptionsBuilder builder_(_fbb); + builder_.add_shrink_axis_mask(shrink_axis_mask); + builder_.add_new_axis_mask(new_axis_mask); + builder_.add_ellipsis_mask(ellipsis_mask); + builder_.add_end_mask(end_mask); + builder_.add_begin_mask(begin_mask); + return builder_.Finish(); +} + +flatbuffers::Offset CreateStridedSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LogSoftmaxOptionsT : public flatbuffers::NativeTable { + typedef LogSoftmaxOptions TableType; +}; + +struct LogSoftmaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LogSoftmaxOptionsT NativeTableType; + typedef LogSoftmaxOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + LogSoftmaxOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LogSoftmaxOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LogSoftmaxOptionsBuilder { + typedef LogSoftmaxOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit LogSoftmaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLogSoftmaxOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + LogSoftmaxOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLogSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct CastOptionsT : public flatbuffers::NativeTable { + typedef CastOptions TableType; + tflite::TensorType in_data_type = tflite::TensorType_FLOAT32; + tflite::TensorType out_data_type = tflite::TensorType_FLOAT32; +}; + +struct CastOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef CastOptionsT NativeTableType; + typedef CastOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_IN_DATA_TYPE = 4, + VT_OUT_DATA_TYPE = 6 + }; + tflite::TensorType in_data_type() const { + return static_cast(GetField(VT_IN_DATA_TYPE, 0)); + } + tflite::TensorType out_data_type() const { + return static_cast(GetField(VT_OUT_DATA_TYPE, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_IN_DATA_TYPE, 1) && + VerifyField(verifier, VT_OUT_DATA_TYPE, 1) && + verifier.EndTable(); + } + CastOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(CastOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct CastOptionsBuilder { + typedef CastOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_in_data_type(tflite::TensorType in_data_type) { + fbb_.AddElement(CastOptions::VT_IN_DATA_TYPE, static_cast(in_data_type), 0); + } + void add_out_data_type(tflite::TensorType out_data_type) { + fbb_.AddElement(CastOptions::VT_OUT_DATA_TYPE, static_cast(out_data_type), 0); + } + explicit CastOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateCastOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::TensorType in_data_type = tflite::TensorType_FLOAT32, + tflite::TensorType out_data_type = tflite::TensorType_FLOAT32) { + CastOptionsBuilder builder_(_fbb); + builder_.add_out_data_type(out_data_type); + builder_.add_in_data_type(in_data_type); + return builder_.Finish(); +} + +flatbuffers::Offset CreateCastOptions(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct DequantizeOptionsT : public flatbuffers::NativeTable { + typedef DequantizeOptions TableType; +}; + +struct DequantizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef DequantizeOptionsT NativeTableType; + typedef DequantizeOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + DequantizeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(DequantizeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct DequantizeOptionsBuilder { + typedef DequantizeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit DequantizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateDequantizeOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + DequantizeOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateDequantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct MaximumMinimumOptionsT : public flatbuffers::NativeTable { + typedef MaximumMinimumOptions TableType; +}; + +struct MaximumMinimumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef MaximumMinimumOptionsT NativeTableType; + typedef MaximumMinimumOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + MaximumMinimumOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(MaximumMinimumOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct MaximumMinimumOptionsBuilder { + typedef MaximumMinimumOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit MaximumMinimumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateMaximumMinimumOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + MaximumMinimumOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateMaximumMinimumOptions(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct TileOptionsT : public flatbuffers::NativeTable { + typedef TileOptions TableType; +}; + +struct TileOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TileOptionsT NativeTableType; + typedef TileOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + TileOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(TileOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct TileOptionsBuilder { + typedef TileOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit TileOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTileOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + TileOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateTileOptions(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ArgMaxOptionsT : public flatbuffers::NativeTable { + typedef ArgMaxOptions TableType; + tflite::TensorType output_type = tflite::TensorType_FLOAT32; +}; + +struct ArgMaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ArgMaxOptionsT NativeTableType; + typedef ArgMaxOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_OUTPUT_TYPE = 4 + }; + tflite::TensorType output_type() const { + return static_cast(GetField(VT_OUTPUT_TYPE, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_OUTPUT_TYPE, 1) && + verifier.EndTable(); + } + ArgMaxOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ArgMaxOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ArgMaxOptionsBuilder { + typedef ArgMaxOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_output_type(tflite::TensorType output_type) { + fbb_.AddElement(ArgMaxOptions::VT_OUTPUT_TYPE, static_cast(output_type), 0); + } + explicit ArgMaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateArgMaxOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::TensorType output_type = tflite::TensorType_FLOAT32) { + ArgMaxOptionsBuilder builder_(_fbb); + builder_.add_output_type(output_type); + return builder_.Finish(); +} + +flatbuffers::Offset CreateArgMaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ArgMinOptionsT : public flatbuffers::NativeTable { + typedef ArgMinOptions TableType; + tflite::TensorType output_type = tflite::TensorType_FLOAT32; +}; + +struct ArgMinOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ArgMinOptionsT NativeTableType; + typedef ArgMinOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_OUTPUT_TYPE = 4 + }; + tflite::TensorType output_type() const { + return static_cast(GetField(VT_OUTPUT_TYPE, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_OUTPUT_TYPE, 1) && + verifier.EndTable(); + } + ArgMinOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ArgMinOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ArgMinOptionsBuilder { + typedef ArgMinOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_output_type(tflite::TensorType output_type) { + fbb_.AddElement(ArgMinOptions::VT_OUTPUT_TYPE, static_cast(output_type), 0); + } + explicit ArgMinOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateArgMinOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::TensorType output_type = tflite::TensorType_FLOAT32) { + ArgMinOptionsBuilder builder_(_fbb); + builder_.add_output_type(output_type); + return builder_.Finish(); +} + +flatbuffers::Offset CreateArgMinOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct GreaterOptionsT : public flatbuffers::NativeTable { + typedef GreaterOptions TableType; +}; + +struct GreaterOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef GreaterOptionsT NativeTableType; + typedef GreaterOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + GreaterOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(GreaterOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct GreaterOptionsBuilder { + typedef GreaterOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit GreaterOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateGreaterOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + GreaterOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateGreaterOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct GreaterEqualOptionsT : public flatbuffers::NativeTable { + typedef GreaterEqualOptions TableType; +}; + +struct GreaterEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef GreaterEqualOptionsT NativeTableType; + typedef GreaterEqualOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + GreaterEqualOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(GreaterEqualOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct GreaterEqualOptionsBuilder { + typedef GreaterEqualOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit GreaterEqualOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateGreaterEqualOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + GreaterEqualOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateGreaterEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LessOptionsT : public flatbuffers::NativeTable { + typedef LessOptions TableType; +}; + +struct LessOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LessOptionsT NativeTableType; + typedef LessOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + LessOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LessOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LessOptionsBuilder { + typedef LessOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit LessOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLessOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + LessOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLessOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LessEqualOptionsT : public flatbuffers::NativeTable { + typedef LessEqualOptions TableType; +}; + +struct LessEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LessEqualOptionsT NativeTableType; + typedef LessEqualOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + LessEqualOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LessEqualOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LessEqualOptionsBuilder { + typedef LessEqualOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit LessEqualOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLessEqualOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + LessEqualOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLessEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct NegOptionsT : public flatbuffers::NativeTable { + typedef NegOptions TableType; +}; + +struct NegOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef NegOptionsT NativeTableType; + typedef NegOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + NegOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(NegOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct NegOptionsBuilder { + typedef NegOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit NegOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateNegOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + NegOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateNegOptions(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SelectOptionsT : public flatbuffers::NativeTable { + typedef SelectOptions TableType; +}; + +struct SelectOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SelectOptionsT NativeTableType; + typedef SelectOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + SelectOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SelectOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SelectOptionsBuilder { + typedef SelectOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit SelectOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSelectOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + SelectOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSelectOptions(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SliceOptionsT : public flatbuffers::NativeTable { + typedef SliceOptions TableType; +}; + +struct SliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SliceOptionsT NativeTableType; + typedef SliceOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + SliceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SliceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SliceOptionsBuilder { + typedef SliceOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit SliceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSliceOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + SliceOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct TransposeConvOptionsT : public flatbuffers::NativeTable { + typedef TransposeConvOptions TableType; + tflite::Padding padding = tflite::Padding_SAME; + int32_t stride_w = 0; + int32_t stride_h = 0; +}; + +struct TransposeConvOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TransposeConvOptionsT NativeTableType; + typedef TransposeConvOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_PADDING = 4, + VT_STRIDE_W = 6, + VT_STRIDE_H = 8 + }; + tflite::Padding padding() const { + return static_cast(GetField(VT_PADDING, 0)); + } + int32_t stride_w() const { + return GetField(VT_STRIDE_W, 0); + } + int32_t stride_h() const { + return GetField(VT_STRIDE_H, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_PADDING, 1) && + VerifyField(verifier, VT_STRIDE_W, 4) && + VerifyField(verifier, VT_STRIDE_H, 4) && + verifier.EndTable(); + } + TransposeConvOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(TransposeConvOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct TransposeConvOptionsBuilder { + typedef TransposeConvOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_padding(tflite::Padding padding) { + fbb_.AddElement(TransposeConvOptions::VT_PADDING, static_cast(padding), 0); + } + void add_stride_w(int32_t stride_w) { + fbb_.AddElement(TransposeConvOptions::VT_STRIDE_W, stride_w, 0); + } + void add_stride_h(int32_t stride_h) { + fbb_.AddElement(TransposeConvOptions::VT_STRIDE_H, stride_h, 0); + } + explicit TransposeConvOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTransposeConvOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::Padding padding = tflite::Padding_SAME, + int32_t stride_w = 0, + int32_t stride_h = 0) { + TransposeConvOptionsBuilder builder_(_fbb); + builder_.add_stride_h(stride_h); + builder_.add_stride_w(stride_w); + builder_.add_padding(padding); + return builder_.Finish(); +} + +flatbuffers::Offset CreateTransposeConvOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ExpandDimsOptionsT : public flatbuffers::NativeTable { + typedef ExpandDimsOptions TableType; +}; + +struct ExpandDimsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ExpandDimsOptionsT NativeTableType; + typedef ExpandDimsOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + ExpandDimsOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ExpandDimsOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ExpandDimsOptionsBuilder { + typedef ExpandDimsOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit ExpandDimsOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateExpandDimsOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + ExpandDimsOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateExpandDimsOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SparseToDenseOptionsT : public flatbuffers::NativeTable { + typedef SparseToDenseOptions TableType; + bool validate_indices = false; +}; + +struct SparseToDenseOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SparseToDenseOptionsT NativeTableType; + typedef SparseToDenseOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VALIDATE_INDICES = 4 + }; + bool validate_indices() const { + return GetField(VT_VALIDATE_INDICES, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_VALIDATE_INDICES, 1) && + verifier.EndTable(); + } + SparseToDenseOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SparseToDenseOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SparseToDenseOptionsBuilder { + typedef SparseToDenseOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_validate_indices(bool validate_indices) { + fbb_.AddElement(SparseToDenseOptions::VT_VALIDATE_INDICES, static_cast(validate_indices), 0); + } + explicit SparseToDenseOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSparseToDenseOptions( + flatbuffers::FlatBufferBuilder &_fbb, + bool validate_indices = false) { + SparseToDenseOptionsBuilder builder_(_fbb); + builder_.add_validate_indices(validate_indices); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSparseToDenseOptions(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct EqualOptionsT : public flatbuffers::NativeTable { + typedef EqualOptions TableType; +}; + +struct EqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef EqualOptionsT NativeTableType; + typedef EqualOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + EqualOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(EqualOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct EqualOptionsBuilder { + typedef EqualOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit EqualOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateEqualOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + EqualOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct NotEqualOptionsT : public flatbuffers::NativeTable { + typedef NotEqualOptions TableType; +}; + +struct NotEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef NotEqualOptionsT NativeTableType; + typedef NotEqualOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + NotEqualOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(NotEqualOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct NotEqualOptionsBuilder { + typedef NotEqualOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit NotEqualOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateNotEqualOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + NotEqualOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateNotEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ShapeOptionsT : public flatbuffers::NativeTable { + typedef ShapeOptions TableType; + tflite::TensorType out_type = tflite::TensorType_FLOAT32; +}; + +struct ShapeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ShapeOptionsT NativeTableType; + typedef ShapeOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_OUT_TYPE = 4 + }; + tflite::TensorType out_type() const { + return static_cast(GetField(VT_OUT_TYPE, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_OUT_TYPE, 1) && + verifier.EndTable(); + } + ShapeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ShapeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ShapeOptionsBuilder { + typedef ShapeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_out_type(tflite::TensorType out_type) { + fbb_.AddElement(ShapeOptions::VT_OUT_TYPE, static_cast(out_type), 0); + } + explicit ShapeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateShapeOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::TensorType out_type = tflite::TensorType_FLOAT32) { + ShapeOptionsBuilder builder_(_fbb); + builder_.add_out_type(out_type); + return builder_.Finish(); +} + +flatbuffers::Offset CreateShapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct RankOptionsT : public flatbuffers::NativeTable { + typedef RankOptions TableType; +}; + +struct RankOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef RankOptionsT NativeTableType; + typedef RankOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + RankOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RankOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct RankOptionsBuilder { + typedef RankOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit RankOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateRankOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + RankOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateRankOptions(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct PowOptionsT : public flatbuffers::NativeTable { + typedef PowOptions TableType; +}; + +struct PowOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef PowOptionsT NativeTableType; + typedef PowOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + PowOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(PowOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct PowOptionsBuilder { + typedef PowOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit PowOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreatePowOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + PowOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreatePowOptions(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct FakeQuantOptionsT : public flatbuffers::NativeTable { + typedef FakeQuantOptions TableType; + float min = 0.0f; + float max = 0.0f; + int32_t num_bits = 0; + bool narrow_range = false; +}; + +struct FakeQuantOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FakeQuantOptionsT NativeTableType; + typedef FakeQuantOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_MIN = 4, + VT_MAX = 6, + VT_NUM_BITS = 8, + VT_NARROW_RANGE = 10 + }; + float min() const { + return GetField(VT_MIN, 0.0f); + } + float max() const { + return GetField(VT_MAX, 0.0f); + } + int32_t num_bits() const { + return GetField(VT_NUM_BITS, 0); + } + bool narrow_range() const { + return GetField(VT_NARROW_RANGE, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_MIN, 4) && + VerifyField(verifier, VT_MAX, 4) && + VerifyField(verifier, VT_NUM_BITS, 4) && + VerifyField(verifier, VT_NARROW_RANGE, 1) && + verifier.EndTable(); + } + FakeQuantOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(FakeQuantOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct FakeQuantOptionsBuilder { + typedef FakeQuantOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_min(float min) { + fbb_.AddElement(FakeQuantOptions::VT_MIN, min, 0.0f); + } + void add_max(float max) { + fbb_.AddElement(FakeQuantOptions::VT_MAX, max, 0.0f); + } + void add_num_bits(int32_t num_bits) { + fbb_.AddElement(FakeQuantOptions::VT_NUM_BITS, num_bits, 0); + } + void add_narrow_range(bool narrow_range) { + fbb_.AddElement(FakeQuantOptions::VT_NARROW_RANGE, static_cast(narrow_range), 0); + } + explicit FakeQuantOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateFakeQuantOptions( + flatbuffers::FlatBufferBuilder &_fbb, + float min = 0.0f, + float max = 0.0f, + int32_t num_bits = 0, + bool narrow_range = false) { + FakeQuantOptionsBuilder builder_(_fbb); + builder_.add_num_bits(num_bits); + builder_.add_max(max); + builder_.add_min(min); + builder_.add_narrow_range(narrow_range); + return builder_.Finish(); +} + +flatbuffers::Offset CreateFakeQuantOptions(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct PackOptionsT : public flatbuffers::NativeTable { + typedef PackOptions TableType; + int32_t values_count = 0; + int32_t axis = 0; +}; + +struct PackOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef PackOptionsT NativeTableType; + typedef PackOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VALUES_COUNT = 4, + VT_AXIS = 6 + }; + int32_t values_count() const { + return GetField(VT_VALUES_COUNT, 0); + } + int32_t axis() const { + return GetField(VT_AXIS, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_VALUES_COUNT, 4) && + VerifyField(verifier, VT_AXIS, 4) && + verifier.EndTable(); + } + PackOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(PackOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct PackOptionsBuilder { + typedef PackOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_values_count(int32_t values_count) { + fbb_.AddElement(PackOptions::VT_VALUES_COUNT, values_count, 0); + } + void add_axis(int32_t axis) { + fbb_.AddElement(PackOptions::VT_AXIS, axis, 0); + } + explicit PackOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreatePackOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t values_count = 0, + int32_t axis = 0) { + PackOptionsBuilder builder_(_fbb); + builder_.add_axis(axis); + builder_.add_values_count(values_count); + return builder_.Finish(); +} + +flatbuffers::Offset CreatePackOptions(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LogicalOrOptionsT : public flatbuffers::NativeTable { + typedef LogicalOrOptions TableType; +}; + +struct LogicalOrOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LogicalOrOptionsT NativeTableType; + typedef LogicalOrOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + LogicalOrOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LogicalOrOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LogicalOrOptionsBuilder { + typedef LogicalOrOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit LogicalOrOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLogicalOrOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + LogicalOrOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLogicalOrOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct OneHotOptionsT : public flatbuffers::NativeTable { + typedef OneHotOptions TableType; + int32_t axis = 0; +}; + +struct OneHotOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef OneHotOptionsT NativeTableType; + typedef OneHotOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_AXIS = 4 + }; + int32_t axis() const { + return GetField(VT_AXIS, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_AXIS, 4) && + verifier.EndTable(); + } + OneHotOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(OneHotOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct OneHotOptionsBuilder { + typedef OneHotOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_axis(int32_t axis) { + fbb_.AddElement(OneHotOptions::VT_AXIS, axis, 0); + } + explicit OneHotOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateOneHotOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t axis = 0) { + OneHotOptionsBuilder builder_(_fbb); + builder_.add_axis(axis); + return builder_.Finish(); +} + +flatbuffers::Offset CreateOneHotOptions(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct AbsOptionsT : public flatbuffers::NativeTable { + typedef AbsOptions TableType; +}; + +struct AbsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef AbsOptionsT NativeTableType; + typedef AbsOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + AbsOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(AbsOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct AbsOptionsBuilder { + typedef AbsOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit AbsOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateAbsOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + AbsOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateAbsOptions(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct HardSwishOptionsT : public flatbuffers::NativeTable { + typedef HardSwishOptions TableType; +}; + +struct HardSwishOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef HardSwishOptionsT NativeTableType; + typedef HardSwishOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + HardSwishOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(HardSwishOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct HardSwishOptionsBuilder { + typedef HardSwishOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit HardSwishOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateHardSwishOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + HardSwishOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateHardSwishOptions(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LogicalAndOptionsT : public flatbuffers::NativeTable { + typedef LogicalAndOptions TableType; +}; + +struct LogicalAndOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LogicalAndOptionsT NativeTableType; + typedef LogicalAndOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + LogicalAndOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LogicalAndOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LogicalAndOptionsBuilder { + typedef LogicalAndOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit LogicalAndOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLogicalAndOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + LogicalAndOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLogicalAndOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LogicalNotOptionsT : public flatbuffers::NativeTable { + typedef LogicalNotOptions TableType; +}; + +struct LogicalNotOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LogicalNotOptionsT NativeTableType; + typedef LogicalNotOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + LogicalNotOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LogicalNotOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LogicalNotOptionsBuilder { + typedef LogicalNotOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit LogicalNotOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLogicalNotOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + LogicalNotOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLogicalNotOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct UnpackOptionsT : public flatbuffers::NativeTable { + typedef UnpackOptions TableType; + int32_t num = 0; + int32_t axis = 0; +}; + +struct UnpackOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef UnpackOptionsT NativeTableType; + typedef UnpackOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NUM = 4, + VT_AXIS = 6 + }; + int32_t num() const { + return GetField(VT_NUM, 0); + } + int32_t axis() const { + return GetField(VT_AXIS, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_NUM, 4) && + VerifyField(verifier, VT_AXIS, 4) && + verifier.EndTable(); + } + UnpackOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(UnpackOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct UnpackOptionsBuilder { + typedef UnpackOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_num(int32_t num) { + fbb_.AddElement(UnpackOptions::VT_NUM, num, 0); + } + void add_axis(int32_t axis) { + fbb_.AddElement(UnpackOptions::VT_AXIS, axis, 0); + } + explicit UnpackOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUnpackOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t num = 0, + int32_t axis = 0) { + UnpackOptionsBuilder builder_(_fbb); + builder_.add_axis(axis); + builder_.add_num(num); + return builder_.Finish(); +} + +flatbuffers::Offset CreateUnpackOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct FloorDivOptionsT : public flatbuffers::NativeTable { + typedef FloorDivOptions TableType; +}; + +struct FloorDivOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FloorDivOptionsT NativeTableType; + typedef FloorDivOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + FloorDivOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(FloorDivOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct FloorDivOptionsBuilder { + typedef FloorDivOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit FloorDivOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateFloorDivOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + FloorDivOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateFloorDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SquareOptionsT : public flatbuffers::NativeTable { + typedef SquareOptions TableType; +}; + +struct SquareOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SquareOptionsT NativeTableType; + typedef SquareOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + SquareOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SquareOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SquareOptionsBuilder { + typedef SquareOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit SquareOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSquareOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + SquareOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSquareOptions(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ZerosLikeOptionsT : public flatbuffers::NativeTable { + typedef ZerosLikeOptions TableType; +}; + +struct ZerosLikeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ZerosLikeOptionsT NativeTableType; + typedef ZerosLikeOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + ZerosLikeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ZerosLikeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ZerosLikeOptionsBuilder { + typedef ZerosLikeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit ZerosLikeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateZerosLikeOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + ZerosLikeOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateZerosLikeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct FillOptionsT : public flatbuffers::NativeTable { + typedef FillOptions TableType; +}; + +struct FillOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FillOptionsT NativeTableType; + typedef FillOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + FillOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(FillOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct FillOptionsBuilder { + typedef FillOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit FillOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateFillOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + FillOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateFillOptions(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct FloorModOptionsT : public flatbuffers::NativeTable { + typedef FloorModOptions TableType; +}; + +struct FloorModOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FloorModOptionsT NativeTableType; + typedef FloorModOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + FloorModOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(FloorModOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct FloorModOptionsBuilder { + typedef FloorModOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit FloorModOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateFloorModOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + FloorModOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateFloorModOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct RangeOptionsT : public flatbuffers::NativeTable { + typedef RangeOptions TableType; +}; + +struct RangeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef RangeOptionsT NativeTableType; + typedef RangeOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + RangeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RangeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct RangeOptionsBuilder { + typedef RangeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit RangeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateRangeOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + RangeOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateRangeOptions(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct LeakyReluOptionsT : public flatbuffers::NativeTable { + typedef LeakyReluOptions TableType; + float alpha = 0.0f; +}; + +struct LeakyReluOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LeakyReluOptionsT NativeTableType; + typedef LeakyReluOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ALPHA = 4 + }; + float alpha() const { + return GetField(VT_ALPHA, 0.0f); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ALPHA, 4) && + verifier.EndTable(); + } + LeakyReluOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LeakyReluOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LeakyReluOptionsBuilder { + typedef LeakyReluOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_alpha(float alpha) { + fbb_.AddElement(LeakyReluOptions::VT_ALPHA, alpha, 0.0f); + } + explicit LeakyReluOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLeakyReluOptions( + flatbuffers::FlatBufferBuilder &_fbb, + float alpha = 0.0f) { + LeakyReluOptionsBuilder builder_(_fbb); + builder_.add_alpha(alpha); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLeakyReluOptions(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SquaredDifferenceOptionsT : public flatbuffers::NativeTable { + typedef SquaredDifferenceOptions TableType; +}; + +struct SquaredDifferenceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SquaredDifferenceOptionsT NativeTableType; + typedef SquaredDifferenceOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + SquaredDifferenceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SquaredDifferenceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquaredDifferenceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SquaredDifferenceOptionsBuilder { + typedef SquaredDifferenceOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit SquaredDifferenceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSquaredDifferenceOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + SquaredDifferenceOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSquaredDifferenceOptions(flatbuffers::FlatBufferBuilder &_fbb, const SquaredDifferenceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct MirrorPadOptionsT : public flatbuffers::NativeTable { + typedef MirrorPadOptions TableType; + tflite::MirrorPadMode mode = tflite::MirrorPadMode_REFLECT; +}; + +struct MirrorPadOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef MirrorPadOptionsT NativeTableType; + typedef MirrorPadOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_MODE = 4 + }; + tflite::MirrorPadMode mode() const { + return static_cast(GetField(VT_MODE, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_MODE, 1) && + verifier.EndTable(); + } + MirrorPadOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(MirrorPadOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct MirrorPadOptionsBuilder { + typedef MirrorPadOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_mode(tflite::MirrorPadMode mode) { + fbb_.AddElement(MirrorPadOptions::VT_MODE, static_cast(mode), 0); + } + explicit MirrorPadOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateMirrorPadOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::MirrorPadMode mode = tflite::MirrorPadMode_REFLECT) { + MirrorPadOptionsBuilder builder_(_fbb); + builder_.add_mode(mode); + return builder_.Finish(); +} + +flatbuffers::Offset CreateMirrorPadOptions(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct UniqueOptionsT : public flatbuffers::NativeTable { + typedef UniqueOptions TableType; + tflite::TensorType idx_out_type = tflite::TensorType_INT32; +}; + +struct UniqueOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef UniqueOptionsT NativeTableType; + typedef UniqueOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_IDX_OUT_TYPE = 4 + }; + tflite::TensorType idx_out_type() const { + return static_cast(GetField(VT_IDX_OUT_TYPE, 2)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_IDX_OUT_TYPE, 1) && + verifier.EndTable(); + } + UniqueOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(UniqueOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct UniqueOptionsBuilder { + typedef UniqueOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_idx_out_type(tflite::TensorType idx_out_type) { + fbb_.AddElement(UniqueOptions::VT_IDX_OUT_TYPE, static_cast(idx_out_type), 2); + } + explicit UniqueOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUniqueOptions( + flatbuffers::FlatBufferBuilder &_fbb, + tflite::TensorType idx_out_type = tflite::TensorType_INT32) { + UniqueOptionsBuilder builder_(_fbb); + builder_.add_idx_out_type(idx_out_type); + return builder_.Finish(); +} + +flatbuffers::Offset CreateUniqueOptions(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ReverseV2OptionsT : public flatbuffers::NativeTable { + typedef ReverseV2Options TableType; +}; + +struct ReverseV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ReverseV2OptionsT NativeTableType; + typedef ReverseV2OptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + ReverseV2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ReverseV2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ReverseV2OptionsBuilder { + typedef ReverseV2Options Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit ReverseV2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateReverseV2Options( + flatbuffers::FlatBufferBuilder &_fbb) { + ReverseV2OptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateReverseV2Options(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct AddNOptionsT : public flatbuffers::NativeTable { + typedef AddNOptions TableType; +}; + +struct AddNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef AddNOptionsT NativeTableType; + typedef AddNOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + AddNOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(AddNOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct AddNOptionsBuilder { + typedef AddNOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit AddNOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateAddNOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + AddNOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateAddNOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct GatherNdOptionsT : public flatbuffers::NativeTable { + typedef GatherNdOptions TableType; +}; + +struct GatherNdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef GatherNdOptionsT NativeTableType; + typedef GatherNdOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + GatherNdOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(GatherNdOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct GatherNdOptionsBuilder { + typedef GatherNdOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit GatherNdOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateGatherNdOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + GatherNdOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateGatherNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct WhereOptionsT : public flatbuffers::NativeTable { + typedef WhereOptions TableType; +}; + +struct WhereOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef WhereOptionsT NativeTableType; + typedef WhereOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + WhereOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(WhereOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct WhereOptionsBuilder { + typedef WhereOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit WhereOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateWhereOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + WhereOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateWhereOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ReverseSequenceOptionsT : public flatbuffers::NativeTable { + typedef ReverseSequenceOptions TableType; + int32_t seq_dim = 0; + int32_t batch_dim = 0; +}; + +struct ReverseSequenceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ReverseSequenceOptionsT NativeTableType; + typedef ReverseSequenceOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SEQ_DIM = 4, + VT_BATCH_DIM = 6 + }; + int32_t seq_dim() const { + return GetField(VT_SEQ_DIM, 0); + } + int32_t batch_dim() const { + return GetField(VT_BATCH_DIM, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_SEQ_DIM, 4) && + VerifyField(verifier, VT_BATCH_DIM, 4) && + verifier.EndTable(); + } + ReverseSequenceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ReverseSequenceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReverseSequenceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ReverseSequenceOptionsBuilder { + typedef ReverseSequenceOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_seq_dim(int32_t seq_dim) { + fbb_.AddElement(ReverseSequenceOptions::VT_SEQ_DIM, seq_dim, 0); + } + void add_batch_dim(int32_t batch_dim) { + fbb_.AddElement(ReverseSequenceOptions::VT_BATCH_DIM, batch_dim, 0); + } + explicit ReverseSequenceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateReverseSequenceOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t seq_dim = 0, + int32_t batch_dim = 0) { + ReverseSequenceOptionsBuilder builder_(_fbb); + builder_.add_batch_dim(batch_dim); + builder_.add_seq_dim(seq_dim); + return builder_.Finish(); +} + +flatbuffers::Offset CreateReverseSequenceOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReverseSequenceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct MatrixDiagOptionsT : public flatbuffers::NativeTable { + typedef MatrixDiagOptions TableType; +}; + +struct MatrixDiagOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef MatrixDiagOptionsT NativeTableType; + typedef MatrixDiagOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + MatrixDiagOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(MatrixDiagOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct MatrixDiagOptionsBuilder { + typedef MatrixDiagOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit MatrixDiagOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateMatrixDiagOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + MatrixDiagOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateMatrixDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct QuantizeOptionsT : public flatbuffers::NativeTable { + typedef QuantizeOptions TableType; +}; + +struct QuantizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef QuantizeOptionsT NativeTableType; + typedef QuantizeOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + QuantizeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(QuantizeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct QuantizeOptionsBuilder { + typedef QuantizeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit QuantizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateQuantizeOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + QuantizeOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateQuantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct MatrixSetDiagOptionsT : public flatbuffers::NativeTable { + typedef MatrixSetDiagOptions TableType; +}; + +struct MatrixSetDiagOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef MatrixSetDiagOptionsT NativeTableType; + typedef MatrixSetDiagOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + MatrixSetDiagOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(MatrixSetDiagOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct MatrixSetDiagOptionsBuilder { + typedef MatrixSetDiagOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit MatrixSetDiagOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateMatrixSetDiagOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + MatrixSetDiagOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateMatrixSetDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct IfOptionsT : public flatbuffers::NativeTable { + typedef IfOptions TableType; + int32_t then_subgraph_index = 0; + int32_t else_subgraph_index = 0; +}; + +struct IfOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef IfOptionsT NativeTableType; + typedef IfOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_THEN_SUBGRAPH_INDEX = 4, + VT_ELSE_SUBGRAPH_INDEX = 6 + }; + int32_t then_subgraph_index() const { + return GetField(VT_THEN_SUBGRAPH_INDEX, 0); + } + int32_t else_subgraph_index() const { + return GetField(VT_ELSE_SUBGRAPH_INDEX, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_THEN_SUBGRAPH_INDEX, 4) && + VerifyField(verifier, VT_ELSE_SUBGRAPH_INDEX, 4) && + verifier.EndTable(); + } + IfOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(IfOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct IfOptionsBuilder { + typedef IfOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_then_subgraph_index(int32_t then_subgraph_index) { + fbb_.AddElement(IfOptions::VT_THEN_SUBGRAPH_INDEX, then_subgraph_index, 0); + } + void add_else_subgraph_index(int32_t else_subgraph_index) { + fbb_.AddElement(IfOptions::VT_ELSE_SUBGRAPH_INDEX, else_subgraph_index, 0); + } + explicit IfOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateIfOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t then_subgraph_index = 0, + int32_t else_subgraph_index = 0) { + IfOptionsBuilder builder_(_fbb); + builder_.add_else_subgraph_index(else_subgraph_index); + builder_.add_then_subgraph_index(then_subgraph_index); + return builder_.Finish(); +} + +flatbuffers::Offset CreateIfOptions(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct CallOnceOptionsT : public flatbuffers::NativeTable { + typedef CallOnceOptions TableType; + int32_t init_subgraph_index = 0; +}; + +struct CallOnceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef CallOnceOptionsT NativeTableType; + typedef CallOnceOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_INIT_SUBGRAPH_INDEX = 4 + }; + int32_t init_subgraph_index() const { + return GetField(VT_INIT_SUBGRAPH_INDEX, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_INIT_SUBGRAPH_INDEX, 4) && + verifier.EndTable(); + } + CallOnceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(CallOnceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct CallOnceOptionsBuilder { + typedef CallOnceOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_init_subgraph_index(int32_t init_subgraph_index) { + fbb_.AddElement(CallOnceOptions::VT_INIT_SUBGRAPH_INDEX, init_subgraph_index, 0); + } + explicit CallOnceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateCallOnceOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t init_subgraph_index = 0) { + CallOnceOptionsBuilder builder_(_fbb); + builder_.add_init_subgraph_index(init_subgraph_index); + return builder_.Finish(); +} + +flatbuffers::Offset CreateCallOnceOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct WhileOptionsT : public flatbuffers::NativeTable { + typedef WhileOptions TableType; + int32_t cond_subgraph_index = 0; + int32_t body_subgraph_index = 0; +}; + +struct WhileOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef WhileOptionsT NativeTableType; + typedef WhileOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_COND_SUBGRAPH_INDEX = 4, + VT_BODY_SUBGRAPH_INDEX = 6 + }; + int32_t cond_subgraph_index() const { + return GetField(VT_COND_SUBGRAPH_INDEX, 0); + } + int32_t body_subgraph_index() const { + return GetField(VT_BODY_SUBGRAPH_INDEX, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_COND_SUBGRAPH_INDEX, 4) && + VerifyField(verifier, VT_BODY_SUBGRAPH_INDEX, 4) && + verifier.EndTable(); + } + WhileOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(WhileOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct WhileOptionsBuilder { + typedef WhileOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_cond_subgraph_index(int32_t cond_subgraph_index) { + fbb_.AddElement(WhileOptions::VT_COND_SUBGRAPH_INDEX, cond_subgraph_index, 0); + } + void add_body_subgraph_index(int32_t body_subgraph_index) { + fbb_.AddElement(WhileOptions::VT_BODY_SUBGRAPH_INDEX, body_subgraph_index, 0); + } + explicit WhileOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateWhileOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t cond_subgraph_index = 0, + int32_t body_subgraph_index = 0) { + WhileOptionsBuilder builder_(_fbb); + builder_.add_body_subgraph_index(body_subgraph_index); + builder_.add_cond_subgraph_index(cond_subgraph_index); + return builder_.Finish(); +} + +flatbuffers::Offset CreateWhileOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct NonMaxSuppressionV4OptionsT : public flatbuffers::NativeTable { + typedef NonMaxSuppressionV4Options TableType; +}; + +struct NonMaxSuppressionV4Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef NonMaxSuppressionV4OptionsT NativeTableType; + typedef NonMaxSuppressionV4OptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + NonMaxSuppressionV4OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(NonMaxSuppressionV4OptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV4OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct NonMaxSuppressionV4OptionsBuilder { + typedef NonMaxSuppressionV4Options Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit NonMaxSuppressionV4OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateNonMaxSuppressionV4Options( + flatbuffers::FlatBufferBuilder &_fbb) { + NonMaxSuppressionV4OptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateNonMaxSuppressionV4Options(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV4OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct NonMaxSuppressionV5OptionsT : public flatbuffers::NativeTable { + typedef NonMaxSuppressionV5Options TableType; +}; + +struct NonMaxSuppressionV5Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef NonMaxSuppressionV5OptionsT NativeTableType; + typedef NonMaxSuppressionV5OptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + NonMaxSuppressionV5OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(NonMaxSuppressionV5OptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV5OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct NonMaxSuppressionV5OptionsBuilder { + typedef NonMaxSuppressionV5Options Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit NonMaxSuppressionV5OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateNonMaxSuppressionV5Options( + flatbuffers::FlatBufferBuilder &_fbb) { + NonMaxSuppressionV5OptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateNonMaxSuppressionV5Options(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV5OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ScatterNdOptionsT : public flatbuffers::NativeTable { + typedef ScatterNdOptions TableType; +}; + +struct ScatterNdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ScatterNdOptionsT NativeTableType; + typedef ScatterNdOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + ScatterNdOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ScatterNdOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ScatterNdOptionsBuilder { + typedef ScatterNdOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit ScatterNdOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateScatterNdOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + ScatterNdOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateScatterNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SelectV2OptionsT : public flatbuffers::NativeTable { + typedef SelectV2Options TableType; +}; + +struct SelectV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SelectV2OptionsT NativeTableType; + typedef SelectV2OptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + SelectV2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SelectV2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SelectV2OptionsBuilder { + typedef SelectV2Options Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit SelectV2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSelectV2Options( + flatbuffers::FlatBufferBuilder &_fbb) { + SelectV2OptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSelectV2Options(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct DensifyOptionsT : public flatbuffers::NativeTable { + typedef DensifyOptions TableType; +}; + +struct DensifyOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef DensifyOptionsT NativeTableType; + typedef DensifyOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + DensifyOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(DensifyOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct DensifyOptionsBuilder { + typedef DensifyOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit DensifyOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateDensifyOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + DensifyOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateDensifyOptions(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SegmentSumOptionsT : public flatbuffers::NativeTable { + typedef SegmentSumOptions TableType; +}; + +struct SegmentSumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SegmentSumOptionsT NativeTableType; + typedef SegmentSumOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + SegmentSumOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SegmentSumOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SegmentSumOptionsBuilder { + typedef SegmentSumOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit SegmentSumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSegmentSumOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + SegmentSumOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct BatchMatMulOptionsT : public flatbuffers::NativeTable { + typedef BatchMatMulOptions TableType; + bool adj_x = false; + bool adj_y = false; + bool asymmetric_quantize_inputs = false; +}; + +struct BatchMatMulOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef BatchMatMulOptionsT NativeTableType; + typedef BatchMatMulOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ADJ_X = 4, + VT_ADJ_Y = 6, + VT_ASYMMETRIC_QUANTIZE_INPUTS = 8 + }; + bool adj_x() const { + return GetField(VT_ADJ_X, 0) != 0; + } + bool adj_y() const { + return GetField(VT_ADJ_Y, 0) != 0; + } + bool asymmetric_quantize_inputs() const { + return GetField(VT_ASYMMETRIC_QUANTIZE_INPUTS, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ADJ_X, 1) && + VerifyField(verifier, VT_ADJ_Y, 1) && + VerifyField(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && + verifier.EndTable(); + } + BatchMatMulOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(BatchMatMulOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct BatchMatMulOptionsBuilder { + typedef BatchMatMulOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_adj_x(bool adj_x) { + fbb_.AddElement(BatchMatMulOptions::VT_ADJ_X, static_cast(adj_x), 0); + } + void add_adj_y(bool adj_y) { + fbb_.AddElement(BatchMatMulOptions::VT_ADJ_Y, static_cast(adj_y), 0); + } + void add_asymmetric_quantize_inputs(bool asymmetric_quantize_inputs) { + fbb_.AddElement(BatchMatMulOptions::VT_ASYMMETRIC_QUANTIZE_INPUTS, static_cast(asymmetric_quantize_inputs), 0); + } + explicit BatchMatMulOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateBatchMatMulOptions( + flatbuffers::FlatBufferBuilder &_fbb, + bool adj_x = false, + bool adj_y = false, + bool asymmetric_quantize_inputs = false) { + BatchMatMulOptionsBuilder builder_(_fbb); + builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs); + builder_.add_adj_y(adj_y); + builder_.add_adj_x(adj_x); + return builder_.Finish(); +} + +flatbuffers::Offset CreateBatchMatMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct CumsumOptionsT : public flatbuffers::NativeTable { + typedef CumsumOptions TableType; + bool exclusive = false; + bool reverse = false; +}; + +struct CumsumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef CumsumOptionsT NativeTableType; + typedef CumsumOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_EXCLUSIVE = 4, + VT_REVERSE = 6 + }; + bool exclusive() const { + return GetField(VT_EXCLUSIVE, 0) != 0; + } + bool reverse() const { + return GetField(VT_REVERSE, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_EXCLUSIVE, 1) && + VerifyField(verifier, VT_REVERSE, 1) && + verifier.EndTable(); + } + CumsumOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(CumsumOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct CumsumOptionsBuilder { + typedef CumsumOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_exclusive(bool exclusive) { + fbb_.AddElement(CumsumOptions::VT_EXCLUSIVE, static_cast(exclusive), 0); + } + void add_reverse(bool reverse) { + fbb_.AddElement(CumsumOptions::VT_REVERSE, static_cast(reverse), 0); + } + explicit CumsumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateCumsumOptions( + flatbuffers::FlatBufferBuilder &_fbb, + bool exclusive = false, + bool reverse = false) { + CumsumOptionsBuilder builder_(_fbb); + builder_.add_reverse(reverse); + builder_.add_exclusive(exclusive); + return builder_.Finish(); +} + +flatbuffers::Offset CreateCumsumOptions(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct BroadcastToOptionsT : public flatbuffers::NativeTable { + typedef BroadcastToOptions TableType; +}; + +struct BroadcastToOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef BroadcastToOptionsT NativeTableType; + typedef BroadcastToOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + BroadcastToOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(BroadcastToOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct BroadcastToOptionsBuilder { + typedef BroadcastToOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit BroadcastToOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateBroadcastToOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + BroadcastToOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateBroadcastToOptions(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct Rfft2dOptionsT : public flatbuffers::NativeTable { + typedef Rfft2dOptions TableType; +}; + +struct Rfft2dOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef Rfft2dOptionsT NativeTableType; + typedef Rfft2dOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + Rfft2dOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(Rfft2dOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct Rfft2dOptionsBuilder { + typedef Rfft2dOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit Rfft2dOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateRfft2dOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + Rfft2dOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateRfft2dOptions(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct HashtableOptionsT : public flatbuffers::NativeTable { + typedef HashtableOptions TableType; + int32_t table_id = 0; + tflite::TensorType key_dtype = tflite::TensorType_FLOAT32; + tflite::TensorType value_dtype = tflite::TensorType_FLOAT32; +}; + +struct HashtableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef HashtableOptionsT NativeTableType; + typedef HashtableOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_TABLE_ID = 4, + VT_KEY_DTYPE = 6, + VT_VALUE_DTYPE = 8 + }; + int32_t table_id() const { + return GetField(VT_TABLE_ID, 0); + } + tflite::TensorType key_dtype() const { + return static_cast(GetField(VT_KEY_DTYPE, 0)); + } + tflite::TensorType value_dtype() const { + return static_cast(GetField(VT_VALUE_DTYPE, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_TABLE_ID, 4) && + VerifyField(verifier, VT_KEY_DTYPE, 1) && + VerifyField(verifier, VT_VALUE_DTYPE, 1) && + verifier.EndTable(); + } + HashtableOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(HashtableOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct HashtableOptionsBuilder { + typedef HashtableOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_table_id(int32_t table_id) { + fbb_.AddElement(HashtableOptions::VT_TABLE_ID, table_id, 0); + } + void add_key_dtype(tflite::TensorType key_dtype) { + fbb_.AddElement(HashtableOptions::VT_KEY_DTYPE, static_cast(key_dtype), 0); + } + void add_value_dtype(tflite::TensorType value_dtype) { + fbb_.AddElement(HashtableOptions::VT_VALUE_DTYPE, static_cast(value_dtype), 0); + } + explicit HashtableOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateHashtableOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t table_id = 0, + tflite::TensorType key_dtype = tflite::TensorType_FLOAT32, + tflite::TensorType value_dtype = tflite::TensorType_FLOAT32) { + HashtableOptionsBuilder builder_(_fbb); + builder_.add_table_id(table_id); + builder_.add_value_dtype(value_dtype); + builder_.add_key_dtype(key_dtype); + return builder_.Finish(); +} + +flatbuffers::Offset CreateHashtableOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct HashtableFindOptionsT : public flatbuffers::NativeTable { + typedef HashtableFindOptions TableType; +}; + +struct HashtableFindOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef HashtableFindOptionsT NativeTableType; + typedef HashtableFindOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + HashtableFindOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(HashtableFindOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct HashtableFindOptionsBuilder { + typedef HashtableFindOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit HashtableFindOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateHashtableFindOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + HashtableFindOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateHashtableFindOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct HashtableImportOptionsT : public flatbuffers::NativeTable { + typedef HashtableImportOptions TableType; +}; + +struct HashtableImportOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef HashtableImportOptionsT NativeTableType; + typedef HashtableImportOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + HashtableImportOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(HashtableImportOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableImportOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct HashtableImportOptionsBuilder { + typedef HashtableImportOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit HashtableImportOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateHashtableImportOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + HashtableImportOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateHashtableImportOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableImportOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct HashtableSizeOptionsT : public flatbuffers::NativeTable { + typedef HashtableSizeOptions TableType; +}; + +struct HashtableSizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef HashtableSizeOptionsT NativeTableType; + typedef HashtableSizeOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + HashtableSizeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(HashtableSizeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct HashtableSizeOptionsBuilder { + typedef HashtableSizeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit HashtableSizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateHashtableSizeOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + HashtableSizeOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateHashtableSizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct VarHandleOptionsT : public flatbuffers::NativeTable { + typedef VarHandleOptions TableType; + std::string container{}; + std::string shared_name{}; +}; + +struct VarHandleOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef VarHandleOptionsT NativeTableType; + typedef VarHandleOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_CONTAINER = 4, + VT_SHARED_NAME = 6 + }; + const flatbuffers::String *container() const { + return GetPointer(VT_CONTAINER); + } + const flatbuffers::String *shared_name() const { + return GetPointer(VT_SHARED_NAME); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_CONTAINER) && + verifier.VerifyString(container()) && + VerifyOffset(verifier, VT_SHARED_NAME) && + verifier.VerifyString(shared_name()) && + verifier.EndTable(); + } + VarHandleOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(VarHandleOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct VarHandleOptionsBuilder { + typedef VarHandleOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_container(flatbuffers::Offset container) { + fbb_.AddOffset(VarHandleOptions::VT_CONTAINER, container); + } + void add_shared_name(flatbuffers::Offset shared_name) { + fbb_.AddOffset(VarHandleOptions::VT_SHARED_NAME, shared_name); + } + explicit VarHandleOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateVarHandleOptions( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset container = 0, + flatbuffers::Offset shared_name = 0) { + VarHandleOptionsBuilder builder_(_fbb); + builder_.add_shared_name(shared_name); + builder_.add_container(container); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateVarHandleOptionsDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *container = nullptr, + const char *shared_name = nullptr) { + auto container__ = container ? _fbb.CreateString(container) : 0; + auto shared_name__ = shared_name ? _fbb.CreateString(shared_name) : 0; + return tflite::CreateVarHandleOptions( + _fbb, + container__, + shared_name__); +} + +flatbuffers::Offset CreateVarHandleOptions(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ReadVariableOptionsT : public flatbuffers::NativeTable { + typedef ReadVariableOptions TableType; +}; + +struct ReadVariableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ReadVariableOptionsT NativeTableType; + typedef ReadVariableOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + ReadVariableOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ReadVariableOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ReadVariableOptionsBuilder { + typedef ReadVariableOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit ReadVariableOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateReadVariableOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + ReadVariableOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateReadVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct AssignVariableOptionsT : public flatbuffers::NativeTable { + typedef AssignVariableOptions TableType; +}; + +struct AssignVariableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef AssignVariableOptionsT NativeTableType; + typedef AssignVariableOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + AssignVariableOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(AssignVariableOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct AssignVariableOptionsBuilder { + typedef AssignVariableOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit AssignVariableOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateAssignVariableOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + AssignVariableOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateAssignVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct RandomOptionsT : public flatbuffers::NativeTable { + typedef RandomOptions TableType; + int64_t seed = 0; + int64_t seed2 = 0; +}; + +struct RandomOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef RandomOptionsT NativeTableType; + typedef RandomOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SEED = 4, + VT_SEED2 = 6 + }; + int64_t seed() const { + return GetField(VT_SEED, 0); + } + int64_t seed2() const { + return GetField(VT_SEED2, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_SEED, 8) && + VerifyField(verifier, VT_SEED2, 8) && + verifier.EndTable(); + } + RandomOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RandomOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct RandomOptionsBuilder { + typedef RandomOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_seed(int64_t seed) { + fbb_.AddElement(RandomOptions::VT_SEED, seed, 0); + } + void add_seed2(int64_t seed2) { + fbb_.AddElement(RandomOptions::VT_SEED2, seed2, 0); + } + explicit RandomOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateRandomOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int64_t seed = 0, + int64_t seed2 = 0) { + RandomOptionsBuilder builder_(_fbb); + builder_.add_seed2(seed2); + builder_.add_seed(seed); + return builder_.Finish(); +} + +flatbuffers::Offset CreateRandomOptions(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct BucketizeOptionsT : public flatbuffers::NativeTable { + typedef BucketizeOptions TableType; + std::vector boundaries{}; +}; + +struct BucketizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef BucketizeOptionsT NativeTableType; + typedef BucketizeOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_BOUNDARIES = 4 + }; + const flatbuffers::Vector *boundaries() const { + return GetPointer *>(VT_BOUNDARIES); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_BOUNDARIES) && + verifier.VerifyVector(boundaries()) && + verifier.EndTable(); + } + BucketizeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(BucketizeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct BucketizeOptionsBuilder { + typedef BucketizeOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_boundaries(flatbuffers::Offset> boundaries) { + fbb_.AddOffset(BucketizeOptions::VT_BOUNDARIES, boundaries); + } + explicit BucketizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateBucketizeOptions( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> boundaries = 0) { + BucketizeOptionsBuilder builder_(_fbb); + builder_.add_boundaries(boundaries); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateBucketizeOptionsDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *boundaries = nullptr) { + auto boundaries__ = boundaries ? _fbb.CreateVector(*boundaries) : 0; + return tflite::CreateBucketizeOptions( + _fbb, + boundaries__); +} + +flatbuffers::Offset CreateBucketizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct GeluOptionsT : public flatbuffers::NativeTable { + typedef GeluOptions TableType; + bool approximate = false; +}; + +struct GeluOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef GeluOptionsT NativeTableType; + typedef GeluOptionsBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_APPROXIMATE = 4 + }; + bool approximate() const { + return GetField(VT_APPROXIMATE, 0) != 0; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_APPROXIMATE, 1) && + verifier.EndTable(); + } + GeluOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(GeluOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct GeluOptionsBuilder { + typedef GeluOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_approximate(bool approximate) { + fbb_.AddElement(GeluOptions::VT_APPROXIMATE, static_cast(approximate), 0); + } + explicit GeluOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateGeluOptions( + flatbuffers::FlatBufferBuilder &_fbb, + bool approximate = false) { + GeluOptionsBuilder builder_(_fbb); + builder_.add_approximate(approximate); + return builder_.Finish(); +} + +flatbuffers::Offset CreateGeluOptions(flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct DynamicUpdateSliceOptionsT : public flatbuffers::NativeTable { + typedef DynamicUpdateSliceOptions TableType; +}; + +struct DynamicUpdateSliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef DynamicUpdateSliceOptionsT NativeTableType; + typedef DynamicUpdateSliceOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + DynamicUpdateSliceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(DynamicUpdateSliceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const DynamicUpdateSliceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct DynamicUpdateSliceOptionsBuilder { + typedef DynamicUpdateSliceOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit DynamicUpdateSliceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateDynamicUpdateSliceOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + DynamicUpdateSliceOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateDynamicUpdateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const DynamicUpdateSliceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct UnsortedSegmentProdOptionsT : public flatbuffers::NativeTable { + typedef UnsortedSegmentProdOptions TableType; +}; + +struct UnsortedSegmentProdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef UnsortedSegmentProdOptionsT NativeTableType; + typedef UnsortedSegmentProdOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + UnsortedSegmentProdOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(UnsortedSegmentProdOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentProdOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct UnsortedSegmentProdOptionsBuilder { + typedef UnsortedSegmentProdOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit UnsortedSegmentProdOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUnsortedSegmentProdOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + UnsortedSegmentProdOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateUnsortedSegmentProdOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentProdOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct UnsortedSegmentMaxOptionsT : public flatbuffers::NativeTable { + typedef UnsortedSegmentMaxOptions TableType; +}; + +struct UnsortedSegmentMaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef UnsortedSegmentMaxOptionsT NativeTableType; + typedef UnsortedSegmentMaxOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + UnsortedSegmentMaxOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(UnsortedSegmentMaxOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMaxOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct UnsortedSegmentMaxOptionsBuilder { + typedef UnsortedSegmentMaxOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit UnsortedSegmentMaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUnsortedSegmentMaxOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + UnsortedSegmentMaxOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateUnsortedSegmentMaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMaxOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct UnsortedSegmentSumOptionsT : public flatbuffers::NativeTable { + typedef UnsortedSegmentSumOptions TableType; +}; + +struct UnsortedSegmentSumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef UnsortedSegmentSumOptionsT NativeTableType; + typedef UnsortedSegmentSumOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + UnsortedSegmentSumOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(UnsortedSegmentSumOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentSumOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct UnsortedSegmentSumOptionsBuilder { + typedef UnsortedSegmentSumOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit UnsortedSegmentSumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUnsortedSegmentSumOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + UnsortedSegmentSumOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateUnsortedSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentSumOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ATan2OptionsT : public flatbuffers::NativeTable { + typedef ATan2Options TableType; +}; + +struct ATan2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ATan2OptionsT NativeTableType; + typedef ATan2OptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + ATan2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ATan2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ATan2OptionsBuilder { + typedef ATan2Options Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit ATan2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateATan2Options( + flatbuffers::FlatBufferBuilder &_fbb) { + ATan2OptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateATan2Options(flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct UnsortedSegmentMinOptionsT : public flatbuffers::NativeTable { + typedef UnsortedSegmentMinOptions TableType; +}; + +struct UnsortedSegmentMinOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef UnsortedSegmentMinOptionsT NativeTableType; + typedef UnsortedSegmentMinOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + UnsortedSegmentMinOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(UnsortedSegmentMinOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMinOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct UnsortedSegmentMinOptionsBuilder { + typedef UnsortedSegmentMinOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit UnsortedSegmentMinOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateUnsortedSegmentMinOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + UnsortedSegmentMinOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateUnsortedSegmentMinOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMinOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SignOptionsT : public flatbuffers::NativeTable { + typedef SignOptions TableType; +}; + +struct SignOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SignOptionsT NativeTableType; + typedef SignOptionsBuilder Builder; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + SignOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SignOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SignOptionsBuilder { + typedef SignOptions Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit SignOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSignOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + SignOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSignOptions(flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct OperatorCodeT : public flatbuffers::NativeTable { + typedef OperatorCode TableType; + int8_t deprecated_builtin_code = 0; + std::string custom_code{}; + int32_t version = 1; + tflite::BuiltinOperator builtin_code = tflite::BuiltinOperator_ADD; +}; + +struct OperatorCode FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef OperatorCodeT NativeTableType; + typedef OperatorCodeBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_DEPRECATED_BUILTIN_CODE = 4, + VT_CUSTOM_CODE = 6, + VT_VERSION = 8, + VT_BUILTIN_CODE = 10 + }; + int8_t deprecated_builtin_code() const { + return GetField(VT_DEPRECATED_BUILTIN_CODE, 0); + } + const flatbuffers::String *custom_code() const { + return GetPointer(VT_CUSTOM_CODE); + } + int32_t version() const { + return GetField(VT_VERSION, 1); + } + tflite::BuiltinOperator builtin_code() const { + return static_cast(GetField(VT_BUILTIN_CODE, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_DEPRECATED_BUILTIN_CODE, 1) && + VerifyOffset(verifier, VT_CUSTOM_CODE) && + verifier.VerifyString(custom_code()) && + VerifyField(verifier, VT_VERSION, 4) && + VerifyField(verifier, VT_BUILTIN_CODE, 4) && + verifier.EndTable(); + } + OperatorCodeT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(OperatorCodeT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct OperatorCodeBuilder { + typedef OperatorCode Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_deprecated_builtin_code(int8_t deprecated_builtin_code) { + fbb_.AddElement(OperatorCode::VT_DEPRECATED_BUILTIN_CODE, deprecated_builtin_code, 0); + } + void add_custom_code(flatbuffers::Offset custom_code) { + fbb_.AddOffset(OperatorCode::VT_CUSTOM_CODE, custom_code); + } + void add_version(int32_t version) { + fbb_.AddElement(OperatorCode::VT_VERSION, version, 1); + } + void add_builtin_code(tflite::BuiltinOperator builtin_code) { + fbb_.AddElement(OperatorCode::VT_BUILTIN_CODE, static_cast(builtin_code), 0); + } + explicit OperatorCodeBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateOperatorCode( + flatbuffers::FlatBufferBuilder &_fbb, + int8_t deprecated_builtin_code = 0, + flatbuffers::Offset custom_code = 0, + int32_t version = 1, + tflite::BuiltinOperator builtin_code = tflite::BuiltinOperator_ADD) { + OperatorCodeBuilder builder_(_fbb); + builder_.add_builtin_code(builtin_code); + builder_.add_version(version); + builder_.add_custom_code(custom_code); + builder_.add_deprecated_builtin_code(deprecated_builtin_code); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateOperatorCodeDirect( + flatbuffers::FlatBufferBuilder &_fbb, + int8_t deprecated_builtin_code = 0, + const char *custom_code = nullptr, + int32_t version = 1, + tflite::BuiltinOperator builtin_code = tflite::BuiltinOperator_ADD) { + auto custom_code__ = custom_code ? _fbb.CreateString(custom_code) : 0; + return tflite::CreateOperatorCode( + _fbb, + deprecated_builtin_code, + custom_code__, + version, + builtin_code); +} + +flatbuffers::Offset CreateOperatorCode(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct OperatorT : public flatbuffers::NativeTable { + typedef Operator TableType; + uint32_t opcode_index = 0; + std::vector inputs{}; + std::vector outputs{}; + tflite::BuiltinOptionsUnion builtin_options{}; + std::vector custom_options{}; + tflite::CustomOptionsFormat custom_options_format = tflite::CustomOptionsFormat_FLEXBUFFERS; + std::vector mutating_variable_inputs{}; + std::vector intermediates{}; +}; + +struct Operator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef OperatorT NativeTableType; + typedef OperatorBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_OPCODE_INDEX = 4, + VT_INPUTS = 6, + VT_OUTPUTS = 8, + VT_BUILTIN_OPTIONS_TYPE = 10, + VT_BUILTIN_OPTIONS = 12, + VT_CUSTOM_OPTIONS = 14, + VT_CUSTOM_OPTIONS_FORMAT = 16, + VT_MUTATING_VARIABLE_INPUTS = 18, + VT_INTERMEDIATES = 20 + }; + uint32_t opcode_index() const { + return GetField(VT_OPCODE_INDEX, 0); + } + const flatbuffers::Vector *inputs() const { + return GetPointer *>(VT_INPUTS); + } + const flatbuffers::Vector *outputs() const { + return GetPointer *>(VT_OUTPUTS); + } + tflite::BuiltinOptions builtin_options_type() const { + return static_cast(GetField(VT_BUILTIN_OPTIONS_TYPE, 0)); + } + const void *builtin_options() const { + return GetPointer(VT_BUILTIN_OPTIONS); + } + template const T *builtin_options_as() const; + const tflite::Conv2DOptions *builtin_options_as_Conv2DOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_Conv2DOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::DepthwiseConv2DOptions *builtin_options_as_DepthwiseConv2DOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_DepthwiseConv2DOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ConcatEmbeddingsOptions *builtin_options_as_ConcatEmbeddingsOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ConcatEmbeddingsOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LSHProjectionOptions *builtin_options_as_LSHProjectionOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LSHProjectionOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::Pool2DOptions *builtin_options_as_Pool2DOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_Pool2DOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SVDFOptions *builtin_options_as_SVDFOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SVDFOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::RNNOptions *builtin_options_as_RNNOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_RNNOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::FullyConnectedOptions *builtin_options_as_FullyConnectedOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_FullyConnectedOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SoftmaxOptions *builtin_options_as_SoftmaxOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SoftmaxOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ConcatenationOptions *builtin_options_as_ConcatenationOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ConcatenationOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::AddOptions *builtin_options_as_AddOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_AddOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::L2NormOptions *builtin_options_as_L2NormOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_L2NormOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LocalResponseNormalizationOptions *builtin_options_as_LocalResponseNormalizationOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LocalResponseNormalizationOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LSTMOptions *builtin_options_as_LSTMOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LSTMOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ResizeBilinearOptions *builtin_options_as_ResizeBilinearOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ResizeBilinearOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::CallOptions *builtin_options_as_CallOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_CallOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ReshapeOptions *builtin_options_as_ReshapeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ReshapeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SkipGramOptions *builtin_options_as_SkipGramOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SkipGramOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SpaceToDepthOptions *builtin_options_as_SpaceToDepthOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SpaceToDepthOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::EmbeddingLookupSparseOptions *builtin_options_as_EmbeddingLookupSparseOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_EmbeddingLookupSparseOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::MulOptions *builtin_options_as_MulOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_MulOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::PadOptions *builtin_options_as_PadOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_PadOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::GatherOptions *builtin_options_as_GatherOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_GatherOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::BatchToSpaceNDOptions *builtin_options_as_BatchToSpaceNDOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_BatchToSpaceNDOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SpaceToBatchNDOptions *builtin_options_as_SpaceToBatchNDOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SpaceToBatchNDOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::TransposeOptions *builtin_options_as_TransposeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_TransposeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ReducerOptions *builtin_options_as_ReducerOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ReducerOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SubOptions *builtin_options_as_SubOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SubOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::DivOptions *builtin_options_as_DivOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_DivOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SqueezeOptions *builtin_options_as_SqueezeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SqueezeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SequenceRNNOptions *builtin_options_as_SequenceRNNOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SequenceRNNOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::StridedSliceOptions *builtin_options_as_StridedSliceOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_StridedSliceOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ExpOptions *builtin_options_as_ExpOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ExpOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::TopKV2Options *builtin_options_as_TopKV2Options() const { + return builtin_options_type() == tflite::BuiltinOptions_TopKV2Options ? static_cast(builtin_options()) : nullptr; + } + const tflite::SplitOptions *builtin_options_as_SplitOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SplitOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LogSoftmaxOptions *builtin_options_as_LogSoftmaxOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LogSoftmaxOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::CastOptions *builtin_options_as_CastOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_CastOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::DequantizeOptions *builtin_options_as_DequantizeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_DequantizeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::MaximumMinimumOptions *builtin_options_as_MaximumMinimumOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_MaximumMinimumOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ArgMaxOptions *builtin_options_as_ArgMaxOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ArgMaxOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LessOptions *builtin_options_as_LessOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LessOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::NegOptions *builtin_options_as_NegOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_NegOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::PadV2Options *builtin_options_as_PadV2Options() const { + return builtin_options_type() == tflite::BuiltinOptions_PadV2Options ? static_cast(builtin_options()) : nullptr; + } + const tflite::GreaterOptions *builtin_options_as_GreaterOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_GreaterOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::GreaterEqualOptions *builtin_options_as_GreaterEqualOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_GreaterEqualOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LessEqualOptions *builtin_options_as_LessEqualOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LessEqualOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SelectOptions *builtin_options_as_SelectOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SelectOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SliceOptions *builtin_options_as_SliceOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SliceOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::TransposeConvOptions *builtin_options_as_TransposeConvOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_TransposeConvOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SparseToDenseOptions *builtin_options_as_SparseToDenseOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SparseToDenseOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::TileOptions *builtin_options_as_TileOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_TileOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ExpandDimsOptions *builtin_options_as_ExpandDimsOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ExpandDimsOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::EqualOptions *builtin_options_as_EqualOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_EqualOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::NotEqualOptions *builtin_options_as_NotEqualOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_NotEqualOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ShapeOptions *builtin_options_as_ShapeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ShapeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::PowOptions *builtin_options_as_PowOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_PowOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ArgMinOptions *builtin_options_as_ArgMinOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ArgMinOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::FakeQuantOptions *builtin_options_as_FakeQuantOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_FakeQuantOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::PackOptions *builtin_options_as_PackOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_PackOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LogicalOrOptions *builtin_options_as_LogicalOrOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LogicalOrOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::OneHotOptions *builtin_options_as_OneHotOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_OneHotOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LogicalAndOptions *builtin_options_as_LogicalAndOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LogicalAndOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LogicalNotOptions *builtin_options_as_LogicalNotOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LogicalNotOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::UnpackOptions *builtin_options_as_UnpackOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_UnpackOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::FloorDivOptions *builtin_options_as_FloorDivOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_FloorDivOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SquareOptions *builtin_options_as_SquareOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SquareOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ZerosLikeOptions *builtin_options_as_ZerosLikeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ZerosLikeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::FillOptions *builtin_options_as_FillOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_FillOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::BidirectionalSequenceLSTMOptions *builtin_options_as_BidirectionalSequenceLSTMOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_BidirectionalSequenceLSTMOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::BidirectionalSequenceRNNOptions *builtin_options_as_BidirectionalSequenceRNNOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_BidirectionalSequenceRNNOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::UnidirectionalSequenceLSTMOptions *builtin_options_as_UnidirectionalSequenceLSTMOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_UnidirectionalSequenceLSTMOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::FloorModOptions *builtin_options_as_FloorModOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_FloorModOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::RangeOptions *builtin_options_as_RangeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_RangeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ResizeNearestNeighborOptions *builtin_options_as_ResizeNearestNeighborOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ResizeNearestNeighborOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::LeakyReluOptions *builtin_options_as_LeakyReluOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_LeakyReluOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SquaredDifferenceOptions *builtin_options_as_SquaredDifferenceOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SquaredDifferenceOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::MirrorPadOptions *builtin_options_as_MirrorPadOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_MirrorPadOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::AbsOptions *builtin_options_as_AbsOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_AbsOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SplitVOptions *builtin_options_as_SplitVOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SplitVOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::UniqueOptions *builtin_options_as_UniqueOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_UniqueOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ReverseV2Options *builtin_options_as_ReverseV2Options() const { + return builtin_options_type() == tflite::BuiltinOptions_ReverseV2Options ? static_cast(builtin_options()) : nullptr; + } + const tflite::AddNOptions *builtin_options_as_AddNOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_AddNOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::GatherNdOptions *builtin_options_as_GatherNdOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_GatherNdOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::CosOptions *builtin_options_as_CosOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_CosOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::WhereOptions *builtin_options_as_WhereOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_WhereOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::RankOptions *builtin_options_as_RankOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_RankOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ReverseSequenceOptions *builtin_options_as_ReverseSequenceOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ReverseSequenceOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::MatrixDiagOptions *builtin_options_as_MatrixDiagOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_MatrixDiagOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::QuantizeOptions *builtin_options_as_QuantizeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_QuantizeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::MatrixSetDiagOptions *builtin_options_as_MatrixSetDiagOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_MatrixSetDiagOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::HardSwishOptions *builtin_options_as_HardSwishOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_HardSwishOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::IfOptions *builtin_options_as_IfOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_IfOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::WhileOptions *builtin_options_as_WhileOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_WhileOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::DepthToSpaceOptions *builtin_options_as_DepthToSpaceOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_DepthToSpaceOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::NonMaxSuppressionV4Options *builtin_options_as_NonMaxSuppressionV4Options() const { + return builtin_options_type() == tflite::BuiltinOptions_NonMaxSuppressionV4Options ? static_cast(builtin_options()) : nullptr; + } + const tflite::NonMaxSuppressionV5Options *builtin_options_as_NonMaxSuppressionV5Options() const { + return builtin_options_type() == tflite::BuiltinOptions_NonMaxSuppressionV5Options ? static_cast(builtin_options()) : nullptr; + } + const tflite::ScatterNdOptions *builtin_options_as_ScatterNdOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ScatterNdOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SelectV2Options *builtin_options_as_SelectV2Options() const { + return builtin_options_type() == tflite::BuiltinOptions_SelectV2Options ? static_cast(builtin_options()) : nullptr; + } + const tflite::DensifyOptions *builtin_options_as_DensifyOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_DensifyOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::SegmentSumOptions *builtin_options_as_SegmentSumOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SegmentSumOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::BatchMatMulOptions *builtin_options_as_BatchMatMulOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_BatchMatMulOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::CumsumOptions *builtin_options_as_CumsumOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_CumsumOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::CallOnceOptions *builtin_options_as_CallOnceOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_CallOnceOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::BroadcastToOptions *builtin_options_as_BroadcastToOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_BroadcastToOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::Rfft2dOptions *builtin_options_as_Rfft2dOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_Rfft2dOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::Conv3DOptions *builtin_options_as_Conv3DOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_Conv3DOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::HashtableOptions *builtin_options_as_HashtableOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_HashtableOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::HashtableFindOptions *builtin_options_as_HashtableFindOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_HashtableFindOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::HashtableImportOptions *builtin_options_as_HashtableImportOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_HashtableImportOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::HashtableSizeOptions *builtin_options_as_HashtableSizeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_HashtableSizeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::VarHandleOptions *builtin_options_as_VarHandleOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_VarHandleOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ReadVariableOptions *builtin_options_as_ReadVariableOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_ReadVariableOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::AssignVariableOptions *builtin_options_as_AssignVariableOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_AssignVariableOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::RandomOptions *builtin_options_as_RandomOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_RandomOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::BucketizeOptions *builtin_options_as_BucketizeOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_BucketizeOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::GeluOptions *builtin_options_as_GeluOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_GeluOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::DynamicUpdateSliceOptions *builtin_options_as_DynamicUpdateSliceOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_DynamicUpdateSliceOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::UnsortedSegmentProdOptions *builtin_options_as_UnsortedSegmentProdOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_UnsortedSegmentProdOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::UnsortedSegmentMaxOptions *builtin_options_as_UnsortedSegmentMaxOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_UnsortedSegmentMaxOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::UnsortedSegmentMinOptions *builtin_options_as_UnsortedSegmentMinOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_UnsortedSegmentMinOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::UnsortedSegmentSumOptions *builtin_options_as_UnsortedSegmentSumOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_UnsortedSegmentSumOptions ? static_cast(builtin_options()) : nullptr; + } + const tflite::ATan2Options *builtin_options_as_ATan2Options() const { + return builtin_options_type() == tflite::BuiltinOptions_ATan2Options ? static_cast(builtin_options()) : nullptr; + } + const tflite::SignOptions *builtin_options_as_SignOptions() const { + return builtin_options_type() == tflite::BuiltinOptions_SignOptions ? static_cast(builtin_options()) : nullptr; + } + const flatbuffers::Vector *custom_options() const { + return GetPointer *>(VT_CUSTOM_OPTIONS); + } + tflite::CustomOptionsFormat custom_options_format() const { + return static_cast(GetField(VT_CUSTOM_OPTIONS_FORMAT, 0)); + } + const flatbuffers::Vector *mutating_variable_inputs() const { + return GetPointer *>(VT_MUTATING_VARIABLE_INPUTS); + } + const flatbuffers::Vector *intermediates() const { + return GetPointer *>(VT_INTERMEDIATES); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_OPCODE_INDEX, 4) && + VerifyOffset(verifier, VT_INPUTS) && + verifier.VerifyVector(inputs()) && + VerifyOffset(verifier, VT_OUTPUTS) && + verifier.VerifyVector(outputs()) && + VerifyField(verifier, VT_BUILTIN_OPTIONS_TYPE, 1) && + VerifyOffset(verifier, VT_BUILTIN_OPTIONS) && + VerifyBuiltinOptions(verifier, builtin_options(), builtin_options_type()) && + VerifyOffset(verifier, VT_CUSTOM_OPTIONS) && + verifier.VerifyVector(custom_options()) && + VerifyField(verifier, VT_CUSTOM_OPTIONS_FORMAT, 1) && + VerifyOffset(verifier, VT_MUTATING_VARIABLE_INPUTS) && + verifier.VerifyVector(mutating_variable_inputs()) && + VerifyOffset(verifier, VT_INTERMEDIATES) && + verifier.VerifyVector(intermediates()) && + verifier.EndTable(); + } + OperatorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(OperatorT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +template<> inline const tflite::Conv2DOptions *Operator::builtin_options_as() const { + return builtin_options_as_Conv2DOptions(); +} + +template<> inline const tflite::DepthwiseConv2DOptions *Operator::builtin_options_as() const { + return builtin_options_as_DepthwiseConv2DOptions(); +} + +template<> inline const tflite::ConcatEmbeddingsOptions *Operator::builtin_options_as() const { + return builtin_options_as_ConcatEmbeddingsOptions(); +} + +template<> inline const tflite::LSHProjectionOptions *Operator::builtin_options_as() const { + return builtin_options_as_LSHProjectionOptions(); +} + +template<> inline const tflite::Pool2DOptions *Operator::builtin_options_as() const { + return builtin_options_as_Pool2DOptions(); +} + +template<> inline const tflite::SVDFOptions *Operator::builtin_options_as() const { + return builtin_options_as_SVDFOptions(); +} + +template<> inline const tflite::RNNOptions *Operator::builtin_options_as() const { + return builtin_options_as_RNNOptions(); +} + +template<> inline const tflite::FullyConnectedOptions *Operator::builtin_options_as() const { + return builtin_options_as_FullyConnectedOptions(); +} + +template<> inline const tflite::SoftmaxOptions *Operator::builtin_options_as() const { + return builtin_options_as_SoftmaxOptions(); +} + +template<> inline const tflite::ConcatenationOptions *Operator::builtin_options_as() const { + return builtin_options_as_ConcatenationOptions(); +} + +template<> inline const tflite::AddOptions *Operator::builtin_options_as() const { + return builtin_options_as_AddOptions(); +} + +template<> inline const tflite::L2NormOptions *Operator::builtin_options_as() const { + return builtin_options_as_L2NormOptions(); +} + +template<> inline const tflite::LocalResponseNormalizationOptions *Operator::builtin_options_as() const { + return builtin_options_as_LocalResponseNormalizationOptions(); +} + +template<> inline const tflite::LSTMOptions *Operator::builtin_options_as() const { + return builtin_options_as_LSTMOptions(); +} + +template<> inline const tflite::ResizeBilinearOptions *Operator::builtin_options_as() const { + return builtin_options_as_ResizeBilinearOptions(); +} + +template<> inline const tflite::CallOptions *Operator::builtin_options_as() const { + return builtin_options_as_CallOptions(); +} + +template<> inline const tflite::ReshapeOptions *Operator::builtin_options_as() const { + return builtin_options_as_ReshapeOptions(); +} + +template<> inline const tflite::SkipGramOptions *Operator::builtin_options_as() const { + return builtin_options_as_SkipGramOptions(); +} + +template<> inline const tflite::SpaceToDepthOptions *Operator::builtin_options_as() const { + return builtin_options_as_SpaceToDepthOptions(); +} + +template<> inline const tflite::EmbeddingLookupSparseOptions *Operator::builtin_options_as() const { + return builtin_options_as_EmbeddingLookupSparseOptions(); +} + +template<> inline const tflite::MulOptions *Operator::builtin_options_as() const { + return builtin_options_as_MulOptions(); +} + +template<> inline const tflite::PadOptions *Operator::builtin_options_as() const { + return builtin_options_as_PadOptions(); +} + +template<> inline const tflite::GatherOptions *Operator::builtin_options_as() const { + return builtin_options_as_GatherOptions(); +} + +template<> inline const tflite::BatchToSpaceNDOptions *Operator::builtin_options_as() const { + return builtin_options_as_BatchToSpaceNDOptions(); +} + +template<> inline const tflite::SpaceToBatchNDOptions *Operator::builtin_options_as() const { + return builtin_options_as_SpaceToBatchNDOptions(); +} + +template<> inline const tflite::TransposeOptions *Operator::builtin_options_as() const { + return builtin_options_as_TransposeOptions(); +} + +template<> inline const tflite::ReducerOptions *Operator::builtin_options_as() const { + return builtin_options_as_ReducerOptions(); +} + +template<> inline const tflite::SubOptions *Operator::builtin_options_as() const { + return builtin_options_as_SubOptions(); +} + +template<> inline const tflite::DivOptions *Operator::builtin_options_as() const { + return builtin_options_as_DivOptions(); +} + +template<> inline const tflite::SqueezeOptions *Operator::builtin_options_as() const { + return builtin_options_as_SqueezeOptions(); +} + +template<> inline const tflite::SequenceRNNOptions *Operator::builtin_options_as() const { + return builtin_options_as_SequenceRNNOptions(); +} + +template<> inline const tflite::StridedSliceOptions *Operator::builtin_options_as() const { + return builtin_options_as_StridedSliceOptions(); +} + +template<> inline const tflite::ExpOptions *Operator::builtin_options_as() const { + return builtin_options_as_ExpOptions(); +} + +template<> inline const tflite::TopKV2Options *Operator::builtin_options_as() const { + return builtin_options_as_TopKV2Options(); +} + +template<> inline const tflite::SplitOptions *Operator::builtin_options_as() const { + return builtin_options_as_SplitOptions(); +} + +template<> inline const tflite::LogSoftmaxOptions *Operator::builtin_options_as() const { + return builtin_options_as_LogSoftmaxOptions(); +} + +template<> inline const tflite::CastOptions *Operator::builtin_options_as() const { + return builtin_options_as_CastOptions(); +} + +template<> inline const tflite::DequantizeOptions *Operator::builtin_options_as() const { + return builtin_options_as_DequantizeOptions(); +} + +template<> inline const tflite::MaximumMinimumOptions *Operator::builtin_options_as() const { + return builtin_options_as_MaximumMinimumOptions(); +} + +template<> inline const tflite::ArgMaxOptions *Operator::builtin_options_as() const { + return builtin_options_as_ArgMaxOptions(); +} + +template<> inline const tflite::LessOptions *Operator::builtin_options_as() const { + return builtin_options_as_LessOptions(); +} + +template<> inline const tflite::NegOptions *Operator::builtin_options_as() const { + return builtin_options_as_NegOptions(); +} + +template<> inline const tflite::PadV2Options *Operator::builtin_options_as() const { + return builtin_options_as_PadV2Options(); +} + +template<> inline const tflite::GreaterOptions *Operator::builtin_options_as() const { + return builtin_options_as_GreaterOptions(); +} + +template<> inline const tflite::GreaterEqualOptions *Operator::builtin_options_as() const { + return builtin_options_as_GreaterEqualOptions(); +} + +template<> inline const tflite::LessEqualOptions *Operator::builtin_options_as() const { + return builtin_options_as_LessEqualOptions(); +} + +template<> inline const tflite::SelectOptions *Operator::builtin_options_as() const { + return builtin_options_as_SelectOptions(); +} + +template<> inline const tflite::SliceOptions *Operator::builtin_options_as() const { + return builtin_options_as_SliceOptions(); +} + +template<> inline const tflite::TransposeConvOptions *Operator::builtin_options_as() const { + return builtin_options_as_TransposeConvOptions(); +} + +template<> inline const tflite::SparseToDenseOptions *Operator::builtin_options_as() const { + return builtin_options_as_SparseToDenseOptions(); +} + +template<> inline const tflite::TileOptions *Operator::builtin_options_as() const { + return builtin_options_as_TileOptions(); +} + +template<> inline const tflite::ExpandDimsOptions *Operator::builtin_options_as() const { + return builtin_options_as_ExpandDimsOptions(); +} + +template<> inline const tflite::EqualOptions *Operator::builtin_options_as() const { + return builtin_options_as_EqualOptions(); +} + +template<> inline const tflite::NotEqualOptions *Operator::builtin_options_as() const { + return builtin_options_as_NotEqualOptions(); +} + +template<> inline const tflite::ShapeOptions *Operator::builtin_options_as() const { + return builtin_options_as_ShapeOptions(); +} + +template<> inline const tflite::PowOptions *Operator::builtin_options_as() const { + return builtin_options_as_PowOptions(); +} + +template<> inline const tflite::ArgMinOptions *Operator::builtin_options_as() const { + return builtin_options_as_ArgMinOptions(); +} + +template<> inline const tflite::FakeQuantOptions *Operator::builtin_options_as() const { + return builtin_options_as_FakeQuantOptions(); +} + +template<> inline const tflite::PackOptions *Operator::builtin_options_as() const { + return builtin_options_as_PackOptions(); +} + +template<> inline const tflite::LogicalOrOptions *Operator::builtin_options_as() const { + return builtin_options_as_LogicalOrOptions(); +} + +template<> inline const tflite::OneHotOptions *Operator::builtin_options_as() const { + return builtin_options_as_OneHotOptions(); +} + +template<> inline const tflite::LogicalAndOptions *Operator::builtin_options_as() const { + return builtin_options_as_LogicalAndOptions(); +} + +template<> inline const tflite::LogicalNotOptions *Operator::builtin_options_as() const { + return builtin_options_as_LogicalNotOptions(); +} + +template<> inline const tflite::UnpackOptions *Operator::builtin_options_as() const { + return builtin_options_as_UnpackOptions(); +} + +template<> inline const tflite::FloorDivOptions *Operator::builtin_options_as() const { + return builtin_options_as_FloorDivOptions(); +} + +template<> inline const tflite::SquareOptions *Operator::builtin_options_as() const { + return builtin_options_as_SquareOptions(); +} + +template<> inline const tflite::ZerosLikeOptions *Operator::builtin_options_as() const { + return builtin_options_as_ZerosLikeOptions(); +} + +template<> inline const tflite::FillOptions *Operator::builtin_options_as() const { + return builtin_options_as_FillOptions(); +} + +template<> inline const tflite::BidirectionalSequenceLSTMOptions *Operator::builtin_options_as() const { + return builtin_options_as_BidirectionalSequenceLSTMOptions(); +} + +template<> inline const tflite::BidirectionalSequenceRNNOptions *Operator::builtin_options_as() const { + return builtin_options_as_BidirectionalSequenceRNNOptions(); +} + +template<> inline const tflite::UnidirectionalSequenceLSTMOptions *Operator::builtin_options_as() const { + return builtin_options_as_UnidirectionalSequenceLSTMOptions(); +} + +template<> inline const tflite::FloorModOptions *Operator::builtin_options_as() const { + return builtin_options_as_FloorModOptions(); +} + +template<> inline const tflite::RangeOptions *Operator::builtin_options_as() const { + return builtin_options_as_RangeOptions(); +} + +template<> inline const tflite::ResizeNearestNeighborOptions *Operator::builtin_options_as() const { + return builtin_options_as_ResizeNearestNeighborOptions(); +} + +template<> inline const tflite::LeakyReluOptions *Operator::builtin_options_as() const { + return builtin_options_as_LeakyReluOptions(); +} + +template<> inline const tflite::SquaredDifferenceOptions *Operator::builtin_options_as() const { + return builtin_options_as_SquaredDifferenceOptions(); +} + +template<> inline const tflite::MirrorPadOptions *Operator::builtin_options_as() const { + return builtin_options_as_MirrorPadOptions(); +} + +template<> inline const tflite::AbsOptions *Operator::builtin_options_as() const { + return builtin_options_as_AbsOptions(); +} + +template<> inline const tflite::SplitVOptions *Operator::builtin_options_as() const { + return builtin_options_as_SplitVOptions(); +} + +template<> inline const tflite::UniqueOptions *Operator::builtin_options_as() const { + return builtin_options_as_UniqueOptions(); +} + +template<> inline const tflite::ReverseV2Options *Operator::builtin_options_as() const { + return builtin_options_as_ReverseV2Options(); +} + +template<> inline const tflite::AddNOptions *Operator::builtin_options_as() const { + return builtin_options_as_AddNOptions(); +} + +template<> inline const tflite::GatherNdOptions *Operator::builtin_options_as() const { + return builtin_options_as_GatherNdOptions(); +} + +template<> inline const tflite::CosOptions *Operator::builtin_options_as() const { + return builtin_options_as_CosOptions(); +} + +template<> inline const tflite::WhereOptions *Operator::builtin_options_as() const { + return builtin_options_as_WhereOptions(); +} + +template<> inline const tflite::RankOptions *Operator::builtin_options_as() const { + return builtin_options_as_RankOptions(); +} + +template<> inline const tflite::ReverseSequenceOptions *Operator::builtin_options_as() const { + return builtin_options_as_ReverseSequenceOptions(); +} + +template<> inline const tflite::MatrixDiagOptions *Operator::builtin_options_as() const { + return builtin_options_as_MatrixDiagOptions(); +} + +template<> inline const tflite::QuantizeOptions *Operator::builtin_options_as() const { + return builtin_options_as_QuantizeOptions(); +} + +template<> inline const tflite::MatrixSetDiagOptions *Operator::builtin_options_as() const { + return builtin_options_as_MatrixSetDiagOptions(); +} + +template<> inline const tflite::HardSwishOptions *Operator::builtin_options_as() const { + return builtin_options_as_HardSwishOptions(); +} + +template<> inline const tflite::IfOptions *Operator::builtin_options_as() const { + return builtin_options_as_IfOptions(); +} + +template<> inline const tflite::WhileOptions *Operator::builtin_options_as() const { + return builtin_options_as_WhileOptions(); +} + +template<> inline const tflite::DepthToSpaceOptions *Operator::builtin_options_as() const { + return builtin_options_as_DepthToSpaceOptions(); +} + +template<> inline const tflite::NonMaxSuppressionV4Options *Operator::builtin_options_as() const { + return builtin_options_as_NonMaxSuppressionV4Options(); +} + +template<> inline const tflite::NonMaxSuppressionV5Options *Operator::builtin_options_as() const { + return builtin_options_as_NonMaxSuppressionV5Options(); +} + +template<> inline const tflite::ScatterNdOptions *Operator::builtin_options_as() const { + return builtin_options_as_ScatterNdOptions(); +} + +template<> inline const tflite::SelectV2Options *Operator::builtin_options_as() const { + return builtin_options_as_SelectV2Options(); +} + +template<> inline const tflite::DensifyOptions *Operator::builtin_options_as() const { + return builtin_options_as_DensifyOptions(); +} + +template<> inline const tflite::SegmentSumOptions *Operator::builtin_options_as() const { + return builtin_options_as_SegmentSumOptions(); +} + +template<> inline const tflite::BatchMatMulOptions *Operator::builtin_options_as() const { + return builtin_options_as_BatchMatMulOptions(); +} + +template<> inline const tflite::CumsumOptions *Operator::builtin_options_as() const { + return builtin_options_as_CumsumOptions(); +} + +template<> inline const tflite::CallOnceOptions *Operator::builtin_options_as() const { + return builtin_options_as_CallOnceOptions(); +} + +template<> inline const tflite::BroadcastToOptions *Operator::builtin_options_as() const { + return builtin_options_as_BroadcastToOptions(); +} + +template<> inline const tflite::Rfft2dOptions *Operator::builtin_options_as() const { + return builtin_options_as_Rfft2dOptions(); +} + +template<> inline const tflite::Conv3DOptions *Operator::builtin_options_as() const { + return builtin_options_as_Conv3DOptions(); +} + +template<> inline const tflite::HashtableOptions *Operator::builtin_options_as() const { + return builtin_options_as_HashtableOptions(); +} + +template<> inline const tflite::HashtableFindOptions *Operator::builtin_options_as() const { + return builtin_options_as_HashtableFindOptions(); +} + +template<> inline const tflite::HashtableImportOptions *Operator::builtin_options_as() const { + return builtin_options_as_HashtableImportOptions(); +} + +template<> inline const tflite::HashtableSizeOptions *Operator::builtin_options_as() const { + return builtin_options_as_HashtableSizeOptions(); +} + +template<> inline const tflite::VarHandleOptions *Operator::builtin_options_as() const { + return builtin_options_as_VarHandleOptions(); +} + +template<> inline const tflite::ReadVariableOptions *Operator::builtin_options_as() const { + return builtin_options_as_ReadVariableOptions(); +} + +template<> inline const tflite::AssignVariableOptions *Operator::builtin_options_as() const { + return builtin_options_as_AssignVariableOptions(); +} + +template<> inline const tflite::RandomOptions *Operator::builtin_options_as() const { + return builtin_options_as_RandomOptions(); +} + +template<> inline const tflite::BucketizeOptions *Operator::builtin_options_as() const { + return builtin_options_as_BucketizeOptions(); +} + +template<> inline const tflite::GeluOptions *Operator::builtin_options_as() const { + return builtin_options_as_GeluOptions(); +} + +template<> inline const tflite::DynamicUpdateSliceOptions *Operator::builtin_options_as() const { + return builtin_options_as_DynamicUpdateSliceOptions(); +} + +template<> inline const tflite::UnsortedSegmentProdOptions *Operator::builtin_options_as() const { + return builtin_options_as_UnsortedSegmentProdOptions(); +} + +template<> inline const tflite::UnsortedSegmentMaxOptions *Operator::builtin_options_as() const { + return builtin_options_as_UnsortedSegmentMaxOptions(); +} + +template<> inline const tflite::UnsortedSegmentMinOptions *Operator::builtin_options_as() const { + return builtin_options_as_UnsortedSegmentMinOptions(); +} + +template<> inline const tflite::UnsortedSegmentSumOptions *Operator::builtin_options_as() const { + return builtin_options_as_UnsortedSegmentSumOptions(); +} + +template<> inline const tflite::ATan2Options *Operator::builtin_options_as() const { + return builtin_options_as_ATan2Options(); +} + +template<> inline const tflite::SignOptions *Operator::builtin_options_as() const { + return builtin_options_as_SignOptions(); +} + +struct OperatorBuilder { + typedef Operator Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_opcode_index(uint32_t opcode_index) { + fbb_.AddElement(Operator::VT_OPCODE_INDEX, opcode_index, 0); + } + void add_inputs(flatbuffers::Offset> inputs) { + fbb_.AddOffset(Operator::VT_INPUTS, inputs); + } + void add_outputs(flatbuffers::Offset> outputs) { + fbb_.AddOffset(Operator::VT_OUTPUTS, outputs); + } + void add_builtin_options_type(tflite::BuiltinOptions builtin_options_type) { + fbb_.AddElement(Operator::VT_BUILTIN_OPTIONS_TYPE, static_cast(builtin_options_type), 0); + } + void add_builtin_options(flatbuffers::Offset builtin_options) { + fbb_.AddOffset(Operator::VT_BUILTIN_OPTIONS, builtin_options); + } + void add_custom_options(flatbuffers::Offset> custom_options) { + fbb_.AddOffset(Operator::VT_CUSTOM_OPTIONS, custom_options); + } + void add_custom_options_format(tflite::CustomOptionsFormat custom_options_format) { + fbb_.AddElement(Operator::VT_CUSTOM_OPTIONS_FORMAT, static_cast(custom_options_format), 0); + } + void add_mutating_variable_inputs(flatbuffers::Offset> mutating_variable_inputs) { + fbb_.AddOffset(Operator::VT_MUTATING_VARIABLE_INPUTS, mutating_variable_inputs); + } + void add_intermediates(flatbuffers::Offset> intermediates) { + fbb_.AddOffset(Operator::VT_INTERMEDIATES, intermediates); + } + explicit OperatorBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateOperator( + flatbuffers::FlatBufferBuilder &_fbb, + uint32_t opcode_index = 0, + flatbuffers::Offset> inputs = 0, + flatbuffers::Offset> outputs = 0, + tflite::BuiltinOptions builtin_options_type = tflite::BuiltinOptions_NONE, + flatbuffers::Offset builtin_options = 0, + flatbuffers::Offset> custom_options = 0, + tflite::CustomOptionsFormat custom_options_format = tflite::CustomOptionsFormat_FLEXBUFFERS, + flatbuffers::Offset> mutating_variable_inputs = 0, + flatbuffers::Offset> intermediates = 0) { + OperatorBuilder builder_(_fbb); + builder_.add_intermediates(intermediates); + builder_.add_mutating_variable_inputs(mutating_variable_inputs); + builder_.add_custom_options(custom_options); + builder_.add_builtin_options(builtin_options); + builder_.add_outputs(outputs); + builder_.add_inputs(inputs); + builder_.add_opcode_index(opcode_index); + builder_.add_custom_options_format(custom_options_format); + builder_.add_builtin_options_type(builtin_options_type); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateOperatorDirect( + flatbuffers::FlatBufferBuilder &_fbb, + uint32_t opcode_index = 0, + const std::vector *inputs = nullptr, + const std::vector *outputs = nullptr, + tflite::BuiltinOptions builtin_options_type = tflite::BuiltinOptions_NONE, + flatbuffers::Offset builtin_options = 0, + const std::vector *custom_options = nullptr, + tflite::CustomOptionsFormat custom_options_format = tflite::CustomOptionsFormat_FLEXBUFFERS, + const std::vector *mutating_variable_inputs = nullptr, + const std::vector *intermediates = nullptr) { + auto inputs__ = inputs ? _fbb.CreateVector(*inputs) : 0; + auto outputs__ = outputs ? _fbb.CreateVector(*outputs) : 0; + auto custom_options__ = custom_options ? _fbb.CreateVector(*custom_options) : 0; + auto mutating_variable_inputs__ = mutating_variable_inputs ? _fbb.CreateVector(*mutating_variable_inputs) : 0; + auto intermediates__ = intermediates ? _fbb.CreateVector(*intermediates) : 0; + return tflite::CreateOperator( + _fbb, + opcode_index, + inputs__, + outputs__, + builtin_options_type, + builtin_options, + custom_options__, + custom_options_format, + mutating_variable_inputs__, + intermediates__); +} + +flatbuffers::Offset CreateOperator(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SubGraphT : public flatbuffers::NativeTable { + typedef SubGraph TableType; + std::vector> tensors{}; + std::vector inputs{}; + std::vector outputs{}; + std::vector> operators{}; + std::string name{}; + SubGraphT() = default; + SubGraphT(const SubGraphT &o); + SubGraphT(SubGraphT&&) FLATBUFFERS_NOEXCEPT = default; + SubGraphT &operator=(SubGraphT o) FLATBUFFERS_NOEXCEPT; +}; + +struct SubGraph FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SubGraphT NativeTableType; + typedef SubGraphBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_TENSORS = 4, + VT_INPUTS = 6, + VT_OUTPUTS = 8, + VT_OPERATORS = 10, + VT_NAME = 12 + }; + const flatbuffers::Vector> *tensors() const { + return GetPointer> *>(VT_TENSORS); + } + const flatbuffers::Vector *inputs() const { + return GetPointer *>(VT_INPUTS); + } + const flatbuffers::Vector *outputs() const { + return GetPointer *>(VT_OUTPUTS); + } + const flatbuffers::Vector> *operators() const { + return GetPointer> *>(VT_OPERATORS); + } + const flatbuffers::String *name() const { + return GetPointer(VT_NAME); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_TENSORS) && + verifier.VerifyVector(tensors()) && + verifier.VerifyVectorOfTables(tensors()) && + VerifyOffset(verifier, VT_INPUTS) && + verifier.VerifyVector(inputs()) && + VerifyOffset(verifier, VT_OUTPUTS) && + verifier.VerifyVector(outputs()) && + VerifyOffset(verifier, VT_OPERATORS) && + verifier.VerifyVector(operators()) && + verifier.VerifyVectorOfTables(operators()) && + VerifyOffset(verifier, VT_NAME) && + verifier.VerifyString(name()) && + verifier.EndTable(); + } + SubGraphT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SubGraphT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SubGraphBuilder { + typedef SubGraph Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_tensors(flatbuffers::Offset>> tensors) { + fbb_.AddOffset(SubGraph::VT_TENSORS, tensors); + } + void add_inputs(flatbuffers::Offset> inputs) { + fbb_.AddOffset(SubGraph::VT_INPUTS, inputs); + } + void add_outputs(flatbuffers::Offset> outputs) { + fbb_.AddOffset(SubGraph::VT_OUTPUTS, outputs); + } + void add_operators(flatbuffers::Offset>> operators) { + fbb_.AddOffset(SubGraph::VT_OPERATORS, operators); + } + void add_name(flatbuffers::Offset name) { + fbb_.AddOffset(SubGraph::VT_NAME, name); + } + explicit SubGraphBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSubGraph( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset>> tensors = 0, + flatbuffers::Offset> inputs = 0, + flatbuffers::Offset> outputs = 0, + flatbuffers::Offset>> operators = 0, + flatbuffers::Offset name = 0) { + SubGraphBuilder builder_(_fbb); + builder_.add_name(name); + builder_.add_operators(operators); + builder_.add_outputs(outputs); + builder_.add_inputs(inputs); + builder_.add_tensors(tensors); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateSubGraphDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector> *tensors = nullptr, + const std::vector *inputs = nullptr, + const std::vector *outputs = nullptr, + const std::vector> *operators = nullptr, + const char *name = nullptr) { + auto tensors__ = tensors ? _fbb.CreateVector>(*tensors) : 0; + auto inputs__ = inputs ? _fbb.CreateVector(*inputs) : 0; + auto outputs__ = outputs ? _fbb.CreateVector(*outputs) : 0; + auto operators__ = operators ? _fbb.CreateVector>(*operators) : 0; + auto name__ = name ? _fbb.CreateString(name) : 0; + return tflite::CreateSubGraph( + _fbb, + tensors__, + inputs__, + outputs__, + operators__, + name__); +} + +flatbuffers::Offset CreateSubGraph(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct BufferT : public flatbuffers::NativeTable { + typedef Buffer TableType; + std::vector data{}; +}; + +struct Buffer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef BufferT NativeTableType; + typedef BufferBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_DATA = 4 + }; + const flatbuffers::Vector *data() const { + return GetPointer *>(VT_DATA); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_DATA) && + verifier.VerifyVector(data()) && + verifier.EndTable(); + } + BufferT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(BufferT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const BufferT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct BufferBuilder { + typedef Buffer Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_data(flatbuffers::Offset> data) { + fbb_.AddOffset(Buffer::VT_DATA, data); + } + explicit BufferBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateBuffer( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> data = 0) { + BufferBuilder builder_(_fbb); + builder_.add_data(data); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateBufferDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *data = nullptr) { + if (data) { _fbb.ForceVectorAlignment(data->size(), sizeof(uint8_t), 16); } + auto data__ = data ? _fbb.CreateVector(*data) : 0; + return tflite::CreateBuffer( + _fbb, + data__); +} + +flatbuffers::Offset CreateBuffer(flatbuffers::FlatBufferBuilder &_fbb, const BufferT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct MetadataT : public flatbuffers::NativeTable { + typedef Metadata TableType; + std::string name{}; + uint32_t buffer = 0; +}; + +struct Metadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef MetadataT NativeTableType; + typedef MetadataBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NAME = 4, + VT_BUFFER = 6 + }; + const flatbuffers::String *name() const { + return GetPointer(VT_NAME); + } + uint32_t buffer() const { + return GetField(VT_BUFFER, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyField(verifier, VT_BUFFER, 4) && + verifier.EndTable(); + } + MetadataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(MetadataT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct MetadataBuilder { + typedef Metadata Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_name(flatbuffers::Offset name) { + fbb_.AddOffset(Metadata::VT_NAME, name); + } + void add_buffer(uint32_t buffer) { + fbb_.AddElement(Metadata::VT_BUFFER, buffer, 0); + } + explicit MetadataBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateMetadata( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset name = 0, + uint32_t buffer = 0) { + MetadataBuilder builder_(_fbb); + builder_.add_buffer(buffer); + builder_.add_name(name); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateMetadataDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *name = nullptr, + uint32_t buffer = 0) { + auto name__ = name ? _fbb.CreateString(name) : 0; + return tflite::CreateMetadata( + _fbb, + name__, + buffer); +} + +flatbuffers::Offset CreateMetadata(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct TensorMapT : public flatbuffers::NativeTable { + typedef TensorMap TableType; + std::string name{}; + uint32_t tensor_index = 0; +}; + +struct TensorMap FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef TensorMapT NativeTableType; + typedef TensorMapBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_NAME = 4, + VT_TENSOR_INDEX = 6 + }; + const flatbuffers::String *name() const { + return GetPointer(VT_NAME); + } + uint32_t tensor_index() const { + return GetField(VT_TENSOR_INDEX, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyField(verifier, VT_TENSOR_INDEX, 4) && + verifier.EndTable(); + } + TensorMapT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(TensorMapT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct TensorMapBuilder { + typedef TensorMap Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_name(flatbuffers::Offset name) { + fbb_.AddOffset(TensorMap::VT_NAME, name); + } + void add_tensor_index(uint32_t tensor_index) { + fbb_.AddElement(TensorMap::VT_TENSOR_INDEX, tensor_index, 0); + } + explicit TensorMapBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTensorMap( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset name = 0, + uint32_t tensor_index = 0) { + TensorMapBuilder builder_(_fbb); + builder_.add_tensor_index(tensor_index); + builder_.add_name(name); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTensorMapDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const char *name = nullptr, + uint32_t tensor_index = 0) { + auto name__ = name ? _fbb.CreateString(name) : 0; + return tflite::CreateTensorMap( + _fbb, + name__, + tensor_index); +} + +flatbuffers::Offset CreateTensorMap(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SignatureDefT : public flatbuffers::NativeTable { + typedef SignatureDef TableType; + std::vector> inputs{}; + std::vector> outputs{}; + std::string signature_key{}; + uint32_t subgraph_index = 0; + SignatureDefT() = default; + SignatureDefT(const SignatureDefT &o); + SignatureDefT(SignatureDefT&&) FLATBUFFERS_NOEXCEPT = default; + SignatureDefT &operator=(SignatureDefT o) FLATBUFFERS_NOEXCEPT; +}; + +struct SignatureDef FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SignatureDefT NativeTableType; + typedef SignatureDefBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_INPUTS = 4, + VT_OUTPUTS = 6, + VT_SIGNATURE_KEY = 8, + VT_SUBGRAPH_INDEX = 12 + }; + const flatbuffers::Vector> *inputs() const { + return GetPointer> *>(VT_INPUTS); + } + const flatbuffers::Vector> *outputs() const { + return GetPointer> *>(VT_OUTPUTS); + } + const flatbuffers::String *signature_key() const { + return GetPointer(VT_SIGNATURE_KEY); + } + uint32_t subgraph_index() const { + return GetField(VT_SUBGRAPH_INDEX, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_INPUTS) && + verifier.VerifyVector(inputs()) && + verifier.VerifyVectorOfTables(inputs()) && + VerifyOffset(verifier, VT_OUTPUTS) && + verifier.VerifyVector(outputs()) && + verifier.VerifyVectorOfTables(outputs()) && + VerifyOffset(verifier, VT_SIGNATURE_KEY) && + verifier.VerifyString(signature_key()) && + VerifyField(verifier, VT_SUBGRAPH_INDEX, 4) && + verifier.EndTable(); + } + SignatureDefT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SignatureDefT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SignatureDefT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SignatureDefBuilder { + typedef SignatureDef Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_inputs(flatbuffers::Offset>> inputs) { + fbb_.AddOffset(SignatureDef::VT_INPUTS, inputs); + } + void add_outputs(flatbuffers::Offset>> outputs) { + fbb_.AddOffset(SignatureDef::VT_OUTPUTS, outputs); + } + void add_signature_key(flatbuffers::Offset signature_key) { + fbb_.AddOffset(SignatureDef::VT_SIGNATURE_KEY, signature_key); + } + void add_subgraph_index(uint32_t subgraph_index) { + fbb_.AddElement(SignatureDef::VT_SUBGRAPH_INDEX, subgraph_index, 0); + } + explicit SignatureDefBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSignatureDef( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset>> inputs = 0, + flatbuffers::Offset>> outputs = 0, + flatbuffers::Offset signature_key = 0, + uint32_t subgraph_index = 0) { + SignatureDefBuilder builder_(_fbb); + builder_.add_subgraph_index(subgraph_index); + builder_.add_signature_key(signature_key); + builder_.add_outputs(outputs); + builder_.add_inputs(inputs); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateSignatureDefDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector> *inputs = nullptr, + const std::vector> *outputs = nullptr, + const char *signature_key = nullptr, + uint32_t subgraph_index = 0) { + auto inputs__ = inputs ? _fbb.CreateVector>(*inputs) : 0; + auto outputs__ = outputs ? _fbb.CreateVector>(*outputs) : 0; + auto signature_key__ = signature_key ? _fbb.CreateString(signature_key) : 0; + return tflite::CreateSignatureDef( + _fbb, + inputs__, + outputs__, + signature_key__, + subgraph_index); +} + +flatbuffers::Offset CreateSignatureDef(flatbuffers::FlatBufferBuilder &_fbb, const SignatureDefT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ModelT : public flatbuffers::NativeTable { + typedef Model TableType; + uint32_t version = 0; + std::vector> operator_codes{}; + std::vector> subgraphs{}; + std::string description{}; + std::vector> buffers{}; + std::vector metadata_buffer{}; + std::vector> metadata{}; + std::vector> signature_defs{}; + ModelT() = default; + ModelT(const ModelT &o); + ModelT(ModelT&&) FLATBUFFERS_NOEXCEPT = default; + ModelT &operator=(ModelT o) FLATBUFFERS_NOEXCEPT; +}; + +struct Model FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ModelT NativeTableType; + typedef ModelBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VERSION = 4, + VT_OPERATOR_CODES = 6, + VT_SUBGRAPHS = 8, + VT_DESCRIPTION = 10, + VT_BUFFERS = 12, + VT_METADATA_BUFFER = 14, + VT_METADATA = 16, + VT_SIGNATURE_DEFS = 18 + }; + uint32_t version() const { + return GetField(VT_VERSION, 0); + } + const flatbuffers::Vector> *operator_codes() const { + return GetPointer> *>(VT_OPERATOR_CODES); + } + const flatbuffers::Vector> *subgraphs() const { + return GetPointer> *>(VT_SUBGRAPHS); + } + const flatbuffers::String *description() const { + return GetPointer(VT_DESCRIPTION); + } + const flatbuffers::Vector> *buffers() const { + return GetPointer> *>(VT_BUFFERS); + } + const flatbuffers::Vector *metadata_buffer() const { + return GetPointer *>(VT_METADATA_BUFFER); + } + const flatbuffers::Vector> *metadata() const { + return GetPointer> *>(VT_METADATA); + } + const flatbuffers::Vector> *signature_defs() const { + return GetPointer> *>(VT_SIGNATURE_DEFS); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_VERSION, 4) && + VerifyOffset(verifier, VT_OPERATOR_CODES) && + verifier.VerifyVector(operator_codes()) && + verifier.VerifyVectorOfTables(operator_codes()) && + VerifyOffset(verifier, VT_SUBGRAPHS) && + verifier.VerifyVector(subgraphs()) && + verifier.VerifyVectorOfTables(subgraphs()) && + VerifyOffset(verifier, VT_DESCRIPTION) && + verifier.VerifyString(description()) && + VerifyOffset(verifier, VT_BUFFERS) && + verifier.VerifyVector(buffers()) && + verifier.VerifyVectorOfTables(buffers()) && + VerifyOffset(verifier, VT_METADATA_BUFFER) && + verifier.VerifyVector(metadata_buffer()) && + VerifyOffset(verifier, VT_METADATA) && + verifier.VerifyVector(metadata()) && + verifier.VerifyVectorOfTables(metadata()) && + VerifyOffset(verifier, VT_SIGNATURE_DEFS) && + verifier.VerifyVector(signature_defs()) && + verifier.VerifyVectorOfTables(signature_defs()) && + verifier.EndTable(); + } + ModelT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ModelT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ModelT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ModelBuilder { + typedef Model Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_version(uint32_t version) { + fbb_.AddElement(Model::VT_VERSION, version, 0); + } + void add_operator_codes(flatbuffers::Offset>> operator_codes) { + fbb_.AddOffset(Model::VT_OPERATOR_CODES, operator_codes); + } + void add_subgraphs(flatbuffers::Offset>> subgraphs) { + fbb_.AddOffset(Model::VT_SUBGRAPHS, subgraphs); + } + void add_description(flatbuffers::Offset description) { + fbb_.AddOffset(Model::VT_DESCRIPTION, description); + } + void add_buffers(flatbuffers::Offset>> buffers) { + fbb_.AddOffset(Model::VT_BUFFERS, buffers); + } + void add_metadata_buffer(flatbuffers::Offset> metadata_buffer) { + fbb_.AddOffset(Model::VT_METADATA_BUFFER, metadata_buffer); + } + void add_metadata(flatbuffers::Offset>> metadata) { + fbb_.AddOffset(Model::VT_METADATA, metadata); + } + void add_signature_defs(flatbuffers::Offset>> signature_defs) { + fbb_.AddOffset(Model::VT_SIGNATURE_DEFS, signature_defs); + } + explicit ModelBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateModel( + flatbuffers::FlatBufferBuilder &_fbb, + uint32_t version = 0, + flatbuffers::Offset>> operator_codes = 0, + flatbuffers::Offset>> subgraphs = 0, + flatbuffers::Offset description = 0, + flatbuffers::Offset>> buffers = 0, + flatbuffers::Offset> metadata_buffer = 0, + flatbuffers::Offset>> metadata = 0, + flatbuffers::Offset>> signature_defs = 0) { + ModelBuilder builder_(_fbb); + builder_.add_signature_defs(signature_defs); + builder_.add_metadata(metadata); + builder_.add_metadata_buffer(metadata_buffer); + builder_.add_buffers(buffers); + builder_.add_description(description); + builder_.add_subgraphs(subgraphs); + builder_.add_operator_codes(operator_codes); + builder_.add_version(version); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateModelDirect( + flatbuffers::FlatBufferBuilder &_fbb, + uint32_t version = 0, + const std::vector> *operator_codes = nullptr, + const std::vector> *subgraphs = nullptr, + const char *description = nullptr, + const std::vector> *buffers = nullptr, + const std::vector *metadata_buffer = nullptr, + const std::vector> *metadata = nullptr, + const std::vector> *signature_defs = nullptr) { + auto operator_codes__ = operator_codes ? _fbb.CreateVector>(*operator_codes) : 0; + auto subgraphs__ = subgraphs ? _fbb.CreateVector>(*subgraphs) : 0; + auto description__ = description ? _fbb.CreateString(description) : 0; + auto buffers__ = buffers ? _fbb.CreateVector>(*buffers) : 0; + auto metadata_buffer__ = metadata_buffer ? _fbb.CreateVector(*metadata_buffer) : 0; + auto metadata__ = metadata ? _fbb.CreateVector>(*metadata) : 0; + auto signature_defs__ = signature_defs ? _fbb.CreateVector>(*signature_defs) : 0; + return tflite::CreateModel( + _fbb, + version, + operator_codes__, + subgraphs__, + description__, + buffers__, + metadata_buffer__, + metadata__, + signature_defs__); +} + +flatbuffers::Offset CreateModel(flatbuffers::FlatBufferBuilder &_fbb, const ModelT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +inline CustomQuantizationT *CustomQuantization::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new CustomQuantizationT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void CustomQuantization::UnPackTo(CustomQuantizationT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = custom(); if (_e) { _o->custom.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->custom.begin()); } } +} + +inline flatbuffers::Offset CustomQuantization::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateCustomQuantization(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateCustomQuantization(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CustomQuantizationT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + _fbb.ForceVectorAlignment(_o->custom.size(), sizeof(uint8_t), 16); + auto _custom = _o->custom.size() ? _fbb.CreateVector(_o->custom) : 0; + return tflite::CreateCustomQuantization( + _fbb, + _custom); +} + +inline QuantizationParametersT *QuantizationParameters::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new QuantizationParametersT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void QuantizationParameters::UnPackTo(QuantizationParametersT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = min(); if (_e) { _o->min.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->min[_i] = _e->Get(_i); } } } + { auto _e = max(); if (_e) { _o->max.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->max[_i] = _e->Get(_i); } } } + { auto _e = scale(); if (_e) { _o->scale.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->scale[_i] = _e->Get(_i); } } } + { auto _e = zero_point(); if (_e) { _o->zero_point.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->zero_point[_i] = _e->Get(_i); } } } + { auto _e = details_type(); _o->details.type = _e; } + { auto _e = details(); if (_e) _o->details.value = tflite::QuantizationDetailsUnion::UnPack(_e, details_type(), _resolver); } + { auto _e = quantized_dimension(); _o->quantized_dimension = _e; } +} + +inline flatbuffers::Offset QuantizationParameters::Pack(flatbuffers::FlatBufferBuilder &_fbb, const QuantizationParametersT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateQuantizationParameters(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateQuantizationParameters(flatbuffers::FlatBufferBuilder &_fbb, const QuantizationParametersT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const QuantizationParametersT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _min = _o->min.size() ? _fbb.CreateVector(_o->min) : 0; + auto _max = _o->max.size() ? _fbb.CreateVector(_o->max) : 0; + auto _scale = _o->scale.size() ? _fbb.CreateVector(_o->scale) : 0; + auto _zero_point = _o->zero_point.size() ? _fbb.CreateVector(_o->zero_point) : 0; + auto _details_type = _o->details.type; + auto _details = _o->details.Pack(_fbb); + auto _quantized_dimension = _o->quantized_dimension; + return tflite::CreateQuantizationParameters( + _fbb, + _min, + _max, + _scale, + _zero_point, + _details_type, + _details, + _quantized_dimension); +} + +inline Int32VectorT *Int32Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new Int32VectorT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Int32Vector::UnPackTo(Int32VectorT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = values(); if (_e) { _o->values.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->values[_i] = _e->Get(_i); } } } +} + +inline flatbuffers::Offset Int32Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateInt32Vector(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateInt32Vector(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const Int32VectorT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _values = _o->values.size() ? _fbb.CreateVector(_o->values) : 0; + return tflite::CreateInt32Vector( + _fbb, + _values); +} + +inline Uint16VectorT *Uint16Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new Uint16VectorT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Uint16Vector::UnPackTo(Uint16VectorT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = values(); if (_e) { _o->values.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->values[_i] = _e->Get(_i); } } } +} + +inline flatbuffers::Offset Uint16Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateUint16Vector(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateUint16Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const Uint16VectorT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + _fbb.ForceVectorAlignment(_o->values.size(), sizeof(uint16_t), 4); + auto _values = _o->values.size() ? _fbb.CreateVector(_o->values) : 0; + return tflite::CreateUint16Vector( + _fbb, + _values); +} + +inline Uint8VectorT *Uint8Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new Uint8VectorT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Uint8Vector::UnPackTo(Uint8VectorT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = values(); if (_e) { _o->values.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->values.begin()); } } +} + +inline flatbuffers::Offset Uint8Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateUint8Vector(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateUint8Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const Uint8VectorT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + _fbb.ForceVectorAlignment(_o->values.size(), sizeof(uint8_t), 4); + auto _values = _o->values.size() ? _fbb.CreateVector(_o->values) : 0; + return tflite::CreateUint8Vector( + _fbb, + _values); +} + +inline DimensionMetadataT *DimensionMetadata::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new DimensionMetadataT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void DimensionMetadata::UnPackTo(DimensionMetadataT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = format(); _o->format = _e; } + { auto _e = dense_size(); _o->dense_size = _e; } + { auto _e = array_segments_type(); _o->array_segments.type = _e; } + { auto _e = array_segments(); if (_e) _o->array_segments.value = tflite::SparseIndexVectorUnion::UnPack(_e, array_segments_type(), _resolver); } + { auto _e = array_indices_type(); _o->array_indices.type = _e; } + { auto _e = array_indices(); if (_e) _o->array_indices.value = tflite::SparseIndexVectorUnion::UnPack(_e, array_indices_type(), _resolver); } +} + +inline flatbuffers::Offset DimensionMetadata::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateDimensionMetadata(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateDimensionMetadata(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DimensionMetadataT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _format = _o->format; + auto _dense_size = _o->dense_size; + auto _array_segments_type = _o->array_segments.type; + auto _array_segments = _o->array_segments.Pack(_fbb); + auto _array_indices_type = _o->array_indices.type; + auto _array_indices = _o->array_indices.Pack(_fbb); + return tflite::CreateDimensionMetadata( + _fbb, + _format, + _dense_size, + _array_segments_type, + _array_segments, + _array_indices_type, + _array_indices); +} + +inline SparsityParametersT::SparsityParametersT(const SparsityParametersT &o) + : traversal_order(o.traversal_order), + block_map(o.block_map) { + dim_metadata.reserve(o.dim_metadata.size()); + for (const auto &dim_metadata_ : o.dim_metadata) { dim_metadata.emplace_back((dim_metadata_) ? new tflite::DimensionMetadataT(*dim_metadata_) : nullptr); } +} + +inline SparsityParametersT &SparsityParametersT::operator=(SparsityParametersT o) FLATBUFFERS_NOEXCEPT { + std::swap(traversal_order, o.traversal_order); + std::swap(block_map, o.block_map); + std::swap(dim_metadata, o.dim_metadata); + return *this; +} + +inline SparsityParametersT *SparsityParameters::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SparsityParametersT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SparsityParameters::UnPackTo(SparsityParametersT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = traversal_order(); if (_e) { _o->traversal_order.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->traversal_order[_i] = _e->Get(_i); } } } + { auto _e = block_map(); if (_e) { _o->block_map.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->block_map[_i] = _e->Get(_i); } } } + { auto _e = dim_metadata(); if (_e) { _o->dim_metadata.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->dim_metadata[_i]) { _e->Get(_i)->UnPackTo(_o->dim_metadata[_i].get(), _resolver); } else { _o->dim_metadata[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } +} + +inline flatbuffers::Offset SparsityParameters::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSparsityParameters(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSparsityParameters(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SparsityParametersT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _traversal_order = _o->traversal_order.size() ? _fbb.CreateVector(_o->traversal_order) : 0; + auto _block_map = _o->block_map.size() ? _fbb.CreateVector(_o->block_map) : 0; + auto _dim_metadata = _o->dim_metadata.size() ? _fbb.CreateVector> (_o->dim_metadata.size(), [](size_t i, _VectorArgs *__va) { return CreateDimensionMetadata(*__va->__fbb, __va->__o->dim_metadata[i].get(), __va->__rehasher); }, &_va ) : 0; + return tflite::CreateSparsityParameters( + _fbb, + _traversal_order, + _block_map, + _dim_metadata); +} + +inline VariantSubTypeT *VariantSubType::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new VariantSubTypeT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void VariantSubType::UnPackTo(VariantSubTypeT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = shape(); if (_e) { _o->shape.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->shape[_i] = _e->Get(_i); } } } + { auto _e = type(); _o->type = _e; } + { auto _e = has_rank(); _o->has_rank = _e; } +} + +inline flatbuffers::Offset VariantSubType::Pack(flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateVariantSubType(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateVariantSubType(flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const VariantSubTypeT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _shape = _o->shape.size() ? _fbb.CreateVector(_o->shape) : 0; + auto _type = _o->type; + auto _has_rank = _o->has_rank; + return tflite::CreateVariantSubType( + _fbb, + _shape, + _type, + _has_rank); +} + +inline TensorT::TensorT(const TensorT &o) + : shape(o.shape), + type(o.type), + buffer(o.buffer), + name(o.name), + quantization((o.quantization) ? new tflite::QuantizationParametersT(*o.quantization) : nullptr), + is_variable(o.is_variable), + sparsity((o.sparsity) ? new tflite::SparsityParametersT(*o.sparsity) : nullptr), + shape_signature(o.shape_signature), + has_rank(o.has_rank) { + variant_tensors.reserve(o.variant_tensors.size()); + for (const auto &variant_tensors_ : o.variant_tensors) { variant_tensors.emplace_back((variant_tensors_) ? new tflite::VariantSubTypeT(*variant_tensors_) : nullptr); } +} + +inline TensorT &TensorT::operator=(TensorT o) FLATBUFFERS_NOEXCEPT { + std::swap(shape, o.shape); + std::swap(type, o.type); + std::swap(buffer, o.buffer); + std::swap(name, o.name); + std::swap(quantization, o.quantization); + std::swap(is_variable, o.is_variable); + std::swap(sparsity, o.sparsity); + std::swap(shape_signature, o.shape_signature); + std::swap(has_rank, o.has_rank); + std::swap(variant_tensors, o.variant_tensors); + return *this; +} + +inline TensorT *Tensor::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new TensorT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Tensor::UnPackTo(TensorT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = shape(); if (_e) { _o->shape.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->shape[_i] = _e->Get(_i); } } } + { auto _e = type(); _o->type = _e; } + { auto _e = buffer(); _o->buffer = _e; } + { auto _e = name(); if (_e) _o->name = _e->str(); } + { auto _e = quantization(); if (_e) { if(_o->quantization) { _e->UnPackTo(_o->quantization.get(), _resolver); } else { _o->quantization = std::unique_ptr(_e->UnPack(_resolver)); } } } + { auto _e = is_variable(); _o->is_variable = _e; } + { auto _e = sparsity(); if (_e) { if(_o->sparsity) { _e->UnPackTo(_o->sparsity.get(), _resolver); } else { _o->sparsity = std::unique_ptr(_e->UnPack(_resolver)); } } } + { auto _e = shape_signature(); if (_e) { _o->shape_signature.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->shape_signature[_i] = _e->Get(_i); } } } + { auto _e = has_rank(); _o->has_rank = _e; } + { auto _e = variant_tensors(); if (_e) { _o->variant_tensors.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->variant_tensors[_i]) { _e->Get(_i)->UnPackTo(_o->variant_tensors[_i].get(), _resolver); } else { _o->variant_tensors[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } +} + +inline flatbuffers::Offset Tensor::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TensorT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateTensor(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateTensor(flatbuffers::FlatBufferBuilder &_fbb, const TensorT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TensorT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _shape = _o->shape.size() ? _fbb.CreateVector(_o->shape) : 0; + auto _type = _o->type; + auto _buffer = _o->buffer; + auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name); + auto _quantization = _o->quantization ? CreateQuantizationParameters(_fbb, _o->quantization.get(), _rehasher) : 0; + auto _is_variable = _o->is_variable; + auto _sparsity = _o->sparsity ? CreateSparsityParameters(_fbb, _o->sparsity.get(), _rehasher) : 0; + auto _shape_signature = _o->shape_signature.size() ? _fbb.CreateVector(_o->shape_signature) : 0; + auto _has_rank = _o->has_rank; + auto _variant_tensors = _o->variant_tensors.size() ? _fbb.CreateVector> (_o->variant_tensors.size(), [](size_t i, _VectorArgs *__va) { return CreateVariantSubType(*__va->__fbb, __va->__o->variant_tensors[i].get(), __va->__rehasher); }, &_va ) : 0; + return tflite::CreateTensor( + _fbb, + _shape, + _type, + _buffer, + _name, + _quantization, + _is_variable, + _sparsity, + _shape_signature, + _has_rank, + _variant_tensors); +} + +inline Conv2DOptionsT *Conv2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new Conv2DOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Conv2DOptions::UnPackTo(Conv2DOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = padding(); _o->padding = _e; } + { auto _e = stride_w(); _o->stride_w = _e; } + { auto _e = stride_h(); _o->stride_h = _e; } + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = dilation_w_factor(); _o->dilation_w_factor = _e; } + { auto _e = dilation_h_factor(); _o->dilation_h_factor = _e; } +} + +inline flatbuffers::Offset Conv2DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateConv2DOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const Conv2DOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _padding = _o->padding; + auto _stride_w = _o->stride_w; + auto _stride_h = _o->stride_h; + auto _fused_activation_function = _o->fused_activation_function; + auto _dilation_w_factor = _o->dilation_w_factor; + auto _dilation_h_factor = _o->dilation_h_factor; + return tflite::CreateConv2DOptions( + _fbb, + _padding, + _stride_w, + _stride_h, + _fused_activation_function, + _dilation_w_factor, + _dilation_h_factor); +} + +inline Conv3DOptionsT *Conv3DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new Conv3DOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Conv3DOptions::UnPackTo(Conv3DOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = padding(); _o->padding = _e; } + { auto _e = stride_d(); _o->stride_d = _e; } + { auto _e = stride_w(); _o->stride_w = _e; } + { auto _e = stride_h(); _o->stride_h = _e; } + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = dilation_d_factor(); _o->dilation_d_factor = _e; } + { auto _e = dilation_w_factor(); _o->dilation_w_factor = _e; } + { auto _e = dilation_h_factor(); _o->dilation_h_factor = _e; } +} + +inline flatbuffers::Offset Conv3DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateConv3DOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateConv3DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const Conv3DOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _padding = _o->padding; + auto _stride_d = _o->stride_d; + auto _stride_w = _o->stride_w; + auto _stride_h = _o->stride_h; + auto _fused_activation_function = _o->fused_activation_function; + auto _dilation_d_factor = _o->dilation_d_factor; + auto _dilation_w_factor = _o->dilation_w_factor; + auto _dilation_h_factor = _o->dilation_h_factor; + return tflite::CreateConv3DOptions( + _fbb, + _padding, + _stride_d, + _stride_w, + _stride_h, + _fused_activation_function, + _dilation_d_factor, + _dilation_w_factor, + _dilation_h_factor); +} + +inline Pool2DOptionsT *Pool2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new Pool2DOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Pool2DOptions::UnPackTo(Pool2DOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = padding(); _o->padding = _e; } + { auto _e = stride_w(); _o->stride_w = _e; } + { auto _e = stride_h(); _o->stride_h = _e; } + { auto _e = filter_width(); _o->filter_width = _e; } + { auto _e = filter_height(); _o->filter_height = _e; } + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } +} + +inline flatbuffers::Offset Pool2DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreatePool2DOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreatePool2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const Pool2DOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _padding = _o->padding; + auto _stride_w = _o->stride_w; + auto _stride_h = _o->stride_h; + auto _filter_width = _o->filter_width; + auto _filter_height = _o->filter_height; + auto _fused_activation_function = _o->fused_activation_function; + return tflite::CreatePool2DOptions( + _fbb, + _padding, + _stride_w, + _stride_h, + _filter_width, + _filter_height, + _fused_activation_function); +} + +inline DepthwiseConv2DOptionsT *DepthwiseConv2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new DepthwiseConv2DOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void DepthwiseConv2DOptions::UnPackTo(DepthwiseConv2DOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = padding(); _o->padding = _e; } + { auto _e = stride_w(); _o->stride_w = _e; } + { auto _e = stride_h(); _o->stride_h = _e; } + { auto _e = depth_multiplier(); _o->depth_multiplier = _e; } + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = dilation_w_factor(); _o->dilation_w_factor = _e; } + { auto _e = dilation_h_factor(); _o->dilation_h_factor = _e; } +} + +inline flatbuffers::Offset DepthwiseConv2DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DepthwiseConv2DOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateDepthwiseConv2DOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateDepthwiseConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const DepthwiseConv2DOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DepthwiseConv2DOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _padding = _o->padding; + auto _stride_w = _o->stride_w; + auto _stride_h = _o->stride_h; + auto _depth_multiplier = _o->depth_multiplier; + auto _fused_activation_function = _o->fused_activation_function; + auto _dilation_w_factor = _o->dilation_w_factor; + auto _dilation_h_factor = _o->dilation_h_factor; + return tflite::CreateDepthwiseConv2DOptions( + _fbb, + _padding, + _stride_w, + _stride_h, + _depth_multiplier, + _fused_activation_function, + _dilation_w_factor, + _dilation_h_factor); +} + +inline ConcatEmbeddingsOptionsT *ConcatEmbeddingsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ConcatEmbeddingsOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ConcatEmbeddingsOptions::UnPackTo(ConcatEmbeddingsOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = num_channels(); _o->num_channels = _e; } + { auto _e = num_columns_per_channel(); if (_e) { _o->num_columns_per_channel.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->num_columns_per_channel[_i] = _e->Get(_i); } } } + { auto _e = embedding_dim_per_channel(); if (_e) { _o->embedding_dim_per_channel.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->embedding_dim_per_channel[_i] = _e->Get(_i); } } } +} + +inline flatbuffers::Offset ConcatEmbeddingsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ConcatEmbeddingsOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateConcatEmbeddingsOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateConcatEmbeddingsOptions(flatbuffers::FlatBufferBuilder &_fbb, const ConcatEmbeddingsOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ConcatEmbeddingsOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _num_channels = _o->num_channels; + auto _num_columns_per_channel = _o->num_columns_per_channel.size() ? _fbb.CreateVector(_o->num_columns_per_channel) : 0; + auto _embedding_dim_per_channel = _o->embedding_dim_per_channel.size() ? _fbb.CreateVector(_o->embedding_dim_per_channel) : 0; + return tflite::CreateConcatEmbeddingsOptions( + _fbb, + _num_channels, + _num_columns_per_channel, + _embedding_dim_per_channel); +} + +inline LSHProjectionOptionsT *LSHProjectionOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LSHProjectionOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LSHProjectionOptions::UnPackTo(LSHProjectionOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = type(); _o->type = _e; } +} + +inline flatbuffers::Offset LSHProjectionOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLSHProjectionOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLSHProjectionOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LSHProjectionOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _type = _o->type; + return tflite::CreateLSHProjectionOptions( + _fbb, + _type); +} + +inline SVDFOptionsT *SVDFOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SVDFOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SVDFOptions::UnPackTo(SVDFOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = rank(); _o->rank = _e; } + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = asymmetric_quantize_inputs(); _o->asymmetric_quantize_inputs = _e; } +} + +inline flatbuffers::Offset SVDFOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSVDFOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSVDFOptions(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SVDFOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _rank = _o->rank; + auto _fused_activation_function = _o->fused_activation_function; + auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs; + return tflite::CreateSVDFOptions( + _fbb, + _rank, + _fused_activation_function, + _asymmetric_quantize_inputs); +} + +inline RNNOptionsT *RNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new RNNOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RNNOptions::UnPackTo(RNNOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = asymmetric_quantize_inputs(); _o->asymmetric_quantize_inputs = _e; } +} + +inline flatbuffers::Offset RNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateRNNOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const RNNOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs; + return tflite::CreateRNNOptions( + _fbb, + _fused_activation_function, + _asymmetric_quantize_inputs); +} + +inline SequenceRNNOptionsT *SequenceRNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SequenceRNNOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SequenceRNNOptions::UnPackTo(SequenceRNNOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = time_major(); _o->time_major = _e; } + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = asymmetric_quantize_inputs(); _o->asymmetric_quantize_inputs = _e; } +} + +inline flatbuffers::Offset SequenceRNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSequenceRNNOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SequenceRNNOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _time_major = _o->time_major; + auto _fused_activation_function = _o->fused_activation_function; + auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs; + return tflite::CreateSequenceRNNOptions( + _fbb, + _time_major, + _fused_activation_function, + _asymmetric_quantize_inputs); +} + +inline BidirectionalSequenceRNNOptionsT *BidirectionalSequenceRNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new BidirectionalSequenceRNNOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void BidirectionalSequenceRNNOptions::UnPackTo(BidirectionalSequenceRNNOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = time_major(); _o->time_major = _e; } + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = merge_outputs(); _o->merge_outputs = _e; } + { auto _e = asymmetric_quantize_inputs(); _o->asymmetric_quantize_inputs = _e; } +} + +inline flatbuffers::Offset BidirectionalSequenceRNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceRNNOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateBidirectionalSequenceRNNOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateBidirectionalSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceRNNOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BidirectionalSequenceRNNOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _time_major = _o->time_major; + auto _fused_activation_function = _o->fused_activation_function; + auto _merge_outputs = _o->merge_outputs; + auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs; + return tflite::CreateBidirectionalSequenceRNNOptions( + _fbb, + _time_major, + _fused_activation_function, + _merge_outputs, + _asymmetric_quantize_inputs); +} + +inline FullyConnectedOptionsT *FullyConnectedOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new FullyConnectedOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void FullyConnectedOptions::UnPackTo(FullyConnectedOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = weights_format(); _o->weights_format = _e; } + { auto _e = keep_num_dims(); _o->keep_num_dims = _e; } + { auto _e = asymmetric_quantize_inputs(); _o->asymmetric_quantize_inputs = _e; } +} + +inline flatbuffers::Offset FullyConnectedOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateFullyConnectedOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateFullyConnectedOptions(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const FullyConnectedOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + auto _weights_format = _o->weights_format; + auto _keep_num_dims = _o->keep_num_dims; + auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs; + return tflite::CreateFullyConnectedOptions( + _fbb, + _fused_activation_function, + _weights_format, + _keep_num_dims, + _asymmetric_quantize_inputs); +} + +inline SoftmaxOptionsT *SoftmaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SoftmaxOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SoftmaxOptions::UnPackTo(SoftmaxOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = beta(); _o->beta = _e; } +} + +inline flatbuffers::Offset SoftmaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSoftmaxOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SoftmaxOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _beta = _o->beta; + return tflite::CreateSoftmaxOptions( + _fbb, + _beta); +} + +inline ConcatenationOptionsT *ConcatenationOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ConcatenationOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ConcatenationOptions::UnPackTo(ConcatenationOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = axis(); _o->axis = _e; } + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } +} + +inline flatbuffers::Offset ConcatenationOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateConcatenationOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateConcatenationOptions(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ConcatenationOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _axis = _o->axis; + auto _fused_activation_function = _o->fused_activation_function; + return tflite::CreateConcatenationOptions( + _fbb, + _axis, + _fused_activation_function); +} + +inline AddOptionsT *AddOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new AddOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void AddOptions::UnPackTo(AddOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = pot_scale_int16(); _o->pot_scale_int16 = _e; } +} + +inline flatbuffers::Offset AddOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateAddOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateAddOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const AddOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + auto _pot_scale_int16 = _o->pot_scale_int16; + return tflite::CreateAddOptions( + _fbb, + _fused_activation_function, + _pot_scale_int16); +} + +inline MulOptionsT *MulOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new MulOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void MulOptions::UnPackTo(MulOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } +} + +inline flatbuffers::Offset MulOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateMulOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MulOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + return tflite::CreateMulOptions( + _fbb, + _fused_activation_function); +} + +inline L2NormOptionsT *L2NormOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new L2NormOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void L2NormOptions::UnPackTo(L2NormOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } +} + +inline flatbuffers::Offset L2NormOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateL2NormOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateL2NormOptions(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const L2NormOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + return tflite::CreateL2NormOptions( + _fbb, + _fused_activation_function); +} + +inline LocalResponseNormalizationOptionsT *LocalResponseNormalizationOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LocalResponseNormalizationOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LocalResponseNormalizationOptions::UnPackTo(LocalResponseNormalizationOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = radius(); _o->radius = _e; } + { auto _e = bias(); _o->bias = _e; } + { auto _e = alpha(); _o->alpha = _e; } + { auto _e = beta(); _o->beta = _e; } +} + +inline flatbuffers::Offset LocalResponseNormalizationOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LocalResponseNormalizationOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLocalResponseNormalizationOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLocalResponseNormalizationOptions(flatbuffers::FlatBufferBuilder &_fbb, const LocalResponseNormalizationOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LocalResponseNormalizationOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _radius = _o->radius; + auto _bias = _o->bias; + auto _alpha = _o->alpha; + auto _beta = _o->beta; + return tflite::CreateLocalResponseNormalizationOptions( + _fbb, + _radius, + _bias, + _alpha, + _beta); +} + +inline LSTMOptionsT *LSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LSTMOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LSTMOptions::UnPackTo(LSTMOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = cell_clip(); _o->cell_clip = _e; } + { auto _e = proj_clip(); _o->proj_clip = _e; } + { auto _e = kernel_type(); _o->kernel_type = _e; } + { auto _e = asymmetric_quantize_inputs(); _o->asymmetric_quantize_inputs = _e; } +} + +inline flatbuffers::Offset LSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLSTMOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LSTMOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + auto _cell_clip = _o->cell_clip; + auto _proj_clip = _o->proj_clip; + auto _kernel_type = _o->kernel_type; + auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs; + return tflite::CreateLSTMOptions( + _fbb, + _fused_activation_function, + _cell_clip, + _proj_clip, + _kernel_type, + _asymmetric_quantize_inputs); +} + +inline UnidirectionalSequenceLSTMOptionsT *UnidirectionalSequenceLSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new UnidirectionalSequenceLSTMOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void UnidirectionalSequenceLSTMOptions::UnPackTo(UnidirectionalSequenceLSTMOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = cell_clip(); _o->cell_clip = _e; } + { auto _e = proj_clip(); _o->proj_clip = _e; } + { auto _e = time_major(); _o->time_major = _e; } + { auto _e = asymmetric_quantize_inputs(); _o->asymmetric_quantize_inputs = _e; } +} + +inline flatbuffers::Offset UnidirectionalSequenceLSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnidirectionalSequenceLSTMOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateUnidirectionalSequenceLSTMOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateUnidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnidirectionalSequenceLSTMOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const UnidirectionalSequenceLSTMOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + auto _cell_clip = _o->cell_clip; + auto _proj_clip = _o->proj_clip; + auto _time_major = _o->time_major; + auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs; + return tflite::CreateUnidirectionalSequenceLSTMOptions( + _fbb, + _fused_activation_function, + _cell_clip, + _proj_clip, + _time_major, + _asymmetric_quantize_inputs); +} + +inline BidirectionalSequenceLSTMOptionsT *BidirectionalSequenceLSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new BidirectionalSequenceLSTMOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void BidirectionalSequenceLSTMOptions::UnPackTo(BidirectionalSequenceLSTMOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = cell_clip(); _o->cell_clip = _e; } + { auto _e = proj_clip(); _o->proj_clip = _e; } + { auto _e = merge_outputs(); _o->merge_outputs = _e; } + { auto _e = time_major(); _o->time_major = _e; } + { auto _e = asymmetric_quantize_inputs(); _o->asymmetric_quantize_inputs = _e; } +} + +inline flatbuffers::Offset BidirectionalSequenceLSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceLSTMOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateBidirectionalSequenceLSTMOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateBidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb, const BidirectionalSequenceLSTMOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BidirectionalSequenceLSTMOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + auto _cell_clip = _o->cell_clip; + auto _proj_clip = _o->proj_clip; + auto _merge_outputs = _o->merge_outputs; + auto _time_major = _o->time_major; + auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs; + return tflite::CreateBidirectionalSequenceLSTMOptions( + _fbb, + _fused_activation_function, + _cell_clip, + _proj_clip, + _merge_outputs, + _time_major, + _asymmetric_quantize_inputs); +} + +inline ResizeBilinearOptionsT *ResizeBilinearOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ResizeBilinearOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ResizeBilinearOptions::UnPackTo(ResizeBilinearOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = align_corners(); _o->align_corners = _e; } + { auto _e = half_pixel_centers(); _o->half_pixel_centers = _e; } +} + +inline flatbuffers::Offset ResizeBilinearOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateResizeBilinearOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateResizeBilinearOptions(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ResizeBilinearOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _align_corners = _o->align_corners; + auto _half_pixel_centers = _o->half_pixel_centers; + return tflite::CreateResizeBilinearOptions( + _fbb, + _align_corners, + _half_pixel_centers); +} + +inline ResizeNearestNeighborOptionsT *ResizeNearestNeighborOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ResizeNearestNeighborOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ResizeNearestNeighborOptions::UnPackTo(ResizeNearestNeighborOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = align_corners(); _o->align_corners = _e; } + { auto _e = half_pixel_centers(); _o->half_pixel_centers = _e; } +} + +inline flatbuffers::Offset ResizeNearestNeighborOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ResizeNearestNeighborOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateResizeNearestNeighborOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateResizeNearestNeighborOptions(flatbuffers::FlatBufferBuilder &_fbb, const ResizeNearestNeighborOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ResizeNearestNeighborOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _align_corners = _o->align_corners; + auto _half_pixel_centers = _o->half_pixel_centers; + return tflite::CreateResizeNearestNeighborOptions( + _fbb, + _align_corners, + _half_pixel_centers); +} + +inline CallOptionsT *CallOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new CallOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void CallOptions::UnPackTo(CallOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = subgraph(); _o->subgraph = _e; } +} + +inline flatbuffers::Offset CallOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateCallOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateCallOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CallOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _subgraph = _o->subgraph; + return tflite::CreateCallOptions( + _fbb, + _subgraph); +} + +inline PadOptionsT *PadOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new PadOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void PadOptions::UnPackTo(PadOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset PadOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreatePadOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreatePadOptions(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const PadOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreatePadOptions( + _fbb); +} + +inline PadV2OptionsT *PadV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new PadV2OptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void PadV2Options::UnPackTo(PadV2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset PadV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadV2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreatePadV2Options(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreatePadV2Options(flatbuffers::FlatBufferBuilder &_fbb, const PadV2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const PadV2OptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreatePadV2Options( + _fbb); +} + +inline ReshapeOptionsT *ReshapeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ReshapeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ReshapeOptions::UnPackTo(ReshapeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = new_shape(); if (_e) { _o->new_shape.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->new_shape[_i] = _e->Get(_i); } } } +} + +inline flatbuffers::Offset ReshapeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateReshapeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateReshapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ReshapeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _new_shape = _o->new_shape.size() ? _fbb.CreateVector(_o->new_shape) : 0; + return tflite::CreateReshapeOptions( + _fbb, + _new_shape); +} + +inline SpaceToBatchNDOptionsT *SpaceToBatchNDOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SpaceToBatchNDOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SpaceToBatchNDOptions::UnPackTo(SpaceToBatchNDOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset SpaceToBatchNDOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSpaceToBatchNDOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSpaceToBatchNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SpaceToBatchNDOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateSpaceToBatchNDOptions( + _fbb); +} + +inline BatchToSpaceNDOptionsT *BatchToSpaceNDOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new BatchToSpaceNDOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void BatchToSpaceNDOptions::UnPackTo(BatchToSpaceNDOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset BatchToSpaceNDOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateBatchToSpaceNDOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateBatchToSpaceNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BatchToSpaceNDOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateBatchToSpaceNDOptions( + _fbb); +} + +inline SkipGramOptionsT *SkipGramOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SkipGramOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SkipGramOptions::UnPackTo(SkipGramOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = ngram_size(); _o->ngram_size = _e; } + { auto _e = max_skip_size(); _o->max_skip_size = _e; } + { auto _e = include_all_ngrams(); _o->include_all_ngrams = _e; } +} + +inline flatbuffers::Offset SkipGramOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSkipGramOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSkipGramOptions(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SkipGramOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _ngram_size = _o->ngram_size; + auto _max_skip_size = _o->max_skip_size; + auto _include_all_ngrams = _o->include_all_ngrams; + return tflite::CreateSkipGramOptions( + _fbb, + _ngram_size, + _max_skip_size, + _include_all_ngrams); +} + +inline SpaceToDepthOptionsT *SpaceToDepthOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SpaceToDepthOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SpaceToDepthOptions::UnPackTo(SpaceToDepthOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = block_size(); _o->block_size = _e; } +} + +inline flatbuffers::Offset SpaceToDepthOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSpaceToDepthOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSpaceToDepthOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SpaceToDepthOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _block_size = _o->block_size; + return tflite::CreateSpaceToDepthOptions( + _fbb, + _block_size); +} + +inline DepthToSpaceOptionsT *DepthToSpaceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new DepthToSpaceOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void DepthToSpaceOptions::UnPackTo(DepthToSpaceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = block_size(); _o->block_size = _e; } +} + +inline flatbuffers::Offset DepthToSpaceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateDepthToSpaceOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateDepthToSpaceOptions(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DepthToSpaceOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _block_size = _o->block_size; + return tflite::CreateDepthToSpaceOptions( + _fbb, + _block_size); +} + +inline SubOptionsT *SubOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SubOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SubOptions::UnPackTo(SubOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } + { auto _e = pot_scale_int16(); _o->pot_scale_int16 = _e; } +} + +inline flatbuffers::Offset SubOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSubOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSubOptions(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SubOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + auto _pot_scale_int16 = _o->pot_scale_int16; + return tflite::CreateSubOptions( + _fbb, + _fused_activation_function, + _pot_scale_int16); +} + +inline DivOptionsT *DivOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new DivOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void DivOptions::UnPackTo(DivOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = fused_activation_function(); _o->fused_activation_function = _e; } +} + +inline flatbuffers::Offset DivOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateDivOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DivOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _fused_activation_function = _o->fused_activation_function; + return tflite::CreateDivOptions( + _fbb, + _fused_activation_function); +} + +inline TopKV2OptionsT *TopKV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new TopKV2OptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void TopKV2Options::UnPackTo(TopKV2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset TopKV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateTopKV2Options(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateTopKV2Options(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TopKV2OptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateTopKV2Options( + _fbb); +} + +inline EmbeddingLookupSparseOptionsT *EmbeddingLookupSparseOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new EmbeddingLookupSparseOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void EmbeddingLookupSparseOptions::UnPackTo(EmbeddingLookupSparseOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = combiner(); _o->combiner = _e; } +} + +inline flatbuffers::Offset EmbeddingLookupSparseOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const EmbeddingLookupSparseOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateEmbeddingLookupSparseOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateEmbeddingLookupSparseOptions(flatbuffers::FlatBufferBuilder &_fbb, const EmbeddingLookupSparseOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const EmbeddingLookupSparseOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _combiner = _o->combiner; + return tflite::CreateEmbeddingLookupSparseOptions( + _fbb, + _combiner); +} + +inline GatherOptionsT *GatherOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new GatherOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void GatherOptions::UnPackTo(GatherOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = axis(); _o->axis = _e; } + { auto _e = batch_dims(); _o->batch_dims = _e; } +} + +inline flatbuffers::Offset GatherOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateGatherOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const GatherOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _axis = _o->axis; + auto _batch_dims = _o->batch_dims; + return tflite::CreateGatherOptions( + _fbb, + _axis, + _batch_dims); +} + +inline TransposeOptionsT *TransposeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new TransposeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void TransposeOptions::UnPackTo(TransposeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset TransposeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateTransposeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateTransposeOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TransposeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateTransposeOptions( + _fbb); +} + +inline ExpOptionsT *ExpOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ExpOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ExpOptions::UnPackTo(ExpOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset ExpOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateExpOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateExpOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ExpOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateExpOptions( + _fbb); +} + +inline CosOptionsT *CosOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new CosOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void CosOptions::UnPackTo(CosOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset CosOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateCosOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateCosOptions(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CosOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateCosOptions( + _fbb); +} + +inline ReducerOptionsT *ReducerOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ReducerOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ReducerOptions::UnPackTo(ReducerOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = keep_dims(); _o->keep_dims = _e; } +} + +inline flatbuffers::Offset ReducerOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateReducerOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateReducerOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ReducerOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _keep_dims = _o->keep_dims; + return tflite::CreateReducerOptions( + _fbb, + _keep_dims); +} + +inline SqueezeOptionsT *SqueezeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SqueezeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SqueezeOptions::UnPackTo(SqueezeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = squeeze_dims(); if (_e) { _o->squeeze_dims.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->squeeze_dims[_i] = _e->Get(_i); } } } +} + +inline flatbuffers::Offset SqueezeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSqueezeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSqueezeOptions(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SqueezeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _squeeze_dims = _o->squeeze_dims.size() ? _fbb.CreateVector(_o->squeeze_dims) : 0; + return tflite::CreateSqueezeOptions( + _fbb, + _squeeze_dims); +} + +inline SplitOptionsT *SplitOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SplitOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SplitOptions::UnPackTo(SplitOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = num_splits(); _o->num_splits = _e; } +} + +inline flatbuffers::Offset SplitOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSplitOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSplitOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SplitOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _num_splits = _o->num_splits; + return tflite::CreateSplitOptions( + _fbb, + _num_splits); +} + +inline SplitVOptionsT *SplitVOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SplitVOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SplitVOptions::UnPackTo(SplitVOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = num_splits(); _o->num_splits = _e; } +} + +inline flatbuffers::Offset SplitVOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSplitVOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSplitVOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SplitVOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _num_splits = _o->num_splits; + return tflite::CreateSplitVOptions( + _fbb, + _num_splits); +} + +inline StridedSliceOptionsT *StridedSliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new StridedSliceOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void StridedSliceOptions::UnPackTo(StridedSliceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = begin_mask(); _o->begin_mask = _e; } + { auto _e = end_mask(); _o->end_mask = _e; } + { auto _e = ellipsis_mask(); _o->ellipsis_mask = _e; } + { auto _e = new_axis_mask(); _o->new_axis_mask = _e; } + { auto _e = shrink_axis_mask(); _o->shrink_axis_mask = _e; } +} + +inline flatbuffers::Offset StridedSliceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateStridedSliceOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateStridedSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const StridedSliceOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _begin_mask = _o->begin_mask; + auto _end_mask = _o->end_mask; + auto _ellipsis_mask = _o->ellipsis_mask; + auto _new_axis_mask = _o->new_axis_mask; + auto _shrink_axis_mask = _o->shrink_axis_mask; + return tflite::CreateStridedSliceOptions( + _fbb, + _begin_mask, + _end_mask, + _ellipsis_mask, + _new_axis_mask, + _shrink_axis_mask); +} + +inline LogSoftmaxOptionsT *LogSoftmaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LogSoftmaxOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LogSoftmaxOptions::UnPackTo(LogSoftmaxOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset LogSoftmaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLogSoftmaxOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLogSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LogSoftmaxOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateLogSoftmaxOptions( + _fbb); +} + +inline CastOptionsT *CastOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new CastOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void CastOptions::UnPackTo(CastOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = in_data_type(); _o->in_data_type = _e; } + { auto _e = out_data_type(); _o->out_data_type = _e; } +} + +inline flatbuffers::Offset CastOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateCastOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateCastOptions(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CastOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _in_data_type = _o->in_data_type; + auto _out_data_type = _o->out_data_type; + return tflite::CreateCastOptions( + _fbb, + _in_data_type, + _out_data_type); +} + +inline DequantizeOptionsT *DequantizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new DequantizeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void DequantizeOptions::UnPackTo(DequantizeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset DequantizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateDequantizeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateDequantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DequantizeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateDequantizeOptions( + _fbb); +} + +inline MaximumMinimumOptionsT *MaximumMinimumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new MaximumMinimumOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void MaximumMinimumOptions::UnPackTo(MaximumMinimumOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset MaximumMinimumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateMaximumMinimumOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateMaximumMinimumOptions(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MaximumMinimumOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateMaximumMinimumOptions( + _fbb); +} + +inline TileOptionsT *TileOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new TileOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void TileOptions::UnPackTo(TileOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset TileOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateTileOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateTileOptions(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TileOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateTileOptions( + _fbb); +} + +inline ArgMaxOptionsT *ArgMaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ArgMaxOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ArgMaxOptions::UnPackTo(ArgMaxOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = output_type(); _o->output_type = _e; } +} + +inline flatbuffers::Offset ArgMaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateArgMaxOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateArgMaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ArgMaxOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _output_type = _o->output_type; + return tflite::CreateArgMaxOptions( + _fbb, + _output_type); +} + +inline ArgMinOptionsT *ArgMinOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ArgMinOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ArgMinOptions::UnPackTo(ArgMinOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = output_type(); _o->output_type = _e; } +} + +inline flatbuffers::Offset ArgMinOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateArgMinOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateArgMinOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ArgMinOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _output_type = _o->output_type; + return tflite::CreateArgMinOptions( + _fbb, + _output_type); +} + +inline GreaterOptionsT *GreaterOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new GreaterOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void GreaterOptions::UnPackTo(GreaterOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset GreaterOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateGreaterOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateGreaterOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const GreaterOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateGreaterOptions( + _fbb); +} + +inline GreaterEqualOptionsT *GreaterEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new GreaterEqualOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void GreaterEqualOptions::UnPackTo(GreaterEqualOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset GreaterEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateGreaterEqualOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateGreaterEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const GreaterEqualOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateGreaterEqualOptions( + _fbb); +} + +inline LessOptionsT *LessOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LessOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LessOptions::UnPackTo(LessOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset LessOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLessOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLessOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LessOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateLessOptions( + _fbb); +} + +inline LessEqualOptionsT *LessEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LessEqualOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LessEqualOptions::UnPackTo(LessEqualOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset LessEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLessEqualOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLessEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LessEqualOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateLessEqualOptions( + _fbb); +} + +inline NegOptionsT *NegOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new NegOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void NegOptions::UnPackTo(NegOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset NegOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateNegOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateNegOptions(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const NegOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateNegOptions( + _fbb); +} + +inline SelectOptionsT *SelectOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SelectOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SelectOptions::UnPackTo(SelectOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset SelectOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSelectOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSelectOptions(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SelectOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateSelectOptions( + _fbb); +} + +inline SliceOptionsT *SliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SliceOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SliceOptions::UnPackTo(SliceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset SliceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSliceOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SliceOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateSliceOptions( + _fbb); +} + +inline TransposeConvOptionsT *TransposeConvOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new TransposeConvOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void TransposeConvOptions::UnPackTo(TransposeConvOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = padding(); _o->padding = _e; } + { auto _e = stride_w(); _o->stride_w = _e; } + { auto _e = stride_h(); _o->stride_h = _e; } +} + +inline flatbuffers::Offset TransposeConvOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateTransposeConvOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateTransposeConvOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TransposeConvOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _padding = _o->padding; + auto _stride_w = _o->stride_w; + auto _stride_h = _o->stride_h; + return tflite::CreateTransposeConvOptions( + _fbb, + _padding, + _stride_w, + _stride_h); +} + +inline ExpandDimsOptionsT *ExpandDimsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ExpandDimsOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ExpandDimsOptions::UnPackTo(ExpandDimsOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset ExpandDimsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateExpandDimsOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateExpandDimsOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ExpandDimsOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateExpandDimsOptions( + _fbb); +} + +inline SparseToDenseOptionsT *SparseToDenseOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SparseToDenseOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SparseToDenseOptions::UnPackTo(SparseToDenseOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = validate_indices(); _o->validate_indices = _e; } +} + +inline flatbuffers::Offset SparseToDenseOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSparseToDenseOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSparseToDenseOptions(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SparseToDenseOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _validate_indices = _o->validate_indices; + return tflite::CreateSparseToDenseOptions( + _fbb, + _validate_indices); +} + +inline EqualOptionsT *EqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new EqualOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void EqualOptions::UnPackTo(EqualOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset EqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateEqualOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const EqualOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateEqualOptions( + _fbb); +} + +inline NotEqualOptionsT *NotEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new NotEqualOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void NotEqualOptions::UnPackTo(NotEqualOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset NotEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateNotEqualOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateNotEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const NotEqualOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateNotEqualOptions( + _fbb); +} + +inline ShapeOptionsT *ShapeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ShapeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ShapeOptions::UnPackTo(ShapeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = out_type(); _o->out_type = _e; } +} + +inline flatbuffers::Offset ShapeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateShapeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateShapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ShapeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _out_type = _o->out_type; + return tflite::CreateShapeOptions( + _fbb, + _out_type); +} + +inline RankOptionsT *RankOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new RankOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RankOptions::UnPackTo(RankOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset RankOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateRankOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateRankOptions(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const RankOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateRankOptions( + _fbb); +} + +inline PowOptionsT *PowOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new PowOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void PowOptions::UnPackTo(PowOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset PowOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreatePowOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreatePowOptions(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const PowOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreatePowOptions( + _fbb); +} + +inline FakeQuantOptionsT *FakeQuantOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new FakeQuantOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void FakeQuantOptions::UnPackTo(FakeQuantOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = min(); _o->min = _e; } + { auto _e = max(); _o->max = _e; } + { auto _e = num_bits(); _o->num_bits = _e; } + { auto _e = narrow_range(); _o->narrow_range = _e; } +} + +inline flatbuffers::Offset FakeQuantOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateFakeQuantOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateFakeQuantOptions(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const FakeQuantOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _min = _o->min; + auto _max = _o->max; + auto _num_bits = _o->num_bits; + auto _narrow_range = _o->narrow_range; + return tflite::CreateFakeQuantOptions( + _fbb, + _min, + _max, + _num_bits, + _narrow_range); +} + +inline PackOptionsT *PackOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new PackOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void PackOptions::UnPackTo(PackOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = values_count(); _o->values_count = _e; } + { auto _e = axis(); _o->axis = _e; } +} + +inline flatbuffers::Offset PackOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreatePackOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreatePackOptions(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const PackOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _values_count = _o->values_count; + auto _axis = _o->axis; + return tflite::CreatePackOptions( + _fbb, + _values_count, + _axis); +} + +inline LogicalOrOptionsT *LogicalOrOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LogicalOrOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LogicalOrOptions::UnPackTo(LogicalOrOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset LogicalOrOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLogicalOrOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLogicalOrOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LogicalOrOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateLogicalOrOptions( + _fbb); +} + +inline OneHotOptionsT *OneHotOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new OneHotOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void OneHotOptions::UnPackTo(OneHotOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = axis(); _o->axis = _e; } +} + +inline flatbuffers::Offset OneHotOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateOneHotOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateOneHotOptions(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const OneHotOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _axis = _o->axis; + return tflite::CreateOneHotOptions( + _fbb, + _axis); +} + +inline AbsOptionsT *AbsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new AbsOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void AbsOptions::UnPackTo(AbsOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset AbsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateAbsOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateAbsOptions(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const AbsOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateAbsOptions( + _fbb); +} + +inline HardSwishOptionsT *HardSwishOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new HardSwishOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void HardSwishOptions::UnPackTo(HardSwishOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset HardSwishOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateHardSwishOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateHardSwishOptions(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const HardSwishOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateHardSwishOptions( + _fbb); +} + +inline LogicalAndOptionsT *LogicalAndOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LogicalAndOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LogicalAndOptions::UnPackTo(LogicalAndOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset LogicalAndOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLogicalAndOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLogicalAndOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LogicalAndOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateLogicalAndOptions( + _fbb); +} + +inline LogicalNotOptionsT *LogicalNotOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LogicalNotOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LogicalNotOptions::UnPackTo(LogicalNotOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset LogicalNotOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLogicalNotOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLogicalNotOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LogicalNotOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateLogicalNotOptions( + _fbb); +} + +inline UnpackOptionsT *UnpackOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new UnpackOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void UnpackOptions::UnPackTo(UnpackOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = num(); _o->num = _e; } + { auto _e = axis(); _o->axis = _e; } +} + +inline flatbuffers::Offset UnpackOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateUnpackOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateUnpackOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const UnpackOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _num = _o->num; + auto _axis = _o->axis; + return tflite::CreateUnpackOptions( + _fbb, + _num, + _axis); +} + +inline FloorDivOptionsT *FloorDivOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new FloorDivOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void FloorDivOptions::UnPackTo(FloorDivOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset FloorDivOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateFloorDivOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateFloorDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const FloorDivOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateFloorDivOptions( + _fbb); +} + +inline SquareOptionsT *SquareOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SquareOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SquareOptions::UnPackTo(SquareOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset SquareOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSquareOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSquareOptions(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SquareOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateSquareOptions( + _fbb); +} + +inline ZerosLikeOptionsT *ZerosLikeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ZerosLikeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ZerosLikeOptions::UnPackTo(ZerosLikeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset ZerosLikeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateZerosLikeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateZerosLikeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ZerosLikeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateZerosLikeOptions( + _fbb); +} + +inline FillOptionsT *FillOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new FillOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void FillOptions::UnPackTo(FillOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset FillOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateFillOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateFillOptions(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const FillOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateFillOptions( + _fbb); +} + +inline FloorModOptionsT *FloorModOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new FloorModOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void FloorModOptions::UnPackTo(FloorModOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset FloorModOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateFloorModOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateFloorModOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const FloorModOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateFloorModOptions( + _fbb); +} + +inline RangeOptionsT *RangeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new RangeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RangeOptions::UnPackTo(RangeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset RangeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateRangeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateRangeOptions(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const RangeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateRangeOptions( + _fbb); +} + +inline LeakyReluOptionsT *LeakyReluOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new LeakyReluOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void LeakyReluOptions::UnPackTo(LeakyReluOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = alpha(); _o->alpha = _e; } +} + +inline flatbuffers::Offset LeakyReluOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLeakyReluOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLeakyReluOptions(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LeakyReluOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _alpha = _o->alpha; + return tflite::CreateLeakyReluOptions( + _fbb, + _alpha); +} + +inline SquaredDifferenceOptionsT *SquaredDifferenceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SquaredDifferenceOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SquaredDifferenceOptions::UnPackTo(SquaredDifferenceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset SquaredDifferenceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquaredDifferenceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSquaredDifferenceOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSquaredDifferenceOptions(flatbuffers::FlatBufferBuilder &_fbb, const SquaredDifferenceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SquaredDifferenceOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateSquaredDifferenceOptions( + _fbb); +} + +inline MirrorPadOptionsT *MirrorPadOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new MirrorPadOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void MirrorPadOptions::UnPackTo(MirrorPadOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = mode(); _o->mode = _e; } +} + +inline flatbuffers::Offset MirrorPadOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateMirrorPadOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateMirrorPadOptions(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MirrorPadOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _mode = _o->mode; + return tflite::CreateMirrorPadOptions( + _fbb, + _mode); +} + +inline UniqueOptionsT *UniqueOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new UniqueOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void UniqueOptions::UnPackTo(UniqueOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = idx_out_type(); _o->idx_out_type = _e; } +} + +inline flatbuffers::Offset UniqueOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateUniqueOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateUniqueOptions(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const UniqueOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _idx_out_type = _o->idx_out_type; + return tflite::CreateUniqueOptions( + _fbb, + _idx_out_type); +} + +inline ReverseV2OptionsT *ReverseV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ReverseV2OptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ReverseV2Options::UnPackTo(ReverseV2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset ReverseV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateReverseV2Options(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateReverseV2Options(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ReverseV2OptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateReverseV2Options( + _fbb); +} + +inline AddNOptionsT *AddNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new AddNOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void AddNOptions::UnPackTo(AddNOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset AddNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateAddNOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateAddNOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const AddNOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateAddNOptions( + _fbb); +} + +inline GatherNdOptionsT *GatherNdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new GatherNdOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void GatherNdOptions::UnPackTo(GatherNdOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset GatherNdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateGatherNdOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateGatherNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const GatherNdOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateGatherNdOptions( + _fbb); +} + +inline WhereOptionsT *WhereOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new WhereOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void WhereOptions::UnPackTo(WhereOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset WhereOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateWhereOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateWhereOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const WhereOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateWhereOptions( + _fbb); +} + +inline ReverseSequenceOptionsT *ReverseSequenceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ReverseSequenceOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ReverseSequenceOptions::UnPackTo(ReverseSequenceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = seq_dim(); _o->seq_dim = _e; } + { auto _e = batch_dim(); _o->batch_dim = _e; } +} + +inline flatbuffers::Offset ReverseSequenceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReverseSequenceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateReverseSequenceOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateReverseSequenceOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReverseSequenceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ReverseSequenceOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _seq_dim = _o->seq_dim; + auto _batch_dim = _o->batch_dim; + return tflite::CreateReverseSequenceOptions( + _fbb, + _seq_dim, + _batch_dim); +} + +inline MatrixDiagOptionsT *MatrixDiagOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new MatrixDiagOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void MatrixDiagOptions::UnPackTo(MatrixDiagOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset MatrixDiagOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateMatrixDiagOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateMatrixDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MatrixDiagOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateMatrixDiagOptions( + _fbb); +} + +inline QuantizeOptionsT *QuantizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new QuantizeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void QuantizeOptions::UnPackTo(QuantizeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset QuantizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateQuantizeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateQuantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const QuantizeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateQuantizeOptions( + _fbb); +} + +inline MatrixSetDiagOptionsT *MatrixSetDiagOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new MatrixSetDiagOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void MatrixSetDiagOptions::UnPackTo(MatrixSetDiagOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset MatrixSetDiagOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateMatrixSetDiagOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateMatrixSetDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MatrixSetDiagOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateMatrixSetDiagOptions( + _fbb); +} + +inline IfOptionsT *IfOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new IfOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void IfOptions::UnPackTo(IfOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = then_subgraph_index(); _o->then_subgraph_index = _e; } + { auto _e = else_subgraph_index(); _o->else_subgraph_index = _e; } +} + +inline flatbuffers::Offset IfOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateIfOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateIfOptions(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const IfOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _then_subgraph_index = _o->then_subgraph_index; + auto _else_subgraph_index = _o->else_subgraph_index; + return tflite::CreateIfOptions( + _fbb, + _then_subgraph_index, + _else_subgraph_index); +} + +inline CallOnceOptionsT *CallOnceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new CallOnceOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void CallOnceOptions::UnPackTo(CallOnceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = init_subgraph_index(); _o->init_subgraph_index = _e; } +} + +inline flatbuffers::Offset CallOnceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateCallOnceOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateCallOnceOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CallOnceOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _init_subgraph_index = _o->init_subgraph_index; + return tflite::CreateCallOnceOptions( + _fbb, + _init_subgraph_index); +} + +inline WhileOptionsT *WhileOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new WhileOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void WhileOptions::UnPackTo(WhileOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = cond_subgraph_index(); _o->cond_subgraph_index = _e; } + { auto _e = body_subgraph_index(); _o->body_subgraph_index = _e; } +} + +inline flatbuffers::Offset WhileOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateWhileOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateWhileOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const WhileOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _cond_subgraph_index = _o->cond_subgraph_index; + auto _body_subgraph_index = _o->body_subgraph_index; + return tflite::CreateWhileOptions( + _fbb, + _cond_subgraph_index, + _body_subgraph_index); +} + +inline NonMaxSuppressionV4OptionsT *NonMaxSuppressionV4Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new NonMaxSuppressionV4OptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void NonMaxSuppressionV4Options::UnPackTo(NonMaxSuppressionV4OptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset NonMaxSuppressionV4Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV4OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateNonMaxSuppressionV4Options(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateNonMaxSuppressionV4Options(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV4OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const NonMaxSuppressionV4OptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateNonMaxSuppressionV4Options( + _fbb); +} + +inline NonMaxSuppressionV5OptionsT *NonMaxSuppressionV5Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new NonMaxSuppressionV5OptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void NonMaxSuppressionV5Options::UnPackTo(NonMaxSuppressionV5OptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset NonMaxSuppressionV5Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV5OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateNonMaxSuppressionV5Options(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateNonMaxSuppressionV5Options(flatbuffers::FlatBufferBuilder &_fbb, const NonMaxSuppressionV5OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const NonMaxSuppressionV5OptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateNonMaxSuppressionV5Options( + _fbb); +} + +inline ScatterNdOptionsT *ScatterNdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ScatterNdOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ScatterNdOptions::UnPackTo(ScatterNdOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset ScatterNdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateScatterNdOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateScatterNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ScatterNdOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateScatterNdOptions( + _fbb); +} + +inline SelectV2OptionsT *SelectV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SelectV2OptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SelectV2Options::UnPackTo(SelectV2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset SelectV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSelectV2Options(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSelectV2Options(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SelectV2OptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateSelectV2Options( + _fbb); +} + +inline DensifyOptionsT *DensifyOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new DensifyOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void DensifyOptions::UnPackTo(DensifyOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset DensifyOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateDensifyOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateDensifyOptions(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DensifyOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateDensifyOptions( + _fbb); +} + +inline SegmentSumOptionsT *SegmentSumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SegmentSumOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SegmentSumOptions::UnPackTo(SegmentSumOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset SegmentSumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSegmentSumOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SegmentSumOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateSegmentSumOptions( + _fbb); +} + +inline BatchMatMulOptionsT *BatchMatMulOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new BatchMatMulOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void BatchMatMulOptions::UnPackTo(BatchMatMulOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = adj_x(); _o->adj_x = _e; } + { auto _e = adj_y(); _o->adj_y = _e; } + { auto _e = asymmetric_quantize_inputs(); _o->asymmetric_quantize_inputs = _e; } +} + +inline flatbuffers::Offset BatchMatMulOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateBatchMatMulOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateBatchMatMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BatchMatMulOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _adj_x = _o->adj_x; + auto _adj_y = _o->adj_y; + auto _asymmetric_quantize_inputs = _o->asymmetric_quantize_inputs; + return tflite::CreateBatchMatMulOptions( + _fbb, + _adj_x, + _adj_y, + _asymmetric_quantize_inputs); +} + +inline CumsumOptionsT *CumsumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new CumsumOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void CumsumOptions::UnPackTo(CumsumOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = exclusive(); _o->exclusive = _e; } + { auto _e = reverse(); _o->reverse = _e; } +} + +inline flatbuffers::Offset CumsumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateCumsumOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateCumsumOptions(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CumsumOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _exclusive = _o->exclusive; + auto _reverse = _o->reverse; + return tflite::CreateCumsumOptions( + _fbb, + _exclusive, + _reverse); +} + +inline BroadcastToOptionsT *BroadcastToOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new BroadcastToOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void BroadcastToOptions::UnPackTo(BroadcastToOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset BroadcastToOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateBroadcastToOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateBroadcastToOptions(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BroadcastToOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateBroadcastToOptions( + _fbb); +} + +inline Rfft2dOptionsT *Rfft2dOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new Rfft2dOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Rfft2dOptions::UnPackTo(Rfft2dOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset Rfft2dOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateRfft2dOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateRfft2dOptions(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const Rfft2dOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateRfft2dOptions( + _fbb); +} + +inline HashtableOptionsT *HashtableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new HashtableOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void HashtableOptions::UnPackTo(HashtableOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = table_id(); _o->table_id = _e; } + { auto _e = key_dtype(); _o->key_dtype = _e; } + { auto _e = value_dtype(); _o->value_dtype = _e; } +} + +inline flatbuffers::Offset HashtableOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateHashtableOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateHashtableOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const HashtableOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _table_id = _o->table_id; + auto _key_dtype = _o->key_dtype; + auto _value_dtype = _o->value_dtype; + return tflite::CreateHashtableOptions( + _fbb, + _table_id, + _key_dtype, + _value_dtype); +} + +inline HashtableFindOptionsT *HashtableFindOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new HashtableFindOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void HashtableFindOptions::UnPackTo(HashtableFindOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset HashtableFindOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateHashtableFindOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateHashtableFindOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const HashtableFindOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateHashtableFindOptions( + _fbb); +} + +inline HashtableImportOptionsT *HashtableImportOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new HashtableImportOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void HashtableImportOptions::UnPackTo(HashtableImportOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset HashtableImportOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableImportOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateHashtableImportOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateHashtableImportOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableImportOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const HashtableImportOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateHashtableImportOptions( + _fbb); +} + +inline HashtableSizeOptionsT *HashtableSizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new HashtableSizeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void HashtableSizeOptions::UnPackTo(HashtableSizeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset HashtableSizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateHashtableSizeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateHashtableSizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const HashtableSizeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateHashtableSizeOptions( + _fbb); +} + +inline VarHandleOptionsT *VarHandleOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new VarHandleOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void VarHandleOptions::UnPackTo(VarHandleOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = container(); if (_e) _o->container = _e->str(); } + { auto _e = shared_name(); if (_e) _o->shared_name = _e->str(); } +} + +inline flatbuffers::Offset VarHandleOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateVarHandleOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateVarHandleOptions(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const VarHandleOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _container = _o->container.empty() ? 0 : _fbb.CreateString(_o->container); + auto _shared_name = _o->shared_name.empty() ? 0 : _fbb.CreateString(_o->shared_name); + return tflite::CreateVarHandleOptions( + _fbb, + _container, + _shared_name); +} + +inline ReadVariableOptionsT *ReadVariableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ReadVariableOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ReadVariableOptions::UnPackTo(ReadVariableOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset ReadVariableOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateReadVariableOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateReadVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ReadVariableOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateReadVariableOptions( + _fbb); +} + +inline AssignVariableOptionsT *AssignVariableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new AssignVariableOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void AssignVariableOptions::UnPackTo(AssignVariableOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset AssignVariableOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateAssignVariableOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateAssignVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const AssignVariableOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateAssignVariableOptions( + _fbb); +} + +inline RandomOptionsT *RandomOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new RandomOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RandomOptions::UnPackTo(RandomOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = seed(); _o->seed = _e; } + { auto _e = seed2(); _o->seed2 = _e; } +} + +inline flatbuffers::Offset RandomOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateRandomOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateRandomOptions(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const RandomOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _seed = _o->seed; + auto _seed2 = _o->seed2; + return tflite::CreateRandomOptions( + _fbb, + _seed, + _seed2); +} + +inline BucketizeOptionsT *BucketizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new BucketizeOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void BucketizeOptions::UnPackTo(BucketizeOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = boundaries(); if (_e) { _o->boundaries.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->boundaries[_i] = _e->Get(_i); } } } +} + +inline flatbuffers::Offset BucketizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateBucketizeOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateBucketizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BucketizeOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _boundaries = _o->boundaries.size() ? _fbb.CreateVector(_o->boundaries) : 0; + return tflite::CreateBucketizeOptions( + _fbb, + _boundaries); +} + +inline GeluOptionsT *GeluOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new GeluOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void GeluOptions::UnPackTo(GeluOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = approximate(); _o->approximate = _e; } +} + +inline flatbuffers::Offset GeluOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateGeluOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateGeluOptions(flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const GeluOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _approximate = _o->approximate; + return tflite::CreateGeluOptions( + _fbb, + _approximate); +} + +inline DynamicUpdateSliceOptionsT *DynamicUpdateSliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new DynamicUpdateSliceOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void DynamicUpdateSliceOptions::UnPackTo(DynamicUpdateSliceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset DynamicUpdateSliceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DynamicUpdateSliceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateDynamicUpdateSliceOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateDynamicUpdateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const DynamicUpdateSliceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const DynamicUpdateSliceOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateDynamicUpdateSliceOptions( + _fbb); +} + +inline UnsortedSegmentProdOptionsT *UnsortedSegmentProdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new UnsortedSegmentProdOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void UnsortedSegmentProdOptions::UnPackTo(UnsortedSegmentProdOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset UnsortedSegmentProdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentProdOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateUnsortedSegmentProdOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateUnsortedSegmentProdOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentProdOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const UnsortedSegmentProdOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateUnsortedSegmentProdOptions( + _fbb); +} + +inline UnsortedSegmentMaxOptionsT *UnsortedSegmentMaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new UnsortedSegmentMaxOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void UnsortedSegmentMaxOptions::UnPackTo(UnsortedSegmentMaxOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset UnsortedSegmentMaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMaxOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateUnsortedSegmentMaxOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateUnsortedSegmentMaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMaxOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const UnsortedSegmentMaxOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateUnsortedSegmentMaxOptions( + _fbb); +} + +inline UnsortedSegmentSumOptionsT *UnsortedSegmentSumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new UnsortedSegmentSumOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void UnsortedSegmentSumOptions::UnPackTo(UnsortedSegmentSumOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset UnsortedSegmentSumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentSumOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateUnsortedSegmentSumOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateUnsortedSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentSumOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const UnsortedSegmentSumOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateUnsortedSegmentSumOptions( + _fbb); +} + +inline ATan2OptionsT *ATan2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ATan2OptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ATan2Options::UnPackTo(ATan2OptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset ATan2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateATan2Options(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateATan2Options(flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ATan2OptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateATan2Options( + _fbb); +} + +inline UnsortedSegmentMinOptionsT *UnsortedSegmentMinOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new UnsortedSegmentMinOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void UnsortedSegmentMinOptions::UnPackTo(UnsortedSegmentMinOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset UnsortedSegmentMinOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMinOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateUnsortedSegmentMinOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateUnsortedSegmentMinOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMinOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const UnsortedSegmentMinOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateUnsortedSegmentMinOptions( + _fbb); +} + +inline SignOptionsT *SignOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SignOptionsT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SignOptions::UnPackTo(SignOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset SignOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSignOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSignOptions(flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SignOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateSignOptions( + _fbb); +} + +inline OperatorCodeT *OperatorCode::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new OperatorCodeT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void OperatorCode::UnPackTo(OperatorCodeT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = deprecated_builtin_code(); _o->deprecated_builtin_code = _e; } + { auto _e = custom_code(); if (_e) _o->custom_code = _e->str(); } + { auto _e = version(); _o->version = _e; } + { auto _e = builtin_code(); _o->builtin_code = _e; } +} + +inline flatbuffers::Offset OperatorCode::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateOperatorCode(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateOperatorCode(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const OperatorCodeT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _deprecated_builtin_code = _o->deprecated_builtin_code; + auto _custom_code = _o->custom_code.empty() ? 0 : _fbb.CreateString(_o->custom_code); + auto _version = _o->version; + auto _builtin_code = _o->builtin_code; + return tflite::CreateOperatorCode( + _fbb, + _deprecated_builtin_code, + _custom_code, + _version, + _builtin_code); +} + +inline OperatorT *Operator::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new OperatorT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Operator::UnPackTo(OperatorT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = opcode_index(); _o->opcode_index = _e; } + { auto _e = inputs(); if (_e) { _o->inputs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inputs[_i] = _e->Get(_i); } } } + { auto _e = outputs(); if (_e) { _o->outputs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->outputs[_i] = _e->Get(_i); } } } + { auto _e = builtin_options_type(); _o->builtin_options.type = _e; } + { auto _e = builtin_options(); if (_e) _o->builtin_options.value = tflite::BuiltinOptionsUnion::UnPack(_e, builtin_options_type(), _resolver); } + { auto _e = custom_options(); if (_e) { _o->custom_options.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->custom_options.begin()); } } + { auto _e = custom_options_format(); _o->custom_options_format = _e; } + { auto _e = mutating_variable_inputs(); if (_e) { _o->mutating_variable_inputs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->mutating_variable_inputs[_i] = _e->Get(_i) != 0; } } } + { auto _e = intermediates(); if (_e) { _o->intermediates.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->intermediates[_i] = _e->Get(_i); } } } +} + +inline flatbuffers::Offset Operator::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateOperator(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateOperator(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const OperatorT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _opcode_index = _o->opcode_index; + auto _inputs = _o->inputs.size() ? _fbb.CreateVector(_o->inputs) : 0; + auto _outputs = _o->outputs.size() ? _fbb.CreateVector(_o->outputs) : 0; + auto _builtin_options_type = _o->builtin_options.type; + auto _builtin_options = _o->builtin_options.Pack(_fbb); + auto _custom_options = _o->custom_options.size() ? _fbb.CreateVector(_o->custom_options) : 0; + auto _custom_options_format = _o->custom_options_format; + auto _mutating_variable_inputs = _o->mutating_variable_inputs.size() ? _fbb.CreateVector(_o->mutating_variable_inputs) : 0; + auto _intermediates = _o->intermediates.size() ? _fbb.CreateVector(_o->intermediates) : 0; + return tflite::CreateOperator( + _fbb, + _opcode_index, + _inputs, + _outputs, + _builtin_options_type, + _builtin_options, + _custom_options, + _custom_options_format, + _mutating_variable_inputs, + _intermediates); +} + +inline SubGraphT::SubGraphT(const SubGraphT &o) + : inputs(o.inputs), + outputs(o.outputs), + name(o.name) { + tensors.reserve(o.tensors.size()); + for (const auto &tensors_ : o.tensors) { tensors.emplace_back((tensors_) ? new tflite::TensorT(*tensors_) : nullptr); } + operators.reserve(o.operators.size()); + for (const auto &operators_ : o.operators) { operators.emplace_back((operators_) ? new tflite::OperatorT(*operators_) : nullptr); } +} + +inline SubGraphT &SubGraphT::operator=(SubGraphT o) FLATBUFFERS_NOEXCEPT { + std::swap(tensors, o.tensors); + std::swap(inputs, o.inputs); + std::swap(outputs, o.outputs); + std::swap(operators, o.operators); + std::swap(name, o.name); + return *this; +} + +inline SubGraphT *SubGraph::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SubGraphT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SubGraph::UnPackTo(SubGraphT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = tensors(); if (_e) { _o->tensors.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->tensors[_i]) { _e->Get(_i)->UnPackTo(_o->tensors[_i].get(), _resolver); } else { _o->tensors[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } + { auto _e = inputs(); if (_e) { _o->inputs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inputs[_i] = _e->Get(_i); } } } + { auto _e = outputs(); if (_e) { _o->outputs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->outputs[_i] = _e->Get(_i); } } } + { auto _e = operators(); if (_e) { _o->operators.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->operators[_i]) { _e->Get(_i)->UnPackTo(_o->operators[_i].get(), _resolver); } else { _o->operators[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } + { auto _e = name(); if (_e) _o->name = _e->str(); } +} + +inline flatbuffers::Offset SubGraph::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSubGraph(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSubGraph(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SubGraphT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _tensors = _o->tensors.size() ? _fbb.CreateVector> (_o->tensors.size(), [](size_t i, _VectorArgs *__va) { return CreateTensor(*__va->__fbb, __va->__o->tensors[i].get(), __va->__rehasher); }, &_va ) : 0; + auto _inputs = _o->inputs.size() ? _fbb.CreateVector(_o->inputs) : 0; + auto _outputs = _o->outputs.size() ? _fbb.CreateVector(_o->outputs) : 0; + auto _operators = _o->operators.size() ? _fbb.CreateVector> (_o->operators.size(), [](size_t i, _VectorArgs *__va) { return CreateOperator(*__va->__fbb, __va->__o->operators[i].get(), __va->__rehasher); }, &_va ) : 0; + auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name); + return tflite::CreateSubGraph( + _fbb, + _tensors, + _inputs, + _outputs, + _operators, + _name); +} + +inline BufferT *Buffer::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new BufferT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Buffer::UnPackTo(BufferT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = data(); if (_e) { _o->data.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->data.begin()); } } +} + +inline flatbuffers::Offset Buffer::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BufferT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateBuffer(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateBuffer(flatbuffers::FlatBufferBuilder &_fbb, const BufferT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BufferT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + _fbb.ForceVectorAlignment(_o->data.size(), sizeof(uint8_t), 16); + auto _data = _o->data.size() ? _fbb.CreateVector(_o->data) : 0; + return tflite::CreateBuffer( + _fbb, + _data); +} + +inline MetadataT *Metadata::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new MetadataT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Metadata::UnPackTo(MetadataT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = name(); if (_e) _o->name = _e->str(); } + { auto _e = buffer(); _o->buffer = _e; } +} + +inline flatbuffers::Offset Metadata::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateMetadata(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateMetadata(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MetadataT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name); + auto _buffer = _o->buffer; + return tflite::CreateMetadata( + _fbb, + _name, + _buffer); +} + +inline TensorMapT *TensorMap::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new TensorMapT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void TensorMap::UnPackTo(TensorMapT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = name(); if (_e) _o->name = _e->str(); } + { auto _e = tensor_index(); _o->tensor_index = _e; } +} + +inline flatbuffers::Offset TensorMap::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateTensorMap(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateTensorMap(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const TensorMapT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name); + auto _tensor_index = _o->tensor_index; + return tflite::CreateTensorMap( + _fbb, + _name, + _tensor_index); +} + +inline SignatureDefT::SignatureDefT(const SignatureDefT &o) + : signature_key(o.signature_key), + subgraph_index(o.subgraph_index) { + inputs.reserve(o.inputs.size()); + for (const auto &inputs_ : o.inputs) { inputs.emplace_back((inputs_) ? new tflite::TensorMapT(*inputs_) : nullptr); } + outputs.reserve(o.outputs.size()); + for (const auto &outputs_ : o.outputs) { outputs.emplace_back((outputs_) ? new tflite::TensorMapT(*outputs_) : nullptr); } +} + +inline SignatureDefT &SignatureDefT::operator=(SignatureDefT o) FLATBUFFERS_NOEXCEPT { + std::swap(inputs, o.inputs); + std::swap(outputs, o.outputs); + std::swap(signature_key, o.signature_key); + std::swap(subgraph_index, o.subgraph_index); + return *this; +} + +inline SignatureDefT *SignatureDef::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new SignatureDefT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void SignatureDef::UnPackTo(SignatureDefT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = inputs(); if (_e) { _o->inputs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->inputs[_i]) { _e->Get(_i)->UnPackTo(_o->inputs[_i].get(), _resolver); } else { _o->inputs[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } + { auto _e = outputs(); if (_e) { _o->outputs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->outputs[_i]) { _e->Get(_i)->UnPackTo(_o->outputs[_i].get(), _resolver); } else { _o->outputs[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } + { auto _e = signature_key(); if (_e) _o->signature_key = _e->str(); } + { auto _e = subgraph_index(); _o->subgraph_index = _e; } +} + +inline flatbuffers::Offset SignatureDef::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SignatureDefT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSignatureDef(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSignatureDef(flatbuffers::FlatBufferBuilder &_fbb, const SignatureDefT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SignatureDefT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _inputs = _o->inputs.size() ? _fbb.CreateVector> (_o->inputs.size(), [](size_t i, _VectorArgs *__va) { return CreateTensorMap(*__va->__fbb, __va->__o->inputs[i].get(), __va->__rehasher); }, &_va ) : 0; + auto _outputs = _o->outputs.size() ? _fbb.CreateVector> (_o->outputs.size(), [](size_t i, _VectorArgs *__va) { return CreateTensorMap(*__va->__fbb, __va->__o->outputs[i].get(), __va->__rehasher); }, &_va ) : 0; + auto _signature_key = _o->signature_key.empty() ? 0 : _fbb.CreateString(_o->signature_key); + auto _subgraph_index = _o->subgraph_index; + return tflite::CreateSignatureDef( + _fbb, + _inputs, + _outputs, + _signature_key, + _subgraph_index); +} + +inline ModelT::ModelT(const ModelT &o) + : version(o.version), + description(o.description), + metadata_buffer(o.metadata_buffer) { + operator_codes.reserve(o.operator_codes.size()); + for (const auto &operator_codes_ : o.operator_codes) { operator_codes.emplace_back((operator_codes_) ? new tflite::OperatorCodeT(*operator_codes_) : nullptr); } + subgraphs.reserve(o.subgraphs.size()); + for (const auto &subgraphs_ : o.subgraphs) { subgraphs.emplace_back((subgraphs_) ? new tflite::SubGraphT(*subgraphs_) : nullptr); } + buffers.reserve(o.buffers.size()); + for (const auto &buffers_ : o.buffers) { buffers.emplace_back((buffers_) ? new tflite::BufferT(*buffers_) : nullptr); } + metadata.reserve(o.metadata.size()); + for (const auto &metadata_ : o.metadata) { metadata.emplace_back((metadata_) ? new tflite::MetadataT(*metadata_) : nullptr); } + signature_defs.reserve(o.signature_defs.size()); + for (const auto &signature_defs_ : o.signature_defs) { signature_defs.emplace_back((signature_defs_) ? new tflite::SignatureDefT(*signature_defs_) : nullptr); } +} + +inline ModelT &ModelT::operator=(ModelT o) FLATBUFFERS_NOEXCEPT { + std::swap(version, o.version); + std::swap(operator_codes, o.operator_codes); + std::swap(subgraphs, o.subgraphs); + std::swap(description, o.description); + std::swap(buffers, o.buffers); + std::swap(metadata_buffer, o.metadata_buffer); + std::swap(metadata, o.metadata); + std::swap(signature_defs, o.signature_defs); + return *this; +} + +inline ModelT *Model::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ModelT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Model::UnPackTo(ModelT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = version(); _o->version = _e; } + { auto _e = operator_codes(); if (_e) { _o->operator_codes.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->operator_codes[_i]) { _e->Get(_i)->UnPackTo(_o->operator_codes[_i].get(), _resolver); } else { _o->operator_codes[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } + { auto _e = subgraphs(); if (_e) { _o->subgraphs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->subgraphs[_i]) { _e->Get(_i)->UnPackTo(_o->subgraphs[_i].get(), _resolver); } else { _o->subgraphs[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } + { auto _e = description(); if (_e) _o->description = _e->str(); } + { auto _e = buffers(); if (_e) { _o->buffers.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->buffers[_i]) { _e->Get(_i)->UnPackTo(_o->buffers[_i].get(), _resolver); } else { _o->buffers[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } + { auto _e = metadata_buffer(); if (_e) { _o->metadata_buffer.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->metadata_buffer[_i] = _e->Get(_i); } } } + { auto _e = metadata(); if (_e) { _o->metadata.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->metadata[_i]) { _e->Get(_i)->UnPackTo(_o->metadata[_i].get(), _resolver); } else { _o->metadata[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } + { auto _e = signature_defs(); if (_e) { _o->signature_defs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->signature_defs[_i]) { _e->Get(_i)->UnPackTo(_o->signature_defs[_i].get(), _resolver); } else { _o->signature_defs[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); }; } } } +} + +inline flatbuffers::Offset Model::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ModelT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateModel(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateModel(flatbuffers::FlatBufferBuilder &_fbb, const ModelT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ModelT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _version = _o->version; + auto _operator_codes = _o->operator_codes.size() ? _fbb.CreateVector> (_o->operator_codes.size(), [](size_t i, _VectorArgs *__va) { return CreateOperatorCode(*__va->__fbb, __va->__o->operator_codes[i].get(), __va->__rehasher); }, &_va ) : 0; + auto _subgraphs = _o->subgraphs.size() ? _fbb.CreateVector> (_o->subgraphs.size(), [](size_t i, _VectorArgs *__va) { return CreateSubGraph(*__va->__fbb, __va->__o->subgraphs[i].get(), __va->__rehasher); }, &_va ) : 0; + auto _description = _o->description.empty() ? 0 : _fbb.CreateString(_o->description); + auto _buffers = _o->buffers.size() ? _fbb.CreateVector> (_o->buffers.size(), [](size_t i, _VectorArgs *__va) { return CreateBuffer(*__va->__fbb, __va->__o->buffers[i].get(), __va->__rehasher); }, &_va ) : 0; + auto _metadata_buffer = _o->metadata_buffer.size() ? _fbb.CreateVector(_o->metadata_buffer) : 0; + auto _metadata = _o->metadata.size() ? _fbb.CreateVector> (_o->metadata.size(), [](size_t i, _VectorArgs *__va) { return CreateMetadata(*__va->__fbb, __va->__o->metadata[i].get(), __va->__rehasher); }, &_va ) : 0; + auto _signature_defs = _o->signature_defs.size() ? _fbb.CreateVector> (_o->signature_defs.size(), [](size_t i, _VectorArgs *__va) { return CreateSignatureDef(*__va->__fbb, __va->__o->signature_defs[i].get(), __va->__rehasher); }, &_va ) : 0; + return tflite::CreateModel( + _fbb, + _version, + _operator_codes, + _subgraphs, + _description, + _buffers, + _metadata_buffer, + _metadata, + _signature_defs); +} + +inline bool VerifyQuantizationDetails(flatbuffers::Verifier &verifier, const void *obj, QuantizationDetails type) { + switch (type) { + case QuantizationDetails_NONE: { + return true; + } + case QuantizationDetails_CustomQuantization: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + default: return true; + } +} + +inline bool VerifyQuantizationDetailsVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { + if (!values || !types) return !values && !types; + if (values->size() != types->size()) return false; + for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { + if (!VerifyQuantizationDetails( + verifier, values->Get(i), types->GetEnum(i))) { + return false; + } + } + return true; +} + +inline void *QuantizationDetailsUnion::UnPack(const void *obj, QuantizationDetails type, const flatbuffers::resolver_function_t *resolver) { + (void)resolver; + switch (type) { + case QuantizationDetails_CustomQuantization: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + default: return nullptr; + } +} + +inline flatbuffers::Offset QuantizationDetailsUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const { + (void)_rehasher; + switch (type) { + case QuantizationDetails_CustomQuantization: { + auto ptr = reinterpret_cast(value); + return CreateCustomQuantization(_fbb, ptr, _rehasher).Union(); + } + default: return 0; + } +} + +inline QuantizationDetailsUnion::QuantizationDetailsUnion(const QuantizationDetailsUnion &u) : type(u.type), value(nullptr) { + switch (type) { + case QuantizationDetails_CustomQuantization: { + value = new tflite::CustomQuantizationT(*reinterpret_cast(u.value)); + break; + } + default: + break; + } +} + +inline void QuantizationDetailsUnion::Reset() { + switch (type) { + case QuantizationDetails_CustomQuantization: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + default: break; + } + value = nullptr; + type = QuantizationDetails_NONE; +} + +inline bool VerifySparseIndexVector(flatbuffers::Verifier &verifier, const void *obj, SparseIndexVector type) { + switch (type) { + case SparseIndexVector_NONE: { + return true; + } + case SparseIndexVector_Int32Vector: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case SparseIndexVector_Uint16Vector: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case SparseIndexVector_Uint8Vector: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + default: return true; + } +} + +inline bool VerifySparseIndexVectorVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { + if (!values || !types) return !values && !types; + if (values->size() != types->size()) return false; + for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { + if (!VerifySparseIndexVector( + verifier, values->Get(i), types->GetEnum(i))) { + return false; + } + } + return true; +} + +inline void *SparseIndexVectorUnion::UnPack(const void *obj, SparseIndexVector type, const flatbuffers::resolver_function_t *resolver) { + (void)resolver; + switch (type) { + case SparseIndexVector_Int32Vector: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case SparseIndexVector_Uint16Vector: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case SparseIndexVector_Uint8Vector: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + default: return nullptr; + } +} + +inline flatbuffers::Offset SparseIndexVectorUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const { + (void)_rehasher; + switch (type) { + case SparseIndexVector_Int32Vector: { + auto ptr = reinterpret_cast(value); + return CreateInt32Vector(_fbb, ptr, _rehasher).Union(); + } + case SparseIndexVector_Uint16Vector: { + auto ptr = reinterpret_cast(value); + return CreateUint16Vector(_fbb, ptr, _rehasher).Union(); + } + case SparseIndexVector_Uint8Vector: { + auto ptr = reinterpret_cast(value); + return CreateUint8Vector(_fbb, ptr, _rehasher).Union(); + } + default: return 0; + } +} + +inline SparseIndexVectorUnion::SparseIndexVectorUnion(const SparseIndexVectorUnion &u) : type(u.type), value(nullptr) { + switch (type) { + case SparseIndexVector_Int32Vector: { + value = new tflite::Int32VectorT(*reinterpret_cast(u.value)); + break; + } + case SparseIndexVector_Uint16Vector: { + value = new tflite::Uint16VectorT(*reinterpret_cast(u.value)); + break; + } + case SparseIndexVector_Uint8Vector: { + value = new tflite::Uint8VectorT(*reinterpret_cast(u.value)); + break; + } + default: + break; + } +} + +inline void SparseIndexVectorUnion::Reset() { + switch (type) { + case SparseIndexVector_Int32Vector: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case SparseIndexVector_Uint16Vector: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case SparseIndexVector_Uint8Vector: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + default: break; + } + value = nullptr; + type = SparseIndexVector_NONE; +} + +inline bool VerifyBuiltinOptions(flatbuffers::Verifier &verifier, const void *obj, BuiltinOptions type) { + switch (type) { + case BuiltinOptions_NONE: { + return true; + } + case BuiltinOptions_Conv2DOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_DepthwiseConv2DOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ConcatEmbeddingsOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LSHProjectionOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_Pool2DOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SVDFOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_RNNOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_FullyConnectedOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SoftmaxOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ConcatenationOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_AddOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_L2NormOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LocalResponseNormalizationOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LSTMOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ResizeBilinearOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_CallOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ReshapeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SkipGramOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SpaceToDepthOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_EmbeddingLookupSparseOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_MulOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_PadOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_GatherOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_BatchToSpaceNDOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SpaceToBatchNDOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_TransposeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ReducerOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SubOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_DivOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SqueezeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SequenceRNNOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_StridedSliceOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ExpOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_TopKV2Options: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SplitOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LogSoftmaxOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_CastOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_DequantizeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_MaximumMinimumOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ArgMaxOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LessOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_NegOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_PadV2Options: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_GreaterOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_GreaterEqualOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LessEqualOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SelectOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SliceOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_TransposeConvOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SparseToDenseOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_TileOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ExpandDimsOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_EqualOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_NotEqualOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ShapeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_PowOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ArgMinOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_FakeQuantOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_PackOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LogicalOrOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_OneHotOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LogicalAndOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LogicalNotOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_UnpackOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_FloorDivOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SquareOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ZerosLikeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_FillOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_BidirectionalSequenceLSTMOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_BidirectionalSequenceRNNOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_UnidirectionalSequenceLSTMOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_FloorModOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_RangeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ResizeNearestNeighborOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_LeakyReluOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SquaredDifferenceOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_MirrorPadOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_AbsOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SplitVOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_UniqueOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ReverseV2Options: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_AddNOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_GatherNdOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_CosOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_WhereOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_RankOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ReverseSequenceOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_MatrixDiagOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_QuantizeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_MatrixSetDiagOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_HardSwishOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_IfOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_WhileOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_DepthToSpaceOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_NonMaxSuppressionV4Options: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_NonMaxSuppressionV5Options: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ScatterNdOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SelectV2Options: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_DensifyOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SegmentSumOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_BatchMatMulOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_CumsumOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_CallOnceOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_BroadcastToOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_Rfft2dOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_Conv3DOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_HashtableOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_HashtableFindOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_HashtableImportOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_HashtableSizeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_VarHandleOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ReadVariableOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_AssignVariableOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_RandomOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_BucketizeOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_GeluOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_DynamicUpdateSliceOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_UnsortedSegmentProdOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_UnsortedSegmentMaxOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_UnsortedSegmentMinOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_UnsortedSegmentSumOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_ATan2Options: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SignOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + default: return true; + } +} + +inline bool VerifyBuiltinOptionsVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { + if (!values || !types) return !values && !types; + if (values->size() != types->size()) return false; + for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { + if (!VerifyBuiltinOptions( + verifier, values->Get(i), types->GetEnum(i))) { + return false; + } + } + return true; +} + +inline void *BuiltinOptionsUnion::UnPack(const void *obj, BuiltinOptions type, const flatbuffers::resolver_function_t *resolver) { + (void)resolver; + switch (type) { + case BuiltinOptions_Conv2DOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_DepthwiseConv2DOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ConcatEmbeddingsOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LSHProjectionOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_Pool2DOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SVDFOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_RNNOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_FullyConnectedOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SoftmaxOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ConcatenationOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_AddOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_L2NormOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LocalResponseNormalizationOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LSTMOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ResizeBilinearOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_CallOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ReshapeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SkipGramOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SpaceToDepthOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_EmbeddingLookupSparseOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_MulOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_PadOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_GatherOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_BatchToSpaceNDOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SpaceToBatchNDOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_TransposeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ReducerOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SubOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_DivOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SqueezeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SequenceRNNOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_StridedSliceOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ExpOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_TopKV2Options: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SplitOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LogSoftmaxOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_CastOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_DequantizeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_MaximumMinimumOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ArgMaxOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LessOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_NegOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_PadV2Options: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_GreaterOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_GreaterEqualOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LessEqualOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SelectOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SliceOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_TransposeConvOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SparseToDenseOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_TileOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ExpandDimsOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_EqualOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_NotEqualOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ShapeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_PowOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ArgMinOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_FakeQuantOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_PackOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LogicalOrOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_OneHotOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LogicalAndOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LogicalNotOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_UnpackOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_FloorDivOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SquareOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ZerosLikeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_FillOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_BidirectionalSequenceLSTMOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_BidirectionalSequenceRNNOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_UnidirectionalSequenceLSTMOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_FloorModOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_RangeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ResizeNearestNeighborOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_LeakyReluOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SquaredDifferenceOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_MirrorPadOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_AbsOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SplitVOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_UniqueOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ReverseV2Options: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_AddNOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_GatherNdOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_CosOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_WhereOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_RankOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ReverseSequenceOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_MatrixDiagOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_QuantizeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_MatrixSetDiagOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_HardSwishOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_IfOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_WhileOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_DepthToSpaceOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_NonMaxSuppressionV4Options: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_NonMaxSuppressionV5Options: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ScatterNdOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SelectV2Options: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_DensifyOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SegmentSumOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_BatchMatMulOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_CumsumOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_CallOnceOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_BroadcastToOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_Rfft2dOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_Conv3DOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_HashtableOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_HashtableFindOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_HashtableImportOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_HashtableSizeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_VarHandleOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ReadVariableOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_AssignVariableOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_RandomOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_BucketizeOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_GeluOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_DynamicUpdateSliceOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_UnsortedSegmentProdOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_UnsortedSegmentMaxOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_UnsortedSegmentMinOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_UnsortedSegmentSumOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_ATan2Options: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SignOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + default: return nullptr; + } +} + +inline flatbuffers::Offset BuiltinOptionsUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const { + (void)_rehasher; + switch (type) { + case BuiltinOptions_Conv2DOptions: { + auto ptr = reinterpret_cast(value); + return CreateConv2DOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_DepthwiseConv2DOptions: { + auto ptr = reinterpret_cast(value); + return CreateDepthwiseConv2DOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ConcatEmbeddingsOptions: { + auto ptr = reinterpret_cast(value); + return CreateConcatEmbeddingsOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LSHProjectionOptions: { + auto ptr = reinterpret_cast(value); + return CreateLSHProjectionOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_Pool2DOptions: { + auto ptr = reinterpret_cast(value); + return CreatePool2DOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SVDFOptions: { + auto ptr = reinterpret_cast(value); + return CreateSVDFOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_RNNOptions: { + auto ptr = reinterpret_cast(value); + return CreateRNNOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_FullyConnectedOptions: { + auto ptr = reinterpret_cast(value); + return CreateFullyConnectedOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SoftmaxOptions: { + auto ptr = reinterpret_cast(value); + return CreateSoftmaxOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ConcatenationOptions: { + auto ptr = reinterpret_cast(value); + return CreateConcatenationOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_AddOptions: { + auto ptr = reinterpret_cast(value); + return CreateAddOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_L2NormOptions: { + auto ptr = reinterpret_cast(value); + return CreateL2NormOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LocalResponseNormalizationOptions: { + auto ptr = reinterpret_cast(value); + return CreateLocalResponseNormalizationOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LSTMOptions: { + auto ptr = reinterpret_cast(value); + return CreateLSTMOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ResizeBilinearOptions: { + auto ptr = reinterpret_cast(value); + return CreateResizeBilinearOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_CallOptions: { + auto ptr = reinterpret_cast(value); + return CreateCallOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ReshapeOptions: { + auto ptr = reinterpret_cast(value); + return CreateReshapeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SkipGramOptions: { + auto ptr = reinterpret_cast(value); + return CreateSkipGramOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SpaceToDepthOptions: { + auto ptr = reinterpret_cast(value); + return CreateSpaceToDepthOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_EmbeddingLookupSparseOptions: { + auto ptr = reinterpret_cast(value); + return CreateEmbeddingLookupSparseOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_MulOptions: { + auto ptr = reinterpret_cast(value); + return CreateMulOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_PadOptions: { + auto ptr = reinterpret_cast(value); + return CreatePadOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_GatherOptions: { + auto ptr = reinterpret_cast(value); + return CreateGatherOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_BatchToSpaceNDOptions: { + auto ptr = reinterpret_cast(value); + return CreateBatchToSpaceNDOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SpaceToBatchNDOptions: { + auto ptr = reinterpret_cast(value); + return CreateSpaceToBatchNDOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_TransposeOptions: { + auto ptr = reinterpret_cast(value); + return CreateTransposeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ReducerOptions: { + auto ptr = reinterpret_cast(value); + return CreateReducerOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SubOptions: { + auto ptr = reinterpret_cast(value); + return CreateSubOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_DivOptions: { + auto ptr = reinterpret_cast(value); + return CreateDivOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SqueezeOptions: { + auto ptr = reinterpret_cast(value); + return CreateSqueezeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SequenceRNNOptions: { + auto ptr = reinterpret_cast(value); + return CreateSequenceRNNOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_StridedSliceOptions: { + auto ptr = reinterpret_cast(value); + return CreateStridedSliceOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ExpOptions: { + auto ptr = reinterpret_cast(value); + return CreateExpOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_TopKV2Options: { + auto ptr = reinterpret_cast(value); + return CreateTopKV2Options(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SplitOptions: { + auto ptr = reinterpret_cast(value); + return CreateSplitOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LogSoftmaxOptions: { + auto ptr = reinterpret_cast(value); + return CreateLogSoftmaxOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_CastOptions: { + auto ptr = reinterpret_cast(value); + return CreateCastOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_DequantizeOptions: { + auto ptr = reinterpret_cast(value); + return CreateDequantizeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_MaximumMinimumOptions: { + auto ptr = reinterpret_cast(value); + return CreateMaximumMinimumOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ArgMaxOptions: { + auto ptr = reinterpret_cast(value); + return CreateArgMaxOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LessOptions: { + auto ptr = reinterpret_cast(value); + return CreateLessOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_NegOptions: { + auto ptr = reinterpret_cast(value); + return CreateNegOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_PadV2Options: { + auto ptr = reinterpret_cast(value); + return CreatePadV2Options(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_GreaterOptions: { + auto ptr = reinterpret_cast(value); + return CreateGreaterOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_GreaterEqualOptions: { + auto ptr = reinterpret_cast(value); + return CreateGreaterEqualOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LessEqualOptions: { + auto ptr = reinterpret_cast(value); + return CreateLessEqualOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SelectOptions: { + auto ptr = reinterpret_cast(value); + return CreateSelectOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SliceOptions: { + auto ptr = reinterpret_cast(value); + return CreateSliceOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_TransposeConvOptions: { + auto ptr = reinterpret_cast(value); + return CreateTransposeConvOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SparseToDenseOptions: { + auto ptr = reinterpret_cast(value); + return CreateSparseToDenseOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_TileOptions: { + auto ptr = reinterpret_cast(value); + return CreateTileOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ExpandDimsOptions: { + auto ptr = reinterpret_cast(value); + return CreateExpandDimsOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_EqualOptions: { + auto ptr = reinterpret_cast(value); + return CreateEqualOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_NotEqualOptions: { + auto ptr = reinterpret_cast(value); + return CreateNotEqualOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ShapeOptions: { + auto ptr = reinterpret_cast(value); + return CreateShapeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_PowOptions: { + auto ptr = reinterpret_cast(value); + return CreatePowOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ArgMinOptions: { + auto ptr = reinterpret_cast(value); + return CreateArgMinOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_FakeQuantOptions: { + auto ptr = reinterpret_cast(value); + return CreateFakeQuantOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_PackOptions: { + auto ptr = reinterpret_cast(value); + return CreatePackOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LogicalOrOptions: { + auto ptr = reinterpret_cast(value); + return CreateLogicalOrOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_OneHotOptions: { + auto ptr = reinterpret_cast(value); + return CreateOneHotOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LogicalAndOptions: { + auto ptr = reinterpret_cast(value); + return CreateLogicalAndOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LogicalNotOptions: { + auto ptr = reinterpret_cast(value); + return CreateLogicalNotOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_UnpackOptions: { + auto ptr = reinterpret_cast(value); + return CreateUnpackOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_FloorDivOptions: { + auto ptr = reinterpret_cast(value); + return CreateFloorDivOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SquareOptions: { + auto ptr = reinterpret_cast(value); + return CreateSquareOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ZerosLikeOptions: { + auto ptr = reinterpret_cast(value); + return CreateZerosLikeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_FillOptions: { + auto ptr = reinterpret_cast(value); + return CreateFillOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_BidirectionalSequenceLSTMOptions: { + auto ptr = reinterpret_cast(value); + return CreateBidirectionalSequenceLSTMOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_BidirectionalSequenceRNNOptions: { + auto ptr = reinterpret_cast(value); + return CreateBidirectionalSequenceRNNOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_UnidirectionalSequenceLSTMOptions: { + auto ptr = reinterpret_cast(value); + return CreateUnidirectionalSequenceLSTMOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_FloorModOptions: { + auto ptr = reinterpret_cast(value); + return CreateFloorModOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_RangeOptions: { + auto ptr = reinterpret_cast(value); + return CreateRangeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ResizeNearestNeighborOptions: { + auto ptr = reinterpret_cast(value); + return CreateResizeNearestNeighborOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_LeakyReluOptions: { + auto ptr = reinterpret_cast(value); + return CreateLeakyReluOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SquaredDifferenceOptions: { + auto ptr = reinterpret_cast(value); + return CreateSquaredDifferenceOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_MirrorPadOptions: { + auto ptr = reinterpret_cast(value); + return CreateMirrorPadOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_AbsOptions: { + auto ptr = reinterpret_cast(value); + return CreateAbsOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SplitVOptions: { + auto ptr = reinterpret_cast(value); + return CreateSplitVOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_UniqueOptions: { + auto ptr = reinterpret_cast(value); + return CreateUniqueOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ReverseV2Options: { + auto ptr = reinterpret_cast(value); + return CreateReverseV2Options(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_AddNOptions: { + auto ptr = reinterpret_cast(value); + return CreateAddNOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_GatherNdOptions: { + auto ptr = reinterpret_cast(value); + return CreateGatherNdOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_CosOptions: { + auto ptr = reinterpret_cast(value); + return CreateCosOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_WhereOptions: { + auto ptr = reinterpret_cast(value); + return CreateWhereOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_RankOptions: { + auto ptr = reinterpret_cast(value); + return CreateRankOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ReverseSequenceOptions: { + auto ptr = reinterpret_cast(value); + return CreateReverseSequenceOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_MatrixDiagOptions: { + auto ptr = reinterpret_cast(value); + return CreateMatrixDiagOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_QuantizeOptions: { + auto ptr = reinterpret_cast(value); + return CreateQuantizeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_MatrixSetDiagOptions: { + auto ptr = reinterpret_cast(value); + return CreateMatrixSetDiagOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_HardSwishOptions: { + auto ptr = reinterpret_cast(value); + return CreateHardSwishOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_IfOptions: { + auto ptr = reinterpret_cast(value); + return CreateIfOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_WhileOptions: { + auto ptr = reinterpret_cast(value); + return CreateWhileOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_DepthToSpaceOptions: { + auto ptr = reinterpret_cast(value); + return CreateDepthToSpaceOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_NonMaxSuppressionV4Options: { + auto ptr = reinterpret_cast(value); + return CreateNonMaxSuppressionV4Options(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_NonMaxSuppressionV5Options: { + auto ptr = reinterpret_cast(value); + return CreateNonMaxSuppressionV5Options(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ScatterNdOptions: { + auto ptr = reinterpret_cast(value); + return CreateScatterNdOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SelectV2Options: { + auto ptr = reinterpret_cast(value); + return CreateSelectV2Options(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_DensifyOptions: { + auto ptr = reinterpret_cast(value); + return CreateDensifyOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SegmentSumOptions: { + auto ptr = reinterpret_cast(value); + return CreateSegmentSumOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_BatchMatMulOptions: { + auto ptr = reinterpret_cast(value); + return CreateBatchMatMulOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_CumsumOptions: { + auto ptr = reinterpret_cast(value); + return CreateCumsumOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_CallOnceOptions: { + auto ptr = reinterpret_cast(value); + return CreateCallOnceOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_BroadcastToOptions: { + auto ptr = reinterpret_cast(value); + return CreateBroadcastToOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_Rfft2dOptions: { + auto ptr = reinterpret_cast(value); + return CreateRfft2dOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_Conv3DOptions: { + auto ptr = reinterpret_cast(value); + return CreateConv3DOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_HashtableOptions: { + auto ptr = reinterpret_cast(value); + return CreateHashtableOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_HashtableFindOptions: { + auto ptr = reinterpret_cast(value); + return CreateHashtableFindOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_HashtableImportOptions: { + auto ptr = reinterpret_cast(value); + return CreateHashtableImportOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_HashtableSizeOptions: { + auto ptr = reinterpret_cast(value); + return CreateHashtableSizeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_VarHandleOptions: { + auto ptr = reinterpret_cast(value); + return CreateVarHandleOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ReadVariableOptions: { + auto ptr = reinterpret_cast(value); + return CreateReadVariableOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_AssignVariableOptions: { + auto ptr = reinterpret_cast(value); + return CreateAssignVariableOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_RandomOptions: { + auto ptr = reinterpret_cast(value); + return CreateRandomOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_BucketizeOptions: { + auto ptr = reinterpret_cast(value); + return CreateBucketizeOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_GeluOptions: { + auto ptr = reinterpret_cast(value); + return CreateGeluOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_DynamicUpdateSliceOptions: { + auto ptr = reinterpret_cast(value); + return CreateDynamicUpdateSliceOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_UnsortedSegmentProdOptions: { + auto ptr = reinterpret_cast(value); + return CreateUnsortedSegmentProdOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_UnsortedSegmentMaxOptions: { + auto ptr = reinterpret_cast(value); + return CreateUnsortedSegmentMaxOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_UnsortedSegmentMinOptions: { + auto ptr = reinterpret_cast(value); + return CreateUnsortedSegmentMinOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_UnsortedSegmentSumOptions: { + auto ptr = reinterpret_cast(value); + return CreateUnsortedSegmentSumOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_ATan2Options: { + auto ptr = reinterpret_cast(value); + return CreateATan2Options(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SignOptions: { + auto ptr = reinterpret_cast(value); + return CreateSignOptions(_fbb, ptr, _rehasher).Union(); + } + default: return 0; + } +} + +inline BuiltinOptionsUnion::BuiltinOptionsUnion(const BuiltinOptionsUnion &u) : type(u.type), value(nullptr) { + switch (type) { + case BuiltinOptions_Conv2DOptions: { + value = new tflite::Conv2DOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_DepthwiseConv2DOptions: { + value = new tflite::DepthwiseConv2DOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ConcatEmbeddingsOptions: { + value = new tflite::ConcatEmbeddingsOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LSHProjectionOptions: { + value = new tflite::LSHProjectionOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_Pool2DOptions: { + value = new tflite::Pool2DOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SVDFOptions: { + value = new tflite::SVDFOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_RNNOptions: { + value = new tflite::RNNOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_FullyConnectedOptions: { + value = new tflite::FullyConnectedOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SoftmaxOptions: { + value = new tflite::SoftmaxOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ConcatenationOptions: { + value = new tflite::ConcatenationOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_AddOptions: { + value = new tflite::AddOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_L2NormOptions: { + value = new tflite::L2NormOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LocalResponseNormalizationOptions: { + value = new tflite::LocalResponseNormalizationOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LSTMOptions: { + value = new tflite::LSTMOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ResizeBilinearOptions: { + value = new tflite::ResizeBilinearOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_CallOptions: { + value = new tflite::CallOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ReshapeOptions: { + value = new tflite::ReshapeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SkipGramOptions: { + value = new tflite::SkipGramOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SpaceToDepthOptions: { + value = new tflite::SpaceToDepthOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_EmbeddingLookupSparseOptions: { + value = new tflite::EmbeddingLookupSparseOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_MulOptions: { + value = new tflite::MulOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_PadOptions: { + value = new tflite::PadOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_GatherOptions: { + value = new tflite::GatherOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_BatchToSpaceNDOptions: { + value = new tflite::BatchToSpaceNDOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SpaceToBatchNDOptions: { + value = new tflite::SpaceToBatchNDOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_TransposeOptions: { + value = new tflite::TransposeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ReducerOptions: { + value = new tflite::ReducerOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SubOptions: { + value = new tflite::SubOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_DivOptions: { + value = new tflite::DivOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SqueezeOptions: { + value = new tflite::SqueezeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SequenceRNNOptions: { + value = new tflite::SequenceRNNOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_StridedSliceOptions: { + value = new tflite::StridedSliceOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ExpOptions: { + value = new tflite::ExpOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_TopKV2Options: { + value = new tflite::TopKV2OptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SplitOptions: { + value = new tflite::SplitOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LogSoftmaxOptions: { + value = new tflite::LogSoftmaxOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_CastOptions: { + value = new tflite::CastOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_DequantizeOptions: { + value = new tflite::DequantizeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_MaximumMinimumOptions: { + value = new tflite::MaximumMinimumOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ArgMaxOptions: { + value = new tflite::ArgMaxOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LessOptions: { + value = new tflite::LessOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_NegOptions: { + value = new tflite::NegOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_PadV2Options: { + value = new tflite::PadV2OptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_GreaterOptions: { + value = new tflite::GreaterOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_GreaterEqualOptions: { + value = new tflite::GreaterEqualOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LessEqualOptions: { + value = new tflite::LessEqualOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SelectOptions: { + value = new tflite::SelectOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SliceOptions: { + value = new tflite::SliceOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_TransposeConvOptions: { + value = new tflite::TransposeConvOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SparseToDenseOptions: { + value = new tflite::SparseToDenseOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_TileOptions: { + value = new tflite::TileOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ExpandDimsOptions: { + value = new tflite::ExpandDimsOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_EqualOptions: { + value = new tflite::EqualOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_NotEqualOptions: { + value = new tflite::NotEqualOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ShapeOptions: { + value = new tflite::ShapeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_PowOptions: { + value = new tflite::PowOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ArgMinOptions: { + value = new tflite::ArgMinOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_FakeQuantOptions: { + value = new tflite::FakeQuantOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_PackOptions: { + value = new tflite::PackOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LogicalOrOptions: { + value = new tflite::LogicalOrOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_OneHotOptions: { + value = new tflite::OneHotOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LogicalAndOptions: { + value = new tflite::LogicalAndOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LogicalNotOptions: { + value = new tflite::LogicalNotOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_UnpackOptions: { + value = new tflite::UnpackOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_FloorDivOptions: { + value = new tflite::FloorDivOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SquareOptions: { + value = new tflite::SquareOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ZerosLikeOptions: { + value = new tflite::ZerosLikeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_FillOptions: { + value = new tflite::FillOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_BidirectionalSequenceLSTMOptions: { + value = new tflite::BidirectionalSequenceLSTMOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_BidirectionalSequenceRNNOptions: { + value = new tflite::BidirectionalSequenceRNNOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_UnidirectionalSequenceLSTMOptions: { + value = new tflite::UnidirectionalSequenceLSTMOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_FloorModOptions: { + value = new tflite::FloorModOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_RangeOptions: { + value = new tflite::RangeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ResizeNearestNeighborOptions: { + value = new tflite::ResizeNearestNeighborOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_LeakyReluOptions: { + value = new tflite::LeakyReluOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SquaredDifferenceOptions: { + value = new tflite::SquaredDifferenceOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_MirrorPadOptions: { + value = new tflite::MirrorPadOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_AbsOptions: { + value = new tflite::AbsOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SplitVOptions: { + value = new tflite::SplitVOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_UniqueOptions: { + value = new tflite::UniqueOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ReverseV2Options: { + value = new tflite::ReverseV2OptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_AddNOptions: { + value = new tflite::AddNOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_GatherNdOptions: { + value = new tflite::GatherNdOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_CosOptions: { + value = new tflite::CosOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_WhereOptions: { + value = new tflite::WhereOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_RankOptions: { + value = new tflite::RankOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ReverseSequenceOptions: { + value = new tflite::ReverseSequenceOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_MatrixDiagOptions: { + value = new tflite::MatrixDiagOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_QuantizeOptions: { + value = new tflite::QuantizeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_MatrixSetDiagOptions: { + value = new tflite::MatrixSetDiagOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_HardSwishOptions: { + value = new tflite::HardSwishOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_IfOptions: { + value = new tflite::IfOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_WhileOptions: { + value = new tflite::WhileOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_DepthToSpaceOptions: { + value = new tflite::DepthToSpaceOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_NonMaxSuppressionV4Options: { + value = new tflite::NonMaxSuppressionV4OptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_NonMaxSuppressionV5Options: { + value = new tflite::NonMaxSuppressionV5OptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ScatterNdOptions: { + value = new tflite::ScatterNdOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SelectV2Options: { + value = new tflite::SelectV2OptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_DensifyOptions: { + value = new tflite::DensifyOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SegmentSumOptions: { + value = new tflite::SegmentSumOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_BatchMatMulOptions: { + value = new tflite::BatchMatMulOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_CumsumOptions: { + value = new tflite::CumsumOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_CallOnceOptions: { + value = new tflite::CallOnceOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_BroadcastToOptions: { + value = new tflite::BroadcastToOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_Rfft2dOptions: { + value = new tflite::Rfft2dOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_Conv3DOptions: { + value = new tflite::Conv3DOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_HashtableOptions: { + value = new tflite::HashtableOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_HashtableFindOptions: { + value = new tflite::HashtableFindOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_HashtableImportOptions: { + value = new tflite::HashtableImportOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_HashtableSizeOptions: { + value = new tflite::HashtableSizeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_VarHandleOptions: { + value = new tflite::VarHandleOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ReadVariableOptions: { + value = new tflite::ReadVariableOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_AssignVariableOptions: { + value = new tflite::AssignVariableOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_RandomOptions: { + value = new tflite::RandomOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_BucketizeOptions: { + value = new tflite::BucketizeOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_GeluOptions: { + value = new tflite::GeluOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_DynamicUpdateSliceOptions: { + value = new tflite::DynamicUpdateSliceOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_UnsortedSegmentProdOptions: { + value = new tflite::UnsortedSegmentProdOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_UnsortedSegmentMaxOptions: { + value = new tflite::UnsortedSegmentMaxOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_UnsortedSegmentMinOptions: { + value = new tflite::UnsortedSegmentMinOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_UnsortedSegmentSumOptions: { + value = new tflite::UnsortedSegmentSumOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_ATan2Options: { + value = new tflite::ATan2OptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SignOptions: { + value = new tflite::SignOptionsT(*reinterpret_cast(u.value)); + break; + } + default: + break; + } +} + +inline void BuiltinOptionsUnion::Reset() { + switch (type) { + case BuiltinOptions_Conv2DOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_DepthwiseConv2DOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ConcatEmbeddingsOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LSHProjectionOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_Pool2DOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SVDFOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_RNNOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_FullyConnectedOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SoftmaxOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ConcatenationOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_AddOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_L2NormOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LocalResponseNormalizationOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LSTMOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ResizeBilinearOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_CallOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ReshapeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SkipGramOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SpaceToDepthOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_EmbeddingLookupSparseOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_MulOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_PadOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_GatherOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_BatchToSpaceNDOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SpaceToBatchNDOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_TransposeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ReducerOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SubOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_DivOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SqueezeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SequenceRNNOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_StridedSliceOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ExpOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_TopKV2Options: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SplitOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LogSoftmaxOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_CastOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_DequantizeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_MaximumMinimumOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ArgMaxOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LessOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_NegOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_PadV2Options: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_GreaterOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_GreaterEqualOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LessEqualOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SelectOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SliceOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_TransposeConvOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SparseToDenseOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_TileOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ExpandDimsOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_EqualOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_NotEqualOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ShapeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_PowOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ArgMinOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_FakeQuantOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_PackOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LogicalOrOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_OneHotOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LogicalAndOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LogicalNotOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_UnpackOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_FloorDivOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SquareOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ZerosLikeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_FillOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_BidirectionalSequenceLSTMOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_BidirectionalSequenceRNNOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_UnidirectionalSequenceLSTMOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_FloorModOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_RangeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ResizeNearestNeighborOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_LeakyReluOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SquaredDifferenceOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_MirrorPadOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_AbsOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SplitVOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_UniqueOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ReverseV2Options: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_AddNOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_GatherNdOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_CosOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_WhereOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_RankOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ReverseSequenceOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_MatrixDiagOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_QuantizeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_MatrixSetDiagOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_HardSwishOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_IfOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_WhileOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_DepthToSpaceOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_NonMaxSuppressionV4Options: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_NonMaxSuppressionV5Options: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ScatterNdOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SelectV2Options: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_DensifyOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SegmentSumOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_BatchMatMulOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_CumsumOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_CallOnceOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_BroadcastToOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_Rfft2dOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_Conv3DOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_HashtableOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_HashtableFindOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_HashtableImportOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_HashtableSizeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_VarHandleOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ReadVariableOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_AssignVariableOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_RandomOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_BucketizeOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_GeluOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_DynamicUpdateSliceOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_UnsortedSegmentProdOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_UnsortedSegmentMaxOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_UnsortedSegmentMinOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_UnsortedSegmentSumOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_ATan2Options: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SignOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + default: break; + } + value = nullptr; + type = BuiltinOptions_NONE; +} + +inline const tflite::Model *GetModel(const void *buf) { + return flatbuffers::GetRoot(buf); +} + +inline const tflite::Model *GetSizePrefixedModel(const void *buf) { + return flatbuffers::GetSizePrefixedRoot(buf); +} + +inline const char *ModelIdentifier() { + return "TFL3"; +} + +inline bool ModelBufferHasIdentifier(const void *buf) { + return flatbuffers::BufferHasIdentifier( + buf, ModelIdentifier()); +} + +inline bool SizePrefixedModelBufferHasIdentifier(const void *buf) { + return flatbuffers::BufferHasIdentifier( + buf, ModelIdentifier(), true); +} + +inline bool VerifyModelBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(ModelIdentifier()); +} + +inline bool VerifySizePrefixedModelBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(ModelIdentifier()); +} + +inline const char *ModelExtension() { + return "tflite"; +} + +inline void FinishModelBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.Finish(root, ModelIdentifier()); +} + +inline void FinishSizePrefixedModelBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root, ModelIdentifier()); +} + +inline std::unique_ptr UnPackModel( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr(GetModel(buf)->UnPack(res)); +} + +inline std::unique_ptr UnPackSizePrefixedModel( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr(GetSizePrefixedModel(buf)->UnPack(res)); +} + +} // namespace tflite + +#endif // FLATBUFFERS_GENERATED_SCHEMA_TFLITE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_utils.cpp b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_utils.cpp new file mode 100644 index 000000000..fc19290b8 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_utils.cpp @@ -0,0 +1,62 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/schema/schema_utils.h" + +#include + +#include "tensorflow/lite/kernels/internal/compatibility.h" + +namespace tflite { + +// The following GetBuiltinCode methods are the utility methods for reading +// builtin operatore code, ensuring compatibility issues between v3 and v3a +// schema. Always the maximum value of the two fields always will be the correct +// value as follows: +// +// - Supporting schema version v3 models +// +// The `builtin_code` field is not available in the v3 models. Flatbuffer +// library will feed zero value, which is the default value in the v3a schema. +// The actual builtin operatore code value will exist in the +// `deprecated_builtin_code` field. At the same time, it implies that +// `deprecated_builtin_code` >= `builtin_code` and the maximum value of the two +// fields will be same with `deprecated_builtin_code'. +// +// - Supporting builtin operator codes beyonds 127 +// +// New builtin operators, whose operator code is larger than 127, can not be +// assigned to the `deprecated_builtin_code` field. In such cases, the +// value of the `builtin_code` field should be used for the builtin operator +// code. In the case, the maximum value of the two fields will be the value of +// the `builtin_code` as the right value. + +BuiltinOperator GetBuiltinCode(const OperatorCode* op_code) { + // Caller should guarantee that the given argument value is not a nullptr. + TFLITE_DCHECK(op_code != nullptr); + + return std::max( + op_code->builtin_code(), + static_cast(op_code->deprecated_builtin_code())); +} + +BuiltinOperator GetBuiltinCode(const OperatorCodeT* op_code) { + // Caller should guarantee that the given argument value is not a nullptr. + TFLITE_DCHECK(op_code != nullptr); + + return std::max(op_code->builtin_code, static_cast( + op_code->deprecated_builtin_code)); +} + +} // namespace tflite diff --git a/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_utils.h b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_utils.h new file mode 100644 index 000000000..4d9142655 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/tensorflow/lite/schema/schema_utils.h @@ -0,0 +1,33 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_SCHEMA_SCHEMA_UTILS_H_ +#define TENSORFLOW_LITE_SCHEMA_SCHEMA_UTILS_H_ + +#include "third_party/flatbuffers/include/flatbuffers/flatbuffers.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +// The following methods are introduced to resolve op builtin code shortage +// problem. The new builtin operator will be assigned to the extended builtin +// code field in the flatbuffer schema. Those methods helps to hide builtin code +// details. +BuiltinOperator GetBuiltinCode(const OperatorCode *op_code); + +BuiltinOperator GetBuiltinCode(const OperatorCodeT *op_code); + +} // namespace tflite + +#endif // TENSORFLOW_LITE_SCHEMA_SCHEMA_UTILS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/LICENSE.txt b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/allocator.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/allocator.h new file mode 100644 index 000000000..50a46734a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/allocator.h @@ -0,0 +1,68 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_ALLOCATOR_H_ +#define FLATBUFFERS_ALLOCATOR_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" + +namespace flatbuffers { + +// Allocator interface. This is flatbuffers-specific and meant only for +// `vector_downward` usage. +class Allocator { + public: + virtual ~Allocator() {} + + // Allocate `size` bytes of memory. + virtual uint8_t *allocate(size_t size) = 0; + + // Deallocate `size` bytes of memory at `p` allocated by this allocator. + virtual void deallocate(uint8_t *p, size_t size) = 0; + + // Reallocate `new_size` bytes of memory, replacing the old region of size + // `old_size` at `p`. In contrast to a normal realloc, this grows downwards, + // and is intended specifcally for `vector_downward` use. + // `in_use_back` and `in_use_front` indicate how much of `old_size` is + // actually in use at each end, and needs to be copied. + virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size, + size_t new_size, size_t in_use_back, + size_t in_use_front) { + FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows + uint8_t *new_p = allocate(new_size); + memcpy_downward(old_p, old_size, new_p, new_size, in_use_back, + in_use_front); + deallocate(old_p, old_size); + return new_p; + } + + protected: + // Called by `reallocate_downward` to copy memory from `old_p` of `old_size` + // to `new_p` of `new_size`. Only memory of size `in_use_front` and + // `in_use_back` will be copied from the front and back of the old memory + // allocation. + void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p, + size_t new_size, size_t in_use_back, + size_t in_use_front) { + memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back, + in_use_back); + memcpy(new_p, old_p, in_use_front); + } +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_ALLOCATOR_H_ \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/array.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/array.h new file mode 100644 index 000000000..17e377565 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/array.h @@ -0,0 +1,243 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_ARRAY_H_ +#define FLATBUFFERS_ARRAY_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/stl_emulation.h" +#include "third_party/flatbuffers/include/flatbuffers/vector.h" + +namespace flatbuffers { + +// This is used as a helper type for accessing arrays. +template class Array { + // Array can carry only POD data types (scalars or structs). + typedef typename flatbuffers::bool_constant::value> + scalar_tag; + typedef + typename flatbuffers::conditional::type + IndirectHelperType; + + public: + typedef uint16_t size_type; + typedef typename IndirectHelper::return_type return_type; + typedef VectorIterator const_iterator; + typedef VectorReverseIterator const_reverse_iterator; + + // If T is a LE-scalar or a struct (!scalar_tag::value). + static FLATBUFFERS_CONSTEXPR bool is_span_observable = + (scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1)) || + !scalar_tag::value; + + FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; } + + return_type Get(uoffset_t i) const { + FLATBUFFERS_ASSERT(i < size()); + return IndirectHelper::Read(Data(), i); + } + + return_type operator[](uoffset_t i) const { return Get(i); } + + // If this is a Vector of enums, T will be its storage type, not the enum + // type. This function makes it convenient to retrieve value with enum + // type E. + template E GetEnum(uoffset_t i) const { + return static_cast(Get(i)); + } + + const_iterator begin() const { return const_iterator(Data(), 0); } + const_iterator end() const { return const_iterator(Data(), size()); } + + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + const_iterator cbegin() const { return begin(); } + const_iterator cend() const { return end(); } + + const_reverse_iterator crbegin() const { return rbegin(); } + const_reverse_iterator crend() const { return rend(); } + + // Get a mutable pointer to elements inside this array. + // This method used to mutate arrays of structs followed by a @p Mutate + // operation. For primitive types use @p Mutate directly. + // @warning Assignments and reads to/from the dereferenced pointer are not + // automatically converted to the correct endianness. + typename flatbuffers::conditional::type + GetMutablePointer(uoffset_t i) const { + FLATBUFFERS_ASSERT(i < size()); + return const_cast(&data()[i]); + } + + // Change elements if you have a non-const pointer to this object. + void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); } + + // The raw data in little endian format. Use with care. + const uint8_t *Data() const { return data_; } + + uint8_t *Data() { return data_; } + + // Similarly, but typed, much like std::vector::data + const T *data() const { return reinterpret_cast(Data()); } + T *data() { return reinterpret_cast(Data()); } + + // Copy data from a span with endian conversion. + // If this Array and the span overlap, the behavior is undefined. + void CopyFromSpan(flatbuffers::span src) { + const auto p1 = reinterpret_cast(src.data()); + const auto p2 = Data(); + FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) && + !(p2 >= p1 && p2 < (p1 + length))); + (void)p1; + (void)p2; + CopyFromSpanImpl(flatbuffers::bool_constant(), src); + } + + protected: + void MutateImpl(flatbuffers::true_type, uoffset_t i, const T &val) { + FLATBUFFERS_ASSERT(i < size()); + WriteScalar(data() + i, val); + } + + void MutateImpl(flatbuffers::false_type, uoffset_t i, const T &val) { + *(GetMutablePointer(i)) = val; + } + + void CopyFromSpanImpl(flatbuffers::true_type, + flatbuffers::span src) { + // Use std::memcpy() instead of std::copy() to avoid performance degradation + // due to aliasing if T is char or unsigned char. + // The size is known at compile time, so memcpy would be inlined. + std::memcpy(data(), src.data(), length * sizeof(T)); + } + + // Copy data from flatbuffers::span with endian conversion. + void CopyFromSpanImpl(flatbuffers::false_type, + flatbuffers::span src) { + for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); } + } + + // This class is only used to access pre-existing data. Don't ever + // try to construct these manually. + // 'constexpr' allows us to use 'size()' at compile time. + // @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on + // a constructor. +#if defined(__cpp_constexpr) + constexpr Array(); +#else + Array(); +#endif + + uint8_t data_[length * sizeof(T)]; + + private: + // This class is a pointer. Copying will therefore create an invalid object. + // Private and unimplemented copy constructor. + Array(const Array &); + Array &operator=(const Array &); +}; + +// Specialization for Array[struct] with access using Offset pointer. +// This specialization used by idl_gen_text.cpp. +template class Array, length> { + static_assert(flatbuffers::is_same::value, "unexpected type T"); + + public: + typedef const void *return_type; + + const uint8_t *Data() const { return data_; } + + // Make idl_gen_text.cpp::PrintContainer happy. + return_type operator[](uoffset_t) const { + FLATBUFFERS_ASSERT(false); + return nullptr; + } + + private: + // This class is only used to access pre-existing data. + Array(); + Array(const Array &); + Array &operator=(const Array &); + + uint8_t data_[1]; +}; + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span(Array &arr) + FLATBUFFERS_NOEXCEPT { + static_assert( + Array::is_span_observable, + "wrong type U, only plain struct, LE-scalar, or byte types are allowed"); + return span(arr.data(), N); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span( + const Array &arr) FLATBUFFERS_NOEXCEPT { + static_assert( + Array::is_span_observable, + "wrong type U, only plain struct, LE-scalar, or byte types are allowed"); + return span(arr.data(), N); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span +make_bytes_span(Array &arr) FLATBUFFERS_NOEXCEPT { + static_assert(Array::is_span_observable, + "internal error, Array might hold only scalars or structs"); + return span(arr.Data(), sizeof(U) * N); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span +make_bytes_span(const Array &arr) FLATBUFFERS_NOEXCEPT { + static_assert(Array::is_span_observable, + "internal error, Array might hold only scalars or structs"); + return span(arr.Data(), sizeof(U) * N); +} + +// Cast a raw T[length] to a raw flatbuffers::Array +// without endian conversion. Use with care. +// TODO: move these Cast-methods to `internal` namespace. +template +Array &CastToArray(T (&arr)[length]) { + return *reinterpret_cast *>(arr); +} + +template +const Array &CastToArray(const T (&arr)[length]) { + return *reinterpret_cast *>(arr); +} + +template +Array &CastToArrayOfEnum(T (&arr)[length]) { + static_assert(sizeof(E) == sizeof(T), "invalid enum type E"); + return *reinterpret_cast *>(arr); +} + +template +const Array &CastToArrayOfEnum(const T (&arr)[length]) { + static_assert(sizeof(E) == sizeof(T), "invalid enum type E"); + return *reinterpret_cast *>(arr); +} + +} // namespace flatbuffers + +#endif // FLATBUFFERS_ARRAY_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/base.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/base.h new file mode 100644 index 000000000..525a8e5ce --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/base.h @@ -0,0 +1,496 @@ +#ifndef FLATBUFFERS_BASE_H_ +#define FLATBUFFERS_BASE_H_ + +// For TFLM, we always want FLATBUFFERS_LOCALE_INDEPENDENT to be defined as 0. +// We could achieve this by adding -DFLATBUFFERS_LOCALE_INDEPENDENT=0 to the +// TFLM Makefile. However, for (at least) the Arduino, adding additional build +// flags during the compilation can be a bit awkward. As such, we have instead +// made a decision to change the default to be FLATBUFFERS_LOCALE_INDEPENDENT=0 +// for TFLM to make it easier for external IDE integration. +#ifndef FLATBUFFERS_LOCALE_INDEPENDENT +#define FLATBUFFERS_LOCALE_INDEPENDENT 0 +#endif + +// clang-format off + +// If activate should be declared and included first. +#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \ + defined(_MSC_VER) && defined(_DEBUG) + // The _CRTDBG_MAP_ALLOC inside will replace + // calloc/free (etc) to its debug version using #define directives. + #define _CRTDBG_MAP_ALLOC + #include + #include + // Replace operator new by trace-enabled version. + #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) + #define new DEBUG_NEW +#endif + +#if !defined(FLATBUFFERS_ASSERT) +#include +#define FLATBUFFERS_ASSERT assert +#elif defined(FLATBUFFERS_ASSERT_INCLUDE) +// Include file with forward declaration +#include FLATBUFFERS_ASSERT_INCLUDE +#endif + +#ifndef ARDUINO +#include +#endif + +#include +#include +#include + +#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) + #include +#else + #include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if defined(__unix__) && !defined(FLATBUFFERS_LOCALE_INDEPENDENT) + #include +#endif + +#ifdef __ANDROID__ + #include +#endif + +#if defined(__ICCARM__) +#include +#endif + +// Note the __clang__ check is needed, because clang presents itself +// as an older GNUC compiler (4.2). +// Clang 3.3 and later implement all of the ISO C++ 2011 standard. +// Clang 3.4 and later implement all of the ISO C++ 2014 standard. +// http://clang.llvm.org/cxx_status.html + +// Note the MSVC value '__cplusplus' may be incorrect: +// The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L, +// indicating (erroneously!) that the compiler conformed to the C++98 Standard. +// This value should be correct starting from MSVC2017-15.7-Preview-3. +// The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set. +// Workaround (for details see MSDN): +// Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility. +// The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch. + +#if defined(__GNUC__) && !defined(__clang__) + #define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#else + #define FLATBUFFERS_GCC 0 +#endif + +#if defined(__clang__) + #define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#else + #define FLATBUFFERS_CLANG 0 +#endif + +/// @cond FLATBUFFERS_INTERNAL +#if __cplusplus <= 199711L && \ + (!defined(_MSC_VER) || _MSC_VER < 1600) && \ + (!defined(__GNUC__) || \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400)) + #error A C++11 compatible compiler with support for the auto typing is \ + required for FlatBuffers. + #error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ +#endif + +#if !defined(__clang__) && \ + defined(__GNUC__) && \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600) + // Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr + // and constexpr keywords. Note the __clang__ check is needed, because clang + // presents itself as an older GNUC compiler. + #ifndef nullptr_t + const class nullptr_t { + public: + template inline operator T*() const { return 0; } + private: + void operator&() const; + } nullptr = {}; + #endif + #ifndef constexpr + #define constexpr const + #endif +#endif + +// The wire format uses a little endian encoding (since that's efficient for +// the common platforms). +#if defined(__s390x__) + #define FLATBUFFERS_LITTLEENDIAN 0 +#endif // __s390x__ +#if !defined(FLATBUFFERS_LITTLEENDIAN) + #if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__) + #if (defined(__BIG_ENDIAN__) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + #define FLATBUFFERS_LITTLEENDIAN 0 + #else + #define FLATBUFFERS_LITTLEENDIAN 1 + #endif // __BIG_ENDIAN__ + #elif defined(_MSC_VER) + #if defined(_M_PPC) + #define FLATBUFFERS_LITTLEENDIAN 0 + #else + #define FLATBUFFERS_LITTLEENDIAN 1 + #endif + #else + #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN. + #endif +#endif // !defined(FLATBUFFERS_LITTLEENDIAN) + +#define FLATBUFFERS_VERSION_MAJOR 2 +#define FLATBUFFERS_VERSION_MINOR 0 +#define FLATBUFFERS_VERSION_REVISION 6 +#define FLATBUFFERS_STRING_EXPAND(X) #X +#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) +namespace flatbuffers { + // Returns version as string "MAJOR.MINOR.REVISION". + const char* FLATBUFFERS_VERSION(); +} + +#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \ + (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \ + defined(__clang__) + #define FLATBUFFERS_FINAL_CLASS final + #define FLATBUFFERS_OVERRIDE override + #define FLATBUFFERS_EXPLICIT_CPP11 explicit + #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t +#else + #define FLATBUFFERS_FINAL_CLASS + #define FLATBUFFERS_OVERRIDE + #define FLATBUFFERS_EXPLICIT_CPP11 + #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE +#endif + +#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ + (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ + (defined(__cpp_constexpr) && __cpp_constexpr >= 200704) + #define FLATBUFFERS_CONSTEXPR constexpr + #define FLATBUFFERS_CONSTEXPR_CPP11 constexpr + #define FLATBUFFERS_CONSTEXPR_DEFINED +#else + #define FLATBUFFERS_CONSTEXPR const + #define FLATBUFFERS_CONSTEXPR_CPP11 +#endif + +#if (defined(__cplusplus) && __cplusplus >= 201402L) || \ + (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) + #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR_CPP11 +#else + #define FLATBUFFERS_CONSTEXPR_CPP14 +#endif + +#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ + (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \ + defined(__clang__) + #define FLATBUFFERS_NOEXCEPT noexcept +#else + #define FLATBUFFERS_NOEXCEPT +#endif + +// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to +// private, so be sure to put it at the end or reset access mode explicitly. +#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \ + (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \ + defined(__clang__) + #define FLATBUFFERS_DELETE_FUNC(func) func = delete +#else + #define FLATBUFFERS_DELETE_FUNC(func) private: func +#endif + +#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ + (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \ + defined(__clang__) + #define FLATBUFFERS_DEFAULT_DECLARATION +#endif + +// Check if we can use template aliases +// Not possible if Microsoft Compiler before 2012 +// Possible is the language feature __cpp_alias_templates is defined well +// Or possible if the C++ std is C+11 or newer +#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \ + || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \ + || (defined(__cplusplus) && __cplusplus >= 201103L) + #define FLATBUFFERS_TEMPLATES_ALIASES +#endif + +#ifndef FLATBUFFERS_HAS_STRING_VIEW + // Only provide flatbuffers::string_view if __has_include can be used + // to detect a header that provides an implementation + #if defined(__has_include) + // Check for std::string_view (in c++17) + #if __has_include() && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17)) + #include + namespace flatbuffers { + typedef std::string_view string_view; + } + #define FLATBUFFERS_HAS_STRING_VIEW 1 + // Check for std::experimental::string_view (in c++14, compiler-dependent) + #elif __has_include() && (__cplusplus >= 201411) + #include + namespace flatbuffers { + typedef std::experimental::string_view string_view; + } + #define FLATBUFFERS_HAS_STRING_VIEW 1 + // Check for absl::string_view + #elif __has_include("absl/strings/string_view.h") + #include "absl/strings/string_view.h" + namespace flatbuffers { + typedef absl::string_view string_view; + } + #define FLATBUFFERS_HAS_STRING_VIEW 1 + #endif + #endif // __has_include +#endif // !FLATBUFFERS_HAS_STRING_VIEW + +#ifndef FLATBUFFERS_GENERAL_HEAP_ALLOC_OK + // Allow heap allocations to be used + #define FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 1 +#endif // !FLATBUFFERS_GENERAL_HEAP_ALLOC_OK + +#ifndef FLATBUFFERS_HAS_NEW_STRTOD + // Modern (C++11) strtod and strtof functions are available for use. + // 1) nan/inf strings as argument of strtod; + // 2) hex-float as argument of strtod/strtof. + #if (defined(_MSC_VER) && _MSC_VER >= 1900) || \ + (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \ + (defined(__clang__)) + #define FLATBUFFERS_HAS_NEW_STRTOD 1 + #endif +#endif // !FLATBUFFERS_HAS_NEW_STRTOD + +#ifndef FLATBUFFERS_LOCALE_INDEPENDENT + // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, + // strtoull_l}. + #if (defined(_MSC_VER) && _MSC_VER >= 1800) || \ + (defined(__ANDROID_API__) && __ANDROID_API__>= 21) || \ + (defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)) && \ + (!defined(__Fuchsia__) && !defined(__ANDROID_API__)) + #define FLATBUFFERS_LOCALE_INDEPENDENT 1 + #else + #define FLATBUFFERS_LOCALE_INDEPENDENT 0 + #endif +#endif // !FLATBUFFERS_LOCALE_INDEPENDENT + +// Suppress Undefined Behavior Sanitizer (recoverable only). Usage: +// - __supress_ubsan__("undefined") +// - __supress_ubsan__("signed-integer-overflow") +#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7)) + #define __supress_ubsan__(type) __attribute__((no_sanitize(type))) +#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409) + #define __supress_ubsan__(type) __attribute__((no_sanitize_undefined)) +#else + #define __supress_ubsan__(type) +#endif + +// This is constexpr function used for checking compile-time constants. +// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`. +template FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) { + return !!t; +} + +// Enable C++ attribute [[]] if std:c++17 or higher. +#if ((__cplusplus >= 201703L) \ + || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))) + // All attributes unknown to an implementation are ignored without causing an error. + #define FLATBUFFERS_ATTRIBUTE(attr) attr + + #define FLATBUFFERS_FALLTHROUGH() [[fallthrough]] +#else + #define FLATBUFFERS_ATTRIBUTE(attr) + + #if FLATBUFFERS_CLANG >= 30800 + #define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]] + #elif FLATBUFFERS_GCC >= 70300 + #define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]] + #else + #define FLATBUFFERS_FALLTHROUGH() + #endif +#endif + +/// @endcond + +/// @file +namespace flatbuffers { + +/// @cond FLATBUFFERS_INTERNAL +// Our default offset / size type, 32bit on purpose on 64bit systems. +// Also, using a consistent offset type maintains compatibility of serialized +// offset values between 32bit and 64bit systems. +typedef uint32_t uoffset_t; + +// Signed offsets for references that can go in both directions. +typedef int32_t soffset_t; + +// Offset/index used in v-tables, can be changed to uint8_t in +// format forks to save a bit of space if desired. +typedef uint16_t voffset_t; + +typedef uintmax_t largest_scalar_t; + +// In 32bits, this evaluates to 2GB - 1 +#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1) + +// The minimum size buffer that can be a valid flatbuffer. +// Includes the offset to the root table (uoffset_t), the offset to the vtable +// of the root table (soffset_t), the size of the vtable (uint16_t), and the +// size of the referring table (uint16_t). +#define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(uoffset_t) + sizeof(soffset_t) + \ + sizeof(uint16_t) + sizeof(uint16_t) + +// We support aligning the contents of buffers up to this size. +#ifndef FLATBUFFERS_MAX_ALIGNMENT + #define FLATBUFFERS_MAX_ALIGNMENT 32 +#endif + +/// @brief The length of a FlatBuffer file header. +static const size_t kFileIdentifierLength = 4; + +inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) { + return (min_align <= align) && (align <= (FLATBUFFERS_MAX_ALIGNMENT)) && + (align & (align - 1)) == 0; // must be power of 2 +} + +#if defined(_MSC_VER) + #pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized + #pragma warning(push) + #pragma warning(disable: 4127) // C4127: conditional expression is constant +#endif + +template T EndianSwap(T t) { + #if defined(_MSC_VER) + #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort + #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong + #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64 + #elif defined(__ICCARM__) + #define FLATBUFFERS_BYTESWAP16 __REV16 + #define FLATBUFFERS_BYTESWAP32 __REV + #define FLATBUFFERS_BYTESWAP64(x) \ + ((__REV(static_cast(x >> 32U))) | (static_cast(__REV(static_cast(x)))) << 32U) + #else + #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__) + // __builtin_bswap16 was missing prior to GCC 4.8. + #define FLATBUFFERS_BYTESWAP16(x) \ + static_cast(__builtin_bswap32(static_cast(x) << 16)) + #else + #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16 + #endif + #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32 + #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64 + #endif + if (sizeof(T) == 1) { // Compile-time if-then's. + return t; + } else if (sizeof(T) == 2) { + union { T t; uint16_t i; } u = { t }; + u.i = FLATBUFFERS_BYTESWAP16(u.i); + return u.t; + } else if (sizeof(T) == 4) { + union { T t; uint32_t i; } u = { t }; + u.i = FLATBUFFERS_BYTESWAP32(u.i); + return u.t; + } else if (sizeof(T) == 8) { + union { T t; uint64_t i; } u = { t }; + u.i = FLATBUFFERS_BYTESWAP64(u.i); + return u.t; + } else { + FLATBUFFERS_ASSERT(0); + return t; + } +} + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + + +template T EndianScalar(T t) { + #if FLATBUFFERS_LITTLEENDIAN + return t; + #else + return EndianSwap(t); + #endif +} + +template +// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. +__supress_ubsan__("alignment") +T ReadScalar(const void *p) { + return EndianScalar(*reinterpret_cast(p)); +} + +// See https://github.com/google/flatbuffers/issues/5950 + +#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + +template +// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. +__supress_ubsan__("alignment") +void WriteScalar(void *p, T t) { + *reinterpret_cast(p) = EndianScalar(t); +} + +template struct Offset; +template __supress_ubsan__("alignment") void WriteScalar(void *p, Offset t) { + *reinterpret_cast(p) = EndianScalar(t.o); +} + +#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) + #pragma GCC diagnostic pop +#endif + +// Computes how many bytes you'd have to pad to be able to write an +// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in +// memory). +__supress_ubsan__("unsigned-integer-overflow") +inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) { + return ((~buf_size) + 1) & (scalar_size - 1); +} + +// Generic 'operator==' with conditional specialisations. +// T e - new value of a scalar field. +// T def - default of scalar (is known at compile-time). +template inline bool IsTheSameAs(T e, T def) { return e == def; } + +#if defined(FLATBUFFERS_NAN_DEFAULTS) && \ + defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) +// Like `operator==(e, def)` with weak NaN if T=(float|double). +template inline bool IsFloatTheSameAs(T e, T def) { + return (e == def) || ((def != def) && (e != e)); +} +template<> inline bool IsTheSameAs(float e, float def) { + return IsFloatTheSameAs(e, def); +} +template<> inline bool IsTheSameAs(double e, double def) { + return IsFloatTheSameAs(e, def); +} +#endif + +// Check 'v' is out of closed range [low; high]. +// Workaround for GCC warning [-Werror=type-limits]: +// comparison is always true due to limited range of data type. +template +inline bool IsOutRange(const T &v, const T &low, const T &high) { + return (v < low) || (high < v); +} + +// Check 'v' is in closed range [low; high]. +template +inline bool IsInRange(const T &v, const T &low, const T &high) { + return !IsOutRange(v, low, high); +} + +} // namespace flatbuffers +#endif // FLATBUFFERS_BASE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/buffer.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/buffer.h new file mode 100644 index 000000000..c0b79a858 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/buffer.h @@ -0,0 +1,142 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_BUFFER_H_ +#define FLATBUFFERS_BUFFER_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" + +namespace flatbuffers { + +// Wrapper for uoffset_t to allow safe template specialization. +// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset). +template struct Offset { + uoffset_t o; + Offset() : o(0) {} + Offset(uoffset_t _o) : o(_o) {} + Offset Union() const { return Offset(o); } + bool IsNull() const { return !o; } +}; + +inline void EndianCheck() { + int endiantest = 1; + // If this fails, see FLATBUFFERS_LITTLEENDIAN above. + FLATBUFFERS_ASSERT(*reinterpret_cast(&endiantest) == + FLATBUFFERS_LITTLEENDIAN); + (void)endiantest; +} + +template FLATBUFFERS_CONSTEXPR size_t AlignOf() { + // clang-format off + #ifdef _MSC_VER + return __alignof(T); + #else + #ifndef alignof + return __alignof__(T); + #else + return alignof(T); + #endif + #endif + // clang-format on +} + +// Lexicographically compare two strings (possibly containing nulls), and +// return true if the first is less than the second. +static inline bool StringLessThan(const char *a_data, uoffset_t a_size, + const char *b_data, uoffset_t b_size) { + const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size)); + return cmp == 0 ? a_size < b_size : cmp < 0; +} + +// When we read serialized data from memory, in the case of most scalars, +// we want to just read T, but in the case of Offset, we want to actually +// perform the indirection and return a pointer. +// The template specialization below does just that. +// It is wrapped in a struct since function templates can't overload on the +// return type like this. +// The typedef is for the convenience of callers of this function +// (avoiding the need for a trailing return decltype) +template struct IndirectHelper { + typedef T return_type; + typedef T mutable_return_type; + static const size_t element_stride = sizeof(T); + static return_type Read(const uint8_t *p, uoffset_t i) { + return EndianScalar((reinterpret_cast(p))[i]); + } +}; +template struct IndirectHelper> { + typedef const T *return_type; + typedef T *mutable_return_type; + static const size_t element_stride = sizeof(uoffset_t); + static return_type Read(const uint8_t *p, uoffset_t i) { + p += i * sizeof(uoffset_t); + return reinterpret_cast(p + ReadScalar(p)); + } +}; +template struct IndirectHelper { + typedef const T *return_type; + typedef T *mutable_return_type; + static const size_t element_stride = sizeof(T); + static return_type Read(const uint8_t *p, uoffset_t i) { + return reinterpret_cast(p + i * sizeof(T)); + } +}; + +/// @brief Get a pointer to the the file_identifier section of the buffer. +/// @return Returns a const char pointer to the start of the file_identifier +/// characters in the buffer. The returned char * has length +/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'. +/// This function is UNDEFINED for FlatBuffers whose schema does not include +/// a file_identifier (likely points at padding or the start of a the root +/// vtable). +inline const char *GetBufferIdentifier(const void *buf, + bool size_prefixed = false) { + return reinterpret_cast(buf) + + ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t)); +} + +// Helper to see if the identifier in a buffer has the expected value. +inline bool BufferHasIdentifier(const void *buf, const char *identifier, + bool size_prefixed = false) { + return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier, + flatbuffers::kFileIdentifierLength) == 0; +} + +/// @cond FLATBUFFERS_INTERNAL +// Helpers to get a typed pointer to the root object contained in the buffer. +template T *GetMutableRoot(void *buf) { + EndianCheck(); + return reinterpret_cast( + reinterpret_cast(buf) + + EndianScalar(*reinterpret_cast(buf))); +} + +template T *GetMutableSizePrefixedRoot(void *buf) { + return GetMutableRoot(reinterpret_cast(buf) + + sizeof(uoffset_t)); +} + +template const T *GetRoot(const void *buf) { + return GetMutableRoot(const_cast(buf)); +} + +template const T *GetSizePrefixedRoot(const void *buf) { + return GetRoot(reinterpret_cast(buf) + sizeof(uoffset_t)); +} + +} // namespace flatbuffers + +#endif // FLATBUFFERS_BUFFER_H_ \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/buffer_ref.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/buffer_ref.h new file mode 100644 index 000000000..c9fd4635a --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/buffer_ref.h @@ -0,0 +1,53 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_BUFFER_REF_H_ +#define FLATBUFFERS_BUFFER_REF_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/verifier.h" + +namespace flatbuffers { + +// Convenient way to bundle a buffer and its length, to pass it around +// typed by its root. +// A BufferRef does not own its buffer. +struct BufferRefBase {}; // for std::is_base_of + +template struct BufferRef : BufferRefBase { + BufferRef() : buf(nullptr), len(0), must_free(false) {} + BufferRef(uint8_t *_buf, uoffset_t _len) + : buf(_buf), len(_len), must_free(false) {} + + ~BufferRef() { + if (must_free) free(buf); + } + + const T *GetRoot() const { return flatbuffers::GetRoot(buf); } + + bool Verify() { + Verifier verifier(buf, len); + return verifier.VerifyBuffer(nullptr); + } + + uint8_t *buf; + uoffset_t len; + bool must_free; +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_BUFFER_REF_H_ \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/default_allocator.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/default_allocator.h new file mode 100644 index 000000000..3c5aa83e5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/default_allocator.h @@ -0,0 +1,58 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_DEFAULT_ALLOCATOR_H_ +#define FLATBUFFERS_DEFAULT_ALLOCATOR_H_ + +#include "third_party/flatbuffers/include/flatbuffers/allocator.h" +#include "third_party/flatbuffers/include/flatbuffers/base.h" + +namespace flatbuffers { + +// DefaultAllocator uses new/delete to allocate memory regions +class DefaultAllocator : public Allocator { + public: + uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE { + return new uint8_t[size]; + } + + void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; } + + static void dealloc(void *p, size_t) { delete[] static_cast(p); } +}; + +// These functions allow for a null allocator to mean use the default allocator, +// as used by DetachedBuffer and vector_downward below. +// This is to avoid having a statically or dynamically allocated default +// allocator, or having to move it between the classes that may own it. +inline uint8_t *Allocate(Allocator *allocator, size_t size) { + return allocator->allocate(size); +} + +inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) { + allocator->deallocate(p, size); +} + +inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p, + size_t old_size, size_t new_size, + size_t in_use_back, size_t in_use_front) { + return allocator->reallocate_downward(old_p, old_size, new_size, in_use_back, + in_use_front); +} + +} // namespace flatbuffers + +#endif // FLATBUFFERS_DEFAULT_ALLOCATOR_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/detached_buffer.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/detached_buffer.h new file mode 100644 index 000000000..3b266656c --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/detached_buffer.h @@ -0,0 +1,114 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_DETACHED_BUFFER_H_ +#define FLATBUFFERS_DETACHED_BUFFER_H_ + +#include "third_party/flatbuffers/include/flatbuffers/allocator.h" +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/default_allocator.h" + +namespace flatbuffers { + +// DetachedBuffer is a finished flatbuffer memory region, detached from its +// builder. The original memory region and allocator are also stored so that +// the DetachedBuffer can manage the memory lifetime. +class DetachedBuffer { + public: + DetachedBuffer() + : allocator_(nullptr), + own_allocator_(false), + buf_(nullptr), + reserved_(0), + cur_(nullptr), + size_(0) {} + + DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf, + size_t reserved, uint8_t *cur, size_t sz) + : allocator_(allocator), + own_allocator_(own_allocator), + buf_(buf), + reserved_(reserved), + cur_(cur), + size_(sz) {} + + DetachedBuffer(DetachedBuffer &&other) + : allocator_(other.allocator_), + own_allocator_(other.own_allocator_), + buf_(other.buf_), + reserved_(other.reserved_), + cur_(other.cur_), + size_(other.size_) { + other.reset(); + } + + DetachedBuffer &operator=(DetachedBuffer &&other) { + if (this == &other) return *this; + + destroy(); + + allocator_ = other.allocator_; + own_allocator_ = other.own_allocator_; + buf_ = other.buf_; + reserved_ = other.reserved_; + cur_ = other.cur_; + size_ = other.size_; + + other.reset(); + + return *this; + } + + ~DetachedBuffer() { destroy(); } + + const uint8_t *data() const { return cur_; } + + uint8_t *data() { return cur_; } + + size_t size() const { return size_; } + + // These may change access mode, leave these at end of public section + FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other)); + FLATBUFFERS_DELETE_FUNC( + DetachedBuffer &operator=(const DetachedBuffer &other)); + + protected: + Allocator *allocator_; + bool own_allocator_; + uint8_t *buf_; + size_t reserved_; + uint8_t *cur_; + size_t size_; + + inline void destroy() { + if (buf_) Deallocate(allocator_, buf_, reserved_); + if (own_allocator_ && allocator_) { delete allocator_; } + reset(); + } + + inline void reset() { + allocator_ = nullptr; + own_allocator_ = false; + buf_ = nullptr; + reserved_ = 0; + cur_ = nullptr; + size_ = 0; + } +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_DETACHED_BUFFER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h new file mode 100644 index 000000000..7233dcc54 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h @@ -0,0 +1,1214 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_FLATBUFFER_BUILDER_H_ +#define FLATBUFFERS_FLATBUFFER_BUILDER_H_ + +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/allocator.h" +#include "third_party/flatbuffers/include/flatbuffers/array.h" +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/buffer_ref.h" +#include "third_party/flatbuffers/include/flatbuffers/default_allocator.h" +#include "third_party/flatbuffers/include/flatbuffers/detached_buffer.h" +#include "third_party/flatbuffers/include/flatbuffers/stl_emulation.h" +#include "third_party/flatbuffers/include/flatbuffers/string.h" +#include "third_party/flatbuffers/include/flatbuffers/struct.h" +#include "third_party/flatbuffers/include/flatbuffers/table.h" +#include "third_party/flatbuffers/include/flatbuffers/vector.h" +#include "third_party/flatbuffers/include/flatbuffers/vector_downward.h" +#include "third_party/flatbuffers/include/flatbuffers/verifier.h" + +namespace flatbuffers { + +// Converts a Field ID to a virtual table offset. +inline voffset_t FieldIndexToOffset(voffset_t field_id) { + // Should correspond to what EndTable() below builds up. + const int fixed_fields = 2; // Vtable size and Object Size. + return static_cast((field_id + fixed_fields) * sizeof(voffset_t)); +} + +template> +const T *data(const std::vector &v) { + // Eventually the returned pointer gets passed down to memcpy, so + // we need it to be non-null to avoid undefined behavior. + static uint8_t t; + return v.empty() ? reinterpret_cast(&t) : &v.front(); +} +template> +T *data(std::vector &v) { + // Eventually the returned pointer gets passed down to memcpy, so + // we need it to be non-null to avoid undefined behavior. + static uint8_t t; + return v.empty() ? reinterpret_cast(&t) : &v.front(); +} + +/// @addtogroup flatbuffers_cpp_api +/// @{ +/// @class FlatBufferBuilder +/// @brief Helper class to hold data needed in creation of a FlatBuffer. +/// To serialize data, you typically call one of the `Create*()` functions in +/// the generated code, which in turn call a sequence of `StartTable`/ +/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/ +/// `CreateVector` functions. Do this is depth-first order to build up a tree to +/// the root. `Finish()` wraps up the buffer ready for transport. +class FlatBufferBuilder { + public: + /// @brief Default constructor for FlatBufferBuilder. + /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults + /// to `1024`. + /// @param[in] allocator An `Allocator` to use. If null will use + /// `DefaultAllocator`. + /// @param[in] own_allocator Whether the builder/vector should own the + /// allocator. Defaults to / `false`. + /// @param[in] buffer_minalign Force the buffer to be aligned to the given + /// minimum alignment upon reallocation. Only needed if you intend to store + /// types with custom alignment AND you wish to read the buffer in-place + /// directly after creation. + explicit FlatBufferBuilder( + size_t initial_size = 1024, Allocator *allocator = nullptr, + bool own_allocator = false, + size_t buffer_minalign = AlignOf()) + : buf_(initial_size, allocator, own_allocator, buffer_minalign), + num_field_loc(0), + max_voffset_(0), + nested(false), + finished(false), + minalign_(1), + force_defaults_(false), + dedup_vtables_(true), + string_pool(nullptr) { + EndianCheck(); + } + + /// @brief Move constructor for FlatBufferBuilder. + FlatBufferBuilder(FlatBufferBuilder &&other) + : buf_(1024, nullptr, false, AlignOf()), + num_field_loc(0), + max_voffset_(0), + nested(false), + finished(false), + minalign_(1), + force_defaults_(false), + dedup_vtables_(true), + string_pool(nullptr) { + EndianCheck(); + // Default construct and swap idiom. + // Lack of delegating constructors in vs2010 makes it more verbose than + // needed. + Swap(other); + } + + /// @brief Move assignment operator for FlatBufferBuilder. + FlatBufferBuilder &operator=(FlatBufferBuilder &&other) { + // Move construct a temporary and swap idiom + FlatBufferBuilder temp(std::move(other)); + Swap(temp); + return *this; + } + + void Swap(FlatBufferBuilder &other) { + using std::swap; + buf_.swap(other.buf_); + swap(num_field_loc, other.num_field_loc); + swap(max_voffset_, other.max_voffset_); + swap(nested, other.nested); + swap(finished, other.finished); + swap(minalign_, other.minalign_); + swap(force_defaults_, other.force_defaults_); + swap(dedup_vtables_, other.dedup_vtables_); + swap(string_pool, other.string_pool); + } + + ~FlatBufferBuilder() { + if (string_pool) delete string_pool; + } + + void Reset() { + Clear(); // clear builder state + buf_.reset(); // deallocate buffer + } + + /// @brief Reset all the state in this FlatBufferBuilder so it can be reused + /// to construct another buffer. + void Clear() { + ClearOffsets(); + buf_.clear(); + nested = false; + finished = false; + minalign_ = 1; + if (string_pool) string_pool->clear(); + } + + /// @brief The current size of the serialized buffer, counting from the end. + /// @return Returns an `uoffset_t` with the current size of the buffer. + uoffset_t GetSize() const { return buf_.size(); } + + /// @brief Get the serialized buffer (after you call `Finish()`). + /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the + /// buffer. + uint8_t *GetBufferPointer() const { + Finished(); + return buf_.data(); + } + + /// @brief Get the serialized buffer (after you call `Finish()`) as a span. + /// @return Returns a constructed flatbuffers::span that is a view over the + /// FlatBuffer data inside the buffer. + flatbuffers::span GetBufferSpan() const { + Finished(); + return flatbuffers::span(buf_.data(), buf_.size()); + } + + /// @brief Get a pointer to an unfinished buffer. + /// @return Returns a `uint8_t` pointer to the unfinished buffer. + uint8_t *GetCurrentBufferPointer() const { return buf_.data(); } + + /// @brief Get the released pointer to the serialized buffer. + /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards! + /// @return A `FlatBuffer` that owns the buffer and its allocator and + /// behaves similar to a `unique_ptr` with a deleter. + FLATBUFFERS_ATTRIBUTE([[deprecated("use Release() instead")]]) + DetachedBuffer ReleaseBufferPointer() { + Finished(); + return buf_.release(); + } + + /// @brief Get the released DetachedBuffer. + /// @return A `DetachedBuffer` that owns the buffer and its allocator. + DetachedBuffer Release() { + Finished(); + return buf_.release(); + } + + /// @brief Get the released pointer to the serialized buffer. + /// @param size The size of the memory block containing + /// the serialized `FlatBuffer`. + /// @param offset The offset from the released pointer where the finished + /// `FlatBuffer` starts. + /// @return A raw pointer to the start of the memory block containing + /// the serialized `FlatBuffer`. + /// @remark If the allocator is owned, it gets deleted when the destructor is + /// called.. + uint8_t *ReleaseRaw(size_t &size, size_t &offset) { + Finished(); + return buf_.release_raw(size, offset); + } + + /// @brief get the minimum alignment this buffer needs to be accessed + /// properly. This is only known once all elements have been written (after + /// you call Finish()). You can use this information if you need to embed + /// a FlatBuffer in some other buffer, such that you can later read it + /// without first having to copy it into its own buffer. + size_t GetBufferMinAlignment() const { + Finished(); + return minalign_; + } + + /// @cond FLATBUFFERS_INTERNAL + void Finished() const { + // If you get this assert, you're attempting to get access a buffer + // which hasn't been finished yet. Be sure to call + // FlatBufferBuilder::Finish with your root table. + // If you really need to access an unfinished buffer, call + // GetCurrentBufferPointer instead. + FLATBUFFERS_ASSERT(finished); + } + /// @endcond + + /// @brief In order to save space, fields that are set to their default value + /// don't get serialized into the buffer. + /// @param[in] fd When set to `true`, always serializes default values that + /// are set. Optional fields which are not set explicitly, will still not be + /// serialized. + void ForceDefaults(bool fd) { force_defaults_ = fd; } + + /// @brief By default vtables are deduped in order to save space. + /// @param[in] dedup When set to `true`, dedup vtables. + void DedupVtables(bool dedup) { dedup_vtables_ = dedup; } + + /// @cond FLATBUFFERS_INTERNAL + void Pad(size_t num_bytes) { buf_.fill(num_bytes); } + + void TrackMinAlign(size_t elem_size) { + if (elem_size > minalign_) minalign_ = elem_size; + } + + void Align(size_t elem_size) { + TrackMinAlign(elem_size); + buf_.fill(PaddingBytes(buf_.size(), elem_size)); + } + + void PushFlatBuffer(const uint8_t *bytes, size_t size) { + PushBytes(bytes, size); + finished = true; + } + + void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); } + + void PopBytes(size_t amount) { buf_.pop(amount); } + + template void AssertScalarT() { + // The code assumes power of 2 sizes and endian-swap-ability. + static_assert(flatbuffers::is_scalar::value, "T must be a scalar type"); + } + + // Write a single aligned scalar to the buffer + template uoffset_t PushElement(T element) { + AssertScalarT(); + Align(sizeof(T)); + buf_.push_small(EndianScalar(element)); + return GetSize(); + } + + template uoffset_t PushElement(Offset off) { + // Special case for offsets: see ReferTo below. + return PushElement(ReferTo(off.o)); + } + + // When writing fields, we track where they are, so we can create correct + // vtables later. + void TrackField(voffset_t field, uoffset_t off) { + FieldLoc fl = { off, field }; + buf_.scratch_push_small(fl); + num_field_loc++; + if (field > max_voffset_) { max_voffset_ = field; } + } + + // Like PushElement, but additionally tracks the field this represents. + template void AddElement(voffset_t field, T e, T def) { + // We don't serialize values equal to the default. + if (IsTheSameAs(e, def) && !force_defaults_) return; + TrackField(field, PushElement(e)); + } + + template void AddElement(voffset_t field, T e) { + TrackField(field, PushElement(e)); + } + + template void AddOffset(voffset_t field, Offset off) { + if (off.IsNull()) return; // Don't store. + AddElement(field, ReferTo(off.o), static_cast(0)); + } + + template void AddStruct(voffset_t field, const T *structptr) { + if (!structptr) return; // Default, don't store. + Align(AlignOf()); + buf_.push_small(*structptr); + TrackField(field, GetSize()); + } + + void AddStructOffset(voffset_t field, uoffset_t off) { + TrackField(field, off); + } + + // Offsets initially are relative to the end of the buffer (downwards). + // This function converts them to be relative to the current location + // in the buffer (when stored here), pointing upwards. + uoffset_t ReferTo(uoffset_t off) { + // Align to ensure GetSize() below is correct. + Align(sizeof(uoffset_t)); + // Offset must refer to something already in buffer. + const uoffset_t size = GetSize(); + FLATBUFFERS_ASSERT(off && off <= size); + return size - off + static_cast(sizeof(uoffset_t)); + } + + void NotNested() { + // If you hit this, you're trying to construct a Table/Vector/String + // during the construction of its parent table (between the MyTableBuilder + // and table.Finish(). + // Move the creation of these sub-objects to above the MyTableBuilder to + // not get this assert. + // Ignoring this assert may appear to work in simple cases, but the reason + // it is here is that storing objects in-line may cause vtable offsets + // to not fit anymore. It also leads to vtable duplication. + FLATBUFFERS_ASSERT(!nested); + // If you hit this, fields were added outside the scope of a table. + FLATBUFFERS_ASSERT(!num_field_loc); + } + + // From generated code (or from the parser), we call StartTable/EndTable + // with a sequence of AddElement calls in between. + uoffset_t StartTable() { + NotNested(); + nested = true; + return GetSize(); + } + + // This finishes one serialized object by generating the vtable if it's a + // table, comparing it against existing vtables, and writing the + // resulting vtable offset. + uoffset_t EndTable(uoffset_t start) { + // If you get this assert, a corresponding StartTable wasn't called. + FLATBUFFERS_ASSERT(nested); + // Write the vtable offset, which is the start of any Table. + // We fill it's value later. + auto vtableoffsetloc = PushElement(0); + // Write a vtable, which consists entirely of voffset_t elements. + // It starts with the number of offsets, followed by a type id, followed + // by the offsets themselves. In reverse: + // Include space for the last offset and ensure empty tables have a + // minimum size. + max_voffset_ = + (std::max)(static_cast(max_voffset_ + sizeof(voffset_t)), + FieldIndexToOffset(0)); + buf_.fill_big(max_voffset_); + auto table_object_size = vtableoffsetloc - start; + // Vtable use 16bit offsets. + FLATBUFFERS_ASSERT(table_object_size < 0x10000); + WriteScalar(buf_.data() + sizeof(voffset_t), + static_cast(table_object_size)); + WriteScalar(buf_.data(), max_voffset_); + // Write the offsets into the table + for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc); + it < buf_.scratch_end(); it += sizeof(FieldLoc)) { + auto field_location = reinterpret_cast(it); + auto pos = static_cast(vtableoffsetloc - field_location->off); + // If this asserts, it means you've set a field twice. + FLATBUFFERS_ASSERT( + !ReadScalar(buf_.data() + field_location->id)); + WriteScalar(buf_.data() + field_location->id, pos); + } + ClearOffsets(); + auto vt1 = reinterpret_cast(buf_.data()); + auto vt1_size = ReadScalar(vt1); + auto vt_use = GetSize(); + // See if we already have generated a vtable with this exact same + // layout before. If so, make it point to the old one, remove this one. + if (dedup_vtables_) { + for (auto it = buf_.scratch_data(); it < buf_.scratch_end(); + it += sizeof(uoffset_t)) { + auto vt_offset_ptr = reinterpret_cast(it); + auto vt2 = reinterpret_cast(buf_.data_at(*vt_offset_ptr)); + auto vt2_size = ReadScalar(vt2); + if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue; + vt_use = *vt_offset_ptr; + buf_.pop(GetSize() - vtableoffsetloc); + break; + } + } + // If this is a new vtable, remember it. + if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); } + // Fill the vtable offset we created above. + // The offset points from the beginning of the object to where the + // vtable is stored. + // Offsets default direction is downward in memory for future format + // flexibility (storing all vtables at the start of the file). + WriteScalar(buf_.data_at(vtableoffsetloc), + static_cast(vt_use) - + static_cast(vtableoffsetloc)); + + nested = false; + return vtableoffsetloc; + } + + FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]]) + uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) { + return EndTable(start); + } + + // This checks a required field has been set in a given table that has + // just been constructed. + template void Required(Offset table, voffset_t field); + + uoffset_t StartStruct(size_t alignment) { + Align(alignment); + return GetSize(); + } + + uoffset_t EndStruct() { return GetSize(); } + + void ClearOffsets() { + buf_.scratch_pop(num_field_loc * sizeof(FieldLoc)); + num_field_loc = 0; + max_voffset_ = 0; + } + + // Aligns such that when "len" bytes are written, an object can be written + // after it with "alignment" without padding. + void PreAlign(size_t len, size_t alignment) { + if (len == 0) return; + TrackMinAlign(alignment); + buf_.fill(PaddingBytes(GetSize() + len, alignment)); + } + template void PreAlign(size_t len) { + AssertScalarT(); + PreAlign(len, sizeof(T)); + } + /// @endcond + + /// @brief Store a string in the buffer, which can contain any binary data. + /// @param[in] str A const char pointer to the data to be stored as a string. + /// @param[in] len The number of bytes that should be stored from `str`. + /// @return Returns the offset in the buffer where the string starts. + Offset CreateString(const char *str, size_t len) { + NotNested(); + PreAlign(len + 1); // Always 0-terminated. + buf_.fill(1); + PushBytes(reinterpret_cast(str), len); + PushElement(static_cast(len)); + return Offset(GetSize()); + } + + /// @brief Store a string in the buffer, which is null-terminated. + /// @param[in] str A const char pointer to a C-string to add to the buffer. + /// @return Returns the offset in the buffer where the string starts. + Offset CreateString(const char *str) { + return CreateString(str, strlen(str)); + } + + /// @brief Store a string in the buffer, which is null-terminated. + /// @param[in] str A char pointer to a C-string to add to the buffer. + /// @return Returns the offset in the buffer where the string starts. + Offset CreateString(char *str) { + return CreateString(str, strlen(str)); + } + + /// @brief Store a string in the buffer, which can contain any binary data. + /// @param[in] str A const reference to a std::string to store in the buffer. + /// @return Returns the offset in the buffer where the string starts. + Offset CreateString(const std::string &str) { + return CreateString(str.c_str(), str.length()); + } + + // clang-format off + #ifdef FLATBUFFERS_HAS_STRING_VIEW + /// @brief Store a string in the buffer, which can contain any binary data. + /// @param[in] str A const string_view to copy in to the buffer. + /// @return Returns the offset in the buffer where the string starts. + Offset CreateString(flatbuffers::string_view str) { + return CreateString(str.data(), str.size()); + } + #endif // FLATBUFFERS_HAS_STRING_VIEW + // clang-format on + + /// @brief Store a string in the buffer, which can contain any binary data. + /// @param[in] str A const pointer to a `String` struct to add to the buffer. + /// @return Returns the offset in the buffer where the string starts + Offset CreateString(const String *str) { + return str ? CreateString(str->c_str(), str->size()) : 0; + } + + /// @brief Store a string in the buffer, which can contain any binary data. + /// @param[in] str A const reference to a std::string like type with support + /// of T::c_str() and T::length() to store in the buffer. + /// @return Returns the offset in the buffer where the string starts. + template Offset CreateString(const T &str) { + return CreateString(str.c_str(), str.length()); + } + + /// @brief Store a string in the buffer, which can contain any binary data. + /// If a string with this exact contents has already been serialized before, + /// instead simply returns the offset of the existing string. This uses a map + /// stored on the heap, but only stores the numerical offsets. + /// @param[in] str A const char pointer to the data to be stored as a string. + /// @param[in] len The number of bytes that should be stored from `str`. + /// @return Returns the offset in the buffer where the string starts. + Offset CreateSharedString(const char *str, size_t len) { + FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK); + if (!string_pool) + string_pool = new StringOffsetMap(StringOffsetCompare(buf_)); + auto size_before_string = buf_.size(); + // Must first serialize the string, since the set is all offsets into + // buffer. + auto off = CreateString(str, len); + auto it = string_pool->find(off); + // If it exists we reuse existing serialized data! + if (it != string_pool->end()) { + // We can remove the string we serialized. + buf_.pop(buf_.size() - size_before_string); + return *it; + } + // Record this string for future use. + string_pool->insert(off); + return off; + } + +#ifdef FLATBUFFERS_HAS_STRING_VIEW + /// @brief Store a string in the buffer, which can contain any binary data. + /// If a string with this exact contents has already been serialized before, + /// instead simply returns the offset of the existing string. This uses a map + /// stored on the heap, but only stores the numerical offsets. + /// @param[in] str A const std::string_view to store in the buffer. + /// @return Returns the offset in the buffer where the string starts + Offset CreateSharedString(const flatbuffers::string_view str) { + return CreateSharedString(str.data(), str.size()); + } +#else + /// @brief Store a string in the buffer, which null-terminated. + /// If a string with this exact contents has already been serialized before, + /// instead simply returns the offset of the existing string. This uses a map + /// stored on the heap, but only stores the numerical offsets. + /// @param[in] str A const char pointer to a C-string to add to the buffer. + /// @return Returns the offset in the buffer where the string starts. + Offset CreateSharedString(const char *str) { + return CreateSharedString(str, strlen(str)); + } + + /// @brief Store a string in the buffer, which can contain any binary data. + /// If a string with this exact contents has already been serialized before, + /// instead simply returns the offset of the existing string. This uses a map + /// stored on the heap, but only stores the numerical offsets. + /// @param[in] str A const reference to a std::string to store in the buffer. + /// @return Returns the offset in the buffer where the string starts. + Offset CreateSharedString(const std::string &str) { + return CreateSharedString(str.c_str(), str.length()); + } +#endif + + /// @brief Store a string in the buffer, which can contain any binary data. + /// If a string with this exact contents has already been serialized before, + /// instead simply returns the offset of the existing string. This uses a map + /// stored on the heap, but only stores the numerical offsets. + /// @param[in] str A const pointer to a `String` struct to add to the buffer. + /// @return Returns the offset in the buffer where the string starts + Offset CreateSharedString(const String *str) { + return CreateSharedString(str->c_str(), str->size()); + } + + /// @cond FLATBUFFERS_INTERNAL + uoffset_t EndVector(size_t len) { + FLATBUFFERS_ASSERT(nested); // Hit if no corresponding StartVector. + nested = false; + return PushElement(static_cast(len)); + } + + void StartVector(size_t len, size_t elemsize) { + NotNested(); + nested = true; + PreAlign(len * elemsize); + PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t. + } + + // Call this right before StartVector/CreateVector if you want to force the + // alignment to be something different than what the element size would + // normally dictate. + // This is useful when storing a nested_flatbuffer in a vector of bytes, + // or when storing SIMD floats, etc. + void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) { + if (len == 0) return; + FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment)); + PreAlign(len * elemsize, alignment); + } + + // Similar to ForceVectorAlignment but for String fields. + void ForceStringAlignment(size_t len, size_t alignment) { + if (len == 0) return; + FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment)); + PreAlign((len + 1) * sizeof(char), alignment); + } + + /// @endcond + + /// @brief Serialize an array into a FlatBuffer `vector`. + /// @tparam T The data type of the array elements. + /// @param[in] v A pointer to the array of type `T` to serialize into the + /// buffer as a `vector`. + /// @param[in] len The number of elements to serialize. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template Offset> CreateVector(const T *v, size_t len) { + // If this assert hits, you're specifying a template argument that is + // causing the wrong overload to be selected, remove it. + AssertScalarT(); + StartVector(len, sizeof(T)); + if (len == 0) { return Offset>(EndVector(len)); } + // clang-format off + #if FLATBUFFERS_LITTLEENDIAN + PushBytes(reinterpret_cast(v), len * sizeof(T)); + #else + if (sizeof(T) == 1) { + PushBytes(reinterpret_cast(v), len); + } else { + for (auto i = len; i > 0; ) { + PushElement(v[--i]); + } + } + #endif + // clang-format on + return Offset>(EndVector(len)); + } + + /// @brief Serialize an array like object into a FlatBuffer `vector`. + /// @tparam T The data type of the array elements. + /// @tparam C The type of the array. + /// @param[in] array A reference to an array like object of type `T` to + /// serialize into the buffer as a `vector`. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template Offset> CreateVector(const C &array) { + return CreateVector(array.data(), array.size()); + } + + /// @brief Serialize an initializer list into a FlatBuffer `vector`. + /// @tparam T The data type of the initializer list elements. + /// @param[in] v The value of the initializer list. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVector(std::initializer_list v) { + return CreateVector(v.begin(), v.size()); + } + + template + Offset>> CreateVector(const Offset *v, size_t len) { + StartVector(len, sizeof(Offset)); + for (auto i = len; i > 0;) { PushElement(v[--i]); } + return Offset>>(EndVector(len)); + } + + /// @brief Serialize a `std::vector` into a FlatBuffer `vector`. + /// @tparam T The data type of the `std::vector` elements. + /// @param v A const reference to the `std::vector` to serialize into the + /// buffer as a `vector`. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template> + Offset> CreateVector(const std::vector &v) { + return CreateVector(data(v), v.size()); + } + + // vector may be implemented using a bit-set, so we can't access it as + // an array. Instead, read elements manually. + // Background: https://isocpp.org/blog/2012/11/on-vectorbool + Offset> CreateVector(const std::vector &v) { + StartVector(v.size(), sizeof(uint8_t)); + for (auto i = v.size(); i > 0;) { + PushElement(static_cast(v[--i])); + } + return Offset>(EndVector(v.size())); + } + + /// @brief Serialize values returned by a function into a FlatBuffer `vector`. + /// This is a convenience function that takes care of iteration for you. + /// @tparam T The data type of the `std::vector` elements. + /// @param f A function that takes the current iteration 0..vector_size-1 and + /// returns any type that you can construct a FlatBuffers vector out of. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVector(size_t vector_size, + const std::function &f) { + FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK); + std::vector elems(vector_size); + for (size_t i = 0; i < vector_size; i++) elems[i] = f(i); + return CreateVector(elems); + } + + /// @brief Serialize values returned by a function into a FlatBuffer `vector`. + /// This is a convenience function that takes care of iteration for you. This + /// uses a vector stored on the heap to store the intermediate results of the + /// iteration. + /// @tparam T The data type of the `std::vector` elements. + /// @param f A function that takes the current iteration 0..vector_size-1, + /// and the state parameter returning any type that you can construct a + /// FlatBuffers vector out of. + /// @param state State passed to f. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVector(size_t vector_size, F f, S *state) { + FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK); + std::vector elems(vector_size); + for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state); + return CreateVector(elems); + } + + /// @brief Serialize a `std::vector` into a FlatBuffer `vector`. + /// whereas StringType is any type that is accepted by the CreateString() + /// overloads. + /// This is a convenience function for a common case. + /// @param v A const reference to the `std::vector` to serialize into the + /// buffer as a `vector`. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template> + Offset>> CreateVectorOfStrings( + const std::vector &v) { + return CreateVectorOfStrings(v.cbegin(), v.cend()); + } + + /// @brief Serialize a collection of Strings into a FlatBuffer `vector`. + /// This is a convenience function for a common case. + /// @param begin The begining iterator of the collection + /// @param end The ending iterator of the collection + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset>> CreateVectorOfStrings(It begin, It end) { + auto size = std::distance(begin, end); + auto scratch_buffer_usage = size * sizeof(Offset); + // If there is not enough space to store the offsets, there definitely won't + // be enough space to store all the strings. So ensuring space for the + // scratch region is OK, for it it fails, it would have failed later. + buf_.ensure_space(scratch_buffer_usage); + for (auto it = begin; it != end; ++it) { + buf_.scratch_push_small(CreateString(*it)); + } + StartVector(size, sizeof(Offset)); + for (auto i = 1; i <= size; i++) { + // Note we re-evaluate the buf location each iteration to account for any + // underlying buffer resizing that may occur. + PushElement(*reinterpret_cast *>( + buf_.scratch_end() - i * sizeof(Offset))); + } + buf_.scratch_pop(scratch_buffer_usage); + return Offset>>(EndVector(size)); + } + + /// @brief Serialize an array of structs into a FlatBuffer `vector`. + /// @tparam T The data type of the struct array elements. + /// @param[in] v A pointer to the array of type `T` to serialize into the + /// buffer as a `vector`. + /// @param[in] len The number of elements to serialize. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVectorOfStructs(const T *v, size_t len) { + StartVector(len * sizeof(T) / AlignOf(), AlignOf()); + if (len > 0) { + PushBytes(reinterpret_cast(v), sizeof(T) * len); + } + return Offset>(EndVector(len)); + } + + /// @brief Serialize an array of native structs into a FlatBuffer `vector`. + /// @tparam T The data type of the struct array elements. + /// @tparam S The data type of the native struct array elements. + /// @param[in] v A pointer to the array of type `S` to serialize into the + /// buffer as a `vector`. + /// @param[in] len The number of elements to serialize. + /// @param[in] pack_func Pointer to a function to convert the native struct + /// to the FlatBuffer struct. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVectorOfNativeStructs( + const S *v, size_t len, T (*const pack_func)(const S &)) { + FLATBUFFERS_ASSERT(pack_func); + auto structs = StartVectorOfStructs(len); + for (size_t i = 0; i < len; i++) { structs[i] = pack_func(v[i]); } + return EndVectorOfStructs(len); + } + + /// @brief Serialize an array of native structs into a FlatBuffer `vector`. + /// @tparam T The data type of the struct array elements. + /// @tparam S The data type of the native struct array elements. + /// @param[in] v A pointer to the array of type `S` to serialize into the + /// buffer as a `vector`. + /// @param[in] len The number of elements to serialize. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVectorOfNativeStructs(const S *v, + size_t len) { + extern T Pack(const S &); + return CreateVectorOfNativeStructs(v, len, Pack); + } + + /// @brief Serialize an array of structs into a FlatBuffer `vector`. + /// @tparam T The data type of the struct array elements. + /// @param[in] filler A function that takes the current iteration + /// 0..vector_size-1 and a pointer to the struct that must be filled. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + /// This is mostly useful when flatbuffers are generated with mutation + /// accessors. + template + Offset> CreateVectorOfStructs( + size_t vector_size, const std::function &filler) { + T *structs = StartVectorOfStructs(vector_size); + for (size_t i = 0; i < vector_size; i++) { + filler(i, structs); + structs++; + } + return EndVectorOfStructs(vector_size); + } + + /// @brief Serialize an array of structs into a FlatBuffer `vector`. + /// @tparam T The data type of the struct array elements. + /// @param[in] f A function that takes the current iteration 0..vector_size-1, + /// a pointer to the struct that must be filled and the state argument. + /// @param[in] state Arbitrary state to pass to f. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + /// This is mostly useful when flatbuffers are generated with mutation + /// accessors. + template + Offset> CreateVectorOfStructs(size_t vector_size, F f, + S *state) { + T *structs = StartVectorOfStructs(vector_size); + for (size_t i = 0; i < vector_size; i++) { + f(i, structs, state); + structs++; + } + return EndVectorOfStructs(vector_size); + } + + /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`. + /// @tparam T The data type of the `std::vector` struct elements. + /// @param[in] v A const reference to the `std::vector` of structs to + /// serialize into the buffer as a `vector`. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template> + Offset> CreateVectorOfStructs( + const std::vector &v) { + return CreateVectorOfStructs(data(v), v.size()); + } + + /// @brief Serialize a `std::vector` of native structs into a FlatBuffer + /// `vector`. + /// @tparam T The data type of the `std::vector` struct elements. + /// @tparam S The data type of the `std::vector` native struct elements. + /// @param[in] v A const reference to the `std::vector` of structs to + /// serialize into the buffer as a `vector`. + /// @param[in] pack_func Pointer to a function to convert the native struct + /// to the FlatBuffer struct. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template> + Offset> CreateVectorOfNativeStructs( + const std::vector &v, T (*const pack_func)(const S &)) { + return CreateVectorOfNativeStructs(data(v), v.size(), pack_func); + } + + /// @brief Serialize a `std::vector` of native structs into a FlatBuffer + /// `vector`. + /// @tparam T The data type of the `std::vector` struct elements. + /// @tparam S The data type of the `std::vector` native struct elements. + /// @param[in] v A const reference to the `std::vector` of structs to + /// serialize into the buffer as a `vector`. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template> + Offset> CreateVectorOfNativeStructs( + const std::vector &v) { + return CreateVectorOfNativeStructs(data(v), v.size()); + } + + /// @cond FLATBUFFERS_INTERNAL + template struct StructKeyComparator { + bool operator()(const T &a, const T &b) const { + return a.KeyCompareLessThan(&b); + } + }; + /// @endcond + + /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector` + /// in sorted order. + /// @tparam T The data type of the `std::vector` struct elements. + /// @param[in] v A const reference to the `std::vector` of structs to + /// serialize into the buffer as a `vector`. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template> + Offset> CreateVectorOfSortedStructs( + std::vector *v) { + return CreateVectorOfSortedStructs(data(*v), v->size()); + } + + /// @brief Serialize a `std::vector` of native structs into a FlatBuffer + /// `vector` in sorted order. + /// @tparam T The data type of the `std::vector` struct elements. + /// @tparam S The data type of the `std::vector` native struct elements. + /// @param[in] v A const reference to the `std::vector` of structs to + /// serialize into the buffer as a `vector`. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template> + Offset> CreateVectorOfSortedNativeStructs( + std::vector *v) { + return CreateVectorOfSortedNativeStructs(data(*v), v->size()); + } + + /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted + /// order. + /// @tparam T The data type of the struct array elements. + /// @param[in] v A pointer to the array of type `T` to serialize into the + /// buffer as a `vector`. + /// @param[in] len The number of elements to serialize. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVectorOfSortedStructs(T *v, size_t len) { + std::stable_sort(v, v + len, StructKeyComparator()); + return CreateVectorOfStructs(v, len); + } + + /// @brief Serialize an array of native structs into a FlatBuffer `vector` in + /// sorted order. + /// @tparam T The data type of the struct array elements. + /// @tparam S The data type of the native struct array elements. + /// @param[in] v A pointer to the array of type `S` to serialize into the + /// buffer as a `vector`. + /// @param[in] len The number of elements to serialize. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVectorOfSortedNativeStructs(S *v, + size_t len) { + extern T Pack(const S &); + auto structs = StartVectorOfStructs(len); + for (size_t i = 0; i < len; i++) { structs[i] = Pack(v[i]); } + std::stable_sort(structs, structs + len, StructKeyComparator()); + return EndVectorOfStructs(len); + } + + /// @cond FLATBUFFERS_INTERNAL + template struct TableKeyComparator { + TableKeyComparator(vector_downward &buf) : buf_(buf) {} + TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {} + bool operator()(const Offset &a, const Offset &b) const { + auto table_a = reinterpret_cast(buf_.data_at(a.o)); + auto table_b = reinterpret_cast(buf_.data_at(b.o)); + return table_a->KeyCompareLessThan(table_b); + } + vector_downward &buf_; + + private: + FLATBUFFERS_DELETE_FUNC( + TableKeyComparator &operator=(const TableKeyComparator &other)); + }; + /// @endcond + + /// @brief Serialize an array of `table` offsets as a `vector` in the buffer + /// in sorted order. + /// @tparam T The data type that the offset refers to. + /// @param[in] v An array of type `Offset` that contains the `table` + /// offsets to store in the buffer in sorted order. + /// @param[in] len The number of elements to store in the `vector`. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset>> CreateVectorOfSortedTables(Offset *v, + size_t len) { + std::stable_sort(v, v + len, TableKeyComparator(buf_)); + return CreateVector(v, len); + } + + /// @brief Serialize an array of `table` offsets as a `vector` in the buffer + /// in sorted order. + /// @tparam T The data type that the offset refers to. + /// @param[in] v An array of type `Offset` that contains the `table` + /// offsets to store in the buffer in sorted order. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template> + Offset>> CreateVectorOfSortedTables( + std::vector, Alloc> *v) { + return CreateVectorOfSortedTables(data(*v), v->size()); + } + + /// @brief Specialized version of `CreateVector` for non-copying use cases. + /// Write the data any time later to the returned buffer pointer `buf`. + /// @param[in] len The number of elements to store in the `vector`. + /// @param[in] elemsize The size of each element in the `vector`. + /// @param[out] buf A pointer to a `uint8_t` pointer that can be + /// written to at a later time to serialize the data into a `vector` + /// in the buffer. + uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, + uint8_t **buf) { + NotNested(); + StartVector(len, elemsize); + buf_.make_space(len * elemsize); + auto vec_start = GetSize(); + auto vec_end = EndVector(len); + *buf = buf_.data_at(vec_start); + return vec_end; + } + + /// @brief Specialized version of `CreateVector` for non-copying use cases. + /// Write the data any time later to the returned buffer pointer `buf`. + /// @tparam T The data type of the data that will be stored in the buffer + /// as a `vector`. + /// @param[in] len The number of elements to store in the `vector`. + /// @param[out] buf A pointer to a pointer of type `T` that can be + /// written to at a later time to serialize the data into a `vector` + /// in the buffer. + template + Offset> CreateUninitializedVector(size_t len, T **buf) { + AssertScalarT(); + return CreateUninitializedVector(len, sizeof(T), + reinterpret_cast(buf)); + } + + template + Offset> CreateUninitializedVectorOfStructs(size_t len, + T **buf) { + return CreateUninitializedVector(len, sizeof(T), + reinterpret_cast(buf)); + } + + // @brief Create a vector of scalar type T given as input a vector of scalar + // type U, useful with e.g. pre "enum class" enums, or any existing scalar + // data of the wrong type. + template + Offset> CreateVectorScalarCast(const U *v, size_t len) { + AssertScalarT(); + AssertScalarT(); + StartVector(len, sizeof(T)); + for (auto i = len; i > 0;) { PushElement(static_cast(v[--i])); } + return Offset>(EndVector(len)); + } + + /// @brief Write a struct by itself, typically to be part of a union. + template Offset CreateStruct(const T &structobj) { + NotNested(); + Align(AlignOf()); + buf_.push_small(structobj); + return Offset(GetSize()); + } + + /// @brief Finish serializing a buffer by writing the root offset. + /// @param[in] file_identifier If a `file_identifier` is given, the buffer + /// will be prefixed with a standard FlatBuffers file header. + template + void Finish(Offset root, const char *file_identifier = nullptr) { + Finish(root.o, file_identifier, false); + } + + /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the + /// buffer following the size field). These buffers are NOT compatible + /// with standard buffers created by Finish, i.e. you can't call GetRoot + /// on them, you have to use GetSizePrefixedRoot instead. + /// All >32 bit quantities in this buffer will be aligned when the whole + /// size pre-fixed buffer is aligned. + /// These kinds of buffers are useful for creating a stream of FlatBuffers. + template + void FinishSizePrefixed(Offset root, + const char *file_identifier = nullptr) { + Finish(root.o, file_identifier, true); + } + + void SwapBufAllocator(FlatBufferBuilder &other) { + buf_.swap_allocator(other.buf_); + } + + /// @brief The length of a FlatBuffer file header. + static const size_t kFileIdentifierLength = + ::flatbuffers::kFileIdentifierLength; + + protected: + // You shouldn't really be copying instances of this class. + FlatBufferBuilder(const FlatBufferBuilder &); + FlatBufferBuilder &operator=(const FlatBufferBuilder &); + + void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) { + NotNested(); + buf_.clear_scratch(); + // This will cause the whole buffer to be aligned. + PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) + + (file_identifier ? kFileIdentifierLength : 0), + minalign_); + if (file_identifier) { + FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength); + PushBytes(reinterpret_cast(file_identifier), + kFileIdentifierLength); + } + PushElement(ReferTo(root)); // Location of root. + if (size_prefix) { PushElement(GetSize()); } + finished = true; + } + + struct FieldLoc { + uoffset_t off; + voffset_t id; + }; + + vector_downward buf_; + + // Accumulating offsets of table members while it is being built. + // We store these in the scratch pad of buf_, after the vtable offsets. + uoffset_t num_field_loc; + // Track how much of the vtable is in use, so we can output the most compact + // possible vtable. + voffset_t max_voffset_; + + // Ensure objects are not nested. + bool nested; + + // Ensure the buffer is finished before it is being accessed. + bool finished; + + size_t minalign_; + + bool force_defaults_; // Serialize values equal to their defaults anyway. + + bool dedup_vtables_; + + struct StringOffsetCompare { + StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {} + bool operator()(const Offset &a, const Offset &b) const { + auto stra = reinterpret_cast(buf_->data_at(a.o)); + auto strb = reinterpret_cast(buf_->data_at(b.o)); + return StringLessThan(stra->data(), stra->size(), strb->data(), + strb->size()); + } + const vector_downward *buf_; + }; + + // For use with CreateSharedString. Instantiated on first use only. + typedef std::set, StringOffsetCompare> StringOffsetMap; + StringOffsetMap *string_pool; + + private: + // Allocates space for a vector of structures. + // Must be completed with EndVectorOfStructs(). + template T *StartVectorOfStructs(size_t vector_size) { + StartVector(vector_size * sizeof(T) / AlignOf(), AlignOf()); + return reinterpret_cast(buf_.make_space(vector_size * sizeof(T))); + } + + // End the vector of structures in the flatbuffers. + // Vector should have previously be started with StartVectorOfStructs(). + template + Offset> EndVectorOfStructs(size_t vector_size) { + return Offset>(EndVector(vector_size)); + } +}; +/// @} + +/// Helpers to get a typed pointer to objects that are currently being built. +/// @warning Creating new objects will lead to reallocations and invalidates +/// the pointer! +template +T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset offset) { + return reinterpret_cast(fbb.GetCurrentBufferPointer() + fbb.GetSize() - + offset.o); +} + +template +const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset offset) { + return GetMutableTemporaryPointer(fbb, offset); +} + +template +void FlatBufferBuilder::Required(Offset table, voffset_t field) { + auto table_ptr = reinterpret_cast(buf_.data_at(table.o)); + bool ok = table_ptr->GetOptionalFieldOffset(field) != 0; + // If this fails, the caller will show what field needs to be set. + FLATBUFFERS_ASSERT(ok); + (void)ok; +} + +} // namespace flatbuffers + +#endif // FLATBUFFERS_VECTOR_DOWNWARD_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flatbuffers.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flatbuffers.h new file mode 100644 index 000000000..6e7dc1b00 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flatbuffers.h @@ -0,0 +1,270 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_H_ +#define FLATBUFFERS_H_ + +// TODO: These includes are for mitigating the pains of users editing their +// source because they relied on flatbuffers.h to include everything for them. +#include "third_party/flatbuffers/include/flatbuffers/array.h" +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/buffer.h" +#include "third_party/flatbuffers/include/flatbuffers/buffer_ref.h" +#include "third_party/flatbuffers/include/flatbuffers/detached_buffer.h" +#include "third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h" +#include "third_party/flatbuffers/include/flatbuffers/stl_emulation.h" +#include "third_party/flatbuffers/include/flatbuffers/string.h" +#include "third_party/flatbuffers/include/flatbuffers/struct.h" +#include "third_party/flatbuffers/include/flatbuffers/table.h" +#include "third_party/flatbuffers/include/flatbuffers/vector.h" +#include "third_party/flatbuffers/include/flatbuffers/vector_downward.h" +#include "third_party/flatbuffers/include/flatbuffers/verifier.h" + +namespace flatbuffers { + +/// @brief This can compute the start of a FlatBuffer from a root pointer, i.e. +/// it is the opposite transformation of GetRoot(). +/// This may be useful if you want to pass on a root and have the recipient +/// delete the buffer afterwards. +inline const uint8_t *GetBufferStartFromRootPointer(const void *root) { + auto table = reinterpret_cast(root); + auto vtable = table->GetVTable(); + // Either the vtable is before the root or after the root. + auto start = (std::min)(vtable, reinterpret_cast(root)); + // Align to at least sizeof(uoffset_t). + start = reinterpret_cast(reinterpret_cast(start) & + ~(sizeof(uoffset_t) - 1)); + // Additionally, there may be a file_identifier in the buffer, and the root + // offset. The buffer may have been aligned to any size between + // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align"). + // Sadly, the exact alignment is only known when constructing the buffer, + // since it depends on the presence of values with said alignment properties. + // So instead, we simply look at the next uoffset_t values (root, + // file_identifier, and alignment padding) to see which points to the root. + // None of the other values can "impersonate" the root since they will either + // be 0 or four ASCII characters. + static_assert(flatbuffers::kFileIdentifierLength == sizeof(uoffset_t), + "file_identifier is assumed to be the same size as uoffset_t"); + for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1; + possible_roots; possible_roots--) { + start -= sizeof(uoffset_t); + if (ReadScalar(start) + start == + reinterpret_cast(root)) + return start; + } + // We didn't find the root, either the "root" passed isn't really a root, + // or the buffer is corrupt. + // Assert, because calling this function with bad data may cause reads + // outside of buffer boundaries. + FLATBUFFERS_ASSERT(false); + return nullptr; +} + +/// @brief This return the prefixed size of a FlatBuffer. +inline uoffset_t GetPrefixedSize(const uint8_t *buf) { + return ReadScalar(buf); +} + +// Base class for native objects (FlatBuffer data de-serialized into native +// C++ data structures). +// Contains no functionality, purely documentative. +struct NativeTable {}; + +/// @brief Function types to be used with resolving hashes into objects and +/// back again. The resolver gets a pointer to a field inside an object API +/// object that is of the type specified in the schema using the attribute +/// `cpp_type` (it is thus important whatever you write to this address +/// matches that type). The value of this field is initially null, so you +/// may choose to implement a delayed binding lookup using this function +/// if you wish. The resolver does the opposite lookup, for when the object +/// is being serialized again. +typedef uint64_t hash_value_t; +typedef std::function + resolver_function_t; +typedef std::function rehasher_function_t; + +// Helper function to test if a field is present, using any of the field +// enums in the generated code. +// `table` must be a generated table type. Since this is a template parameter, +// this is not typechecked to be a subclass of Table, so beware! +// Note: this function will return false for fields equal to the default +// value, since they're not stored in the buffer (unless force_defaults was +// used). +template +bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) { + // Cast, since Table is a private baseclass of any table types. + return reinterpret_cast(table)->CheckField( + static_cast(field)); +} + +// Utility function for reverse lookups on the EnumNames*() functions +// (in the generated C++ code) +// names must be NULL terminated. +inline int LookupEnum(const char **names, const char *name) { + for (const char **p = names; *p; p++) + if (!strcmp(*p, name)) return static_cast(p - names); + return -1; +} + +// These macros allow us to layout a struct with a guarantee that they'll end +// up looking the same on different compilers and platforms. +// It does this by disallowing the compiler to do any padding, and then +// does padding itself by inserting extra padding fields that make every +// element aligned to its own size. +// Additionally, it manually sets the alignment of the struct as a whole, +// which is typically its largest element, or a custom size set in the schema +// by the force_align attribute. +// These are used in the generated code only. + +// clang-format off +#if defined(_MSC_VER) + #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ + __pragma(pack(1)) \ + struct __declspec(align(alignment)) + #define FLATBUFFERS_STRUCT_END(name, size) \ + __pragma(pack()) \ + static_assert(sizeof(name) == size, "compiler breaks packing rules") +#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__) + #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ + _Pragma("pack(1)") \ + struct __attribute__((aligned(alignment))) + #define FLATBUFFERS_STRUCT_END(name, size) \ + _Pragma("pack()") \ + static_assert(sizeof(name) == size, "compiler breaks packing rules") +#else + #error Unknown compiler, please define structure alignment macros +#endif +// clang-format on + +// Minimal reflection via code generation. +// Besides full-fat reflection (see reflection.h) and parsing/printing by +// loading schemas (see idl.h), we can also have code generation for minimal +// reflection data which allows pretty-printing and other uses without needing +// a schema or a parser. +// Generate code with --reflect-types (types only) or --reflect-names (names +// also) to enable. +// See minireflect.h for utilities using this functionality. + +// These types are organized slightly differently as the ones in idl.h. +enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM }; + +// Scalars have the same order as in idl.h +// clang-format off +#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \ + ET(ET_UTYPE) \ + ET(ET_BOOL) \ + ET(ET_CHAR) \ + ET(ET_UCHAR) \ + ET(ET_SHORT) \ + ET(ET_USHORT) \ + ET(ET_INT) \ + ET(ET_UINT) \ + ET(ET_LONG) \ + ET(ET_ULONG) \ + ET(ET_FLOAT) \ + ET(ET_DOUBLE) \ + ET(ET_STRING) \ + ET(ET_SEQUENCE) // See SequenceType. + +enum ElementaryType { + #define FLATBUFFERS_ET(E) E, + FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) + #undef FLATBUFFERS_ET +}; + +inline const char * const *ElementaryTypeNames() { + static const char * const names[] = { + #define FLATBUFFERS_ET(E) #E, + FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) + #undef FLATBUFFERS_ET + }; + return names; +} +// clang-format on + +// Basic type info cost just 16bits per field! +// We're explicitly defining the signedness since the signedness of integer +// bitfields is otherwise implementation-defined and causes warnings on older +// GCC compilers. +struct TypeCode { + // ElementaryType + unsigned short base_type : 4; + // Either vector (in table) or array (in struct) + unsigned short is_repeating : 1; + // Index into type_refs below, or -1 for none. + signed short sequence_ref : 11; +}; + +static_assert(sizeof(TypeCode) == 2, "TypeCode"); + +struct TypeTable; + +// Signature of the static method present in each type. +typedef const TypeTable *(*TypeFunction)(); + +struct TypeTable { + SequenceType st; + size_t num_elems; // of type_codes, values, names (but not type_refs). + const TypeCode *type_codes; // num_elems count + const TypeFunction *type_refs; // less than num_elems entries (see TypeCode). + const int16_t *array_sizes; // less than num_elems entries (see TypeCode). + const int64_t *values; // Only set for non-consecutive enum/union or structs. + const char *const *names; // Only set if compiled with --reflect-names. +}; + +// String which identifies the current version of FlatBuffers. +inline const char *flatbuffers_version_string() { + return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "." + FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "." + FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION); +} + +// clang-format off +#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\ + inline E operator | (E lhs, E rhs){\ + return E(T(lhs) | T(rhs));\ + }\ + inline E operator & (E lhs, E rhs){\ + return E(T(lhs) & T(rhs));\ + }\ + inline E operator ^ (E lhs, E rhs){\ + return E(T(lhs) ^ T(rhs));\ + }\ + inline E operator ~ (E lhs){\ + return E(~T(lhs));\ + }\ + inline E operator |= (E &lhs, E rhs){\ + lhs = lhs | rhs;\ + return lhs;\ + }\ + inline E operator &= (E &lhs, E rhs){\ + lhs = lhs & rhs;\ + return lhs;\ + }\ + inline E operator ^= (E &lhs, E rhs){\ + lhs = lhs ^ rhs;\ + return lhs;\ + }\ + inline bool operator !(E rhs) \ + {\ + return !bool(T(rhs)); \ + } +/// @endcond +} // namespace flatbuffers + +// clang-format on + +#endif // FLATBUFFERS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flexbuffers.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flexbuffers.h new file mode 100644 index 000000000..2061c6c09 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/flexbuffers.h @@ -0,0 +1,1903 @@ +/* + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_FLEXBUFFERS_H_ +#define FLATBUFFERS_FLEXBUFFERS_H_ + +#include +// Used to select STL variant. +#include "third_party/flatbuffers/include/flatbuffers/base.h" +// We use the basic binary writing functions from the regular FlatBuffers. +#include "third_party/flatbuffers/include/flatbuffers/util.h" + +#ifdef _MSC_VER +# include +#endif + +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4127) // C4127: conditional expression is constant +#endif + +namespace flexbuffers { + +class Reference; +class Map; + +// These are used in the lower 2 bits of a type field to determine the size of +// the elements (and or size field) of the item pointed to (e.g. vector). +enum BitWidth { + BIT_WIDTH_8 = 0, + BIT_WIDTH_16 = 1, + BIT_WIDTH_32 = 2, + BIT_WIDTH_64 = 3, +}; + +// These are used as the upper 6 bits of a type field to indicate the actual +// type. +enum Type { + FBT_NULL = 0, + FBT_INT = 1, + FBT_UINT = 2, + FBT_FLOAT = 3, + // Types above stored inline, types below (except FBT_BOOL) store an offset. + FBT_KEY = 4, + FBT_STRING = 5, + FBT_INDIRECT_INT = 6, + FBT_INDIRECT_UINT = 7, + FBT_INDIRECT_FLOAT = 8, + FBT_MAP = 9, + FBT_VECTOR = 10, // Untyped. + FBT_VECTOR_INT = 11, // Typed any size (stores no type table). + FBT_VECTOR_UINT = 12, + FBT_VECTOR_FLOAT = 13, + FBT_VECTOR_KEY = 14, + // DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead. + // Read test.cpp/FlexBuffersDeprecatedTest() for details on why. + FBT_VECTOR_STRING_DEPRECATED = 15, + FBT_VECTOR_INT2 = 16, // Typed tuple (no type table, no size field). + FBT_VECTOR_UINT2 = 17, + FBT_VECTOR_FLOAT2 = 18, + FBT_VECTOR_INT3 = 19, // Typed triple (no type table, no size field). + FBT_VECTOR_UINT3 = 20, + FBT_VECTOR_FLOAT3 = 21, + FBT_VECTOR_INT4 = 22, // Typed quad (no type table, no size field). + FBT_VECTOR_UINT4 = 23, + FBT_VECTOR_FLOAT4 = 24, + FBT_BLOB = 25, + FBT_BOOL = 26, + FBT_VECTOR_BOOL = + 36, // To Allow the same type of conversion of type to vector type + + FBT_MAX_TYPE = 37 +}; + +inline bool IsInline(Type t) { return t <= FBT_FLOAT || t == FBT_BOOL; } + +inline bool IsTypedVectorElementType(Type t) { + return (t >= FBT_INT && t <= FBT_STRING) || t == FBT_BOOL; +} + +inline bool IsTypedVector(Type t) { + return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) || + t == FBT_VECTOR_BOOL; +} + +inline bool IsFixedTypedVector(Type t) { + return t >= FBT_VECTOR_INT2 && t <= FBT_VECTOR_FLOAT4; +} + +inline Type ToTypedVector(Type t, size_t fixed_len = 0) { + FLATBUFFERS_ASSERT(IsTypedVectorElementType(t)); + switch (fixed_len) { + case 0: return static_cast(t - FBT_INT + FBT_VECTOR_INT); + case 2: return static_cast(t - FBT_INT + FBT_VECTOR_INT2); + case 3: return static_cast(t - FBT_INT + FBT_VECTOR_INT3); + case 4: return static_cast(t - FBT_INT + FBT_VECTOR_INT4); + default: FLATBUFFERS_ASSERT(0); return FBT_NULL; + } +} + +inline Type ToTypedVectorElementType(Type t) { + FLATBUFFERS_ASSERT(IsTypedVector(t)); + return static_cast(t - FBT_VECTOR_INT + FBT_INT); +} + +inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) { + FLATBUFFERS_ASSERT(IsFixedTypedVector(t)); + auto fixed_type = t - FBT_VECTOR_INT2; + *len = static_cast(fixed_type / 3 + + 2); // 3 types each, starting from length 2. + return static_cast(fixed_type % 3 + FBT_INT); +} + +// TODO: implement proper support for 8/16bit floats, or decide not to +// support them. +typedef int16_t half; +typedef int8_t quarter; + +// TODO: can we do this without conditionals using intrinsics or inline asm +// on some platforms? Given branch prediction the method below should be +// decently quick, but it is the most frequently executed function. +// We could do an (unaligned) 64-bit read if we ifdef out the platforms for +// which that doesn't work (or where we'd read into un-owned memory). +template +R ReadSizedScalar(const uint8_t *data, uint8_t byte_width) { + return byte_width < 4 + ? (byte_width < 2 + ? static_cast(flatbuffers::ReadScalar(data)) + : static_cast(flatbuffers::ReadScalar(data))) + : (byte_width < 8 + ? static_cast(flatbuffers::ReadScalar(data)) + : static_cast(flatbuffers::ReadScalar(data))); +} + +inline int64_t ReadInt64(const uint8_t *data, uint8_t byte_width) { + return ReadSizedScalar( + data, byte_width); +} + +inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) { + // This is the "hottest" function (all offset lookups use this), so worth + // optimizing if possible. + // TODO: GCC apparently replaces memcpy by a rep movsb, but only if count is a + // constant, which here it isn't. Test if memcpy is still faster than + // the conditionals in ReadSizedScalar. Can also use inline asm. + + // clang-format off + #if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC) + // This is 64-bit Windows only, __movsb does not work on 32-bit Windows. + uint64_t u = 0; + __movsb(reinterpret_cast(&u), + reinterpret_cast(data), byte_width); + return flatbuffers::EndianScalar(u); + #else + return ReadSizedScalar( + data, byte_width); + #endif + // clang-format on +} + +inline double ReadDouble(const uint8_t *data, uint8_t byte_width) { + return ReadSizedScalar(data, + byte_width); +} + +inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) { + return offset - ReadUInt64(offset, byte_width); +} + +template const uint8_t *Indirect(const uint8_t *offset) { + return offset - flatbuffers::ReadScalar(offset); +} + +inline BitWidth WidthU(uint64_t u) { +#define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width) \ + { \ + if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \ + } + FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 8); + FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 16); + FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 32); +#undef FLATBUFFERS_GET_FIELD_BIT_WIDTH + return BIT_WIDTH_64; +} + +inline BitWidth WidthI(int64_t i) { + auto u = static_cast(i) << 1; + return WidthU(i >= 0 ? u : ~u); +} + +inline BitWidth WidthF(double f) { + return static_cast(static_cast(f)) == f ? BIT_WIDTH_32 + : BIT_WIDTH_64; +} + +// Base class of all types below. +// Points into the data buffer and allows access to one type. +class Object { + public: + Object(const uint8_t *data, uint8_t byte_width) + : data_(data), byte_width_(byte_width) {} + + protected: + const uint8_t *data_; + uint8_t byte_width_; +}; + +// Object that has a size, obtained either from size prefix, or elsewhere. +class Sized : public Object { + public: + // Size prefix. + Sized(const uint8_t *data, uint8_t byte_width) + : Object(data, byte_width), size_(read_size()) {} + // Manual size. + Sized(const uint8_t *data, uint8_t byte_width, size_t sz) + : Object(data, byte_width), size_(sz) {} + size_t size() const { return size_; } + // Access size stored in `byte_width_` bytes before data_ pointer. + size_t read_size() const { + return static_cast(ReadUInt64(data_ - byte_width_, byte_width_)); + } + + protected: + size_t size_; +}; + +class String : public Sized { + public: + // Size prefix. + String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {} + // Manual size. + String(const uint8_t *data, uint8_t byte_width, size_t sz) + : Sized(data, byte_width, sz) {} + + size_t length() const { return size(); } + const char *c_str() const { return reinterpret_cast(data_); } + std::string str() const { return std::string(c_str(), size()); } + + static String EmptyString() { + static const char *empty_string = ""; + return String(reinterpret_cast(empty_string), 1, 0); + } + bool IsTheEmptyString() const { return data_ == EmptyString().data_; } +}; + +class Blob : public Sized { + public: + Blob(const uint8_t *data_buf, uint8_t byte_width) + : Sized(data_buf, byte_width) {} + + static Blob EmptyBlob() { + static const uint8_t empty_blob[] = { 0 /*len*/ }; + return Blob(empty_blob + 1, 1); + } + bool IsTheEmptyBlob() const { return data_ == EmptyBlob().data_; } + const uint8_t *data() const { return data_; } +}; + +class Vector : public Sized { + public: + Vector(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {} + + Reference operator[](size_t i) const; + + static Vector EmptyVector() { + static const uint8_t empty_vector[] = { 0 /*len*/ }; + return Vector(empty_vector + 1, 1); + } + bool IsTheEmptyVector() const { return data_ == EmptyVector().data_; } +}; + +class TypedVector : public Sized { + public: + TypedVector(const uint8_t *data, uint8_t byte_width, Type element_type) + : Sized(data, byte_width), type_(element_type) {} + + Reference operator[](size_t i) const; + + static TypedVector EmptyTypedVector() { + static const uint8_t empty_typed_vector[] = { 0 /*len*/ }; + return TypedVector(empty_typed_vector + 1, 1, FBT_INT); + } + bool IsTheEmptyVector() const { + return data_ == TypedVector::EmptyTypedVector().data_; + } + + Type ElementType() { return type_; } + + friend Reference; + + private: + Type type_; + + friend Map; +}; + +class FixedTypedVector : public Object { + public: + FixedTypedVector(const uint8_t *data, uint8_t byte_width, Type element_type, + uint8_t len) + : Object(data, byte_width), type_(element_type), len_(len) {} + + Reference operator[](size_t i) const; + + static FixedTypedVector EmptyFixedTypedVector() { + static const uint8_t fixed_empty_vector[] = { 0 /* unused */ }; + return FixedTypedVector(fixed_empty_vector, 1, FBT_INT, 0); + } + bool IsTheEmptyFixedTypedVector() const { + return data_ == FixedTypedVector::EmptyFixedTypedVector().data_; + } + + Type ElementType() const { return type_; } + uint8_t size() const { return len_; } + + private: + Type type_; + uint8_t len_; +}; + +class Map : public Vector { + public: + Map(const uint8_t *data, uint8_t byte_width) : Vector(data, byte_width) {} + + Reference operator[](const char *key) const; + Reference operator[](const std::string &key) const; + + Vector Values() const { return Vector(data_, byte_width_); } + + TypedVector Keys() const { + const size_t num_prefixed_fields = 3; + auto keys_offset = data_ - byte_width_ * num_prefixed_fields; + return TypedVector(Indirect(keys_offset, byte_width_), + static_cast( + ReadUInt64(keys_offset + byte_width_, byte_width_)), + FBT_KEY); + } + + static Map EmptyMap() { + static const uint8_t empty_map[] = { + 0 /*keys_len*/, 0 /*keys_offset*/, 1 /*keys_width*/, 0 /*len*/ + }; + return Map(empty_map + 4, 1); + } + + bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; } +}; + +template +void AppendToString(std::string &s, T &&v, bool keys_quoted) { + s += "[ "; + for (size_t i = 0; i < v.size(); i++) { + if (i) s += ", "; + v[i].ToString(true, keys_quoted, s); + } + s += " ]"; +} + +class Reference { + public: + Reference() + : data_(nullptr), parent_width_(0), byte_width_(0), type_(FBT_NULL) {} + + Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width, + Type type) + : data_(data), + parent_width_(parent_width), + byte_width_(byte_width), + type_(type) {} + + Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type) + : data_(data), parent_width_(parent_width) { + byte_width_ = 1U << static_cast(packed_type & 3); + type_ = static_cast(packed_type >> 2); + } + + Type GetType() const { return type_; } + + bool IsNull() const { return type_ == FBT_NULL; } + bool IsBool() const { return type_ == FBT_BOOL; } + bool IsInt() const { return type_ == FBT_INT || type_ == FBT_INDIRECT_INT; } + bool IsUInt() const { + return type_ == FBT_UINT || type_ == FBT_INDIRECT_UINT; + } + bool IsIntOrUint() const { return IsInt() || IsUInt(); } + bool IsFloat() const { + return type_ == FBT_FLOAT || type_ == FBT_INDIRECT_FLOAT; + } + bool IsNumeric() const { return IsIntOrUint() || IsFloat(); } + bool IsString() const { return type_ == FBT_STRING; } + bool IsKey() const { return type_ == FBT_KEY; } + bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; } + bool IsUntypedVector() const { return type_ == FBT_VECTOR; } + bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); } + bool IsFixedTypedVector() const { + return flexbuffers::IsFixedTypedVector(type_); + } + bool IsAnyVector() const { + return (IsTypedVector() || IsFixedTypedVector() || IsVector()); + } + bool IsMap() const { return type_ == FBT_MAP; } + bool IsBlob() const { return type_ == FBT_BLOB; } + bool AsBool() const { + return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_) + : AsUInt64()) != 0; + } + + // Reads any type as a int64_t. Never fails, does most sensible conversion. + // Truncates floats, strings are attempted to be parsed for a number, + // vectors/maps return their size. Returns 0 if all else fails. + int64_t AsInt64() const { + if (type_ == FBT_INT) { + // A fast path for the common case. + return ReadInt64(data_, parent_width_); + } else + switch (type_) { + case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_); + case FBT_UINT: return ReadUInt64(data_, parent_width_); + case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_); + case FBT_FLOAT: + return static_cast(ReadDouble(data_, parent_width_)); + case FBT_INDIRECT_FLOAT: + return static_cast(ReadDouble(Indirect(), byte_width_)); + case FBT_NULL: return 0; + case FBT_STRING: return flatbuffers::StringToInt(AsString().c_str()); + case FBT_VECTOR: return static_cast(AsVector().size()); + case FBT_BOOL: return ReadInt64(data_, parent_width_); + default: + // Convert other things to int. + return 0; + } + } + + // TODO: could specialize these to not use AsInt64() if that saves + // extension ops in generated code, and use a faster op than ReadInt64. + int32_t AsInt32() const { return static_cast(AsInt64()); } + int16_t AsInt16() const { return static_cast(AsInt64()); } + int8_t AsInt8() const { return static_cast(AsInt64()); } + + uint64_t AsUInt64() const { + if (type_ == FBT_UINT) { + // A fast path for the common case. + return ReadUInt64(data_, parent_width_); + } else + switch (type_) { + case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_); + case FBT_INT: return ReadInt64(data_, parent_width_); + case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_); + case FBT_FLOAT: + return static_cast(ReadDouble(data_, parent_width_)); + case FBT_INDIRECT_FLOAT: + return static_cast(ReadDouble(Indirect(), byte_width_)); + case FBT_NULL: return 0; + case FBT_STRING: return flatbuffers::StringToUInt(AsString().c_str()); + case FBT_VECTOR: return static_cast(AsVector().size()); + case FBT_BOOL: return ReadUInt64(data_, parent_width_); + default: + // Convert other things to uint. + return 0; + } + } + + uint32_t AsUInt32() const { return static_cast(AsUInt64()); } + uint16_t AsUInt16() const { return static_cast(AsUInt64()); } + uint8_t AsUInt8() const { return static_cast(AsUInt64()); } + + double AsDouble() const { + if (type_ == FBT_FLOAT) { + // A fast path for the common case. + return ReadDouble(data_, parent_width_); + } else + switch (type_) { + case FBT_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_); + case FBT_INT: + return static_cast(ReadInt64(data_, parent_width_)); + case FBT_UINT: + return static_cast(ReadUInt64(data_, parent_width_)); + case FBT_INDIRECT_INT: + return static_cast(ReadInt64(Indirect(), byte_width_)); + case FBT_INDIRECT_UINT: + return static_cast(ReadUInt64(Indirect(), byte_width_)); + case FBT_NULL: return 0.0; + case FBT_STRING: { +#if 1 +#if !defined( _MSC_VER) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnull-dereference" +#endif + // See b/173239141 for additional context. Patched via + // micro/tools/make/flexbuffers_download.sh + // Introduce a segfault for an unsupported code path for TFLM. + return *(static_cast(nullptr)); +#if !defined( _MSC_VER) +#pragma GCC diagnostic pop +#endif +#else + // This is the original code + double d; + flatbuffers::StringToNumber(AsString().c_str(), &d); + return d; +#endif + } + case FBT_VECTOR: return static_cast(AsVector().size()); + case FBT_BOOL: + return static_cast(ReadUInt64(data_, parent_width_)); + default: + // Convert strings and other things to float. + return 0; + } + } + + float AsFloat() const { return static_cast(AsDouble()); } + + const char *AsKey() const { + if (type_ == FBT_KEY || type_ == FBT_STRING) { + return reinterpret_cast(Indirect()); + } else { + return ""; + } + } + + // This function returns the empty string if you try to read something that + // is not a string or key. + String AsString() const { + if (type_ == FBT_STRING) { + return String(Indirect(), byte_width_); + } else if (type_ == FBT_KEY) { + auto key = Indirect(); + return String(key, byte_width_, + strlen(reinterpret_cast(key))); + } else { + return String::EmptyString(); + } + } + + // Unlike AsString(), this will convert any type to a std::string. + std::string ToString() const { + std::string s; + ToString(false, false, s); + return s; + } + + // Convert any type to a JSON-like string. strings_quoted determines if + // string values at the top level receive "" quotes (inside other values + // they always do). keys_quoted determines if keys are quoted, at any level. + // TODO(wvo): add further options to have indentation/newlines. + void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const { + if (type_ == FBT_STRING) { + String _str(Indirect(), byte_width_); + if (strings_quoted) { + flatbuffers::EscapeString(_str.c_str(), _str.length(), &s, true, false); + } else { + s.append(_str.c_str(), _str.length()); + } + } else if (IsKey()) { + auto str = AsKey(); + if (keys_quoted) { + flatbuffers::EscapeString(str, strlen(str), &s, true, false); + } else { + s += str; + } + } else if (IsInt()) { + s += flatbuffers::NumToString(AsInt64()); + } else if (IsUInt()) { + s += flatbuffers::NumToString(AsUInt64()); + } else if (IsFloat()) { + s += flatbuffers::NumToString(AsDouble()); + } else if (IsNull()) { + s += "null"; + } else if (IsBool()) { + s += AsBool() ? "true" : "false"; + } else if (IsMap()) { + s += "{ "; + auto m = AsMap(); + auto keys = m.Keys(); + auto vals = m.Values(); + for (size_t i = 0; i < keys.size(); i++) { + bool kq = keys_quoted; + if (!kq) { + // FlexBuffers keys may contain arbitrary characters, only allow + // unquoted if it looks like an "identifier": + const char *p = keys[i].AsKey(); + if (!flatbuffers::is_alpha(*p) && *p != '_') { + kq = true; + } else { + while (*++p) { + if (!flatbuffers::is_alnum(*p) && *p != '_') { + kq = true; + break; + } + } + } + } + keys[i].ToString(true, kq, s); + s += ": "; + vals[i].ToString(true, keys_quoted, s); + if (i < keys.size() - 1) s += ", "; + } + s += " }"; + } else if (IsVector()) { + AppendToString(s, AsVector(), keys_quoted); + } else if (IsTypedVector()) { + AppendToString(s, AsTypedVector(), keys_quoted); + } else if (IsFixedTypedVector()) { + AppendToString(s, AsFixedTypedVector(), keys_quoted); + } else if (IsBlob()) { + auto blob = AsBlob(); + flatbuffers::EscapeString(reinterpret_cast(blob.data()), + blob.size(), &s, true, false); + } else { + s += "(?)"; + } + } + + // This function returns the empty blob if you try to read a not-blob. + // Strings can be viewed as blobs too. + Blob AsBlob() const { + if (type_ == FBT_BLOB || type_ == FBT_STRING) { + return Blob(Indirect(), byte_width_); + } else { + return Blob::EmptyBlob(); + } + } + + // This function returns the empty vector if you try to read a not-vector. + // Maps can be viewed as vectors too. + Vector AsVector() const { + if (type_ == FBT_VECTOR || type_ == FBT_MAP) { + return Vector(Indirect(), byte_width_); + } else { + return Vector::EmptyVector(); + } + } + + TypedVector AsTypedVector() const { + if (IsTypedVector()) { + auto tv = + TypedVector(Indirect(), byte_width_, ToTypedVectorElementType(type_)); + if (tv.type_ == FBT_STRING) { + // These can't be accessed as strings, since we don't know the bit-width + // of the size field, see the declaration of + // FBT_VECTOR_STRING_DEPRECATED above for details. + // We change the type here to be keys, which are a subtype of strings, + // and will ignore the size field. This will truncate strings with + // embedded nulls. + tv.type_ = FBT_KEY; + } + return tv; + } else { + return TypedVector::EmptyTypedVector(); + } + } + + FixedTypedVector AsFixedTypedVector() const { + if (IsFixedTypedVector()) { + uint8_t len = 0; + auto vtype = ToFixedTypedVectorElementType(type_, &len); + return FixedTypedVector(Indirect(), byte_width_, vtype, len); + } else { + return FixedTypedVector::EmptyFixedTypedVector(); + } + } + + Map AsMap() const { + if (type_ == FBT_MAP) { + return Map(Indirect(), byte_width_); + } else { + return Map::EmptyMap(); + } + } + + template T As() const; + + // Experimental: Mutation functions. + // These allow scalars in an already created buffer to be updated in-place. + // Since by default scalars are stored in the smallest possible space, + // the new value may not fit, in which case these functions return false. + // To avoid this, you can construct the values you intend to mutate using + // Builder::ForceMinimumBitWidth. + bool MutateInt(int64_t i) { + if (type_ == FBT_INT) { + return Mutate(data_, i, parent_width_, WidthI(i)); + } else if (type_ == FBT_INDIRECT_INT) { + return Mutate(Indirect(), i, byte_width_, WidthI(i)); + } else if (type_ == FBT_UINT) { + auto u = static_cast(i); + return Mutate(data_, u, parent_width_, WidthU(u)); + } else if (type_ == FBT_INDIRECT_UINT) { + auto u = static_cast(i); + return Mutate(Indirect(), u, byte_width_, WidthU(u)); + } else { + return false; + } + } + + bool MutateBool(bool b) { + return type_ == FBT_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8); + } + + bool MutateUInt(uint64_t u) { + if (type_ == FBT_UINT) { + return Mutate(data_, u, parent_width_, WidthU(u)); + } else if (type_ == FBT_INDIRECT_UINT) { + return Mutate(Indirect(), u, byte_width_, WidthU(u)); + } else if (type_ == FBT_INT) { + auto i = static_cast(u); + return Mutate(data_, i, parent_width_, WidthI(i)); + } else if (type_ == FBT_INDIRECT_INT) { + auto i = static_cast(u); + return Mutate(Indirect(), i, byte_width_, WidthI(i)); + } else { + return false; + } + } + + bool MutateFloat(float f) { + if (type_ == FBT_FLOAT) { + return MutateF(data_, f, parent_width_, BIT_WIDTH_32); + } else if (type_ == FBT_INDIRECT_FLOAT) { + return MutateF(Indirect(), f, byte_width_, BIT_WIDTH_32); + } else { + return false; + } + } + + bool MutateFloat(double d) { + if (type_ == FBT_FLOAT) { + return MutateF(data_, d, parent_width_, WidthF(d)); + } else if (type_ == FBT_INDIRECT_FLOAT) { + return MutateF(Indirect(), d, byte_width_, WidthF(d)); + } else { + return false; + } + } + + bool MutateString(const char *str, size_t len) { + auto s = AsString(); + if (s.IsTheEmptyString()) return false; + // This is very strict, could allow shorter strings, but that creates + // garbage. + if (s.length() != len) return false; + memcpy(const_cast(s.c_str()), str, len); + return true; + } + bool MutateString(const char *str) { return MutateString(str, strlen(str)); } + bool MutateString(const std::string &str) { + return MutateString(str.data(), str.length()); + } + + private: + const uint8_t *Indirect() const { + return flexbuffers::Indirect(data_, parent_width_); + } + + template + bool Mutate(const uint8_t *dest, T t, size_t byte_width, + BitWidth value_width) { + auto fits = static_cast(static_cast(1U) << value_width) <= + byte_width; + if (fits) { + t = flatbuffers::EndianScalar(t); + memcpy(const_cast(dest), &t, byte_width); + } + return fits; + } + + template + bool MutateF(const uint8_t *dest, T t, size_t byte_width, + BitWidth value_width) { + if (byte_width == sizeof(double)) + return Mutate(dest, static_cast(t), byte_width, value_width); + if (byte_width == sizeof(float)) + return Mutate(dest, static_cast(t), byte_width, value_width); + FLATBUFFERS_ASSERT(false); + return false; + } + + friend class Verifier; + + const uint8_t *data_; + uint8_t parent_width_; + uint8_t byte_width_; + Type type_; +}; + +// Template specialization for As(). +template<> inline bool Reference::As() const { return AsBool(); } + +template<> inline int8_t Reference::As() const { return AsInt8(); } +template<> inline int16_t Reference::As() const { return AsInt16(); } +template<> inline int32_t Reference::As() const { return AsInt32(); } +template<> inline int64_t Reference::As() const { return AsInt64(); } + +template<> inline uint8_t Reference::As() const { return AsUInt8(); } +template<> inline uint16_t Reference::As() const { + return AsUInt16(); +} +template<> inline uint32_t Reference::As() const { + return AsUInt32(); +} +template<> inline uint64_t Reference::As() const { + return AsUInt64(); +} + +template<> inline double Reference::As() const { return AsDouble(); } +template<> inline float Reference::As() const { return AsFloat(); } + +template<> inline String Reference::As() const { return AsString(); } +template<> inline std::string Reference::As() const { + return AsString().str(); +} + +template<> inline Blob Reference::As() const { return AsBlob(); } +template<> inline Vector Reference::As() const { return AsVector(); } +template<> inline TypedVector Reference::As() const { + return AsTypedVector(); +} +template<> inline FixedTypedVector Reference::As() const { + return AsFixedTypedVector(); +} +template<> inline Map Reference::As() const { return AsMap(); } + +inline uint8_t PackedType(BitWidth bit_width, Type type) { + return static_cast(bit_width | (type << 2)); +} + +inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, FBT_NULL); } + +// Vector accessors. +// Note: if you try to access outside of bounds, you get a Null value back +// instead. Normally this would be an assert, but since this is "dynamically +// typed" data, you may not want that (someone sends you a 2d vector and you +// wanted 3d). +// The Null converts seamlessly into a default value for any other type. +// TODO(wvo): Could introduce an #ifdef that makes this into an assert? +inline Reference Vector::operator[](size_t i) const { + auto len = size(); + if (i >= len) return Reference(nullptr, 1, NullPackedType()); + auto packed_type = (data_ + len * byte_width_)[i]; + auto elem = data_ + i * byte_width_; + return Reference(elem, byte_width_, packed_type); +} + +inline Reference TypedVector::operator[](size_t i) const { + auto len = size(); + if (i >= len) return Reference(nullptr, 1, NullPackedType()); + auto elem = data_ + i * byte_width_; + return Reference(elem, byte_width_, 1, type_); +} + +inline Reference FixedTypedVector::operator[](size_t i) const { + if (i >= len_) return Reference(nullptr, 1, NullPackedType()); + auto elem = data_ + i * byte_width_; + return Reference(elem, byte_width_, 1, type_); +} + +template int KeyCompare(const void *key, const void *elem) { + auto str_elem = reinterpret_cast( + Indirect(reinterpret_cast(elem))); + auto skey = reinterpret_cast(key); + return strcmp(skey, str_elem); +} + +inline Reference Map::operator[](const char *key) const { + auto keys = Keys(); + // We can't pass keys.byte_width_ to the comparison function, so we have + // to pick the right one ahead of time. + int (*comp)(const void *, const void *) = nullptr; + switch (keys.byte_width_) { + case 1: comp = KeyCompare; break; + case 2: comp = KeyCompare; break; + case 4: comp = KeyCompare; break; + case 8: comp = KeyCompare; break; + default: FLATBUFFERS_ASSERT(false); return Reference(); + } + auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp); + if (!res) return Reference(nullptr, 1, NullPackedType()); + auto i = (reinterpret_cast(res) - keys.data_) / keys.byte_width_; + return (*static_cast(this))[i]; +} + +inline Reference Map::operator[](const std::string &key) const { + return (*this)[key.c_str()]; +} + +inline Reference GetRoot(const uint8_t *buffer, size_t size) { + // See Finish() below for the serialization counterpart of this. + // The root starts at the end of the buffer, so we parse backwards from there. + auto end = buffer + size; + auto byte_width = *--end; + auto packed_type = *--end; + end -= byte_width; // The root data item. + return Reference(end, byte_width, packed_type); +} + +inline Reference GetRoot(const std::vector &buffer) { + return GetRoot(buffer.data(), buffer.size()); +} + +// Flags that configure how the Builder behaves. +// The "Share" flags determine if the Builder automatically tries to pool +// this type. Pooling can reduce the size of serialized data if there are +// multiple maps of the same kind, at the expense of slightly slower +// serialization (the cost of lookups) and more memory use (std::set). +// By default this is on for keys, but off for strings. +// Turn keys off if you have e.g. only one map. +// Turn strings on if you expect many non-unique string values. +// Additionally, sharing key vectors can save space if you have maps with +// identical field populations. +enum BuilderFlag { + BUILDER_FLAG_NONE = 0, + BUILDER_FLAG_SHARE_KEYS = 1, + BUILDER_FLAG_SHARE_STRINGS = 2, + BUILDER_FLAG_SHARE_KEYS_AND_STRINGS = 3, + BUILDER_FLAG_SHARE_KEY_VECTORS = 4, + BUILDER_FLAG_SHARE_ALL = 7, +}; + +class Builder FLATBUFFERS_FINAL_CLASS { + public: + Builder(size_t initial_size = 256, + BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS) + : buf_(initial_size), + finished_(false), + has_duplicate_keys_(false), + flags_(flags), + force_min_bit_width_(BIT_WIDTH_8), + key_pool(KeyOffsetCompare(buf_)), + string_pool(StringOffsetCompare(buf_)) { + buf_.clear(); + } + +#ifdef FLATBUFFERS_DEFAULT_DECLARATION + Builder(Builder &&) = default; + Builder &operator=(Builder &&) = default; +#endif + + /// @brief Get the serialized buffer (after you call `Finish()`). + /// @return Returns a vector owned by this class. + const std::vector &GetBuffer() const { + Finished(); + return buf_; + } + + // Size of the buffer. Does not include unfinished values. + size_t GetSize() const { return buf_.size(); } + + // Reset all state so we can re-use the buffer. + void Clear() { + buf_.clear(); + stack_.clear(); + finished_ = false; + // flags_ remains as-is; + force_min_bit_width_ = BIT_WIDTH_8; + key_pool.clear(); + string_pool.clear(); + } + + // All value constructing functions below have two versions: one that + // takes a key (for placement inside a map) and one that doesn't (for inside + // vectors and elsewhere). + + void Null() { stack_.push_back(Value()); } + void Null(const char *key) { + Key(key); + Null(); + } + + void Int(int64_t i) { stack_.push_back(Value(i, FBT_INT, WidthI(i))); } + void Int(const char *key, int64_t i) { + Key(key); + Int(i); + } + + void UInt(uint64_t u) { stack_.push_back(Value(u, FBT_UINT, WidthU(u))); } + void UInt(const char *key, uint64_t u) { + Key(key); + UInt(u); + } + + void Float(float f) { stack_.push_back(Value(f)); } + void Float(const char *key, float f) { + Key(key); + Float(f); + } + + void Double(double f) { stack_.push_back(Value(f)); } + void Double(const char *key, double d) { + Key(key); + Double(d); + } + + void Bool(bool b) { stack_.push_back(Value(b)); } + void Bool(const char *key, bool b) { + Key(key); + Bool(b); + } + + void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); } + void IndirectInt(const char *key, int64_t i) { + Key(key); + IndirectInt(i); + } + + void IndirectUInt(uint64_t u) { + PushIndirect(u, FBT_INDIRECT_UINT, WidthU(u)); + } + void IndirectUInt(const char *key, uint64_t u) { + Key(key); + IndirectUInt(u); + } + + void IndirectFloat(float f) { + PushIndirect(f, FBT_INDIRECT_FLOAT, BIT_WIDTH_32); + } + void IndirectFloat(const char *key, float f) { + Key(key); + IndirectFloat(f); + } + + void IndirectDouble(double f) { + PushIndirect(f, FBT_INDIRECT_FLOAT, WidthF(f)); + } + void IndirectDouble(const char *key, double d) { + Key(key); + IndirectDouble(d); + } + + size_t Key(const char *str, size_t len) { + auto sloc = buf_.size(); + WriteBytes(str, len + 1); + if (flags_ & BUILDER_FLAG_SHARE_KEYS) { + auto it = key_pool.find(sloc); + if (it != key_pool.end()) { + // Already in the buffer. Remove key we just serialized, and use + // existing offset instead. + buf_.resize(sloc); + sloc = *it; + } else { + key_pool.insert(sloc); + } + } + stack_.push_back(Value(static_cast(sloc), FBT_KEY, BIT_WIDTH_8)); + return sloc; + } + + size_t Key(const char *str) { return Key(str, strlen(str)); } + size_t Key(const std::string &str) { return Key(str.c_str(), str.size()); } + + size_t String(const char *str, size_t len) { + auto reset_to = buf_.size(); + auto sloc = CreateBlob(str, len, 1, FBT_STRING); + if (flags_ & BUILDER_FLAG_SHARE_STRINGS) { + StringOffset so(sloc, len); + auto it = string_pool.find(so); + if (it != string_pool.end()) { + // Already in the buffer. Remove string we just serialized, and use + // existing offset instead. + buf_.resize(reset_to); + sloc = it->first; + stack_.back().u_ = sloc; + } else { + string_pool.insert(so); + } + } + return sloc; + } + size_t String(const char *str) { return String(str, strlen(str)); } + size_t String(const std::string &str) { + return String(str.c_str(), str.size()); + } + void String(const flexbuffers::String &str) { + String(str.c_str(), str.length()); + } + + void String(const char *key, const char *str) { + Key(key); + String(str); + } + void String(const char *key, const std::string &str) { + Key(key); + String(str); + } + void String(const char *key, const flexbuffers::String &str) { + Key(key); + String(str); + } + + size_t Blob(const void *data, size_t len) { + return CreateBlob(data, len, 0, FBT_BLOB); + } + size_t Blob(const std::vector &v) { + return CreateBlob(v.data(), v.size(), 0, FBT_BLOB); + } + + void Blob(const char *key, const void *data, size_t len) { + Key(key); + Blob(data, len); + } + void Blob(const char *key, const std::vector &v) { + Key(key); + Blob(v); + } + + // TODO(wvo): support all the FlexBuffer types (like flexbuffers::String), + // e.g. Vector etc. Also in overloaded versions. + // Also some FlatBuffers types? + + size_t StartVector() { return stack_.size(); } + size_t StartVector(const char *key) { + Key(key); + return stack_.size(); + } + size_t StartMap() { return stack_.size(); } + size_t StartMap(const char *key) { + Key(key); + return stack_.size(); + } + + // TODO(wvo): allow this to specify an alignment greater than the natural + // alignment. + size_t EndVector(size_t start, bool typed, bool fixed) { + auto vec = CreateVector(start, stack_.size() - start, 1, typed, fixed); + // Remove temp elements and return vector. + stack_.resize(start); + stack_.push_back(vec); + return static_cast(vec.u_); + } + + size_t EndMap(size_t start) { + // We should have interleaved keys and values on the stack. + // Make sure it is an even number: + auto len = stack_.size() - start; + FLATBUFFERS_ASSERT(!(len & 1)); + len /= 2; + // Make sure keys are all strings: + for (auto key = start; key < stack_.size(); key += 2) { + FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY); + } + // Now sort values, so later we can do a binary search lookup. + // We want to sort 2 array elements at a time. + struct TwoValue { + Value key; + Value val; + }; + // TODO(wvo): strict aliasing? + // TODO(wvo): allow the caller to indicate the data is already sorted + // for maximum efficiency? With an assert to check sortedness to make sure + // we're not breaking binary search. + // Or, we can track if the map is sorted as keys are added which would be + // be quite cheap (cheaper than checking it here), so we can skip this + // step automatically when appliccable, and encourage people to write in + // sorted fashion. + // std::sort is typically already a lot faster on sorted data though. + auto dict = reinterpret_cast(stack_.data() + start); + std::sort( + dict, dict + len, [&](const TwoValue &a, const TwoValue &b) -> bool { + auto as = reinterpret_cast(buf_.data() + a.key.u_); + auto bs = reinterpret_cast(buf_.data() + b.key.u_); + auto comp = strcmp(as, bs); + // We want to disallow duplicate keys, since this results in a + // map where values cannot be found. + // But we can't assert here (since we don't want to fail on + // random JSON input) or have an error mechanism. + // Instead, we set has_duplicate_keys_ in the builder to + // signal this. + // TODO: Have to check for pointer equality, as some sort + // implementation apparently call this function with the same + // element?? Why? + if (!comp && &a != &b) has_duplicate_keys_ = true; + return comp < 0; + }); + // First create a vector out of all keys. + // TODO(wvo): if kBuilderFlagShareKeyVectors is true, see if we can share + // the first vector. + auto keys = CreateVector(start, len, 2, true, false); + auto vec = CreateVector(start + 1, len, 2, false, false, &keys); + // Remove temp elements and return map. + stack_.resize(start); + stack_.push_back(vec); + return static_cast(vec.u_); + } + + // Call this after EndMap to see if the map had any duplicate keys. + // Any map with such keys won't be able to retrieve all values. + bool HasDuplicateKeys() const { return has_duplicate_keys_; } + + template size_t Vector(F f) { + auto start = StartVector(); + f(); + return EndVector(start, false, false); + } + template size_t Vector(F f, T &state) { + auto start = StartVector(); + f(state); + return EndVector(start, false, false); + } + template size_t Vector(const char *key, F f) { + auto start = StartVector(key); + f(); + return EndVector(start, false, false); + } + template + size_t Vector(const char *key, F f, T &state) { + auto start = StartVector(key); + f(state); + return EndVector(start, false, false); + } + + template void Vector(const T *elems, size_t len) { + if (flatbuffers::is_scalar::value) { + // This path should be a lot quicker and use less space. + ScalarVector(elems, len, false); + } else { + auto start = StartVector(); + for (size_t i = 0; i < len; i++) Add(elems[i]); + EndVector(start, false, false); + } + } + template + void Vector(const char *key, const T *elems, size_t len) { + Key(key); + Vector(elems, len); + } + template void Vector(const std::vector &vec) { + Vector(vec.data(), vec.size()); + } + + template size_t TypedVector(F f) { + auto start = StartVector(); + f(); + return EndVector(start, true, false); + } + template size_t TypedVector(F f, T &state) { + auto start = StartVector(); + f(state); + return EndVector(start, true, false); + } + template size_t TypedVector(const char *key, F f) { + auto start = StartVector(key); + f(); + return EndVector(start, true, false); + } + template + size_t TypedVector(const char *key, F f, T &state) { + auto start = StartVector(key); + f(state); + return EndVector(start, true, false); + } + + template size_t FixedTypedVector(const T *elems, size_t len) { + // We only support a few fixed vector lengths. Anything bigger use a + // regular typed vector. + FLATBUFFERS_ASSERT(len >= 2 && len <= 4); + // And only scalar values. + static_assert(flatbuffers::is_scalar::value, "Unrelated types"); + return ScalarVector(elems, len, true); + } + + template + size_t FixedTypedVector(const char *key, const T *elems, size_t len) { + Key(key); + return FixedTypedVector(elems, len); + } + + template size_t Map(F f) { + auto start = StartMap(); + f(); + return EndMap(start); + } + template size_t Map(F f, T &state) { + auto start = StartMap(); + f(state); + return EndMap(start); + } + template size_t Map(const char *key, F f) { + auto start = StartMap(key); + f(); + return EndMap(start); + } + template size_t Map(const char *key, F f, T &state) { + auto start = StartMap(key); + f(state); + return EndMap(start); + } + template void Map(const std::map &map) { + auto start = StartMap(); + for (auto it = map.begin(); it != map.end(); ++it) + Add(it->first.c_str(), it->second); + EndMap(start); + } + + // If you wish to share a value explicitly (a value not shared automatically + // through one of the BUILDER_FLAG_SHARE_* flags) you can do so with these + // functions. Or if you wish to turn those flags off for performance reasons + // and still do some explicit sharing. For example: + // builder.IndirectDouble(M_PI); + // auto id = builder.LastValue(); // Remember where we stored it. + // .. more code goes here .. + // builder.ReuseValue(id); // Refers to same double by offset. + // LastValue works regardless of whether the value has a key or not. + // Works on any data type. + struct Value; + Value LastValue() { return stack_.back(); } + void ReuseValue(Value v) { stack_.push_back(v); } + void ReuseValue(const char *key, Value v) { + Key(key); + ReuseValue(v); + } + + // Overloaded Add that tries to call the correct function above. + void Add(int8_t i) { Int(i); } + void Add(int16_t i) { Int(i); } + void Add(int32_t i) { Int(i); } + void Add(int64_t i) { Int(i); } + void Add(uint8_t u) { UInt(u); } + void Add(uint16_t u) { UInt(u); } + void Add(uint32_t u) { UInt(u); } + void Add(uint64_t u) { UInt(u); } + void Add(float f) { Float(f); } + void Add(double d) { Double(d); } + void Add(bool b) { Bool(b); } + void Add(const char *str) { String(str); } + void Add(const std::string &str) { String(str); } + void Add(const flexbuffers::String &str) { String(str); } + + template void Add(const std::vector &vec) { Vector(vec); } + + template void Add(const char *key, const T &t) { + Key(key); + Add(t); + } + + template void Add(const std::map &map) { + Map(map); + } + + template void operator+=(const T &t) { Add(t); } + + // This function is useful in combination with the Mutate* functions above. + // It forces elements of vectors and maps to have a minimum size, such that + // they can later be updated without failing. + // Call with no arguments to reset. + void ForceMinimumBitWidth(BitWidth bw = BIT_WIDTH_8) { + force_min_bit_width_ = bw; + } + + void Finish() { + // If you hit this assert, you likely have objects that were never included + // in a parent. You need to have exactly one root to finish a buffer. + // Check your Start/End calls are matched, and all objects are inside + // some other object. + FLATBUFFERS_ASSERT(stack_.size() == 1); + + // Write root value. + auto byte_width = Align(stack_[0].ElemWidth(buf_.size(), 0)); + WriteAny(stack_[0], byte_width); + // Write root type. + Write(stack_[0].StoredPackedType(), 1); + // Write root size. Normally determined by parent, but root has no parent :) + Write(byte_width, 1); + + finished_ = true; + } + + private: + void Finished() const { + // If you get this assert, you're attempting to get access a buffer + // which hasn't been finished yet. Be sure to call + // Builder::Finish with your root object. + FLATBUFFERS_ASSERT(finished_); + } + + // Align to prepare for writing a scalar with a certain size. + uint8_t Align(BitWidth alignment) { + auto byte_width = 1U << alignment; + buf_.insert(buf_.end(), flatbuffers::PaddingBytes(buf_.size(), byte_width), + 0); + return static_cast(byte_width); + } + + void WriteBytes(const void *val, size_t size) { + buf_.insert(buf_.end(), reinterpret_cast(val), + reinterpret_cast(val) + size); + } + + template void Write(T val, size_t byte_width) { + FLATBUFFERS_ASSERT(sizeof(T) >= byte_width); + val = flatbuffers::EndianScalar(val); + WriteBytes(&val, byte_width); + } + + void WriteDouble(double f, uint8_t byte_width) { + switch (byte_width) { + case 8: Write(f, byte_width); break; + case 4: Write(static_cast(f), byte_width); break; + // case 2: Write(static_cast(f), byte_width); break; + // case 1: Write(static_cast(f), byte_width); break; + default: FLATBUFFERS_ASSERT(0); + } + } + + void WriteOffset(uint64_t o, uint8_t byte_width) { + auto reloff = buf_.size() - o; + FLATBUFFERS_ASSERT(byte_width == 8 || reloff < 1ULL << (byte_width * 8)); + Write(reloff, byte_width); + } + + template void PushIndirect(T val, Type type, BitWidth bit_width) { + auto byte_width = Align(bit_width); + auto iloc = buf_.size(); + Write(val, byte_width); + stack_.push_back(Value(static_cast(iloc), type, bit_width)); + } + + static BitWidth WidthB(size_t byte_width) { + switch (byte_width) { + case 1: return BIT_WIDTH_8; + case 2: return BIT_WIDTH_16; + case 4: return BIT_WIDTH_32; + case 8: return BIT_WIDTH_64; + default: FLATBUFFERS_ASSERT(false); return BIT_WIDTH_64; + } + } + + template static Type GetScalarType() { + static_assert(flatbuffers::is_scalar::value, "Unrelated types"); + return flatbuffers::is_floating_point::value + ? FBT_FLOAT + : flatbuffers::is_same::value + ? FBT_BOOL + : (flatbuffers::is_unsigned::value ? FBT_UINT + : FBT_INT); + } + + public: + // This was really intended to be private, except for LastValue/ReuseValue. + struct Value { + union { + int64_t i_; + uint64_t u_; + double f_; + }; + + Type type_; + + // For scalars: of itself, for vector: of its elements, for string: length. + BitWidth min_bit_width_; + + Value() : i_(0), type_(FBT_NULL), min_bit_width_(BIT_WIDTH_8) {} + + Value(bool b) + : u_(static_cast(b)), + type_(FBT_BOOL), + min_bit_width_(BIT_WIDTH_8) {} + + Value(int64_t i, Type t, BitWidth bw) + : i_(i), type_(t), min_bit_width_(bw) {} + Value(uint64_t u, Type t, BitWidth bw) + : u_(u), type_(t), min_bit_width_(bw) {} + + Value(float f) + : f_(static_cast(f)), + type_(FBT_FLOAT), + min_bit_width_(BIT_WIDTH_32) {} + Value(double f) : f_(f), type_(FBT_FLOAT), min_bit_width_(WidthF(f)) {} + + uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const { + return PackedType(StoredWidth(parent_bit_width_), type_); + } + + BitWidth ElemWidth(size_t buf_size, size_t elem_index) const { + if (IsInline(type_)) { + return min_bit_width_; + } else { + // We have an absolute offset, but want to store a relative offset + // elem_index elements beyond the current buffer end. Since whether + // the relative offset fits in a certain byte_width depends on + // the size of the elements before it (and their alignment), we have + // to test for each size in turn. + for (size_t byte_width = 1; + byte_width <= sizeof(flatbuffers::largest_scalar_t); + byte_width *= 2) { + // Where are we going to write this offset? + auto offset_loc = buf_size + + flatbuffers::PaddingBytes(buf_size, byte_width) + + elem_index * byte_width; + // Compute relative offset. + auto offset = offset_loc - u_; + // Does it fit? + auto bit_width = WidthU(offset); + if (static_cast(static_cast(1U) << bit_width) == + byte_width) + return bit_width; + } + FLATBUFFERS_ASSERT(false); // Must match one of the sizes above. + return BIT_WIDTH_64; + } + } + + BitWidth StoredWidth(BitWidth parent_bit_width_ = BIT_WIDTH_8) const { + if (IsInline(type_)) { + return (std::max)(min_bit_width_, parent_bit_width_); + } else { + return min_bit_width_; + } + } + }; + + private: + void WriteAny(const Value &val, uint8_t byte_width) { + switch (val.type_) { + case FBT_NULL: + case FBT_INT: Write(val.i_, byte_width); break; + case FBT_BOOL: + case FBT_UINT: Write(val.u_, byte_width); break; + case FBT_FLOAT: WriteDouble(val.f_, byte_width); break; + default: WriteOffset(val.u_, byte_width); break; + } + } + + size_t CreateBlob(const void *data, size_t len, size_t trailing, Type type) { + auto bit_width = WidthU(len); + auto byte_width = Align(bit_width); + Write(len, byte_width); + auto sloc = buf_.size(); + WriteBytes(data, len + trailing); + stack_.push_back(Value(static_cast(sloc), type, bit_width)); + return sloc; + } + + template + size_t ScalarVector(const T *elems, size_t len, bool fixed) { + auto vector_type = GetScalarType(); + auto byte_width = sizeof(T); + auto bit_width = WidthB(byte_width); + // If you get this assert, you're trying to write a vector with a size + // field that is bigger than the scalars you're trying to write (e.g. a + // byte vector > 255 elements). For such types, write a "blob" instead. + // TODO: instead of asserting, could write vector with larger elements + // instead, though that would be wasteful. + FLATBUFFERS_ASSERT(WidthU(len) <= bit_width); + Align(bit_width); + if (!fixed) Write(len, byte_width); + auto vloc = buf_.size(); + for (size_t i = 0; i < len; i++) Write(elems[i], byte_width); + stack_.push_back(Value(static_cast(vloc), + ToTypedVector(vector_type, fixed ? len : 0), + bit_width)); + return vloc; + } + + Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed, + bool fixed, const Value *keys = nullptr) { + FLATBUFFERS_ASSERT( + !fixed || + typed); // typed=false, fixed=true combination is not supported. + // Figure out smallest bit width we can store this vector with. + auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len)); + auto prefix_elems = 1; + if (keys) { + // If this vector is part of a map, we will pre-fix an offset to the keys + // to this vector. + bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0)); + prefix_elems += 2; + } + Type vector_type = FBT_KEY; + // Check bit widths and types for all elements. + for (size_t i = start; i < stack_.size(); i += step) { + auto elem_width = + stack_[i].ElemWidth(buf_.size(), i - start + prefix_elems); + bit_width = (std::max)(bit_width, elem_width); + if (typed) { + if (i == start) { + vector_type = stack_[i].type_; + } else { + // If you get this assert, you are writing a typed vector with + // elements that are not all the same type. + FLATBUFFERS_ASSERT(vector_type == stack_[i].type_); + } + } + } + // If you get this assert, your typed types are not one of: + // Int / UInt / Float / Key. + FLATBUFFERS_ASSERT(!typed || IsTypedVectorElementType(vector_type)); + auto byte_width = Align(bit_width); + // Write vector. First the keys width/offset if available, and size. + if (keys) { + WriteOffset(keys->u_, byte_width); + Write(1ULL << keys->min_bit_width_, byte_width); + } + if (!fixed) Write(vec_len, byte_width); + // Then the actual data. + auto vloc = buf_.size(); + for (size_t i = start; i < stack_.size(); i += step) { + WriteAny(stack_[i], byte_width); + } + // Then the types. + if (!typed) { + for (size_t i = start; i < stack_.size(); i += step) { + buf_.push_back(stack_[i].StoredPackedType(bit_width)); + } + } + return Value(static_cast(vloc), + keys ? FBT_MAP + : (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0) + : FBT_VECTOR), + bit_width); + } + + // You shouldn't really be copying instances of this class. + Builder(const Builder &); + Builder &operator=(const Builder &); + + std::vector buf_; + std::vector stack_; + + bool finished_; + bool has_duplicate_keys_; + + BuilderFlag flags_; + + BitWidth force_min_bit_width_; + + struct KeyOffsetCompare { + explicit KeyOffsetCompare(const std::vector &buf) : buf_(&buf) {} + bool operator()(size_t a, size_t b) const { + auto stra = reinterpret_cast(buf_->data() + a); + auto strb = reinterpret_cast(buf_->data() + b); + return strcmp(stra, strb) < 0; + } + const std::vector *buf_; + }; + + typedef std::pair StringOffset; + struct StringOffsetCompare { + explicit StringOffsetCompare(const std::vector &buf) + : buf_(&buf) {} + bool operator()(const StringOffset &a, const StringOffset &b) const { + auto stra = buf_->data() + a.first; + auto strb = buf_->data() + b.first; + auto cr = memcmp(stra, strb, (std::min)(a.second, b.second) + 1); + return cr < 0 || (cr == 0 && a.second < b.second); + } + const std::vector *buf_; + }; + + typedef std::set KeyOffsetMap; + typedef std::set StringOffsetMap; + + KeyOffsetMap key_pool; + StringOffsetMap string_pool; + + friend class Verifier; +}; + +// Helper class to verify the integrity of a FlexBuffer +class Verifier FLATBUFFERS_FINAL_CLASS { + public: + Verifier(const uint8_t *buf, size_t buf_len, + // Supplying this vector likely results in faster verification + // of larger buffers with many shared keys/strings, but + // comes at the cost of using additional memory the same size of + // the buffer being verified, so it is by default off. + std::vector *reuse_tracker = nullptr, + bool _check_alignment = true, size_t max_depth = 64) + : buf_(buf), + size_(buf_len), + depth_(0), + max_depth_(max_depth), + num_vectors_(0), + max_vectors_(buf_len), + check_alignment_(_check_alignment), + reuse_tracker_(reuse_tracker) { + FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE); + if (reuse_tracker_) { + reuse_tracker_->clear(); + reuse_tracker_->resize(size_, PackedType(BIT_WIDTH_8, FBT_NULL)); + } + } + + private: + // Central location where any verification failures register. + bool Check(bool ok) const { + // clang-format off + #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE + FLATBUFFERS_ASSERT(ok); + #endif + // clang-format on + return ok; + } + + // Verify any range within the buffer. + bool VerifyFrom(size_t elem, size_t elem_len) const { + return Check(elem_len < size_ && elem <= size_ - elem_len); + } + bool VerifyBefore(size_t elem, size_t elem_len) const { + return Check(elem_len <= elem); + } + + bool VerifyFromPointer(const uint8_t *p, size_t len) { + auto o = static_cast(p - buf_); + return VerifyFrom(o, len); + } + bool VerifyBeforePointer(const uint8_t *p, size_t len) { + auto o = static_cast(p - buf_); + return VerifyBefore(o, len); + } + + bool VerifyByteWidth(size_t width) { + return Check(width == 1 || width == 2 || width == 4 || width == 8); + } + + bool VerifyType(int type) { return Check(type >= 0 && type < FBT_MAX_TYPE); } + + bool VerifyOffset(uint64_t off, const uint8_t *p) { + return Check(off <= static_cast(size_)) && + off <= static_cast(p - buf_); + } + + bool VerifyAlignment(const uint8_t *p, size_t size) const { + auto o = static_cast(p - buf_); + return Check((o & (size - 1)) == 0 || !check_alignment_); + } + +// Macro, since we want to escape from parent function & use lazy args. +#define FLEX_CHECK_VERIFIED(P, PACKED_TYPE) \ + if (reuse_tracker_) { \ + auto packed_type = PACKED_TYPE; \ + auto existing = (*reuse_tracker_)[P - buf_]; \ + if (existing == packed_type) return true; \ + /* Fail verification if already set with different type! */ \ + if (!Check(existing == 0)) return false; \ + (*reuse_tracker_)[P - buf_] = packed_type; \ + } + + bool VerifyVector(Reference r, const uint8_t *p, Type elem_type) { + // Any kind of nesting goes thru this function, so guard against that + // here, both with simple nesting checks, and the reuse tracker if on. + depth_++; + num_vectors_++; + if (!Check(depth_ <= max_depth_ && num_vectors_ <= max_vectors_)) + return false; + auto size_byte_width = r.byte_width_; + if (!VerifyBeforePointer(p, size_byte_width)) return false; + FLEX_CHECK_VERIFIED(p - size_byte_width, + PackedType(Builder::WidthB(size_byte_width), r.type_)); + auto sized = Sized(p, size_byte_width); + auto num_elems = sized.size(); + auto elem_byte_width = r.type_ == FBT_STRING || r.type_ == FBT_BLOB + ? uint8_t(1) + : r.byte_width_; + auto max_elems = SIZE_MAX / elem_byte_width; + if (!Check(num_elems < max_elems)) + return false; // Protect against byte_size overflowing. + auto byte_size = num_elems * elem_byte_width; + if (!VerifyFromPointer(p, byte_size)) return false; + if (elem_type == FBT_NULL) { + // Verify type bytes after the vector. + if (!VerifyFromPointer(p + byte_size, num_elems)) return false; + auto v = Vector(p, size_byte_width); + for (size_t i = 0; i < num_elems; i++) + if (!VerifyRef(v[i])) return false; + } else if (elem_type == FBT_KEY) { + auto v = TypedVector(p, elem_byte_width, FBT_KEY); + for (size_t i = 0; i < num_elems; i++) + if (!VerifyRef(v[i])) return false; + } else { + FLATBUFFERS_ASSERT(IsInline(elem_type)); + } + depth_--; + return true; + } + + bool VerifyKeys(const uint8_t *p, uint8_t byte_width) { + // The vector part of the map has already been verified. + const size_t num_prefixed_fields = 3; + if (!VerifyBeforePointer(p, byte_width * num_prefixed_fields)) return false; + p -= byte_width * num_prefixed_fields; + auto off = ReadUInt64(p, byte_width); + if (!VerifyOffset(off, p)) return false; + auto key_byte_with = + static_cast(ReadUInt64(p + byte_width, byte_width)); + if (!VerifyByteWidth(key_byte_with)) return false; + return VerifyVector(Reference(p, byte_width, key_byte_with, FBT_VECTOR_KEY), + p - off, FBT_KEY); + } + + bool VerifyKey(const uint8_t *p) { + FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY)); + while (p < buf_ + size_) + if (*p++) return true; + return false; + } + +#undef FLEX_CHECK_VERIFIED + + bool VerifyTerminator(const String &s) { + return VerifyFromPointer(reinterpret_cast(s.c_str()), + s.size() + 1); + } + + bool VerifyRef(Reference r) { + // r.parent_width_ and r.data_ already verified. + if (!VerifyByteWidth(r.byte_width_) || !VerifyType(r.type_)) { + return false; + } + if (IsInline(r.type_)) { + // Inline scalars, don't require further verification. + return true; + } + // All remaining types are an offset. + auto off = ReadUInt64(r.data_, r.parent_width_); + if (!VerifyOffset(off, r.data_)) return false; + auto p = r.Indirect(); + if (!VerifyAlignment(p, r.byte_width_)) return false; + switch (r.type_) { + case FBT_INDIRECT_INT: + case FBT_INDIRECT_UINT: + case FBT_INDIRECT_FLOAT: return VerifyFromPointer(p, r.byte_width_); + case FBT_KEY: return VerifyKey(p); + case FBT_MAP: + return VerifyVector(r, p, FBT_NULL) && VerifyKeys(p, r.byte_width_); + case FBT_VECTOR: return VerifyVector(r, p, FBT_NULL); + case FBT_VECTOR_INT: return VerifyVector(r, p, FBT_INT); + case FBT_VECTOR_BOOL: + case FBT_VECTOR_UINT: return VerifyVector(r, p, FBT_UINT); + case FBT_VECTOR_FLOAT: return VerifyVector(r, p, FBT_FLOAT); + case FBT_VECTOR_KEY: return VerifyVector(r, p, FBT_KEY); + case FBT_VECTOR_STRING_DEPRECATED: + // Use of FBT_KEY here intentional, see elsewhere. + return VerifyVector(r, p, FBT_KEY); + case FBT_BLOB: return VerifyVector(r, p, FBT_UINT); + case FBT_STRING: + return VerifyVector(r, p, FBT_UINT) && + VerifyTerminator(String(p, r.byte_width_)); + case FBT_VECTOR_INT2: + case FBT_VECTOR_UINT2: + case FBT_VECTOR_FLOAT2: + case FBT_VECTOR_INT3: + case FBT_VECTOR_UINT3: + case FBT_VECTOR_FLOAT3: + case FBT_VECTOR_INT4: + case FBT_VECTOR_UINT4: + case FBT_VECTOR_FLOAT4: { + uint8_t len = 0; + auto vtype = ToFixedTypedVectorElementType(r.type_, &len); + if (!VerifyType(vtype)) return false; + return VerifyFromPointer(p, r.byte_width_ * len); + } + default: return false; + } + } + + public: + bool VerifyBuffer() { + if (!Check(size_ >= 3)) return false; + auto end = buf_ + size_; + auto byte_width = *--end; + auto packed_type = *--end; + return VerifyByteWidth(byte_width) && Check(end - buf_ >= byte_width) && + VerifyRef(Reference(end - byte_width, byte_width, packed_type)); + } + + private: + const uint8_t *buf_; + size_t size_; + size_t depth_; + const size_t max_depth_; + size_t num_vectors_; + const size_t max_vectors_; + bool check_alignment_; + std::vector *reuse_tracker_; +}; + +// Utility function that contructs the Verifier for you, see above for +// parameters. +inline bool VerifyBuffer(const uint8_t *buf, size_t buf_len, + std::vector *reuse_tracker = nullptr) { + Verifier verifier(buf, buf_len, reuse_tracker); + return verifier.VerifyBuffer(); +} + +} // namespace flexbuffers + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif // FLATBUFFERS_FLEXBUFFERS_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/stl_emulation.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/stl_emulation.h new file mode 100644 index 000000000..0b91f0d78 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/stl_emulation.h @@ -0,0 +1,509 @@ +/* + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_STL_EMULATION_H_ +#define FLATBUFFERS_STL_EMULATION_H_ + +// clang-format off +#include "third_party/flatbuffers/include/flatbuffers/base.h" + +#include +#include +#include +#include +#include + +#ifndef FLATBUFFERS_USE_STD_OPTIONAL + // Detect C++17 compatible compiler. + // __cplusplus >= 201703L - a compiler has support of 'static inline' variables. + #if (defined(__cplusplus) && __cplusplus >= 201703L) \ + || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + #define FLATBUFFERS_USE_STD_OPTIONAL 1 + #else + #define FLATBUFFERS_USE_STD_OPTIONAL 0 + #endif // (defined(__cplusplus) && __cplusplus >= 201703L) ... +#endif // FLATBUFFERS_USE_STD_OPTIONAL + +#if FLATBUFFERS_USE_STD_OPTIONAL + #include +#endif + +// The __cpp_lib_span is the predefined feature macro. +#if defined(FLATBUFFERS_USE_STD_SPAN) + #include +#elif defined(__cpp_lib_span) && defined(__has_include) + #if __has_include() + #include + #define FLATBUFFERS_USE_STD_SPAN + #endif +#else + // Disable non-trivial ctors if FLATBUFFERS_SPAN_MINIMAL defined. + #if !defined(FLATBUFFERS_TEMPLATES_ALIASES) + #define FLATBUFFERS_SPAN_MINIMAL + #else + // Enable implicit construction of a span from a std::array. + #include + #endif +#endif // defined(FLATBUFFERS_USE_STD_SPAN) + +// This header provides backwards compatibility for older versions of the STL. +namespace flatbuffers { + +#if defined(FLATBUFFERS_TEMPLATES_ALIASES) + template + using numeric_limits = std::numeric_limits; +#else + template class numeric_limits : + public std::numeric_limits {}; +#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) + +#if defined(FLATBUFFERS_TEMPLATES_ALIASES) + template using is_scalar = std::is_scalar; + template using is_same = std::is_same; + template using is_floating_point = std::is_floating_point; + template using is_unsigned = std::is_unsigned; + template using is_enum = std::is_enum; + template using make_unsigned = std::make_unsigned; + template + using conditional = std::conditional; + template + using integral_constant = std::integral_constant; + template + using bool_constant = integral_constant; + using true_type = std::true_type; + using false_type = std::false_type; +#else + // MSVC 2010 doesn't support C++11 aliases. + template struct is_scalar : public std::is_scalar {}; + template struct is_same : public std::is_same {}; + template struct is_floating_point : + public std::is_floating_point {}; + template struct is_unsigned : public std::is_unsigned {}; + template struct is_enum : public std::is_enum {}; + template struct make_unsigned : public std::make_unsigned {}; + template + struct conditional : public std::conditional {}; + template + struct integral_constant : public std::integral_constant {}; + template + struct bool_constant : public integral_constant {}; + typedef bool_constant true_type; + typedef bool_constant false_type; +#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) + +#if defined(FLATBUFFERS_TEMPLATES_ALIASES) + template using unique_ptr = std::unique_ptr; +#else + // MSVC 2010 doesn't support C++11 aliases. + // We're manually "aliasing" the class here as we want to bring unique_ptr + // into the flatbuffers namespace. We have unique_ptr in the flatbuffers + // namespace we have a completely independent implementation (see below) + // for C++98 STL implementations. + template class unique_ptr : public std::unique_ptr { + public: + unique_ptr() {} + explicit unique_ptr(T* p) : std::unique_ptr(p) {} + unique_ptr(std::unique_ptr&& u) { *this = std::move(u); } + unique_ptr(unique_ptr&& u) { *this = std::move(u); } + unique_ptr& operator=(std::unique_ptr&& u) { + std::unique_ptr::reset(u.release()); + return *this; + } + unique_ptr& operator=(unique_ptr&& u) { + std::unique_ptr::reset(u.release()); + return *this; + } + unique_ptr& operator=(T* p) { + return std::unique_ptr::operator=(p); + } + }; +#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) + +#if FLATBUFFERS_USE_STD_OPTIONAL +template +using Optional = std::optional; +using nullopt_t = std::nullopt_t; +inline constexpr nullopt_t nullopt = std::nullopt; + +#else +// Limited implementation of Optional type for a scalar T. +// This implementation limited by trivial types compatible with +// std::is_arithmetic or std::is_enum type traits. + +// A tag to indicate an empty flatbuffers::optional. +struct nullopt_t { + explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {} +}; + +#if defined(FLATBUFFERS_CONSTEXPR_DEFINED) + namespace internal { + template struct nullopt_holder { + static constexpr nullopt_t instance_ = nullopt_t(0); + }; + template + constexpr nullopt_t nullopt_holder::instance_; + } + static constexpr const nullopt_t &nullopt = internal::nullopt_holder::instance_; + +#else + namespace internal { + template struct nullopt_holder { + static const nullopt_t instance_; + }; + template + const nullopt_t nullopt_holder::instance_ = nullopt_t(0); + } + static const nullopt_t &nullopt = internal::nullopt_holder::instance_; + +#endif + +template +class Optional FLATBUFFERS_FINAL_CLASS { + // Non-scalar 'T' would extremely complicated Optional. + // Use is_scalar checking because flatbuffers flatbuffers::is_arithmetic + // isn't implemented. + static_assert(flatbuffers::is_scalar::value, "unexpected type T"); + + public: + ~Optional() {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT + : value_(), has_value_(false) {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT + : value_(), has_value_(false) {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT + : value_(val), has_value_(true) {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT + : value_(other.value_), has_value_(other.has_value_) {} + + FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT { + value_ = other.value_; + has_value_ = other.has_value_; + return *this; + } + + FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT { + value_ = T(); + has_value_ = false; + return *this; + } + + FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT { + value_ = val; + has_value_ = true; + return *this; + } + + void reset() FLATBUFFERS_NOEXCEPT { + *this = nullopt; + } + + void swap(Optional &other) FLATBUFFERS_NOEXCEPT { + std::swap(value_, other.value_); + std::swap(has_value_, other.has_value_); + } + + FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT { + return has_value_; + } + + FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT { + return has_value_; + } + + FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT { + return value_; + } + + const T& value() const { + FLATBUFFERS_ASSERT(has_value()); + return value_; + } + + T value_or(T default_value) const FLATBUFFERS_NOEXCEPT { + return has_value() ? value_ : default_value; + } + + private: + T value_; + bool has_value_; +}; + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional& opt, nullopt_t) FLATBUFFERS_NOEXCEPT { + return !opt; +} +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional& opt) FLATBUFFERS_NOEXCEPT { + return !opt; +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT { + return static_cast(lhs) && (*lhs == rhs); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional& rhs) FLATBUFFERS_NOEXCEPT { + return static_cast(rhs) && (lhs == *rhs); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional& lhs, const Optional& rhs) FLATBUFFERS_NOEXCEPT { + return static_cast(lhs) != static_cast(rhs) + ? false + : !static_cast(lhs) ? false : (*lhs == *rhs); +} +#endif // FLATBUFFERS_USE_STD_OPTIONAL + + +// Very limited and naive partial implementation of C++20 std::span. +#if defined(FLATBUFFERS_USE_STD_SPAN) + inline constexpr std::size_t dynamic_extent = std::dynamic_extent; + template + using span = std::span; + +#else // !defined(FLATBUFFERS_USE_STD_SPAN) +FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast(-1); + +// Exclude this code if MSVC2010 or non-STL Android is active. +// The non-STL Android doesn't have `std::is_convertible` required for SFINAE. +#if !defined(FLATBUFFERS_SPAN_MINIMAL) +namespace internal { + // This is SFINAE helper class for checking of a common condition: + // > This overload only participates in overload resolution + // > Check whether a pointer to an array of From can be converted + // > to a pointer to an array of To. + // This helper is used for checking of 'From -> const From'. + template + struct is_span_convertable { + using type = + typename std::conditional::value + && (Extent == dynamic_extent || N == Extent), + int, void>::type; + }; + + template + struct SpanIterator { + // TODO: upgrade to std::random_access_iterator_tag. + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = typename std::remove_cv::type; + using reference = T&; + using pointer = T*; + + // Convince MSVC compiler that this iterator is trusted (it is verified). + #ifdef _MSC_VER + using _Unchecked_type = pointer; + #endif // _MSC_VER + + SpanIterator(pointer ptr) : ptr_(ptr) {} + reference operator*() const { return *ptr_; } + pointer operator->() { return ptr_; } + SpanIterator& operator++() { ptr_++; return *this; } + SpanIterator operator++(int) { auto tmp = *this; ++(*this); return tmp; } + + friend bool operator== (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ == rhs.ptr_; } + friend bool operator!= (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ != rhs.ptr_; } + + private: + pointer ptr_; + }; +} // namespace internal +#endif // !defined(FLATBUFFERS_SPAN_MINIMAL) + +// T - element type; must be a complete type that is not an abstract +// class type. +// Extent - the number of elements in the sequence, or dynamic. +template +class span FLATBUFFERS_FINAL_CLASS { + public: + typedef T element_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef std::size_t size_type; + + static FLATBUFFERS_CONSTEXPR size_type extent = Extent; + + // Returns the number of elements in the span. + FLATBUFFERS_CONSTEXPR_CPP11 size_type size() const FLATBUFFERS_NOEXCEPT { + return count_; + } + + // Returns the size of the sequence in bytes. + FLATBUFFERS_CONSTEXPR_CPP11 + size_type size_bytes() const FLATBUFFERS_NOEXCEPT { + return size() * sizeof(element_type); + } + + // Checks if the span is empty. + FLATBUFFERS_CONSTEXPR_CPP11 bool empty() const FLATBUFFERS_NOEXCEPT { + return size() == 0; + } + + // Returns a pointer to the beginning of the sequence. + FLATBUFFERS_CONSTEXPR_CPP11 pointer data() const FLATBUFFERS_NOEXCEPT { + return data_; + } + + #if !defined(FLATBUFFERS_SPAN_MINIMAL) + using Iterator = internal::SpanIterator; + + Iterator begin() const { return Iterator(data()); } + Iterator end() const { return Iterator(data() + size()); } + #endif + + // Returns a reference to the idx-th element of the sequence. + // The behavior is undefined if the idx is greater than or equal to size(). + FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const { + return data()[idx]; + } + + FLATBUFFERS_CONSTEXPR_CPP11 span(const span &other) FLATBUFFERS_NOEXCEPT + : data_(other.data_), count_(other.count_) {} + + FLATBUFFERS_CONSTEXPR_CPP14 span &operator=(const span &other) + FLATBUFFERS_NOEXCEPT { + data_ = other.data_; + count_ = other.count_; + } + + // Limited implementation of + // `template constexpr std::span(It first, size_type count);`. + // + // Constructs a span that is a view over the range [first, first + count); + // the resulting span has: data() == first and size() == count. + // The behavior is undefined if [first, first + count) is not a valid range, + // or if (extent != flatbuffers::dynamic_extent && count != extent). + FLATBUFFERS_CONSTEXPR_CPP11 + explicit span(pointer first, size_type count) FLATBUFFERS_NOEXCEPT + : data_ (Extent == dynamic_extent ? first : (Extent == count ? first : nullptr)), + count_(Extent == dynamic_extent ? count : (Extent == count ? Extent : 0)) { + // Make span empty if the count argument is incompatible with span. + } + + // Exclude this code if MSVC2010 is active. The MSVC2010 isn't C++11 + // compliant, it doesn't support default template arguments for functions. + #if defined(FLATBUFFERS_SPAN_MINIMAL) + FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr), + count_(0) { + static_assert(extent == 0 || extent == dynamic_extent, "invalid span"); + } + + #else + // Constructs an empty span whose data() == nullptr and size() == 0. + // This overload only participates in overload resolution if + // extent == 0 || extent == flatbuffers::dynamic_extent. + // A dummy template argument N is need dependency for SFINAE. + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr), + count_(0) { + static_assert(extent == 0 || extent == dynamic_extent, "invalid span"); + } + + // Constructs a span that is a view over the array arr; the resulting span + // has size() == N and data() == std::data(arr). These overloads only + // participate in overload resolution if + // extent == std::dynamic_extent || N == extent is true and + // std::remove_pointer_t(*)[] + // is convertible to element_type (*)[]. + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT + : data_(arr), count_(N) {} + + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span(std::array &arr) FLATBUFFERS_NOEXCEPT + : data_(arr.data()), count_(N) {} + + //template + //FLATBUFFERS_CONSTEXPR_CPP11 span(std::array &arr) FLATBUFFERS_NOEXCEPT + // : data_(arr.data()), count_(N) {} + + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array &arr) FLATBUFFERS_NOEXCEPT + : data_(arr.data()), count_(N) {} + + // Converting constructor from another span s; + // the resulting span has size() == s.size() and data() == s.data(). + // This overload only participates in overload resolution + // if extent == std::dynamic_extent || N == extent is true and U (*)[] + // is convertible to element_type (*)[]. + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span &s) FLATBUFFERS_NOEXCEPT + : span(s.data(), s.size()) { + } + + #endif // !defined(FLATBUFFERS_SPAN_MINIMAL) + + private: + // This is a naive implementation with 'count_' member even if (Extent != dynamic_extent). + pointer const data_; + size_type count_; +}; +#endif // defined(FLATBUFFERS_USE_STD_SPAN) + +#if !defined(FLATBUFFERS_SPAN_MINIMAL) +template +FLATBUFFERS_CONSTEXPR_CPP11 +flatbuffers::span make_span(ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT { + return span(arr); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 +flatbuffers::span make_span(const ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT { + return span(arr); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 +flatbuffers::span make_span(std::array &arr) FLATBUFFERS_NOEXCEPT { + return span(arr); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 +flatbuffers::span make_span(const std::array &arr) FLATBUFFERS_NOEXCEPT { + return span(arr); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 +flatbuffers::span make_span(ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT { + return span(first, count); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 +flatbuffers::span make_span(const ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT { + return span(first, count); +} +#endif // !defined(FLATBUFFERS_SPAN_MINIMAL) + +} // namespace flatbuffers + +#endif // FLATBUFFERS_STL_EMULATION_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/string.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/string.h new file mode 100644 index 000000000..e08d96057 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/string.h @@ -0,0 +1,64 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_STRING_H_ +#define FLATBUFFERS_STRING_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/vector.h" + +namespace flatbuffers { + +struct String : public Vector { + const char *c_str() const { return reinterpret_cast(Data()); } + std::string str() const { return std::string(c_str(), size()); } + + // clang-format off + #ifdef FLATBUFFERS_HAS_STRING_VIEW + flatbuffers::string_view string_view() const { + return flatbuffers::string_view(c_str(), size()); + } + #endif // FLATBUFFERS_HAS_STRING_VIEW + // clang-format on + + bool operator<(const String &o) const { + return StringLessThan(this->data(), this->size(), o.data(), o.size()); + } +}; + +// Convenience function to get std::string from a String returning an empty +// string on null pointer. +static inline std::string GetString(const String *str) { + return str ? str->str() : ""; +} + +// Convenience function to get char* from a String returning an empty string on +// null pointer. +static inline const char *GetCstring(const String *str) { + return str ? str->c_str() : ""; +} + +#ifdef FLATBUFFERS_HAS_STRING_VIEW +// Convenience function to get string_view from a String returning an empty +// string_view on null pointer. +static inline flatbuffers::string_view GetStringView(const String *str) { + return str ? str->string_view() : flatbuffers::string_view(); +} +#endif // FLATBUFFERS_HAS_STRING_VIEW + +} // namespace flatbuffers + +#endif // FLATBUFFERS_STRING_H_ \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/struct.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/struct.h new file mode 100644 index 000000000..dd3510d7d --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/struct.h @@ -0,0 +1,53 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_STRUCT_H_ +#define FLATBUFFERS_STRUCT_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" + +namespace flatbuffers { + +// "structs" are flat structures that do not have an offset table, thus +// always have all members present and do not support forwards/backwards +// compatible extensions. + +class Struct FLATBUFFERS_FINAL_CLASS { + public: + template T GetField(uoffset_t o) const { + return ReadScalar(&data_[o]); + } + + template T GetStruct(uoffset_t o) const { + return reinterpret_cast(&data_[o]); + } + + const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; } + uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; } + + private: + // private constructor & copy constructor: you obtain instances of this + // class by pointing to existing data only + Struct(); + Struct(const Struct &); + Struct &operator=(const Struct &); + + uint8_t data_[1]; +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_STRUCT_H_ \ No newline at end of file diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/table.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/table.h new file mode 100644 index 000000000..bfafb3ad7 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/table.h @@ -0,0 +1,168 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_TABLE_H_ +#define FLATBUFFERS_TABLE_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/verifier.h" + +namespace flatbuffers { + +// "tables" use an offset table (possibly shared) that allows fields to be +// omitted and added at will, but uses an extra indirection to read. +class Table { + public: + const uint8_t *GetVTable() const { + return data_ - ReadScalar(data_); + } + + // This gets the field offset for any of the functions below it, or 0 + // if the field was not present. + voffset_t GetOptionalFieldOffset(voffset_t field) const { + // The vtable offset is always at the start. + auto vtable = GetVTable(); + // The first element is the size of the vtable (fields + type id + itself). + auto vtsize = ReadScalar(vtable); + // If the field we're accessing is outside the vtable, we're reading older + // data, so it's the same as if the offset was 0 (not present). + return field < vtsize ? ReadScalar(vtable + field) : 0; + } + + template T GetField(voffset_t field, T defaultval) const { + auto field_offset = GetOptionalFieldOffset(field); + return field_offset ? ReadScalar(data_ + field_offset) : defaultval; + } + + template P GetPointer(voffset_t field) { + auto field_offset = GetOptionalFieldOffset(field); + auto p = data_ + field_offset; + return field_offset ? reinterpret_cast

(p + ReadScalar(p)) + : nullptr; + } + template P GetPointer(voffset_t field) const { + return const_cast(this)->GetPointer

(field); + } + + template P GetStruct(voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + auto p = const_cast(data_ + field_offset); + return field_offset ? reinterpret_cast

(p) : nullptr; + } + + template + flatbuffers::Optional GetOptional(voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + auto p = data_ + field_offset; + return field_offset ? Optional(static_cast(ReadScalar(p))) + : Optional(); + } + + template bool SetField(voffset_t field, T val, T def) { + auto field_offset = GetOptionalFieldOffset(field); + if (!field_offset) return IsTheSameAs(val, def); + WriteScalar(data_ + field_offset, val); + return true; + } + template bool SetField(voffset_t field, T val) { + auto field_offset = GetOptionalFieldOffset(field); + if (!field_offset) return false; + WriteScalar(data_ + field_offset, val); + return true; + } + + bool SetPointer(voffset_t field, const uint8_t *val) { + auto field_offset = GetOptionalFieldOffset(field); + if (!field_offset) return false; + WriteScalar(data_ + field_offset, + static_cast(val - (data_ + field_offset))); + return true; + } + + uint8_t *GetAddressOf(voffset_t field) { + auto field_offset = GetOptionalFieldOffset(field); + return field_offset ? data_ + field_offset : nullptr; + } + const uint8_t *GetAddressOf(voffset_t field) const { + return const_cast

(this)->GetAddressOf(field); + } + + bool CheckField(voffset_t field) const { + return GetOptionalFieldOffset(field) != 0; + } + + // Verify the vtable of this table. + // Call this once per table, followed by VerifyField once per field. + bool VerifyTableStart(Verifier &verifier) const { + return verifier.VerifyTableStart(data_); + } + + // Verify a particular field. + template + bool VerifyField(const Verifier &verifier, voffset_t field, + size_t align) const { + // Calling GetOptionalFieldOffset should be safe now thanks to + // VerifyTable(). + auto field_offset = GetOptionalFieldOffset(field); + // Check the actual field. + return !field_offset || verifier.VerifyField(data_, field_offset, align); + } + + // VerifyField for required fields. + template + bool VerifyFieldRequired(const Verifier &verifier, voffset_t field, + size_t align) const { + auto field_offset = GetOptionalFieldOffset(field); + return verifier.Check(field_offset != 0) && + verifier.VerifyField(data_, field_offset, align); + } + + // Versions for offsets. + bool VerifyOffset(const Verifier &verifier, voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + return !field_offset || verifier.VerifyOffset(data_, field_offset); + } + + bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + return verifier.Check(field_offset != 0) && + verifier.VerifyOffset(data_, field_offset); + } + + private: + // private constructor & copy constructor: you obtain instances of this + // class by pointing to existing data only + Table(); + Table(const Table &other); + Table &operator=(const Table &); + + uint8_t data_[1]; +}; + +// This specialization allows avoiding warnings like: +// MSVC C4800: type: forcing value to bool 'true' or 'false'. +template<> +inline flatbuffers::Optional Table::GetOptional( + voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + auto p = data_ + field_offset; + return field_offset ? Optional(ReadScalar(p) != 0) + : Optional(); +} + +} // namespace flatbuffers + +#endif // FLATBUFFERS_TABLE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/util.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/util.h new file mode 100644 index 000000000..150739618 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/util.h @@ -0,0 +1,725 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_UTIL_H_ +#define FLATBUFFERS_UTIL_H_ + +#include +#include + +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/stl_emulation.h" + +// For TFLM we always want to use FLATBUFFERS_PREFER_PRINTF=1. See +// http://b/211811553 for more context. +#ifndef FLATBUFFERS_PREFER_PRINTF +#define FLATBUFFERS_PREFER_PRINTF 1 +#endif + +#ifndef FLATBUFFERS_PREFER_PRINTF +# include +# include +#else // FLATBUFFERS_PREFER_PRINTF +# include +# include +#endif // FLATBUFFERS_PREFER_PRINTF + +#include + +namespace flatbuffers { + +// @locale-independent functions for ASCII characters set. + +// Fast checking that character lies in closed range: [a <= x <= b] +// using one compare (conditional branch) operator. +inline bool check_ascii_range(char x, char a, char b) { + FLATBUFFERS_ASSERT(a <= b); + // (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`. + // The x, a, b will be promoted to int and subtracted without overflow. + return static_cast(x - a) <= static_cast(b - a); +} + +// Case-insensitive isalpha +inline bool is_alpha(char c) { + // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF). + return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF); +} + +// Check for uppercase alpha +inline bool is_alpha_upper(char c) { return check_ascii_range(c, 'A', 'Z'); } + +// Check (case-insensitive) that `c` is equal to alpha. +inline bool is_alpha_char(char c, char alpha) { + FLATBUFFERS_ASSERT(is_alpha(alpha)); + // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF). + return ((c & 0xDF) == (alpha & 0xDF)); +} + +// https://en.cppreference.com/w/cpp/string/byte/isxdigit +// isdigit and isxdigit are the only standard narrow character classification +// functions that are not affected by the currently installed C locale. although +// some implementations (e.g. Microsoft in 1252 codepage) may classify +// additional single-byte characters as digits. +inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); } + +inline bool is_xdigit(char c) { + // Replace by look-up table. + return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF); +} + +// Case-insensitive isalnum +inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); } + +inline char CharToUpper(char c) { + return static_cast(::toupper(static_cast(c))); +} + +inline char CharToLower(char c) { + return static_cast(::tolower(static_cast(c))); +} + +// @end-locale-independent functions for ASCII character set + +#ifdef FLATBUFFERS_PREFER_PRINTF +template size_t IntToDigitCount(T t) { + size_t digit_count = 0; + // Count the sign for negative numbers + if (t < 0) digit_count++; + // Count a single 0 left of the dot for fractional numbers + if (-1 < t && t < 1) digit_count++; + // Count digits until fractional part + T eps = std::numeric_limits::epsilon(); + while (t <= (-1 + eps) || (1 - eps) <= t) { + t /= 10; + digit_count++; + } + return digit_count; +} + +template size_t NumToStringWidth(T t, int precision = 0) { + size_t string_width = IntToDigitCount(t); + // Count the dot for floating point numbers + if (precision) string_width += (precision + 1); + return string_width; +} + +template +std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0) { + size_t string_width = NumToStringWidth(t, precision); + std::string s(string_width, 0x00); + // Allow snprintf to use std::string trailing null to detect buffer overflow + snprintf(const_cast(s.data()), (s.size() + 1), fmt, string_width, t); + return s; +} +#endif // FLATBUFFERS_PREFER_PRINTF + +// Convert an integer or floating point value to a string. +// In contrast to std::stringstream, "char" values are +// converted to a string of digits, and we don't use scientific notation. +template std::string NumToString(T t) { + // clang-format off + + #ifndef FLATBUFFERS_PREFER_PRINTF + std::stringstream ss; + ss << t; + return ss.str(); + #else // FLATBUFFERS_PREFER_PRINTF + auto v = static_cast(t); + return NumToStringImplWrapper(v, "%.*lld"); + #endif // FLATBUFFERS_PREFER_PRINTF + // clang-format on +} +// Avoid char types used as character data. +template<> inline std::string NumToString(signed char t) { + return NumToString(static_cast(t)); +} +template<> inline std::string NumToString(unsigned char t) { + return NumToString(static_cast(t)); +} +template<> inline std::string NumToString(char t) { + return NumToString(static_cast(t)); +} + +// Special versions for floats/doubles. +template std::string FloatToString(T t, int precision) { + // clang-format off + + #ifndef FLATBUFFERS_PREFER_PRINTF + // to_string() prints different numbers of digits for floats depending on + // platform and isn't available on Android, so we use stringstream + std::stringstream ss; + // Use std::fixed to suppress scientific notation. + ss << std::fixed; + // Default precision is 6, we want that to be higher for doubles. + ss << std::setprecision(precision); + ss << t; + auto s = ss.str(); + #else // FLATBUFFERS_PREFER_PRINTF + auto v = static_cast(t); + auto s = NumToStringImplWrapper(v, "%0.*f", precision); + #endif // FLATBUFFERS_PREFER_PRINTF + // clang-format on + // Sadly, std::fixed turns "1" into "1.00000", so here we undo that. + auto p = s.find_last_not_of('0'); + if (p != std::string::npos) { + // Strip trailing zeroes. If it is a whole number, keep one zero. + s.resize(p + (s[p] == '.' ? 2 : 1)); + } + return s; +} + +template<> inline std::string NumToString(double t) { + return FloatToString(t, 12); +} +template<> inline std::string NumToString(float t) { + return FloatToString(t, 6); +} + +// Convert an integer value to a hexadecimal string. +// The returned string length is always xdigits long, prefixed by 0 digits. +// For example, IntToStringHex(0x23, 8) returns the string "00000023". +inline std::string IntToStringHex(int i, int xdigits) { + FLATBUFFERS_ASSERT(i >= 0); + // clang-format off + + #ifndef FLATBUFFERS_PREFER_PRINTF + std::stringstream ss; + ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase + << i; + return ss.str(); + #else // FLATBUFFERS_PREFER_PRINTF + return NumToStringImplWrapper(i, "%.*X", xdigits); + #endif // FLATBUFFERS_PREFER_PRINTF + // clang-format on +} + +// clang-format off +// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}. +#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0) + class ClassicLocale { + #ifdef _MSC_VER + typedef _locale_t locale_type; + #else + typedef locale_t locale_type; // POSIX.1-2008 locale_t type + #endif + ClassicLocale(); + ~ClassicLocale(); + locale_type locale_; + static ClassicLocale instance_; + public: + static locale_type Get() { return instance_.locale_; } + }; + + #ifdef _MSC_VER + #define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get()) + #define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get()) + #define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get()) + #define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get()) + #else + #define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get()) + #define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get()) + #define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get()) + #define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get()) + #endif +#else + #define __strtod_impl(s, pe) strtod(s, pe) + #define __strtof_impl(s, pe) static_cast(strtod(s, pe)) + #ifdef _MSC_VER + #define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b) + #define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b) + #else + #define __strtoull_impl(s, pe, b) strtoull(s, pe, b) + #define __strtoll_impl(s, pe, b) strtoll(s, pe, b) + #endif +#endif + +inline void strtoval_impl(int64_t *val, const char *str, char **endptr, + int base) { + *val = __strtoll_impl(str, endptr, base); +} + +inline void strtoval_impl(uint64_t *val, const char *str, char **endptr, + int base) { + *val = __strtoull_impl(str, endptr, base); +} + +inline void strtoval_impl(double *val, const char *str, char **endptr) { + *val = __strtod_impl(str, endptr); +} + +// UBSAN: double to float is safe if numeric_limits::is_iec559 is true. +__supress_ubsan__("float-cast-overflow") +inline void strtoval_impl(float *val, const char *str, char **endptr) { + *val = __strtof_impl(str, endptr); +} +#undef __strtoull_impl +#undef __strtoll_impl +#undef __strtod_impl +#undef __strtof_impl +// clang-format on + +// Adaptor for strtoull()/strtoll(). +// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9), +// while strtoll with base=0 interprets first leading zero as octal prefix. +// In future, it is possible to add prefixed 0b0101. +// 1) Checks errno code for overflow condition (out of range). +// 2) If base <= 0, function try to detect base of number by prefix. +// +// Return value (like strtoull and strtoll, but reject partial result): +// - If successful, an integer value corresponding to the str is returned. +// - If full string conversion can't be performed, 0 is returned. +// - If the converted value falls out of range of corresponding return type, a +// range error occurs. In this case value MAX(T)/MIN(T) is returned. +template +inline bool StringToIntegerImpl(T *val, const char *const str, + const int base = 0, + const bool check_errno = true) { + // T is int64_t or uint64_T + FLATBUFFERS_ASSERT(str); + if (base <= 0) { + auto s = str; + while (*s && !is_digit(*s)) s++; + if (s[0] == '0' && is_alpha_char(s[1], 'X')) + return StringToIntegerImpl(val, str, 16, check_errno); + // if a prefix not match, try base=10 + return StringToIntegerImpl(val, str, 10, check_errno); + } else { + if (check_errno) errno = 0; // clear thread-local errno + auto endptr = str; + strtoval_impl(val, str, const_cast(&endptr), base); + if ((*endptr != '\0') || (endptr == str)) { + *val = 0; // erase partial result + return false; // invalid string + } + // errno is out-of-range, return MAX/MIN + if (check_errno && errno) return false; + return true; + } +} + +template +inline bool StringToFloatImpl(T *val, const char *const str) { + // Type T must be either float or double. + FLATBUFFERS_ASSERT(str && val); + auto end = str; + strtoval_impl(val, str, const_cast(&end)); + auto done = (end != str) && (*end == '\0'); + if (!done) *val = 0; // erase partial result + return done; +} + +// Convert a string to an instance of T. +// Return value (matched with StringToInteger64Impl and strtod): +// - If successful, a numeric value corresponding to the str is returned. +// - If full string conversion can't be performed, 0 is returned. +// - If the converted value falls out of range of corresponding return type, a +// range error occurs. In this case value MAX(T)/MIN(T) is returned. +template inline bool StringToNumber(const char *s, T *val) { + // Assert on `unsigned long` and `signed long` on LP64. + // If it is necessary, it could be solved with flatbuffers::enable_if. + static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T"); + FLATBUFFERS_ASSERT(s && val); + int64_t i64; + // The errno check isn't needed, will return MAX/MIN on overflow. + if (StringToIntegerImpl(&i64, s, 0, false)) { + const int64_t max = (flatbuffers::numeric_limits::max)(); + const int64_t min = flatbuffers::numeric_limits::lowest(); + if (i64 > max) { + *val = static_cast(max); + return false; + } + if (i64 < min) { + // For unsigned types return max to distinguish from + // "no conversion can be performed" when 0 is returned. + *val = static_cast(flatbuffers::is_unsigned::value ? max : min); + return false; + } + *val = static_cast(i64); + return true; + } + *val = 0; + return false; +} + +template<> inline bool StringToNumber(const char *str, int64_t *val) { + return StringToIntegerImpl(val, str); +} + +template<> +inline bool StringToNumber(const char *str, uint64_t *val) { + if (!StringToIntegerImpl(val, str)) return false; + // The strtoull accepts negative numbers: + // If the minus sign was part of the input sequence, the numeric value + // calculated from the sequence of digits is negated as if by unary minus + // in the result type, which applies unsigned integer wraparound rules. + // Fix this behaviour (except -0). + if (*val) { + auto s = str; + while (*s && !is_digit(*s)) s++; + s = (s > str) ? (s - 1) : s; // step back to one symbol + if (*s == '-') { + // For unsigned types return the max to distinguish from + // "no conversion can be performed". + *val = (flatbuffers::numeric_limits::max)(); + return false; + } + } + return true; +} + +template<> inline bool StringToNumber(const char *s, float *val) { + return StringToFloatImpl(val, s); +} + +template<> inline bool StringToNumber(const char *s, double *val) { + return StringToFloatImpl(val, s); +} + +inline int64_t StringToInt(const char *s, int base = 10) { + int64_t val; + return StringToIntegerImpl(&val, s, base) ? val : 0; +} + +inline uint64_t StringToUInt(const char *s, int base = 10) { + uint64_t val; + return StringToIntegerImpl(&val, s, base) ? val : 0; +} + +typedef bool (*LoadFileFunction)(const char *filename, bool binary, + std::string *dest); +typedef bool (*FileExistsFunction)(const char *filename); + +LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function); + +FileExistsFunction SetFileExistsFunction( + FileExistsFunction file_exists_function); + +// Check if file "name" exists. +bool FileExists(const char *name); + +// Check if "name" exists and it is also a directory. +bool DirExists(const char *name); + +// Load file "name" into "buf" returning true if successful +// false otherwise. If "binary" is false data is read +// using ifstream's text mode, otherwise data is read with +// no transcoding. +bool LoadFile(const char *name, bool binary, std::string *buf); + +// Save data "buf" of length "len" bytes into a file +// "name" returning true if successful, false otherwise. +// If "binary" is false data is written using ifstream's +// text mode, otherwise data is written with no +// transcoding. +bool SaveFile(const char *name, const char *buf, size_t len, bool binary); + +// Save data "buf" into file "name" returning true if +// successful, false otherwise. If "binary" is false +// data is written using ifstream's text mode, otherwise +// data is written with no transcoding. +inline bool SaveFile(const char *name, const std::string &buf, bool binary) { + return SaveFile(name, buf.c_str(), buf.size(), binary); +} + +// Functionality for minimalistic portable path handling. + +// The functions below behave correctly regardless of whether posix ('/') or +// Windows ('/' or '\\') separators are used. + +// Any new separators inserted are always posix. +FLATBUFFERS_CONSTEXPR char kPathSeparator = '/'; + +// Returns the path with the extension, if any, removed. +std::string StripExtension(const std::string &filepath); + +// Returns the extension, if any. +std::string GetExtension(const std::string &filepath); + +// Return the last component of the path, after the last separator. +std::string StripPath(const std::string &filepath); + +// Strip the last component of the path + separator. +std::string StripFileName(const std::string &filepath); + +std::string StripPrefix(const std::string &filepath, + const std::string &prefix_to_remove); + +// Concatenates a path with a filename, regardless of whether the path +// ends in a separator or not. +std::string ConCatPathFileName(const std::string &path, + const std::string &filename); + +// Replaces any '\\' separators with '/' +std::string PosixPath(const char *path); +std::string PosixPath(const std::string &path); + +// This function ensure a directory exists, by recursively +// creating dirs for any parts of the path that don't exist yet. +void EnsureDirExists(const std::string &filepath); + +// Obtains the absolute path from any other path. +// Returns the input path if the absolute path couldn't be resolved. +std::string AbsolutePath(const std::string &filepath); + +// Returns files relative to the --project_root path, prefixed with `//`. +std::string RelativeToRootPath(const std::string &project, + const std::string &filepath); + +// To and from UTF-8 unicode conversion functions + +// Convert a unicode code point into a UTF-8 representation by appending it +// to a string. Returns the number of bytes generated. +inline int ToUTF8(uint32_t ucc, std::string *out) { + FLATBUFFERS_ASSERT(!(ucc & 0x80000000)); // Top bit can't be set. + // 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8 + for (int i = 0; i < 6; i++) { + // Max bits this encoding can represent. + uint32_t max_bits = 6 + i * 5 + static_cast(!i); + if (ucc < (1u << max_bits)) { // does it fit? + // Remaining bits not encoded in the first byte, store 6 bits each + uint32_t remain_bits = i * 6; + // Store first byte: + (*out) += static_cast((0xFE << (max_bits - remain_bits)) | + (ucc >> remain_bits)); + // Store remaining bytes: + for (int j = i - 1; j >= 0; j--) { + (*out) += static_cast(((ucc >> (j * 6)) & 0x3F) | 0x80); + } + return i + 1; // Return the number of bytes added. + } + } + FLATBUFFERS_ASSERT(0); // Impossible to arrive here. + return -1; +} + +// Converts whatever prefix of the incoming string corresponds to a valid +// UTF-8 sequence into a unicode code. The incoming pointer will have been +// advanced past all bytes parsed. +// returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in +// this case). +inline int FromUTF8(const char **in) { + int len = 0; + // Count leading 1 bits. + for (int mask = 0x80; mask >= 0x04; mask >>= 1) { + if (**in & mask) { + len++; + } else { + break; + } + } + if ((static_cast(**in) << len) & 0x80) + return -1; // Bit after leading 1's must be 0. + if (!len) return *(*in)++; + // UTF-8 encoded values with a length are between 2 and 4 bytes. + if (len < 2 || len > 4) { return -1; } + // Grab initial bits of the code. + int ucc = *(*in)++ & ((1 << (7 - len)) - 1); + for (int i = 0; i < len - 1; i++) { + if ((**in & 0xC0) != 0x80) return -1; // Upper bits must 1 0. + ucc <<= 6; + ucc |= *(*in)++ & 0x3F; // Grab 6 more bits of the code. + } + // UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for + // UTF-16 surrogate pairs). + if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; } + // UTF-8 must represent code points in their shortest possible encoding. + switch (len) { + case 2: + // Two bytes of UTF-8 can represent code points from U+0080 to U+07FF. + if (ucc < 0x0080 || ucc > 0x07FF) { return -1; } + break; + case 3: + // Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF. + if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; } + break; + case 4: + // Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF. + if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; } + break; + } + return ucc; +} + +#ifndef FLATBUFFERS_PREFER_PRINTF +// Wraps a string to a maximum length, inserting new lines where necessary. Any +// existing whitespace will be collapsed down to a single space. A prefix or +// suffix can be provided, which will be inserted before or after a wrapped +// line, respectively. +inline std::string WordWrap(const std::string in, size_t max_length, + const std::string wrapped_line_prefix, + const std::string wrapped_line_suffix) { + std::istringstream in_stream(in); + std::string wrapped, line, word; + + in_stream >> word; + line = word; + + while (in_stream >> word) { + if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) < + max_length) { + line += " " + word; + } else { + wrapped += line + wrapped_line_suffix + "\n"; + line = wrapped_line_prefix + word; + } + } + wrapped += line; + + return wrapped; +} +#endif // !FLATBUFFERS_PREFER_PRINTF + +inline bool EscapeString(const char *s, size_t length, std::string *_text, + bool allow_non_utf8, bool natural_utf8) { + std::string &text = *_text; + text += "\""; + for (uoffset_t i = 0; i < length; i++) { + char c = s[i]; + switch (c) { + case '\n': text += "\\n"; break; + case '\t': text += "\\t"; break; + case '\r': text += "\\r"; break; + case '\b': text += "\\b"; break; + case '\f': text += "\\f"; break; + case '\"': text += "\\\""; break; + case '\\': text += "\\\\"; break; + default: + if (c >= ' ' && c <= '~') { + text += c; + } else { + // Not printable ASCII data. Let's see if it's valid UTF-8 first: + const char *utf8 = s + i; + int ucc = FromUTF8(&utf8); + if (ucc < 0) { + if (allow_non_utf8) { + text += "\\x"; + text += IntToStringHex(static_cast(c), 2); + } else { + // There are two cases here: + // + // 1) We reached here by parsing an IDL file. In that case, + // we previously checked for non-UTF-8, so we shouldn't reach + // here. + // + // 2) We reached here by someone calling GenerateText() + // on a previously-serialized flatbuffer. The data might have + // non-UTF-8 Strings, or might be corrupt. + // + // In both cases, we have to give up and inform the caller + // they have no JSON. + return false; + } + } else { + if (natural_utf8) { + // utf8 points to past all utf-8 bytes parsed + text.append(s + i, static_cast(utf8 - s - i)); + } else if (ucc <= 0xFFFF) { + // Parses as Unicode within JSON's \uXXXX range, so use that. + text += "\\u"; + text += IntToStringHex(ucc, 4); + } else if (ucc <= 0x10FFFF) { + // Encode Unicode SMP values to a surrogate pair using two \u + // escapes. + uint32_t base = ucc - 0x10000; + auto high_surrogate = (base >> 10) + 0xD800; + auto low_surrogate = (base & 0x03FF) + 0xDC00; + text += "\\u"; + text += IntToStringHex(high_surrogate, 4); + text += "\\u"; + text += IntToStringHex(low_surrogate, 4); + } + // Skip past characters recognized. + i = static_cast(utf8 - s - 1); + } + } + break; + } + } + text += "\""; + return true; +} + +inline std::string BufferToHexText(const void *buffer, size_t buffer_size, + size_t max_length, + const std::string &wrapped_line_prefix, + const std::string &wrapped_line_suffix) { + std::string text = wrapped_line_prefix; + size_t start_offset = 0; + const char *s = reinterpret_cast(buffer); + for (size_t i = 0; s && i < buffer_size; i++) { + // Last iteration or do we have more? + bool have_more = i + 1 < buffer_size; + text += "0x"; + text += IntToStringHex(static_cast(s[i]), 2); + if (have_more) { text += ','; } + // If we have more to process and we reached max_length + if (have_more && + text.size() + wrapped_line_suffix.size() >= start_offset + max_length) { + text += wrapped_line_suffix; + text += '\n'; + start_offset = text.size(); + text += wrapped_line_prefix; + } + } + text += wrapped_line_suffix; + return text; +} + +// Remove paired quotes in a string: "text"|'text' -> text. +std::string RemoveStringQuotes(const std::string &s); + +// Change th global C-locale to locale with name . +// Returns an actual locale name in <_value>, useful if locale_name is "" or +// null. +bool SetGlobalTestLocale(const char *locale_name, + std::string *_value = nullptr); + +// Read (or test) a value of environment variable. +bool ReadEnvironmentVariable(const char *var_name, + std::string *_value = nullptr); + +// MSVC specific: Send all assert reports to STDOUT to prevent CI hangs. +void SetupDefaultCRTReportMode(); + +enum class Case { + kUnknown = 0, + // TheQuickBrownFox + kUpperCamel = 1, + // theQuickBrownFox + kLowerCamel = 2, + // the_quick_brown_fox + kSnake = 3, + // THE_QUICK_BROWN_FOX + kScreamingSnake = 4, + // THEQUICKBROWNFOX + kAllUpper = 5, + // thequickbrownfox + kAllLower = 6, + // the-quick-brown-fox + kDasher = 7, + // THEQuiCKBr_ownFox (or whatever you want, we won't change it) + kKeep = 8, + // the_quick_brown_fox123 (as opposed to the_quick_brown_fox_123) + kSnake2 = 9, +}; + +// Convert the `input` string of case `input_case` to the specified `output_case`. +std::string ConvertCase(const std::string &input, Case output_case, + Case input_case = Case::kSnake); + +} // namespace flatbuffers + +#endif // FLATBUFFERS_UTIL_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/vector.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/vector.h new file mode 100644 index 000000000..f0cd2f037 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/vector.h @@ -0,0 +1,389 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_VECTOR_H_ +#define FLATBUFFERS_VECTOR_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/buffer.h" +#include "third_party/flatbuffers/include/flatbuffers/stl_emulation.h" + +namespace flatbuffers { + +struct String; + +// An STL compatible iterator implementation for Vector below, effectively +// calling Get() for every element. +template struct VectorIterator { + typedef std::random_access_iterator_tag iterator_category; + typedef IT value_type; + typedef ptrdiff_t difference_type; + typedef IT *pointer; + typedef IT &reference; + + VectorIterator(const uint8_t *data, uoffset_t i) + : data_(data + IndirectHelper::element_stride * i) {} + VectorIterator(const VectorIterator &other) : data_(other.data_) {} + VectorIterator() : data_(nullptr) {} + + VectorIterator &operator=(const VectorIterator &other) { + data_ = other.data_; + return *this; + } + + VectorIterator &operator=(VectorIterator &&other) { + data_ = other.data_; + return *this; + } + + bool operator==(const VectorIterator &other) const { + return data_ == other.data_; + } + + bool operator<(const VectorIterator &other) const { + return data_ < other.data_; + } + + bool operator!=(const VectorIterator &other) const { + return data_ != other.data_; + } + + difference_type operator-(const VectorIterator &other) const { + return (data_ - other.data_) / IndirectHelper::element_stride; + } + + // Note: return type is incompatible with the standard + // `reference operator*()`. + IT operator*() const { return IndirectHelper::Read(data_, 0); } + + // Note: return type is incompatible with the standard + // `pointer operator->()`. + IT operator->() const { return IndirectHelper::Read(data_, 0); } + + VectorIterator &operator++() { + data_ += IndirectHelper::element_stride; + return *this; + } + + VectorIterator operator++(int) { + VectorIterator temp(data_, 0); + data_ += IndirectHelper::element_stride; + return temp; + } + + VectorIterator operator+(const uoffset_t &offset) const { + return VectorIterator(data_ + offset * IndirectHelper::element_stride, + 0); + } + + VectorIterator &operator+=(const uoffset_t &offset) { + data_ += offset * IndirectHelper::element_stride; + return *this; + } + + VectorIterator &operator--() { + data_ -= IndirectHelper::element_stride; + return *this; + } + + VectorIterator operator--(int) { + VectorIterator temp(data_, 0); + data_ -= IndirectHelper::element_stride; + return temp; + } + + VectorIterator operator-(const uoffset_t &offset) const { + return VectorIterator(data_ - offset * IndirectHelper::element_stride, + 0); + } + + VectorIterator &operator-=(const uoffset_t &offset) { + data_ -= offset * IndirectHelper::element_stride; + return *this; + } + + private: + const uint8_t *data_; +}; + +template +struct VectorReverseIterator : public std::reverse_iterator { + explicit VectorReverseIterator(Iterator iter) + : std::reverse_iterator(iter) {} + + // Note: return type is incompatible with the standard + // `reference operator*()`. + typename Iterator::value_type operator*() const { + auto tmp = std::reverse_iterator::current; + return *--tmp; + } + + // Note: return type is incompatible with the standard + // `pointer operator->()`. + typename Iterator::value_type operator->() const { + auto tmp = std::reverse_iterator::current; + return *--tmp; + } +}; + +// This is used as a helper type for accessing vectors. +// Vector::data() assumes the vector elements start after the length field. +template class Vector { + public: + typedef VectorIterator::mutable_return_type> + iterator; + typedef VectorIterator::return_type> + const_iterator; + typedef VectorReverseIterator reverse_iterator; + typedef VectorReverseIterator const_reverse_iterator; + + typedef typename flatbuffers::bool_constant::value> + scalar_tag; + + static FLATBUFFERS_CONSTEXPR bool is_span_observable = + scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1); + + uoffset_t size() const { return EndianScalar(length_); } + + // Deprecated: use size(). Here for backwards compatibility. + FLATBUFFERS_ATTRIBUTE([[deprecated("use size() instead")]]) + uoffset_t Length() const { return size(); } + + typedef typename IndirectHelper::return_type return_type; + typedef typename IndirectHelper::mutable_return_type mutable_return_type; + typedef return_type value_type; + + return_type Get(uoffset_t i) const { + FLATBUFFERS_ASSERT(i < size()); + return IndirectHelper::Read(Data(), i); + } + + return_type operator[](uoffset_t i) const { return Get(i); } + + // If this is a Vector of enums, T will be its storage type, not the enum + // type. This function makes it convenient to retrieve value with enum + // type E. + template E GetEnum(uoffset_t i) const { + return static_cast(Get(i)); + } + + // If this a vector of unions, this does the cast for you. There's no check + // to make sure this is the right type! + template const U *GetAs(uoffset_t i) const { + return reinterpret_cast(Get(i)); + } + + // If this a vector of unions, this does the cast for you. There's no check + // to make sure this is actually a string! + const String *GetAsString(uoffset_t i) const { + return reinterpret_cast(Get(i)); + } + + const void *GetStructFromOffset(size_t o) const { + return reinterpret_cast(Data() + o); + } + + iterator begin() { return iterator(Data(), 0); } + const_iterator begin() const { return const_iterator(Data(), 0); } + + iterator end() { return iterator(Data(), size()); } + const_iterator end() const { return const_iterator(Data(), size()); } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + const_iterator cbegin() const { return begin(); } + + const_iterator cend() const { return end(); } + + const_reverse_iterator crbegin() const { return rbegin(); } + + const_reverse_iterator crend() const { return rend(); } + + // Change elements if you have a non-const pointer to this object. + // Scalars only. See reflection.h, and the documentation. + void Mutate(uoffset_t i, const T &val) { + FLATBUFFERS_ASSERT(i < size()); + WriteScalar(data() + i, val); + } + + // Change an element of a vector of tables (or strings). + // "val" points to the new table/string, as you can obtain from + // e.g. reflection::AddFlatBuffer(). + void MutateOffset(uoffset_t i, const uint8_t *val) { + FLATBUFFERS_ASSERT(i < size()); + static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types"); + WriteScalar(data() + i, + static_cast(val - (Data() + i * sizeof(uoffset_t)))); + } + + // Get a mutable pointer to tables/strings inside this vector. + mutable_return_type GetMutableObject(uoffset_t i) const { + FLATBUFFERS_ASSERT(i < size()); + return const_cast(IndirectHelper::Read(Data(), i)); + } + + // The raw data in little endian format. Use with care. + const uint8_t *Data() const { + return reinterpret_cast(&length_ + 1); + } + + uint8_t *Data() { return reinterpret_cast(&length_ + 1); } + + // Similarly, but typed, much like std::vector::data + const T *data() const { return reinterpret_cast(Data()); } + T *data() { return reinterpret_cast(Data()); } + + template return_type LookupByKey(K key) const { + void *search_result = std::bsearch( + &key, Data(), size(), IndirectHelper::element_stride, KeyCompare); + + if (!search_result) { + return nullptr; // Key not found. + } + + const uint8_t *element = reinterpret_cast(search_result); + + return IndirectHelper::Read(element, 0); + } + + template mutable_return_type MutableLookupByKey(K key) { + return const_cast(LookupByKey(key)); + } + + protected: + // This class is only used to access pre-existing data. Don't ever + // try to construct these manually. + Vector(); + + uoffset_t length_; + + private: + // This class is a pointer. Copying will therefore create an invalid object. + // Private and unimplemented copy constructor. + Vector(const Vector &); + Vector &operator=(const Vector &); + + template static int KeyCompare(const void *ap, const void *bp) { + const K *key = reinterpret_cast(ap); + const uint8_t *data = reinterpret_cast(bp); + auto table = IndirectHelper::Read(data, 0); + + // std::bsearch compares with the operands transposed, so we negate the + // result here. + return -table->KeyCompareWithValue(*key); + } +}; + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span(Vector &vec) + FLATBUFFERS_NOEXCEPT { + static_assert(Vector::is_span_observable, + "wrong type U, only LE-scalar, or byte types are allowed"); + return span(vec.data(), vec.size()); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span( + const Vector &vec) FLATBUFFERS_NOEXCEPT { + static_assert(Vector::is_span_observable, + "wrong type U, only LE-scalar, or byte types are allowed"); + return span(vec.data(), vec.size()); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_bytes_span( + Vector &vec) FLATBUFFERS_NOEXCEPT { + static_assert(Vector::scalar_tag::value, + "wrong type U, only LE-scalar, or byte types are allowed"); + return span(vec.Data(), vec.size() * sizeof(U)); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_bytes_span( + const Vector &vec) FLATBUFFERS_NOEXCEPT { + static_assert(Vector::scalar_tag::value, + "wrong type U, only LE-scalar, or byte types are allowed"); + return span(vec.Data(), vec.size() * sizeof(U)); +} + +// Convenient helper functions to get a span of any vector, regardless +// of whether it is null or not (the field is not set). +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span(Vector *ptr) + FLATBUFFERS_NOEXCEPT { + static_assert(Vector::is_span_observable, + "wrong type U, only LE-scalar, or byte types are allowed"); + return ptr ? make_span(*ptr) : span(); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span( + const Vector *ptr) FLATBUFFERS_NOEXCEPT { + static_assert(Vector::is_span_observable, + "wrong type U, only LE-scalar, or byte types are allowed"); + return ptr ? make_span(*ptr) : span(); +} + +// Represent a vector much like the template above, but in this case we +// don't know what the element types are (used with reflection.h). +class VectorOfAny { + public: + uoffset_t size() const { return EndianScalar(length_); } + + const uint8_t *Data() const { + return reinterpret_cast(&length_ + 1); + } + uint8_t *Data() { return reinterpret_cast(&length_ + 1); } + + protected: + VectorOfAny(); + + uoffset_t length_; + + private: + VectorOfAny(const VectorOfAny &); + VectorOfAny &operator=(const VectorOfAny &); +}; + +template +Vector> *VectorCast(Vector> *ptr) { + static_assert(std::is_base_of::value, "Unrelated types"); + return reinterpret_cast> *>(ptr); +} + +template +const Vector> *VectorCast(const Vector> *ptr) { + static_assert(std::is_base_of::value, "Unrelated types"); + return reinterpret_cast> *>(ptr); +} + +// Convenient helper function to get the length of any vector, regardless +// of whether it is null or not (the field is not set). +template static inline size_t VectorLength(const Vector *v) { + return v ? v->size() : 0; +} + +} // namespace flatbuffers + +#endif // FLATBUFFERS_VERIFIER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/vector_downward.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/vector_downward.h new file mode 100644 index 000000000..dbe8e56a5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/vector_downward.h @@ -0,0 +1,271 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_VECTOR_DOWNWARD_H_ +#define FLATBUFFERS_VECTOR_DOWNWARD_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/default_allocator.h" +#include "third_party/flatbuffers/include/flatbuffers/detached_buffer.h" + +namespace flatbuffers { + +// This is a minimal replication of std::vector functionality, +// except growing from higher to lower addresses. i.e push_back() inserts data +// in the lowest address in the vector. +// Since this vector leaves the lower part unused, we support a "scratch-pad" +// that can be stored there for temporary data, to share the allocated space. +// Essentially, this supports 2 std::vectors in a single buffer. +class vector_downward { + public: + explicit vector_downward(size_t initial_size, Allocator *allocator, + bool own_allocator, size_t buffer_minalign) + : allocator_(allocator), + own_allocator_(own_allocator), + initial_size_(initial_size), + buffer_minalign_(buffer_minalign), + reserved_(0), + size_(0), + buf_(nullptr), + cur_(nullptr), + scratch_(nullptr) {} + + vector_downward(vector_downward &&other) + // clang-format on + : allocator_(other.allocator_), + own_allocator_(other.own_allocator_), + initial_size_(other.initial_size_), + buffer_minalign_(other.buffer_minalign_), + reserved_(other.reserved_), + size_(other.size_), + buf_(other.buf_), + cur_(other.cur_), + scratch_(other.scratch_) { + // No change in other.allocator_ + // No change in other.initial_size_ + // No change in other.buffer_minalign_ + other.own_allocator_ = false; + other.reserved_ = 0; + other.buf_ = nullptr; + other.cur_ = nullptr; + other.scratch_ = nullptr; + } + + vector_downward &operator=(vector_downward &&other) { + // Move construct a temporary and swap idiom + vector_downward temp(std::move(other)); + swap(temp); + return *this; + } + + ~vector_downward() { + clear_buffer(); + clear_allocator(); + } + + void reset() { + clear_buffer(); + clear(); + } + + void clear() { + if (buf_) { + cur_ = buf_ + reserved_; + } else { + reserved_ = 0; + cur_ = nullptr; + } + size_ = 0; + clear_scratch(); + } + + void clear_scratch() { scratch_ = buf_; } + + void clear_allocator() { + if (own_allocator_ && allocator_) { delete allocator_; } + allocator_ = nullptr; + own_allocator_ = false; + } + + void clear_buffer() { + if (buf_) Deallocate(allocator_, buf_, reserved_); + buf_ = nullptr; + } + + // Relinquish the pointer to the caller. + uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) { + auto *buf = buf_; + allocated_bytes = reserved_; + offset = static_cast(cur_ - buf_); + + // release_raw only relinquishes the buffer ownership. + // Does not deallocate or reset the allocator. Destructor will do that. + buf_ = nullptr; + clear(); + return buf; + } + + // Relinquish the pointer to the caller. + DetachedBuffer release() { + // allocator ownership (if any) is transferred to DetachedBuffer. + DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_, + size()); + if (own_allocator_) { + allocator_ = nullptr; + own_allocator_ = false; + } + buf_ = nullptr; + clear(); + return fb; + } + + size_t ensure_space(size_t len) { + FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_); + if (len > static_cast(cur_ - scratch_)) { reallocate(len); } + // Beyond this, signed offsets may not have enough range: + // (FlatBuffers > 2GB not supported). + FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE); + return len; + } + + inline uint8_t *make_space(size_t len) { + if (len) { + ensure_space(len); + cur_ -= len; + size_ += static_cast(len); + } + return cur_; + } + + // Returns nullptr if using the DefaultAllocator. + Allocator *get_custom_allocator() { return allocator_; } + + inline uoffset_t size() const { return size_; } + + uoffset_t scratch_size() const { + return static_cast(scratch_ - buf_); + } + + size_t capacity() const { return reserved_; } + + uint8_t *data() const { + FLATBUFFERS_ASSERT(cur_); + return cur_; + } + + uint8_t *scratch_data() const { + FLATBUFFERS_ASSERT(buf_); + return buf_; + } + + uint8_t *scratch_end() const { + FLATBUFFERS_ASSERT(scratch_); + return scratch_; + } + + uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; } + + void push(const uint8_t *bytes, size_t num) { + if (num > 0) { memcpy(make_space(num), bytes, num); } + } + + // Specialized version of push() that avoids memcpy call for small data. + template void push_small(const T &little_endian_t) { + make_space(sizeof(T)); + *reinterpret_cast(cur_) = little_endian_t; + } + + template void scratch_push_small(const T &t) { + ensure_space(sizeof(T)); + *reinterpret_cast(scratch_) = t; + scratch_ += sizeof(T); + } + + // fill() is most frequently called with small byte counts (<= 4), + // which is why we're using loops rather than calling memset. + void fill(size_t zero_pad_bytes) { + make_space(zero_pad_bytes); + for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0; + } + + // Version for when we know the size is larger. + // Precondition: zero_pad_bytes > 0 + void fill_big(size_t zero_pad_bytes) { + memset(make_space(zero_pad_bytes), 0, zero_pad_bytes); + } + + void pop(size_t bytes_to_remove) { + cur_ += bytes_to_remove; + size_ -= static_cast(bytes_to_remove); + } + + void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; } + + void swap(vector_downward &other) { + using std::swap; + swap(allocator_, other.allocator_); + swap(own_allocator_, other.own_allocator_); + swap(initial_size_, other.initial_size_); + swap(buffer_minalign_, other.buffer_minalign_); + swap(reserved_, other.reserved_); + swap(size_, other.size_); + swap(buf_, other.buf_); + swap(cur_, other.cur_); + swap(scratch_, other.scratch_); + } + + void swap_allocator(vector_downward &other) { + using std::swap; + swap(allocator_, other.allocator_); + swap(own_allocator_, other.own_allocator_); + } + + private: + // You shouldn't really be copying instances of this class. + FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &)); + FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &)); + + Allocator *allocator_; + bool own_allocator_; + size_t initial_size_; + size_t buffer_minalign_; + size_t reserved_; + uoffset_t size_; + uint8_t *buf_; + uint8_t *cur_; // Points at location between empty (below) and used (above). + uint8_t *scratch_; // Points to the end of the scratchpad in use. + + void reallocate(size_t len) { + auto old_reserved = reserved_; + auto old_size = size(); + auto old_scratch_size = scratch_size(); + reserved_ += + (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_); + reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1); + if (buf_) { + buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_, + old_size, old_scratch_size); + } else { + buf_ = Allocate(allocator_, reserved_); + } + cur_ = buf_ + reserved_ - old_size; + scratch_ = buf_ + old_scratch_size; + } +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_VECTOR_DOWNWARD_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/verifier.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/verifier.h new file mode 100644 index 000000000..16a335f79 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/flatbuffers/include/flatbuffers/verifier.h @@ -0,0 +1,304 @@ +/* + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_VERIFIER_H_ +#define FLATBUFFERS_VERIFIER_H_ + +#include "third_party/flatbuffers/include/flatbuffers/base.h" +#include "third_party/flatbuffers/include/flatbuffers/vector.h" + +namespace flatbuffers { + +// Helper class to verify the integrity of a FlatBuffer +class Verifier FLATBUFFERS_FINAL_CLASS { + public: + Verifier(const uint8_t *const buf, const size_t buf_len, + const uoffset_t _max_depth = 64, + const uoffset_t _max_tables = 1000000, + const bool _check_alignment = true) + : buf_(buf), + size_(buf_len), + max_depth_(_max_depth), + max_tables_(_max_tables), + check_alignment_(_check_alignment), + upper_bound_(0), + depth_(0), + num_tables_(0), + flex_reuse_tracker_(nullptr) { + FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE); + } + + // Central location where any verification failures register. + bool Check(const bool ok) const { + // clang-format off + #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE + FLATBUFFERS_ASSERT(ok); + #endif + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + if (!ok) + upper_bound_ = 0; + #endif + // clang-format on + return ok; + } + + // Verify any range within the buffer. + bool Verify(const size_t elem, const size_t elem_len) const { + // clang-format off + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + auto upper_bound = elem + elem_len; + if (upper_bound_ < upper_bound) + upper_bound_ = upper_bound; + #endif + // clang-format on + return Check(elem_len < size_ && elem <= size_ - elem_len); + } + + bool VerifyAlignment(const size_t elem, const size_t align) const { + return Check((elem & (align - 1)) == 0 || !check_alignment_); + } + + // Verify a range indicated by sizeof(T). + template bool Verify(const size_t elem) const { + return VerifyAlignment(elem, sizeof(T)) && Verify(elem, sizeof(T)); + } + + bool VerifyFromPointer(const uint8_t *const p, const size_t len) { + return Verify(static_cast(p - buf_), len); + } + + // Verify relative to a known-good base pointer. + bool VerifyFieldStruct(const uint8_t *const base, const voffset_t elem_off, + const size_t elem_len, const size_t align) const { + const auto f = static_cast(base - buf_) + elem_off; + return VerifyAlignment(f, align) && Verify(f, elem_len); + } + + template + bool VerifyField(const uint8_t *const base, const voffset_t elem_off, + const size_t align) const { + const auto f = static_cast(base - buf_) + elem_off; + return VerifyAlignment(f, align) && Verify(f, sizeof(T)); + } + + // Verify a pointer (may be NULL) of a table type. + template bool VerifyTable(const T *const table) { + return !table || table->Verify(*this); + } + + // Verify a pointer (may be NULL) of any vector type. + template bool VerifyVector(const Vector *const vec) const { + return !vec || VerifyVectorOrString(reinterpret_cast(vec), + sizeof(T)); + } + + // Verify a pointer (may be NULL) of a vector to struct. + template + bool VerifyVector(const Vector *const vec) const { + return VerifyVector(reinterpret_cast *>(vec)); + } + + // Verify a pointer (may be NULL) to string. + bool VerifyString(const String *const str) const { + size_t end; + return !str || (VerifyVectorOrString(reinterpret_cast(str), + 1, &end) && + Verify(end, 1) && // Must have terminator + Check(buf_[end] == '\0')); // Terminating byte must be 0. + } + + // Common code between vectors and strings. + bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size, + size_t *const end = nullptr) const { + const auto veco = static_cast(vec - buf_); + // Check we can read the size field. + if (!Verify(veco)) return false; + // Check the whole array. If this is a string, the byte past the array + // must be 0. + const auto size = ReadScalar(vec); + const auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size; + if (!Check(size < max_elems)) + return false; // Protect against byte_size overflowing. + const auto byte_size = sizeof(size) + elem_size * size; + if (end) *end = veco + byte_size; + return Verify(veco, byte_size); + } + + // Special case for string contents, after the above has been called. + bool VerifyVectorOfStrings(const Vector> *const vec) const { + if (vec) { + for (uoffset_t i = 0; i < vec->size(); i++) { + if (!VerifyString(vec->Get(i))) return false; + } + } + return true; + } + + // Special case for table contents, after the above has been called. + template + bool VerifyVectorOfTables(const Vector> *const vec) { + if (vec) { + for (uoffset_t i = 0; i < vec->size(); i++) { + if (!vec->Get(i)->Verify(*this)) return false; + } + } + return true; + } + + __supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart( + const uint8_t *const table) { + // Check the vtable offset. + const auto tableo = static_cast(table - buf_); + if (!Verify(tableo)) return false; + // This offset may be signed, but doing the subtraction unsigned always + // gives the result we want. + const auto vtableo = + tableo - static_cast(ReadScalar(table)); + // Check the vtable size field, then check vtable fits in its entirety. + if (!(VerifyComplexity() && Verify(vtableo) && + VerifyAlignment(ReadScalar(buf_ + vtableo), + sizeof(voffset_t)))) + return false; + const auto vsize = ReadScalar(buf_ + vtableo); + return Check((vsize & 1) == 0) && Verify(vtableo, vsize); + } + + template + bool VerifyBufferFromStart(const char *const identifier, const size_t start) { + // Buffers have to be of some size to be valid. The reason it is a runtime + // check instead of static_assert, is that nested flatbuffers go through + // this call and their size is determined at runtime. + if (!Check(size_ >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false; + + // If an identifier is provided, check that we have a buffer + if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) && + BufferHasIdentifier(buf_ + start, identifier)))) { + return false; + } + + // Call T::Verify, which must be in the generated code for this type. + const auto o = VerifyOffset(start); + return Check(o != 0) && + reinterpret_cast(buf_ + start + o)->Verify(*this) + // clang-format off + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + && GetComputedSize() + #endif + ; + // clang-format on + } + + template + bool VerifyNestedFlatBuffer(const Vector *const buf, + const char *const identifier) { + // An empty buffer is OK as it indicates not present. + if (!buf) return true; + + // If there is a nested buffer, it must be greater than the min size. + if(!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false; + + Verifier nested_verifier(buf->data(), buf->size()); + return nested_verifier.VerifyBuffer(identifier); + } + + // Verify this whole buffer, starting with root type T. + template bool VerifyBuffer() { return VerifyBuffer(nullptr); } + + template bool VerifyBuffer(const char *const identifier) { + return VerifyBufferFromStart(identifier, 0); + } + + template + bool VerifySizePrefixedBuffer(const char *const identifier) { + return Verify(0U) && + Check(ReadScalar(buf_) == size_ - sizeof(uoffset_t)) && + VerifyBufferFromStart(identifier, sizeof(uoffset_t)); + } + + uoffset_t VerifyOffset(const size_t start) const { + if (!Verify(start)) return 0; + const auto o = ReadScalar(buf_ + start); + // May not point to itself. + if (!Check(o != 0)) return 0; + // Can't wrap around / buffers are max 2GB. + if (!Check(static_cast(o) >= 0)) return 0; + // Must be inside the buffer to create a pointer from it (pointer outside + // buffer is UB). + if (!Verify(start + o, 1)) return 0; + return o; + } + + uoffset_t VerifyOffset(const uint8_t *const base, + const voffset_t start) const { + return VerifyOffset(static_cast(base - buf_) + start); + } + + // Called at the start of a table to increase counters measuring data + // structure depth and amount, and possibly bails out with false if + // limits set by the constructor have been hit. Needs to be balanced + // with EndTable(). + bool VerifyComplexity() { + depth_++; + num_tables_++; + return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_); + } + + // Called at the end of a table to pop the depth count. + bool EndTable() { + depth_--; + return true; + } + + // Returns the message size in bytes + size_t GetComputedSize() const { + // clang-format off + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + uintptr_t size = upper_bound_; + // Align the size to uoffset_t + size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1); + return (size > size_) ? 0 : size; + #else + // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work. + (void)upper_bound_; + FLATBUFFERS_ASSERT(false); + return 0; + #endif + // clang-format on + } + + std::vector *GetFlexReuseTracker() { return flex_reuse_tracker_; } + + void SetFlexReuseTracker(std::vector *const rt) { + flex_reuse_tracker_ = rt; + } + + private: + const uint8_t *buf_; + const size_t size_; + const uoffset_t max_depth_; + const uoffset_t max_tables_; + const bool check_alignment_; + + mutable size_t upper_bound_; + + uoffset_t depth_; + uoffset_t num_tables_; + std::vector *flex_reuse_tracker_; +}; + +} // namespace flatbuffers + +#endif // FLATBUFFERS_VERIFIER_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/LICENSE b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint.h new file mode 100644 index 000000000..51b5aff41 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint.h @@ -0,0 +1,900 @@ +// Copyright 2015 The Gemmlowp Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// fixedpoint.h: fixed-point arithmetic, with basic operations and +// a few math functions such as tanh. + +#ifndef GEMMLOWP_INTERNAL_FIXEDPOINT_H_ +#define GEMMLOWP_INTERNAL_FIXEDPOINT_H_ + +#include +#include +#include +#include +#include + +#include "../internal/detect_platform.h" + +namespace gemmlowp { + +// Part 1: Low-level integer-arithmetic primitives. +// The implementations here are generic implementations valid for +// scalar types (e.g. std::int32_t). Architecture-specific SIMD types +// (e.g. NEON int32x4_t) may be supported by providing +// specializations for them in separate files. +// +// The purpose of these primitives is two-fold: +// - They will be used to implement higher-level fixed-point +// abstractions, namely the FixedPoint class and its arithmetic +// operators. +// - They will be directly used to implement some more involved +// fixed-point computations, e.g. the fixed-point implementation +// of math functions such as tanh. + +// Some compile-time traits around raw types to handle SIMD aspects: +// number of lanes, underlying scalar type. +template +struct FixedPointRawTypeTraits {}; + +template <> +struct FixedPointRawTypeTraits { + typedef std::int32_t ScalarRawType; + static constexpr int kLanes = 1; +}; + +template <> +struct FixedPointRawTypeTraits { + typedef std::int16_t ScalarRawType; + static constexpr int kLanes = 1; +}; + +// Returns a SIMD value duplicating a scalar value across all lanes. +template +tRawType Dup(typename FixedPointRawTypeTraits::ScalarRawType x) { + return x; +} + +// Plain bit-wise AND +template +tIntegerType BitAnd(tIntegerType a, tIntegerType b) { + return a & b; +} + +// Plain bit-wise OR +template +tIntegerType BitOr(tIntegerType a, tIntegerType b) { + return a | b; +} + +// Plain bit-wise XOR +template +tIntegerType BitXor(tIntegerType a, tIntegerType b) { + return a ^ b; +} + +// Plain bit-wise NOT +template +tIntegerType BitNot(tIntegerType a) { + return ~a; +} + +// Integer addition. Not saturating. Overflow is undefined behavior. +template +tIntegerType Add(tIntegerType a, tIntegerType b) { + return a + b; +} + +// Integer subtraction. Not saturating. Overflow is undefined behavior. +template +tIntegerType Mul(tIntegerType a, tIntegerType b) { + return a * b; +} + +template +tIntegerType Sub(tIntegerType a, tIntegerType b) { + return a - b; +} + +// Integer unary negative. Not saturating. Overflow is undefined behavior. +template +tIntegerType Neg(tIntegerType a) { + return -a; +} + +// Integer arithmetic left-shift, equivalent to multiplying with a power of two. +// Negative values are OK. In case of overflow, no Undefined +// Behavior, but the results are implementation-defined (in practice, +// they currently are saturated, but we make no commitment to that). The idea +// is that the caller will want to implement the overflowing cases with +// saturation with compare-and-mask, so we don't care about the results +// in the overflow case, we just want to avoid undefined behavior. +// +// tIntegerType may be int32 or any narrower signed type. +template +tIntegerType ShiftLeft(tIntegerType a, int offset) { + const std::int64_t wide_a = static_cast(a); + const std::int64_t wide_shifted = wide_a * (1 << offset); + const auto min = std::numeric_limits::min(); + const auto max = std::numeric_limits::max(); + return wide_shifted < min + ? min + : wide_shifted > max ? max + : static_cast(wide_shifted); +} + +// Integer arithmetic right-shift. Not rounding. +// Relying on implementation-defined, but in-practice-consistent, +// C++ compiler behavior. +template +tIntegerType ShiftRight(tIntegerType a, int offset) { + return a >> offset; +} + +// Each bit of the result is set to the corresponding bit of either then_val or +// else_val depending on whether the corresponding bit of if_mask is set. +// Equivalent to the VBSL instruction in ARM NEON. +template +tIntegerType SelectUsingMask(tIntegerType if_mask, tIntegerType then_val, + tIntegerType else_val) { + return BitXor(BitAnd(if_mask, then_val), BitAnd(BitNot(if_mask), else_val)); +} + +// For each input scalar, the corresponding bits of the result are set if the +// input scalar is non-zero. +template +tIntegerType MaskIfNonZero(tIntegerType a) { + static constexpr tIntegerType zero = 0; + return a ? BitNot(zero) : zero; +} + +// For each input scalar, the corresponding bits of the result are set if the +// input scalar is zero. +template +tIntegerType MaskIfZero(tIntegerType a) { + return MaskIfNonZero(!a); +} + +// For each pair of input scalars, the corresponding bits of the result are +// set if the input scalars are equal. +template +tIntegerType MaskIfEqual(tIntegerType a, tIntegerType b) { + return MaskIfNonZero(a == b); +} + +// For each pair of input scalars, the corresponding bits of the result are +// set if the input scalars are not equal. +template +tIntegerType MaskIfNotEqual(tIntegerType a, tIntegerType b) { + return MaskIfNonZero(a != b); +} + +// For each pair of input scalars, the corresponding bits of the result are +// set if the input scalars a, b satisfy a > b. +template +tIntegerType MaskIfGreaterThan(tIntegerType a, tIntegerType b) { + return MaskIfNonZero(a > b); +} + +// For each pair of input scalars, the corresponding bits of the result are +// set if the input scalars a, b satisfy a >= b. +template +tIntegerType MaskIfGreaterThanOrEqual(tIntegerType a, tIntegerType b) { + return MaskIfNonZero(a >= b); +} + +// For each pair of input scalars, the corresponding bits of the result are +// set if the input scalars a, b satisfy a < b. +template +tIntegerType MaskIfLessThan(tIntegerType a, tIntegerType b) { + return MaskIfNonZero(a < b); +} + +// For each pair of input scalars, the corresponding bits of the result are +// set if the input scalars a, b satisfy a <= b. +template +tIntegerType MaskIfLessThanOrEqual(tIntegerType a, tIntegerType b) { + return MaskIfNonZero(a <= b); +} + +// Returns true if all of the input scalars are nonzero. +// This function may currently assume that each of the input scalars has either +// all or none of its bits set. Otherwise, its behavior is currently undefined. +template +bool All(tIntegerType a) { + return a; +} + +// Returns true if any of the input scalars are nonzero. +// This function may currently assume that each of the input scalars has either +// all or none of its bits set. Otherwise, its behavior is currently undefined. +template +bool Any(tIntegerType a) { + return a; +} + +// Returns (a+b)/2, rounded to the nearest integer. +// Equivalent to VRHADD in the ARM NEON instruction set. +template +IntegerType RoundingHalfSum(IntegerType a, IntegerType b) { + static_assert(std::is_same::value, "unimplemented"); + (void)b; + return a; +} + +template <> +inline std::int32_t RoundingHalfSum(std::int32_t a, std::int32_t b) { + std::int64_t a64 = a; + std::int64_t b64 = b; + std::int64_t sum = a64 + b64; + std::int64_t sign = sum >= 0 ? 1 : -1; + return static_cast((sum + sign) / 2); +} + +template <> +inline std::int16_t RoundingHalfSum(std::int16_t a, std::int16_t b) { + std::int32_t a32 = a; + std::int32_t b32 = b; + std::int32_t sum = a32 + b32; + std::int32_t sign = sum >= 0 ? 1 : -1; + return static_cast((sum + sign) / 2); +} + +template +IntegerType SaturatingAdd(IntegerType a, IntegerType b) { + static_assert(std::is_same::value, "unimplemented"); + (void)b; + return a; +} + +// So far this is only needed for int16. +template <> +inline std::int16_t SaturatingAdd(std::int16_t a, std::int16_t b) { + std::int32_t a32 = a; + std::int32_t b32 = b; + std::int32_t sum = a32 + b32; + return static_cast( + std::min(static_cast(32767), + std::max(static_cast(-32768), sum))); +} + +// Returns a+b, saturating if the integers are 16bit or narrower, +// otherwise just a plain addition. +template +struct AddSaturatingIf16BitImpl { + static IntegerType Run(IntegerType a, IntegerType b) { return Add(a, b); } +}; +template +struct AddSaturatingIf16BitImpl { + static IntegerType Run(IntegerType a, IntegerType b) { + return SaturatingAdd(a, b); + } +}; +template +IntegerType AddSaturatingIf16Bit(IntegerType a, IntegerType b) { + using ScalarType = + typename FixedPointRawTypeTraits::ScalarRawType; + return AddSaturatingIf16BitImpl::Run(a, + b); +} + +// Returns the integer that represents the product of two fixed-point +// numbers, interpreting all integers as fixed-point values in the +// interval [-1, 1), rounding to the nearest value, and saturating +// -1 * -1 to the maximum value (since 1 is not in the half-open +// interval [-1, 1)). +// +// [The explanation below specializes to std::int32_t for example purpose.] +// +// The mapping between IntegerType and the interval [-1, 1) is unique and +// implied by IntegerType, which is assumed to be signed. For example, +// for IntegerType==std::int32_t, the mapping is +// real_value = integer_value / 2^31. +// So in this case, and leaving aside rounding and saturating, this +// function computes ((a / 2^31) * (b / 2^31)) * 2^31, which simplifies to +// (a * b) / 2^31. +// +// The 'doubling' part in the name of this function comes from the fact that +// this operation is very close to a "multiply-high" operation, keeping only +// the top half bits, except that that would be effectively computing +// (a * b) / 2^32, +// so here we are computing 2x that, since +// 1/2^31 = 2 * 1/2^32. +// The idea is to use all of the available 32 bits in the destination int32 +// value. +// +// [End of the explanation specializing to int32.] +// +// This is equivalent to the VQRDMULH instruction in ARM NEON. +template +IntegerType SaturatingRoundingDoublingHighMul(IntegerType a, IntegerType b) { + static_assert(std::is_same::value, "unimplemented"); + (void)b; + return a; +} + +// This function implements the same computation as the ARMv7 NEON VQRDMULH +// instruction. +template <> +inline std::int32_t SaturatingRoundingDoublingHighMul(std::int32_t a, + std::int32_t b) { + bool overflow = a == b && a == std::numeric_limits::min(); + std::int64_t a_64(a); + std::int64_t b_64(b); + std::int64_t ab_64 = a_64 * b_64; + std::int32_t nudge = ab_64 >= 0 ? (1 << 30) : (1 - (1 << 30)); + std::int32_t ab_x2_high32 = + static_cast((ab_64 + nudge) / (1ll << 31)); + return overflow ? std::numeric_limits::max() : ab_x2_high32; +} + +template <> +inline std::int16_t SaturatingRoundingDoublingHighMul(std::int16_t a, + std::int16_t b) { + bool overflow = a == b && a == std::numeric_limits::min(); + std::int32_t a_32(a); + std::int32_t b_32(b); + std::int32_t ab_32 = a_32 * b_32; + std::int16_t nudge = ab_32 >= 0 ? (1 << 14) : (1 - (1 << 14)); + std::int16_t ab_x2_high16 = + static_cast((ab_32 + nudge) / (1 << 15)); + return overflow ? std::numeric_limits::max() : ab_x2_high16; +} + +// Correctly-rounded-to-nearest division by a power-of-two. +// Also known as a rounding arithmetic right shift. +template +inline IntegerType RoundingDivideByPOT(IntegerType x, int exponent) { + assert(exponent >= 0); + assert(exponent <= 31); + const IntegerType mask = Dup((1ll << exponent) - 1); + const IntegerType zero = Dup(0); + const IntegerType one = Dup(1); + const IntegerType remainder = BitAnd(x, mask); + const IntegerType threshold = + Add(ShiftRight(mask, 1), BitAnd(MaskIfLessThan(x, zero), one)); + return Add(ShiftRight(x, exponent), + BitAnd(MaskIfGreaterThan(remainder, threshold), one)); +} + +// Returns the product of a run-time integer value by a compile-time power +// of two, with either a positive exponent (equivalent to an arithmetic +// left shift, saturating) or a negative exponent (equivalent to an arithmetic +// right shift, rounding to nearest). +template 0 ? 1 : Exponent < 0 ? -1 : 0)> +struct ImplSaturatingRoundingMultiplyByPOT {}; + +template +struct ImplSaturatingRoundingMultiplyByPOT { + static IntegerType eval(IntegerType x) { return x; } +}; + +template +struct ImplSaturatingRoundingMultiplyByPOT { + static IntegerType eval(IntegerType x) { + using ScalarIntegerType = + typename FixedPointRawTypeTraits::ScalarRawType; + const IntegerType min = + Dup(std::numeric_limits::min()); + const IntegerType max = + Dup(std::numeric_limits::max()); + const int ScalarIntegerTypeBits = 8 * sizeof(ScalarIntegerType); + + const std::int32_t threshold = + ((1 << (ScalarIntegerTypeBits - 1 - Exponent)) - 1); + const IntegerType positive_mask = + MaskIfGreaterThan(x, Dup(threshold)); + const IntegerType negative_mask = + MaskIfLessThan(x, Dup(-threshold)); + + IntegerType result = ShiftLeft(x, Exponent); + result = SelectUsingMask(positive_mask, max, result); + result = SelectUsingMask(negative_mask, min, result); + return result; + } +}; + +template +struct ImplSaturatingRoundingMultiplyByPOT { + static IntegerType eval(IntegerType x) { + return RoundingDivideByPOT(x, -Exponent); + } +}; + +template +IntegerType SaturatingRoundingMultiplyByPOT(IntegerType x) { + return ImplSaturatingRoundingMultiplyByPOT::eval(x); +} + +// Part 2: the FixedPoint class. + +// A FixedPoint object represents a fixed-point value stored in the underlying +// integer type tRawType, if tRawType is a plain scalar integer type. +// Alternatively, tRawType may be a SIMD type (e.g. NEON int32x4_t) in which +// case a FixedPoint object represents a corresponding SIMD vector of fixed +// point values. +// +// tIntegerBits describes the range of the fixed-point format: if +// tIntegerBits == m then the range of representable values is the half-open +// interval [-2^m; 2^m) where the open boundary on the right side means that +// 2^m is not representable (how close the maximum representable value is to +// it, depends on bit-depth of tRawType). +// +// In "Q format notation", +// https://en.wikipedia.org/wiki/Q_(number_format) +// we are describing the format +// Qm.n +// where +// m = tIntegerBits +// and +// n = NumberOfBits(tRawType) - (m + 1) +// Note that the (m + 1) in the above line is because we adopt the convention +// that we count the integer bits exclusively of the sign bit; so (m + 1) is +// the total number of integer bits inclusive of the sign bit. +// +// Accordingly, the number of integral representable values in our range +// [-2^m ; 2^m) +// is equal to 2^(m+1). +template +class FixedPoint { + public: + typedef tRawType RawType; + + typedef FixedPointRawTypeTraits RawTypeTraits; + typedef typename RawTypeTraits::ScalarRawType ScalarRawType; + + static constexpr int kTotalBits = 8 * sizeof(ScalarRawType); + static constexpr int kIntegerBits = tIntegerBits; + static constexpr int kFractionalBits = kTotalBits - 1 - kIntegerBits; + static_assert(kIntegerBits >= 0 && kIntegerBits < kTotalBits, + "bad IntegerBits"); + + typedef FixedPoint ScalarFixedPointType; + + static const ScalarRawType ScalarRawMin() { + return std::numeric_limits::min(); + } + + static const ScalarRawType ScalarRawMax() { + return std::numeric_limits::max(); + } + + static const ScalarRawType RawMin() { + return VectorFromScalar(ScalarRawMin()); + } + + static const ScalarRawType RawMax() { + return VectorFromScalar(ScalarRawMax()); + } + + static FixedPoint FromRaw(RawType x) { + FixedPoint retval; + retval.raw() = x; + return retval; + } + + static FixedPoint FromScalarRaw(ScalarRawType x) { + FixedPoint retval; + retval.raw() = Dup(x); + return retval; + } + + static FixedPoint FromScalarFixedPoint(ScalarFixedPointType x) { + return FromScalarRaw(x.raw()); + } + + template + static FixedPoint ConstantPOT() { + static constexpr int kOffset = kFractionalBits + Exponent; + static_assert( + kOffset < 31, + "Constant not exactly representable in this fixed-point format"); + return FromScalarRaw(ScalarRawType(1) << kOffset); + } + + static FixedPoint Zero() { return FromScalarRaw(0); } + + static FixedPoint One() { + return FromScalarRaw( + kIntegerBits == 0 + ? ScalarRawMax() + : (ScalarRawType(1) << (kIntegerBits == 0 ? 0 : kFractionalBits))); + } + + static FixedPoint FromDouble(double x) { + const double min_bound = static_cast(ScalarRawMin()); + const double max_bound = static_cast(ScalarRawMax()); + return FromScalarRaw(static_cast(std::min( + std::max(round(x * static_cast(1ll << kFractionalBits)), + min_bound), + max_bound))); + } + + RawType raw() const { return i_; } + RawType& raw() { return i_; } + + private: + RawType i_; +}; + +// Part 3: implementation of arithmetic operators for the +// FixedPoint class, and a few related functions. + +// A FixedPoint multiplication is just a +// SaturatingRoundingDoublingHighMul operation on the underlying +// raw integer values. The IntegerBits simply add up, as is obvious +// from the fact that the range is [-2^IntegerBits, 2^IntegerBits). +template +FixedPoint operator*( + FixedPoint a, + FixedPoint b) { + FixedPoint c; + c.raw() = SaturatingRoundingDoublingHighMul(a.raw(), b.raw()); + return c; +} + +// Tweaking IntegerBits gives exact multiplication by a power of two. +template +FixedPoint ExactMulByPot( + FixedPoint a) { + FixedPoint c; + c.raw() = a.raw(); + return c; +} + +// If we want to leave IntegerBits fixed, then multiplication +// by a power of two has to be saturating/rounding, not exact anymore. +template +FixedPoint SaturatingRoundingMultiplyByPOT( + FixedPoint a) { + return FixedPoint::FromRaw( + SaturatingRoundingMultiplyByPOT(a.raw())); +} + +// Generic arithmetic operators. + +#define MAKE_FIXEDPOINT_UNARY_FUNC(FuncName, ImplFuncName) \ + template \ + FixedPoint FuncName( \ + FixedPoint a) { \ + return FixedPoint::FromRaw(ImplFuncName(a.raw())); \ + } + +#define MAKE_FIXEDPOINT_BINARY_FUNC(FuncName, ImplFuncName) \ + template \ + FixedPoint FuncName( \ + FixedPoint a, \ + FixedPoint b) { \ + return FixedPoint::FromRaw( \ + ImplFuncName(a.raw(), b.raw())); \ + } + +MAKE_FIXEDPOINT_UNARY_FUNC(operator-, Neg) +MAKE_FIXEDPOINT_UNARY_FUNC(operator~, BitNot) +MAKE_FIXEDPOINT_BINARY_FUNC(operator+, Add) +MAKE_FIXEDPOINT_BINARY_FUNC(operator-, Sub) +MAKE_FIXEDPOINT_BINARY_FUNC(operator&, BitAnd) +MAKE_FIXEDPOINT_BINARY_FUNC(operator^, BitXor) +MAKE_FIXEDPOINT_BINARY_FUNC(operator|, BitOr) +MAKE_FIXEDPOINT_BINARY_FUNC(RoundingHalfSum, RoundingHalfSum) + +#undef MAKE_FIXEDPOINT_UNARY_FUNC +#undef MAKE_FIXEDPOINT_BINARY_FUNC + +#define MAKE_FIXEDPOINT_UNARY_FUNC_RETURNING_RAW(FuncName) \ + template \ + tRawType FuncName(FixedPoint a) { \ + return FuncName(a.raw()); \ + } + +#define MAKE_FIXEDPOINT_BINARY_FUNC_RETURNING_RAW(FuncName) \ + template \ + tRawType FuncName(FixedPoint a, \ + FixedPoint b) { \ + return FuncName(a.raw(), b.raw()); \ + } + +MAKE_FIXEDPOINT_UNARY_FUNC_RETURNING_RAW(MaskIfZero) +MAKE_FIXEDPOINT_UNARY_FUNC_RETURNING_RAW(MaskIfNonZero) +MAKE_FIXEDPOINT_BINARY_FUNC_RETURNING_RAW(MaskIfEqual) +MAKE_FIXEDPOINT_BINARY_FUNC_RETURNING_RAW(MaskIfNotEqual) +MAKE_FIXEDPOINT_BINARY_FUNC_RETURNING_RAW(MaskIfGreaterThan) +MAKE_FIXEDPOINT_BINARY_FUNC_RETURNING_RAW(MaskIfGreaterThanOrEqual) +MAKE_FIXEDPOINT_BINARY_FUNC_RETURNING_RAW(MaskIfLessThan) +MAKE_FIXEDPOINT_BINARY_FUNC_RETURNING_RAW(MaskIfLessThanOrEqual) + +#undef MAKE_FIXEDPOINT_UNARY_FUNC_RETURNING_RAW +#undef MAKE_FIXEDPOINT_BINARY_FUNC_RETURNING_RAW + +template +FixedPoint SelectUsingMask( + tRawType if_mask, FixedPoint then_val, + FixedPoint else_val) { + return FixedPoint::FromRaw( + SelectUsingMask(if_mask, then_val.raw(), else_val.raw())); +} + +template +bool operator==(FixedPoint a, + FixedPoint b) { + return All(MaskIfEqual(a.raw(), b.raw())); +} + +template +bool operator!=(FixedPoint a, + FixedPoint b) { + return !(a == b); +} + +template +FixedPoint SaturatingAdd( + FixedPoint a, + FixedPoint b) { + return FixedPoint::FromRaw( + SaturatingAdd(a.raw(), b.raw())); +} + +template +FixedPoint AddSaturatingIf16Bit( + FixedPoint a, + FixedPoint b) { + return FixedPoint::FromRaw( + AddSaturatingIf16Bit(a.raw(), b.raw())); +} + +// Conversion to floating-point. +template +double ToDouble(FixedPoint x) { + static_assert(FixedPointRawTypeTraits::kLanes == 1, + "not applicable to SIMD types"); + typedef FixedPoint F; + return x.raw() / static_cast(1ll << F::kFractionalBits); +} + +// Rescale changes the number of IntegerBits and updates the underlying +// raw integer value accordingly. +template +FixedPoint Rescale( + FixedPoint x) { + static constexpr int kExponent = tIntegerBitsSrc - tIntegerBitsDst; + FixedPoint result; + result.raw() = SaturatingRoundingMultiplyByPOT(x.raw()); + return result; +} + +// CheckedFixedPointConstant allows to specify fixed-point constants +// initialized as real numbers, in a way that does not compile floating-point +// arithmetic in production code, yet still checks agreement with the +// floating-point expressions when asserts are enabled. +// +// The raw integer value provided is always a int32, encoding a 32-bit +// fixed-point value, regardless of the actual Scalar type. This allows +// writing generic code that applies just as well to the 32-bit and 16-bit +// cases. In the 16-bit case, the raw integer value is internally +// rounding-shifted by 16 bits to the right. +template +inline typename FixedPointType::ScalarRawType RescaleConstantInitializer( + std::int32_t int32_value) { + typedef typename FixedPointType::ScalarRawType ScalarRawType; + static constexpr int ScalarTypeBits = 8 * sizeof(ScalarRawType); + return static_cast( + RoundingDivideByPOT(int32_value, 32 - ScalarTypeBits)); +} +#ifdef GEMMLOWP_ENABLE_FIXEDPOINT_CONSTANTS_CHECKS +template +FixedPointType CheckedFixedPointConstant(std::int32_t raw_value, + double double_value) { + const FixedPointType result = FixedPointType::FromScalarRaw(raw_value); + assert(result == FixedPointType::FromDouble(double_value)); + return result; +} +#define GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(FixedPointType, \ + ScalarRawInt32Value, DoubleValue) \ + (gemmlowp::CheckedFixedPointConstant( \ + gemmlowp::RescaleConstantInitializer( \ + ScalarRawInt32Value), \ + DoubleValue)) + +#else +#define GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(FixedPointType, \ + ScalarRawInt32Value, DoubleValue) \ + (FixedPointType::FromScalarRaw( \ + gemmlowp::RescaleConstantInitializer( \ + ScalarRawInt32Value))) +#endif + +// Implementation of exponential function. + +// Returns exp(x) for x in [-1/4, 0). +template +FixedPoint exp_on_interval_between_negative_one_quarter_and_0_excl( + FixedPoint a) { + typedef FixedPoint F; + const F constant_term = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(F, 1895147668, std::exp(-1.0 / 8.0)); + const F constant_1_over_3 = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(F, 715827883, 1.0 / 3.0); + // We're evaluating a Taylor expansion around -1/8, so we do the change of + // variable: x = a + 1/8. + // In fixed-point with 0 integer bits, 1/8 is represented by 1 << 28. + F x = a + F::template ConstantPOT<-3>(); + F x2 = x * x; + F x3 = x2 * x; + F x4 = x2 * x2; + F x4_over_4 = SaturatingRoundingMultiplyByPOT<-2>(x4); + F x4_over_24_plus_x3_over_6_plus_x2_over_2 = + SaturatingRoundingMultiplyByPOT<-1>( + ((x4_over_4 + x3) * constant_1_over_3) + x2); + return AddSaturatingIf16Bit( + constant_term, + constant_term * (x + x4_over_24_plus_x3_over_6_plus_x2_over_2)); +} + +// Returns exp(x) for x < 0. +template +FixedPoint exp_on_negative_values( + FixedPoint a) { + typedef FixedPoint InputF; + typedef FixedPoint ResultF; + static constexpr int kFractionalBits = InputF::kFractionalBits; + static constexpr int kIntegerBits = InputF::kIntegerBits; + const InputF kOneQuarter = InputF::template ConstantPOT<-2>(); + InputF mask = kOneQuarter - InputF::FromScalarRaw(1); + InputF a_mod_quarter_minus_one_quarter = (a & mask) - kOneQuarter; + ResultF result = exp_on_interval_between_negative_one_quarter_and_0_excl( + Rescale<0>(a_mod_quarter_minus_one_quarter)); + tRawType remainder = (a_mod_quarter_minus_one_quarter - a).raw(); + +#define GEMMLOWP_EXP_BARREL_SHIFTER(Exponent, FixedPointMultiplier) \ + if (kIntegerBits > Exponent) { \ + const ResultF kMultiplier = GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT( \ + ResultF, FixedPointMultiplier, std::exp(-std::pow(2.0, Exponent))); \ + static constexpr int kShiftAmount = \ + kIntegerBits > Exponent ? kFractionalBits + Exponent : 0; \ + result = SelectUsingMask( \ + MaskIfNonZero(BitAnd(remainder, Dup(1 << kShiftAmount))), \ + result * kMultiplier, result); \ + } + + GEMMLOWP_EXP_BARREL_SHIFTER(-2, 1672461947); + GEMMLOWP_EXP_BARREL_SHIFTER(-1, 1302514674); + GEMMLOWP_EXP_BARREL_SHIFTER(+0, 790015084); + GEMMLOWP_EXP_BARREL_SHIFTER(+1, 290630308); + GEMMLOWP_EXP_BARREL_SHIFTER(+2, 39332535); + GEMMLOWP_EXP_BARREL_SHIFTER(+3, 720401); + GEMMLOWP_EXP_BARREL_SHIFTER(+4, 242); + +#undef GEMMLOWP_EXP_BARREL_SHIFTER + + static constexpr int clampB = kIntegerBits > 5 ? 36 - kIntegerBits : 0; + if (kIntegerBits > 5) { + const InputF clamp = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(InputF, -(1 << clampB), -32.0); + result = SelectUsingMask(MaskIfLessThan(a, clamp), ResultF::Zero(), result); + } + + result = SelectUsingMask(MaskIfZero(a), ResultF::One(), result); + return result; +} + +// Implementation of tanh: (1 - exp(-2x)) / (1 + exp(-2x)). + +// Returns (1 - x) / (1 + x) for x in (0, 1). +template +FixedPoint one_minus_x_over_one_plus_x_for_x_in_0_1( + FixedPoint a) { + typedef FixedPoint F0; + typedef FixedPoint F2; + F0 half_denominator = RoundingHalfSum(a, F0::One()); + // Newton-Raphson division + // https://en.wikipedia.org/wiki/Division_algorithm#Newton.E2.80.93Raphson_division + // Refer to that page for the logic behind the 48/17 and 32/17 constants. + const F2 constant_48_over_17 = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(F2, 1515870810, 48.0 / 17.0); + const F2 constant_neg_32_over_17 = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(F2, -1010580540, -32.0 / 17.0); + F2 x = constant_48_over_17 + half_denominator * constant_neg_32_over_17; + for (int i = 0; i < 3; i++) { + F2 half_denominator_times_x = half_denominator * x; + F2 one_minus_half_denominator_times_x = + F2::One() - half_denominator_times_x; + x = x + Rescale<2>(x * one_minus_half_denominator_times_x); + } + return Rescale<0>(x - F2::One()); +} + +// Returns -tanh(x) for x < 0. +template +FixedPoint neg_tanh_on_negative_values( + FixedPoint a) { + return one_minus_x_over_one_plus_x_for_x_in_0_1( + exp_on_negative_values(ExactMulByPot<1>(a))); +} + +// Returns tanh(x) for any x. +template +FixedPoint tanh(FixedPoint a) { + typedef FixedPoint InputF; + typedef FixedPoint ResultF; + tRawType mask_if_negative = MaskIfLessThan(a, InputF::Zero()); + tRawType mask_if_zero = MaskIfZero(a); + InputF n = SelectUsingMask(mask_if_negative, a, -a); + ResultF t = neg_tanh_on_negative_values(n); + return SelectUsingMask(mask_if_zero, ResultF::Zero(), + SelectUsingMask(mask_if_negative, -t, t)); +} + +// Implementation of logistic function. + +// Returns 1 / (1 + x) for x in (0, 1). +template +FixedPoint one_over_one_plus_x_for_x_in_0_1( + FixedPoint a) { + typedef FixedPoint F0; + typedef FixedPoint F2; + F0 half_denominator = RoundingHalfSum(a, F0::One()); + // Newton-Raphson division + // https://en.wikipedia.org/wiki/Division_algorithm#Newton.E2.80.93Raphson_division + // Refer to that page for the logic behind the 48/17 and 32/17 constants. + const F2 constant_48_over_17 = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(F2, 1515870810, 48.0 / 17.0); + const F2 constant_neg_32_over_17 = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(F2, -1010580540, -32.0 / 17.0); + F2 x = constant_48_over_17 + half_denominator * constant_neg_32_over_17; + for (int i = 0; i < 3; i++) { + F2 half_denominator_times_x = half_denominator * x; + F2 one_minus_half_denominator_times_x = + F2::One() - half_denominator_times_x; + x = x + Rescale<2>(x * one_minus_half_denominator_times_x); + } + return Rescale<0>(ExactMulByPot<-1>(x)); +} + +// Returns logistic(x) = 1 / (1 + exp(-x)) for x > 0. +template +FixedPoint logistic_on_positive_values( + FixedPoint a) { + return one_over_one_plus_x_for_x_in_0_1(exp_on_negative_values(-a)); +} + +// Returns logistic(x) = 1 / (1 + exp(-x)) for any x. +template +FixedPoint logistic(FixedPoint a) { + typedef FixedPoint InputF; + typedef FixedPoint ResultF; + tRawType mask_if_positive = MaskIfGreaterThan(a, InputF::Zero()); + tRawType mask_if_zero = MaskIfZero(a); + InputF abs_input = SelectUsingMask(mask_if_positive, a, -a); + ResultF result_if_positive = logistic_on_positive_values(abs_input); + ResultF result_if_negative = ResultF::One() - result_if_positive; + const ResultF one_half = + GEMMLOWP_CHECKED_FIXEDPOINT_CONSTANT(ResultF, 1 << 30, 0.5); + return SelectUsingMask(mask_if_zero, one_half, + SelectUsingMask(mask_if_positive, result_if_positive, + result_if_negative)); +} + +} // end namespace gemmlowp + +#ifdef GEMMLOWP_NEON +#include "./fixedpoint_neon.h" +#elif defined(GEMMLOWP_AVX2) +#include "./fixedpoint_avx.h" +#elif defined(GEMMLOWP_SSE4) +#include "./fixedpoint_sse.h" +#elif defined(GEMMLOWP_MSA) +#include "./fixedpoint_msa.h" +#endif + +#endif // GEMMLOWP_INTERNAL_FIXEDPOINT_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint_neon.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint_neon.h new file mode 100644 index 000000000..646c5907b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint_neon.h @@ -0,0 +1,331 @@ +// Copyright 2015 The Gemmlowp Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// fixedpoint_neon.h: optimized NEON specializations of the templates +// in fixedpoint.h. + +#ifndef GEMMLOWP_INTERNAL_FIXEDPOINT_NEON_H_ +#define GEMMLOWP_INTERNAL_FIXEDPOINT_NEON_H_ + +#include + +namespace gemmlowp { + +template <> +struct FixedPointRawTypeTraits { + typedef std::int32_t ScalarRawType; + static constexpr int kLanes = 4; +}; + +template <> +struct FixedPointRawTypeTraits { + typedef std::int16_t ScalarRawType; + static constexpr int kLanes = 8; +}; + +template <> +inline int32x4_t BitAnd(int32x4_t a, int32x4_t b) { + return vandq_s32(a, b); +} + +template <> +inline int16x8_t BitAnd(int16x8_t a, int16x8_t b) { + return vandq_s16(a, b); +} + +template <> +inline int32x4_t BitOr(int32x4_t a, int32x4_t b) { + return vorrq_s32(a, b); +} + +template <> +inline int16x8_t BitOr(int16x8_t a, int16x8_t b) { + return vorrq_s16(a, b); +} + +template <> +inline int32x4_t BitXor(int32x4_t a, int32x4_t b) { + return veorq_s32(a, b); +} + +template <> +inline int16x8_t BitXor(int16x8_t a, int16x8_t b) { + return veorq_s16(a, b); +} + +template <> +inline int32x4_t BitNot(int32x4_t a) { + return veorq_s32(a, vdupq_n_s32(-1)); +} + +template <> +inline int16x8_t BitNot(int16x8_t a) { + return veorq_s16(a, vdupq_n_s16(-1)); +} + +template <> +inline int32x4_t Add(int32x4_t a, int32x4_t b) { + return vaddq_s32(a, b); +} + +template <> +inline int16x8_t Add(int16x8_t a, int16x8_t b) { + return vaddq_s16(a, b); +} + +template <> +inline int32x4_t Sub(int32x4_t a, int32x4_t b) { + return vsubq_s32(a, b); +} + +template <> +inline int16x8_t Sub(int16x8_t a, int16x8_t b) { + return vsubq_s16(a, b); +} + +template <> +inline int32x4_t Neg(int32x4_t a) { + return vnegq_s32(a); +} + +template <> +inline int16x8_t Neg(int16x8_t a) { + return vnegq_s16(a); +} + +template <> +inline int32x4_t ShiftLeft(int32x4_t a, int offset) { + return vshlq_s32(a, vdupq_n_s32(offset)); +} + +template <> +inline int16x8_t ShiftLeft(int16x8_t a, int offset) { + return vshlq_s16(a, vdupq_n_s16(offset)); +} + +template <> +inline int32x4_t ShiftRight(int32x4_t a, int offset) { + return vshlq_s32(a, vdupq_n_s32(-offset)); +} + +template <> +inline int16x8_t ShiftRight(int16x8_t a, int offset) { + return vshlq_s16(a, vdupq_n_s16(-offset)); +} + +template <> +inline int32x4_t SelectUsingMask(int32x4_t if_mask, int32x4_t then_val, + int32x4_t else_val) { + return vbslq_s32(vreinterpretq_u32_s32(if_mask), then_val, else_val); +} + +template <> +inline int16x8_t SelectUsingMask(int16x8_t if_mask, int16x8_t then_val, + int16x8_t else_val) { + return vbslq_s16(vreinterpretq_u16_s16(if_mask), then_val, else_val); +} + +template <> +inline int32x4_t MaskIfEqual(int32x4_t a, int32x4_t b) { + return vreinterpretq_s32_u32(vceqq_s32(a, b)); +} + +template <> +inline int16x8_t MaskIfEqual(int16x8_t a, int16x8_t b) { + return vreinterpretq_s16_u16(vceqq_s16(a, b)); +} + +template <> +inline int32x4_t MaskIfNotEqual(int32x4_t a, int32x4_t b) { + return BitNot(MaskIfEqual(a, b)); +} + +template <> +inline int16x8_t MaskIfNotEqual(int16x8_t a, int16x8_t b) { + return BitNot(MaskIfEqual(a, b)); +} + +template <> +inline int32x4_t MaskIfZero(int32x4_t a) { + return MaskIfEqual(a, vdupq_n_s32(0)); +} + +template <> +inline int16x8_t MaskIfZero(int16x8_t a) { + return MaskIfEqual(a, vdupq_n_s16(0)); +} + +template <> +inline int32x4_t MaskIfNonZero(int32x4_t a) { + return vreinterpretq_s32_u32(vtstq_s32(a, a)); +} + +template <> +inline int16x8_t MaskIfNonZero(int16x8_t a) { + return vreinterpretq_s16_u16(vtstq_s16(a, a)); +} + +template <> +inline int32x4_t MaskIfGreaterThan(int32x4_t a, int32x4_t b) { + return vreinterpretq_s32_u32(vcgtq_s32(a, b)); +} + +template <> +inline int16x8_t MaskIfGreaterThan(int16x8_t a, int16x8_t b) { + return vreinterpretq_s16_u16(vcgtq_s16(a, b)); +} + +template <> +inline int32x4_t MaskIfGreaterThanOrEqual(int32x4_t a, int32x4_t b) { + return vreinterpretq_s32_u32(vcgeq_s32(a, b)); +} + +template <> +inline int16x8_t MaskIfGreaterThanOrEqual(int16x8_t a, int16x8_t b) { + return vreinterpretq_s16_u16(vcgeq_s16(a, b)); +} + +template <> +inline int32x4_t MaskIfLessThan(int32x4_t a, int32x4_t b) { + return vreinterpretq_s32_u32(vcltq_s32(a, b)); +} + +template <> +inline int16x8_t MaskIfLessThan(int16x8_t a, int16x8_t b) { + return vreinterpretq_s16_u16(vcltq_s16(a, b)); +} + +template <> +inline int32x4_t MaskIfLessThanOrEqual(int32x4_t a, int32x4_t b) { + return vreinterpretq_s32_u32(vcleq_s32(a, b)); +} + +template <> +inline int16x8_t MaskIfLessThanOrEqual(int16x8_t a, int16x8_t b) { + return vreinterpretq_s16_u16(vcleq_s16(a, b)); +} + +template <> +inline bool All(int32x4_t a) { + a = vandq_s32(a, vextq_s32(a, a, 1)); + a = vandq_s32(a, vextq_s32(a, a, 2)); + return vgetq_lane_s32(a, 0); +} + +template <> +inline bool All(int16x8_t a) { + a = vandq_s16(a, vextq_s16(a, a, 1)); + a = vandq_s16(a, vextq_s16(a, a, 2)); + a = vandq_s16(a, vextq_s16(a, a, 4)); + return vgetq_lane_s16(a, 0); +} + +template <> +inline bool Any(int32x4_t a) { + a = vorrq_s32(a, vextq_s32(a, a, 1)); + a = vorrq_s32(a, vextq_s32(a, a, 2)); + return vgetq_lane_s32(a, 0); +} + +template <> +inline bool Any(int16x8_t a) { + a = vorrq_s16(a, vextq_s16(a, a, 1)); + a = vorrq_s16(a, vextq_s16(a, a, 2)); + a = vorrq_s16(a, vextq_s16(a, a, 4)); + return vgetq_lane_s16(a, 0); +} + +template <> +inline int32x4_t RoundingHalfSum(int32x4_t a, int32x4_t b) { + return vrhaddq_s32(a, b); +} + +template <> +inline int16x8_t RoundingHalfSum(int16x8_t a, int16x8_t b) { + return vrhaddq_s16(a, b); +} + +template <> +inline int32x4_t SaturatingRoundingDoublingHighMul(int32x4_t a, int32x4_t b) { + return vqrdmulhq_s32(a, b); +} + +template <> +inline int16x8_t SaturatingRoundingDoublingHighMul(int16x8_t a, int16x8_t b) { + return vqrdmulhq_s16(a, b); +} + +template <> +inline int32x4_t RoundingDivideByPOT(int32x4_t x, int exponent) { + const int32x4_t shift_vec = vdupq_n_s32(-exponent); + const int32x4_t fixup = vshrq_n_s32(vandq_s32(x, shift_vec), 31); + const int32x4_t fixed_up_x = vqaddq_s32(x, fixup); + return vrshlq_s32(fixed_up_x, shift_vec); +} + +template <> +inline int16x8_t RoundingDivideByPOT(int16x8_t x, int exponent) { + const int16x8_t shift_vec = vdupq_n_s16(-exponent); + const int16x8_t fixup = vshrq_n_s16(vandq_s16(x, shift_vec), 15); + const int16x8_t fixed_up_x = vqaddq_s16(x, fixup); + return vrshlq_s16(fixed_up_x, shift_vec); +} + +template +struct ImplSaturatingRoundingMultiplyByPOT { + static int32x4_t eval(int32x4_t x) { return vqshlq_n_s32(x, Exponent); } +}; + +template +struct ImplSaturatingRoundingMultiplyByPOT { + static int32x4_t eval(int32x4_t x) { + const int32x4_t fixup = vshrq_n_s32(x, 31); + const int32x4_t fixed_up_x = vqaddq_s32(x, fixup); + return vrshrq_n_s32(fixed_up_x, -Exponent); + } +}; + +template +struct ImplSaturatingRoundingMultiplyByPOT { + static int16x8_t eval(int16x8_t x) { return vqshlq_n_s16(x, Exponent); } +}; + +template +struct ImplSaturatingRoundingMultiplyByPOT { + static int16x8_t eval(int16x8_t x) { + const int16x8_t fixup = vshrq_n_s16(x, 15); + const int16x8_t fixed_up_x = vqaddq_s16(x, fixup); + return vrshrq_n_s16(fixed_up_x, -Exponent); + } +}; + +template <> +inline int32x4_t Dup(std::int32_t x) { + return vdupq_n_s32(x); +} + +template <> +inline int16x8_t Dup(std::int16_t x) { + return vdupq_n_s16(x); +} + +// So far this is only needed for int16. +template <> +inline int16x8_t SaturatingAdd(int16x8_t a, int16x8_t b) { + return vqaddq_s16(a, b); +} + +} // end namespace gemmlowp + +#endif // GEMMLOWP_INTERNAL_FIXEDPOINT_NEON_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint_sse.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint_sse.h new file mode 100644 index 000000000..45e0e5597 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/fixedpoint/fixedpoint_sse.h @@ -0,0 +1,384 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// fixedpoint_SSE.h: optimized SSE specializations of the templates +// in fixedpoint.h. + +#ifndef GEMMLOWP_INTERNAL_FIXEDPOINT_SSE_H_ +#define GEMMLOWP_INTERNAL_FIXEDPOINT_SSE_H_ + +#include +#include "third_party/gemmlowp/fixedpoint/fixedpoint.h" + +namespace gemmlowp { + +// SSE intrinsics are not finely typed: there is a single __m128i vector +// type that does not distinguish between "int32x4" and "int16x8" use +// cases, unlike the NEON equivalents. Because we had initially focused +// on int32x4, we did not pay attention and specialized these fixedpoint +// templates directly for __m128i hardcoding the int32x4 semantics, +// not leaving room for int16x8 semantics. Amending that by adding a separate +// data type, int16x8_m128i, that wraps __m128i while being a separate +// type. +struct int16x8_m128i { + int16x8_m128i() {} + explicit int16x8_m128i(__m128i w) : v(w) {} + ~int16x8_m128i() {} + + __m128i v; +}; + +template <> +struct FixedPointRawTypeTraits<__m128i> { + typedef std::int32_t ScalarRawType; + static constexpr int kLanes = 4; +}; + +template <> +struct FixedPointRawTypeTraits { + typedef std::int16_t ScalarRawType; + static constexpr int kLanes = 8; +}; + +template <> +inline __m128i BitAnd(__m128i a, __m128i b) { + return _mm_and_si128(a, b); +} + +template <> +inline int16x8_m128i BitAnd(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_and_si128(a.v, b.v)); +} + +template <> +inline __m128i BitOr(__m128i a, __m128i b) { + return _mm_or_si128(a, b); +} + +template <> +inline int16x8_m128i BitOr(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_or_si128(a.v, b.v)); +} + +template <> +inline __m128i BitXor(__m128i a, __m128i b) { + return _mm_xor_si128(a, b); +} + +template <> +inline int16x8_m128i BitXor(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_xor_si128(a.v, b.v)); +} + +template <> +inline __m128i BitNot(__m128i a) { + return _mm_andnot_si128(a, _mm_set1_epi32(-1)); +} + +template <> +inline int16x8_m128i BitNot(int16x8_m128i a) { + return int16x8_m128i(_mm_andnot_si128(a.v, _mm_set1_epi16(-1))); +} + +template <> +inline __m128i Add(__m128i a, __m128i b) { + return _mm_add_epi32(a, b); +} + +template <> +inline int16x8_m128i Add(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_add_epi16(a.v, b.v)); +} + +template <> +inline __m128i Mul(__m128i a, __m128i b) { + return _mm_mullo_epi32(a, b); +} + +template <> +inline int16x8_m128i Mul(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_mullo_epi16(a.v, b.v)); +} + +template <> +inline __m128i Sub(__m128i a, __m128i b) { + return _mm_sub_epi32(a, b); +} + +template <> +inline int16x8_m128i Sub(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_sub_epi16(a.v, b.v)); +} + +template <> +inline __m128i Neg(__m128i a) { + return _mm_sign_epi32(a, _mm_set1_epi32(-1)); +} + +template <> +inline int16x8_m128i Neg(int16x8_m128i a) { + return int16x8_m128i(_mm_sign_epi16(a.v, _mm_set1_epi16(-1))); +} + +template <> +inline __m128i ShiftLeft(__m128i a, int offset) { + return _mm_slli_epi32(a, offset); +} + +template <> +inline int16x8_m128i ShiftLeft(int16x8_m128i a, int offset) { + return int16x8_m128i(_mm_slli_epi16(a.v, offset)); +} + +template <> +inline __m128i ShiftRight(__m128i a, int offset) { + return _mm_srai_epi32(a, offset); +} + +template <> +inline int16x8_m128i ShiftRight(int16x8_m128i a, int offset) { + return int16x8_m128i(_mm_srai_epi16(a.v, offset)); +} + +template <> +inline __m128i SelectUsingMask(__m128i if_mask, __m128i then_val, + __m128i else_val) { + // borrowed from Intel's arm_neon_sse.h header. + return _mm_or_si128(_mm_and_si128(if_mask, then_val), + _mm_andnot_si128(if_mask, else_val)); +} + +template <> +inline int16x8_m128i SelectUsingMask(int16x8_m128i if_mask, + int16x8_m128i then_val, + int16x8_m128i else_val) { + // borrowed from Intel's arm_neon_sse.h header. + return int16x8_m128i(SelectUsingMask(if_mask.v, then_val.v, else_val.v)); +} + +template <> +inline __m128i MaskIfEqual(__m128i a, __m128i b) { + return _mm_cmpeq_epi32(a, b); +} + +template <> +inline int16x8_m128i MaskIfEqual(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_cmpeq_epi16(a.v, b.v)); +} + +template <> +inline __m128i MaskIfNotEqual(__m128i a, __m128i b) { + return BitNot(MaskIfEqual(a, b)); +} + +template <> +inline int16x8_m128i MaskIfNotEqual(int16x8_m128i a, int16x8_m128i b) { + return BitNot(MaskIfEqual(a, b)); +} + +template <> +inline __m128i MaskIfZero(__m128i a) { + return MaskIfEqual(a, _mm_set1_epi32(0)); +} + +template <> +inline int16x8_m128i MaskIfZero(int16x8_m128i a) { + return MaskIfEqual(a, int16x8_m128i(_mm_set1_epi16(0))); +} + +template <> +inline __m128i MaskIfNonZero(__m128i a) { + return MaskIfNotEqual(a, _mm_set1_epi32(0)); +} + +template <> +inline int16x8_m128i MaskIfNonZero(int16x8_m128i a) { + return MaskIfNotEqual(a, int16x8_m128i(_mm_set1_epi16(0))); +} + +template <> +inline __m128i MaskIfGreaterThan(__m128i a, __m128i b) { + return _mm_cmpgt_epi32(a, b); +} + +template <> +inline int16x8_m128i MaskIfGreaterThan(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_cmpgt_epi16(a.v, b.v)); +} + +template <> +inline __m128i MaskIfLessThan(__m128i a, __m128i b) { + return _mm_cmplt_epi32(a, b); +} + +template <> +inline int16x8_m128i MaskIfLessThan(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_cmplt_epi16(a.v, b.v)); +} + +template <> +inline __m128i MaskIfGreaterThanOrEqual(__m128i a, __m128i b) { + return BitNot(MaskIfLessThan(a, b)); +} + +template <> +inline int16x8_m128i MaskIfGreaterThanOrEqual(int16x8_m128i a, + int16x8_m128i b) { + return BitNot(MaskIfLessThan(a, b)); +} + +template <> +inline __m128i MaskIfLessThanOrEqual(__m128i a, __m128i b) { + return BitNot(MaskIfGreaterThan(a, b)); +} + +template <> +inline int16x8_m128i MaskIfLessThanOrEqual(int16x8_m128i a, int16x8_m128i b) { + return BitNot(MaskIfGreaterThan(a, b)); +} + +/* Assumptions: + - All and Any are used on masks. + - masks are all_ones for true lanes, all_zeroes otherwise. +Hence, All means all 128bits set, and Any means any bit set. +*/ + +template <> +inline bool All(__m128i a) { + return _mm_testc_si128(a, a); +} + +template <> +inline bool All(int16x8_m128i a) { + return _mm_testc_si128(a.v, a.v); +} + +template <> +inline bool Any(__m128i a) { + return !_mm_testz_si128(a, a); +} + +template <> +inline bool Any(int16x8_m128i a) { + return !_mm_testz_si128(a.v, a.v); +} + +template <> +inline __m128i RoundingHalfSum(__m128i a, __m128i b) { + /* __m128i round_bit_mask, a_over_2, b_over_2, round_bit, sum; */ + /* We divide the inputs before the add to avoid the overflow and costly test + */ + /* of checking if an overflow occured on signed add */ + /* round_bit_mask = _mm_set1_epi32(1); */ + /* a_over_2 = _mm_srai_epi32(a, 1); */ + /* b_over_2 = _mm_srai_epi32(b, 1); */ + /* sum = Add(a_over_2, b_over_2); */ + /* round_bit = _mm_sign_epi32(BitAnd(BitOr(a,b), round_bit_mask), sum); */ + /* return Add(sum, round_bit); */ + + /* Other possibility detecting overflow and xor the sign if an overflow + * happened*/ + __m128i one, sign_bit_mask, sum, rounded_half_sum, overflow, result; + one = _mm_set1_epi32(1); + sign_bit_mask = _mm_set1_epi32(0x80000000); + sum = Add(a, b); + rounded_half_sum = _mm_srai_epi32(Add(sum, one), 1); + overflow = + BitAnd(BitAnd(BitXor(a, rounded_half_sum), BitXor(b, rounded_half_sum)), + sign_bit_mask); + result = BitXor(rounded_half_sum, overflow); + return result; +} + +template <> +inline int16x8_m128i RoundingHalfSum(int16x8_m128i a, int16x8_m128i b) { + // Idea: go to unsigned to use _mm_avg_epu16, + // borrowed from Intel's arm_neon_sse.h header. + __m128i constant_neg_32768 = _mm_set1_epi16(-32768); + __m128i a_unsigned = _mm_sub_epi16(a.v, constant_neg_32768); + __m128i b_unsigned = _mm_sub_epi16(b.v, constant_neg_32768); + __m128i avg_unsigned = _mm_avg_epu16(a_unsigned, b_unsigned); + __m128i avg = _mm_add_epi16(avg_unsigned, constant_neg_32768); + return int16x8_m128i(avg); +} + +template <> +inline __m128i SaturatingRoundingDoublingHighMul(__m128i a, __m128i b) { + __m128i min, saturation_mask, a0_a2, a1_a3, b0_b2, b1_b3; + __m128i a0b0_a2b2, a1b1_a3b3, a0b0_a2b2_rounded, a1b1_a3b3_rounded; + __m128i a0b0_a2b2_rounded_2x, a1b1_a3b3_rounded_2x, result; + __m128i nudge; + + // saturation only happen if a == b == INT_MIN + min = _mm_set1_epi32(std::numeric_limits::min()); + saturation_mask = BitAnd(MaskIfEqual(a, b), MaskIfEqual(a, min)); + + // a = a0 | a1 | a2 | a3 + // b = b0 | b1 | b2 | b3 + a0_a2 = a; + a1_a3 = _mm_srli_si128(a, 4); + b0_b2 = b; + b1_b3 = _mm_srli_si128(b, 4); + + a0b0_a2b2 = _mm_mul_epi32(a0_a2, b0_b2); + a1b1_a3b3 = _mm_mul_epi32(a1_a3, b1_b3); + + // do the rounding and take into account that it will be doubled + nudge = _mm_set1_epi64x(1 << 30); + a0b0_a2b2_rounded = _mm_add_epi64(a0b0_a2b2, nudge); + a1b1_a3b3_rounded = _mm_add_epi64(a1b1_a3b3, nudge); + + // do the doubling + a0b0_a2b2_rounded_2x = _mm_slli_epi64(a0b0_a2b2_rounded, 1); + a1b1_a3b3_rounded_2x = _mm_slli_epi64(a1b1_a3b3_rounded, 1); + + // get the high part of the products + result = _mm_blend_epi16(_mm_srli_si128(a0b0_a2b2_rounded_2x, 4), + a1b1_a3b3_rounded_2x, 0xcc); + + // saturate those which overflowed + return SelectUsingMask(saturation_mask, min, result); +} + +template <> +inline int16x8_m128i SaturatingRoundingDoublingHighMul(int16x8_m128i a, + int16x8_m128i b) { + // Idea: use _mm_mulhrs_epi16 then saturate with a bit-operation, + // borrowed from Intel's arm_neon_sse.h header. + __m128i result_unsaturated = _mm_mulhrs_epi16(a.v, b.v); + __m128i saturation_mask = + _mm_cmpeq_epi16(result_unsaturated, _mm_set1_epi16(0x8000)); + __m128i result = _mm_xor_si128(result_unsaturated, saturation_mask); + return int16x8_m128i(result); +} + +template <> +inline __m128i Dup<__m128i>(std::int32_t x) { + return _mm_set1_epi32(x); +} + +template <> +inline int16x8_m128i Dup(std::int16_t x) { + return int16x8_m128i(_mm_set1_epi16(x)); +} + +// So far this is only needed for int16. +template <> +inline int16x8_m128i SaturatingAdd(int16x8_m128i a, int16x8_m128i b) { + return int16x8_m128i(_mm_adds_epi16(a.v, b.v)); +} + +} // end namespace gemmlowp + +#endif // GEMMLOWP_INTERNAL_FIXEDPOINT_SSE_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/internal/detect_platform.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/internal/detect_platform.h new file mode 100644 index 000000000..6f06d19f6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/gemmlowp/internal/detect_platform.h @@ -0,0 +1,166 @@ +// Copyright 2018 The Gemmlowp Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// detect_platform.h: Sets up macros that control architecture-specific +// features of gemmlowp's implementation. + +#ifndef GEMMLOWP_INTERNAL_DETECT_PLATFORM_H_ +#define GEMMLOWP_INTERNAL_DETECT_PLATFORM_H_ + +// Our inline assembly path assume GCC/Clang syntax. +// Native Client doesn't seem to support inline assembly(?). +#if defined(__GNUC__) && !defined(__native_client__) +#define GEMMLOWP_ALLOW_INLINE_ASM +#endif + +// Define macro statement that avoids inlining for GCC. +// For non-GCC, define as empty macro. +#if defined(__GNUC__) +#define GEMMLOWP_NOINLINE __attribute__((noinline)) +#else +#define GEMMLOWP_NOINLINE +#endif + +// Detect ARM, 32-bit or 64-bit +#ifdef __arm__ +#define GEMMLOWP_ARM_32 +#endif + +#ifdef __aarch64__ +#define GEMMLOWP_ARM_64 +#endif + +#if defined(GEMMLOWP_ARM_32) || defined(GEMMLOWP_ARM_64) +#define GEMMLOWP_ARM +#endif + +// Detect MIPS, 32-bit or 64-bit +#if defined(__mips) && !defined(__LP64__) +#define GEMMLOWP_MIPS_32 +#endif + +#if defined(__mips) && defined(__LP64__) +#define GEMMLOWP_MIPS_64 +#endif + +#if defined(GEMMLOWP_MIPS_32) || defined(GEMMLOWP_MIPS_64) +#define GEMMLOWP_MIPS +#endif + +// Detect x86, 32-bit or 64-bit +#if defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__i386) +#define GEMMLOWP_X86_32 +#endif + +#if defined(__x86_64__) || defined(_M_X64) || defined(__amd64) +#define GEMMLOWP_X86_64 +#endif + +#if defined(GEMMLOWP_X86_32) || defined(GEMMLOWP_X86_64) +#define GEMMLOWP_X86 +#endif + +// Some of our optimized paths use inline assembly and for +// now we don't bother enabling some other optimized paths using intrinddics +// where we can't use inline assembly paths. +#ifdef GEMMLOWP_ALLOW_INLINE_ASM + +// Detect NEON. It's important to check for both tokens. +#if (defined __ARM_NEON) || (defined __ARM_NEON__) +#define GEMMLOWP_NEON +#endif + +// Convenience NEON tokens for 32-bit or 64-bit +#if defined(GEMMLOWP_NEON) && defined(GEMMLOWP_ARM_32) +#define GEMMLOWP_NEON_32 +#endif + +#if defined(GEMMLOWP_NEON) && defined(GEMMLOWP_ARM_64) +#define GEMMLOWP_NEON_64 +#endif + +// Detect MIPS MSA. +// Limit MSA optimizations to little-endian CPUs for now. +// TODO: Perhaps, eventually support MSA optimizations on big-endian CPUs? +#if defined(GEMMLOWP_MIPS) && (__mips_isa_rev >= 5) && defined(__mips_msa) && \ + defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#define GEMMLOWP_MSA +#endif + +// Convenience MIPS MSA tokens for 32-bit or 64-bit. +#if defined(GEMMLOWP_MSA) && defined(GEMMLOWP_MIPS_32) +#define GEMMLOWP_MSA_32 +#endif + +#if defined(GEMMLOWP_MSA) && defined(GEMMLOWP_MIPS_64) +#define GEMMLOWP_MSA_64 +#endif + +// compiler define for AVX2 -D GEMMLOWP_ENABLE_AVX2 +// Detect AVX2 +#if defined(__AVX2__) && defined(GEMMLOWP_ENABLE_AVX2) +#define GEMMLOWP_AVX2 +// Detect SSE4. +// MSVC does not have __SSE4_1__ macro, but will enable SSE4 +// when AVX is turned on. +#elif defined(__SSE4_1__) || (defined(_MSC_VER) && defined(__AVX__)) +#define GEMMLOWP_SSE4 +// Detect SSE3. +#elif defined(__SSE3__) +#define GEMMLOWP_SSE3 +#endif + +// Convenience SSE4 tokens for 32-bit or 64-bit +#if defined(GEMMLOWP_SSE4) && defined(GEMMLOWP_X86_32) && \ + !defined(GEMMLOWP_DISABLE_SSE4) +#define GEMMLOWP_SSE4_32 +#endif + +#if defined(GEMMLOWP_SSE3) && defined(GEMMLOWP_X86_32) +#define GEMMLOWP_SSE3_32 +#endif + +#if defined(GEMMLOWP_SSE4) && defined(GEMMLOWP_X86_64) && \ + !defined(GEMMLOWP_DISABLE_SSE4) +#define GEMMLOWP_SSE4_64 +#endif + +#if defined(GEMMLOWP_SSE3) && defined(GEMMLOWP_X86_64) +#define GEMMLOWP_SSE3_64 +#endif + +#if defined(GEMMLOWP_AVX2) && defined(GEMMLOWP_X86_64) +#define GEMMLOWP_AVX2_64 +#endif + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#include +#define GEMMLOWP_MARK_MEMORY_AS_INITIALIZED __msan_unpoison +#elif __has_feature(address_sanitizer) +#include +#define GEMMLOWP_MARK_MEMORY_AS_INITIALIZED __asan_unpoison_memory_region +#endif +#endif + +#endif // GEMMLOWP_ALLOW_INLINE_ASM + +// Detect Android. Don't conflate with ARM - we care about tuning +// for non-ARM Android devices too. This can be used in conjunction +// with x86 to tune differently for mobile x86 CPUs (Atom) vs. desktop x86 CPUs. +#if defined(__ANDROID__) || defined(ANDROID) +#define GEMMLOWP_ANDROID +#endif + +#endif // GEMMLOWP_INTERNAL_DETECT_PLATFORM_H_ diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/COPYING b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/COPYING new file mode 100644 index 000000000..2fc6685a6 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/COPYING @@ -0,0 +1,11 @@ +Copyright (c) 2003-2010 Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/_kiss_fft_guts.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/_kiss_fft_guts.h new file mode 100644 index 000000000..2f8b37af5 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/_kiss_fft_guts.h @@ -0,0 +1,168 @@ +#ifndef _KISS_FFT_GUTS_H +#define _KISS_FFT_GUTS_H + +/* +Copyright (c) 2003-2010, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. +*/ + +/* kiss_fft.h + defines kiss_fft_scalar as either short or a float type + and defines + typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ +#include "third_party/kissfft/kiss_fft.h" +#include + +#define MAXFACTORS 32 +/* e.g. an fft of length 128 has 4 factors + as far as kissfft is concerned + 4*4*4*2 + */ + +struct kiss_fft_state{ + int nfft; + int inverse; + int factors[2*MAXFACTORS]; + kiss_fft_cpx twiddles[1]; +}; + +/* + Explanation of macros dealing with complex math: + + C_MUL(m,a,b) : m = a*b + C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise + C_SUB( res, a,b) : res = a - b + C_SUBFROM( res , a) : res -= a + C_ADDTO( res , a) : res += a + * */ +#ifdef FIXED_POINT +#if (FIXED_POINT==32) +# define FRACBITS 31 +# define SAMPPROD int64_t +#define SAMP_MAX 2147483647 +#else +# define FRACBITS 15 +# define SAMPPROD int32_t +#define SAMP_MAX 32767 +#endif + +#define SAMP_MIN -SAMP_MAX + +#if defined(CHECK_OVERFLOW) +# define CHECK_OVERFLOW_OP(a,op,b) \ + if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ + fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } +#endif + + +# define smul(a,b) ( (SAMPPROD)(a)*(b) ) +# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) + +# define S_MUL(a,b) sround( smul(a,b) ) + +# define C_MUL(m,a,b) \ + do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ + (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) + +# define DIVSCALAR(x,k) \ + (x) = sround( smul( x, SAMP_MAX/k ) ) + +# define C_FIXDIV(c,div) \ + do { DIVSCALAR( (c).r , div); \ + DIVSCALAR( (c).i , div); }while (0) + +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r = sround( smul( (c).r , s ) ) ;\ + (c).i = sround( smul( (c).i , s ) ) ; }while(0) + +#else /* not FIXED_POINT*/ + +# define S_MUL(a,b) ( (a)*(b) ) +#define C_MUL(m,a,b) \ + do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ + (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) +# define C_FIXDIV(c,div) /* NOOP */ +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r *= (s);\ + (c).i *= (s); }while(0) +#endif + +#ifndef CHECK_OVERFLOW_OP +# define CHECK_OVERFLOW_OP(a,op,b) /* noop */ +#endif + +#define C_ADD( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,+,(b).r)\ + CHECK_OVERFLOW_OP((a).i,+,(b).i)\ + (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ + }while(0) +#define C_SUB( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,-,(b).r)\ + CHECK_OVERFLOW_OP((a).i,-,(b).i)\ + (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ + }while(0) +#define C_ADDTO( res , a)\ + do { \ + CHECK_OVERFLOW_OP((res).r,+,(a).r)\ + CHECK_OVERFLOW_OP((res).i,+,(a).i)\ + (res).r += (a).r; (res).i += (a).i;\ + }while(0) + +#define C_SUBFROM( res , a)\ + do {\ + CHECK_OVERFLOW_OP((res).r,-,(a).r)\ + CHECK_OVERFLOW_OP((res).i,-,(a).i)\ + (res).r -= (a).r; (res).i -= (a).i; \ + }while(0) + + +#ifdef FIXED_POINT +# define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase)) +# define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase)) +# define HALF_OF(x) ((x)>>1) +#elif defined(USE_SIMD) +# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) +# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) +# define HALF_OF(x) ((x)*_mm_set1_ps(.5)) +#else +# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) +# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) +# define HALF_OF(x) ((x)*(kiss_fft_scalar).5) +#endif + +#define kf_cexp(x,phase) \ + do{ \ + (x)->r = KISS_FFT_COS(phase);\ + (x)->i = KISS_FFT_SIN(phase);\ + }while(0) + + +/* a debugging function */ +#define pcpx(c)\ + fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) + + +#ifdef KISS_FFT_USE_ALLOCA +// define this to allow use of alloca instead of malloc for temporary buffers +// Temporary buffers are used in two case: +// 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5 +// 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform. +#include +#define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes) +#define KISS_FFT_TMP_FREE(ptr) +#else +#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes) +#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr) +#endif +#endif // _KISS_FFT_GUTS_H diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/kiss_fft.c b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/kiss_fft.c new file mode 100644 index 000000000..02da5e870 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/kiss_fft.c @@ -0,0 +1,408 @@ +/* +Copyright (c) 2003-2010, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. +*/ + + +#include "third_party/kissfft/_kiss_fft_guts.h" +/* The guts header contains all the multiplication and addition macros that are defined for + fixed or floating point complex numbers. It also delares the kf_ internal functions. + */ + +static void kf_bfly2( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + int m + ) +{ + kiss_fft_cpx * Fout2; + kiss_fft_cpx * tw1 = st->twiddles; + kiss_fft_cpx t; + Fout2 = Fout + m; + do{ + C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2); + + C_MUL (t, *Fout2 , *tw1); + tw1 += fstride; + C_SUB( *Fout2 , *Fout , t ); + C_ADDTO( *Fout , t ); + ++Fout2; + ++Fout; + }while (--m); +} + +static void kf_bfly4( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + const size_t m + ) +{ + kiss_fft_cpx *tw1,*tw2,*tw3; + kiss_fft_cpx scratch[6]; + size_t k=m; + const size_t m2=2*m; + const size_t m3=3*m; + + + tw3 = tw2 = tw1 = st->twiddles; + + do { + C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4); + + C_MUL(scratch[0],Fout[m] , *tw1 ); + C_MUL(scratch[1],Fout[m2] , *tw2 ); + C_MUL(scratch[2],Fout[m3] , *tw3 ); + + C_SUB( scratch[5] , *Fout, scratch[1] ); + C_ADDTO(*Fout, scratch[1]); + C_ADD( scratch[3] , scratch[0] , scratch[2] ); + C_SUB( scratch[4] , scratch[0] , scratch[2] ); + C_SUB( Fout[m2], *Fout, scratch[3] ); + tw1 += fstride; + tw2 += fstride*2; + tw3 += fstride*3; + C_ADDTO( *Fout , scratch[3] ); + + if(st->inverse) { + Fout[m].r = scratch[5].r - scratch[4].i; + Fout[m].i = scratch[5].i + scratch[4].r; + Fout[m3].r = scratch[5].r + scratch[4].i; + Fout[m3].i = scratch[5].i - scratch[4].r; + }else{ + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + } + ++Fout; + }while(--k); +} + +static void kf_bfly3( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + size_t m + ) +{ + size_t k=m; + const size_t m2 = 2*m; + kiss_fft_cpx *tw1,*tw2; + kiss_fft_cpx scratch[5]; + kiss_fft_cpx epi3; + epi3 = st->twiddles[fstride*m]; + + tw1=tw2=st->twiddles; + + do{ + C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3); + + C_MUL(scratch[1],Fout[m] , *tw1); + C_MUL(scratch[2],Fout[m2] , *tw2); + + C_ADD(scratch[3],scratch[1],scratch[2]); + C_SUB(scratch[0],scratch[1],scratch[2]); + tw1 += fstride; + tw2 += fstride*2; + + Fout[m].r = Fout->r - HALF_OF(scratch[3].r); + Fout[m].i = Fout->i - HALF_OF(scratch[3].i); + + C_MULBYSCALAR( scratch[0] , epi3.i ); + + C_ADDTO(*Fout,scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + }while(--k); +} + +static void kf_bfly5( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + int m + ) +{ + kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; + int u; + kiss_fft_cpx scratch[13]; + kiss_fft_cpx * twiddles = st->twiddles; + kiss_fft_cpx *tw; + kiss_fft_cpx ya,yb; + ya = twiddles[fstride*m]; + yb = twiddles[fstride*2*m]; + + Fout0=Fout; + Fout1=Fout0+m; + Fout2=Fout0+2*m; + Fout3=Fout0+3*m; + Fout4=Fout0+4*m; + + tw=st->twiddles; + for ( u=0; ur += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); + scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); + + scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); + scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i); + + C_SUB(*Fout1,scratch[5],scratch[6]); + C_ADD(*Fout4,scratch[5],scratch[6]); + + scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); + scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); + scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); + scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i); + + C_ADD(*Fout2,scratch[11],scratch[12]); + C_SUB(*Fout3,scratch[11],scratch[12]); + + ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; + } +} + +/* perform the butterfly for one stage of a mixed radix FFT */ +static void kf_bfly_generic( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_cfg st, + int m, + int p + ) +{ + int u,k,q1,q; + kiss_fft_cpx * twiddles = st->twiddles; + kiss_fft_cpx t; + int Norig = st->nfft; + + kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p); + + for ( u=0; u=Norig) twidx-=Norig; + C_MUL(t,scratch[q] , twiddles[twidx] ); + C_ADDTO( Fout[ k ] ,t); + } + k += m; + } + } + KISS_FFT_TMP_FREE(scratch); +} + +static +void kf_work( + kiss_fft_cpx * Fout, + const kiss_fft_cpx * f, + const size_t fstride, + int in_stride, + int * factors, + const kiss_fft_cfg st + ) +{ + kiss_fft_cpx * Fout_beg=Fout; + const int p=*factors++; /* the radix */ + const int m=*factors++; /* stage's fft length/p */ + const kiss_fft_cpx * Fout_end = Fout + p*m; + +#ifdef _OPENMP + // use openmp extensions at the + // top-level (not recursive) + if (fstride==1 && p<=5) + { + int k; + + // execute the p different work units in different threads +# pragma omp parallel for + for (k=0;k floor_sqrt) + p = n; /* no more factors, skip to end */ + } + n /= p; + *facbuf++ = p; + *facbuf++ = n; + } while (n > 1); +} + +/* + * + * User-callable function to allocate all necessary storage space for the fft. + * + * The return value is a contiguous block of memory, allocated with malloc. As such, + * It can be freed with free(), rather than a kiss_fft-specific function. + * */ +kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem ) +{ + kiss_fft_cfg st=NULL; + size_t memneeded = sizeof(struct kiss_fft_state) + + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/ + + if ( lenmem==NULL ) { + st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded ); + }else{ + if (mem != NULL && *lenmem >= memneeded) + st = (kiss_fft_cfg)mem; + *lenmem = memneeded; + } + if (st) { + int i; + st->nfft=nfft; + st->inverse = inverse_fft; + + for (i=0;iinverse) + phase *= -1; + kf_cexp(st->twiddles+i, phase ); + } + + kf_factor(nfft,st->factors); + } + return st; +} + + +void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride) +{ + if (fin == fout) { + //NOTE: this is not really an in-place FFT algorithm. + //It just performs an out-of-place FFT into a temp buffer + kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft); + kf_work(tmpbuf,fin,1,in_stride, st->factors,st); + /* memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft); */ + KISS_FFT_TMP_FREE(tmpbuf); + }else{ + kf_work( fout, fin, 1,in_stride, st->factors,st ); + } +} + +void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) +{ + kiss_fft_stride(cfg,fin,fout,1); +} + + +void kiss_fft_cleanup(void) +{ + // nothing needed any more +} + +int kiss_fft_next_fast_size(int n) +{ + while(1) { + int m=n; + while ( (m%2) == 0 ) m/=2; + while ( (m%3) == 0 ) m/=3; + while ( (m%5) == 0 ) m/=5; + if (m<=1) + break; /* n is completely factorable by twos, threes, and fives */ + n++; + } + return n; +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/kiss_fft.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/kiss_fft.h new file mode 100644 index 000000000..c2c5d8ff0 --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/kiss_fft.h @@ -0,0 +1,125 @@ +#ifndef KISS_FFT_H +#define KISS_FFT_H + +#include +#include +#include +//#include +/* Patched by create_tflm_arduino.py for Arduino compatibility */ + +#ifdef __cplusplus +extern "C++" { +#endif + +/* + ATTENTION! + If you would like a : + -- a utility that will handle the caching of fft objects + -- real-only (no imaginary time component ) FFT + -- a multi-dimensional FFT + -- a command-line utility to perform ffts + -- a command-line utility to perform fast-convolution filtering + + Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c + in the tools/ directory. +*/ + +#ifdef USE_SIMD +# include +# define kiss_fft_scalar __m128 +#define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16) +#define KISS_FFT_FREE _mm_free +#else +#define KISS_FFT_MALLOC(X) (void*)(0x0) /* Patched. */ +#define KISS_FFT_FREE(X) /* Patched. */ +#endif + + +#ifdef FIXED_POINT +#include /* Patched. */ +# if (FIXED_POINT == 32) +# define kiss_fft_scalar int32_t +# else +# define kiss_fft_scalar int16_t +# endif +#else +# ifndef kiss_fft_scalar +/* default is float */ +# define kiss_fft_scalar float +# endif +#endif + +typedef struct { + kiss_fft_scalar r; + kiss_fft_scalar i; +}kiss_fft_cpx; + +typedef struct kiss_fft_state* kiss_fft_cfg; + +/* + * kiss_fft_alloc + * + * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. + * + * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL); + * + * The return value from fft_alloc is a cfg buffer used internally + * by the fft routine or NULL. + * + * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc. + * The returned value should be free()d when done to avoid memory leaks. + * + * The state can be placed in a user supplied buffer 'mem': + * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, + * then the function places the cfg in mem and the size used in *lenmem + * and returns mem. + * + * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), + * then the function returns NULL and places the minimum cfg + * buffer size in *lenmem. + * */ + +kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); + +/* + * kiss_fft(cfg,in_out_buf) + * + * Perform an FFT on a complex input buffer. + * for a forward FFT, + * fin should be f[0] , f[1] , ... ,f[nfft-1] + * fout will be F[0] , F[1] , ... ,F[nfft-1] + * Note that each element is complex and can be accessed like + f[k].r and f[k].i + * */ +void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); + +/* + A more generic version of the above function. It reads its input from every Nth sample. + * */ +void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); + +/* If kiss_fft_alloc allocated a buffer, it is one contiguous + buffer and can be simply free()d when no longer needed*/ +#define kiss_fft_free free + +/* + Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up + your compiler output to call this before you exit. +*/ +void kiss_fft_cleanup(void); + + +/* + * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) + */ +int kiss_fft_next_fast_size(int n); + +/* for real ffts, we need an even size */ +#define kiss_fftr_next_fast_size_real(n) \ + (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/tools/kiss_fftr.c b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/tools/kiss_fftr.c new file mode 100644 index 000000000..dd3a1b79b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/tools/kiss_fftr.c @@ -0,0 +1,159 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. +*/ + +#include "third_party/kissfft/tools/kiss_fftr.h" +#include "third_party/kissfft/_kiss_fft_guts.h" + +struct kiss_fftr_state{ + kiss_fft_cfg substate; + kiss_fft_cpx * tmpbuf; + kiss_fft_cpx * super_twiddles; +#ifdef USE_SIMD + void * pad; +#endif +}; + +kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) +{ + int i; + kiss_fftr_cfg st = NULL; + size_t subsize, memneeded; + + if (nfft & 1) { + /* fprintf(stderr,"Real FFT optimization must be even.\n"); */ + return NULL; + } + nfft >>= 1; + + kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize); + memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2); + + if (lenmem == NULL) { + st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded); + } else { + if (*lenmem >= memneeded) + st = (kiss_fftr_cfg) mem; + *lenmem = memneeded; + } + if (!st) + return NULL; + + st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */ + st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize); + st->super_twiddles = st->tmpbuf + nfft; + kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); + + for (i = 0; i < nfft/2; ++i) { + double phase = + -3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5); + if (inverse_fft) + phase *= -1; + kf_cexp (st->super_twiddles+i,phase); + } + return st; +} + +void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata) +{ + /* input buffer timedata is stored row-wise */ + int k,ncfft; + kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc; + + if ( st->substate->inverse) { + /* fprintf(stderr,"kiss fft usage error: improper alloc\n"); */ + return; /* exit(1); */ + } + + ncfft = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag*/ + kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); + /* The real part of the DC element of the frequency spectrum in st->tmpbuf + * contains the sum of the even-numbered elements of the input time sequence + * The imag part is the sum of the odd-numbered elements + * + * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * yielding DC of input time sequence + * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... + * yielding Nyquist bin of input time sequence + */ + + tdc.r = st->tmpbuf[0].r; + tdc.i = st->tmpbuf[0].i; + C_FIXDIV(tdc,2); + CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); + CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); + freqdata[0].r = tdc.r + tdc.i; + freqdata[ncfft].r = tdc.r - tdc.i; +#ifdef USE_SIMD + freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0); +#else + freqdata[ncfft].i = freqdata[0].i = 0; +#endif + + for ( k=1;k <= ncfft/2 ; ++k ) { + fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[ncfft-k].r; + fpnk.i = - st->tmpbuf[ncfft-k].i; + C_FIXDIV(fpk,2); + C_FIXDIV(fpnk,2); + + C_ADD( f1k, fpk , fpnk ); + C_SUB( f2k, fpk , fpnk ); + C_MUL( tw , f2k , st->super_twiddles[k-1]); + + freqdata[k].r = HALF_OF(f1k.r + tw.r); + freqdata[k].i = HALF_OF(f1k.i + tw.i); + freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r); + freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i); + } +} + +void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + + if (st->substate->inverse == 0) { + /* fprintf (stderr, "kiss fft usage error: improper alloc\n"); */ + return; /* exit (1); */ + } + + ncfft = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; + st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; + C_FIXDIV(st->tmpbuf[0],2); + + for (k = 1; k <= ncfft / 2; ++k) { + kiss_fft_cpx fk, fnkc, fek, fok, tmp; + fk = freqdata[k]; + fnkc.r = freqdata[ncfft - k].r; + fnkc.i = -freqdata[ncfft - k].i; + C_FIXDIV( fk , 2 ); + C_FIXDIV( fnkc , 2 ); + + C_ADD (fek, fk, fnkc); + C_SUB (tmp, fk, fnkc); + C_MUL (fok, tmp, st->super_twiddles[k-1]); + C_ADD (st->tmpbuf[k], fek, fok); + C_SUB (st->tmpbuf[ncfft - k], fek, fok); +#ifdef USE_SIMD + st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); +#else + st->tmpbuf[ncfft - k].i *= -1; +#endif + } + kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); +} diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/tools/kiss_fftr.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/tools/kiss_fftr.h new file mode 100644 index 000000000..8faf0628b --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/kissfft/tools/kiss_fftr.h @@ -0,0 +1,46 @@ +#ifndef KISS_FTR_H +#define KISS_FTR_H + +#include "third_party/kissfft/kiss_fft.h" +#ifdef __cplusplus +extern "C++" { +#endif + + +/* + + Real optimized version can save about 45% cpu time vs. complex fft of a real seq. + + + + */ + +typedef struct kiss_fftr_state *kiss_fftr_cfg; + + +kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); +/* + nfft must be even + + If you don't care to allocate space, use mem = lenmem = NULL +*/ + + +void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); +/* + input timedata has nfft scalar points + output freqdata has nfft/2+1 complex points +*/ + +void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); +/* + input freqdata has nfft/2+1 complex points + output timedata has nfft scalar points +*/ + +#define kiss_fftr_free free + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/libesp32_ml/tf_lite_esp32/src/third_party/ruy/ruy/profiler/instrumentation.h b/lib/libesp32_ml/tf_lite_esp32/src/third_party/ruy/ruy/profiler/instrumentation.h new file mode 100644 index 000000000..c4df1e68f --- /dev/null +++ b/lib/libesp32_ml/tf_lite_esp32/src/third_party/ruy/ruy/profiler/instrumentation.h @@ -0,0 +1,203 @@ +/* Copyright 2020 Google LLC. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef RUY_RUY_PROFILER_INSTRUMENTATION_H_ +#define RUY_RUY_PROFILER_INSTRUMENTATION_H_ + +#ifdef RUY_PROFILER +#include +#include +#include +#endif + +namespace ruy { +namespace profiler { + +#ifdef RUY_PROFILER + +// A label is how a code scope is annotated to appear in profiles. +// The stacks that are sampled by the profiler are stacks of such labels. +// A label consists of a literal string, plus optional integer arguments. +class Label { + public: + Label() {} + template + explicit Label(Args... args) { + Set(args...); + } + void Set(const char* format) { + format_ = format; + args_count_ = 0; + } + template + void Set(const char* format, Args... args) { + format_ = format; + args_count_ = sizeof...(args); + SetArgs(0, args...); + } + + void operator=(const Label& other); + + bool operator==(const Label& other) const; + + std::string Formatted() const; + const char* format() const { return format_; } + + private: + void SetArgs(int position, int arg0) { args_[position] = arg0; } + + template + void SetArgs(int position, int arg0, Args... args) { + SetArgs(position, arg0); + SetArgs(position + 1, args...); + } + + static constexpr int kMaxArgs = 4; + const char* format_ = nullptr; + int args_count_ = 0; + int args_[kMaxArgs]; +}; + +namespace detail { + +// Forward-declaration, see class ThreadStack below. +class ThreadStack; + +bool& GlobalIsProfilerRunning(); + +// Returns the global vector of pointers to all stacks, there being one stack +// per thread executing instrumented code. +std::vector* GlobalAllThreadStacks(); + +// Returns the mutex to be locked around any access to GlobalAllThreadStacks(). +std::mutex* GlobalsMutex(); + +// Returns the thread-local stack, specific to the current thread. +ThreadStack* ThreadLocalThreadStack(); + +// This 'stack' is what may be more appropriately called a 'pseudostack': +// It contains Label entries that are 'manually' entered by instrumentation +// code. It's unrelated to real call stacks. +struct Stack { + std::uint32_t id = 0; + static constexpr int kMaxSize = 64; + int size = 0; + Label labels[kMaxSize]; +}; + +// Returns the buffer byte size required by CopyToSample. +int GetBufferSize(const Stack& stack); + +// Copies this Stack into a byte buffer, called a 'sample'. +void CopyToBuffer(const Stack& stack, char* dst); + +// Populates this Stack from an existing sample buffer, typically +// produced by CopyToSample. +void ReadFromBuffer(const char* src, Stack* stack); + +// ThreadStack is meant to be used as a thread-local singleton, assigning to +// each thread a Stack object holding its pseudo-stack of profile labels, +// plus a mutex allowing to synchronize accesses to this pseudo-stack between +// this thread and a possible profiler thread sampling it. +class ThreadStack { + public: + ThreadStack(); + ~ThreadStack(); + + const Stack& stack() const { return stack_; } + + // Returns the mutex to lock around any access to this stack. Each stack is + // accessed by potentially two threads: the thread that it belongs to + // (which calls Push and Pop) and the profiler thread during profiling + // (which calls CopyToSample). + std::mutex& Mutex() const { return mutex_; } + + // Pushes a new label on the top of this Stack. + template + void Push(Args... args) { + // This mutex locking is needed to guard against race conditions as both + // the current thread and the profiler thread may be concurrently accessing + // this stack. In addition to that, this mutex locking also serves the other + // purpose of acting as a barrier (of compiler code reordering, of runtime + // CPU instruction reordering, and of memory access reordering), which + // gives a measure of correctness to this profiler. The downside is some + // latency. As this lock will be uncontended most of the times, the cost + // should be roughly that of an sequentially-consistent atomic access, + // comparable to an access to the level of CPU data cache that is shared + // among all cores, typically 60 cycles on current ARM CPUs, plus side + // effects from barrier instructions. + std::lock_guard lock(mutex_); + // Avoid overrunning the stack, even in 'release' builds. This profiling + // instrumentation code should not ship in release builds anyway, the + // overhead of this check is negligible, and overrunning a stack array would + // be bad. + if (stack_.size >= Stack::kMaxSize) { + abort(); + } + stack_.labels[stack_.size++].Set(args...); + } + + // Pops the top-most label from this Stack. + void Pop() { + // See the comment in Push about this lock. While it would be tempting to + // try to remove this lock and just atomically decrement size_ with a + // store-release, that would not necessarily be a substitute for all of the + // purposes that this lock serves, or if it was done carefully to serve all + // of the same purposes, then that wouldn't be faster than this (mostly + // uncontended) lock. + std::lock_guard lock(mutex_); + stack_.size--; + } + + private: + mutable std::mutex mutex_; + Stack stack_; +}; + +} // namespace detail + +// RAII user-facing way to construct Labels associated with their life scope +// and get them pushed to / popped from the current thread stack. +class ScopeLabel { + public: + template + ScopeLabel(Args... args) : thread_stack_(detail::ThreadLocalThreadStack()) { + thread_stack_->Push(args...); + } + + ~ScopeLabel() { thread_stack_->Pop(); } + + private: + detail::ThreadStack* thread_stack_; +}; + +#else // no RUY_PROFILER + +class ScopeLabel { + public: + template + explicit ScopeLabel(Args...) {} + + // This destructor is needed to consistently silence clang's -Wunused-variable + // which seems to trigger semi-randomly. + ~ScopeLabel() {} +}; + +#endif + +} // namespace profiler +} // namespace ruy + +#endif // RUY_RUY_PROFILER_INSTRUMENTATION_H_ diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tf_lite_micro.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tf_lite_micro.ino new file mode 100644 index 000000000..35166944e --- /dev/null +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tf_lite_micro.ino @@ -0,0 +1,930 @@ +/* + xdrv_52_3_tf_lite_micro.ino - Berry scripting language, High-Level Tensor Flow Lite for Microprocessors model deployer + + Copyright (C) 2022 Christian Baars & Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY + +#include + +#ifdef USE_BERRY_TF_LITE + +#include +#include "tensorflow/lite/micro/all_ops_resolver.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/micro/micro_interpreter.h" +#include "tensorflow/lite/c/c_api_types.h" +#include "tensorflow/lite/micro/system_setup.h" +#include "tensorflow/lite/schema/schema_generated.h" +#include "freertos/ringbuf.h" +#include "tensorflow/lite/c/common.h" + +#ifdef USE_I2S +#include +#include "mfcc.h" +#endif //USE_I2S + +/*********************************************************************************************\ + * Internal helper classes and constants +\*********************************************************************************************/ +#ifdef USE_I2S + +#define kObservationWindow 1000 //milliseconds +#define kAudioSampleFrequency 16000 +#define kAudioSampleBits 16 + +#endif //USE_I2S + +struct TFL_mic_descriptor_t{ + // uint8_t i2s_comm_format; // i2s_comm_format_t - enum as uint8_t + uint8_t channel_fmt; // i2s_channelformat_t - enum as uint8_t (right = 3, left = 4) + uint8_t preamp; // factor + uint8_t slice_dur; // milliseconds + uint8_t slice_stride; // milliseconds + uint8_t num_filter; // mfe bins + uint8_t num_coeff; // mfcc coefficients, if 0 -> compute MFE only + uint8_t fft_bins; // 2^fft_bins + uint8_t max_invocations; // max. invocations per second + uint8_t db_floor; // filter out noise below decibel threshold, treated as negative value + uint8_t preemphasis; // as preemphasis/100.0f , 0 - no preemphasis +}; + +struct TFL_mic_ctx_t{ + TaskHandle_t audio_capture_task = nullptr; + SemaphoreHandle_t feature_buffer_mutex = nullptr; + MFCC * mfcc; + int8_t* model_input_buffer = nullptr; + File *file = nullptr; + int32_t file_bytes_left; + union{ + struct { + uint32_t is_audio_initialized:1; + uint32_t is_first_time:1; + uint32_t new_feature_data:1; + uint32_t continue_audio_capture:1; + uint32_t stop_audio_capture:1; + uint32_t audio_capture_ended:1; + uint32_t use_mfcc:1; + uint32_t use_gain_filter:1; + uint32_t mode_record_audio:1; + uint32_t file_is_open:1; + } flag; + uint32_t flags; + }; + int feature_buffer_idx = 0; + int8_t *feature_buffer; + // user input + // int32_t i2s_comm_format; + i2s_channel_fmt_t channel_fmt; + int32_t preamp; // factor + int32_t slice_dur; // milliseconds + int32_t slice_stride; // milliseconds + uint8_t num_filter; // mfe filter bins + uint8_t num_coeff; // mfcc coefficients, if 0 -> compute MFE only + int32_t fft_bins; // 2^fft_bins + // calculated + int32_t slice_size; // bytes + int32_t slice_count; + uint16_t i2s_samples_to_get; + int16_t db_floor; // filter out noise below decibel threshold, this is now a negative value + float preemphasis; +}; + +struct TFL_stats_t{ + uint32_t model_size = 0; + uint32_t used_arena_bytes = 0; + uint32_t invokations = 0; + uint32_t loop_task_free_stack_bytes = 0; + uint32_t mic_task_free_stack_bytes = 0; +}; + +struct TFL_ctx_t{ +const tflite::Model* model = nullptr; +TfLiteTensor* input = nullptr; +TfLiteTensor* output = nullptr; +int8_t *berry_output_buf = nullptr; +size_t berry_output_bufsize; +int TensorArenaSize = 2000; +uint8_t max_invocations; // max. invocations per second + +TaskHandle_t loop_task = nullptr; +// QueueHandle_t loop_queue = nullptr; +union{ + struct { + uint32_t init_done:1; + uint32_t delay_next_invocation:1; + uint32_t running_invocation:1; + uint32_t running_loop:1; + // uint32_t stop_loop:1; + uint32_t loop_ended:1; + uint32_t unread_output:1; + uint32_t use_cam:1; + uint32_t use_mic:1; + uint32_t mode_inference:1; + } option; + uint32_t options; +}; +#ifdef USE_I2S +TFL_mic_ctx_t *mic = nullptr; +#endif +TFL_stats_t *stats = nullptr; +}; + +TFL_ctx_t *TFL = nullptr; +RingbufHandle_t TFL_log_buffer = nullptr; + + +/*********************************************************************************************\ + * Internal driver functions +\*********************************************************************************************/ + +void TFL_Log(char *s){ + size_t len = strlen(s); + if(len<5) return; // we assume this is for the trash + // s[len] = 0; //strip CR/LF + xRingbufferSend(TFL_log_buffer, s, len+1 , pdMS_TO_TICKS(3)); +} + +bool TFL_create_task(){ + if (TFL->option.running_loop) return bfalse; + if(TFL->loop_task!=nullptr) vTaskDelete(TFL->loop_task); + + xTaskCreatePinnedToCore( + TFL_task_loop, /* Function to implement the task */ + "tfl_loop", /* Name of the task */ + 8000 + (TFL->TensorArenaSize),/* Stack size in words */ + NULL, /* Task input parameter */ + 1, /* Priority of the task */ + &TFL->loop_task, /* Task handle. */ + 1); /* Core where the task should run */ + + return btrue; +} + +bool TFL_init_CAM(){ + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: mode webcam not implemented yet")); + delete TFL; + TFL = nullptr; + return bfalse; +} + +#ifdef USE_I2S +/** + * @brief Set up some buffers and tables for feature extraction of audio samples. Must run once before starting audio capturing. + * + * @return int - not used ATM + */ +int TFL_InitializeFeatures() { + uint32_t samples_to_process = (TFL->mic->i2s_samples_to_get * TFL->mic->slice_dur)/TFL->mic->slice_stride; + TFL->mic->mfcc = new MFCC(TFL->mic->num_coeff, samples_to_process, TFL->mic->num_filter, kAudioSampleFrequency, 300, 8000); + TFL->mic->mfcc->set_preamp(TFL->mic->preamp); + TFL->mic->mfcc->set_preemphasis(TFL->mic->preemphasis); + MicroPrintf( PSTR( "MFCC %u initialized for %u samples, preamp: %u, preemphasis: %f"),TFL->mic->num_coeff,samples_to_process, TFL->mic->preamp, TFL->mic->preemphasis); + return kTfLiteOk; +} + +/** + * @brief Computes features from every audio slice immediately after capturing it. + * + * @param input - audio buffer + * @param input_size - length auf audio input in samples (16-bit) + * @param output_size - length of feature buffer in bytes (we use int8_t quantization) + * @param output - feature buffer for one slize of audio + * @param num_samples_read - not used anymore, to be removed + * @return int + */ +int TFL_GenerateFeatures(const int16_t* input, int input_size, + int output_size, int8_t* output, + size_t* num_samples_read) { + + float out_buf[output_size]; + + TFL->mic->mfcc->mfcc_compute(input, out_buf); + if(TFL->mic->num_coeff == 0){ // mfe only + TFL->mic->mfcc->log10_normalize(out_buf, output_size, TFL->mic->db_floor); + } + + float scale = TFL->input->params.scale; + int32_t zero_point = TFL->input->params.zero_point; + float min_f = 1; + float max_f = 0; + + for (size_t i = 0; i < output_size; ++i) { + int32_t value = ((out_buf[i]/ scale) + zero_point); + if(value < -128){ + value = -128; + } + else if(value > 127){ + value = 127; + } + output[i] = value; + // if(min_f>out_buf[i]) min_f = out_buf[i]; + // if(max_fmic->file != nullptr){ + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: close open file")); + TFL->mic->file->close(); + delete TFL->mic->file; + } + TFL->mic->file = new File(ufsp->open(fname, "w")); + if(TFL->mic->file != nullptr){ + TFL->mic->flag.file_is_open = 1; + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: file open")); + } + else{ + return false; + } + +#define WAVE_HEADER_SIZE 44 + + uint32_t sample_rate = kAudioSampleFrequency; + uint8_t sample_bits = kAudioSampleBits; + uint32_t byte_rate = sample_rate * (sample_bits/8); + uint32_t wav_size = byte_rate * record_time; + uint32_t file_size = wav_size + WAVE_HEADER_SIZE - 8; + +#define U32_BYTE(x,y) (uint8_t)((x>>(y*8))&0xff) + + const char set_wav_header[] = { + 'R','I','F','F', // ChunkID + U32_BYTE(file_size,0),U32_BYTE(file_size,1),U32_BYTE(file_size,2),U32_BYTE(file_size,3), // ChunkSize + 'W','A','V','E', // Format + 'f','m','t',' ', // Subchunk1ID + sample_bits, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM) + 0x01, 0x00, // AudioFormat (1 for PCM) + 0x01, 0x00, // NumChannels (1 channel) + U32_BYTE(sample_rate,0),U32_BYTE(sample_rate,1),U32_BYTE(sample_rate,2),U32_BYTE(sample_rate,3), // ChuSampleRatekSize + U32_BYTE(byte_rate,0),U32_BYTE(byte_rate,1),U32_BYTE(byte_rate,2),U32_BYTE(byte_rate,3), // ByteRate + 0x02, 0x00, // BlockAlign + sample_bits, 0x00, // BitsPerSample (16 bits) + 'd','a','t','a', // Subchunk2ID + U32_BYTE(wav_size,0),U32_BYTE(wav_size,1),U32_BYTE(wav_size,2),U32_BYTE(wav_size,3), // ByteRate + }; + + TFL->mic->file->write((uint8_t*)set_wav_header,WAVE_HEADER_SIZE); + TFL->mic->file_bytes_left = wav_size; + + return true; +} + +/** + * @brief Init I2S microphone. Pins must be configured in the "usual" Tasmota way. Some properties are variables stored in the descriptor. + * + * @param descriptor - byte array passed from Berry. Arbitrary format - might change in the future!! + * @return true - success + * @return false - failure + */ +bool TFL_init_MIC(const uint8_t* descriptor){ + if (PinUsed(GPIO_I2S_BCLK) && PinUsed(GPIO_I2S_WS) && PinUsed(GPIO_I2S_DIN)) { + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: init mic")); + } + else{ + AddLog(LOG_LEVEL_ERROR, PSTR("TFL: I2S GPIO's not set for mic input!")); + return bfalse; + } + + #define I2S_NUM (i2s_port_t)I2S_NUM_0 // 0 or 1 + + TFL->mic = new TFL_mic_ctx_t; + TFL->mic->flags = 0; + TFL_set_mic_config(descriptor); + + i2s_config_t i2s_config = { + .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), + .sample_rate = kAudioSampleFrequency, + .bits_per_sample = (i2s_bits_per_sample_t)kAudioSampleBits, + .channel_format = TFL->mic->channel_fmt, + .communication_format = I2S_COMM_FORMAT_STAND_I2S, ///i2s_comm_format_t(1), // ?? I2S_COMM_FORMAT_STAND_I2S | I2S_COMM_FORMAT_STAND_MSB + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, + .dma_buf_count = 5, + .dma_buf_len = 320, + .use_apll = false, + .tx_desc_auto_clear = false, + .fixed_mclk = 0 + }; + + i2s_pin_config_t pin_config = { + .bck_io_num = Pin(GPIO_I2S_BCLK), + .ws_io_num = Pin(GPIO_I2S_WS), + .data_out_num = I2S_PIN_NO_CHANGE, + .data_in_num = Pin(GPIO_I2S_DIN) + }; + + esp_err_t ret = ESP_OK; + ret = i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL); + + if (ret != ESP_OK) { + AddLog(LOG_LEVEL_ERROR, PSTR("TFL: Error in i2s_driver_install")); + return bfalse; + } + ret = i2s_set_pin(I2S_NUM, &pin_config); + if (ret != ESP_OK) { + AddLog(LOG_LEVEL_ERROR, PSTR("Error in i2s_set_pin")); + return bfalse; + } + + TFL->mic->feature_buffer_mutex = xSemaphoreCreateMutex(); + + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: MIC ctx created")); + return btrue; +} + +void TFL_append_audio_to_file(uint8_t *byte_buffer, uint16_t length){ + int16_t *samples = (int16_t *)byte_buffer; + + for(int i=0;imic->preamp; //gain ... a lot + } + + // float buffer[length/2]; + // for (int i = 0; i < length/2; i++) { + // buffer[i] = (float)samples[i]/(float)(1<<15); + // if(samples[i] > pre_noisefloor || samples[i] + pre_noisefloor < 0){ + // buffer[i] *= (float)TFL->mic->preamp; + // } + // } + // TFL->mic->file->write((uint8_t*)buffer, length*2); + + TFL->mic->file->write(byte_buffer,length); + + TFL->mic->file_bytes_left -= length; + if(TFL->mic->file_bytes_left<0){ + TFL->mic->file->close(); + delete TFL->mic->file; + TFL->mic->flag.file_is_open = 0; + TFL->mic->flag.continue_audio_capture = 0; + TFL->option.running_loop = 0; + MicroPrintf( PSTR( "Closing file.")); + } +} + +/** + * @brief Function spawned as a task for capturing audio. Used for recording or inference. + * + * @param arg - not used + */ +void TFL_capture_samples(void* arg) { + MicroPrintf( PSTR( "Capture task started")); + int i2s_bytes_to_read = TFL->mic->i2s_samples_to_get * 2; // according to slize duration + + int buffer_size = (i2s_bytes_to_read * TFL->mic->slice_dur)/TFL->mic->slice_stride; // in bytes, current slice duration plus (potential) history data + + size_t samples_to_read; + size_t bytes_read; + int tf_status = 0; + + int16_t i2s_sample_buffer[buffer_size/2] = {0}; // in shorts, add the size to hold history data + uint8_t *i2s_byte_buffer = (uint8_t*)i2s_sample_buffer; + uint32_t *i2s_long_buffer = (uint32_t*)i2s_sample_buffer; + uint8_t *i2s_read_buffer = i2s_byte_buffer + (buffer_size - i2s_bytes_to_read); // behind the history data, if slize duration != slize stride + + // read to "nowhere" to get no startup noise on some mics + i2s_read(I2S_NUM, i2s_byte_buffer, i2s_bytes_to_read, &bytes_read, pdMS_TO_TICKS(100)); + vTaskDelay(pdMS_TO_TICKS(1000)); + + if(TFL->option.mode_inference == 1){ + TFL_InitializeFeatures(); // TODO: check or not for success + } + + TFL->mic->flag.continue_audio_capture = 1; + MicroPrintf( PSTR( "Enter capture samples loop")); + + // "clean" the DMA buffers a last time + i2s_zero_dma_buffer(I2S_NUM); + vTaskDelay(pdMS_TO_TICKS(TFL->mic->slice_stride)); + + while (TFL->mic->flag.continue_audio_capture == 1) { + TFL->stats->mic_task_free_stack_bytes = uxTaskGetStackHighWaterMark(NULL); + TickType_t xLastWakeTime = xTaskGetTickCount(); + + /* read slice data at once from i2s */ + i2s_read(I2S_NUM, i2s_read_buffer, i2s_bytes_to_read, &bytes_read, pdMS_TO_TICKS(TFL->mic->slice_stride)); + // taskYIELD(); + if (bytes_read <= 0) { + MicroPrintf( PSTR( "Error in I2S read : %d"), bytes_read); + } + else if(TFL->mic->flag.file_is_open == 1){ + TFL_append_audio_to_file(i2s_read_buffer,bytes_read); + if (bytes_read < i2s_bytes_to_read) { + MicroPrintf(PSTR("Partial I2S read: %d"), bytes_read); + } + } + else { + if (bytes_read < i2s_bytes_to_read) { + MicroPrintf(PSTR("Partial I2S read: %d"), bytes_read); + } + // MicroPrintf( PSTR( "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u"), i2s_long_buffer[0], i2s_long_buffer[1], i2s_long_buffer[2], i2s_long_buffer[3], i2s_long_buffer[4], i2s_long_buffer[5] + // , i2s_long_buffer[6], i2s_long_buffer[7], i2s_long_buffer[8], i2s_long_buffer[9], i2s_long_buffer[10] + // , i2s_long_buffer[11], i2s_long_buffer[12], i2s_long_buffer[13], i2s_long_buffer[14], i2s_long_buffer[15]); + + // test_file->read(i2s_byte_buffer, 1024); + + xSemaphoreTake(TFL->mic->feature_buffer_mutex, pdMS_TO_TICKS(TFL->mic->slice_stride) ); + + tf_status = TFL_GenerateFeatures((const int16_t*)i2s_sample_buffer, buffer_size/2 , TFL->mic->slice_size, + TFL->mic->feature_buffer + (TFL->mic->feature_buffer_idx * TFL->mic->slice_size), + &samples_to_read); + + for(int i=0;i<(buffer_size - i2s_bytes_to_read)/4;i++){ + i2s_long_buffer[i] = i2s_long_buffer[i + ((buffer_size - i2s_bytes_to_read)/4)]; //move history to the front + } + + TFL->mic->feature_buffer_idx += 1; + if(TFL->mic->feature_buffer_idx == TFL->mic->slice_count){ + TFL->mic->feature_buffer_idx = 0; + } + TFL->mic->flag.new_feature_data = 1; + xSemaphoreGive(TFL->mic->feature_buffer_mutex); + + } + // MicroPrintf( PSTR("t: %u"),xTaskGetTickCount()-xLastWakeTime); + + if(TFL->mic->flag.continue_audio_capture == 1) vTaskDelayUntil( &xLastWakeTime, pdMS_TO_TICKS(TFL->mic->slice_stride) ); + } + i2s_driver_uninstall(I2S_NUM); + delete TFL->mic->mfcc; + MicroPrintf( PSTR("end capture task")); + TFL->mic->flag.audio_capture_ended = 1; + vTaskDelete(NULL); +} + +/** + * @brief Pass descriptor variables from Berry to the MIC context. Will also calculate some vars. + * + * @param descriptor_buffer - byte array from Berry + */ +void TFL_set_mic_config(const uint8_t *descriptor_buffer){ + TFL_mic_descriptor_t *mic_descriptor = (TFL_mic_descriptor_t*)descriptor_buffer; + TFL->mic->channel_fmt = (i2s_channel_fmt_t)mic_descriptor->channel_fmt; + TFL->mic->preamp = mic_descriptor->preamp; + TFL->mic->slice_dur = mic_descriptor->slice_dur; + TFL->mic->slice_stride = mic_descriptor->slice_stride; + TFL->mic->num_filter = mic_descriptor->num_filter; + TFL->mic->num_coeff = mic_descriptor->num_coeff; + TFL->mic->fft_bins = mic_descriptor->fft_bins; + TFL->max_invocations = mic_descriptor->max_invocations; + // now calculate the other settings + TFL->mic->slice_size = mic_descriptor->num_coeff == 0 ? mic_descriptor->num_filter : mic_descriptor->num_coeff; + TFL->mic->slice_count = (int32_t)((kObservationWindow/(float)TFL->mic->slice_stride) - 0.01); // floor(x) to int + TFL->mic->preemphasis = (float)(mic_descriptor-> preemphasis)/100.0f; + TFL->mic->i2s_samples_to_get = (TFL->mic->slice_stride * (kAudioSampleFrequency / 1000)); + TFL->mic->db_floor = mic_descriptor->db_floor * -1; + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: filter: %u, coefficients: %u"), TFL->mic->num_filter, TFL->mic->num_coeff); + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: slice stride: %u ms -> slize count: %u, samples to read: %u"), TFL->mic->slice_stride, TFL->mic->slice_count, TFL->mic->i2s_samples_to_get); +} + +/** + * @brief Updates the input tensor with the data from the featuree buffer, which works as a ring buffer and is a shared resorce. + * + */ +void TFL_mic_feature_buf_to_input(){ + xSemaphoreTake(TFL->mic->feature_buffer_mutex, pdMS_TO_TICKS(TFL->mic->slice_stride) ); + // Copy feature buffer to input tensor + // MicroPrintf( PSTR("loop audio, idx: %u"),TFL->mic->feature_buffer_idx); + int idx = TFL->mic->feature_buffer_idx + 1; //oldest slice right after the newest slice + if(idx == TFL->mic->slice_count) idx = 0; + int slices_upperstack = TFL->mic->slice_count - idx; + int slices_lowerstack = TFL->mic->slice_count - slices_upperstack; + // MicroPrintf( PSTR("idx,slices_upperstack, slices_lowerstack: %u %u %u"), idx, slices_upperstack,slices_lowerstack); + memcpy(TFL->mic->model_input_buffer,TFL->mic->feature_buffer + (idx * TFL->mic->slice_size), TFL->mic->slice_size * slices_upperstack); + memcpy(TFL->mic->model_input_buffer + (TFL->mic->slice_size * slices_upperstack),TFL->mic->feature_buffer, TFL->mic->slice_size * slices_lowerstack); + // MicroPrintf( PSTR("written: %u"),size_head + size_wrap); + // MicroPrintf("%d %d %d %d %d %d %d %d %d %d %d %d %d",TFL->mic->feature_buffer[0],TFL->mic->feature_buffer[1] ,TFL->mic->feature_buffer[2] ,TFL->mic->feature_buffer[3] ,TFL->mic->feature_buffer[4] ,TFL->mic->feature_buffer[5] ,TFL->mic->feature_buffer[6] ,TFL->mic->feature_buffer[7] ,TFL->mic->feature_buffer[8] ,TFL->mic->feature_buffer[9] ,TFL->mic->feature_buffer[10] ,TFL->mic->feature_buffer[11] ,TFL->mic->feature_buffer[12] ); + // MicroPrintf("%d %d %d %d %d %d %d %d %d %d %d %d %d",TFL->mic->model_input_buffer[0],TFL->mic->model_input_buffer[1] ,TFL->mic->model_input_buffer[2] ,TFL->mic->model_input_buffer[3] ,TFL->mic->model_input_buffer[4] ,TFL->mic->model_input_buffer[5] ,TFL->mic->model_input_buffer[6] ,TFL->mic->model_input_buffer[7] ,TFL->mic->model_input_buffer[8] ,TFL->mic->model_input_buffer[9] ,TFL->mic->model_input_buffer[10] ,TFL->mic->model_input_buffer[11] ,TFL->mic->model_input_buffer[12] ); + xSemaphoreGive(TFL->mic->feature_buffer_mutex); + return; +} + +/** + * @brief Helper function to stop audio capture task + * + */ +void TFL_stop_audio_capture(){ + MicroPrintf( PSTR("shall stop_capture_task")); + if(TFL->mic->flag.continue_audio_capture == 0) return; + TFL->mic->flag.continue_audio_capture = 0; + uint32_t timeout = 0; + while(TFL->mic->flag.audio_capture_ended == 0){ + if(timeout>3) break; + // MicroPrintf( PSTR("wait for stop_capture_task")); + vTaskDelay(pdMS_TO_TICKS(TFL->mic->slice_stride) ); + timeout++; + } + vSemaphoreDelete(TFL->mic->feature_buffer_mutex); + delete[] TFL->mic->feature_buffer; +} +#endif //USE_I2S + +/** + * @brief Helper function to stop all runnning tasks + * + */ +void TFL_delete_tasks(){ + if(TFL == nullptr) return; + TFL->option.running_loop = 0; + // delay(20); + while(TFL->option.loop_ended == 0){ + // AddLog(LOG_LEVEL_DEBUG, PSTR("...")); + vTaskDelay(pdMS_TO_TICKS(10)); + } + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: task loop did stop")); + if(TFL->mic != nullptr){ + delete TFL->mic; + } + delete TFL; + TFL = nullptr; +} + +/** + * @brief Starts inference task and the run loop. Should be terminated by signal from helper function. + * + * @param pvParameters - not used + */ +void TFL_task_loop(void *pvParameters){ + uint8_t tensor_arena[TFL->TensorArenaSize]; + TFL->stats = new TFL_stats_t; + tflite::AllOpsResolver resolver; //TODO: infer needed Ops from model?? + tflite::MicroInterpreter interpreter( + TFL->model, resolver, tensor_arena, TFL->TensorArenaSize); + int allocate_status = interpreter.AllocateTensors(); + if (allocate_status != kTfLiteOk) { + MicroPrintf( PSTR("AllocateTensors() failed")); + goto loop_task_exit; + } + else{ + TFL->stats->used_arena_bytes = interpreter.arena_used_bytes(); + } + // Obtain pointers to the model's input/output, we can use it externally + TFL->input = interpreter.input(0); + TFL->output = interpreter.output(0); + +#ifdef USE_I2S + if(TFL->option.use_mic == 1){ + TFL->mic->feature_buffer = new int8_t[TFL->mic->slice_size * TFL->mic->slice_count](); + xTaskCreatePinnedToCore(TFL_capture_samples, "tfl_mic", 1024 * 5, NULL, 15, &TFL->mic->audio_capture_task, 0); + if(TFL->mic->audio_capture_task == nullptr){ + MicroPrintf( PSTR("Creating capture task failed")); + goto loop_task_exit; + } + MicroPrintf( PSTR("Created capture task")); + TFL->mic->model_input_buffer = TFL->input->data.int8; + vTaskDelay(pdMS_TO_TICKS(2000)); // wait for at least the time of the the microphone warm up + } +#endif + + TFL->option.running_loop = 1; + +// loop section + MicroPrintf(PSTR("Enter task loop")); + while (TFL->option.running_loop == 1) + { + TickType_t xLastWakeTime = xTaskGetTickCount(); + TFL->stats->loop_task_free_stack_bytes = uxTaskGetStackHighWaterMark(NULL); + #ifdef USE_I2S + if(TFL->option.use_mic == 1){ + if(TFL->mic->flag.mode_record_audio == 1){ + vTaskDelay(1000/ portTICK_PERIOD_MS); // sit and wait while recording + continue; + } + } + #endif //USE_I2S + + bool do_invokation = true; + while(TFL->option.delay_next_invocation == 1 && TFL->option.running_loop == 1){ + MicroPrintf(PSTR("delay_next_invocation")); + vTaskDelay(10/ portTICK_PERIOD_MS); + } + TFL->option.delay_next_invocation = 1; + + #ifdef USE_I2S + if(TFL->option.use_mic == 1){ + TFL->option.delay_next_invocation = 0; // Clean up later + // MicroPrintf(PSTR("new_feature_data: %d"), TFL->mic->flag.new_feature_data); + if (TFL->mic->flag.new_feature_data == 0){ + // MicroPrintf(PSTR("no invokation yet")); + do_invokation = false; + } + // MicroPrintf(PSTR(" yes")); + if(TFL->mic->flag.continue_audio_capture == 1){ + // MicroPrintf(PSTR(" now loop audio")); + TFL_mic_feature_buf_to_input(); + } + } + #endif + if(do_invokation){ + // MicroPrintf(PSTR("Invokation requested")); + TFL->option.running_invocation = 1; + int invoke_status = interpreter.Invoke(); + if (invoke_status != kTfLiteOk) { + MicroPrintf(PSTR("Invoke failed")); + TFL->option.running_loop = 0; + } + // TFL->output = interpreter.output(0); + if(TFL->berry_output_buf != nullptr){ + memcpy(TFL->berry_output_buf,(int8_t*)TFL->output->data.data,TFL->berry_output_bufsize); + } + TFL->stats->invokations++; + + // MicroPrintf(PSTR("Invokation done")); + TFL->option.unread_output = 1; + #ifdef USE_I2S + if(TFL->option.use_mic == 1) { + TFL->mic->flag.new_feature_data = 0; + } + TFL->option.running_invocation = 0; + #endif //USE_I2S + } + if(TFL->option.running_loop == 1) vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(1000 / TFL->max_invocations)); //maybe we already want to exit + } + +// end of loop section +loop_task_exit: + delete TFL->stats; + if(TFL->option.use_mic == 1) {TFL_stop_audio_capture();} + MicroPrintf(PSTR("end loop task")); + TFL->option.loop_ended = 1; + vTaskDelete( NULL ); +} + +/*********************************************************************************************\ + * Native functions mapped to Berry functions +\*********************************************************************************************/ +extern "C" { + +/** + * @brief Create a context for a tensor flow session, that will later run in a task + * + * @param vm + * @param type BUF - generic byte buffer, CAM - webcam input, MIC - microphone input + * @return btrue + * @return bfalse + */ + bbool be_TFL_begin(struct bvm *vm, const char* type, const uint8_t *descriptor, size_t len) { + if (!TFL_log_buffer){ + TFL_log_buffer = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT); + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: init log buffer")); + } + TFL_delete_tasks(); + if(strlen(type) == 0){ + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: context deleted")); + return btrue; + } + TFL = new TFL_ctx_t; + TFL->options = 0; + + if(*(uint32_t*)type == 0x00465542){ //BUF + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: mode generic buffer")); + } + else if(*(uint32_t*)type == 0x004D4143){ //CAM - not yet implemented + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: mode webcam")); + if(TFL_init_CAM()){ + TFL->option.use_cam = 1; + } + else{ + return bfalse; + } + } + else if(*(uint32_t*)type == 0x0043494D){ //MIC + if(descriptor && len==sizeof(TFL_mic_descriptor_t)){ + if(TFL_init_MIC(descriptor)){ + TFL->option.use_mic = 1; + } + else{ + return bfalse; + } + } + else{ + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: expected descriptor of size: %u"), sizeof(TFL_mic_descriptor_t)); + return bfalse; + } + } + else{ + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: unknown mode")); + return bfalse; + } + if(TFL!=nullptr){ + AddLog(LOG_LEVEL_INFO, PSTR("TFL: start TFL context with type: %s"), type); + TFL->option.init_done = 1; + return btrue; + } + return bfalse; + } + +/** + * @brief Load tensor flow lite model and then start the tensor flow session in a task + * + * @param vm + * @param buf Model in a byte buffer + * @param size Size of buffer, must be 8-byte-aligned (auto-calculated by Berry) + * @param arean Size of the Tensor Arena in the stack of the TFL task + * @return btrue + * @return bfalse + */ + bbool be_TFL_load(struct bvm *vm, const uint8_t *model_buf, size_t model_size, const uint8_t *output_buf, size_t output_size,int arena) { + if(TFL){ + if(TFL->option.init_done){ + TFL->model = tflite::GetModel(model_buf); + if ( TFL->model->version() != TFLITE_SCHEMA_VERSION) { + AddLog(LOG_LEVEL_INFO, PSTR("TFL: Model schema version %d not supported " + "version %d."), TFL->model->version(), TFLITE_SCHEMA_VERSION); + return bfalse; + } + if(model_size%8 != 0){ + AddLog(LOG_LEVEL_INFO, PSTR("TFL: model not 8-byte aligned")); + return bfalse; + } + if(arena){ + TFL->TensorArenaSize = arena; + } + TFL->option.mode_inference = 1; + TFL->berry_output_buf = (int8_t*)output_buf; + TFL->berry_output_bufsize = output_size; + TFL_create_task(); + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: starting TFL task, model sz: %u, allocated arena sz: %u"),model_size,TFL->TensorArenaSize); + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: Berry output buffer of size: %u"),output_size); + return btrue; + } + } + return bfalse; + } + + /** + * @brief Send new input data to the tensor flow session + * + * @param vm + * @param buf Arbitrary data in a byte buffer, must fit to the TF model + * @param size Size of buffer (auto-calculated by Berry) + * @return btrue + * @return bfalse + */ + + bbool be_TFL_input(struct bvm *vm, const uint8_t *buf, size_t size){ + if(!TFL) return bfalse; + if(TFL->option.running_loop == 1){ + uint32_t timeout = 0; + while(!TFL->option.delay_next_invocation == 1) { + if(timeout>10) break; + delay(2); + timeout++; + } + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: imput new data and invoke")); + memcpy((uint8_t*)TFL->input->data.data,(uint8_t*)buf,size); + TFL->option.delay_next_invocation = 0; + return btrue; + } + return bfalse; + } + + /** + * @brief Get copy of the output sensor of the tensor flow session + * + * @param vm + * @param buf Arbitrary data in a byte buffer, must fit in size to the TF model + * @param size Size of buffer (auto-calculated by Berry) + * @return btrue - new data + * @return bfalse - old data + */ + bbool be_TFL_output(struct bvm *vm, const uint8_t *buf, size_t size){ + if(!TFL) return bfalse; + if(TFL->option.running_loop == 0) return bfalse; + if(TFL->option.unread_output == 1){ + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: read output data")); + if(TFL->output != nullptr){ + // memcpy((uint8_t*)buf,(uint8_t*)TFL->output->data.data,size); + TFL->option.unread_output = 0; + return btrue; //new data + } + } + return bfalse; // old data + } + +/** + * @brief Read from the logging buffer from the TFL tasks + * + * @param vm + * @return const char* + */ + const char * be_TFL_log(struct bvm *vm){ + size_t size; + char * item = (char *)xRingbufferReceive(TFL_log_buffer, &size, pdMS_TO_TICKS(5)); + if(item != NULL){ + // item[size] = 0; // 0-terminate string + vRingbufferReturnItem(TFL_log_buffer, (void *)item); + } + return (const char *)item; + } + + +/** + * @brief Shows statistiscs about the model and the running TFL session + * + * @param vm + * @return json string + */ + const char * be_TFL_stats(struct bvm *vm){ + + const size_t size = 512; + char * s = (char*)calloc(size,1); + uint32_t pos = 0; + uint32_t inc = 0; + inc = snprintf_P(s + pos, size, PSTR("{\"model\":{\"input_shape\":[")); + pos += inc; + uint32_t dims = TFL->input->dims->size; + for(int i=0;iinput->dims->data[i]); + pos += inc; + if (i != dims-1){ + inc = snprintf_P(s + pos, size-pos,","); + pos += inc; + } + } + inc = snprintf_P(s + pos, size-pos, PSTR("],\"input_type\":%u,\"output_shape\":["),TFL->input->type); + pos += inc; + dims = TFL->output->dims->size; + for(int i=0;ioutput->dims->data[i]); + pos += inc; + if (i != dims-1){ + inc = snprintf_P(s + pos, size-pos,","); + pos += inc; + } + } + inc = snprintf_P(s + pos, size-pos, PSTR("],\"output_type\":%u}"),TFL->output->type); + pos += inc; + inc = snprintf_P(s + pos, size-pos, PSTR(",\"sessiom\":{\"used_arena\":%u"),TFL->stats->used_arena_bytes); + pos += inc; + inc = snprintf_P(s + pos, size-pos, PSTR(",\"loop_stack\":%u"),TFL->stats->loop_task_free_stack_bytes); + pos += inc; + if(TFL->option.use_mic == 1){ + inc = snprintf_P(s + pos, size-pos, PSTR(",\"audio_stack\":%u"),TFL->stats->mic_task_free_stack_bytes); + pos += inc; + } + inc = snprintf_P(s + pos, size-pos, PSTR(",\"invokations\":%u}}"),TFL->stats->invokations); + be_pushstring(vm, s); + free(s); + return s; + } + + void be_TFL_rec(struct bvm *vm, const char* filename, size_t seconds){ + if(TFL){ + TFL->option.loop_ended = 1; // just in case someone wants to stop this from another scope + if(TFL->mic != nullptr){ + if(TFL->mic->flag.continue_audio_capture == 1){ + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: running recording, requesting termination")); + TFL->mic->flag.continue_audio_capture = 0; + return; + } + if(TFL_init_wave_file(filename,seconds)){ + AddLog(LOG_LEVEL_DEBUG, PSTR("TFL: starting recording to: %s"),filename); + TFL->mic->flag.mode_record_audio = 1; + TFL->stats = new TFL_stats_t; + xTaskCreatePinnedToCore(TFL_capture_samples, "tfl_mic", 1024 * 3, NULL, 10, &TFL->mic->audio_capture_task, 0); + } + } + } + else{ + AddLog(LOG_LEVEL_ERROR, PSTR("TFL: no MIC context initialized")); + } + } +} //extern "C" + +#endif // USE_BERRY_TF_LITE + +#endif // USE_BERRY