diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/BUILD b/tensorflow/lite/experimental/micro/examples/micro_speech/BUILD index 51ba2976a2e..29d40e702d9 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/BUILD +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/BUILD @@ -11,34 +11,34 @@ load( ) cc_library( - name = "model_settings", + name = "simple_model_settings", srcs = [ - "model_settings.cc", + "simple_features/simple_model_settings.cc", ], hdrs = [ - "model_settings.h", + "simple_features/simple_model_settings.h", ], ) cc_library( - name = "tiny_conv_model_data", + name = "tiny_conv_simple_features_model_data", srcs = [ - "tiny_conv_model_data.cc", + "simple_features/tiny_conv_simple_features_model_data.cc", ], hdrs = [ - "tiny_conv_model_data.h", + "simple_features/tiny_conv_simple_features_model_data.h", ], ) cc_library( - name = "features_test_data", + name = "simple_features_test_data", srcs = [ - "no_features_data.cc", - "yes_features_data.cc", + "simple_features/no_simple_features_data.cc", + "simple_features/yes_simple_features_data.cc", ], hdrs = [ - "no_features_data.h", - "yes_features_data.h", + "simple_features/no_simple_features_data.h", + "simple_features/yes_simple_features_data.h", ], ) @@ -48,10 +48,10 @@ tflite_micro_cc_test( "micro_speech_test.cc", ], deps = [ - ":features_test_data", - ":tiny_conv_model_data", "//tensorflow/lite:schema_fbs_version", "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_features_test_data", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:tiny_conv_micro_features_model_data", "//tensorflow/lite/experimental/micro/kernels:all_ops_resolver", "//tensorflow/lite/experimental/micro/kernels:micro_ops", "//tensorflow/lite/experimental/micro/testing:micro_test", @@ -60,45 +60,66 @@ tflite_micro_cc_test( ) cc_library( - name = "preprocessor_test_data", + name = "audio_sample_test_data", srcs = [ "no_30ms_sample_data.cc", - "no_power_spectrum_data.cc", "yes_30ms_sample_data.cc", - "yes_power_spectrum_data.cc", ], hdrs = [ "no_30ms_sample_data.h", - "no_power_spectrum_data.h", "yes_30ms_sample_data.h", - "yes_power_spectrum_data.h", ], ) cc_library( - name = "preprocessor_reference", + name = "audio_large_sample_test_data", srcs = [ - "preprocessor.cc", + "no_1000ms_sample_data.cc", + "yes_1000ms_sample_data.cc", ], hdrs = [ - "preprocessor.h", + "no_1000ms_sample_data.h", + "yes_1000ms_sample_data.h", + ], +) + +cc_library( + name = "simple_features_generator_test_data", + srcs = [ + "simple_features/no_power_spectrum_data.cc", + "simple_features/yes_power_spectrum_data.cc", + ], + hdrs = [ + "simple_features/no_power_spectrum_data.h", + "simple_features/yes_power_spectrum_data.h", + ], +) + +cc_library( + name = "simple_features_generator_reference", + srcs = [ + "simple_features/simple_features_generator.cc", + ], + hdrs = [ + "simple_features/simple_features_generator.h", ], deps = [ - ":model_settings", + ":simple_model_settings", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", ], ) tflite_micro_cc_test( - name = "preprocessor_reference_test", + name = "simple_features_generator_reference_test", srcs = [ - "preprocessor_test.cc", + "simple_features/simple_features_generator_test.cc", ], deps = [ - ":model_settings", - ":preprocessor_reference", - ":preprocessor_test_data", + ":audio_sample_test_data", + ":simple_features_generator_reference", + ":simple_features_generator_test_data", + ":simple_model_settings", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", "//tensorflow/lite/experimental/micro/testing:micro_test", @@ -106,29 +127,30 @@ tflite_micro_cc_test( ) cc_library( - name = "preprocessor_fixed", + name = "simple_features_generator_fixed", srcs = [ - "fixed_point/preprocessor.cc", + "simple_features/fixed_point/simple_features_generator.cc", ], hdrs = [ - "preprocessor.h", + "simple_features/simple_features_generator.h", ], deps = [ - ":model_settings", + ":simple_model_settings", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", ], ) tflite_micro_cc_test( - name = "preprocessor_fixed_test", + name = "simple_features_generator_fixed_test", srcs = [ - "preprocessor_test.cc", + "simple_features/simple_features_generator_test.cc", ], deps = [ - ":model_settings", - ":preprocessor_fixed", - ":preprocessor_test_data", + ":audio_sample_test_data", + ":simple_features_generator_fixed", + ":simple_features_generator_test_data", + ":simple_model_settings", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", "//tensorflow/lite/experimental/micro/testing:micro_test", @@ -144,9 +166,25 @@ cc_library( "audio_provider.h", ], deps = [ - ":model_settings", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", + ], +) + +cc_library( + name = "audio_provider_mock", + srcs = [ + "audio_provider_mock.cc", + ], + hdrs = [ + "audio_provider.h", + ], + deps = [ + ":audio_large_sample_test_data", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", ], ) @@ -157,9 +195,24 @@ tflite_micro_cc_test( ], deps = [ ":audio_provider", - ":model_settings", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +tflite_micro_cc_test( + name = "audio_provider_mock_test", + srcs = [ + "audio_provider_mock_test.cc", + ], + deps = [ + ":audio_large_sample_test_data", + ":audio_provider_mock", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", "//tensorflow/lite/experimental/micro/testing:micro_test", ], ) @@ -174,10 +227,10 @@ cc_library( ], deps = [ ":audio_provider", - ":model_settings", - ":preprocessor_reference", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_features_generator", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", ], ) @@ -189,9 +242,41 @@ tflite_micro_cc_test( deps = [ ":audio_provider", ":feature_provider", - ":model_settings", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +cc_library( + name = "feature_provider_mock", + srcs = [ + "feature_provider.cc", + ], + hdrs = [ + "feature_provider.h", + ], + deps = [ + ":audio_provider_mock", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_features_generator", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", + ], +) + +tflite_micro_cc_test( + name = "feature_provider_mock_test", + srcs = [ + "feature_provider_mock_test.cc", + ], + deps = [ + ":feature_provider_mock", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_features_test_data", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", "//tensorflow/lite/experimental/micro/testing:micro_test", ], ) @@ -205,9 +290,9 @@ cc_library( "recognize_commands.h", ], deps = [ - ":model_settings", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", ], ) @@ -235,11 +320,29 @@ cc_binary( deps = [ ":audio_provider", ":feature_provider", - ":model_settings", ":recognize_commands", - ":tiny_conv_model_data", "//tensorflow/lite:schema_fbs_version", "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:tiny_conv_micro_features_model_data", + "//tensorflow/lite/experimental/micro/kernels:all_ops_resolver", + "//tensorflow/lite/schema:schema_fbs", + ], +) + +cc_binary( + name = "micro_speech_mock", + srcs = [ + "main.cc", + ], + deps = [ + ":audio_provider_mock", + ":feature_provider", + ":recognize_commands", + "//tensorflow/lite:schema_fbs_version", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:micro_model_settings", + "//tensorflow/lite/experimental/micro/examples/micro_speech/micro_features:tiny_conv_micro_features_model_data", "//tensorflow/lite/experimental/micro/kernels:all_ops_resolver", "//tensorflow/lite/schema:schema_fbs", ], diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/Makefile.inc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/Makefile.inc index 2d0deb0c60a..73b884f29de 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/Makefile.inc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/Makefile.inc @@ -17,6 +17,7 @@ ifneq ($(filter CMSIS,$(ALL_TAGS)),) CMSIS_PREPROCESSOR_HDRS := \ tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h \ tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h \ + third_party/CMSIS_ext/README.md \ third_party/CMSIS_ext/arm_cmplx_mag_squared_q10p6.h PREPROCESSOR_TEST_SRCS += $(CMSIS_PREPROCESSOR_SRCS) @@ -43,6 +44,7 @@ ifneq ($(filter CMSIS,$(ALL_TAGS)),) $(MAKEFILE_DIR)/downloads/cmsis/CMSIS/DSP/Source/StatisticsFunctions/arm_max_q7.c THIRD_PARTY_CC_HDRS += \ + third_party/cmsis/LICENSE.txt \ third_party/cmsis/CMSIS/Core/Include/cmsis_compiler.h \ third_party/cmsis/CMSIS/Core/Include/cmsis_gcc.h \ third_party/cmsis/CMSIS/Core/Include/cmsis_version.h \ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/Makefile.inc b/tensorflow/lite/experimental/micro/examples/micro_speech/Makefile.inc index 49aace3d7d0..c4e0f0e6ca1 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/Makefile.inc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/Makefile.inc @@ -1,106 +1,349 @@ +INCLUDES += \ + -I$(MAKEFILE_DIR)/downloads/kissfft + +PROJECT_INCLUDES += \ +third_party/kissfft + +KISSFFT_LIB_SRCS := \ +$(MAKEFILE_DIR)/downloads/kissfft/kiss_fft.c \ +$(MAKEFILE_DIR)/downloads/kissfft/tools/kiss_fftr.c + +KISSFFT_LIB_HDRS := \ +$(MAKEFILE_DIR)/downloads/kissfft/COPYING \ +$(MAKEFILE_DIR)/downloads/kissfft/kiss_fft.h \ +$(MAKEFILE_DIR)/downloads/kissfft/_kiss_fft_guts.h \ +$(MAKEFILE_DIR)/downloads/kissfft/tools/kiss_fftr.h + MICRO_SPEECH_TEST_SRCS := \ tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.cc MICRO_SPEECH_TEST_HDRS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h \ -PREPROCESSOR_TEST_SRCS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc \ +SIMPLE_FEATURES_GENERATOR_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator_test.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.cc -PREPROCESSOR_TEST_HDRS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h \ +SIMPLE_FEATURES_GENERATOR_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_30ms_sample_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_30ms_sample_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.h + +MICRO_FEATURES_LIB_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.cc \ +$(KISSFFT_LIB_SRCS) + +MICRO_FEATURES_LIB_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/bits.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.h \ +$(KISSFFT_LIB_HDRS) + +MICRO_FEATURES_FFT_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.cc \ +$(KISSFFT_LIB_SRCS) + +MICRO_FEATURES_FFT_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h \ +$(KISSFFT_LIB_HDRS) + +MICRO_FEATURES_FILTERBANK_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.cc + +MICRO_FEATURES_FILTERBANK_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h + +MICRO_FEATURES_FRONTEND_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_test.cc \ +$(MICRO_FEATURES_LIB_SRCS) + +MICRO_FEATURES_FRONTEND_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.h \ +$(MICRO_FEATURES_LIB_HDRS) + +MICRO_FEATURES_LOG_SCALE_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.cc + +MICRO_FEATURES_LOG_SCALE_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/bits.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h + +MICRO_FEATURES_NOISE_REDUCTION_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.cc + +MICRO_FEATURES_NOISE_REDUCTION_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h + +MICRO_FEATURES_PCAN_GAIN_CONTROL_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.cc + +MICRO_FEATURES_PCAN_GAIN_CONTROL_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h + +MICRO_FEATURES_WINDOW_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.cc + +MICRO_FEATURES_WINDOW_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h + +MICRO_FEATURES_GENERATOR_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.cc \ +$(MICRO_FEATURES_LIB_SRCS) + +MICRO_FEATURES_GENERATOR_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h \ +$(MICRO_FEATURES_LIB_HDRS) + +MICRO_FEATURES_GENERATOR_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.cc \ +$(MICRO_FEATURES_GENERATOR_SRCS) + +MICRO_FEATURES_GENERATOR_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.h \ tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.h \ tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.h +$(MICRO_FEATURES_GENERATOR_HDRS) AUDIO_PROVIDER_TEST_SRCS := \ tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc AUDIO_PROVIDER_TEST_HDRS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h \ + +AUDIO_PROVIDER_MOCK_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock.cc + +AUDIO_PROVIDER_MOCK_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.h \ tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h \ FEATURE_PROVIDER_TEST_SRCS := \ tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc +tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc \ +$(MICRO_FEATURES_GENERATOR_SRCS) FEATURE_PROVIDER_TEST_HDRS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h \ tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h +tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h \ +$(MICRO_FEATURES_GENERATOR_HDRS) + +FEATURE_PROVIDER_MOCK_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.cc \ +$(MICRO_FEATURES_GENERATOR_SRCS) + +FEATURE_PROVIDER_MOCK_TEST_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h \ +$(MICRO_FEATURES_GENERATOR_HDRS) RECOGNIZE_COMMANDS_TEST_SRCS := \ tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.cc RECOGNIZE_COMMANDS_TEST_HDRS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h \ tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.h MICRO_SPEECH_SRCS := \ tensorflow/lite/experimental/micro/examples/micro_speech/main.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.cc +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.cc \ +$(MICRO_FEATURES_GENERATOR_SRCS) MICRO_SPEECH_HDRS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h \ tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h \ tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h \ -tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.h +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.h \ +$(MICRO_FEATURES_GENERATOR_HDRS) + +MICRO_SPEECH_MOCK_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/main.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.cc \ +$(MICRO_FEATURES_GENERATOR_SRCS) + +MICRO_SPEECH_MOCK_HDRS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.h \ +tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.h \ +$(MICRO_FEATURES_GENERATOR_HDRS) # Find any platform-specific rules for this example. include $(wildcard tensorflow/lite/experimental/micro/examples/micro_speech/*/Makefile.inc) +$(eval $(call microlite_test,micro_features_fft_test,\ +$(MICRO_FEATURES_FFT_TEST_SRCS),$(MICRO_FEATURES_FFT_TEST_HDRS))) + +$(eval $(call microlite_test,micro_features_filterbank_test,\ +$(MICRO_FEATURES_FILTERBANK_TEST_SRCS),$(MICRO_FEATURES_FILTERBANK_TEST_HDRS))) + +$(eval $(call microlite_test,micro_features_frontend_test,\ +$(MICRO_FEATURES_FRONTEND_TEST_SRCS),$(MICRO_FEATURES_FRONTEND_TEST_HDRS))) + +$(eval $(call microlite_test,micro_features_log_scale_test,\ +$(MICRO_FEATURES_LOG_SCALE_TEST_SRCS),$(MICRO_FEATURES_LOG_SCALE_TEST_HDRS))) + +$(eval $(call microlite_test,micro_features_noise_reduction_test,\ +$(MICRO_FEATURES_NOISE_REDUCTION_TEST_SRCS),$(MICRO_FEATURES_NOISE_REDUCTION_TEST_HDRS))) + +$(eval $(call microlite_test,micro_features_pcan_gain_control_test,\ +$(MICRO_FEATURES_PCAN_GAIN_CONTROL_TEST_SRCS),$(MICRO_FEATURES_PCAN_GAIN_CONTROL_TEST_HDRS))) + +$(eval $(call microlite_test,micro_features_window_test,\ +$(MICRO_FEATURES_WINDOW_TEST_SRCS),$(MICRO_FEATURES_WINDOW_TEST_HDRS))) + +# Test the code for feature generation. +$(eval $(call microlite_test,micro_features_generator_test,\ +$(MICRO_FEATURES_GENERATOR_TEST_SRCS), $(MICRO_FEATURES_GENERATOR_TEST_HDRS))) + # Tests loading and running a speech model. $(eval $(call microlite_test,micro_speech_test,\ $(MICRO_SPEECH_TEST_SRCS),$(MICRO_SPEECH_TEST_HDRS))) # Test the code for feature generation. -$(eval $(call microlite_test,preprocessor_test,\ -$(PREPROCESSOR_TEST_SRCS), $(PREPROCESSOR_TEST_HDRS))) +$(eval $(call microlite_test,simple_features_generator_test,\ +$(SIMPLE_FEATURES_GENERATOR_TEST_SRCS), $(SIMPLE_FEATURES_GENERATOR_TEST_HDRS))) # Tests the audio provider module. $(eval $(call microlite_test,audio_provider_test,\ $(AUDIO_PROVIDER_TEST_SRCS),$(AUDIO_PROVIDER_TEST_HDRS))) +# Tests the audio provider mock module. +$(eval $(call microlite_test,audio_provider_mock_test,\ +$(AUDIO_PROVIDER_MOCK_TEST_SRCS),$(AUDIO_PROVIDER_MOCK_TEST_HDRS))) + # Tests the feature provider module. $(eval $(call microlite_test,feature_provider_test,\ $(FEATURE_PROVIDER_TEST_SRCS),$(FEATURE_PROVIDER_TEST_HDRS))) -# Tests the feature provider module. +# Tests the feature provider module using the mock audio provider. +$(eval $(call microlite_test,feature_provider_mock_test,\ +$(FEATURE_PROVIDER_MOCK_TEST_SRCS),$(FEATURE_PROVIDER_MOCK_TEST_HDRS))) + +# Tests the command recognizer module. $(eval $(call microlite_test,recognize_commands_test,\ $(RECOGNIZE_COMMANDS_TEST_SRCS),$(RECOGNIZE_COMMANDS_TEST_HDRS))) # Builds a standalone speech command recognizer binary. $(eval $(call microlite_test,micro_speech,\ $(MICRO_SPEECH_SRCS),$(MICRO_SPEECH_HDRS))) + +# Builds a standalone speech command recognizer binary using fake audio input. +$(eval $(call microlite_test,micro_speech_mock,\ +$(MICRO_SPEECH_MOCK_SRCS),$(MICRO_SPEECH_MOCK_HDRS))) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/README.md b/tensorflow/lite/experimental/micro/examples/micro_speech/README.md index 500eed33bab..3cc81c4b5b4 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/README.md +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/README.md @@ -83,7 +83,8 @@ If you see a compiling error on older machines, try leaving out the `--copt` arg ``` bazel run tensorflow/examples/speech_commands:freeze -- \ --model_architecture=tiny_conv --window_stride=20 --preprocess=average \ ---wanted_words="yes,no" --quantize=1 --output_file=/tmp/tiny_conv.pb +--wanted_words="yes,no" --quantize=1 --output_file=/tmp/tiny_conv.pb \ +--start_checkpoint=/tmp/speech_commands_train/tiny_conv.ckpt-18000 ``` The next step is to create a TensorFlow Lite file from the frozen graph: @@ -99,5 +100,5 @@ bazel run tensorflow/lite/toco:toco -- \ Finally, convert the file into a C source file that can be compiled into an embedded system: ``` -xxd -i /tmp/tiny_conv.tflite > /tmp/tiny_conv_model_data.cc +xxd -i /tmp/tiny_conv.tflite > /tmp/tiny_conv_simple_features_model_data.cc ``` diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/Makefile.inc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/Makefile.inc index 0aa362be003..c83090344ba 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/Makefile.inc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/Makefile.inc @@ -5,7 +5,7 @@ ifeq ($(TARGET), apollo3evb) $(AP3_MICRO_DIR)/../preprocessor.cc \ $(AP3_MICRO_DIR)/pushbutton_main.c \ $(AP3_MICRO_DIR)/pushbutton_test.cc \ - $(AP3_MICRO_DIR)/../tiny_conv_model_data.cc \ + $(AP3_MICRO_DIR)/../simple_features/tiny_conv_simple_features_model_data.cc \ $(APOLLO3_SDK)/devices/am_devices_led.c ALL_SRCS += $(PUSHBUTTON_MICRO_SPEECH_TEST_SRCS) PUSHBUTTON_MICRO_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ @@ -24,8 +24,8 @@ ifeq ($(TARGET), apollo3evb) PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS := \ $(AP3_MICRO_DIR)/pushbutton_main.c \ $(AP3_MICRO_DIR)/pushbutton_test.cc \ - $(AP3_MICRO_DIR)/../tiny_conv_model_data.cc \ - $(CMSIS_DIR)/preprocessor.cc \ + $(AP3_MICRO_DIR)/../simple_features/tiny_conv_simple_features_model_data.cc \ + $(CMSIS_DIR)/simple_features_generator.cc \ $(CMSIS_EXT_DIR)/arm_cmplx_mag_squared_q10p6.c \ $(CMSIS_DIR)/hanning.c \ $(APOLLO3_SDK)/devices/am_devices_led.c \ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc index 95043f857b3..d4583dbf4a6 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc @@ -17,8 +17,8 @@ limitations under the License. * micro_speech_test.cc */ #include "tensorflow/lite/c/c_api_internal.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/tiny_conv_simple_features_model_data.h" #include "tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/micro_interpreter.h" @@ -32,20 +32,36 @@ uint8_t g_unknown_score = 0; uint8_t g_yes_score = 0; uint8_t g_no_score = 0; +namespace { + +TfLiteStatus GenerateSimpleFeatures_1sec(tflite::ErrorReporter* error_reporter, + const int16_t* input, + uint8_t* output) { + int i; + for (i = 0; i < 49; i++) { + GenerateSimpleFeatures(error_reporter, input + i * 320, 480, 43, + output + i * 43); + } + return kTfLiteOk; +} + +} // namespace + TF_LITE_MICRO_TESTS_BEGIN -TF_LITE_MICRO_TEST(TestPreprocessor) { +TF_LITE_MICRO_TEST(TestSimpleFeaturesGenerator) { tflite::MicroErrorReporter micro_error_reporter; tflite::ErrorReporter* error_reporter = µ_error_reporter; uint8_t preprocessed_data[43 * 49]; - TfLiteStatus preprocess_1sec_status = - Preprocess_1sec(error_reporter, captured_data, preprocessed_data); - TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, preprocess_1sec_status); + TfLiteStatus generate_1sec_status = GenerateSimpleFeatures_1sec( + error_reporter, captured_data, preprocessed_data); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, generate_1sec_status); // Map the model into a usable data structure. This doesn't involve any // copying or parsing, it's a very lightweight operation. - const tflite::Model* model = ::tflite::GetModel(g_tiny_conv_model_data); + const tflite::Model* model = + ::tflite::GetModel(g_tiny_conv_simple_features_model_data); if (model->version() != TFLITE_SCHEMA_VERSION) { error_reporter->Report( "Model provided is schema version %d not equal " diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc index 52db18e6868..08811c83b43 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc @@ -15,7 +15,7 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" namespace { int16_t g_dummy_audio_data[kMaxAudioSampleSize]; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock.cc new file mode 100644 index 00000000000..9c9792510b0 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock.cc @@ -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. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.h" + +namespace { +int16_t g_dummy_audio_data[kMaxAudioSampleSize]; +int32_t g_latest_audio_timestamp = 0; +} // namespace + +TfLiteStatus GetAudioSamples(tflite::ErrorReporter* error_reporter, + int start_ms, int duration_ms, + int* audio_samples_size, int16_t** audio_samples) { + const int yes_start = (0 * kAudioSampleFrequency) / 1000; + const int yes_end = (1000 * kAudioSampleFrequency) / 1000; + const int no_start = (4000 * kAudioSampleFrequency) / 1000; + const int no_end = (5000 * kAudioSampleFrequency) / 1000; + const int wraparound = (8000 * kAudioSampleFrequency) / 1000; + const int start_sample = (start_ms * kAudioSampleFrequency) / 1000; + for (int i = 0; i < kMaxAudioSampleSize; ++i) { + const int sample_index = (start_sample + i) % wraparound; + int16_t sample; + if ((sample_index >= yes_start) && (sample_index < yes_end)) { + sample = g_yes_1000ms_sample_data[sample_index - yes_start]; + } else if ((sample_index >= no_start) && (sample_index < no_end)) { + sample = g_no_1000ms_sample_data[sample_index - no_start]; + } else { + sample = 0; + } + g_dummy_audio_data[i] = sample; + } + *audio_samples_size = kMaxAudioSampleSize; + *audio_samples = g_dummy_audio_data; + return kTfLiteOk; +} + +int32_t LatestAudioTimestamp() { + g_latest_audio_timestamp += 100; + return g_latest_audio_timestamp; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock_test.cc new file mode 100644 index 00000000000..b73d436ad63 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_mock_test.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/experimental/micro/examples/micro_speech/audio_provider.h" + +#include + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.h" + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(TestAudioProviderMock) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + int audio_samples_size = 0; + int16_t* audio_samples = nullptr; + TfLiteStatus get_status = + GetAudioSamples(error_reporter, 0, kFeatureSliceDurationMs, + &audio_samples_size, &audio_samples); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, get_status); + TF_LITE_MICRO_EXPECT_LE(audio_samples_size, kMaxAudioSampleSize); + TF_LITE_MICRO_EXPECT_NE(audio_samples, nullptr); + for (int i = 0; i < audio_samples_size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(g_yes_1000ms_sample_data[i], audio_samples[i]); + } + + get_status = GetAudioSamples(error_reporter, 500, kFeatureSliceDurationMs, + &audio_samples_size, &audio_samples); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, get_status); + TF_LITE_MICRO_EXPECT_LE(audio_samples_size, kMaxAudioSampleSize); + TF_LITE_MICRO_EXPECT_NE(audio_samples, nullptr); + for (int i = 0; i < audio_samples_size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(g_yes_1000ms_sample_data[i + 8000], + audio_samples[i]); + } + + get_status = GetAudioSamples(error_reporter, 1500, kFeatureSliceDurationMs, + &audio_samples_size, &audio_samples); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, get_status); + TF_LITE_MICRO_EXPECT_LE(audio_samples_size, kMaxAudioSampleSize); + TF_LITE_MICRO_EXPECT_NE(audio_samples, nullptr); + for (int i = 0; i < audio_samples_size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(0, audio_samples[i]); + } + + get_status = GetAudioSamples(error_reporter, 12250, kFeatureSliceDurationMs, + &audio_samples_size, &audio_samples); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, get_status); + TF_LITE_MICRO_EXPECT_LE(audio_samples_size, kMaxAudioSampleSize); + TF_LITE_MICRO_EXPECT_NE(audio_samples, nullptr); + for (int i = 0; i < audio_samples_size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(g_no_1000ms_sample_data[i + 4000], + audio_samples[i]); + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_test.cc index 85fbbb80a6c..f9212aa3491 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_test.cc @@ -18,7 +18,7 @@ limitations under the License. #include #include "tensorflow/lite/c/c_api_internal.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/testing/micro_test.h" diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/disco_f746ng/audio_provider.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/disco_f746ng/audio_provider.cc index 06647d0c536..49fea826759 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/disco_f746ng/audio_provider.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/disco_f746ng/audio_provider.cc @@ -15,7 +15,7 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" #include "AUDIO_DISCO_F746NG.h" #include "SDRAM_DISCO_F746NG.h" diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc index 7f9ece41dd3..b5dfa3d9440 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc @@ -16,8 +16,8 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h" #include "tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" FeatureProvider::FeatureProvider(int feature_size, uint8_t* feature_data) : feature_size_(feature_size), @@ -48,6 +48,10 @@ TfLiteStatus FeatureProvider::PopulateFeatureData( int slices_needed = current_step - last_step; // 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; slices_needed = kFeatureSliceCount; } @@ -94,16 +98,17 @@ TfLiteStatus FeatureProvider::PopulateFeatureData( GetAudioSamples(error_reporter, slice_start_ms, kFeatureSliceDurationMs, &audio_samples_size, &audio_samples); if (audio_samples_size < kMaxAudioSampleSize) { - error_reporter->Report("Audio data size %d too small, want %d", + error_reporter->Report("Audio data size %d too small, want %d", audio_samples_size, kMaxAudioSampleSize); return kTfLiteError; } uint8_t* new_slice_data = feature_data_ + (new_slice * kFeatureSliceSize); - TfLiteStatus preprocess_status = - Preprocess(error_reporter, audio_samples, audio_samples_size, - kFeatureSliceSize, new_slice_data); - if (preprocess_status != kTfLiteOk) { - return preprocess_status; + 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; } } } diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_mock_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_mock_test.cc new file mode 100644 index 00000000000..b05912e26f8 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_mock_test.cc @@ -0,0 +1,66 @@ +/* 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/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(TestFeatureProviderMockYes) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + uint8_t feature_data[kFeatureElementCount]; + FeatureProvider feature_provider(kFeatureElementCount, feature_data); + + int how_many_new_slices = 0; + TfLiteStatus populate_status = feature_provider.PopulateFeatureData( + error_reporter, /* last_time_in_ms= */ 0, /* time_in_ms= */ 970, + &how_many_new_slices); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, populate_status); + TF_LITE_MICRO_EXPECT_EQ(kFeatureSliceCount, how_many_new_slices); + + for (int i = 0; i < kFeatureElementCount; ++i) { + TF_LITE_MICRO_EXPECT_EQ(g_yes_micro_f2e59fea_nohash_1_data[i], + feature_data[i]); + } +} + +TF_LITE_MICRO_TEST(TestFeatureProviderMockNo) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + uint8_t feature_data[kFeatureElementCount]; + FeatureProvider feature_provider(kFeatureElementCount, feature_data); + + int how_many_new_slices = 0; + TfLiteStatus populate_status = feature_provider.PopulateFeatureData( + error_reporter, /* last_time_in_ms= */ 4000, /* time_in_ms= */ 4970, + &how_many_new_slices); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, populate_status); + TF_LITE_MICRO_EXPECT_EQ(kFeatureSliceCount, how_many_new_slices); + + for (int i = 0; i < kFeatureElementCount; ++i) { + TF_LITE_MICRO_EXPECT_EQ(g_no_micro_f9643d42_nohash_4_data[i], + feature_data[i]); + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc index 556cbfe799b..e7655a3be53 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc @@ -15,7 +15,7 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h" #include "tensorflow/lite/c/c_api_internal.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/testing/micro_test.h" diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/main.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/main.cc index 3a9a5a4df1b..e71e62170e4 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/main.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/main.cc @@ -15,9 +15,9 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h" #include "tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.h" #include "tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h" #include "tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/micro_interpreter.h" @@ -31,7 +31,8 @@ int main(int argc, char* argv[]) { // Map the model into a usable data structure. This doesn't involve any // copying or parsing, it's a very lightweight operation. - const tflite::Model* model = ::tflite::GetModel(g_tiny_conv_model_data); + const tflite::Model* model = + ::tflite::GetModel(g_tiny_conv_micro_features_model_data); if (model->version() != TFLITE_SCHEMA_VERSION) { error_reporter->Report( "Model provided is schema version %d not equal " @@ -123,7 +124,8 @@ int main(int argc, char* argv[]) { return 1; } if (is_new_command) { - error_reporter->Report("Heard %s (%d)", found_command, score); + error_reporter->Report("Heard %s (%d) @%dms", found_command, score, + current_time); } } diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/BUILD b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/BUILD new file mode 100644 index 00000000000..1e684e1efd0 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/BUILD @@ -0,0 +1,300 @@ +# Library for generating feature vectors from audio data + +package( + default_visibility = ["//visibility:public"], +) + +licenses(["notice"]) # Apache 2.0 + +load( + "//tensorflow/lite/experimental/micro/testing:micro_test.bzl", + "tflite_micro_cc_test", +) + +cc_library( + name = "micro_model_settings", + srcs = [ + "micro_model_settings.cc", + ], + hdrs = [ + "micro_model_settings.h", + ], +) + +cc_library( + name = "tiny_conv_micro_features_model_data", + srcs = [ + "tiny_conv_micro_features_model_data.cc", + ], + hdrs = [ + "tiny_conv_micro_features_model_data.h", + ], +) + +cc_library( + name = "micro_features_test_data", + srcs = [ + "no_micro_features_data.cc", + "yes_micro_features_data.cc", + ], + hdrs = [ + "no_micro_features_data.h", + "yes_micro_features_data.h", + ], +) + +cc_library( + name = "bits", + hdrs = ["bits.h"], +) + +cc_library( + name = "static_alloc", + hdrs = ["static_alloc.h"], +) + +cc_library( + name = "fft", + srcs = [ + "fft.cc", + "fft_util.cc", + ], + hdrs = [ + "fft.h", + "fft_util.h", + ], + deps = [ + ":micro_model_settings", + ":static_alloc", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + "@kissfft//:kiss_fftr_16", + ], +) + +cc_library( + name = "filterbank", + srcs = [ + "filterbank.cc", + "filterbank_util.cc", + ], + hdrs = [ + "filterbank.h", + "filterbank_util.h", + ], + deps = [ + ":bits", + ":fft", + ":micro_model_settings", + ":static_alloc", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +cc_library( + name = "frontend", + srcs = [ + "frontend.cc", + "frontend_util.cc", + ], + hdrs = [ + "frontend.h", + "frontend_util.h", + ], + deps = [ + ":bits", + ":fft", + ":filterbank", + ":log_scale", + ":micro_model_settings", + ":noise_reduction", + ":pcan_gain_control", + ":window", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +cc_library( + name = "log_scale", + srcs = [ + "log_lut.cc", + "log_scale.cc", + "log_scale_util.cc", + ], + hdrs = [ + "log_lut.h", + "log_scale.h", + "log_scale_util.h", + ], + deps = [ + ":bits", + ":micro_model_settings", + ":static_alloc", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +cc_library( + name = "noise_reduction", + srcs = [ + "noise_reduction.cc", + "noise_reduction_util.cc", + ], + hdrs = [ + "noise_reduction.h", + "noise_reduction_util.h", + ], + deps = [ + ":micro_model_settings", + ":static_alloc", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +cc_library( + name = "pcan_gain_control", + srcs = [ + "pcan_gain_control.cc", + "pcan_gain_control_util.cc", + ], + hdrs = [ + "pcan_gain_control.h", + "pcan_gain_control_util.h", + ], + deps = [ + ":bits", + ":micro_model_settings", + ":static_alloc", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +cc_library( + name = "window", + srcs = [ + "window.cc", + "window_util.cc", + ], + hdrs = [ + "window.h", + "window_util.h", + ], + deps = [ + ":micro_model_settings", + ":static_alloc", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +cc_library( + name = "micro_features_generator", + srcs = [ + "micro_features_generator.cc", + ], + hdrs = [ + "micro_features_generator.h", + ], + deps = [ + ":frontend", + ":micro_model_settings", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +cc_library( + name = "micro_features_generator_test_data", + srcs = [ + "no_feature_data_slice.cc", + "yes_feature_data_slice.cc", + ], + hdrs = [ + "no_feature_data_slice.h", + "yes_feature_data_slice.h", + ], +) + +tflite_micro_cc_test( + name = "fft_test", + srcs = ["fft_test.cc"], + deps = [ + ":fft", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +tflite_micro_cc_test( + name = "filterbank_test", + srcs = ["filterbank_test.cc"], + deps = [ + ":filterbank", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +tflite_micro_cc_test( + name = "frontend_test", + srcs = ["frontend_test.cc"], + deps = [ + ":frontend", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +tflite_micro_cc_test( + name = "log_scale_test", + srcs = ["log_scale_test.cc"], + deps = [ + ":log_scale", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +tflite_micro_cc_test( + name = "noise_reduction_test", + srcs = ["noise_reduction_test.cc"], + deps = [ + ":noise_reduction", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +tflite_micro_cc_test( + name = "pcan_gain_control_test", + srcs = ["pcan_gain_control_test.cc"], + deps = [ + ":pcan_gain_control", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +tflite_micro_cc_test( + name = "window_test", + srcs = ["window_test.cc"], + deps = [ + ":window", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +tflite_micro_cc_test( + name = "micro_features_generator_test", + srcs = [ + "micro_features_generator_test.cc", + ], + deps = [ + ":micro_features_generator", + ":micro_features_generator_test_data", + ":micro_model_settings", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/examples/micro_speech:audio_sample_test_data", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/bits.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/bits.h new file mode 100644 index 00000000000..3b19ee6f030 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/bits.h @@ -0,0 +1,94 @@ +/* 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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_BITS_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_BITS_H_ + +#include + +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 __buitin_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 __buitin_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); +} + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_BITS_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.cc new file mode 100644 index 00000000000..cde4e38740e --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.cc @@ -0,0 +1,54 @@ +/* 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/micro/examples/micro_speech/micro_features/fft.h" + +#include + +#define FIXED_POINT 16 +#include "kiss_fft.h" +// Internal test dependency placeholder1 +// Internal test dependency placeholder2 +#include "tools/kiss_fftr.h" +// Internal test dependency placeholder3 + +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. + int i; + for (i = 0; i < input_size; ++i) { + *fft_input++ = (*input++) << input_scale_shift; + } + // Zero out whatever else remains in the top part of the input. + for (; i < fft_size; ++i) { + *fft_input++ = 0; + } + + // Apply the FFT. + 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/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.h new file mode 100644 index 00000000000..d5d29f68a2c --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.h @@ -0,0 +1,48 @@ +/* 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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FFT_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FFT_H_ + +#include +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" + +struct complex_int16_t { + int16_t real; + int16_t imag; +}; + +struct FftState { + int16_t input[kMaxAudioSampleSize]; + struct complex_int16_t output[kMaxAudioSampleSize + 2]; + size_t fft_size; + size_t input_size; + // This magic number was derived from KissFFT's estimate of how much space it + // will need to process the particular lengths and datatypes we need to for + // these model settings. This size will need to be recalculated for different + // models, but you will see a runtime error if it's not large enough. + char scratch[2848]; + 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); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FFT_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_test.cc new file mode 100644 index 00000000000..b89b01445a6 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_test.cc @@ -0,0 +1,55 @@ +/* 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/micro/examples/micro_speech/micro_features/fft.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.h" + +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +namespace { + +const int16_t kFakeWindow[] = { + 0, 1151, 0, -5944, 0, 13311, 0, -21448, 0, 28327, 0, -32256, 0, 32255, + 0, -28328, 0, 21447, 0, -13312, 0, 5943, 0, -1152, 0}; +const int kScaleShift = 0; + +} // namespace + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(FftTest_CheckOutputValues) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + struct FftState state; + TF_LITE_MICRO_EXPECT(FftPopulateState( + error_reporter, &state, sizeof(kFakeWindow) / sizeof(kFakeWindow[0]))); + + FftInit(&state); + FftCompute(&state, kFakeWindow, kScaleShift); + + const struct complex_int16_t expected[] = { + {0, 0}, {-10, 9}, {-20, 0}, {-9, -10}, {0, 25}, {-119, 119}, + {-887, 0}, {3000, 3000}, {0, -6401}, {-3000, 3000}, {886, 0}, {118, 119}, + {0, 25}, {9, -10}, {19, 0}, {9, 9}, {0, 0}}; + TF_LITE_MICRO_EXPECT_EQ(state.fft_size / 2 + 1, + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i <= state.fft_size / 2; ++i) { + TF_LITE_MICRO_EXPECT_NEAR(state.output[i].real, expected[i].real, 2); + TF_LITE_MICRO_EXPECT_NEAR(state.output[i].imag, expected[i].imag, 2); + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.cc new file mode 100644 index 00000000000..ab742893197 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.cc @@ -0,0 +1,54 @@ +/* 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/micro/examples/micro_speech/micro_features/fft_util.h" + +#define FIXED_POINT 16 +#include "kiss_fft.h" +#include "tools/kiss_fftr.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h" + +int FftPopulateState(tflite::ErrorReporter* error_reporter, + 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; + } + + STATIC_ALLOC_ENSURE_ARRAY_SIZE(state->input, + (state->fft_size * sizeof(*state->input))); + + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + state->output, ((state->fft_size / 2 + 1) * sizeof(*state->output) * 2)); + + // Ask kissfft how much memory it wants. + size_t scratch_size = 0; + kiss_fftr_cfg kfft_cfg = + kiss_fftr_alloc(state->fft_size, 0, nullptr, &scratch_size); + if (kfft_cfg != nullptr) { + error_reporter->Report("Kiss memory sizing failed."); + return 0; + } + STATIC_ALLOC_ENSURE_ARRAY_SIZE(state->scratch, scratch_size); + state->scratch_size = scratch_size; + // Let kissfft configure the scratch space we just allocated + kfft_cfg = kiss_fftr_alloc(state->fft_size, 0, state->scratch, &scratch_size); + if (reinterpret_cast(kfft_cfg) != state->scratch) { + error_reporter->Report("Kiss memory preallocation strategy failed."); + return 0; + } + return 1; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.h new file mode 100644 index 00000000000..1dea097bc99 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.h @@ -0,0 +1,26 @@ +/* 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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FFT_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FFT_UTIL_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" + +// Prepares and FFT for the given input size. +int FftPopulateState(tflite::ErrorReporter* error_reporter, + struct FftState* state, size_t input_size); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FFT_UTIL_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.cc new file mode 100644 index 00000000000..67f69dd6758 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.cc @@ -0,0 +1,135 @@ +/* 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/micro/examples/micro_speech/micro_features/filterbank.h" + +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/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++ * (static_cast(*magnitudes)); + unweight_accumulator += + *unweights++ * (static_cast(*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(static_cast(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 int64_t* work = reinterpret_cast(state->work + 1); + // Reuse the work buffer since we're fine clobbering it at this point to hold + // the output. + uint32_t* output = reinterpret_cast(state->work); + int i; + for (i = 0; i < num_channels; ++i) { + *output++ = Sqrt64(*work++) >> scale_down_shift; + } + return reinterpret_cast(state->work); +} + +void FilterbankReset(struct FilterbankState* state) { + memset(state->work, 0, (state->num_channels + 1) * sizeof(*state->work)); +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.h new file mode 100644 index 00000000000..f7b479d4899 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.h @@ -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. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FILTERBANK_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FILTERBANK_H_ + +#include +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" + +#define kFilterbankBits 12 + +struct FilterbankState { + int num_channels; + int start_index; + int end_index; + int16_t channel_frequency_starts[kFeatureSliceSize + 1]; + int16_t channel_weight_starts[kFeatureSliceSize + 1]; + int16_t channel_widths[kFeatureSliceSize + 1]; + int16_t weights[316]; + int16_t unweights[316]; + uint64_t work[kFeatureSliceSize + 1]; +}; + +// 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); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FILTERBANK_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_test.cc new file mode 100644 index 00000000000..682b216ace3 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_test.cc @@ -0,0 +1,228 @@ +/* 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/micro/examples/micro_speech/micro_features/filterbank.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.h" + +#include + +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +namespace { + +const int kSampleRate = 1000; +const int kSpectrumSize = 17; +const int kStartIndex = 1; +const int kEndIndex = 15; +const int32_t kEnergy[] = {-1, 181, 400, 181, 625, 28322, + 786769, 18000000, 40972801, 18000000, 784996, 28085, + 625, 181, 361, -1, -1}; +const uint64_t kWork[] = {1835887, 61162970173, 258694800000}; +const int kScaleShift = 0; + +// Test filterbank generation using scaled-down defaults. +class FilterbankTestConfig { + public: + FilterbankTestConfig() { + config_.num_channels = 2; + config_.lower_band_limit = 8.0; + config_.upper_band_limit = 450.0; + } + + struct FilterbankConfig config_; +}; + +} // namespace + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(FilterbankTest_CheckStartIndex) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FilterbankTestConfig config; + struct FilterbankState state; + TF_LITE_MICRO_EXPECT(FilterbankPopulateState( + error_reporter, &config.config_, &state, kSampleRate, kSpectrumSize)); + + TF_LITE_MICRO_EXPECT_EQ(state.start_index, kStartIndex); +} + +TF_LITE_MICRO_TEST(FilterbankTest_CheckEndIndex) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FilterbankTestConfig config; + struct FilterbankState state; + TF_LITE_MICRO_EXPECT(FilterbankPopulateState( + error_reporter, &config.config_, &state, kSampleRate, kSpectrumSize)); + + TF_LITE_MICRO_EXPECT_EQ(state.end_index, kEndIndex); +} + +TF_LITE_MICRO_TEST(FilterbankTest_CheckChannelFrequencyStarts) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FilterbankTestConfig config; + struct FilterbankState state; + TF_LITE_MICRO_EXPECT(FilterbankPopulateState( + error_reporter, &config.config_, &state, kSampleRate, kSpectrumSize)); + + const int16_t expected[] = {0, 4, 8}; + TF_LITE_MICRO_EXPECT_EQ(state.num_channels + 1, + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i <= state.num_channels; ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.channel_frequency_starts[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(FilterbankTest_CheckChannelWeightStarts) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FilterbankTestConfig config; + struct FilterbankState state; + TF_LITE_MICRO_EXPECT(FilterbankPopulateState( + error_reporter, &config.config_, &state, kSampleRate, kSpectrumSize)); + + const int16_t expected[] = {0, 8, 16}; + TF_LITE_MICRO_EXPECT_EQ(state.num_channels + 1, + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i <= state.num_channels; ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.channel_weight_starts[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(FilterbankTest_CheckChannelWidths) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FilterbankTestConfig config; + struct FilterbankState state; + TF_LITE_MICRO_EXPECT(FilterbankPopulateState( + error_reporter, &config.config_, &state, kSampleRate, kSpectrumSize)); + + const int16_t expected[] = {8, 8, 8}; + TF_LITE_MICRO_EXPECT_EQ(state.num_channels + 1, + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i <= state.num_channels; ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.channel_widths[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(FilterbankTest_CheckWeights) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FilterbankTestConfig config; + struct FilterbankState state; + TF_LITE_MICRO_EXPECT(FilterbankPopulateState( + error_reporter, &config.config_, &state, kSampleRate, kSpectrumSize)); + + const int16_t expected[] = {0, 3277, 2217, 1200, 222, 0, 0, 0, + 0, 3376, 2468, 1591, 744, 0, 0, 0, + 0, 4020, 3226, 2456, 1708, 983, 277, 0}; + TF_LITE_MICRO_EXPECT_EQ(state.channel_weight_starts[state.num_channels] + + state.channel_widths[state.num_channels], + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < sizeof(expected) / sizeof(expected[0]); ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.weights[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(FilterbankTest_CheckUnweights) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FilterbankTestConfig config; + struct FilterbankState state; + TF_LITE_MICRO_EXPECT(FilterbankPopulateState( + error_reporter, &config.config_, &state, kSampleRate, kSpectrumSize)); + + const int16_t expected[] = {0, 819, 1879, 2896, 3874, 0, 0, 0, + 0, 720, 1628, 2505, 3352, 0, 0, 0, + 0, 76, 870, 1640, 2388, 3113, 3819, 0}; + TF_LITE_MICRO_EXPECT_EQ(state.channel_weight_starts[state.num_channels] + + state.channel_widths[state.num_channels], + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < sizeof(expected) / sizeof(expected[0]); ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.unweights[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(FilterbankTest_CheckConvertFftComplexToEnergy) { + struct FilterbankState state; + state.start_index = kStartIndex; + state.end_index = kEndIndex; + + struct complex_int16_t fake_fft[] = { + {0, 0}, {-10, 9}, {-20, 0}, {-9, -10}, {0, 25}, {-119, 119}, + {-887, 0}, {3000, 3000}, {0, -6401}, {-3000, 3000}, {886, 0}, {118, 119}, + {0, 25}, {9, -10}, {19, 0}, {9, 9}, {0, 0}}; + int32_t* energy = reinterpret_cast(fake_fft); + FilterbankConvertFftComplexToEnergy(&state, fake_fft, energy); + + int i; + for (i = state.start_index; i < state.end_index; ++i) { + TF_LITE_MICRO_EXPECT_EQ(energy[i], kEnergy[i]); + } +} + +TF_LITE_MICRO_TEST(FilterbankTest_CheckAccumulateChannels) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FilterbankTestConfig config; + struct FilterbankState state; + TF_LITE_MICRO_EXPECT(FilterbankPopulateState( + error_reporter, &config.config_, &state, kSampleRate, kSpectrumSize)); + + FilterbankAccumulateChannels(&state, kEnergy); + + TF_LITE_MICRO_EXPECT_EQ(state.num_channels + 1, + sizeof(kWork) / sizeof(kWork[0])); + int i; + for (i = 0; i <= state.num_channels; ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.work[i], kWork[i]); + } +} + +TF_LITE_MICRO_TEST(FilterbankTest_CheckSqrt) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FilterbankTestConfig config; + struct FilterbankState state; + TF_LITE_MICRO_EXPECT(FilterbankPopulateState( + error_reporter, &config.config_, &state, kSampleRate, kSpectrumSize)); + std::memcpy(state.work, kWork, sizeof(kWork)); + + uint32_t* scaled_filterbank = FilterbankSqrt(&state, kScaleShift); + + const uint32_t expected[] = {247311, 508620}; + TF_LITE_MICRO_EXPECT_EQ(state.num_channels, + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < state.num_channels; ++i) { + TF_LITE_MICRO_EXPECT_EQ(scaled_filterbank[i], expected[i]); + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.cc new file mode 100644 index 00000000000..ea4aa5179bc --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.cc @@ -0,0 +1,212 @@ +/* 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/micro/examples/micro_speech/micro_features/filterbank_util.h" + +#include +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h" + +#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 * log(1.0 + (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 / (static_cast(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(tflite::ErrorReporter* error_reporter, + 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)); + + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + state->channel_frequency_starts, + (num_channels_plus_1 * sizeof(*state->channel_frequency_starts))); + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + state->channel_weight_starts, + (num_channels_plus_1 * sizeof(*state->channel_weight_starts))); + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + state->channel_widths, + (num_channels_plus_1 * sizeof(*state->channel_widths))); + STATIC_ALLOC_ENSURE_ARRAY_SIZE(state->work, + (num_channels_plus_1 * sizeof(*state->work))); + + float center_mel_freqs[kFeatureSliceSize + 1]; + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + center_mel_freqs, (num_channels_plus_1 * sizeof(*center_mel_freqs))); + + int16_t actual_channel_starts[kFeatureSliceSize + 1]; + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + actual_channel_starts, + (num_channels_plus_1 * sizeof(*actual_channel_starts))); + + int16_t actual_channel_widths[kFeatureSliceSize + 1]; + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + actual_channel_widths, + (num_channels_plus_1 * sizeof(*actual_channel_widths))); + + 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 / (static_cast(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. + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + state->weights, (weight_index_start * sizeof(*state->weights))); + for (int i = 0; i < weight_index_start; ++i) { + state->weights[i] = 0; + } + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + state->unweights, (weight_index_start * sizeof(*state->unweights))); + for (int i = 0; i < weight_index_start; ++i) { + state->unweights[i] = 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; + } + } + + if (state->end_index >= spectrum_size) { + error_reporter->Report("Filterbank end_index is above spectrum size."); + return 0; + } + return 1; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.h new file mode 100644 index 00000000000..0bf0c8494ce --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.h @@ -0,0 +1,42 @@ +/* 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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FILTERBANK_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FILTERBANK_UTIL_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" + +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(tflite::ErrorReporter* error_reporter, + const struct FilterbankConfig* config, + struct FilterbankState* state, int sample_rate, + int spectrum_size); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FILTERBANK_UTIL_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.cc new file mode 100644 index 00000000000..c609190e4db --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.cc @@ -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/micro/examples/micro_speech/micro_features/frontend.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/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 = nullptr; + 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 = reinterpret_cast(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/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.h new file mode 100644 index 00000000000..3221d283e87 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.h @@ -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. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FRONTEND_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FRONTEND_H_ + +#include +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.h" + +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); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FRONTEND_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_test.cc new file mode 100644 index 00000000000..4d9f86d48d8 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_test.cc @@ -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/micro/examples/micro_speech/micro_features/frontend.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.h" + +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +namespace { + +const int kSampleRate = 1000; +const int kWindowSamples = 25; +const int kStepSamples = 10; +const int16_t kFakeAudioData[] = { + 0, 32767, 0, -32768, 0, 32767, 0, -32768, 0, 32767, 0, -32768, + 0, 32767, 0, -32768, 0, 32767, 0, -32768, 0, 32767, 0, -32768, + 0, 32767, 0, -32768, 0, 32767, 0, -32768, 0, 32767, 0, -32768}; + +// Test end-to-end frontend behaviors. +class FrontendTestConfig { + public: + FrontendTestConfig() { + config_.window.size_ms = 25; + config_.window.step_size_ms = 10; + config_.noise_reduction.smoothing_bits = 10; + config_.filterbank.num_channels = 2; + config_.filterbank.lower_band_limit = 8.0; + config_.filterbank.upper_band_limit = 450.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 = true; + 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 = true; + config_.log_scale.scale_shift = 6; + } + + struct FrontendConfig config_; +}; + +} // namespace + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(FrontendTest_CheckOutputValues) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FrontendTestConfig config; + struct FrontendState state; + TF_LITE_MICRO_EXPECT(FrontendPopulateState(error_reporter, &config.config_, + &state, kSampleRate)); + size_t num_samples_read; + + struct FrontendOutput output = FrontendProcessSamples( + &state, kFakeAudioData, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]), &num_samples_read); + + const uint16_t expected[] = {479, 425}; + TF_LITE_MICRO_EXPECT_EQ(output.size, sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < output.size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(output.values[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(FrontendTest_CheckConsecutiveWindow) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FrontendTestConfig config; + struct FrontendState state; + TF_LITE_MICRO_EXPECT(FrontendPopulateState(error_reporter, &config.config_, + &state, kSampleRate)); + size_t num_samples_read; + + FrontendProcessSamples(&state, kFakeAudioData, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]), + &num_samples_read); + struct FrontendOutput output = FrontendProcessSamples( + &state, kFakeAudioData + kWindowSamples, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]) - kWindowSamples, + &num_samples_read); + + const int16_t expected[] = {436, 378}; + TF_LITE_MICRO_EXPECT_EQ(output.size, sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < output.size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(output.values[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(FrontendTest_CheckNotEnoughSamples) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + FrontendTestConfig config; + struct FrontendState state; + TF_LITE_MICRO_EXPECT(FrontendPopulateState(error_reporter, &config.config_, + &state, kSampleRate)); + size_t num_samples_read; + + FrontendProcessSamples(&state, kFakeAudioData, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]), + &num_samples_read); + FrontendProcessSamples( + &state, kFakeAudioData + kWindowSamples, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]) - kWindowSamples, + &num_samples_read); + struct FrontendOutput output = FrontendProcessSamples( + &state, kFakeAudioData + kWindowSamples + kStepSamples, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]) - kWindowSamples - + kStepSamples, + &num_samples_read); + + TF_LITE_MICRO_EXPECT_EQ(output.size, 0); + TF_LITE_MICRO_EXPECT_EQ(output.values, nullptr); +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.cc new file mode 100644 index 00000000000..220bc130fb9 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.cc @@ -0,0 +1,80 @@ +/* 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/micro/examples/micro_speech/micro_features/frontend_util.h" + +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/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(tflite::ErrorReporter* error_reporter, + const struct FrontendConfig* config, + struct FrontendState* state, int sample_rate) { + memset(state, 0, sizeof(*state)); + + if (!WindowPopulateState(error_reporter, &config->window, &state->window, + sample_rate)) { + error_reporter->Report("Failed to populate window state"); + return 0; + } + + if (!FftPopulateState(error_reporter, &state->fft, state->window.size)) { + error_reporter->Report("Failed to populate fft state"); + return 0; + } + FftInit(&state->fft); + + if (!FilterbankPopulateState(error_reporter, &config->filterbank, + &state->filterbank, sample_rate, + state->fft.fft_size / 2 + 1)) { + error_reporter->Report("Failed to populate filterbank state"); + return 0; + } + + if (!NoiseReductionPopulateState(error_reporter, &config->noise_reduction, + &state->noise_reduction, + state->filterbank.num_channels)) { + error_reporter->Report("Failed to populate noise reduction state"); + return 0; + } + + int input_correction_bits = + MostSignificantBit32(state->fft.fft_size) - 1 - (kFilterbankBits / 2); + if (!PcanGainControlPopulateState( + error_reporter, &config->pcan_gain_control, &state->pcan_gain_control, + state->noise_reduction.estimate, state->filterbank.num_channels, + state->noise_reduction.smoothing_bits, input_correction_bits)) { + error_reporter->Report("Failed to populate pcan gain control state"); + return 0; + } + + if (!LogScalePopulateState(error_reporter, &config->log_scale, + &state->log_scale)) { + error_reporter->Report("Failed to populate log scale state"); + return 0; + } + + FrontendReset(state); + + // All good, return a true value. + return 1; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.h new file mode 100644 index 00000000000..f7267644ae0 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.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_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FRONTEND_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FRONTEND_UTIL_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/fft_util.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/filterbank_util.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" + +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); + +// Prepares any buffers. +int FrontendPopulateState(tflite::ErrorReporter* error_reporter, + const struct FrontendConfig* config, + struct FrontendState* state, int sample_rate); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_FRONTEND_UTIL_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.cc new file mode 100644 index 00000000000..c651caad8c6 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.cc @@ -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/micro/examples/micro_speech/micro_features/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/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.h new file mode 100644 index 00000000000..d5ed9339bd0 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.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_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_LOG_LUT_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_LOG_LUT_H_ + +#include + +// 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[]; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_LOG_LUT_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.cc new file mode 100644 index 00000000000..f85e9c1a2f5 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.cc @@ -0,0 +1,84 @@ +/* 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/micro/examples/micro_speech/micro_features/log_scale.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/bits.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/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 = + ((static_cast(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 = + ((static_cast(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 = reinterpret_cast(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/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.h new file mode 100644 index 00000000000..d90b87fb6d6 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.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_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_LOG_SCALE_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_LOG_SCALE_H_ + +#include +#include + +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); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_LOG_SCALE_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_test.cc new file mode 100644 index 00000000000..d5b23323a27 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_test.cc @@ -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. +==============================================================================*/ +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.h" + +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +namespace { + +const int kScaleShift = 6; +const int kCorrectionBits = -1; + +} // namespace + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(LogScaleTest_CheckOutputValues) { + struct LogScaleState state; + state.enable_log = true; + state.scale_shift = kScaleShift; + + uint32_t fake_signal[] = {3578, 1533}; + uint16_t* output = LogScaleApply(&state, fake_signal, + sizeof(fake_signal) / sizeof(fake_signal[0]), + kCorrectionBits); + + const uint16_t expected[] = {479, 425}; + int i; + for (i = 0; i < sizeof(expected) / sizeof(expected[0]); ++i) { + TF_LITE_MICRO_EXPECT_EQ(output[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(LogScaleTest_CheckOutputValuesNoLog) { + struct LogScaleState state; + state.enable_log = false; + state.scale_shift = kScaleShift; + + uint32_t fake_signal[] = {85964, 45998}; + uint16_t* output = LogScaleApply(&state, fake_signal, + sizeof(fake_signal) / sizeof(fake_signal[0]), + kCorrectionBits); + + const uint16_t expected[] = {65535, 45998}; + int i; + for (i = 0; i < sizeof(expected) / sizeof(expected[0]); ++i) { + TF_LITE_MICRO_EXPECT_EQ(output[i], expected[i]); + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.cc new file mode 100644 index 00000000000..09adc09c351 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.cc @@ -0,0 +1,28 @@ +/* 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/micro/examples/micro_speech/micro_features/log_scale_util.h" + +void LogScaleFillConfigWithDefaults(struct LogScaleConfig* config) { + config->enable_log = 1; + config->scale_shift = 6; +} + +int LogScalePopulateState(tflite::ErrorReporter* error_reporter, + const struct LogScaleConfig* config, + struct LogScaleState* state) { + state->enable_log = config->enable_log; + state->scale_shift = config->scale_shift; + return 1; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.h new file mode 100644 index 00000000000..3caf207f269 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale_util.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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_LOG_SCALE_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_LOG_SCALE_UTIL_H_ + +#include +#include + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" + +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(tflite::ErrorReporter* error_reporter, + const struct LogScaleConfig* config, + struct LogScaleState* state); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_LOG_SCALE_UTIL_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.cc new file mode 100644 index 00000000000..6657c6f3205 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.cc @@ -0,0 +1,99 @@ +/* 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/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.h" + +#include +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/frontend_util.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" + +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(error_reporter, &config, &g_micro_features_state, + kAudioSampleFrequency)) { + error_reporter->Report("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, uint8_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 + 160; + } + FrontendOutput frontend_output = FrontendProcessSamples( + &g_micro_features_state, frontend_input, input_size, num_samples_read); + + for (int i = 0; i < frontend_output.size; ++i) { + // These scaling values are derived from those used in input_data.py in the + // training pipeline. + constexpr int32_t value_scale = (10 * 255); + constexpr int32_t value_div = (256 * 26); + int32_t value = + ((frontend_output.values[i] * value_scale) + (value_div / 2)) / + value_div; + if (value < 0) { + value = 0; + } + if (value > 255) { + value = 255; + } + output[i] = value; + } + + return kTfLiteOk; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.h new file mode 100644 index 00000000000..46fa55d62ff --- /dev/null +++ b/tensorflow/lite/experimental/micro/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_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_FEATURES_GENERATOR_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_FEATURES_GENERATOR_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/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, uint8_t* output, + size_t* num_samples_read); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_FEATURES_GENERATOR_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator_test.cc new file mode 100644 index 00000000000..2c2da7a799c --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_features_generator_test.cc @@ -0,0 +1,100 @@ +/* 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/experimental/micro/examples/micro_speech/micro_features/micro_features_generator.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +// This is a test-only API, not exposed in any public headers, so declare it. +void SetMicroFeaturesNoiseEstimates(const uint32_t* estimate_presets); + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(TestMicroFeaturesGeneratorYes) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, InitializeMicroFeatures(error_reporter)); + + // The micro features pipeline retains state from previous calls to help + // estimate the background noise. Unfortunately this makes it harder to + // exactly reproduce results in a test environment, so use a known snapshot + // of the parameters at the point that the golden feature values were + // created. + const uint32_t yes_estimate_presets[] = { + 1062898, 2644477, 1257642, 1864718, 412722, 725703, 395721, 474082, + 173046, 255856, 158966, 153736, 69181, 199100, 144493, 227740, + 110573, 164330, 79666, 144650, 122947, 476799, 398553, 497493, + 322152, 1140005, 566716, 690605, 308902, 347481, 109891, 170457, + 73901, 100975, 42963, 72325, 34183, 20207, 6640, 9468, + }; + SetMicroFeaturesNoiseEstimates(yes_estimate_presets); + + uint8_t yes_calculated_data[g_yes_feature_data_slice_size]; + size_t num_samples_read; + TfLiteStatus yes_status = GenerateMicroFeatures( + error_reporter, g_yes_30ms_sample_data, g_yes_30ms_sample_data_size, + g_yes_feature_data_slice_size, yes_calculated_data, &num_samples_read); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, yes_status); + + for (int i = 0; i < g_yes_feature_data_slice_size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(g_yes_feature_data_slice[i], + yes_calculated_data[i]); + if (g_yes_feature_data_slice[i] != yes_calculated_data[i]) { + error_reporter->Report("Expected value %d but found %d", + g_yes_feature_data_slice[i], + yes_calculated_data[i]); + } + } +} + +TF_LITE_MICRO_TEST(TestMicroFeaturesGeneratorNo) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, InitializeMicroFeatures(error_reporter)); + // As we did for the previous features, set known good noise state + // parameters. + const uint32_t no_estimate_presets[] = { + 2563964, 1909393, 559801, 538670, 203643, 175959, 75088, 139491, + 59691, 95307, 43865, 129263, 52517, 80058, 51330, 100731, + 76674, 76262, 15497, 22598, 13778, 21460, 8946, 17806, + 10023, 18810, 8002, 10842, 7578, 9983, 6267, 10759, + 8946, 18488, 9691, 39785, 9939, 17835, 9671, 18512, + }; + SetMicroFeaturesNoiseEstimates(no_estimate_presets); + + uint8_t no_calculated_data[g_no_feature_data_slice_size]; + size_t num_samples_read; + TfLiteStatus no_status = GenerateMicroFeatures( + error_reporter, g_no_30ms_sample_data, g_no_30ms_sample_data_size, + g_no_feature_data_slice_size, no_calculated_data, &num_samples_read); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, no_status); + + for (int i = 0; i < g_no_feature_data_slice_size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(g_no_feature_data_slice[i], no_calculated_data[i]); + if (g_no_feature_data_slice[i] != no_calculated_data[i]) { + error_reporter->Report("Expected value %d but found %d", + g_no_feature_data_slice[i], no_calculated_data[i]); + } + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.cc similarity index 95% rename from tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.cc index b9b8fb37b19..09f65ca24b3 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" const char* kCategoryLabels[kCategoryCount] = { "silence", diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h new file mode 100644 index 00000000000..b74a4d01ca4 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h @@ -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. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_MODEL_SETTINGS_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_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; + +// 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 kFeatureSliceSize = 40; +constexpr int kFeatureSliceCount = 49; +constexpr int kFeatureElementCount = (kFeatureSliceSize * kFeatureSliceCount); +constexpr int kFeatureSliceStrideMs = 20; +constexpr int kFeatureSliceDurationMs = 30; + +constexpr int kCategoryCount = 4; +constexpr int kSilenceIndex = 0; +constexpr int kUnknownIndex = 1; +extern const char* kCategoryLabels[kCategoryCount]; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_MICRO_MODEL_SETTINGS_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.cc new file mode 100644 index 00000000000..1dbb606e184 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.cc @@ -0,0 +1,24 @@ +/* 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. +==============================================================================*/ + +// See the header for documentation on the meaning of this data. + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.h" + +const uint8_t g_no_feature_data_slice[g_no_feature_data_slice_size] = { + 216, 195, 223, 211, 238, 223, 243, 215, 226, 204, 232, 211, 232, 213, + 240, 218, 235, 214, 238, 205, 207, 173, 149, 201, 215, 200, 230, 213, + 208, 195, 175, 151, 195, 175, 182, 163, 235, 217, 218, 190, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.h new file mode 100644 index 00000000000..72ea2bf6a23 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_feature_data_slice.h @@ -0,0 +1,29 @@ +/* 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 data was extracted from the larger feature data held in +// no_features_data.cc and consists of the 29th spectrogram slice of 43 values. +// This is the expected result of running the sample data in +// no_30ms_sample_data.cc through through the preprocessing pipeline. + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NO_FEATURE_DATA_SLICE_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NO_FEATURE_DATA_SLICE_H_ + +#include + +constexpr int g_no_feature_data_slice_size = 40; +extern const uint8_t g_no_feature_data_slice[]; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NO_FEATURE_DATA_SLICE_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.cc new file mode 100644 index 00000000000..865209b01df --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.cc @@ -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. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h" + +/* File automatically created by + * tensorflow/examples/speech_commands/wav_to_features.py \ + * --sample_rate=16000 \ + * --clip_duration_ms=1000 \ + * --window_size_ms=30 \ + * --window_stride_ms=20 \ + * --feature_bin_count=40 \ + * --quantize=1 \ + * --preprocess="micro" \ + * --input_wav="speech_commands_test_set_v0.02/no/f9643d42_nohash_4.wav" \ + * --output_c_file="/tmp/no_micro_features_data.cc" \ + */ + +const int g_no_micro_f9643d42_nohash_4_width = 40; +const int g_no_micro_f9643d42_nohash_4_height = 49; +const unsigned char g_no_micro_f9643d42_nohash_4_data[] = { + 230, 205, 191, 203, 202, 181, 180, 194, 205, 187, 183, 197, 203, 198, 196, + 186, 202, 159, 151, 126, 110, 138, 141, 142, 137, 148, 133, 120, 110, 126, + 117, 110, 117, 116, 137, 134, 95, 116, 123, 110, 184, 144, 183, 189, 197, + 172, 188, 164, 194, 179, 175, 174, 182, 173, 184, 174, 200, 145, 154, 148, + 147, 135, 143, 122, 127, 138, 116, 99, 122, 105, 110, 125, 127, 133, 131, + 123, 116, 119, 127, 114, 193, 176, 185, 170, 175, 146, 166, 167, 185, 185, + 185, 183, 195, 185, 176, 178, 197, 155, 137, 144, 164, 132, 153, 132, 138, + 137, 134, 95, 120, 116, 131, 122, 99, 120, 120, 110, 116, 110, 126, 127, + 128, 159, 187, 119, 178, 187, 197, 167, 199, 184, 180, 165, 194, 176, 144, + 134, 187, 136, 142, 134, 145, 132, 145, 105, 119, 123, 125, 116, 125, 102, + 129, 138, 130, 99, 99, 90, 120, 123, 134, 95, 194, 172, 187, 123, 191, + 179, 195, 182, 201, 137, 167, 142, 185, 161, 187, 146, 167, 152, 154, 107, + 152, 112, 134, 144, 117, 116, 105, 85, 105, 105, 99, 90, 123, 112, 112, + 68, 107, 105, 117, 99, 116, 143, 139, 90, 154, 142, 188, 172, 178, 135, + 175, 149, 177, 110, 173, 160, 169, 162, 173, 119, 132, 110, 85, 85, 117, + 129, 117, 112, 117, 51, 112, 95, 139, 102, 105, 90, 128, 119, 112, 99, + 170, 168, 195, 152, 174, 173, 180, 0, 157, 130, 169, 149, 149, 123, 170, + 130, 170, 133, 159, 102, 134, 90, 85, 105, 126, 119, 130, 90, 78, 68, + 127, 120, 95, 51, 122, 110, 112, 78, 116, 95, 180, 135, 179, 146, 179, + 162, 197, 153, 172, 135, 154, 0, 149, 95, 145, 114, 166, 0, 114, 110, + 145, 107, 114, 90, 136, 68, 95, 95, 95, 85, 116, 99, 116, 0, 95, + 68, 102, 51, 102, 78, 185, 157, 138, 158, 180, 117, 173, 142, 145, 117, + 169, 130, 159, 99, 138, 123, 169, 90, 78, 0, 123, 85, 107, 51, 114, + 102, 95, 0, 116, 85, 119, 95, 95, 68, 85, 51, 116, 68, 102, 78, + 167, 105, 164, 163, 178, 126, 164, 154, 154, 51, 177, 120, 156, 85, 134, + 139, 168, 90, 161, 102, 114, 116, 122, 95, 112, 102, 107, 51, 114, 85, + 119, 78, 114, 90, 102, 51, 102, 51, 114, 99, 177, 68, 152, 102, 184, + 166, 179, 129, 177, 129, 180, 110, 158, 105, 139, 0, 145, 85, 148, 102, + 117, 102, 116, 0, 78, 68, 90, 51, 107, 85, 78, 0, 51, 0, 51, + 0, 95, 51, 107, 68, 180, 117, 90, 0, 138, 0, 187, 146, 119, 140, + 164, 90, 136, 0, 131, 51, 159, 99, 141, 138, 116, 51, 90, 51, 90, + 68, 105, 0, 85, 78, 112, 51, 122, 95, 128, 68, 85, 0, 112, 68, + 147, 126, 178, 146, 171, 130, 190, 147, 188, 123, 170, 78, 132, 0, 130, + 125, 159, 95, 102, 0, 110, 0, 95, 85, 120, 68, 78, 51, 99, 51, + 105, 0, 112, 102, 105, 68, 90, 51, 90, 0, 127, 95, 166, 175, 187, + 133, 135, 0, 171, 139, 132, 128, 140, 51, 126, 107, 161, 0, 95, 51, + 119, 0, 114, 0, 95, 110, 116, 51, 112, 0, 90, 0, 116, 51, 68, + 0, 105, 68, 105, 0, 164, 78, 173, 0, 194, 166, 145, 114, 116, 51, + 107, 122, 151, 0, 156, 102, 148, 51, 122, 95, 129, 0, 85, 0, 127, + 78, 90, 0, 78, 0, 95, 0, 110, 0, 68, 119, 120, 68, 68, 0, + 122, 99, 147, 127, 200, 167, 85, 114, 161, 85, 161, 125, 143, 99, 156, + 85, 147, 68, 99, 0, 107, 102, 132, 51, 112, 68, 95, 78, 99, 0, + 68, 0, 51, 0, 90, 78, 128, 51, 95, 0, 166, 136, 174, 138, 189, + 144, 130, 129, 138, 134, 132, 120, 134, 0, 51, 78, 147, 51, 51, 0, + 51, 0, 78, 0, 68, 68, 95, 78, 90, 0, 0, 0, 68, 0, 90, + 68, 110, 0, 95, 51, 165, 151, 157, 0, 0, 0, 112, 0, 112, 95, + 149, 107, 119, 68, 126, 68, 138, 0, 78, 0, 78, 0, 99, 51, 112, + 0, 102, 0, 78, 51, 85, 0, 0, 0, 78, 0, 95, 0, 95, 78, + 105, 0, 152, 0, 0, 51, 132, 105, 159, 0, 129, 102, 114, 0, 138, + 51, 123, 0, 129, 78, 119, 51, 51, 51, 105, 0, 78, 85, 95, 0, + 85, 0, 0, 0, 85, 0, 78, 0, 0, 0, 172, 142, 141, 0, 137, + 0, 148, 128, 157, 120, 146, 120, 120, 0, 95, 78, 141, 68, 68, 0, + 68, 0, 90, 0, 85, 0, 107, 0, 78, 0, 85, 51, 102, 0, 68, + 78, 68, 0, 51, 0, 125, 0, 141, 51, 102, 138, 175, 51, 120, 51, + 173, 85, 116, 141, 164, 68, 150, 123, 133, 51, 114, 0, 117, 68, 150, + 51, 116, 68, 78, 0, 68, 0, 68, 0, 85, 0, 78, 0, 51, 78, + 155, 90, 161, 0, 132, 99, 123, 78, 107, 0, 134, 90, 95, 0, 78, + 0, 162, 143, 85, 0, 107, 78, 125, 90, 90, 51, 51, 0, 85, 0, + 0, 0, 132, 102, 102, 154, 128, 0, 99, 68, 162, 102, 151, 0, 99, + 51, 147, 141, 156, 0, 112, 120, 158, 127, 145, 139, 187, 171, 135, 138, + 146, 0, 95, 68, 127, 0, 85, 0, 105, 0, 0, 0, 187, 170, 162, + 188, 165, 51, 51, 78, 243, 215, 225, 196, 205, 181, 205, 168, 176, 134, + 157, 110, 126, 114, 133, 139, 193, 163, 159, 116, 160, 126, 122, 127, 171, + 99, 114, 68, 123, 85, 90, 0, 157, 146, 166, 179, 136, 0, 116, 90, + 242, 219, 240, 204, 216, 164, 188, 171, 176, 164, 154, 158, 190, 157, 190, + 141, 182, 177, 169, 128, 172, 145, 105, 129, 157, 90, 78, 51, 119, 68, + 137, 68, 116, 78, 141, 132, 151, 122, 156, 140, 234, 206, 229, 201, 216, + 174, 191, 144, 162, 85, 122, 157, 194, 167, 204, 149, 180, 166, 166, 139, + 122, 133, 156, 126, 145, 85, 128, 0, 99, 51, 145, 0, 126, 51, 166, + 162, 166, 162, 177, 157, 228, 198, 221, 197, 214, 177, 173, 166, 173, 139, + 185, 191, 202, 163, 205, 172, 206, 189, 135, 68, 166, 134, 149, 134, 135, + 90, 127, 107, 175, 90, 136, 117, 135, 140, 172, 167, 166, 149, 177, 152, + 221, 191, 215, 194, 211, 0, 156, 147, 182, 178, 208, 163, 190, 157, 208, + 200, 195, 164, 179, 154, 181, 150, 143, 99, 132, 137, 185, 143, 163, 85, + 51, 107, 132, 134, 164, 127, 167, 159, 175, 141, 216, 195, 223, 211, 238, + 223, 243, 215, 226, 204, 232, 211, 232, 213, 240, 218, 235, 214, 238, 205, + 207, 173, 149, 201, 215, 200, 230, 213, 208, 195, 175, 151, 195, 175, 182, + 163, 235, 217, 218, 190, 211, 191, 215, 191, 217, 220, 241, 215, 229, 206, + 236, 210, 227, 216, 236, 188, 183, 149, 202, 189, 208, 172, 191, 201, 220, + 193, 221, 207, 216, 208, 201, 131, 170, 187, 229, 197, 211, 194, 226, 201, + 205, 184, 206, 177, 221, 210, 226, 184, 204, 197, 218, 198, 212, 209, 213, + 141, 172, 110, 175, 167, 180, 156, 213, 188, 192, 179, 213, 205, 204, 174, + 200, 147, 162, 181, 203, 167, 198, 187, 210, 164, 196, 169, 189, 168, 224, + 198, 213, 204, 198, 195, 230, 211, 221, 197, 208, 0, 0, 0, 85, 90, + 167, 130, 175, 173, 203, 164, 193, 144, 170, 145, 185, 148, 154, 139, 198, + 159, 180, 171, 216, 174, 178, 161, 166, 136, 216, 184, 215, 197, 199, 190, + 228, 195, 208, 51, 117, 0, 0, 0, 0, 0, 140, 51, 135, 154, 188, + 155, 168, 0, 90, 0, 156, 85, 110, 0, 174, 90, 172, 154, 179, 99, + 142, 166, 179, 157, 177, 95, 192, 142, 204, 198, 217, 147, 173, 0, 112, + 0, 0, 0, 0, 0, 0, 0, 110, 0, 107, 0, 160, 0, 148, 95, + 172, 0, 0, 0, 116, 0, 122, 114, 170, 0, 0, 0, 0, 0, 179, + 110, 196, 85, 205, 183, 169, 0, 99, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 141, 0, 112, 0, 0, 0, 134, 0, 0, 0, 0, + 0, 0, 0, 139, 0, 0, 0, 0, 112, 186, 78, 163, 0, 169, 128, + 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, + 0, 105, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 95, 0, + 0, 0, 0, 0, 0, 0, 119, 0, 164, 78, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 68, + 117, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, + 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h new file mode 100644 index 00000000000..178323eeba6 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h @@ -0,0 +1,23 @@ +/* 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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NO_MICRO_FEATURES_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NO_MICRO_FEATURES_DATA_H_ + +extern const int g_no_micro_f9643d42_nohash_4_width; +extern const int g_no_micro_f9643d42_nohash_4_height; +extern const unsigned char g_no_micro_f9643d42_nohash_4_data[]; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NO_MICRO_FEATURES_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.cc new file mode 100644 index 00000000000..3b3aa19cda5 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.cc @@ -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/micro/examples/micro_speech/micro_features/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 = + ((static_cast(signal_scaled_up) * smoothing) + + (static_cast(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 = + (static_cast(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/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.h new file mode 100644 index 00000000000..699144345d5 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NOISE_REDUCTION_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NOISE_REDUCTION_H_ + +#define kNoiseReductionBits 14 + +#include +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" + +struct NoiseReductionState { + int smoothing_bits; + uint16_t even_smoothing; + uint16_t odd_smoothing; + uint16_t min_signal_remaining; + int num_channels; + uint32_t estimate[kFeatureSliceSize]; +}; + +// 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); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NOISE_REDUCTION_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_test.cc new file mode 100644 index 00000000000..de7181d710b --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_test.cc @@ -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/micro/examples/micro_speech/micro_features/noise_reduction.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.h" + +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +namespace { + +const int kNumChannels = 2; + +// Test noise reduction using default config values. +class NoiseReductionTestConfig { + public: + NoiseReductionTestConfig() { + config_.smoothing_bits = 10; + config_.even_smoothing = 0.025; + config_.odd_smoothing = 0.06; + config_.min_signal_remaining = 0.05; + } + + struct NoiseReductionConfig config_; +}; + +} // namespace + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(NoiseReductionTest_TestNoiseReductionEstimate) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + NoiseReductionTestConfig config; + struct NoiseReductionState state; + TF_LITE_MICRO_EXPECT(NoiseReductionPopulateState( + error_reporter, &config.config_, &state, kNumChannels)); + + uint32_t signal[] = {247311, 508620}; + NoiseReductionApply(&state, signal); + + const uint32_t expected[] = {6321887, 31248341}; + TF_LITE_MICRO_EXPECT_EQ(state.num_channels, + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < state.num_channels; ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.estimate[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(NoiseReductionTest_TestNoiseReduction) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + NoiseReductionTestConfig config; + struct NoiseReductionState state; + TF_LITE_MICRO_EXPECT(NoiseReductionPopulateState( + error_reporter, &config.config_, &state, kNumChannels)); + + uint32_t signal[] = {247311, 508620}; + NoiseReductionApply(&state, signal); + + const uint32_t expected[] = {241137, 478104}; + TF_LITE_MICRO_EXPECT_EQ(state.num_channels, + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < state.num_channels; ++i) { + TF_LITE_MICRO_EXPECT_EQ(signal[i], expected[i]); + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.cc new file mode 100644 index 00000000000..42a5c2136f2 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.cc @@ -0,0 +1,42 @@ +/* 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/micro/examples/micro_speech/micro_features/noise_reduction_util.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h" + +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(tflite::ErrorReporter* error_reporter, + 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; + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + state->estimate, (state->num_channels * sizeof(*state->estimate))); + for (int i = 0; i < state->num_channels; ++i) { + state->estimate[i] = 0; + } + return 1; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.h new file mode 100644 index 00000000000..60f9de5067c --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction_util.h @@ -0,0 +1,42 @@ +/* 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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NOISE_REDUCTION_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NOISE_REDUCTION_UTIL_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/noise_reduction.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" + +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); + +// Prepares any buffers. +int NoiseReductionPopulateState(tflite::ErrorReporter* error_reporter, + const struct NoiseReductionConfig* config, + struct NoiseReductionState* state, + int num_channels); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_NOISE_REDUCTION_UTIL_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.cc new file mode 100644 index 00000000000..50656758d72 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.cc @@ -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. +==============================================================================*/ +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/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 = (static_cast(lut[2]) * frac) >> 5; + result += (static_cast(lut[1])) << 5; + result *= frac; + result = (result + (1 << 14)) >> 15; + result += lut[0]; + return static_cast(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 = + (static_cast(signal[i]) * gain) >> state->snr_shift; + signal[i] = PcanShrink(snr); + } +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.h new file mode 100644 index 00000000000..06d6fc99038 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.h @@ -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. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_PCAN_GAIN_CONTROL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_PCAN_GAIN_CONTROL_H_ + +#include +#include + +#define kPcanSnrBits 12 +#define kPcanOutputBits 6 + +#define kWideDynamicFunctionBits 32 +#define kWideDynamicFunctionLUTSize (4 * kWideDynamicFunctionBits - 3) + +struct PcanGainControlState { + int enable_pcan; + uint32_t* noise_estimate; + int num_channels; + int16_t gain_lut[kWideDynamicFunctionLUTSize]; + 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); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_PCAN_GAIN_CONTROL_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_test.cc new file mode 100644 index 00000000000..7dee66746f3 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_test.cc @@ -0,0 +1,66 @@ +/* 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/micro/examples/micro_speech/micro_features/pcan_gain_control.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.h" + +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +namespace { + +const int kNumChannels = 2; +const int kSmoothingBits = 10; +const int kCorrectionBits = -1; + +// Test pcan auto gain control using default config values. +class PcanGainControlTestConfig { + public: + PcanGainControlTestConfig() { + config_.enable_pcan = 1; + config_.strength = 0.95; + config_.offset = 80.0; + config_.gain_bits = 21; + } + + struct PcanGainControlConfig config_; +}; + +} // namespace + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(PcanGainControlTest_TestPcanGainControl) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + uint32_t estimate[] = {6321887, 31248341}; + PcanGainControlTestConfig config; + struct PcanGainControlState state; + TF_LITE_MICRO_EXPECT(PcanGainControlPopulateState( + error_reporter, &config.config_, &state, estimate, kNumChannels, + kSmoothingBits, kCorrectionBits)); + + uint32_t signal[] = {241137, 478104}; + PcanGainControlApply(&state, signal); + + const uint32_t expected[] = {3578, 1533}; + TF_LITE_MICRO_EXPECT_EQ(state.num_channels, + sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < state.num_channels; ++i) { + TF_LITE_MICRO_EXPECT_EQ(signal[i], expected[i]); + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.cc new file mode 100644 index 00000000000..e7867ac6284 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.cc @@ -0,0 +1,87 @@ +/* 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/micro/examples/micro_speech/micro_features/pcan_gain_control_util.h" + +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h" + +#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 = + (static_cast(x)) / (static_cast(1) << input_bits); + const float gain_as_float = + (static_cast(1) << config->gain_bits) * + powf(x_as_float + config->offset, -config->strength); + + if (gain_as_float > kint16max) { + return kint16max; + } + return static_cast(gain_as_float + 0.5f); +} + +int PcanGainControlPopulateState(tflite::ErrorReporter* error_reporter, + 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; + STATIC_ALLOC_ENSURE_ARRAY_SIZE( + state->gain_lut, (kWideDynamicFunctionLUTSize * sizeof(int16_t))); + 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); + int16_t* temp_gain_lut = state->gain_lut - 6; + int interval; + for (interval = 2; interval <= kWideDynamicFunctionBits; ++interval) { + const uint32_t x0 = static_cast(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 = static_cast(y1) - y0; + const int32_t diff2 = static_cast(y2) - y0; + const int32_t a1 = 4 * diff1 - diff2; + const int32_t a2 = diff2 - a1; + + temp_gain_lut[4 * interval] = y0; + temp_gain_lut[4 * interval + 1] = static_cast(a1); + temp_gain_lut[4 * interval + 2] = static_cast(a2); + } + return 1; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.h new file mode 100644 index 00000000000..4cc1de7bb25 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control_util.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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_PCAN_GAIN_CONTROL_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_PCAN_GAIN_CONTROL_UTIL_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/pcan_gain_control.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" + +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(tflite::ErrorReporter* error_reporter, + 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); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_PCAN_GAIN_CONTROL_UTIL_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h new file mode 100644 index 00000000000..e2af862de75 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.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_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_STATIC_ALLOC_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_STATIC_ALLOC_H_ + +// Checks to ensure that the C-style array passed in has a compile-time size of +// at least the number of bytes requested. This doesn't work with raw pointers +// since sizeof() doesn't know their actual length, so only use this to check +// statically-allocated arrays with known sizes. +#define STATIC_ALLOC_ENSURE_ARRAY_SIZE(A, N) \ + do { \ + if (sizeof(A) < (N)) { \ + error_reporter->Report(#A " too small (%d bytes, wanted %d) at %s:%d", \ + sizeof(A), (N), __FILE__, __LINE__); \ + return 0; \ + } \ + } while (0) + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_STATIC_ALLOC_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.cc new file mode 100644 index 00000000000..57a32c3595d --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.cc @@ -0,0 +1,1541 @@ +/* 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. +==============================================================================*/ + +// Automatically created from a TensorFlow Lite flatbuffer using the command: +// xxd -i tiny_conv.tflite > tiny_conv_simple_features_model_data.cc +// See the README for a full description of the creation process. + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.h" + +const unsigned char g_tiny_conv_micro_features_model_data[] = { + 0x18, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x00, 0x00, 0x0e, 0x00, + 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xd0, 0x46, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xb4, 0x41, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x54, 0x4f, 0x43, 0x4f, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, + 0x65, 0x64, 0x2e, 0x00, 0x09, 0x00, 0x00, 0x00, 0x94, 0x41, 0x00, 0x00, + 0x74, 0x41, 0x00, 0x00, 0x44, 0x41, 0x00, 0x00, 0xb4, 0x3e, 0x00, 0x00, + 0xac, 0x3e, 0x00, 0x00, 0xa4, 0x3e, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf0, 0xb9, 0xff, 0xff, + 0xf4, 0xb9, 0xff, 0xff, 0x52, 0xba, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x80, 0x3e, 0x00, 0x00, 0x68, 0x95, 0x91, 0x7d, 0x9b, 0x85, 0x85, 0x81, + 0x77, 0x85, 0x99, 0x89, 0x7e, 0x8a, 0x85, 0x92, 0xa5, 0x7e, 0x93, 0x97, + 0x97, 0x91, 0xa3, 0x97, 0x88, 0x8b, 0xa6, 0x71, 0x77, 0x85, 0x95, 0x86, + 0x6b, 0x93, 0xcb, 0x96, 0x7a, 0x9a, 0x7f, 0x85, 0x7a, 0x8e, 0xac, 0x98, + 0x6d, 0x9d, 0x9b, 0x70, 0x9a, 0x90, 0xba, 0x99, 0x7b, 0x93, 0x6e, 0x68, + 0x75, 0x86, 0xc4, 0x8b, 0x66, 0x5d, 0x96, 0x7f, 0x92, 0x91, 0xb6, 0x7b, + 0x96, 0x95, 0x9a, 0x77, 0x9a, 0x96, 0xce, 0x80, 0x88, 0x65, 0x8e, 0x80, + 0x88, 0x85, 0xb7, 0x9c, 0x7b, 0x93, 0x9d, 0x95, 0x83, 0x92, 0xd0, 0x7e, + 0x68, 0x88, 0x6c, 0x78, 0x98, 0x81, 0xac, 0x95, 0x9e, 0x98, 0xa2, 0x99, + 0x8d, 0x7d, 0xb8, 0x81, 0x6e, 0x68, 0xa1, 0x81, 0x9d, 0x99, 0xb4, 0x7d, + 0x92, 0x86, 0x9d, 0x93, 0xa3, 0xb0, 0xd6, 0x79, 0x93, 0x76, 0x8d, 0x84, + 0x91, 0x9d, 0xbe, 0x94, 0xb0, 0x70, 0x84, 0x80, 0x85, 0x99, 0x9e, 0xa2, + 0x86, 0x8a, 0x7a, 0x76, 0x91, 0x8d, 0xa6, 0x76, 0x8d, 0x82, 0x98, 0x8c, + 0x92, 0x8f, 0x8c, 0xb3, 0x78, 0x75, 0xa5, 0x88, 0x73, 0x8c, 0x91, 0x7c, + 0x82, 0x7d, 0x93, 0x9e, 0x8b, 0x97, 0x7c, 0x90, 0x84, 0x95, 0x7e, 0x9e, + 0xa4, 0x52, 0x8a, 0xb4, 0x97, 0x65, 0x7d, 0xb6, 0x83, 0x7d, 0x99, 0x80, + 0x97, 0x85, 0x96, 0x5f, 0x8e, 0x87, 0x95, 0x6d, 0x76, 0x84, 0x97, 0x8c, + 0x66, 0x97, 0xae, 0x6b, 0x93, 0xb3, 0xa8, 0x8b, 0xa1, 0x79, 0xa3, 0x94, + 0x7e, 0xa8, 0x8d, 0xad, 0x78, 0x82, 0xa2, 0x7b, 0x90, 0xa4, 0x7d, 0xb3, + 0xa0, 0x7b, 0x94, 0x85, 0x9a, 0x8d, 0x76, 0x82, 0x65, 0x73, 0xab, 0xa4, + 0xaa, 0x74, 0x93, 0x9c, 0x83, 0x66, 0xbf, 0x7a, 0xaa, 0x81, 0x92, 0x89, + 0x7e, 0x88, 0xa6, 0x66, 0xaf, 0x92, 0x9f, 0x97, 0x6c, 0x89, 0x9c, 0x74, + 0x7e, 0x82, 0x8e, 0x88, 0xb2, 0x85, 0xba, 0x96, 0x90, 0x78, 0x8d, 0xa7, + 0x9e, 0x87, 0xbc, 0x7f, 0xb2, 0x8b, 0x77, 0x9b, 0xab, 0x8f, 0xa4, 0x7d, + 0x6f, 0x77, 0x8c, 0x98, 0x6f, 0x89, 0xb1, 0x9f, 0xa7, 0x94, 0x7d, 0xae, + 0x88, 0x8a, 0xa9, 0x75, 0x7d, 0x7c, 0x88, 0x99, 0x90, 0x9d, 0x97, 0xa7, + 0x8d, 0x7f, 0x73, 0xa1, 0xa3, 0x87, 0xa9, 0x92, 0x98, 0x7e, 0x9c, 0x88, + 0x73, 0x6b, 0x78, 0x8e, 0x7d, 0x86, 0x6c, 0x7c, 0x92, 0x40, 0x86, 0xa7, + 0x65, 0x93, 0x67, 0x91, 0x67, 0x71, 0x6c, 0xa8, 0x81, 0x70, 0x8e, 0xa8, + 0x7b, 0x63, 0x89, 0x76, 0x69, 0x90, 0x73, 0x5e, 0x92, 0x78, 0x7e, 0x9d, + 0x87, 0x86, 0x89, 0x64, 0x66, 0xa9, 0x92, 0x8d, 0x72, 0x7c, 0x63, 0x7f, + 0x94, 0x5c, 0x92, 0x89, 0x87, 0x9d, 0x8b, 0x75, 0x93, 0x8c, 0x94, 0x68, + 0x97, 0x87, 0x78, 0x7d, 0x7f, 0x84, 0x84, 0x77, 0x6b, 0x8e, 0x83, 0xab, + 0x7e, 0x62, 0x90, 0x83, 0x8e, 0x71, 0x7e, 0x9b, 0x96, 0x6d, 0x83, 0x6a, + 0x76, 0x68, 0x71, 0x90, 0x98, 0x90, 0x9b, 0x68, 0x89, 0x89, 0x95, 0x85, + 0x6e, 0x75, 0x8e, 0x95, 0x83, 0x7a, 0x91, 0x7f, 0x8b, 0x71, 0x90, 0x7d, + 0xad, 0x91, 0x6f, 0x74, 0x98, 0x8a, 0xb0, 0xa8, 0x80, 0xa3, 0x8e, 0x7c, + 0xa5, 0x67, 0xa4, 0x66, 0xa9, 0x7b, 0x85, 0x9d, 0x88, 0xab, 0x7d, 0x81, + 0x6e, 0x7f, 0x8f, 0x97, 0x97, 0x84, 0x89, 0x74, 0x9d, 0x5f, 0x9c, 0x88, + 0x6f, 0x74, 0x96, 0x9e, 0x7e, 0x7e, 0xa4, 0x85, 0x94, 0x91, 0xaf, 0x99, + 0x7a, 0xaa, 0x8c, 0x92, 0x85, 0x9d, 0x6c, 0x79, 0x57, 0x7a, 0x80, 0x84, + 0x79, 0x79, 0x74, 0xa5, 0x55, 0xab, 0x73, 0x8c, 0x72, 0x9d, 0x72, 0xa9, + 0x90, 0x73, 0x8f, 0xa0, 0x89, 0x6d, 0x68, 0x66, 0x61, 0x6f, 0x57, 0x7d, + 0x66, 0x8c, 0x65, 0x87, 0x62, 0x76, 0x83, 0x77, 0x89, 0xa4, 0x73, 0x89, + 0x7f, 0x70, 0x79, 0x6b, 0x86, 0x6f, 0x8d, 0x96, 0x65, 0x89, 0x66, 0x53, + 0x73, 0xae, 0x6a, 0x72, 0x88, 0x97, 0x7a, 0x7f, 0x5d, 0xa1, 0x86, 0x88, + 0x5f, 0x9f, 0x9b, 0x8a, 0x74, 0x9a, 0x7a, 0x7e, 0x8b, 0x71, 0x58, 0x74, + 0x8f, 0x9b, 0x9b, 0x8d, 0x6b, 0x83, 0x60, 0x7f, 0x75, 0x91, 0x79, 0x93, + 0x7a, 0x92, 0x8c, 0x7e, 0x7a, 0x95, 0x84, 0x69, 0x8f, 0x8c, 0x7c, 0x6e, + 0x8b, 0x87, 0x82, 0x62, 0xa6, 0x97, 0x91, 0x65, 0xa2, 0xa4, 0x9b, 0x8b, + 0x85, 0xa4, 0x84, 0x7b, 0x67, 0x93, 0x96, 0x84, 0x85, 0x75, 0x6d, 0x9e, + 0x80, 0x80, 0x73, 0x8c, 0x81, 0x70, 0x8a, 0x68, 0x9c, 0x8e, 0x63, 0x91, + 0x89, 0x79, 0x8d, 0x79, 0xa4, 0x9a, 0x96, 0xa0, 0x83, 0x63, 0x88, 0x8f, + 0x76, 0xb4, 0xa8, 0x8e, 0x68, 0x8d, 0x8e, 0x95, 0x78, 0xae, 0x5d, 0x89, + 0x66, 0x7e, 0x7b, 0x8a, 0x75, 0x86, 0x71, 0x97, 0x6d, 0xb3, 0x67, 0x76, + 0x82, 0x7d, 0x70, 0x79, 0x8a, 0x9c, 0x82, 0xa7, 0x82, 0xab, 0x58, 0x86, + 0x5c, 0x70, 0x8c, 0x71, 0x61, 0xa6, 0x74, 0xa8, 0x65, 0x78, 0x72, 0x9d, + 0x6c, 0x92, 0x70, 0x88, 0x88, 0x79, 0x96, 0x6f, 0x68, 0xa4, 0x7a, 0x7b, + 0x96, 0xac, 0x6d, 0x76, 0x6a, 0xab, 0x82, 0x7d, 0x71, 0x8d, 0x6b, 0x81, + 0x6c, 0x9d, 0x71, 0x59, 0x5c, 0x71, 0x77, 0x6d, 0x6a, 0x96, 0x76, 0x69, + 0x80, 0x83, 0x88, 0x70, 0x97, 0xb4, 0x8a, 0x6c, 0xa5, 0x6e, 0x64, 0x75, + 0x73, 0xa2, 0x7f, 0x97, 0x9e, 0x75, 0x8f, 0x86, 0x68, 0xbb, 0x6b, 0x86, + 0x8d, 0x80, 0x8e, 0x58, 0x6d, 0xb2, 0x76, 0x99, 0x8f, 0x70, 0x6c, 0x86, + 0x78, 0x9e, 0x91, 0x90, 0xa2, 0x7c, 0x8c, 0x81, 0x80, 0xb4, 0x77, 0x7a, + 0x8c, 0x5f, 0x85, 0x56, 0x7a, 0x93, 0x6b, 0x5c, 0x74, 0x59, 0x7e, 0x86, + 0x8c, 0xae, 0x76, 0x7d, 0x76, 0x7e, 0x81, 0x5f, 0x81, 0x8e, 0x7b, 0x90, + 0xaa, 0x99, 0x79, 0x89, 0x93, 0xbc, 0x86, 0x91, 0xa2, 0x88, 0x79, 0x82, + 0x80, 0xb6, 0x4a, 0x93, 0x7b, 0x89, 0x75, 0x8d, 0x7a, 0x8d, 0x66, 0x7c, + 0x81, 0x9f, 0x6e, 0x86, 0x4d, 0x82, 0x66, 0x88, 0x73, 0x89, 0x7d, 0xac, + 0x89, 0x9f, 0x58, 0x7f, 0x6b, 0x8c, 0x6a, 0x82, 0x59, 0xb8, 0x83, 0x67, + 0x8b, 0x8a, 0x84, 0x7b, 0x7f, 0xb5, 0x44, 0x57, 0x5a, 0x73, 0x8b, 0x6d, + 0x7c, 0x9e, 0x71, 0x72, 0x8d, 0x93, 0x80, 0x60, 0x7f, 0xc5, 0x69, 0x5c, + 0x67, 0x92, 0x6c, 0x75, 0x66, 0x8f, 0x91, 0x5a, 0x6c, 0x70, 0x90, 0x84, + 0x88, 0xab, 0x90, 0x66, 0x9c, 0x64, 0x6e, 0x68, 0x92, 0x9e, 0x89, 0x8d, + 0x82, 0x97, 0x77, 0x75, 0x7f, 0xa7, 0x91, 0x75, 0x8c, 0x89, 0xa4, 0x6b, + 0x98, 0x99, 0x80, 0x7d, 0x6b, 0x7f, 0x7d, 0x88, 0x79, 0xa1, 0x87, 0x90, + 0x81, 0x8e, 0x94, 0x96, 0x7d, 0xa8, 0x86, 0x84, 0x86, 0x79, 0x97, 0x6e, + 0xaa, 0x95, 0x8a, 0x9f, 0x8c, 0x72, 0x99, 0x77, 0x81, 0x94, 0x91, 0x9f, + 0x6e, 0x67, 0x87, 0x70, 0x7d, 0xad, 0x58, 0x7f, 0x6d, 0x96, 0x8e, 0x82, + 0x7d, 0xa6, 0x77, 0x99, 0x87, 0x95, 0x89, 0x7e, 0xa6, 0x9e, 0x86, 0xac, + 0x78, 0x9f, 0x9b, 0x85, 0x76, 0x99, 0x6a, 0x92, 0x66, 0x7b, 0x9a, 0x99, + 0x83, 0x8b, 0x57, 0x65, 0x75, 0x9f, 0xa6, 0x8a, 0x8d, 0x96, 0x6f, 0x80, + 0x65, 0x8f, 0x80, 0x9f, 0x82, 0x85, 0x55, 0x75, 0x5c, 0x84, 0x91, 0x86, + 0x76, 0x96, 0x5a, 0x6c, 0x62, 0x7b, 0x92, 0x88, 0x61, 0xca, 0x75, 0x66, + 0x70, 0x70, 0x8e, 0x7a, 0x75, 0xb2, 0x66, 0x81, 0x5b, 0x79, 0x92, 0x97, + 0x94, 0xaf, 0x72, 0x8a, 0x9b, 0x5f, 0x65, 0x96, 0x81, 0xb6, 0x8a, 0x6f, + 0x94, 0x7a, 0x96, 0x92, 0x79, 0x94, 0x8e, 0x53, 0x9a, 0x73, 0x6a, 0x9d, + 0xa1, 0xa3, 0xa4, 0x8f, 0x6b, 0xa4, 0x8b, 0x82, 0x96, 0xb1, 0x8c, 0x92, + 0x7f, 0x91, 0x5f, 0x98, 0x8a, 0xa4, 0x7e, 0x80, 0x97, 0x86, 0x86, 0x86, + 0x8f, 0xa6, 0x77, 0x9a, 0x82, 0x80, 0x6e, 0x73, 0x83, 0xaf, 0x87, 0x6d, + 0x77, 0x9a, 0x83, 0x9f, 0x7c, 0xa4, 0x71, 0x6f, 0x7d, 0x75, 0x9d, 0x82, + 0x83, 0xaf, 0x85, 0x80, 0x8d, 0x7f, 0xa4, 0xa2, 0x88, 0xba, 0x76, 0x76, + 0x94, 0x6b, 0x76, 0x83, 0x77, 0x96, 0x78, 0x8c, 0xb0, 0x8e, 0x83, 0x87, + 0xa0, 0xcc, 0x7f, 0xa4, 0x8c, 0x77, 0x84, 0x8c, 0x80, 0xa0, 0x57, 0x76, + 0x76, 0x71, 0x86, 0x9c, 0x7f, 0x88, 0x57, 0x95, 0x4d, 0x8c, 0x7f, 0x80, + 0x66, 0x9e, 0x42, 0x8d, 0x6a, 0x8e, 0x8c, 0x80, 0x89, 0x9d, 0x4f, 0x83, + 0x54, 0x8a, 0x5e, 0x64, 0x70, 0x94, 0x78, 0x90, 0x7d, 0x78, 0x8d, 0x71, + 0x56, 0x9a, 0x8c, 0x65, 0x8b, 0x62, 0x88, 0x9a, 0x6c, 0x8e, 0x7b, 0x78, + 0x68, 0x86, 0x64, 0x6b, 0x67, 0xaa, 0x8c, 0x7b, 0x67, 0x75, 0x58, 0x7e, + 0x6b, 0x97, 0x92, 0x87, 0x9c, 0x79, 0x71, 0x76, 0x7d, 0xbb, 0x89, 0x75, + 0x83, 0x57, 0x74, 0x98, 0xa1, 0x8f, 0xb0, 0x89, 0x76, 0x88, 0x69, 0x9c, + 0x74, 0xb0, 0x86, 0x9c, 0x79, 0x6f, 0x84, 0x70, 0x94, 0xa1, 0x6e, 0x7a, + 0xa3, 0x88, 0xa0, 0x7a, 0x94, 0xa1, 0x82, 0x93, 0x99, 0x95, 0x7f, 0xab, + 0x97, 0x9d, 0x6e, 0x68, 0x79, 0x73, 0x76, 0x83, 0x76, 0xbd, 0x87, 0x87, + 0x86, 0x74, 0x8f, 0x6e, 0x65, 0xba, 0x6a, 0x78, 0x91, 0x62, 0x72, 0x67, + 0x75, 0xbd, 0x8c, 0x5e, 0x85, 0x6d, 0x72, 0x85, 0x7d, 0x96, 0x8f, 0xb9, + 0x9f, 0x97, 0xa2, 0x8a, 0xa1, 0xc1, 0x8d, 0xbc, 0x85, 0x78, 0x93, 0x97, + 0x99, 0x9f, 0x3a, 0x98, 0x65, 0x8d, 0x6a, 0x6c, 0x92, 0x85, 0x49, 0x7e, + 0x6a, 0xaa, 0x8a, 0x94, 0x6b, 0x93, 0x40, 0x8a, 0x8c, 0x9c, 0x6f, 0xad, + 0x72, 0xb0, 0x58, 0x88, 0x60, 0x8c, 0x86, 0x84, 0x74, 0x96, 0x8f, 0x97, + 0x5e, 0x6c, 0x79, 0x92, 0x51, 0xa8, 0x92, 0x58, 0x62, 0x6f, 0x6c, 0x76, + 0x5f, 0x9e, 0x86, 0x71, 0x9c, 0x69, 0x7e, 0x80, 0x8a, 0x97, 0x6f, 0x79, + 0x8b, 0x6f, 0x6c, 0x88, 0x73, 0x9c, 0x6d, 0x91, 0x77, 0x73, 0x7f, 0x97, + 0x86, 0xa9, 0xac, 0x71, 0x82, 0x90, 0x83, 0x8a, 0x80, 0x9d, 0xa8, 0x85, + 0x78, 0x7f, 0x94, 0x99, 0x8e, 0xa3, 0x89, 0x70, 0x87, 0x62, 0x82, 0x87, + 0x8c, 0x98, 0x7a, 0x88, 0x72, 0x7e, 0x78, 0xa0, 0x78, 0x95, 0x97, 0x8f, + 0x7b, 0x7c, 0x83, 0x94, 0x93, 0xa7, 0x77, 0x97, 0x90, 0x5e, 0x76, 0x7c, + 0x68, 0xaa, 0x69, 0x67, 0x76, 0x84, 0x7e, 0x64, 0xa3, 0xbe, 0x7e, 0x8b, + 0x82, 0x50, 0x8a, 0x82, 0x89, 0xc0, 0x79, 0x78, 0x68, 0x7c, 0x6b, 0x77, + 0x82, 0x99, 0x7b, 0x83, 0x80, 0x90, 0x96, 0x96, 0x87, 0xb7, 0xa5, 0x94, + 0x82, 0x99, 0x95, 0x91, 0x7e, 0xa2, 0x49, 0x95, 0x6d, 0x8e, 0xa9, 0x89, + 0x8e, 0x8f, 0x3d, 0x95, 0x6a, 0x8c, 0x8b, 0x8c, 0x7e, 0x88, 0x63, 0x94, + 0x69, 0x94, 0x88, 0x92, 0x79, 0xa7, 0x68, 0x60, 0x76, 0x85, 0xa1, 0x6f, + 0x54, 0x96, 0x63, 0x7a, 0x5c, 0x73, 0x74, 0x6e, 0x53, 0x99, 0x69, 0x76, + 0x69, 0x57, 0x6a, 0x82, 0x55, 0x93, 0x82, 0x80, 0x65, 0x7f, 0x7b, 0x76, + 0x72, 0x87, 0x8d, 0x97, 0x98, 0x78, 0x7e, 0x6d, 0x7a, 0x95, 0x78, 0x70, + 0x90, 0x83, 0x89, 0x80, 0x7f, 0x9d, 0x73, 0x73, 0x84, 0x77, 0x8e, 0x77, + 0x8e, 0x75, 0x9e, 0xa5, 0x86, 0x68, 0x89, 0x7d, 0x8d, 0x99, 0x79, 0x8f, + 0x8e, 0x87, 0x87, 0x97, 0x8c, 0x91, 0xa1, 0x96, 0x83, 0x73, 0x87, 0xa9, + 0x8c, 0xa6, 0x85, 0x8c, 0x96, 0x7d, 0x7f, 0x8e, 0x7e, 0xb0, 0x85, 0x8f, + 0x7f, 0x7d, 0x95, 0x7d, 0x9c, 0xb3, 0x71, 0x86, 0x81, 0x69, 0x7b, 0x69, + 0x76, 0xb6, 0x5d, 0x67, 0x8a, 0x68, 0x9c, 0xa6, 0x70, 0xbf, 0x79, 0x60, + 0x8b, 0x7f, 0x7a, 0x7b, 0x8b, 0xaf, 0x8c, 0xa1, 0x86, 0x92, 0x76, 0x8d, + 0x89, 0xa2, 0xa8, 0xa3, 0xa0, 0xa2, 0x96, 0x9d, 0x7c, 0x92, 0x3f, 0x9b, + 0x6d, 0x8a, 0x80, 0x81, 0xa0, 0x92, 0x50, 0x7c, 0x82, 0x99, 0x80, 0xa6, + 0x8e, 0x8d, 0x4f, 0x8d, 0x65, 0x71, 0x77, 0x81, 0x51, 0xa6, 0x3f, 0x5c, + 0x63, 0x6f, 0x61, 0x93, 0x5c, 0xaa, 0x77, 0x8f, 0x5d, 0x53, 0x79, 0x74, + 0x6b, 0x94, 0x86, 0x81, 0x85, 0x48, 0x81, 0x80, 0x6b, 0x85, 0x6c, 0x91, + 0x92, 0x6a, 0x74, 0x78, 0x72, 0x87, 0x6c, 0x82, 0x88, 0x7b, 0x93, 0x71, + 0x91, 0x8d, 0x67, 0x83, 0x86, 0x5b, 0x86, 0x79, 0x81, 0x9f, 0x95, 0x8a, + 0x70, 0x66, 0x9e, 0x6b, 0x72, 0x98, 0x97, 0x95, 0x72, 0x93, 0x84, 0x92, + 0x8c, 0x96, 0xa2, 0x65, 0x80, 0x75, 0xa2, 0xa7, 0x7d, 0x97, 0x71, 0x8f, + 0x69, 0x65, 0x8f, 0xae, 0x9c, 0x97, 0x5d, 0xb3, 0x98, 0x83, 0x98, 0xa0, + 0x5f, 0x7e, 0x7a, 0x7a, 0x87, 0x7c, 0x92, 0xa0, 0x81, 0xa6, 0x71, 0x8e, + 0x88, 0x52, 0xa3, 0x88, 0x6a, 0x9d, 0x84, 0x82, 0x7c, 0x78, 0x9f, 0x92, + 0x66, 0xa4, 0x53, 0x6a, 0x7e, 0x84, 0x60, 0x84, 0x92, 0xb0, 0x93, 0x9d, + 0xa0, 0x5f, 0x95, 0x8c, 0x77, 0xa1, 0x8c, 0x90, 0xa0, 0x9c, 0x9a, 0x95, + 0x85, 0xa1, 0x22, 0x8f, 0x57, 0x80, 0x96, 0x7d, 0x92, 0x8b, 0x41, 0xa6, + 0x61, 0xa2, 0x6f, 0x80, 0x5d, 0x91, 0x66, 0xab, 0x6d, 0x7e, 0x88, 0x93, + 0x5c, 0xa5, 0x75, 0x6e, 0x6c, 0x86, 0x69, 0x73, 0x4e, 0x8e, 0x77, 0x6b, + 0x6c, 0x60, 0x67, 0x91, 0x75, 0x91, 0x6c, 0x7c, 0x53, 0x6e, 0x75, 0x8e, + 0x79, 0x8c, 0x8b, 0x74, 0x6b, 0x57, 0x71, 0xa1, 0x7f, 0x83, 0x6c, 0x6b, + 0x93, 0x99, 0x7a, 0x78, 0x71, 0x8c, 0x78, 0x88, 0x9f, 0x85, 0x77, 0x7b, + 0x86, 0x85, 0xa1, 0x61, 0x78, 0x65, 0x61, 0x75, 0x82, 0x7d, 0xa9, 0xa2, + 0x84, 0x82, 0x94, 0x95, 0x90, 0x9f, 0x83, 0x97, 0x76, 0x95, 0x8a, 0x83, + 0x9b, 0x87, 0x8b, 0x7a, 0x6c, 0x6e, 0x75, 0x95, 0x85, 0x95, 0x84, 0x9e, + 0x96, 0x74, 0x7d, 0xa5, 0x85, 0x8e, 0x7e, 0x73, 0x85, 0x8d, 0x87, 0x80, + 0x8a, 0x96, 0x65, 0x87, 0x7c, 0x73, 0x80, 0x96, 0x73, 0x8d, 0x5e, 0x79, + 0x7e, 0x8d, 0x79, 0x85, 0x63, 0xa0, 0x62, 0x89, 0x9d, 0x8c, 0x74, 0x7b, + 0x9c, 0xa5, 0x71, 0x8c, 0x83, 0x91, 0x8e, 0x8d, 0x89, 0x8b, 0x8b, 0xa4, + 0x78, 0x88, 0x9e, 0x85, 0x8b, 0x94, 0x38, 0x84, 0x7b, 0x86, 0x7d, 0xa2, + 0x73, 0x8f, 0x47, 0x7b, 0x69, 0xb4, 0x85, 0x71, 0x61, 0x9d, 0x59, 0x95, + 0x74, 0x93, 0x6a, 0x88, 0x62, 0xa2, 0x56, 0x93, 0x8d, 0x68, 0x7e, 0x80, + 0x6b, 0xb7, 0x63, 0x90, 0x5d, 0x54, 0x6c, 0x90, 0x5a, 0x8e, 0x7e, 0x7d, + 0x82, 0x73, 0x7f, 0x89, 0x94, 0x8e, 0x7a, 0x70, 0x6c, 0x79, 0x88, 0x88, + 0x9b, 0x8b, 0x70, 0x81, 0x83, 0x83, 0x8b, 0x86, 0x64, 0x93, 0x82, 0x66, + 0x66, 0x79, 0x74, 0x91, 0x92, 0x94, 0x7c, 0x87, 0x72, 0x79, 0x8d, 0xaa, + 0xa2, 0x9e, 0xaf, 0x95, 0xb1, 0x8a, 0x95, 0x8b, 0x94, 0x7e, 0x79, 0x8e, + 0x99, 0x98, 0x97, 0x9e, 0x94, 0x87, 0x74, 0x72, 0x63, 0x92, 0x92, 0x95, + 0xb0, 0x94, 0x86, 0x91, 0x77, 0x8f, 0x91, 0x7e, 0x83, 0x88, 0x90, 0xa5, + 0x79, 0x70, 0x85, 0x8f, 0x67, 0x90, 0x98, 0x8d, 0x8a, 0x5d, 0x8c, 0x9c, + 0x94, 0x91, 0x80, 0x95, 0x6e, 0x95, 0x73, 0x8d, 0x63, 0x8e, 0x53, 0x8a, + 0x77, 0x88, 0x8f, 0x6f, 0x87, 0x9e, 0x8b, 0xb7, 0x99, 0xb2, 0x85, 0x82, + 0xa1, 0x89, 0x9b, 0xa7, 0x80, 0x81, 0xa0, 0x8e, 0x84, 0xa9, 0x27, 0x73, + 0x5e, 0x85, 0x5f, 0x92, 0x8c, 0xa2, 0x34, 0x8e, 0x6e, 0xb2, 0x7b, 0x8c, + 0x69, 0x93, 0x47, 0x9e, 0x58, 0x7e, 0x94, 0x86, 0x47, 0xa3, 0x53, 0x6b, + 0x6e, 0x6a, 0x7f, 0x73, 0x5b, 0x8c, 0x7a, 0x99, 0x6c, 0x5d, 0x82, 0x82, + 0x62, 0x8a, 0x7a, 0x8e, 0x88, 0x62, 0xa0, 0x8e, 0x5c, 0x9a, 0x72, 0x79, + 0x66, 0x6b, 0x75, 0x78, 0x82, 0x8a, 0x59, 0x91, 0x93, 0x68, 0x78, 0xb4, + 0x86, 0x7e, 0x8c, 0x6e, 0x88, 0x7f, 0x96, 0x8e, 0x6e, 0x8b, 0x8c, 0x73, + 0xab, 0x79, 0x88, 0xa6, 0x86, 0x81, 0x9a, 0x80, 0x9a, 0x9e, 0x8b, 0x6d, + 0x9a, 0x70, 0x8e, 0x8a, 0x84, 0x7a, 0xaf, 0xb8, 0x9e, 0x90, 0x89, 0xb3, + 0x9b, 0x85, 0x94, 0xb6, 0x87, 0x8c, 0x6e, 0xa3, 0xac, 0x9e, 0x8c, 0x7c, + 0x81, 0x83, 0x70, 0x8d, 0x7c, 0x81, 0x77, 0x82, 0x69, 0x8e, 0x5e, 0x80, + 0x8a, 0x8e, 0x7c, 0x8a, 0x89, 0x90, 0x58, 0x59, 0x85, 0x88, 0x7a, 0x86, + 0x73, 0x9c, 0x4a, 0x81, 0x8d, 0x89, 0x91, 0x95, 0x72, 0x83, 0x9d, 0x99, + 0x8d, 0x6b, 0x95, 0x7e, 0x70, 0x94, 0x8c, 0x9f, 0x8a, 0x8f, 0xa7, 0x84, + 0x87, 0xb6, 0x42, 0x81, 0x63, 0x8a, 0x79, 0x77, 0x74, 0x90, 0x23, 0x85, + 0x74, 0x8f, 0x87, 0x80, 0x50, 0xa1, 0x4d, 0x9b, 0x55, 0x82, 0x74, 0x8e, + 0x4a, 0xa7, 0x52, 0x4d, 0x77, 0x67, 0x77, 0x9e, 0x62, 0xa5, 0x7d, 0x96, + 0x6f, 0x45, 0x80, 0x8c, 0x6c, 0x92, 0x99, 0x6f, 0x5d, 0x56, 0x93, 0xac, + 0x94, 0x9c, 0x95, 0x92, 0x6e, 0x71, 0x87, 0x8c, 0x7b, 0xa9, 0x7f, 0x7a, + 0x69, 0x6b, 0x7d, 0x90, 0x6f, 0x81, 0x9f, 0x80, 0x83, 0x67, 0x78, 0x85, + 0x85, 0x91, 0x8a, 0x80, 0xaa, 0x86, 0x8c, 0x88, 0x8c, 0x8f, 0x9b, 0x85, + 0x8b, 0x7e, 0x83, 0x82, 0x95, 0x75, 0x6b, 0x8f, 0x85, 0x8b, 0xb0, 0x9f, + 0xa7, 0x8e, 0x61, 0x9d, 0x72, 0xac, 0x92, 0x87, 0x94, 0x96, 0x68, 0x8f, + 0x63, 0x85, 0x9c, 0xa8, 0x82, 0x9b, 0x85, 0x9b, 0x6b, 0x72, 0x83, 0x85, + 0x90, 0x87, 0x74, 0xa4, 0x88, 0x57, 0x63, 0x90, 0x8e, 0x7b, 0x80, 0x81, + 0x94, 0x74, 0x68, 0x8a, 0x7f, 0x86, 0x78, 0x72, 0x75, 0x67, 0x7a, 0x8a, + 0x7a, 0x74, 0x8c, 0xad, 0x75, 0xa2, 0x7d, 0x9a, 0x9e, 0x83, 0x92, 0xa2, + 0xa3, 0x98, 0xa5, 0x91, 0x84, 0xb0, 0x21, 0x9a, 0x5f, 0x8c, 0x7e, 0x86, + 0x80, 0xa0, 0x16, 0x9b, 0x5b, 0x9c, 0x76, 0x8d, 0x77, 0x9f, 0x62, 0x86, + 0x6a, 0x6c, 0x6e, 0x8f, 0x4e, 0xc1, 0x61, 0x6f, 0x74, 0x79, 0x80, 0x5f, + 0x59, 0x9e, 0x7c, 0x87, 0x7f, 0x4b, 0x6c, 0x8b, 0x5a, 0x8f, 0x65, 0x8a, + 0x62, 0x58, 0x66, 0x8d, 0x83, 0x97, 0x8a, 0x7a, 0x77, 0x79, 0x6c, 0x83, + 0x8c, 0x93, 0x82, 0x5e, 0x61, 0x8c, 0x82, 0x80, 0x88, 0x88, 0x85, 0x87, + 0x77, 0x70, 0x8d, 0x7f, 0x7a, 0x89, 0x72, 0x7e, 0xa3, 0x99, 0x6b, 0xaa, + 0x81, 0x87, 0x90, 0x6f, 0x7f, 0x77, 0x96, 0x83, 0x89, 0x89, 0x6a, 0x77, + 0xa4, 0x6c, 0x97, 0x7e, 0x95, 0xa4, 0x63, 0x8d, 0x71, 0x96, 0x8a, 0xa4, + 0x9f, 0x7c, 0x54, 0x94, 0x7a, 0x89, 0x8a, 0x90, 0x7e, 0x9d, 0x53, 0x7c, + 0x9d, 0x83, 0x90, 0x84, 0xa1, 0x8e, 0x80, 0x74, 0x69, 0x7a, 0x69, 0x93, + 0x8a, 0x90, 0x83, 0x76, 0x8b, 0x6f, 0x8e, 0x93, 0x82, 0x84, 0x7d, 0x94, + 0xa1, 0x78, 0x7d, 0x68, 0x79, 0x83, 0x85, 0x9d, 0x89, 0xa0, 0x8a, 0x93, + 0x90, 0x8c, 0x82, 0x86, 0x80, 0x71, 0xb3, 0xa1, 0x90, 0xb2, 0x27, 0xa3, + 0x5e, 0xa3, 0xa6, 0x64, 0x75, 0xa0, 0x23, 0x8c, 0x7c, 0xc4, 0x7a, 0x8c, + 0x4d, 0xa3, 0x4c, 0x93, 0x71, 0x7b, 0x71, 0x8b, 0x34, 0xa5, 0x47, 0x7f, + 0x4e, 0x73, 0x51, 0x8a, 0x67, 0xa0, 0x9d, 0x7f, 0x65, 0x38, 0x61, 0x70, + 0x71, 0x8d, 0x6a, 0x7e, 0x7e, 0x4c, 0x7d, 0x8d, 0x81, 0x80, 0xa5, 0x84, + 0x6f, 0x57, 0x70, 0x91, 0x8b, 0x99, 0x9d, 0x84, 0x77, 0x7f, 0x6b, 0x7f, + 0x76, 0x8f, 0x90, 0x72, 0x6c, 0x58, 0x6b, 0x85, 0xa6, 0x8a, 0xa2, 0x6d, + 0x8a, 0x71, 0x71, 0x95, 0x92, 0x7c, 0x88, 0x67, 0x86, 0x6d, 0x8d, 0x95, + 0x79, 0x8e, 0x65, 0x71, 0x71, 0x91, 0x85, 0x99, 0xa9, 0x87, 0x80, 0x88, + 0x74, 0x86, 0x75, 0x83, 0x8b, 0x7f, 0x78, 0xb1, 0x90, 0xa8, 0x7b, 0x98, + 0x8a, 0x7b, 0x5b, 0x99, 0x6f, 0x7f, 0xa0, 0x79, 0xa5, 0x93, 0x8b, 0x7b, + 0x7e, 0x7a, 0x61, 0x9d, 0x98, 0x8b, 0x82, 0x7c, 0x76, 0x73, 0x81, 0x8a, + 0x7e, 0x8d, 0x6e, 0x71, 0xa0, 0x65, 0x80, 0x62, 0x7d, 0x8d, 0x5e, 0x9b, + 0x8f, 0x85, 0x89, 0xad, 0x71, 0x73, 0x7f, 0x89, 0x8d, 0x89, 0xb3, 0xa1, + 0x7c, 0xaf, 0x43, 0x82, 0x49, 0x92, 0x62, 0x7f, 0x79, 0xa6, 0x23, 0x99, + 0x6c, 0x9a, 0x8a, 0x90, 0x6c, 0xb9, 0x6f, 0x8a, 0x61, 0x7f, 0x8f, 0x8a, + 0x57, 0xb9, 0x55, 0x65, 0x4b, 0x51, 0x66, 0x6e, 0x4a, 0xa1, 0x83, 0x8a, + 0x73, 0x23, 0x8a, 0x6d, 0x46, 0xa7, 0x87, 0x64, 0x84, 0x5f, 0x6f, 0x6f, + 0x9b, 0x9d, 0x76, 0x83, 0x60, 0x6e, 0x76, 0x8a, 0x9a, 0xa6, 0x75, 0x73, + 0x86, 0x5b, 0x97, 0x88, 0x7b, 0x8e, 0x82, 0x5c, 0x97, 0x71, 0x74, 0x85, + 0x83, 0x91, 0x89, 0x6f, 0x93, 0x94, 0x8b, 0xa9, 0x7d, 0x84, 0x80, 0x89, + 0x97, 0x80, 0x65, 0x92, 0x9a, 0x85, 0x5a, 0x6a, 0x6b, 0x58, 0x6f, 0x8c, + 0x9a, 0x8b, 0x6e, 0x81, 0x9d, 0xae, 0x8c, 0x86, 0x8d, 0x90, 0x6c, 0xb8, + 0x91, 0x89, 0x98, 0xbd, 0x8b, 0x78, 0x7d, 0x87, 0x9c, 0x72, 0x73, 0x80, + 0x9e, 0x92, 0x5d, 0x77, 0x78, 0x4f, 0x87, 0x7b, 0x7a, 0x9e, 0x74, 0x67, + 0x6a, 0x58, 0x95, 0x80, 0x75, 0x97, 0x81, 0x75, 0x94, 0x75, 0x73, 0x92, + 0x83, 0x7b, 0x6b, 0x8e, 0x82, 0x6e, 0x7d, 0x9b, 0x91, 0x7f, 0x9e, 0xaa, + 0x8c, 0xa3, 0xa8, 0x8c, 0x9a, 0xc1, 0x28, 0xac, 0x49, 0x9b, 0x59, 0x8a, + 0x60, 0xa7, 0x39, 0xa7, 0x75, 0x9b, 0x95, 0x94, 0x76, 0xb3, 0x4a, 0x6b, + 0x60, 0x6c, 0xa5, 0x71, 0x40, 0xc4, 0x4c, 0x7c, 0x76, 0x7b, 0x67, 0x76, + 0x76, 0xa4, 0x7b, 0x83, 0x67, 0x4d, 0x87, 0x87, 0x6e, 0x93, 0x84, 0x70, + 0x78, 0x41, 0x87, 0x9f, 0x7a, 0x8c, 0x87, 0x69, 0x73, 0x6c, 0x93, 0x73, + 0x77, 0xa2, 0x52, 0x72, 0x5c, 0x75, 0x6c, 0x8f, 0x65, 0x92, 0x87, 0x52, + 0x67, 0x54, 0x54, 0x75, 0x90, 0x9c, 0x91, 0x6f, 0xa3, 0x86, 0x87, 0x9c, + 0x99, 0x86, 0x9f, 0x71, 0x8a, 0x7a, 0x7a, 0x97, 0x7a, 0x86, 0x6c, 0x99, + 0x89, 0x7e, 0x9c, 0x83, 0x98, 0x78, 0x73, 0x7f, 0x91, 0x96, 0x9a, 0x8d, + 0xb0, 0x9e, 0x6a, 0x80, 0x92, 0x86, 0x95, 0x83, 0x94, 0x92, 0x6f, 0x86, + 0x8a, 0x52, 0x6e, 0x82, 0x84, 0x8b, 0x77, 0x88, 0x70, 0x54, 0x8f, 0x7f, + 0x7d, 0x7e, 0x57, 0x89, 0x6d, 0x6f, 0x9c, 0x93, 0x90, 0x93, 0x52, 0x70, + 0x75, 0x92, 0x73, 0x88, 0x93, 0x77, 0x77, 0x91, 0x89, 0xa2, 0x9d, 0xa6, + 0xae, 0x84, 0x7d, 0xab, 0x92, 0x7e, 0x9c, 0x98, 0x7b, 0xc3, 0x38, 0x98, + 0x4f, 0x97, 0x8f, 0x93, 0x62, 0xb8, 0x23, 0xa4, 0x6d, 0x9c, 0x81, 0x8e, + 0x6f, 0x9d, 0x56, 0x89, 0x50, 0x94, 0x70, 0x77, 0x5d, 0xb7, 0x60, 0x5b, + 0x72, 0x45, 0x81, 0x8c, 0x66, 0xbc, 0x8f, 0x7f, 0x57, 0x43, 0x85, 0x96, + 0x5a, 0xb2, 0x91, 0x7d, 0x6c, 0x3a, 0x73, 0x92, 0x63, 0x93, 0x89, 0x90, + 0x7f, 0x52, 0x7f, 0x7b, 0xa1, 0xa6, 0x8f, 0x60, 0x78, 0x51, 0x5f, 0xac, + 0x7b, 0x89, 0x88, 0x97, 0x7e, 0x64, 0x57, 0x72, 0x6c, 0x96, 0x74, 0x78, + 0xab, 0x66, 0x62, 0x8d, 0x6f, 0x86, 0x91, 0x93, 0x7d, 0x74, 0x82, 0x80, + 0x73, 0x84, 0x9c, 0x8e, 0x68, 0x69, 0x9e, 0xa1, 0x8a, 0x83, 0x7a, 0x87, + 0x94, 0x8c, 0x83, 0x7e, 0x91, 0x92, 0x82, 0x7b, 0xa0, 0x8e, 0x73, 0x86, + 0xa9, 0x95, 0x7c, 0xa5, 0x6c, 0x6f, 0x8c, 0x87, 0xa6, 0x8a, 0x77, 0x86, + 0x7d, 0x79, 0x89, 0x75, 0x8f, 0x82, 0x54, 0x61, 0x82, 0x8e, 0x80, 0x84, + 0x7b, 0x8e, 0x61, 0x82, 0x86, 0x77, 0x7d, 0x7c, 0x7e, 0x6c, 0x7b, 0xad, + 0x7b, 0x90, 0x88, 0x80, 0x64, 0x83, 0x7e, 0xa7, 0x83, 0x7e, 0xb5, 0xbb, + 0x88, 0xd9, 0x21, 0x9a, 0x4d, 0x9f, 0x91, 0x97, 0x64, 0xb5, 0x1c, 0x8a, + 0x5f, 0xaf, 0x7e, 0x7b, 0x67, 0xad, 0x48, 0x7f, 0x4e, 0x87, 0x8f, 0x7c, + 0x46, 0xab, 0x70, 0x7f, 0x4b, 0x4e, 0x48, 0x8c, 0x63, 0xc5, 0xa2, 0x7f, + 0x68, 0x3b, 0x59, 0x7f, 0x53, 0xa1, 0x8e, 0x6e, 0x7a, 0x4a, 0x5f, 0x62, + 0x5b, 0xa1, 0x62, 0x78, 0x74, 0x57, 0x78, 0x91, 0x7b, 0x9b, 0x75, 0x73, + 0x73, 0x72, 0x94, 0x92, 0x79, 0xaa, 0x94, 0x75, 0x86, 0x58, 0x8c, 0x71, + 0x77, 0x91, 0xa5, 0x74, 0x8f, 0x73, 0x89, 0x77, 0x68, 0x8e, 0x90, 0x96, + 0x9f, 0x79, 0x77, 0x7d, 0x89, 0x9b, 0x8c, 0x94, 0x81, 0x88, 0x91, 0x8f, + 0x9b, 0x91, 0x78, 0x87, 0x82, 0x72, 0xa7, 0xa2, 0x85, 0x98, 0xa3, 0x91, + 0x83, 0x75, 0x72, 0x93, 0x80, 0x8f, 0x85, 0x70, 0x97, 0x58, 0x9f, 0x72, + 0x91, 0x8e, 0x93, 0x74, 0x97, 0x73, 0x74, 0x91, 0x80, 0x84, 0x96, 0x94, + 0x76, 0x69, 0x66, 0x9e, 0x81, 0x8a, 0x8b, 0x63, 0x65, 0x7c, 0xa1, 0x9a, + 0x72, 0x84, 0x9e, 0x89, 0x9a, 0x86, 0x98, 0x7f, 0x77, 0x85, 0x82, 0xaa, + 0xa3, 0x88, 0xac, 0x9e, 0x76, 0xca, 0x2b, 0xa0, 0x40, 0xad, 0x6f, 0x6c, + 0x66, 0xc8, 0x07, 0x9e, 0x3e, 0x9f, 0x85, 0x9f, 0x5e, 0xb7, 0x53, 0x91, + 0x56, 0x6d, 0x62, 0x95, 0x4c, 0xc7, 0x46, 0x56, 0x4b, 0x5d, 0x6f, 0x52, + 0x4d, 0xa3, 0x8c, 0x90, 0x78, 0x4d, 0x58, 0x8d, 0x53, 0x93, 0x8e, 0x68, + 0x6f, 0x3b, 0x49, 0x86, 0x6e, 0x9d, 0x76, 0x74, 0x5b, 0x44, 0x7b, 0x8c, + 0x89, 0xb0, 0x64, 0x62, 0x6a, 0x6d, 0x7a, 0xae, 0x84, 0x95, 0x8c, 0x71, + 0x8b, 0x60, 0x82, 0x9e, 0x8c, 0xa8, 0x90, 0x66, 0xa1, 0x7b, 0x65, 0x82, + 0x8f, 0x7d, 0x8d, 0x78, 0x8e, 0x5f, 0x75, 0x88, 0x5d, 0x93, 0xa1, 0x93, + 0x6b, 0x67, 0x7a, 0xa7, 0x92, 0x8c, 0x65, 0x88, 0x95, 0x93, 0x87, 0x81, + 0x9c, 0x97, 0x62, 0x9d, 0x90, 0x62, 0xa1, 0x9f, 0x87, 0x94, 0x94, 0x99, + 0x92, 0x8f, 0x71, 0x80, 0x77, 0x82, 0x92, 0x78, 0x67, 0x69, 0x7e, 0x81, + 0x93, 0x89, 0x80, 0x9b, 0x71, 0x57, 0x63, 0x83, 0x7b, 0x9f, 0x5d, 0x92, + 0x85, 0x96, 0x7e, 0x92, 0x84, 0x7f, 0x81, 0xa3, 0xa8, 0x96, 0x91, 0x8e, + 0x8c, 0x8e, 0x7d, 0xb0, 0x86, 0x72, 0x9d, 0x8e, 0x8e, 0xd0, 0x05, 0x77, + 0x45, 0xad, 0x91, 0x95, 0x71, 0xb8, 0x01, 0x9a, 0x41, 0xb8, 0x94, 0x6e, + 0x63, 0xd3, 0x58, 0x8c, 0x5a, 0x89, 0x85, 0x83, 0x52, 0xc1, 0x7b, 0x6a, + 0x65, 0x6e, 0x73, 0x63, 0x68, 0xba, 0x67, 0x78, 0x79, 0x4a, 0x73, 0x8f, + 0x51, 0xc9, 0x85, 0x8a, 0x6b, 0x45, 0x6a, 0x8f, 0x6c, 0xad, 0x8a, 0x8d, + 0x6a, 0x6e, 0x6b, 0x7f, 0x86, 0xb4, 0x88, 0x7d, 0xaa, 0x71, 0x5c, 0x69, + 0x5d, 0xa8, 0x62, 0x7d, 0x6c, 0x6e, 0x6f, 0x6a, 0x7c, 0x9d, 0x7a, 0x83, + 0x7d, 0x79, 0x7b, 0x9c, 0x73, 0x93, 0x7f, 0x9d, 0x8c, 0x75, 0x78, 0x83, + 0x85, 0x88, 0x81, 0x81, 0x98, 0x79, 0xa3, 0xae, 0x5b, 0x90, 0x89, 0x9d, + 0x6d, 0x90, 0xa3, 0x8e, 0x87, 0x96, 0x60, 0xa7, 0x76, 0x82, 0x81, 0x84, + 0x84, 0x9c, 0x73, 0x8a, 0x6c, 0x58, 0x64, 0x96, 0x89, 0x8b, 0x76, 0x60, + 0x91, 0x72, 0x7f, 0x86, 0x9a, 0x89, 0x67, 0x7d, 0x77, 0x84, 0x73, 0x5c, + 0x67, 0x8a, 0x82, 0x8c, 0x8c, 0x94, 0x8a, 0xa2, 0xaa, 0x7e, 0x5f, 0x7f, + 0x86, 0x90, 0x96, 0xab, 0x8d, 0x91, 0x7c, 0xb6, 0x82, 0x8d, 0xb8, 0xa9, + 0x92, 0xea, 0x1b, 0x74, 0x25, 0xab, 0x8d, 0x61, 0x81, 0xd8, 0x2c, 0x86, + 0x2f, 0xcf, 0xa2, 0x84, 0x7f, 0xa4, 0x36, 0x86, 0x47, 0x8d, 0x60, 0x8a, + 0x62, 0xb1, 0x4a, 0x54, 0x48, 0x73, 0x64, 0x9d, 0x72, 0xb2, 0x76, 0x4c, + 0x8e, 0x4e, 0x76, 0x94, 0x7c, 0xad, 0x74, 0x6c, 0x6c, 0x54, 0x7f, 0x63, + 0x97, 0xb3, 0x74, 0x6c, 0x99, 0x5f, 0x86, 0x6a, 0xa3, 0x94, 0x7c, 0x83, + 0x8d, 0x81, 0x79, 0xac, 0x61, 0x9b, 0x65, 0x7b, 0x66, 0x89, 0x60, 0x76, + 0x8d, 0x93, 0x8d, 0x84, 0x71, 0x65, 0x82, 0x8c, 0x94, 0xa7, 0x59, 0xa1, + 0x8b, 0x72, 0x84, 0x65, 0x75, 0x95, 0x62, 0x71, 0x71, 0x7e, 0x7b, 0x97, + 0x9b, 0x9a, 0x80, 0xb1, 0x77, 0x7a, 0x73, 0x8e, 0x9c, 0x8c, 0x7d, 0x96, + 0x89, 0x7d, 0x7e, 0x80, 0x8e, 0x93, 0x63, 0x72, 0x6b, 0x57, 0x78, 0x8f, + 0x90, 0x86, 0x62, 0x75, 0x7e, 0x54, 0x7d, 0x95, 0x85, 0x84, 0x73, 0x7b, + 0x8f, 0x9e, 0x72, 0x8c, 0x90, 0x96, 0x8e, 0x6c, 0x80, 0x8b, 0x9e, 0x8c, + 0x87, 0x8e, 0x9b, 0x97, 0x8f, 0x94, 0xa3, 0x6b, 0xad, 0x93, 0x8a, 0x96, + 0x8d, 0x91, 0xa6, 0x8a, 0x9e, 0xce, 0x6b, 0x98, 0x6d, 0xa9, 0x92, 0x92, + 0x7c, 0xe2, 0x63, 0x97, 0x42, 0xc8, 0xa3, 0xa0, 0x88, 0xdc, 0x75, 0x9b, + 0x51, 0x7d, 0x5c, 0x80, 0x89, 0xc0, 0x83, 0x5e, 0x5e, 0xa4, 0x3e, 0x74, + 0x9b, 0xb6, 0x7f, 0x63, 0x78, 0x7d, 0x74, 0x57, 0x93, 0xa2, 0x83, 0x70, + 0x5e, 0x7d, 0x60, 0x69, 0x93, 0x9e, 0x79, 0x86, 0x91, 0x67, 0x86, 0x95, + 0xa2, 0xad, 0x62, 0x74, 0x68, 0x7e, 0x7e, 0x82, 0x8c, 0xb0, 0xa0, 0x63, + 0x8b, 0x82, 0x8f, 0x8c, 0xa4, 0xa3, 0x76, 0x6c, 0x8e, 0x87, 0x72, 0x85, + 0xaa, 0xa4, 0x7f, 0x7b, 0x8e, 0x9a, 0x69, 0x91, 0x9d, 0xa0, 0x81, 0x92, + 0x90, 0x85, 0x66, 0x82, 0xa3, 0xa9, 0x7f, 0x8f, 0x83, 0x9d, 0x8b, 0x8d, + 0x96, 0xa3, 0x8f, 0x7a, 0x6d, 0x89, 0x74, 0x8a, 0xa9, 0xa9, 0x7b, 0x77, + 0x93, 0x8b, 0x63, 0x92, 0x99, 0x8b, 0x88, 0x4f, 0x87, 0x7c, 0x67, 0x78, + 0x83, 0xa5, 0xa5, 0x58, 0x8d, 0x70, 0x86, 0x82, 0x9e, 0xa7, 0xa5, 0x96, + 0x8d, 0x7b, 0x96, 0x8c, 0x95, 0xa3, 0x8d, 0x9c, 0x92, 0x95, 0x98, 0x94, + 0x87, 0x90, 0x92, 0x92, 0x95, 0x96, 0xad, 0x6e, 0x97, 0x8c, 0x92, 0x7f, + 0x95, 0x8b, 0x8a, 0x90, 0x9b, 0x87, 0x9e, 0x86, 0x91, 0xa0, 0x68, 0x82, + 0x85, 0x8e, 0x82, 0xa8, 0x9f, 0x68, 0x87, 0x75, 0x9b, 0x70, 0x95, 0x91, + 0x6c, 0x77, 0x8b, 0x7b, 0x95, 0x80, 0x99, 0x65, 0x95, 0x82, 0x92, 0x9a, + 0x8a, 0x65, 0x70, 0x8c, 0x98, 0x9e, 0x80, 0x7b, 0xa5, 0x9b, 0x93, 0x94, + 0x84, 0x6a, 0x69, 0x82, 0x80, 0x7a, 0x75, 0x72, 0x94, 0x79, 0xad, 0xb2, + 0x81, 0x8b, 0x85, 0x6c, 0x86, 0x88, 0x9e, 0x79, 0x86, 0x9e, 0x7e, 0x91, + 0x7b, 0x6d, 0x93, 0x91, 0x82, 0x97, 0x6b, 0xa6, 0xaa, 0x9f, 0xa8, 0x74, + 0x94, 0x7f, 0x63, 0x98, 0x90, 0xa1, 0x8c, 0x7f, 0x71, 0x86, 0x89, 0x95, + 0x88, 0x80, 0x77, 0x67, 0x85, 0x7d, 0x89, 0x6d, 0x9c, 0x76, 0x72, 0x8d, + 0x96, 0x94, 0x88, 0x98, 0x9f, 0x94, 0x8e, 0x84, 0x7a, 0x88, 0x79, 0x9f, + 0x81, 0xa1, 0x7c, 0x8b, 0x71, 0x79, 0x7d, 0x9d, 0x7b, 0x6a, 0x8c, 0x66, + 0x9e, 0x7b, 0x77, 0x7a, 0xb0, 0x74, 0x7f, 0x8d, 0x8d, 0x71, 0x72, 0x84, + 0x90, 0x98, 0x7b, 0x89, 0x9b, 0x8e, 0x85, 0x7a, 0x67, 0x8a, 0x72, 0x84, + 0x82, 0x91, 0x91, 0x7a, 0x85, 0x8a, 0xae, 0x8a, 0x9a, 0x9a, 0x7f, 0x85, + 0x8a, 0x90, 0x69, 0x7b, 0x76, 0x78, 0x98, 0x54, 0x94, 0x7e, 0x6c, 0x72, + 0x89, 0x88, 0x82, 0x96, 0x59, 0x95, 0x76, 0x91, 0x94, 0x96, 0x83, 0x84, + 0x72, 0x8d, 0x97, 0x71, 0x68, 0x8e, 0x88, 0x8b, 0x7c, 0xa9, 0x73, 0x8a, + 0x95, 0x86, 0x87, 0x96, 0x91, 0x77, 0xb1, 0x88, 0x6e, 0x7d, 0x7c, 0x9f, + 0x8f, 0x82, 0x79, 0x83, 0xa6, 0x81, 0x89, 0x83, 0x85, 0x9b, 0x7c, 0x68, + 0x6f, 0x84, 0x7c, 0xa1, 0x8e, 0x80, 0x78, 0x8f, 0x96, 0x77, 0x7e, 0x7b, + 0x8f, 0x81, 0xa5, 0x84, 0x86, 0x91, 0x7b, 0x73, 0x92, 0x85, 0xa3, 0x7e, + 0x80, 0x95, 0x7d, 0x5f, 0x8c, 0x94, 0x95, 0x73, 0x95, 0x78, 0x87, 0xa1, + 0x94, 0x6c, 0xac, 0x6c, 0x77, 0x89, 0x86, 0x9c, 0x82, 0x76, 0x99, 0x93, + 0x92, 0x88, 0x80, 0x80, 0x85, 0x8a, 0xa8, 0x8f, 0x7a, 0x89, 0x9a, 0x7a, + 0x8f, 0x91, 0x86, 0x82, 0x7f, 0x82, 0x91, 0x95, 0x85, 0x71, 0x7d, 0x8f, + 0x83, 0x8c, 0x79, 0x97, 0x7a, 0x9b, 0x91, 0x88, 0xa2, 0x86, 0x8a, 0x80, + 0xa0, 0x96, 0x8b, 0x7d, 0x76, 0x96, 0x9f, 0x8d, 0x95, 0x8a, 0x94, 0xa0, + 0x80, 0x95, 0x9b, 0x96, 0x81, 0xa8, 0x59, 0x89, 0x92, 0xb2, 0x83, 0x89, + 0x85, 0x81, 0x7e, 0x64, 0x77, 0x82, 0x90, 0x96, 0x7e, 0x9f, 0xab, 0x8a, + 0x6e, 0x9b, 0x90, 0x89, 0x6e, 0x7d, 0x81, 0x65, 0x81, 0x86, 0xa1, 0x93, + 0x8b, 0x83, 0x81, 0x89, 0x8b, 0x90, 0x7e, 0x97, 0x8e, 0x75, 0x7e, 0x7e, + 0x7b, 0x81, 0x9a, 0x64, 0x90, 0xab, 0x90, 0x82, 0x8a, 0x82, 0x8d, 0xad, + 0x90, 0x74, 0x7f, 0x9a, 0x88, 0x92, 0x83, 0x97, 0xa6, 0x6e, 0x9d, 0x81, + 0xa2, 0x98, 0x74, 0x84, 0x93, 0x85, 0x84, 0x7d, 0xa2, 0x92, 0x92, 0x87, + 0x73, 0x8b, 0x92, 0x74, 0x96, 0x70, 0x83, 0x86, 0x8a, 0x89, 0x86, 0x88, + 0x87, 0x7c, 0x7d, 0x81, 0x8d, 0x71, 0x8c, 0x89, 0x70, 0x94, 0x8f, 0x9a, + 0x83, 0x9d, 0x99, 0x78, 0x74, 0x88, 0x84, 0x9a, 0x95, 0x8b, 0x8e, 0x7f, + 0xa2, 0xa0, 0x76, 0x93, 0x9b, 0x7c, 0x97, 0x81, 0x83, 0x8c, 0xa1, 0x99, + 0x9d, 0x7f, 0x87, 0x75, 0xa7, 0x75, 0x89, 0x7e, 0x88, 0x80, 0x8f, 0x84, + 0x9a, 0x77, 0x8d, 0x90, 0x9d, 0x6c, 0x88, 0x8d, 0x8e, 0x81, 0x97, 0x6d, + 0x81, 0x88, 0x64, 0x8c, 0x77, 0x8e, 0x91, 0x8a, 0x7f, 0x8a, 0x94, 0x7a, + 0x89, 0x93, 0x8c, 0x69, 0x85, 0x8c, 0x93, 0x61, 0x7e, 0x89, 0x7e, 0x8a, + 0x65, 0x8a, 0xa9, 0x7f, 0x80, 0x86, 0x82, 0x90, 0x66, 0x7a, 0x99, 0x71, + 0x7f, 0x73, 0x8d, 0x94, 0x7d, 0x73, 0x7a, 0x7d, 0x87, 0x7a, 0x97, 0x70, + 0x81, 0x60, 0x61, 0x7a, 0x91, 0x88, 0x93, 0x7a, 0x9e, 0xa6, 0x92, 0x9d, + 0x92, 0x67, 0x99, 0x9a, 0xae, 0x71, 0x89, 0xa5, 0x9f, 0xa6, 0x98, 0x89, + 0x97, 0x90, 0x9b, 0x9a, 0xc0, 0x95, 0x8f, 0x9c, 0x95, 0x93, 0x88, 0x95, + 0x95, 0xa0, 0x8e, 0x8c, 0xa8, 0x94, 0x6e, 0x9e, 0x6f, 0x7b, 0xa5, 0x96, + 0x98, 0x90, 0x91, 0x89, 0x93, 0x8f, 0x84, 0xb2, 0x7f, 0x5e, 0xc2, 0x75, + 0x8f, 0x90, 0x9c, 0xbf, 0x8a, 0x84, 0xa6, 0x85, 0x7d, 0x84, 0x8a, 0xad, + 0x6f, 0x88, 0xac, 0x77, 0x91, 0x8d, 0x94, 0xac, 0x8f, 0x7f, 0xa1, 0xa5, + 0x8e, 0x6d, 0x8a, 0x82, 0x85, 0x80, 0x9b, 0x7a, 0x9f, 0x60, 0x95, 0x97, + 0x90, 0x67, 0x8f, 0x91, 0x86, 0x89, 0x88, 0x89, 0x96, 0x6c, 0x8b, 0x94, + 0x8a, 0x75, 0x84, 0x96, 0x8a, 0x86, 0x7c, 0x91, 0x74, 0x8f, 0x97, 0x89, + 0x8f, 0x8e, 0x6b, 0x97, 0x93, 0x89, 0x6b, 0x7e, 0x65, 0xa4, 0xa5, 0x63, + 0x85, 0x88, 0x81, 0xa3, 0x70, 0x9b, 0x9e, 0x8c, 0x62, 0x73, 0x85, 0xb4, + 0x88, 0x6e, 0x92, 0x6f, 0x91, 0x88, 0x79, 0x91, 0x7f, 0x7d, 0x9a, 0x6b, + 0x78, 0x93, 0x7e, 0x79, 0x93, 0x7a, 0x74, 0x91, 0x8d, 0x92, 0xb3, 0x61, + 0xa3, 0x76, 0x81, 0x99, 0x96, 0x8b, 0x93, 0x8f, 0xa7, 0x6f, 0x8f, 0xa6, + 0xb2, 0x76, 0xa1, 0x83, 0xa8, 0x8b, 0xae, 0x99, 0x90, 0x6a, 0x97, 0x97, + 0xaa, 0x95, 0x85, 0x7d, 0x97, 0x94, 0x86, 0x94, 0x89, 0xa4, 0xa9, 0x81, + 0x89, 0x7c, 0x96, 0xb3, 0x92, 0x7d, 0xa4, 0x6f, 0x6d, 0x92, 0x83, 0xb4, + 0x7b, 0x94, 0x8c, 0x79, 0x61, 0x6f, 0x8f, 0xb7, 0x88, 0x66, 0xaa, 0x7d, + 0x89, 0x7f, 0x90, 0xbd, 0x99, 0xac, 0xb1, 0x96, 0x9c, 0x7c, 0x92, 0xb7, + 0x73, 0x94, 0xad, 0x9d, 0x7c, 0x80, 0x87, 0x96, 0x73, 0x8d, 0xa8, 0x88, + 0xa9, 0x83, 0x7b, 0x84, 0x9d, 0x99, 0x83, 0x89, 0x9d, 0x7f, 0x7e, 0x86, + 0x75, 0x83, 0x77, 0x7d, 0x8b, 0x7d, 0x80, 0x9d, 0xa2, 0x94, 0x72, 0x92, + 0x75, 0x95, 0x99, 0xa0, 0x7b, 0x83, 0x99, 0x89, 0x82, 0x92, 0x5b, 0x9e, + 0x7c, 0x91, 0x95, 0x79, 0x61, 0x86, 0x60, 0xc7, 0x72, 0x91, 0xb5, 0x88, + 0x71, 0x8d, 0x85, 0x91, 0x83, 0x74, 0xa8, 0x67, 0x79, 0x77, 0x7f, 0x79, + 0x68, 0x84, 0x95, 0x69, 0x98, 0x88, 0x74, 0x72, 0x9c, 0x86, 0x87, 0x95, + 0x90, 0x95, 0x9b, 0x8b, 0xc5, 0x7d, 0x81, 0x8f, 0x88, 0x8c, 0xb0, 0x95, + 0xa8, 0x8c, 0x84, 0xa0, 0xb0, 0x89, 0x9a, 0x90, 0xaa, 0x88, 0x96, 0x9b, + 0x88, 0xa9, 0x89, 0x99, 0xb7, 0x82, 0x99, 0xa0, 0x85, 0x70, 0x9c, 0x9a, + 0x94, 0x74, 0x91, 0x81, 0x76, 0x70, 0x8f, 0xc2, 0x8c, 0x91, 0x8f, 0x69, + 0x74, 0x7e, 0x6d, 0x9a, 0x80, 0x77, 0xa5, 0x94, 0x8b, 0x6d, 0x82, 0xcf, + 0x8e, 0x74, 0xc4, 0x86, 0x7f, 0x78, 0x72, 0xb3, 0x78, 0x7a, 0xac, 0x9c, + 0x7d, 0x77, 0x8d, 0xca, 0x67, 0x8c, 0xd5, 0x8f, 0x7f, 0x71, 0x70, 0x82, + 0x7e, 0x9f, 0xb0, 0x7f, 0x75, 0x90, 0x79, 0x7b, 0x8d, 0x7b, 0xa6, 0x87, + 0x98, 0x76, 0x84, 0x96, 0x81, 0x6a, 0x96, 0x86, 0x8e, 0x77, 0xa3, 0x83, + 0x91, 0x83, 0x8a, 0x6c, 0x74, 0x83, 0x99, 0x7d, 0x7c, 0x8a, 0x88, 0x9a, + 0x6b, 0x86, 0x59, 0xa3, 0x8a, 0x8e, 0xbb, 0x8a, 0x75, 0x78, 0x68, 0xb5, + 0x9b, 0x7b, 0xa7, 0x93, 0x5b, 0x6c, 0x6b, 0xa0, 0x74, 0x99, 0xc0, 0x73, + 0x8b, 0x7e, 0x8e, 0x83, 0x64, 0x7c, 0x7d, 0x7a, 0x98, 0x7d, 0x82, 0x7c, + 0x8f, 0x7e, 0x74, 0x86, 0xa9, 0x84, 0xba, 0x8f, 0xc7, 0x6f, 0x87, 0xae, + 0x97, 0x91, 0xad, 0x82, 0xb2, 0x70, 0x8a, 0xa0, 0xb0, 0x7d, 0x95, 0x8d, + 0xc2, 0x85, 0x80, 0xad, 0x9f, 0x85, 0x8b, 0x76, 0xaa, 0xab, 0x8f, 0xa0, + 0x89, 0x9b, 0x8a, 0xb3, 0xa0, 0x72, 0xbe, 0x8c, 0x93, 0x7a, 0xa0, 0xad, + 0x99, 0x6f, 0xa2, 0x79, 0x78, 0x8b, 0x6d, 0xae, 0x75, 0x6f, 0xa1, 0x8d, + 0x68, 0x81, 0x74, 0xb3, 0x8f, 0x81, 0xc6, 0x96, 0x77, 0x68, 0x85, 0xaf, + 0x86, 0x9f, 0xbb, 0x8a, 0x7e, 0x8a, 0x86, 0xab, 0x8b, 0x87, 0x94, 0x96, + 0x99, 0x82, 0x6a, 0xaa, 0x7b, 0x81, 0xa6, 0x9b, 0xb6, 0x73, 0x78, 0x9a, + 0x8f, 0xaa, 0x93, 0x81, 0x97, 0x7a, 0x72, 0x82, 0x79, 0x81, 0x7c, 0x88, + 0x8e, 0x79, 0x9d, 0x81, 0x9a, 0x75, 0x9b, 0x89, 0x73, 0x6a, 0xa6, 0x84, + 0x5c, 0x6f, 0xa0, 0x9d, 0x81, 0x84, 0x3e, 0xaf, 0x94, 0xa1, 0xb8, 0x93, + 0x81, 0x89, 0x68, 0xd4, 0x87, 0x99, 0x99, 0x95, 0x79, 0x72, 0x81, 0xa1, + 0x78, 0x7d, 0x8f, 0x7e, 0x87, 0x78, 0x8e, 0x97, 0x7e, 0x96, 0x86, 0x86, + 0x97, 0x74, 0x6f, 0x7d, 0xa5, 0x81, 0x6f, 0x8e, 0x9e, 0x8b, 0xad, 0xac, + 0xbd, 0x75, 0x84, 0xa2, 0x93, 0x76, 0xc7, 0x9e, 0xb0, 0x75, 0x89, 0xa4, + 0x95, 0x92, 0xb5, 0xaa, 0xb9, 0x7d, 0x79, 0xa5, 0x88, 0x70, 0x84, 0x70, + 0xa3, 0x81, 0xa1, 0xa6, 0x8f, 0x96, 0x96, 0x8d, 0xa5, 0x83, 0xb2, 0x8f, + 0x88, 0x74, 0x96, 0xbc, 0x8b, 0x81, 0xa4, 0x85, 0x7c, 0x87, 0x64, 0xb4, + 0x80, 0x88, 0x92, 0x90, 0x78, 0x79, 0x77, 0xa5, 0x79, 0x8b, 0xbd, 0x7d, + 0x84, 0x8c, 0x96, 0xd4, 0x78, 0x81, 0xa4, 0x8c, 0x97, 0x89, 0x78, 0xc4, + 0x9f, 0x94, 0xb9, 0x83, 0x76, 0x78, 0x89, 0x86, 0x81, 0x8f, 0xbd, 0xa7, + 0x88, 0x79, 0x8e, 0x92, 0x86, 0x88, 0xad, 0x8a, 0x7b, 0x7f, 0x80, 0xad, + 0x7a, 0xaf, 0x8a, 0x93, 0xa6, 0x84, 0x92, 0x8e, 0x84, 0x99, 0x80, 0xae, + 0x74, 0x7c, 0x95, 0x9c, 0x7b, 0x84, 0x84, 0x84, 0xa4, 0x82, 0x57, 0xb5, + 0x95, 0xc1, 0xb7, 0xa0, 0x85, 0x7b, 0x69, 0xc3, 0xb1, 0x8e, 0xa0, 0x8e, + 0x81, 0x88, 0x78, 0x9e, 0x81, 0x97, 0xb2, 0x74, 0x81, 0x84, 0x91, 0x87, + 0x6f, 0x6f, 0x75, 0x78, 0x92, 0x7a, 0x6d, 0x80, 0x9a, 0x7e, 0x81, 0xa1, + 0xa8, 0x6d, 0xb5, 0x98, 0xb4, 0x7f, 0x9a, 0xa4, 0x9d, 0x7b, 0xba, 0xaa, + 0xce, 0x93, 0x79, 0xa5, 0x81, 0x95, 0xa6, 0x7f, 0x8c, 0x8b, 0x96, 0xa4, + 0xa1, 0x8d, 0x91, 0x97, 0xce, 0x8e, 0x8e, 0x9d, 0x86, 0x7f, 0x97, 0xa3, + 0x99, 0x75, 0xa3, 0xa0, 0x69, 0x6a, 0x87, 0xa0, 0x9a, 0x80, 0xa2, 0x72, + 0x6d, 0x85, 0x6b, 0x94, 0x8d, 0x77, 0x9f, 0x84, 0x7f, 0x92, 0x64, 0xaa, + 0x78, 0x82, 0xa7, 0x8f, 0x84, 0x79, 0x84, 0xb9, 0x92, 0x7c, 0xb6, 0x96, + 0x9c, 0x99, 0x8f, 0xab, 0xab, 0x8a, 0xa2, 0xab, 0x6d, 0x97, 0x7b, 0xb1, + 0x9e, 0x6c, 0x9a, 0x99, 0xaa, 0xa3, 0x70, 0x80, 0x81, 0x6f, 0xb6, 0x95, + 0x93, 0x93, 0x8e, 0x80, 0x86, 0xb0, 0x87, 0x91, 0x8f, 0x8c, 0xa4, 0x86, + 0x89, 0x8f, 0x93, 0x83, 0x75, 0x7d, 0x9b, 0x86, 0x7d, 0x5a, 0x9d, 0x67, + 0x9f, 0x78, 0x5c, 0xa5, 0x8e, 0xa2, 0xc1, 0x95, 0x89, 0x84, 0x53, 0xd1, + 0x7d, 0x9b, 0xc0, 0x8f, 0x73, 0x7f, 0x85, 0x9e, 0x8a, 0x7b, 0xa6, 0x84, + 0x6c, 0x74, 0x95, 0x93, 0x7a, 0x7a, 0x81, 0x7d, 0x89, 0x86, 0x76, 0x8a, + 0xad, 0x66, 0x90, 0x90, 0x9d, 0x77, 0xb4, 0xad, 0xac, 0x8e, 0xb3, 0xa5, + 0x9d, 0x91, 0xd7, 0x94, 0xba, 0x8b, 0x72, 0xa4, 0x93, 0x7e, 0xa7, 0x86, + 0xae, 0x83, 0x63, 0xa6, 0xa0, 0x78, 0x81, 0x8b, 0xc4, 0x82, 0x8f, 0x98, + 0xa1, 0x8f, 0x79, 0x9a, 0x92, 0x85, 0x9d, 0x91, 0x92, 0x84, 0x8f, 0x84, + 0x91, 0x6d, 0x7b, 0x69, 0x75, 0x87, 0x5d, 0x99, 0x92, 0x83, 0xab, 0x8f, + 0x53, 0x90, 0x7b, 0xa0, 0x71, 0x89, 0xc2, 0x7f, 0x6a, 0x7c, 0x86, 0xb2, + 0x8d, 0x89, 0xaf, 0x9c, 0x81, 0x8c, 0x84, 0xbe, 0x93, 0x9c, 0xa8, 0x97, + 0x68, 0x9b, 0x84, 0xa3, 0x8a, 0x77, 0xa5, 0x79, 0x7b, 0x87, 0x86, 0xa5, + 0x80, 0x83, 0x9e, 0x8d, 0xb1, 0x94, 0x7a, 0x8b, 0xa6, 0xa8, 0x80, 0x98, + 0x8c, 0x73, 0xa9, 0x7b, 0x91, 0x8f, 0x71, 0x82, 0x68, 0x84, 0xa5, 0x96, + 0x67, 0x63, 0xa6, 0x71, 0xa7, 0x85, 0x57, 0x9f, 0x91, 0xb2, 0xa6, 0x87, + 0x80, 0x8f, 0x6a, 0xba, 0x9d, 0xb7, 0xb9, 0x8b, 0x75, 0x7c, 0x6f, 0x9f, + 0x74, 0x8d, 0xaf, 0x6e, 0x7c, 0x65, 0x6c, 0x8a, 0x7c, 0x81, 0x89, 0x77, + 0x8b, 0x74, 0x65, 0x9b, 0xa5, 0x6b, 0x92, 0x71, 0xbb, 0x70, 0x99, 0xbf, + 0xb0, 0x7b, 0x92, 0xb4, 0xa4, 0x84, 0xc4, 0x92, 0xa8, 0x94, 0x7e, 0xcd, + 0x83, 0x87, 0xaf, 0xa0, 0xa5, 0x94, 0x72, 0xb9, 0x90, 0xa6, 0x9e, 0x9e, + 0x9b, 0x7a, 0x68, 0xc0, 0x8f, 0x89, 0x72, 0x94, 0x9b, 0x81, 0x81, 0x91, + 0x88, 0x90, 0xa8, 0x8d, 0x90, 0x78, 0x7c, 0x67, 0x64, 0x8e, 0x55, 0xa1, + 0x6d, 0x86, 0xa3, 0x6f, 0x5c, 0x7d, 0x79, 0xa3, 0x64, 0x71, 0xd4, 0x87, + 0x73, 0x85, 0x76, 0xc7, 0x72, 0x86, 0xb2, 0x8c, 0x7b, 0x8d, 0x96, 0xc3, + 0xad, 0x87, 0xac, 0xa8, 0x84, 0x94, 0x7b, 0xbf, 0x83, 0x74, 0x8e, 0x8c, + 0x9c, 0x99, 0x88, 0x8e, 0x86, 0x88, 0xae, 0x7f, 0x70, 0x96, 0x6f, 0x74, + 0x8f, 0x85, 0x7c, 0x86, 0x97, 0x83, 0xa0, 0x6a, 0x8b, 0x82, 0x88, 0x90, + 0x72, 0x84, 0x9b, 0xa1, 0x6f, 0x72, 0xa4, 0x95, 0xa6, 0x7d, 0x65, 0xbd, + 0x90, 0xb6, 0x9e, 0x98, 0xa1, 0x94, 0x66, 0xb3, 0x9c, 0xb3, 0xa7, 0x7f, + 0x91, 0x69, 0x6e, 0xb1, 0x68, 0x7a, 0xaa, 0x91, 0x7c, 0x71, 0x9f, 0x95, + 0x83, 0x86, 0x76, 0x69, 0x9b, 0x7f, 0x8c, 0x94, 0x9c, 0x89, 0x86, 0x93, + 0xc1, 0x79, 0x98, 0x9e, 0xb1, 0x90, 0x9b, 0xb7, 0xab, 0x86, 0xc6, 0xa1, + 0xa9, 0xaa, 0x86, 0xb0, 0x8b, 0x79, 0xb9, 0x85, 0xbe, 0x92, 0x60, 0xc0, + 0x9f, 0x9a, 0x90, 0x8d, 0xb5, 0x77, 0x95, 0xad, 0x8b, 0x93, 0x8a, 0x93, + 0x93, 0x7e, 0x86, 0xa6, 0x7d, 0x89, 0x6b, 0x81, 0x93, 0x75, 0x7f, 0x86, + 0x66, 0x8f, 0x56, 0x8f, 0x84, 0x75, 0x9e, 0x77, 0x78, 0x89, 0x62, 0xb3, + 0x78, 0x76, 0xb5, 0x92, 0x7f, 0x80, 0x7a, 0xb9, 0x7d, 0x80, 0xc2, 0xb9, + 0x7d, 0x8f, 0x8f, 0x8c, 0xa0, 0x78, 0xa2, 0xaf, 0x68, 0x98, 0x77, 0xac, + 0x96, 0x77, 0x96, 0x99, 0x84, 0xb1, 0x72, 0x8e, 0x96, 0xa4, 0xa9, 0x8e, + 0x84, 0x7b, 0x85, 0x8d, 0x8f, 0x83, 0x83, 0x7f, 0x85, 0x6e, 0xa4, 0x98, + 0xab, 0x83, 0x90, 0x8e, 0x77, 0x8e, 0xab, 0x9c, 0x73, 0x79, 0x8d, 0x6e, + 0xa0, 0x97, 0x68, 0xa7, 0x8a, 0xbd, 0x95, 0x96, 0x96, 0x8b, 0x72, 0xc7, + 0x8d, 0x8c, 0xa5, 0x83, 0x9b, 0x8b, 0x6c, 0xac, 0x62, 0x78, 0xae, 0x78, + 0x71, 0x7a, 0x8d, 0xae, 0x91, 0x87, 0x90, 0x82, 0x9b, 0x83, 0x90, 0x97, + 0xb0, 0x96, 0x82, 0xa5, 0xa9, 0x76, 0xa5, 0xa0, 0xac, 0xa1, 0x93, 0x94, + 0xb7, 0x91, 0xbb, 0x9b, 0xa4, 0xa5, 0x8c, 0xb5, 0x95, 0x7b, 0x92, 0x91, + 0xb0, 0x97, 0x73, 0xb9, 0x86, 0xa7, 0x92, 0x98, 0x9e, 0x70, 0x77, 0xba, + 0x96, 0x7b, 0xa6, 0x86, 0x97, 0x85, 0x8e, 0xaa, 0x93, 0x97, 0x8f, 0x8b, + 0x8d, 0x79, 0x84, 0x7e, 0x70, 0x95, 0x52, 0x8f, 0x62, 0x75, 0x8b, 0x8b, + 0x7b, 0x8b, 0x79, 0xaf, 0x90, 0x6d, 0xc8, 0x8d, 0x84, 0x8c, 0x72, 0xaf, + 0x70, 0x8d, 0xa5, 0x8a, 0x76, 0x97, 0x87, 0x8e, 0xa9, 0x83, 0xb2, 0x8d, + 0x7e, 0x9b, 0x76, 0xc2, 0xa2, 0x72, 0xc5, 0x87, 0x75, 0xb7, 0x92, 0x95, + 0x9e, 0xa0, 0xc3, 0x82, 0x8d, 0x8f, 0x7d, 0x85, 0x90, 0x99, 0x7b, 0x82, + 0x87, 0x87, 0xa0, 0x87, 0x9a, 0x8b, 0xa2, 0xa4, 0x67, 0x93, 0xa5, 0xbb, + 0x73, 0x5f, 0x8c, 0x60, 0xa5, 0x7d, 0x6c, 0xb3, 0xb2, 0xb3, 0xa9, 0xa9, + 0x8d, 0x8d, 0x67, 0xd7, 0x63, 0x99, 0xaa, 0x83, 0x88, 0x6a, 0x6f, 0x9e, + 0x5e, 0x9e, 0x9d, 0x81, 0x84, 0x6e, 0x98, 0x90, 0x89, 0x7c, 0x95, 0x7d, + 0x81, 0x8a, 0xa2, 0x8c, 0x92, 0x85, 0x80, 0x92, 0xac, 0x80, 0x9b, 0x9b, + 0xc3, 0x8c, 0x95, 0xbc, 0xaa, 0x7c, 0xb5, 0x8d, 0xa1, 0xb8, 0x70, 0xb6, + 0x8c, 0x92, 0xa8, 0x8e, 0xa3, 0x76, 0x6c, 0xbe, 0xa0, 0x8c, 0x92, 0x8e, + 0xa1, 0x83, 0x76, 0xb2, 0x91, 0x7b, 0x8e, 0x87, 0x7f, 0x89, 0x8a, 0xa1, + 0x91, 0xa0, 0x7a, 0x95, 0x7b, 0x86, 0x99, 0x92, 0x78, 0x8a, 0x62, 0x9e, + 0x7b, 0x7b, 0x89, 0x79, 0x78, 0x87, 0x82, 0x94, 0x7d, 0x91, 0x96, 0x79, + 0x7b, 0x8d, 0x80, 0xa7, 0x88, 0x95, 0xa6, 0x8f, 0x7d, 0x95, 0x79, 0xa2, + 0x91, 0x9b, 0x9d, 0x90, 0x79, 0xa4, 0x88, 0x98, 0x9b, 0x7a, 0xa5, 0x7f, + 0x71, 0x9c, 0x87, 0x96, 0x8c, 0x8f, 0xbc, 0x74, 0x95, 0x99, 0x7f, 0x78, + 0x8c, 0x63, 0x7c, 0x7a, 0x92, 0x8c, 0xa8, 0x78, 0xa8, 0x89, 0x9a, 0x86, + 0x69, 0x7e, 0xa1, 0xc3, 0x57, 0x68, 0x84, 0x89, 0xa9, 0x8d, 0x6f, 0xa9, + 0x8a, 0xab, 0xa5, 0xad, 0x94, 0x83, 0x6b, 0xa7, 0x7e, 0x95, 0x9b, 0x7f, + 0x8b, 0x78, 0x73, 0x90, 0x65, 0x8d, 0xb1, 0x91, 0x84, 0x65, 0x90, 0xb4, + 0x8c, 0x89, 0x94, 0x7c, 0x99, 0x8b, 0x98, 0xb7, 0xb0, 0x91, 0x9e, 0x88, + 0xbd, 0xa0, 0xa4, 0xb9, 0xad, 0x96, 0x97, 0xa3, 0xb6, 0x81, 0xba, 0x9b, + 0xbc, 0xa9, 0x94, 0xb9, 0xa0, 0x85, 0x8e, 0xa1, 0xac, 0x87, 0x65, 0xa6, + 0x98, 0x8e, 0xaa, 0xa3, 0xa3, 0x7f, 0x79, 0xb4, 0x93, 0x76, 0x90, 0x99, + 0x8b, 0x90, 0x84, 0xa6, 0x90, 0x8f, 0x88, 0xa6, 0x89, 0x83, 0x86, 0x7a, + 0x5d, 0x96, 0x71, 0xa5, 0x64, 0x94, 0x9a, 0x85, 0x7c, 0xa1, 0x96, 0x9d, + 0x76, 0x8f, 0x95, 0xa0, 0x7f, 0x8c, 0x80, 0xc7, 0x6c, 0x7d, 0xb7, 0xb2, + 0x82, 0x8e, 0x82, 0xbd, 0xb3, 0x82, 0x99, 0x9b, 0x80, 0x94, 0x8c, 0x94, + 0x94, 0x6b, 0xc6, 0xa9, 0x81, 0x9f, 0x8c, 0x7e, 0x87, 0x88, 0xb3, 0x7d, + 0x88, 0x8c, 0x81, 0x81, 0x7e, 0x7e, 0x86, 0x87, 0x96, 0x85, 0xb4, 0x87, + 0xab, 0x91, 0x8f, 0xa1, 0x72, 0x83, 0xa4, 0x89, 0x6b, 0x75, 0x85, 0x7c, + 0x94, 0x85, 0x6f, 0xad, 0x91, 0xae, 0xa4, 0xa5, 0xa7, 0x8e, 0x6c, 0xb2, + 0x73, 0x99, 0x96, 0x92, 0x89, 0x81, 0x7d, 0x88, 0x60, 0x8d, 0x94, 0x83, + 0x99, 0x68, 0x86, 0xa2, 0x94, 0x8e, 0x82, 0x76, 0x89, 0x8d, 0x98, 0x86, + 0x94, 0x90, 0x83, 0x7d, 0xad, 0x94, 0xa6, 0x90, 0xcb, 0x96, 0xa2, 0xb2, + 0xb6, 0x89, 0xc4, 0x9d, 0xc7, 0xa5, 0x75, 0xc3, 0x92, 0x8c, 0x8e, 0xad, + 0x96, 0x94, 0x8e, 0xab, 0x94, 0x90, 0xa8, 0x84, 0xb5, 0x84, 0x66, 0xce, + 0x74, 0x8c, 0x93, 0x8d, 0x8f, 0x95, 0x8b, 0xa1, 0x7b, 0xa1, 0x79, 0x9e, + 0x81, 0xa4, 0xa0, 0x98, 0x5f, 0x78, 0x8e, 0x97, 0x6f, 0x81, 0x96, 0x8d, + 0x70, 0x93, 0x72, 0x9c, 0x7b, 0x98, 0x8b, 0x8a, 0x8f, 0x8b, 0x6c, 0xa9, + 0x81, 0x99, 0xb3, 0xa3, 0x71, 0x9c, 0x8b, 0x94, 0xa6, 0x8a, 0xb8, 0xa0, + 0x7b, 0x98, 0x74, 0x9f, 0x92, 0x92, 0xb2, 0x89, 0x81, 0xa8, 0x87, 0x97, + 0x96, 0x86, 0xa4, 0x7b, 0x63, 0x8e, 0x86, 0x7d, 0x76, 0x81, 0x93, 0x94, + 0x98, 0x8b, 0xaf, 0x6d, 0xab, 0x9b, 0x85, 0x9b, 0x91, 0x86, 0x95, 0x95, + 0x65, 0x89, 0x9e, 0x6b, 0xa4, 0x82, 0x68, 0xb5, 0x8b, 0xd1, 0x9d, 0x93, + 0x7d, 0x67, 0x5e, 0xba, 0x9b, 0x94, 0x93, 0x8d, 0x88, 0x73, 0x7c, 0x8e, + 0x7d, 0x83, 0x9a, 0x82, 0xa4, 0x62, 0x9a, 0x8d, 0x86, 0xa0, 0x7b, 0x72, + 0xa9, 0x84, 0xa7, 0x94, 0xb2, 0x98, 0x8f, 0x81, 0xbe, 0x84, 0x9d, 0x94, + 0x9c, 0x9a, 0x94, 0x8f, 0xb1, 0x82, 0xb1, 0x82, 0xb1, 0xb2, 0x78, 0xa7, + 0x95, 0x99, 0x8b, 0x8c, 0xb1, 0x81, 0x5b, 0xbb, 0x88, 0x7a, 0x90, 0xa3, + 0x8d, 0x78, 0x6f, 0xbf, 0x8c, 0x93, 0xa1, 0x8e, 0x9f, 0x98, 0x88, 0xb3, + 0x7e, 0x82, 0x8a, 0x8e, 0x7d, 0x8a, 0x96, 0x6a, 0x6c, 0x7b, 0x91, 0x94, + 0x6f, 0x89, 0x9a, 0x84, 0x73, 0x8b, 0x8c, 0x91, 0x7d, 0x8e, 0x9e, 0x80, + 0x88, 0x81, 0x78, 0xaf, 0x86, 0xa5, 0xa2, 0x8d, 0x6a, 0x8a, 0x75, 0xa1, + 0x83, 0x87, 0xaf, 0x7d, 0x6c, 0xa3, 0x65, 0x77, 0x89, 0x91, 0x9a, 0xa1, + 0xa1, 0xaf, 0x78, 0x94, 0x93, 0xb2, 0xaf, 0x92, 0x74, 0x7a, 0xa7, 0x7b, + 0x8f, 0x9c, 0x86, 0x8d, 0x8f, 0x79, 0xb0, 0xb3, 0x97, 0x82, 0x8e, 0x92, + 0x92, 0x81, 0xa7, 0xbc, 0x6e, 0x6e, 0x89, 0xa5, 0x9a, 0x8d, 0x84, 0xb6, + 0x83, 0xae, 0xa5, 0xa7, 0xae, 0x86, 0x6b, 0xb9, 0x89, 0xb0, 0x8f, 0x82, + 0x8f, 0x6f, 0x83, 0x98, 0x6a, 0x98, 0x9a, 0x85, 0x9f, 0x78, 0x93, 0x8d, + 0x83, 0x88, 0x88, 0x7e, 0x97, 0x99, 0x8a, 0x9b, 0xb0, 0x90, 0x86, 0x88, + 0xb5, 0x90, 0xb3, 0xaa, 0xad, 0x96, 0x93, 0xa3, 0x9d, 0x81, 0xa3, 0x9a, + 0x9f, 0x99, 0x90, 0x9c, 0x9e, 0x8e, 0x88, 0x93, 0xa8, 0x94, 0x62, 0xa6, + 0x94, 0x92, 0xa1, 0x86, 0xb7, 0x8a, 0x6a, 0xa6, 0x81, 0x7e, 0x7b, 0x80, + 0x89, 0x8f, 0x74, 0xa6, 0x72, 0x91, 0xa6, 0x9b, 0x73, 0x97, 0x7e, 0x6f, + 0x70, 0x8d, 0x73, 0x98, 0x80, 0x90, 0x8f, 0x7e, 0x83, 0x77, 0x84, 0x92, + 0x7f, 0x8c, 0x91, 0xa6, 0x99, 0x90, 0x9d, 0xb1, 0x88, 0x85, 0x89, 0x85, + 0x7c, 0x9f, 0x7e, 0xb0, 0xaa, 0x84, 0xa0, 0x8e, 0x74, 0x93, 0x78, 0x90, + 0x9a, 0x8b, 0x8e, 0x97, 0x8f, 0x9f, 0x7c, 0x83, 0x8a, 0x88, 0xa5, 0x8f, + 0x8b, 0x74, 0x84, 0x9a, 0x7f, 0x91, 0x88, 0x77, 0x9c, 0x91, 0xbc, 0x93, + 0x9c, 0x82, 0x89, 0x9b, 0x8a, 0x7d, 0xb7, 0xb8, 0x6f, 0x68, 0xb5, 0x8e, + 0xb4, 0x86, 0x8c, 0xb3, 0x94, 0xb6, 0xa4, 0x93, 0x98, 0x8b, 0x70, 0xb3, + 0x96, 0xaa, 0x87, 0x89, 0x99, 0x68, 0x74, 0xa4, 0x69, 0x9e, 0x8e, 0x6b, + 0x9f, 0x6b, 0x95, 0x9c, 0x88, 0x89, 0x8a, 0x86, 0x8d, 0x75, 0x94, 0x88, + 0xa0, 0x94, 0x77, 0x8c, 0x9c, 0x8d, 0x8e, 0xa4, 0xac, 0xa7, 0x8a, 0x9b, + 0xa9, 0x81, 0xab, 0xac, 0xaf, 0xaf, 0x87, 0xbb, 0x9b, 0x95, 0x8e, 0x9e, + 0x9f, 0xa1, 0x6c, 0xb4, 0x98, 0x8f, 0x81, 0x8d, 0x98, 0x8f, 0x78, 0x96, + 0x89, 0x86, 0x6c, 0x91, 0x8d, 0x9f, 0x95, 0x9f, 0x6b, 0x7f, 0x93, 0x7c, + 0x96, 0x8e, 0x8a, 0x58, 0x80, 0x8e, 0x7a, 0x93, 0x8b, 0x78, 0x99, 0x92, + 0x62, 0x8e, 0x83, 0x8e, 0x87, 0x83, 0x86, 0x99, 0x93, 0x92, 0x80, 0x95, + 0xa2, 0x72, 0xa2, 0x97, 0x78, 0x87, 0x7b, 0xa3, 0x99, 0x78, 0x98, 0x9c, + 0x80, 0x9b, 0x5e, 0x8a, 0x9c, 0x99, 0xa6, 0x7a, 0x8e, 0x99, 0x7a, 0x8e, + 0x8b, 0x76, 0x9b, 0x89, 0x80, 0x8e, 0x83, 0x8a, 0x80, 0x7c, 0x80, 0x74, + 0x95, 0x8c, 0xbf, 0x7e, 0xa8, 0x7a, 0x99, 0x7d, 0x7d, 0x73, 0xb4, 0xae, + 0x88, 0x76, 0xae, 0x78, 0xaa, 0x65, 0x94, 0xbe, 0x97, 0xaf, 0xa4, 0x91, + 0x9c, 0x95, 0x6c, 0xbe, 0x82, 0xb1, 0x9b, 0x91, 0x85, 0x7d, 0x66, 0x9c, + 0x99, 0xbd, 0xa3, 0x88, 0xa8, 0x73, 0x81, 0x94, 0x92, 0x8e, 0x90, 0x8d, + 0xaf, 0x75, 0x86, 0x9b, 0x8b, 0x8b, 0x8d, 0x74, 0xbd, 0x85, 0x97, 0x8b, + 0x9d, 0xba, 0x90, 0xa8, 0x9d, 0x72, 0xa5, 0xa8, 0xbf, 0xbb, 0x7b, 0xb6, + 0xad, 0x94, 0x6f, 0x9a, 0xa7, 0x97, 0x78, 0x9c, 0x98, 0x8d, 0x8c, 0x93, + 0xb8, 0xa8, 0x7f, 0x9d, 0x98, 0x7f, 0x8f, 0x8a, 0x8d, 0xa8, 0x86, 0x7b, + 0x5d, 0x89, 0x8a, 0x83, 0x8c, 0x8b, 0x81, 0x56, 0x7c, 0x87, 0x89, 0xa6, + 0x75, 0x7c, 0x92, 0x74, 0x96, 0x92, 0x78, 0x8d, 0x8d, 0x98, 0xae, 0x7a, + 0x95, 0x8f, 0x8b, 0x9c, 0x95, 0x9f, 0xae, 0x93, 0x7b, 0x93, 0x8c, 0x9a, + 0x79, 0x74, 0x94, 0x6e, 0x7e, 0x8f, 0x64, 0x9f, 0x9c, 0x88, 0x8f, 0x8e, + 0x84, 0x8d, 0x89, 0x95, 0x96, 0x8f, 0x9d, 0x60, 0x85, 0x86, 0x7c, 0x93, + 0x8d, 0x68, 0x83, 0x7c, 0x94, 0x87, 0xb8, 0xa2, 0x9d, 0x82, 0x8e, 0x84, + 0x6c, 0x73, 0xa8, 0xbc, 0x84, 0x85, 0xa2, 0x79, 0x92, 0x64, 0x69, 0xa9, + 0x82, 0xa7, 0x9d, 0x95, 0x8e, 0x6f, 0x9f, 0xa7, 0x97, 0xb1, 0x9d, 0x8e, + 0xa1, 0x70, 0x80, 0x9e, 0x8e, 0x91, 0xa0, 0xaa, 0x81, 0x5b, 0x98, 0x8f, + 0xa0, 0xaa, 0x83, 0x7a, 0x91, 0x7a, 0x73, 0x80, 0xa6, 0x9a, 0x80, 0x7d, + 0x9e, 0x75, 0x7b, 0xa3, 0xad, 0x92, 0x98, 0xc0, 0xa1, 0x80, 0x88, 0xa2, + 0xa5, 0xa4, 0x7e, 0x9b, 0xa0, 0x80, 0x6e, 0xa0, 0x9f, 0xa3, 0x8a, 0x8f, + 0xa2, 0x93, 0x86, 0x8d, 0x8f, 0x93, 0x7e, 0x90, 0x98, 0x83, 0x7d, 0x9b, + 0x9f, 0x9a, 0x97, 0x83, 0x6e, 0x8d, 0x94, 0x6c, 0x7b, 0x7f, 0x73, 0x65, + 0x6a, 0x93, 0x8a, 0x94, 0x83, 0x89, 0x7d, 0x7b, 0x77, 0x8a, 0x7a, 0x9b, + 0x8e, 0x8d, 0x94, 0x89, 0x86, 0x83, 0x7c, 0x8e, 0x8b, 0x90, 0xab, 0x99, + 0x81, 0x8e, 0x77, 0x9c, 0x8c, 0x82, 0x97, 0x8f, 0x78, 0x91, 0x5f, 0xa1, + 0x8b, 0x83, 0xa9, 0x8d, 0x7b, 0x97, 0x77, 0x80, 0x84, 0x7e, 0x9e, 0x75, + 0xa3, 0x86, 0x67, 0x7c, 0x80, 0x6d, 0x77, 0x75, 0x88, 0x75, 0xad, 0x7a, + 0x93, 0x89, 0x8c, 0x87, 0x7a, 0x79, 0xb2, 0xa1, 0x69, 0x80, 0xb5, 0x7a, + 0xa6, 0x7b, 0x95, 0xac, 0x95, 0xa9, 0x98, 0xa4, 0xad, 0x83, 0x8d, 0xbe, + 0xa4, 0x98, 0xad, 0x7d, 0x8b, 0x65, 0x65, 0xad, 0x6a, 0xae, 0xa3, 0xa8, + 0x9c, 0x63, 0x90, 0x91, 0x6d, 0x9a, 0x81, 0x98, 0x86, 0x6a, 0x83, 0x84, + 0x94, 0x9c, 0x77, 0x86, 0xc2, 0x7f, 0x9b, 0xa9, 0xad, 0xae, 0xa7, 0xa6, + 0xd4, 0x70, 0x9d, 0xb5, 0xaa, 0xdb, 0x8f, 0xa3, 0xa5, 0x87, 0x88, 0x9e, + 0xa9, 0x9f, 0x62, 0xa7, 0xa2, 0x8e, 0x7d, 0x8a, 0x9d, 0xa2, 0x6b, 0xa7, + 0x96, 0x6d, 0x76, 0x8c, 0x9b, 0x8c, 0x86, 0x86, 0x93, 0x7c, 0x9d, 0x7c, + 0x7e, 0x93, 0x5c, 0x79, 0x76, 0x8c, 0x8a, 0x87, 0x79, 0x97, 0x9a, 0x7a, + 0x85, 0x8c, 0x7f, 0x85, 0x7a, 0xa1, 0xa7, 0x72, 0x87, 0x7f, 0x96, 0x9e, + 0x92, 0x92, 0x9e, 0xa0, 0x72, 0x99, 0x7a, 0xb0, 0x8c, 0x8d, 0xa3, 0x9b, + 0x91, 0xa6, 0x63, 0x94, 0x8b, 0x81, 0xbb, 0x94, 0x79, 0x95, 0x99, 0x9a, + 0xa0, 0x7a, 0x96, 0x72, 0x82, 0x9a, 0x83, 0x7f, 0x72, 0x7f, 0x6d, 0x75, + 0x91, 0x7f, 0xbc, 0x84, 0x9a, 0x81, 0x95, 0x69, 0x7d, 0x6d, 0xa2, 0xa8, + 0x7e, 0x64, 0xac, 0x86, 0x85, 0x6d, 0x99, 0xaa, 0x7e, 0x79, 0x9c, 0xa0, + 0xa4, 0x77, 0x99, 0xac, 0xa8, 0x8d, 0xb7, 0xa2, 0xa3, 0x61, 0x82, 0x98, + 0x84, 0x8e, 0xa1, 0x8c, 0x88, 0x82, 0x6f, 0x7d, 0x88, 0x80, 0x7a, 0x8a, + 0x8c, 0x6d, 0x87, 0x6f, 0xab, 0x8f, 0x8b, 0x76, 0xa0, 0x7d, 0x9f, 0xab, + 0xb0, 0xb8, 0x9c, 0x8d, 0xb8, 0x81, 0x89, 0x94, 0xa8, 0xc8, 0x92, 0x9b, + 0x8d, 0x83, 0x7b, 0xaf, 0x97, 0x94, 0x6e, 0xa5, 0x9b, 0x97, 0x89, 0x8d, + 0xaa, 0x8a, 0x66, 0x88, 0x93, 0x84, 0xa1, 0x88, 0xa0, 0x99, 0x85, 0x89, + 0x7d, 0x84, 0x8b, 0x6a, 0x92, 0xa1, 0x74, 0x76, 0x73, 0x87, 0x7a, 0x9a, + 0x77, 0x86, 0x89, 0x5f, 0x7f, 0x8b, 0x7f, 0x8d, 0x7e, 0x81, 0x95, 0x8a, + 0x7d, 0x85, 0x74, 0x9a, 0x87, 0x8c, 0x9e, 0xae, 0x80, 0x88, 0x7d, 0x8b, + 0xaa, 0x79, 0x7c, 0x97, 0x79, 0x90, 0x7b, 0x97, 0x97, 0x9f, 0xa1, 0xa2, + 0xab, 0x97, 0x69, 0x7a, 0x8d, 0x9f, 0x9f, 0x89, 0x90, 0x8c, 0x66, 0x98, + 0x6e, 0x86, 0x7b, 0x6e, 0x86, 0x8a, 0xb2, 0xa6, 0x93, 0x7d, 0x8c, 0x81, + 0x7e, 0x84, 0xa6, 0xb6, 0x83, 0x92, 0xa0, 0x88, 0x90, 0x5f, 0x7c, 0x92, + 0x98, 0x94, 0x92, 0x98, 0xa7, 0x65, 0x90, 0xa2, 0xa2, 0x9b, 0xa6, 0x7d, + 0x8b, 0x5a, 0x94, 0x95, 0x9b, 0xa5, 0x99, 0xa5, 0x7e, 0x61, 0x9a, 0x7a, + 0x8b, 0x77, 0x87, 0x76, 0x9d, 0x72, 0x9a, 0x84, 0x98, 0x94, 0x92, 0x73, + 0xae, 0x78, 0x8e, 0xaa, 0xa0, 0xc3, 0x7a, 0xa4, 0xa0, 0x75, 0xa9, 0xae, + 0x8c, 0xd6, 0x87, 0x8f, 0x9f, 0x8c, 0x9b, 0x90, 0x99, 0x97, 0x73, 0x8f, + 0x9b, 0x9c, 0x8c, 0x89, 0xa5, 0x84, 0x8f, 0x7b, 0x8b, 0x7f, 0x97, 0x98, + 0x8d, 0x7b, 0x94, 0x9d, 0x9c, 0x8e, 0x92, 0x89, 0x88, 0x8d, 0x6c, 0x63, + 0x73, 0x81, 0x72, 0x8a, 0x88, 0x8a, 0x9f, 0x79, 0x81, 0x82, 0x9a, 0xa9, + 0x7a, 0x92, 0x7d, 0x76, 0x7b, 0x7a, 0x6a, 0xbe, 0x91, 0x7d, 0x86, 0xad, + 0x84, 0x86, 0x6c, 0x91, 0x91, 0x9f, 0x92, 0x6b, 0x95, 0x98, 0x84, 0xa0, + 0x8f, 0x8b, 0x9e, 0x7f, 0x9f, 0x97, 0x7e, 0x87, 0x80, 0x9e, 0x79, 0x8d, + 0x68, 0x87, 0x88, 0x7d, 0x89, 0x81, 0x6d, 0x85, 0x80, 0x82, 0xa0, 0x97, + 0xa3, 0x72, 0x94, 0x74, 0x8e, 0x56, 0x96, 0x98, 0x91, 0x6f, 0xa0, 0xae, + 0x7c, 0x6e, 0x8e, 0xa9, 0x7c, 0x80, 0x87, 0xa3, 0x9e, 0x57, 0x8e, 0xb5, + 0x87, 0xa6, 0x87, 0x79, 0x8f, 0x55, 0x8a, 0x81, 0x97, 0x6c, 0x9b, 0x99, + 0x78, 0x5c, 0x82, 0x80, 0x91, 0x76, 0x80, 0x91, 0x8b, 0x65, 0x89, 0x7d, + 0xa9, 0x95, 0x89, 0x97, 0x96, 0x6a, 0x89, 0xad, 0x92, 0x9f, 0xb6, 0x82, + 0x88, 0x79, 0x9d, 0xa5, 0x9c, 0xae, 0x9a, 0x93, 0x77, 0x8e, 0x8a, 0xb5, + 0x84, 0xb0, 0x76, 0xa2, 0x89, 0xa0, 0x96, 0x7a, 0xa5, 0x8e, 0x7e, 0x74, + 0x8d, 0x89, 0x89, 0x9e, 0x93, 0x95, 0x90, 0x78, 0x93, 0x8f, 0xa5, 0x7c, + 0x9d, 0x7c, 0x77, 0x85, 0x81, 0x92, 0x7c, 0x87, 0x92, 0x82, 0x98, 0xa3, + 0x63, 0x76, 0x9b, 0x91, 0x7b, 0x8e, 0x97, 0x7e, 0x66, 0x90, 0x63, 0xb4, + 0x71, 0x88, 0x86, 0x8e, 0x6f, 0x89, 0x7a, 0x88, 0x93, 0x7f, 0x96, 0xa8, + 0x7d, 0x88, 0x88, 0x86, 0x7b, 0x91, 0x88, 0x6b, 0xa6, 0x8b, 0x69, 0x78, + 0x82, 0x80, 0x83, 0x6b, 0xaf, 0x81, 0x7b, 0x64, 0x8f, 0x78, 0x6e, 0x7f, + 0x86, 0x91, 0x92, 0xa3, 0xa0, 0x97, 0x82, 0x88, 0x92, 0x90, 0x9e, 0x89, + 0x9d, 0x7b, 0x96, 0x82, 0xa3, 0x8c, 0x7f, 0x84, 0x7a, 0x6c, 0x60, 0x85, + 0xa9, 0x74, 0x83, 0xa2, 0x89, 0x87, 0x9b, 0x77, 0x9b, 0x9a, 0x99, 0x84, + 0x7c, 0x9c, 0x8d, 0x90, 0x8d, 0x7b, 0x74, 0x77, 0x93, 0x8c, 0x6c, 0x8b, + 0x85, 0x78, 0x7f, 0x7d, 0x75, 0x7f, 0x7e, 0x85, 0x8f, 0x7d, 0x62, 0x8c, + 0x7c, 0xad, 0x7f, 0x83, 0xa1, 0xa1, 0x97, 0x7b, 0x72, 0x82, 0x9d, 0x81, + 0x94, 0x81, 0x8d, 0x9f, 0x6f, 0x8f, 0x9d, 0x89, 0x6a, 0x7e, 0x7f, 0x7f, + 0x8d, 0x7e, 0x91, 0x86, 0x7d, 0x8a, 0x7e, 0x70, 0x7b, 0x9b, 0x6e, 0x5f, + 0xa8, 0x7a, 0x73, 0x8a, 0x7a, 0x71, 0x90, 0x95, 0x8d, 0x78, 0x7b, 0x72, + 0x5e, 0x89, 0x62, 0xa1, 0x87, 0x7f, 0x83, 0x75, 0x98, 0x7f, 0x76, 0x72, + 0x8f, 0x9b, 0x7a, 0x8b, 0xa1, 0x7f, 0x60, 0x99, 0x96, 0x6e, 0x67, 0x76, + 0x88, 0x98, 0x6c, 0x7b, 0x9b, 0x8d, 0x5f, 0x89, 0x7c, 0x81, 0x79, 0x86, + 0x69, 0x9e, 0x83, 0x65, 0x8e, 0x82, 0x83, 0x89, 0x85, 0x7f, 0x90, 0x80, + 0xa2, 0x81, 0x85, 0x83, 0x8e, 0x94, 0x94, 0x75, 0x86, 0x87, 0x9a, 0xb2, + 0x82, 0x99, 0x85, 0x7f, 0x8c, 0x7e, 0x81, 0x9a, 0x81, 0x7d, 0x87, 0x81, + 0xa3, 0x8c, 0x8d, 0x85, 0x8d, 0x96, 0x86, 0x7c, 0xa7, 0x87, 0x7e, 0x9d, + 0x63, 0xa8, 0x7c, 0x97, 0xa2, 0xa4, 0x7e, 0x87, 0x93, 0x9e, 0x89, 0x8d, + 0x6b, 0x6d, 0x9d, 0x9b, 0x78, 0x8a, 0x8e, 0x7f, 0x7b, 0xa5, 0x6e, 0x8c, + 0x89, 0x88, 0x73, 0x7e, 0x77, 0x9d, 0xa6, 0xa7, 0x77, 0x87, 0x7e, 0x7e, + 0x97, 0x84, 0x6b, 0x59, 0x60, 0x90, 0x85, 0x76, 0x8f, 0x61, 0x7f, 0x94, + 0x8f, 0x84, 0x8b, 0x7f, 0x73, 0x77, 0x73, 0x71, 0x8a, 0x9b, 0x7b, 0x89, + 0x97, 0x8f, 0x76, 0x63, 0xa3, 0xa1, 0x6b, 0x7c, 0x62, 0x95, 0x8e, 0xa3, + 0x9f, 0x89, 0x8f, 0x7f, 0x92, 0x7c, 0xa2, 0xa4, 0xa6, 0x92, 0x89, 0x93, + 0x74, 0x73, 0x73, 0x96, 0xad, 0x9b, 0x87, 0xac, 0x91, 0x8a, 0xa0, 0x70, + 0x70, 0x7e, 0x8f, 0x74, 0x75, 0xaf, 0x8d, 0x82, 0x8e, 0x82, 0x96, 0x7d, + 0x69, 0x9c, 0x64, 0xa2, 0x82, 0x89, 0x83, 0x9d, 0x83, 0x88, 0x62, 0x92, + 0x72, 0x89, 0x6d, 0x7f, 0x92, 0x70, 0x8e, 0x80, 0x7e, 0x8d, 0x91, 0x85, + 0x8d, 0x89, 0x83, 0x96, 0x90, 0x96, 0x9c, 0xa6, 0x8a, 0x73, 0x89, 0x79, + 0xa9, 0x70, 0x80, 0x78, 0x96, 0x80, 0x7b, 0x85, 0xa5, 0x80, 0x93, 0x95, + 0xc5, 0x74, 0x81, 0x88, 0xa2, 0x93, 0x86, 0x9c, 0xa3, 0x6d, 0x92, 0x8a, + 0x92, 0x99, 0x98, 0x65, 0xad, 0x63, 0x9d, 0x95, 0x99, 0x89, 0x7f, 0x7a, + 0x99, 0x91, 0x7f, 0x78, 0x90, 0x8f, 0x80, 0x85, 0xa1, 0x68, 0x9d, 0x6c, + 0x83, 0x8f, 0x7c, 0x5e, 0x99, 0x7b, 0x80, 0x91, 0x66, 0x8a, 0x92, 0xb3, + 0x7a, 0x99, 0x91, 0x7e, 0x7d, 0x96, 0x69, 0x9e, 0x7c, 0x89, 0xad, 0x8f, + 0x9d, 0x90, 0x85, 0x8e, 0x72, 0xa9, 0x89, 0x83, 0x7c, 0x82, 0x70, 0x82, + 0x6b, 0x79, 0x75, 0x8d, 0x77, 0x9b, 0x7c, 0x8f, 0x8a, 0x95, 0x87, 0x9f, + 0x7c, 0x90, 0x87, 0x70, 0x83, 0x83, 0x98, 0x9f, 0x85, 0x86, 0x8d, 0x81, + 0x87, 0x87, 0x87, 0x9d, 0x8f, 0x9d, 0x7c, 0x98, 0xa2, 0xac, 0x88, 0x93, + 0x88, 0x7d, 0x9b, 0x76, 0x82, 0x67, 0x69, 0x7f, 0x8c, 0x8d, 0x94, 0x7d, + 0x7b, 0xae, 0x8c, 0x85, 0x8b, 0xa7, 0x8c, 0x87, 0x96, 0x7d, 0x8b, 0x90, + 0x90, 0x7c, 0x92, 0xa8, 0x81, 0x87, 0xa4, 0xa4, 0x82, 0x8b, 0x8d, 0x89, + 0x8f, 0x70, 0x9d, 0x7f, 0xa0, 0x84, 0x99, 0x65, 0x99, 0x78, 0x94, 0x8b, + 0xc5, 0x8d, 0x8d, 0x55, 0xb3, 0x8d, 0x78, 0x93, 0xb4, 0x6d, 0x84, 0x90, + 0xd5, 0x76, 0x7a, 0x9e, 0xc8, 0x8f, 0x86, 0x8a, 0xaa, 0x8b, 0x7f, 0x90, + 0xaa, 0x95, 0x9c, 0x81, 0xb4, 0x6b, 0x64, 0x8a, 0x99, 0x84, 0x74, 0x6e, + 0x95, 0x75, 0x98, 0x92, 0x9a, 0x91, 0x8c, 0x7d, 0x88, 0x6e, 0x89, 0x7d, + 0x87, 0x80, 0x8e, 0x86, 0x78, 0x9f, 0x96, 0x75, 0x76, 0x82, 0x84, 0xaf, + 0x8a, 0xb3, 0x93, 0x97, 0x86, 0x7c, 0x7e, 0x96, 0x7c, 0x6d, 0x90, 0x8e, + 0x85, 0x88, 0x8a, 0x9f, 0x70, 0x89, 0x9f, 0x99, 0x95, 0x87, 0x91, 0x9d, + 0x80, 0x74, 0x88, 0x7c, 0x7f, 0xa8, 0x93, 0x77, 0x66, 0xa6, 0x80, 0xa2, + 0x88, 0xa0, 0xaf, 0x6f, 0x76, 0x70, 0x82, 0x9a, 0x73, 0x89, 0x9a, 0x75, + 0x75, 0x8e, 0x5f, 0x85, 0x6a, 0x76, 0x98, 0x66, 0x87, 0xa3, 0x7a, 0x73, + 0x9d, 0xa1, 0x98, 0x8e, 0x78, 0x91, 0x83, 0x8c, 0x82, 0x9e, 0x90, 0x87, + 0x8f, 0x9b, 0x8b, 0x8f, 0x89, 0x62, 0x74, 0x82, 0x7b, 0x7f, 0x8a, 0x9d, + 0x89, 0x93, 0x8c, 0x7a, 0x99, 0x77, 0xac, 0x75, 0x9b, 0x7f, 0x7f, 0x56, + 0x8c, 0x96, 0x70, 0x79, 0xc2, 0x7d, 0x90, 0x64, 0xe9, 0x79, 0x68, 0xb2, + 0xc2, 0xa6, 0xa7, 0x7e, 0xd9, 0x98, 0x79, 0x87, 0xc0, 0x97, 0x87, 0x66, + 0xd0, 0x9f, 0x92, 0x82, 0xa4, 0xa8, 0x8d, 0x78, 0xa6, 0xa1, 0x76, 0x7d, + 0xa4, 0x87, 0x89, 0x51, 0xae, 0x88, 0x5b, 0x76, 0x7d, 0x70, 0x74, 0x93, + 0x89, 0x74, 0x9e, 0x7a, 0x79, 0x64, 0x9a, 0x94, 0x65, 0x93, 0xb0, 0x8d, + 0x88, 0x7e, 0x8e, 0xa5, 0x63, 0x94, 0x94, 0x7d, 0x91, 0x87, 0x84, 0x95, + 0x75, 0x9e, 0x81, 0x99, 0x65, 0x76, 0x82, 0x9c, 0x6a, 0xab, 0x84, 0x85, + 0x88, 0x72, 0x92, 0x83, 0x82, 0xaf, 0x6d, 0x9d, 0x9e, 0x73, 0x98, 0x7f, + 0x91, 0xb4, 0x62, 0x8d, 0x74, 0x6e, 0xb4, 0x94, 0x97, 0x9e, 0x6f, 0x9a, + 0x83, 0x7b, 0xa9, 0x7d, 0x87, 0x97, 0x60, 0xa9, 0x7a, 0x75, 0xad, 0x6c, + 0x77, 0xa4, 0x88, 0x82, 0x6f, 0x8a, 0x83, 0x74, 0x9a, 0xa7, 0x83, 0x91, + 0x7c, 0x7c, 0x78, 0x77, 0x83, 0x92, 0x7a, 0x83, 0x90, 0x6f, 0x79, 0x6b, + 0x9b, 0x8d, 0x99, 0x95, 0x7b, 0x89, 0x8e, 0x6c, 0x8e, 0x6c, 0x9b, 0x91, + 0x97, 0x80, 0x83, 0x6f, 0xaa, 0x91, 0x66, 0x76, 0xc9, 0x77, 0x82, 0x4d, + 0xd7, 0x5f, 0x58, 0x9a, 0xb1, 0x7a, 0xb1, 0x6b, 0xe5, 0x9d, 0x76, 0x89, + 0xb6, 0x94, 0x90, 0x5b, 0xb8, 0x92, 0x7d, 0x90, 0xbd, 0x9a, 0x85, 0x4e, + 0xb4, 0x84, 0x61, 0x82, 0x94, 0x8e, 0x70, 0x57, 0x90, 0x89, 0x6f, 0x60, + 0x78, 0x90, 0x78, 0x85, 0x8e, 0x7c, 0x76, 0x74, 0x71, 0x5d, 0x94, 0x93, + 0x71, 0x8f, 0xc2, 0x80, 0x75, 0x7d, 0x77, 0xa8, 0x70, 0x8f, 0xa6, 0x83, + 0x74, 0x6b, 0x79, 0x97, 0x76, 0xa2, 0xad, 0x93, 0x5b, 0x8c, 0x7c, 0x7e, + 0x82, 0x9b, 0xa0, 0x76, 0x71, 0x7a, 0xa3, 0x80, 0x87, 0x90, 0x92, 0xa6, + 0x85, 0x71, 0x99, 0x91, 0x91, 0x8c, 0x99, 0x9b, 0x92, 0x74, 0xb2, 0x79, + 0x9c, 0x7c, 0x7b, 0xa8, 0x8c, 0x6f, 0xb5, 0x69, 0x7a, 0x8a, 0x68, 0x9f, + 0x82, 0x7d, 0xbd, 0x5f, 0xa1, 0x92, 0x83, 0x9f, 0x6f, 0xa1, 0x88, 0x61, + 0x7b, 0x94, 0x89, 0x83, 0x6f, 0x6e, 0x92, 0x9d, 0x65, 0x7f, 0x97, 0x83, + 0x87, 0x75, 0x92, 0x8a, 0x82, 0x82, 0x79, 0x92, 0x78, 0x89, 0x92, 0x7a, + 0x91, 0x64, 0x8a, 0x93, 0x9d, 0x74, 0x78, 0x64, 0xab, 0x57, 0x7a, 0x84, + 0xcf, 0x7d, 0x95, 0x4f, 0xde, 0x63, 0x78, 0x9a, 0xb7, 0x7a, 0x8b, 0x5b, + 0xda, 0xa3, 0x94, 0x99, 0xbd, 0x88, 0xa4, 0x53, 0xad, 0x8b, 0x81, 0x96, + 0xca, 0x8f, 0x76, 0x5e, 0xbd, 0x9d, 0x70, 0x81, 0x9b, 0x7d, 0x8a, 0x44, + 0xa0, 0x77, 0x52, 0x6e, 0x82, 0x62, 0x6a, 0x6b, 0x9d, 0xaa, 0x81, 0x85, + 0x7d, 0x5f, 0x7f, 0x9c, 0x65, 0x99, 0x97, 0x81, 0x7f, 0x65, 0x65, 0xa4, + 0x84, 0x8c, 0xa1, 0x6d, 0x7a, 0x70, 0x79, 0x90, 0x98, 0xaa, 0x76, 0x95, + 0x7f, 0x91, 0x95, 0x96, 0x6e, 0xa5, 0x95, 0xa2, 0x7d, 0x7e, 0x93, 0x87, + 0x7d, 0x9b, 0x85, 0x9b, 0x85, 0x79, 0x96, 0x6b, 0x9d, 0x9d, 0x61, 0x99, + 0x9c, 0x74, 0xcc, 0x7e, 0x9a, 0x83, 0x83, 0x98, 0x6f, 0x6d, 0xc5, 0x69, + 0xb0, 0xa5, 0x5c, 0x91, 0x6c, 0x7b, 0xcc, 0x72, 0x9a, 0x9d, 0x7e, 0xa3, + 0x8a, 0x96, 0x8e, 0x74, 0x7b, 0x80, 0x6b, 0x85, 0x84, 0x56, 0x92, 0x83, + 0x64, 0x90, 0x86, 0x86, 0x88, 0x79, 0x8b, 0xa0, 0x86, 0x72, 0xab, 0x95, + 0x80, 0x81, 0x96, 0x8f, 0x75, 0x7f, 0x71, 0x92, 0x9e, 0x75, 0x62, 0x5e, + 0xc3, 0x7a, 0x6c, 0x84, 0xba, 0x81, 0x8f, 0x49, 0xc9, 0x76, 0x54, 0x89, + 0xc2, 0x8c, 0xa2, 0x54, 0xd8, 0xa4, 0x72, 0x90, 0xb1, 0x91, 0xa0, 0x7a, + 0xbf, 0x9a, 0x6f, 0x82, 0xbb, 0x81, 0x6a, 0x52, 0xc2, 0x82, 0x52, 0x65, + 0x8d, 0x8a, 0x84, 0x46, 0xa2, 0x90, 0x45, 0x52, 0x82, 0x61, 0x8c, 0x77, + 0x92, 0x6d, 0x87, 0x5b, 0x5e, 0x72, 0x76, 0x97, 0x73, 0x8d, 0x8d, 0x70, + 0x7a, 0x66, 0x76, 0x89, 0x72, 0xbf, 0xb0, 0x84, 0x7d, 0x80, 0x71, 0x8f, + 0x85, 0xa9, 0xa3, 0x7d, 0x7b, 0x84, 0x83, 0xa1, 0x97, 0xa7, 0xaf, 0x84, + 0x86, 0x7d, 0x94, 0x78, 0x80, 0x98, 0x71, 0x84, 0x94, 0x73, 0xb0, 0x74, + 0x99, 0xa2, 0x68, 0xa7, 0x8b, 0x86, 0xe0, 0x75, 0x9e, 0x93, 0x5c, 0xb2, + 0xa2, 0x68, 0xb8, 0x61, 0x92, 0xa3, 0x68, 0xa4, 0x89, 0x59, 0xd0, 0x77, + 0x97, 0xa9, 0x6a, 0x9b, 0x7d, 0x69, 0x9b, 0x79, 0x8c, 0x7c, 0x68, 0x8b, + 0x7a, 0x53, 0x99, 0x9c, 0x7e, 0x8d, 0x89, 0x96, 0x9e, 0x83, 0x89, 0x74, + 0x7f, 0x94, 0x92, 0x8f, 0x85, 0x8a, 0x8a, 0x80, 0x99, 0x87, 0x7a, 0x7d, + 0xac, 0x93, 0x74, 0x68, 0xba, 0x87, 0x6a, 0x98, 0xc7, 0x79, 0x91, 0x54, + 0xeb, 0x80, 0x45, 0x80, 0xc4, 0xb4, 0x94, 0x61, 0xd2, 0xa6, 0x7b, 0x95, + 0xa4, 0xaa, 0x93, 0x7b, 0xb1, 0x74, 0x53, 0x7c, 0xaa, 0x91, 0x64, 0x51, + 0xa9, 0x6e, 0x5e, 0x7c, 0x79, 0x82, 0x8b, 0x2e, 0x9d, 0x66, 0x61, 0x5e, + 0x72, 0x7f, 0x6e, 0x6d, 0x8c, 0x79, 0x7d, 0x60, 0x76, 0x79, 0x68, 0x84, + 0x4d, 0x8e, 0xa8, 0x8f, 0x78, 0x74, 0x69, 0xa4, 0x6e, 0xa9, 0xb9, 0x59, + 0x83, 0x7f, 0x7a, 0x93, 0x90, 0x9b, 0x8d, 0x93, 0x78, 0x80, 0x77, 0x8b, + 0x72, 0xa3, 0x97, 0x73, 0x91, 0x6c, 0x9a, 0x97, 0xa3, 0xad, 0x89, 0x96, + 0x9e, 0x6d, 0xb5, 0x7c, 0xa4, 0x98, 0x61, 0x8a, 0x93, 0x5f, 0xdc, 0x63, + 0xba, 0x92, 0x84, 0x94, 0xab, 0x6f, 0xbf, 0x66, 0x98, 0x93, 0x74, 0x85, + 0x96, 0x63, 0xb8, 0x60, 0x94, 0xbb, 0x79, 0x94, 0x7b, 0x67, 0x8a, 0x64, + 0x99, 0xac, 0x60, 0x98, 0xb0, 0x65, 0xa2, 0x73, 0x8f, 0x94, 0x8c, 0x92, + 0x84, 0x84, 0x9b, 0x8f, 0x84, 0x8d, 0x9f, 0x90, 0x91, 0x85, 0x93, 0x74, + 0x97, 0x66, 0x7f, 0x78, 0xa2, 0x95, 0x73, 0x6b, 0xc5, 0x6f, 0x62, 0x79, + 0xbd, 0x81, 0x89, 0x4a, 0xbd, 0x93, 0x57, 0x81, 0xba, 0xb0, 0x9b, 0x4c, + 0xe8, 0xa2, 0x85, 0xa2, 0x96, 0x92, 0x93, 0x62, 0xbe, 0x7a, 0x71, 0x8b, + 0x8d, 0x97, 0x53, 0x56, 0xb1, 0x5f, 0x67, 0x60, 0x7a, 0x8e, 0x8a, 0x3a, + 0x86, 0x67, 0x6d, 0x53, 0x6e, 0x91, 0x7b, 0x60, 0x99, 0x6d, 0x71, 0x5d, + 0x67, 0x65, 0x63, 0x87, 0x71, 0x8a, 0x92, 0x6d, 0x8f, 0x6f, 0x6f, 0xae, + 0x6c, 0xa2, 0x87, 0x6f, 0x99, 0x88, 0x78, 0x94, 0x8a, 0xb2, 0x93, 0x89, + 0x90, 0x8d, 0x8c, 0x98, 0x81, 0x86, 0x90, 0x6d, 0xa2, 0x82, 0xa2, 0xa3, + 0x9d, 0x8f, 0x7a, 0x9f, 0x87, 0x70, 0xbd, 0x8e, 0xa5, 0x99, 0x5d, 0x70, + 0x8c, 0x60, 0xc7, 0x78, 0x97, 0xb0, 0x6f, 0x94, 0x92, 0x5a, 0xc3, 0x6e, + 0x8b, 0x9f, 0x79, 0xa3, 0x8c, 0x5e, 0xbf, 0x79, 0x8e, 0x98, 0x76, 0x8e, + 0x67, 0x31, 0x9b, 0x85, 0x8e, 0x85, 0x71, 0x99, 0x72, 0x77, 0x84, 0x81, + 0x91, 0x95, 0x80, 0x98, 0x82, 0x6f, 0x90, 0xa0, 0x91, 0x91, 0x8e, 0x75, + 0x8a, 0x89, 0x93, 0x69, 0x95, 0x7f, 0x9a, 0xa0, 0x9e, 0x9b, 0x88, 0x4e, + 0xc3, 0x8d, 0x65, 0x74, 0xba, 0x8d, 0x97, 0x4d, 0xd6, 0x94, 0x73, 0xa0, + 0xb1, 0xb3, 0x8c, 0x67, 0xdd, 0x9f, 0x7f, 0xaa, 0xaf, 0x9a, 0x88, 0x67, + 0xc2, 0x8f, 0x71, 0x7b, 0x8f, 0x9f, 0x47, 0x52, 0x93, 0x72, 0x5a, 0x52, + 0x97, 0x9d, 0x67, 0x3c, 0xa9, 0x59, 0x59, 0x5b, 0x88, 0x92, 0x82, 0x57, + 0x83, 0x67, 0x94, 0x77, 0x52, 0x74, 0x60, 0x9e, 0x52, 0x84, 0xa2, 0x69, + 0x71, 0x96, 0x73, 0xb0, 0x5e, 0xb0, 0x89, 0x71, 0x94, 0x8a, 0x66, 0xa0, + 0x75, 0xc1, 0x99, 0x8e, 0x83, 0x8a, 0x91, 0x89, 0x6b, 0xa5, 0x79, 0x82, + 0x8b, 0x73, 0x95, 0xb0, 0x77, 0x9b, 0x82, 0x7d, 0x8f, 0x60, 0xb9, 0x78, + 0x8b, 0x8f, 0x7b, 0x74, 0x84, 0x6d, 0xbf, 0x76, 0x8f, 0xa3, 0x91, 0xa1, + 0x81, 0x59, 0xcb, 0x69, 0xac, 0x90, 0x98, 0x92, 0xa7, 0x5d, 0xb4, 0x8b, + 0xaa, 0xb1, 0x98, 0x8c, 0xa2, 0x4d, 0xa1, 0x69, 0x7f, 0xa0, 0x7d, 0x8a, + 0x9b, 0x77, 0x8e, 0x71, 0x82, 0x8a, 0x78, 0x8d, 0x98, 0x78, 0x90, 0x91, + 0x7e, 0x7f, 0x78, 0x85, 0x97, 0x8a, 0x97, 0x6d, 0xb3, 0x94, 0x89, 0xa3, + 0xa5, 0x9a, 0x76, 0x6b, 0xbd, 0x79, 0x71, 0x95, 0xce, 0xab, 0x93, 0x1f, + 0xe9, 0x97, 0x4c, 0x84, 0xd5, 0x9f, 0x98, 0x6e, 0xdd, 0x8d, 0x80, 0x9c, + 0xa8, 0x9e, 0x8d, 0x75, 0xbc, 0x8c, 0x80, 0x89, 0xa1, 0x89, 0x74, 0x58, + 0x92, 0x86, 0x55, 0x87, 0x91, 0x8d, 0x70, 0x33, 0xb8, 0x50, 0x63, 0x6b, + 0x79, 0x99, 0x76, 0x71, 0x75, 0x59, 0x73, 0x6b, 0x62, 0x62, 0x74, 0x85, + 0x73, 0xa3, 0xac, 0x78, 0x77, 0x88, 0x64, 0xa0, 0x73, 0xa1, 0xa8, 0x73, + 0x91, 0x8e, 0x5f, 0x9a, 0x68, 0xc9, 0xa1, 0x92, 0x7a, 0x7c, 0x69, 0x77, + 0x7d, 0x9e, 0x8f, 0x76, 0x88, 0x80, 0x92, 0x93, 0x91, 0x99, 0x8c, 0x85, + 0x9f, 0x69, 0xa8, 0x9b, 0x9f, 0x9a, 0x64, 0x7a, 0x99, 0x70, 0xc4, 0x6d, + 0x9a, 0x99, 0x82, 0xa0, 0x8b, 0x59, 0xc8, 0x61, 0x8f, 0x95, 0x72, 0x8c, + 0x90, 0x63, 0xa9, 0x7e, 0x88, 0x8c, 0x85, 0x78, 0x76, 0x58, 0x8e, 0x72, + 0xa3, 0x9a, 0x7c, 0xa0, 0x7f, 0x6d, 0xa6, 0x83, 0x7e, 0x8d, 0x83, 0x88, + 0x86, 0x68, 0x8d, 0x96, 0xaa, 0x78, 0x90, 0xa5, 0x9c, 0x9d, 0x99, 0x88, + 0xb0, 0x82, 0x6f, 0x7e, 0xad, 0xa9, 0x7b, 0x6a, 0xba, 0x6c, 0x6d, 0x89, + 0xc1, 0x9e, 0x8e, 0x2f, 0xf2, 0x77, 0x50, 0x73, 0xdb, 0xc4, 0x9c, 0x6c, + 0xd0, 0x90, 0x88, 0xbe, 0x97, 0xb9, 0x9e, 0x6e, 0xbe, 0x8e, 0x83, 0x8e, + 0x96, 0x98, 0x4c, 0x4e, 0xa7, 0x8d, 0x43, 0x92, 0x8f, 0x92, 0x6d, 0x27, + 0x94, 0x73, 0x5f, 0x42, 0x7c, 0xa7, 0x8a, 0x5a, 0x81, 0x60, 0x85, 0x66, + 0x73, 0x72, 0x74, 0x9d, 0x5a, 0x9e, 0xa3, 0x71, 0x75, 0x91, 0x4f, 0xa2, + 0x67, 0xa6, 0x91, 0x64, 0x92, 0x7e, 0x95, 0x8d, 0x6e, 0xbe, 0x9b, 0x57, + 0x9b, 0x82, 0x89, 0x70, 0x6f, 0x9e, 0x7e, 0x86, 0x97, 0x81, 0x85, 0x8e, + 0x70, 0x96, 0x6c, 0x72, 0xab, 0x6d, 0x9c, 0x91, 0xa0, 0x8a, 0x8d, 0x88, + 0x9e, 0x75, 0xc6, 0x76, 0x7c, 0xa7, 0x6b, 0xa8, 0x94, 0x72, 0xb6, 0x78, + 0x8d, 0x90, 0x7b, 0x8c, 0xa6, 0x65, 0xad, 0x9b, 0xaa, 0x94, 0x89, 0x7d, + 0x90, 0x69, 0xaa, 0x7e, 0x9e, 0xad, 0x7f, 0x94, 0x81, 0x7d, 0xa1, 0x7b, + 0x6c, 0x65, 0x83, 0x95, 0x89, 0x75, 0x93, 0x87, 0x94, 0x87, 0xa8, 0x92, + 0x8d, 0xa6, 0x9f, 0x78, 0xaa, 0x72, 0x95, 0x94, 0xac, 0xa6, 0x91, 0x5a, + 0xdb, 0x82, 0x55, 0xb6, 0xc1, 0xa3, 0x84, 0x4f, 0xc9, 0x88, 0x53, 0x8f, + 0xbb, 0xae, 0x9b, 0x8a, 0xd8, 0xa9, 0x68, 0xc2, 0xa0, 0xa9, 0x87, 0x6b, + 0xbd, 0x99, 0x7e, 0x86, 0x88, 0xa7, 0x5e, 0x53, 0xa4, 0x84, 0x6b, 0x6e, + 0x89, 0x95, 0x84, 0x2d, 0xb5, 0x43, 0x3e, 0x50, 0x71, 0x96, 0x9a, 0x5b, + 0xa1, 0x60, 0x80, 0x70, 0x6a, 0x73, 0x8f, 0x95, 0x52, 0x9b, 0xae, 0x71, + 0x76, 0x7d, 0x61, 0x99, 0x5b, 0xc3, 0xa8, 0x76, 0x98, 0x72, 0x7f, 0x8a, + 0x66, 0xc7, 0xa3, 0x7b, 0x8e, 0x8f, 0x70, 0x74, 0x6a, 0xae, 0x85, 0x83, + 0x96, 0x7d, 0x98, 0xa7, 0x8f, 0x94, 0x7e, 0x84, 0x96, 0x7a, 0xab, 0x7d, + 0x83, 0xb1, 0x6f, 0x7d, 0x9f, 0x80, 0xca, 0x8f, 0x9b, 0xa9, 0x69, 0x7a, + 0x92, 0x73, 0xaa, 0x74, 0x88, 0x98, 0x87, 0x8f, 0xa7, 0x68, 0xa0, 0x74, + 0x97, 0x95, 0x6e, 0x6f, 0x83, 0x53, 0x9b, 0x79, 0x71, 0x87, 0x7d, 0x8b, + 0x79, 0x87, 0xa3, 0x75, 0x68, 0x73, 0x7e, 0x89, 0x8f, 0x81, 0x98, 0x7a, + 0x9a, 0x83, 0x9d, 0x95, 0x90, 0x98, 0x97, 0x57, 0x93, 0x7e, 0xa2, 0x9a, + 0xa8, 0x8a, 0x85, 0x53, 0xbd, 0x7a, 0x61, 0x8b, 0xca, 0xac, 0x9b, 0x2e, + 0xe8, 0xa5, 0x66, 0x86, 0xca, 0xa7, 0xa0, 0x85, 0xcf, 0xa4, 0x6a, 0xc2, + 0xb0, 0xaa, 0x76, 0x76, 0xb6, 0xa2, 0x72, 0xa9, 0xa1, 0xa1, 0x67, 0x67, + 0xac, 0x90, 0x70, 0x6d, 0x8f, 0xb5, 0x6d, 0x3b, 0x85, 0x64, 0x4a, 0x6e, + 0x72, 0x9f, 0x98, 0x5b, 0x97, 0x3e, 0x8a, 0x6a, 0x6c, 0x7d, 0x77, 0x98, + 0x5a, 0x92, 0xa3, 0x81, 0x6f, 0x91, 0x7b, 0xa6, 0x6e, 0x9c, 0x9b, 0x5f, + 0x9e, 0x7e, 0x77, 0x9d, 0x88, 0xc6, 0x81, 0x5a, 0x93, 0x8b, 0x6c, 0x71, + 0x63, 0x9e, 0x78, 0x79, 0x70, 0x90, 0x95, 0x9f, 0x71, 0xa9, 0x90, 0x73, + 0x98, 0x8a, 0xa5, 0x8e, 0x87, 0xb0, 0x79, 0x79, 0x92, 0x7d, 0xcc, 0xa8, + 0x7a, 0x92, 0x82, 0x91, 0x90, 0x69, 0xa4, 0x9b, 0x97, 0x8f, 0x75, 0x7c, + 0xa3, 0x69, 0xb5, 0x87, 0x8d, 0x88, 0x7b, 0x94, 0x8b, 0x55, 0xa2, 0x6d, + 0x89, 0x8e, 0x81, 0x8a, 0x9e, 0x87, 0x86, 0x83, 0x8b, 0x84, 0x87, 0xa7, + 0x8e, 0x79, 0xa4, 0x9c, 0x99, 0x82, 0xa3, 0x8f, 0x91, 0x9a, 0x95, 0x5b, + 0x9f, 0x6e, 0x85, 0x93, 0xa6, 0x9a, 0x91, 0x4c, 0xd8, 0x6b, 0x6d, 0x85, + 0xde, 0xaa, 0x97, 0x51, 0xcf, 0x8c, 0x5f, 0x9a, 0xc2, 0x9d, 0x9a, 0x7c, + 0xc6, 0xb1, 0x84, 0xac, 0xba, 0xa5, 0x7c, 0x76, 0xbd, 0x93, 0x7f, 0xa0, + 0x86, 0xae, 0x47, 0x41, 0x88, 0x82, 0x62, 0x62, 0x73, 0xad, 0x6b, 0x23, + 0xa0, 0x48, 0x5a, 0x5a, 0x8f, 0x98, 0xbd, 0x5c, 0x9c, 0x72, 0x7c, 0x68, + 0x50, 0x78, 0x91, 0xab, 0x5c, 0xc1, 0xc6, 0x66, 0x87, 0x86, 0x60, 0x99, + 0x65, 0xac, 0x94, 0x91, 0x7e, 0x8c, 0x7d, 0x9b, 0x70, 0xb2, 0x9a, 0x7d, + 0x82, 0x91, 0x6b, 0x86, 0x6f, 0xbb, 0x7f, 0x66, 0x7a, 0x79, 0x94, 0x96, + 0x71, 0xa5, 0x75, 0x73, 0x95, 0x81, 0xa4, 0x8b, 0x87, 0xaa, 0x8e, 0x92, + 0xa9, 0x82, 0xb0, 0x92, 0x89, 0xa7, 0x83, 0x81, 0x8c, 0x6d, 0xc4, 0x7a, + 0x89, 0xa5, 0xa1, 0xa2, 0xa4, 0x6b, 0xa4, 0x82, 0x90, 0xb2, 0x8d, 0x72, + 0x83, 0x60, 0xa7, 0x7a, 0x80, 0x97, 0x65, 0x90, 0x87, 0x85, 0xae, 0x71, + 0x7d, 0x71, 0x98, 0xa8, 0x90, 0x75, 0xa9, 0x96, 0xa2, 0x91, 0x7b, 0x6b, + 0xa0, 0x9d, 0x8d, 0x5d, 0xa4, 0x79, 0x8c, 0xa4, 0xad, 0x94, 0x7e, 0x77, + 0xb6, 0x92, 0x74, 0xaf, 0xb5, 0x9b, 0x99, 0x67, 0xe7, 0x8e, 0x6a, 0x87, + 0xc1, 0x98, 0x9b, 0x7e, 0xd7, 0x9b, 0x5b, 0xae, 0xc9, 0x94, 0x7a, 0x6d, + 0x9e, 0xb4, 0x86, 0x8e, 0xa3, 0xa1, 0x5e, 0x5d, 0x8e, 0x8f, 0x6b, 0x59, + 0xa5, 0xa9, 0x69, 0x20, 0xa4, 0x64, 0x35, 0x61, 0x83, 0x9d, 0x8a, 0x4e, + 0x8b, 0x6c, 0x5e, 0x5b, 0x68, 0x76, 0x89, 0x94, 0x5f, 0x87, 0x98, 0x7a, + 0x5d, 0x81, 0x89, 0xa6, 0x54, 0xa3, 0xb4, 0x7b, 0x83, 0x8a, 0x90, 0x8b, + 0x86, 0xbc, 0x86, 0x59, 0x91, 0x79, 0x71, 0x6b, 0x7c, 0x94, 0x98, 0x7f, + 0x81, 0x76, 0x85, 0xad, 0x69, 0xa8, 0x83, 0x8c, 0x8f, 0x70, 0x9a, 0x91, + 0x78, 0xb3, 0x8f, 0x6d, 0x90, 0x86, 0xbd, 0x97, 0x7f, 0xaf, 0x7e, 0x90, + 0x8f, 0x63, 0xa2, 0x93, 0x6e, 0xab, 0x75, 0x72, 0x8d, 0x74, 0xa1, 0x72, + 0x82, 0xaa, 0x70, 0x82, 0x8d, 0x67, 0x94, 0x91, 0x92, 0xa5, 0x7f, 0xa5, + 0x6f, 0x6d, 0xaf, 0x80, 0x89, 0x7d, 0x92, 0x99, 0x92, 0x72, 0x9d, 0x7d, + 0x92, 0x78, 0xa9, 0x89, 0xa9, 0x9b, 0xa3, 0x73, 0x98, 0x71, 0x98, 0x86, + 0x9e, 0x97, 0x9e, 0x6a, 0xb9, 0x6a, 0x6e, 0x90, 0xde, 0x94, 0x9a, 0x52, + 0xdd, 0xa9, 0x6a, 0x79, 0xb9, 0xa3, 0xaa, 0x95, 0xba, 0xa2, 0x75, 0xc2, + 0xbf, 0xb5, 0x6d, 0x8d, 0xae, 0x9b, 0x8d, 0x9a, 0x92, 0xb4, 0x5e, 0x4b, + 0x8b, 0x99, 0x4f, 0x65, 0x94, 0xb6, 0x5d, 0x3a, 0xa3, 0x77, 0x51, 0x4e, + 0x6d, 0xa3, 0x94, 0x59, 0x80, 0x56, 0x8c, 0x67, 0x67, 0x74, 0x99, 0x85, + 0x57, 0x7b, 0x9e, 0x7e, 0x84, 0x85, 0x94, 0x96, 0x71, 0xbf, 0x97, 0x5f, + 0x7d, 0x80, 0x93, 0x87, 0x6b, 0xb9, 0x7d, 0x8b, 0x84, 0x84, 0x6b, 0x8c, + 0x6c, 0xc4, 0x85, 0x82, 0x87, 0x8d, 0x64, 0x90, 0x80, 0xb6, 0x9a, 0x70, + 0x9c, 0x68, 0xa0, 0x88, 0x81, 0x9d, 0x83, 0x75, 0x9d, 0x84, 0xbf, 0x8f, + 0x83, 0x9b, 0x75, 0x82, 0x9c, 0x76, 0xa4, 0x9d, 0x8a, 0xa7, 0x8e, 0x96, + 0x9c, 0x64, 0xc0, 0x95, 0x88, 0xa5, 0x6f, 0x74, 0x7e, 0x5d, 0x9f, 0x7d, + 0x89, 0x81, 0x71, 0xa8, 0x82, 0x6e, 0x9b, 0x9a, 0x6f, 0xa5, 0x88, 0x89, + 0xa4, 0x7e, 0xa4, 0x90, 0xa1, 0x83, 0x8b, 0x9c, 0x9a, 0x89, 0xa2, 0x89, + 0x9d, 0x5d, 0x86, 0xa5, 0xc4, 0x96, 0x9c, 0x85, 0xd6, 0x7c, 0x69, 0x88, + 0xc9, 0xa5, 0x9b, 0x60, 0xea, 0xab, 0x62, 0x9f, 0xd1, 0xa5, 0x86, 0x7e, + 0xb3, 0xbd, 0x7a, 0xa1, 0xbd, 0xa0, 0x7c, 0x92, 0xa6, 0xa3, 0x7d, 0xa9, + 0x98, 0xa6, 0x71, 0x5c, 0x9b, 0x9b, 0x58, 0x6f, 0x8f, 0xaa, 0x5e, 0x3b, + 0xa6, 0x5f, 0x3a, 0x79, 0x94, 0xa5, 0x84, 0x6f, 0x83, 0x5d, 0x75, 0x65, + 0x6c, 0x77, 0x86, 0xad, 0x4a, 0x92, 0x8e, 0x8a, 0x8f, 0x7b, 0x72, 0x96, + 0x79, 0xa6, 0xa8, 0x6d, 0x7b, 0x7b, 0x98, 0xa9, 0x79, 0xb9, 0x9e, 0x8f, + 0x90, 0x6d, 0x76, 0x82, 0x81, 0xc1, 0x95, 0x7c, 0x97, 0x8d, 0x95, 0xa2, + 0x7c, 0xa4, 0x7b, 0x9b, 0x7f, 0x6f, 0xac, 0x83, 0x7e, 0xa1, 0x7c, 0x7c, + 0xa1, 0x7a, 0xa1, 0x6d, 0x95, 0x86, 0x77, 0x98, 0x8e, 0x58, 0xa2, 0x76, + 0x8e, 0xa8, 0x94, 0x90, 0xa7, 0x62, 0xb8, 0x8a, 0x9f, 0xac, 0x87, 0x91, + 0x88, 0x50, 0xa7, 0x83, 0x88, 0x65, 0x7a, 0x92, 0x9d, 0x70, 0xa9, 0x99, + 0x7c, 0x87, 0x8c, 0x96, 0x8e, 0x73, 0xa4, 0xa7, 0x9b, 0x70, 0x99, 0x96, + 0x8f, 0x88, 0xb4, 0x85, 0xa8, 0x6a, 0x9e, 0x78, 0xb0, 0x82, 0x9f, 0x89, + 0xc9, 0x8d, 0x71, 0x7f, 0xc0, 0x98, 0xa0, 0x6d, 0xd2, 0x8e, 0x64, 0x9e, + 0xb2, 0xa9, 0x93, 0x6e, 0xcc, 0xbb, 0x89, 0xb1, 0xc1, 0x9b, 0x86, 0x94, + 0xb5, 0xb5, 0x95, 0xa0, 0x9c, 0x9b, 0x62, 0x5f, 0x7b, 0x91, 0x69, 0x74, + 0x9e, 0xa3, 0x81, 0x30, 0x85, 0x59, 0x49, 0x5e, 0x83, 0x85, 0x7d, 0x6a, + 0x90, 0x51, 0x80, 0x5e, 0x64, 0x6f, 0x99, 0x93, 0x75, 0x9a, 0xa7, 0x72, + 0x6c, 0x5d, 0xa3, 0x93, 0x87, 0xa7, 0xbd, 0x6f, 0x92, 0x6d, 0x85, 0x98, + 0x6f, 0xc7, 0xb6, 0x7c, 0x80, 0x71, 0x8a, 0x9f, 0x71, 0xb5, 0x8c, 0x6d, + 0xac, 0x7b, 0x72, 0xb7, 0x69, 0xa6, 0x9d, 0x66, 0xab, 0x7a, 0x8b, 0x70, + 0x8c, 0x9e, 0x86, 0x75, 0x96, 0x7b, 0xa3, 0x93, 0x8f, 0xb7, 0x84, 0x8c, + 0x87, 0x56, 0xae, 0x82, 0x71, 0xa3, 0x8d, 0x93, 0xaf, 0x59, 0xb3, 0x8a, + 0x97, 0x99, 0x75, 0x73, 0x8e, 0x51, 0xae, 0x84, 0x8b, 0x7a, 0x76, 0x77, + 0x6e, 0x75, 0xa4, 0x8a, 0x75, 0x8e, 0x8f, 0xa2, 0x96, 0x76, 0x9a, 0x80, + 0x96, 0x7d, 0x94, 0x71, 0x8a, 0x90, 0xac, 0x82, 0xa5, 0x61, 0xa3, 0x84, + 0xac, 0x8f, 0x74, 0x5c, 0xb6, 0x77, 0x8b, 0x9b, 0xb5, 0x8b, 0xb6, 0x52, + 0xd7, 0xaa, 0x4b, 0x8c, 0xbf, 0xb8, 0x9f, 0x6d, 0xcb, 0xa3, 0x6e, 0x97, + 0xaa, 0x8d, 0x7c, 0x99, 0xc0, 0xd0, 0x9e, 0xb7, 0x93, 0xaa, 0x5a, 0x6a, + 0x7d, 0x9a, 0x63, 0x71, 0x78, 0x8c, 0x67, 0x43, 0x87, 0x52, 0x64, 0x68, + 0x68, 0x9c, 0x65, 0x60, 0x7a, 0x35, 0x68, 0x66, 0x63, 0x69, 0x8d, 0x8f, + 0x72, 0x9b, 0x99, 0x5b, 0x80, 0x67, 0x93, 0xa2, 0x97, 0x9d, 0x8c, 0x68, + 0x80, 0x86, 0x96, 0x91, 0x64, 0xbf, 0x98, 0x63, 0x83, 0x85, 0x61, 0x97, + 0x6a, 0xac, 0xb4, 0x99, 0x8d, 0x7b, 0x7b, 0xad, 0x8b, 0xb2, 0x9e, 0x7f, + 0x9a, 0x73, 0x91, 0x84, 0x89, 0x9f, 0x8a, 0x87, 0x8b, 0x72, 0x8e, 0x79, + 0x86, 0xa7, 0x77, 0x84, 0x90, 0x58, 0xb2, 0x90, 0x93, 0xa0, 0x7f, 0x8a, + 0x91, 0x5a, 0xb1, 0x80, 0x99, 0xc1, 0x80, 0x7d, 0x97, 0x5c, 0x9a, 0x8c, + 0x71, 0x96, 0x7e, 0x7f, 0xad, 0x7b, 0xb9, 0x8a, 0x84, 0x84, 0x81, 0x97, + 0x94, 0x64, 0x9f, 0x7e, 0x9b, 0x8d, 0x7d, 0x8d, 0x9a, 0x9e, 0xac, 0x72, + 0xb2, 0x73, 0x81, 0x84, 0xc8, 0x81, 0x88, 0x72, 0xbe, 0x85, 0x86, 0x97, + 0xd3, 0x8a, 0xc7, 0x75, 0xce, 0x9c, 0x69, 0xa6, 0xb0, 0xa1, 0x8e, 0x64, + 0xb1, 0xa6, 0x67, 0xaa, 0xcd, 0x95, 0x97, 0xa2, 0xb2, 0xb2, 0x85, 0x9a, + 0x9d, 0xa3, 0x5e, 0x73, 0x6e, 0xae, 0x50, 0x83, 0x8c, 0xab, 0x92, 0x43, + 0x6b, 0x66, 0x43, 0x5c, 0x8f, 0x8a, 0x9a, 0x6c, 0x84, 0x48, 0x80, 0x6b, + 0x8d, 0x82, 0xaf, 0x89, 0x71, 0x9f, 0xa4, 0x9a, 0x7b, 0x68, 0x91, 0xaa, + 0x6b, 0xa3, 0x9c, 0x62, 0x8d, 0x6d, 0x87, 0x87, 0x81, 0x9a, 0x97, 0x6c, + 0x9c, 0x76, 0x63, 0xbc, 0x62, 0xbc, 0xb0, 0x97, 0xa7, 0x81, 0x70, 0x8f, + 0x7d, 0xb2, 0xa6, 0x98, 0xa1, 0x7b, 0x8e, 0x83, 0x8c, 0xa2, 0x7e, 0x73, + 0x99, 0x65, 0xc1, 0x77, 0x8e, 0xbc, 0x72, 0xa6, 0x8c, 0x55, 0xab, 0x8e, + 0x7d, 0xa3, 0x79, 0x80, 0x9e, 0x6b, 0xa9, 0x6c, 0x80, 0xb6, 0x81, 0xa6, + 0x92, 0x5b, 0xb7, 0x99, 0x81, 0x7e, 0x8e, 0x89, 0x97, 0x86, 0x93, 0x86, + 0x7b, 0x9a, 0x7f, 0x9a, 0x8e, 0x69, 0xa3, 0xa4, 0x9f, 0x8b, 0x96, 0x6f, + 0x8b, 0x97, 0xb4, 0x74, 0x96, 0x53, 0x99, 0x91, 0xa7, 0xa8, 0x69, 0x72, + 0xc9, 0x85, 0x99, 0x93, 0xc0, 0x90, 0xaa, 0x7f, 0xc7, 0x71, 0x74, 0x8d, + 0xb7, 0xab, 0x91, 0x69, 0xb4, 0x9b, 0x7d, 0x95, 0xc3, 0xb0, 0x9b, 0xa9, + 0xb3, 0x9f, 0x79, 0xa5, 0x9f, 0xad, 0x6b, 0x85, 0x90, 0xad, 0x69, 0x62, + 0x7e, 0xa6, 0x69, 0x4e, 0x80, 0x7e, 0x52, 0x57, 0x5f, 0x95, 0x72, 0x4c, + 0x87, 0x4e, 0x5a, 0x62, 0x7d, 0x70, 0x92, 0x98, 0x76, 0x8e, 0x99, 0x7d, + 0x73, 0x6d, 0x86, 0x8e, 0x6b, 0x80, 0xa7, 0x9d, 0x91, 0x73, 0x95, 0x70, + 0x80, 0xc3, 0x9f, 0x8b, 0x72, 0x86, 0x6b, 0xad, 0x76, 0xbe, 0xad, 0x8e, + 0x9c, 0x78, 0x6a, 0xbf, 0x7d, 0xa8, 0x88, 0x8a, 0x8b, 0x8c, 0x9c, 0x8c, + 0x8a, 0x85, 0x73, 0x92, 0xa2, 0x7b, 0xa5, 0x96, 0x9b, 0xa3, 0x6c, 0x80, + 0xa6, 0x63, 0xac, 0x98, 0xa3, 0x9a, 0x83, 0x8a, 0x8c, 0x63, 0xb9, 0x8c, + 0x99, 0xa1, 0x7a, 0x6c, 0x9e, 0x59, 0x90, 0x84, 0x8a, 0x93, 0x8f, 0x87, + 0x98, 0x84, 0x99, 0xa4, 0x72, 0x6d, 0x95, 0xa2, 0x95, 0x72, 0xc3, 0x88, + 0x8f, 0x6a, 0x77, 0x7d, 0x8b, 0xae, 0xa3, 0x7c, 0xa8, 0x5d, 0x7c, 0xa8, + 0xa1, 0x85, 0x7e, 0x8c, 0xac, 0x8d, 0x73, 0x88, 0xc1, 0x89, 0xaa, 0x89, + 0xb2, 0x92, 0x75, 0x9a, 0x9c, 0x8e, 0xb9, 0xaa, 0xaa, 0xac, 0x78, 0x85, + 0xbc, 0x9f, 0x6d, 0xb7, 0x89, 0xa6, 0xb3, 0x8e, 0xa5, 0xbb, 0x6b, 0x9d, + 0x8f, 0x8b, 0x69, 0x7a, 0x82, 0x99, 0x8c, 0x49, 0x87, 0x74, 0x37, 0x63, + 0x5d, 0x92, 0x77, 0x66, 0x63, 0x56, 0x77, 0x5d, 0x7f, 0x68, 0x97, 0x74, + 0x84, 0x94, 0x7d, 0x7d, 0x91, 0x78, 0x87, 0x96, 0x7f, 0x97, 0x94, 0x6f, + 0x89, 0x6c, 0x96, 0x71, 0x83, 0x8f, 0x8a, 0x89, 0x7d, 0x84, 0x8a, 0xa6, + 0x7b, 0x95, 0x89, 0x77, 0x94, 0x80, 0x7f, 0x93, 0x5e, 0xbb, 0x9c, 0xa8, + 0xa2, 0x7e, 0xa6, 0x86, 0x7d, 0x8b, 0x92, 0x73, 0xac, 0x78, 0xaa, 0x98, + 0xb1, 0x94, 0x79, 0x8b, 0x8f, 0x70, 0xa7, 0xae, 0x92, 0xad, 0xb1, 0x8b, + 0xb0, 0x78, 0xbc, 0xa9, 0xa4, 0xa3, 0x9e, 0x76, 0x89, 0x67, 0xab, 0x98, + 0x75, 0x8c, 0x86, 0x95, 0x9e, 0x77, 0x96, 0x85, 0x8c, 0x8e, 0x8b, 0x8a, + 0x8a, 0x4b, 0x71, 0x8a, 0x9b, 0x6d, 0x6e, 0x89, 0x81, 0x82, 0xa7, 0x98, + 0xa5, 0x66, 0x72, 0x8b, 0x99, 0x9a, 0x8b, 0x8b, 0x9f, 0x87, 0x79, 0x84, + 0x99, 0x6d, 0x90, 0x7d, 0x9d, 0xa7, 0x81, 0xa3, 0x9d, 0x96, 0x82, 0x86, + 0xa2, 0x8e, 0x8d, 0x7f, 0x84, 0x8c, 0x98, 0xbc, 0x83, 0xb4, 0xb5, 0x78, + 0x7d, 0xab, 0x8d, 0x87, 0x71, 0x8d, 0x6e, 0x8f, 0x89, 0xaa, 0x7c, 0x6f, + 0x71, 0x69, 0x65, 0x60, 0x81, 0x91, 0x94, 0x6d, 0x76, 0x66, 0x74, 0x5e, + 0x77, 0x7c, 0xa2, 0xa6, 0x70, 0x90, 0xa3, 0x68, 0x83, 0x69, 0x71, 0x72, + 0x6c, 0xa9, 0x85, 0x71, 0x88, 0x60, 0x90, 0x84, 0x8a, 0xba, 0x8b, 0x8c, + 0x72, 0x8f, 0x98, 0x84, 0x8b, 0x8a, 0xb1, 0xa2, 0x93, 0x8d, 0x86, 0x99, + 0xa2, 0x99, 0xb0, 0xa6, 0x92, 0x78, 0x86, 0x87, 0x9c, 0x9d, 0x6f, 0x92, + 0x9a, 0x8a, 0xbf, 0xaa, 0xa3, 0xa2, 0x71, 0x8d, 0x93, 0x70, 0xb5, 0x9c, + 0xa8, 0x97, 0xb4, 0x93, 0xa6, 0x75, 0xbb, 0xa3, 0x92, 0x95, 0x95, 0x94, + 0x90, 0x5b, 0xbf, 0x92, 0x8a, 0x95, 0xa0, 0xa1, 0x68, 0x7e, 0x9a, 0x7f, + 0x88, 0xa7, 0x93, 0xa1, 0x7a, 0x93, 0x95, 0x8b, 0x96, 0x94, 0x70, 0xa0, + 0x70, 0x8f, 0x9d, 0x96, 0x8e, 0x9c, 0x90, 0x9f, 0x7e, 0x83, 0x84, 0x9e, + 0x7f, 0x65, 0x72, 0x84, 0x64, 0x94, 0x75, 0xa7, 0x62, 0xa3, 0x8a, 0x9b, + 0x82, 0x99, 0x87, 0x70, 0x81, 0x6d, 0xac, 0x7b, 0x74, 0x68, 0x5d, 0x95, + 0xa0, 0x6e, 0x84, 0xab, 0x79, 0x8e, 0x8b, 0x79, 0x7b, 0x83, 0xa0, 0x7b, + 0x96, 0x71, 0x5d, 0xad, 0xa4, 0x82, 0x79, 0x96, 0x73, 0x84, 0x7d, 0x98, + 0x87, 0x93, 0x86, 0xa6, 0x7f, 0x7c, 0x71, 0x9d, 0xa4, 0x9b, 0x8a, 0x7c, + 0x87, 0x6a, 0x7f, 0x8d, 0x97, 0x92, 0xa0, 0x88, 0x77, 0x7d, 0x70, 0x9c, + 0x9f, 0xa0, 0x71, 0xa3, 0x73, 0x95, 0x76, 0x79, 0x94, 0x95, 0x83, 0x8b, + 0x8d, 0x82, 0x7a, 0x77, 0xa6, 0x88, 0x72, 0x7a, 0x90, 0x76, 0x7f, 0x95, + 0x83, 0x90, 0x9e, 0x7c, 0x8e, 0x9a, 0x6b, 0xa4, 0x98, 0x9f, 0x86, 0x8c, + 0x76, 0x70, 0x74, 0x97, 0x7e, 0xa4, 0x5f, 0xa3, 0xa7, 0x7f, 0x67, 0x8d, + 0x82, 0x95, 0x93, 0x99, 0x82, 0x70, 0x75, 0xa8, 0xa1, 0xaf, 0x8a, 0x8a, + 0xb0, 0x89, 0x88, 0x6b, 0x98, 0xaf, 0x75, 0x7f, 0x86, 0x90, 0x8f, 0x8c, + 0x84, 0x8d, 0x7f, 0x8b, 0x94, 0x9f, 0x80, 0x8b, 0x93, 0xa2, 0x98, 0xa5, + 0x83, 0x81, 0x8a, 0xaa, 0x86, 0xa3, 0xb0, 0xac, 0x64, 0x9c, 0x7c, 0x93, + 0xac, 0x85, 0x7f, 0x88, 0x7a, 0xa5, 0x75, 0x69, 0x94, 0xa8, 0x95, 0xa9, + 0x6f, 0x9f, 0x85, 0x8a, 0xa5, 0x97, 0x98, 0xa9, 0x76, 0x80, 0x7e, 0x95, + 0x89, 0xaf, 0x68, 0x7b, 0xb4, 0x8a, 0x6b, 0xa4, 0x7b, 0x90, 0x79, 0xba, + 0x9f, 0x82, 0x7d, 0x89, 0x85, 0x82, 0x94, 0xa5, 0x78, 0x8f, 0x6f, 0x71, + 0x62, 0x66, 0x73, 0x98, 0x8c, 0x7d, 0x81, 0xa2, 0x69, 0x7c, 0x76, 0xa4, + 0x94, 0x8f, 0x6f, 0x8a, 0x94, 0x8e, 0x8a, 0x88, 0x8c, 0xa3, 0x6f, 0xa2, + 0x7d, 0x90, 0x8f, 0x96, 0x6c, 0x76, 0x6e, 0x8e, 0x82, 0x85, 0x7f, 0x93, + 0x81, 0x83, 0x7b, 0x9f, 0x91, 0x89, 0x75, 0x9c, 0x9f, 0x86, 0x7a, 0x8c, + 0x7a, 0x7b, 0x82, 0xae, 0x6a, 0x7d, 0x82, 0x82, 0xa0, 0x85, 0x99, 0x9f, + 0x88, 0x8b, 0x8c, 0x8f, 0x90, 0x96, 0x8e, 0x98, 0xa3, 0x87, 0x7f, 0x9b, + 0x94, 0x73, 0x96, 0x86, 0x72, 0x7c, 0x75, 0x7c, 0x90, 0x79, 0x83, 0x80, + 0x79, 0x9e, 0x9c, 0x8e, 0x99, 0x8c, 0x7a, 0x9c, 0x8d, 0x99, 0x9d, 0x84, + 0xa5, 0x93, 0x85, 0x96, 0x88, 0x94, 0x80, 0x90, 0x73, 0xa3, 0x7c, 0xa1, + 0x88, 0xa4, 0x98, 0x9f, 0x9e, 0x92, 0x6c, 0xa0, 0x84, 0x87, 0x8a, 0x83, + 0x7b, 0x91, 0x8c, 0x9e, 0x73, 0xa6, 0x93, 0xa0, 0x8d, 0x98, 0x74, 0xa1, + 0x83, 0x9a, 0x80, 0xbc, 0x62, 0x70, 0x9e, 0xad, 0x9e, 0x8f, 0x8f, 0x9e, + 0x7e, 0xac, 0xb0, 0xa9, 0x79, 0x6f, 0x79, 0x8f, 0x7e, 0x71, 0x8d, 0xab, + 0x97, 0x76, 0x86, 0xa2, 0x98, 0x95, 0x8b, 0x9b, 0x75, 0x7a, 0x71, 0x85, + 0x7f, 0x61, 0x76, 0x8e, 0x99, 0x91, 0x88, 0x73, 0x71, 0x65, 0x82, 0xa0, + 0x9b, 0x8f, 0x79, 0x70, 0x78, 0x66, 0x85, 0x94, 0x8b, 0x91, 0x75, 0x80, + 0x9c, 0x94, 0x7f, 0xa5, 0x82, 0x91, 0x7d, 0x76, 0x80, 0x78, 0x83, 0x82, + 0x79, 0x98, 0x83, 0x87, 0x94, 0x71, 0x73, 0x77, 0x71, 0x94, 0x6a, 0xa8, + 0x9e, 0x8d, 0x90, 0x78, 0x7a, 0x81, 0x9c, 0x91, 0x96, 0x80, 0x79, 0x83, + 0x92, 0x9f, 0x8a, 0x84, 0x8e, 0x97, 0x8c, 0x81, 0x87, 0x74, 0x8b, 0x8e, + 0xa7, 0x86, 0x8b, 0x8a, 0x8e, 0x8f, 0x9b, 0x6b, 0x82, 0x8a, 0x9f, 0x7a, + 0x96, 0x80, 0x91, 0x94, 0xa6, 0x8e, 0x7a, 0x97, 0x8a, 0x6c, 0xad, 0xa1, + 0x78, 0x95, 0x9d, 0x9d, 0x88, 0x94, 0x99, 0x86, 0x80, 0x9b, 0x7c, 0x9c, + 0x87, 0x7a, 0xa0, 0xa8, 0x83, 0x74, 0x8e, 0x9b, 0x65, 0x95, 0x83, 0xc2, + 0x69, 0x88, 0x87, 0xa7, 0x86, 0x98, 0x9f, 0xc6, 0x5c, 0x7f, 0xb9, 0x9c, + 0x8b, 0x6e, 0x95, 0xbd, 0x72, 0x83, 0xbf, 0xb1, 0x89, 0x6d, 0x89, 0x8e, + 0x9d, 0x87, 0x95, 0x92, 0x76, 0x8d, 0x7f, 0x7f, 0x6d, 0x9d, 0x7b, 0x95, + 0x86, 0x69, 0x90, 0xa0, 0x62, 0x7c, 0x56, 0xa0, 0x9c, 0x8b, 0x81, 0x79, + 0xa6, 0x73, 0x69, 0xaa, 0x7b, 0x87, 0x8b, 0x7e, 0xa1, 0x9f, 0x6d, 0xa6, + 0x7e, 0x7e, 0x87, 0x7c, 0xa5, 0x84, 0x7b, 0xa2, 0xae, 0x92, 0x8e, 0x67, + 0x93, 0x88, 0x8b, 0xa2, 0x8d, 0x96, 0x92, 0x8e, 0x71, 0x7a, 0x82, 0x80, + 0x9e, 0x8b, 0x7b, 0x87, 0x96, 0xa0, 0xa4, 0x92, 0x88, 0x7e, 0x77, 0x8e, + 0x91, 0x7e, 0x81, 0x77, 0x79, 0x93, 0x8d, 0x9d, 0x8a, 0x71, 0x8d, 0x88, + 0x9d, 0x89, 0x85, 0x94, 0x99, 0x80, 0x89, 0x8f, 0x87, 0x81, 0x83, 0x74, + 0x8a, 0x89, 0x68, 0x7e, 0x99, 0x82, 0x8c, 0x76, 0xc6, 0x8f, 0x90, 0x7d, + 0x6c, 0x68, 0xbd, 0x90, 0x78, 0x9d, 0x7b, 0xa3, 0x99, 0x76, 0xaf, 0x8d, + 0x7d, 0x84, 0x7f, 0x9f, 0x8b, 0x7a, 0xaa, 0xa8, 0x79, 0x89, 0x8f, 0x8f, + 0x71, 0x80, 0x7f, 0xaa, 0x85, 0x70, 0xa8, 0x96, 0x6c, 0x8c, 0xaf, 0xeb, + 0x57, 0x7e, 0xcf, 0x8d, 0x93, 0x72, 0xa6, 0xd2, 0x52, 0xab, 0xbb, 0xa8, + 0x8d, 0x82, 0x7a, 0xbc, 0x72, 0x95, 0xa3, 0xa7, 0x8b, 0x74, 0x84, 0x85, + 0x6a, 0x85, 0x92, 0x9f, 0x91, 0x6b, 0x9b, 0x73, 0x77, 0xa2, 0x7f, 0x81, + 0x8e, 0x8b, 0x71, 0x8c, 0x7f, 0x60, 0x86, 0x81, 0x9c, 0x86, 0x93, 0x65, + 0x84, 0x84, 0x89, 0xa2, 0x98, 0x67, 0x88, 0x71, 0x92, 0x80, 0x65, 0xa2, + 0xa5, 0x99, 0x85, 0x95, 0x8f, 0x85, 0x8f, 0x82, 0x7e, 0x9a, 0x8a, 0x74, + 0x9d, 0x75, 0x88, 0x7e, 0xa2, 0x77, 0x82, 0x9e, 0x78, 0xa1, 0x74, 0x79, + 0x7f, 0x87, 0x91, 0x8d, 0x7a, 0x73, 0x96, 0xa2, 0xa3, 0x81, 0x7d, 0x8a, + 0x85, 0x75, 0x84, 0x81, 0x8b, 0x7f, 0x6c, 0x86, 0x8d, 0x7b, 0x79, 0x78, + 0x89, 0x85, 0x8c, 0x9a, 0xa6, 0x96, 0x7a, 0x78, 0xa2, 0x85, 0x9b, 0x89, + 0xc8, 0x97, 0xa3, 0x82, 0x8b, 0x7f, 0xe7, 0x8f, 0x8f, 0x74, 0x75, 0x83, + 0x87, 0x79, 0xb3, 0xab, 0x70, 0x9a, 0x9a, 0xa6, 0x81, 0x7e, 0xb8, 0x91, + 0x8b, 0x8d, 0x93, 0xa1, 0x79, 0x7d, 0x81, 0xb4, 0x79, 0x94, 0xa5, 0x89, + 0x8e, 0x7c, 0x9b, 0xe2, 0x50, 0x94, 0xdf, 0xa0, 0x53, 0x5d, 0x90, 0xde, + 0x67, 0x90, 0xaf, 0x8a, 0x8f, 0x73, 0x7b, 0xcb, 0x64, 0x9f, 0x91, 0x86, + 0x95, 0x84, 0x83, 0x88, 0x76, 0x8b, 0x8a, 0x8f, 0x9c, 0x9a, 0x92, 0x96, + 0x7f, 0x8e, 0x79, 0x80, 0x91, 0x6d, 0x86, 0x59, 0x74, 0x8a, 0x53, 0x88, + 0xae, 0x7b, 0x80, 0x70, 0x87, 0x74, 0x75, 0x91, 0xa4, 0x74, 0x8d, 0x5a, + 0x83, 0x95, 0x65, 0xa1, 0xb3, 0x74, 0x87, 0x7d, 0xaa, 0x82, 0x79, 0x78, + 0x9b, 0x7c, 0x78, 0x74, 0x9e, 0x74, 0x92, 0x92, 0xa3, 0x6e, 0x75, 0x92, + 0x6a, 0x6f, 0xa3, 0x7c, 0x9e, 0x7f, 0x92, 0x6b, 0x96, 0x79, 0x9a, 0x87, + 0x83, 0x8c, 0x72, 0x79, 0x6a, 0xa3, 0x79, 0x7d, 0x6d, 0x6c, 0x81, 0x96, + 0x98, 0x7f, 0x94, 0x81, 0x8a, 0x8a, 0xa7, 0x8c, 0x9a, 0x84, 0xa7, 0x89, + 0x9d, 0x85, 0xa6, 0xa8, 0xd0, 0x92, 0x97, 0x9f, 0x76, 0x86, 0xe6, 0x6f, + 0x7c, 0x84, 0x98, 0x8d, 0x80, 0x75, 0xc5, 0x86, 0x6b, 0x8d, 0x9e, 0x9e, + 0x7f, 0x71, 0x97, 0xa1, 0x75, 0x92, 0xa9, 0x9e, 0x91, 0x5e, 0xa2, 0xa2, + 0x68, 0xad, 0xa5, 0xa0, 0x7e, 0x68, 0xac, 0xdc, 0x50, 0xa2, 0xc1, 0x8a, + 0x63, 0x74, 0x7e, 0xd9, 0x3f, 0xbb, 0xba, 0x9d, 0x7f, 0x76, 0x5f, 0xb0, + 0x74, 0x8e, 0xb1, 0x95, 0x9a, 0x81, 0x63, 0x9f, 0x98, 0x74, 0x80, 0x89, + 0x95, 0x8e, 0x9e, 0x78, 0x87, 0x82, 0x57, 0x87, 0x8d, 0x90, 0x79, 0x80, + 0x76, 0x7c, 0x7d, 0x8a, 0xa6, 0x82, 0x98, 0x7a, 0x96, 0x97, 0x84, 0x87, + 0xab, 0x7f, 0x87, 0x57, 0x83, 0x6a, 0x6a, 0x84, 0x9c, 0x8d, 0x74, 0x68, + 0xa2, 0x92, 0x90, 0x98, 0x98, 0x8b, 0x6d, 0x72, 0x90, 0x8c, 0x7c, 0x7d, + 0x9b, 0x6e, 0x71, 0x76, 0x6b, 0x7b, 0x63, 0x81, 0xad, 0x71, 0x78, 0x8e, + 0x74, 0x87, 0x8e, 0x8a, 0xab, 0x8e, 0x83, 0x85, 0x7d, 0xa0, 0x67, 0x7f, + 0x9c, 0x74, 0x6b, 0x88, 0x66, 0x92, 0x7f, 0x83, 0x94, 0x92, 0xa5, 0x82, + 0xa1, 0x7b, 0x6f, 0x70, 0xab, 0x72, 0xb5, 0x91, 0xb7, 0x89, 0x91, 0x77, + 0x77, 0x8a, 0xdb, 0x88, 0x8a, 0x8d, 0x89, 0x6c, 0x7b, 0x83, 0xc8, 0xb5, + 0x4b, 0x96, 0x8b, 0x92, 0x91, 0x76, 0xa9, 0xae, 0x70, 0xa8, 0x74, 0x9d, + 0x96, 0x6d, 0xa1, 0xba, 0x86, 0xbc, 0xbc, 0xa2, 0x8d, 0x6c, 0x96, 0xd8, + 0x71, 0xb1, 0xae, 0xb0, 0x79, 0x7b, 0x71, 0xd8, 0x32, 0xaa, 0xae, 0xa7, + 0x7c, 0x6b, 0x77, 0xc0, 0x7c, 0x9e, 0x9f, 0x89, 0x92, 0x8a, 0x76, 0xae, + 0x97, 0x75, 0x87, 0x8c, 0x7f, 0x86, 0x8b, 0x73, 0x6b, 0x64, 0x87, 0x6d, + 0x99, 0x8f, 0x8d, 0x66, 0x76, 0x87, 0x6d, 0x6e, 0x98, 0x7a, 0x91, 0x92, + 0x8c, 0x7c, 0x89, 0x9b, 0x9e, 0x83, 0x86, 0x62, 0x90, 0x6e, 0x62, 0x82, + 0xa3, 0x7e, 0x86, 0x6a, 0x93, 0x9b, 0x73, 0x6c, 0xa8, 0x99, 0x73, 0x99, + 0x8c, 0x89, 0x85, 0x67, 0x98, 0x78, 0x63, 0x98, 0x77, 0xa6, 0x6e, 0x81, + 0xa4, 0x64, 0x8f, 0x8a, 0x7f, 0x9b, 0x91, 0x91, 0x94, 0x82, 0x8b, 0x8b, + 0x76, 0x66, 0x83, 0x81, 0x94, 0x71, 0x82, 0x9e, 0x93, 0x85, 0x80, 0x8c, + 0xae, 0x94, 0x96, 0x74, 0x91, 0x9a, 0x6f, 0x9e, 0xa9, 0x76, 0xab, 0x8e, + 0xd6, 0x9c, 0x7d, 0x98, 0x83, 0x6e, 0xfe, 0x83, 0x71, 0x82, 0x9f, 0x93, + 0x7b, 0x67, 0xcb, 0xb9, 0x66, 0x89, 0x99, 0x8a, 0xac, 0x8c, 0xa0, 0x9c, + 0x70, 0xaf, 0x81, 0x88, 0x9c, 0x7e, 0xa8, 0xa5, 0x65, 0x8c, 0xa1, 0x8c, + 0x83, 0x85, 0x9d, 0xcb, 0x4b, 0xc1, 0xb5, 0xa2, 0x75, 0x63, 0x75, 0xbd, + 0x34, 0xae, 0xca, 0xa2, 0x89, 0x7a, 0x69, 0xb0, 0x70, 0xae, 0x94, 0x76, + 0x85, 0x93, 0x6a, 0x90, 0x6a, 0x8a, 0xac, 0x71, 0x7e, 0x81, 0xa2, 0x71, + 0x98, 0x86, 0x99, 0x76, 0x8f, 0x6f, 0x90, 0x93, 0x7c, 0x72, 0x81, 0x8c, + 0x78, 0x77, 0x97, 0x84, 0x98, 0x70, 0x96, 0x9a, 0x9b, 0x93, 0x92, 0x5f, + 0xaa, 0x88, 0x5b, 0x74, 0xaa, 0x96, 0x6a, 0x73, 0x87, 0x83, 0x72, 0x89, + 0xab, 0x8a, 0x5f, 0x71, 0xa4, 0x94, 0x92, 0x60, 0x96, 0x7b, 0x53, 0x88, + 0x69, 0x8b, 0x5e, 0x7b, 0xa0, 0x83, 0x70, 0x95, 0x6d, 0x9b, 0x6d, 0x98, + 0x99, 0x86, 0x6e, 0x7a, 0x87, 0x86, 0x68, 0x8a, 0x7e, 0x87, 0x90, 0x7d, + 0x76, 0x93, 0x80, 0x8a, 0x8f, 0x97, 0xac, 0x71, 0xa2, 0x96, 0x7f, 0x8e, + 0xc2, 0x71, 0xab, 0xa9, 0xd1, 0x85, 0x8c, 0x74, 0x70, 0x72, 0xff, 0x77, + 0x6d, 0x77, 0x91, 0x5d, 0x71, 0x5d, 0xb2, 0xb1, 0x38, 0x76, 0xa6, 0x80, + 0x91, 0x86, 0xa3, 0x9c, 0x85, 0x95, 0x99, 0xab, 0x8a, 0x6e, 0x9f, 0xa6, + 0x75, 0xa9, 0xb3, 0x97, 0x69, 0x85, 0xa4, 0xc9, 0x59, 0xb4, 0xca, 0x8d, + 0x5c, 0x67, 0x7d, 0xcd, 0x29, 0xca, 0xdb, 0x8c, 0x86, 0x8c, 0x70, 0xaa, + 0x5c, 0x9e, 0x98, 0x86, 0x92, 0x7e, 0x6b, 0x8e, 0x8f, 0x6a, 0x84, 0x71, + 0x9a, 0x76, 0x87, 0x84, 0x8b, 0x7f, 0x7f, 0x6e, 0xa3, 0x83, 0x85, 0x78, + 0x6f, 0x7c, 0x6f, 0x96, 0x95, 0x8c, 0xa3, 0x72, 0x92, 0x66, 0x7b, 0x99, + 0x9c, 0x9c, 0x9a, 0x63, 0xaa, 0x81, 0x7f, 0x90, 0x8c, 0xa0, 0x7e, 0x67, + 0x94, 0x96, 0x7f, 0x8a, 0x95, 0x91, 0x5c, 0x73, 0x88, 0x9b, 0x85, 0x70, + 0x87, 0x79, 0x56, 0x92, 0x69, 0x95, 0x62, 0x78, 0x93, 0x83, 0x63, 0x98, + 0x7a, 0xa4, 0x95, 0x7c, 0x8e, 0x69, 0x86, 0x92, 0x7d, 0x6b, 0x69, 0x85, + 0xa8, 0x90, 0x7c, 0x7b, 0x9e, 0x87, 0x7b, 0x90, 0x98, 0x7a, 0xa4, 0x92, + 0xad, 0x97, 0xa0, 0x6d, 0xa6, 0x74, 0xb7, 0x7f, 0xb9, 0x94, 0x6c, 0x77, + 0x65, 0x6f, 0xfc, 0x7d, 0x68, 0x74, 0xa1, 0x6c, 0x71, 0x61, 0xc3, 0xb5, + 0x60, 0x86, 0x8b, 0x7d, 0x89, 0x8b, 0x93, 0xa4, 0x68, 0xa0, 0x8f, 0x73, + 0x96, 0x6e, 0x81, 0x99, 0x81, 0x9d, 0xae, 0x93, 0x6a, 0x8b, 0x9a, 0xcb, + 0x68, 0xaf, 0xca, 0x81, 0x73, 0x6e, 0x70, 0xd7, 0x49, 0xb9, 0xc5, 0x9d, + 0x87, 0x8d, 0x61, 0xa8, 0x5e, 0xa4, 0xb7, 0xab, 0x96, 0x84, 0x76, 0x98, + 0x84, 0x99, 0x8f, 0x70, 0x79, 0x94, 0xa5, 0x87, 0x6e, 0x73, 0x63, 0x7e, + 0x83, 0x8c, 0x88, 0x71, 0x7a, 0x81, 0x7d, 0x94, 0x92, 0x89, 0xab, 0x7a, + 0x96, 0x66, 0x7b, 0x8b, 0x8f, 0x8e, 0x94, 0x5b, 0xa0, 0x7f, 0x82, 0x84, + 0x84, 0x80, 0x7d, 0x81, 0x89, 0x7b, 0x97, 0x78, 0x83, 0x93, 0x4c, 0x95, + 0x7f, 0x93, 0x8e, 0x70, 0x89, 0x81, 0x69, 0x87, 0x76, 0x73, 0x9a, 0x74, + 0xa2, 0x88, 0x5e, 0xac, 0x74, 0x8e, 0x74, 0x8e, 0x94, 0x85, 0x7b, 0x7a, + 0x72, 0x82, 0x68, 0x77, 0x96, 0x8a, 0x7b, 0x6c, 0x88, 0x8b, 0x6b, 0x86, + 0xa4, 0x88, 0xac, 0xa1, 0x90, 0x8e, 0x85, 0x6d, 0xb1, 0x69, 0xb1, 0xa2, + 0xbe, 0x9a, 0x7c, 0xb4, 0x63, 0x56, 0xf2, 0x90, 0x5e, 0x71, 0xa3, 0x6a, + 0x8b, 0x67, 0xbe, 0xa8, 0x6e, 0x8b, 0x90, 0x83, 0xa0, 0x78, 0x9f, 0xa5, + 0x65, 0xa3, 0x8b, 0x94, 0x84, 0x6c, 0xa5, 0x97, 0x7d, 0xa7, 0x9f, 0x9c, + 0x62, 0x7d, 0xb5, 0xb1, 0x58, 0x98, 0xba, 0x8d, 0x7f, 0x57, 0x86, 0xc5, + 0x39, 0xb3, 0xc9, 0xa9, 0x89, 0x8e, 0x55, 0xaf, 0x54, 0xb4, 0xb0, 0x8f, + 0x8b, 0x7c, 0x6e, 0x8e, 0x96, 0x90, 0x8a, 0x83, 0x84, 0x8c, 0x96, 0x7f, + 0x89, 0x67, 0x99, 0x60, 0x74, 0x8d, 0x9b, 0x82, 0x6f, 0x61, 0x84, 0x9a, + 0x7c, 0x85, 0x86, 0x7c, 0x9b, 0x5f, 0x81, 0x96, 0x90, 0x9b, 0xa0, 0x58, + 0xaf, 0x78, 0x81, 0x8f, 0x96, 0x81, 0x77, 0x7d, 0xa2, 0x85, 0x74, 0x84, + 0x99, 0x8d, 0x5f, 0x77, 0x8a, 0x8c, 0x85, 0x78, 0x8f, 0x80, 0x5c, 0x6f, + 0x77, 0x73, 0x80, 0x99, 0x83, 0x89, 0x6f, 0x8e, 0x85, 0x7e, 0x6c, 0x81, + 0x99, 0x89, 0x69, 0x70, 0x8c, 0x8f, 0x6b, 0x89, 0x80, 0x7a, 0x83, 0x7a, + 0x96, 0x99, 0x73, 0x76, 0x9c, 0x67, 0xab, 0xab, 0xbd, 0x8b, 0x85, 0x90, + 0xb0, 0x6b, 0xbd, 0x9c, 0xb9, 0xa0, 0x7c, 0x7d, 0x66, 0x78, 0xdb, 0x97, + 0x55, 0x67, 0x96, 0x69, 0x80, 0x49, 0xc1, 0xbb, 0x6c, 0x91, 0x8a, 0x92, + 0x9a, 0x98, 0xa5, 0x98, 0x51, 0xa6, 0x99, 0x8e, 0x73, 0x73, 0x9d, 0x9f, + 0x77, 0xa6, 0xa4, 0x92, 0x64, 0x75, 0xac, 0xb2, 0x5d, 0xa1, 0xab, 0xa4, + 0x5a, 0x5b, 0xb3, 0xb7, 0x2d, 0xca, 0xc8, 0x76, 0x94, 0x8e, 0x59, 0xb0, + 0x52, 0x9d, 0xbd, 0x89, 0x97, 0x84, 0x5d, 0x9a, 0x87, 0x9b, 0x94, 0x6c, + 0x7b, 0xaa, 0x8a, 0x8b, 0x79, 0x5d, 0x90, 0x5c, 0x8b, 0x7b, 0xbe, 0x68, + 0x84, 0x6f, 0x75, 0x72, 0x98, 0x82, 0x92, 0x7a, 0xa2, 0x6e, 0x7b, 0x7d, + 0x9c, 0x99, 0x97, 0x5d, 0x9b, 0x69, 0x80, 0xa3, 0x96, 0x8d, 0x7c, 0x82, + 0xa3, 0x76, 0x95, 0x67, 0x93, 0x8e, 0x62, 0x7b, 0x78, 0x96, 0x69, 0x67, + 0x84, 0x8f, 0x62, 0x80, 0x88, 0x7e, 0x6c, 0x94, 0xab, 0x8b, 0x82, 0x9e, + 0x7e, 0x8c, 0x70, 0x83, 0x9c, 0x9c, 0x80, 0x87, 0x8f, 0xa1, 0x7f, 0x81, + 0x95, 0x83, 0x6d, 0x7a, 0xa0, 0x77, 0x6d, 0x76, 0x91, 0x7e, 0xa3, 0x62, + 0xa0, 0x93, 0x7e, 0x97, 0xb6, 0x6c, 0xad, 0x72, 0xb2, 0x95, 0x73, 0x83, + 0x62, 0x56, 0xe2, 0x99, 0x6e, 0x66, 0xb0, 0x6c, 0x75, 0x4e, 0xb2, 0xc7, + 0x51, 0x98, 0x90, 0x8c, 0x82, 0x63, 0xa8, 0x99, 0x54, 0xc1, 0x87, 0x80, + 0x79, 0x62, 0xad, 0x81, 0x76, 0x99, 0xa9, 0x9b, 0x4e, 0x8c, 0xaf, 0xb6, + 0x5d, 0x9b, 0xb4, 0x9f, 0x6d, 0x60, 0xa5, 0xb5, 0x3e, 0xb2, 0xc4, 0x96, + 0x86, 0x6d, 0x48, 0x99, 0x50, 0xc1, 0xa8, 0x93, 0x8a, 0x92, 0x7d, 0x8f, + 0x74, 0x87, 0x91, 0x71, 0x8c, 0x87, 0x90, 0x80, 0x80, 0x82, 0x7b, 0x85, + 0x81, 0x7f, 0xa7, 0x6a, 0x78, 0x4e, 0x90, 0x85, 0x9f, 0x93, 0x91, 0x91, + 0xa5, 0x6e, 0x9d, 0xa7, 0x9e, 0x7f, 0x9a, 0x66, 0xbe, 0x6f, 0x82, 0x81, + 0x85, 0x86, 0x89, 0x6c, 0x88, 0x92, 0x6d, 0x6a, 0x8c, 0x95, 0x68, 0x70, + 0x91, 0x9b, 0x76, 0x59, 0x87, 0x93, 0x6f, 0x79, 0x7a, 0x99, 0x7d, 0x76, + 0xa3, 0x9c, 0x69, 0x75, 0x8f, 0x8e, 0x7e, 0x7a, 0x80, 0x8b, 0x76, 0x82, + 0x70, 0x71, 0x77, 0x7a, 0x88, 0xa1, 0x79, 0x75, 0x9e, 0x7e, 0x6d, 0x6f, + 0xa5, 0x84, 0xb1, 0x77, 0xad, 0x94, 0x98, 0x90, 0xa7, 0x5c, 0xb6, 0x84, + 0x99, 0x91, 0x71, 0x7b, 0x6d, 0x54, 0xd2, 0x84, 0x5d, 0x75, 0xb4, 0x7e, + 0x7d, 0x53, 0xc5, 0x98, 0x70, 0xaa, 0x9e, 0x81, 0x7d, 0x68, 0xa7, 0x8d, + 0x63, 0xab, 0x9b, 0x96, 0x7e, 0x6b, 0xa3, 0x9e, 0x6d, 0x98, 0xaf, 0x9b, + 0x78, 0x74, 0xae, 0xc7, 0x70, 0x98, 0xd4, 0x9a, 0x6e, 0x75, 0xa2, 0xcd, + 0x42, 0xb0, 0xc9, 0x89, 0x88, 0x77, 0x6a, 0xa4, 0x66, 0xb5, 0xbc, 0x8a, + 0x96, 0x87, 0x5e, 0xa5, 0x87, 0x95, 0x91, 0x5d, 0x85, 0x91, 0xaa, 0x8f, + 0x99, 0x78, 0x79, 0x74, 0x7f, 0x81, 0xa1, 0x74, 0x77, 0x64, 0x6c, 0x94, + 0xa0, 0x8b, 0x9b, 0x8e, 0xac, 0x6a, 0x98, 0x9c, 0x7a, 0x9f, 0xab, 0x7e, + 0xa3, 0x8b, 0x68, 0x7f, 0x84, 0x9f, 0x93, 0x77, 0x90, 0x98, 0x8f, 0x87, + 0x81, 0x8e, 0x76, 0x95, 0x66, 0x78, 0x85, 0x79, 0x95, 0x89, 0x64, 0x8e, + 0x8a, 0x87, 0x6f, 0x65, 0xa4, 0x98, 0x7a, 0x83, 0x85, 0x7e, 0x6b, 0xaa, + 0x81, 0x94, 0x7c, 0x6e, 0x78, 0x85, 0x87, 0x6d, 0x7a, 0x92, 0x67, 0x7a, + 0x8d, 0x95, 0x77, 0x7f, 0x9f, 0x71, 0xb1, 0xa1, 0xb2, 0x91, 0x7f, 0xb0, + 0xac, 0x5c, 0xaf, 0x6a, 0xae, 0x98, 0x63, 0x7e, 0x67, 0x6f, 0xc4, 0x8a, + 0x75, 0x61, 0xac, 0x73, 0x86, 0x54, 0xc3, 0xa8, 0x5d, 0xa9, 0xb4, 0x9b, + 0x80, 0x6d, 0xa1, 0x8d, 0x64, 0xaa, 0x86, 0x96, 0x86, 0x6c, 0x9b, 0x8b, + 0x73, 0x9f, 0x9a, 0x87, 0x64, 0x6c, 0xad, 0xa6, 0x64, 0x8a, 0xbe, 0x88, + 0x67, 0x67, 0xaf, 0xb0, 0x71, 0xae, 0xde, 0x95, 0x9f, 0x7c, 0x7d, 0xa1, + 0x79, 0xb8, 0xaa, 0x9c, 0x84, 0x91, 0x6b, 0xac, 0x74, 0xa1, 0xad, 0x74, + 0x88, 0x93, 0x94, 0x72, 0x97, 0x7a, 0x78, 0x86, 0x76, 0x93, 0xb1, 0x6f, + 0x91, 0x44, 0x96, 0x8e, 0x8e, 0xa5, 0x9a, 0x70, 0x99, 0x79, 0x84, 0x82, + 0x7f, 0x78, 0xac, 0x6f, 0x9c, 0x80, 0x7d, 0x87, 0x7f, 0x9d, 0x6a, 0x71, + 0x7c, 0x92, 0x78, 0x7a, 0x93, 0x90, 0x55, 0x83, 0x7a, 0x8a, 0x9a, 0x65, + 0x86, 0x9b, 0x7c, 0x6b, 0xa3, 0x85, 0x86, 0x71, 0xab, 0x9a, 0x86, 0x90, + 0x86, 0x88, 0x88, 0x88, 0x99, 0x98, 0x77, 0x86, 0x88, 0x90, 0x79, 0x7c, + 0x6e, 0x9f, 0x76, 0x70, 0x84, 0x67, 0x7e, 0x8b, 0xa5, 0x68, 0xa7, 0x9d, + 0xb5, 0x9b, 0x8b, 0x8a, 0xc0, 0x60, 0x9e, 0x83, 0xb0, 0xb7, 0x65, 0x7f, + 0x7a, 0x7e, 0xc3, 0x7b, 0x74, 0x8f, 0xa4, 0x68, 0x5f, 0x47, 0xbb, 0xa4, + 0x74, 0x95, 0xab, 0x80, 0x70, 0x5c, 0x9a, 0x8a, 0x7d, 0xa5, 0x90, 0x7d, + 0x86, 0x68, 0xb1, 0x73, 0x6d, 0xad, 0x93, 0x8d, 0x7b, 0x64, 0xbd, 0xae, + 0x7a, 0x98, 0xcb, 0x97, 0x83, 0x67, 0xab, 0xb0, 0x61, 0xa7, 0xcd, 0x7e, + 0x87, 0x78, 0x76, 0x95, 0x6a, 0xba, 0xa9, 0x84, 0x8f, 0x95, 0x7c, 0x8b, + 0x90, 0x89, 0x8b, 0x81, 0x87, 0x8b, 0x76, 0x73, 0x6f, 0x61, 0x94, 0x73, + 0x83, 0x97, 0xb3, 0x6b, 0x9c, 0x55, 0x7f, 0x96, 0x9a, 0x92, 0x85, 0x52, + 0xc6, 0x73, 0x88, 0x9c, 0x7c, 0x86, 0x98, 0x6d, 0x99, 0x87, 0x80, 0x7c, + 0x7d, 0x98, 0x74, 0x7c, 0x89, 0x8a, 0x7d, 0x7b, 0x83, 0x90, 0x7d, 0x81, + 0x7a, 0xa0, 0x86, 0x5f, 0x74, 0x8e, 0x68, 0x7b, 0x6c, 0x86, 0x90, 0x84, + 0x7e, 0xae, 0x73, 0x6f, 0x8d, 0x81, 0x7c, 0x93, 0xa0, 0xb3, 0x6b, 0x9a, + 0x88, 0xab, 0x8a, 0x94, 0x9c, 0x87, 0x9c, 0x75, 0x7d, 0x8f, 0x7c, 0x7f, + 0x9b, 0x69, 0xa8, 0x99, 0x9d, 0x89, 0x8f, 0x72, 0xba, 0x61, 0xac, 0x91, + 0xb5, 0xa7, 0x84, 0x99, 0x71, 0x7e, 0xd0, 0x7c, 0x6d, 0x66, 0xb6, 0x72, + 0x79, 0x61, 0xb6, 0xab, 0x69, 0xa0, 0xaa, 0x7d, 0x74, 0x61, 0x95, 0xa5, + 0x71, 0xb0, 0x93, 0x95, 0x86, 0x7d, 0x9f, 0x7e, 0x6c, 0x97, 0x85, 0x87, + 0x72, 0x7b, 0xb4, 0xad, 0x84, 0x7b, 0xcd, 0xa9, 0x7e, 0x6d, 0xc8, 0xc7, + 0x7e, 0xb7, 0xcf, 0x98, 0x7b, 0x7c, 0x69, 0xaf, 0x64, 0xa6, 0xc1, 0x8e, + 0x8f, 0x9c, 0x7d, 0x93, 0x7a, 0x96, 0x8a, 0x65, 0x92, 0x95, 0x8d, 0x6f, + 0x9f, 0x7f, 0x65, 0x69, 0x7a, 0x92, 0x9f, 0x5c, 0x90, 0x4e, 0x69, 0x89, + 0x8f, 0x9c, 0xa8, 0x7a, 0xb6, 0x7d, 0x84, 0x97, 0x7f, 0x91, 0x8d, 0x71, + 0xae, 0x86, 0x80, 0x78, 0x81, 0x87, 0x6e, 0x88, 0x87, 0x7f, 0x8f, 0x9d, + 0x78, 0x91, 0x74, 0x91, 0x7f, 0x7a, 0x80, 0x63, 0x93, 0xa0, 0x7f, 0x6f, + 0xa3, 0x88, 0x76, 0x5c, 0x6e, 0xa1, 0x6e, 0x7f, 0x84, 0x8b, 0x87, 0x6d, + 0x87, 0x9f, 0x79, 0x7c, 0x83, 0x89, 0x7e, 0x86, 0xa0, 0x82, 0x80, 0x8e, + 0x8b, 0x6c, 0x6e, 0x69, 0x9f, 0x79, 0xaa, 0x6e, 0xa2, 0x8f, 0x9d, 0x87, + 0xb4, 0x5d, 0xba, 0x6c, 0xaf, 0xa0, 0x84, 0x87, 0x8c, 0x89, 0xcb, 0x6f, + 0x8e, 0x71, 0xae, 0x5d, 0x6c, 0x61, 0xb3, 0xaf, 0x7a, 0x94, 0xb1, 0x8a, + 0x80, 0x65, 0x8a, 0x9d, 0x61, 0xb6, 0x8b, 0x97, 0x8a, 0x73, 0xa8, 0x82, + 0x74, 0x8a, 0x9c, 0x73, 0x61, 0x69, 0xb8, 0x9f, 0x76, 0x90, 0xc5, 0xaa, + 0x6b, 0x5f, 0xb7, 0xce, 0x6d, 0xb7, 0xcc, 0x97, 0x7a, 0x81, 0x95, 0xbe, + 0x78, 0xb1, 0xb4, 0x97, 0x8e, 0x99, 0x70, 0xa2, 0x72, 0x8d, 0x8e, 0x7d, + 0x90, 0x9f, 0x7b, 0x63, 0x87, 0x89, 0x7a, 0x5f, 0x81, 0x97, 0x8d, 0x78, + 0x94, 0x64, 0x95, 0x9d, 0x90, 0x87, 0xb3, 0x6e, 0xc2, 0x80, 0x94, 0x86, + 0x87, 0x93, 0xb3, 0x57, 0xb8, 0x73, 0x8a, 0x81, 0x6f, 0x95, 0x89, 0x82, + 0x94, 0x7a, 0x8e, 0x97, 0x8a, 0x91, 0x7f, 0x77, 0x98, 0x72, 0x67, 0x5f, + 0x7b, 0x8d, 0x78, 0x74, 0x91, 0x82, 0x86, 0x5c, 0x88, 0xa3, 0x73, 0x6f, + 0x92, 0x78, 0x9c, 0x95, 0x99, 0x9d, 0x70, 0x89, 0x8f, 0xa7, 0x74, 0x89, + 0x77, 0x90, 0x72, 0x8d, 0x9c, 0x6f, 0x7a, 0x6c, 0x9f, 0x72, 0xad, 0x6c, + 0xa5, 0x7a, 0x9d, 0x78, 0xa4, 0x52, 0xbd, 0x94, 0xb5, 0x97, 0x75, 0x78, + 0x86, 0x72, 0xdf, 0x6f, 0x98, 0x81, 0xab, 0x5d, 0x62, 0x65, 0x9d, 0xbc, + 0x68, 0x8a, 0xc1, 0x7e, 0x67, 0x7f, 0x88, 0x95, 0x7f, 0xbd, 0x9c, 0x77, + 0x7d, 0x7e, 0x96, 0x7c, 0x7f, 0xa1, 0xa4, 0x90, 0x7c, 0x74, 0xc0, 0xac, + 0x7d, 0xa1, 0xdb, 0x85, 0x85, 0x51, 0xbc, 0xb1, 0x6c, 0xcb, 0xd1, 0xa7, + 0x76, 0x70, 0x7d, 0xba, 0x88, 0xb6, 0xaf, 0xa2, 0x9d, 0x9b, 0x71, 0x96, + 0x80, 0x89, 0xa3, 0x86, 0x89, 0x8f, 0x76, 0x77, 0xa9, 0x82, 0x8f, 0x69, + 0x7f, 0x9d, 0xac, 0x80, 0x98, 0x6c, 0x70, 0x72, 0x81, 0x8b, 0xaf, 0x80, + 0xb1, 0x6f, 0x7c, 0x90, 0x91, 0x82, 0xa5, 0x67, 0x9c, 0x76, 0x8c, 0x6b, + 0x9c, 0x9b, 0x87, 0x8c, 0x8e, 0x8b, 0xb0, 0x9d, 0x89, 0x8f, 0x76, 0x87, + 0x9b, 0x90, 0x8e, 0x74, 0x73, 0x91, 0x85, 0x80, 0x81, 0x72, 0x99, 0x84, + 0x87, 0x95, 0x84, 0x8c, 0x8a, 0x6e, 0x8c, 0x82, 0xad, 0x9d, 0x80, 0x7f, + 0x96, 0x9c, 0x7f, 0x67, 0xb0, 0x98, 0x69, 0x84, 0x94, 0xa9, 0x7e, 0x83, + 0x9d, 0x62, 0x92, 0x6e, 0x95, 0x88, 0xa4, 0x90, 0x97, 0x4d, 0xae, 0x89, + 0xb6, 0xa1, 0x88, 0x9f, 0x7a, 0x70, 0xc2, 0x71, 0x7f, 0x83, 0x90, 0x83, + 0x5e, 0x50, 0xa9, 0x9f, 0x73, 0x8c, 0xb2, 0x80, 0x79, 0x65, 0x7c, 0x90, + 0x6d, 0x9a, 0x91, 0x8d, 0x6f, 0x65, 0x97, 0x87, 0x82, 0xa0, 0xa4, 0x8c, + 0x68, 0x76, 0xa8, 0xa2, 0x7f, 0xa4, 0xcd, 0x91, 0x70, 0x54, 0x95, 0xc6, + 0x6e, 0x9c, 0xe2, 0xa1, 0x86, 0x82, 0x73, 0xbc, 0x89, 0xaa, 0xb2, 0x7d, + 0x82, 0x84, 0x8b, 0x9e, 0x84, 0x94, 0xa0, 0x7a, 0x98, 0x9d, 0x99, 0x7b, + 0x7b, 0x89, 0x8f, 0x66, 0x89, 0x9b, 0xa7, 0x8b, 0x9b, 0x62, 0x9b, 0x78, + 0x8b, 0x95, 0xbd, 0x7a, 0x9e, 0x61, 0x80, 0x84, 0x89, 0x8e, 0xb4, 0x7b, + 0xb8, 0x70, 0x75, 0x8e, 0x7b, 0x9c, 0x9e, 0x9f, 0x89, 0x86, 0x9b, 0x7a, + 0x7b, 0x95, 0x83, 0x95, 0x80, 0x94, 0x85, 0x65, 0x8c, 0x81, 0x67, 0x77, + 0x94, 0x8a, 0x92, 0x74, 0x72, 0x90, 0x6b, 0x74, 0x7e, 0x75, 0x71, 0x84, + 0x9e, 0xa6, 0x64, 0x80, 0x8d, 0x7a, 0x8c, 0x82, 0x98, 0x96, 0x64, 0x7d, + 0x8b, 0x82, 0x6a, 0x7f, 0x97, 0x4e, 0x91, 0x74, 0x94, 0x99, 0x6d, 0x6a, + 0xb3, 0x5a, 0xb8, 0x64, 0xa3, 0x95, 0x5d, 0x95, 0x90, 0x87, 0xcc, 0x72, + 0x85, 0x85, 0x8f, 0x55, 0x6f, 0x65, 0x84, 0xb6, 0x7b, 0x77, 0xce, 0x79, + 0x82, 0x59, 0x8a, 0xa2, 0x68, 0x9b, 0xa3, 0x81, 0x9c, 0x7a, 0x97, 0x87, + 0x6b, 0x8c, 0x9c, 0xaa, 0x5c, 0x69, 0xb8, 0xb7, 0x7c, 0xa0, 0xb5, 0x92, + 0x8d, 0x67, 0x96, 0xd2, 0x77, 0xa6, 0xd9, 0xad, 0xaa, 0x79, 0x90, 0xc9, + 0x81, 0xbf, 0xd0, 0x8d, 0x9d, 0x88, 0x9c, 0x91, 0x90, 0x94, 0x89, 0x8a, + 0x91, 0x9b, 0x89, 0x79, 0x92, 0x80, 0x8f, 0x7b, 0x7e, 0x8b, 0xb1, 0x85, + 0xa4, 0x5a, 0xb4, 0x7a, 0xa7, 0x8c, 0xa4, 0x75, 0xb9, 0x66, 0x93, 0x86, + 0x8a, 0x87, 0xad, 0x64, 0xa2, 0x7e, 0x99, 0x9f, 0x81, 0xa2, 0x9b, 0x88, + 0x9e, 0xa2, 0xb9, 0x8a, 0x78, 0x84, 0x91, 0x8e, 0x8b, 0x90, 0x83, 0x80, + 0x64, 0x93, 0x77, 0x89, 0x81, 0x86, 0x96, 0x7a, 0x81, 0xab, 0x6d, 0x73, + 0x7d, 0x7e, 0xaa, 0x85, 0x95, 0xac, 0x8b, 0x89, 0x8b, 0x77, 0xa3, 0x8b, + 0xa3, 0xa0, 0x87, 0x86, 0x7a, 0x74, 0x6f, 0x7c, 0x90, 0x58, 0xa2, 0x64, + 0x94, 0x8b, 0xa0, 0x88, 0xab, 0x53, 0xce, 0x67, 0xb7, 0x7f, 0x8d, 0x69, + 0x84, 0x74, 0xaf, 0x72, 0xab, 0x70, 0x8f, 0x6e, 0x5d, 0x61, 0x96, 0xa1, + 0x7b, 0x6f, 0xa2, 0x75, 0x8f, 0x5d, 0x93, 0x72, 0x82, 0x97, 0x76, 0x65, + 0x7e, 0x96, 0xb3, 0x8b, 0x8d, 0x89, 0x8f, 0x7b, 0x6f, 0x71, 0xa1, 0x9e, + 0x91, 0x7c, 0xc9, 0x9f, 0x7c, 0x71, 0xa1, 0xba, 0x77, 0xa5, 0xd4, 0xa6, + 0xa0, 0x82, 0x7b, 0x95, 0x9d, 0xb7, 0xaa, 0x8d, 0x71, 0x87, 0x94, 0x7e, + 0x88, 0x7f, 0x8b, 0x6e, 0x93, 0x9f, 0x82, 0x88, 0x94, 0x8a, 0x97, 0x7f, + 0x7d, 0x8c, 0xa0, 0x84, 0xb4, 0x7c, 0x8c, 0x7f, 0x71, 0x8c, 0x8e, 0x7f, + 0xc6, 0x64, 0x81, 0x8d, 0x89, 0x8d, 0xc4, 0x77, 0xaf, 0x75, 0x92, 0x7f, + 0x84, 0xa1, 0x99, 0x94, 0x9e, 0x82, 0x7a, 0x98, 0x7e, 0x8e, 0x93, 0x8c, + 0x6b, 0x93, 0x84, 0xaa, 0x7f, 0x8f, 0x6b, 0x94, 0xa3, 0x8a, 0x78, 0x82, + 0x60, 0x92, 0x8b, 0x8d, 0x75, 0x8c, 0x8e, 0x6e, 0x7e, 0x9d, 0x6d, 0x8e, + 0x79, 0x8d, 0x80, 0x89, 0xaa, 0x99, 0x7e, 0xa3, 0x83, 0x95, 0x83, 0x85, + 0x9c, 0x60, 0x99, 0x78, 0x93, 0x8b, 0x80, 0x82, 0x9d, 0x6b, 0xc2, 0x54, + 0xb9, 0x7a, 0x83, 0x98, 0x88, 0x65, 0xcb, 0x52, 0xa7, 0x8d, 0x7f, 0x81, + 0x6b, 0x6d, 0x9e, 0x92, 0x85, 0x82, 0x9f, 0x67, 0x6f, 0x74, 0xaa, 0x75, + 0x99, 0x9f, 0x8a, 0x8b, 0x88, 0x82, 0xb8, 0x6b, 0x85, 0x99, 0x93, 0x90, + 0x8d, 0x7a, 0xaa, 0x9d, 0x86, 0x7f, 0xbd, 0x91, 0x67, 0x65, 0x8c, 0xb3, + 0x87, 0x94, 0xa3, 0x9a, 0x7e, 0x73, 0x83, 0xaa, 0x7a, 0xba, 0xaa, 0x9e, + 0x9e, 0x86, 0x9a, 0x63, 0x9c, 0x98, 0x5e, 0xa0, 0x9c, 0x9e, 0x8b, 0x85, + 0xa2, 0x74, 0x80, 0x8d, 0x7e, 0x89, 0xc0, 0x75, 0xa5, 0x3f, 0x97, 0xa2, + 0x8c, 0x8c, 0x9d, 0x88, 0xa4, 0x5e, 0x75, 0x5f, 0x87, 0x82, 0xbc, 0x72, + 0xa3, 0x77, 0x83, 0x79, 0x82, 0x95, 0x8d, 0x77, 0x73, 0x81, 0x9d, 0x9b, + 0x6c, 0x87, 0x93, 0x96, 0x83, 0x86, 0x8b, 0x89, 0x72, 0x7d, 0x96, 0x78, + 0x67, 0xa2, 0x8d, 0x81, 0x6a, 0x98, 0x75, 0x80, 0x8a, 0x80, 0x9e, 0x82, + 0x76, 0x9b, 0x6c, 0x94, 0x7a, 0x96, 0x74, 0x92, 0x78, 0x91, 0x7a, 0x7c, + 0x9a, 0x98, 0x70, 0x5d, 0x9c, 0x4b, 0x70, 0x7d, 0xa9, 0x9b, 0x70, 0x96, + 0xad, 0x59, 0xc4, 0x63, 0xbc, 0x8f, 0x5c, 0x86, 0x8e, 0x97, 0xa0, 0x7c, + 0xa6, 0x77, 0xaa, 0x93, 0x68, 0x66, 0x93, 0x91, 0x7b, 0x7e, 0xa2, 0x7a, + 0x98, 0x77, 0x97, 0x59, 0x84, 0x76, 0x9c, 0x7b, 0x8b, 0x76, 0x88, 0x7a, + 0x8c, 0x7b, 0xa4, 0xae, 0x6e, 0x7d, 0xb3, 0x99, 0x8d, 0x68, 0x9e, 0x7e, + 0x77, 0x59, 0x80, 0xbe, 0x80, 0x83, 0xd9, 0x9f, 0x7d, 0x60, 0x8b, 0x98, + 0x7f, 0x9e, 0xa3, 0x8d, 0x7d, 0x81, 0x9e, 0x78, 0x99, 0x94, 0x70, 0x80, + 0x9b, 0x89, 0x8c, 0x6d, 0x9c, 0x95, 0x76, 0x7c, 0x83, 0x87, 0x97, 0x93, + 0x89, 0x6d, 0x77, 0x7e, 0x7e, 0x87, 0x8e, 0x7e, 0x94, 0x61, 0x94, 0xa2, + 0x94, 0x91, 0xa1, 0x64, 0xc1, 0x78, 0x79, 0xaf, 0x67, 0x7a, 0x9b, 0xa1, + 0x95, 0x8e, 0x97, 0x84, 0x7b, 0x85, 0x80, 0xa1, 0x6f, 0x87, 0x79, 0x83, + 0x73, 0x9d, 0x81, 0x64, 0x7a, 0x7f, 0x8f, 0x91, 0x73, 0x97, 0x74, 0x8b, + 0x7e, 0x88, 0x7f, 0x7e, 0x6e, 0xa1, 0x85, 0x8f, 0x77, 0x93, 0x7a, 0x6f, + 0x7b, 0x91, 0x67, 0x73, 0x8b, 0x97, 0x6d, 0x87, 0x84, 0xf8, 0xff, 0xff, + 0x88, 0xf8, 0xff, 0xff, 0xe6, 0xf8, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x80, 0x02, 0x00, 0x00, 0x73, 0x84, 0xbb, 0xa4, 0xa5, 0x44, 0x5c, 0xb1, + 0x8e, 0x50, 0x82, 0x8b, 0x81, 0x86, 0x48, 0x80, 0xa9, 0x61, 0xa3, 0xa8, + 0xca, 0x5a, 0x9d, 0x8a, 0x89, 0x7c, 0x65, 0x91, 0x5e, 0x70, 0x84, 0x71, + 0xbc, 0x36, 0x8e, 0x8b, 0xa6, 0x63, 0xb7, 0x75, 0x92, 0x59, 0x60, 0x7e, + 0x33, 0x8f, 0x90, 0x7a, 0xa9, 0x27, 0x72, 0x80, 0x62, 0x95, 0x93, 0x7b, + 0x60, 0x46, 0x40, 0x55, 0x01, 0x9e, 0x8a, 0x6b, 0x58, 0x8a, 0xa6, 0xb7, + 0x91, 0x39, 0x72, 0xb4, 0x6e, 0x67, 0x83, 0x91, 0x82, 0x7b, 0x64, 0x7a, + 0x87, 0x6e, 0xb0, 0xa0, 0xd3, 0x53, 0xb7, 0x93, 0x76, 0xa6, 0x68, 0x8a, + 0x74, 0x6a, 0x96, 0x6e, 0xb3, 0x53, 0xaa, 0x89, 0xf1, 0x76, 0xb8, 0x75, + 0x8b, 0x66, 0x5f, 0x6e, 0x52, 0x92, 0x6f, 0x82, 0xbe, 0x45, 0x8d, 0x69, + 0x98, 0x98, 0x80, 0x87, 0x73, 0x7d, 0x4d, 0x42, 0x1f, 0xa5, 0x6a, 0x73, + 0x47, 0x87, 0x8a, 0xd1, 0x75, 0x30, 0x91, 0xae, 0x60, 0x82, 0x7a, 0x94, + 0x75, 0x71, 0x6a, 0x7c, 0x74, 0x7a, 0xac, 0xa2, 0xb6, 0x51, 0xc6, 0x97, + 0x63, 0xa0, 0x67, 0x7f, 0x80, 0x69, 0x88, 0x6b, 0xa5, 0x5e, 0xc2, 0x72, + 0xf4, 0x6e, 0xaf, 0x76, 0x7f, 0x7c, 0x55, 0x68, 0x67, 0x97, 0x61, 0x7b, + 0xbe, 0x5e, 0xab, 0x58, 0xca, 0xa2, 0x77, 0x7a, 0x8f, 0x6e, 0x54, 0x33, + 0x4d, 0xa7, 0x5d, 0x66, 0x47, 0x92, 0x6f, 0xd6, 0x5c, 0x25, 0xa9, 0xbc, + 0x5c, 0xb8, 0x64, 0x9b, 0x58, 0x6e, 0x77, 0x76, 0x6a, 0x94, 0xb2, 0xac, + 0x9a, 0x51, 0xd0, 0x94, 0x62, 0xcc, 0x5a, 0x7f, 0x74, 0x6e, 0x7d, 0x71, + 0x9b, 0x69, 0xd3, 0x64, 0xef, 0x76, 0xaa, 0x75, 0x89, 0x84, 0x50, 0x76, + 0x72, 0x97, 0x5f, 0x77, 0xc5, 0x66, 0xce, 0x3a, 0xe5, 0xad, 0x5a, 0x81, + 0x9e, 0x8e, 0x60, 0x3d, 0x6d, 0xa9, 0x46, 0x6b, 0x44, 0x89, 0x4d, 0xd8, + 0x4c, 0x28, 0xb1, 0xb7, 0x60, 0xc7, 0x57, 0xb5, 0x50, 0x68, 0x88, 0x7c, + 0x60, 0x98, 0xac, 0x9a, 0x7f, 0x51, 0xce, 0x8a, 0x5e, 0xd8, 0x51, 0x7d, + 0x68, 0x6e, 0x7f, 0x6e, 0x90, 0x7b, 0xdf, 0x60, 0xda, 0x77, 0x91, 0x6f, + 0x85, 0xa0, 0x58, 0x73, 0x70, 0x93, 0x51, 0x7d, 0xb9, 0x70, 0xf5, 0x31, + 0xe9, 0xa3, 0x47, 0x76, 0xa7, 0x9b, 0x72, 0x3d, 0x90, 0xb2, 0x57, 0x64, + 0x5b, 0x6f, 0x2b, 0xcf, 0x52, 0x28, 0xc1, 0xa7, 0x6a, 0x78, 0x51, 0xad, + 0x49, 0x70, 0x90, 0x81, 0x5c, 0x7e, 0x9e, 0x99, 0x77, 0x50, 0xc0, 0x94, + 0x63, 0xb7, 0x4d, 0x71, 0x58, 0x66, 0x76, 0x6d, 0x78, 0x6a, 0xe1, 0x40, + 0xc7, 0x73, 0x7f, 0x65, 0x7c, 0x7f, 0x4d, 0x80, 0x64, 0x95, 0x57, 0x81, + 0xb1, 0x5e, 0xff, 0x26, 0xd6, 0xa2, 0x3a, 0x73, 0xa7, 0x81, 0x76, 0x5d, + 0x92, 0xb1, 0x58, 0x48, 0x4e, 0x5e, 0x1a, 0xc8, 0x58, 0x2c, 0xb6, 0xa7, + 0x67, 0x89, 0x5e, 0xa0, 0x4f, 0x78, 0x93, 0x8b, 0x57, 0x7b, 0x95, 0x78, + 0x6e, 0x46, 0xb2, 0x98, 0x55, 0xd3, 0x5e, 0x66, 0x56, 0x68, 0x74, 0x7e, + 0x72, 0x74, 0xdd, 0x36, 0xa6, 0x64, 0x65, 0x6b, 0x81, 0x98, 0x56, 0x76, + 0x65, 0x93, 0x58, 0x7d, 0x9b, 0x82, 0xef, 0x44, 0xbf, 0xa4, 0x3d, 0x57, + 0xa0, 0xa7, 0x7a, 0x74, 0x9f, 0xa8, 0x70, 0x52, 0x55, 0x5f, 0x1a, 0x94, + 0x64, 0x37, 0xa7, 0xa6, 0x80, 0x7d, 0x6e, 0x99, 0x5d, 0x81, 0x8a, 0x99, + 0x5c, 0x76, 0x8f, 0x44, 0x68, 0x50, 0x94, 0x97, 0x63, 0xb6, 0x73, 0x56, + 0x5b, 0x70, 0x66, 0x8b, 0x72, 0x78, 0xcc, 0x31, 0x8b, 0x68, 0x4a, 0x74, + 0x7d, 0x99, 0x54, 0x91, 0x6a, 0x90, 0x5d, 0x80, 0x8c, 0x82, 0xcd, 0x4f, + 0xb0, 0x96, 0x63, 0x56, 0x97, 0xb3, 0x7e, 0x97, 0xa4, 0x9d, 0x7a, 0x5d, + 0x49, 0x36, 0x18, 0x64, 0x60, 0x43, 0x89, 0xa2, 0x6a, 0x49, 0x7f, 0x58, + 0x6a, 0x83, 0x77, 0x9d, 0x70, 0x3b, 0x83, 0x21, 0x59, 0x52, 0x6d, 0x95, + 0x48, 0xa8, 0x8a, 0x42, 0x50, 0x6d, 0x44, 0x95, 0x69, 0x50, 0xc1, 0x4b, + 0x7c, 0x59, 0x42, 0x78, 0x77, 0x7f, 0x5b, 0x98, 0x67, 0x89, 0x55, 0x8b, + 0x82, 0x47, 0xb7, 0x64, 0x9d, 0x83, 0x5c, 0x53, 0x89, 0x90, 0x79, 0xb2, + 0x90, 0x98, 0x85, 0x5a, 0x4d, 0x2b, 0x19, 0x1e, 0x52, 0x50, 0x57, 0x8b, + 0x73, 0x3a, 0x88, 0x1e, 0x65, 0x80, 0x4d, 0x9b, 0x6c, 0x3c, 0x86, 0x26, + 0x5b, 0x56, 0x36, 0x98, 0x49, 0x87, 0x9f, 0x2a, 0x40, 0x61, 0x27, 0x9d, + 0x63, 0x40, 0xa8, 0x46, 0x6b, 0x52, 0x52, 0x7f, 0x67, 0x6a, 0x58, 0xa1, + 0x5d, 0x6d, 0x5f, 0x9a, 0x72, 0x3a, 0x99, 0x63, 0x8c, 0x80, 0x68, 0x58, + 0x72, 0x6a, 0x7c, 0xbb, 0x7e, 0x78, 0x94, 0x60, 0x72, 0xfb, 0xff, 0xff, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x96, 0xfe, 0xff, 0xff, + 0x8f, 0x00, 0x00, 0x00, 0x8f, 0xfc, 0xff, 0xff, 0xb4, 0xfe, 0xff, 0xff, + 0xc1, 0xfd, 0xff, 0xff, 0x59, 0xff, 0xff, 0xff, 0xbc, 0xfe, 0xff, 0xff, + 0x09, 0xff, 0xff, 0xff, 0x9e, 0xfb, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xe9, 0x03, 0x00, 0x00, 0x2b, 0xfd, 0xff, 0xff, + 0x3b, 0xfd, 0xff, 0xff, 0x91, 0x01, 0x00, 0x00, 0x60, 0xfb, 0xff, 0xff, + 0x04, 0xfd, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x78, 0x03, 0x00, 0x00, + 0x88, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x64, 0x02, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, + 0xb2, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, 0x24, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 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, 0x84, 0xfd, 0xff, 0xff, + 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3b, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x3f, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x22, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, + 0x1c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x5f, + 0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0xec, 0xfd, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x17, 0xb1, 0x3d, + 0x01, 0x00, 0x00, 0x00, 0x84, 0xdb, 0x33, 0x41, 0x01, 0x00, 0x00, 0x00, + 0x9d, 0xf0, 0x2c, 0xc1, 0x8e, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, + 0x48, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x73, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x5f, 0x31, 0x2f, + 0x46, 0x61, 0x6b, 0x65, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x57, 0x69, 0x74, + 0x68, 0x4d, 0x69, 0x6e, 0x4d, 0x61, 0x78, 0x56, 0x61, 0x72, 0x73, 0x2f, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x00, + 0x84, 0xfe, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xac, 0x5f, 0xf6, 0x39, 0x01, 0x00, 0x00, 0x00, 0x1d, 0xaf, 0x62, 0x3d, + 0x01, 0x00, 0x00, 0x00, 0x5e, 0x1b, 0x83, 0xbd, 0x22, 0xfe, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x03, 0x1c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x24, 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, 0xf4, 0xfe, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 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, 0x47, 0x0f, 0x72, 0x3d, + 0x01, 0x00, 0x00, 0x00, 0x38, 0x1d, 0x71, 0x41, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x96, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, + 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68, + 0x61, 0x70, 0x65, 0x5f, 0x31, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x6c, 0xff, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 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, 0xc6, 0xd0, 0xd0, 0x3d, + 0x01, 0x00, 0x00, 0x00, 0xf5, 0xff, 0xcf, 0x41, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x03, + 0x3c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x73, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x2f, 0x46, 0x61, + 0x6b, 0x65, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x4d, + 0x69, 0x6e, 0x4d, 0x61, 0x78, 0x56, 0x61, 0x72, 0x73, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 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, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf7, 0x5e, 0x6c, 0x3a, + 0x01, 0x00, 0x00, 0x00, 0x30, 0x42, 0xec, 0x3d, 0x01, 0x00, 0x00, 0x00, + 0x42, 0xca, 0xe8, 0xbd, 0xaa, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, + 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x76, + 0x32, 0x44, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 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, + 0xec, 0xcd, 0xc0, 0x38, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x08, 0x00, + 0x07, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x25, 0xf5, 0xe8, 0x37, 0x03, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, + 0x14, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x07, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x07, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xff, 0xff, + 0x00, 0x19, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x09, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04}; +const int g_tiny_conv_micro_features_model_data_len = 18208; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.h new file mode 100644 index 00000000000..22c0a970b77 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_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 tiny_conv.tflite > tiny_conv_simple_features_model_data.cc + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_TINY_CONV_MICRO_FEATURES_MODEL_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_TINY_CONV_MICRO_FEATURES_MODEL_DATA_H_ + +extern const unsigned char g_tiny_conv_micro_features_model_data[]; +extern const int g_tiny_conv_micro_features_model_data_len; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_TINY_CONV_MICRO_FEATURES_MODEL_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.cc new file mode 100644 index 00000000000..51b7d8b35bc --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.cc @@ -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/micro/examples/micro_speech/micro_features/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 = ((static_cast(*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/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.h new file mode 100644 index 00000000000..b32c059d81a --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.h @@ -0,0 +1,43 @@ +/* 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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_WINDOW_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_WINDOW_H_ + +#include +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" + +#define kFrontendWindowBits 12 + +struct WindowState { + size_t size; + int16_t coefficients[kMaxAudioSampleSize]; + size_t step; + + int16_t input[kMaxAudioSampleSize]; + size_t input_used; + int16_t output[kMaxAudioSampleSize]; + 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); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_WINDOW_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_test.cc new file mode 100644 index 00000000000..310f84fc60b --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_test.cc @@ -0,0 +1,183 @@ +/* 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/micro/examples/micro_speech/micro_features/window.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.h" + +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +namespace { + +const int kSampleRate = 1000; +const int kWindowSamples = 25; +const int kStepSamples = 10; +const int16_t kFakeAudioData[] = { + 0, 32767, 0, -32768, 0, 32767, 0, -32768, 0, 32767, 0, -32768, + 0, 32767, 0, -32768, 0, 32767, 0, -32768, 0, 32767, 0, -32768, + 0, 32767, 0, -32768, 0, 32767, 0, -32768, 0, 32767, 0, -32768}; + +// Test window function behaviors using default config values. +class WindowTestConfig { + public: + WindowTestConfig() { + config_.size_ms = 25; + config_.step_size_ms = 10; + } + + struct WindowConfig config_; +}; + +} // namespace + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(WindowState_CheckCoefficients) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + WindowTestConfig config; + struct WindowState state; + TF_LITE_MICRO_EXPECT(WindowPopulateState(error_reporter, &config.config_, + &state, kSampleRate)); + + const int16_t expected[] = {16, 144, 391, 743, 1176, 1664, 2177, + 2681, 3145, 3541, 3843, 4032, 4096, 4032, + 3843, 3541, 3145, 2681, 2177, 1664, 1176, + 743, 391, 144, 16}; + TF_LITE_MICRO_EXPECT_EQ(state.size, sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < state.size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.coefficients[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(WindowState_CheckResidualInput) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + WindowTestConfig config; + struct WindowState state; + TF_LITE_MICRO_EXPECT(WindowPopulateState(error_reporter, &config.config_, + &state, kSampleRate)); + size_t num_samples_read; + + TF_LITE_MICRO_EXPECT(WindowProcessSamples( + &state, kFakeAudioData, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]), &num_samples_read)); + + int i; + for (i = kStepSamples; i < kWindowSamples; ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.input[i - kStepSamples], kFakeAudioData[i]); + } +} + +TF_LITE_MICRO_TEST(WindowState_CheckOutputValues) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + WindowTestConfig config; + struct WindowState state; + TF_LITE_MICRO_EXPECT(WindowPopulateState(error_reporter, &config.config_, + &state, kSampleRate)); + size_t num_samples_read; + + TF_LITE_MICRO_EXPECT(WindowProcessSamples( + &state, kFakeAudioData, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]), &num_samples_read)); + + const int16_t expected[] = { + 0, 1151, 0, -5944, 0, 13311, 0, -21448, 0, 28327, 0, -32256, 0, 32255, + 0, -28328, 0, 21447, 0, -13312, 0, 5943, 0, -1152, 0}; + TF_LITE_MICRO_EXPECT_EQ(state.size, sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < state.size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.output[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(WindowState_CheckMaxAbsValue) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + WindowTestConfig config; + struct WindowState state; + TF_LITE_MICRO_EXPECT(WindowPopulateState(error_reporter, &config.config_, + &state, kSampleRate)); + size_t num_samples_read; + + TF_LITE_MICRO_EXPECT(WindowProcessSamples( + &state, kFakeAudioData, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]), &num_samples_read)); + + TF_LITE_MICRO_EXPECT_EQ(state.max_abs_output_value, 32256); +} + +TF_LITE_MICRO_TEST(WindowState_CheckConsecutiveWindow) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + WindowTestConfig config; + struct WindowState state; + TF_LITE_MICRO_EXPECT(WindowPopulateState(error_reporter, &config.config_, + &state, kSampleRate)); + size_t num_samples_read; + + TF_LITE_MICRO_EXPECT(WindowProcessSamples( + &state, kFakeAudioData, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]), &num_samples_read)); + TF_LITE_MICRO_EXPECT(WindowProcessSamples( + &state, kFakeAudioData + kWindowSamples, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]) - kWindowSamples, + &num_samples_read)); + + const int16_t expected[] = { + 0, -1152, 0, 5943, 0, -13312, 0, 21447, 0, -28328, 0, 32255, 0, -32256, + 0, 28327, 0, -21448, 0, 13311, 0, -5944, 0, 1151, 0}; + TF_LITE_MICRO_EXPECT_EQ(state.size, sizeof(expected) / sizeof(expected[0])); + int i; + for (i = 0; i < state.size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(state.output[i], expected[i]); + } +} + +TF_LITE_MICRO_TEST(WindowState_CheckNotEnoughSamples) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + WindowTestConfig config; + struct WindowState state; + TF_LITE_MICRO_EXPECT(WindowPopulateState(error_reporter, &config.config_, + &state, kSampleRate)); + size_t num_samples_read; + + TF_LITE_MICRO_EXPECT(WindowProcessSamples( + &state, kFakeAudioData, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]), &num_samples_read)); + TF_LITE_MICRO_EXPECT(WindowProcessSamples( + &state, kFakeAudioData + kWindowSamples, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]) - kWindowSamples, + &num_samples_read)); + TF_LITE_MICRO_EXPECT_EQ( + false, WindowProcessSamples( + &state, kFakeAudioData + kWindowSamples + kStepSamples, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]) - + kWindowSamples - kStepSamples, + &num_samples_read)); + + TF_LITE_MICRO_EXPECT_EQ( + state.input_used, + sizeof(kFakeAudioData) / sizeof(kFakeAudioData[0]) - 2 * kStepSamples); +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.cc new file mode 100644 index 00000000000..618973b39b2 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.cc @@ -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. +==============================================================================*/ +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.h" + +#include +#include +#include + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/static_alloc.h" + +// Needed because some platforms don't have M_PI defined. +#define WINDOW_PI (3.14159265358979323846f) + +void WindowFillConfigWithDefaults(struct WindowConfig* config) { + config->size_ms = 25; + config->step_size_ms = 10; +} + +int WindowPopulateState(tflite::ErrorReporter* error_reporter, + 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; + + STATIC_ALLOC_ENSURE_ARRAY_SIZE(state->coefficients, + (state->size * sizeof(*state->coefficients))); + + // Populate the window values. + const float arg = WINDOW_PI * 2.0 / (static_cast(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; + STATIC_ALLOC_ENSURE_ARRAY_SIZE(state->input, + (state->size * sizeof(*state->input))); + + STATIC_ALLOC_ENSURE_ARRAY_SIZE(state->output, + (state->size * sizeof(*state->output))); + return 1; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.h new file mode 100644 index 00000000000..d0c61c29dc9 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window_util.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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_WINDOW_UTIL_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_WINDOW_UTIL_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/window.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" + +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(tflite::ErrorReporter* error_reporter, + const struct WindowConfig* config, + struct WindowState* state, int sample_rate); + +// Frees any allocated buffers. +void WindowFreeStateContents(struct WindowState* state); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_WINDOW_UTIL_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.cc new file mode 100644 index 00000000000..48535d12d5d --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.cc @@ -0,0 +1,24 @@ +/* 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. +==============================================================================*/ + +// See the header for documentation on the meaning of this data. + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.h" + +const uint8_t g_yes_feature_data_slice[g_yes_feature_data_slice_size] = { + 214, 215, 236, 202, 235, 203, 225, 191, 203, 188, 199, 194, 212, 127, + 51, 0, 174, 188, 219, 196, 228, 221, 240, 207, 235, 220, 241, 219, + 237, 207, 212, 142, 95, 0, 139, 78, 162, 177, 197, 183, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.h new file mode 100644 index 00000000000..e73a13153b6 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_feature_data_slice.h @@ -0,0 +1,29 @@ +/* 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 data was extracted from the larger feature data held in +// no_micro_features_data.cc and consists of the 26th spectrogram slice of 40 +// values. This is the expected result of running the sample data in +// yes_30ms_sample_data.cc through through the preprocessing pipeline. + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_YES_FEATURE_DATA_SLICE_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_YES_FEATURE_DATA_SLICE_H_ + +#include + +constexpr int g_yes_feature_data_slice_size = 40; +extern const uint8_t g_yes_feature_data_slice[]; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_YES_FEATURE_DATA_SLICE_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.cc new file mode 100644 index 00000000000..2c2ee0995c0 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.cc @@ -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. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h" + +/* File automatically created by + * tensorflow/examples/speech_commands/wav_to_features.py \ + * --sample_rate=16000 \ + * --clip_duration_ms=1000 \ + * --window_size_ms=30 \ + * --window_stride_ms=20 \ + * --feature_bin_count=40 \ + * --quantize=1 \ + * --preprocess="micro" \ + * --input_wav="speech_commands_test_set_v0.02/yes/f2e59fea_nohash_1.wav" \ + * --output_c_file="yes_micro_features_data.cc" \ + */ + +const int g_yes_micro_f2e59fea_nohash_1_width = 40; +const int g_yes_micro_f2e59fea_nohash_1_height = 49; +const unsigned char g_yes_micro_f2e59fea_nohash_1_data[] = { + 244, 226, 245, 223, 234, 213, 228, 208, 194, 110, 95, 116, 102, 0, 137, + 161, 183, 173, 137, 116, 133, 157, 151, 156, 128, 110, 128, 0, 68, 78, + 78, 90, 68, 68, 78, 102, 95, 78, 95, 78, 210, 188, 209, 183, 204, + 188, 201, 191, 166, 119, 90, 107, 110, 107, 175, 157, 179, 168, 182, 145, + 152, 164, 171, 165, 136, 143, 122, 68, 0, 78, 90, 90, 110, 90, 102, + 99, 90, 68, 78, 68, 223, 186, 179, 123, 182, 110, 196, 171, 159, 110, + 102, 95, 90, 99, 160, 134, 125, 136, 153, 152, 164, 134, 164, 151, 141, + 136, 99, 90, 90, 90, 78, 78, 102, 119, 102, 90, 110, 90, 68, 51, + 177, 175, 211, 172, 183, 0, 95, 68, 129, 102, 68, 85, 114, 105, 110, + 85, 102, 95, 140, 51, 85, 51, 95, 90, 143, 116, 90, 78, 78, 51, + 107, 85, 68, 0, 68, 51, 90, 51, 68, 0, 164, 117, 193, 120, 156, + 0, 138, 51, 90, 0, 51, 0, 51, 85, 0, 0, 51, 0, 0, 0, + 0, 0, 114, 0, 85, 78, 90, 51, 0, 0, 51, 85, 99, 85, 107, + 68, 90, 85, 78, 0, 51, 0, 110, 0, 68, 0, 0, 0, 51, 0, + 51, 0, 0, 0, 68, 90, 107, 0, 68, 0, 0, 0, 68, 0, 51, + 68, 0, 78, 68, 0, 51, 0, 78, 68, 90, 68, 78, 51, 51, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, + 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 68, + 0, 0, 78, 0, 78, 0, 78, 0, 51, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 51, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 51, + 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, + 0, 0, 0, 0, 51, 78, 0, 0, 51, 51, 0, 0, 0, 78, 0, + 213, 170, 192, 180, 196, 188, 173, 131, 173, 116, 137, 105, 159, 127, 0, + 0, 0, 0, 127, 164, 165, 161, 170, 164, 185, 197, 195, 167, 134, 138, + 159, 134, 136, 105, 51, 0, 99, 0, 51, 0, 228, 215, 229, 218, 237, + 215, 228, 210, 237, 222, 239, 211, 208, 211, 234, 218, 220, 209, 225, 219, + 235, 222, 245, 225, 245, 224, 243, 223, 241, 218, 237, 224, 234, 213, 221, + 193, 197, 164, 157, 128, 227, 188, 232, 196, 220, 220, 240, 219, 234, 213, + 234, 211, 231, 218, 233, 213, 239, 215, 228, 207, 229, 206, 224, 208, 226, + 207, 232, 210, 225, 208, 230, 199, 227, 206, 210, 205, 218, 174, 178, 141, + 235, 208, 220, 206, 225, 203, 233, 203, 225, 167, 205, 199, 208, 190, 221, + 204, 223, 207, 225, 188, 225, 197, 215, 188, 199, 183, 225, 195, 224, 200, + 216, 178, 208, 188, 215, 202, 214, 183, 176, 140, 198, 150, 211, 194, 203, + 120, 175, 188, 204, 189, 219, 192, 223, 202, 216, 186, 203, 185, 210, 182, + 214, 183, 204, 170, 204, 125, 184, 187, 206, 185, 198, 182, 210, 161, 202, + 198, 218, 173, 145, 120, 188, 183, 205, 168, 200, 170, 210, 177, 187, 190, + 209, 193, 193, 166, 210, 162, 175, 119, 174, 147, 182, 161, 181, 134, 176, + 143, 187, 165, 186, 149, 185, 141, 192, 181, 202, 123, 170, 143, 144, 78, + 149, 0, 208, 182, 170, 78, 170, 0, 117, 51, 156, 99, 195, 170, 200, + 130, 152, 68, 175, 141, 173, 134, 194, 132, 189, 164, 198, 134, 173, 117, + 171, 149, 183, 181, 185, 99, 153, 117, 125, 0, 166, 0, 173, 117, 144, + 0, 117, 102, 188, 120, 193, 166, 197, 68, 163, 119, 169, 99, 134, 0, + 162, 0, 164, 68, 171, 116, 126, 0, 120, 68, 68, 0, 105, 0, 159, + 95, 150, 51, 90, 85, 0, 0, 131, 0, 105, 0, 145, 51, 170, 51, + 120, 0, 107, 0, 145, 85, 160, 0, 85, 0, 0, 51, 149, 0, 78, + 0, 0, 0, 0, 0, 0, 0, 90, 0, 112, 0, 78, 102, 122, 0, + 0, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, + 0, 164, 120, 143, 0, 0, 0, 0, 0, 51, 0, 90, 0, 78, 0, + 0, 0, 0, 0, 110, 0, 139, 0, 112, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 0, 51, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 127, 110, 133, 0, 167, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 0, 190, + 194, 202, 0, 197, 187, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 214, 213, 223, 203, 218, 189, 200, 122, 78, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 191, 210, 231, 197, 226, 217, 238, 216, 236, 207, + 199, 0, 0, 0, 0, 0, 107, 122, 155, 160, 214, 215, 236, 202, 235, + 203, 225, 191, 203, 188, 199, 194, 212, 127, 51, 0, 174, 188, 219, 196, + 228, 221, 240, 207, 235, 220, 241, 219, 237, 207, 212, 142, 95, 0, 139, + 78, 162, 177, 197, 183, 211, 199, 235, 208, 238, 215, 227, 207, 211, 201, + 224, 213, 226, 192, 213, 170, 223, 205, 234, 221, 245, 225, 242, 220, 245, + 221, 239, 221, 238, 213, 226, 180, 159, 112, 176, 159, 208, 202, 213, 191, + 205, 191, 225, 197, 238, 219, 224, 201, 227, 200, 221, 201, 225, 203, 212, + 195, 229, 210, 228, 210, 239, 216, 226, 212, 233, 205, 225, 200, 229, 207, + 222, 151, 147, 119, 179, 185, 230, 218, 223, 192, 202, 136, 205, 177, 223, + 204, 228, 215, 232, 209, 221, 189, 221, 205, 209, 200, 226, 209, 229, 205, + 235, 192, 209, 198, 228, 190, 206, 185, 207, 187, 214, 175, 177, 184, 220, + 195, 214, 207, 230, 184, 205, 159, 208, 184, 189, 169, 224, 213, 219, 199, + 229, 203, 216, 205, 222, 204, 224, 206, 231, 208, 231, 176, 197, 184, 216, + 193, 211, 139, 212, 195, 231, 164, 166, 195, 217, 182, 208, 190, 217, 179, + 205, 68, 182, 119, 195, 168, 182, 136, 204, 179, 193, 158, 182, 140, 188, + 154, 197, 169, 190, 99, 184, 0, 125, 0, 131, 0, 99, 68, 179, 85, + 190, 184, 213, 203, 223, 202, 212, 190, 209, 138, 178, 0, 159, 51, 128, + 51, 105, 0, 139, 51, 179, 125, 185, 114, 171, 128, 175, 132, 181, 174, + 155, 0, 0, 0, 90, 0, 125, 0, 176, 188, 227, 217, 244, 215, 234, + 221, 239, 192, 224, 210, 0, 0, 134, 0, 51, 0, 105, 0, 105, 0, + 143, 90, 192, 119, 175, 147, 141, 51, 184, 110, 85, 0, 0, 0, 0, + 0, 0, 0, 151, 139, 201, 203, 232, 203, 226, 208, 236, 206, 230, 212, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 0, 119, + 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 133, + 200, 180, 220, 197, 228, 201, 221, 184, 213, 193, 110, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 78, 0, 164, 0, 0, 0, 0, 0, 107, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 164, 202, 182, 224, + 197, 211, 179, 212, 193, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 0, 150, 0, 85, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 102, 90, 193, 160, 203, 164, 200, 178, 205, 174, + 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 114, 123, 0, 114, + 0, 145, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 102, 68, 199, 170, 195, 180, 208, 176, 200, 164, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 102, 172, 110, 186, + 167, 185, 147, 189, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 177, 0, 158, 136, 197, 155, 189, 166, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 0, 155, 90, 175, 117, 175, 138, 202, 165, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 139, + 0, 120, 68, 51, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 78, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h new file mode 100644 index 00000000000..d19bf8f067d --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h @@ -0,0 +1,23 @@ +/* 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_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_YES_MICRO_FEATURES_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_YES_MICRO_FEATURES_DATA_H_ + +extern const int g_yes_micro_f2e59fea_nohash_1_width; +extern const int g_yes_micro_f2e59fea_nohash_1_height; +extern const unsigned char g_yes_micro_f2e59fea_nohash_1_data[]; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MICRO_FEATURES_YES_MICRO_FEATURES_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc index 4e54ff670eb..6f0c2581771 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc @@ -13,9 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/no_micro_features_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/tiny_conv_micro_features_model_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/yes_micro_features_data.h" #include "tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/micro_interpreter.h" @@ -32,7 +32,8 @@ TF_LITE_MICRO_TEST(TestInvoke) { // Map the model into a usable data structure. This doesn't involve any // copying or parsing, it's a very lightweight operation. - const tflite::Model* model = ::tflite::GetModel(g_tiny_conv_model_data); + const tflite::Model* model = + ::tflite::GetModel(g_tiny_conv_micro_features_model_data); if (model->version() != TFLITE_SCHEMA_VERSION) { error_reporter->Report( "Model provided is schema version %d not equal " @@ -61,12 +62,12 @@ TF_LITE_MICRO_TEST(TestInvoke) { TF_LITE_MICRO_EXPECT_EQ(4, input->dims->size); TF_LITE_MICRO_EXPECT_EQ(1, input->dims->data[0]); TF_LITE_MICRO_EXPECT_EQ(49, input->dims->data[1]); - TF_LITE_MICRO_EXPECT_EQ(43, input->dims->data[2]); + TF_LITE_MICRO_EXPECT_EQ(40, input->dims->data[2]); TF_LITE_MICRO_EXPECT_EQ(kTfLiteUInt8, input->type); // Copy a spectrogram created from a .wav audio file of someone saying "Yes", // into the memory area used for the input. - const uint8_t* yes_features_data = g_yes_f2e59fea_nohash_1_data; + const uint8_t* yes_features_data = g_yes_micro_f2e59fea_nohash_1_data; for (int i = 0; i < input->bytes; ++i) { input->data.uint8[i] = yes_features_data[i]; } @@ -102,7 +103,7 @@ TF_LITE_MICRO_TEST(TestInvoke) { TF_LITE_MICRO_EXPECT_GT(yes_score, no_score); // Now test with a different input, from a recording of "No". - const uint8_t* no_features_data = g_no_f9643d42_nohash_4_data; + const uint8_t* no_features_data = g_no_micro_f9643d42_nohash_4_data; for (int i = 0; i < input->bytes; ++i) { input->data.uint8[i] = no_features_data[i]; } diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.cc new file mode 100644 index 00000000000..85113a90dcf --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.cc @@ -0,0 +1,1477 @@ +/* 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. +==============================================================================*/ + +// See the header for documentation on the meaning of this data. + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.h" + +const int g_no_1000ms_sample_data_size = 16000; +const int16_t g_no_1000ms_sample_data[16000] = { + 5, 1, -10, -16, -14, -10, -4, -5, -10, -15, -13, + -17, -22, -21, -23, -25, -22, -26, -28, -31, -28, -25, + -20, -24, -21, -13, -7, -1, -1, 3, 3, 4, -4, + -6, -8, -10, -13, -4, -2, 5, 8, 11, 26, 28, + 34, 32, 34, 30, 21, 18, 15, 13, 8, 5, 14, + 13, 7, 8, 4, -5, -7, -4, -9, -13, -17, -21, + -16, -14, -12, -12, -14, -11, -9, -2, 5, -1, 2, + 0, 2, 1, -3, -13, -14, -16, -11, -10, -9, -13, + -17, -19, -25, -21, -21, -20, -13, -5, -3, 0, 3, + 6, 5, 1, 0, -1, -7, -10, -11, -9, -6, -7, + -11, -10, -5, -14, -20, -23, -22, -22, -19, -15, -12, + -6, -5, 3, 13, 16, 17, 25, 26, 28, 34, 34, + 33, 34, 30, 21, 22, 18, 13, 20, 22, 24, 27, + 26, 23, 21, 18, 9, 5, -2, -7, -8, -10, -8, + -8, -4, 2, 2, -1, -7, -10, -8, -12, -13, -15, + -9, -5, -4, -3, -6, -11, -11, -18, -16, -13, -10, + -12, -6, 0, -2, 0, -3, -4, -8, -12, -19, -16, + -17, -19, -23, -30, -33, -36, -38, -39, -40, -36, -37, + -32, -27, -25, -31, -38, -41, -47, -52, -50, -42, -32, + -16, -7, -3, 0, -1, -1, -5, -16, -23, -29, -34, + -33, -27, -17, -11, 1, 4, 10, 18, 21, 24, 24, + 25, 30, 34, 30, 29, 26, 23, 20, 15, 14, 13, + 14, 16, 23, 28, 21, 23, 21, 13, 12, 12, 14, + 17, 21, 26, 27, 30, 30, 26, 20, 15, 15, 9, + 8, 9, 10, 7, 8, 7, 1, -2, -6, -10, -10, + -12, -15, -10, -7, -6, -5, 0, -3, -3, -12, -25, + -35, -49, -53, -49, -51, -48, -46, -48, -39, -33, -31, + -37, -42, -47, -49, -46, -47, -47, -46, -42, -39, -33, + -26, -23, -14, -8, -9, -7, -10, -11, -13, -13, -19, + -20, -16, -11, -9, 7, 16, 21, 29, 27, 29, 28, + 21, 14, 13, 17, 19, 20, 18, 13, 17, 16, 18, + 20, 17, 13, 16, 23, 26, 26, 25, 27, 31, 30, + 31, 34, 32, 35, 32, 36, 31, 26, 23, 27, 27, + 29, 27, 26, 32, 31, 28, 26, 23, 14, 6, 0, + -4, -7, -9, -10, -8, -3, 4, 12, 11, 15, 11, + 8, 2, -3, -3, -4, -6, -11, -14, -20, -28, -32, + -38, -46, -42, -44, -40, -34, -26, -29, -25, -23, -24, + -17, -21, -26, -23, -25, -19, -10, -11, -10, -10, -12, + -9, -3, 0, -3, -7, -10, -13, -10, -14, -13, -17, + -22, -22, -30, -28, -29, -26, -18, -6, -1, -3, -4, + -6, -10, -13, -10, -14, -16, -11, -15, -9, -3, -6, + -1, 2, 3, 4, 6, 6, 3, 4, 12, 14, 17, + 21, 19, 20, 16, 17, 15, 21, 21, 22, 20, 17, + 16, 16, 20, 17, 15, 9, 5, 11, 18, 24, 28, + 26, 23, 23, 26, 22, 18, 21, 23, 26, 27, 25, + 27, 29, 26, 20, 10, 7, 11, 8, 16, 25, 33, + 37, 38, 39, 35, 30, 20, 13, 9, 6, 5, 13, + 13, 14, 15, 12, 8, 3, 3, 3, 2, 9, 11, + 10, 5, 5, 0, -7, -11, -12, -15, -17, -12, -13, + -18, -19, -21, -24, -22, -27, -34, -36, -36, -32, -20, + -16, -15, -5, -5, -9, -10, -9, -17, -19, -20, -14, + -13, -10, -4, -7, -7, -14, -19, -28, -31, -30, -31, + -23, -19, -20, -12, -11, -14, -16, -20, -18, -20, -21, + -24, -29, -30, -30, -34, -31, -25, -21, -18, -11, -4, + 2, 2, 3, 3, 2, 4, -1, -4, -8, -3, -1, + 7, 15, 18, 22, 20, 20, 16, 16, 14, 13, 21, + 25, 26, 35, 28, 28, 28, 25, 21, 19, 18, 21, + 24, 20, 25, 28, 19, 16, 15, 8, 3, -1, 3, + 5, 13, 18, 25, 31, 33, 39, 36, 36, 32, 36, + 37, 39, 42, 36, 32, 27, 30, 24, 18, 15, 10, + 7, 5, 6, -1, -4, -10, -17, -15, -19, -15, -7, + -4, 3, 0, 3, 4, -2, -7, -13, -21, -23, -28, + -27, -26, -25, -15, -10, -4, -6, -5, -9, -5, -3, + 1, 2, -1, 1, -4, -7, -8, -17, -17, -15, -14, + -9, -5, -7, -6, -9, -16, -15, -15, -16, -16, -11, + -15, -15, -6, -6, -5, -2, 0, -9, -10, -12, -13, + -10, -4, 0, 8, 5, 4, 2, 0, -5, -8, -16, + -15, -12, -3, 9, 17, 24, 26, 30, 28, 22, 17, + 14, 9, 8, 9, 8, 11, 12, 12, 15, 14, 18, + 20, 17, 19, 22, 21, 12, 5, 0, 3, -3, -4, + -6, -7, 1, 8, 8, 8, 10, 2, -3, -8, -15, + -20, -24, -22, -23, -13, -6, -7, -5, -10, -8, -15, + -19, -22, -20, -17, -18, -13, -10, -1, 6, 5, 3, + 1, -5, -11, -10, -14, -19, -15, -13, -8, -2, -3, + -4, -3, -4, -1, 1, 0, -3, -4, -8, -18, -21, + -25, -24, -16, -9, -2, 1, 5, 1, 3, -2, -7, + -10, -23, -30, -29, -23, -9, -3, 4, 11, 11, 6, + 2, 0, -12, -20, -28, -24, -22, -17, -22, -19, -14, + -21, -17, -17, -12, -8, -3, 2, 0, -6, -5, -8, + -12, -17, -27, -34, -31, -30, -27, -19, -14, -14, -14, + -14, -19, -22, -21, -19, -14, -1, 5, 9, 8, 6, + 5, -4, -2, -3, -3, -1, -2, -3, 2, 7, 8, + 7, 6, 6, 3, 2, 1, -2, 0, 6, 11, 18, + 18, 19, 17, 14, 9, 4, 3, 3, 0, -1, 3, + -1, -5, 0, -2, 0, 1, 7, 7, 8, 20, 29, + 33, 31, 24, 14, 5, -6, -11, -8, -11, -2, 6, + 10, 12, 16, 26, 26, 24, 18, 12, 10, 4, 7, + 6, -2, -12, -17, -17, -20, -23, -23, -18, -8, 1, + 3, 5, 6, 3, 0, -6, -12, -12, -15, -12, -7, + 3, 3, 8, 7, 7, 7, 1, -1, -1, 4, 11, + 17, 25, 32, 35, 42, 50, 52, 56, 50, 55, 53, + 52, 47, 40, 38, 30, 26, 27, 28, 29, 25, 23, + 23, 28, 30, 25, 26, 21, 19, 14, 9, 16, 22, + 25, 33, 39, 45, 49, 48, 55, 51, 43, 35, 20, + 14, 13, 23, 25, 24, 20, 22, 28, 22, 22, 17, + 16, 13, 10, 10, 10, 9, 9, 14, 11, 10, 10, + 4, 0, 0, -2, -3, -5, -7, -3, 1, -8, -8, + -9, -4, 4, 9, 11, 14, 11, 6, 8, 3, -6, + -10, -19, -22, -24, -27, -22, -16, -21, -25, -33, -33, + -32, -30, -21, -13, -6, -5, 2, 1, 4, 9, 7, + 5, 1, 1, 8, 6, 7, 6, 0, -6, -15, -18, + -23, -22, -23, -25, -22, -21, -19, -17, -13, -10, -10, + -16, -17, -15, -13, -8, -9, -14, -13, -17, -20, -26, + -28, -31, -29, -26, -23, -13, -10, -6, -1, 5, 7, + 2, -3, -7, -20, -18, -16, -21, -27, -33, -25, -27, + -22, -22, -21, -16, -11, -7, -2, 2, 11, 18, 11, + 9, 4, 1, -1, -6, -4, -5, -9, -12, -16, -25, + -29, -37, -37, -38, -37, -33, -23, -16, -14, -7, -1, + -4, -3, -4, -5, -11, -14, -8, -8, -8, -8, -9, + -4, -14, -21, -22, -21, -18, -15, -2, 3, -3, 0, + -2, 0, -4, -7, -1, -2, 3, 3, -3, -10, -13, + -10, -16, -19, -17, -17, -14, -7, 5, 5, 7, 8, + 12, 7, 0, -5, -13, -17, -18, -14, -7, -4, 3, + 11, 11, 12, 11, 8, 4, -5, -5, -11, -15, -17, + -23, -22, -18, -14, -14, -12, -6, -4, -1, 3, 1, + -4, -10, -22, -29, -30, -26, -15, -2, 6, 16, 21, + 28, 32, 25, 24, 20, 9, 5, 0, 3, 7, 10, + 11, 13, 17, 15, 16, 13, 11, 11, 8, 7, 1, + 1, -5, -2, -2, -1, 4, 8, 17, 22, 24, 24, + 26, 23, 20, 17, 16, 9, 4, 6, 5, 8, 2, + -1, -5, -4, -10, -14, -14, -17, -19, -18, -16, -14, + -6, -3, 1, 3, 0, -4, -6, -4, -1, -1, 2, + 5, 3, 8, 7, 7, 14, 13, 20, 24, 29, 24, + 12, 7, -1, -6, -15, -22, -20, -27, -22, -14, -6, + 2, 7, 9, 9, 2, -3, -7, -8, -10, -9, -3, + -6, -11, -12, -8, -5, -4, -5, -3, 0, 3, 6, + 6, 7, 5, -7, -10, -14, -13, -14, -17, -11, -7, + -4, 1, 1, 4, -4, -8, -18, -23, -23, -25, -19, + -16, -15, -9, 3, 10, 19, 25, 30, 31, 26, 27, + 23, 19, 16, 8, 7, 2, 0, -1, -1, 1, 5, + 6, 6, 1, 3, -1, -7, -11, -17, -19, -19, -7, + 0, 3, 11, 12, 18, 20, 16, 9, -2, -7, -14, + -19, -22, -30, -33, -34, -36, -26, -14, -11, -9, -3, + 0, -2, 1, -2, -3, -5, -12, -15, -19, -14, -9, + -8, -2, -6, -13, -15, -19, -22, -25, -26, -21, -20, + -11, -1, 1, 5, 9, 13, 15, 12, 11, 3, 1, + -1, 0, 8, 13, 16, 16, 15, 16, 15, 12, 9, + 7, 8, 4, 6, 4, 3, 3, 7, 0, -4, -8, + -11, -18, -18, -15, -20, -23, -21, -22, -21, -27, -25, + -15, -7, -2, 8, 9, 8, 8, 3, 3, 7, 8, + 8, 8, 12, 11, 12, 4, -1, -7, -11, -15, -18, + -17, -17, -20, -19, -13, -11, -3, -3, -1, 1, -3, + 1, 1, 8, 10, 15, 24, 26, 29, 34, 36, 26, + 20, 12, -2, -6, -9, -7, -6, 1, 10, 13, 19, + 22, 22, 18, 21, 24, 28, 35, 37, 34, 33, 34, + 34, 30, 19, 15, 10, 19, 21, 23, 24, 21, 19, + 18, 21, 22, 22, 27, 30, 31, 32, 33, 32, 32, + 24, 18, 10, 8, 10, 10, 6, 2, -7, -14, -22, + -29, -27, -29, -32, -30, -28, -23, -22, -11, -11, -13, + -3, 2, -1, 1, 1, -3, -7, -5, -7, -11, -17, + -23, -25, -26, -27, -26, -23, -14, -5, -3, -1, -2, + -2, -1, 1, -2, -7, -4, 2, 4, 10, 13, 6, + 3, -2, -6, -7, -11, -17, -21, -15, -7, -2, 11, + 16, 22, 25, 25, 23, 24, 23, 21, 22, 25, 23, + 17, 17, 12, 8, -2, -4, 1, 0, 4, 9, 8, + 10, 9, 9, 15, 13, 10, 8, 1, 1, -3, 1, + 4, 11, 10, 9, 5, 5, 4, 1, -1, -4, 0, + 8, 7, 4, 3, 3, 0, -9, -16, -19, -20, -21, + -18, -16, -11, -10, -9, -13, -12, -19, -25, -21, -15, + -5, 8, 14, 21, 24, 18, 20, 17, 6, 1, -2, + -2, 1, 1, 4, 1, -3, 2, 0, -3, -3, -4, + 1, 0, -5, -11, -17, -21, -20, -20, -20, -14, -9, + -3, 3, 7, 5, 3, 1, -1, -3, -4, -1, 1, + -5, -1, -1, -7, -11, -14, -12, -14, -17, -18, -23, + -29, -24, -27, -19, -12, -13, -2, -3, 4, 4, 0, + -3, -5, -2, -1, -5, -6, -7, -7, -7, -9, -13, + -9, -4, 1, 1, 1, -4, -11, -8, -15, -19, -19, + -12, -5, 1, 7, 12, 8, 10, 10, 10, 11, 11, + 19, 12, 9, 9, 2, -4, -13, -22, -24, -25, -24, + -26, -19, -14, -10, -1, 5, 4, -1, -4, -5, -10, + -14, -11, -8, -10, -8, -9, -7, -8, -6, -1, -5, + -10, -18, -27, -29, -24, -19, -11, -7, 1, 10, 8, + 8, 5, 2, -5, -1, -1, 0, 2, 2, -2, -8, + -8, -14, -26, -25, -23, -18, -9, 2, 2, 7, 13, + 6, 7, 5, 4, 3, 2, 1, 7, 2, -1, 1, + -2, 2, 0, -2, -6, -3, 5, 7, 9, 6, 5, + 4, 2, 0, -1, -3, 3, 7, 6, 14, 18, 22, + 20, 22, 19, 13, 9, 2, -8, -11, -6, -2, -3, + -3, 0, 0, 0, 1, -1, -2, 1, 7, 11, 10, + 11, 17, 17, 11, 11, 4, 6, 6, 13, 19, 22, + 23, 27, 25, 24, 22, 14, 11, 13, 7, 0, -3, + -9, -11, -7, -7, -6, -4, 1, 7, 9, 15, 18, + 18, 10, 5, 3, -3, -6, -5, -8, -5, 4, 8, + 8, 11, 10, 9, 4, 4, 1, -3, -10, -11, -8, + -16, -20, -22, -19, -12, -7, -10, -10, -13, -14, -11, + -11, -13, -18, -21, -19, -17, -22, -18, -22, -22, -16, + -9, -3, 0, 3, 6, 3, 3, -3, -6, -9, -14, + -1, 14, 21, 30, 37, 33, 27, 26, 19, 15, 14, + 11, 20, 12, 9, 10, 19, 20, 19, 22, 20, 22, + 17, 13, 14, 10, 8, 12, 15, 13, 12, 12, 12, + 9, 10, 11, 11, 9, 6, 4, 5, -2, 1, 1, + -1, 5, 1, 8, 6, 3, -1, -4, -15, -24, -27, + -26, -23, -19, -9, -3, -4, -9, -9, -10, -16, -22, + -19, -18, -15, -2, 3, 5, 6, 7, 8, 11, 3, + 1, 2, 1, 1, 0, -4, -13, -18, -19, -19, -20, + -23, -15, -10, -5, -3, -1, -1, -1, 3, -1, 0, + -8, -11, -13, -14, -13, -8, -6, -3, 1, 1, 0, + 0, 5, 4, 5, 5, 5, 4, 0, -1, -4, -13, + -22, -21, -28, -26, -22, -28, -23, -23, -14, -11, -10, + -7, -8, -5, -4, 1, 9, 10, 15, 19, 21, 17, + 18, 19, 16, 13, 16, 21, 27, 29, 22, 22, 13, + 4, 1, 0, -5, -6, -2, 3, 5, 8, 6, 9, + 10, 2, -3, -9, -8, -4, -2, -7, -6, -4, -8, + -6, -8, -11, -8, -8, -6, 2, -2, -2, -1, 2, + 4, 8, 5, -1, -8, -10, -7, -6, -5, -6, -5, + 6, 13, 22, 28, 33, 31, 38, 35, 28, 27, 22, + 22, 23, 26, 23, 21, 28, 28, 23, 23, 22, 21, + 20, 14, 6, -1, -5, -8, -5, -1, 2, 5, 5, + 7, 8, 5, 4, 0, 3, 6, 10, 13, 13, 6, + 4, 4, 0, -2, -3, 0, 3, 5, 7, 9, 7, + 6, 10, 8, 3, 4, -1, -4, -2, 0, -2, -2, + -2, -3, 5, 8, 6, 4, -1, -7, -6, -7, -12, + -18, -11, -2, -1, -1, -1, -2, -7, -7, -3, -3, + -5, -6, -6, -6, -6, -6, -9, -12, -9, -5, 1, + 3, 5, 5, 8, 7, 3, -5, -3, -2, 2, 3, + 5, 5, -1, -2, -4, -8, -9, -9, -7, -12, -13, + -17, -19, -16, -19, -21, -21, -19, -11, -6, -3, 7, + 8, 6, 2, 0, 1, 1, -2, -5, 0, -2, 2, + 1, 2, 0, -2, -1, -10, -21, -25, -24, -21, -19, + -14, -8, -3, -5, 0, 0, -5, -6, -3, -6, -9, + -13, -19, -20, -21, -21, -24, -25, -27, -27, -29, -26, + -19, -14, -14, -13, -8, -5, -10, -10, -6, 1, 4, + 14, 22, 23, 24, 20, 20, 18, 14, 11, 9, 6, + 8, 12, 15, 18, 18, 12, 8, 9, 9, 9, 7, + 4, 9, 5, 6, 5, 3, 3, -1, -1, -6, -10, + -6, -8, -3, 0, -2, -3, -2, -6, -6, -7, -3, + -3, -3, -2, 1, -1, -10, -7, -13, -21, -23, -20, + -19, -18, -18, -19, -15, -16, -7, -6, -9, -13, -12, + -6, -1, 3, 6, 7, 5, 3, -3, -11, -18, -20, + -26, -29, -27, -27, -24, -30, -29, -28, -23, -18, -21, + -18, -15, -9, 1, 9, 17, 21, 23, 18, 14, 5, + -1, -2, -1, 0, 3, 6, 5, 4, 4, 0, -1, + 1, -4, -9, -13, -11, -20, -21, -19, -14, -9, -4, + 1, 6, 10, 16, 24, 30, 35, 31, 38, 37, 35, + 39, 36, 36, 32, 30, 33, 31, 24, 19, 12, 4, + -1, -7, -11, -7, -5, -3, 2, 6, 10, 16, 19, + 21, 21, 16, 10, 14, 12, 14, 13, 12, 12, 5, + 6, 2, 0, 1, 3, 4, 6, 9, 6, 2, -1, + -3, -10, -15, -13, -17, -19, -15, -16, -15, -13, -8, + -8, -7, -10, -5, -2, 1, 5, 5, 11, 10, 12, + 10, 9, 9, 15, 23, 33, 35, 33, 34, 34, 35, + 34, 24, 30, 26, 23, 21, 20, 15, 10, 3, 4, + 0, -7, -8, -9, -9, -8, -4, 0, 5, 5, 2, + 3, -2, 0, 0, -1, 0, -1, 1, 2, 6, 3, + 1, -9, -5, -6, -2, -8, -12, -9, -10, -7, -8, + -8, -6, -2, -2, -1, 0, -2, -1, -8, -18, -19, + -27, -37, -42, -40, -39, -33, -30, -23, -16, -16, -9, + -13, -11, -10, -10, -8, -3, -1, 2, 0, -1, 2, + 6, 4, 8, 10, 17, 21, 28, 31, 33, 28, 20, + 12, 8, -3, -5, -4, -3, 2, 6, 9, 8, 2, + 7, 4, -6, -9, -15, -13, -15, -17, -14, -11, -12, + -5, -6, -4, -6, -11, -11, -7, -4, -6, -8, -13, + -10, -7, -12, -11, -12, -13, -12, -9, -9, -10, -10, + -6, -8, -8, -7, -9, -9, -7, 2, 5, 5, 6, + 3, 4, 6, 3, -1, -2, -2, -2, 1, 5, 3, + 4, 2, -2, -7, -9, -13, -11, -8, 2, 12, 23, + 31, 37, 41, 40, 37, 36, 31, 31, 27, 28, 24, + 13, 16, 14, 15, 9, 4, 4, 5, 4, 7, 12, + 16, 14, 11, 13, 6, -2, -4, -1, -3, 3, 6, + 6, 9, 7, 9, 7, 5, 0, 1, -1, -2, -4, + -1, 0, 0, -4, 0, -4, -9, -15, -16, -18, -15, + -10, -6, -8, -5, -2, -2, 0, 4, 7, 0, -2, + -3, 4, 3, 2, -1, -3, -8, -19, -19, -19, -16, + -8, -5, 0, 1, 2, 1, -1, -2, -10, -12, -10, + -4, 3, 4, 2, 7, 8, 4, 1, -5, -5, -4, + -1, 9, 10, 12, 15, 15, 14, 11, 20, 16, 19, + 18, 26, 29, 21, 23, 16, 16, 3, -3, -4, -10, + -12, -10, -6, -7, -12, -17, -14, -16, -19, -13, -10, + -13, -13, -2, 2, 3, 7, 13, 22, 21, 21, 21, + 24, 27, 23, 22, 20, 17, 17, 16, 13, 11, 5, + 1, 1, 5, 5, 3, 2, -1, 2, -5, -6, -3, + -11, -9, -6, -5, -10, -4, -1, 1, 2, -1, -4, + -4, -9, -9, -7, -3, 3, -2, 1, 1, 4, -4, + -8, -8, -17, -17, -13, -13, -18, -18, -25, -27, -21, + -22, -18, -7, -1, 5, 9, 11, 11, 11, 15, 11, + 4, 1, 6, 8, 17, 12, 10, 5, -2, -3, -14, + -17, -25, -26, -22, -20, -13, -12, -12, -13, -10, -4, + -6, -6, -4, -6, -4, 0, -3, -7, -7, -10, -17, + -14, -9, -3, 4, 4, 6, 1, 0, 0, -6, -3, + -4, -3, -6, -9, -9, -5, 0, 1, 2, -2, 3, + -1, -4, -5, -11, -14, -17, -14, -12, -14, -19, -21, + -25, -35, -40, -39, -31, -24, -13, -4, -1, 0, 0, + 2, -2, -5, -8, -8, -9, -6, -2, 0, -5, -6, + 2, 5, 4, 1, 6, 8, 9, 14, 13, 19, 15, + 19, 13, 14, 20, 16, 16, 14, 14, 17, 13, 12, + 11, 6, -1, -7, -9, -10, -11, -2, 8, 12, 12, + 12, 8, 4, 1, -3, -4, -4, -3, 1, 9, 14, + 16, 10, 12, 9, 6, 4, -1, 8, 6, 3, 6, + 1, -11, -10, -10, -13, -9, -6, -2, -2, 9, 13, + 17, 17, 19, 17, 16, 9, -2, -5, -5, -3, -9, + -8, -8, -12, -17, -16, -18, -15, -9, -7, 1, 10, + 17, 18, 23, 25, 23, 20, 15, 17, 18, 23, 33, + 40, 43, 45, 51, 53, 47, 36, 27, 10, 5, 1, + 4, 5, 4, 0, 0, 6, 7, 8, 9, 3, 2, + 1, 0, -1, 3, 5, 5, 13, 7, 4, 4, 3, + 11, 17, 21, 31, 31, 31, 31, 28, 26, 23, 19, + 16, 17, 16, 10, 10, 12, 9, 7, -1, -7, -12, + -15, -15, -15, -13, -13, -16, -19, -19, -23, -31, -34, + -38, -39, -31, -30, -21, -21, -18, -11, -16, -20, -25, + -22, -18, -14, -7, -8, -3, 2, 10, 13, 12, 10, + 6, 2, 0, 0, 0, -6, -4, -1, 0, 0, -1, + -2, 1, 3, 8, 9, 3, 6, 2, -4, -2, -3, + -7, -4, -3, 2, 6, 8, 10, 12, 15, 11, 15, + 12, 13, 14, 15, 18, 14, 8, 4, 4, 3, -4, + -5, -4, -2, -3, -2, 4, 9, 13, 18, 21, 20, + 18, 15, 11, 6, 7, 10, 8, 6, 3, -3, -7, + -14, -21, -29, -33, -32, -26, -17, -12, -11, -9, -3, + -10, -13, -18, -23, -21, -26, -26, -24, -28, -25, -29, + -30, -30, -27, -17, -7, 2, 10, 13, 16, 16, 17, + 18, 17, 19, 19, 20, 15, 14, 16, 14, 10, 5, + 0, -4, -18, -21, -25, -20, -16, -13, -8, -5, 2, + 6, 11, 12, 18, 16, 18, 15, 13, 17, 18, 22, + 21, 25, 26, 25, 26, 28, 31, 27, 20, 10, 3, + -6, -10, -16, -19, -18, -15, -13, -10, -2, 0, 2, + 4, 3, 5, -1, 0, 1, 2, 0, -2, -1, -6, + -5, -7, -12, -10, -9, -4, -1, 3, 4, 2, 4, + 4, 3, -3, -6, -11, -14, -15, -23, -25, -29, -30, + -28, -25, -22, -19, -21, -19, -11, -7, -7, -3, -3, + -6, -8, -13, -10, -10, -5, 1, 4, 9, 7, 6, + 6, 4, -5, -11, -8, -6, -3, 0, 3, 7, 11, + 7, 3, 5, 6, 10, 12, 14, 16, 8, 5, -1, + -1, 4, 0, 0, -3, -5, -5, -4, -2, -2, 1, + 4, 7, 5, 10, 9, 6, 9, 12, 19, 28, 32, + 32, 33, 31, 29, 20, 17, 16, 14, 15, 6, -2, + -5, -7, -10, -10, -11, -9, -6, -3, 8, 10, 10, + 10, 12, 12, 7, 7, 5, 3, 2, 2, -2, -5, + -4, -7, -2, -6, -5, -6, -11, -14, -13, -10, -11, + -15, -16, -11, -11, -11, -10, -16, -15, -15, -16, -10, + -11, -11, -5, -1, 2, 1, 2, 0, 1, 4, 8, + 5, -4, -2, -4, -12, -18, -24, -20, -25, -14, -3, + 4, 11, 13, 13, 7, 4, -4, -9, -13, -17, -10, + -6, -1, 0, 2, 2, -1, 1, -8, -18, -22, -19, + -19, -22, -20, -22, -20, -17, -12, -9, -4, 3, 9, + 9, 9, 7, 6, 13, 10, 11, 8, 4, -1, 5, + 7, 7, 8, 4, 2, 2, -2, -8, -11, -16, -18, + -12, -12, -9, -2, 3, 3, 5, 5, 6, 9, 11, + 20, 22, 26, 30, 28, 22, 15, 15, 10, 11, 9, + 6, 9, 9, 11, 10, 12, 10, 8, 8, 7, 9, + 4, 3, 9, 5, 1, 2, 0, -3, -3, 0, 3, + 0, -2, 1, 4, 6, 4, 0, 1, -4, -13, -13, + -11, -20, -21, -15, -17, -23, -22, -24, -29, -24, -29, + -32, -21, -13, -11, -9, -9, -8, -13, -11, -11, -11, + -11, -17, -17, -21, -23, -27, -32, -33, -32, -31, -35, + -31, -26, -24, -18, -10, -1, 5, 13, 17, 15, 13, + 8, 4, 6, 9, 10, 13, 11, 12, 13, 9, 5, + 6, 8, 12, 21, 25, 24, 23, 16, 8, 7, 0, + -3, -8, -9, -2, 1, 11, 18, 25, 30, 31, 27, + 21, 19, 19, 18, 18, 22, 24, 16, 14, 8, 2, + -4, -9, -7, -10, -6, -8, -8, -13, -14, -11, -13, + -8, -7, 6, 9, 10, 15, 17, 11, 11, 9, 2, + 2, -2, 2, -6, -6, -7, -14, -11, -12, -13, -17, + -22, -25, -30, -24, -16, -4, 5, 2, 7, 5, 2, + -1, 1, -4, -4, 4, 8, 8, 5, 6, 6, 2, + 1, -2, -9, -14, -17, -16, -15, -14, -12, -11, -6, + -6, -2, -3, -3, 6, 13, 18, 27, 27, 26, 24, + 22, 19, 18, 19, 12, 8, 7, -2, 0, -6, -8, + -6, -4, -6, -14, -16, -16, -15, -12, -2, 6, 12, + 16, 18, 14, 16, 13, 12, 17, 16, 17, 17, 12, + 13, 10, 14, 14, 10, 2, -1, -3, -5, -10, -15, + -13, -20, -21, -21, -21, -19, -20, -18, -8, -4, -1, + -1, 4, 2, -3, 0, -5, -5, -3, -1, 0, 6, + 5, 6, 7, 7, 3, 2, 1, -5, -3, 0, 3, + 5, 7, 4, 10, 15, 15, 11, 6, 8, 9, 14, + 19, 18, 14, 12, 16, 15, 11, 9, 9, 5, 4, + 0, -7, -12, -18, -22, -29, -32, -36, -37, -38, -39, + -32, -24, -20, -14, -10, -2, 0, 1, 9, 13, 21, + 26, 31, 35, 40, 38, 32, 33, 25, 14, 11, 7, + 1, -1, -6, -5, -11, -20, -22, -19, -16, -9, 2, + 9, 14, 14, 13, 13, 12, 10, 3, 2, 1, 0, + 6, 5, -1, -4, -13, -17, -21, -25, -29, -30, -23, + -14, -4, 4, 11, 11, 12, 13, 13, 5, 6, 6, + 7, 5, 5, 9, -2, 3, 0, -2, -3, -5, -1, + 3, 9, 16, 18, 17, 17, 11, 5, 1, -4, -13, + -12, -7, -7, 1, 6, 4, 2, 3, 1, 1, 0, + -1, -5, -5, -3, -5, -1, 8, 9, 7, 12, 7, + 6, 4, 3, -1, -1, -4, -14, -16, -18, -24, -34, + -44, -37, -37, -36, -28, -19, -15, -6, -2, -3, 2, + 5, 6, 3, 6, 6, 9, 7, 3, -4, -15, -25, + -34, -37, -41, -41, -38, -33, -27, -22, -14, -15, -18, + -18, -15, -8, -7, -2, 2, 0, 4, 12, 13, 10, + 17, 20, 16, 17, 23, 24, 22, 24, 22, 28, 26, + 24, 22, 26, 28, 27, 23, 17, 10, 4, 4, 1, + -1, 0, 4, 9, 15, 14, 15, 14, 14, 13, 8, + 0, -1, -11, -13, -4, -3, -5, -3, -1, -6, -5, + -7, -4, -2, 2, 7, 15, 20, 14, 13, 8, 2, + -6, -15, -23, -25, -20, -22, -20, -14, -10, -4, -2, + 1, -10, -15, -12, -8, -8, -7, -5, -10, -12, -20, + -28, -26, -24, -16, -8, -5, 3, 8, 9, 12, 12, + 12, 14, 13, 12, 10, 13, 23, 29, 28, 33, 36, + 32, 28, 23, 25, 26, 30, 34, 27, 22, 16, 12, + 3, -6, -13, -13, -15, -14, -9, -11, -13, -13, -16, + -15, -20, -22, -20, -32, -30, -29, -24, -18, -18, -18, + -13, -15, -15, -16, -17, -10, -11, -12, -15, -17, -17, + -19, -21, -22, -26, -28, -21, -18, -14, -5, 2, 6, + 7, 5, 3, -2, 0, -4, -2, -3, -6, -9, -12, + -11, -11, -19, -23, -20, -21, -16, -19, -23, -22, -24, + -21, -22, -17, -15, -8, -1, 4, 14, 18, 23, 24, + 25, 25, 18, 15, 7, 2, 14, 19, 22, 20, 23, + 22, 20, 19, 20, 17, 16, 21, 22, 21, 18, 9, + 3, -6, -14, -19, -30, -36, -40, -32, -22, -21, -16, + -7, -1, 3, 2, 3, 6, 9, 16, 20, 22, 26, + 27, 29, 32, 30, 23, 19, 20, 21, 18, 22, 24, + 15, 14, 9, 9, 7, 6, 9, 9, 16, 22, 20, + 18, 18, 9, -1, -10, -16, -19, -22, -22, -20, -16, + -11, -5, 0, 1, 4, 2, 0, 3, 5, 10, 8, + 12, 10, 11, 9, 8, 7, -3, -4, -10, -11, -5, + 2, 8, 12, 12, 13, 14, 15, 14, 12, 10, 14, + 13, 8, 0, -2, -3, -9, -6, -13, -21, -12, -12, + -8, -9, -14, -16, -19, -23, -22, -23, -30, -26, -17, + -14, -9, -2, 3, 11, 16, 17, 17, 11, 12, 13, + 12, 9, 8, 7, 10, 17, 14, 13, 9, 7, 6, + 5, 10, 10, 6, 10, 9, 1, -5, -10, -12, -17, + -16, -14, -13, -10, -6, -2, 0, -1, 2, 2, -1, + 2, 6, 12, 18, 23, 22, 23, 24, 20, 16, 10, + 6, 9, 16, 15, 15, 16, 14, 8, 4, 0, -3, + -7, -4, -5, -5, 0, -4, 1, 1, 1, -4, -10, + -17, -25, -25, -28, -28, -27, -25, -20, -20, -20, -22, + -14, -11, -4, 4, 6, 11, 10, 12, 9, 6, 2, + -6, -10, -12, -7, -1, -6, 0, 1, 2, 5, 1, + -1, 1, -3, -6, -4, -5, -4, -6, -5, -7, -10, + -10, -8, -11, -9, -2, 9, 15, 14, 20, 19, 19, + 16, 16, 11, 3, 2, 2, 5, 4, 5, 3, -1, + -1, -6, -11, -16, -18, -18, -12, -17, -18, -13, -15, + -5, -4, -3, -1, 2, 6, 7, 11, 14, 17, 17, + 18, 21, 18, 19, 18, 23, 27, 36, 32, 35, 30, + 24, 25, 18, 10, 3, -1, -4, -11, -16, -21, -33, + -37, -35, -36, -35, -30, -26, -26, -21, -10, -7, -3, + -4, -3, -3, -9, -12, -16, -25, -22, -11, -6, 2, + 5, 7, 4, -2, -8, -16, -23, -30, -28, -23, -20, + -11, -11, -8, 5, 2, -3, -1, -11, -15, -10, -13, + -8, -8, -12, -9, -10, -15, -8, -4, -3, 7, 6, + 13, 20, 25, 24, 25, 27, 28, 25, 23, 22, 27, + 28, 27, 30, 28, 26, 20, 16, 13, 7, 2, 1, + 6, 3, -4, -6, -13, -18, -19, -21, -15, -3, -1, + 10, 16, 17, 20, 24, 28, 28, 26, 26, 28, 27, + 24, 23, 20, 20, 24, 20, 17, 14, 6, 0, 2, + 1, 0, -3, -7, -12, -18, -29, -28, -30, -32, -23, + -27, -25, -20, -17, -13, -11, -14, -17, -21, -22, -18, + -11, -12, -6, -8, -9, -5, -6, -10, -18, -19, -16, + -13, -9, -6, -7, -13, -10, -14, -22, -30, -37, -35, + -37, -35, -34, -36, -30, -23, -17, -16, -16, -11, -6, + -2, 3, 7, 7, 6, 7, 7, 13, 21, 20, 22, + 23, 22, 24, 17, 5, -1, -2, -8, -13, -14, -17, + -24, -28, -23, -22, -19, -12, -14, -10, -14, -21, -20, + -21, -22, -13, -6, -1, 6, 4, 10, 11, 8, 10, + 10, 17, 20, 27, 34, 32, 26, 26, 24, 17, 13, + 6, 9, 12, 15, 17, 12, 11, 9, 3, -3, -3, + -8, -9, -4, -2, -2, 2, 1, -1, -3, -7, -8, + -11, -15, -8, -5, 1, 9, 7, 10, 13, 17, 14, + 12, 8, 6, 3, 6, 9, 8, 5, 0, -2, 1, + 1, -3, -6, -12, -17, -17, -23, -28, -33, -31, -29, + -30, -35, -28, -25, -17, -5, 0, 6, 10, 14, 27, + 31, 26, 31, 30, 32, 41, 42, 42, 43, 34, 32, + 21, 12, 2, 1, -3, -1, 8, 13, 20, 19, 18, + 19, 13, 8, 5, 7, 6, 7, 6, 4, 3, -2, + 0, 2, -4, -1, -3, 2, 12, 22, 33, 32, 31, + 35, 35, 34, 32, 26, 27, 26, 21, 17, 10, 1, + -3, -14, -21, -19, -21, -19, -24, -24, -19, -16, -13, + -16, -13, -15, -17, -12, -9, -4, 7, 19, 27, 33, + 37, 34, 35, 30, 24, 23, 25, 21, 20, 18, 15, + 12, 13, 8, 2, -4, -12, -18, -17, -14, -10, -14, + -8, -14, -14, -12, -14, -19, -23, -31, -32, -28, -30, + -22, -20, -13, 1, 0, 6, 14, 15, 20, 22, 20, + 16, 9, 2, 1, 3, 6, 7, 9, 10, 14, 17, + 16, 14, 4, -7, -16, -31, -40, -41, -40, -38, -34, + -40, -37, -33, -28, -22, -17, -11, -10, -12, -5, -5, + -8, -4, 0, -1, 1, 1, 6, 11, 14, 22, 25, + 28, 31, 32, 32, 31, 31, 20, 13, 12, 5, 4, + 4, 2, 0, -3, -6, -8, -4, -4, -4, -1, 7, + 9, 10, 13, 13, 16, 10, 7, 3, 6, 8, 8, + 15, 20, 23, 18, 15, 12, 4, 1, 0, -4, -4, + -1, 8, 11, 13, 21, 24, 19, 12, 2, -5, -11, + -15, -17, -17, -19, -23, -28, -34, -33, -37, -29, -27, + -24, -17, -13, -8, -6, -2, 5, 3, 4, -2, -5, + -4, 0, 2, 3, 1, -5, -5, -6, -11, -11, -15, + -15, -19, -17, -17, -21, -23, -21, -22, -24, -28, -27, + -25, -15, -8, -1, 2, 2, 3, 3, 2, -2, 0, + 1, -1, 2, 5, 7, 2, 0, 2, -6, -9, -8, + -6, -3, -3, 3, 0, 5, 0, 0, -5, -12, -13, + -20, -14, -14, -6, -5, -2, 0, 6, 11, 9, 9, + 11, 10, 13, 19, 26, 29, 36, 37, 40, 35, 27, + 20, 13, 6, 3, -1, -1, -1, -3, -6, -8, -14, + -16, -25, -28, -23, -21, -24, -22, -22, -22, -24, -28, + -35, -43, -42, -37, -29, -20, -5, 2, 10, 23, 28, + 30, 31, 30, 39, 43, 40, 41, 43, 43, 38, 29, + 18, 14, 12, 3, 6, 3, 3, 0, -1, -3, -5, + -5, -8, -8, -10, -6, -1, 1, 5, 1, 2, 6, + 0, -3, -7, -13, -10, -7, -8, -7, -3, -5, -4, + -4, -4, -5, -2, 2, 3, 6, 4, 3, -1, -2, + -5, -16, -22, -31, -39, -38, -42, -47, -42, -42, -35, + -27, -30, -28, -25, -26, -24, -20, -19, -19, -19, -19, + -14, -16, -13, -9, -10, -1, 8, 17, 21, 28, 26, + 28, 24, 14, 8, 2, 0, -4, -4, -13, -16, -16, + -13, -12, -7, -5, 0, -4, -1, 2, 4, 8, 8, + 10, 10, 10, 14, 16, 17, 23, 20, 27, 27, 27, + 21, 14, 11, 0, -4, -8, -8, -1, -1, 1, 6, + 8, 23, 22, 23, 23, 25, 26, 26, 22, 21, 20, + 22, 17, 12, 8, 3, -2, -2, -4, -5, -3, 1, + 7, 6, 8, 9, 12, 6, 1, -4, -8, -6, -3, + -4, -5, -3, -7, -6, -6, -11, -11, -19, -23, -26, + -28, -34, -41, -41, -44, -45, -47, -40, -39, -33, -29, + -21, -14, -16, -6, -7, -3, 1, 6, 8, 11, 14, + 14, 15, 15, 18, 18, 16, 17, 12, 15, 20, 21, + 19, 21, 23, 22, 21, 16, 12, 8, 7, 7, 10, + 13, 13, 16, 16, 16, 16, 15, 15, 12, 14, 14, + 15, 12, 11, 17, 19, 19, 14, 13, 15, 17, 18, + 20, 24, 27, 24, 19, 11, 10, 1, 0, 0, -1, + 3, 8, 16, 18, 17, 22, 22, 21, 19, 7, 0, + 1, -1, -2, -1, -6, -8, -12, -14, -20, -21, -24, + -19, -9, -4, -3, 2, 2, 3, 0, -10, -19, -23, + -29, -31, -35, -29, -33, -28, -25, -25, -19, -22, -23, + -24, -21, -17, -15, -17, -13, -15, -12, -15, -14, -14, + -12, -9, -5, 1, 9, 13, 13, 17, 17, 15, 11, + 12, 8, 13, 20, 24, 30, 29, 33, 30, 26, 23, + 13, 9, 4, 3, 3, 5, 3, 2, 5, 3, 2, + 1, 3, 6, 10, 14, 19, 23, 21, 20, 21, 17, + 11, 5, -3, -7, -12, -15, -16, -13, -15, -13, -7, + -4, -5, -5, -1, 5, 11, 8, 7, -2, -2, -5, + -6, -1, -2, 0, 2, 8, 13, 15, 17, 15, 16, + 10, 13, 3, -1, -4, -4, -4, 0, 8, 13, 15, + 9, 11, 9, 12, 9, 10, 10, 5, 11, 16, 21, + 20, 15, 13, 5, 3, -3, 1, 1, 0, -4, -7, + -9, -7, -9, -10, -7, -6, -3, -2, -3, -3, -6, + -12, -16, -22, -21, -26, -28, -25, -24, -23, -23, -28, + -32, -29, -26, -26, -23, -29, -23, -16, -11, -7, -9, + -10, -12, -18, -20, -20, -26, -23, -16, -17, -10, -7, + 0, 3, -2, 0, -4, -7, -8, -6, -3, -7, -5, + -5, 1, 0, -3, -2, -3, 5, 7, 10, 19, 17, + 22, 21, 20, 16, 8, 9, 10, 12, 20, 28, 31, + 28, 28, 26, 21, 14, 8, 5, 4, 5, 8, 9, + 9, 13, 17, 16, 14, 20, 17, 13, 16, 17, 18, + 18, 15, 11, 5, -2, -8, -15, -17, -17, -24, -24, + -23, -18, -13, -13, -9, -7, -4, 0, 3, 6, 2, + 2, -4, -5, -5, -4, -4, -2, 2, 6, 10, 7, + 4, 2, -2, -3, -8, -10, -14, -27, -29, -37, -36, + -29, -27, -19, -7, -3, 0, -2, 2, 8, 13, 18, + 15, 10, 10, 6, 1, -5, -12, -17, -20, -23, -23, + -22, -19, -17, -10, -6, -3, 2, 0, 4, 11, 14, + 19, 16, 6, 7, 3, 3, 4, 1, 7, 8, 7, + 3, -2, 0, 0, 0, -1, -2, 0, 4, 3, 5, + 9, 9, 12, 7, 5, 0, 0, 1, 0, 2, -6, + -10, -9, -13, -15, -19, -15, -18, -16, -17, -9, -5, + -2, 2, 2, 3, 7, 2, -3, -8, -13, -8, 1, + 8, 12, 15, 17, 17, 11, 7, 0, -4, -8, -8, + -3, -1, -4, -6, -6, -13, -12, -12, -13, -12, -8, + -9, -5, -4, -2, 0, -1, -6, -7, -6, -10, -10, + -8, -6, 1, 5, 6, 15, 18, 16, 12, 12, 12, + 10, 13, 7, 0, -9, -10, -11, -6, -8, -8, -4, + 0, 6, 10, 11, 15, 15, 15, 12, 10, 6, 6, + 11, 12, 20, 25, 23, 25, 18, 12, 6, -1, -4, + -10, -12, -9, -13, -16, -15, -18, -18, -22, -22, -17, + -14, -12, -8, -3, 1, 4, 11, 13, 7, 0, -8, + -11, -11, -13, -14, -12, -11, -9, -6, -5, -2, 1, + 5, 6, 10, 18, 17, 15, 13, 11, 12, 13, 10, + 9, 13, 16, 16, 13, 11, 6, 5, 0, -5, -4, + -3, 2, 6, 5, 6, 11, 14, 20, 23, 28, 27, + 22, 24, 23, 22, 16, 17, 12, 7, -1, -9, -10, + -9, -9, -13, -11, -9, -2, -2, -7, -8, -6, -7, + -12, -12, -10, 0, 5, 11, 13, 11, 10, 7, 3, + 0, 0, 3, 10, 14, 16, 18, 19, 21, 14, 15, + 12, 7, 6, 7, 9, 7, 11, 6, 4, 4, -1, + -9, -12, -12, -14, -9, -9, -6, -5, -4, -6, -7, + -12, -15, -17, -27, -23, -20, -19, -19, -18, -24, -20, + -25, -28, -33, -31, -29, -27, -15, -12, -7, -3, 1, + -3, -3, -5, -8, -6, 0, 13, 17, 24, 25, 23, + 24, 18, 8, -3, -4, -4, -7, -3, 1, 4, 7, + 9, 10, 14, 14, 20, 28, 35, 38, 42, 43, 43, + 39, 30, 27, 19, 15, 8, 10, 12, 19, 25, 26, + 27, 23, 22, 15, 10, 6, 8, 4, 6, 6, 3, + 7, 7, 15, 11, 7, 6, 5, 9, 6, 0, -3, + -14, -21, -21, -30, -39, -42, -40, -37, -37, -36, -32, + -30, -24, -21, -22, -23, -24, -28, -31, -31, -29, -27, + -30, -31, -31, -31, -34, -33, -34, -26, -21, -15, -10, + -5, -3, -2, -3, -6, -5, -11, -14, -10, -5, 0, + 9, 10, 18, 21, 19, 21, 11, 7, 4, 6, 6, + 7, 3, -6, -9, -16, -23, -24, -23, -26, -18, -16, + -11, -8, 0, 6, 5, 6, 10, 8, 8, 16, 24, + 24, 23, 24, 24, 24, 18, 9, 4, -3, -11, -16, + -15, -18, -14, -12, -9, -3, -4, -1, 8, 11, 10, + 19, 21, 21, 23, 20, 22, 15, 9, 7, 5, 3, + 1, 12, 13, 10, 18, 23, 31, 37, 40, 36, 38, + 40, 40, 38, 27, 24, 21, 14, 12, 12, 7, 7, + 15, 18, 19, 18, 17, 18, 14, 12, 11, 7, 5, + 7, 9, 9, 15, 14, 15, 18, 16, 7, 0, -5, + -6, -6, -6, -1, 7, 9, 12, 6, 4, 4, 2, + -1, 2, 3, 3, 5, 4, -1, -13, -19, -29, -34, + -39, -43, -49, -54, -53, -55, -55, -56, -59, -58, -49, + -41, -32, -19, -10, -2, -4, -1, -6, -19, -27, -26, + -27, -27, -21, -22, -20, -26, -26, -20, -20, -20, -21, + -17, -18, -7, -6, -6, -5, -1, 7, 18, 10, 16, + 25, 24, 31, 30, 32, 30, 26, 24, 22, 23, 21, + 23, 21, 24, 19, 17, 13, 12, 15, 6, 2, -5, + -9, -13, -10, -5, 1, 10, 13, 17, 13, 8, 5, + 5, 6, 5, 13, 19, 16, 14, 12, 7, 15, 18, + 19, 16, 4, -1, 0, -1, -2, -9, -15, -19, -21, + -13, -13, -10, -7, -7, -7, -6, -11, -22, -18, -19, + -22, -22, -19, -18, -10, -7, -9, -7, -12, -16, -20, + -27, -35, -37, -37, -33, -24, -14, -4, 8, 14, 19, + 19, 16, 12, 6, 2, -5, -6, -11, -17, -16, -14, + -13, -12, -17, -21, -22, -24, -18, -14, -12, -1, 4, + 9, 17, 14, 9, 13, 14, 13, 14, 14, 12, 11, + 15, 11, 16, 21, 20, 20, 22, 31, 30, 26, 15, + 13, 6, 8, 5, 1, -5, -3, 2, 9, 14, 13, + 16, 17, 18, 13, 10, 8, 7, 9, 12, 21, 23, + 23, 21, 19, 16, 14, 5, -4, -12, -15, -16, -12, + -9, -12, -14, -17, -16, -15, -14, -15, -28, -27, -24, + -12, -8, -3, 3, 9, 15, 18, 25, 25, 31, 32, + 35, 36, 33, 36, 24, 13, 2, -11, -19, -18, -18, + -10, -6, -4, 0, -3, -3, -15, -18, -17, -9, -7, + 2, 5, 7, 6, 2, -2, -12, -16, -16, -9, -3, + 6, 8, 15, 17, 16, 18, 11, 5, -4, -8, -17, + -16, -22, -24, -25, -28, -23, -19, -11, -3, 5, 11, + 22, 26, 29, 24, 14, 12, 7, 6, -2, -1, 2, + 10, 23, 33, 36, 32, 31, 16, 3, -4, -3, -3, + 1, 8, 11, 13, 12, 8, 3, 5, 3, 1, -1, + 4, 2, 3, 8, 5, 5, 1, -2, -1, -3, -1, + 5, 8, 10, 17, 17, 15, 19, 27, 18, 21, 23, + 19, 20, 15, 1, -7, -18, -24, -24, -33, -28, -32, + -30, -30, -30, -30, -29, -30, -41, -43, -50, -51, -49, + -42, -32, -19, -10, 0, 4, -2, 5, 9, 8, 12, + 19, 17, 10, 9, 3, 1, -4, -8, -4, 0, 5, + 7, 10, 9, 12, 0, -6, -7, -13, -16, -10, -10, + -9, -1, -1, -2, -6, -11, -14, -17, -18, -10, -3, + -3, 0, 6, 1, 6, 4, 3, 3, 9, 16, 22, + 28, 27, 32, 18, 21, 25, 20, 21, 18, 18, 22, + 23, 15, 8, -3, -9, -10, -13, -8, 3, 7, 18, + 26, 23, 26, 30, 17, 11, 9, -1, 0, 2, 2, + 12, 15, 6, 1, 0, -5, 2, 1, -3, -1, -6, + -2, -4, -11, -18, -30, -38, -36, -33, -32, -27, -19, + -18, -14, -13, -16, -11, -12, -12, -4, 0, 7, 13, + 13, 10, 11, 6, 3, 3, 3, 4, 10, 4, -1, + -3, -11, -21, -27, -34, -33, -31, -33, -28, -22, -21, + -14, -8, -13, -10, -8, -12, -7, -11, -3, 3, 5, + 7, 7, -1, -12, -13, -17, -21, -8, -2, 4, 7, + 13, 18, 18, 16, 15, 13, 11, 15, 13, 12, 17, + 18, 15, 15, 11, -3, -1, 2, 11, 15, 10, 18, + 13, 10, 12, 9, 2, 2, 4, -1, 6, 9, 11, + 5, 7, 13, 8, 9, 10, 11, 9, 7, 11, 5, + 3, 1, -9, -19, -31, -40, -42, -33, -27, -24, -22, + -20, -25, -20, -12, -17, -23, -23, -25, -25, -20, -18, + -17, -19, -15, -22, -20, -19, -13, -8, -12, 0, 2, + -6, -1, -5, -15, -10, -12, -19, -8, -6, -3, 9, + 5, 12, 22, 10, 9, 12, 5, 8, 28, 13, 20, + 25, 11, 16, 19, 10, 15, 14, 6, 23, 19, 18, + 32, 17, 12, 19, -1, -8, 11, -4, -8, 9, -4, + -6, 0, -10, -7, -3, -8, -11, -11, -23, -7, -4, + -4, 14, 6, 4, 9, 3, -4, 4, 2, 9, 26, + 19, 26, 33, 22, 22, 24, 13, 20, 18, 18, 28, + 28, 19, 24, 16, -1, 1, -12, -34, -28, -25, -27, + -13, 6, 8, 21, 25, 22, 19, 3, 4, 0, -5, + 6, 8, 1, 6, 8, -4, -3, -10, -23, -17, -9, + -10, 3, 6, -1, 3, -10, -22, -28, -49, -49, -36, + -29, -10, 8, -1, 4, 14, -3, -14, -5, -16, -10, + 8, 7, 21, 24, 17, 25, 15, -4, 13, -7, -23, + 0, -7, -14, 12, 1, -18, -10, -27, -43, -31, -34, + -19, -3, -10, 15, 20, -7, 10, 9, -20, 7, 28, + 14, 42, 54, 32, 34, 24, 5, 10, -11, -13, 11, + -6, -4, 31, 7, 0, 34, 3, -9, 5, -24, -33, + -14, -11, -1, 8, 0, 10, 7, -7, 11, 10, -6, + 17, 16, 0, 10, 3, -26, -23, -33, -39, -26, -29, + -18, -6, -9, -1, 5, -11, -6, 7, -6, 1, 13, + 8, 1, 3, -13, -23, -25, -33, -28, -21, -9, 2, + 4, 1, 8, 4, -13, -5, -12, -14, 3, 14, 18, + 26, 30, 21, 20, 15, 15, 10, 5, 13, 11, 20, + 25, 29, 18, 19, 9, -10, -15, -13, -12, 1, 16, + 20, 30, 39, 37, 21, 15, 3, -7, -9, -1, 2, + -6, -7, -10, -20, -19, -19, -31, -25, -12, -15, -13, + -17, -18, -14, -24, -24, -18, -28, -24, -3, 1, 17, + 46, 48, 43, 46, 34, 12, 6, -14, -19, -10, -14, + 3, 15, 3, 7, 7, -13, 4, 9, -2, 3, 22, + 19, 25, 41, 48, 46, 36, 42, 40, 24, 33, 50, + 29, 30, 57, 35, 13, 29, 17, -9, 5, 15, 7, + 13, 38, 47, 40, 56, 72, 42, 29, 40, 18, 14, + 36, 52, 50, 58, 55, 42, 22, 20, 13, -8, 8, + 32, 26, 41, 70, 48, 51, 65, 36, 27, 23, 4, + 5, 1, -3, 2, -8, -23, -6, -30, -46, -24, -40, + -45, -22, -32, -35, -24, -50, -41, -35, -56, -38, -29, + -55, -25, -7, -40, -26, -25, -63, -51, -40, -61, -47, + -38, -38, -5, 2, 3, 26, -1, -7, 8, -20, -17, + 10, -14, -6, 41, 24, 27, 52, 26, 13, 25, 5, + -6, 2, -7, -2, 10, 4, 29, 36, 30, 74, 93, + 91, 131, 150, 132, 167, 177, 158, 189, 188, 178, 200, + 199, 187, 212, 202, 188, 210, 188, 173, 187, 175, 183, + 215, 218, 236, 264, 253, 279, 296, 275, 290, 288, 261, + 261, 261, 230, 216, 199, 157, 160, 147, 115, 108, 84, + 50, 32, 7, -30, -56, -96, -130, -146, -179, -199, -223, + -255, -280, -293, -326, -341, -352, -391, -410, -429, -464, -489, + -507, -538, -559, -577, -602, -634, -656, -679, -696, -702, -700, + -699, -700, -687, -666, -665, -656, -634, -626, -609, -572, -539, + -518, -484, -462, -444, -418, -390, -364, -336, -295, -245, -210, + -175, -127, -97, -63, -28, 10, 45, 83, 121, 167, 222, + 272, 324, 369, 396, 439, 485, 502, 536, 571, 585, 618, + 656, 676, 705, 729, 744, 767, 776, 786, 798, 796, 813, + 849, 855, 865, 883, 862, 843, 834, 794, 781, 778, 767, + 746, 744, 721, 702, 681, 638, 607, 562, 521, 490, 447, + 398, 361, 313, 255, 204, 123, 20, -59, -143, -217, -270, + -328, -400, -462, -529, -607, -666, -737, -797, -854, -906, -936, + -944, -955, -965, -976, -993, -1003, -1007, -1032, -1040, -1045, -1055, + -1039, -1016, -1003, -990, -995, -1026, -1046, -1070, -1079, -1058, -1060, + -1062, -1028, -1010, -1006, -991, -1000, -1004, -987, -981, -958, -921, + -890, -852, -798, -754, -713, -681, -682, -658, -617, -585, -524, + -452, -404, -332, -258, -224, -183, -144, -132, -94, -64, -31, + 37, 99, 147, 219, 280, 329, 389, 439, 483, 563, 632, + 702, 799, 884, 965, 1050, 1107, 1150, 1209, 1260, 1308, 1383, + 1446, 1514, 1582, 1632, 1679, 1727, 1770, 1804, 1837, 1872, 1916, + 1961, 1999, 2038, 2071, 2089, 2097, 2107, 2091, 2084, 2072, 2051, + 2021, 1998, 1940, 1868, 1814, 1734, 1641, 1559, 1480, 1395, 1305, + 1213, 1115, 1015, 901, 785, 667, 520, 381, 256, 110, -26, + -141, -284, -417, -528, -670, -805, -935, -1080, -1206, -1324, -1438, + -1527, -1622, -1725, -1798, -1879, -1956, -2006, -2063, -2128, -2166, -2201, + -2238, -2257, -2292, -2316, -2337, -2357, -2356, -2362, -2382, -2375, -2368, + -2367, -2358, -2337, -2329, -2318, -2296, -2273, -2240, -2195, -2140, -2095, + -2044, -1990, -1932, -1872, -1803, -1737, -1673, -1602, -1520, -1428, -1325, + -1219, -1112, -1006, -896, -780, -681, -591, -481, -388, -294, -189, + -85, 30, 148, 252, 348, 466, 579, 692, 811, 918, 1041, + 1162, 1271, 1389, 1507, 1611, 1735, 1864, 1965, 2085, 2203, 2312, + 2436, 2536, 2614, 2697, 2760, 2812, 2886, 2956, 3010, 3066, 3088, + 3098, 3120, 3110, 3101, 3106, 3108, 3130, 3149, 3139, 3122, 3085, + 3016, 2951, 2874, 2770, 2671, 2559, 2435, 2315, 2198, 2059, 1915, + 1761, 1570, 1387, 1185, 984, 787, 601, 413, 224, 40, -158, + -348, -560, -760, -960, -1147, -1312, -1471, -1621, -1779, -1925, -2069, + -2206, -2333, -2463, -2570, -2664, -2743, -2811, -2860, -2886, -2934, -2976, + -3015, -3057, -3074, -3076, -3079, -3060, -3032, -2998, -2950, -2920, -2893, + -2863, -2837, -2806, -2761, -2715, -2662, -2607, -2554, -2486, -2402, -2325, + -2264, -2190, -2127, -2063, -1989, -1932, -1862, -1788, -1724, -1640, -1545, + -1455, -1346, -1234, -1112, -984, -859, -735, -610, -494, -384, -280, + -176, -68, 40, 140, 244, 363, 478, 596, 739, 876, 1001, + 1128, 1240, 1352, 1474, 1595, 1717, 1853, 1972, 2093, 2215, 2328, + 2432, 2533, 2641, 2744, 2855, 2949, 3055, 3157, 3242, 3329, 3415, + 3479, 3528, 3569, 3588, 3617, 3649, 3676, 3708, 3747, 3751, 3753, + 3744, 3693, 3640, 3576, 3470, 3369, 3248, 3098, 2976, 2838, 2690, + 2557, 2395, 2222, 2055, 1872, 1675, 1488, 1279, 1057, 851, 623, + 393, 180, -74, -315, -537, -771, -979, -1161, -1373, -1558, -1729, + -1932, -2110, -2294, -2478, -2636, -2785, -2917, -3007, -3094, -3183, -3247, + -3319, -3402, -3450, -3510, -3564, -3595, -3622, -3635, -3627, -3635, -3639, + -3620, -3620, -3610, -3596, -3581, -3535, -3495, -3455, -3410, -3361, -3323, + -3265, -3202, -3141, -3078, -3001, -2919, -2830, -2739, -2640, -2540, -2430, + -2320, -2192, -2057, -1909, -1761, -1603, -1422, -1244, -1059, -887, -726, + -570, -425, -256, -92, 69, 238, 411, 557, 728, 910, 1066, + 1229, 1403, 1561, 1727, 1895, 2050, 2208, 2352, 2492, 2638, 2765, + 2893, 3025, 3145, 3263, 3387, 3496, 3595, 3707, 3804, 3884, 3975, + 4046, 4105, 4167, 4204, 4220, 4237, 4243, 4247, 4260, 4255, 4251, + 4246, 4201, 4143, 4092, 3996, 3885, 3772, 3604, 3435, 3283, 3086, + 2923, 2742, 2535, 2341, 2130, 1887, 1649, 1411, 1137, 915, 659, + 398, 163, -81, -351, -580, -814, -1069, -1262, -1476, -1689, -1850, + -2043, -2237, -2395, -2591, -2763, -2918, -3095, -3224, -3319, -3435, -3508, + -3582, -3698, -3772, -3858, -3950, -4008, -4047, -4088, -4093, -4085, -4098, + -4064, -4052, -4057, -4033, -4028, -4018, -3991, -3971, -3933, -3865, -3802, + -3727, -3633, -3562, -3477, -3392, -3300, -3210, -3115, -3018, -2924, -2819, + -2721, -2606, -2490, -2381, -2246, -2111, -1963, -1810, -1638, -1460, -1293, + -1132, -980, -828, -666, -496, -322, -125, 72, 264, 470, 676, + 879, 1087, 1280, 1457, 1633, 1799, 1970, 2152, 2327, 2501, 2678, + 2840, 3007, 3165, 3301, 3434, 3558, 3667, 3791, 3912, 4023, 4140, + 4257, 4359, 4475, 4554, 4614, 4656, 4682, 4697, 4726, 4749, 4775, + 4810, 4812, 4812, 4810, 4768, 4697, 4620, 4502, 4368, 4210, 4031, + 3860, 3663, 3472, 3291, 3076, 2849, 2642, 2392, 2140, 1890, 1610, + 1325, 1064, 782, 494, 231, -50, -329, -593, -861, -1112, -1345, + -1588, -1812, -2022, -2257, -2467, -2682, -2924, -3126, -3317, -3495, -3630, + -3737, -3855, -3941, -4031, -4128, -4200, -4281, -4348, -4388, -4427, -4449, + -4444, -4450, -4458, -4452, -4464, -4460, -4451, -4444, -4425, -4384, -4344, + -4289, -4234, -4160, -4076, -4000, -3917, -3837, -3753, -3669, -3558, -3460, + -3354, -3230, -3111, -2966, -2824, -2665, -2495, -2333, -2151, -1951, -1752, + -1554, -1367, -1222, -1053, -882, -716, -520, -331, -141, 62, 270, + 476, 707, 923, 1133, 1349, 1534, 1735, 1943, 2124, 2317, 2511, + 2668, 2839, 3002, 3140, 3317, 3481, 3615, 3771, 3920, 4050, 4196, + 4319, 4430, 4556, 4657, 4765, 4868, 4945, 4999, 5057, 5075, 5100, + 5123, 5133, 5134, 5127, 5104, 5084, 5058, 4968, 4896, 4750, 4575, + 4381, 4179, 3971, 3776, 3590, 3394, 3209, 2991, 2800, 2535, 2269, + 1972, 1654, 1319, 998, 697, 384, 105, -187, -476, -759, -1047, + -1316, -1579, -1841, -2085, -2317, -2550, -2745, -2938, -3145, -3326, -3523, + -3706, -3859, -3998, -4124, -4218, -4288, -4346, -4386, -4437, -4495, -4550, + -4619, -4680, -4732, -4779, -4813, -4820, -4842, -4825, -4791, -4773, -4742, + -4715, -4709, -4683, -4652, -4605, -4527, -4428, -4315, -4194, -4086, -3978, + -3872, -3779, -3685, -3569, -3458, -3313, -3121, -2921, -2693, -2454, -2230, + -1998, -1783, -1588, -1414, -1240, -1069, -886, -690, -473, -256, -36, + 170, 384, 594, 797, 1015, 1235, 1449, 1664, 1882, 2098, 2311, + 2504, 2681, 2843, 3019, 3171, 3337, 3534, 3709, 3885, 4072, 4235, + 4380, 4524, 4641, 4746, 4864, 4979, 5087, 5213, 5308, 5393, 5450, + 5468, 5475, 5472, 5452, 5462, 5467, 5453, 5451, 5425, 5342, 5255, + 5113, 4914, 4725, 4512, 4273, 4053, 3866, 3632, 3436, 3205, 2955, + 2705, 2420, 2095, 1794, 1503, 1195, 941, 639, 342, 56, -269, + -601, -894, -1208, -1499, -1736, -1994, -2239, -2426, -2652, -2891, -3099, + -3361, -3588, -3793, -4013, -4183, -4302, -4439, -4523, -4613, -4734, -4809, + -4891, -4999, -5056, -5090, -5131, -5092, -5061, -5044, -4987, -4954, -4955, + -4924, -4911, -4873, -4809, -4755, -4673, -4555, -4440, -4316, -4187, -4088, + -3986, -3881, -3802, -3717, -3605, -3495, -3359, -3207, -3063, -2889, -2698, + -2504, -2306, -2088, -1861, -1627, -1415, -1201, -1000, -799, -593, -410, + -220, -7, 203, 412, 634, 865, 1126, 1367, 1602, 1838, 2052, + 2257, 2474, 2659, 2863, 3076, 3255, 3429, 3617, 3773, 3939, 4102, + 4222, 4358, 4501, 4611, 4733, 4846, 4939, 5056, 5147, 5217, 5301, + 5357, 5388, 5428, 5417, 5400, 5430, 5422, 5406, 5442, 5446, 5431, + 5437, 5381, 5304, 5212, 5057, 4874, 4683, 4465, 4249, 4026, 3767, + 3545, 3304, 3021, 2741, 2450, 2113, 1807, 1490, 1151, 841, 544, + 212, -102, -439, -788, -1091, -1413, -1730, -2033, -2336, -2627, -2854, + -3118, -3350, -3560, -3781, -4008, -4194, -4376, -4524, -4640, -4757, -4865, + -4945, -5016, -5083, -5131, -5170, -5184, -5198, -5208, -5211, -5210, -5209, + -5192, -5174, -5154, -5108, -5052, -5002, -4932, -4854, -4780, -4704, -4604, + -4514, -4421, -4309, -4208, -4111, -4004, -3880, -3751, -3622, -3496, -3367, + -3210, -3047, -2867, -2654, -2430, -2177, -1897, -1651, -1417, -1182, -983, + -793, -593, -406, -211, 17, 232, 461, 716, 958, 1197, 1441, + 1674, 1899, 2130, 2355, 2573, 2788, 3004, 3220, 3419, 3612, 3809, + 3973, 4120, 4277, 4433, 4573, 4742, 4902, 5037, 5165, 5282, 5377, + 5460, 5539, 5596, 5654, 5716, 5741, 5759, 5770, 5776, 5762, 5751, + 5737, 5706, 5675, 5644, 5550, 5446, 5324, 5169, 4974, 4767, 4530, + 4289, 4067, 3823, 3621, 3391, 3145, 2878, 2575, 2228, 1890, 1525, + 1149, 807, 473, 145, -152, -454, -769, -1057, -1374, -1703, -2033, + -2372, -2701, -2977, -3258, -3495, -3694, -3897, -4089, -4270, -4483, -4668, + -4840, -5015, -5140, -5225, -5304, -5334, -5350, -5390, -5398, -5403, -5428, + -5438, -5449, -5472, -5463, -5441, -5401, -5333, -5252, -5151, -5051, -4974, + -4880, -4805, -4729, -4626, -4526, -4403, -4248, -4088, -3939, -3778, -3617, + -3464, -3308, -3173, -3027, -2852, -2669, -2461, -2233, -1979, -1713, -1455, + -1216, -996, -796, -610, -397, -198, 21, 272, 517, 775, 1037, + 1295, 1544, 1790, 2007, 2211, 2423, 2634, 2848, 3081, 3319, 3551, + 3792, 4000, 4171, 4303, 4418, 4518, 4596, 4679, 4807, 4913, 5044, + 5172, 5288, 5405, 5518, 5609, 5664, 5713, 5735, 5735, 5737, 5701, + 5691, 5656, 5633, 5611, 5552, 5475, 5394, 5293, 5177, 5064, 4924, + 4737, 4599, 4420, 4237, 4048, 3828, 3623, 3413, 3183, 2915, 2622, + 2308, 1980, 1657, 1261, 901, 549, 205, -85, -383, -688, -969, + -1246, -1530, -1850, -2206, -2561, -2915, -3224, -3482, -3713, -3921, -4107, + -4287, -4470, -4660, -4850, -5057, -5239, -5395, -5540, -5619, -5697, -5724, + -5697, -5675, -5633, -5590, -5579, -5530, -5486, -5442, -5426, -5391, -5348, + -5276, -5197, -5124, -5039, -4925, -4808, -4677, -4581, -4479, -4343, -4218, + -4087, -3970, -3858, -3729, -3570, -3384, -3206, -3020, -2839, -2636, -2453, + -2287, -2185, -2154, -1926, -1562, -1223, -758, -473, -64, 395, 599, + 880, 814, 938, 1172, 1498, 1928, 2127, 2422, 2608, 2841, 2937, + 2886, 2815, 2985, 3324, 3757, 4152, 4481, 4652, 4917, 4965, 4766, + 4583, 4328, 4503, 4815, 5118, 5408, 5682, 5956, 6082, 6055, 5744, + 5426, 5341, 5427, 5606, 5882, 6065, 6226, 6428, 6477, 6385, 6009, + 5728, 5552, 5439, 5339, 5200, 5008, 4947, 4835, 4614, 4330, 3887, + 3521, 3111, 2460, 1983, 1297, 650, 279, -353, -720, -1044, -1518, + -1668, -2117, -2496, -2743, -3266, -3607, -3790, -4149, -4075, -4042, -4096, + -3981, -4138, -4226, -4214, -4503, -4455, -4577, -4642, -4346, -4351, -4270, + -4263, -4522, -4521, -4673, -4814, -4731, -4950, -5011, -5004, -5288, -5341, + -5566, -5833, -5783, -5929, -5847, -5765, -5828, -5644, -5613, -5615, -5428, + -5291, -5014, -4554, -4277, -3964, -3854, -3829, -3612, -3603, -3438, -3137, + -2831, -2164, -1438, -939, -330, -156, 46, 242, 73, 242, 220, + 239, 542, 565, 739, 872, 801, 857, 676, 543, 586, 567, + 828, 1142, 1490, 1985, 2508, 2982, 3438, 3699, 3939, 4069, 4178, + 4420, 4622, 4917, 5338, 5801, 6285, 6658, 6963, 7213, 7233, 7328, + 7176, 7038, 7031, 6860, 6957, 6767, 6599, 6523, 6212, 6147, 6063, + 5860, 6020, 6015, 6033, 6184, 5722, 5607, 5016, 4337, 4063, 3229, + 3080, 3006, 2804, 3035, 2541, 2136, 1879, 1012, 401, -575, -1584, + -1930, -2278, -2485, -2477, -2712, -2747, -2766, -3320, -3592, -4188, -4669, + -4672, -4939, -4789, -4426, -4203, -3674, -3563, -3656, -3759, -4067, -4257, + -4522, -4970, -5204, -5237, -5139, -4907, -4911, -4917, -4921, -5007, -5230, + -5654, -6122, -6464, -6733, -6948, -7067, -6972, -6800, -6520, -6132, -5830, + -5382, -5091, -4797, -4546, -4472, -4362, -4350, -4235, -3851, -3454, -3144, + -2735, -2341, -1845, -1262, -958, -549, -166, 66, 382, 366, 352, + 341, 85, -13, -176, -303, -235, -341, -309, -227, -249, -50, + 143, 384, 874, 1149, 1552, 2155, 2767, 3499, 3994, 4460, 4920, + 5288, 5569, 5704, 5881, 6094, 6461, 6653, 6803, 7115, 7311, 7521, + 7612, 7443, 7380, 7124, 6742, 6495, 5964, 5656, 5415, 5167, 5656, + 5813, 6027, 6401, 6351, 6787, 7019, 6581, 6512, 5965, 5308, 5140, + 4336, 4147, 3899, 3398, 3360, 2830, 2624, 1968, 1026, 395, -699, + -1424, -2327, -3006, -3192, -3435, -3337, -3686, -3513, -3350, -3502, -3261, + -3878, -4005, -4063, -4187, -3767, -3598, -3384, -3300, -3094, -2857, -3023, + -3274, -3851, -4352, -4523, -4943, -5477, -5612, -5682, -5733, -5714, -5965, + -6110, -5950, -6158, -6548, -6897, -7165, -7281, -7352, -7258, -7185, -6659, + -5946, -5470, -4738, -4046, -3707, -3210, -3108, -3270, -3227, -3222, -3218, + -3017, -2943, -2668, -2296, -1593, -1061, -811, -403, -513, -361, -128, + -595, -633, -991, -1205, -1159, -1284, -1330, -1164, -999, -729, -538, + -336, 27, 350, 794, 1245, 1646, 2446, 3210, 4017, 4835, 5271, + 5739, 6028, 6140, 6212, 6161, 6066, 5984, 6081, 5995, 6152, 6301, + 6278, 6424, 6377, 6396, 6362, 6152, 5788, 5309, 5071, 4860, 4704, + 4804, 4919, 5258, 5869, 6121, 6365, 6694, 6692, 6694, 6532, 6187, + 5808, 5704, 5302, 4816, 4611, 4043, 3775, 3249, 2600, 1933, 982, + 336, -848, -1538, -2242, -3103, -3374, -3756, -3975, -4017, -4061, -3972, + -3749, -3609, -3853, -3850, -3714, -3760, -3736, -3914, -3923, -3830, -3541, + -3649, -3757, -3661, -3913, -4038, -4231, -4594, -4769, -5009, -5273, -5588, + -5676, -5937, -5997, -6060, -6164, -6414, -6623, -6765, -6857, -6771, -6921, + -6914, -6535, -6187, -5626, -5206, -4742, -4189, -3618, -3120, -2823, -2606, + -2550, -2703, -2736, -2626, -2498, -2406, -2133, -1852, -1348, -753, -318, + 162, 330, 524, 375, 9, -204, -866, -1249, -1532, -1669, -1455, + -1235, -723, -283, 262, 535, 862, 1340, 1712, 2316, 2625, 3171, + 4015, 4698, 5516, 6006, 6452, 6838, 6921, 7003, 6735, 6339, 6138, + 5768, 5575, 5593, 5568, 5728, 6041, 6233, 6260, 6175, 6048, 5728, + 5366, 4931, 4340, 4194, 4174, 4330, 4743, 5028, 5754, 6250, 6598, + 7120, 7114, 6962, 6675, 6157, 5373, 4797, 4081, 3237, 3153, 2588, + 2143, 1639, 1021, 681, -149, -816, -1987, -3003, -3493, -4138, -4420, + -4607, -4841, -4725, -4254, -4033, -3845, -3842, -4063, -4035, -4099, -4582, + -4718, -4779, -4689, -4437, -4327, -4352, -4119, -3881, -4061, -4345, -4768, + -5248, -5610, -5920, -6383, -6779, -6731, -6673, -6677, -6597, -6659, -6619, + -6417, -6516, -6862, -7017, -7069, -6944, -6715, -6376, -6000, -5162, -4333, + -3577, -2884, -2355, -1807, -1366, -1380, -1590, -1869, -1962, -1945, -2006, + -2141, -1960, -1516, -1025, -471, -135, 85, 348, 239, -8, -475, + -951, -1245, -1520, -1569, -1448, -1188, -517, 134, 827, 1585, 2114, + 2792, 3214, 3651, 4230, 4546, 4894, 5321, 5588, 6105, 6583, 6877, + 7014, 7087, 7068, 6876, 6695, 6280, 5684, 5385, 5205, 5064, 5033, + 5028, 5080, 5322, 5510, 5461, 5390, 5541, 5494, 5443, 5306, 5065, + 5193, 5338, 5513, 5818, 5911, 6345, 6506, 6514, 6543, 5981, 5703, + 5082, 4228, 3517, 2424, 1880, 1245, 562, -130, -864, -1156, -1561, + -1970, -2597, -3357, -3707, -4189, -4521, -4975, -5477, -5478, -5585, -5445, + -5353, -5327, -4971, -4580, -4431, -4469, -4432, -4422, -4275, -4227, -4507, + -4745, -4758, -4752, -4845, -4933, -5118, -5117, -5124, -5324, -5673, -5971, + -6152, -6366, -6702, -6970, -7159, -7136, -6929, -6917, -6703, -6520, -6302, + -5794, -5484, -5123, -4694, -4254, -3722, -3334, -2917, -2410, -1721, -1010, + -584, -312, 27, 321, 327, 214, -17, -363, -402, -550, -638, + -469, -315, -86, 142, 242, 387, 448, 458, 423, 321, 194, + 285, 417, 717, 1176, 1673, 2402, 3144, 3985, 4764, 5406, 6056, + 6507, 6783, 6891, 6868, 6850, 6717, 6532, 6359, 6248, 6303, 6279, + 6140, 6071, 5927, 5687, 5480, 5146, 4835, 4572, 4447, 4481, 4578, + 4840, 4936, 5246, 5659, 5732, 5856, 5658, 5403, 5282, 5004, 4949, + 4843, 4681, 4884, 4886, 4967, 5108, 4781, 4647, 4240, 3443, 2768, + 1830, 983, 309, -769, -1382, -1987, -2553, -2750, -3346, -3555, -4052, + -4400, -4599, -5196, -5437, -5945, -6340, -6343, -6554, -6611, -6381, -6184, + -5681, -5398, -5098, -4751, -4529, -4138, -4100, -4088, -4044, -4186, -4189, + -4263, -4453, -4465, -4598, -4651, -4726, -4919, -4926, -5142, -5286, -5490, + -5831, -6002, -6341, -6492, -6562, -6710, -6553, -6506, -6219, -5766, -5521, + -5008, -4556, -4002, -3293, -2769, -2069, -1467, -824, -34, 509, 1034, + 1385, 1560, 1650, 1664, 1419, 1016, 834, 511, 353, 381, 299, + 523, 833, 956, 1280, 1492, 1425, 1547, 1350, 1143, 1114, 931, + 1054, 1217, 1583, 2217, 2917, 4017, 4965, 5827, 6816, 7393, 7875, + 8197, 8175, 7924, 7578, 7040, 6566, 6242, 5746, 5530, 5334, 5222, + 5237, 5074, 5146, 5011, 4902, 4753, 4442, 4482, 4254, 4247, 4319, + 4187, 4516, 4690, 4935, 5193, 5229, 5350, 5332, 5486, 5386, 5143, + 4999, 4494, 4304, 3961, 3421, 2781, 2032, 1404, 614, -88, -956, + -1714, -2155, -2684, -3038, -3237, -3368, -3423, -3569, -3809, -4213, -4533, + -4973, -5514, -6011, -6663, -7084, -7258, -7158, -6947, -6639, -6111, -5548, + -4887, -4362, -4043, -3895, -3940, -4107, -4452, -4836, -5143, -5500, -5532, + -5510, -5485, -5096, -4739, -4375, -4065, -4063, -4094, -4252, -4576, -4904, + -5431, -5837, -6190, -6402, -6310, -6292, -5992, -5516, -5025, -4342, -3899, + -3386, -2697, -2077, -1493, -994, -392, 232, 931, 1608, 1988, 2360, + 2589, 2639, 2623, 2471, 2121, 1708, 1478, 1181, 1167, 1296, 1279, + 1648, 1859, 2107, 2368, 2359, 2390, 2122, 1904, 1629, 1418, 1502, + 1524, 1859, 2357, 3041, 3909, 4810, 5751, 6449, 7128, 7534, 7767, + 7908, 7699, 7460, 7032, 6647, 6301, 5876, 5556, 5190, 4948, 4762, + 4576, 4464, 4370, 4338, 4275, 4287, 4265, 4320, 4221, 4066, 3947, + 3514, 3379, 3003, 2635, 2534, 2078, 2040, 1950, 1958, 2152, 2085, + 2390, 2321, 2319, 2359, 1851, 1643, 877, 168, -527, -1245, -1704, + -2519, -2739, -3251, -3382, -3236, -3527, -3294, -3523, -3732, -3916, -4434, + -4888, -5615, -6161, -6729, -7283, -7543, -7920, -7865, -7660, -7430, -7034, + -6758, -6224, -5866, -5441, -5076, -4998, -4760, -4673, -4539, -4410, -4308, + -4131, -3992, -3791, -3611, -3448, -3213, -3070, -3046, -3048, -3168, -3244, + -3354, -3607, -3834, -4170, -4439, -4648, -4864, -4892, -4928, -4821, -4524, + -4211, -3576, -2819, -1968, -929, -19, 1029, 2064, 2949, 3716, 4159, + 4450, 4536, 4503, 4301, 3968, 3655, 3242, 2979, 2856, 2744, 2750, + 2771, 2749, 2859, 2850, 2793, 2702, 2402, 2179, 1877, 1672, 1581, + 1543, 1769, 1967, 2485, 3089, 3783, 4662, 5406, 6246, 6950, 7542, + 8016, 8200, 8245, 8027, 7584, 6958, 6241, 5494, 4710, 3974, 3255, + 2653, 2274, 2038, 1986, 1964, 2141, 2321, 2513, 2772, 2756, 2743, + 2636, 2406, 2125, 1836, 1456, 1247, 1145, 995, 1077, 1140, 1290, + 1561, 1685, 1762, 1609, 1391, 1147, 544, 84, -754, -1546, -2107, + -2806, -3137, -3522, -3732, -3826, -3834, -3609, -3493, -3340, -3254, -3499, + -3621, -3981, -4455, -4859, -5513, -6080, -6626, -7061, -7372, -7556, -7573, + -7515, -7366, -7091, -6799, -6366, -5887, -5484, -5098, -4746, -4334, -3941, + -3558, -3269, -3053, -2844, -2663, -2497, -2314, -2227, -2185, -2141, -2139, + -2070, -2037, -2031, -2062, -2205, -2348, -2544, -2774, -2979, -3298, -3520, + -3647, -3622, -3395, -3054, -2513, -1829, -948, 64, 1090, 2169, 3127, + 3987, 4712, 5229, 5560, 5754, 5741, 5619, 5401, 5005, 4666, 4287, + 3967, 3734, 3476, 3322, 3203, 3147, 3144, 3116, 3080, 3011, 2871, + 2735, 2544, 2363, 2245, 2075, 2032, 2118, 2263, 2688, 3066, 3605, + 4244, 4746, 5384, 5819, 6151, 6319, 6194, 5938, 5495, 4929, 4305, + 3581, 2924, 2279, 1713, 1372, 1086, 1006, 983, 1006, 1146, 1249, + 1349, 1360, 1231, 1084, 794, 502, 264, -85, -238, -411, -504, + -394, -322, -51, 188, 420, 589, 624, 666, 573, 338, -86, + -564, -1056, -1560, -1925, -2434, -2806, -3017, -3341, -3320, -3375, -3480, + -3410, -3567, -3553, -3595, -3805, -3919, -4284, -4482, -4754, -5190, -5354, + -5806, -6050, -6136, -6387, -6343, -6330, -6206, -5851, -5468, -4960, -4549, + -4080, -3542, -3150, -2698, -2440, -2318, -2132, -2067, -2081, -2017, -2099, + -2151, -2060, -2067, -1916, -1823, -1718, -1523, -1386, -1221, -1189, -1141, + -1014, -1008, -966, -996, -1015, -916, -809, -648, -467, -128, 237, + 735, 1358, 1969, 2697, 3399, 4060, 4732, 5295, 5720, 6077, 6169, + 6139, 5928, 5614, 5292, 4766, 4247, 3705, 3262, 3030, 2827, 2702, + 2684, 2728, 2887, 3092, 3216, 3310, 3313, 3214, 3098, 2873, 2620, + 2343, 2031, 1799, 1589, 1491, 1537, 1645, 1913, 2210, 2548, 2922, + 3295, 3650, 3951, 4100, 4099, 3972, 3740, 3421, 2948, 2427, 1762, + 1136, 574, 44, -330, -642, -846, -852, -751, -520, -229, 44, + 272, 446, 502, 443, 329, 66, -191, -492, -841, -1002, -1240, + -1237, -1199, -1177, -936, -867, -660, -456, -508, -464, -706, -997, + -1265, -1780, -2178, -2724, -3270, -3735, -4142, -4378, -4609, -4666, -4749, + -4575, -4355, -4137, -3767, -3563, -3218, -2970, -2834, -2630, -2716, -2776, + -2920, -3210, -3363, -3764, -4023, -4125, -4268, -4194, -4223, -4005, -3639, + -3258, -2891, -2644, -2297, -1987, -1751, -1587, -1570, -1485, -1415, -1342, + -1194, -1100, -889, -613, -267, 161, 482, 865, 1269, 1639, 2005, + 2202, 2381, 2549, 2628, 2700, 2625, 2559, 2481, 2357, 2319, 2192, + 2142, 2199, 2283, 2514, 2670, 2919, 3214, 3510, 3830, 3971, 4080, + 4073, 3911, 3700, 3359, 2954, 2549, 2094, 1766, 1556, 1442, 1462, + 1560, 1808, 2070, 2357, 2606, 2730, 2831, 2737, 2582, 2309, 1931, + 1585, 1178, 834, 529, 288, 214, 218, 302, 470, 679, 944, + 1211, 1420, 1562, 1674, 1631, 1548, 1355, 1072, 776, 375, 25, + -320, -614, -818, -992, -991, -906, -755, -525, -291, -17, 225, + 447, 528, 546, 466, 270, 96, -205, -536, -861, -1148, -1383, + -1586, -1688, -1814, -1783, -1772, -1745, -1630, -1611, -1505, -1488, -1462, + -1409, -1519, -1489, -1609, -1723, -1755, -1977, -2042, -2132, -2215, -2184, + -2268, -2205, -2170, -2107, -1978, -1990, -1909, -1886, -1943, -1997, -2152, + -2326, -2500, -2762, -2987, -3227, -3392, -3522, -3630, -3579, -3469, -3262, + -2916, -2555, -2103, -1581, -1090, -531, -20, 457, 873, 1228, 1561, + 1809, 1999, 2105, 2139, 2196, 2201, 2149, 2113, 2038, 1990, 1913, + 1787, 1705, 1595, 1490, 1372, 1201, 1113, 998, 917, 917, 894, + 961, 1007, 1098, 1321, 1470, 1681, 1882, 2067, 2317, 2465, 2626, + 2750, 2777, 2783, 2694, 2569, 2431, 2142, 1843, 1597, 1306, 1069, + 824, 622, 532, 430, 388, 357, 377, 438, 414, 481, 468, + 431, 454, 383, 374, 305, 207, 187, 133, 157, 115, 113, + 206, 244, 382, 475, 591, 753, 821, 916, 908, 855, 754, + 577, 399, 123, -159, -399, -647, -784, -923, -1010, -965, -918, + -806, -647, -504, -355, -253, -179, -130, -138, -156, -262, -339, + -401, -552, -600, -671, -697, -662, -673, -616, -597, -522, -495, + -513, -490, -624, -701, -804, -961, -1073, -1328, -1503, -1656, -1798, + -1801, -1913, -1863, -1785, -1720, -1453, -1309, -1051, -846, -715, -487, + -457, -357, -331, -400, -427, -627, -765, -873, -1021, -1105, -1255, + -1312, -1357, -1370, -1288, -1261, -1165, -1139, -1062, -917, -808, -680, + -597, -452, -277, -104, 122, 312, 558, 771, 919, 1110, 1205, + 1312, 1355, 1302, 1280, 1151, 1049, 946, 818, 733, 569, 451, + 429, 388, 408, 387, 376, 426, 463, 542, 576, 632, 666, + 673, 740, 766, 791, 845, 829, 857, 841, 822, 835, 796, + 773, 671, 600, 560, 484, 460, 371, 311, 284, 242, 277, + 261, 261, 277, 273, 358, 380, 410, 433, 435, 471, 432, + 414, 386, 330, 294, 194, 149, 108, 69, 84, 69, 92, + 83, 75, 88, 53, 12, -96, -194, -269, -369, -438, -523, + -553, -528, -500, -392, -277, -136, 53, 240, 466, 678, 870, + 1050, 1178, 1294, 1336, 1310, 1247, 1080, 916, 677, 387, 120, + -182, -471, -740, -972, -1148, -1273, -1343, -1402, -1363, -1263, -1129, + -922, -724, -518, -288, -79, 111, 250, 364, 405, 405, 395, + 284, 199, 83, -43, -126, -244, -313, -400, -451, -497, -610, + -672, -807, -951, -1087, -1325, -1517, -1736, -1929, -2086, -2260, -2318, + -2356, -2271, -2125, -1967, -1685, -1379, -1000, -598, -238, 149, 481, + 790, 1042, 1185, 1287, 1274, 1195, 1068, 868, 654, 386, 138, + -65, -273, -450, -598, -665, -670, -669, -620, -553, -425, -288, + -179, -72, 15, 122, 205, 263, 324, 357, 435, 518, 603, + 709, 779, 892, 1006, 1107, 1170, 1183, 1190, 1173, 1116, 1016, + 890, 750, 628, 488, 331, 197, 95, 43, 25, 1, 22, + 97, 209, 363, 495, 615, 724, 833, 937, 984, 990, 933, + 884, 851, 747, 678, 573, 497, 469, 401, 391, 352, 339, + 352, 337, 354, 361, 370, 402, 411, 418, 440, 468, 526, + 576, 619, 683, 766, 857, 965, 1038, 1114, 1159, 1172, 1167, + 1106, 1006, 840, 644, 426, 177, -110, -390, -665, -929, -1160, + -1375, -1497, -1550, -1592, -1553, -1507, -1394, -1201, -1084, -863, -685, + -540, -322, -234, -68, 29, 59, 160, 141, 170, 140, 79, + 77, -11, -53, -179, -274, -327, -480, -564, -736, -884, -995, + -1185, -1300, -1461, -1617, -1711, -1832, -1831, -1863, -1865, -1776, -1691, + -1516, -1353, -1168, -954, -729, -490, -305, -93, 81, 211, 322, + 364, 392, 384, 332, 264, 146, 29, -101, -230, -357, -486, + -616, -705, -752, -801, -809, -788, -750, -654, -546, -456, -328, + -200, -78, 45, 137, 232, 316, 388, 447, 485, 528, 578, + 630, 697, 760, 835, 910, 988, 1068, 1124, 1154, 1157, 1166, + 1163, 1116, 1070, 1024, 994, 986, 988, 1030, 1110, 1212, 1303, + 1411, 1498, 1551, 1599, 1587, 1565, 1481, 1336, 1212, 1028, 847, + 669, 466, 330, 187, 61, -9, -54, -55, -20, 11, 69, + 133, 195, 244, 253, 225, 182, 133, 62, -11, -96, -168, + -199, -214, -213, -197, -167, -127, -105, -86, -83, -109, -140, + -217, -323, -448, -588, -717, -854, -971, -1086, -1185, -1211, -1227, + -1180, -1135, -1099, -992, -918, -788, -704, -651, -562, -542, -470, + -421, -431, -391, -429, -386, -344, -336, -260, -257, -162, -61, + -6, 100, 120, 178, 215, 179, 132, 15, -106, -238, -416, + -595, -765, -929, -1066, -1170, -1252, -1278, -1290, -1258, -1173, -1114, + -1012, -945, -868, -741, -695, -612, -547, -494, -388, -332, -225, + -110, 22, 182, 318, 496, 677, 835, 992, 1104, 1162, 1166, + 1133, 1054, 916, 709, 430, 164, -90, -340, -600, -853, -1033, + -1135, -1177, -1146, -1079, -946, -746, -500, -208, 83, 377, 673, + 950, 1183, 1356, 1503, 1627, 1707, 1735, 1708, 1678, 1668, 1645, + 1588, 1494, 1419, 1354, 1291, 1194, 1052, 900, 718, 524, 325, + 110, -114, -330, -500, -630, -729, -803, -834, -795, -727, -627, + -492, -325, -125, 54, 238, 393, 528, 642, 691, 706, 661, + 585, 504, 380, 245, 87, -61, -195, -320, -435, -556, -663, + -742, -814, -883, -952, -1009, -1038, -1047, -1067, -1063, -1050, -1020, + -949, -888, -795, -698, -574, -405, -257, -70, 68, 203, 381, + 479, 580, 619, 623, 645, 565, 492, 364, 206, 106, -71, + -191, -331, -460, -469, -527, -471, -441, -386, -222, -123, 60, + 168, 245, 404, 470, 596, 605, 581, 633, 548, 562, 468, + 355, 334, 192, 161, 62, -36, -39, -146, -121, -167, -243, + -229, -302, -276, -327, -415, -419, -444, -396, -433, -455, -407, + -357, -244, -221, -158, -63, 36, 172, 210, 296, 326, 351, + 424, 367, 369, 300, 224, 235, 124, 54, -39, -122, -118, + -239, -304, -360, -403, -361, -418, -427, -394, -342, -259, -232, + -176, -110, -48, 27, 48, 78, 90, 86, 91, 76, 57, + -1, -34, -53, -103, -151, -209, -239, -261, -319, -354, -372, + -382, -385, -411, -432, -428, -431, -446, -471, -496, -512, -532, + -562, -570, -567, -543, -499, -457, -379, -290, -204, -94, -11, + 78, 155, 196, 234, 222, 198, 160, 113, 64, 5, -57, + -108, -136, -175, -186, -196, -184, -125, -90, -25, 58, 146, + 271, 372, 472, 562, 636, 709, 741, 760, 752, 730, 710, + 688, 655, 608, 595, 570, 556, 540, 517, 513, 511, 497, + 481, 449, 417, 401, 347, 325, 295, 248, 261, 238, 250, + 294, 295, 367, 380, 416, 454, 430, 479, 443, 431, 430, + 386, 397, 333, 292, 238, 176, 153, 54, 24, -37, -84, + -109, -172, -155, -199, -220, -219, -261, -227, -255, -280, -266, + -293, -277, -273, -243, -214, -221, -179, -153, -130, -109, -154, + -149, -151, -155, -186, -243, -253, -311, -326, -358, -434, -427, + -491, -533, -554, -598, -596, -655, -668, -679, -714, -671, -694, + -643, -607, -602, -532, -496, -409, -408, -377, -309, -289, -211, + -223, -196, -145, -147, -104, -157, -123, -125, -177, -152, -229, + -192, -204, -243, -213, -259, -194, -190, -172, -98, -123, -43, + -12, 41, 103, 87, 148, 150, 166, 154, 113, 118, 80, + 54, 8, 4, 25, 12, 59, 70, 162, 260, 305, 387, + 427, 501, 549, 564, 571, 517, 488, 423, 355, 294, 206, + 165, 113, 92, 77, 62, 115, 116, 154, 162, 171, 218, + 210, 221, 208, 192, 215, 176, 169, 114, 89, 89, 52, + 62, 29, 35, 73, 98, 167, 195, 261, 325, 349, 401, + 382, 393, 368, 302, 254, 174, 104, 6, -78, -136, -203, + -229, -291, -303, -284, -294, -241, -235, -222, -186, -187, -156, + -160, -149, -122, -114, -71, -44, -28, 6, 20, 47, 57, + 54, 52, 55, 53, 23, 9, -16, -59, -86, -158, -223, + -292, -372, -421, -498, -532, -561, -570, -531, -512, -456, -367, + -297, -206, -125, -37, 26, 88, 147, 157, 188, 169, 152, + 152, 131, 99, 62, 44, 46, 53, 61, 61, 79, 110, + 159, 175, 185, 237, 220, 278, 276, 239, 264, 203, 190, + 138, 70, 34, -9, 18, 1, 10, 71, 115, 191, 220, + 255, 265, 296, 319, 270, 266, 214, 189, 187, 155, 145, + 123, 149, 166, 172, 186, 179, 195, 213, 201, 182, 161, + 150, 116, 76, 41, -29, -58, -101, -183, -209, -269, -314, + -342, -385, -379, -380, -348, -304, -273, -197, -144, -88, -28, + -5, 11, 20, 27, -5, -24, -22, -61, -73, -87, -124, + -118, -133, -150, -160, -198, -196, -219, -228, -239, -281, -276, + -275, -288, -277, -305, -324, -302, -294, -292, -266, -261, -224, + -203, -210, -190, -198, -176, -180, -201, -196, -198, -175, -166, + -151, -127, -114, -59, -48, -8, 39, 75, 126, 131, 168, + 160, 152, 142, 82, 36, -13, -49, -81, -105, -105, -103, + -65, -38, -16, 19, 33, 67, 82, 95, 110, 98, 111, + 98, 87, 67, 54, 66, 52, 49, 53, 71, 106, 139, + 186, 224, 270, 320, 361, 413, 433, 462, 473, 478, 480, + 459, 441, 391, 339, 298, 239, 206, 159, 149, 120, 114, + 117, 95, 106, 81, 67, 61, 30, 11, -29, -42, -76, + -97, -98, -124, -107, -107, -103, -69, -71, -36, -12, 23, + 69, 86, 129, 152, 158, 162, 152, 127, 81, 48, -9, + -80, -120, -172, -201, -225, -276, -297, -311, -330, -339, -361, + -375, -389, -376, -365, -374, -378, -375, -370, -358, -347, -355, + -338, -314, -289, -244, -212, -168, -129, -80, -26, -12, 47, + 79, 92, 105, 105, 113, 99, 85, 29, -18, -53, -110, + -133, -167, -186, -196, -199, -176, -177, -150, -122, -106, -73, + -61, -30, -34, -29, -40, -68, -63, -85, -84, -71, -65, + -40, -16, 23, 56, 87, 144, 167, 196, 206, 221, 243, + 226, 233, 210, 192, 190, 150, 140, 110, 91, 77, 43, + 27, -10, -5, -5, -22, -9, -7, 27, 48, 59, 64, + 70, 87, 104, 139, 151, 188, 239, 270, 317, 311, 336, + 349, 341, 330, 274, 254, 223, 195, 163, 102, 81, 43, + 20, 8, -37, -28, -31, -29, -21, -39, -16, -22, -11, + -21, -41, -32, -47, -39, -60, -75, -71, -94, -98, -131, + -147, -139, -145, -146, -165, -150, -136, -112, -90, -106, -86, + -91, -87, -98, -136, -121, -135, -124, -132, -144, -114, -108, + -87, -74, -75, -50, -30, -5, -18, -24, -3, -3, -6, + -41, -76, -98, -127, -159, -215, -257, -263, -268, -266, -262, + -237, -194, -144, -113, -99, -61, -28, 12, 21, 46, 76, + 92, 130, 115, 123, 132, 135, 149, 134, 133, 132, 135, + 138, 94, 76, 51, 19, -15, -72, -98, -125, -135, -154, + -174, -171, -164, -139, -130, -99, -74, -40, 9, 34, 86, + 129, 176, 214, 226, 245, 250, 280, 271, 256, 250, 226, + 234, 212, 187, 178, 148, 144, 104, 79, 64, 37, 36, + 9, -10, -23, -38, -35, -62, -67, -67, -82, -70, -80, + -75, -59, -34, -3, 9, 48, 76, 101, 120, 120, 123, + 126, 131, 112, 92, 77, 61, 54, 32, 3, -18, -28, + -39, -56, -71, -91, -92, -100, -124, -134, -142, -144, -155, + -177, -178, -175, -171, -168, -160, -141, -123, -89, -73, -64, + -46, -39, -18, -19, -34, -32, -46, -51, -63, -74, -73, + -81, -70, -83, -71, -49, -39, -12, -1, 30, 48, 65, + 94, 100, 125, 136, 148, 156, 138, 140, 124, 115, 86, + 58, 57, 32, 43, 40, 44, 63, 60, 83, 90, 99, + 115, 113, 135, 140, 148, 164, 172, 187, 182, 190, 183, + 171, 171, 146, 139, 121, 105, 94, 61, 46, 17, -6, + -34, -70, -89, -121, -138, -158, -178, -190, -206, -206, -210, + -214, -204, -196, -173, -154, -128, -97, -81, -58, -51, -46, + -38, -47, -49, -57, -58, -57, -59, -49, -58, -58, -54, + -60, -48, -65, -72, -72, -78, -70, -77, -73, -76, -79, + -76, -90, -90, -91, -88, -76, -67, -43, -16, 6, 27, + 39, 55, 69, 71, 74, 65, 56, 60, 47, 37, 27, + 8, -5, -29, -50, -71, -89, -96, -114, -111, -113, -115, + -105, -112, -90, -78, -68, -49, -46, -26, -14, 5, 18, + 10, 14, 3, 5, -9, -20, -15, -30, -26, -33, -31, + -23, -23, -12, -21, -20, -16, -23, -20, -13, -7, 6, + 28, 47, 69, 96, 115, 134, 147, 154, 166, 174, 186, + 196, 202, 204, 198, 193, 181, 164, 144, 125, 113, 102, + 96, 90, 92, 91, 96, 99, 99, 100, 99, 99, 93, + 94, 86, 68, 55, 44, 36, 22, 13, 15, 13, 15, + 21, 16, 11, 3, -15, -31, -50, -75, -105, -125, -145, + -154, -155, -164, -178, -189, -186, -177, -174, -169, -152, -134, + -114, -93, -65, -42, -23, -4, -1, 6, 6, 2, -4, + -18, -26, -25, -25, -23, -32, -31, -33, -39, -50, -68, + -69, -74, -79, -78, -83, -85, -85, -77, -71, -61, -42, + -27, -3, 28, 59, 95, 123, 146, 155, 160, 162, 144, + 130, 112, 94, 82, 67, 60, 46, 35, 35, 22, 4, + -14, -27, -35, -45, -52, -61, -62, -65, -68, -55, -52, + -43, -38, -34, -20, -8, 8, 18, 24, 34, 36, 37, + 42, 46, 51, 50, 58, 76, 75, 70, 67, 58, 53, + 48, 36, 23, 18, 10, 3, 9, 14, 24, 39, 43, + 53, 62, 63, 66, 62, 66, 64, 59, 51, 25, 19, + 6, -10, -19, -26, -35, -43, -44, -37, -47, -43, -50, + -54, -60, -69, -75, -84, -91, -93, -98, -96, -99, -91, + -87, -91, -88, -84, -80, -75, -61, -48, -44, -40, -37, + -34, -45, -52, -58, -72, -82, -84, -78, -68, -65, -63, + -51, -42, -27, -22, -13, -3, 8, 20, 26, 31, 31, + 37, 33, 29, 33, 31, 32, 31, 34, 44, 55, 68, + 74, 69, 75, 73, 72, 65, 63, 67, 70, 83, 81, + 81, 85, 84, 80, 75, 69, 53, 44, 36, 27, 20, + 11, 1, -4, -19, -26, -27, -25, -21, -14, -12, -12, + -14, -9, -21, -29, -40, -50, -50, -54, -46, -35, -17, + -4, -1, 7, 20, 28, 26, 22, 23, 21, 23, 18, + 13, 12, 7, 6, 3, 2, -1, -1, 4, 6, 17, + 29, 35, 34, 34, 32, 28, 33, 26, 22, 16, 16, + 22, 20, 13, -1, -1, -7, -15, -20, -30, -32, -38, + -39, -45, -45, -53, -63, -70, -83, -96, -107, -113, -122, + -122, -118, -114, -114, -113, -112, -111, -110, -107, -103, -102, + -94, -80, -71, -58, -52, -47, -40, -43, -47, -48, -50, + -39, -46, -44, -44, -44, -43, -45, -41, -40, -34, -32, + -23, -12, -6, -1, -1, 6, 12, 18, 20, 22, 32, + 48, 65, 80, 93, 109, 122, 128, 131, 135, 135, 129, + 126, 130, 127, 124, 125, 121, 122, 115, 118, 122, 128, + 137, 143, 143, 141, 142, 134, 131, 121, 109, 105, 97, + 93, 99, 96, 96, 94, 83, 84, 80, 77, 66, 59, + 46, 42, 44, 32, 28, 20, 12, 8, 4, 4, 5, + 3, -4, -7, -6, -14, -19, -24, -34, -40, -45, -52, + -61, -62, -60, -57, -57, -61, -63, -61, -65, -73, -81, + -89, -94, -93, -89, -87, -82, -82, -84, -81, -86, -82, + -84, -86, -90, -86, -83, -82, -81, -80, -80, -76, -75, + -76, -70, -69, -68, -61, -53, -50, -43, -38, -42, -43, + -41, -41, -39, -34, -27, -21, -16, -20, -22, -27, -36, + -39, -38, -40, -37, -35, -28, -14, -6, -3, -2, 2, + 4, 5, 15, 18, 25, 35, 36, 41, 45, 48, 52, + 54, 52, 50, 60, 67, 76, 85, 85, 90, 86, 83, + 84, 77, 77, 72, 77, 81, 89, 91, 93, 99, 101, + 102, 98, 94, 87, 77, 70, 69, 63, 62, 55, 59, + 58, 54, 51, 53, 57, 62, 65, 60, 54, 48, 45, + 40, 29, 17, 8, -3, -14, -17, -18, -20, -25, -34, + -40, -44, -53, -56, -63, -71, -71, -69, -66, -62, -66, + -67, -68, -71, -75, -79, -79, -73, -67, -60, -49, -46, + -45, -45, -46, -55, -64, -67, -72, -74, -70, -68, -67, + -69, -70, -64, -56, -55, -54, -51, -41, -30, -26, -28, + -29, -30, -28, -25, -27, -20, -12, -5, -2, 2, 3, + -3, 0, -7, -8, -14, -15, -9, -7, 4, 12, 24, + 36, 41, 52, 58, 59, 51, 45, 48, 44, 46, 43, + 40, 42, 47, 53, 52, 52, 63, 69, 74, 75, 80, + 78, 69, 68, 59, 60, 54, 54, 54, 58, 66, 71, + 78, 78, 75, 78, 72, 71, 61, 55, 53, 42, 36, + 31, 28, 29, 23, 19, 25, 27, 27, 23, 29, 29, + 20, 11, 5, -4, -10, -31, -38, -39, -36, -33, -27, + -17, -15, -14, -17, -13, -14, -25, -33, -44, -51, -61, + -63, -63, -65, -67, -66, -63, -59, -52, -48, -45, -44, + -50, -62, -74, -84, -89, -100, -101, -102, -96, -95, -85, + -76, -78, -72, -71, -66, -61, -63, -60, -62, -72, -69, + -69, -58, -56, -50, -37, -28, -17, -17, -16, -17, -18, + -18, -13, -7, -4, 6, 17, 23, 25, 28, 24, 21, + 17, 21, 27, 30, 33, 35, 46, 49, 48, 54, 56, + 57, 58, 60, 64, 62, 64, 66, 67, 64, 70, 77, + 83, 82, 84, 88, 89, 95, 86, 75, 64, 51, 36, + 29, 26, 21, 26, 31, 38, 40, 55, 63, 65, 65, + 64, 60, 54, 54, 49, 41, 34, 26, 21, 9, 6, + 6, 5, -1, 3, 5, 3, 2, -4, -13, -13, -24, + -32, -33, -36, -33, -24, -18, -15, -9, -5, -5, -14, + -17, -24, -34, -36, -42, -43, -36, -42, -43, -43, -38, + -36, -27, -20, -23, -21, -28, -25, -22, -24, -25, -23, + -22, -30, -31, -26, -25, -20, -15, -8, -10, -11, -13, + -18, -22, -30, -36, -35, -39, -35, -34, -27, -24, -19, + -15, -7, -6, -7, -2, 0, 7, 12, 14, 19, 20, + 26, 26, 24, 16, 10, 4, 1, 3, 2, 9, 11, + 17, 19, 27, 31, 31, 32, 30, 27, 25, 28, 27, + 25, 22, 23, 23, 20, 21, 25, 36, 38, 40, 43, + 40, 32, 27, 20, 9, 4, 1, 12, 27, 37, 49, + 63, 73, 72, 73, 70, 67, 53, 39, 33, 26, 23, + 13, 9, 6, 0, -2, -3, 0, -1, 0, -1, -4, + -9, -16, -22, -21, -24, -21, -19, -12, -3, 0, 12, + 14, 13, 3, -6, -13, -27, -34, -42, -41, -44, -42, + -43, -46, -42, -40, -39, -36, -31, -29, -30, -22, -19, + -21, -20, -17, -17, -22, -31, -41, -45, -54, -65, -64, + -68, -70, -74, -70, -64, -62, -61, -60, -58, -52, -46, + -43, -37, -35, -40, -41, -47, -52, -58, -62, -61, -53, + -54, -46, -41, -40, -34, -29, -20, -15, -8, 2, 12, + 28, 35, 41, 42, 42, 43, 41, 43, 39, 45, 44, + 46, 55, 54, 55, 55, 51, 48, 42, 43, 39, 40, + 46, 54, 65, 70, 76, 81, 86, 89, 79, 73, 70, + 62, 56, 52, 39, 32, 28, 17, 18, 19, 18, 15, + 19, 20, 15, 13, 13, 10, 6, 5, 12, 10, 15, + 20, 24, 30, 31, 28, 22, 17, 2, -15, -24, -39, + -52, -53, -55, -46, -40, -34, -26, -21, -22, -31, -32, + -38, -36, -35, -32, -33, -34, -30, -28, -27, -35, -40, + -42, -45, -44, -45, -44, -52, -54, -57, -57, -53, -60, + -63, -63, -65, -51, -45, -40, -40, -39, -39, -43, -44, + -46, -52, -46, -51, -49, -45, -45, -47, -47, -45, -50, + -47, -40, -35, -32, -24, -17, -19, -14, -13, -9, -7, + -7, -7, -9, 0, 3, 7, 13, 12, 14, 15, 13, + 6, -1, -3, -9, -10, -5, -2, 6, 9, 11, 12, + 15, 19, 24, 37, 47, 47, 56, 53, 51, 52, 52, + 47, 39, 38, 40, 41, 43, 44, 42, 43, 42, 41, + 43, 40, 41, 35, 37, 39, 40, 41, 38, 30, 21, + 14, 5, 2, -1, -2, 1, -2, 6, 2, 4, 2, + -1, -11, -16, -23, -25, -20, -18, -25, -27, -32, -27, + -24, -16, -15, -11, -9, -3, -4, -2, -9, -10, -18, + -28, -33, -38, -37, -41, -41, -33, -24, -22, -25, -25, + -25, -24, -33, -38, -42, -52, -57, -55, -50, -51, -53, + -52, -48, -49, -49, -53, -55, -58, -51, -34, -19, -12, + -12, -5, 1, 1, 0, -6, -2, -10, -11, -11, -6, + 0, -6, 2, -2, -6, 2, 5, 16, 18, 18, 21, + 16, 18, 18, 20, 20, 13, 18, 9, 7, 12, 7, + 8, 10, 16, 17, 18, 23, 26, 36, 44, 51, 55, + 60, 64, 69, 68, 71, 70, 62, 58, 52, 44, 35, + 31, 34, 32, 33, 36, 37, 38, 41, 47, 55, 56, + 58, 60, 60, 57, 48, 41, 29, 19, 7, 4, 8, + 9, 10, 8, 13, 15, 13, 8, 8, 6, 4, 10, + 8, -4, -6, -9, -20, -28, -39, -38, -27, -24, -22, + -19, -23, -32, -35, -36, -41, -48, -51, -50, -52, -55, + -60, -67, -72, -76, -84, -82, -80, -81, -75, -64, -50, + -36, -28, -18, -14, -12, -15, -12, -18, -24, -21, -22, + -19, -21, -19, -22, -20, -18, -16, -17, -19, -15, -7, + 1, 0, 0, 9, 14, 20, 24, 20, 16, 17, 20, + 20, 25, 27, 26, 32, 33, 35, 38, 42, 38, 37, + 39, 46, 44, 43, 45, 45, 42, 37, 34, 25, 21, + 22, 33, 44, 49, 54, 53, 58, 54, 51, 46, 40, + 37, 37, 39, 34, 37, 39, 31, 39, 38, 36, 35, + 32, 33, 33, 32, 28, 23, 18, 22, 28, 31, 27, + 18, 3, 4, 0, -4, -7, -15, -18, -24, -32, -34, + -39, -42, -36, -31, -24, -12, -10, -10, -13, -20, -28, + -34, -44, -49, -50, -53, -56, -54, -52, -53, -47, -43, + -41, -45, -41, -38, -38, -33, -32, -34, -35, -33, -40, + -45, -53, -62, -61, -67, -72, -70, -67, -68, -59, -51, + -47, -38, -31, -20, -13, -13, -13, -14, -17, -21, -22, + -29, -31, -27, -23, -13, -6, 4, 12, 17, 25, 23, + 23, 25, 30, 30, 32, 31, 28, 27, 18, 14, 13, + 3, 5, 7, 19, 35, 47, 61, 70, 84, 90, 95, + 92, 94, 89, 77, 71, 66, 59, 50, 51, 50, 51, + 53, 56, 65, 67, 69, 75, 74, 69, 67, 56, 51, + 44, 34, 25, 17, 10, 6, 7, 7, 4, 6, -1, + -1, -2, -9, -9, -9, -7, -5, 1, -2, -5, -11, + -19, -27, -39, -38, -44, -45, -48, -48, -54, -59, -53, + -51, -49, -52, -50, -50, -47, -42, -32, -28, -28, -26, + -27, -34, -40, -40, -36, -37, -37, -34, -37, -36, -41, + -36, -40, -46, -48, -52, -47, -44, -40, -40, -38, -43, + -43, -47, -59, -62, -59, -59, -51, -41, -29, -19, -8, + -2, 1, 1, -4, -9, -19, -23, -29, -29, -25, -23, + -15, -7, -2, 6, 8, 15, 27, 35, 43, 40, 36, + 35, 32, 25, 22, 19, 17, 13, 13, 21, 25, 28, + 36, 44, 50, 57, 56, 58, 59, 62, 66, 70, 73, + 69, 66, 66, 66, 62, 53, 48, 44, 38, 39, 44, + 52, 51, 55, 57, 52, 49, 44, 36, 26, 16, 13, + 13, 14, 14, 17, 14, 10, 6, -5, -14, -23, -24, + -21, -28, -25, -27, -29, -29, -33, -33, -39, -42, -43, + -41, -40, -43, -46, -45, -43, -42, -41, -41, -46, -46, + -52, -52, -52, -59, -63, -70, -68, -73, -77, -73, -68, + -66, -62, -64, -66, -58, -54, -51, -52, -48, -47, -43, + -40, -39, -33, -26, -19, -17, -16, -17, -14, -9, -10, + -3, 5, 5, 9, 5, 9, 8, 4, 3, 0, -5, + -10, -3, 2, 8, 14, 16, 20, 27, 39, 40, 44, + 48, 43, 39, 34, 29, 22, 12, 8, 5, 0, -2, + -3, 5, 12, 16, 19, 22, 25, 28, 35, 28, 30, + 31, 30, 39, 43, 47, 43, 42, 41, 41, 41, 37, + 37, 39, 37, 38, 43, 44, 41, 43, 34, 28, 25, + 23, 30, 34, 32, 33, 29, 21, 18, 13, 14, 11, + 3, 2, 1, 3, 1, -1, 0, -3, -1, -3, -8, + -9, -7, -9, -2, 0, -3, 0, 1, 5, 0, -1, + -9, -13, -8, -11, -18, -23, -25, -29, -29, -26, -27, + -29, -25, -24, -23, -18, -19, -18, -17, -21, -22, -30, + -38, -42, -42, -42, -40, -41, -43, -39, -38, -37, -36, + -33, -31, -28, -27, -18, -15, -7, -8, -8, -1, 1, + 3, -5, 0, -4, -5, -4, -8, -10, -14, -21, -24, + -25, -20, -11, -4, 3, 6, 13, 15, 12, 17, 16, + 17, 17, 15, 21, 28, 33, 36, 35, 35, 29, 31, + 29, 28, 23, 21, 14, 15, 27, 36, 40, 40, 43, + 51, 56, 62, 69, 77, 80, 88, 88, 88, 82, 76, + 63, 52, 44, 36, 26, 23, 25, 24, 27, 26, 31, + 21, 13, 8, -8, -8, -11, -14, -18, -28, -28, -30, + -32, -29, -26, -26, -27, -24, -20, -14, -8, -6, -8, + -5, -10, -14, -18, -26, -34, -36, -38, -44, -51, -57, + -66, -64, -68, -72, -75, -75, -70, -68, -65, -64, -62, + -68, -63, -60, -65, -65, -69, -68, -67, -57, -46, -41, + -38, -34, -31, -39, -40, -45, -45, -48, -47, -40, -39, + -32, -26, -24, -14, -9, -7, -3, -2, 3, 4, 0, + -2, -2, -2, 1, 3, 2, 3, 8, 13, 20, 25, + 29, 31, 26, 17, 11, 3, -5, 2, 6, 9, 11, + 19, 26, 40, 51, 61, 60, 58, 61, 55, 55, 57, + 60, 54, 40, 42, 38, 34, 38, 37, 34, 32, 35, + 36, 35, 41, 36, 32, 29, 23, 22, 23, 22, 14, + 13, 19, 19, 20, 22, 22, 17, 13, 6, 9, 13, + 15, 17, 19, 11, 15, 8, 4, 6, -1, -3, 3, + 7, 11, 8, 10, 7, 6, 4, -4, -5, -11, -9, + -16, -14, -14, -16, -16, -22, -19, -19, -13, -9, -4, + 1, 1, 2, -6, -14, -25, -32, -41, -46, -50, -49, + -42, -39, -34, -24, -14, -18, -15, -17, -21, -23, -21, + -19, -21, -20, -19, -20, -19, -16, -17, -19, -20, -20, + -20, -20, -22, -22, -23, -22, -22, -14, -5, 5, 8, + 13, 16, 19, 23, 19, 21, 16, 16, 18, 13, 18, + 13, 15, 18, 12, 12, 6, 11, 8, 5, 5, 9, + 17, 14, 15, 14, 16, 14, 14, 12, 9, 7, 9, + 11, 13, 15, 15, 19, 17, 14, 8, 7, 4, 0, + 3, 8, 10, 7, 8, 19, 15, 19, 18, 19, 17, + 9, 14, 10, 4, -3, -11, -19, -25, -31, -35, -36, + -28, -21, -8, 5, 8, 11, 13, 7, 4, 1, -7, + -15, -17, -17, -21, -28, -33, -37, -40, -39, -41, -45, + -46, -44, -40, -41, -36, -31, -41, -40, -42, -44, -47, + -50, -49, -55, -52, -52, -52, -45, -50, -52, -56, -58, + -60, -69, -75, -82, -86, -91, -87, -80, -80, -72, -58, + -52, -45, -33, -21, -13, -12, -10, -6, -1, -2, -7, + -7, -5, -6, -3, 9, 15, 25, 36, 35, 39, 28, + 16, 11, 8, 11, 17, 27, 34, 36, 47, 49, 52, + 52, 42, 46, 49, 55, 65, 66, 67, 62, 56, 53, + 49, 50, 55, 53, 62, 69, 72, 73, 68, 61, 54, + 46, 43, 38, 34, 39, 43, 42, 39, 36, 31, 26, + 24, 17, 13, 14, 14, 21, 26, 29, 28, 26, 24, + 18, 19, 16, 11, 6, 2, -2, 1, 3, 2, -4, + -3, -1, -3, -2, -2, -5, -3, 0, 3, -3, -6, + -6, -15, -19, -25, -30, -35, -39, -34, -34, -34, -31, + -17, -17, -8, -2, -2, 8, 14, 25, 24, 26, 22, + 16, 10, 2, -3, -5, -12, -15, -11, -14, -16, -17, + -17, -16, -21, -18, -18, -21, -23, -21, -15, -11, -4, + -2, 3, 8, 10, 17, 18, 25, 24, 24, 24, 21, + 24, 23, 24, 22, 23, 31, 39, 49, 58, 64, 67, + 63, 57, 53, 52, 44, 45, 43, 40, 45, 42, 49, + 50, 49, 52, 51, 48, 46, 38, 37, 35, 36, 37, + 37, 37, 44, 45, 47, 42, 42, 36, 35, 44, 40, + 40, 28, 24, 23, 18, 12, 9, 8, 10, 17, 17, + 18, 12, 5, -2, -12, -16, -20, -27, -29, -29, -26, + -22, -17, -16, -15, -14, -15, -11, -11, -15, -19, -15, + -20, -22, -24, -37, -52, -62, -63, -68, -64, -59, -51, + -43, -42, -36, -32, -33, -33, -33, -41, -48, -51, -49, + -48, -47, -42, -45, -42, -41, -40, -39, -33, -29, -25, + -14, -1, -4, -6, -11, -16, -19, -26, -29, -28, -25, + -17, -10, -1, -1, 3, 7, -1, -3, -8, -18, -20, + -20, -16, -13, -11, -8, 0, 6, 8, 11, 14, 15, + 20, 26, 26, 26, 24, 23, 24, 30, 34, 41, 52, + 61, 70, 80, 85, 86, 89, 84, 87, 79, 67, 60, + 57, 59, 63, 68, 74, 78, 84, 89, 91, 87, 81, + 74, 69, 63, 59, 59, 56, 58, 60, 60, 59, 54, + 49, 41, 40, 34, 25, 19, 11, 1, 0, -1, -4, + -8, -12, -12, -17, -22, -31, -44, -54, -58, -68, -74, + -80, -80, -73, -65, -61, -61, -55, -50, -50, -59, -65, + -69, -73, -73, -78, -79, -83, -87, -87, -88, -94, -103, + -107, -107, -109, -106, -113, -115, -110, -105, -100, -100, -92, + -78, -62, -49, -39, -35, -27, -26, -25, -24, -22, -23, + -28, -26, -22, -15, -11, -4, 4, 13, 21, 32, 31, + 28, 30, 30, 28, 23, 25, 23, 21, 25, 21, 26, + 27, 32, 40, 48, 53, 55, 54, 55, 55, 54, 48, + 44, 47, 48, 54, 60, 71, 79, 79, 74, 72, 59, + 48, 42, 32, 26, 22, 21, 23, 22, 31, 42, 44, + 41, 36, 30, 30, 33, 38, 35, 30, 28, 20, 15, + 8, 4, 6, 9, 16, 26, 27, 23, 19, 16, 10, + 4, -4, -12, -12, -16, -16, -19, -24, -23, -23, -31, + -34, -38, -40, -41, -39, -39, -36, -36, -40, -45, -48, + -53, -66, -73, -76, -76, -78, -75, -71, -65, -59, -58, + -59, -56, -60, -62, -62, -62, -64, -68, -73, -79, -80, + -85, -87, -85, -78, -72, -66, -56, -48, -42, -37, -35, + -32, -33, -31, -25, -26, -27, -16, -18, -18, -13, -14, + -17, -22, -24, -25, -23, -19, -14, -12, -11, -7, -4, + -1, 2, 5, 8, 10, 10, 18, 28, 29, 25, 22, + 29, 21, 20, 21, 22, 30, 32, 41, 41, 45, 46, + 49, 52, 57, 59, 58, 52, 46, 47, 56, 58, 49, + 49, 46, 40, 33, 23, 14, 11, 16, 29, 34, 37, + 41, 42, 48, 54, 60, 61, 62, 62, 69, 79, 76, + 71, 72, 71, 64, 59, 54, 49, 40, 42, 34, 23, + 27, 18, 13, 9, 3, -4, -8, -16, -18, -20, -26, + -28, -30, -32, -29, -32, -35, -39, -41, -38, -34, -31, + -26, -18, -21, -20, -22, -28, -35, -34, -31, -33, -31, + -31, -40, -43, -45, -53, -64, -67, -74, -75, -74, -75, + -70, -61, -56, -45, -37, -30, -33, -35, -32, -31, -27, + -25, -19, -17, -14, -9, -4, -1, -3, -4, 1, 8, + 14, 20, 24, 25, 18, 11, 7, -3, -9, -3, 4, + 15, 30, 29, 33, 33, 36, 35, 31, 33, 34, 42, + 43, 42, 47, 49, 53, 61, 69, 73, 74, 79, 81, + 84, 76, 69, 62, 47, 39, 31, 19, 8, 2, -6, + -5, -3, -3, -1, 1, -2, -3, -3, -6, -12, -13, + -15, -11, -5, -4, -8, -14, -9, -3, 0, -3, -4, + 0, 3, 0, -6, -14, -23, -33, -38, -41, -38, -38, + -34, -30, -29, -29, -26, -31, -33, -41, -49, -50, -56, + -57, -58, -54, -46, -39, -39, -34, -31, -28, -30, -30, + -31, -29, -27, -16, -18, -17, -15, -13, -15, -12, -7, + -11, -9, -9, -4, -11, -7, -7, -8, -9, -10, -7, + -9, 1, 9, 15, 12, 19, 19, 18, 17, 13, 11, + 8, 6, 10, 17, 20, 26, 28, 33, 39, 30, 25, + 25, 18, 16, 21, 26, 30, 33, 32, 36, 42, 49, + 46, 39, 44, 44, 37, 35, 30, 24, 22, 23, 26, + 23, 25, 21, 24, 24, 22, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.h new file mode 100644 index 00000000000..4cc8030cdac --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/no_1000ms_sample_data.h @@ -0,0 +1,29 @@ +/* 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 data was created from the PCM data in a WAV file held in v2 of the +// Speech Commands test dataset, at the path: +// speech_commands_test_set_v0.02/no/f9643d42_nohash_4.wav +// This should contain all 16,000 samples from the one-second file. + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_1000MS_SAMPLE_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_1000MS_SAMPLE_DATA_H_ + +#include + +extern const int g_no_1000ms_sample_data_size; +extern const int16_t g_no_1000ms_sample_data[]; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_1000MS_SAMPLE_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/osx/audio_provider.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/osx/audio_provider.cc index 892757e799f..6468c1a95a9 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/osx/audio_provider.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/osx/audio_provider.cc @@ -17,7 +17,7 @@ limitations under the License. #include -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.h" namespace { diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.cc index 9366dc71e0d..1ba331d2704 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.cc @@ -28,7 +28,7 @@ RecognizeCommands::RecognizeCommands(tflite::ErrorReporter* error_reporter, suppression_ms_(suppression_ms), minimum_count_(minimum_count), previous_results_(error_reporter) { - previous_top_label_ = "_silence_"; + previous_top_label_ = "silence"; previous_top_label_time_ = 0; } diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.h b/tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.h index adefffe8500..fdbff065083 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/recognize_commands.h @@ -19,7 +19,7 @@ limitations under the License. #include #include "tensorflow/lite/c/c_api_internal.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/micro_model_settings.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" // Partial implementation of std::dequeue, just providing the functionality @@ -129,8 +129,8 @@ class RecognizeCommands { // help reduce spurious recognitions. explicit RecognizeCommands(tflite::ErrorReporter* error_reporter, int32_t average_window_duration_ms = 1000, - uint8_t detection_threshold = 51, - int32_t suppression_ms = 500, + 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. diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/CMSIS/simple_features_generator.cc similarity index 85% rename from tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/CMSIS/simple_features_generator.cc index 78155cc2bab..403976e222f 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/CMSIS/simple_features_generator.cc @@ -13,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.h" + extern "C" { #define IFFT_FLAG_R 0 #define BIT_REVERSE_FLAG 1 @@ -23,8 +25,6 @@ extern "C" { #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h" } -#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" - void quantize(q15_t* bufA, q15_t* bufB, uint8_t* output); q15_t bufA[FFT_SIZE]; @@ -41,9 +41,9 @@ constexpr int kOutputSize = ((kInputSize / 2) + (kAverageWindowSize - 1)) / kAverageWindowSize; } // namespace -TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, - const int16_t* input, int input_size, int output_size, - uint8_t* output) { +TfLiteStatus GenerateSimpleFeatures(tflite::ErrorReporter* error_reporter, + const int16_t* input, int input_size, + int output_size, uint8_t* output) { if (input_size > kInputSize) { error_reporter->Report("Input size %d larger than %d", input_size, kInputSize); @@ -93,12 +93,3 @@ void quantize(q15_t* bufA, q15_t* bufB, uint8_t* output) { output[i] = (uint8_t)(bufA[i] >> 5); } } - -TfLiteStatus Preprocess_1sec(tflite::ErrorReporter* error_reporter, - const int16_t* input, uint8_t* output) { - int i; - for (i = 0; i < 49; i++) { - Preprocess(error_reporter, input + i * 320, 480, 43, output + i * 43); - } - return kTfLiteOk; -} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/fixed_point/simple_features_generator.cc similarity index 96% rename from tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/fixed_point/simple_features_generator.cc index b623d8d11b7..ad11684b0a9 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/fixed_point/simple_features_generator.cc @@ -27,11 +27,11 @@ limitations under the License. // instead of floating point, to help show how this can work on platforms that // don't have good float support. -#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.h" #include -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.h" namespace { @@ -118,9 +118,9 @@ void CalculatePeriodicHann(int window_length, int16_t* window_function) { } // namespace -TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, - const int16_t* input, int input_size, int output_size, - uint8_t* output) { +TfLiteStatus GenerateSimpleFeatures(tflite::ErrorReporter* error_reporter, + const int16_t* input, int input_size, + int output_size, uint8_t* output) { // Ensure our input and output data arrays are valid. if (input_size > kMaxAudioSampleSize) { error_reporter->Report("Input size %d larger than %d", input_size, diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.cc similarity index 95% rename from tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.cc index c4fc5c33bb3..0b20f2f86fb 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.cc @@ -15,7 +15,7 @@ limitations under the License. // See the header for documentation on the meaning of this data. -#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.h" const uint8_t g_no_power_spectrum_data[g_no_power_spectrum_data_size] = { 255, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.h similarity index 90% rename from tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.h rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.h index fa39d3c70d7..9693950fb5e 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.h @@ -18,12 +18,12 @@ limitations under the License. // This is the expected result of running the sample data in // no_30ms_sample_data.cc through through the preprocessing pipeline. -#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_POWER_SPECTRUM_DATA_H_ -#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_POWER_SPECTRUM_DATA_H_ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_NO_POWER_SPECTRUM_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_NO_POWER_SPECTRUM_DATA_H_ #include constexpr int g_no_power_spectrum_data_size = 43; extern const uint8_t g_no_power_spectrum_data[]; -#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_POWER_SPECTRUM_DATA_H_ +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_NO_POWER_SPECTRUM_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_simple_features_data.cc similarity index 97% rename from tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_simple_features_data.cc index e98c84f7ed2..3d3a9538fb5 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_simple_features_data.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_simple_features_data.h" /* File automatically created by * tensorflow/examples/speech_commands/wav_to_features.py \ @@ -22,15 +22,15 @@ limitations under the License. * --window_size_ms=30 \ * --window_stride_ms=20 \ * --feature_bin_count=40 \ - * --quantize \ + * --quantize=1 \ * --preprocess="average" \ * --input_wav="speech_commands_test_set_v0.02/no/f9643d42_nohash_4.wav" \ - * --output_c_file="no_features_data.cc" \ + * --output_c_file="no_simple_features_data.cc" \ */ -const int g_no_f9643d42_nohash_4_width = 43; -const int g_no_f9643d42_nohash_4_height = 49; -const unsigned char g_no_f9643d42_nohash_4_data[] = { +const int g_no_simple_f9643d42_nohash_4_width = 43; +const int g_no_simple_f9643d42_nohash_4_height = 49; +const unsigned char g_no_simple_f9643d42_nohash_4_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_simple_features_data.h similarity index 73% rename from tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.h rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_simple_features_data.h index e2ee0c46cf1..30332b30c5c 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_simple_features_data.h @@ -13,11 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_FEATURES_DATA_H_ -#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_FEATURES_DATA_H_ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_NO_SIMPLE_FEATURES_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_NO_SIMPLE_FEATURES_DATA_H_ -extern const int g_no_f9643d42_nohash_4_width; -extern const int g_no_f9643d42_nohash_4_height; -extern const unsigned char g_no_f9643d42_nohash_4_data[]; +extern const int g_no_simple_f9643d42_nohash_4_width; +extern const int g_no_simple_f9643d42_nohash_4_height; +extern const unsigned char g_no_simple_f9643d42_nohash_4_data[]; -#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_FEATURES_DATA_H_ +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_NO_SIMPLE_FEATURES_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.cc similarity index 92% rename from tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.cc index f8858aad72f..3aa05b7bf1d 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.cc @@ -24,11 +24,11 @@ limitations under the License. // functions used here, for example replacing the DFT with an FFT, so this // version shouldn't be used where performance is critical. -#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.h" #include -#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.h" namespace { @@ -72,9 +72,9 @@ void CalculatePeriodicHann(int window_length, float* window_function) { } // namespace -TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, - const int16_t* input, int input_size, int output_size, - uint8_t* output) { +TfLiteStatus GenerateSimpleFeatures(tflite::ErrorReporter* error_reporter, + const int16_t* input, int input_size, + int output_size, uint8_t* output) { // Ensure our input and output data arrays are valid. if (input_size > kMaxAudioSampleSize) { error_reporter->Report("Input size %d larger than %d", input_size, @@ -146,12 +146,3 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, } return kTfLiteOk; } - -TfLiteStatus Preprocess_1sec(tflite::ErrorReporter* error_reporter, - const int16_t* input, uint8_t* output) { - int i; - for (i = 0; i < 49; i++) { - Preprocess(error_reporter, input + i * 320, 480, 43, output + i * 43); - } - return kTfLiteOk; -} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.h similarity index 77% rename from tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.h index d710beeceea..f4e86b18a4c 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.h @@ -13,8 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ -#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_SIMPLE_FEATURES_GENERATOR_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_SIMPLE_FEATURES_GENERATOR_H_ #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" @@ -24,11 +24,8 @@ limitations under the License. // both floating point and fixed point available, but because the calculations // involved can be time-consuming, it's recommended that you use or write // specialized versions for your platform. -TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, - const int16_t* input, int input_size, int output_size, - uint8_t* output); +TfLiteStatus GenerateSimpleFeatures(tflite::ErrorReporter* error_reporter, + const int16_t* input, int input_size, + int output_size, uint8_t* output); -TfLiteStatus Preprocess_1sec(tflite::ErrorReporter* error_reporter, - const int16_t* input, uint8_t* output); - -#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_SIMPLE_FEATURES_GENERATOR_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator_test.cc similarity index 90% rename from tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator_test.cc index e8b49f67e3d..65e526327c7 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator_test.cc @@ -13,23 +13,23 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_features_generator.h" #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/no_power_spectrum_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.h" #include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/testing/micro_test.h" TF_LITE_MICRO_TESTS_BEGIN -TF_LITE_MICRO_TEST(TestPreprocessor) { +TF_LITE_MICRO_TEST(TestSimpleFeaturesGenerator) { tflite::MicroErrorReporter micro_error_reporter; tflite::ErrorReporter* error_reporter = µ_error_reporter; uint8_t yes_calculated_data[g_yes_power_spectrum_data_size]; - TfLiteStatus yes_status = Preprocess( + TfLiteStatus yes_status = GenerateSimpleFeatures( error_reporter, g_yes_30ms_sample_data, g_yes_30ms_sample_data_size, g_yes_power_spectrum_data_size, yes_calculated_data); TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, yes_status); @@ -45,7 +45,7 @@ TF_LITE_MICRO_TEST(TestPreprocessor) { } uint8_t no_calculated_data[g_yes_power_spectrum_data_size]; - TfLiteStatus no_status = Preprocess( + TfLiteStatus no_status = GenerateSimpleFeatures( error_reporter, g_no_30ms_sample_data, g_no_30ms_sample_data_size, g_no_power_spectrum_data_size, no_calculated_data); TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, no_status); diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.cc new file mode 100644 index 00000000000..4842f8dbd90 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.cc @@ -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 "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.h" + +const char* kCategoryLabels[kCategoryCount] = { + "silence", + "unknown", + "yes", + "no", +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.h similarity index 93% rename from tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.h index f48252d14d2..d31d6b33622 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/simple_model_settings.h @@ -13,8 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MODEL_SETTINGS_H_ -#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MODEL_SETTINGS_H_ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_SIMPLE_MODEL_SETTINGS_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_SIMPLE_MODEL_SETTINGS_H_ // Keeping these as constant expressions allow us to allocate fixed-sized arrays // on the stack for our working memory. @@ -40,4 +40,4 @@ constexpr int kSilenceIndex = 0; constexpr int kUnknownIndex = 1; extern const char* kCategoryLabels[kCategoryCount]; -#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MODEL_SETTINGS_H_ +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_SIMPLE_MODEL_SETTINGS_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/tiny_conv_simple_features_model_data.cc similarity index 99% rename from tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/tiny_conv_simple_features_model_data.cc index 62e4359859a..a14412edc94 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/tiny_conv_simple_features_model_data.cc @@ -14,12 +14,12 @@ limitations under the License. ==============================================================================*/ // Automatically created from a TensorFlow Lite flatbuffer using the command: -// xxd -i tiny_conv.tflite > tiny_conv_model_data.cc +// xxd -i tiny_conv.tflite > tiny_conv_simple_features_model_data.cc // See the README for a full description of the creation process. -#include "tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/tiny_conv_simple_features_model_data.h" -const unsigned char g_tiny_conv_model_data[] = { +const unsigned char g_tiny_conv_simple_features_model_data[] = { 0x18, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x4d, 0x00, 0x00, @@ -1670,4 +1670,4 @@ const unsigned char g_tiny_conv_model_data[] = { 0x04, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xff, 0xff, 0x00, 0x19, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}; -const int g_tiny_conv_model_data_len = 19800; +const int g_tiny_conv_simple_features_model_data_len = 19800; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/tiny_conv_simple_features_model_data.h similarity index 74% rename from tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/tiny_conv_simple_features_model_data.h index a465dbfabf7..cadf7d0de75 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/tiny_conv_simple_features_model_data.h @@ -16,12 +16,12 @@ 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 tiny_conv.tflite > tiny_conv_model_data.cc +// xxd -i tiny_conv.tflite > tiny_conv_simple_features_model_data.cc -#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_TINY_CONV_MODEL_DATA_H_ -#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_TINY_CONV_MODEL_DATA_H_ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_TINY_CONV_SIMPLE_FEATURES_MODEL_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_TINY_CONV_SIMPLE_FEATURES_MODEL_DATA_H_ -extern const unsigned char g_tiny_conv_model_data[]; -extern const int g_tiny_conv_model_data_len; +extern const unsigned char g_tiny_conv_simple_features_model_data[]; +extern const int g_tiny_conv_simple_features_model_data_len; -#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_TINY_CONV_MODEL_DATA_H_ +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_TINY_CONV_SIMPLE_FEATURES_MODEL_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.cc similarity index 95% rename from tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.cc index 9a34a2045a2..cd46408c0fb 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.cc @@ -15,7 +15,7 @@ limitations under the License. // See the header for documentation on the meaning of this data. -#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.h" const uint8_t g_yes_power_spectrum_data[g_yes_power_spectrum_data_size] = { 8, 89, 8, 0, 0, 0, 0, 0, 0, 0, 0, 4, 13, 1, 6, 23, 20, 6, 4, 0, 0, 0, diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.h similarity index 90% rename from tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.h rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.h index 5c8c00ac111..77e52d58b54 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_power_spectrum_data.h @@ -18,12 +18,12 @@ limitations under the License. // This is the expected result of running the sample data in // yes_30ms_sample_data.cc through through the preprocessing pipeline. -#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_POWER_SPECTRUM_DATA_H_ -#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_POWER_SPECTRUM_DATA_H_ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_YES_POWER_SPECTRUM_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_YES_POWER_SPECTRUM_DATA_H_ #include constexpr int g_yes_power_spectrum_data_size = 43; extern const uint8_t g_yes_power_spectrum_data[]; -#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_POWER_SPECTRUM_DATA_H_ +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_YES_POWER_SPECTRUM_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_simple_features_data.cc similarity index 97% rename from tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_simple_features_data.cc index 2eb737fb8e1..2d660bb8b5c 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_simple_features_data.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_simple_features_data.h" /* File automatically created by * tensorflow/examples/speech_commands/wav_to_features.py \ @@ -22,15 +22,15 @@ limitations under the License. * --window_size_ms=30 \ * --window_stride_ms=20 \ * --feature_bin_count=40 \ - * --quantize \ + * --quantize=1 \ * --preprocess="average" \ * --input_wav="speech_commands_test_set_v0.02/yes/f2e59fea_nohash_1.wav" \ - * --output_c_file="yes_features_data.cc" \ + * --output_c_file="yes_simple_features_data.cc" \ */ -const int g_yes_f2e59fea_nohash_1_width = 43; -const int g_yes_f2e59fea_nohash_1_height = 49; -const unsigned char g_yes_f2e59fea_nohash_1_data[] = { +const int g_yes_simple_f2e59fea_nohash_1_width = 43; +const int g_yes_simple_f2e59fea_nohash_1_height = 49; +const unsigned char g_yes_simple_f2e59fea_nohash_1_data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_simple_features_data.h similarity index 73% rename from tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.h rename to tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_simple_features_data.h index 39a3bb914cc..87ea4a4aea8 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/simple_features/yes_simple_features_data.h @@ -13,11 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_FEATURES_DATA_H_ -#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_FEATURES_DATA_H_ +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_YES_SIMPLE_FEATURES_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_YES_SIMPLE_FEATURES_DATA_H_ -extern const int g_yes_f2e59fea_nohash_1_width; -extern const int g_yes_f2e59fea_nohash_1_height; -extern const unsigned char g_yes_f2e59fea_nohash_1_data[]; +extern const int g_yes_simple_f2e59fea_nohash_1_width; +extern const int g_yes_simple_f2e59fea_nohash_1_height; +extern const unsigned char g_yes_simple_f2e59fea_nohash_1_data[]; -#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_FEATURES_DATA_H_ +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIMPLE_FEATURES_YES_SIMPLE_FEATURES_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.cc new file mode 100644 index 00000000000..e5f6ceb3f0b --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.cc @@ -0,0 +1,1800 @@ +/* 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. +==============================================================================*/ + +// See the header for documentation on the meaning of this data. + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.h" + +const int g_yes_1000ms_sample_data_size = 16000; +const int16_t g_yes_1000ms_sample_data[16000] = { + -7, -12, -18, -20, -20, -21, -21, -25, -29, + -31, -31, -30, -30, -29, -30, -30, -29, -28, + -24, -22, -17, -12, -8, -7, -6, -1, 2, + 5, 7, 8, 11, 15, 18, 19, 23, 24, + 24, 27, 27, 26, 25, 28, 30, 32, 33, + 31, 29, 27, 28, 30, 28, 26, 26, 24, + 22, 17, 16, 15, 13, 10, 5, 0, -4, + -4, -7, -9, -12, -14, -14, -13, -11, -10, + -8, -6, -3, 3, 7, 8, 12, 15, 18, + 21, 19, 19, 21, 23, 24, 23, 22, 19, + 17, 11, 5, -3, -12, -22, -28, -35, -45, + -54, -62, -69, -76, -84, -92, -100, -109, -116, + -117, -120, -120, -120, -122, -124, -126, -123, -121, + -116, -113, -107, -97, -88, -75, -61, -50, -41, + -27, -12, 4, 21, 37, 58, 76, 93, 108, + 121, 137, 156, 172, 184, 196, 205, 215, 224, + 235, 242, 245, 242, 240, 238, 231, 223, 214, + 205, 195, 178, 158, 135, 112, 90, 69, 46, + 19, -11, -45, -76, -105, -133, -159, -186, -211, + -236, -260, -280, -294, -308, -320, -331, -336, -338, + -335, -326, -316, -301, -286, -267, -246, -225, -203, + -180, -154, -124, -91, -59, -34, -8, 19, 42, + 64, 87, 103, 119, 134, 148, 162, 174, 182, + 188, 190, 189, 187, 184, 180, 177, 171, 162, + 154, 144, 137, 129, 118, 106, 95, 81, 69, + 58, 48, 37, 26, 14, 3, -7, -22, -31, + -42, -52, -62, -69, -75, -79, -82, -87, -88, + -92, -94, -91, -87, -85, -81, -74, -70, -64, + -55, -47, -40, -33, -25, -19, -12, -6, -4, + -1, 1, 1, -2, -9, -15, -17, -18, -20, + -22, -22, -26, -31, -33, -35, -31, -26, -17, + -4, 8, 19, 31, 44, 54, 64, 71, 79, + 86, 92, 102, 109, 111, 109, 104, 96, 84, + 70, 60, 51, 38, 27, 13, 4, -3, -9, + -13, -18, -26, -33, -32, -27, -20, -10, -4, + 2, 6, 10, 14, 16, 21, 25, 29, 31, + 33, 35, 37, 33, 22, 15, 13, 11, 12, + 9, 5, 2, 1, -3, -9, -17, -27, -32, + -35, -36, -36, -42, -50, -56, -66, -77, -85, + -96, -100, -106, -113, -118, -121, -119, -117, -119, + -122, -124, -123, -112, -94, -77, -64, -51, -37, + -22, -3, 17, 37, 54, 68, 86, 100, 114, + 134, 154, 167, 174, 178, 182, 189, 189, 187, + 185, 179, 177, 174, 171, 157, 138, 123, 108, + 94, 76, 50, 25, 6, -8, -20, -37, -59, + -86, -110, -132, -147, -159, -169, -178, -191, -203, + -213, -217, -215, -208, -199, -194, -195, -190, -178, + -165, -155, -144, -134, -123, -103, -80, -56, -35, + -18, -4, 11, 23, 36, 50, 65, 78, 93, + 111, 122, 129, 132, 131, 127, 125, 126, 126, + 128, 127, 125, 122, 118, 111, 108, 104, 99, + 93, 89, 90, 87, 82, 78, 75, 68, 65, + 67, 69, 66, 61, 54, 39, 28, 15, 3, + -7, -18, -25, -29, -35, -42, -52, -66, -78, + -83, -85, -86, -86, -82, -83, -84, -83, -81, + -75, -62, -57, -53, -49, -46, -41, -34, -26, + -16, -10, -7, -2, 2, 6, 12, 15, 19, + 18, 15, 17, 21, 24, 30, 33, 27, 22, + 21, 20, 23, 24, 21, 15, 13, 8, 3, + 1, -1, -3, -4, -6, -9, -11, -11, -8, + -10, -13, -15, -19, -17, -11, -2, 1, 2, + 6, 9, 10, 12, 13, 9, 8, 10, 13, + 20, 18, 13, 10, 4, 1, -2, -6, -11, + -13, -16, -18, -15, -18, -21, -21, -22, -23, + -25, -23, -22, -20, -19, -16, -12, -10, -9, + -11, -15, -19, -22, -19, -14, -11, -9, -11, + -17, -20, -18, -19, -15, -11, -8, -2, 8, + 19, 30, 36, 37, 36, 38, 45, 57, 69, + 77, 81, 79, 75, 76, 74, 69, 66, 60, + 53, 45, 36, 28, 22, 17, 10, 0, -5, + -11, -15, -18, -26, -31, -33, -34, -34, -35, + -37, -37, -35, -28, -24, -29, -37, -45, -46, + -41, -36, -31, -32, -33, -37, -37, -36, -36, + -34, -27, -19, -14, -11, -8, -1, 6, 14, + 19, 21, 25, 30, 34, 38, 38, 33, 26, + 22, 19, 20, 18, 17, 15, 10, 2, -3, + -5, -10, -13, -13, -13, -16, -16, -16, -15, + -13, -14, -13, -16, -19, -20, -18, -17, -18, + -16, -16, -24, -28, -28, -28, -23, -21, -21, + -20, -24, -27, -23, -18, -14, -7, 4, 11, + 15, 19, 21, 25, 33, 39, 41, 45, 47, + 50, 56, 58, 57, 59, 59, 55, 50, 47, + 39, 34, 30, 24, 18, 11, 8, 3, 0, + -3, -8, -14, -15, -13, -13, -12, -14, -17, + -17, -12, -10, -4, -7, -12, -10, -14, -17, + -17, -19, -25, -28, -27, -29, -30, -31, -35, + -38, -43, -47, -51, -52, -50, -49, -48, -47, + -45, -39, -32, -30, -31, -35, -35, -31, -24, + -17, -12, -11, -14, -15, -17, -16, -9, -5, + -3, -1, 0, 1, 0, 3, 12, 21, 26, + 33, 35, 38, 45, 50, 53, 53, 54, 58, + 61, 64, 69, 67, 66, 64, 58, 54, 51, + 46, 44, 45, 41, 35, 31, 27, 25, 27, + 25, 20, 13, 12, 16, 17, 17, 12, 7, + 3, 2, -2, -4, -8, -14, -19, -25, -29, + -38, -49, -60, -69, -73, -71, -74, -82, -89, + -98, -103, -104, -103, -99, -98, -98, -98, -99, + -97, -94, -91, -85, -82, -78, -74, -74, -71, + -68, -61, -54, -52, -47, -41, -36, -32, -21, + -12, -3, 11, 26, 36, 44, 48, 55, 64, + 77, 92, 100, 108, 117, 120, 122, 128, 130, + 129, 130, 127, 124, 122, 121, 118, 114, 110, + 102, 92, 85, 80, 77, 68, 55, 46, 39, + 36, 34, 31, 27, 15, 5, -1, -5, -11, + -20, -29, -37, -43, -46, -47, -54, -61, -65, + -74, -82, -84, -91, -94, -96, -104, -109, -111, + -111, -112, -113, -111, -112, -110, -104, -99, -96, + -93, -89, -87, -81, -71, -63, -54, -45, -43, + -37, -30, -24, -17, -12, -8, -2, 2, 15, + 23, 28, 35, 41, 42, 44, 52, 58, 66, + 74, 78, 80, 82, 85, 88, 90, 92, 92, + 88, 87, 87, 79, 73, 69, 64, 62, 55, + 50, 45, 41, 36, 29, 24, 20, 16, 12, + 8, 5, 2, 1, 1, 0, 1, -4, -4, + -4, -4, -1, 1, 2, 1, -3, -6, -1, + 5, 6, 7, 8, 4, 2, 0, -2, -3, + 0, -3, -4, -3, -4, -5, -8, -15, -20, + -25, -28, -32, -37, -38, -39, -43, -48, -55, + -62, -69, -75, -75, -78, -81, -83, -89, -89, + -92, -91, -91, -89, -83, -81, -74, -66, -63, + -54, -45, -39, -31, -23, -15, -4, 6, 14, + 23, 29, 35, 41, 45, 49, 55, 61, 69, + 75, 75, 76, 75, 74, 74, 73, 74, 72, + 69, 69, 65, 62, 57, 52, 44, 35, 33, + 29, 24, 14, 7, 3, -4, -12, -17, -20, + -22, -27, -32, -34, -39, -42, -43, -42, -43, + -40, -38, -36, -36, -37, -36, -33, -31, -27, + -24, -23, -22, -17, -11, -7, -7, -7, -3, + 5, 13, 19, 25, 27, 25, 27, 35, 40, + 40, 41, 45, 47, 50, 54, 52, 50, 45, + 43, 44, 40, 34, 28, 24, 18, 11, 6, + -2, -9, -14, -21, -27, -35, -39, -43, -50, + -57, -62, -66, -68, -71, -72, -73, -74, -76, + -76, -77, -75, -75, -74, -67, -61, -55, -49, + -45, -40, -30, -21, -11, -4, 4, 13, 23, + 34, 44, 52, 59, 65, 70, 77, 84, 87, + 88, 90, 91, 90, 89, 85, 80, 75, 72, + 71, 64, 56, 48, 41, 34, 27, 21, 12, + 1, -11, -19, -28, -33, -39, -46, -50, -53, + -58, -63, -66, -71, -73, -76, -76, -74, -73, + -71, -67, -65, -62, -60, -55, -51, -45, -39, + -35, -31, -27, -20, -13, -6, -3, 1, 8, + 12, 18, 24, 26, 30, 35, 38, 44, 47, + 47, 51, 53, 52, 53, 52, 50, 51, 49, + 50, 51, 50, 48, 48, 45, 43, 42, 37, + 34, 31, 31, 30, 26, 24, 21, 15, 12, + 11, 7, 4, 1, -3, -5, -7, -9, -15, + -21, -26, -28, -31, -35, -39, -46, -48, -49, + -53, -58, -63, -67, -69, -71, -72, -74, -75, + -77, -77, -73, -72, -69, -65, -60, -55, -50, + -47, -43, -38, -30, -25, -20, -12, -4, 4, + 9, 16, 20, 24, 28, 35, 43, 50, 58, + 61, 65, 72, 74, 74, 76, 79, 78, 76, + 78, 76, 76, 74, 70, 64, 59, 52, 46, + 41, 33, 26, 19, 12, 5, -2, -8, -15, + -20, -26, -31, -37, -39, -41, -44, -44, -47, + -51, -52, -52, -48, -45, -46, -48, -45, -42, + -40, -36, -32, -27, -24, -22, -18, -16, -11, + -10, -5, 0, 3, 8, 11, 16, 18, 21, + 23, 25, 26, 27, 28, 30, 31, 31, 30, + 29, 27, 26, 23, 19, 17, 13, 10, 6, + 0, -2, -5, -10, -12, -15, -19, -23, -26, + -29, -30, -30, -32, -33, -34, -35, -34, -31, + -29, -29, -28, -28, -23, -19, -17, -12, -12, + -10, -5, -2, 3, 7, 10, 13, 14, 19, + 22, 26, 31, 34, 34, 35, 36, 39, 43, + 45, 47, 47, 48, 49, 51, 48, 47, 50, + 45, 41, 41, 38, 34, 34, 30, 23, 17, + 11, 7, 4, -4, -9, -15, -23, -28, -32, + -35, -39, -45, -46, -49, -53, -52, -53, -55, + -56, -56, -55, -54, -53, -53, -51, -47, -44, + -42, -40, -37, -33, -28, -25, -23, -18, -15, + -8, -6, -2, 3, 8, 15, 18, 23, 26, + 27, 32, 36, 36, 36, 39, 38, 38, 40, + 39, 35, 31, 29, 25, 23, 19, 15, 11, + 7, 5, 3, 1, -1, -6, -8, -7, -10, + -9, -10, -11, -10, -7, -6, -8, -6, -5, + -4, 1, 2, 4, 7, 7, 9, 11, 11, + 9, 9, 10, 11, 13, 17, 15, 15, 15, + 17, 19, 17, 17, 17, 15, 15, 13, 11, + 12, 8, 7, 5, 3, 0, -4, -4, -6, + -9, -12, -14, -15, -15, -16, -20, -19, -20, + -20, -20, -18, -18, -21, -22, -21, -21, -23, + -20, -20, -23, -24, -23, -25, -25, -25, -25, + -26, -24, -23, -23, -23, -23, -22, -19, -18, + -15, -14, -10, -8, -4, -1, 1, 3, 6, + 8, 9, 14, 19, 22, 24, 26, 29, 32, + 31, 34, 39, 42, 42, 46, 49, 50, 50, + 52, 53, 52, 49, 49, 48, 48, 46, 45, + 40, 34, 30, 25, 21, 17, 13, 10, 6, + 2, -4, -9, -12, -15, -18, -21, -26, -28, + -31, -32, -33, -35, -35, -38, -37, -36, -34, + -35, -35, -33, -33, -34, -30, -26, -27, -25, + -23, -22, -18, -15, -16, -12, -9, -9, -6, + -1, 2, 3, 5, 8, 7, 9, 12, 15, + 17, 18, 18, 19, 18, 20, 19, 18, 21, + 20, 19, 18, 16, 15, 15, 15, 14, 12, + 9, 9, 10, 8, 6, 4, 2, 1, -1, + -3, -1, -3, -2, -4, -5, -5, -8, -8, + -10, -10, -8, -8, -8, -7, -8, -8, -8, + -9, -11, -12, -11, -9, -7, -8, -8, -8, + -10, -8, -7, -8, -7, -6, -7, -5, -3, + -3, -3, -3, -2, 0, 3, 3, 5, 7, + 10, 11, 10, 10, 12, 13, 16, 16, 16, + 17, 15, 16, 17, 16, 14, 16, 13, 11, + 11, 9, 9, 6, 4, 4, 3, 0, -2, + -4, -7, -7, -7, -13, -15, -13, -14, -16, + -15, -15, -17, -16, -16, -18, -19, -19, -20, + -19, -16, -15, -13, -12, -10, -7, -6, -4, + -4, -2, 0, 2, 6, 8, 10, 12, 14, + 15, 14, 13, 13, 13, 15, 15, 17, 17, + 17, 18, 17, 16, 15, 15, 14, 11, 9, + 8, 8, 9, 8, 5, 5, 3, -1, -1, + -4, -5, -7, -8, -8, -8, -9, -10, -8, + -11, -12, -12, -12, -12, -13, -11, -11, -9, + -8, -7, -8, -7, -6, -7, -6, -5, -4, + -4, -2, -2, -3, -2, -2, -3, 0, -1, + -3, 1, 1, 2, 4, 3, 5, 6, 3, + 3, 4, 3, 3, 4, 5, 4, 6, 7, + 7, 7, 6, 3, 3, 5, 3, 3, 6, + 6, 7, 6, 4, 5, 2, 1, 1, 0, + 0, 2, 1, 1, 1, -1, -2, -3, -5, + -4, -5, -4, -4, -6, -4, -4, -4, -5, + -6, -5, -6, -5, -4, -5, -4, -3, -4, + 0, 2, 2, 2, 2, 2, 2, 3, 3, + 5, 6, 6, 5, 6, 7, 6, 8, 6, + 5, 5, 5, 6, 6, 6, 5, 5, 2, + 2, 1, 2, 0, -1, -1, -1, -1, 0, + -1, -4, -6, -8, -8, -9, -8, -7, -6, + -5, -5, -6, -3, -4, -5, -4, -7, -6, + -4, -2, -1, -1, 1, 1, 1, 1, 1, + 2, 2, 1, 3, 4, 4, 6, 6, 6, + 6, 4, 4, 4, 4, 3, 2, 2, 2, + 2, 1, 1, 1, 0, 1, 1, 0, -2, + -2, -3, -3, -3, -3, -5, -4, -3, -5, + -5, -3, -5, -4, -4, -2, -2, -2, -1, + -3, -2, -2, -1, -3, -2, -1, -2, -2, + -2, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 2, 3, 3, 3, 4, 5, 4, 3, + 4, 5, 5, 7, 7, 6, 9, 8, 6, + 7, 8, 6, 5, 7, 8, 8, 8, 7, + 6, 5, 4, 4, 4, 5, 4, 2, 1, + 2, 1, 0, -2, -3, -2, -4, -6, -6, + -7, -7, -8, -9, -9, -9, -9, -9, -9, + -9, -10, -10, -10, -8, -7, -8, -6, -5, + -4, -3, -5, -2, -2, -2, -1, -1, 0, + 1, 1, 2, 3, 2, 4, 3, 3, 5, + 3, 3, 5, 4, 5, 6, 5, 4, 5, + 3, 2, 2, 3, 4, 4, 4, 4, 4, + 3, 4, 4, 4, 3, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 1, 1, 2, 1, + 1, 2, 1, 1, 2, 1, 1, 1, -1, + 0, 1, 0, -1, 1, -1, -1, -1, -2, + -1, -1, -1, -1, -1, -1, -1, -1, -2, + -1, 0, -1, -1, 1, 1, 2, 0, -1, + 0, -1, -1, 0, 0, 1, 2, 2, 2, + 1, 1, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, -1, -2, -1, -3, -4, + -4, -4, -4, -4, -4, -4, -3, -3, -5, + -6, -4, -2, -2, -1, -1, -1, -2, 1, + -1, 1, 0, 0, 1, 1, 1, 1, 2, + 1, 2, 2, 3, 3, 3, 3, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 6, + 5, 5, 5, 6, 6, 5, 3, 6, 5, + 4, 5, 3, 2, 2, 2, 2, 1, 1, + 2, 0, -1, 0, -1, -1, -1, -1, -1, + -1, -1, -3, -3, -3, -3, -4, -4, -5, + -6, -6, -6, -6, -6, -6, -5, -5, -6, + -5, -4, -4, -4, -4, -2, -2, -2, -1, + -2, 0, 1, 0, 1, 3, 4, 4, 4, + 4, 4, 4, 5, 4, 4, 4, 5, 7, + 5, 4, 4, 4, 4, 3, 2, 2, 2, + 2, 2, 0, 1, 1, 0, 1, 1, -1, + 0, -1, -2, -1, -3, -4, -4, -3, -5, + -5, -5, -5, -5, -5, -4, -3, -3, -2, + -3, -2, -2, -5, -3, -3, -3, -2, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 3, + 3, 4, 4, 4, 4, 5, 5, 2, 3, + 4, 3, 5, 4, 3, 4, 3, 3, 5, + 5, 3, 4, 2, 1, 1, 3, 4, 3, + 1, 3, 2, 1, 2, 1, 0, 1, 0, + 1, 0, 1, 1, 1, 1, 0, -1, 0, + 0, -1, -1, -2, -1, -1, -2, 0, -1, + -2, -1, -1, -2, -2, -1, -3, -3, -3, + -3, -3, -4, -3, -5, -6, -4, -4, -5, + -4, -3, -5, -6, -4, -5, -6, -4, -3, + -5, -4, -3, -4, -3, -2, -2, -2, 0, + 0, 1, 1, 0, 0, 0, 1, 1, 3, + 3, 3, 4, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, -2, -1, 1, 0, -1, -2, -2, + 0, 1, 0, 1, 1, 1, 1, 0, 0, + 1, 0, 0, 2, 1, 0, 1, 1, 1, + 1, 3, 3, 3, 4, 3, 3, 4, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 2, + 2, 2, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -3, -3, -3, -5, -4, -5, -5, + -5, -5, -7, -7, -7, -8, -7, -8, -7, + -8, -8, -7, -8, -8, -8, -8, -7, -6, + -6, -6, -7, -6, -6, -5, -5, -3, -2, + -2, -1, 0, -1, 0, 1, 2, 2, 3, + 3, 3, 6, 7, 7, 7, 8, 9, 8, + 10, 10, 9, 10, 11, 9, 10, 12, 11, + 10, 9, 9, 9, 9, 10, 9, 6, 6, + 5, 5, 6, 3, 1, 1, 0, 1, 0, + 0, 1, -1, -2, -2, -1, -3, -3, -2, + -4, -4, -3, -2, -4, -4, -4, -5, -3, + -3, -5, -3, -3, -5, -4, -2, -2, -3, + -3, -1, 0, -1, 0, 0, 0, -2, -1, + 0, -1, -2, -2, -2, -2, -1, -3, -2, + -3, -4, -3, -3, -3, -3, -3, -3, -3, + -2, -4, -6, -5, -3, -2, -4, -3, -2, + -4, -4, -4, -3, -4, -5, -4, -5, -3, + -2, -5, -2, -4, -4, -3, -2, -1, -1, + -1, 0, 2, 2, 1, 1, 3, 3, 3, + 3, 4, 4, 5, 6, 5, 5, 6, 7, + 7, 7, 8, 8, 7, 9, 9, 9, 9, + 10, 9, 9, 9, 9, 9, 9, 8, 7, + 9, 9, 6, 7, 5, 2, 3, 2, 1, + 1, 0, -2, -2, -2, -3, -3, -2, -2, + -4, -5, -4, -4, -4, -4, -5, -4, -4, + -5, -4, -5, -4, -5, -6, -4, -4, -5, + -5, -5, -5, -6, -4, -4, -4, -3, -2, + -3, -3, -2, -2, -1, -2, -3, -1, 0, + -1, 0, 0, 0, 0, 1, 0, 0, 0, + 0, -1, 1, 1, 1, 0, -2, -2, -3, + -3, -4, -4, -6, -7, -5, -4, -5, -5, + -4, -6, -8, -7, -6, -5, -5, -5, -4, + -4, -5, -4, -3, -3, 0, 0, -2, -1, + 0, 0, 1, 1, 2, 2, 2, 2, 2, + 4, 5, 5, 5, 6, 7, 7, 9, 10, + 10, 10, 12, 12, 13, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 14, 15, 15, 12, + 13, 13, 12, 10, 11, 11, 11, 10, 8, + 6, 5, 7, 6, 6, 4, 3, 4, 5, + 3, 2, 2, 1, 1, 2, 3, 1, 0, + 0, 1, 0, -2, -1, -2, -3, -3, -3, + -3, -4, -6, -8, -9, -9, -10, -12, -14, + -15, -18, -21, -21, -21, -21, -22, -24, -26, + -26, -27, -27, -28, -26, -25, -26, -28, -27, + -24, -23, -23, -24, -21, -17, -17, -15, -12, + -12, -12, -12, -9, -7, -6, -5, -3, -3, + -2, 0, 0, 1, 3, 7, 6, 4, 6, + 7, 8, 11, 10, 10, 13, 15, 14, 13, + 18, 20, 18, 19, 21, 23, 24, 23, 22, + 24, 26, 26, 26, 27, 25, 23, 25, 27, + 28, 28, 28, 23, 19, 23, 24, 20, 20, + 21, 15, 13, 15, 16, 14, 11, 8, 7, + 8, 11, 11, 6, 4, 8, 7, 6, 7, + 6, 4, 7, 13, 12, 7, 8, 8, 4, + 1, 1, 1, 2, -4, -12, -18, -24, -25, + -25, -32, -41, -55, -59, -61, -75, -87, -96, + -109, -122, -133, -141, -148, -157, -168, -180, -191, + -198, -202, -207, -206, -207, -211, -211, -208, -203, + -189, -171, -153, -132, -114, -96, -75, -54, -30, + -5, 19, 43, 61, 77, 93, 106, 123, 143, + 161, 182, 198, 202, 201, 209, 229, 242, 240, + 235, 239, 249, 258, 255, 242, 233, 245, 268, + 278, 256, 223, 223, 253, 263, 235, 198, 178, + 188, 215, 230, 200, 143, 113, 128, 158, 158, + 128, 99, 90, 82, 70, 56, 32, 7, 14, + 46, 36, -23, -71, -76, -54, -36, -39, -74, + -118, -134, -122, -101, -104, -129, -164, -174, -129, + -86, -109, -184, -219, -191, -147, -141, -183, -249, + -290, -269, -236, -266, -346, -394, -366, -325, -353, + -431, -472, -406, -313, -316, -398, -449, -401, -287, + -194, -164, -193, -245, -212, -55, 75, 67, 26, + 67, 165, 237, 269, 293, 319, 333, 368, 414, + 432, 463, 488, 448, 404, 391, 377, 361, 365, + 376, 308, 197, 150, 129, 73, 53, 91, 43, + -107, -165, -54, 1, -148, -312, -273, -125, -62, + -128, -258, -294, -141, 70, 57, -217, -378, -145, + 198, 289, 169, -47, -219, -101, 264, 458, 217, + -163, -199, 13, 121, 101, -51, -293, -319, -62, + 24, -274, -474, -296, -170, -336, -422, -285, -248, + -302, -130, 98, -11, -257, -146, 184, 278, 264, + 331, 192, -35, 235, 805, 830, 315, 82, 322, + 503, 522, 619, 557, 242, 163, 399, 507, 489, + 618, 602, 156, -164, 112, 476, 406, 94, -154, + -242, -132, 56, 5, -325, -566, -527, -478, -624, + -692, -561, -551, -744, -836, -671, -520, -626, -736, + -647, -581, -639, -687, -702, -739, -665, -383, -236, + -414, -513, -321, -114, -43, 32, 65, -98, -236, + 34, 608, 924, 680, 218, 56, 329, 847, 1214, + 1006, 341, 11, 340, 667, 553, 353, 355, 415, + 416, 364, 257, 108, 6, 113, 293, 233, 46, + 4, 25, -10, -12, 55, 40, -65, -56, -26, + -101, -61, 143, 229, 78, -161, -210, 103, 424, + 377, 86, -274, -491, -328, -37, 60, 128, 188, + -105, -625, -823, -464, 138, 389, 111, -343, -526, + -306, 13, 205, 250, -35, -554, -764, -498, -42, + 167, -210, -639, -448, -101, -110, -171, -74, -39, + 47, 424, 616, 324, 98, 367, 853, 942, 416, + -184, -130, 339, 472, 369, 239, -165, -418, 101, + 742, 659, 325, 365, 476, 233, -14, 270, 785, + 719, -29, -533, -220, 237, 305, 179, -190, -644, + -610, -380, -526, -601, -237, 48, -36, -124, -49, + -6, 23, 117, 55, -199, -428, -512, -338, -238, + -424, -323, -135, -464, -657, -189, 100, -379, -964, + -893, -346, -64, -322, -650, -480, 32, 238, 201, + 386, 616, 611, 400, 195, 357, 842, 1051, 832, + 712, 829, 1070, 1307, 1081, 551, 363, 544, 623, + 239, -374, -609, -230, 375, 486, -52, -446, -270, + 181, 645, 601, -135, -654, -256, 567, 840, 380, + -54, 18, 334, 386, 21, -214, 83, 243, -316, + -937, -1074, -1006, -896, -674, -424, -331, -354, -380, + -481, -392, 80, 358, 171, -170, -624, -796, -130, + 706, 803, 381, 152, 367, 620, 685, 655, 347, + 36, 180, 417, 412, 358, 288, 189, 150, 16, + -240, -428, -428, -266, -335, -819, -1150, -946, -587, + -437, -580, -961, -1218, -1065, -704, -431, -350, -315, + -214, -162, -81, 26, -8, -52, -117, -226, -40, + 285, 241, -2, -69, 57, 207, 81, -144, -69, + 65, 84, 49, -168, -248, 126, 502, 472, 192, + 120, 442, 667, 551, 512, 634, 814, 1014, 1098, + 1156, 1112, 974, 1144, 1330, 1099, 825, 847, 877, + 555, 2, -243, -102, -196, -471, -377, -235, -439, + -622, -547, -470, -495, -431, -197, -21, 21, -9, + -246, -438, -238, -31, 0, 96, 137, -25, -211, + -181, -149, -350, -368, -33, 21, -308, -323, 32, + 379, 605, 531, 85, -374, -367, 9, 277, 147, + -356, -698, -494, -140, -126, -354, -549, -673, -642, + -428, -269, -273, -246, -216, -349, -323, -16, 32, + -387, -742, -662, -434, -223, 41, 140, -58, -227, + -80, 93, 20, -166, -360, -536, -555, -305, -33, + -23, -86, -75, -9, 82, -1, -156, 24, 532, + 916, 956, 835, 901, 1127, 1279, 1417, 1435, 1144, + 822, 862, 1214, 1352, 1001, 611, 539, 532, 369, + 189, 170, 308, 465, 430, 232, 64, 14, 51, + -37, -244, -321, -276, -144, 57, 77, -215, -467, + -335, -186, -245, -133, -81, -588, -1130, -959, -520, + -631, -1122, -1270, -971, -873, -1118, -1157, -1078, -1296, + -1365, -1010, -873, -1138, -1061, -379, 89, 51, 177, + 372, 185, -14, 63, 197, 125, -123, -60, 243, + 195, 88, 201, 115, -63, -12, -79, -492, -751, + -489, 49, 163, -293, -424, -52, 229, 302, 212, + 217, 315, 70, -207, -210, -173, 129, 619, 556, + 213, 181, 170, 112, 167, 322, 451, 206, -136, + 58, 426, 526, 524, 394, 387, 568, 481, 297, + 164, 8, 263, 664, 777, 943, 989, 934, 1283, + 1495, 1153, 861, 738, 582, 614, 692, 655, 629, + 432, 127, -119, -338, -313, -138, -204, -561, -994, + -1168, -948, -700, -658, -788, -1053, -1027, -684, -566, + -528, -355, -335, -323, -28, 206, 87, 56, 387, + 585, 296, 24, 261, 492, 248, -132, -469, -674, + -502, -235, -255, -517, -847, -1038, -965, -707, -630, + -767, -639, -298, -193, -290, -310, -118, 74, -77, + -337, -324, -120, 187, 323, -72, -552, -454, -14, + 29, -427, -803, -735, -586, -762, -918, -783, -649, + -723, -857, -786, -626, -591, -417, -83, 167, 262, + 49, -161, 157, 842, 1298, 1356, 1206, 1041, 1194, + 1461, 1323, 1070, 1221, 1687, 2051, 2002, 1673, 1464, + 1550, 1851, 1907, 1531, 1327, 1399, 1342, 1287, 1264, + 1152, 1030, 878, 716, 601, 454, 264, 264, 352, + 151, -193, -296, -161, -93, -215, -423, -617, -668, + -547, -416, -464, -807, -1175, -1174, -1045, -1076, -1023, + -829, -710, -745, -1069, -1443, -1417, -1099, -939, -1165, + -1307, -1056, -843, -638, -304, -190, -334, -578, -770, + -705, -675, -947, -957, -565, -437, -617, -843, -1015, + -813, -489, -584, -904, -1054, -797, -229, -26, -208, + -66, 398, 710, 644, 390, 413, 726, 992, 1204, + 1337, 1234, 1104, 1038, 1001, 1043, 982, 847, 885, + 1024, 1098, 1138, 1108, 1038, 966, 885, 882, 878, + 929, 1005, 944, 1008, 1284, 1415, 1289, 1007, 760, + 812, 947, 806, 455, 111, -72, -290, -611, -626, + -559, -765, -1034, -1375, -1632, -1565, -1588, -1728, -1585, + -1477, -1547, -1533, -1371, -1103, -995, -1090, -1102, -947, + -686, -403, -295, -250, -107, -86, -171, -150, 12, + 234, 283, 185, 300, 461, 393, 382, 434, 378, + 306, 202, 195, 253, -8, -307, -105, 264, 342, + 212, 34, -57, 78, 435, 571, 180, -165, -51, + 339, 705, 683, 464, 658, 958, 825, 579, 465, + 390, 241, 61, 202, 429, 128, -122, 241, 406, + 39, -167, -60, 15, -31, -68, 146, 402, 344, + 227, 208, 87, -25, -31, -66, -169, -249, -87, + 75, -181, -438, -249, 49, 87, -40, -16, 53, + -86, -74, 98, 78, 110, 169, -84, -323, -251, + -102, -172, -513, -750, -675, -568, -587, -583, -523, + -450, -302, -245, -356, -480, -590, -495, -183, -105, + -191, -215, -308, -206, 39, 4, -77, -21, 74, + 186, 218, 356, 611, 489, 83, 13, 246, 371, + 348, 240, 61, -66, -107, -170, -205, -74, 200, + 277, 45, -11, 180, 263, 100, -74, 102, 246, + 6, -154, -162, -197, -128, -189, -227, -49, -238, + -490, -333, -188, 1, 215, 150, 144, 128, -33, + 187, 532, 676, 911, 773, 283, 351, 673, 620, + 349, 105, 205, 425, 325, 295, 372, 340, 511, + 628, 394, 224, 187, 91, -174, -556, -482, -37, + -9, -226, -382, -568, -466, -208, -241, -426, -656, + -814, -788, -902, -1065, -946, -860, -896, -831, -744, + -672, -685, -743, -723, -783, -813, -570, -341, -239, + -57, 137, 348, 576, 593, 454, 429, 503, 449, + 238, 173, 350, 423, 419, 530, 501, 272, 156, + 207, 295, 404, 568, 676, 419, 30, 113, 463, + 550, 473, 349, 126, 33, 144, 207, 193, 267, + 304, 81, -252, -401, -368, -347, -404, -452, -408, + -272, -40, 234, 281, 48, -72, -18, 54, 208, + 309, 285, 245, 164, 38, -20, 148, 430, 563, + 655, 679, 453, 300, 319, 219, 25, -15, 54, + -117, -444, -431, -135, -147, -468, -667, -722, -593, + -301, -217, -428, -642, -598, -400, -422, -602, -628, + -554, -509, -501, -541, -488, -250, -129, -284, -441, + -358, -161, -82, 4, 134, 157, 290, 516, 582, + 702, 859, 871, 858, 759, 615, 616, 754, 839, + 725, 464, 259, 187, 127, 150, 280, 238, 92, + 78, 5, -86, 6, 67, -14, -92, -143, -211, + -89, 213, 300, 107, -91, -154, -153, -238, -355, + -314, -227, -168, -92, -142, -219, -156, -47, 53, + -15, -195, -161, -186, -382, -395, -297, -238, -240, + -390, -502, -336, -97, -29, -116, -290, -289, -67, + 74, 112, 119, 182, 358, 382, 315, 341, 290, + 218, 190, 101, -51, -168, -132, -41, -39, -15, + 104, 186, 151, 68, 89, 154, 67, 10, 143, + 120, -185, -382, -365, -263, -145, -111, -159, -190, + -53, 151, 177, 179, 384, 553, 502, 490, 572, + 600, 573, 442, 119, -212, -260, -166, -318, -506, + -413, -279, -285, -354, -390, -278, -142, -85, -18, + -19, -121, -143, -32, 88, 118, 42, -96, -187, + -167, -113, -172, -270, -256, -178, -192, -249, -128, + 103, 132, -47, -147, -104, -56, -9, 45, 35, + 109, 315, 381, 326, 336, 457, 667, 786, 675, + 489, 460, 569, 595, 470, 303, 272, 448, 620, + 545, 226, -92, -128, 91, 172, -98, -385, -378, + -264, -284, -362, -314, -148, -72, -198, -350, -353, + -344, -389, -353, -292, -327, -413, -473, -519, -588, + -577, -546, -737, -989, -1030, -997, -1010, -861, -683, + -731, -690, -419, -197, -47, 112, 167, 74, 41, + 176, 309, 438, 671, 781, 793, 868, 904, 991, + 1099, 987, 812, 816, 869, 766, 605, 633, 728, + 592, 424, 460, 405, 170, 75, 30, -105, -58, + 63, -58, -242, -359, -415, -255, -44, -127, -266, + -191, -187, -296, -273, -260, -341, -345, -324, -384, + -467, -421, -233, -125, -227, -341, -256, -168, -217, + -249, -302, -447, -425, -274, -289, -299, -229, -275, + -272, -103, -57, -117, -106, -162, -256, -184, -31, + 51, 69, 31, -19, 72, 256, 318, 331, 254, + 28, -7, 121, 48, -64, 58, 183, 152, 161, + 201, 167, 190, 287, 278, 157, 56, 103, 332, + 460, 299, 166, 238, 308, 374, 508, 509, 373, + 275, 270, 298, 229, 185, 192, 23, -160, -80, + 67, 31, -170, -378, -384, -330, -500, -648, -615, + -686, -716, -510, -510, -771, -752, -475, -434, -556, + -480, -403, -515, -464, -255, -177, -105, 29, 95, + 152, 210, 190, 180, 279, 408, 325, 225, 462, + 607, 537, 759, 1022, 973, 945, 964, 846, 818, + 952, 907, 584, 313, 302, 428, 533, 479, 260, + 178, 262, 185, 18, -77, -263, -370, -208, -240, + -589, -739, -572, -444, -405, -357, -475, -738, -771, + -542, -441, -529, -651, -803, -823, -556, -285, -227, + -233, -202, -168, -110, -78, -220, -302, -56, 129, + -60, -149, 54, 130, 169, 324, 231, 24, 89, + 269, 320, 262, 231, 225, 138, 67, 153, 310, + 399, 269, -21, -197, -183, -59, 144, 234, -13, + -274, -168, 32, -37, -277, -417, -441, -416, -324, + -312, -467, -540, -373, -166, -161, -297, -365, -341, + -246, -69, 81, 99, -3, 11, 305, 540, 449, + 394, 586, 667, 606, 685, 665, 425, 410, 585, + 509, 360, 424, 538, 583, 482, 250, 159, 310, + 423, 217, -131, -280, -204, -51, -12, -204, -338, + -232, -143, -201, -306, -374, -336, -229, -257, -453, + -576, -497, -379, -326, -302, -372, -504, -453, -229, + -133, -226, -328, -326, -261, -151, -6, 97, 143, + 164, 143, 138, 267, 433, 500, 470, 297, 143, + 279, 504, 556, 475, 333, 233, 225, 228, 198, + 128, 24, -17, 4, -55, -187, -251, -213, -119, + -94, -214, -357, -349, -246, -195, -183, -261, -440, + -533, -476, -341, -213, -170, -220, -299, -220, -8, + 51, -11, 19, 172, 292, 189, 9, -6, 102, + 238, 384, 477, 448, 353, 304, 354, 473, 543, + 400, 229, 275, 380, 425, 415, 371, 398, 460, + 377, 202, 154, 199, 110, -123, -365, -524, -524, + -360, -134, -47, -182, -348, -453, -542, -503, -376, + -398, -521, -595, -621, -560, -439, -284, -115, -80, + -123, -57, 28, -15, -60, -9, 47, 119, 203, + 288, 435, 571, 635, 706, 750, 627, 436, 345, + 330, 398, 460, 368, 213, 127, 140, 215, 202, + 58, -99, -244, -387, -470, -527, -637, -754, -791, + -768, -742, -739, -735, -704, -649, -552, -479, -491, + -494, -454, -433, -422, -398, -315, -115, 75, 175, + 244, 307, 360, 398, 460, 532, 529, 446, 422, + 497, 541, 504, 541, 702, 803, 744, 645, 621, + 727, 877, 873, 734, 593, 513, 523, 516, 412, + 336, 334, 274, 199, 163, 123, 125, 117, 107, + 140, 72, -73, -114, -68, -15, 13, -122, -338, + -367, -325, -386, -497, -608, -634, -546, -477, -427, + -377, -412, -464, -436, -343, -276, -327, -390, -313, + -149, -17, 2, -93, -146, -104, -76, -87, -131, + -224, -280, -194, -46, 12, -76, -189, -151, 18, + 160, 200, 99, -81, -149, -95, -31, -6, -45, + -93, -97, -71, 0, 73, 34, -82, -129, -102, + -84, -96, -107, -69, -5, 6, 18, 48, 35, + 27, 32, -4, -71, -30, 119, 205, 266, 352, + 325, 237, 282, 352, 358, 342, 265, 203, 200, + 159, 120, 159, 195, 185, 133, 37, 20, 152, + 312, 363, 316, 255, 251, 259, 211, 160, 86, + -4, -30, -79, -154, -213, -271, -243, -146, -147, + -211, -283, -319, -219, -157, -207, -237, -252, -245, + -136, 0, 42, -22, -108, -82, 34, 130, 179, + 152, 98, 105, 110, 116, 180, 175, 66, -9, + -9, 36, 82, 75, 12, -39, -14, 23, 1, + 12, 31, -61, -155, -184, -158, -86, -60, -67, + -63, -84, -100, -81, -115, -171, -157, -150, -179, + -191, -209, -245, -217, -128, -54, -42, -73, -100, + -88, -10, 104, 199, 249, 227, 201, 204, 151, + 83, 75, 87, 84, 67, 34, 18, 44, 110, + 218, 275, 232, 190, 209, 263, 294, 256, 174, + 108, 37, -54, -110, -129, -179, -293, -360, -339, + -282, -190, -135, -188, -239, -234, -227, -182, -127, + -89, -51, -73, -136, -151, -85, 0, 72, 129, + 122, 65, 44, 103, 202, 272, 252, 170, 148, + 167, 152, 130, 127, 79, 14, 70, 157, 142, + 109, 70, -25, -57, -6, 46, 98, 135, 135, + 82, 16, 10, 68, 87, -20, -120, -116, -98, + -102, -129, -204, -271, -282, -252, -216, -215, -221, + -156, -70, -66, -120, -156, -146, -126, -84, -15, + -21, -76, -8, 131, 146, 86, 42, 12, 44, + 110, 169, 171, 91, 68, 173, 262, 248, 160, + 36, -90, -109, -24, -12, -57, -64, -78, -89, + -75, -87, -101, -82, -72, -76, -81, -63, -34, + -4, 61, 87, 46, 23, -1, -8, 40, 63, + 46, 45, 39, 14, -11, -25, -16, 36, 78, + 85, 110, 120, 132, 189, 228, 217, 154, 89, + 57, 14, -14, -6, 0, 13, 8, -50, -68, + -60, -107, -140, -126, -122, -151, -147, -118, -105, + -85, -83, -100, -139, -195, -194, -168, -183, -173, + -148, -166, -168, -123, -59, -11, 20, 64, 98, + 80, 58, 83, 111, 143, 176, 171, 152, 146, + 165, 174, 143, 93, 30, 5, 21, 42, 35, + -37, -94, -61, -12, -5, -27, -58, -85, -81, + -11, 79, 65, -14, -17, 15, -4, -2, 39, + 20, -29, -19, 3, -11, -39, -62, -43, -34, + -60, -77, -119, -163, -128, -5, 87, 73, 51, + 116, 189, 217, 240, 234, 177, 192, 295, 344, + 313, 263, 236, 240, 230, 179, 99, 19, -25, + -16, -9, -35, -66, -53, -16, -40, -70, -81, + -102, -86, -87, -156, -225, -228, -145, -52, -22, + -57, -171, -255, -247, -208, -165, -187, -242, -275, + -261, -168, -75, -13, 8, -62, -125, -136, -133, + -81, -11, -17, -80, -115, -103, -27, 71, 134, + 137, 44, -48, -24, 69, 156, 194, 175, 112, + 55, 54, 101, 148, 157, 142, 100, 44, 27, + 63, 106, 107, 89, 67, 37, 17, 30, 63, + 69, 61, 21, -37, -55, -72, -53, -26, -53, + -77, -87, -109, -119, -80, -36, -29, -38, -48, + -57, -65, -16, 52, 83, 83, 24, -27, -14, + 9, 27, 52, 50, 45, 90, 132, 117, 75, + 16, -1, 60, 95, 55, 25, 26, 20, 61, + 119, 89, 1, -61, -68, -46, -36, -40, -39, + -49, -58, -16, 30, 13, -12, 18, 35, 6, + 3, 30, 22, 25, 52, 32, 12, 9, -5, + -16, -25, -33, -38, -44, -76, -118, -118, -96, + -54, -3, 9, -31, -82, -84, -35, 18, 25, + -26, -72, -48, 8, 25, 8, -20, -66, -105, + -102, -80, -73, -79, -80, -70, -59, -55, -82, + -113, -85, -51, -59, -57, -38, -13, -7, -18, + -6, 20, 51, 55, 18, -8, -7, 24, 78, + 119, 137, 135, 139, 153, 144, 155, 179, 166, + 128, 56, 8, 38, 85, 94, 72, 20, -32, + -9, 25, 17, -15, -84, -123, -106, -82, -62, + -60, -43, -4, -12, -45, -68, -108, -100, -47, + -49, -64, -50, -9, 37, 59, 68, 62, 53, + 49, 25, 13, 32, 40, 60, 109, 82, 18, + 10, -1, 21, 102, 111, 40, -10, -9, 20, + 31, 0, -51, -108, -135, -89, -21, 1, -54, + -125, -129, -113, -144, -205, -227, -167, -118, -114, + -100, -71, 5, 34, -51, -119, -120, -72, 10, + 56, 51, 58, 65, 98, 135, 84, 20, -3, + -1, 57, 135, 137, 90, 88, 107, 102, 45, + -4, 9, 48, 95, 99, 65, 42, 44, 78, + 80, 29, 11, 39, 27, 0, 7, 19, 10, + -45, -99, -86, -77, -74, -57, -74, -84, -92, + -134, -114, -65, -73, -76, -96, -105, -50, -31, + -17, 17, 9, 18, 62, 75, 55, 63, 76, + 61, 61, 80, 103, 107, 110, 131, 134, 120, + 94, 66, 70, 78, 59, 52, 57, 53, 72, + 76, 31, -18, -53, -57, -35, -17, -9, -27, + -34, -7, -17, -26, -13, -60, -86, -53, -42, + -36, -36, -46, -13, 19, -16, -47, -15, 11, + -9, -18, -26, -24, 14, 8, -53, -54, 15, + 43, 15, -9, -5, 5, -12, -40, -57, -74, + -94, -105, -91, -20, 30, -10, -50, -58, -52, + -42, -47, -54, -61, -83, -64, -30, -3, 31, + 9, -35, -43, -31, 6, 50, 54, 55, 67, + 53, 43, 30, 27, 62, 37, -26, -52, -54, + -29, 3, -12, -23, 11, 26, 23, 31, 57, + 66, 46, 32, 35, 83, 124, 111, 124, 157, + 143, 101, 80, 60, 27, 11, 21, 22, 9, + -4, -26, -41, -35, -50, -103, -138, -116, -90, + -89, -90, -79, -74, -58, -18, -12, -29, -36, + -17, 22, 30, -1, -8, 8, 10, 19, 31, + 36, 38, 41, 28, -7, -14, -6, -20, -30, + -11, -2, -9, 0, 25, 56, 78, 68, 40, + 34, 47, 50, 40, 37, 26, 28, 53, 61, + 57, 25, -35, -75, -65, -48, -65, -81, -67, + -53, -41, 3, 19, -3, -9, -2, -1, -24, + -36, -23, -26, -29, -9, 0, -15, -17, -9, + 12, 50, 45, 14, 19, 37, 24, 9, 16, + 13, -16, -19, 3, -3, -12, -10, -23, -43, + -47, -38, -46, -44, -7, 3, -19, -13, -26, + -52, -29, -19, -32, 0, 11, -26, -24, -20, + -41, -30, -24, -53, -67, -26, 23, 20, 9, + 6, -8, 3, 16, 7, 3, -5, 2, 33, + 53, 72, 94, 86, 69, 96, 118, 95, 91, + 78, 32, 26, 48, 48, 37, 21, 7, -6, + -8, 8, 1, -17, -2, 18, 1, -28, -51, + -84, -93, -74, -46, -18, -19, -31, -10, 10, + 10, 7, -5, -30, -39, -28, -9, 10, 17, + 11, 14, 20, -1, 2, 18, 7, 15, 40, + 40, 32, 27, 23, 31, 43, 33, 7, -3, + 18, 51, 53, 31, 21, 14, 16, 14, 4, + 11, 16, 1, -24, -38, -33, -27, -50, -74, + -70, -60, -54, -44, -22, -22, -43, -33, -16, + -35, -36, -18, -27, -42, -46, -36, -17, -15, + -22, -21, -20, -2, 15, 12, 22, 27, 22, + 41, 57, 60, 63, 54, 56, 65, 62, 68, + 58, 34, 53, 70, 58, 60, 51, 33, 41, + 39, 16, -3, -16, -18, -15, -18, -32, -76, + -85, -62, -82, -87, -68, -84, -75, -40, -48, + -55, -45, -42, -24, -14, -1, 27, 23, -1, + -2, 12, 15, 32, 55, 52, 55, 82, 81, + 58, 62, 59, 37, 24, 20, 17, 18, 19, + 15, 14, 5, -18, -27, -20, -19, -34, -39, + -29, -30, -27, -27, -48, -52, -54, -77, -48, + -18, -36, -34, -13, -21, -38, -28, -15, -7, + -6, -20, -18, 2, 4, -11, -5, 7, 1, + 1, 12, -2, -17, 7, 15, 2, 15, 34, + 48, 78, 94, 82, 66, 66, 64, 47, 44, + 57, 64, 74, 65, 34, 26, 31, 32, 33, + 18, 5, -1, -18, -22, -31, -54, -37, -32, + -74, -89, -77, -73, -65, -72, -75, -39, -21, + -31, -31, -24, -19, -8, -4, 7, 26, 22, + 15, 13, 11, 28, 47, 42, 35, 28, 5, + 18, 55, 55, 45, 44, 18, 9, 18, -2, + -5, 6, -15, -16, -12, -20, -4, 4, -15, + -18, -10, -5, -2, -16, -24, -14, -7, -14, + -33, -33, -20, -17, -17, -18, -30, -37, -35, + -34, -13, -3, -28, -28, -10, -21, -17, -4, + -12, -16, -20, -27, -16, -8, -4, 14, 24, + 11, 17, 30, 27, 14, 7, 28, 30, 22, + 45, 47, 23, 31, 23, -5, 10, 17, -5, + 2, 15, 9, 20, 29, 11, -9, -8, 8, + 10, -1, -14, -30, -30, -8, -9, -20, -17, + -17, -12, 1, 6, -7, -18, -6, 10, -6, + -7, 29, 35, 21, 16, 9, 25, 44, 26, + 21, 34, 28, 40, 41, 9, -2, 1, 12, + 34, 18, -12, -10, -16, -29, -24, -25, -20, + -17, -35, -29, -12, -29, -39, -32, -30, -17, + -12, -28, -20, -5, -4, 7, 14, 10, 3, + -3, 0, 19, 27, 4, -21, -18, -7, -4, + 0, 1, -6, -17, -30, -24, -11, -9, 0, + -1, 0, -3, -12, 1, 15, -2, 3, 16, + -3, -8, 7, 3, 13, 32, 23, 10, -6, + -11, 8, 4, -12, -9, 3, 12, -2, -31, + -36, -33, -37, -17, -5, -20, -14, 4, 5, + 4, 6, 17, 31, 27, 23, 16, -1, -4, + 15, 24, 21, 18, 7, -7, -14, 18, 41, + 25, 14, 13, 2, 5, 12, 8, 15, 10, + 2, 13, 10, 3, 5, -1, 0, 11, 10, + 6, 2, 7, 10, -4, -3, 2, -13, -4, + 14, -4, -17, -11, -4, 8, 3, -8, -1, + -7, -20, -4, 23, 23, 8, 5, 24, 21, + -5, -2, 7, -9, -15, -8, -6, 6, 2, + -26, -19, 1, -19, -31, -27, -34, -41, -47, + -39, -12, -12, -29, -32, -41, -36, -26, -36, + -35, -33, -29, -1, 5, -13, -21, -21, -3, + 12, 1, -7, -1, 2, 12, 9, -1, 15, + 21, 18, 25, 4, -13, 5, 12, 16, 33, + 33, 19, 21, 26, 30, 30, 24, 23, 19, + 22, 34, 39, 28, 15, 14, 24, 24, 18, + 12, 10, 4, 8, 28, 29, 2, -7, 6, + 8, 10, 2, -13, -8, -2, 0, 12, 13, + -1, 3, 21, 26, 24, 17, 11, 15, 19, + 19, 19, 11, 1, 3, 3, 0, -5, -11, + -16, -26, -18, 3, -5, -17, 2, 10, 6, + 6, -8, -11, 4, -3, -17, -10, -17, -37, + -31, -17, -26, -37, -42, -53, -49, -34, -40, + -39, -21, -17, -23, -23, -25, -30, -24, -13, + -10, -10, 1, 1, -7, 7, 19, 11, 4, + -3, -8, 1, 6, 7, 25, 22, -5, 3, + 20, 7, -1, 14, 17, 18, 20, 12, 25, + 41, 23, 19, 37, 39, 21, 17, 23, 17, + 6, 9, 15, 4, -15, -8, 8, 7, 1, + -12, -18, -14, -15, -10, 0, -3, 3, 13, + -8, -21, -8, -26, -29, -1, -9, -24, -19, + -22, -24, -18, -25, -27, -28, -34, -26, -9, + -14, -14, -8, -8, -5, 4, 4, -10, -12, + -7, -8, -10, -15, -19, -10, -5, -9, -9, + -19, -33, -27, -14, -15, -14, -16, -25, -10, + 5, -7, -11, 2, 3, 7, 17, 28, 33, + 32, 33, 39, 49, 57, 63, 62, 64, 67, + 59, 55, 67, 71, 58, 53, 53, 44, 38, + 44, 51, 51, 45, 35, 34, 46, 55, 48, + 36, 21, 3, -5, 2, 7, 0, -17, -30, + -34, -48, -62, -64, -66, -66, -62, -79, -90, + -85, -88, -88, -85, -88, -103, -112, -112, -102, + -99, -102, -103, -110, -100, -80, -60, -57, -68, + -59, -45, -35, -6, 9, -3, 2, 32, 45, + 48, 51, 40, 51, 78, 85, 83, 87, 94, + 101, 104, 105, 100, 86, 82, 96, 102, 96, + 85, 68, 63, 65, 55, 50, 46, 28, 32, + 43, 33, 30, 27, 8, 18, 36, 27, 20, + 13, -14, -19, 8, 12, 0, -1, -12, -24, + -20, -27, -39, -39, -39, -44, -38, -32, -42, + -38, -33, -43, -55, -57, -60, -61, -56, -57, + -55, -43, -46, -58, -55, -50, -50, -51, -48, + -46, -44, -36, -26, -20, -13, -11, -8, 1, + 5, 0, 8, 21, 31, 42, 39, 43, 56, + 48, 37, 45, 45, 47, 52, 46, 40, 26, + 18, 28, 30, 22, 14, 0, -3, 8, 0, + -7, 0, -10, -13, -9, -13, -13, -18, -33, + -32, -26, -37, -41, -32, -26, -30, -34, -31, + -38, -40, -24, -25, -29, -15, -18, -23, -4, + 2, -7, 0, 5, 10, 22, 23, 25, 31, + 33, 37, 38, 39, 43, 46, 41, 44, 46, + 37, 35, 46, 63, 67, 52, 38, 30, 35, + 41, 41, 41, 29, 15, 16, 4, -4, 3, + -12, -18, -13, -27, -39, -47, -55, -44, -43, + -53, -45, -36, -37, -37, -38, -40, -49, -57, + -41, -24, -28, -31, -26, -20, -15, -21, -23, + -18, -19, -14, -10, -11, 1, -6, -26, -14, + -1, -7, -10, -11, -9, 0, -4, -9, 3, + 8, 0, -2, 1, 16, 20, 7, 9, 10, + 8, 18, 12, 11, 17, -6, -19, 0, 0, + -10, -6, -12, -14, -11, -9, -2, -10, -19, + -9, -11, -4, 18, 7, -3, 9, 17, 23, + 28, 25, 19, 19, 24, 33, 37, 30, 28, + 35, 44, 43, 33, 31, 30, 26, 33, 39, + 35, 31, 27, 19, 23, 24, 19, 13, 0, + 0, 2, -7, -9, -10, -13, -6, -6, -23, + -28, -15, -9, -20, -34, -30, -15, -12, -11, + -3, -4, -4, 6, 15, 9, -11, -20, 3, + 26, 23, 1, -16, -3, 12, 2, -22, -36, + -35, -28, -20, -13, -19, -38, -43, -29, -11, + -5, -15, -37, -40, -9, 12, -1, -23, -30, + -16, 12, 21, -1, -25, -21, 4, 34, 55, + 34, -12, -11, 47, 99, 107, 58, 0, 8, + 78, 148, 151, 56, -40, -2, 142, 215, 99, + -67, -64, 76, 153, 99, -21, -107, -92, -1, + 106, 107, -123, -395, -334, 60, 274, -69, -597, + -626, -126, 238, 18, -447, -577, -312, -34, 20, + -89, -242, -332, -222, 74, 262, 64, -285, -232, + 259, 563, 294, -138, -130, 312, 642, 515, 189, + 57, 187, 415, 538, 467, 277, 109, 134, 334, + 441, 299, 59, -7, 128, 228, 146, -20, -99, + -34, 60, 24, -108, -188, -147, -57, -48, -142, + -224, -210, -144, -122, -175, -212, -176, -150, -199, + -256, -210, -100, -79, -195, -298, -248, -107, -48, + -110, -192, -224, -189, -112, -40, -31, -124, -238, + -193, -3, 87, -53, -221, -165, 48, 132, -2, + -150, -109, 61, 147, 83, -20, -60, -13, 85, + 157, 130, 17, -68, -10, 147, 217, 116, -20, + -21, 103, 200, 158, 52, 35, 105, 155, 132, + 81, 74, 110, 114, 74, 48, 68, 100, 77, + 27, 30, 48, 19, -15, 7, 63, 53, -56, + -123, -41, 81, 75, -61, -154, -84, 45, 68, + -24, -105, -76, 22, 53, -13, -63, -21, 54, + 59, -1, -34, 16, 80, 81, 48, 37, 61, + 89, 88, 101, 134, 132, 100, 83, 125, 188, + 173, 101, 95, 172, 214, 149, 68, 94, 181, + 177, 103, 83, 132, 165, 122, 83, 140, 191, + 153, 92, 106, 198, 226, 138, 85, 146, 215, + 187, 110, 77, 115, 146, 115, 91, 96, 78, + 27, -3, 42, 102, 71, -23, -46, 30, 95, + 63, -18, -25, 77, 174, 138, 13, -25, 96, + 218, 181, 34, -70, -45, 17, 2, -67, -174, + -346, -516, -553, -446, -455, -789, -1213, -1308, -1046, + -878, -1179, -1691, -1839, -1528, -1219, -1292, -1623, -1772, + -1538, -1147, -921, -951, -1038, -929, -549, -95, 155, + 127, 97, 387, 931, 1339, 1380, 1234, 1276, 1661, + 2102, 2223, 2027, 1848, 1942, 2198, 2295, 2119, 1856, + 1725, 1745, 1752, 1601, 1335, 1102, 993, 952, 830, + 570, 286, 139, 133, 85, -135, -436, -638, -645, + -571, -620, -835, -1064, -1151, -1069, -951, -964, -1109, + -1209, -1162, -1044, -961, -944, -977, -1001, -912, -687, + -517, -623, -887, -897, -469, 10, -35, -590, -934, + -545, 184, 427, -53, -619, -563, 40, 489, 339, + -128, -306, -6, 403, 497, 232, -55, 0, 388, + 704, 584, 145, -76, 260, 816, 942, 485, 2, + 65, 575, 923, 744, 290, 76, 276, 596, 662, + 419, 134, 92, 280, 434, 344, 88, -66, 8, + 151, 126, -81, -239, -176, -29, -74, -351, -574, + -487, -208, -132, -426, -780, -797, -577, -595, -978, + -1169, -667, -36, -548, -2285, -3281, -1756, 927, 1236, + -1911, -5006, -4073, -66, 2017, -295, -3701, -3797, -892, + 975, -165, -1978, -1636, 374, 1482, 679, -567, -591, + 706, 2337, 3224, 2743, 1269, 287, 1221, 3597, 5083, + 4106, 1858, 972, 2334, 4096, 4167, 2806, 1916, 2383, + 3045, 2508, 1220, 820, 1784, 2669, 1981, 204, -876, + -470, 510, 803, 170, -787, -1568, -1893, -1598, -1027, + -992, -1803, -2610, -2484, -1905, -2113, -3113, -3399, -2267, + -1261, -2007, -3637, -3909, -2340, -893, -1158, -2272, -2486, + -1639, -915, -777, -596, -91, 196, 85, 210, 875, + 1373, 1247, 1219, 1958, 2718, 2328, 1196, 1008, 2350, + 3677, 3269, 1503, 366, 922, 2264, 2810, 1996, 608, + -168, 75, 680, 811, 395, -56, -318, -607, -966, + -1108, -925, -613, -368, -369, -919, -1926, -2460, -1685, + -300, 155, -611, -1524, -2204, -3227, -3859, -2037, 1622, + 2382, -2583, -8448, -7544, -84, 4814, 915, -6423, -7558, + -1746, 2515, -59, -4587, -3858, 1260, 3625, 187, -4148, + -3500, 1542, 5467, 4780, 1256, -1127, -403, 2481, 5332, + 6346, 5014, 2536, 1216, 2467, 5039, 6238, 5070, 3381, + 3269, 4173, 3905, 2248, 1586, 3299, 5240, 4362, 1004, + -1382, -489, 2113, 3168, 1620, -742, -1824, -1435, -897, + -1058, -1500, -1545, -1398, -1965, -3266, -4136, -3756, -2609, + -1804, -1986, -3087, -4599, -5296, -4051, -1731, -781, -2228, + -4092, -3977, -2325, -1353, -1568, -1490, -428, 178, -672, + -1650, -1058, 749, 2039, 2079, 1540, 897, 310, 572, + 2266, 4265, 4265, 1869, -231, 559, 3332, 4752, 3229, + 768, 101, 1364, 2463, 1984, 819, 411, 723, 675, + -162, -923, -743, -32, 185, -516, -1653, -2359, -2103, + -986, 42, -205, -1702, -2870, -2337, -809, -221, -982, + -1544, -946, -598, -2117, -4291, -4100, -857, 1948, 338, + -4799, -7972, -5403, 173, 2371, -1063, -5533, -5578, -1777, + 605, -985, -3249, -2213, 1184, 2691, 560, -2356, -2288, + 1233, 5244, 6441, 4004, 370, -663, 2555, 7404, 9282, + 6573, 2612, 1836, 4662, 7467, 7393, 5421, 4262, 4741, + 5362, 4705, 3163, 2397, 3337, 4887, 4810, 2254, -749, + -1316, 772, 2706, 2016, -573, -2552, -2746, -2012, -1647, + -1978, -2579, -3105, -3473, -3911, -4484, -4891, -4795, -4163, + -3543, -3538, -4275, -5356, -5743, -4637, -2614, -1301, -1825, + -3341, -4011, -2937, -751, 1007, 1245, 235, -639, -61, + 1626, 2864, 2967, 2734, 3013, 3329, 2914, 2312, 2666, + 3839, 4308, 3162, 1453, 768, 1255, 1887, 2006, 1715, + 1031, -297, -1660, -1690, -277, 813, -30, -2137, -3370, + -2854, -1553, -593, -413, -1146, -2567, -3440, -2369, -205, + 379, -1258, -2315, -812, 262, -3205, -8576, -7894, 738, + 7492, 1951, -11595, -17098, -6934, 7139, 8065, -4575, -14199, + -8946, 3606, 7504, -547, -8242, -5113, 4406, 8113, 2134, + -5040, -4089, 4157, 10934, 10158, 4167, -565, -192, 4428, + 9765, 12201, 9861, 4512, 1225, 3451, 8483, 10133, 6497, + 2574, 3333, 6806, 6986, 2487, -1214, 623, 5416, 6647, + 2204, -3289, -4556, -1565, 1544, 1525, -1236, -4293, -5695, + -5174, -3995, -3403, -3449, -3750, -4505, -6014, -7296, -6523, + -3849, -2096, -3288, -5722, -6004, -3581, -1497, -1960, -3330, + -2800, -434, 964, -111, -1739, -1136, 1736, 4151, 3736, + 1274, -451, 469, 3386, 5833, 5898, 3646, 1085, 272, + 1743, 4061, 5108, 3837, 1490, 246, 967, 1866, 859, + -1069, -974, 1542, 2835, 47, -4285, -5068, -1567, 1781, + 1223, -1997, -4227, -3747, -1720, 41, 245, -1228, -2972, + -2673, 22, 1980, -930, -7721, -11271, -5725, 4974, 8484, + -2007, -16979, -19255, -4670, 11057, 9690, -6417, -17537, -10841, + 4262, 9292, 206, -9128, -6224, 4828, 10018, 3699, -5183, + -5121, 4702, 14279, 14466, 5778, -2633, -2185, 7036, 16118, + 16305, 8081, 390, 499, 6580, 11150, 10036, 5704, 2902, + 3378, 4664, 3786, 863, -796, 1216, 4609, 4493, -338, + -5670, -6486, -2751, 884, 571, -3095, -6446, -6997, -5770, + -5041, -5016, -4216, -2579, -2468, -5088, -8129, -7964, -4228, + -323, 497, -1556, -3653, -3615, -1718, 464, 1808, 2386, + 2832, 3085, 2905, 2676, 3473, 5501, 7094, 6442, 3929, + 1663, 1436, 3254, 5807, 7100, 5044, -34, -4091, -2992, + 2149, 5333, 2562, -3067, -5877, -4480, -2080, -1793, -3026, + -3838, -3735, -3663, -4472, -5756, -5753, -3576, -640, -274, + -3965, -7787, -6757, -717, 4380, 3595, -1553, -5936, -8603, + -10223, -8952, -922, 9700, 9355, -7788, -25795, -22413, 2268, + 20887, 12133, -11291, -20129, -5899, 10236, 8585, -3645, -6300, + 4667, 14216, 9346, -3593, -8558, 715, 15085, 21179, 14887, + 3733, -2703, -675, 7170, 15131, 18360, 13959, 4205, -2825, + -656, 7594, 11845, 7182, 319, -439, 3255, 3213, -3299, + -8972, -6318, 2300, 7190, 2254, -9247, -17334, -15064, -4452, + 5160, 5127, -4268, -14501, -17256, -11145, -1830, 3786, 2984, + -2498, -8101, -9587, -5703, 622, 4570, 4035, 1442, 729, + 2493, 3534, 2433, 2239, 5944, 11438, 12371, 6496, -211, + -156, 7092, 13566, 11979, 3928, -2545, -2226, 2713, 6150, + 5117, 1270, -1851, -2859, -2376, -1909, -2364, -3401, -4183, + -3897, -2875, -3205, -5503, -7822, -7501, -3934, -942, -1572, + -4262, -5939, -4671, -2353, -1387, -1159, -1270, -1328, -606, + 474, 1044, -2647, -11603, -17081, -10374, 5922, 14849, 2056, + -22033, -31238, -14612, 11094, 17910, 1778, -15538, -15417, -2045, + 6690, 2855, -2559, 473, 8823, 11423, 3782, -4649, -2775, + 9111, 20847, 21610, 11572, 962, -1465, 5731, 15559, 20008, + 16950, 9230, 2204, 114, 3088, 8130, 10523, 7643, 2045, + -2107, -2945, -2538, -3593, -5210, -4403, -857, 1328, -2497, + -11667, -18881, -16866, -6286, 3400, 2835, -7811, -18322, -19279, + -10025, 1525, 6930, 3766, -4647, -11401, -9904, -322, 10100, + 12428, 5874, -274, 926, 6762, 9360, 6778, 5904, 10509, + 15077, 12681, 3846, -1653, 2460, 11036, 14737, 8967, -1021, + -6168, -3899, 2328, 6041, 3404, -2878, -7672, -6869, -1918, + 801, -2188, -7419, -8083, -2687, 1898, -692, -8121, -11198, + -5642, 2830, 5915, 1120, -5666, -8314, -5770, 118, 4614, + 4713, 1482, -2544, -3331, -3779, -8931, -13840, -10273, 3355, + 13432, 2906, -20058, -30890, -17080, 7759, 16047, 2886, -12525, + -15117, -5998, 1614, 2294, 2684, 4610, 6236, 5486, 2514, + 1346, 1962, 4564, 11022, 17438, 18182, 10179, -796, -3019, + 5456, 15942, 18468, 11176, 2796, -143, 1670, 3922, 3836, + 3337, 3330, 1623, -2609, -7177, -7654, -4250, -2210, -3491, + -5312, -4380, -3103, -6738, -13209, -14278, -6529, 3346, 4931, + -2861, -11176, -12097, -5552, 2679, 7102, 6050, 1301, -3350, + -3378, 1785, 7413, 9059, 7013, 5043, 5331, 5197, 3143, + 1862, 3790, 8037, 10159, 7236, 1450, -3393, -3980, 598, + 6251, 7410, 1502, -7144, -10260, -5116, 2386, 4197, -894, + -6255, -6026, -1493, 873, -1639, -4426, -2720, 2252, 4206, + 158, -4631, -4466, 537, 4709, 4528, 1691, -828, -1394, + -455, 756, 2662, 3101, 1730, -3579, -12987, -18531, -12998, + 1944, 11963, 1503, -19826, -29919, -18138, 2254, 7644, -1829, + -9260, -6516, 134, -793, -5234, -2336, 6264, 12828, 11829, + 6589, 3429, 2592, 4795, 11433, 19490, 21681, 13136, 379, + -4138, 3585, 14812, 17633, 10124, 623, -2287, 696, 2273, + -926, -5000, -4391, -386, 139, -4657, -11003, -13946, -11930, + -7460, -1932, 1277, -2311, -10543, -16920, -14512, -4039, 4987, + 7518, 3175, -4213, -7535, -4747, 3590, 12231, 13419, 8429, + 2377, 1080, 5563, 8497, 7304, 5331, 5656, 8235, 6997, + 998, -3131, -1857, 3017, 5883, 3744, -408, -4503, -6489, + -4796, -374, 3254, 1651, -2830, -5206, -3690, -681, -969, + -2819, -2616, 19, 3379, 2359, -2476, -6413, -6111, -463, + 4664, 4106, -565, -4801, -4960, -1242, 2479, 3706, 2168, + -1104, -3048, -1563, 1217, 2013, -5714, -17921, -21743, -10839, + 7751, 13091, -4648, -26509, -29653, -9872, 10100, 9523, -4335, + -12121, -5509, 4923, 6380, 1839, -508, 3312, 10704, 14545, + 12317, 5508, -243, 2421, 11485, 19096, 18306, 8626, -1357, + -5542, -1695, 7815, 13549, 10229, -23, -8373, -7496, -2775, + -1016, -2900, -4868, -4103, -4535, -6851, -8099, -8137, -6414, + -4023, -1790, -45, -1513, -4791, -6160, -4105, 1060, 5970, + 7099, 3934, -996, -2213, 1973, 6975, 7927, 4726, 2474, + 3951, 5221, 2642, -2359, -3579, 1362, 6614, 6282, 116, + -5643, -5733, -1884, 2107, 3418, 2566, 684, -2319, -3803, + -2133, 1512, 2943, 475, -1004, 753, 3095, 1652, -3074, + -4562, -932, 3815, 4486, -22, -4199, -4666, -2201, 284, + 316, -914, -2297, -2441, -1538, -435, 909, 626, -1222, + -1534, -429, 1711, 2386, -1786, -10676, -18200, -16272, -3805, + 9505, 8238, -9397, -24577, -22256, -4907, 8659, 5940, -3701, + -6764, 40, 6190, 4239, 208, 238, 7081, 14458, 15143, + 10726, 3479, -706, 1700, 9131, 17577, 17708, 7959, -5009, + -11508, -5347, 5635, 10789, 6499, -3121, -9303, -9814, -6625, + -3333, -3193, -4349, -5615, -6188, -5123, -4441, -4550, -4074, + -2769, -61, 2441, 2881, 1395, -578, -341, 2509, 6034, + 8202, 6377, 2696, 1272, 2589, 4787, 4611, 2378, 2124, + 3911, 4872, 2049, -3374, -5770, -2705, 3179, 5905, 2589, + -2792, -5419, -3176, 1056, 2875, 2483, 1205, 605, 856, + 1012, 892, 105, -411, 707, 2924, 4184, 1755, -2553, + -4857, -3556, 401, 2466, 945, -2315, -5556, -5549, -2241, + 534, 601, -1774, -3034, -1962, -886, -448, -720, -467, + 864, 760, -22, -2546, -10211, -17121, -15877, -4803, 7993, + 7254, -6563, -18374, -17755, -6143, 3291, 4322, 1822, 416, + 2788, 5190, 4256, 2627, 2590, 6398, 12709, 15757, 12829, + 5542, -667, 167, 7241, 14346, 14826, 6392, -3516, -7434, + -4607, 1054, 2988, 847, -1549, -2641, -3046, -5363, -8256, + -9130, -6906, -1460, 2260, 1568, -2911, -8580, -9418, -3675, + 5021, 10127, 7909, 1478, -4015, -3331, 2450, 7291, 7632, + 2567, -2022, -899, 3418, 5544, 1349, -4117, -3409, 1758, + 6000, 3526, -3975, -7331, -3931, 2747, 7037, 4962, -21, + -2902, -2008, 1306, 4461, 6364, 5956, 3623, 1734, 793, + 44, -893, -1041, 1633, 5264, 4870, -943, -7404, -8611, + -4974, -1192, 185, -1334, -3672, -4910, -5132, -4387, -3532, + -3233, -2430, -469, 1245, 892, -969, -2441, -2140, 320, + 4999, 5954, -4638, -20056, -24424, -8954, 13558, 16089, -3145, + -20665, -19447, -4802, 4488, 3733, 943, 683, 3109, 6219, + 9247, 7736, 782, -1410, 8024, 20877, 20174, 4723, -7148, + -2758, 11240, 17896, 11462, 414, -6134, -4913, 113, 2818, + 98, -5900, -8369, -4446, 924, 1657, -3389, -10569, -13223, + -7690, 2339, 7741, 1634, -9014, -10982, -1172, 9642, 9098, + 1310, -2795, -1040, 2790, 3808, 3559, 3064, -527, -3160, + -1391, 3120, 5224, -144, -6714, -6416, -719, 5630, 7253, + 2735, -2973, -4325, 679, 7146, 8220, 4055, -42, 814, + 5288, 7658, 6592, 3051, -746, -541, 3401, 6030, 1953, + -6340, -8619, -2689, 4076, 3217, -4875, -9612, -7826, -4293, + -2441, -4080, -5740, -5529, -3656, -506, -1035, -5787, -9518, + -7034, 2323, 9287, 6495, -1853, -6110, -3281, -1708, -8958, + -19544, -18870, -2771, 13029, 10762, -7491, -21837, -18923, -4183, + 8733, 12580, 9779, 4597, 738, 1460, 6302, 9711, 8375, + 8143, 12512, 15808, 11272, 389, -5554, 161, 11080, 15851, + 10426, 692, -6372, -6808, -2525, 652, 827, -219, -349, + -622, -3328, -7883, -11020, -8961, -3240, 1884, 4155, 1995, + -3530, -7816, -6444, -218, 6086, 9279, 7901, 3113, -2352, + -5757, -3836, 2022, 4572, 894, -3519, -3311, -534, -618, + -3716, -5515, -3290, 1495, 4374, 4455, 2961, -645, -3247, + -656, 5273, 9838, 9751, 5755, 1863, 158, 1457, 4585, + 6390, 5379, 2894, 2284, 1867, -2279, -7051, -6578, 70, + 4745, 1660, -4524, -8007, -7088, -5690, -5467, -4178, -2679, + -2218, -3422, -4167, -4313, -6105, -6633, -4202, 864, 5119, + 4084, -163, -5331, -8699, -8710, -7313, -4649, -2471, -1419, + -1136, -3199, -6428, -8048, -4902, 1089, 4681, 5723, 5535, + 5146, 4006, 2052, 2314, 5274, 8680, 9907, 8776, 6722, + 2548, -2403, -3303, 1224, 7406, 9468, 5089, -1197, -4384, + -3570, -298, 1776, 2005, 2041, 1326, 971, -180, -2334, + -1170, 1913, 4281, 4732, 2874, 1174, -1341, -3384, -2503, + 368, 4031, 3270, -986, -3519, -5360, -6004, -5576, -3603, + 208, 708, -2137, -4940, -5349, -3588, -2796, -1399, 1017, + 3144, 4196, 2483, 828, 338, 919, 3842, 6202, 7189, + 7499, 6330, 4847, 3252, 2136, 3698, 5845, 5566, 3019, + 267, -55, -1091, -4220, -5041, -3430, -280, 171, -4649, + -8723, -9280, -5975, -3192, -3974, -3912, -4053, -3748, -3570, + -5871, -5499, -3552, -1691, 320, 341, 748, -313, -3436, + -4687, -3681, 21, 2550, 643, -2123, -3254, -2226, -1044, + -1617, -1510, 183, 1250, 726, -1662, -3388, -1759, 933, + 3817, 5242, 3025, 248, -1339, -514, 2022, 3410, 3970, + 3324, 2632, 2603, 2240, 2166, 1271, 487, 1076, 2039, + 3296, 3836, 3610, 2913, 2718, 4213, 5555, 6023, 4769, + 2442, 2067, 2173, 1623, 1201, 348, 52, -124, -1528, + -2834, -3604, -3463, -2357, -2564, -3775, -3801, -1929, -465, + -2109, -3743, -2657, 200, 2580, 954, -1304, -95, 1549, + 2303, 1795, 1633, 3356, 3699, 2361, 792, 1148, 4045, + 4820, 3851, 3197, 2449, 2704, 1722, -652, -1154, -393, + 113, -1010, -3328, -4342, -3939, -3345, -3697, -5115, -5610, + -4202, -3639, -5088, -5351, -3216, -862, -414, -1839, -3996, + -4831, -2467, 147, 1055, 1288, -247, -2225, -2233, -1562, + -1278, -936, -961, -935, -367, -323, -459, -1940, -3974, + -2262, -13, 2, -401, -1825, -2308, -1124, 448, 2154, + 2434, 1300, -812, -1337, 1325, 3374, 3466, 2500, 2156, + 3439, 3549, 2068, 1392, 1986, 3025, 3944, 3898, 3259, + 4467, 6347, 5356, 2893, 1690, 2072, 4136, 5313, 2776, + -236, -1063, -794, 524, 802, -1377, -2879, -2167, -1439, + -1595, -1539, -1666, -2495, -2375, -1253, -515, -187, -1409, + -2847, -511, 2411, 1761, 492, -18, 607, 2350, 3288, + 3505, 2741, 1099, 699, 2017, 3214, 3333, 1567, 33, + 1260, 1925, 808, -377, -2558, -3781, -1677, 164, -580, + -1727, -2619, -3421, -3586, -3957, -4562, -3646, -2285, -3437, + -5293, -4792, -4128, -4012, -2920, -2249, -2439, -3737, -5607, + -4427, -1259, 71, 609, 555, -1039, -3354, -5388, -3760, + 415, 2513, 2513, 819, -1436, -2780, -2740, -501, 2727, + 3936, 1491, -965, -766, -484, -223, 361, 695, 1771, + 1130, -1839, -1764, 797, -31, -2549, -1790, 2108, 4043, + 887, -154, 2411, 2605, 2012, 1977, 3923, 6630, 4176, + 107, -311, 1731, 1910, 1011, 3119, 3219, 998, -1282, + -2832, -1645, -685, 945, 2574, 2543, -267, -5015, -3819, + -342, 1228, 2055, -619, -1233, 2069, 2896, 1095, 62, + 1365, 3366, 4584, 4956, 3323, -19, -50, 4024, 5222, + 3695, 3118, 1933, 1256, 1443, 128, -119, 2043, 2477, + 1823, 1324, 30, -1363, -3023, -3074, -188, 621, -1775, + -2806, -2961, -2753, -4359, -5350, -1220, -116, -4157, -4811, + -2793, -1040, -1957, -2862, -1901, -3192, -3720, -2357, -1727, + -387, -2131, -5011, -3650, -454, 596, -1298, -3716, -3122, + 496, 136, -2415, -1675, -811, -837, 140, -1243, -187, + -1431, -5320, -2121, 100, -467, 2465, 681, -2093, 1224, + 1632, 1428, 1776, 648, 2480, 3622, 876, 259, 1403, + 2139, 3117, 497, -763, -170, 279, 1769, 342, -871, + -25, -1549, -2290, 290, 1042, -796, -4291, -3895, 159, + 1264, -540, -2328, -702, 1972, 852, -2274, -798, 1126, + -579, -480, 3481, 3833, 1004, 901, 1536, 1809, 3103, + 2521, 3183, 5220, 1800, -266, 4663, 4230, -790, 159, + 2274, 5114, 4304, -1998, 344, 4921, -343, -2048, 1180, + 2112, 3109, -10, -1818, 552, -1360, -2889, -1302, -1918, + -37, 1406, -1762, -3054, -1446, -2073, -4292, -3214, 1163, + 2333, -712, -2583, -2058, -1034, -600, -3796, -2395, 2137, + -1122, -1927, 702, -2196, -4374, -3257, -1558, -256, -728, + -395, -176, -1529, -2772, -1121, -340, -1147, -250, -4079, + -473, 4241, -2818, -3523, 3255, 2355, -2550, -1082, 1197, + 2213, -94, -237, 3123, 1314, -1075, 977, 1081, 2045, + 2966, -1328, -1069, -741, -524, -380, -2766, -986, 926, + -3281, -1554, 2554, -3620, -6394, -1680, -321, 2889, 243, + -1567, 2276, -1294, -525, 2010, -4883, -1495, 6778, 2085, + -873, 2496, 418, -1156, -1179, 1604, 6173, 1190, -2381, + 5788, 2431, -4941, -242, 1248, 1023, 4426, 3399, 2726, + 1388, -922, 595, 392, 1414, 6260, 2673, -973, 2237, + 1776, -2393, -757, 4158, 2842, -2327, 505, 1230, -3623, + -917, 336, -1400, -1018, 1771, 2696, -570, -2435, 886, + 2309, -2865, -1328, 2077, -1967, -3486, -411, 961, -1661, + -1979, 1179, -493, -2597, 1995, 284, -3300, -2213, 184, + 312, -1665, -641, -1325, -1276, 90, 69, 476, -778, + -1099, 853, 1515, 1630, 1188, -877, -1751, 702, 2983, + -201, 664, 4018, -352, -1864, 875, 2367, 813, -2463, + -702, 886, -2204, -2216, 399, -1729, -2408, 1412, -2757, + -3530, 449, -2554, -3910, 906, 697, -1696, 566, -1360, + -1991, 81, -1756, -159, 1180, -667, -584, -359, 183, + 1943, -412, -1747, 1659, 1961, 280, 294, 222, 2000, + 2076, 829, -43, -880, 3353, 3615, 1279, 1746, -1031, + 1301, 3477, -777, 2567, 1215, -2344, 3556, 561, -2166, + 1119, 2377, -391, -1825, -2359, 49, 1764, 391, -291, + 325, 1223, 1443, -624, -2828, 1381, 2438, 28, -652, + -166, 581, -2039, -374, -20, -2459, -1149, 1505, 2008, + -1798, -3848, -1796, -2208, -2224, -878, 728, -154, -534, + 1061, 538, -1465, 73, 1147, 82, -119, 3800, 4797, + -873, 784, 1458, -148, 3180, 1319, 908, 4951, 584, + -57, 2394, -967, 586, 405, -1601, 3566, -285, -3949, + -1301, -1953, -1223, -1831, -3477, -779, -389, -3169, -1828, + -1496, -1451, -556, -3327, -209, 534, -4908, 131, -386, + -5232, 1373, 2129, -1740, -1957, -1102, 76, 396, -1426, + -179, 1357, -3276, -1420, 3819, -44, 56, 2777, -1202, + 1908, 1410, 2031, 3495, -2197, -163, 1565, 239, 2803, + 480, -1636, 1180, 616, 1206, 1166, -1579, 1572, 814, + -774, 2310, 740, -2606, 1234, -603, -362, 1562, -2134, + 652, -777, -2353, 5464, 377, -2490, 1012, 157, 680, + -1389, -1898, 1135, -1, -1730, 1800, -1466, -1687, -1469, + -3250, -1081, 1381, -81, -204, -26, 353, 1941, 174, + 104, 2009, 1032, -871, 3280, 3398, -651, -154, 3309, + 1964, 448, 812, -17, 887, 2405, 3295, -54, -2396, + 1410, 1380, -1156, 296, -1706, -1729, 401, -970, -878, + -723, -2285, 1259, 1320, -1960, -1039, -211, -661, -763, + -1599, -43, 308, -1841, 72, -2075, -3010, -497, 506, + -377, 247, 1932, -1788, -2419, 257, 208, -2176, 488, + 2827, -1720, -1649, -619, 520, 1103, -1231, -1327, 2162, + 1535, -383, 315, -1488, -235, 1761, -27, -232, 515, + 127, -2239, 654, 2871, -379, -1274, 2445, 874, -2444, + 514, -206, -1289, 1314, 1869, 1316, 1878, -1454, -982, + 476, 359, 2084, -708, 405, -246, -1071, 1757, -866, + -2331, 783, 501, -853, 896, 36, -2468, -1138, 1445, + -613, -687, 1999, -449, -731, 1478, 384, -45, 96, + 1530, 1919, 186, -94, 1347, -329, -348, 1631, 574, + 1062, 735, -1652, 675, 244, 1241, 1137, -2469, 621, + 45, -612, 1308, -2015, -208, 2392, -1646, -67, 77, + -1558, 113, 1263, -236, -971, -333, -733, -555, 2024, + -135, -3817, -398, 1696, -1179, -1473, 1175, -166, 618, + 1132, -2504, -575, 146, -688, 1323, 150, -2021, 15, + 1673, 347, -1535, -106, 235, -32, 1167, -471, -503, + -1260, 416, -13, -1082, 1036, -790, -1676, 487, 985, + 77, 57, -1175, 1146, 2023, -1706, -404, 3249, -739, + -979, 3044, -514, -168, 2201, -2863, 1009, 1833, -2309, + 1565, 476, -1698, 1667, -496, -2193, 1686, 532, 336, + -1095, -1655, 578, -909, -1263, 2569, -2833, -1808, 2860, + -822, 27, 1098, -1371, 1585, -284, -1074, 2944, -764, + -2871, 2484, 1179, -1213, -670, -1226, 1112, 1837, -299, + -388, -51, 1, 992, -723, -361, 1723, -1115, -2012, + 1261, -9, -127, -510, -1550, 1448, 957, -1930, 171, + 776, -2104, 14, 764, -599, -745, -438, -371, -659, + 1075, 282, -3116, 684, 3747, 22, -2139, 816, 1413, + -333, 458, 906, 483, -1084, 797, 1039, -467, -377, + 1386, -1182, 610, 1787, -1354, -2800, 2638, 424, -2372, + 1153, -51, -689, 290, -2199, 818, 3755, -2674, -1689, + 3497, -507, -1978, 1729, 1413, 215, -76, 53, 759, + 371, -1529, 1005, -770, -685, 1754, -908, -653, 1047, + -1066, -784, -199, -526, 86, -1750, -916, 1839, 580, + -1884, 319, 226, -977, 212, 202, -741, -1013, 2057, + 69, -2961, 974, 1964, -512, -224, 1554, -79, -1142, + 1853, -71, 1009, 1174, -718, 2040, -158, -1508, 1042, + 0, -1219, 1212, 448, -208, -47, -779, -867, 1924, + -254, -1085, -221, -1283, 1543, -584, -951, 225, -1089, + -464, -853, -615, 1576, -2313, -1214, 950, -2548, -314, + 1201, -1527, 952, 764, -1915, 528, 169, -1676, 1742, + 425, -2346, 932, 290, 109, 492, -379, 932, 70, + 582, 135, 769, 1665, -1751, 576, 1013, 366, 2339, + 71, 637, 1500, 576, 111, 494, 765, 1170, 1421, + -5, -892, 2054, -640, 160, 1426, -651, 348, -841, + -558, 1563, 277, -408, -1468, 482, -1538, -2255, 968, + -1307, -454, 1306, -3085, -1680, 2624, -2191, -1719, 1891, + -3826, -1441, 2736, -3694, -266, 1897, -4468, 841, 2828, + -4060, -318, 2305, -1662, 528, 3056, -2429, -156, 2045, + -753, 475, 419, -597, 1100, 1845, 504, 1067, -402, + -824, 1807, 1192, 459, 200, 1728, 50, -497, 678, + -355, 938, 1239, -1223, 360, 1251, -95, 981, 1029, + -1940, 260, 1627, -2387, 3426, 519, -3141, 1822, -506, + -1471, 1101, -2137, 1069, 885, -2618, 1673, -463, -1558, + 1439, -386, -1923, 1538, -1313, -1735, 540, -1433, -915, + 494, -839, -1527, -1143, 480, -1081, 27, 1732, -1285, + -1833, 1952, -667, -1626, 1819, -1293, -1323, 2139, -376, + -1392, 1277, -1172, -240, 2907, -1875, -238, 2573, -1068, + -471, 2065, -686, -1315, 2575, 233, -1005, 1135, 706, + 534, 278, -182, 1091, -21, -222, 1413, -371, -54, + 1108, -103, 382, -70, 787, 894, -108, 1308, 1113, + -1412, 574, 1140, -2032, 500, 569, -1251, 951, -50, + -1398, 772, -474, -1536, 1297, 251, -2321, 109, -703, + -425, 40, -1354, -773, -225, -1743, -1839, 1244, 261, + -3082, -424, 1162, -937, 123, -322, -407, -561, -331, + 1369, -1142, -1050, 1024, 1116, -213, -752, 1521, -383, + -415, 1011, 947, -713, 743, 1945, -237, 881, 600, + -757, 885, -835, 756, 2454, -1985, 699, 1572, -1652, + 673, 232, -42, 1975, -736, -270, 1660, -704, -96, + 1264, -428, 278, 774, -954, -1325, 756, 1275, -594, + -353, 204, -1130, -782, -432, -979, 268, 378, 20, + -870, 405, -357, -1661, 637, 473, 293, -314, -895, + 3, -175, -1016, -643, 204, -588, -1007, -131, 401, + -849, -476, 271, 320, -198, 533, -25, -1994, 1421, + 525, -1611, 1261, 507, -488, 1093, 361, -1814, 2230, + 312, -196, 3242, -803, -962, 1714, -1479, 1426, 1612, + -1953, 1376, -581, -669, 1370, -1251, 426, 1274, -470, + 1757, 807, -589, 1275, 126, -871, 1025, -1331, 287, + 1258, -1813, 146, -839, -1471, 828, -402, -281, 1704, + -1341, -231, 939, -1035, -472, -197, -764, -380, -816, + -266, 382, -497, -1708, -591, 1119, -1941, 178, 969, + -1656, 685, 1004, -1114, -127, -1473, -678, 1610, -1253, + 277, 1807, -1642, -461, 2033, -1449, 392, 98, -157, + 1525, -860, 2455, 413, -2159, 2457, 475, -374, 1532, + -981, 843, 973, 324, 1168, 225, -407, 1487, 681, + -680, 1098, 117, 245, 1238, -223, 1076, -428, -466, + 2593, -663, -1225, 1303, -933, -561, 1190, -1071, -1229, + 406, -284, -13, 198, -1494, -637, 352, -1960, 420, + 49, -1472, -761, -234, -2213, -1750, -521, -1554, -813, + 662, -633, -1388, -15, -947, -391, -152, -894, 631, + -461, -885, 633, -51, -1063, 218, 1149, -61, -274, + 988, -140, 7, 1774, 1558, -623, 755, 1352, -511, + 1106, 744, 17, 2640, -91, 697, 1547, -1757, 1832, + 1859, -206, 1505, 575, -444, 556, 250, 1786, 792, + -125, -266, 407, 501, 798, -536, -1214, 58, 6, + 354, -685, 613, 99, -2022, -116, -236, -182, 263, + -824, -1187, -142, -138, -1228, -1008, 786, -1421, -1127, + -269, -2278, 841, 222, -2423, 678, -1153, -2082, 574, + -570, -729, 180, -777, 212, 270, -274, 1077, -493, + 118, 804, -1260, 349, 799, 545, 481, 971, 1099, + 1146, -273, 34, 1728, 1128, 411, 758, 308, -808, + 950, 1490, 209, -265, 1154, -11, -460, 2644, -122, + -728, 2033, -1100, -305, 1774, -208, -1567, -57, -140, + -670, -454, -1390, -80, 978, -438, -731, -684, 344, + -458, -199, -126, -1663, -883, 642, -1517, -1144, -375, + -422, -452, -1815, -791, 763, -1502, -205, 684, -1641, + 448, 1399, -2160, 804, 1088, -2214, 1030, 1585, -1093, + -11, 1718, -360, -81, 1294, 398, 218, 1225, 644, + 505, 2090, -385, 526, 2111, -303, -316, 1550, 1323, + -459, 881, 1874, -1256, 1429, 2485, -1003, -552, 14, + 432, 952, 471, -633, 408, -358, 140, 554, -1260, + -404, 245, -2572, 954, 1005, -1621, -82, -175, -957, + 112, 106, -1117, -819, -62, -785, 71, 93, -1296, + -1680, 242, -956, -2696, 302, -204, -1404, 254, -558, + -201, -630, 16, -436, -1647, 1649, -1096, -1267, 2273, + -1270, 20, 1749, -2509, 780, 942, -1859, 2762, 304, + -300, 2617, -947, 861, 2601, -1153, 754, 1629, -681, + 686, 1443, -235, 1900, 5, -565, 1559, 285, -170, + 757, 480, 547, 752, -427, 50, 839, -95, -791, + -1698, -291, -62, -1730, 524, 1008, -2176, -369, 165, + -749, -972, -287, 889, -1218, -1712, 833, -855, -995, + -14, -793, -1815, 605, -607, -1890, 769, -781, 230, + 1155, -2000, 876, 1835, -1617, 9, 1058, -1232, 859, + 1486, -1301, 1595, 501, -951, 2935, -921, -634, 2826, + -793, 655, 2660, -232, 235, 1879, 481, -51, 804, + 987, -360, -331, 2099, -302, -149, 1966, -1233, -12, + 1330, -2265, 1256, -116, -1394, 2937, -995, -1572, 2964, + -2257, -2587, 1820, -2132, -1609, 778, -1596, -486, 560, + -1749, 274, -706, -1714, 1304, -360, -2657, 1833, -750, + -1729, 433, -1461, -794, -1545, -892, 385, -891, -374, + 1261, -589, 235, 815, -773, -669, 636, -471, 136, + 871, -392, 782, 677, -472, 1130, 1029, -1262, 1070, + 2171, 575, 675, 600, 2104, 1077, -182, 2621, -604, + -30, 3302, -1331, 599, 742, 291, 1329, -551, 1043, + 1729, -1754, 1220, 1113, -2174, 1281, 743, -2027, 851, + -205, -1576, 214, -1629, -605, -394, -1508, -254, -63, + -489, -847, -26, -997, -1065, -120, -376, -1283, -1393, + 83, -212, -1610, 419, -1120, -590, 395, -1210, -21, + -273, -622, 899, -196, -1059, 1130, 616, -529, -166, + 794, 22, -216, 862, 664, -390, 980, 228, 789, + 182, 402, 2149, -1133, 799, 2637, -799, 176, 1306, + 905, -93, 677, 338, 121, 483, 297, 339, 347, + 249, 731, 40, 66, 112, -889, -128, 582, -1191, + -67, -1364, -233, 488, -1734, -634, 1517, -1657, -1015, + 594, -1422, 1396, -1357, -1617, 1254, -1596, -941, 789, + -1860, -77, 245, -327, 569, -723, 104, 905, -543, + -918, 1387, -42, -440, 619, 68, 45, 1364, -880, + 19, 1491, -561, 1174, 1403, -1411, 1351, 1222, -612, + 864, 877, -658, 382, 864, -552, 1286, 309, -105, + 1083, -170, -289, 1049, -248, -537, 625, -48, 337, + -385, 532, -315, -1398, 588, -628, -1192, 649, -806, + -170, 541, -2267, 1052, 274, -1970, 833, 253, -1345, + -290, -120, -959, -94, -189, -1397, -136, -155, -654, + 207, -706, 617, 415, -1962, 1169, 670, -1132, 319, + 297, -589, 100, 510, -620, 610, -153, -15, 1327, + -99, 229, 281, 169, 1015, -106, 1197, 577, -698, + 577, 931, -964, 1605, 505, -1713, 2369, 115, -1585, + 1839, 664, -1411, 867, 620, 329, 491, -1119, 420, + 266, -1708, 499, -69, -1037, 795, -321, -959, 32, + 235, -1748, 295, -249, -230, 485, -1185, -97, 489, + -2036, 711, 405, -2800, 593, 434, -1038, 536, 347, + -570, 705, -806, -290, 818, -999, 53, 1585, -756, + -657, 1180, 115, -364, 217, -226, 1033, 347, -20, + 611, 658, 590, -128, -451, 1676, -660, -21, 805, + -880, 1481, 412, -1534, 1522, 221, -132, 662, -407, + 613, 1132, -551, -187, 1184, -577, -444, 953, -1034, + -472, 461, -865, -99, 637, -572, 300, 450, -591, + 137, 404, -972, 306, -524, -1167, 433, 124, -1326, + -368, -305, -917, 452, -626, -695, 656, 258, -1401, + 270, 446, -1045, 636, -357, -1072, 913, 512, -1732, + 489, 952, -747, 58, 673, -453, 1125, -488, 46, + 1723, -1244, 417, 1803, -1215, 623, 659, -560, 676, + -9, 92, 701, 1100, -623, 142, 283, -512, 547, + 576, -525, -155, 1143, -1286, -329, 1959, -1302, -459, + 1188, -1199, 1020, -118, -1303, 956, -905, -647, 595, + -356, -1354, -74, 750, -791, -335, 56, -862, -36, + 276, -279, 46, -485, -181, 196, -584, -238, 259, + -314, -77, 383, 509, -386, -180, 859, -542, 955, + 372, -362, 1458, 113, -106, 1495, -534, 63, 1295, + -505, 846, 983, -1097, 1764, 320, -185, 1061, -525, + 115, 217, -328, 326, 312, 374, 179, -683, 485, + -1286, 147, -583, -979, 888, -504, -1235, 715, -1050, + -1111, 848, -828, -1043, -115, -327, 22, -451, -1008, + 98, -262, -545, -363, -48, -257, -731, 878, 96, + -1186, 426, 359, -1101, 1074, -267, 521, -375, -166, + 1398, -994, 780, 550, 124, -298, 581, 236, 305, + -111, 396, 741, -10, 662, 155, 271, 563, 65, + -318, 812, -483, 843, 75, -714, 1152, -26, -190, + -97, 533, -111, -564, 724, -24, -820, 835, -473, + -632, 154, -104, -932, 919, -606, -619, 496, -310, + -271, -360, 120, -630, 126, 65, -931, 548, -207, + -455, 410, -282, -931, 944, -354, 69, 412, -661, + 1068, -969, -443, 1894, -1281, -442, 2003, -1640, 713, + 852, -1344, 1338, -457, 243, 498, -697, -129, 993, + -388, -76, 1039, -768, 492, -104, -58, 951, -854, + 181, 1093, -1111, 491, 544, -1061, 118, 586, -477, + -411, 392, 233, 91, -908, 532, 218, -1176, 670, + -74, -674, 696, -801, 194, 592, -1790, 762, -564, + -791, 595, -145, -727, 228, 434, -246, -232, -169, + 281, -324, 289, -120, -270, -49, 282, 250, -56, + -405, 507, 27, -1060, 1329, -203, -204, 1677, -767, + -313, 1272, -968, 717, 183, -1652, 2157, -75, -1906, + 2590, -428, -1614, 2564, -1511, -240, 1421, -1911, 1420, + 396, -1397, 1691, -694, -1500, 1942, -823, -784, 841, + -635, 759, -447, 351, 44, -946, 227, 441, -564, + 155, -719, 182, 509, -320, -300, 205, -662, 726, + 469, -1240, 191, 664, -269, -152, -18, 214, -149, + -257, 347, 76, -79, -384, 874, -387, -269, 892, + -783, 537, 46, 27, 251, -332, 133, 377, -522, + 232, 626, -362, -499, 1112, -342, -522, 362, -187, + 547, -384, -155, 517, -551, 227, 651, -825, -88, + 579, -758, -40, 456, -774, 542, -164, -482, 968, + -1000, -394, 1094, -885, 431, 74, -348, 403, -959, + 831, -465, -330, 762, -717, -645, 1342, -499, -416, + 944, -417, -438, 737, -368, -42, 740, -1234, 689, + 29, -106, 619, -824, -10, 1047, -824, 146, -59, + 210, 163, -43, 522, -352, 213, 460, -1049, 599, + 308, -843, 632, 223, -504, 296, 530, -931, 751, + -176, -524, 379, 236, -626, 66, 662, -575, 191, + -175, -619, 660, -424, -217, 704, -498, 200, 62, + -543, 280, 91, -378, 54, 168, -554, 670, -215, + -1097, 1805, -1015, -617, 1642, -1560, 727, 61, 7, + -48, -659, 1308, -752, -613, 914, 160, -469, 164, + -167, 274, 326, -667, 497, 333, -757, 1252, -481, + -1257, 2019, -949, -719, 1676, -1078, 250, 323, -1100, + 1550, 145, -1697, 972, 522, -966, 374, -365, 846, + -276, -756, 629, -278, 302, -151, -243, -363, 841, + -7, -1092, 476, 45, 201, -378, -456, 1113, -926, + 97, 178, -240, 326, -597, 472, -10, -190, 394, + -501, -259, 307, 133, 240, -433, -192, 472, -190, + 12, 398, -191, -605, 1295, -576, -154, 474, -661, + 866, -968, 172, 887, -736, 36, 259, -201, 265, + 460, -859, 622, 102, -690, 776, -80, -745, 919, + 140, -750, 224, 134, -236, -196, 456, 409, -1069, + 600, 239, -306, -383, 541, -213, -323, -121, 700, + -735, 179, 222, -613, 653, -711, -81, 592, -694, + 117, 703, -772, -264, 644, -117, -422, 276, 64, + -355, -430, 800, -74, -619, 1207, -1057, 4, 960, + -1219, 977, -78, -1186, 1536, 267, -1388, 1144, -90, + -1052, 1889, -1255, -387, 1815, -1763, 1037, 421, -1003, + 767, -24, -277, -54, 759, -285, -1015, 1422, -581, + -121, 547, -687, 288, 440, -626, -623, 1261, -248, + -1133, 1204, -714, 382, 219, -851, 240, -161, 672, + -261, -855, 1043, -599, 111, -362, 225, 641, -913, + -122, 1075, -1165, 432, 131, -803, 978, 33, -1291, + 992, 224, -1054, 789, -121, -215, 262, -11, 89, + -174, 365, -240, 114, 406, -813, 291, 233, 158, + -377, 194, 216, -477, 635, -228, -512, 599, 23, + -273, 71, 258, 10, -155, -198, 354, 61, -749, + 768, -19, -709, 596, 97, -276, 164, 69, -144, + -20, 529, -897, 188, 480, -703, 836, -874, 259, + 917, -1044, -7, 566, -97, -439, 256, -466, 998, + -360, -1134, 1619, -762, -752, 1446, -707, -177, 652, + -899, 579, 253, -410, 146, -262, 275, 353, -610, + 52, 671, -862, 419, -140, 273, 247, -1062, 1005, + -175, -497, 772, -431, -101, 450, -598, 266, 428, + -842, 477, -11, -554, 642, 17, -787, 544, 445, + -625, -205, 796, -222, -733, 764, -572, 423, 166, + -994, 931, -228, -303, 362, -214, 104, 448, -1091, + 722, 570, -1311, 773, 259, -648, 477, 193, -682, + 302, 459, -464, -383, 1120, -561, -564, 1083, -372, + -354, 864, -586, -200, 502, -331, 27, 446, -657, + 281, 571, -888, 502, 251, -423, 116, 277, -263, + 118, -170, 168, 367, -723, 202, 438, -793, 451, + -30, -292, 202, 38, -188, -66, 221, -90, -105, + 7, 346, -578, 337, 247, -371, -14, 22, 36, + 151, -322, -244, 692, -556, -5, 550, -560, 200, + 161, -347, 191, 258, -520, 441, -212, -215, 584, + -428, -251, 213, 90, -187, 109, 138, -211, -17, + 191, 111, -259, 161, -141, 232, -175, 0, 154, + -369, 539, -171, -438, 484, 43, -375, -37, 249, + 196, -328, -106, 541, -531, 103, 240, -191, 186, + -363, 40, 585, -573, 258, 170, -593, 515, -261, + -86, 407, -339, 164, -214, -34, 464, -377, -206, + 336, -230, 239, -85, -69, 322, -503, 322, 142, + -748, 867, -160, -753, 836, -249, -362, 750, -374, + -222, 448, -82, -246, 399, 13, -429, 441, -47, + -127, -29, 337, -502, 318, 132, -457, 498, -145, + -91, 98, 208, -179, 54, 62, -260, 237, 96, + -161, 32, -150, 93, 21, -31, 74, 75, -322, + 164, 168, -191, 119, -121, -66, -195, 296, -128, + -251, 381, -56, -338, 281, -29, -472, 664, -301, + -275, 423, -285, -77, 258, -82, -139, 160, -54, + -26, 27, 75, -49, -196, 305, -131, -187, 262, + -37, -206, 65, 269, -240, -144, 261, 54, -338, + 355, 3, -503, 535, -253, -210, 433, -290, -33, + 381, -546, 173, 252, -364, 271, -329, 166, 266, + -564, 507, -32, -648, 861, -400, -357, 819, -519, + -74, 392, -423, 426, -306, -93, 691, -991, 537, + 467, -992, 614, 426, -823, 491, 182, -371, 174, + 84, -64, 98, -96, 23, 182, -69, -211, 226, + 18, -134, 334, -514, 352, 378, -623, 363, 266, + -592, 493, -46, -369, 594, -440, -10, 295, -368, + 326, -192, -140, 306, -305, 140, 198, -396, 202, + 154, -341, 208, -8, -169, -76, 106, 20, -347, + 233, 30, -193, 117, -9, -165, 182, -4, -195, + 96, 131, -188, -106, 166, -71, -99, 57, 4, + -31, -131, 101, 63, -199, 225, -25, -281, 342, + -247, -170, 516, -289, -263, 422, -158, -148, 363, + -192, -138, 122, 62, -105, 7, 194, -53, -224, + 83, 173, -182, 20, 178, -274, 182, 74, -109, + -5, 319, -303, -72, 428, -371, 50, 271, -204, + 17, 161, -256, 169, 93, -169, 94, -89, 139, + 80, -199, 325, -67, -83, 202, -154, 16, 202, + -325, 162, 61, -93, 201, -278, 236, 108, -477, + 594, -145, -370, 647, -261, -356, 669, -369, -181, + 420, -266, -154, 159, -25, 53, -40, -22, 68, + -203, 144, -2, -173, 88, -3, -62, 2, 75, + 55, -95, -130, 219, -142, -191, 164, -170, 44, + 0, -246, 249, -27, -413, 461, 27, -490, 292, + 19, -145, 13, 99, 91, -466, 209, 295, -773, + 465, 210, -680, 410, 163, -358, 399, -201, 87, + 23, -212, 270, -230, 86, 159, -353, 381, -73, + -456, 726, -353, -357, 754, -367, -344, 657, -59, + -417, 432, 35, -309, 153, 97, -69, 89, -101, + 63, 107, -127, 106, 112, -26, -236, 376, 43, + -479, 544, -57, -407, 447, -148, -103, 195, -198, + 80, 156, -228, 35, 145, -77, -55, 130, -33, + -190, 123, 41, -170, 74, 114, -241, 67, 192, + -195, -76, 186, -136, -133, 213, -105, -110, 144, + -51, -126, 154, -59, -124, 147, -49, -132, 82, + 26, -130, 63, 68, -211, 97, 131, -224, 59, + 184, -250, 59, 205, -225, -67, 163, -135, -24, + 74, -22, -4, -81, 21, 71, -137, 71, 47, + -120, 71, 34, -65, 138, -6, -116, 112, -47, + -39, 20, -75, 64, -7, 2, 35, 52, -61, + -29, 81, -61, -30, 195, -91, -136, 261, -11, + -186, 162, -86, -35, 152, -106, -32, 126, -4, + 49, 33, -9, -11, 46, 111, -132, -3, 204, + -175, -10, 281, -146, -94, 226, -126, -36, 58, + -14, 61, -172, 48, 193, -221, 83, 149, -279, + 195, 130, -357, 226, 102, -260, 191, 16, -223, + 124, 14, -144, 90, -31, -81, -66, 54, 103, + -181, 29, 174, -281, 92, 81, -226, 139, -133, + -41, 167, -147, 44, 27, -132, 107, -34, -122, + 105, -54, 17, 52, -131, 138, 33, -206, 158, + 43, -80, 24, 10, -27, 33, 43, -71, 15, + 71, -42, 14, 18, 0, -3, -14, -14, 58, + 46, -99, 122, 105, -202, 125, 119, -238, 112, + 133, -242, 113, 129, -301, 52, 161, -177, 82, + 73, -139, 46, 122, -119, 22, 155, -230, 23, + 242, -211, -12, 182, -184, -57, 190, -34, -101, + 58, -20, 6, 103, -61, -78, 12, 18, 12, + 86, -71, -27, 43, -24, 8, 39, -109, 21, + -4, -44, 66, 13, -59, 61, -39, 35, 113, + -179, 19, 171, -158, 14, 112, -133, 26, 9, + -43, -9, 6, 41, -77, 22, 80, -61, -63, + 65, -32, -32, 125, -105, -11, 114, -120, 42, + 42, -92, 45, -56, -25, 131, -83, -24, 97, + -51, -5, 67, -69, 7, 41, -27, 8, 3, + -10, 8, -3, -87, -28, 122, -33, -58, 124, + -53, -50, 67, -115, -17, 111, -112, -30, 101, + -24, -13, 41, 3, 45, -13, -34, 23, 23, + -19, 13, -49, -49, 68, -68, -32, 91, -58, + -18, 73, -19, -27, 17, -33, -35, 99, -38, + -99, 78, -31, -62, 95, -71, -124, 184, -15, + -146, 160, -27, -109, 140, -25, -63, 84, -34, + -18, 58, -68, -16, 22, -87, 86, 23, -130, + 61, 62, -132, 51, 168, -139, 35, 133, -121, + 50, 102, -120, 40, 126, -87, -40, 119, -14, + -59, 78, 11, -68, 41, 24, -25, 55, -2, + 15, 21, -73, 56, 88, -74, -41, 4, -10, + -4, 5, 7, -39, -3, -4, -39, 94, 52, + -135, 42, 90, -86, 12, 21, -55, -70, -37, + 55, -63, -35, 50, -100, 21, 84, -151, 24, + 87, -94, 51, 2, -58, 104, -61, -70, 60, + -25, -42, -31, 55, 35, -129, 47, 69, -65, + 77, 2, -60, 110, -32, -69, 84, -54, -26, + 98, -28, -7, 49, -49, -19, 119, -11, -157, + 20, 106, 29, -8, -38, -30, 72, 30, -3, + 1, -32, -11, -9, 52, 46, -144, -38, 86, + -31, -9, -42, -75, 142, 34, -64, 79, -109, + -55, 195, -69, -80, 48, -49, 62, 25, -111, + -42, 52, 19, -41, 1, -16, -33, 44, 30, + -21, 17, -2, -30, 111, 34, -111, 83, 55, + -119, 66, 62, -89, 63, -39, -143, 168, 21, + -158, 158, 32, -132, 134, -3, -77, 88, -45, + -18, 117, -51, -71, 10, 30, 35, -27, -63, + 13, 34, 23, -23, 19, -4, -92, 34, 74, + -69, -15, 20, -36, 56, -36, -96, 69, -34, + -122, 32, 31, -51, -3, -21, 4, 43, -44, + 6, 81, -39, -35, 26, -38, -24, 29, -16, + -47, -6, 19, -7, -9, 41, 32, 13, -2, + -21, 3, 24, 49, -3, -66, 14, 95, -7, + -52, 80, 68, -72, -14, 39, 2, 24, -6, + -53, 86, 21, -78, 67, 28, -34, 16, -23, + -1, 70, -3, -58, 45, 33, -94, -34, 62, + 41, -11, -27, 27, 46, 14, -33, -12, 44, + -16, -59, 6, 45, -3, -42, 2, 13, 19, + -1, -71, 3, 42, -36, 6, 17, 26, 5, + -46, 6, -68, -75, 86, -20, -90, 80, 4, + -86, 5, 2, -33, -15, -2, -8, -18, 15, + -7, -25, 27, -28, -88, 39, -2, -85, 58, + 40, -45, 3, 17, 0, 11, -4, -3, 84, + 22, -113, 8, 94, 10, 9, 28, 6, -3, + 5, -2, 23, 23, -1, -40, 20, 48, -40, + -21, 72, 7, -40, -1, 27, 16, 30, 31, + -16, 11, 9, -71, -7, 62, 21, -61, -19, + 78, -2, -22, 67, -42, -12, 75, -79, 47, + 86, -124, -42, 21, 4, 23, -32, -7, 19, + 1, -13, -46, 2, 32, -43, -7, 86, -16, + -22, 46, -61, -35, 11, -64, -38, 17, -12, + -27, 20, 41, 6, -58, -61, 58, -51, -77, + 36, -25, 19, 93, -76, 1, 72, -92, 15, + 40, -56, 65, 13, -29, 82, -9, -21, 24, + -83, -5, 4, -63, 77, 80, -58, -6, -19, + -43, 100, 5, -36, 63, 33, -26, -48, 26, + -18, -75, 34, 24, -45, -1, 6, -35, -24, + -23, -22, 47, -15, -46, 31, -40, -41, 74, + -32, -73, 59, -51, -26, 143, -29, -42, 93, + -44, -21, 56, -7, 55, 51, -61, 74, 111, + -71, 35, 124, -123, -3, 62, -79, 100, 49, + -122, 143, 79, -137, 72, 30, -82, 75, -10, + -48, 35, -23, -25, 34, 0, -54, -6, 34, + -46, -59, -7, -72, -6, 70, -41, -39, 23, + -33, 11, 104, -44, -30, 54, -69, -20, 62, + -75, 1, 45, -69, 1, 40, -59, -15, 18, + -16, 38, -1, -52, 8, 14, -32, 11, -15, + -58, 18, -22, -44, 69, 40, -50, -21, 1, + -35, -3, -5, -20, 40, 36, -41, -36, -43, + -11, 48, -34, -40, 51, -10, -9, 30, 10, + 12, 51, 51, -8, -16, 32, -6, 31, 24, + -38, 43, 18, -15, 53, -10, -55, 9, 8, + -28, 21, 10, -26, 21, 10, -9, 5, -29, + -13, 38, -1, -11, 49, 0, -41, 10, 23, + -25, -35, -2, -32, -10, 58, -6, -18, 16, + -9, 4, 11, 17, 21, 21, 12, -2, 49, + -16, -128, 21, 75, -32, 22, 34, -59, 48, + 75, -69, -11, -2, -65, 39, 57, -54, -79, + -11, -20, -13, 38, 4, -9, -22, -22, 33, + -7, -52, 10, -10, -19, 54, 47, -21, -35, + -6, -4, 11, 8, -28, 1, 8, -4, 30, + 1, -22, 26, -7, -24, 56, 25, -45, 13, + 24, -32, 13, 22, -46, -2, 15, -39, 28, + 32, -69, 0, 27, -69, 0, 39, -40, 28, + 55, -27, -13, 0, -14, 37, 25, -25, 34, + -3, -69, 26, 39, -41, -6, 29, -7, 5, + 66, 41, -27, -17, 6, -14, -21, 0, 29, + -9, -26, 32, -5, -34, 60, 15, -60, 20, + 13, 11, 43, -48, -15, 88, -13, -55, 26, + -32, -46, 35, 14, -37, -11, 12, -20, 11, + 9, -64, -16, 17, 5, 38, 7, -30, -9, + -49, -11, 52, -15, -38, -27, -12, 36, 53, + 1, -37, -17, -12, 0, 31, 1, 13, 40, + -15, 2, 47, -15, -17, 28, -2, -4, 25, + -6, -12, 2, -17, -9, 5, -15, 17, 21, + -28, 0, 15, -43, -63, -6, -14, -8, 37, + -34, -40, 30, -12, -14, 37, -13, -16, 26, + -15, -2, 13, -37, -13, 32, 13, -8, -2, + -12, -8, 9, 9, -3, 4, 13, 34, -2, + -22, 40, 19, 29, 25, -48, -17, 23, 17, + 7, 3, 0, 12, 37, -1, -25, 30, 41, + -7, 7, 29, -31, -31, -23, -27, 5, 2, + -18, -2, 22, 9, -6, 5, -7, -24, 9, + 0, -28, 19, 61, -11, -45, 21, -28, -65, + 28, 33, -44, -27, -6, -26, -8, 4, 5, + 9, -10, -46, -20, 20, -7, -7, -33, -26, + 50, 9, -65, -22, -3, -20, 15, 21, 20, + 24, -16, -27, -13, 14, 21, -38, -48, 9, + 35, 28, 21, 3, -31, -8, 57, 32, -35, + -22, 20, 14, 12, 28, 39, 0, -18, 44, + -2, -17, 53, 0, -27, 33, 43, 5, -10, + 25, 47, -3, -4, 36, 15, -12, -3, 29, + 41, 23, 23, -8, -32, 15, 37, 0, 3, + 22, 31, 1, -20, 27, 2, -50, 0, 33, + 16, -16, -17, 18, -26, -34, 31, -27, -84, + -33, 4, -5, -22, -17, -28, -66, -24, 8, + -16, -25, -51, -13, 45, -11, -49, -26, -49, + -38, 21, 10, -52, -58, -19, -4, 9, -31, + -29, 55, 2, -45, 29, 10, -22, 49, 33, + -27, -19, -5, 30, 47, 11, -11, -2, 8, + 5, 17, 8, 3, 57, 63, 28, 24, 11, + 2, 14, 22, 7, 7, 2, 23, 33, -2, + -8, 14, 7, 20, 57, 32, -5, 12, 23, + 10, 17, 26, -18, -72, -6, 74, 61, 13, + -17, -21, -7, 29, 45, 5, -52, -49, 1, + 10, 35, 40, -46, -66, 7, 31, -27, -44, + -12, -41, -22, 32, -12, -32, -3, -17, -22, + -22, -31, -30, -23, -13, 3, 0, -21, -19, + -7, -17, -9, 18, -40, -64, 1, 4, -4, + 8, -17, -28, -1, 9, -7, -9, 27, 6, + -63, -32, 52, 25, -46, -23, -6, -11, 35, + 29, -50, -44, 17, -6, -12, 53, 28, -17, + -9, 28, 34, -20, -18, 22, 43, 28, -6, + 8, 14, 19, 28, 14, 27, 26, 12, 76, + 66, -18, -2, 18, -12, -1, -2, -1, 51, + 30, -18, 5, 14, -12, 2, 13, -25, -9, + 32, 7, -5, 15, -12, -33, -18, -13, 6, + 0, -25, -12, 1, -17, 0, 13, -24, -27, + 4, 35, 14, -22, 5, 13, -18, -30, -10, + -7, -7, 31, 23, -27, -26, 9, 47, 6, + -50, -11, 19, 1, 11, 12, -19, -43, -18, + 10, -6, -3, 12, 2, -12, -16, 10, 9, + -25, -21, -10, -13, 0, 8, -1, -9, 10, + 4, -34, 14, 46, 5, 18, 24, -15, -7, + 20, -1, -13, 7, 11, 14, 11, -2, 8, + 27, 10, -1, 13, -2, -7, 48, 44, -15, + -16, -6, 3, 7, -35, -25, 8, -31, -16, + 30, 36, 22, -13, -21, -10, 8, 2, -58, + -37, 32, 25, -1, -25, -21, 3, 3, -6, + -11, -3, 2, 4, 34, 22, -25, -19, 0, + -6, -10, -8, -35, -32, 8, -3, -20, -11, + -6, 3, 8, -8, 3, 25, 23, -7, -35, + -15, 8, -20, -6, 15, -44, -29, 19, -5, + -1, 18, 28, 6, -21, 9, 11, -20, -10, + 18, 22, 6, -2, 12, 6, 23, 34, -20, + -19, 1, -10, 34, 41, 13, 6, 3, 22, + 11, -4, 4, -12, -8, 17, 18, 12, -1, + 5, 9, -6, -2, 4, 1, 3, 2, -6, + -32, -25, 9, 18, 27, -4, -54, -29, 2, + -3, -18, -38, -28, -10, 9, 20, 5, -9, + -15, -3, 2, -14, -15, -6, 5, 10, 6, + 3, -11, -9, -5, -20, -13, 8, 3, -14, + 6, 20, -15, -21, 9, 19, 21, 12, -4, + -21, -17, 16, 27, -4, -28, -2, 26, 9, + -12, -16, -28, -28, -4, 4, -15, -9, 3, + -10, -16, 2, 17, -10, -26, 3, 16, 26, + 17, -12, -9, 2, -2, -5, -11, 5, 28, + 1, -14, 13, 14, 5, 18, 6, -17, -5, + 7, 2, -3, 11, 10, -1, 50, 36, -28, + 21, 39, -9, -6, 2, 10, 36, 20, -2, + -3, -11, -10, -6, -5, -4, -8, 2, 17, + 1, -13, 11, -13, -36, 11, 14, -19, -6, + 3, 0, 20, -5, -24, 12, 7, -11, 2, + -15, -28, -1, 6, -14, -31, -39, -19, 19, + 37, 3, -32, -27, -6, 13, 31, 15, -41, + -41, 25, 35, -3, -16, -25, -19, -10, -3, + 19, 10, -4, 7, -4, -19, -12, -13, -9, + 6, 2, -12, -6, 12, 6, -1, -5, -19, + -7, 7, 40, 56, -3, -13, 21, 24, 7, + -11, -9, -3, 24, 28, -10, 1, 12, 21, + 24, -16, -15, 4, -7, -2, 19, 13, -11, + -7, -8, 15, 41, 5, -16, -18, -11, 26, + 26, -5, -12, -14, -6, 10, 8, -8, -16, + -16, -3, 10, 1, -3, -3, -2, -15, -18, + 6, -4, -4, 21, 4, -2, 15, 13, 0, + -2, 12, 7, -15, -9, 1, -2, 2, -1, + -9, -15, -17, -14, -10, 1, -4, -16, -17, + -1, 18, 8, 1, 22, 11, -19, -10, 4, + -23, -29, 0, -2, -14, -6, 13, 7, -23, + -13, 10, 9, 11, 10, 4, -4, -4, 1, + 6, 14, 9, 2, 0, 2, 6, 4, -9, + -18, -8, 8, 18, 8, 13, 9, -27, -22, + -10, -24, -9, 17, 11, 2, 9, 3, -13, + -10, -1, -7, -1, 10, -4, 1, 16, 12, + -6, -14, -2, -5, -1, 0, -1, 6, -9, + -3, 12, 4, 1, -2, 2, 17, 24, 22, + 9, 8, 21, 14, -2, -2, 4, -1, -7, + -7, -6, -1, -6, 17, 30, -7, -10, -3, + -19, -18, 2, 21, 4, -20, -6, -1, -18, + -14, -6, -7, -1, 6, 10, 8, -5, 0, + 10, -22, -40, -22, 4, 34, 16, -19, -16, + -12, -17, -16, -17, -29, -28, -4, 10, 16, + 22, 13, 4, -1, -5, 16, 15, -11, -6, + 9, 3, -14, -22, -19, -12, 5, -5, -15, + 3, 9, 27, 17, -4, 8, -2, 1, 16, + 11, 9, 9, 8, -14, -16, 7, -5, -15, + -11, -5, 19, 25, 25, 43, 21, -9, -9, + -19, -10, 14, -11, -19, 8, 3, 1, 11, + -1, -24, -20, -1, 2, 7, 24, 22, 11, + 8, 6, -2, -11, -3, -2, -4, 0, -7, + 0, 6, -1, -16, -35, -8, 8, -11, -6, + 6, 18, 16, 7, 12, 5, -2, -3, -10, + -21, -27, -10, -3, -3, 8, 0, -9, -10, + -3, 0, -5, 6, 9, 19, 23, 8, -5, + -19, -16, -5, -6, -27, -22, 1, 6, 8, + 2, -9, -13, -15, -18, -13, 4, 25, 29, + 26, -2, -22, 1, 8, 1, -6, -6, -7, + -20, 0, 13, -14, -24, -24, -21, 2, 14, + 16, 23, 15, 10, 10, 5, 0, -26, -32, + 3, 19, 5, -8, -7, -8, -3, 17, 27, + -7, -28, 10, 32, 10, 1, 10, 3, -4, + 22, 24, -31, -40, 0, 6, 5, 17, 17, + 1, 10, 30, 8, -12, -6, 9, 6, -12, + -5, 1, -4, 6, 11, 0, -9, -4, -3, + -4, -3, 2, 0, -2, -9, -27, -23, 2, + 13, -6, -9, -3, -12, -2, 10, 6, -7, + -19, -31, -13, 16, 11, -3, -13, -15, 0, + 7, -3, -7, -1, -4, 7, 15, 0, -12, + -8, -1, -7, -12, -21, -17, 5, 30, 25, + -6, -6, 0, -12, -8, 2, 13, 11, 1, + 5, 4, 4, 10, -1, -20, -12, -4, 3, + 15, 11, -7, -24, -4, 8, -2, -14, -25, + -17, 7, 21, 14, 1, 0, 12, 17, 13, + 6, 1, 6, 14, 11, -10, -21, -12, -4, + 3, -2, -21, -24, -2, 12, 14, 17, 4, + -2, 11, 11, 11, 1, -34, -32, -5, 10, + 7, -11, -12, 6, 7, -4, -10, -15, -5, + 17, 21, 0, -15, -15, -1, 5, -18, -18, + -10, -9, 24, 27, -9, -14, 0, 9, 25, + 22, 1, -7, -2, 16, 13, -14, -10, 7, + 0, 2, 15, 2, -9, 5, 10, -5, -3, + 10, 3, 0, 15, 15, -1, -3, 8, 6, + -7, -7, 2, 0, -4, 5, -8, -37, -28, + -1, 8, 6, 10, -1, -12, 12, 28, 8, + -17, -16, -15, -17, 1, 6, -4, -8, -4, + -15, -15, 6, -9, -15, 10, 9, -13, -8, + 5, -2, -10, 5, 12, -27, -33, 9, 8, + -16, -3, 16, -3, -7, 22, 22, 10, 5, + -11, -16, -4, 9, 12, 6, -3, 2, 2, + -1, 4, -7, -8, 1, 8, 19, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.h new file mode 100644 index 00000000000..33aeea516fb --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/yes_1000ms_sample_data.h @@ -0,0 +1,29 @@ +/* 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 data was created from the PCM data in a WAV file held in v2 of the +// Speech Commands test dataset, at the path: +// speech_commands_test_set_v0.02/yes/f2e59fea_nohash_1.wav +// This should contain all 16,000 samples from the one-second file. + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_1000MS_SAMPLE_DATA_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_1000MS_SAMPLE_DATA_H_ + +#include + +extern const int g_yes_1000ms_sample_data_size; +extern const int16_t g_yes_1000ms_sample_data[]; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_1000MS_SAMPLE_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/testing/micro_test.h b/tensorflow/lite/experimental/micro/testing/micro_test.h index 2f20dd5ac77..32e9a57f76e 100644 --- a/tensorflow/lite/experimental/micro/testing/micro_test.h +++ b/tensorflow/lite/experimental/micro/testing/micro_test.h @@ -107,13 +107,13 @@ extern tflite::ErrorReporter* reporter; } \ } while (false) -#define TF_LITE_MICRO_EXPECT_EQ(x, y) \ - do { \ - if ((x) != (y)) { \ - micro_test::reporter->Report(#x " == " #y " failed at %s:%d", __FILE__, \ - __LINE__); \ - micro_test::did_test_fail = true; \ - } \ +#define TF_LITE_MICRO_EXPECT_EQ(x, y) \ + do { \ + if ((x) != (y)) { \ + micro_test::reporter->Report(#x " == " #y " failed at %s:%d (%d vs %d)", \ + __FILE__, __LINE__, (x), (y)); \ + micro_test::did_test_fail = true; \ + } \ } while (false) #define TF_LITE_MICRO_EXPECT_NE(x, y) \ diff --git a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh index 4c747ac3978..639f002c3bf 100755 --- a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh +++ b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh @@ -39,6 +39,7 @@ AM_SDK_URL="http://s3.asia.ambiqmicro.com/downloads/AmbiqSuite-Rel2.0.0.zip" AP3_URL="https://github.com/AmbiqMicro/TFLiteMicro_Apollo3/archive/dfbcef9a57276c087d95aab7cb234f1d4c9eaaba.zip" CUST_CMSIS_URL="https://github.com/AmbiqMicro/TFLiteMicro_CustCMSIS/archive/8f63966c5692e6a3a83956efd2e4aed77c4c9949.zip" GCC_EMBEDDED_URL="https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2" +KISSFFT_URL="http://downloads.sourceforge.net/project/kissfft/kissfft/v1_3_0/kiss_fft130.zip" download_and_extract() { local usage="Usage: download_and_extract URL DIR" @@ -100,6 +101,15 @@ patch_am_sdk() { echo "Finished preparing Apollo3 files" } +patch_kissfft() { + sed -i -E "s@#ifdef FIXED_POINT@// Patched automatically by download_dependencies.sh so default is 16 bit.\n#ifndef FIXED_POINT\n#define FIXED_POINT (16)\n#endif\n// End patch.\n\n#ifdef FIXED_POINT@g" tensorflow/lite/experimental/micro/tools/make/downloads/kissfft/kiss_fft.h + sed -i -E "s@#define KISS_FFT_MALLOC malloc@#define KISS_FFT_MALLOC(X) (void*)(0) /* Patched. */@g" tensorflow/lite/experimental/micro/tools/make/downloads/kissfft/kiss_fft.h + sed -i -E "s@#define KISS_FFT_FREE free@#define KISS_FFT_FREE(X) /* Patched. */@g" tensorflow/lite/experimental/micro/tools/make/downloads/kissfft/kiss_fft.h + sed -i -E "s@(fprintf.*\);)@/* \1 */@g" tensorflow/lite/experimental/micro/tools/make/downloads/kissfft/tools/kiss_fftr.c + sed -i -E "s@(exit.*\);)@return; /* \1 */@g" tensorflow/lite/experimental/micro/tools/make/downloads/kissfft/tools/kiss_fftr.c + echo "Finished patching kissfft" +} + download_and_extract "${GEMMLOWP_URL}" "${DOWNLOADS_DIR}/gemmlowp" download_and_extract "${FLATBUFFERS_URL}" "${DOWNLOADS_DIR}/flatbuffers" download_and_extract "${CMSIS_URL}" "${DOWNLOADS_DIR}/cmsis" @@ -111,5 +121,7 @@ patch_am_sdk "${DOWNLOADS_DIR}/AmbiqSuite-Rel2.0.0" download_and_extract "${AP3_URL}" "${DOWNLOADS_DIR}/apollo3_ext" download_and_extract "${CUST_CMSIS_URL}" "${DOWNLOADS_DIR}/CMSIS_ext" download_and_extract "${GCC_EMBEDDED_URL}" "${DOWNLOADS_DIR}/gcc_embedded" +download_and_extract "${KISSFFT_URL}" "${DOWNLOADS_DIR}/kissfft" +patch_kissfft "${DOWNLOADS_DIR}/kissfft" echo "download_dependencies.sh completed successfully." >&2